├── .cspell.json ├── .devcontainer └── devcontainer.json ├── .dockerignore ├── .editorconfig ├── .gitattributes ├── .github ├── CONTRIBUTING.md ├── ISSUE_TEMPLATE.md ├── ISSUE_TEMPLATE │ ├── bug-report.md │ ├── feature-request.md │ └── operation-request.md └── workflows │ ├── codeql.yml │ ├── master.yml │ ├── pull_requests.yml │ └── releases.yml ├── .gitignore ├── .npmignore ├── .nvmrc ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── Dockerfile ├── Gruntfile.js ├── LICENSE ├── README.md ├── SECURITY.md ├── babel.config.js ├── eslint.config.mjs ├── nightwatch.json ├── package-lock.json ├── package.json ├── postcss.config.js ├── src ├── core │ ├── Chef.mjs │ ├── ChefWorker.js │ ├── Dish.mjs │ ├── Ingredient.mjs │ ├── Operation.mjs │ ├── Recipe.mjs │ ├── Utils.mjs │ ├── config │ │ ├── Categories.json │ │ └── scripts │ │ │ ├── generateConfig.mjs │ │ │ ├── generateOpsIndex.mjs │ │ │ ├── newMinorVersion.mjs │ │ │ └── newOperation.mjs │ ├── dishTypes │ │ ├── DishBigNumber.mjs │ │ ├── DishByteArray.mjs │ │ ├── DishFile.mjs │ │ ├── DishHTML.mjs │ │ ├── DishJSON.mjs │ │ ├── DishListFile.mjs │ │ ├── DishNumber.mjs │ │ ├── DishString.mjs │ │ ├── DishType.mjs │ │ └── index.mjs │ ├── errors │ │ ├── DishError.mjs │ │ ├── ExcludedOperationError.mjs │ │ ├── OperationError.mjs │ │ └── index.mjs │ ├── lib │ │ ├── Arithmetic.mjs │ │ ├── BCD.mjs │ │ ├── Bacon.mjs │ │ ├── Base32.mjs │ │ ├── Base45.mjs │ │ ├── Base58.mjs │ │ ├── Base64.mjs │ │ ├── Base85.mjs │ │ ├── Base92.mjs │ │ ├── Binary.mjs │ │ ├── BitwiseOp.mjs │ │ ├── Blowfish.mjs │ │ ├── Bombe.mjs │ │ ├── Braille.mjs │ │ ├── CanvasComponents.mjs │ │ ├── Charts.mjs │ │ ├── ChrEnc.mjs │ │ ├── CipherSaber2.mjs │ │ ├── Ciphers.mjs │ │ ├── Code.mjs │ │ ├── Colossus.mjs │ │ ├── ConvertCoordinates.mjs │ │ ├── Crypt.mjs │ │ ├── DateTime.mjs │ │ ├── Decimal.mjs │ │ ├── Delim.mjs │ │ ├── Enigma.mjs │ │ ├── Extract.mjs │ │ ├── FileSignatures.mjs │ │ ├── FileType.mjs │ │ ├── FlowControl.mjs │ │ ├── FuzzyMatch.mjs │ │ ├── Hash.mjs │ │ ├── Hex.mjs │ │ ├── IP.mjs │ │ ├── ImageManipulation.mjs │ │ ├── JA4.mjs │ │ ├── JWT.mjs │ │ ├── LS47.mjs │ │ ├── LZNT1.mjs │ │ ├── LZString.mjs │ │ ├── LoremIpsum.mjs │ │ ├── Lorenz.mjs │ │ ├── Magic.mjs │ │ ├── Modhex.mjs │ │ ├── PGP.mjs │ │ ├── Protobuf.mjs │ │ ├── Protocol.mjs │ │ ├── PublicKey.mjs │ │ ├── QRCode.mjs │ │ ├── RSA.mjs │ │ ├── Rotate.mjs │ │ ├── SIGABA.mjs │ │ ├── SM2.mjs │ │ ├── SM4.mjs │ │ ├── Salsa20.mjs │ │ ├── Sort.mjs │ │ ├── Stream.mjs │ │ ├── TLS.mjs │ │ ├── TLVParser.mjs │ │ ├── Typex.mjs │ │ ├── XXTEA.mjs │ │ └── Zlib.mjs │ ├── operations │ │ ├── A1Z26CipherDecode.mjs │ │ ├── A1Z26CipherEncode.mjs │ │ ├── ADD.mjs │ │ ├── AESDecrypt.mjs │ │ ├── AESEncrypt.mjs │ │ ├── AESKeyUnwrap.mjs │ │ ├── AESKeyWrap.mjs │ │ ├── AMFDecode.mjs │ │ ├── AMFEncode.mjs │ │ ├── AND.mjs │ │ ├── AddLineNumbers.mjs │ │ ├── AddTextToImage.mjs │ │ ├── Adler32Checksum.mjs │ │ ├── AffineCipherDecode.mjs │ │ ├── AffineCipherEncode.mjs │ │ ├── AlternatingCaps.mjs │ │ ├── AnalyseHash.mjs │ │ ├── AnalyseUUID.mjs │ │ ├── Argon2.mjs │ │ ├── Argon2Compare.mjs │ │ ├── AtbashCipher.mjs │ │ ├── AvroToJSON.mjs │ │ ├── BLAKE2b.mjs │ │ ├── BLAKE2s.mjs │ │ ├── BLAKE3.mjs │ │ ├── BSONDeserialise.mjs │ │ ├── BSONSerialise.mjs │ │ ├── BaconCipherDecode.mjs │ │ ├── BaconCipherEncode.mjs │ │ ├── Bcrypt.mjs │ │ ├── BcryptCompare.mjs │ │ ├── BcryptParse.mjs │ │ ├── BifidCipherDecode.mjs │ │ ├── BifidCipherEncode.mjs │ │ ├── BitShiftLeft.mjs │ │ ├── BitShiftRight.mjs │ │ ├── BlowfishDecrypt.mjs │ │ ├── BlowfishEncrypt.mjs │ │ ├── BlurImage.mjs │ │ ├── Bombe.mjs │ │ ├── Bzip2Compress.mjs │ │ ├── Bzip2Decompress.mjs │ │ ├── CBORDecode.mjs │ │ ├── CBOREncode.mjs │ │ ├── CMAC.mjs │ │ ├── CRCChecksum.mjs │ │ ├── CSSBeautify.mjs │ │ ├── CSSMinify.mjs │ │ ├── CSSSelector.mjs │ │ ├── CSVToJSON.mjs │ │ ├── CTPH.mjs │ │ ├── CaesarBoxCipher.mjs │ │ ├── CaretMdecode.mjs │ │ ├── CartesianProduct.mjs │ │ ├── CetaceanCipherDecode.mjs │ │ ├── CetaceanCipherEncode.mjs │ │ ├── ChaCha.mjs │ │ ├── ChangeIPFormat.mjs │ │ ├── ChiSquare.mjs │ │ ├── CipherSaber2Decrypt.mjs │ │ ├── CipherSaber2Encrypt.mjs │ │ ├── CitrixCTX1Decode.mjs │ │ ├── CitrixCTX1Encode.mjs │ │ ├── Colossus.mjs │ │ ├── Comment.mjs │ │ ├── CompareCTPHHashes.mjs │ │ ├── CompareSSDEEPHashes.mjs │ │ ├── ConditionalJump.mjs │ │ ├── ContainImage.mjs │ │ ├── ConvertArea.mjs │ │ ├── ConvertCoordinateFormat.mjs │ │ ├── ConvertDataUnits.mjs │ │ ├── ConvertDistance.mjs │ │ ├── ConvertImageFormat.mjs │ │ ├── ConvertLeetSpeak.mjs │ │ ├── ConvertMass.mjs │ │ ├── ConvertSpeed.mjs │ │ ├── ConvertToNATOAlphabet.mjs │ │ ├── CountOccurrences.mjs │ │ ├── CoverImage.mjs │ │ ├── CropImage.mjs │ │ ├── DESDecrypt.mjs │ │ ├── DESEncrypt.mjs │ │ ├── DNSOverHTTPS.mjs │ │ ├── DateTimeDelta.mjs │ │ ├── DechunkHTTPResponse.mjs │ │ ├── DecodeNetBIOSName.mjs │ │ ├── DecodeText.mjs │ │ ├── DefangIPAddresses.mjs │ │ ├── DefangURL.mjs │ │ ├── DeriveEVPKey.mjs │ │ ├── DeriveHKDFKey.mjs │ │ ├── DerivePBKDF2Key.mjs │ │ ├── DetectFileType.mjs │ │ ├── Diff.mjs │ │ ├── DisassembleX86.mjs │ │ ├── DitherImage.mjs │ │ ├── Divide.mjs │ │ ├── DropBytes.mjs │ │ ├── DropNthBytes.mjs │ │ ├── ECDSASign.mjs │ │ ├── ECDSASignatureConversion.mjs │ │ ├── ECDSAVerify.mjs │ │ ├── ELFInfo.mjs │ │ ├── EncodeNetBIOSName.mjs │ │ ├── EncodeText.mjs │ │ ├── Enigma.mjs │ │ ├── Entropy.mjs │ │ ├── EscapeString.mjs │ │ ├── EscapeUnicodeCharacters.mjs │ │ ├── ExpandAlphabetRange.mjs │ │ ├── ExtractDates.mjs │ │ ├── ExtractDomains.mjs │ │ ├── ExtractEXIF.mjs │ │ ├── ExtractEmailAddresses.mjs │ │ ├── ExtractFilePaths.mjs │ │ ├── ExtractFiles.mjs │ │ ├── ExtractHashes.mjs │ │ ├── ExtractID3.mjs │ │ ├── ExtractIPAddresses.mjs │ │ ├── ExtractLSB.mjs │ │ ├── ExtractMACAddresses.mjs │ │ ├── ExtractRGBA.mjs │ │ ├── ExtractURLs.mjs │ │ ├── FangURL.mjs │ │ ├── FernetDecrypt.mjs │ │ ├── FernetEncrypt.mjs │ │ ├── FileTree.mjs │ │ ├── Filter.mjs │ │ ├── FindReplace.mjs │ │ ├── Fletcher16Checksum.mjs │ │ ├── Fletcher32Checksum.mjs │ │ ├── Fletcher64Checksum.mjs │ │ ├── Fletcher8Checksum.mjs │ │ ├── FlipImage.mjs │ │ ├── Fork.mjs │ │ ├── FormatMACAddresses.mjs │ │ ├── FrequencyDistribution.mjs │ │ ├── FromBCD.mjs │ │ ├── FromBase.mjs │ │ ├── FromBase32.mjs │ │ ├── FromBase45.mjs │ │ ├── FromBase58.mjs │ │ ├── FromBase62.mjs │ │ ├── FromBase64.mjs │ │ ├── FromBase85.mjs │ │ ├── FromBase92.mjs │ │ ├── FromBinary.mjs │ │ ├── FromBraille.mjs │ │ ├── FromCaseInsensitiveRegex.mjs │ │ ├── FromCharcode.mjs │ │ ├── FromDecimal.mjs │ │ ├── FromFloat.mjs │ │ ├── FromHTMLEntity.mjs │ │ ├── FromHex.mjs │ │ ├── FromHexContent.mjs │ │ ├── FromHexdump.mjs │ │ ├── FromMessagePack.mjs │ │ ├── FromModhex.mjs │ │ ├── FromMorseCode.mjs │ │ ├── FromOctal.mjs │ │ ├── FromPunycode.mjs │ │ ├── FromQuotedPrintable.mjs │ │ ├── FromUNIXTimestamp.mjs │ │ ├── FuzzyMatch.mjs │ │ ├── GOSTDecrypt.mjs │ │ ├── GOSTEncrypt.mjs │ │ ├── GOSTHash.mjs │ │ ├── GOSTKeyUnwrap.mjs │ │ ├── GOSTKeyWrap.mjs │ │ ├── GOSTSign.mjs │ │ ├── GOSTVerify.mjs │ │ ├── GenerateAllChecksums.mjs │ │ ├── GenerateAllHashes.mjs │ │ ├── GenerateDeBruijnSequence.mjs │ │ ├── GenerateECDSAKeyPair.mjs │ │ ├── GenerateHOTP.mjs │ │ ├── GenerateImage.mjs │ │ ├── GenerateLoremIpsum.mjs │ │ ├── GeneratePGPKeyPair.mjs │ │ ├── GenerateQRCode.mjs │ │ ├── GenerateRSAKeyPair.mjs │ │ ├── GenerateTOTP.mjs │ │ ├── GenerateUUID.mjs │ │ ├── GenericCodeBeautify.mjs │ │ ├── GetAllCasings.mjs │ │ ├── GetTime.mjs │ │ ├── GroupIPAddresses.mjs │ │ ├── Gunzip.mjs │ │ ├── Gzip.mjs │ │ ├── HAS160.mjs │ │ ├── HASSHClientFingerprint.mjs │ │ ├── HASSHServerFingerprint.mjs │ │ ├── HMAC.mjs │ │ ├── HTMLToText.mjs │ │ ├── HTTPRequest.mjs │ │ ├── HammingDistance.mjs │ │ ├── HaversineDistance.mjs │ │ ├── Head.mjs │ │ ├── HeatmapChart.mjs │ │ ├── HexDensityChart.mjs │ │ ├── HexToObjectIdentifier.mjs │ │ ├── HexToPEM.mjs │ │ ├── IPv6TransitionAddresses.mjs │ │ ├── ImageBrightnessContrast.mjs │ │ ├── ImageFilter.mjs │ │ ├── ImageHueSaturationLightness.mjs │ │ ├── ImageOpacity.mjs │ │ ├── IndexOfCoincidence.mjs │ │ ├── InvertImage.mjs │ │ ├── JA3Fingerprint.mjs │ │ ├── JA3SFingerprint.mjs │ │ ├── JA4Fingerprint.mjs │ │ ├── JA4ServerFingerprint.mjs │ │ ├── JPathExpression.mjs │ │ ├── JSONBeautify.mjs │ │ ├── JSONMinify.mjs │ │ ├── JSONToCSV.mjs │ │ ├── JSONtoYAML.mjs │ │ ├── JWKToPem.mjs │ │ ├── JWTDecode.mjs │ │ ├── JWTSign.mjs │ │ ├── JWTVerify.mjs │ │ ├── JavaScriptBeautify.mjs │ │ ├── JavaScriptMinify.mjs │ │ ├── JavaScriptParser.mjs │ │ ├── Jq.mjs │ │ ├── Jsonata.mjs │ │ ├── Jump.mjs │ │ ├── Keccak.mjs │ │ ├── LMHash.mjs │ │ ├── LS47Decrypt.mjs │ │ ├── LS47Encrypt.mjs │ │ ├── LZ4Compress.mjs │ │ ├── LZ4Decompress.mjs │ │ ├── LZMACompress.mjs │ │ ├── LZMADecompress.mjs │ │ ├── LZNT1Decompress.mjs │ │ ├── LZStringCompress.mjs │ │ ├── LZStringDecompress.mjs │ │ ├── Label.mjs │ │ ├── LevenshteinDistance.mjs │ │ ├── Lorenz.mjs │ │ ├── LuhnChecksum.mjs │ │ ├── MD2.mjs │ │ ├── MD4.mjs │ │ ├── MD5.mjs │ │ ├── MD6.mjs │ │ ├── MIMEDecoding.mjs │ │ ├── Magic.mjs │ │ ├── Mean.mjs │ │ ├── Median.mjs │ │ ├── Merge.mjs │ │ ├── MicrosoftScriptDecoder.mjs │ │ ├── MultipleBombe.mjs │ │ ├── Multiply.mjs │ │ ├── MurmurHash3.mjs │ │ ├── NOT.mjs │ │ ├── NTHash.mjs │ │ ├── NormaliseImage.mjs │ │ ├── NormaliseUnicode.mjs │ │ ├── Numberwang.mjs │ │ ├── OR.mjs │ │ ├── ObjectIdentifierToHex.mjs │ │ ├── OffsetChecker.mjs │ │ ├── OpticalCharacterRecognition.mjs │ │ ├── PEMToHex.mjs │ │ ├── PEMToJWK.mjs │ │ ├── PGPDecrypt.mjs │ │ ├── PGPDecryptAndVerify.mjs │ │ ├── PGPEncrypt.mjs │ │ ├── PGPEncryptAndSign.mjs │ │ ├── PGPVerify.mjs │ │ ├── PHPDeserialize.mjs │ │ ├── PHPSerialize.mjs │ │ ├── PLISTViewer.mjs │ │ ├── PadLines.mjs │ │ ├── ParseASN1HexString.mjs │ │ ├── ParseCSR.mjs │ │ ├── ParseColourCode.mjs │ │ ├── ParseDateTime.mjs │ │ ├── ParseIPRange.mjs │ │ ├── ParseIPv4Header.mjs │ │ ├── ParseIPv6Address.mjs │ │ ├── ParseObjectIDTimestamp.mjs │ │ ├── ParseQRCode.mjs │ │ ├── ParseSSHHostKey.mjs │ │ ├── ParseTCP.mjs │ │ ├── ParseTLSRecord.mjs │ │ ├── ParseTLV.mjs │ │ ├── ParseUDP.mjs │ │ ├── ParseUNIXFilePermissions.mjs │ │ ├── ParseURI.mjs │ │ ├── ParseUserAgent.mjs │ │ ├── ParseX509CRL.mjs │ │ ├── ParseX509Certificate.mjs │ │ ├── PlayMedia.mjs │ │ ├── PowerSet.mjs │ │ ├── ProtobufDecode.mjs │ │ ├── ProtobufEncode.mjs │ │ ├── PseudoRandomNumberGenerator.mjs │ │ ├── PubKeyFromCert.mjs │ │ ├── PubKeyFromPrivKey.mjs │ │ ├── RAKE.mjs │ │ ├── RC2Decrypt.mjs │ │ ├── RC2Encrypt.mjs │ │ ├── RC4.mjs │ │ ├── RC4Drop.mjs │ │ ├── RIPEMD.mjs │ │ ├── ROT13.mjs │ │ ├── ROT13BruteForce.mjs │ │ ├── ROT47.mjs │ │ ├── ROT47BruteForce.mjs │ │ ├── ROT8000.mjs │ │ ├── RSADecrypt.mjs │ │ ├── RSAEncrypt.mjs │ │ ├── RSASign.mjs │ │ ├── RSAVerify.mjs │ │ ├── Rabbit.mjs │ │ ├── RailFenceCipherDecode.mjs │ │ ├── RailFenceCipherEncode.mjs │ │ ├── RandomizeColourPalette.mjs │ │ ├── RawDeflate.mjs │ │ ├── RawInflate.mjs │ │ ├── Register.mjs │ │ ├── RegularExpression.mjs │ │ ├── RemoveDiacritics.mjs │ │ ├── RemoveEXIF.mjs │ │ ├── RemoveLineNumbers.mjs │ │ ├── RemoveNullBytes.mjs │ │ ├── RemoveWhitespace.mjs │ │ ├── RenderImage.mjs │ │ ├── RenderMarkdown.mjs │ │ ├── ResizeImage.mjs │ │ ├── Return.mjs │ │ ├── Reverse.mjs │ │ ├── RisonDecode.mjs │ │ ├── RisonEncode.mjs │ │ ├── RotateImage.mjs │ │ ├── RotateLeft.mjs │ │ ├── RotateRight.mjs │ │ ├── SHA0.mjs │ │ ├── SHA1.mjs │ │ ├── SHA2.mjs │ │ ├── SHA3.mjs │ │ ├── SIGABA.mjs │ │ ├── SM2Decrypt.mjs │ │ ├── SM2Encrypt.mjs │ │ ├── SM3.mjs │ │ ├── SM4Decrypt.mjs │ │ ├── SM4Encrypt.mjs │ │ ├── SQLBeautify.mjs │ │ ├── SQLMinify.mjs │ │ ├── SSDEEP.mjs │ │ ├── SUB.mjs │ │ ├── Salsa20.mjs │ │ ├── ScanForEmbeddedFiles.mjs │ │ ├── ScatterChart.mjs │ │ ├── Scrypt.mjs │ │ ├── SeriesChart.mjs │ │ ├── SetDifference.mjs │ │ ├── SetIntersection.mjs │ │ ├── SetUnion.mjs │ │ ├── Shake.mjs │ │ ├── SharpenImage.mjs │ │ ├── ShowBase64Offsets.mjs │ │ ├── ShowOnMap.mjs │ │ ├── Shuffle.mjs │ │ ├── Sleep.mjs │ │ ├── Snefru.mjs │ │ ├── Sort.mjs │ │ ├── Split.mjs │ │ ├── SplitColourChannels.mjs │ │ ├── StandardDeviation.mjs │ │ ├── Streebog.mjs │ │ ├── Strings.mjs │ │ ├── StripHTMLTags.mjs │ │ ├── StripHTTPHeaders.mjs │ │ ├── StripIPv4Header.mjs │ │ ├── StripTCPHeader.mjs │ │ ├── StripUDPHeader.mjs │ │ ├── Subsection.mjs │ │ ├── Substitute.mjs │ │ ├── Subtract.mjs │ │ ├── Sum.mjs │ │ ├── SwapCase.mjs │ │ ├── SwapEndianness.mjs │ │ ├── SymmetricDifference.mjs │ │ ├── SyntaxHighlighter.mjs │ │ ├── TCPIPChecksum.mjs │ │ ├── Tail.mjs │ │ ├── TakeBytes.mjs │ │ ├── TakeNthBytes.mjs │ │ ├── Tar.mjs │ │ ├── Template.mjs │ │ ├── TextEncodingBruteForce.mjs │ │ ├── ToBCD.mjs │ │ ├── ToBase.mjs │ │ ├── ToBase32.mjs │ │ ├── ToBase45.mjs │ │ ├── ToBase58.mjs │ │ ├── ToBase62.mjs │ │ ├── ToBase64.mjs │ │ ├── ToBase85.mjs │ │ ├── ToBase92.mjs │ │ ├── ToBinary.mjs │ │ ├── ToBraille.mjs │ │ ├── ToCamelCase.mjs │ │ ├── ToCaseInsensitiveRegex.mjs │ │ ├── ToCharcode.mjs │ │ ├── ToDecimal.mjs │ │ ├── ToFloat.mjs │ │ ├── ToHTMLEntity.mjs │ │ ├── ToHex.mjs │ │ ├── ToHexContent.mjs │ │ ├── ToHexdump.mjs │ │ ├── ToKebabCase.mjs │ │ ├── ToLowerCase.mjs │ │ ├── ToMessagePack.mjs │ │ ├── ToModhex.mjs │ │ ├── ToMorseCode.mjs │ │ ├── ToOctal.mjs │ │ ├── ToPunycode.mjs │ │ ├── ToQuotedPrintable.mjs │ │ ├── ToSnakeCase.mjs │ │ ├── ToTable.mjs │ │ ├── ToUNIXTimestamp.mjs │ │ ├── ToUpperCase.mjs │ │ ├── TranslateDateTimeFormat.mjs │ │ ├── TripleDESDecrypt.mjs │ │ ├── TripleDESEncrypt.mjs │ │ ├── Typex.mjs │ │ ├── UNIXTimestampToWindowsFiletime.mjs │ │ ├── URLDecode.mjs │ │ ├── URLEncode.mjs │ │ ├── UnescapeString.mjs │ │ ├── UnescapeUnicodeCharacters.mjs │ │ ├── UnicodeTextFormat.mjs │ │ ├── Unique.mjs │ │ ├── Untar.mjs │ │ ├── Unzip.mjs │ │ ├── VarIntDecode.mjs │ │ ├── VarIntEncode.mjs │ │ ├── ViewBitPlane.mjs │ │ ├── VigenèreDecode.mjs │ │ ├── VigenèreEncode.mjs │ │ ├── Whirlpool.mjs │ │ ├── WindowsFiletimeToUNIXTimestamp.mjs │ │ ├── XKCDRandomNumber.mjs │ │ ├── XMLBeautify.mjs │ │ ├── XMLMinify.mjs │ │ ├── XOR.mjs │ │ ├── XORBruteForce.mjs │ │ ├── XORChecksum.mjs │ │ ├── XPathExpression.mjs │ │ ├── XSalsa20.mjs │ │ ├── XXTEADecrypt.mjs │ │ ├── XXTEAEncrypt.mjs │ │ ├── YAMLToJSON.mjs │ │ ├── YARARules.mjs │ │ ├── Zip.mjs │ │ ├── ZlibDeflate.mjs │ │ └── ZlibInflate.mjs │ └── vendor │ │ ├── DisassembleX86-64.mjs │ │ ├── gost │ │ ├── gostCipher.mjs │ │ ├── gostCoding.mjs │ │ ├── gostCrypto.mjs │ │ ├── gostDigest.mjs │ │ ├── gostEngine.mjs │ │ ├── gostRandom.mjs │ │ └── gostSign.mjs │ │ ├── remove-exif.mjs │ │ └── tesseract │ │ └── lang-data │ │ └── eng.traineddata.gz ├── node │ ├── File.mjs │ ├── NodeDish.mjs │ ├── NodeRecipe.mjs │ ├── api.mjs │ ├── apiUtils.mjs │ ├── config │ │ ├── excludedOperations.mjs │ │ └── scripts │ │ │ └── generateNodeIndex.mjs │ ├── repl.mjs │ └── wrapper.js └── web │ ├── App.mjs │ ├── HTMLCategory.mjs │ ├── HTMLIngredient.mjs │ ├── HTMLOperation.mjs │ ├── Manager.mjs │ ├── html │ └── index.html │ ├── index.js │ ├── static │ ├── fonts │ │ ├── MaterialIcons-Regular.ttf │ │ └── bmfonts │ │ │ ├── Roboto72White.fnt │ │ │ ├── Roboto72White.png │ │ │ ├── RobotoBlack72White.fnt │ │ │ ├── RobotoBlack72White.png │ │ │ ├── RobotoMono72White.fnt │ │ │ ├── RobotoMono72White.png │ │ │ ├── RobotoSlab72White.fnt │ │ │ └── RobotoSlab72White.png │ ├── ga.html │ ├── images │ │ ├── IMAGE_LICENCES.md │ │ ├── bombe.svg │ │ ├── cook_female-32x32.png │ │ ├── cook_male-32x32.png │ │ ├── cyberchef-128x128.png │ │ ├── cyberchef-256x256.png │ │ ├── cyberchef-32x32.png │ │ ├── cyberchef-512x512.png │ │ ├── cyberchef-64x64.png │ │ ├── favicon.ico │ │ ├── file-128x128.png │ │ ├── file-32x32.png │ │ ├── fork_me.png │ │ ├── gitter-badge.svg │ │ └── logo │ │ │ ├── cyberchef.svg │ │ │ ├── cyberchef_512.png │ │ │ ├── cyberchef_banner.svg │ │ │ ├── cyberchef_banner_1500.png │ │ │ ├── cyberchef_hat.svg │ │ │ ├── cyberchef_hat_512.png │ │ │ ├── cyberchef_hat_text_512.png │ │ │ ├── cyberchef_human.svg │ │ │ └── cyberchef_robot.svg │ ├── sitemap.mjs │ └── structuredData.json │ ├── stylesheets │ ├── components │ │ ├── _button.css │ │ ├── _list.css │ │ ├── _operation.css │ │ └── _pane.css │ ├── index.css │ ├── index.js │ ├── layout │ │ ├── _banner.css │ │ ├── _controls.css │ │ ├── _io.css │ │ ├── _modals.css │ │ ├── _operations.css │ │ ├── _recipe.css │ │ └── _structure.css │ ├── operations │ │ ├── diff.css │ │ └── json.css │ ├── preloader.css │ ├── themes │ │ ├── _classic.css │ │ ├── _dark.css │ │ ├── _geocities.css │ │ ├── _solarizedDark.css │ │ └── _solarizedLight.css │ └── utils │ │ ├── _general.css │ │ └── _overrides.css │ ├── utils │ ├── copyOverride.mjs │ ├── editorUtils.mjs │ ├── fileDetails.mjs │ ├── htmlWidget.mjs │ ├── sidePanel.mjs │ └── statusBar.mjs │ ├── waiters │ ├── BackgroundWorkerWaiter.mjs │ ├── BindingsWaiter.mjs │ ├── ControlsWaiter.mjs │ ├── HighlighterWaiter.mjs │ ├── InputWaiter.mjs │ ├── OperationsWaiter.mjs │ ├── OptionsWaiter.mjs │ ├── OutputWaiter.mjs │ ├── RecipeWaiter.mjs │ ├── SeasonalWaiter.mjs │ ├── TabWaiter.mjs │ ├── TimingWaiter.mjs │ ├── WindowWaiter.mjs │ └── WorkerWaiter.mjs │ └── workers │ ├── DishWorker.mjs │ ├── InputWorker.mjs │ ├── LoaderWorker.js │ └── ZipWorker.mjs ├── tests ├── browser │ ├── 00_nightwatch.js │ ├── 01_io.js │ ├── 02_ops.js │ └── browserUtils.js ├── lib │ ├── TestRegister.mjs │ └── utils.mjs ├── node │ ├── assertionHandler.mjs │ ├── consumers │ │ ├── cjs-consumer.js │ │ └── esm-consumer.mjs │ ├── index.mjs │ ├── sampleData │ │ └── pic.jpg │ └── tests │ │ ├── Categories.mjs │ │ ├── Dish.mjs │ │ ├── File.mjs │ │ ├── NodeDish.mjs │ │ ├── Utils.mjs │ │ ├── nodeApi.mjs │ │ └── operations.mjs ├── operations │ ├── index.mjs │ └── tests │ │ ├── AESKeyWrap.mjs │ │ ├── AlternatingCaps.mjs │ │ ├── AvroToJSON.mjs │ │ ├── BCD.mjs │ │ ├── BLAKE2b.mjs │ │ ├── BLAKE2s.mjs │ │ ├── BLAKE3.mjs │ │ ├── BSON.mjs │ │ ├── BaconCipher.mjs │ │ ├── Base32.mjs │ │ ├── Base45.mjs │ │ ├── Base58.mjs │ │ ├── Base62.mjs │ │ ├── Base64.mjs │ │ ├── Base85.mjs │ │ ├── Base92.mjs │ │ ├── BitwiseOp.mjs │ │ ├── Bombe.mjs │ │ ├── ByteRepr.mjs │ │ ├── CBORDecode.mjs │ │ ├── CBOREncode.mjs │ │ ├── CMAC.mjs │ │ ├── CRCChecksum.mjs │ │ ├── CSV.mjs │ │ ├── CaesarBoxCipher.mjs │ │ ├── CaretMdecode.mjs │ │ ├── CartesianProduct.mjs │ │ ├── CetaceanCipherDecode.mjs │ │ ├── CetaceanCipherEncode.mjs │ │ ├── ChaCha.mjs │ │ ├── ChangeIPFormat.mjs │ │ ├── CharEnc.mjs │ │ ├── Charts.mjs │ │ ├── CipherSaber2.mjs │ │ ├── Ciphers.mjs │ │ ├── Code.mjs │ │ ├── Colossus.mjs │ │ ├── Comment.mjs │ │ ├── Compress.mjs │ │ ├── ConditionalJump.mjs │ │ ├── ConvertCoordinateFormat.mjs │ │ ├── ConvertLeetSpeak.mjs │ │ ├── ConvertToNATOAlphabet.mjs │ │ ├── Crypt.mjs │ │ ├── DateTime.mjs │ │ ├── DefangIP.mjs │ │ ├── DropNthBytes.mjs │ │ ├── ECDSA.mjs │ │ ├── ELFInfo.mjs │ │ ├── Enigma.mjs │ │ ├── ExtractEmailAddresses.mjs │ │ ├── ExtractHashes.mjs │ │ ├── ExtractIPAddresses.mjs │ │ ├── Fernet.mjs │ │ ├── FileTree.mjs │ │ ├── FletcherChecksum.mjs │ │ ├── Float.mjs │ │ ├── Fork.mjs │ │ ├── FromDecimal.mjs │ │ ├── GOST.mjs │ │ ├── GenerateAllChecksums.mjs │ │ ├── GenerateAllHashes.mjs │ │ ├── GenerateDeBruijnSequence.mjs │ │ ├── GetAllCasings.mjs │ │ ├── Gunzip.mjs │ │ ├── Gzip.mjs │ │ ├── HASSH.mjs │ │ ├── HKDF.mjs │ │ ├── Hash.mjs │ │ ├── HaversineDistance.mjs │ │ ├── Hex.mjs │ │ ├── Hexdump.mjs │ │ ├── IPv6Transition.mjs │ │ ├── Image.mjs │ │ ├── IndexOfCoincidence.mjs │ │ ├── JA3Fingerprint.mjs │ │ ├── JA3SFingerprint.mjs │ │ ├── JA4.mjs │ │ ├── JSONBeautify.mjs │ │ ├── JSONMinify.mjs │ │ ├── JSONtoCSV.mjs │ │ ├── JSONtoYAML.mjs │ │ ├── JWK.mjs │ │ ├── JWTDecode.mjs │ │ ├── JWTSign.mjs │ │ ├── JWTVerify.mjs │ │ ├── Jsonata.mjs │ │ ├── Jump.mjs │ │ ├── LS47.mjs │ │ ├── LZNT1Decompress.mjs │ │ ├── LZString.mjs │ │ ├── LevenshteinDistance.mjs │ │ ├── Lorenz.mjs │ │ ├── LuhnChecksum.mjs │ │ ├── MIMEDecoding.mjs │ │ ├── MS.mjs │ │ ├── Magic.mjs │ │ ├── Media.mjs │ │ ├── Modhex.mjs │ │ ├── MorseCode.mjs │ │ ├── MultipleBombe.mjs │ │ ├── MurmurHash3.mjs │ │ ├── NTLM.mjs │ │ ├── NetBIOS.mjs │ │ ├── NormaliseUnicode.mjs │ │ ├── OTP.mjs │ │ ├── PEMtoHex.mjs │ │ ├── PGP.mjs │ │ ├── PHP.mjs │ │ ├── PHPSerialize.mjs │ │ ├── ParseCSR.mjs │ │ ├── ParseIPRange.mjs │ │ ├── ParseObjectIDTimestamp.mjs │ │ ├── ParseQRCode.mjs │ │ ├── ParseSSHHostKey.mjs │ │ ├── ParseTCP.mjs │ │ ├── ParseTLSRecord.mjs │ │ ├── ParseTLV.mjs │ │ ├── ParseUDP.mjs │ │ ├── ParseX509CRL.mjs │ │ ├── PowerSet.mjs │ │ ├── Protobuf.mjs │ │ ├── PubKeyFromCert.mjs │ │ ├── PubKeyFromPrivKey.mjs │ │ ├── RAKE.mjs │ │ ├── RSA.mjs │ │ ├── Rabbit.mjs │ │ ├── Regex.mjs │ │ ├── Register.mjs │ │ ├── RisonEncodeDecode.mjs │ │ ├── Rotate.mjs │ │ ├── SIGABA.mjs │ │ ├── SM2.mjs │ │ ├── SM4.mjs │ │ ├── Salsa20.mjs │ │ ├── SeqUtils.mjs │ │ ├── SetDifference.mjs │ │ ├── SetIntersection.mjs │ │ ├── SetUnion.mjs │ │ ├── Shuffle.mjs │ │ ├── SplitColourChannels.mjs │ │ ├── StrUtils.mjs │ │ ├── StripIPv4Header.mjs │ │ ├── StripTCPHeader.mjs │ │ ├── StripUDPHeader.mjs │ │ ├── Subsection.mjs │ │ ├── SwapCase.mjs │ │ ├── SymmetricDifference.mjs │ │ ├── TakeNthBytes.mjs │ │ ├── Template.mjs │ │ ├── TextEncodingBruteForce.mjs │ │ ├── ToFromInsensitiveRegex.mjs │ │ ├── TranslateDateTimeFormat.mjs │ │ ├── Typex.mjs │ │ ├── URLEncodeDecode.mjs │ │ ├── UnescapeString.mjs │ │ ├── Unicode.mjs │ │ ├── XORChecksum.mjs │ │ ├── XSalsa20.mjs │ │ ├── XXTEA.mjs │ │ └── YARA.mjs └── samples │ ├── Ciphers.mjs │ ├── Executables.mjs │ ├── Images.mjs │ └── files │ ├── Hitchhikers_Guide.jpeg │ ├── TowelDay.jpeg │ ├── mp3example.mp3 │ └── testocr.png └── webpack.config.js /.cspell.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2", 3 | "language": "en,en-gb", 4 | "words": [], 5 | "dictionaries": [ 6 | "npm", 7 | "softwareTerms", 8 | "node", 9 | "html", 10 | "css", 11 | "bash", 12 | "en-gb", 13 | "misc" 14 | ], 15 | "ignorePaths": ["package.json", "package-lock.json", "node_modules"] 16 | } 17 | -------------------------------------------------------------------------------- /.devcontainer/devcontainer.json: -------------------------------------------------------------------------------- 1 | // For format details, see https://aka.ms/devcontainer.json. For config options, see the 2 | // README at: https://github.com/devcontainers/templates/tree/main/src/javascript-node 3 | { 4 | "name": "CyberChef", 5 | // Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile 6 | "image": "mcr.microsoft.com/devcontainers/javascript-node:1-18-bookworm", 7 | 8 | // Features to add to the dev container. More info: https://containers.dev/features. 9 | "features": { 10 | "ghcr.io/devcontainers/features/github-cli": "latest" 11 | }, 12 | 13 | // Use 'forwardPorts' to make a list of ports inside the container available locally. 14 | "forwardPorts": [8080], 15 | 16 | // Use 'postCreateCommand' to run commands after the container is created. 17 | "postCreateCommand": { 18 | "npm": "bash -c \"sudo chown node node_modules && npm install\"" 19 | }, 20 | 21 | "containerEnv": { 22 | "DISPLAY": ":99" 23 | }, 24 | 25 | "mounts": [ 26 | "source=${localWorkspaceFolderBasename}-node_modules,target=${containerWorkspaceFolder}/node_modules,type=volume" 27 | ], 28 | 29 | // Configure tool-specific properties. 30 | "customizations": { 31 | "vscode": { 32 | "extensions": [ 33 | "dbaeumer.vscode-eslint", 34 | "GitHub.vscode-github-actions" 35 | ] 36 | } 37 | } 38 | 39 | // Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root. 40 | // "remoteUser": "root" 41 | } 42 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | build 3 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # top-most EditorConfig file 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | end_of_line = lf 7 | insert_final_newline = true 8 | trim_trailing_whitespace = true 9 | indent_style = space 10 | indent_size = 4 11 | 12 | [{package.json,.travis.yml,nightwatch.json}] 13 | indent_style = space 14 | indent_size = 2 15 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto eol=lf 2 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug-report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: 'Bug report: ' 5 | labels: bug 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behaviour or a link to the recipe / input used to cause the bug: 15 | 16 | 1. Go to '...' 17 | 2. Click on '....' 18 | 3. Scroll down to '....' 19 | 4. See error 20 | 21 | **Expected behaviour** 22 | A clear and concise description of what you expected to happen. 23 | 24 | **Screenshots** 25 | If applicable, add screenshots to help explain your problem. 26 | 27 | **Desktop (if relevant, please complete the following information):** 28 | - OS: [e.g. Windows] 29 | - Browser: [e.g. chrome 72, firefox 60] 30 | - CyberChef version: [e.g. 9.7.14] 31 | 32 | **Additional context** 33 | Add any other context about the problem here. 34 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature-request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for the project 4 | title: 'Feature request: ' 5 | labels: feature 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. E.g. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/operation-request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Operation request 3 | about: Suggest a new operation 4 | title: 'Operation request: ' 5 | labels: operation 6 | assignees: '' 7 | 8 | --- 9 | 10 | ## Summary 11 | 12 | ### Example Input 13 | 14 | ### Example Output 15 | -------------------------------------------------------------------------------- /.github/workflows/codeql.yml: -------------------------------------------------------------------------------- 1 | name: "CodeQL Analysis" 2 | 3 | on: 4 | workflow_dispatch: 5 | push: 6 | branches: [ master ] 7 | pull_request: 8 | # The branches below must be a subset of the branches above 9 | branches: [ master ] 10 | types: [synchronize, opened, reopened] 11 | schedule: 12 | - cron: '22 17 * * 5' 13 | 14 | jobs: 15 | analyze: 16 | name: Analyze 17 | runs-on: ubuntu-latest 18 | permissions: 19 | actions: read 20 | contents: read 21 | security-events: write 22 | 23 | strategy: 24 | fail-fast: false 25 | matrix: 26 | language: [ 'javascript' ] 27 | 28 | steps: 29 | - name: Checkout repository 30 | uses: actions/checkout@v3 31 | 32 | - name: Initialize CodeQL 33 | uses: github/codeql-action/init@v2 34 | with: 35 | languages: ${{ matrix.language }} 36 | 37 | - name: Perform CodeQL Analysis 38 | uses: github/codeql-action/analyze@v2 39 | with: 40 | category: "/language:${{matrix.language}}" 41 | -------------------------------------------------------------------------------- /.github/workflows/pull_requests.yml: -------------------------------------------------------------------------------- 1 | name: "Pull Requests" 2 | 3 | on: 4 | workflow_dispatch: 5 | pull_request: 6 | types: [synchronize, opened, reopened] 7 | 8 | jobs: 9 | main: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - uses: actions/checkout@v3 13 | 14 | - name: Set node version 15 | uses: actions/setup-node@v3 16 | with: 17 | node-version: '18.x' 18 | 19 | - name: Install 20 | run: | 21 | export DETECT_CHROMEDRIVER_VERSION=true 22 | npm install 23 | npm run setheapsize 24 | 25 | - name: Lint 26 | run: npx grunt lint 27 | 28 | - name: Unit Tests 29 | run: | 30 | npm test 31 | npm run testnodeconsumer 32 | 33 | - name: Production Build 34 | if: success() 35 | run: npx grunt prod 36 | 37 | - name: Production Image Build 38 | if: success() 39 | id: build-image 40 | uses: redhat-actions/buildah-build@v2 41 | with: 42 | # Not being uploaded to any registry, use a simple name to allow Buildah to build correctly. 43 | image: cyberchef 44 | containerfiles: ./Dockerfile 45 | platforms: linux/amd64 46 | oci: true 47 | # Webpack seems to use a lot of open files, increase the max open file limit to accomodate. 48 | extra-args: | 49 | --ulimit nofile=10000 50 | 51 | - name: UI Tests 52 | if: success() 53 | run: | 54 | sudo apt-get install xvfb 55 | xvfb-run --server-args="-screen 0 1200x800x24" npx grunt testui 56 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | npm-debug.log 3 | travis.log 4 | build 5 | .vscode 6 | .idea 7 | .*.swp 8 | src/core/config/modules/* 9 | src/core/config/OperationConfig.json 10 | src/core/operations/index.mjs 11 | src/node/config/OperationConfig.json 12 | src/node/index.mjs 13 | **/*.DS_Store 14 | tests/browser/output/* 15 | .node-version 16 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | npm-debug.log 3 | travis.log 4 | build/* 5 | !build/node 6 | .vscode 7 | .github 8 | -------------------------------------------------------------------------------- /.nvmrc: -------------------------------------------------------------------------------- 1 | 18 2 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | ##################################### 2 | # Build the app to a static website # 3 | ##################################### 4 | # Modifier --platform=$BUILDPLATFORM limits the platform to "BUILDPLATFORM" during buildx multi-platform builds 5 | # This is because npm "chromedriver" package is not compatiable with all platforms 6 | # For more info see: https://docs.docker.com/build/building/multi-platform/#cross-compilation 7 | FROM --platform=$BUILDPLATFORM node:18-alpine AS builder 8 | 9 | WORKDIR /app 10 | 11 | COPY package.json . 12 | COPY package-lock.json . 13 | 14 | # Install dependencies 15 | # --ignore-scripts prevents postinstall script (which runs grunt) as it depends on files other than package.json 16 | RUN npm ci --ignore-scripts 17 | 18 | # Copy files needed for postinstall and build 19 | COPY . . 20 | 21 | # npm postinstall runs grunt, which depends on files other than package.json 22 | RUN npm run postinstall 23 | 24 | # Build the app 25 | RUN npm run build 26 | 27 | ######################################### 28 | # Package static build files into nginx # 29 | ######################################### 30 | # We are using Github Actions: redhat-actions/buildah-build@v2 which needs manual selection of arch in base image 31 | # Remove TARGETARCH if docker buildx is supported in the CI release as --platform=$TARGETPLATFORM will be automatically set 32 | ARG TARGETPLATFORM 33 | FROM --platform=${TARGETPLATFORM} nginx:stable-alpine AS cyberchef 34 | 35 | COPY --from=builder /app/build/prod /usr/share/nginx/html/ 36 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Supported Versions 4 | 5 | CyberChef is supported on a best endeavours basis. Patches will be applied to 6 | the latest version rather than retroactively to older versions. To ensure you 7 | are using the most secure version of CyberChef, please make sure you have the 8 | [latest release](https://github.com/gchq/CyberChef/releases/latest). The 9 | official [live demo](https://gchq.github.io/CyberChef/) is always up to date. 10 | 11 | ## Reporting a Vulnerability 12 | 13 | In most scenarios, the most appropriate way to report a vulnerability is to 14 | [raise a new issue](https://github.com/gchq/CyberChef/issues/new/choose) 15 | describing the problem in as much detail as possible, ideally with examples. 16 | This will obviously be public. If you feel that the vulnerability is 17 | significant enough to warrant a private disclosure, please email 18 | [oss@gchq.gov.uk](mailto:oss@gchq.gov.uk) and 19 | [n1474335@gmail.com](mailto:n1474335@gmail.com). 20 | 21 | Disclosures of vulnerabilities in CyberChef are always welcomed. Whilst we aim 22 | to write clean and secure code free from bugs, we recognise that this is an open 23 | source project written by analysts in their spare time, relying on dozens of 24 | open source libraries that are modified and updated on a regular basis. We hope 25 | that the community will continue to support us as we endeavour to maintain and 26 | develop this tool together. 27 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = function(api) { 2 | api.cache.forever(); 3 | 4 | return { 5 | "presets": [ 6 | ["@babel/preset-env", { 7 | "modules": false, 8 | "useBuiltIns": "entry", 9 | "corejs": 3 10 | }] 11 | ], 12 | "plugins": [ 13 | "dynamic-import-node", 14 | "@babel/plugin-syntax-import-assertions", 15 | [ 16 | "babel-plugin-transform-builtin-extend", { 17 | "globals": ["Error"] 18 | } 19 | ], 20 | [ 21 | "@babel/plugin-transform-runtime", { 22 | "regenerator": true 23 | } 24 | ] 25 | ] 26 | }; 27 | }; 28 | -------------------------------------------------------------------------------- /nightwatch.json: -------------------------------------------------------------------------------- 1 | { 2 | "src_folders": ["tests/browser"], 3 | "exclude": ["tests/browser/browserUtils.js"], 4 | "output_folder": "tests/browser/output", 5 | 6 | "test_settings": { 7 | 8 | "default": { 9 | "launch_url": "http://localhost:8080", 10 | "webdriver": { 11 | "start_process": true, 12 | "server_path": "./node_modules/.bin/chromedriver", 13 | "port": 9515, 14 | "log_path": "tests/browser/output" 15 | }, 16 | "desiredCapabilities": { 17 | "browserName": "chrome" 18 | }, 19 | "enable_fail_fast": true 20 | }, 21 | 22 | "dev": { 23 | "launch_url": "http://localhost:8080" 24 | }, 25 | 26 | "prod": { 27 | "launch_url": "http://localhost:8000/index.html" 28 | } 29 | 30 | } 31 | } 32 | 33 | -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: [ 3 | require("postcss-import"), 4 | require("autoprefixer"), 5 | require("postcss-css-variables")({ 6 | preserve: true 7 | }), 8 | ] 9 | }; 10 | -------------------------------------------------------------------------------- /src/core/dishTypes/DishBigNumber.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * @author d98762625 [d98762625@gmail.com] 3 | * @copyright Crown Copyright 2019 4 | * @license Apache-2.0 5 | */ 6 | 7 | import DishType from "./DishType.mjs"; 8 | import Utils from "../Utils.mjs"; 9 | import BigNumber from "bignumber.js"; 10 | 11 | /** 12 | * translation methods for BigNumber Dishes 13 | */ 14 | class DishBigNumber extends DishType { 15 | 16 | /** 17 | * convert the given value to a ArrayBuffer 18 | * @param {BigNumber} value 19 | */ 20 | static toArrayBuffer() { 21 | DishBigNumber.checkForValue(this.value); 22 | this.value = BigNumber.isBigNumber(this.value) ? Utils.strToArrayBuffer(this.value.toFixed()) : new ArrayBuffer; 23 | } 24 | 25 | /** 26 | * convert the given value from a ArrayBuffer 27 | */ 28 | static fromArrayBuffer() { 29 | DishBigNumber.checkForValue(this.value); 30 | try { 31 | this.value = new BigNumber(Utils.arrayBufferToStr(this.value)); 32 | } catch (err) { 33 | this.value = new BigNumber(NaN); 34 | } 35 | } 36 | } 37 | 38 | export default DishBigNumber; 39 | -------------------------------------------------------------------------------- /src/core/dishTypes/DishByteArray.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * @author d98762625 [d98762625@gmail.com] 3 | * @copyright Crown Copyright 2019 4 | * @license Apache-2.0 5 | */ 6 | 7 | import DishType from "./DishType.mjs"; 8 | 9 | /** 10 | * Translation methods for ArrayBuffer Dishes 11 | */ 12 | class DishByteArray extends DishType { 13 | 14 | /** 15 | * convert the given value to a ArrayBuffer 16 | */ 17 | static toArrayBuffer() { 18 | DishByteArray.checkForValue(this.value); 19 | this.value = new Uint8Array(this.value).buffer; 20 | } 21 | 22 | /** 23 | * convert the given value from a ArrayBuffer 24 | */ 25 | static fromArrayBuffer() { 26 | DishByteArray.checkForValue(this.value); 27 | this.value = Array.prototype.slice.call(new Uint8Array(this.value)); 28 | } 29 | } 30 | 31 | export default DishByteArray; 32 | -------------------------------------------------------------------------------- /src/core/dishTypes/DishFile.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * @author d98762625 [d98762625@gmail.com] 3 | * @copyright Crown Copyright 2019 4 | * @license Apache-2.0 5 | */ 6 | 7 | import DishType from "./DishType.mjs"; 8 | import Utils, { isNodeEnvironment } from "../Utils.mjs"; 9 | 10 | /** 11 | * Translation methods for file Dishes 12 | */ 13 | class DishFile extends DishType { 14 | 15 | /** 16 | * convert the given value to an ArrayBuffer 17 | * @param {File} value 18 | */ 19 | static toArrayBuffer() { 20 | DishFile.checkForValue(this.value); 21 | if (isNodeEnvironment()) { 22 | this.value = Utils.readFileSync(this.value); 23 | } else { 24 | return new Promise((resolve, reject) => { 25 | Utils.readFile(this.value) 26 | .then(v => this.value = v.buffer) 27 | .then(resolve) 28 | .catch(reject); 29 | }); 30 | } 31 | } 32 | 33 | /** 34 | * convert the given value from an ArrayBuffer 35 | */ 36 | static fromArrayBuffer() { 37 | DishFile.checkForValue(this.value); 38 | this.value = new File(this.value, "unknown"); 39 | } 40 | } 41 | 42 | export default DishFile; 43 | -------------------------------------------------------------------------------- /src/core/dishTypes/DishHTML.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * @author d98762625 [d98762625@gmail.com] 3 | * @copyright Crown Copyright 2019 4 | * @license Apache-2.0 5 | */ 6 | 7 | import DishString from "./DishString.mjs"; 8 | import Utils from "../Utils.mjs"; 9 | 10 | /** 11 | * Translation methods for HTML Dishes 12 | */ 13 | class DishHTML extends DishString { 14 | 15 | /** 16 | * convert the given value to a ArrayBuffer 17 | * @param {String} value 18 | */ 19 | static toArrayBuffer() { 20 | DishHTML.checkForValue(this.value); 21 | this.value = this.value ? Utils.strToArrayBuffer(Utils.unescapeHtml(Utils.stripHtmlTags(this.value, true))) : new ArrayBuffer; 22 | } 23 | 24 | } 25 | 26 | export default DishHTML; 27 | -------------------------------------------------------------------------------- /src/core/dishTypes/DishJSON.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * @author d98762625 [d98762625@gmail.com] 3 | * @copyright Crown Copyright 2019 4 | * @license Apache-2.0 5 | */ 6 | 7 | import DishType from "./DishType.mjs"; 8 | import Utils from "../Utils.mjs"; 9 | 10 | /** 11 | * Translation methods for JSON dishes 12 | */ 13 | class DishJSON extends DishType { 14 | 15 | /** 16 | * convert the given value to a ArrayBuffer 17 | */ 18 | static toArrayBuffer() { 19 | DishJSON.checkForValue(this.value); 20 | this.value = this.value !== undefined ? Utils.strToArrayBuffer(JSON.stringify(this.value, null, 4)) : new ArrayBuffer; 21 | } 22 | 23 | /** 24 | * convert the given value from a ArrayBuffer 25 | */ 26 | static fromArrayBuffer() { 27 | DishJSON.checkForValue(this.value); 28 | this.value = JSON.parse(Utils.arrayBufferToStr(this.value)); 29 | } 30 | } 31 | 32 | export default DishJSON; 33 | -------------------------------------------------------------------------------- /src/core/dishTypes/DishNumber.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * @author d98762625 [d98762625@gmail.com] 3 | * @copyright Crown Copyright 2019 4 | * @license Apache-2.0 5 | */ 6 | 7 | 8 | import DishType from "./DishType.mjs"; 9 | import Utils from "../Utils.mjs"; 10 | 11 | /** 12 | * Translation methods for number dishes 13 | */ 14 | class DishNumber extends DishType { 15 | 16 | /** 17 | * convert the given value to a ArrayBuffer 18 | */ 19 | static toArrayBuffer() { 20 | DishNumber.checkForValue(this.value); 21 | this.value = typeof this.value === "number" ? Utils.strToArrayBuffer(this.value.toString()) : new ArrayBuffer; 22 | } 23 | 24 | /** 25 | * convert the given value from a ArrayBuffer 26 | */ 27 | static fromArrayBuffer() { 28 | DishNumber.checkForValue(this.value); 29 | this.value = this.value ? parseFloat(Utils.arrayBufferToStr(this.value)) : 0; 30 | } 31 | } 32 | 33 | export default DishNumber; 34 | -------------------------------------------------------------------------------- /src/core/dishTypes/DishString.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * @author d98762625 [d98762625@gmail.com] 3 | * @copyright Crown Copyright 2019 4 | * @license Apache-2.0 5 | */ 6 | 7 | 8 | import DishType from "./DishType.mjs"; 9 | import Utils from "../Utils.mjs"; 10 | 11 | /** 12 | * Translation methods for string dishes 13 | */ 14 | class DishString extends DishType { 15 | 16 | /** 17 | * convert the given value to a ArrayBuffer 18 | */ 19 | static toArrayBuffer() { 20 | DishString.checkForValue(this.value); 21 | this.value = this.value ? Utils.strToArrayBuffer(this.value) : new ArrayBuffer; 22 | } 23 | 24 | /** 25 | * convert the given value from a ArrayBuffer 26 | */ 27 | static fromArrayBuffer() { 28 | DishString.checkForValue(this.value); 29 | this.value = this.value ? Utils.arrayBufferToStr(this.value) : ""; 30 | } 31 | } 32 | 33 | export default DishString; 34 | -------------------------------------------------------------------------------- /src/core/dishTypes/DishType.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * @author d98762625 [d98762625@gmail.com] 3 | * @copyright Crown Copyright 2019 4 | * @license Apache-2.0 5 | */ 6 | 7 | 8 | /** 9 | * Abstract class for dish translation methods 10 | */ 11 | class DishType { 12 | 13 | /** 14 | * Warn translations dont work without value from bind 15 | */ 16 | static checkForValue(value) { 17 | if (value === undefined) { 18 | throw new Error("only use translation methods with .bind"); 19 | } 20 | } 21 | 22 | /** 23 | * convert the given value to a ArrayBuffer 24 | * @param {*} value 25 | */ 26 | static toArrayBuffer() { 27 | throw new Error("toArrayBuffer has not been implemented"); 28 | } 29 | 30 | /** 31 | * convert the given value from a ArrayBuffer 32 | */ 33 | static fromArrayBuffer() { 34 | throw new Error("fromArrayBuffer has not been implemented"); 35 | } 36 | } 37 | 38 | export default DishType; 39 | -------------------------------------------------------------------------------- /src/core/dishTypes/index.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * @author d98762625 [d98762625@gmail.com] 3 | * @copyright Crown Copyright 2019 4 | * @license Apache-2.0 5 | */ 6 | 7 | 8 | import DishByteArray from "./DishByteArray.mjs"; 9 | import DishBigNumber from "./DishBigNumber.mjs"; 10 | import DishFile from "./DishFile.mjs"; 11 | import DishHTML from "./DishHTML.mjs"; 12 | import DishJSON from "./DishJSON.mjs"; 13 | import DishListFile from "./DishListFile.mjs"; 14 | import DishNumber from "./DishNumber.mjs"; 15 | import DishString from "./DishString.mjs"; 16 | 17 | export { 18 | DishByteArray, 19 | DishBigNumber, 20 | DishFile, 21 | DishHTML, 22 | DishJSON, 23 | DishListFile, 24 | DishNumber, 25 | DishString, 26 | }; 27 | -------------------------------------------------------------------------------- /src/core/errors/DishError.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * Custom error type for handling Dish type errors. 3 | * i.e. where the Dish cannot be successfully translated between types 4 | * 5 | * @author n1474335 [n1474335@gmail.com] 6 | * @copyright Crown Copyright 2018 7 | * @license Apache-2.0 8 | */ 9 | class DishError extends Error { 10 | /** 11 | * Standard error constructor. Adds no new behaviour. 12 | * 13 | * @param args - Standard error args 14 | */ 15 | constructor(...args) { 16 | super(...args); 17 | 18 | this.type = "DishError"; 19 | 20 | if (Error.captureStackTrace) { 21 | Error.captureStackTrace(this, DishError); 22 | } 23 | } 24 | } 25 | 26 | export default DishError; 27 | -------------------------------------------------------------------------------- /src/core/errors/ExcludedOperationError.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * Custom error type for handling operation that isnt included in node.js API 3 | * 4 | * @author d98762625 [d98762625@gmail.com] 5 | * @copyright Crown Copyright 2018 6 | * @license Apache-2.0 7 | */ 8 | class ExcludedOperationError extends Error { 9 | /** 10 | * Standard error constructor. Adds no new behaviour. 11 | * 12 | * @param args - Standard error args 13 | */ 14 | constructor(...args) { 15 | super(...args); 16 | 17 | this.type = "ExcludedOperationError"; 18 | 19 | if (Error.captureStackTrace) { 20 | Error.captureStackTrace(this, ExcludedOperationError); 21 | } 22 | } 23 | } 24 | 25 | export default ExcludedOperationError; 26 | -------------------------------------------------------------------------------- /src/core/errors/OperationError.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * Custom error type for handling operation input errors. 3 | * i.e. where the operation can handle the error and print a message to the screen. 4 | * 5 | * @author d98762625 [d98762625@gmail.com] 6 | * @copyright Crown Copyright 2018 7 | * @license Apache-2.0 8 | */ 9 | class OperationError extends Error { 10 | /** 11 | * Standard error constructor. Adds no new behaviour. 12 | * 13 | * @param args - Standard error args 14 | */ 15 | constructor(...args) { 16 | super(...args); 17 | 18 | this.type = "OperationError"; 19 | 20 | if (Error.captureStackTrace) { 21 | Error.captureStackTrace(this, OperationError); 22 | } 23 | } 24 | } 25 | 26 | export default OperationError; 27 | -------------------------------------------------------------------------------- /src/core/errors/index.mjs: -------------------------------------------------------------------------------- 1 | import OperationError from "./OperationError.mjs"; 2 | import DishError from "./DishError.mjs"; 3 | import ExcludedOperationError from "./ExcludedOperationError.mjs"; 4 | 5 | export { 6 | OperationError, 7 | DishError, 8 | ExcludedOperationError, 9 | }; 10 | -------------------------------------------------------------------------------- /src/core/lib/BCD.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * Binary Code Decimal resources. 3 | * 4 | * @author n1474335 [n1474335@gmail.com] 5 | * @copyright Crown Copyright 2017 6 | * @license Apache-2.0 7 | */ 8 | 9 | /** 10 | * BCD encoding schemes. 11 | */ 12 | export const ENCODING_SCHEME = [ 13 | "8 4 2 1", 14 | "7 4 2 1", 15 | "4 2 2 1", 16 | "2 4 2 1", 17 | "8 4 -2 -1", 18 | "Excess-3", 19 | "IBM 8 4 2 1", 20 | ]; 21 | 22 | /** 23 | * Lookup table for the binary value of each digit representation. 24 | * 25 | * I wrote a very nice algorithm to generate 8 4 2 1 encoding programmatically, 26 | * but unfortunately it's much easier (if less elegant) to use lookup tables 27 | * when supporting multiple encoding schemes. 28 | * 29 | * "Practicality beats purity" - PEP 20 30 | * 31 | * In some schemes it is possible to represent the same value in multiple ways. 32 | * For instance, in 4 2 2 1 encoding, 0100 and 0010 both represent 2. Support 33 | * has not yet been added for this. 34 | */ 35 | export const ENCODING_LOOKUP = { 36 | "8 4 2 1": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], 37 | "7 4 2 1": [0, 1, 2, 3, 4, 5, 6, 8, 9, 10], 38 | "4 2 2 1": [0, 1, 4, 5, 8, 9, 12, 13, 14, 15], 39 | "2 4 2 1": [0, 1, 2, 3, 4, 11, 12, 13, 14, 15], 40 | "8 4 -2 -1": [0, 7, 6, 5, 4, 11, 10, 9, 8, 15], 41 | "Excess-3": [3, 4, 5, 6, 7, 8, 9, 10, 11, 12], 42 | "IBM 8 4 2 1": [10, 1, 2, 3, 4, 5, 6, 7, 8, 9], 43 | }; 44 | 45 | /** 46 | * BCD formats. 47 | */ 48 | export const FORMAT = ["Nibbles", "Bytes", "Raw"]; 49 | -------------------------------------------------------------------------------- /src/core/lib/Base32.mjs: -------------------------------------------------------------------------------- 1 | // import Utils from "../Utils.mjs"; 2 | 3 | /** 4 | * Base32 resources. 5 | * 6 | * @author Peter C-S [petercs@purelymail.com] 7 | * @license Apache-2.0 8 | */ 9 | 10 | /** 11 | * Base32 alphabets. 12 | */ 13 | export const ALPHABET_OPTIONS = [ 14 | { 15 | name: "Standard", // https://www.rfc-editor.org/rfc/rfc4648#section-6 16 | value: "A-Z2-7=", 17 | }, 18 | { 19 | name: "Hex Extended", // https://www.rfc-editor.org/rfc/rfc4648#section-7 20 | value: "0-9A-V=", 21 | }, 22 | ]; 23 | 24 | -------------------------------------------------------------------------------- /src/core/lib/Base45.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * Base45 resources. 3 | * 4 | * @author Thomas Weißschuh [thomas@t-8ch.de] 5 | * @copyright Crown Copyright 2021 6 | * @license Apache-2.0 7 | */ 8 | 9 | /** 10 | * Highlight to Base45 11 | */ 12 | export function highlightToBase45(pos, args) { 13 | pos[0].start = Math.floor(pos[0].start / 2) * 3; 14 | pos[0].end = Math.ceil(pos[0].end / 2) * 3; 15 | return pos; 16 | } 17 | 18 | /** 19 | * Highlight from Base45 20 | */ 21 | export function highlightFromBase45(pos, args) { 22 | pos[0].start = Math.floor(pos[0].start / 3) * 2; 23 | pos[0].end = Math.ceil(pos[0].end / 3) * 2; 24 | return pos; 25 | } 26 | 27 | export const ALPHABET = "0-9A-Z $%*+\\-./:"; 28 | -------------------------------------------------------------------------------- /src/core/lib/Base58.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * Base58 resources. 3 | * 4 | * @author tlwr [toby@toby.codes] 5 | * @author n1474335 [n1474335@gmail.com] 6 | * @copyright Crown Copyright 2017 7 | * @license Apache-2.0 8 | */ 9 | 10 | /** 11 | * Base58 alphabet options. 12 | */ 13 | export const ALPHABET_OPTIONS = [ 14 | { 15 | name: "Bitcoin", 16 | value: "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz", 17 | }, 18 | { 19 | name: "Ripple", 20 | value: "rpshnaf39wBUDNEGHJKLM4PQRST7VWXYZ2bcdeCg65jkm8oFqi1tuvAxyz", 21 | }, 22 | ]; 23 | -------------------------------------------------------------------------------- /src/core/lib/Base85.mjs: -------------------------------------------------------------------------------- 1 | import Utils from "../Utils.mjs"; 2 | 3 | /** 4 | * Base85 resources. 5 | * 6 | * @author PenguinGeorge [george@penguingeorge.com] 7 | * @copyright Crown Copyright 2018 8 | * @license Apache-2.0 9 | */ 10 | 11 | /** 12 | * Base85 alphabet options. 13 | */ 14 | export const ALPHABET_OPTIONS = [ 15 | { 16 | name: "Standard", 17 | value: "!-u", 18 | }, 19 | { 20 | name: "Z85 (ZeroMQ)", 21 | value: "0-9a-zA-Z.\\-:+=^!/*?&<>()[]{}@%$#", 22 | }, 23 | { 24 | name: "IPv6", 25 | value: "0-9A-Za-z!#$%&()*+\\-;<=>?@^_`{|}~", 26 | } 27 | ]; 28 | 29 | 30 | /** 31 | * Returns the name of the alphabet, when given the alphabet. 32 | * 33 | * @param {string} alphabet 34 | * @returns {string} 35 | */ 36 | export function alphabetName(alphabet) { 37 | alphabet = escape(alphabet); 38 | let name; 39 | 40 | ALPHABET_OPTIONS.forEach(function(a) { 41 | const expanded = Utils.expandAlphRange(a.value).join(""); 42 | if (alphabet === escape(expanded)) name = a.name; 43 | }); 44 | 45 | return name; 46 | } 47 | -------------------------------------------------------------------------------- /src/core/lib/Base92.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * Base92 resources. 3 | * 4 | * @author sg5506844 [sg5506844@gmail.com] 5 | * @copyright Crown Copyright 2021 6 | * @license Apache-2.0 7 | */ 8 | 9 | import OperationError from "../errors/OperationError.mjs"; 10 | 11 | /** 12 | * Base92 alphabet char 13 | * 14 | * @param {number} val 15 | * @returns {number} 16 | */ 17 | export function base92Chr(val) { 18 | if (val < 0 || val >= 91) { 19 | throw new OperationError("Invalid value"); 20 | } 21 | if (val === 0) 22 | return "!".charCodeAt(0); 23 | else if (val <= 61) 24 | return "#".charCodeAt(0) + val - 1; 25 | else 26 | return "a".charCodeAt(0) + val - 62; 27 | } 28 | 29 | /** 30 | * Base92 alphabet ord 31 | * 32 | * @param {string} val 33 | * @returns {number} 34 | */ 35 | export function base92Ord(val) { 36 | if (val === "!") 37 | return 0; 38 | else if ("#" <= val && val <= "_") 39 | return val.charCodeAt(0) - "#".charCodeAt(0) + 1; 40 | else if ("a" <= val && val <= "}") 41 | return val.charCodeAt(0) - "a".charCodeAt(0) + 62; 42 | throw new OperationError(`${val} is not a base92 character`); 43 | } 44 | 45 | -------------------------------------------------------------------------------- /src/core/lib/Braille.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * Braille resources. 3 | * 4 | * @author n1474335 [n1474335@gmail.com] 5 | * @copyright Crown Copyright 2018 6 | * @license Apache-2.0 7 | */ 8 | 9 | /** 10 | * Braille lookup table. 11 | */ 12 | export const BRAILLE_LOOKUP = { 13 | ascii: " A1B'K2L@CIF/MSP\"E3H9O6R^DJG>NTQ,*5<-U8V.%[$+X!&;:4\\0Z7(_?W]#Y)=", 14 | dot6: "⠀⠁⠂⠃⠄⠅⠆⠇⠈⠉⠊⠋⠌⠍⠎⠏⠐⠑⠒⠓⠔⠕⠖⠗⠘⠙⠚⠛⠜⠝⠞⠟⠠⠡⠢⠣⠤⠥⠦⠧⠨⠩⠪⠫⠬⠭⠮⠯⠰⠱⠲⠳⠴⠵⠶⠷⠸⠹⠺⠻⠼⠽⠾⠿" 15 | }; 16 | -------------------------------------------------------------------------------- /src/core/lib/CipherSaber2.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * @author n1073645 [n1073645@gmail.com] 3 | * @copyright Crown Copyright 2020 4 | * @license Apache-2.0 5 | */ 6 | export function encode(tempIVP, key, rounds, input) { 7 | const ivp = new Uint8Array([...key, ...tempIVP]); 8 | const state = new Array(256).fill(0); 9 | let j = 0, i = 0; 10 | const result = []; 11 | 12 | // Mixing states based off of IV. 13 | for (let i = 0; i < 256; i++) 14 | state[i] = i; 15 | const ivpLength = ivp.length; 16 | for (let r = 0; r < rounds; r ++) { 17 | for (let k = 0; k < 256; k++) { 18 | j = (j + state[k] + ivp[k % ivpLength]) % 256; 19 | [state[k], state[j]] = [state[j], state[k]]; 20 | } 21 | } 22 | j = 0; 23 | i = 0; 24 | 25 | // XOR cipher with key. 26 | for (let x = 0; x < input.length; x++) { 27 | i = (++i) % 256; 28 | j = (j + state[i]) % 256; 29 | [state[i], state[j]] = [state[j], state[i]]; 30 | const n = (state[i] + state[j]) % 256; 31 | result.push(state[n] ^ input[x]); 32 | } 33 | return result; 34 | } 35 | -------------------------------------------------------------------------------- /src/core/lib/Code.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * Code resources. 3 | * 4 | * @author n1474335 [n1474335@gmail.com] 5 | * @copyright Crown Copyright 2018 6 | * @license Apache-2.0 7 | */ 8 | 9 | /** 10 | * This tries to rename variable names in a code snippet according to a function. 11 | * 12 | * @param {string} input 13 | * @param {function} replacer - This function will be fed the token which should be renamed. 14 | * @returns {string} 15 | */ 16 | export function replaceVariableNames(input, replacer) { 17 | const tokenRegex = /\\"|"(?:\\"|[^"])*"|(\b[a-z0-9\-_]+\b)/ig; 18 | 19 | return input.replace(tokenRegex, (...args) => { 20 | const match = args[0], 21 | quotes = args[1]; 22 | 23 | if (!quotes) { 24 | return match; 25 | } else { 26 | return replacer(match); 27 | } 28 | }); 29 | } 30 | -------------------------------------------------------------------------------- /src/core/lib/Crypt.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * Crypt resources. 3 | * 4 | * @author n1474335 [n1474335@gmail.com] 5 | * @copyright Crown Copyright 2021 6 | * @license Apache-2.0 7 | */ 8 | 9 | export const cryptNotice = "WARNING: Cryptographic operations in CyberChef should not be relied upon to provide security in any situation. No guarantee is offered for their correctness. We advise you not to use keys generated from CyberChef in operational contexts."; 10 | -------------------------------------------------------------------------------- /src/core/lib/Decimal.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * Decimal functions. 3 | * 4 | * @author n1474335 [n1474335@gmail.com] 5 | * @copyright Crown Copyright 2018 6 | * @license Apache-2.0 7 | */ 8 | 9 | import Utils from "../Utils.mjs"; 10 | 11 | 12 | /** 13 | * Convert a string of decimal values into a byte array. 14 | * 15 | * @param {string} data 16 | * @param {string} [delim] 17 | * @returns {byteArray} 18 | * 19 | * @example 20 | * // returns [10,20,30] 21 | * fromDecimal("10 20 30"); 22 | * 23 | * // returns [10,20,30] 24 | * fromDecimal("10:20:30", "Colon"); 25 | */ 26 | export function fromDecimal(data, delim="Auto") { 27 | delim = Utils.charRep(delim); 28 | const output = []; 29 | let byteStr = data.split(delim); 30 | if (byteStr[byteStr.length-1] === "") 31 | byteStr = byteStr.slice(0, byteStr.length-1); 32 | 33 | for (let i = 0; i < byteStr.length; i++) { 34 | output[i] = parseInt(byteStr[i], 10); 35 | } 36 | return output; 37 | } 38 | -------------------------------------------------------------------------------- /src/core/lib/FlowControl.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * Flow control functions 3 | * 4 | * @author d98762625 [d98762625@gmail.com] 5 | * @copyright Crown Copyright 2018 6 | * @license Apache-2.0 7 | */ 8 | 9 | /** 10 | * Returns the index of a label. 11 | * 12 | * @param {Object} state - The current state of the recipe. 13 | * @param {string} name - The label name to look for. 14 | * @returns {number} 15 | */ 16 | export function getLabelIndex(name, state) { 17 | return state.opList.findIndex((operation) => { 18 | return (operation.name === "Label") && (name === operation.ingValues[0]); 19 | }); 20 | } 21 | -------------------------------------------------------------------------------- /src/core/lib/Hash.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * Hashing resources. 3 | * 4 | * @author n1474335 [n1474335@gmail.com] 5 | * 6 | * @copyright Crown Copyright 2016 7 | * @license Apache-2.0 8 | */ 9 | 10 | import Utils from "../Utils.mjs"; 11 | import CryptoApi from "crypto-api/src/crypto-api.mjs"; 12 | 13 | 14 | /** 15 | * Generic hash function. 16 | * 17 | * @param {string} name 18 | * @param {ArrayBuffer} input 19 | * @param {Object} [options={}] 20 | * @returns {string} 21 | */ 22 | export function runHash(name, input, options={}) { 23 | const msg = Utils.arrayBufferToStr(input, false), 24 | hasher = CryptoApi.getHasher(name, options); 25 | hasher.update(msg); 26 | return CryptoApi.encoder.toHex(hasher.finalize()); 27 | } 28 | 29 | -------------------------------------------------------------------------------- /src/core/lib/JWT.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * JWT resources 3 | * 4 | * @author mt3571 [mt3571@protonmail.com] 5 | * @copyright Crown Copyright 2020 6 | * @license Apache-2.0 7 | */ 8 | 9 | 10 | /** 11 | * List of the JWT algorithms that can be used 12 | */ 13 | export const JWT_ALGORITHMS = [ 14 | "HS256", 15 | "HS384", 16 | "HS512", 17 | "RS256", 18 | "RS384", 19 | "RS512", 20 | "ES256", 21 | "ES384", 22 | "ES512", 23 | "None" 24 | ]; 25 | -------------------------------------------------------------------------------- /src/core/lib/LZString.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * lz-string exports. 3 | * 4 | * @author crespyl [peter@crespyl.net] 5 | * @copyright Peter Jacobs 2021 6 | * @license Apache-2.0 7 | */ 8 | 9 | import LZString from "lz-string"; 10 | 11 | export const COMPRESSION_OUTPUT_FORMATS = ["default", "UTF16", "Base64"]; 12 | export const COMPRESSION_FUNCTIONS = { 13 | "default": LZString.compress, 14 | "UTF16": LZString.compressToUTF16, 15 | "Base64": LZString.compressToBase64, 16 | }; 17 | export const DECOMPRESSION_FUNCTIONS = { 18 | "default": LZString.decompress, 19 | "UTF16": LZString.decompressFromUTF16, 20 | "Base64": LZString.decompressFromBase64, 21 | }; 22 | -------------------------------------------------------------------------------- /src/core/lib/Protocol.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * Protocol parsing functions. 3 | * 4 | * @author n1474335 [n1474335@gmail.com] 5 | * @copyright Crown Copyright 2022 6 | * @license Apache-2.0 7 | */ 8 | 9 | import BigNumber from "bignumber.js"; 10 | import {toHexFast} from "../lib/Hex.mjs"; 11 | 12 | /** 13 | * Recursively displays a JSON object as an HTML table 14 | * 15 | * @param {Object} obj 16 | * @returns string 17 | */ 18 | export function objToTable(obj, nested=false) { 19 | let html = ``; 22 | if (!nested) 23 | html += ` 24 | 25 | 26 | `; 27 | 28 | for (const key in obj) { 29 | if (typeof obj[key] === "function") 30 | continue; 31 | 32 | html += ``; 33 | if (typeof obj[key] === "object") 34 | html += ``; 35 | else 36 | html += ``; 37 | html += ""; 38 | } 39 | html += "
FieldValue
${key}${objToTable(obj[key], true)}${obj[key]}
"; 40 | return html; 41 | } 42 | 43 | /** 44 | * Converts bytes into a BigNumber string 45 | * @param {Uint8Array} bs 46 | * @returns {string} 47 | */ 48 | export function bytesToLargeNumber(bs) { 49 | return BigNumber(toHexFast(bs), 16).toString(); 50 | } 51 | -------------------------------------------------------------------------------- /src/core/lib/RSA.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * RSA resources. 3 | * 4 | * @author Matt C [me@mitt.dev] 5 | * @copyright Crown Copyright 2021 6 | * @license Apache-2.0 7 | */ 8 | 9 | import forge from "node-forge"; 10 | 11 | export const MD_ALGORITHMS = { 12 | "SHA-1": forge.md.sha1, 13 | "MD5": forge.md.md5, 14 | "SHA-256": forge.md.sha256, 15 | "SHA-384": forge.md.sha384, 16 | "SHA-512": forge.md.sha512, 17 | }; 18 | -------------------------------------------------------------------------------- /src/core/lib/Zlib.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * Zlib exports. 3 | * 4 | * @author n1474335 [n1474335@gmail.com] 5 | * @copyright Crown Copyright 2016 6 | * @license Apache-2.0 7 | */ 8 | 9 | import zlibAndGzip from "zlibjs/bin/zlib_and_gzip.min.js"; 10 | 11 | const Zlib = zlibAndGzip.Zlib; 12 | 13 | export const COMPRESSION_TYPE = ["Dynamic Huffman Coding", "Fixed Huffman Coding", "None (Store)"]; 14 | export const INFLATE_BUFFER_TYPE = ["Adaptive", "Block"]; 15 | export const ZLIB_COMPRESSION_TYPE_LOOKUP = { 16 | "Fixed Huffman Coding": Zlib.Deflate.CompressionType.FIXED, 17 | "Dynamic Huffman Coding": Zlib.Deflate.CompressionType.DYNAMIC, 18 | "None (Store)": Zlib.Deflate.CompressionType.NONE, 19 | }; 20 | -------------------------------------------------------------------------------- /src/core/operations/AddLineNumbers.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * @author n1474335 [n1474335@gmail.com] 3 | * @copyright Crown Copyright 2016 4 | * @license Apache-2.0 5 | */ 6 | 7 | import Operation from "../Operation.mjs"; 8 | 9 | /** 10 | * Add line numbers operation 11 | */ 12 | class AddLineNumbers extends Operation { 13 | 14 | /** 15 | * AddLineNumbers constructor 16 | */ 17 | constructor() { 18 | super(); 19 | 20 | this.name = "Add line numbers"; 21 | this.module = "Default"; 22 | this.description = "Adds line numbers to the output."; 23 | this.inputType = "string"; 24 | this.outputType = "string"; 25 | this.args = [ 26 | { 27 | "name": "Offset", 28 | "type": "number", 29 | "value": 0 30 | } 31 | ]; 32 | } 33 | 34 | /** 35 | * @param {string} input 36 | * @param {Object[]} args 37 | * @returns {string} 38 | */ 39 | run(input, args) { 40 | const lines = input.split("\n"), 41 | width = lines.length.toString().length; 42 | const offset = args[0] ? parseInt(args[0], 10) : 0; 43 | let output = ""; 44 | 45 | for (let n = 0; n < lines.length; n++) { 46 | output += (n+1+offset).toString().padStart(width, " ") + " " + lines[n] + "\n"; 47 | } 48 | return output.slice(0, output.length-1); 49 | } 50 | 51 | } 52 | 53 | export default AddLineNumbers; 54 | -------------------------------------------------------------------------------- /src/core/operations/AnalyseUUID.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * @author n1474335 [n1474335@gmail.com] 3 | * @copyright Crown Copyright 2023 4 | * @license Apache-2.0 5 | */ 6 | 7 | import * as uuid from "uuid"; 8 | 9 | import Operation from "../Operation.mjs"; 10 | import OperationError from "../errors/OperationError.mjs"; 11 | 12 | /** 13 | * Analyse UUID operation 14 | */ 15 | class AnalyseUUID extends Operation { 16 | 17 | /** 18 | * AnalyseUUID constructor 19 | */ 20 | constructor() { 21 | super(); 22 | 23 | this.name = "Analyse UUID"; 24 | this.module = "Crypto"; 25 | this.description = "Tries to determine information about a given UUID and suggests which version may have been used to generate it"; 26 | this.infoURL = "https://wikipedia.org/wiki/Universally_unique_identifier"; 27 | this.inputType = "string"; 28 | this.outputType = "string"; 29 | this.args = []; 30 | } 31 | 32 | /** 33 | * @param {string} input 34 | * @param {Object[]} args 35 | * @returns {string} 36 | */ 37 | run(input, args) { 38 | try { 39 | const uuidVersion = uuid.version(input); 40 | return "UUID version: " + uuidVersion; 41 | } catch (error) { 42 | throw new OperationError("Invalid UUID"); 43 | } 44 | } 45 | 46 | } 47 | 48 | export default AnalyseUUID; 49 | -------------------------------------------------------------------------------- /src/core/operations/Argon2Compare.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * @author Tan Zhen Yong [tzy@beyondthesprawl.com] 3 | * @copyright Crown Copyright 2019 4 | * @license Apache-2.0 5 | */ 6 | 7 | import Operation from "../Operation.mjs"; 8 | import argon2 from "argon2-browser"; 9 | 10 | /** 11 | * Argon2 compare operation 12 | */ 13 | class Argon2Compare extends Operation { 14 | 15 | /** 16 | * Argon2Compare constructor 17 | */ 18 | constructor() { 19 | super(); 20 | 21 | this.name = "Argon2 compare"; 22 | this.module = "Crypto"; 23 | this.description = "Tests whether the input matches the given Argon2 hash. To test multiple possible passwords, use the 'Fork' operation."; 24 | this.infoURL = "https://wikipedia.org/wiki/Argon2"; 25 | this.inputType = "string"; 26 | this.outputType = "string"; 27 | this.args = [ 28 | { 29 | "name": "Encoded hash", 30 | "type": "string", 31 | "value": "" 32 | } 33 | ]; 34 | } 35 | 36 | /** 37 | * @param {string} input 38 | * @param {Object[]} args 39 | * @returns {string} 40 | */ 41 | async run(input, args) { 42 | const encoded = args[0]; 43 | 44 | try { 45 | await argon2.verify({ 46 | pass: input, 47 | encoded 48 | }); 49 | 50 | return `Match: ${input}`; 51 | } catch (err) { 52 | return "No match"; 53 | } 54 | } 55 | 56 | } 57 | 58 | export default Argon2Compare; 59 | -------------------------------------------------------------------------------- /src/core/operations/BcryptParse.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * @author n1474335 [n1474335@gmail.com] 3 | * @copyright Crown Copyright 2016 4 | * @license Apache-2.0 5 | */ 6 | 7 | import Operation from "../Operation.mjs"; 8 | import OperationError from "../errors/OperationError.mjs"; 9 | import bcrypt from "bcryptjs"; 10 | 11 | /** 12 | * Bcrypt parse operation 13 | */ 14 | class BcryptParse extends Operation { 15 | 16 | /** 17 | * BcryptParse constructor 18 | */ 19 | constructor() { 20 | super(); 21 | 22 | this.name = "Bcrypt parse"; 23 | this.module = "Crypto"; 24 | this.description = "Parses a bcrypt hash to determine the number of rounds used, the salt, and the password hash."; 25 | this.infoURL = "https://wikipedia.org/wiki/Bcrypt"; 26 | this.inputType = "string"; 27 | this.outputType = "string"; 28 | this.args = []; 29 | } 30 | 31 | /** 32 | * @param {string} input 33 | * @param {Object[]} args 34 | * @returns {string} 35 | */ 36 | async run(input, args) { 37 | try { 38 | return `Rounds: ${bcrypt.getRounds(input)} 39 | Salt: ${bcrypt.getSalt(input)} 40 | Password hash: ${input.split(bcrypt.getSalt(input))[1]} 41 | Full hash: ${input}`; 42 | } catch (err) { 43 | throw new OperationError("Error: " + err.toString()); 44 | } 45 | } 46 | 47 | } 48 | 49 | export default BcryptParse; 50 | -------------------------------------------------------------------------------- /src/core/operations/CBORDecode.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * @author Danh4 [dan.h4@ncsc.gov.uk] 3 | * @copyright Crown Copyright 2020 4 | * @license Apache-2.0 5 | */ 6 | 7 | import Operation from "../Operation.mjs"; 8 | import Cbor from "cbor"; 9 | 10 | /** 11 | * CBOR Decode operation 12 | */ 13 | class CBORDecode extends Operation { 14 | 15 | /** 16 | * CBORDecode constructor 17 | */ 18 | constructor() { 19 | super(); 20 | 21 | this.name = "CBOR Decode"; 22 | this.module = "Serialise"; 23 | this.description = "Concise Binary Object Representation (CBOR) is a binary data serialization format loosely based on JSON. Like JSON it allows the transmission of data objects that contain name–value pairs, but in a more concise manner. This increases processing and transfer speeds at the cost of human readability. It is defined in IETF RFC 8949."; 24 | this.infoURL = "https://wikipedia.org/wiki/CBOR"; 25 | this.inputType = "ArrayBuffer"; 26 | this.outputType = "JSON"; 27 | this.args = []; 28 | } 29 | 30 | /** 31 | * @param {ArrayBuffer} input 32 | * @param {Object[]} args 33 | * @returns {JSON} 34 | */ 35 | run(input, args) { 36 | return Cbor.decodeFirstSync(Buffer.from(input).toString("hex")); 37 | } 38 | 39 | } 40 | 41 | export default CBORDecode; 42 | -------------------------------------------------------------------------------- /src/core/operations/CBOREncode.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * @author Danh4 [dan.h4@ncsc.gov.uk] 3 | * @copyright Crown Copyright 2020 4 | * @license Apache-2.0 5 | */ 6 | 7 | import Operation from "../Operation.mjs"; 8 | import Cbor from "cbor"; 9 | 10 | /** 11 | * CBOR Encode operation 12 | */ 13 | class CBOREncode extends Operation { 14 | 15 | /** 16 | * CBOREncode constructor 17 | */ 18 | constructor() { 19 | super(); 20 | 21 | this.name = "CBOR Encode"; 22 | this.module = "Serialise"; 23 | this.description = "Concise Binary Object Representation (CBOR) is a binary data serialization format loosely based on JSON. Like JSON it allows the transmission of data objects that contain name–value pairs, but in a more concise manner. This increases processing and transfer speeds at the cost of human readability. It is defined in IETF RFC 8949."; 24 | this.infoURL = "https://wikipedia.org/wiki/CBOR"; 25 | this.inputType = "JSON"; 26 | this.outputType = "ArrayBuffer"; 27 | this.args = []; 28 | } 29 | 30 | /** 31 | * @param {JSON} input 32 | * @param {Object[]} args 33 | * @returns {ArrayBuffer} 34 | */ 35 | run(input, args) { 36 | return new Uint8Array(Cbor.encodeCanonical(input)).buffer; 37 | } 38 | 39 | } 40 | 41 | export default CBOREncode; 42 | -------------------------------------------------------------------------------- /src/core/operations/CSSBeautify.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * @author n1474335 [n1474335@gmail.com] 3 | * @copyright Crown Copyright 2016 4 | * @license Apache-2.0 5 | */ 6 | 7 | import vkbeautify from "vkbeautify"; 8 | import Operation from "../Operation.mjs"; 9 | 10 | /** 11 | * CSS Beautify operation 12 | */ 13 | class CSSBeautify extends Operation { 14 | 15 | /** 16 | * CSSBeautify constructor 17 | */ 18 | constructor() { 19 | super(); 20 | 21 | this.name = "CSS Beautify"; 22 | this.module = "Code"; 23 | this.description = "Indents and prettifies Cascading Style Sheets (CSS) code."; 24 | this.inputType = "string"; 25 | this.outputType = "string"; 26 | this.args = [ 27 | { 28 | "name": "Indent string", 29 | "type": "binaryShortString", 30 | "value": "\\t" 31 | } 32 | ]; 33 | } 34 | 35 | /** 36 | * @param {string} input 37 | * @param {Object[]} args 38 | * @returns {string} 39 | */ 40 | run(input, args) { 41 | const indentStr = args[0]; 42 | return vkbeautify.css(input, indentStr); 43 | } 44 | 45 | } 46 | 47 | export default CSSBeautify; 48 | -------------------------------------------------------------------------------- /src/core/operations/CSSMinify.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * @author n1474335 [n1474335@gmail.com] 3 | * @copyright Crown Copyright 2016 4 | * @license Apache-2.0 5 | */ 6 | 7 | import vkbeautify from "vkbeautify"; 8 | import Operation from "../Operation.mjs"; 9 | 10 | /** 11 | * CSS Minify operation 12 | */ 13 | class CSSMinify extends Operation { 14 | 15 | /** 16 | * CSSMinify constructor 17 | */ 18 | constructor() { 19 | super(); 20 | 21 | this.name = "CSS Minify"; 22 | this.module = "Code"; 23 | this.description = "Compresses Cascading Style Sheets (CSS) code."; 24 | this.inputType = "string"; 25 | this.outputType = "string"; 26 | this.args = [ 27 | { 28 | "name": "Preserve comments", 29 | "type": "boolean", 30 | "value": false 31 | } 32 | ]; 33 | } 34 | 35 | /** 36 | * @param {string} input 37 | * @param {Object[]} args 38 | * @returns {string} 39 | */ 40 | run(input, args) { 41 | const preserveComments = args[0]; 42 | return vkbeautify.cssmin(input, preserveComments); 43 | } 44 | 45 | } 46 | 47 | export default CSSMinify; 48 | -------------------------------------------------------------------------------- /src/core/operations/CTPH.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * @author n1474335 [n1474335@gmail.com] 3 | * @copyright Crown Copyright 2016 4 | * @license Apache-2.0 5 | */ 6 | 7 | import Operation from "../Operation.mjs"; 8 | import ctphjs from "ctph.js"; 9 | 10 | /** 11 | * CTPH operation 12 | */ 13 | class CTPH extends Operation { 14 | 15 | /** 16 | * CTPH constructor 17 | */ 18 | constructor() { 19 | super(); 20 | 21 | this.name = "CTPH"; 22 | this.module = "Crypto"; 23 | this.description = "Context Triggered Piecewise Hashing, also called Fuzzy Hashing, can match inputs that have homologies. Such inputs have sequences of identical bytes in the same order, although bytes in between these sequences may be different in both content and length.

CTPH was originally based on the work of Dr. Andrew Tridgell and a spam email detector called SpamSum. This method was adapted by Jesse Kornblum and published at the DFRWS conference in 2006 in a paper 'Identifying Almost Identical Files Using Context Triggered Piecewise Hashing'."; 24 | this.infoURL = "https://forensics.wiki/context_triggered_piecewise_hashing/"; 25 | this.inputType = "string"; 26 | this.outputType = "string"; 27 | this.args = []; 28 | } 29 | 30 | /** 31 | * @param {string} input 32 | * @param {Object[]} args 33 | * @returns {string} 34 | */ 35 | run(input, args) { 36 | return ctphjs.digest(input); 37 | } 38 | 39 | } 40 | 41 | export default CTPH; 42 | -------------------------------------------------------------------------------- /src/core/operations/CetaceanCipherEncode.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * @author dolphinOnKeys [robin@weird.io] 3 | * @copyright Crown Copyright 2022 4 | * @license Apache-2.0 5 | */ 6 | 7 | import Operation from "../Operation.mjs"; 8 | import {toBinary} from "../lib/Binary.mjs"; 9 | 10 | /** 11 | * Cetacean Cipher Encode operation 12 | */ 13 | class CetaceanCipherEncode extends Operation { 14 | 15 | /** 16 | * CetaceanCipherEncode constructor 17 | */ 18 | constructor() { 19 | super(); 20 | 21 | this.name = "Cetacean Cipher Encode"; 22 | this.module = "Ciphers"; 23 | this.description = "Converts any input into Cetacean Cipher.

e.g. hi becomes EEEEEEEEEeeEeEEEEEEEEEEEEeeEeEEe"; 24 | this.infoURL = "https://hitchhikers.fandom.com/wiki/Dolphins"; 25 | this.inputType = "string"; 26 | this.outputType = "string"; 27 | } 28 | 29 | /** 30 | * @param {string} input 31 | * @param {Object[]} args 32 | * @returns {string} 33 | */ 34 | run(input, args) { 35 | const result = []; 36 | const charArray = input.split(""); 37 | 38 | charArray.map(character => { 39 | if (character === " ") { 40 | result.push(character); 41 | } else { 42 | const binaryArray = toBinary(character.charCodeAt(0), "None", 16).split(""); 43 | result.push(binaryArray.map(str => str === "1" ? "e" : "E").join("")); 44 | } 45 | }); 46 | 47 | return result.join(""); 48 | } 49 | } 50 | 51 | export default CetaceanCipherEncode; 52 | -------------------------------------------------------------------------------- /src/core/operations/ChiSquare.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * @author n1474335 [n1474335@gmail.com] 3 | * @copyright Crown Copyright 2017 4 | * @license Apache-2.0 5 | */ 6 | 7 | import Operation from "../Operation.mjs"; 8 | 9 | /** 10 | * Chi Square operation 11 | */ 12 | class ChiSquare extends Operation { 13 | 14 | /** 15 | * ChiSquare constructor 16 | */ 17 | constructor() { 18 | super(); 19 | 20 | this.name = "Chi Square"; 21 | this.module = "Default"; 22 | this.description = "Calculates the Chi Square distribution of values."; 23 | this.infoURL = "https://wikipedia.org/wiki/Chi-squared_distribution"; 24 | this.inputType = "ArrayBuffer"; 25 | this.outputType = "number"; 26 | this.args = []; 27 | } 28 | 29 | /** 30 | * @param {ArrayBuffer} input 31 | * @param {Object[]} args 32 | * @returns {number} 33 | */ 34 | run(input, args) { 35 | const data = new Uint8Array(input); 36 | const distArray = new Array(256).fill(0); 37 | let total = 0; 38 | 39 | for (let i = 0; i < data.length; i++) { 40 | distArray[data[i]]++; 41 | } 42 | 43 | for (let i = 0; i < distArray.length; i++) { 44 | if (distArray[i] > 0) { 45 | total += Math.pow(distArray[i] - data.length / 256, 2) / (data.length / 256); 46 | } 47 | } 48 | 49 | return total; 50 | } 51 | 52 | } 53 | 54 | export default ChiSquare; 55 | -------------------------------------------------------------------------------- /src/core/operations/CitrixCTX1Encode.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * @author bwhitn [brian.m.whitney@gmail.com] 3 | * @copyright Crown Copyright 2018 4 | * @license Apache-2.0 5 | */ 6 | 7 | import Operation from "../Operation.mjs"; 8 | import cptable from "codepage"; 9 | 10 | /** 11 | * Citrix CTX1 Encode operation 12 | */ 13 | class CitrixCTX1Encode extends Operation { 14 | 15 | /** 16 | * CitrixCTX1Encode constructor 17 | */ 18 | constructor() { 19 | super(); 20 | 21 | this.name = "Citrix CTX1 Encode"; 22 | this.module = "Encodings"; 23 | this.description = "Encodes strings to Citrix CTX1 password format."; 24 | this.infoURL = "https://www.reddit.com/r/AskNetsec/comments/1s3r6y/citrix_ctx1_hash_decoding/"; 25 | this.inputType = "string"; 26 | this.outputType = "byteArray"; 27 | this.args = []; 28 | } 29 | 30 | /** 31 | * @param {string} input 32 | * @param {Object[]} args 33 | * @returns {byteArray} 34 | */ 35 | run(input, args) { 36 | const utf16pass = Array.from(cptable.utils.encode(1200, input)); 37 | const result = []; 38 | let temp = 0; 39 | for (let i = 0; i < utf16pass.length; i++) { 40 | temp = utf16pass[i] ^ 0xa5 ^ temp; 41 | result.push(((temp >>> 4) & 0xf) + 0x41); 42 | result.push((temp & 0xf) + 0x41); 43 | } 44 | 45 | return result; 46 | } 47 | 48 | } 49 | 50 | export default CitrixCTX1Encode; 51 | -------------------------------------------------------------------------------- /src/core/operations/Comment.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * @author n1474335 [n1474335@gmail.com] 3 | * @copyright Crown Copyright 2018 4 | * @license Apache-2.0 5 | */ 6 | 7 | import Operation from "../Operation.mjs"; 8 | 9 | /** 10 | * Comment operation 11 | */ 12 | class Comment extends Operation { 13 | 14 | /** 15 | * Comment constructor 16 | */ 17 | constructor() { 18 | super(); 19 | 20 | this.name = "Comment"; 21 | this.flowControl = true; 22 | this.module = "Default"; 23 | this.description = "Provides a place to write comments within the flow of the recipe. This operation has no computational effect."; 24 | this.inputType = "string"; 25 | this.outputType = "string"; 26 | this.args = [ 27 | { 28 | "name": "", 29 | "type": "text", 30 | "value": "" 31 | } 32 | ]; 33 | } 34 | 35 | /** 36 | * @param {Object} state - The current state of the recipe. 37 | * @param {number} state.progress - The current position in the recipe. 38 | * @param {Dish} state.dish - The Dish being operated on. 39 | * @param {Operation[]} state.opList - The list of operations in the recipe. 40 | * @returns {Object} The updated state of the recipe. 41 | */ 42 | run(state) { 43 | return state; 44 | } 45 | 46 | } 47 | 48 | export default Comment; 49 | -------------------------------------------------------------------------------- /src/core/operations/Divide.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * @author bwhitn [brian.m.whitney@outlook.com] 3 | * @author d98762625 [d98762625@gmail.com] 4 | * @copyright Crown Copyright 2018 5 | * @license Apache-2.0 6 | */ 7 | 8 | import BigNumber from "bignumber.js"; 9 | import Operation from "../Operation.mjs"; 10 | import { div, createNumArray } from "../lib/Arithmetic.mjs"; 11 | import { ARITHMETIC_DELIM_OPTIONS } from "../lib/Delim.mjs"; 12 | 13 | 14 | /** 15 | * Divide operation 16 | */ 17 | class Divide extends Operation { 18 | 19 | /** 20 | * Divide constructor 21 | */ 22 | constructor() { 23 | super(); 24 | 25 | this.name = "Divide"; 26 | this.module = "Default"; 27 | this.description = "Divides a list of numbers. If an item in the string is not a number it is excluded from the list.

e.g. 0x0a 8 .5 becomes 2.5"; 28 | this.inputType = "string"; 29 | this.outputType = "BigNumber"; 30 | this.args = [ 31 | { 32 | "name": "Delimiter", 33 | "type": "option", 34 | "value": ARITHMETIC_DELIM_OPTIONS, 35 | } 36 | ]; 37 | } 38 | 39 | /** 40 | * @param {string} input 41 | * @param {Object[]} args 42 | * @returns {BigNumber} 43 | */ 44 | run(input, args) { 45 | const val = div(createNumArray(input, args[0])); 46 | return BigNumber.isBigNumber(val) ? val : new BigNumber(NaN); 47 | } 48 | 49 | } 50 | 51 | export default Divide; 52 | -------------------------------------------------------------------------------- /src/core/operations/ExpandAlphabetRange.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * @author n1474335 [n1474335@gmail.com] 3 | * @copyright Crown Copyright 2016 4 | * @license Apache-2.0 5 | */ 6 | 7 | import Operation from "../Operation.mjs"; 8 | import Utils from "../Utils.mjs"; 9 | 10 | /** 11 | * Expand alphabet range operation 12 | */ 13 | class ExpandAlphabetRange extends Operation { 14 | 15 | /** 16 | * ExpandAlphabetRange constructor 17 | */ 18 | constructor() { 19 | super(); 20 | 21 | this.name = "Expand alphabet range"; 22 | this.module = "Default"; 23 | this.description = "Expand an alphabet range string into a list of the characters in that range.

e.g. a-z becomes abcdefghijklmnopqrstuvwxyz."; 24 | this.inputType = "string"; 25 | this.outputType = "string"; 26 | this.args = [ 27 | { 28 | "name": "Delimiter", 29 | "type": "binaryString", 30 | "value": "" 31 | } 32 | ]; 33 | } 34 | 35 | /** 36 | * @param {string} input 37 | * @param {Object[]} args 38 | * @returns {string} 39 | */ 40 | run(input, args) { 41 | return Utils.expandAlphRange(input).join(args[0]); 42 | } 43 | 44 | } 45 | 46 | export default ExpandAlphabetRange; 47 | -------------------------------------------------------------------------------- /src/core/operations/FromCaseInsensitiveRegex.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * @author masq [github.cyberchef@masq.cc] 3 | * @copyright Crown Copyright 2018 4 | * @license Apache-2.0 5 | */ 6 | 7 | import Operation from "../Operation.mjs"; 8 | 9 | /** 10 | * From Case Insensitive Regex operation 11 | */ 12 | class FromCaseInsensitiveRegex extends Operation { 13 | 14 | /** 15 | * FromCaseInsensitiveRegex constructor 16 | */ 17 | constructor() { 18 | super(); 19 | 20 | this.name = "From Case Insensitive Regex"; 21 | this.module = "Default"; 22 | this.description = "Converts a case-insensitive regex string to a case sensitive regex string (no guarantee on it being the proper original casing) in case the i flag wasn't available at the time but now is, or you need it to be case-sensitive again.

e.g. [mM][oO][zZ][iI][lL][lL][aA]/[0-9].[0-9] .* becomes Mozilla/[0-9].[0-9] .*"; 23 | this.infoURL = "https://wikipedia.org/wiki/Regular_expression"; 24 | this.inputType = "string"; 25 | this.outputType = "string"; 26 | this.args = []; 27 | } 28 | 29 | /** 30 | * @param {string} input 31 | * @param {Object[]} args 32 | * @returns {string} 33 | */ 34 | run(input, args) { 35 | return input.replace(/\[[a-z]{2}\]/ig, m => m[1].toUpperCase() === m[2].toUpperCase() ? m[1] : m); 36 | } 37 | } 38 | 39 | export default FromCaseInsensitiveRegex; 40 | -------------------------------------------------------------------------------- /src/core/operations/FromMessagePack.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * @author Matt C [matt@artemisbot.uk] 3 | * @copyright Crown Copyright 2018 4 | * @license Apache-2.0 5 | */ 6 | 7 | import Operation from "../Operation.mjs"; 8 | import OperationError from "../errors/OperationError.mjs"; 9 | import notepack from "notepack.io"; 10 | 11 | /** 12 | * From MessagePack operation 13 | */ 14 | class FromMessagePack extends Operation { 15 | 16 | /** 17 | * FromMessagePack constructor 18 | */ 19 | constructor() { 20 | super(); 21 | 22 | this.name = "From MessagePack"; 23 | this.module = "Code"; 24 | this.description = "Converts MessagePack encoded data to JSON. MessagePack is a computer data interchange format. It is a binary form for representing simple data structures like arrays and associative arrays."; 25 | this.infoURL = "https://wikipedia.org/wiki/MessagePack"; 26 | this.inputType = "ArrayBuffer"; 27 | this.outputType = "JSON"; 28 | this.args = []; 29 | } 30 | 31 | /** 32 | * @param {ArrayBuffer} input 33 | * @param {Object[]} args 34 | * @returns {JSON} 35 | */ 36 | run(input, args) { 37 | try { 38 | const buf = Buffer.from(new Uint8Array(input)); 39 | return notepack.decode(buf); 40 | } catch (err) { 41 | throw new OperationError(`Could not decode MessagePack to JSON: ${err}`); 42 | } 43 | } 44 | 45 | } 46 | 47 | export default FromMessagePack; 48 | -------------------------------------------------------------------------------- /src/core/operations/FromPunycode.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * @author n1474335 [n1474335@gmail.com] 3 | * @copyright Crown Copyright 2016 4 | * @license Apache-2.0 5 | */ 6 | 7 | import Operation from "../Operation.mjs"; 8 | import punycode from "punycode"; 9 | 10 | /** 11 | * From Punycode operation 12 | */ 13 | class FromPunycode extends Operation { 14 | 15 | /** 16 | * FromPunycode constructor 17 | */ 18 | constructor() { 19 | super(); 20 | 21 | this.name = "From Punycode"; 22 | this.module = "Encodings"; 23 | this.description = "Punycode is a way to represent Unicode with the limited character subset of ASCII supported by the Domain Name System.

e.g. mnchen-3ya decodes to m\xfcnchen"; 24 | this.infoURL = "https://wikipedia.org/wiki/Punycode"; 25 | this.inputType = "string"; 26 | this.outputType = "string"; 27 | this.args = [ 28 | { 29 | "name": "Internationalised domain name", 30 | "type": "boolean", 31 | "value": false 32 | } 33 | ]; 34 | } 35 | 36 | /** 37 | * @param {string} input 38 | * @param {Object[]} args 39 | * @returns {string} 40 | */ 41 | run(input, args) { 42 | const idn = args[0]; 43 | 44 | if (idn) { 45 | return punycode.toUnicode(input); 46 | } else { 47 | return punycode.decode(input); 48 | } 49 | } 50 | 51 | } 52 | 53 | export default FromPunycode; 54 | -------------------------------------------------------------------------------- /src/core/operations/GetAllCasings.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * @author n1073645 [n1073645@gmail.com] 3 | * @copyright Crown Copyright 2020 4 | * @license Apache-2.0 5 | */ 6 | 7 | import Operation from "../Operation.mjs"; 8 | 9 | /** 10 | * Permutate String operation 11 | */ 12 | class GetAllCasings extends Operation { 13 | 14 | /** 15 | * GetAllCasings constructor 16 | */ 17 | constructor() { 18 | super(); 19 | 20 | this.name = "Get All Casings"; 21 | this.module = "Default"; 22 | this.description = "Outputs all possible casing variations of a string."; 23 | this.infoURL = ""; 24 | this.inputType = "string"; 25 | this.outputType = "string"; 26 | this.args = []; 27 | } 28 | 29 | /** 30 | * @param {string} input 31 | * @param {Object[]} args 32 | * @returns {string} 33 | */ 34 | run(input, args) { 35 | const length = input.length; 36 | const max = 1 << length; 37 | input = input.toLowerCase(); 38 | let result = ""; 39 | 40 | for (let i = 0; i < max; i++) { 41 | const temp = input.split(""); 42 | for (let j = 0; j < length; j++) { 43 | if (((i >> j) & 1) === 1) { 44 | temp[j] = temp[j].toUpperCase(); 45 | } 46 | } 47 | result += temp.join("") + "\n"; 48 | } 49 | return result.slice(0, -1); 50 | } 51 | } 52 | 53 | export default GetAllCasings; 54 | -------------------------------------------------------------------------------- /src/core/operations/Gunzip.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * @author n1474335 [n1474335@gmail.com] 3 | * @copyright Crown Copyright 2016 4 | * @license Apache-2.0 5 | */ 6 | 7 | import Operation from "../Operation.mjs"; 8 | import gunzip from "zlibjs/bin/gunzip.min.js"; 9 | 10 | const Zlib = gunzip.Zlib; 11 | 12 | /** 13 | * Gunzip operation 14 | */ 15 | class Gunzip extends Operation { 16 | 17 | /** 18 | * Gunzip constructor 19 | */ 20 | constructor() { 21 | super(); 22 | 23 | this.name = "Gunzip"; 24 | this.module = "Compression"; 25 | this.description = "Decompresses data which has been compressed using the deflate algorithm with gzip headers."; 26 | this.infoURL = "https://wikipedia.org/wiki/Gzip"; 27 | this.inputType = "ArrayBuffer"; 28 | this.outputType = "ArrayBuffer"; 29 | this.args = []; 30 | this.checks = [ 31 | { 32 | pattern: "^\\x1f\\x8b\\x08", 33 | flags: "", 34 | args: [] 35 | } 36 | ]; 37 | } 38 | 39 | /** 40 | * @param {ArrayBuffer} input 41 | * @param {Object[]} args 42 | * @returns {File} 43 | */ 44 | run(input, args) { 45 | const gzipObj = new Zlib.Gunzip(new Uint8Array(input)); 46 | return new Uint8Array(gzipObj.decompress()).buffer; 47 | } 48 | 49 | } 50 | 51 | export default Gunzip; 52 | -------------------------------------------------------------------------------- /src/core/operations/HTMLToText.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * @author tlwr [toby@toby.codes] 3 | * @author Matt C [me@mitt.dev] 4 | * @copyright Crown Copyright 2019 5 | * @license Apache-2.0 6 | */ 7 | 8 | import Operation from "../Operation.mjs"; 9 | 10 | /** 11 | * HTML To Text operation 12 | */ 13 | class HTMLToText extends Operation { 14 | 15 | /** 16 | * HTMLToText constructor 17 | */ 18 | constructor() { 19 | super(); 20 | 21 | this.name = "HTML To Text"; 22 | this.module = "Default"; 23 | this.description = "Converts an HTML output from an operation to a readable string instead of being rendered in the DOM."; 24 | this.infoURL = ""; 25 | this.inputType = "html"; 26 | this.outputType = "string"; 27 | this.args = []; 28 | } 29 | 30 | /** 31 | * @param {html} input 32 | * @param {Object[]} args 33 | * @returns {string} 34 | */ 35 | run(input, args) { 36 | return input; 37 | } 38 | 39 | } 40 | 41 | export default HTMLToText; 42 | -------------------------------------------------------------------------------- /src/core/operations/HexToObjectIdentifier.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * @author n1474335 [n1474335@gmail.com] 3 | * @copyright Crown Copyright 2016 4 | * @license Apache-2.0 5 | */ 6 | 7 | import r from "jsrsasign"; 8 | import Operation from "../Operation.mjs"; 9 | 10 | /** 11 | * Hex to Object Identifier operation 12 | */ 13 | class HexToObjectIdentifier extends Operation { 14 | 15 | /** 16 | * HexToObjectIdentifier constructor 17 | */ 18 | constructor() { 19 | super(); 20 | 21 | this.name = "Hex to Object Identifier"; 22 | this.module = "PublicKey"; 23 | this.description = "Converts a hexadecimal string into an object identifier (OID)."; 24 | this.infoURL = "https://wikipedia.org/wiki/Object_identifier"; 25 | this.inputType = "string"; 26 | this.outputType = "string"; 27 | this.args = []; 28 | } 29 | 30 | /** 31 | * @param {string} input 32 | * @param {Object[]} args 33 | * @returns {string} 34 | */ 35 | run(input, args) { 36 | return r.KJUR.asn1.ASN1Util.oidHexToInt(input.replace(/\s/g, "")); 37 | } 38 | 39 | } 40 | 41 | export default HexToObjectIdentifier; 42 | -------------------------------------------------------------------------------- /src/core/operations/HexToPEM.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * @author n1474335 [n1474335@gmail.com] 3 | * @copyright Crown Copyright 2016 4 | * @license Apache-2.0 5 | */ 6 | 7 | import r from "jsrsasign"; 8 | import Operation from "../Operation.mjs"; 9 | 10 | /** 11 | * Hex to PEM operation 12 | */ 13 | class HexToPEM extends Operation { 14 | 15 | /** 16 | * HexToPEM constructor 17 | */ 18 | constructor() { 19 | super(); 20 | 21 | this.name = "Hex to PEM"; 22 | this.module = "PublicKey"; 23 | this.description = "Converts a hexadecimal DER (Distinguished Encoding Rules) string into PEM (Privacy Enhanced Mail) format."; 24 | this.infoURL = "https://wikipedia.org/wiki/Privacy-Enhanced_Mail"; 25 | this.inputType = "string"; 26 | this.outputType = "string"; 27 | this.args = [ 28 | { 29 | "name": "Header string", 30 | "type": "string", 31 | "value": "CERTIFICATE" 32 | } 33 | ]; 34 | } 35 | 36 | /** 37 | * @param {string} input 38 | * @param {Object[]} args 39 | * @returns {string} 40 | */ 41 | run(input, args) { 42 | return r.KJUR.asn1.ASN1Util.getPEMStringFromHex(input.replace(/\s/g, ""), args[0]); 43 | } 44 | 45 | } 46 | 47 | export default HexToPEM; 48 | -------------------------------------------------------------------------------- /src/core/operations/JSONMinify.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * @author n1474335 [n1474335@gmail.com] 3 | * @copyright Crown Copyright 2016 4 | * @license Apache-2.0 5 | */ 6 | 7 | import vkbeautify from "vkbeautify"; 8 | import Operation from "../Operation.mjs"; 9 | 10 | /** 11 | * JSON Minify operation 12 | */ 13 | class JSONMinify extends Operation { 14 | 15 | /** 16 | * JSONMinify constructor 17 | */ 18 | constructor() { 19 | super(); 20 | 21 | this.name = "JSON Minify"; 22 | this.module = "Code"; 23 | this.description = "Compresses JavaScript Object Notation (JSON) code."; 24 | this.inputType = "string"; 25 | this.outputType = "string"; 26 | this.args = []; 27 | } 28 | 29 | /** 30 | * @param {string} input 31 | * @param {Object[]} args 32 | * @returns {string} 33 | */ 34 | run(input, args) { 35 | if (!input) return ""; 36 | return vkbeautify.jsonmin(input); 37 | } 38 | 39 | } 40 | 41 | export default JSONMinify; 42 | -------------------------------------------------------------------------------- /src/core/operations/JSONtoYAML.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * @author ccarpo [ccarpo@gmx.net] 3 | * @copyright Crown Copyright 2021 4 | * @license Apache-2.0 5 | */ 6 | 7 | import Operation from "../Operation.mjs"; 8 | import OperationError from "../errors/OperationError.mjs"; 9 | import YAML from "yaml"; 10 | 11 | /** 12 | * JSON to YAML operation 13 | */ 14 | class JSONtoYAML extends Operation { 15 | 16 | /** 17 | * JSONtoYAML constructor 18 | */ 19 | constructor() { 20 | super(); 21 | 22 | this.name = "JSON to YAML"; 23 | this.module = "Default"; 24 | this.description = "Format a JSON object into YAML"; 25 | this.infoURL = "https://en.wikipedia.org/wiki/YAML"; 26 | this.inputType = "JSON"; 27 | this.outputType = "string"; 28 | this.args = []; 29 | } 30 | 31 | /** 32 | * @param {JSON} input 33 | * @param {Object[]} args 34 | * @returns {string} 35 | */ 36 | run(input, args) { 37 | try { 38 | return YAML.stringify(input); 39 | } catch (err) { 40 | throw new OperationError("Test"); 41 | } 42 | } 43 | 44 | } 45 | 46 | export default JSONtoYAML; 47 | -------------------------------------------------------------------------------- /src/core/operations/JavaScriptMinify.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * @author n1474335 [n1474335@gmail.com] 3 | * @copyright Crown Copyright 2016 4 | * @license Apache-2.0 5 | */ 6 | 7 | import OperationError from "../errors/OperationError.mjs"; 8 | import Operation from "../Operation.mjs"; 9 | import * as terser from "terser"; 10 | 11 | /** 12 | * JavaScript Minify operation 13 | */ 14 | class JavaScriptMinify extends Operation { 15 | 16 | /** 17 | * JavaScriptMinify constructor 18 | */ 19 | constructor() { 20 | super(); 21 | 22 | this.name = "JavaScript Minify"; 23 | this.module = "Code"; 24 | this.description = "Compresses JavaScript code."; 25 | this.inputType = "string"; 26 | this.outputType = "string"; 27 | this.args = []; 28 | } 29 | 30 | /** 31 | * @param {string} input 32 | * @param {Object[]} args 33 | * @returns {string} 34 | */ 35 | async run(input, args) { 36 | const result = await terser.minify(input); 37 | if (result.error) { 38 | throw new OperationError(`Error minifying JavaScript. (${result.error})`); 39 | } 40 | return result.code; 41 | } 42 | 43 | } 44 | 45 | export default JavaScriptMinify; 46 | -------------------------------------------------------------------------------- /src/core/operations/Jq.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * @author zhzy0077 [zhzy0077@hotmail.com] 3 | * @copyright Crown Copyright 2023 4 | * @license Apache-2.0 5 | */ 6 | 7 | import Operation from "../Operation.mjs"; 8 | import OperationError from "../errors/OperationError.mjs"; 9 | import jq from "jq-web"; 10 | 11 | /** 12 | * jq operation 13 | */ 14 | class Jq extends Operation { 15 | 16 | /** 17 | * Jq constructor 18 | */ 19 | constructor() { 20 | super(); 21 | 22 | this.name = "Jq"; 23 | this.module = "Jq"; 24 | this.description = "jq is a lightweight and flexible command-line JSON processor."; 25 | this.infoURL = "https://github.com/jqlang/jq"; 26 | this.inputType = "JSON"; 27 | this.outputType = "string"; 28 | this.args = [ 29 | { 30 | name: "Query", 31 | type: "string", 32 | value: "" 33 | } 34 | ]; 35 | } 36 | 37 | /** 38 | * @param {JSON} input 39 | * @param {Object[]} args 40 | * @returns {string} 41 | */ 42 | run(input, args) { 43 | const [query] = args; 44 | let result; 45 | 46 | try { 47 | result = jq.json(input, query); 48 | } catch (err) { 49 | throw new OperationError(`Invalid jq expression: ${err.message}`); 50 | } 51 | 52 | return JSON.stringify(result); 53 | } 54 | 55 | } 56 | 57 | export default Jq; 58 | -------------------------------------------------------------------------------- /src/core/operations/LMHash.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * @author n1474335 [n1474335@gmail.com] 3 | * @copyright Crown Copyright 2022 4 | * @license Apache-2.0 5 | */ 6 | 7 | import Operation from "../Operation.mjs"; 8 | import {smbhash} from "ntlm"; 9 | 10 | /** 11 | * LM Hash operation 12 | */ 13 | class LMHash extends Operation { 14 | 15 | /** 16 | * LMHash constructor 17 | */ 18 | constructor() { 19 | super(); 20 | 21 | this.name = "LM Hash"; 22 | this.module = "Crypto"; 23 | this.description = "An LM Hash, or LAN Manager Hash, is a deprecated way of storing passwords on old Microsoft operating systems. It is particularly weak and can be cracked in seconds on modern hardware using rainbow tables."; 24 | this.infoURL = "https://wikipedia.org/wiki/LAN_Manager#Password_hashing_algorithm"; 25 | this.inputType = "string"; 26 | this.outputType = "string"; 27 | this.args = []; 28 | } 29 | 30 | /** 31 | * @param {string} input 32 | * @param {Object[]} args 33 | * @returns {string} 34 | */ 35 | run(input, args) { 36 | return smbhash.lmhash(input); 37 | } 38 | 39 | } 40 | 41 | export default LMHash; 42 | -------------------------------------------------------------------------------- /src/core/operations/LZ4Compress.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * @author n1474335 [n1474335@gmail.com] 3 | * @copyright Crown Copyright 2022 4 | * @license Apache-2.0 5 | */ 6 | 7 | import Operation from "../Operation.mjs"; 8 | import lz4 from "lz4js"; 9 | 10 | /** 11 | * LZ4 Compress operation 12 | */ 13 | class LZ4Compress extends Operation { 14 | 15 | /** 16 | * LZ4Compress constructor 17 | */ 18 | constructor() { 19 | super(); 20 | 21 | this.name = "LZ4 Compress"; 22 | this.module = "Compression"; 23 | this.description = "LZ4 is a lossless data compression algorithm that is focused on compression and decompression speed. It belongs to the LZ77 family of byte-oriented compression schemes."; 24 | this.infoURL = "https://wikipedia.org/wiki/LZ4_(compression_algorithm)"; 25 | this.inputType = "ArrayBuffer"; 26 | this.outputType = "ArrayBuffer"; 27 | this.args = []; 28 | } 29 | 30 | /** 31 | * @param {ArrayBuffer} input 32 | * @param {Object[]} args 33 | * @returns {ArrayBuffer} 34 | */ 35 | run(input, args) { 36 | const inBuf = new Uint8Array(input); 37 | const compressed = lz4.compress(inBuf); 38 | return compressed.buffer; 39 | } 40 | 41 | } 42 | 43 | export default LZ4Compress; 44 | -------------------------------------------------------------------------------- /src/core/operations/LZ4Decompress.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * @author n1474335 [n1474335@gmail.com] 3 | * @copyright Crown Copyright 2022 4 | * @license Apache-2.0 5 | */ 6 | 7 | import Operation from "../Operation.mjs"; 8 | import lz4 from "lz4js"; 9 | 10 | /** 11 | * LZ4 Decompress operation 12 | */ 13 | class LZ4Decompress extends Operation { 14 | 15 | /** 16 | * LZ4Decompress constructor 17 | */ 18 | constructor() { 19 | super(); 20 | 21 | this.name = "LZ4 Decompress"; 22 | this.module = "Compression"; 23 | this.description = "LZ4 is a lossless data compression algorithm that is focused on compression and decompression speed. It belongs to the LZ77 family of byte-oriented compression schemes."; 24 | this.infoURL = "https://wikipedia.org/wiki/LZ4_(compression_algorithm)"; 25 | this.inputType = "ArrayBuffer"; 26 | this.outputType = "ArrayBuffer"; 27 | this.args = []; 28 | } 29 | 30 | /** 31 | * @param {ArrayBuffer} input 32 | * @param {Object[]} args 33 | * @returns {ArrayBuffer} 34 | */ 35 | run(input, args) { 36 | const inBuf = new Uint8Array(input); 37 | const decompressed = lz4.decompress(inBuf); 38 | return decompressed.buffer; 39 | } 40 | 41 | } 42 | 43 | export default LZ4Decompress; 44 | -------------------------------------------------------------------------------- /src/core/operations/LZNT1Decompress.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * @author 0xThiebaut [thiebaut.dev] 3 | * @copyright Crown Copyright 2023 4 | * @license Apache-2.0 5 | */ 6 | 7 | import Operation from "../Operation.mjs"; 8 | import {decompress} from "../lib/LZNT1.mjs"; 9 | 10 | /** 11 | * LZNT1 Decompress operation 12 | */ 13 | class LZNT1Decompress extends Operation { 14 | 15 | /** 16 | * LZNT1 Decompress constructor 17 | */ 18 | constructor() { 19 | super(); 20 | 21 | this.name = "LZNT1 Decompress"; 22 | this.module = "Compression"; 23 | this.description = "Decompresses data using the LZNT1 algorithm.

Similar to the Windows API RtlDecompressBuffer."; 24 | this.infoURL = "https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-xca/5655f4a3-6ba4-489b-959f-e1f407c52f15"; 25 | this.inputType = "byteArray"; 26 | this.outputType = "byteArray"; 27 | this.args = []; 28 | } 29 | 30 | /** 31 | * @param {byteArray} input 32 | * @param {Object[]} args 33 | * @returns {byteArray} 34 | */ 35 | run(input, args) { 36 | return decompress(input); 37 | } 38 | 39 | } 40 | 41 | export default LZNT1Decompress; 42 | -------------------------------------------------------------------------------- /src/core/operations/LZStringCompress.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * @author crespyl [peter@crespyl.net] 3 | * @copyright Peter Jacobs 2021 4 | * @license Apache-2.0 5 | */ 6 | 7 | import Operation from "../Operation.mjs"; 8 | import OperationError from "../errors/OperationError.mjs"; 9 | 10 | import {COMPRESSION_OUTPUT_FORMATS, COMPRESSION_FUNCTIONS} from "../lib/LZString.mjs"; 11 | 12 | /** 13 | * LZString Compress operation 14 | */ 15 | class LZStringCompress extends Operation { 16 | 17 | /** 18 | * LZStringCompress constructor 19 | */ 20 | constructor() { 21 | super(); 22 | 23 | this.name = "LZString Compress"; 24 | this.module = "Compression"; 25 | this.description = "Compress the input with lz-string."; 26 | this.infoURL = "https://pieroxy.net/blog/pages/lz-string/index.html"; 27 | this.inputType = "string"; 28 | this.outputType = "string"; 29 | this.args = [ 30 | { 31 | name: "Compression Format", 32 | type: "option", 33 | defaultIndex: 0, 34 | value: COMPRESSION_OUTPUT_FORMATS 35 | } 36 | ]; 37 | } 38 | 39 | /** 40 | * @param {string} input 41 | * @param {Object[]} args 42 | * @returns {string} 43 | */ 44 | run(input, args) { 45 | const compress = COMPRESSION_FUNCTIONS[args[0]]; 46 | if (compress) { 47 | return compress(input); 48 | } else { 49 | throw new OperationError("Unable to find compression function"); 50 | } 51 | } 52 | 53 | } 54 | 55 | export default LZStringCompress; 56 | -------------------------------------------------------------------------------- /src/core/operations/Label.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * @author n1474335 [n1474335@gmail.com] 3 | * @copyright Crown Copyright 2016 4 | * @license Apache-2.0 5 | */ 6 | 7 | import Operation from "../Operation.mjs"; 8 | 9 | /** 10 | * Label operation. For use with Jump and Conditional Jump. 11 | */ 12 | class Label extends Operation { 13 | 14 | /** 15 | * Label constructor 16 | */ 17 | constructor() { 18 | super(); 19 | 20 | this.name = "Label"; 21 | this.flowControl = true; 22 | this.module = "Default"; 23 | this.description = "Provides a location for conditional and fixed jumps to redirect execution to."; 24 | this.inputType = "string"; 25 | this.outputType = "string"; 26 | this.args = [ 27 | { 28 | "name": "Name", 29 | "type": "shortString", 30 | "value": "" 31 | } 32 | ]; 33 | } 34 | 35 | /** 36 | * @param {Object} state - The current state of the recipe. 37 | * @param {number} state.progress - The current position in the recipe. 38 | * @param {Dish} state.dish - The Dish being operated on. 39 | * @param {Operation[]} state.opList - The list of operations in the recipe. 40 | * @returns {Object} The updated state of the recipe. 41 | */ 42 | run(state) { 43 | return state; 44 | } 45 | 46 | } 47 | 48 | export default Label; 49 | -------------------------------------------------------------------------------- /src/core/operations/MD2.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * @author n1474335 [n1474335@gmail.com] 3 | * @copyright Crown Copyright 2016 4 | * @license Apache-2.0 5 | */ 6 | 7 | import Operation from "../Operation.mjs"; 8 | import {runHash} from "../lib/Hash.mjs"; 9 | 10 | /** 11 | * MD2 operation 12 | */ 13 | class MD2 extends Operation { 14 | 15 | /** 16 | * MD2 constructor 17 | */ 18 | constructor() { 19 | super(); 20 | 21 | this.name = "MD2"; 22 | this.module = "Crypto"; 23 | this.description = "The MD2 (Message-Digest 2) algorithm is a cryptographic hash function developed by Ronald Rivest in 1989. The algorithm is optimized for 8-bit computers.

Although MD2 is no longer considered secure, even as of 2014, it remains in use in public key infrastructures as part of certificates generated with MD2 and RSA. The message digest algorithm consists, by default, of 18 rounds."; 24 | this.infoURL = "https://wikipedia.org/wiki/MD2_(cryptography)"; 25 | this.inputType = "ArrayBuffer"; 26 | this.outputType = "string"; 27 | this.args = [ 28 | { 29 | name: "Rounds", 30 | type: "number", 31 | value: 18, 32 | min: 0 33 | } 34 | ]; 35 | } 36 | 37 | /** 38 | * @param {ArrayBuffer} input 39 | * @param {Object[]} args 40 | * @returns {string} 41 | */ 42 | run(input, args) { 43 | return runHash("md2", input, {rounds: args[0]}); 44 | } 45 | 46 | } 47 | 48 | export default MD2; 49 | -------------------------------------------------------------------------------- /src/core/operations/MD4.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * @author n1474335 [n1474335@gmail.com] 3 | * @copyright Crown Copyright 2016 4 | * @license Apache-2.0 5 | */ 6 | 7 | import Operation from "../Operation.mjs"; 8 | import {runHash} from "../lib/Hash.mjs"; 9 | 10 | /** 11 | * MD4 operation 12 | */ 13 | class MD4 extends Operation { 14 | 15 | /** 16 | * MD4 constructor 17 | */ 18 | constructor() { 19 | super(); 20 | 21 | this.name = "MD4"; 22 | this.module = "Crypto"; 23 | this.description = "The MD4 (Message-Digest 4) algorithm is a cryptographic hash function developed by Ronald Rivest in 1990. The digest length is 128 bits. The algorithm has influenced later designs, such as the MD5, SHA-1 and RIPEMD algorithms.

The security of MD4 has been severely compromised."; 24 | this.infoURL = "https://wikipedia.org/wiki/MD4"; 25 | this.inputType = "ArrayBuffer"; 26 | this.outputType = "string"; 27 | this.args = []; 28 | } 29 | 30 | /** 31 | * @param {ArrayBuffer} input 32 | * @param {Object[]} args 33 | * @returns {string} 34 | */ 35 | run(input, args) { 36 | return runHash("md4", input); 37 | } 38 | 39 | } 40 | 41 | export default MD4; 42 | -------------------------------------------------------------------------------- /src/core/operations/MD5.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * @author n1474335 [n1474335@gmail.com] 3 | * @copyright Crown Copyright 2016 4 | * @license Apache-2.0 5 | */ 6 | 7 | import Operation from "../Operation.mjs"; 8 | import {runHash} from "../lib/Hash.mjs"; 9 | 10 | /** 11 | * MD5 operation 12 | */ 13 | class MD5 extends Operation { 14 | 15 | /** 16 | * MD5 constructor 17 | */ 18 | constructor() { 19 | super(); 20 | 21 | this.name = "MD5"; 22 | this.module = "Crypto"; 23 | this.description = "MD5 (Message-Digest 5) is a widely used hash function. It has been used in a variety of security applications and is also commonly used to check the integrity of files.

However, MD5 is not collision resistant and it isn't suitable for applications like SSL/TLS certificates or digital signatures that rely on this property."; 24 | this.infoURL = "https://wikipedia.org/wiki/MD5"; 25 | this.inputType = "ArrayBuffer"; 26 | this.outputType = "string"; 27 | this.args = []; 28 | } 29 | 30 | /** 31 | * @param {ArrayBuffer} input 32 | * @param {Object[]} args 33 | * @returns {string} 34 | */ 35 | run(input, args) { 36 | return runHash("md5", input); 37 | } 38 | 39 | } 40 | 41 | export default MD5; 42 | -------------------------------------------------------------------------------- /src/core/operations/Mean.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * @author bwhitn [brian.m.whitney@outlook.com] 3 | * @author d98762625 [d98762625@gmail.com] 4 | * @copyright Crown Copyright 2018 5 | * @license Apache-2.0 6 | */ 7 | 8 | import Operation from "../Operation.mjs"; 9 | import { mean, createNumArray } from "../lib/Arithmetic.mjs"; 10 | import { ARITHMETIC_DELIM_OPTIONS } from "../lib/Delim.mjs"; 11 | import BigNumber from "bignumber.js"; 12 | 13 | /** 14 | * Mean operation 15 | */ 16 | class Mean extends Operation { 17 | 18 | /** 19 | * Mean constructor 20 | */ 21 | constructor() { 22 | super(); 23 | 24 | this.name = "Mean"; 25 | this.module = "Default"; 26 | this.description = "Computes the mean (average) of a number list. If an item in the string is not a number it is excluded from the list.

e.g. 0x0a 8 .5 .5 becomes 4.75"; 27 | this.infoURL = "https://wikipedia.org/wiki/Arithmetic_mean"; 28 | this.inputType = "string"; 29 | this.outputType = "BigNumber"; 30 | this.args = [ 31 | { 32 | "name": "Delimiter", 33 | "type": "option", 34 | "value": ARITHMETIC_DELIM_OPTIONS, 35 | } 36 | ]; 37 | } 38 | 39 | /** 40 | * @param {string} input 41 | * @param {Object[]} args 42 | * @returns {BigNumber} 43 | */ 44 | run(input, args) { 45 | const val = mean(createNumArray(input, args[0])); 46 | return BigNumber.isBigNumber(val) ? val : new BigNumber(NaN); 47 | } 48 | 49 | } 50 | 51 | export default Mean; 52 | -------------------------------------------------------------------------------- /src/core/operations/Median.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * @author bwhitn [brian.m.whitney@outlook.com] 3 | * @author d98762625 [d98762625@gmail.com] 4 | * @copyright Crown Copyright 2018 5 | * @license Apache-2.0 6 | */ 7 | 8 | import BigNumber from "bignumber.js"; 9 | import Operation from "../Operation.mjs"; 10 | import { median, createNumArray } from "../lib/Arithmetic.mjs"; 11 | import { ARITHMETIC_DELIM_OPTIONS } from "../lib/Delim.mjs"; 12 | 13 | /** 14 | * Median operation 15 | */ 16 | class Median extends Operation { 17 | 18 | /** 19 | * Median constructor 20 | */ 21 | constructor() { 22 | super(); 23 | 24 | this.name = "Median"; 25 | this.module = "Default"; 26 | this.description = "Computes the median of a number list. If an item in the string is not a number it is excluded from the list.

e.g. 0x0a 8 1 .5 becomes 4.5"; 27 | this.infoURL = "https://wikipedia.org/wiki/Median"; 28 | this.inputType = "string"; 29 | this.outputType = "BigNumber"; 30 | this.args = [ 31 | { 32 | "name": "Delimiter", 33 | "type": "option", 34 | "value": ARITHMETIC_DELIM_OPTIONS, 35 | } 36 | ]; 37 | } 38 | 39 | /** 40 | * @param {string} input 41 | * @param {Object[]} args 42 | * @returns {BigNumber} 43 | */ 44 | run(input, args) { 45 | const val = median(createNumArray(input, args[0])); 46 | return BigNumber.isBigNumber(val) ? val : new BigNumber(NaN); 47 | } 48 | 49 | } 50 | 51 | export default Median; 52 | -------------------------------------------------------------------------------- /src/core/operations/Merge.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * @author n1474335 [n1474335@gmail.com] 3 | * @copyright Crown Copyright 2018 4 | * @license Apache-2.0 5 | */ 6 | 7 | import Operation from "../Operation.mjs"; 8 | 9 | /** 10 | * Merge operation 11 | */ 12 | class Merge extends Operation { 13 | 14 | /** 15 | * Merge constructor 16 | */ 17 | constructor() { 18 | super(); 19 | 20 | this.name = "Merge"; 21 | this.flowControl = true; 22 | this.module = "Default"; 23 | this.description = "Consolidate all branches back into a single trunk. The opposite of Fork. Unticking the Merge All checkbox will only consolidate all branches up to the nearest Fork/Subsection."; 24 | this.inputType = "string"; 25 | this.outputType = "string"; 26 | this.args = [ 27 | { 28 | name: "Merge All", 29 | type: "boolean", 30 | value: true, 31 | } 32 | ]; 33 | } 34 | 35 | /** 36 | * @param {Object} state - The current state of the recipe. 37 | * @param {number} state.progress - The current position in the recipe. 38 | * @param {Dish} state.dish - The Dish being operated on. 39 | * @param {Operation[]} state.opList - The list of operations in the recipe. 40 | * @returns {Object} The updated state of the recipe. 41 | */ 42 | run(state) { 43 | // No need to actually do anything here. The fork operation will 44 | // merge when it sees this operation. 45 | return state; 46 | } 47 | 48 | } 49 | 50 | export default Merge; 51 | -------------------------------------------------------------------------------- /src/core/operations/Multiply.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * @author bwhitn [brian.m.whitney@outlook.com] 3 | * @author d98762625 [d98762625@gmail.com] 4 | * @copyright Crown Copyright 2018 5 | * @license Apache-2.0 6 | */ 7 | 8 | import BigNumber from "bignumber.js"; 9 | import Operation from "../Operation.mjs"; 10 | import { multi, createNumArray } from "../lib/Arithmetic.mjs"; 11 | import { ARITHMETIC_DELIM_OPTIONS } from "../lib/Delim.mjs"; 12 | 13 | 14 | /** 15 | * Multiply operation 16 | */ 17 | class Multiply extends Operation { 18 | 19 | /** 20 | * Multiply constructor 21 | */ 22 | constructor() { 23 | super(); 24 | 25 | this.name = "Multiply"; 26 | this.module = "Default"; 27 | this.description = "Multiplies a list of numbers. If an item in the string is not a number it is excluded from the list.

e.g. 0x0a 8 .5 becomes 40"; 28 | this.infoURL = "https://wikipedia.org/wiki/Multiplication"; 29 | this.inputType = "string"; 30 | this.outputType = "BigNumber"; 31 | this.args = [ 32 | { 33 | "name": "Delimiter", 34 | "type": "option", 35 | "value": ARITHMETIC_DELIM_OPTIONS, 36 | } 37 | ]; 38 | } 39 | 40 | /** 41 | * @param {string} input 42 | * @param {Object[]} args 43 | * @returns {BigNumber} 44 | */ 45 | run(input, args) { 46 | const val = multi(createNumArray(input, args[0])); 47 | return BigNumber.isBigNumber(val) ? val : new BigNumber(NaN); 48 | } 49 | 50 | } 51 | 52 | export default Multiply; 53 | -------------------------------------------------------------------------------- /src/core/operations/NTHash.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * @author brun0ne [brunonblok@gmail.com] 3 | * @copyright Crown Copyright 2022 4 | * @license Apache-2.0 5 | */ 6 | 7 | import Operation from "../Operation.mjs"; 8 | import {runHash} from "../lib/Hash.mjs"; 9 | 10 | /** 11 | * NT Hash operation 12 | */ 13 | class NTHash extends Operation { 14 | 15 | /** 16 | * NTHash constructor 17 | */ 18 | constructor() { 19 | super(); 20 | 21 | this.name = "NT Hash"; 22 | this.module = "Crypto"; 23 | this.description = "An NT Hash, sometimes referred to as an NTLM hash, is a method of storing passwords on Windows systems. It works by running MD4 on UTF-16LE encoded input. NTLM hashes are considered weak because they can be brute-forced very easily with modern hardware."; 24 | this.infoURL = "https://wikipedia.org/wiki/NT_LAN_Manager"; 25 | this.inputType = "string"; 26 | this.outputType = "string"; 27 | this.args = []; 28 | } 29 | 30 | /** 31 | * @param {string} input 32 | * @param {Object[]} args 33 | * @returns {string} 34 | */ 35 | run(input, args) { 36 | // Convert to UTF-16LE 37 | const buf = new ArrayBuffer(input.length * 2); 38 | const bufView = new Uint16Array(buf); 39 | for (let i = 0; i < input.length; i++) { 40 | bufView[i] = input.charCodeAt(i); 41 | } 42 | 43 | const hashed = runHash("md4", buf); 44 | return hashed.toUpperCase(); 45 | } 46 | } 47 | 48 | export default NTHash; 49 | -------------------------------------------------------------------------------- /src/core/operations/ObjectIdentifierToHex.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * @author n1474335 [n1474335@gmail.com] 3 | * @copyright Crown Copyright 2016 4 | * @license Apache-2.0 5 | */ 6 | 7 | import r from "jsrsasign"; 8 | import Operation from "../Operation.mjs"; 9 | 10 | /** 11 | * Object Identifier to Hex operation 12 | */ 13 | class ObjectIdentifierToHex extends Operation { 14 | 15 | /** 16 | * ObjectIdentifierToHex constructor 17 | */ 18 | constructor() { 19 | super(); 20 | 21 | this.name = "Object Identifier to Hex"; 22 | this.module = "PublicKey"; 23 | this.description = "Converts an object identifier (OID) into a hexadecimal string."; 24 | this.infoURL = "https://wikipedia.org/wiki/Object_identifier"; 25 | this.inputType = "string"; 26 | this.outputType = "string"; 27 | this.args = []; 28 | } 29 | 30 | /** 31 | * @param {string} input 32 | * @param {Object[]} args 33 | * @returns {string} 34 | */ 35 | run(input, args) { 36 | return r.KJUR.asn1.ASN1Util.oidIntToHex(input); 37 | } 38 | 39 | } 40 | 41 | export default ObjectIdentifierToHex; 42 | -------------------------------------------------------------------------------- /src/core/operations/ParseObjectIDTimestamp.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * @author dmfj [dominic@dmfj.io] 3 | * @copyright Crown Copyright 2020 4 | * @license Apache-2.0 5 | */ 6 | 7 | import Operation from "../Operation.mjs"; 8 | import OperationError from "../errors/OperationError.mjs"; 9 | import BSON from "bson"; 10 | 11 | /** 12 | * Parse ObjectID timestamp operation 13 | */ 14 | class ParseObjectIDTimestamp extends Operation { 15 | 16 | /** 17 | * ParseObjectIDTimestamp constructor 18 | */ 19 | constructor() { 20 | super(); 21 | 22 | this.name = "Parse ObjectID timestamp"; 23 | this.module = "Serialise"; 24 | this.description = "Parse timestamp from MongoDB/BSON ObjectID hex string."; 25 | this.infoURL = "https://docs.mongodb.com/manual/reference/method/ObjectId.getTimestamp/"; 26 | this.inputType = "string"; 27 | this.outputType = "string"; 28 | this.args = []; 29 | } 30 | 31 | /** 32 | * @param {string} input 33 | * @param {Object[]} args 34 | * @returns {string} 35 | */ 36 | run(input, args) { 37 | try { 38 | const objectId = new BSON.ObjectID(input); 39 | return objectId.getTimestamp().toISOString(); 40 | } catch (err) { 41 | throw new OperationError(err); 42 | } 43 | } 44 | 45 | } 46 | 47 | export default ParseObjectIDTimestamp; 48 | -------------------------------------------------------------------------------- /src/core/operations/ProtobufEncode.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * @author GCHQ Contributor [3] 3 | * @copyright Crown Copyright 2021 4 | * @license Apache-2.0 5 | */ 6 | 7 | import Operation from "../Operation.mjs"; 8 | import OperationError from "../errors/OperationError.mjs"; 9 | import Protobuf from "../lib/Protobuf.mjs"; 10 | 11 | /** 12 | * Protobuf Encode operation 13 | */ 14 | class ProtobufEncode extends Operation { 15 | 16 | /** 17 | * ProtobufEncode constructor 18 | */ 19 | constructor() { 20 | super(); 21 | 22 | this.name = "Protobuf Encode"; 23 | this.module = "Protobuf"; 24 | this.description = "Encodes a valid JSON object into a protobuf byte array using the input .proto schema."; 25 | this.infoURL = "https://developers.google.com/protocol-buffers/docs/encoding"; 26 | this.inputType = "JSON"; 27 | this.outputType = "ArrayBuffer"; 28 | this.args = [ 29 | { 30 | name: "Schema (.proto text)", 31 | type: "text", 32 | value: "", 33 | rows: 8, 34 | hint: "Drag and drop is enabled on this ingredient" 35 | } 36 | ]; 37 | } 38 | 39 | /** 40 | * @param {Object} input 41 | * @param {Object[]} args 42 | * @returns {ArrayBuffer} 43 | */ 44 | run(input, args) { 45 | try { 46 | return Protobuf.encode(input, args); 47 | } catch (error) { 48 | throw new OperationError(error); 49 | } 50 | } 51 | 52 | } 53 | 54 | export default ProtobufEncode; 55 | -------------------------------------------------------------------------------- /src/core/operations/RIPEMD.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * @author n1474335 [n1474335@gmail.com] 3 | * @copyright Crown Copyright 2016 4 | * @license Apache-2.0 5 | */ 6 | 7 | import Operation from "../Operation.mjs"; 8 | import {runHash} from "../lib/Hash.mjs"; 9 | 10 | /** 11 | * RIPEMD operation 12 | */ 13 | class RIPEMD extends Operation { 14 | 15 | /** 16 | * RIPEMD constructor 17 | */ 18 | constructor() { 19 | super(); 20 | 21 | this.name = "RIPEMD"; 22 | this.module = "Crypto"; 23 | this.description = "RIPEMD (RACE Integrity Primitives Evaluation Message Digest) is a family of cryptographic hash functions developed in Leuven, Belgium, by Hans Dobbertin, Antoon Bosselaers and Bart Preneel at the COSIC research group at the Katholieke Universiteit Leuven, and first published in 1996.

RIPEMD was based upon the design principles used in MD4, and is similar in performance to the more popular SHA-1.

"; 24 | this.infoURL = "https://wikipedia.org/wiki/RIPEMD"; 25 | this.inputType = "ArrayBuffer"; 26 | this.outputType = "string"; 27 | this.args = [ 28 | { 29 | "name": "Size", 30 | "type": "option", 31 | "value": ["320", "256", "160", "128"] 32 | } 33 | ]; 34 | } 35 | 36 | /** 37 | * @param {ArrayBuffer} input 38 | * @param {Object[]} args 39 | * @returns {string} 40 | */ 41 | run(input, args) { 42 | const size = args[0]; 43 | return runHash("ripemd" + size, input); 44 | } 45 | 46 | } 47 | 48 | export default RIPEMD; 49 | -------------------------------------------------------------------------------- /src/core/operations/RemoveDiacritics.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * @author Klaxon [klaxon@veyr.com] 3 | * @copyright Crown Copyright 2018 4 | * @license Apache-2.0 5 | */ 6 | 7 | import Operation from "../Operation.mjs"; 8 | 9 | /** 10 | * Remove Diacritics operation 11 | */ 12 | class RemoveDiacritics extends Operation { 13 | 14 | /** 15 | * RemoveDiacritics constructor 16 | */ 17 | constructor() { 18 | super(); 19 | 20 | this.name = "Remove Diacritics"; 21 | this.module = "Default"; 22 | this.description = "Replaces accented characters with their latin character equivalent. Accented characters are made up of Unicode combining characters, so unicode text formatting such as strikethroughs and underlines will also be removed."; 23 | this.infoURL = "https://wikipedia.org/wiki/Diacritic"; 24 | this.inputType = "string"; 25 | this.outputType = "string"; 26 | this.args = []; 27 | } 28 | 29 | /** 30 | * @param {string} input 31 | * @param {Object[]} args 32 | * @returns {string} 33 | */ 34 | run(input, args) { 35 | // reference: https://stackoverflow.com/questions/990904/remove-accents-diacritics-in-a-string-in-javascript/37511463 36 | return input.normalize("NFD").replace(/[\u0300-\u036f]/g, ""); 37 | } 38 | 39 | } 40 | 41 | export default RemoveDiacritics; 42 | -------------------------------------------------------------------------------- /src/core/operations/RemoveLineNumbers.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * @author n1474335 [n1474335@gmail.com] 3 | * @copyright Crown Copyright 2016 4 | * @license Apache-2.0 5 | */ 6 | 7 | import Operation from "../Operation.mjs"; 8 | 9 | /** 10 | * Remove line numbers operation 11 | */ 12 | class RemoveLineNumbers extends Operation { 13 | 14 | /** 15 | * RemoveLineNumbers constructor 16 | */ 17 | constructor() { 18 | super(); 19 | 20 | this.name = "Remove line numbers"; 21 | this.module = "Default"; 22 | this.description = "Removes line numbers from the output if they can be trivially detected."; 23 | this.inputType = "string"; 24 | this.outputType = "string"; 25 | this.args = []; 26 | } 27 | 28 | /** 29 | * @param {string} input 30 | * @param {Object[]} args 31 | * @returns {string} 32 | */ 33 | run(input, args) { 34 | return input.replace(/^[ \t]{0,5}\d+[\s:|\-,.)\]]/gm, ""); 35 | } 36 | 37 | } 38 | 39 | export default RemoveLineNumbers; 40 | -------------------------------------------------------------------------------- /src/core/operations/RemoveNullBytes.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * @author n1474335 [n1474335@gmail.com] 3 | * @copyright Crown Copyright 2016 4 | * @license Apache-2.0 5 | */ 6 | 7 | import Operation from "../Operation.mjs"; 8 | 9 | /** 10 | * Remove null bytes operation 11 | */ 12 | class RemoveNullBytes extends Operation { 13 | 14 | /** 15 | * RemoveNullBytes constructor 16 | */ 17 | constructor() { 18 | super(); 19 | 20 | this.name = "Remove null bytes"; 21 | this.module = "Default"; 22 | this.description = "Removes all null bytes (0x00) from the input."; 23 | this.inputType = "ArrayBuffer"; 24 | this.outputType = "byteArray"; 25 | this.args = []; 26 | } 27 | 28 | /** 29 | * @param {ArrayBuffer} input 30 | * @param {Object[]} args 31 | * @returns {byteArray} 32 | */ 33 | run(input, args) { 34 | input = new Uint8Array(input); 35 | const output = []; 36 | for (let i = 0; i < input.length; i++) { 37 | if (input[i] !== 0) output.push(input[i]); 38 | } 39 | return output; 40 | } 41 | 42 | } 43 | 44 | export default RemoveNullBytes; 45 | -------------------------------------------------------------------------------- /src/core/operations/Return.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * @author n1474335 [n1474335@gmail.com] 3 | * @copyright Crown Copyright 2018 4 | * @license Apache-2.0 5 | */ 6 | 7 | import Operation from "../Operation.mjs"; 8 | 9 | /** 10 | * Return operation 11 | */ 12 | class Return extends Operation { 13 | 14 | /** 15 | * Return constructor 16 | */ 17 | constructor() { 18 | super(); 19 | 20 | this.name = "Return"; 21 | this.flowControl = true; 22 | this.module = "Default"; 23 | this.description = "End execution of operations at this point in the recipe."; 24 | this.inputType = "string"; 25 | this.outputType = "string"; 26 | this.args = []; 27 | } 28 | 29 | /** 30 | * @param {Object} state - The current state of the recipe. 31 | * @param {number} state.progress - The current position in the recipe. 32 | * @param {Dish} state.dish - The Dish being operated on. 33 | * @param {Operation[]} state.opList - The list of operations in the recipe. 34 | * @returns {Object} The updated state of the recipe. 35 | */ 36 | run(state) { 37 | state.progress = state.opList.length; 38 | return state; 39 | } 40 | 41 | } 42 | 43 | export default Return; 44 | -------------------------------------------------------------------------------- /src/core/operations/SHA0.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * @author n1474335 [n1474335@gmail.com] 3 | * @copyright Crown Copyright 2016 4 | * @license Apache-2.0 5 | */ 6 | 7 | import Operation from "../Operation.mjs"; 8 | import {runHash} from "../lib/Hash.mjs"; 9 | 10 | /** 11 | * SHA0 operation 12 | */ 13 | class SHA0 extends Operation { 14 | 15 | /** 16 | * SHA0 constructor 17 | */ 18 | constructor() { 19 | super(); 20 | 21 | this.name = "SHA0"; 22 | this.module = "Crypto"; 23 | this.description = "SHA-0 is a retronym applied to the original version of the 160-bit hash function published in 1993 under the name 'SHA'. It was withdrawn shortly after publication due to an undisclosed 'significant flaw' and replaced by the slightly revised version SHA-1. The message digest algorithm consists, by default, of 80 rounds."; 24 | this.infoURL = "https://wikipedia.org/wiki/SHA-1#SHA-0"; 25 | this.inputType = "ArrayBuffer"; 26 | this.outputType = "string"; 27 | this.args = [ 28 | { 29 | name: "Rounds", 30 | type: "number", 31 | value: 80, 32 | min: 16 33 | } 34 | ]; 35 | } 36 | 37 | /** 38 | * @param {ArrayBuffer} input 39 | * @param {Object[]} args 40 | * @returns {string} 41 | */ 42 | run(input, args) { 43 | return runHash("sha0", input, {rounds: args[0]}); 44 | } 45 | 46 | } 47 | 48 | export default SHA0; 49 | -------------------------------------------------------------------------------- /src/core/operations/SHA1.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * @author n1474335 [n1474335@gmail.com] 3 | * @copyright Crown Copyright 2016 4 | * @license Apache-2.0 5 | */ 6 | 7 | import Operation from "../Operation.mjs"; 8 | import {runHash} from "../lib/Hash.mjs"; 9 | 10 | /** 11 | * SHA1 operation 12 | */ 13 | class SHA1 extends Operation { 14 | 15 | /** 16 | * SHA1 constructor 17 | */ 18 | constructor() { 19 | super(); 20 | 21 | this.name = "SHA1"; 22 | this.module = "Crypto"; 23 | this.description = "The SHA (Secure Hash Algorithm) hash functions were designed by the NSA. SHA-1 is the most established of the existing SHA hash functions and it is used in a variety of security applications and protocols.

However, SHA-1's collision resistance has been weakening as new attacks are discovered or improved. The message digest algorithm consists, by default, of 80 rounds."; 24 | this.infoURL = "https://wikipedia.org/wiki/SHA-1"; 25 | this.inputType = "ArrayBuffer"; 26 | this.outputType = "string"; 27 | this.args = [ 28 | { 29 | name: "Rounds", 30 | type: "number", 31 | value: 80, 32 | min: 16 33 | } 34 | ]; 35 | } 36 | 37 | /** 38 | * @param {ArrayBuffer} input 39 | * @param {Object[]} args 40 | * @returns {string} 41 | */ 42 | run(input, args) { 43 | return runHash("sha1", input, {rounds: args[0]}); 44 | } 45 | 46 | } 47 | 48 | export default SHA1; 49 | -------------------------------------------------------------------------------- /src/core/operations/SQLBeautify.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * @author n1474335 [n1474335@gmail.com] 3 | * @copyright Crown Copyright 2016 4 | * @license Apache-2.0 5 | */ 6 | 7 | import vkbeautify from "vkbeautify"; 8 | import Operation from "../Operation.mjs"; 9 | 10 | /** 11 | * SQL Beautify operation 12 | */ 13 | class SQLBeautify extends Operation { 14 | 15 | /** 16 | * SQLBeautify constructor 17 | */ 18 | constructor() { 19 | super(); 20 | 21 | this.name = "SQL Beautify"; 22 | this.module = "Code"; 23 | this.description = "Indents and prettifies Structured Query Language (SQL) code."; 24 | this.inputType = "string"; 25 | this.outputType = "string"; 26 | this.args = [ 27 | { 28 | "name": "Indent string", 29 | "type": "binaryShortString", 30 | "value": "\\t" 31 | } 32 | ]; 33 | } 34 | 35 | /** 36 | * @param {string} input 37 | * @param {Object[]} args 38 | * @returns {string} 39 | */ 40 | run(input, args) { 41 | const indentStr = args[0]; 42 | return vkbeautify.sql(input, indentStr); 43 | } 44 | 45 | } 46 | 47 | export default SQLBeautify; 48 | -------------------------------------------------------------------------------- /src/core/operations/SQLMinify.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * @author n1474335 [n1474335@gmail.com] 3 | * @copyright Crown Copyright 2016 4 | * @license Apache-2.0 5 | */ 6 | 7 | import vkbeautify from "vkbeautify"; 8 | import Operation from "../Operation.mjs"; 9 | 10 | /** 11 | * SQL Minify operation 12 | */ 13 | class SQLMinify extends Operation { 14 | 15 | /** 16 | * SQLMinify constructor 17 | */ 18 | constructor() { 19 | super(); 20 | 21 | this.name = "SQL Minify"; 22 | this.module = "Code"; 23 | this.description = "Compresses Structured Query Language (SQL) code."; 24 | this.inputType = "string"; 25 | this.outputType = "string"; 26 | this.args = []; 27 | } 28 | 29 | /** 30 | * @param {string} input 31 | * @param {Object[]} args 32 | * @returns {string} 33 | */ 34 | run(input, args) { 35 | return vkbeautify.sqlmin(input); 36 | } 37 | 38 | } 39 | 40 | export default SQLMinify; 41 | -------------------------------------------------------------------------------- /src/core/operations/SSDEEP.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * @author n1474335 [n1474335@gmail.com] 3 | * @copyright Crown Copyright 2016 4 | * @license Apache-2.0 5 | */ 6 | 7 | import Operation from "../Operation.mjs"; 8 | import ssdeepjs from "ssdeep.js"; 9 | 10 | /** 11 | * SSDEEP operation 12 | */ 13 | class SSDEEP extends Operation { 14 | 15 | /** 16 | * SSDEEP constructor 17 | */ 18 | constructor() { 19 | super(); 20 | 21 | this.name = "SSDEEP"; 22 | this.module = "Crypto"; 23 | this.description = "SSDEEP is a program for computing context triggered piecewise hashes (CTPH). Also called fuzzy hashes, CTPH can match inputs that have homologies. Such inputs have sequences of identical bytes in the same order, although bytes in between these sequences may be different in both content and length.

SSDEEP hashes are now widely used for simple identification purposes (e.g. the 'Basic Properties' section in VirusTotal). Although 'better' fuzzy hashes are available, SSDEEP is still one of the primary choices because of its speed and being a de facto standard.

This operation is fundamentally the same as the CTPH operation, however their outputs differ in format."; 24 | this.infoURL = "https://forensics.wiki/ssdeep"; 25 | this.inputType = "string"; 26 | this.outputType = "string"; 27 | this.args = []; 28 | } 29 | 30 | /** 31 | * @param {string} input 32 | * @param {Object[]} args 33 | * @returns {string} 34 | */ 35 | run(input, args) { 36 | return ssdeepjs.digest(input); 37 | } 38 | 39 | } 40 | 41 | export default SSDEEP; 42 | -------------------------------------------------------------------------------- /src/core/operations/Sleep.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * @author n1474335 [n1474335@gmail.com] 3 | * @copyright Crown Copyright 2018 4 | * @license Apache-2.0 5 | */ 6 | 7 | import Operation from "../Operation.mjs"; 8 | 9 | /** 10 | * Sleep operation 11 | */ 12 | class Sleep extends Operation { 13 | 14 | /** 15 | * Sleep constructor 16 | */ 17 | constructor() { 18 | super(); 19 | 20 | this.name = "Sleep"; 21 | this.module = "Default"; 22 | this.description = "Sleep causes the recipe to wait for a specified number of milliseconds before continuing execution."; 23 | this.inputType = "ArrayBuffer"; 24 | this.outputType = "ArrayBuffer"; 25 | this.args = [ 26 | { 27 | "name": "Time (ms)", 28 | "type": "number", 29 | "value": 1000 30 | } 31 | ]; 32 | } 33 | 34 | /** 35 | * @param {ArrayBuffer} input 36 | * @param {Object[]} args 37 | * @returns {ArrayBuffer} 38 | */ 39 | async run(input, args) { 40 | const ms = args[0]; 41 | await new Promise(r => setTimeout(r, ms)); 42 | return input; 43 | } 44 | 45 | } 46 | 47 | export default Sleep; 48 | -------------------------------------------------------------------------------- /src/core/operations/Split.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * @author n1474335 [n1474335@gmail.com] 3 | * @copyright Crown Copyright 2016 4 | * @license Apache-2.0 5 | */ 6 | 7 | import Operation from "../Operation.mjs"; 8 | import {SPLIT_DELIM_OPTIONS, JOIN_DELIM_OPTIONS} from "../lib/Delim.mjs"; 9 | 10 | /** 11 | * Split operation 12 | */ 13 | class Split extends Operation { 14 | 15 | /** 16 | * Split constructor 17 | */ 18 | constructor() { 19 | super(); 20 | 21 | this.name = "Split"; 22 | this.module = "Default"; 23 | this.description = "Splits a string into sections around a given delimiter."; 24 | this.inputType = "string"; 25 | this.outputType = "string"; 26 | this.args = [ 27 | { 28 | "name": "Split delimiter", 29 | "type": "editableOptionShort", 30 | "value": SPLIT_DELIM_OPTIONS 31 | }, 32 | { 33 | "name": "Join delimiter", 34 | "type": "editableOptionShort", 35 | "value": JOIN_DELIM_OPTIONS 36 | } 37 | ]; 38 | } 39 | 40 | /** 41 | * @param {string} input 42 | * @param {Object[]} args 43 | * @returns {string} 44 | */ 45 | run(input, args) { 46 | const splitDelim = args[0], 47 | joinDelim = args[1], 48 | sections = input.split(splitDelim); 49 | 50 | return sections.join(joinDelim); 51 | } 52 | 53 | } 54 | 55 | export default Split; 56 | -------------------------------------------------------------------------------- /src/core/operations/StripHTTPHeaders.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * @author n1474335 [n1474335@gmail.com] 3 | * @copyright Crown Copyright 2016 4 | * @license Apache-2.0 5 | */ 6 | 7 | import Operation from "../Operation.mjs"; 8 | 9 | /** 10 | * Strip HTTP headers operation 11 | */ 12 | class StripHTTPHeaders extends Operation { 13 | 14 | /** 15 | * StripHTTPHeaders constructor 16 | */ 17 | constructor() { 18 | super(); 19 | 20 | this.name = "Strip HTTP headers"; 21 | this.module = "Default"; 22 | this.description = "Removes HTTP headers from a request or response by looking for the first instance of a double newline."; 23 | this.infoURL = "https://wikipedia.org/wiki/Hypertext_Transfer_Protocol#Message_format"; 24 | this.inputType = "string"; 25 | this.outputType = "string"; 26 | this.args = []; 27 | this.checks = [ 28 | { 29 | pattern: "^HTTP(.|\\s)+?(\\r?\\n){2}", 30 | flags: "", 31 | args: [] 32 | } 33 | ]; 34 | } 35 | 36 | /** 37 | * @param {string} input 38 | * @param {Object[]} args 39 | * @returns {string} 40 | */ 41 | run(input, args) { 42 | let headerEnd = input.indexOf("\r\n\r\n"); 43 | headerEnd = (headerEnd < 0) ? input.indexOf("\n\n") + 2 : headerEnd + 4; 44 | 45 | return (headerEnd < 2) ? input : input.slice(headerEnd, input.length); 46 | } 47 | 48 | } 49 | 50 | export default StripHTTPHeaders; 51 | -------------------------------------------------------------------------------- /src/core/operations/StripUDPHeader.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * @author c65722 [] 3 | * @copyright Crown Copyright 2024 4 | * @license Apache-2.0 5 | */ 6 | 7 | import Operation from "../Operation.mjs"; 8 | import Stream from "../lib/Stream.mjs"; 9 | import OperationError from "../errors/OperationError.mjs"; 10 | 11 | /** 12 | * Strip UDP header operation 13 | */ 14 | class StripUDPHeader extends Operation { 15 | 16 | /** 17 | * StripUDPHeader constructor 18 | */ 19 | constructor() { 20 | super(); 21 | 22 | this.name = "Strip UDP header"; 23 | this.module = "Default"; 24 | this.description = "Strips the UDP header from a UDP datagram, outputting the payload."; 25 | this.infoURL = "https://wikipedia.org/wiki/User_Datagram_Protocol"; 26 | this.inputType = "ArrayBuffer"; 27 | this.outputType = "ArrayBuffer"; 28 | this.args = []; 29 | } 30 | 31 | /** 32 | * @param {ArrayBuffer} input 33 | * @param {Object[]} args 34 | * @returns {ArrayBuffer} 35 | */ 36 | run(input, args) { 37 | const HEADER_LEN = 8; 38 | 39 | const s = new Stream(new Uint8Array(input)); 40 | if (s.length < HEADER_LEN) { 41 | throw new OperationError("Need 8 bytes for a UDP Header"); 42 | } 43 | 44 | s.moveTo(HEADER_LEN); 45 | 46 | return s.getBytes().buffer; 47 | } 48 | 49 | } 50 | 51 | export default StripUDPHeader; 52 | -------------------------------------------------------------------------------- /src/core/operations/Subtract.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * @author bwhitn [brian.m.whitney@outlook.com] 3 | * @author d98762625 [d98762625@gmail.com] 4 | * @copyright Crown Copyright 2018 5 | * @license Apache-2.0 6 | */ 7 | 8 | import BigNumber from "bignumber.js"; 9 | import Operation from "../Operation.mjs"; 10 | import { sub, createNumArray } from "../lib/Arithmetic.mjs"; 11 | import { ARITHMETIC_DELIM_OPTIONS } from "../lib/Delim.mjs"; 12 | 13 | 14 | /** 15 | * Subtract operation 16 | */ 17 | class Subtract extends Operation { 18 | 19 | /** 20 | * Subtract constructor 21 | */ 22 | constructor() { 23 | super(); 24 | 25 | this.name = "Subtract"; 26 | this.module = "Default"; 27 | this.description = "Subtracts a list of numbers. If an item in the string is not a number it is excluded from the list.

e.g. 0x0a 8 .5 becomes 1.5"; 28 | this.infoURL = "https://wikipedia.org/wiki/Subtraction"; 29 | this.inputType = "string"; 30 | this.outputType = "BigNumber"; 31 | this.args = [ 32 | { 33 | "name": "Delimiter", 34 | "type": "option", 35 | "value": ARITHMETIC_DELIM_OPTIONS, 36 | } 37 | ]; 38 | } 39 | 40 | /** 41 | * @param {string} input 42 | * @param {Object[]} args 43 | * @returns {BigNumber} 44 | */ 45 | run(input, args) { 46 | const val = sub(createNumArray(input, args[0])); 47 | return BigNumber.isBigNumber(val) ? val : new BigNumber(NaN); 48 | } 49 | 50 | } 51 | 52 | export default Subtract; 53 | -------------------------------------------------------------------------------- /src/core/operations/Sum.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * @author bwhitn [brian.m.whitney@outlook.com] 3 | * @author d98762625 [d98762625@gmail.com] 4 | * @copyright Crown Copyright 2016 5 | * @license Apache-2.0 6 | */ 7 | 8 | import BigNumber from "bignumber.js"; 9 | import Operation from "../Operation.mjs"; 10 | import { sum, createNumArray } from "../lib/Arithmetic.mjs"; 11 | import { ARITHMETIC_DELIM_OPTIONS } from "../lib/Delim.mjs"; 12 | 13 | 14 | /** 15 | * Sum operation 16 | */ 17 | class Sum extends Operation { 18 | 19 | /** 20 | * Sum constructor 21 | */ 22 | constructor() { 23 | super(); 24 | 25 | this.name = "Sum"; 26 | this.module = "Default"; 27 | this.description = "Adds together a list of numbers. If an item in the string is not a number it is excluded from the list.

e.g. 0x0a 8 .5 becomes 18.5"; 28 | this.infoURL = "https://wikipedia.org/wiki/Summation"; 29 | this.inputType = "string"; 30 | this.outputType = "BigNumber"; 31 | this.args = [ 32 | { 33 | "name": "Delimiter", 34 | "type": "option", 35 | "value": ARITHMETIC_DELIM_OPTIONS, 36 | } 37 | ]; 38 | } 39 | 40 | /** 41 | * @param {string} input 42 | * @param {Object[]} args 43 | * @returns {BigNumber} 44 | */ 45 | run(input, args) { 46 | const val = sum(createNumArray(input, args[0])); 47 | return BigNumber.isBigNumber(val) ? val : new BigNumber(NaN); 48 | } 49 | 50 | } 51 | 52 | export default Sum; 53 | -------------------------------------------------------------------------------- /src/core/operations/TCPIPChecksum.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * @author n1474335 [n1474335@gmail.com] 3 | * @copyright Crown Copyright 2016 4 | * @license Apache-2.0 5 | */ 6 | 7 | import Operation from "../Operation.mjs"; 8 | import Utils from "../Utils.mjs"; 9 | 10 | /** 11 | * TCP/IP Checksum operation 12 | */ 13 | class TCPIPChecksum extends Operation { 14 | 15 | /** 16 | * TCPIPChecksum constructor 17 | */ 18 | constructor() { 19 | super(); 20 | 21 | this.name = "TCP/IP Checksum"; 22 | this.module = "Crypto"; 23 | this.description = "Calculates the checksum for a TCP (Transport Control Protocol) or IP (Internet Protocol) header from an input of raw bytes."; 24 | this.infoURL = "https://wikipedia.org/wiki/IPv4_header_checksum"; 25 | this.inputType = "ArrayBuffer"; 26 | this.outputType = "string"; 27 | this.args = []; 28 | } 29 | 30 | /** 31 | * @param {ArrayBuffer} input 32 | * @param {Object[]} args 33 | * @returns {string} 34 | */ 35 | run(input, args) { 36 | input = new Uint8Array(input); 37 | let csum = 0; 38 | 39 | for (let i = 0; i < input.length; i++) { 40 | if (i % 2 === 0) { 41 | csum += (input[i] << 8); 42 | } else { 43 | csum += input[i]; 44 | } 45 | } 46 | 47 | csum = (csum >> 16) + (csum & 0xffff); 48 | 49 | return Utils.hex(0xffff - csum); 50 | } 51 | 52 | } 53 | 54 | export default TCPIPChecksum; 55 | -------------------------------------------------------------------------------- /src/core/operations/Template.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * @author kendallgoto [k@kgo.to] 3 | * @copyright Crown Copyright 2025 4 | * @license Apache-2.0 5 | */ 6 | 7 | import Operation from "../Operation.mjs"; 8 | import OperationError from "../errors/OperationError.mjs"; 9 | import Handlebars from "handlebars"; 10 | 11 | /** 12 | * Template operation 13 | */ 14 | class Template extends Operation { 15 | 16 | /** 17 | * Template constructor 18 | */ 19 | constructor() { 20 | super(); 21 | 22 | this.name = "Template"; 23 | this.module = "Handlebars"; 24 | this.description = "Render a template with Handlebars/Mustache substituting variables using JSON input. Templates will be rendered to plain-text only, to prevent XSS."; 25 | this.infoURL = "https://handlebarsjs.com/"; 26 | this.inputType = "JSON"; 27 | this.outputType = "string"; 28 | this.args = [ 29 | { 30 | name: "Template definition (.handlebars)", 31 | type: "text", 32 | value: "" 33 | } 34 | ]; 35 | } 36 | 37 | /** 38 | * @param {JSON} input 39 | * @param {Object[]} args 40 | * @returns {string} 41 | */ 42 | run(input, args) { 43 | const [templateStr] = args; 44 | try { 45 | const template = Handlebars.compile(templateStr); 46 | return template(input); 47 | } catch (e) { 48 | throw new OperationError(e); 49 | } 50 | } 51 | } 52 | 53 | export default Template; 54 | -------------------------------------------------------------------------------- /src/core/operations/ToBase.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * @author n1474335 [n1474335@gmail.com] 3 | * @copyright Crown Copyright 2016 4 | * @license Apache-2.0 5 | */ 6 | 7 | import Operation from "../Operation.mjs"; 8 | import OperationError from "../errors/OperationError.mjs"; 9 | 10 | /** 11 | * To Base operation 12 | */ 13 | class ToBase extends Operation { 14 | 15 | /** 16 | * ToBase constructor 17 | */ 18 | constructor() { 19 | super(); 20 | 21 | this.name = "To Base"; 22 | this.module = "Default"; 23 | this.description = "Converts a decimal number to a given numerical base."; 24 | this.infoURL = "https://wikipedia.org/wiki/Radix"; 25 | this.inputType = "BigNumber"; 26 | this.outputType = "string"; 27 | this.args = [ 28 | { 29 | "name": "Radix", 30 | "type": "number", 31 | "value": 36 32 | } 33 | ]; 34 | } 35 | 36 | /** 37 | * @param {BigNumber} input 38 | * @param {Object[]} args 39 | * @returns {string} 40 | */ 41 | run(input, args) { 42 | if (!input) { 43 | throw new OperationError("Error: Input must be a number"); 44 | } 45 | const radix = args[0]; 46 | if (radix < 2 || radix > 36) { 47 | throw new OperationError("Error: Radix argument must be between 2 and 36"); 48 | } 49 | return input.toString(radix); 50 | } 51 | 52 | } 53 | 54 | export default ToBase; 55 | -------------------------------------------------------------------------------- /src/core/operations/ToLowerCase.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * @author n1474335 [n1474335@gmail.com] 3 | * @copyright Crown Copyright 2016 4 | * @license Apache-2.0 5 | */ 6 | 7 | import Operation from "../Operation.mjs"; 8 | 9 | /** 10 | * To Lower case operation 11 | */ 12 | class ToLowerCase extends Operation { 13 | 14 | /** 15 | * ToLowerCase constructor 16 | */ 17 | constructor() { 18 | super(); 19 | 20 | this.name = "To Lower case"; 21 | this.module = "Default"; 22 | this.description = "Converts every character in the input to lower case."; 23 | this.inputType = "string"; 24 | this.outputType = "string"; 25 | this.args = []; 26 | } 27 | 28 | /** 29 | * @param {string} input 30 | * @param {Object[]} args 31 | * @returns {string} 32 | */ 33 | run(input, args) { 34 | return input.toLowerCase(); 35 | } 36 | 37 | /** 38 | * Highlight To Lower case 39 | * 40 | * @param {Object[]} pos 41 | * @param {number} pos[].start 42 | * @param {number} pos[].end 43 | * @param {Object[]} args 44 | * @returns {Object[]} pos 45 | */ 46 | highlight(pos, args) { 47 | return pos; 48 | } 49 | 50 | /** 51 | * Highlight To Lower case in reverse 52 | * 53 | * @param {Object[]} pos 54 | * @param {number} pos[].start 55 | * @param {number} pos[].end 56 | * @param {Object[]} args 57 | * @returns {Object[]} pos 58 | */ 59 | highlightReverse(pos, args) { 60 | return pos; 61 | } 62 | 63 | } 64 | 65 | export default ToLowerCase; 66 | -------------------------------------------------------------------------------- /src/core/operations/ToModhex.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * @author linuxgemini [ilteris@asenkron.com.tr] 3 | * @copyright Crown Copyright 2024 4 | * @license Apache-2.0 5 | */ 6 | 7 | import Operation from "../Operation.mjs"; 8 | import { TO_MODHEX_DELIM_OPTIONS, toModhex } from "../lib/Modhex.mjs"; 9 | import Utils from "../Utils.mjs"; 10 | 11 | /** 12 | * To Modhex operation 13 | */ 14 | class ToModhex extends Operation { 15 | 16 | /** 17 | * ToModhex constructor 18 | */ 19 | constructor() { 20 | super(); 21 | 22 | this.name = "To Modhex"; 23 | this.module = "Default"; 24 | this.description = "Converts the input string to modhex bytes separated by the specified delimiter."; 25 | this.infoURL = "https://en.wikipedia.org/wiki/YubiKey#ModHex"; 26 | this.inputType = "ArrayBuffer"; 27 | this.outputType = "string"; 28 | this.args = [ 29 | { 30 | name: "Delimiter", 31 | type: "option", 32 | value: TO_MODHEX_DELIM_OPTIONS 33 | }, 34 | { 35 | name: "Bytes per line", 36 | type: "number", 37 | value: 0 38 | } 39 | ]; 40 | } 41 | 42 | /** 43 | * @param {ArrayBuffer} input 44 | * @param {Object[]} args 45 | * @returns {string} 46 | */ 47 | run(input, args) { 48 | const delim = Utils.charRep(args[0]); 49 | const lineSize = args[1]; 50 | 51 | return toModhex(new Uint8Array(input), delim, 2, "", lineSize); 52 | } 53 | } 54 | 55 | export default ToModhex; 56 | -------------------------------------------------------------------------------- /src/core/operations/ToOctal.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * @author Matt C [matt@artemisbot.uk] 3 | * @copyright Crown Copyright 2017 4 | * @license Apache-2.0 5 | */ 6 | 7 | import Operation from "../Operation.mjs"; 8 | import Utils from "../Utils.mjs"; 9 | import {DELIM_OPTIONS} from "../lib/Delim.mjs"; 10 | 11 | 12 | /** 13 | * To Octal operation 14 | */ 15 | class ToOctal extends Operation { 16 | 17 | /** 18 | * ToOctal constructor 19 | */ 20 | constructor() { 21 | super(); 22 | 23 | this.name = "To Octal"; 24 | this.module = "Default"; 25 | this.description = "Converts the input string to octal bytes separated by the specified delimiter.

e.g. The UTF-8 encoded string Γειά σου becomes 316 223 316 265 316 271 316 254 40 317 203 316 277 317 205"; 26 | this.infoURL = "https://wikipedia.org/wiki/Octal"; 27 | this.inputType = "byteArray"; 28 | this.outputType = "string"; 29 | this.args = [ 30 | { 31 | "name": "Delimiter", 32 | "type": "option", 33 | "value": DELIM_OPTIONS 34 | } 35 | ]; 36 | } 37 | 38 | /** 39 | * @param {byteArray} input 40 | * @param {Object[]} args 41 | * @returns {string} 42 | */ 43 | run(input, args) { 44 | const delim = Utils.charRep(args[0] || "Space"); 45 | return input.map(val => val.toString(8)).join(delim); 46 | } 47 | 48 | } 49 | 50 | export default ToOctal; 51 | -------------------------------------------------------------------------------- /src/core/operations/ToPunycode.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * @author n1474335 [n1474335@gmail.com] 3 | * @copyright Crown Copyright 2016 4 | * @license Apache-2.0 5 | */ 6 | 7 | import Operation from "../Operation.mjs"; 8 | import punycode from "punycode"; 9 | 10 | /** 11 | * To Punycode operation 12 | */ 13 | class ToPunycode extends Operation { 14 | 15 | /** 16 | * ToPunycode constructor 17 | */ 18 | constructor() { 19 | super(); 20 | 21 | this.name = "To Punycode"; 22 | this.module = "Encodings"; 23 | this.description = "Punycode is a way to represent Unicode with the limited character subset of ASCII supported by the Domain Name System.

e.g. m\xfcnchen encodes to mnchen-3ya"; 24 | this.infoURL = "https://wikipedia.org/wiki/Punycode"; 25 | this.inputType = "string"; 26 | this.outputType = "string"; 27 | this.args = [ 28 | { 29 | "name": "Internationalised domain name", 30 | "type": "boolean", 31 | "value": false 32 | } 33 | ]; 34 | } 35 | 36 | /** 37 | * @param {string} input 38 | * @param {Object[]} args 39 | * @returns {string} 40 | */ 41 | run(input, args) { 42 | const idn = args[0]; 43 | 44 | if (idn) { 45 | return punycode.toASCII(input); 46 | } else { 47 | return punycode.encode(input); 48 | } 49 | } 50 | 51 | } 52 | 53 | export default ToPunycode; 54 | -------------------------------------------------------------------------------- /src/core/operations/VarIntDecode.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * @author GCHQ Contributor [3] 3 | * @copyright Crown Copyright 2019 4 | * @license Apache-2.0 5 | */ 6 | 7 | import Operation from "../Operation.mjs"; 8 | import OperationError from "../errors/OperationError.mjs"; 9 | import Protobuf from "../lib/Protobuf.mjs"; 10 | 11 | /** 12 | * VarInt Decode operation 13 | */ 14 | class VarIntDecode extends Operation { 15 | 16 | /** 17 | * VarIntDecode constructor 18 | */ 19 | constructor() { 20 | super(); 21 | 22 | this.name = "VarInt Decode"; 23 | this.module = "Default"; 24 | this.description = "Decodes a VarInt encoded integer. VarInt is an efficient way of encoding variable length integers and is commonly used with Protobuf."; 25 | this.infoURL = "https://developers.google.com/protocol-buffers/docs/encoding#varints"; 26 | this.inputType = "byteArray"; 27 | this.outputType = "number"; 28 | this.args = []; 29 | } 30 | 31 | /** 32 | * @param {byteArray} input 33 | * @param {Object[]} args 34 | * @returns {number} 35 | */ 36 | run(input, args) { 37 | try { 38 | return Protobuf.varIntDecode(input); 39 | } catch (err) { 40 | throw new OperationError(err); 41 | } 42 | } 43 | 44 | } 45 | 46 | export default VarIntDecode; 47 | -------------------------------------------------------------------------------- /src/core/operations/VarIntEncode.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * @author GCHQ Contributor [3] 3 | * @copyright Crown Copyright 2019 4 | * @license Apache-2.0 5 | */ 6 | 7 | import Operation from "../Operation.mjs"; 8 | import OperationError from "../errors/OperationError.mjs"; 9 | import Protobuf from "../lib/Protobuf.mjs"; 10 | 11 | /** 12 | * VarInt Encode operation 13 | */ 14 | class VarIntEncode extends Operation { 15 | 16 | /** 17 | * VarIntEncode constructor 18 | */ 19 | constructor() { 20 | super(); 21 | 22 | this.name = "VarInt Encode"; 23 | this.module = "Default"; 24 | this.description = "Encodes a Vn integer as a VarInt. VarInt is an efficient way of encoding variable length integers and is commonly used with Protobuf."; 25 | this.infoURL = "https://developers.google.com/protocol-buffers/docs/encoding#varints"; 26 | this.inputType = "number"; 27 | this.outputType = "byteArray"; 28 | this.args = []; 29 | } 30 | 31 | /** 32 | * @param {number} input 33 | * @param {Object[]} args 34 | * @returns {byteArray} 35 | */ 36 | run(input, args) { 37 | try { 38 | return Protobuf.varIntEncode(input); 39 | } catch (err) { 40 | throw new OperationError(err); 41 | } 42 | } 43 | 44 | } 45 | 46 | export default VarIntEncode; 47 | -------------------------------------------------------------------------------- /src/core/operations/XKCDRandomNumber.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * @author n1474335 [n1474335@gmail.com] 3 | * @copyright Crown Copyright 2018 4 | * @license Apache-2.0 5 | */ 6 | 7 | import Operation from "../Operation.mjs"; 8 | 9 | /** 10 | * XKCD Random Number operation 11 | */ 12 | class XKCDRandomNumber extends Operation { 13 | 14 | /** 15 | * XKCDRandomNumber constructor 16 | */ 17 | constructor() { 18 | super(); 19 | 20 | this.name = "XKCD Random Number"; 21 | this.module = "Default"; 22 | this.description = "RFC 1149.5 specifies 4 as the standard IEEE-vetted random number."; 23 | this.infoURL = "https://xkcd.com/221/"; 24 | this.inputType = "string"; 25 | this.outputType = "number"; 26 | this.args = []; 27 | } 28 | 29 | /** 30 | * @param {string} input 31 | * @param {Object[]} args 32 | * @returns {number} 33 | */ 34 | run(input, args) { 35 | return 4; // chosen by fair dice roll. 36 | // guaranteed to be random. 37 | } 38 | 39 | } 40 | 41 | export default XKCDRandomNumber; 42 | -------------------------------------------------------------------------------- /src/core/operations/XMLBeautify.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * @author n1474335 [n1474335@gmail.com] 3 | * @copyright Crown Copyright 2016 4 | * @license Apache-2.0 5 | */ 6 | 7 | import vkbeautify from "vkbeautify"; 8 | import Operation from "../Operation.mjs"; 9 | 10 | /** 11 | * XML Beautify operation 12 | */ 13 | class XMLBeautify extends Operation { 14 | 15 | /** 16 | * XMLBeautify constructor 17 | */ 18 | constructor() { 19 | super(); 20 | 21 | this.name = "XML Beautify"; 22 | this.module = "Code"; 23 | this.description = "Indents and prettifies eXtensible Markup Language (XML) code."; 24 | this.inputType = "string"; 25 | this.outputType = "string"; 26 | this.args = [ 27 | { 28 | "name": "Indent string", 29 | "type": "binaryShortString", 30 | "value": "\\t" 31 | } 32 | ]; 33 | } 34 | 35 | /** 36 | * @param {string} input 37 | * @param {Object[]} args 38 | * @returns {string} 39 | */ 40 | run(input, args) { 41 | const indentStr = args[0]; 42 | return vkbeautify.xml(input, indentStr); 43 | } 44 | 45 | } 46 | 47 | export default XMLBeautify; 48 | -------------------------------------------------------------------------------- /src/core/operations/XMLMinify.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * @author n1474335 [n1474335@gmail.com] 3 | * @copyright Crown Copyright 2016 4 | * @license Apache-2.0 5 | */ 6 | 7 | import vkbeautify from "vkbeautify"; 8 | import Operation from "../Operation.mjs"; 9 | 10 | /** 11 | * XML Minify operation 12 | */ 13 | class XMLMinify extends Operation { 14 | 15 | /** 16 | * XMLMinify constructor 17 | */ 18 | constructor() { 19 | super(); 20 | 21 | this.name = "XML Minify"; 22 | this.module = "Code"; 23 | this.description = "Compresses eXtensible Markup Language (XML) code."; 24 | this.inputType = "string"; 25 | this.outputType = "string"; 26 | this.args = [ 27 | { 28 | "name": "Preserve comments", 29 | "type": "boolean", 30 | "value": false 31 | } 32 | ]; 33 | } 34 | 35 | /** 36 | * @param {string} input 37 | * @param {Object[]} args 38 | * @returns {string} 39 | */ 40 | run(input, args) { 41 | const preserveComments = args[0]; 42 | return vkbeautify.xmlmin(input, preserveComments); 43 | } 44 | 45 | } 46 | 47 | export default XMLMinify; 48 | -------------------------------------------------------------------------------- /src/core/operations/YAMLToJSON.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * @author ccarpo [ccarpo@gmx.net] 3 | * @copyright Crown Copyright 2021 4 | * @license Apache-2.0 5 | */ 6 | 7 | import Operation from "../Operation.mjs"; 8 | import OperationError from "../errors/OperationError.mjs"; 9 | import jsYaml from "js-yaml"; 10 | /** 11 | * YAML to JSON operation 12 | */ 13 | class YAMLToJSON extends Operation { 14 | 15 | /** 16 | * YAMLToJSON constructor 17 | */ 18 | constructor() { 19 | super(); 20 | 21 | this.name = "YAML to JSON"; 22 | this.module = "Default"; 23 | this.description = "Convert YAML to JSON"; 24 | this.infoURL = "https://en.wikipedia.org/wiki/YAML"; 25 | this.inputType = "string"; 26 | this.outputType = "JSON"; 27 | this.args = []; 28 | } 29 | 30 | /** 31 | * @param {string} input 32 | * @param {Object[]} args 33 | * @returns {JSON} 34 | */ 35 | run(input, args) { 36 | try { 37 | return jsYaml.load(input); 38 | } catch (err) { 39 | throw new OperationError("Unable to parse YAML: " + err); 40 | } 41 | } 42 | 43 | } 44 | 45 | export default YAMLToJSON; 46 | -------------------------------------------------------------------------------- /src/core/operations/ZlibDeflate.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * @author n1474335 [n1474335@gmail.com] 3 | * @copyright Crown Copyright 2016 4 | * @license Apache-2.0 5 | */ 6 | 7 | import Operation from "../Operation.mjs"; 8 | import {COMPRESSION_TYPE, ZLIB_COMPRESSION_TYPE_LOOKUP} from "../lib/Zlib.mjs"; 9 | import zlibAndGzip from "zlibjs/bin/zlib_and_gzip.min.js"; 10 | 11 | const Zlib = zlibAndGzip.Zlib; 12 | 13 | /** 14 | * Zlib Deflate operation 15 | */ 16 | class ZlibDeflate extends Operation { 17 | 18 | /** 19 | * ZlibDeflate constructor 20 | */ 21 | constructor() { 22 | super(); 23 | 24 | this.name = "Zlib Deflate"; 25 | this.module = "Compression"; 26 | this.description = "Compresses data using the deflate algorithm adding zlib headers."; 27 | this.infoURL = "https://wikipedia.org/wiki/Zlib"; 28 | this.inputType = "ArrayBuffer"; 29 | this.outputType = "ArrayBuffer"; 30 | this.args = [ 31 | { 32 | name: "Compression type", 33 | type: "option", 34 | value: COMPRESSION_TYPE 35 | } 36 | ]; 37 | } 38 | 39 | /** 40 | * @param {ArrayBuffer} input 41 | * @param {Object[]} args 42 | * @returns {ArrayBuffer} 43 | */ 44 | run(input, args) { 45 | const deflate = new Zlib.Deflate(new Uint8Array(input), { 46 | compressionType: ZLIB_COMPRESSION_TYPE_LOOKUP[args[0]] 47 | }); 48 | return new Uint8Array(deflate.compress()).buffer; 49 | } 50 | 51 | } 52 | 53 | export default ZlibDeflate; 54 | -------------------------------------------------------------------------------- /src/core/vendor/tesseract/lang-data/eng.traineddata.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gchq/CyberChef/c57556f49f723863b9be15668fd240672cd15b09/src/core/vendor/tesseract/lang-data/eng.traineddata.gz -------------------------------------------------------------------------------- /src/node/config/excludedOperations.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * Operations to exclude from the Node API 3 | * 4 | * @author d98762656 [d98762625@gmail.com] 5 | * @copyright Crown Copyright 2018 6 | * @license Apache-2.0 7 | */ 8 | export default [ 9 | // This functionality can be done more easily using JavaScript 10 | "Fork", 11 | "Merge", 12 | "Jump", 13 | "ConditionalJump", 14 | "Label", 15 | "Comment", 16 | 17 | // esprima doesn't work in .mjs 18 | "JavaScriptBeautify", 19 | "JavaScriptMinify", 20 | "JavaScriptParser", 21 | 22 | // Irrelevant in Node console 23 | "SyntaxHighlighter", 24 | ]; 25 | -------------------------------------------------------------------------------- /src/node/repl.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * Create a REPL server for chef 3 | * 4 | * 5 | * @author d98762656 [d98762625@gmail.com] 6 | * @copyright Crown Copyright 2018 7 | * @license Apache-2.0 8 | */ 9 | 10 | import chef from "./index.mjs"; 11 | import repl from "repl"; 12 | 13 | 14 | /* eslint no-console: ["off"] */ 15 | 16 | console.log(` 17 | ______ __ ________ ____ 18 | / ____/_ __/ /_ ___ _____/ ____/ /_ ___ / __/ 19 | / / / / / / __ \\/ _ \\/ ___/ / / __ \\/ _ \\/ /_ 20 | / /___/ /_/ / /_/ / __/ / / /___/ / / / __/ __/ 21 | \\____/\\__, /_.___/\\___/_/ \\____/_/ /_/\\___/_/ 22 | /____/ 23 | 24 | `); 25 | const replServer = repl.start({ 26 | prompt: "chef > ", 27 | }); 28 | 29 | global.File = chef.File; 30 | 31 | Object.keys(chef).forEach((key) => { 32 | if (key !== "operations") { 33 | replServer.context[key] = chef[key]; 34 | } 35 | }); 36 | 37 | -------------------------------------------------------------------------------- /src/node/wrapper.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Export the main ESM module as CommonJS 3 | * 4 | * 5 | * @author d98762656 [d98762625@gmail.com] 6 | * @copyright Crown Copyright 2019 7 | * @license Apache-2.0 8 | */ 9 | 10 | module.exports = (async () => await import("./index.mjs"))(); 11 | module.exports.File = (async () => await import("./File.mjs"))(); 12 | -------------------------------------------------------------------------------- /src/web/static/fonts/MaterialIcons-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gchq/CyberChef/c57556f49f723863b9be15668fd240672cd15b09/src/web/static/fonts/MaterialIcons-Regular.ttf -------------------------------------------------------------------------------- /src/web/static/fonts/bmfonts/Roboto72White.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gchq/CyberChef/c57556f49f723863b9be15668fd240672cd15b09/src/web/static/fonts/bmfonts/Roboto72White.png -------------------------------------------------------------------------------- /src/web/static/fonts/bmfonts/RobotoBlack72White.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gchq/CyberChef/c57556f49f723863b9be15668fd240672cd15b09/src/web/static/fonts/bmfonts/RobotoBlack72White.png -------------------------------------------------------------------------------- /src/web/static/fonts/bmfonts/RobotoMono72White.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gchq/CyberChef/c57556f49f723863b9be15668fd240672cd15b09/src/web/static/fonts/bmfonts/RobotoMono72White.png -------------------------------------------------------------------------------- /src/web/static/fonts/bmfonts/RobotoSlab72White.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gchq/CyberChef/c57556f49f723863b9be15668fd240672cd15b09/src/web/static/fonts/bmfonts/RobotoSlab72White.png -------------------------------------------------------------------------------- /src/web/static/ga.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/web/static/images/IMAGE_LICENCES.md: -------------------------------------------------------------------------------- 1 | ## Image attribution 2 | 3 | The following image files in this directory are taken from open sources: 4 | 5 | | File | Licence | Attribution | 6 | | --------------------- | ----------------------------------------- | ----------------------------------------------------------------------------- | 7 | | cook_female-32x32.png | Creative Commons Attribution 3.0 Unported | https://commons.wikimedia.org/wiki/File:Farm-Fresh_user_cook_female_white.png | 8 | | cook_male-32x32.png | Creative Commons Attribution 3.0 Unported | https://commons.wikimedia.org/wiki/File:Farm-Fresh_user_cook_male_white.png | 9 | | file-32x32.png | Free for commercial use | https://www.iconfinder.com/icons/66768/file_info_icon | 10 | | file-128x128.png | Free for commercial use | https://www.iconfinder.com/icons/66768/file_info_icon | 11 | -------------------------------------------------------------------------------- /src/web/static/images/cook_female-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gchq/CyberChef/c57556f49f723863b9be15668fd240672cd15b09/src/web/static/images/cook_female-32x32.png -------------------------------------------------------------------------------- /src/web/static/images/cook_male-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gchq/CyberChef/c57556f49f723863b9be15668fd240672cd15b09/src/web/static/images/cook_male-32x32.png -------------------------------------------------------------------------------- /src/web/static/images/cyberchef-128x128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gchq/CyberChef/c57556f49f723863b9be15668fd240672cd15b09/src/web/static/images/cyberchef-128x128.png -------------------------------------------------------------------------------- /src/web/static/images/cyberchef-256x256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gchq/CyberChef/c57556f49f723863b9be15668fd240672cd15b09/src/web/static/images/cyberchef-256x256.png -------------------------------------------------------------------------------- /src/web/static/images/cyberchef-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gchq/CyberChef/c57556f49f723863b9be15668fd240672cd15b09/src/web/static/images/cyberchef-32x32.png -------------------------------------------------------------------------------- /src/web/static/images/cyberchef-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gchq/CyberChef/c57556f49f723863b9be15668fd240672cd15b09/src/web/static/images/cyberchef-512x512.png -------------------------------------------------------------------------------- /src/web/static/images/cyberchef-64x64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gchq/CyberChef/c57556f49f723863b9be15668fd240672cd15b09/src/web/static/images/cyberchef-64x64.png -------------------------------------------------------------------------------- /src/web/static/images/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gchq/CyberChef/c57556f49f723863b9be15668fd240672cd15b09/src/web/static/images/favicon.ico -------------------------------------------------------------------------------- /src/web/static/images/file-128x128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gchq/CyberChef/c57556f49f723863b9be15668fd240672cd15b09/src/web/static/images/file-128x128.png -------------------------------------------------------------------------------- /src/web/static/images/file-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gchq/CyberChef/c57556f49f723863b9be15668fd240672cd15b09/src/web/static/images/file-32x32.png -------------------------------------------------------------------------------- /src/web/static/images/fork_me.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gchq/CyberChef/c57556f49f723863b9be15668fd240672cd15b09/src/web/static/images/fork_me.png -------------------------------------------------------------------------------- /src/web/static/images/gitter-badge.svg: -------------------------------------------------------------------------------- 1 | chatchaton gitteron gitter -------------------------------------------------------------------------------- /src/web/static/images/logo/cyberchef_512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gchq/CyberChef/c57556f49f723863b9be15668fd240672cd15b09/src/web/static/images/logo/cyberchef_512.png -------------------------------------------------------------------------------- /src/web/static/images/logo/cyberchef_banner_1500.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gchq/CyberChef/c57556f49f723863b9be15668fd240672cd15b09/src/web/static/images/logo/cyberchef_banner_1500.png -------------------------------------------------------------------------------- /src/web/static/images/logo/cyberchef_hat_512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gchq/CyberChef/c57556f49f723863b9be15668fd240672cd15b09/src/web/static/images/logo/cyberchef_hat_512.png -------------------------------------------------------------------------------- /src/web/static/images/logo/cyberchef_hat_text_512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gchq/CyberChef/c57556f49f723863b9be15668fd240672cd15b09/src/web/static/images/logo/cyberchef_hat_text_512.png -------------------------------------------------------------------------------- /src/web/static/sitemap.mjs: -------------------------------------------------------------------------------- 1 | import sm from "sitemap"; 2 | import OperationConfig from "../../core/config/OperationConfig.json" assert {type: "json"}; 3 | 4 | 5 | /** 6 | * Generates an XML sitemap for all CyberChef operations and a number of recipes. 7 | * 8 | * @author n1474335 [n1474335@gmail.com] 9 | * @copyright Crown Copyright 2018 10 | * @license Apache-2.0 11 | */ 12 | 13 | const smStream = new sm.SitemapStream({ 14 | hostname: "https://gchq.github.io/CyberChef", 15 | }); 16 | 17 | smStream.write({ 18 | url: "/", 19 | changefreq: "weekly", 20 | priority: 1.0 21 | }); 22 | 23 | for (const op in OperationConfig) { 24 | smStream.write({ 25 | url: `/?op=${encodeURIComponent(op)}`, 26 | changeFreq: "yearly", 27 | priority: 0.5 28 | }); 29 | } 30 | smStream.end(); 31 | 32 | sm.streamToPromise(smStream).then( 33 | buffer => console.log(buffer.toString()) // eslint-disable-line no-console 34 | ); 35 | -------------------------------------------------------------------------------- /src/web/static/structuredData.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "@context": "http://schema.org", 4 | "@graph": [ 5 | { 6 | "@type": "Organization", 7 | "url": "https://gchq.github.io/CyberChef/", 8 | "logo": "https://gchq.github.io/CyberChef/images/cyberchef-128x128.png", 9 | "sameAs": [ 10 | "https://github.com/gchq/CyberChef", 11 | "https://www.npmjs.com/package/cyberchef" 12 | ] 13 | }, 14 | { 15 | "@type": "WebSite", 16 | "url": "https://gchq.github.io/CyberChef/", 17 | "name": "CyberChef", 18 | "potentialAction": { 19 | "@type": "SearchAction", 20 | "target": "https://gchq.github.io/CyberChef/?op={operation_search_term}", 21 | "query-input": "required name=operation_search_term" 22 | } 23 | } 24 | ] 25 | } 26 | ] -------------------------------------------------------------------------------- /src/web/stylesheets/components/_button.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Button styles 3 | * 4 | * @author n1474335 [n1474335@gmail.com] 5 | * @copyright Crown Copyright 2017 6 | * @license Apache-2.0 7 | */ 8 | 9 | button img, 10 | span.btn img { 11 | margin-right: 3px; 12 | margin-bottom: 1px; 13 | } 14 | -------------------------------------------------------------------------------- /src/web/stylesheets/components/_list.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Operation list styles 3 | * 4 | * @author n1474335 [n1474335@gmail.com] 5 | * @copyright Crown Copyright 2017 6 | * @license Apache-2.0 7 | */ 8 | 9 | .op-list { 10 | list-style-type: none; 11 | margin: 0; 12 | padding: 0; 13 | } 14 | 15 | .category-title { 16 | display: block; 17 | padding: 10px; 18 | background-color: var(--secondary-background-colour); 19 | border-bottom: 1px solid var(--secondary-border-colour); 20 | font-weight: var(--title-weight); 21 | } 22 | 23 | .category-title[href='#catFavourites'] { 24 | border-bottom-color: var(--primary-border-colour); 25 | } 26 | 27 | .category-title[aria-expanded=true] { 28 | border-bottom-color: var(--primary-border-colour); 29 | } 30 | 31 | .category-title.collapsed { 32 | border-bottom-color: var(--secondary-border-colour); 33 | } 34 | 35 | .category-title:hover { 36 | color: var(--op-list-operation-font-colour); 37 | } 38 | 39 | .category { 40 | margin: 0 !important; 41 | border-radius: 0 !important; 42 | border: none; 43 | } 44 | 45 | .op-count { 46 | float: right; 47 | color: var(--subtext-font-colour); 48 | font-weight: normal; 49 | font-size: xx-small; 50 | opacity: 0.5; 51 | padding-left: .5em; 52 | } 53 | -------------------------------------------------------------------------------- /src/web/stylesheets/components/_pane.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Workspace pane styles 3 | * 4 | * @author n1474335 [n1474335@gmail.com] 5 | * @copyright Crown Copyright 2017 6 | * @license Apache-2.0 7 | */ 8 | 9 | :root { 10 | --title-height: 48px; 11 | --tab-height: 40px; 12 | } 13 | 14 | .title { 15 | padding: 8px; 16 | padding-left: 12px; 17 | padding-right: 12px; 18 | height: var(--title-height); 19 | border-bottom: 1px solid var(--primary-border-colour); 20 | font-weight: var(--title-weight); 21 | font-size: var(--title-size); 22 | color: var(--title-colour); 23 | background-color: var(--title-background-colour); 24 | line-height: calc(var(--title-height) - 14px); 25 | } 26 | 27 | .pane-controls { 28 | position: absolute; 29 | right: 8px; 30 | top: 8px; 31 | display: flex; 32 | flex-direction: row; 33 | } 34 | 35 | .pane-controls .btn { 36 | margin-left: 2px; 37 | } 38 | 39 | .list-area { 40 | position: absolute; 41 | top: var(--title-height); 42 | bottom: 0; 43 | width: 100%; 44 | list-style-type: none; 45 | margin: 0; 46 | padding: 0; 47 | } 48 | 49 | #files .card-header .float-right a:hover { 50 | text-decoration: none; 51 | } 52 | -------------------------------------------------------------------------------- /src/web/stylesheets/index.css: -------------------------------------------------------------------------------- 1 | /** 2 | * CyberChef styles 3 | * 4 | * @author n1474335 [n1474335@gmail.com] 5 | * @copyright Crown Copyright 2017 6 | * @license Apache-2.0 7 | */ 8 | 9 | /* Themes */ 10 | @import "./themes/_classic.css"; 11 | @import "./themes/_dark.css"; 12 | @import "./themes/_geocities.css"; 13 | @import "./themes/_solarizedDark.css"; 14 | @import "./themes/_solarizedLight.css"; 15 | 16 | /* Utilities */ 17 | @import "./utils/_overrides.css"; 18 | @import "./utils/_general.css"; 19 | 20 | /* Preloader styles */ 21 | @import "./preloader.css"; 22 | 23 | /* Components */ 24 | @import "./components/_button.css"; 25 | @import "./components/_list.css"; 26 | @import "./components/_operation.css"; 27 | @import "./components/_pane.css"; 28 | 29 | /* Layout */ 30 | @import "./layout/_banner.css"; 31 | @import "./layout/_controls.css"; 32 | @import "./layout/_io.css"; 33 | @import "./layout/_modals.css"; 34 | @import "./layout/_operations.css"; 35 | @import "./layout/_recipe.css"; 36 | @import "./layout/_structure.css"; 37 | 38 | /* Operations */ 39 | @import "./operations/diff.css"; 40 | @import "./operations/json.css"; 41 | -------------------------------------------------------------------------------- /src/web/stylesheets/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Styles index 3 | * 4 | * @author n1474335 [n1474335@gmail.com] 5 | * @copyright Crown Copyright 2017 6 | * @license Apache-2.0 7 | */ 8 | 9 | /* Libraries */ 10 | import "highlight.js/styles/vs.css"; 11 | 12 | /* Frameworks */ 13 | import "bootstrap-material-design/dist/css/bootstrap-material-design.css"; 14 | import "bootstrap-colorpicker/dist/css/bootstrap-colorpicker.css"; 15 | 16 | /* CyberChef styles */ 17 | import "./index.css"; 18 | -------------------------------------------------------------------------------- /src/web/stylesheets/layout/_banner.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Banner area styles 3 | * 4 | * @author n1474335 [n1474335@gmail.com] 5 | * @copyright Crown Copyright 2017 6 | * @license Apache-2.0 7 | */ 8 | 9 | #banner { 10 | position: absolute; 11 | height: 30px; 12 | width: 100%; 13 | line-height: 30px; 14 | border-bottom: 1px solid var(--primary-border-colour); 15 | color: var(--banner-font-colour); 16 | background-color: var(--banner-bg-colour); 17 | margin: 0; 18 | } 19 | 20 | #banner i { 21 | vertical-align: middle; 22 | padding-right: 10px; 23 | } 24 | 25 | #banner a { 26 | color: var(--banner-url-colour); 27 | } 28 | 29 | #notice-wrapper { 30 | text-align: center; 31 | overflow: hidden; 32 | text-overflow: ellipsis; 33 | white-space: nowrap; 34 | } 35 | -------------------------------------------------------------------------------- /src/web/stylesheets/layout/_operations.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Operation area styles 3 | * 4 | * @author n1474335 [n1474335@gmail.com] 5 | * @copyright Crown Copyright 2017 6 | * @license Apache-2.0 7 | */ 8 | 9 | .op-list .operation { 10 | color: var(--op-list-operation-font-colour); 11 | background-color: var(--op-list-operation-bg-colour); 12 | border-color: var(--op-list-operation-border-colour); 13 | } 14 | 15 | #search { 16 | padding-left: 10px; 17 | padding-right: 10px; 18 | background-image: 19 | linear-gradient(to top, var(--input-highlight-colour) 2px, rgba(0, 0, 0, 0) 2px), 20 | linear-gradient(to top, var(--primary-border-colour) 1px, rgba(0, 0, 0, 0) 1px); 21 | } 22 | 23 | #edit-favourites { 24 | float: right; 25 | margin-top: -7px; 26 | } 27 | 28 | .favourites-hover { 29 | color: var(--rec-list-operation-font-colour); 30 | background-color: var(--rec-list-operation-bg-colour); 31 | border: 2px dashed var(--rec-list-operation-font-colour) !important; 32 | padding: 8px 8px 9px 8px; 33 | } 34 | 35 | #categories a { 36 | color: var(--category-list-font-colour); 37 | cursor: pointer; 38 | } 39 | 40 | #categories a:hover, 41 | .op-list .operation:hover { 42 | filter: brightness(98%); 43 | } 44 | -------------------------------------------------------------------------------- /src/web/stylesheets/layout/_recipe.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Recipe area styles 3 | * 4 | * @author n1474335 [n1474335@gmail.com] 5 | * @copyright Crown Copyright 2017 6 | * @license Apache-2.0 7 | */ 8 | 9 | #rec-list { 10 | overflow: auto; 11 | } 12 | 13 | #rec-list .operation { 14 | color: var(--rec-list-operation-font-colour); 15 | background-color: var(--rec-list-operation-bg-colour); 16 | border-color: var(--rec-list-operation-border-colour); 17 | } 18 | -------------------------------------------------------------------------------- /src/web/stylesheets/operations/diff.css: -------------------------------------------------------------------------------- 1 | del { 2 | background-color: var(--hl3); 3 | } 4 | 5 | ins { 6 | text-decoration: underline; /* shouldn't be needed, but Chromium doesn't copy to clipboard without it */ 7 | background-color: var(--hl5); 8 | } 9 | -------------------------------------------------------------------------------- /tests/node/assertionHandler.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * assertionHandler.mjs 3 | * 4 | * Pair native node assertions with a description for 5 | * the benefit of the TestRegister. 6 | * 7 | * @author d98762625 [d98762625@gmail.com] 8 | * @copyright Crown Copyright 2019 9 | * @license Apache-2.0 10 | */ 11 | 12 | /* eslint no-console: 0 */ 13 | 14 | 15 | /** 16 | * Print useful stack on error 17 | */ 18 | const wrapRun = (run) => async () => { 19 | try { 20 | await run(); 21 | } catch (e) { 22 | console.dir(e); 23 | throw e; 24 | } 25 | }; 26 | 27 | 28 | /** 29 | * it - wrapper for assertions to provide a helpful description 30 | * to the TestRegister 31 | * @namespace ApiTests 32 | * @param {String} description - The description of the test 33 | * @param {Function} assertion - The test 34 | * 35 | * @example 36 | * // One assertion 37 | * it("should run one assertion", () => assert.equal(1,1)) 38 | * 39 | * @example 40 | * // multiple assertions 41 | * it("should handle multiple assertions", () => { 42 | * assert.equal(1,1) 43 | * assert.notEqual(3,4) 44 | * }) 45 | * 46 | * @example 47 | * // async assertions 48 | * it("should handle async", async () => { 49 | * let r = await asyncFunc() 50 | * assert(r) 51 | * }) 52 | */ 53 | export function it(name, run) { 54 | return { 55 | name: `Node API: ${name}`, 56 | run: wrapRun(run), 57 | }; 58 | } 59 | 60 | export default it; 61 | -------------------------------------------------------------------------------- /tests/node/consumers/cjs-consumer.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Tests to ensure that a consuming app can use CJS require 3 | * 4 | * @author d98762625 [d98762625@gmail.com] 5 | * @copyright Crown Copyright 2019 6 | * @license Apache-2.0 7 | */ 8 | 9 | const assert = require("assert"); 10 | 11 | require("cyberchef").then(chef => { 12 | 13 | const d = chef.bake("Testing, 1 2 3", [ 14 | chef.toHex, 15 | chef.reverse, 16 | { 17 | op: chef.unique, 18 | args: { 19 | delimiter: "Space", 20 | } 21 | }, 22 | { 23 | op: chef.multiply, 24 | args: { 25 | delimiter: "Space", 26 | } 27 | } 28 | ]); 29 | 30 | assert.equal(d.value, "630957449041920"); 31 | 32 | }); 33 | -------------------------------------------------------------------------------- /tests/node/consumers/esm-consumer.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * Tests to ensure that a consuming app can use ESM imports 3 | * 4 | * @author d98762625 [d98762625@gmail.com] 5 | * @copyright Crown Copyright 2019 6 | * @license Apache-2.0 7 | */ 8 | import assert from "assert"; 9 | import chef from "cyberchef"; 10 | import { bake, toHex, reverse, unique, multiply } from "cyberchef"; 11 | 12 | const a = bake("Testing, 1 2 3", [ 13 | toHex, 14 | reverse, 15 | { 16 | op: unique, 17 | args: { 18 | delimiter: "Space", 19 | } 20 | }, 21 | { 22 | op: multiply, 23 | args: { 24 | delimiter: "Space", 25 | } 26 | } 27 | ]); 28 | 29 | assert.equal(a.value, "630957449041920"); 30 | 31 | const b = chef.bake("Testing, 1 2 3", [ 32 | chef.toHex, 33 | chef.reverse, 34 | { 35 | op: chef.unique, 36 | args: { 37 | delimiter: "Space", 38 | } 39 | }, 40 | { 41 | op: chef.multiply, 42 | args: { 43 | delimiter: "Space", 44 | } 45 | } 46 | ]); 47 | 48 | assert.equal(b.value, "630957449041920"); 49 | -------------------------------------------------------------------------------- /tests/node/index.mjs: -------------------------------------------------------------------------------- 1 | /* eslint no-console: 0 */ 2 | 3 | /** 4 | * Node API Test Runner 5 | * 6 | * @author d98762625 [d98762625@gmail.com] 7 | * @author tlwr [toby@toby.codes] 8 | * @author n1474335 [n1474335@gmail.com] 9 | * @copyright Crown Copyright 2018 10 | * @license Apache-2.0 11 | */ 12 | 13 | import { 14 | setLongTestFailure, 15 | logTestReport, 16 | } from "../lib/utils.mjs"; 17 | 18 | import TestRegister from "../lib/TestRegister.mjs"; 19 | import "./tests/nodeApi.mjs"; 20 | import "./tests/operations.mjs"; 21 | import "./tests/File.mjs"; 22 | import "./tests/Dish.mjs"; 23 | import "./tests/NodeDish.mjs"; 24 | import "./tests/Utils.mjs"; 25 | import "./tests/Categories.mjs"; 26 | 27 | const testStatus = { 28 | allTestsPassing: true, 29 | counts: { 30 | total: 0, 31 | } 32 | }; 33 | 34 | setLongTestFailure(); 35 | 36 | const logOpsTestReport = logTestReport.bind(null, testStatus); 37 | 38 | (async function() { 39 | const results = await TestRegister.runApiTests(); 40 | logOpsTestReport(results); 41 | })(); 42 | -------------------------------------------------------------------------------- /tests/node/sampleData/pic.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gchq/CyberChef/c57556f49f723863b9be15668fd240672cd15b09/tests/node/sampleData/pic.jpg -------------------------------------------------------------------------------- /tests/node/tests/Categories.mjs: -------------------------------------------------------------------------------- 1 | import TestRegister from "../../lib/TestRegister.mjs"; 2 | import Categories from "../../../src/core/config/Categories.json" assert {type: "json"}; 3 | import OperationConfig from "../../../src/core/config/OperationConfig.json" assert {type: "json"}; 4 | import it from "../assertionHandler.mjs"; 5 | import assert from "assert"; 6 | 7 | TestRegister.addApiTests([ 8 | it("Categories: operations should be in a category", () => { 9 | const catOps = []; 10 | Categories.forEach(cat => { 11 | catOps.push(...cat.ops); 12 | }); 13 | 14 | for (const op in OperationConfig) { 15 | assert(catOps.includes(op), `'${op}' operation is not present in any category`); 16 | } 17 | }), 18 | 19 | ]); 20 | -------------------------------------------------------------------------------- /tests/node/tests/Dish.mjs: -------------------------------------------------------------------------------- 1 | import TestRegister from "../../lib/TestRegister.mjs"; 2 | import Dish from "../../../src/core/Dish.mjs"; 3 | import it from "../../node/assertionHandler.mjs"; 4 | import assert from "assert"; 5 | 6 | TestRegister.addApiTests([ 7 | it("Dish - presentAs: should exist", () => { 8 | const dish = new Dish(); 9 | assert(dish.presentAs); 10 | }), 11 | 12 | ]); 13 | -------------------------------------------------------------------------------- /tests/node/tests/Utils.mjs: -------------------------------------------------------------------------------- 1 | import TestRegister from "../../lib/TestRegister.mjs"; 2 | import Utils from "../../../src/core/Utils.mjs"; 3 | import it from "../assertionHandler.mjs"; 4 | import assert from "assert"; 5 | 6 | TestRegister.addApiTests([ 7 | it("Utils: should parse six backslashes correctly", () => { 8 | assert.equal(Utils.parseEscapedChars("\\\\\\\\\\\\"), "\\\\\\"); 9 | }), 10 | 11 | it("Utils: should parse escaped quotes correctly", () => { 12 | assert.equal(Utils.parseEscapedChars("\\'"), "'"); 13 | }), 14 | 15 | it("Utils: should parse escaped quotes and backslashes correctly", () => { 16 | assert.equal(Utils.parseEscapedChars("\\\\'"), "\\'"); 17 | }), 18 | 19 | it("Utils: should parse escaped quotes and escaped backslashes correctly", () => { 20 | assert.equal(Utils.parseEscapedChars("\\\\\\'"), "\\'"); 21 | }), 22 | 23 | ]); 24 | -------------------------------------------------------------------------------- /tests/operations/tests/AlternatingCaps.mjs: -------------------------------------------------------------------------------- 1 | /* @author sw5678 2 | * @copyright Crown Copyright 2024 3 | * @license Apache-2.0 4 | */ 5 | import TestRegister from "../../lib/TestRegister.mjs"; 6 | 7 | TestRegister.addTests([ 8 | { 9 | "name": "AlternatingCaps: Basic Example", 10 | "input": "Hello, world!", 11 | "expectedOutput": "hElLo, WoRlD!", 12 | "recipeConfig": [ 13 | { 14 | "op": "Alternating Caps", 15 | "args": [] 16 | }, 17 | ], 18 | } 19 | ]); 20 | -------------------------------------------------------------------------------- /tests/operations/tests/BLAKE2s.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * BitwiseOp tests 3 | * 4 | * @author h345983745 5 | * @copyright Crown Copyright 2019 6 | * @license Apache-2.0 7 | */ 8 | import TestRegister from "../../lib/TestRegister.mjs"; 9 | 10 | TestRegister.addTests([ 11 | { 12 | name: "BLAKE2s: 256 - Hello World", 13 | input: "Hello World", 14 | expectedOutput: "7706af019148849e516f95ba630307a2018bb7bf03803eca5ed7ed2c3c013513", 15 | recipeConfig: [ 16 | { "op": "BLAKE2s", 17 | "args": ["256", "Hex", {string: "", option: "UTF8"}] } 18 | ] 19 | }, 20 | { 21 | name: "BLAKE2s: 160 - Hello World", 22 | input: "Hello World", 23 | expectedOutput: "0e4fcfc2ee0097ac1d72d70b595a39e09a3c7c7e", 24 | recipeConfig: [ 25 | { "op": "BLAKE2s", 26 | "args": ["160", "Hex", {string: "", option: "UTF8"}] } 27 | ] 28 | }, 29 | { 30 | name: "BLAKE2s: 128 - Hello World", 31 | input: "Hello World", 32 | expectedOutput: "9964ee6f36126626bf864363edfa96f6", 33 | recipeConfig: [ 34 | { "op": "BLAKE2s", 35 | "args": ["128", "Hex", {string: "", option: "UTF8"}] } 36 | ] 37 | }, 38 | { 39 | name: "BLAKE2s: Key Test", 40 | input: "Hello World", 41 | expectedOutput: "9964ee6f36126626bf864363edfa96f6", 42 | recipeConfig: [ 43 | { "op": "BLAKE2s", 44 | "args": ["128", "Hex", {string: "", option: "UTF8"}] } 45 | ] 46 | } 47 | ]); 48 | -------------------------------------------------------------------------------- /tests/operations/tests/BSON.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * BSON tests. 3 | * 4 | * @author n1474335 [n1474335@gmail.com] 5 | * 6 | * @copyright Crown Copyright 2018 7 | * @license Apache-2.0 8 | */ 9 | import TestRegister from "../../lib/TestRegister.mjs"; 10 | 11 | TestRegister.addTests([ 12 | { 13 | name: "BSON serialise: nothing", 14 | input: "", 15 | expectedOutput: "", 16 | recipeConfig: [ 17 | { 18 | op: "BSON serialise", 19 | args: [], 20 | }, 21 | ], 22 | }, 23 | { 24 | name: "BSON serialise: basic", 25 | input: "{\"hello\":\"world\"}", 26 | expectedOutput: "\x16\x00\x00\x00\x02hello\x00\x06\x00\x00\x00world\x00\x00", 27 | recipeConfig: [ 28 | { 29 | op: "BSON serialise", 30 | args: [], 31 | }, 32 | ], 33 | }, 34 | { 35 | name: "BSON deserialise: nothing", 36 | input: "", 37 | expectedOutput: "", 38 | recipeConfig: [ 39 | { 40 | op: "BSON deserialise", 41 | args: [], 42 | }, 43 | ], 44 | }, 45 | { 46 | name: "BSON deserialise: basic", 47 | input: "\x16\x00\x00\x00\x02hello\x00\x06\x00\x00\x00world\x00\x00", 48 | expectedOutput: "{\n \"hello\": \"world\"\n}", 49 | recipeConfig: [ 50 | { 51 | op: "BSON deserialise", 52 | args: [], 53 | }, 54 | ], 55 | }, 56 | ]); 57 | -------------------------------------------------------------------------------- /tests/operations/tests/CaesarBoxCipher.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * Caesar Box Cipher tests. 3 | * 4 | * @author n1073645 [n1073645@gmail.com] 5 | * 6 | * @copyright Crown Copyright 2020 7 | * @license Apache-2.0 8 | */ 9 | import TestRegister from "../../lib/TestRegister.mjs"; 10 | 11 | TestRegister.addTests([ 12 | { 13 | name: "Caesar Box Cipher: nothing", 14 | input: "", 15 | expectedOutput: "", 16 | recipeConfig: [ 17 | { 18 | op: "Caesar Box Cipher", 19 | args: ["1"], 20 | }, 21 | ], 22 | }, 23 | { 24 | name: "Caesar Box Cipher: Hello World!", 25 | input: "Hello World!", 26 | expectedOutput: "Hlodeor!lWl", 27 | recipeConfig: [ 28 | { 29 | op: "Caesar Box Cipher", 30 | args: ["3"], 31 | }, 32 | ], 33 | }, 34 | { 35 | name: "Caesar Box Cipher: Hello World!", 36 | input: "Hlodeor!lWl", 37 | expectedOutput: "HelloWorld!", 38 | recipeConfig: [ 39 | { 40 | op: "Caesar Box Cipher", 41 | args: ["4"], 42 | }, 43 | ], 44 | } 45 | ]); 46 | -------------------------------------------------------------------------------- /tests/operations/tests/CetaceanCipherDecode.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * CetaceanCipher Encode tests 3 | * 4 | * @author dolphinOnKeys 5 | * @copyright Crown Copyright 2022 6 | * @licence Apache-2.0 7 | */ 8 | import TestRegister from "../../lib/TestRegister.mjs"; 9 | 10 | TestRegister.addTests([ 11 | { 12 | name: "Cetacean Cipher Decode", 13 | input: "EEEEEEEEEeeEEEEe EEEEEEEEEeeEEEeE EEEEEEEEEeeEEEee EEeeEEEEEeeEEeee", 14 | expectedOutput: "a b c で", 15 | recipeConfig: [ 16 | { 17 | op: "Cetacean Cipher Decode", 18 | args: [] 19 | }, 20 | ], 21 | } 22 | ]); 23 | -------------------------------------------------------------------------------- /tests/operations/tests/CetaceanCipherEncode.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * CetaceanCipher Encode tests 3 | * 4 | * @author dolphinOnKeys 5 | * @copyright Crown Copyright 2022 6 | * @licence Apache-2.0 7 | */ 8 | import TestRegister from "../../lib/TestRegister.mjs"; 9 | 10 | TestRegister.addTests([ 11 | { 12 | name: "Cetacean Cipher Encode", 13 | input: "a b c で", 14 | expectedOutput: "EEEEEEEEEeeEEEEe EEEEEEEEEeeEEEeE EEEEEEEEEeeEEEee EEeeEEEEEeeEEeee", 15 | recipeConfig: [ 16 | { 17 | op: "Cetacean Cipher Encode", 18 | args: [] 19 | }, 20 | ], 21 | } 22 | ]); 23 | -------------------------------------------------------------------------------- /tests/operations/tests/ChangeIPFormat.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * Change IP format tests. 3 | * 4 | * @author Chris Smith 5 | * @copyright Crown Copyright 2019 6 | * @license Apache-2.0 7 | */ 8 | import TestRegister from "../../lib/TestRegister.mjs"; 9 | 10 | TestRegister.addTests([ 11 | { 12 | name: "Change IP format: Dotted Decimal to Hex", 13 | input: "192.168.1.1", 14 | expectedOutput: "c0a80101", 15 | recipeConfig: [ 16 | { 17 | op: "Change IP format", 18 | args: ["Dotted Decimal", "Hex"], 19 | }, 20 | ], 21 | }, { 22 | name: "Change IP format: Decimal to Dotted Decimal", 23 | input: "3232235777", 24 | expectedOutput: "192.168.1.1", 25 | recipeConfig: [ 26 | { 27 | op: "Change IP format", 28 | args: ["Decimal", "Dotted Decimal"], 29 | }, 30 | ], 31 | }, { 32 | name: "Change IP format: Hex to Octal", 33 | input: "c0a80101", 34 | expectedOutput: "030052000401", 35 | recipeConfig: [ 36 | { 37 | op: "Change IP format", 38 | args: ["Hex", "Octal"], 39 | }, 40 | ], 41 | }, { 42 | name: "Change IP format: Octal to Decimal", 43 | input: "030052000401", 44 | expectedOutput: "3232235777", 45 | recipeConfig: [ 46 | { 47 | op: "Change IP format", 48 | args: ["Octal", "Decimal"], 49 | }, 50 | ], 51 | }, 52 | ]); 53 | -------------------------------------------------------------------------------- /tests/operations/tests/CipherSaber2.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * Ciphersaber2 tests. 3 | * 4 | * @author n1073645 [n1073645@gmail.com] 5 | * 6 | * @copyright Crown Copyright 2020 7 | * @license Apache-2.0 8 | */ 9 | import TestRegister from "../../lib/TestRegister.mjs"; 10 | 11 | TestRegister.addTests([ 12 | { 13 | name: "CipherSaber2 Encrypt", 14 | input: "Hello World", 15 | expectedMatch: /.{21}/s, 16 | recipeConfig: [ 17 | { 18 | op: "CipherSaber2 Encrypt", 19 | args: [{ "option": "Latin1", "string": "test" }, 20], 20 | }, 21 | ], 22 | }, 23 | { 24 | // input taken from https://ciphersaber.gurus.org/ 25 | name: "CipherSaber2 Decrypt", 26 | input: "\x6f\x6d\x0b\xab\xf3\xaa\x67\x19\x03\x15\x30\xed\xb6\x77" + 27 | "\xca\x74\xe0\x08\x9d\xd0\xe7\xb8\x85\x43\x56\xbb\x14\x48\xe3" + 28 | "\x7c\xdb\xef\xe7\xf3\xa8\x4f\x4f\x5f\xb3\xfd", 29 | expectedOutput: "This is a test of CipherSaber.", 30 | recipeConfig: [ 31 | { 32 | op: "CipherSaber2 Decrypt", 33 | args: [{ "option": "Latin1", "string": "asdfg" }, 1], 34 | }, 35 | ], 36 | }, 37 | { 38 | name: "CipherSaber2 Encrypt", 39 | input: "", 40 | expectedMatch: /.{10}/s, 41 | recipeConfig: [ 42 | { 43 | op: "CipherSaber2 Encrypt", 44 | args: [{ "option": "Latin1", "string": "" }, 20], 45 | }, 46 | ], 47 | }, 48 | ]); 49 | -------------------------------------------------------------------------------- /tests/operations/tests/ConvertLeetSpeak.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * @author bartblaze [] 3 | * @copyright Crown Copyright 2025 4 | * @license Apache-2.0 5 | */ 6 | 7 | import TestRegister from "../../lib/TestRegister.mjs"; 8 | 9 | TestRegister.addTests([ 10 | { 11 | name: "Convert to Leet Speak: basic text", 12 | input: "leet", 13 | expectedOutput: "l337", 14 | recipeConfig: [ 15 | { 16 | op: "Convert Leet Speak", 17 | args: ["To Leet Speak"] 18 | } 19 | ] 20 | }, 21 | { 22 | name: "Convert from Leet Speak: basic leet", 23 | input: "l337", 24 | expectedOutput: "leet", 25 | recipeConfig: [ 26 | { 27 | op: "Convert Leet Speak", 28 | args: ["From Leet Speak"] 29 | } 30 | ] 31 | }, 32 | { 33 | name: "Convert to Leet Speak: basic text, keep case", 34 | input: "HELLO", 35 | expectedOutput: "H3LL0", 36 | recipeConfig: [ 37 | { 38 | op: "Convert Leet Speak", 39 | args: ["To Leet Speak"] 40 | } 41 | ] 42 | }, 43 | { 44 | name: "Convert from Leet Speak: basic leet, keep case", 45 | input: "H3LL0", 46 | expectedOutput: "HeLLo", 47 | recipeConfig: [ 48 | { 49 | op: "Convert Leet Speak", 50 | args: ["From Leet Speak"] 51 | } 52 | ] 53 | } 54 | ]); 55 | 56 | -------------------------------------------------------------------------------- /tests/operations/tests/ConvertToNATOAlphabet.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * @author MarvinJWendt [git@marvinjwendt.com] 3 | * @copyright Crown Copyright 2019 4 | * @license Apache-2.0 5 | */ 6 | 7 | import TestRegister from "../../lib/TestRegister.mjs"; 8 | 9 | TestRegister.addTests([ 10 | { 11 | name: "Convert to NATO alphabet: nothing", 12 | input: "", 13 | expectedOutput: "", 14 | recipeConfig: [ 15 | { 16 | op: "Convert to NATO alphabet", 17 | args: [] 18 | } 19 | ] 20 | }, 21 | { 22 | name: "Convert to NATO alphabet: full alphabet with numbers", 23 | input: "abcdefghijklmnopqrstuvwxyz0123456789,/.", 24 | expectedOutput: "Alfa Bravo Charlie Delta Echo Foxtrot Golf Hotel India Juliett Kilo Lima Mike November Oscar Papa Quebec Romeo Sierra Tango Uniform Victor Whiskey X-ray Yankee Zulu Zero One Two Three Four Five Six Seven Eight Nine Comma Fraction bar Full stop ", 25 | recipeConfig: [ 26 | { 27 | op: "Convert to NATO alphabet", 28 | args: [] 29 | } 30 | ] 31 | } 32 | ]); 33 | -------------------------------------------------------------------------------- /tests/operations/tests/DefangIP.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * DefangIP tests. 3 | * 4 | * @author h345983745 5 | * 6 | * @copyright Crown Copyright 2019 7 | * @license Apache-2.0 8 | */ 9 | import TestRegister from "../../lib/TestRegister.mjs"; 10 | 11 | TestRegister.addTests([ 12 | { 13 | name: "Defang IP: Valid IPV4", 14 | input: "192.168.1.1", 15 | expectedOutput: "192[.]168[.]1[.]1", 16 | recipeConfig: [ 17 | { 18 | op: "Defang IP Addresses", 19 | args: [], 20 | }, 21 | ], 22 | }, { 23 | name: "Defang IP: Valid IPV6", 24 | input: "2001:0db8:85a3:0000:0000:8a2e:0370:7343", 25 | expectedOutput: "2001[:]0db8[:]85a3[:]0000[:]0000[:]8a2e[:]0370[:]7343", 26 | recipeConfig: [ 27 | { 28 | op: "Defang IP Addresses", 29 | args: [], 30 | }, 31 | ], 32 | }, { 33 | name: "Defang IP: Valid IPV6 Shorthand", 34 | input: "2001:db8:3c4d:15::1a2f:1a2b", 35 | expectedOutput: "2001[:]db8[:]3c4d[:]15[:][:]1a2f[:]1a2b", 36 | recipeConfig: [ 37 | { 38 | op: "Defang IP Addresses", 39 | args: [], 40 | }, 41 | ], 42 | }, 43 | ]); 44 | -------------------------------------------------------------------------------- /tests/operations/tests/FileTree.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * File tree tests. 3 | * 4 | * @author sw5678 5 | * @copyright Crown Copyright 2023 6 | * @license Apache-2.0 7 | */ 8 | import TestRegister from "../../lib/TestRegister.mjs"; 9 | 10 | TestRegister.addTests([ 11 | { 12 | "name": "File Tree: basic example", 13 | "input": "/test_dir1/test_file1.txt\n/test_dir1/test_file2.txt\n/test_dir2/test_file1.txt", 14 | "expectedOutput": "test_dir1\n|---test_file1.txt\n|---test_file2.txt\ntest_dir2\n|---test_file1.txt", 15 | "recipeConfig": [ 16 | { 17 | "op": "File Tree", 18 | "args": ["/", "Line feed"], 19 | }, 20 | ], 21 | } 22 | ]); 23 | -------------------------------------------------------------------------------- /tests/operations/tests/FromDecimal.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * From Decimal tests 3 | * 4 | * @author qistoph 5 | * @copyright Crown Copyright 2018 6 | * @licence Apache-2.0 7 | */ 8 | import TestRegister from "../../lib/TestRegister.mjs"; 9 | 10 | TestRegister.addTests([ 11 | { 12 | name: "From Decimal", 13 | input: "83 97 109 112 108 101 32 84 101 120 116", 14 | expectedOutput: "Sample Text", 15 | recipeConfig: [ 16 | { 17 | op: "From Decimal", 18 | args: ["Space", false] 19 | }, 20 | ], 21 | }, 22 | { 23 | name: "From Decimal with negatives", 24 | input: "-130,-140,-152,-151,115,33,0,-1", 25 | expectedOutput: "~this!\u0000\u00ff", 26 | recipeConfig: [ 27 | { 28 | op: "From Decimal", 29 | args: ["Comma", true] 30 | }, 31 | ], 32 | }, 33 | ]); 34 | -------------------------------------------------------------------------------- /tests/operations/tests/GetAllCasings.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * GetAllCasings tests. 3 | * 4 | * @author n1073645 [n1073645@gmail.com] 5 | * @copyright Crown Copyright 2020 6 | * @license Apache-2.0 7 | */ 8 | import TestRegister from "../../lib/TestRegister.mjs"; 9 | 10 | TestRegister.addTests([ 11 | { 12 | name: "All casings of test", 13 | input: "test", 14 | expectedOutput: "test\nTest\ntEst\nTEst\nteSt\nTeSt\ntESt\nTESt\ntesT\nTesT\ntEsT\nTEsT\nteST\nTeST\ntEST\nTEST", 15 | recipeConfig: [ 16 | { 17 | "op": "Get All Casings", 18 | "args": [] 19 | } 20 | ] 21 | }, 22 | { 23 | name: "All casings of t", 24 | input: "t", 25 | expectedOutput: "t\nT", 26 | recipeConfig: [ 27 | { 28 | "op": "Get All Casings", 29 | "args": [] 30 | } 31 | ] 32 | }, 33 | { 34 | name: "All casings of null", 35 | input: "", 36 | expectedOutput: "", 37 | recipeConfig: [ 38 | { 39 | "op": "Get All Casings", 40 | "args": [] 41 | } 42 | ] 43 | } 44 | ]); 45 | -------------------------------------------------------------------------------- /tests/operations/tests/HaversineDistance.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * Haversine distance tests. 3 | * 4 | * @author Dachande663 [dachande663@gmail.com] 5 | * @copyright Crown Copyright 2018 6 | * @license Apache-2.0 7 | */ 8 | import TestRegister from "../../lib/TestRegister.mjs"; 9 | 10 | TestRegister.addTests([ 11 | { 12 | name: "Haversine distance", 13 | input: "51.487263,-0.124323, 38.9517,-77.1467", 14 | expectedOutput: "5902542.836307819", 15 | recipeConfig: [ 16 | { 17 | "op": "Haversine distance", 18 | "args": [] 19 | } 20 | ], 21 | }, 22 | { 23 | name: "Haversine distance, zero distance", 24 | input: "51.487263,-0.124323, 51.487263,-0.124323", 25 | expectedOutput: "0", 26 | recipeConfig: [ 27 | { 28 | "op": "Haversine distance", 29 | "args": [] 30 | } 31 | ], 32 | } 33 | ]); 34 | -------------------------------------------------------------------------------- /tests/operations/tests/IndexOfCoincidence.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * Index of Coincidence tests. 3 | * 4 | * @author George O [georgeomnet+cyberchef@gmail.com] 5 | * @copyright Crown Copyright 2019 6 | * @license Apache-2.0 7 | */ 8 | import TestRegister from "../../lib/TestRegister.mjs"; 9 | 10 | TestRegister.addTests([ 11 | { 12 | name: "Index of Coincidence", 13 | input: "Hello world, this is a test to determine the correct IC value.", 14 | expectedMatch: /^Index of Coincidence: 0\.07142857142857142\nNormalized: 1\.857142857142857/, 15 | recipeConfig: [ 16 | { 17 | "op": "Index of Coincidence", 18 | "args": [] 19 | }, 20 | ], 21 | }, 22 | ]); 23 | -------------------------------------------------------------------------------- /tests/operations/tests/JSONtoYAML.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * YAML tests. 3 | * 4 | * @author ccarpo [ccarpo@gmx.net] 5 | * 6 | * @copyright Crown Copyright 2021 7 | * @license Apache-2.0 8 | */ 9 | import TestRegister from "../../lib/TestRegister.mjs"; 10 | 11 | const EXAMPLE_YAML = `number: 3\nplain: string\nblock: |\n two\n lines`; 12 | const EXAMPLE_JSON = `{ "number": 3, "plain": "string" }`; 13 | 14 | TestRegister.addTests([ 15 | { 16 | name: "YAML to JSON", 17 | input: EXAMPLE_YAML, 18 | expectedOutput: JSON.stringify({ 19 | "number": 3, 20 | "plain": "string", 21 | "block": "two\nlines\n" 22 | }, null, 4), 23 | recipeConfig: [ 24 | { 25 | op: "YAML to JSON", 26 | args: [], 27 | } 28 | ], 29 | }, 30 | { 31 | name: "JSON to YAML", 32 | input: EXAMPLE_JSON, 33 | expectedOutput: `number: 3\nplain: string\n`, 34 | recipeConfig: [ 35 | { 36 | op: "JSON to YAML", 37 | args: [], 38 | } 39 | ], 40 | }, 41 | ]); 42 | -------------------------------------------------------------------------------- /tests/operations/tests/Jump.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * Jump tests 3 | * 4 | * @author tlwr [toby@toby.codes] 5 | * 6 | * @copyright Crown Copyright 2018 7 | * @license Apache-2.0 8 | */ 9 | import TestRegister from "../../lib/TestRegister.mjs"; 10 | 11 | TestRegister.addTests([ 12 | { 13 | name: "Jump: Empty Label", 14 | input: [ 15 | "should be changed", 16 | ].join("\n"), 17 | expectedOutput: [ 18 | "c2hvdWxkIGJlIGNoYW5nZWQ=", 19 | ].join("\n"), 20 | recipeConfig: [ 21 | { 22 | op: "Jump", 23 | args: ["", 10], 24 | }, 25 | { 26 | op: "To Base64", 27 | args: ["A-Za-z0-9+/="], 28 | }, 29 | ], 30 | }, 31 | { 32 | name: "Jump: skips 1", 33 | input: [ 34 | "shouldnt be changed", 35 | ].join("\n"), 36 | expectedOutput: [ 37 | "shouldnt be changed", 38 | ].join("\n"), 39 | recipeConfig: [ 40 | { 41 | op: "Jump", 42 | args: ["skipReplace", 10], 43 | }, 44 | { 45 | op: "To Base64", 46 | args: ["A-Za-z0-9+/="], 47 | }, 48 | { 49 | op: "Label", 50 | args: ["skipReplace"] 51 | }, 52 | ], 53 | } 54 | ]); 55 | -------------------------------------------------------------------------------- /tests/operations/tests/LS47.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * LS47 tests. 3 | * 4 | * @author n1073645 [n1073645@gmail.com] 5 | * 6 | * @copyright Crown Copyright 2020 7 | * @license Apache-2.0 8 | */ 9 | import TestRegister from "../../lib/TestRegister.mjs"; 10 | 11 | TestRegister.addTests([ 12 | { 13 | name: "LS47 Encrypt", 14 | input: "thequickbrownfoxjumped", 15 | expectedOutput: "(,t74ci78cp/8trx*yesu:alp1wqy", 16 | recipeConfig: [ 17 | { 18 | op: "LS47 Encrypt", 19 | args: ["helloworld", 0, "test"], 20 | }, 21 | ], 22 | }, 23 | { 24 | name: "LS47 Decrypt", 25 | input: "(,t74ci78cp/8trx*yesu:alp1wqy", 26 | expectedOutput: "thequickbrownfoxjumped---test", 27 | recipeConfig: [ 28 | { 29 | op: "LS47 Decrypt", 30 | args: ["helloworld", 0], 31 | }, 32 | ], 33 | }, 34 | { 35 | name: "LS47 Encrypt", 36 | input: "thequickbrownfoxjumped", 37 | expectedOutput: "Letter H is not included in LS47", 38 | recipeConfig: [ 39 | { 40 | op: "LS47 Encrypt", 41 | args: ["Helloworld", 0, "test"], 42 | }, 43 | ], 44 | } 45 | ]); 46 | -------------------------------------------------------------------------------- /tests/operations/tests/LZNT1Decompress.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * LZNT1 Decompress tests. 3 | * 4 | * @author 0xThiebaut [thiebaut.dev] 5 | * @copyright Crown Copyright 2023 6 | * @license Apache-2.0 7 | */ 8 | import TestRegister from "../../lib/TestRegister.mjs"; 9 | 10 | TestRegister.addTests([ 11 | { 12 | name: "LZNT1 Decompress", 13 | input: "\x1a\xb0\x00compress\x00edtestda\x04ta\x07\x88alot", 14 | expectedOutput: "compressedtestdatacompressedalot", 15 | recipeConfig: [ 16 | { 17 | op: "LZNT1 Decompress", 18 | args: [] 19 | } 20 | ], 21 | } 22 | ]); 23 | -------------------------------------------------------------------------------- /tests/operations/tests/LZString.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * LZString tests. 3 | * 4 | * @author crespyl [peter@crespyl.net] 5 | * @copyright Peter Jacobs 2021 6 | * @license Apache-2.0 7 | */ 8 | import TestRegister from "../../lib/TestRegister.mjs"; 9 | 10 | TestRegister.addTests([ 11 | { 12 | name: "LZString Compress To Base64", 13 | input: "hello world", 14 | expectedOutput: "BYUwNmD2AEDukCcwBMg=", 15 | recipeConfig: [ 16 | { 17 | "op": "LZString Compress", 18 | "args": ["Base64"] 19 | } 20 | ], 21 | }, 22 | { 23 | name: "LZString Decompress From Base64", 24 | input: "BYUwNmD2AEDukCcwBMg=", 25 | expectedOutput: "hello world", 26 | recipeConfig: [ 27 | { 28 | "op": "LZString Decompress", 29 | "args": ["Base64"] 30 | } 31 | ], 32 | } 33 | ]); 34 | -------------------------------------------------------------------------------- /tests/operations/tests/MS.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * MS tests. 3 | * 4 | * @author bwhitn [brian.m.whitney@outlook.com] 5 | * @copyright Crown Copyright 2017 6 | * @license Apache-2.0 7 | */ 8 | import TestRegister from "../../lib/TestRegister.mjs"; 9 | 10 | TestRegister.addTests([ 11 | { 12 | name: "Microsoft Script Decoder", 13 | input: "#@~^RQAAAA==-mD~sX|:/TP{~J:+dYbxL~@!F@*@!+@*@!&@*eEI@#@&@#@&\x7fjm.raY 214Wv:zms/obI0xEAAA==^#~@", 14 | expectedOutput: "var my_msg = \"Testing <1><2><3>!\";\r\n\r\nWScript.Echo(my_msg);", 15 | recipeConfig: [ 16 | { 17 | "op": "Microsoft Script Decoder", 18 | "args": [] 19 | }, 20 | ], 21 | }, 22 | ]); 23 | -------------------------------------------------------------------------------- /tests/operations/tests/MorseCode.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * Base58 tests. 3 | * 4 | * @author tlwr [toby@toby.codes] 5 | * 6 | * @copyright Crown Copyright 2017 7 | * @license Apache-2.0 8 | */ 9 | import TestRegister from "../../lib/TestRegister.mjs"; 10 | 11 | TestRegister.addTests([ 12 | { 13 | name: "To Morse Code: 'SOS'", 14 | input: "SOS", 15 | expectedOutput: "... --- ...", 16 | recipeConfig: [ 17 | { 18 | op: "To Morse Code", 19 | args: ["-/.", "Space", "Line feed"], 20 | }, 21 | ], 22 | }, 23 | { 24 | name: "From Morse Code '... --- ...'", 25 | input: "... --- ...", 26 | expectedOutput: "SOS", 27 | recipeConfig: [ 28 | { 29 | op: "From Morse Code", 30 | args: ["Space", "Line feed"], 31 | }, 32 | ], 33 | }, 34 | ]); 35 | -------------------------------------------------------------------------------- /tests/operations/tests/NTLM.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * NTLM test. 3 | * 4 | * @author brun0ne [brunonblok@gmail.com] 5 | * @copyright Crown Copyright 2022 6 | * @license Apache-2.0 7 | */ 8 | import TestRegister from "../../lib/TestRegister.mjs"; 9 | 10 | TestRegister.addTests([ 11 | { 12 | name: "NT Hash", 13 | input: "QWERTYUIOPASDFGHJKLZXCVBNM1234567890!@#$%^&*()_+.,?/", 14 | expectedOutput: "C5FA1C40E55734A8E528DBFE21766D23", 15 | recipeConfig: [ 16 | { 17 | op: "NT Hash", 18 | args: [], 19 | }, 20 | ], 21 | }, 22 | { 23 | name: "LM Hash", 24 | input: "QWERTYUIOPASDFGHJKLZXCVBNM1234567890!@#$%^&*()_+.,?/", 25 | expectedOutput: "6D9DF16655336CA75A3C13DD18BA8156", 26 | recipeConfig: [ 27 | { 28 | op: "LM Hash", 29 | args: [], 30 | }, 31 | ], 32 | }, 33 | 34 | ]); 35 | -------------------------------------------------------------------------------- /tests/operations/tests/NetBIOS.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * NetBIOS tests. 3 | * 4 | * @author bwhitn [brian.m.whitney@outlook.com] 5 | * 6 | * @copyright Crown Copyright 2017 7 | * @license Apache-2.0 8 | */ 9 | import TestRegister from "../../lib/TestRegister.mjs"; 10 | 11 | TestRegister.addTests([ 12 | { 13 | name: "Encode NetBIOS name", 14 | input: "The NetBIOS name", 15 | expectedOutput: "FEGIGFCAEOGFHEECEJEPFDCAGOGBGNGF", 16 | recipeConfig: [ 17 | { 18 | op: "Encode NetBIOS Name", 19 | args: [65], 20 | }, 21 | ], 22 | }, 23 | { 24 | name: "Decode NetBIOS Name", 25 | input: "FEGIGFCAEOGFHEECEJEPFDCAGOGBGNGF", 26 | expectedOutput: "The NetBIOS name", 27 | recipeConfig: [ 28 | { 29 | op: "Decode NetBIOS Name", 30 | args: [65], 31 | }, 32 | ], 33 | }, 34 | ]); 35 | -------------------------------------------------------------------------------- /tests/operations/tests/NormaliseUnicode.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * Text Encoding Brute Force tests. 3 | * 4 | * @author Matthieu [m@tthieux.xyz] 5 | * 6 | * @copyright Crown Copyright 2019 7 | * @license Apache-2.0 8 | */ 9 | import TestRegister from "../../lib/TestRegister.mjs"; 10 | 11 | TestRegister.addTests([ 12 | { 13 | name: "Normalise Unicode - NFD", 14 | input: "\u00c7\u0043\u0327\u2160", 15 | expectedMatch: /C\u0327C\u0327\u2160/, 16 | recipeConfig: [ 17 | { 18 | op: "Normalise Unicode", 19 | args: ["NFD"], 20 | }, 21 | ], 22 | }, { 23 | name: "Normalise Unicode - NFC", 24 | input: "\u00c7\u0043\u0327\u2160", 25 | expectedMatch: /\u00C7\u00C7\u2160/, 26 | recipeConfig: [ 27 | { 28 | op: "Normalise Unicode", 29 | args: ["NFC"], 30 | }, 31 | ], 32 | }, { 33 | name: "Normalise Unicode - NFKD", 34 | input: "\u00c7\u0043\u0327\u2160", 35 | expectedMatch: /C\u0327C\u0327I/, 36 | recipeConfig: [ 37 | { 38 | op: "Normalise Unicode", 39 | args: ["NFKD"], 40 | }, 41 | ], 42 | }, { 43 | name: "Normalise Unicode - NFKC", 44 | input: "\u00c7\u0043\u0327\u2160", 45 | expectedMatch: /\u00C7\u00C7I/, 46 | recipeConfig: [ 47 | { 48 | op: "Normalise Unicode", 49 | args: ["NFKC"], 50 | }, 51 | ], 52 | }, 53 | ]); 54 | 55 | -------------------------------------------------------------------------------- /tests/operations/tests/OTP.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * OTP HOTP tests. 3 | * 4 | * @author bwhitn [brian.m.whitney@outlook.com] 5 | * 6 | * @copyright Crown Copyright 2017 7 | * @license Apache-2.0 8 | */ 9 | import TestRegister from "../../lib/TestRegister.mjs"; 10 | 11 | TestRegister.addTests([ 12 | { 13 | name: "Generate HOTP", 14 | input: "JBSWY3DPEHPK3PXP", 15 | expectedOutput: `URI: otpauth://hotp/?secret=JBSWY3DPEHPK3PXP&algorithm=SHA1&digits=6&counter=0\n\nPassword: 282760`, 16 | recipeConfig: [ 17 | { 18 | op: "Generate HOTP", 19 | args: ["", 6, 0], // [Name, Code length, Counter] 20 | }, 21 | ], 22 | }, 23 | ]); 24 | -------------------------------------------------------------------------------- /tests/operations/tests/ParseObjectIDTimestamp.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * Parse ObjectID timestamp tests 3 | * 4 | * @author dmfj [dominic@dmfj.io] 5 | * 6 | * @copyright Crown Copyright 2018 7 | * @license Apache-2.0 8 | */ 9 | import TestRegister from "../../lib/TestRegister.mjs"; 10 | 11 | 12 | TestRegister.addTests([ 13 | { 14 | name: "Parse ISO timestamp from ObjectId", 15 | input: "000000000000000000000000", 16 | expectedOutput: "1970-01-01T00:00:00.000Z", 17 | recipeConfig: [ 18 | { 19 | op: "Parse ObjectID timestamp", 20 | args: [], 21 | } 22 | ], 23 | } 24 | ]); 25 | -------------------------------------------------------------------------------- /tests/operations/tests/ParseTCP.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * Parse TCP tests. 3 | * 4 | * @author n1474335 5 | * @copyright Crown Copyright 2022 6 | * @license Apache-2.0 7 | */ 8 | import TestRegister from "../../lib/TestRegister.mjs"; 9 | 10 | TestRegister.addTests([ 11 | { 12 | name: "Parse TCP: No options", 13 | input: "c2eb0050a138132e70dc9fb9501804025ea70000", 14 | expectedMatch: /1026 \(Scaled: 1026\)/, 15 | recipeConfig: [ 16 | { 17 | op: "Parse TCP", 18 | args: ["Hex"], 19 | } 20 | ], 21 | }, 22 | { 23 | name: "Parse TCP: Options", 24 | input: "c2eb0050a1380c1f000000008002faf080950000020405b40103030801010402", 25 | expectedMatch: /1460/, 26 | recipeConfig: [ 27 | { 28 | op: "Parse TCP", 29 | args: ["Hex"], 30 | } 31 | ], 32 | }, 33 | { 34 | name: "Parse TCP: Timestamps", 35 | input: "9e90e11574d57b2c00000000a002ffffe5740000020405b40402080aa4e8c8f50000000001030308", 36 | expectedMatch: /2766719221/, 37 | recipeConfig: [ 38 | { 39 | op: "Parse TCP", 40 | args: ["Hex"], 41 | } 42 | ], 43 | } 44 | ]); 45 | -------------------------------------------------------------------------------- /tests/operations/tests/PowerSet.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * Power Set tests. 3 | * 4 | * @author d98762625 5 | * 6 | * @copyright Crown Copyright 2018 7 | * @license Apache-2.0 8 | */ 9 | import TestRegister from "../../lib/TestRegister.mjs"; 10 | 11 | TestRegister.addTests([ 12 | { 13 | name: "Power set: nothing", 14 | input: "", 15 | expectedOutput: "", 16 | recipeConfig: [ 17 | { 18 | op: "Power Set", 19 | args: [","], 20 | }, 21 | ], 22 | }, 23 | { 24 | name: "Power set", 25 | input: "1 2 4", 26 | expectedOutput: "\n4\n2\n1\n2 4\n1 4\n1 2\n1 2 4\n", 27 | recipeConfig: [ 28 | { 29 | op: "Power Set", 30 | args: [" "], 31 | }, 32 | ], 33 | }, 34 | ]); 35 | -------------------------------------------------------------------------------- /tests/operations/tests/RAKE.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * RAKE, Rapid Automatic Keyword Extraction tests. 3 | * 4 | * @author sw5678 5 | * @copyright Crown Copyright 2024 6 | * @license Apache-2.0 7 | */ 8 | import TestRegister from "../../lib/TestRegister.mjs"; 9 | 10 | TestRegister.addTests([ 11 | { 12 | "name": "RAKE: Basic Example", 13 | "input": "test1 test2. test2", 14 | "expectedOutput": "Scores: , Keywords: \n3.5, test1 test2\n1.5, test2", 15 | "recipeConfig": [ 16 | { 17 | "op": "RAKE", 18 | "args": ["\\s", "\\.\\s|\\n", "i,me,my,myself,we,our"] 19 | }, 20 | ], 21 | } 22 | ]); 23 | -------------------------------------------------------------------------------- /tests/operations/tests/Shuffle.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * @author mikecat 3 | * @copyright Crown Copyright 2022 4 | * @license Apache-2.0 5 | */ 6 | import TestRegister from "../../lib/TestRegister.mjs"; 7 | 8 | TestRegister.addTests([ 9 | { 10 | "name": "Shuffle empty", 11 | "input": "", 12 | "expectedOutput": "", 13 | "recipeConfig": [ 14 | { 15 | "op": "Shuffle", 16 | "args": ["Comma"] 17 | } 18 | ] 19 | }, 20 | { 21 | "name": "Shuffle bytes", 22 | "input": "12345678", 23 | "expectedOutput": "31 32 33 34 35 36 37 38", 24 | "recipeConfig": [ 25 | { 26 | "op": "Shuffle", 27 | "args": ["Nothing (separate chars)"] 28 | }, 29 | { 30 | "op": "To Hex", 31 | "args": ["Space", 0] 32 | }, 33 | { 34 | "op": "Sort", 35 | "args": ["Space", false, "Alphabetical (case sensitive)"] 36 | } 37 | ] 38 | }, 39 | { 40 | "name": "Shuffle lines", 41 | "input": "1\n2\n3\n4\n5\n6\n7\n8\n9\na\nb\nc\nd\ne\nf\n", 42 | "expectedOutput": "\n1\n2\n3\n4\n5\n6\n7\n8\n9\na\nb\nc\nd\ne\nf", 43 | "recipeConfig": [ 44 | { 45 | "op": "Shuffle", 46 | "args": ["Line feed"] 47 | }, 48 | { 49 | "op": "Sort", 50 | "args": ["Line feed", false, "Alphabetical (case sensitive)"] 51 | } 52 | ] 53 | } 54 | ]); 55 | -------------------------------------------------------------------------------- /tests/operations/tests/SwapCase.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * @author mikecat 3 | * @copyright Crown Copyright 2023 4 | * @license Apache-2.0 5 | */ 6 | import TestRegister from "../../lib/TestRegister.mjs"; 7 | 8 | TestRegister.addTests([ 9 | { 10 | "name": "Swap Case: basic example", 11 | "input": "Hello, World!", 12 | "expectedOutput": "hELLO, wORLD!", 13 | "recipeConfig": [ 14 | { 15 | "op": "Swap case", 16 | "args": [ 17 | ], 18 | }, 19 | ], 20 | }, 21 | { 22 | "name": "Swap Case: empty input", 23 | "input": "", 24 | "expectedOutput": "", 25 | "recipeConfig": [ 26 | { 27 | "op": "Swap case", 28 | "args": [ 29 | ], 30 | }, 31 | ], 32 | }, 33 | ]); 34 | -------------------------------------------------------------------------------- /tests/operations/tests/TextEncodingBruteForce.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * Text Encoding Brute Force tests. 3 | * 4 | * @author Cynser 5 | * 6 | * @copyright Crown Copyright 2018 7 | * @license Apache-2.0 8 | */ 9 | import TestRegister from "../../lib/TestRegister.mjs"; 10 | 11 | TestRegister.addTests([ 12 | { 13 | name: "Text Encoding Brute Force - Encode", 14 | input: "Булкі праз ляніва сабаку.", 15 | expectedMatch: /Windows-1251 Cyrillic \(1251\).{1,10}Булкі праз ляніва сабаку\./, 16 | recipeConfig: [ 17 | { 18 | op: "Text Encoding Brute Force", 19 | args: ["Encode"], 20 | }, 21 | ], 22 | }, 23 | { 24 | name: "Text Encoding Brute Force - Decode", 25 | input: "Áóëê³ ïðàç ëÿí³âà ñàáàêó.", 26 | expectedMatch: /Windows-1251 Cyrillic \(1251\).{1,10}Булкі праз ляніва сабаку\./, 27 | recipeConfig: [ 28 | { 29 | op: "Text Encoding Brute Force", 30 | args: ["Decode"], 31 | }, 32 | ], 33 | } 34 | ]); 35 | 36 | -------------------------------------------------------------------------------- /tests/operations/tests/UnescapeString.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * UnescapeString tests. 3 | * 4 | * @copyright Crown Copyright 2022 5 | * @license Apache-2.0 6 | */ 7 | import TestRegister from "../../lib/TestRegister.mjs"; 8 | 9 | TestRegister.addTests([ 10 | { 11 | name: "UnescapeString: escape sequences", 12 | input: "\\a\\b\\f\\n\\r\\t\\v\\'\\\"", 13 | expectedOutput: String.fromCharCode(0x07, 0x08, 0x0c, 0x0a, 0x0d, 0x09, 14 | 0x0b, 0x27, 0x22), 15 | recipeConfig: [ 16 | { 17 | op: "Unescape string", 18 | args: [], 19 | }, 20 | ], 21 | }, 22 | { 23 | name: "UnescapeString: octals", 24 | input: "\\0\\01\\012\\1\\12", 25 | expectedOutput: String.fromCharCode(0, 1, 10, 1, 10), 26 | recipeConfig: [ 27 | { 28 | op: "Unescape string", 29 | args: [], 30 | }, 31 | ], 32 | }, 33 | { 34 | name: "UnescapeString: hexadecimals", 35 | input: "\\x00\\xAA\\xaa", 36 | expectedOutput: String.fromCharCode(0, 170, 170), 37 | recipeConfig: [ 38 | { 39 | op: "Unescape string", 40 | args: [], 41 | }, 42 | ], 43 | }, 44 | { 45 | name: "UnescapeString: unicode", 46 | input: "\\u0061\\u{0062}", 47 | expectedOutput: "ab", 48 | recipeConfig: [ 49 | { 50 | op: "Unescape string", 51 | args: [], 52 | }, 53 | ], 54 | }, 55 | ]); 56 | -------------------------------------------------------------------------------- /tests/operations/tests/XXTEA.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * XXTEA tests. 3 | * 4 | * @author devcydo [devcydo@gmail.com] 5 | * @author n1474335 [n1474335@gmail.com] 6 | * @copyright Crown Copyright 2024 7 | * @license Apache-2.0 8 | */ 9 | import TestRegister from "../../lib/TestRegister.mjs"; 10 | 11 | TestRegister.addTests([ 12 | { 13 | name: "XXTEA Encrypt and Decrypt", 14 | input: "Hello World! 你好,中国!", 15 | expectedOutput: "Hello World! 你好,中国!", 16 | recipeConfig: [ 17 | { 18 | "op": "XXTEA Encrypt", 19 | "args": [{ "option": "UTF8", "string": "1234567890" }] 20 | }, 21 | { 22 | "op": "XXTEA Decrypt", 23 | "args": [{ "option": "UTF8", "string": "1234567890" }] 24 | } 25 | ], 26 | }, 27 | { 28 | name: "XXTEA Encrypt", 29 | input: "ნუ პანიკას", 30 | expectedOutput: "3db5a39db1663fc029bb630a38635b8de5bfef62192e52cc4bf83cda8ccbc701", 31 | recipeConfig: [ 32 | { 33 | "op": "XXTEA Encrypt", 34 | "args": [{ "option": "UTF8", "string": "1234567890" }] 35 | }, 36 | { 37 | "op": "To Hex", 38 | "args": ["None", 0] 39 | } 40 | ], 41 | } 42 | ]); 43 | -------------------------------------------------------------------------------- /tests/samples/files/Hitchhikers_Guide.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gchq/CyberChef/c57556f49f723863b9be15668fd240672cd15b09/tests/samples/files/Hitchhikers_Guide.jpeg -------------------------------------------------------------------------------- /tests/samples/files/TowelDay.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gchq/CyberChef/c57556f49f723863b9be15668fd240672cd15b09/tests/samples/files/TowelDay.jpeg -------------------------------------------------------------------------------- /tests/samples/files/mp3example.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gchq/CyberChef/c57556f49f723863b9be15668fd240672cd15b09/tests/samples/files/mp3example.mp3 -------------------------------------------------------------------------------- /tests/samples/files/testocr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gchq/CyberChef/c57556f49f723863b9be15668fd240672cd15b09/tests/samples/files/testocr.png --------------------------------------------------------------------------------