2
0
mirror of https://github.com/gchq/CyberChef synced 2026-01-19 08:53:47 +00:00

Compare commits

..

2 Commits

Author SHA1 Message Date
MANDEM_VIGNESH_KUMAR_REDDY
3e04e75fce Merge 27c9330b9f into 1b8c229df2 2025-02-18 05:44:46 +00:00
MANDEM_VIGNESH_KUMAR_REDDY
27c9330b9f Create vigenere.js
in these peice of code you can use it for the alphabets and including numbers and removing out all the traces of punctuation marks and special characters and making it easy to work with and along side these code has both the encryption and decryption codes
2025-02-18 11:05:23 +05:30
27 changed files with 604 additions and 3989 deletions

7
package-lock.json generated
View File

@@ -48,7 +48,6 @@
"highlight.js": "^11.9.0",
"ieee754": "^1.2.1",
"jimp": "^0.22.12",
"jq-web": "^0.5.1",
"jquery": "3.7.1",
"js-crc": "^0.2.0",
"js-sha3": "^0.9.3",
@@ -12291,12 +12290,6 @@
"integrity": "sha512-WZzeDOEtTOBK4Mdsar0IqEU5sMr3vSV2RqkAIzUEV2BHnUfKGyswWFPFwK5EeDo93K3FohSHbLAjj0s1Wzd+dg==",
"license": "BSD-3-Clause"
},
"node_modules/jq-web": {
"version": "0.5.1",
"resolved": "https://registry.npmjs.org/jq-web/-/jq-web-0.5.1.tgz",
"integrity": "sha512-3Fa3E6g3U1O1j46ljy0EM10yRr4txzILga8J7bqOG8F89gZ6Lilz82WG9z6TItWpYEO0YGa4W8yFGj+NMM1xqQ==",
"license": "ISC"
},
"node_modules/jquery": {
"version": "3.7.1",
"resolved": "https://registry.npmjs.org/jquery/-/jquery-3.7.1.tgz",

View File

@@ -134,8 +134,8 @@
"highlight.js": "^11.9.0",
"ieee754": "^1.2.1",
"jimp": "^0.22.12",
"jq-web": "^0.5.1",
"jquery": "3.7.1",
"js-crc": "^0.2.0",
"js-sha3": "^0.9.3",
"jsesc": "^3.0.2",
"json5": "^2.2.3",

View File

@@ -72,8 +72,6 @@
"Avro to JSON",
"CBOR Encode",
"CBOR Decode",
"YAML to JSON",
"JSON to YAML",
"Caret/M-decode",
"Rison Encode",
"Rison Decode",
@@ -195,9 +193,7 @@
"Parse SSH Host Key",
"Parse CSR",
"Public Key from Certificate",
"Public Key from Private Key",
"SM2 Encrypt",
"SM2 Decrypt"
"Public Key from Private Key"
]
},
{
@@ -445,7 +441,9 @@
"Fletcher-64 Checksum",
"Adler-32 Checksum",
"Luhn Checksum",
"CRC Checksum",
"CRC-8 Checksum",
"CRC-16 Checksum",
"CRC-32 Checksum",
"TCP/IP Checksum"
]
},
@@ -467,7 +465,6 @@
"CSS Minify",
"XPath expression",
"JPath expression",
"Jq",
"CSS selector",
"PHP Deserialize",
"Microsoft Script Decoder",

View File

@@ -1,258 +0,0 @@
/**
* Utilities and operations utilized for SM2 encryption and decryption
* @author flakjacket95 [dflack95@gmail.com]
* @copyright Crown Copyright 2024
* @license Apache-2.0
*/
import OperationError from "../errors/OperationError.mjs";
import { fromHex } from "../lib/Hex.mjs";
import Utils from "../Utils.mjs";
import Sm3 from "crypto-api/src/hasher/sm3.mjs";
import {toHex} from "crypto-api/src/encoder/hex.mjs";
import r from "jsrsasign";
/**
* SM2 Class for encryption and decryption operations
*/
export class SM2 {
/**
* Constructor for SM2 class; sets up with the curve and the output format as specified in user args
*
* @param {*} curve
* @param {*} format
*/
constructor(curve, format) {
this.ecParams = null;
this.rng = new r.SecureRandom();
/*
For any additional curve definitions utilized by SM2, add another block like the below for that curve, then add the curve name to the Curve selection dropdown
*/
r.crypto.ECParameterDB.regist(
"sm2p256v1", // name / p = 2**256 - 2**224 - 2**96 + 2**64 - 1
256,
"FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF", // p
"FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC", // a
"28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93", // b
"FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123", // n
"1", // h
"32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7", // gx
"BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0", // gy
[]
); // alias
this.ecParams = r.crypto.ECParameterDB.getByName(curve);
this.format = format;
}
/**
* Set the public key coordinates for the SM2 class
*
* @param {string} publicKeyX
* @param {string} publicKeyY
*/
setPublicKey(publicKeyX, publicKeyY) {
/*
* TODO: This needs some additional length validation; and checking for errors in the decoding process
* TODO: Can probably support other public key encoding methods here as well in the future
*/
this.publicKey = this.ecParams.curve.decodePointHex("04" + publicKeyX + publicKeyY);
if (this.publicKey.isInfinity()) {
throw new OperationError("Invalid Public Key");
}
}
/**
* Set the private key value for the SM2 class
*
* @param {string} privateKey
*/
setPrivateKey(privateKeyHex) {
this.privateKey = new r.BigInteger(privateKeyHex, 16);
}
/**
* Main encryption function; takes user input, processes encryption and returns the result in hex (with the components arranged as configured by the user args)
*
* @param {*} input
* @returns {string}
*/
encrypt(input) {
const G = this.ecParams.G;
/*
* Compute a new, random public key along the same elliptic curve to form the starting point for our encryption process (record the resulting X and Y as hex to provide as part of the operation output)
* k: Randomly generated BigInteger
* c1: Result of dotting our curve generator point `G` with the value of `k`
*/
const k = this.generatePublicKey();
const c1 = G.multiply(k);
const [hexC1X, hexC1Y] = this.getPointAsHex(c1);
/*
* Compute p2 (secret) using the public key, and the chosen k value above
*/
const p2 = this.publicKey.multiply(k);
/*
* Compute the C3 SM3 hash before we transform the array
*/
const c3 = this.c3(p2, input);
/*
* Genreate a proper length encryption key, XOR iteratively, and convert newly encrypted data to hex
*/
const key = this.kdf(p2, input.byteLength);
for (let i = 0; i < input.byteLength; i++) {
input[i] ^= Utils.ord(key[i]);
}
const c2 = Buffer.from(input).toString("hex");
/*
* Check user input specs; order the output components as selected
*/
if (this.format === "C1C3C2") {
return hexC1X + hexC1Y + c3 + c2;
} else {
return hexC1X + hexC1Y + c2 + c3;
}
}
/**
* Function to decrypt an SM2 encrypted message
*
* @param {*} input
*/
decrypt(input) {
const c1X = input.slice(0, 64);
const c1Y = input.slice(64, 128);
let c3 = "";
let c2 = "";
if (this.format === "C1C3C2") {
c3 = input.slice(128, 192);
c2 = input.slice(192);
} else {
c2 = input.slice(128, -64);
c3 = input.slice(-64);
}
c2 = Uint8Array.from(fromHex(c2));
const c1 = this.ecParams.curve.decodePointHex("04" + c1X + c1Y);
/*
* Compute the p2 (secret) value by taking the C1 point provided in the encrypted package, and multiplying by the private k value
*/
const p2 = c1.multiply(this.privateKey);
/*
* Similar to encryption; compute sufficient length key material and XOR the input data to recover the original message
*/
const key = this.kdf(p2, c2.byteLength);
for (let i = 0; i < c2.byteLength; i++) {
c2[i] ^= Utils.ord(key[i]);
}
const check = this.c3(p2, c2);
if (check === c3) {
return c2.buffer;
} else {
throw new OperationError("Decryption Error -- Computed Hashes Do Not Match");
}
}
/**
* Generates a large random number
*
* @param {*} limit
* @returns
*/
getBigRandom(limit) {
return new r.BigInteger(limit.bitLength(), this.rng)
.mod(limit.subtract(r.BigInteger.ONE))
.add(r.BigInteger.ONE);
}
/**
* Helper function for generating a large random K number; utilized for generating our initial C1 point
* TODO: Do we need to do any sort of validation on the resulting k values?
*
* @returns {BigInteger}
*/
generatePublicKey() {
const n = this.ecParams.n;
const k = this.getBigRandom(n);
return k;
}
/**
* SM2 Key Derivation Function (KDF); Takes P2 point, and generates a key material stream large enough to encrypt all of the input data
*
* @param {*} p2
* @param {*} len
* @returns {string}
*/
kdf(p2, len) {
const [hX, hY] = this.getPointAsHex(p2);
const total = Math.ceil(len / 32) + 1;
let cnt = 1;
let keyMaterial = "";
while (cnt < total) {
const num = Utils.intToByteArray(cnt, 4, "big");
const overall = fromHex(hX).concat(fromHex(hY)).concat(num);
keyMaterial += this.sm3(overall);
cnt++;
}
return keyMaterial;
}
/**
* Calculates the C3 component of our final encrypted payload; which is the SM3 hash of the P2 point and the original, unencrypted input data
*
* @param {*} p2
* @param {*} input
* @returns {string}
*/
c3(p2, input) {
const [hX, hY] = this.getPointAsHex(p2);
const overall = fromHex(hX).concat(Array.from(input)).concat(fromHex(hY));
return toHex(this.sm3(overall));
}
/**
* SM3 setup helper function; takes input data as an array, processes the hash and returns the result
*
* @param {*} data
* @returns {string}
*/
sm3(data) {
const hashData = Utils.arrayBufferToStr(Uint8Array.from(data).buffer, false);
const hasher = new Sm3();
hasher.update(hashData);
return hasher.finalize();
}
/**
* Utility function, returns an elliptic curve points X and Y values as hex;
*
* @param {EcPointFp} point
* @returns {[]}
*/
getPointAsHex(point) {
const biX = point.getX().toBigInteger();
const biY = point.getY().toBigInteger();
const charlen = this.ecParams.keycharlen;
const hX = ("0000000000" + biX.toString(16)).slice(- charlen);
const hY = ("0000000000" + biY.toString(16)).slice(- charlen);
return [hX, hY];
}
}

View File

@@ -0,0 +1,41 @@
/**
* @author n1474335 [n1474335@gmail.com]
* @copyright Crown Copyright 2016
* @license Apache-2.0
*/
import Operation from "../Operation.mjs";
import JSCRC from "js-crc";
/**
* CRC-16 Checksum operation
*/
class CRC16Checksum extends Operation {
/**
* CRC16Checksum constructor
*/
constructor() {
super();
this.name = "CRC-16 Checksum";
this.module = "Crypto";
this.description = "A cyclic redundancy check (CRC) is an error-detecting code commonly used in digital networks and storage devices to detect accidental changes to raw data.<br><br>The CRC was invented by W. Wesley Peterson in 1961.";
this.infoURL = "https://wikipedia.org/wiki/Cyclic_redundancy_check";
this.inputType = "ArrayBuffer";
this.outputType = "string";
this.args = [];
}
/**
* @param {ArrayBuffer} input
* @param {Object[]} args
* @returns {string}
*/
run(input, args) {
return JSCRC.crc16(input);
}
}
export default CRC16Checksum;

View File

@@ -0,0 +1,41 @@
/**
* @author n1474335 [n1474335@gmail.com]
* @copyright Crown Copyright 2016
* @license Apache-2.0
*/
import Operation from "../Operation.mjs";
import JSCRC from "js-crc";
/**
* CRC-32 Checksum operation
*/
class CRC32Checksum extends Operation {
/**
* CRC32Checksum constructor
*/
constructor() {
super();
this.name = "CRC-32 Checksum";
this.module = "Crypto";
this.description = "A cyclic redundancy check (CRC) is an error-detecting code commonly used in digital networks and storage devices to detect accidental changes to raw data.<br><br>The CRC was invented by W. Wesley Peterson in 1961; the 32-bit CRC function of Ethernet and many other standards is the work of several researchers and was published in 1975.";
this.infoURL = "https://wikipedia.org/wiki/Cyclic_redundancy_check";
this.inputType = "ArrayBuffer";
this.outputType = "string";
this.args = [];
}
/**
* @param {ArrayBuffer} input
* @param {Object[]} args
* @returns {string}
*/
run(input, args) {
return JSCRC.crc32(input);
}
}
export default CRC32Checksum;

View File

@@ -0,0 +1,157 @@
/**
* @author mshwed [m@ttshwed.com]
* @copyright Crown Copyright 2019
* @license Apache-2.0
*/
import Operation from "../Operation.mjs";
import OperationError from "../errors/OperationError.mjs";
import { toHexFast } from "../lib/Hex.mjs";
/**
* CRC-8 Checksum operation
*/
class CRC8Checksum extends Operation {
/**
* CRC8Checksum constructor
*/
constructor() {
super();
this.name = "CRC-8 Checksum";
this.module = "Crypto";
this.description = "A cyclic redundancy check (CRC) is an error-detecting code commonly used in digital networks and storage devices to detect accidental changes to raw data.<br><br>The CRC was invented by W. Wesley Peterson in 1961.";
this.infoURL = "https://wikipedia.org/wiki/Cyclic_redundancy_check";
this.inputType = "ArrayBuffer";
this.outputType = "string";
this.args = [
{
"name": "Algorithm",
"type": "option",
"value": [
"CRC-8",
"CRC-8/CDMA2000",
"CRC-8/DARC",
"CRC-8/DVB-S2",
"CRC-8/EBU",
"CRC-8/I-CODE",
"CRC-8/ITU",
"CRC-8/MAXIM",
"CRC-8/ROHC",
"CRC-8/WCDMA"
]
}
];
}
/**
* Generates the pre-computed lookup table for byte division
*
* @param polynomial
*/
calculateCRC8LookupTable(polynomial) {
const crc8Table = new Uint8Array(256);
let currentByte;
for (let i = 0; i < 256; i++) {
currentByte = i;
for (let bit = 0; bit < 8; bit++) {
if ((currentByte & 0x80) !== 0) {
currentByte <<= 1;
currentByte ^= polynomial;
} else {
currentByte <<= 1;
}
}
crc8Table[i] = currentByte;
}
return crc8Table;
}
/**
* Calculates the CRC-8 Checksum from an input
*
* @param {ArrayBuffer} input
* @param {number} polynomial
* @param {number} initializationValue
* @param {boolean} inputReflection
* @param {boolean} outputReflection
* @param {number} xorOut
*/
calculateCRC8(input, polynomial, initializationValue, inputReflection, outputReflection, xorOut) {
const crcSize = 8;
const crcTable = this.calculateCRC8LookupTable(polynomial);
let crc = initializationValue !== 0 ? initializationValue : 0;
let currentByte, position;
input = new Uint8Array(input);
for (const inputByte of input) {
currentByte = inputReflection ? this.reverseBits(inputByte, crcSize) : inputByte;
position = (currentByte ^ crc) & 255;
crc = crcTable[position];
}
crc = outputReflection ? this.reverseBits(crc, crcSize) : crc;
if (xorOut !== 0) crc = crc ^ xorOut;
return toHexFast(new Uint8Array([crc]));
}
/**
* Reverse the bits for a given input byte.
*
* @param {number} input
*/
reverseBits(input, hashSize) {
let reversedByte = 0;
for (let i = hashSize - 1; i >= 0; i--) {
reversedByte |= ((input & 1) << i);
input >>= 1;
}
return reversedByte;
}
/**
* @param {ArrayBuffer} input
* @param {Object[]} args
* @returns {string}
*/
run(input, args) {
const algorithm = args[0];
switch (algorithm) {
case "CRC-8":
return this.calculateCRC8(input, 0x7, 0x0, false, false, 0x0);
case "CRC-8/CDMA2000":
return this.calculateCRC8(input, 0x9B, 0xFF, false, false, 0x0);
case "CRC-8/DARC":
return this.calculateCRC8(input, 0x39, 0x0, true, true, 0x0);
case "CRC-8/DVB-S2":
return this.calculateCRC8(input, 0xD5, 0x0, false, false, 0x0);
case "CRC-8/EBU":
return this.calculateCRC8(input, 0x1D, 0xFF, true, true, 0x0);
case "CRC-8/I-CODE":
return this.calculateCRC8(input, 0x1D, 0xFD, false, false, 0x0);
case "CRC-8/ITU":
return this.calculateCRC8(input, 0x7, 0x0, false, false, 0x55);
case "CRC-8/MAXIM":
return this.calculateCRC8(input, 0x31, 0x0, true, true, 0x0);
case "CRC-8/ROHC":
return this.calculateCRC8(input, 0x7, 0xFF, true, true, 0x0);
case "CRC-8/WCDMA":
return this.calculateCRC8(input, 0x9B, 0x0, true, true, 0x0);
default:
throw new OperationError("Unknown checksum algorithm");
}
}
}
export default CRC8Checksum;

File diff suppressed because it is too large Load Diff

View File

@@ -18,7 +18,7 @@ class ConvertLeetSpeak extends Operation {
this.name = "Convert Leet Speak";
this.module = "Default";
this.description = "Converts to and from Leet Speak.";
this.description = "Converts to and from Leet Speak";
this.infoURL = "https://wikipedia.org/wiki/Leet";
this.inputType = "string";
this.outputType = "string";
@@ -39,16 +39,13 @@ class ConvertLeetSpeak extends Operation {
*/
run(input, args) {
const direction = args[0];
if (direction === "To Leet Speak") {
return input.replace(/[a-z]/gi, char => {
const leetChar = toLeetMap[char.toLowerCase()] || char;
return char === char.toUpperCase() ? leetChar.toUpperCase() : leetChar;
return input.replace(/[abcdefghijklmnopqrstuvwxyz]/gi, char => {
return toLeetMap[char.toLowerCase()] || char;
});
} else if (direction === "From Leet Speak") {
return input.replace(/[48cd3f6h1jklmn0pqr57uvwxyz]/gi, char => {
const normalChar = fromLeetMap[char] || char;
return normalChar;
return input.replace(/[48cd3f6h1jklmn0pqr57uvwxyz]/g, char => {
return fromLeetMap[char] || char;
});
}
}

View File

@@ -27,7 +27,9 @@ import Fletcher16Checksum from "./Fletcher16Checksum.mjs";
import Fletcher32Checksum from "./Fletcher32Checksum.mjs";
import Fletcher64Checksum from "./Fletcher64Checksum.mjs";
import Adler32Checksum from "./Adler32Checksum.mjs";
import CRCChecksum from "./CRCChecksum.mjs";
import CRC8Checksum from "./CRC8Checksum.mjs";
import CRC16Checksum from "./CRC16Checksum.mjs";
import CRC32Checksum from "./CRC32Checksum.mjs";
import BLAKE2b from "./BLAKE2b.mjs";
import BLAKE2s from "./BLAKE2s.mjs";
import Streebog from "./Streebog.mjs";
@@ -118,9 +120,9 @@ class GenerateAllHashes extends Operation {
{name: "Fletcher-32", algo: (new Fletcher32Checksum), inputType: "byteArray", params: []},
{name: "Fletcher-64", algo: (new Fletcher64Checksum), inputType: "byteArray", params: []},
{name: "Adler-32", algo: (new Adler32Checksum), inputType: "byteArray", params: []},
{name: "CRC-8", algo: (new CRCChecksum), inputType: "arrayBuffer", params: ["CRC-8"]},
{name: "CRC-16", algo: (new CRCChecksum), inputType: "arrayBuffer", params: ["CRC-16"]},
{name: "CRC-32", algo: (new CRCChecksum), inputType: "arrayBuffer", params: ["CRC-32"]}
{name: "CRC-8", algo: (new CRC8Checksum), inputType: "arrayBuffer", params: ["CRC-8"]},
{name: "CRC-16", algo: (new CRC16Checksum), inputType: "arrayBuffer", params: []},
{name: "CRC-32", algo: (new CRC32Checksum), inputType: "arrayBuffer", params: []}
];
}

View File

@@ -1,46 +0,0 @@
/**
* @author ccarpo [ccarpo@gmx.net]
* @copyright Crown Copyright 2021
* @license Apache-2.0
*/
import Operation from "../Operation.mjs";
import OperationError from "../errors/OperationError.mjs";
import YAML from "yaml";
/**
* JSON to YAML operation
*/
class JSONtoYAML extends Operation {
/**
* JSONtoYAML constructor
*/
constructor() {
super();
this.name = "JSON to YAML";
this.module = "Default";
this.description = "Format a JSON object into YAML";
this.infoURL = "https://en.wikipedia.org/wiki/YAML";
this.inputType = "JSON";
this.outputType = "string";
this.args = [];
}
/**
* @param {JSON} input
* @param {Object[]} args
* @returns {string}
*/
run(input, args) {
try {
return YAML.stringify(input);
} catch (err) {
throw new OperationError("Test");
}
}
}
export default JSONtoYAML;

View File

@@ -1,57 +0,0 @@
/**
* @author zhzy0077 [zhzy0077@hotmail.com]
* @copyright Crown Copyright 2023
* @license Apache-2.0
*/
import Operation from "../Operation.mjs";
import OperationError from "../errors/OperationError.mjs";
import jq from "jq-web";
/**
* jq operation
*/
class Jq extends Operation {
/**
* Jq constructor
*/
constructor() {
super();
this.name = "Jq";
this.module = "Jq";
this.description = "jq is a lightweight and flexible command-line JSON processor.";
this.infoURL = "https://github.com/jqlang/jq";
this.inputType = "JSON";
this.outputType = "string";
this.args = [
{
name: "Query",
type: "string",
value: ""
}
];
}
/**
* @param {JSON} input
* @param {Object[]} args
* @returns {string}
*/
run(input, args) {
const [query] = args;
let result;
try {
result = jq.json(input, query);
} catch (err) {
throw new OperationError(`Invalid jq expression: ${err.message}`);
}
return JSON.stringify(result);
}
}
export default Jq;

View File

@@ -6,8 +6,7 @@
import r from "jsrsasign";
import { fromBase64 } from "../lib/Base64.mjs";
import { runHash } from "../lib/Hash.mjs";
import { fromHex, toHex } from "../lib/Hex.mjs";
import { toHex } from "../lib/Hex.mjs";
import { formatByteStr, formatDnObj } from "../lib/PublicKey.mjs";
import Operation from "../Operation.mjs";
import Utils from "../Utils.mjs";
@@ -82,8 +81,7 @@ class ParseX509Certificate extends Operation {
}
if (undefinedInputFormat) throw "Undefined input format";
const hex = Utils.strToArrayBuffer(Utils.byteArrayToChars(fromHex(cert.hex))),
sn = cert.getSerialNumberHex(),
const sn = cert.getSerialNumberHex(),
issuer = cert.getIssuer(),
subject = cert.getSubject(),
pk = cert.getPublicKey(),
@@ -193,10 +191,6 @@ Issuer
${issuerStr}
Subject
${subjectStr}
Fingerprints
MD5: ${runHash("md5", hex)}
SHA1: ${runHash("sha1", hex)}
SHA256: ${runHash("sha256", hex)}
Public Key
${pkStr.slice(0, -1)}
Certificate Signature

View File

@@ -1,71 +0,0 @@
/**
* @author flakjacket95 [dflack95@gmail.com]
* @copyright Crown Copyright 2024
* @license Apache-2.0
*/
import OperationError from "../errors/OperationError.mjs";
import Operation from "../Operation.mjs";
import { SM2 } from "../lib/SM2.mjs";
/**
* SM2Decrypt operation
*/
class SM2Decrypt extends Operation {
/**
* SM2Decrypt constructor
*/
constructor() {
super();
this.name = "SM2 Decrypt";
this.module = "Crypto";
this.description = "Decrypts a message utilizing the SM2 standard";
this.infoURL = ""; // Usually a Wikipedia link. Remember to remove localisation (i.e. https://wikipedia.org/etc rather than https://en.wikipedia.org/etc)
this.inputType = "string";
this.outputType = "ArrayBuffer";
this.args = [
{
name: "Private Key",
type: "string",
value: "DEADBEEF"
},
{
"name": "Input Format",
"type": "option",
"value": ["C1C3C2", "C1C2C3"],
"defaultIndex": 0
},
{
name: "Curve",
type: "option",
"value": ["sm2p256v1"],
"defaultIndex": 0
}
];
}
/**
* @param {string} input
* @param {Object[]} args
* @returns {ArrayBuffer}
*/
run(input, args) {
const [privateKey, inputFormat, curveName] = args;
if (privateKey.length !== 64) {
throw new OperationError("Input private key must be in hex; and should be 32 bytes");
}
const sm2 = new SM2(curveName, inputFormat);
sm2.setPrivateKey(privateKey);
const result = sm2.decrypt(input);
return result;
}
}
export default SM2Decrypt;

View File

@@ -1,77 +0,0 @@
/**
* @author flakjacket95 [dflack95@gmail.com]
* @copyright Crown Copyright 2024
* @license Apache-2.0
*/
import OperationError from "../errors/OperationError.mjs";
import Operation from "../Operation.mjs";
import { SM2 } from "../lib/SM2.mjs";
/**
* SM2 Encrypt operation
*/
class SM2Encrypt extends Operation {
/**
* SM2Encrypt constructor
*/
constructor() {
super();
this.name = "SM2 Encrypt";
this.module = "Crypto";
this.description = "Encrypts a message utilizing the SM2 standard";
this.infoURL = ""; // Usually a Wikipedia link. Remember to remove localisation (i.e. https://wikipedia.org/etc rather than https://en.wikipedia.org/etc)
this.inputType = "ArrayBuffer";
this.outputType = "string";
this.args = [
{
name: "Public Key X",
type: "string",
value: "DEADBEEF"
},
{
name: "Public Key Y",
type: "string",
value: "DEADBEEF"
},
{
"name": "Output Format",
"type": "option",
"value": ["C1C3C2", "C1C2C3"],
"defaultIndex": 0
},
{
name: "Curve",
type: "option",
"value": ["sm2p256v1"],
"defaultIndex": 0
}
];
}
/**
* @param {ArrayBuffer} input
* @param {Object[]} args
* @returns {byteArray}
*/
run(input, args) {
const [publicKeyX, publicKeyY, outputFormat, curveName] = args;
this.outputFormat = outputFormat;
if (publicKeyX.length !== 64 || publicKeyY.length !== 64) {
throw new OperationError("Invalid Public Key - Ensure each component is 32 bytes in size and in hex");
}
const sm2 = new SM2(curveName, outputFormat);
sm2.setPublicKey(publicKeyX, publicKeyY);
const result = sm2.encrypt(new Uint8Array(input));
return result;
}
}
export default SM2Encrypt;

View File

@@ -1,45 +0,0 @@
/**
* @author ccarpo [ccarpo@gmx.net]
* @copyright Crown Copyright 2021
* @license Apache-2.0
*/
import Operation from "../Operation.mjs";
import OperationError from "../errors/OperationError.mjs";
import jsYaml from "js-yaml";
/**
* YAML to JSON operation
*/
class YAMLToJSON extends Operation {
/**
* YAMLToJSON constructor
*/
constructor() {
super();
this.name = "YAML to JSON";
this.module = "Default";
this.description = "Convert YAML to JSON";
this.infoURL = "https://en.wikipedia.org/wiki/YAML";
this.inputType = "string";
this.outputType = "JSON";
this.args = [];
}
/**
* @param {string} input
* @param {Object[]} args
* @returns {JSON}
*/
run(input, args) {
try {
return jsYaml.load(input);
} catch (err) {
throw new OperationError("Unable to parse YAML: " + err);
}
}
}
export default YAMLToJSON;

View File

@@ -23,7 +23,7 @@
<html lang="en" class="classic">
<head>
<meta charset="UTF-8">
<title>Netlify CyberChef</title>
<title>CyberChef</title>
<meta name="copyright" content="Crown Copyright 2016-<%= htmlWebpackPlugin.options.compileYear %>" />
<meta name="description" content="The Cyber Swiss Army Knife - a web app for encryption, encoding, compression and data analysis" />

View File

@@ -160,35 +160,16 @@ class OptionsWaiter {
// Update theme selection
const themeSelect = document.getElementById("theme");
let themeOption = themeSelect.querySelector(`option[value="${theme}"]`);
if (!themeOption) {
const preferredColorScheme = this.getPreferredColorScheme();
document.querySelector(":root").className = preferredColorScheme;
themeOption = themeSelect.querySelector(`option[value="${preferredColorScheme}"]`);
}
themeSelect.selectedIndex = themeOption.index;
themeSelect.selectedIndex = themeSelect.querySelector(`option[value="${theme}"`).index;
}
/**
* Applies the user's preferred color scheme using the `prefers-color-scheme` media query.
*/
applyPreferredColorScheme() {
const themeFromStorage = this.app?.options?.theme;
let theme = themeFromStorage;
if (!theme) {
theme = this.getPreferredColorScheme();
}
this.changeTheme(theme);
}
/**
* Get the user's preferred color scheme using the `prefers-color-scheme` media query.
*/
getPreferredColorScheme() {
const prefersDarkScheme = window.matchMedia("(prefers-color-scheme: dark)").matches;
return prefersDarkScheme ? "dark" : "classic";
const theme = prefersDarkScheme ? "dark" : "classic";
this.changeTheme(theme);
}
/**

View File

@@ -64,9 +64,9 @@ module.exports = {
testOp(browser, ["From Hex", "Bzip2 Decompress"], "425a68393141592653597b0884b7000003038000008200ce00200021a647a4218013709517c5dc914e14241ec2212dc0", "test_output", [[], [true]]);
// testOp(browser, "CBOR Decode", "test input", "test output");
// testOp(browser, "CBOR Encode", "test input", "test output");
testOp(browser, "CRC Checksum", "test input", "77c7", ["CRC-16"]);
testOp(browser, "CRC Checksum", "test input", "29822bc8", ["CRC-32"]);
testOp(browser, "CRC Checksum", "test input", "9d", ["CRC-8"]);
testOp(browser, "CRC-16 Checksum", "test input", "77c7");
testOp(browser, "CRC-32 Checksum", "test input", "29822bc8");
testOp(browser, "CRC-8 Checksum", "test input", "9d");
// testOp(browser, "CSS Beautify", "test input", "test_output");
// testOp(browser, "CSS Minify", "test input", "test_output");
// testOp(browser, "CSS selector", "test input", "test_output");

View File

@@ -305,6 +305,16 @@ Full hash: $2a$10$ODeP1.6fMsb.ENk2ngPUCO7qTGVPyHA9TqDVcyupyed8FjsiF65L6`;
assert.strictEqual(result.toString(), "2");
}),
it("CRC16 Checksum", () => {
const result = chef.CRC16Checksum("Rain on Your Parade");
assert.strictEqual(result.toString(), "db1c");
}),
it("CRC32 Checksum", () => {
const result = chef.CRC32Checksum("Rain on Your Parade");
assert.strictEqual(result.toString(), "e902f76c");
}),
it("CSS Beautify", () => {
const result = chef.CSSBeautify("header {color:black;padding:3rem;}");
const expected = `header {

View File

@@ -44,6 +44,7 @@ import "./tests/ChaCha.mjs";
import "./tests/ChangeIPFormat.mjs";
import "./tests/CharEnc.mjs";
import "./tests/Charts.mjs";
import "./tests/Checksum.mjs";
import "./tests/Ciphers.mjs";
import "./tests/CipherSaber2.mjs";
import "./tests/CMAC.mjs";
@@ -55,7 +56,6 @@ import "./tests/ConditionalJump.mjs";
import "./tests/ConvertCoordinateFormat.mjs";
import "./tests/ConvertLeetSpeak.mjs";
import "./tests/ConvertToNATOAlphabet.mjs";
import "./tests/CRCChecksum.mjs";
import "./tests/Crypt.mjs";
import "./tests/CSV.mjs";
import "./tests/DateTime.mjs";
@@ -144,7 +144,6 @@ import "./tests/SetIntersection.mjs";
import "./tests/SetUnion.mjs";
import "./tests/Shuffle.mjs";
import "./tests/SIGABA.mjs";
import "./tests/SM2.mjs";
import "./tests/SM4.mjs";
// import "./tests/SplitColourChannels.mjs"; // Cannot test operations that use the File type yet
import "./tests/StrUtils.mjs";
@@ -161,16 +160,6 @@ import "./tests/TranslateDateTimeFormat.mjs";
import "./tests/Typex.mjs";
import "./tests/UnescapeString.mjs";
import "./tests/Unicode.mjs";
import "./tests/RSA.mjs";
import "./tests/CBOREncode.mjs";
import "./tests/CBORDecode.mjs";
import "./tests/JA3Fingerprint.mjs";
import "./tests/JA3SFingerprint.mjs";
import "./tests/HASSH.mjs";
import "./tests/JSONtoYAML.mjs";
// Cannot test operations that use the File type yet
// import "./tests/SplitColourChannels.mjs";
import "./tests/YARA.mjs";
import "./tests/ParseCSR.mjs";
import "./tests/XXTEA.mjs";

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,241 @@
/**
* Checksum tests.
*
* @author n1474335 [n1474335@gmail.com]
* @copyright Crown Copyright 2018
* @license Apache-2.0
*/
import TestRegister from "../../lib/TestRegister.mjs";
const BASIC_STRING = "The ships hung in the sky in much the same way that bricks don't.";
const UTF8_STR = "ნუ პანიკას";
const ALL_BYTES = [
"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
"\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
"\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f",
"\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f",
"\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f",
"\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f",
"\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f",
"\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f",
"\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f",
"\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f",
"\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf",
"\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf",
"\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf",
"\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf",
"\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef",
"\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff",
].join("");
TestRegister.addTests([
{
name: "CRC-8: nothing",
input: "",
expectedOutput: "00",
recipeConfig: [
{
"op": "CRC-8 Checksum",
"args": ["CRC-8"]
}
]
},
{
name: "CRC-8: default check",
input: "123456789",
expectedOutput: "f4",
recipeConfig: [
{
"op": "CRC-8 Checksum",
"args": ["CRC-8"]
}
]
},
{
name: "CRC-8: CDMA2000",
input: "123456789",
expectedOutput: "da",
recipeConfig: [
{
"op": "CRC-8 Checksum",
"args": ["CRC-8/CDMA2000"]
}
]
},
{
name: "CRC-8: DARC",
input: "123456789",
expectedOutput: "15",
recipeConfig: [
{
"op": "CRC-8 Checksum",
"args": ["CRC-8/DARC"]
}
]
},
{
name: "CRC-8: DVB-S2",
input: "123456789",
expectedOutput: "bc",
recipeConfig: [
{
"op": "CRC-8 Checksum",
"args": ["CRC-8/DVB-S2"]
}
]
},
{
name: "CRC-8: EBU",
input: "123456789",
expectedOutput: "97",
recipeConfig: [
{
"op": "CRC-8 Checksum",
"args": ["CRC-8/EBU"]
}
]
},
{
name: "CRC-8: I-CODE",
input: "123456789",
expectedOutput: "7e",
recipeConfig: [
{
"op": "CRC-8 Checksum",
"args": ["CRC-8/I-CODE"]
}
]
},
{
name: "CRC-8: ITU",
input: "123456789",
expectedOutput: "a1",
recipeConfig: [
{
"op": "CRC-8 Checksum",
"args": ["CRC-8/ITU"]
}
]
},
{
name: "CRC-8: MAXIM",
input: "123456789",
expectedOutput: "a1",
recipeConfig: [
{
"op": "CRC-8 Checksum",
"args": ["CRC-8/MAXIM"]
}
]
},
{
name: "CRC-8: ROHC",
input: "123456789",
expectedOutput: "d0",
recipeConfig: [
{
"op": "CRC-8 Checksum",
"args": ["CRC-8/ROHC"]
}
]
},
{
name: "CRC-8: WCDMA",
input: "123456789",
expectedOutput: "25",
recipeConfig: [
{
"op": "CRC-8 Checksum",
"args": ["CRC-8/WCDMA"]
}
]
},
{
name: "CRC-16: nothing",
input: "",
expectedOutput: "0000",
recipeConfig: [
{
"op": "CRC-16 Checksum",
"args": []
}
]
},
{
name: "CRC-16: basic string",
input: BASIC_STRING,
expectedOutput: "0c70",
recipeConfig: [
{
"op": "CRC-16 Checksum",
"args": []
}
]
},
{
name: "CRC-16: UTF-8",
input: UTF8_STR,
expectedOutput: "dcf6",
recipeConfig: [
{
"op": "CRC-16 Checksum",
"args": []
}
]
},
{
name: "CRC-16: all bytes",
input: ALL_BYTES,
expectedOutput: "bad3",
recipeConfig: [
{
"op": "CRC-16 Checksum",
"args": []
}
]
},
{
name: "CRC-32: nothing",
input: "",
expectedOutput: "00000000",
recipeConfig: [
{
"op": "CRC-32 Checksum",
"args": []
}
]
},
{
name: "CRC-32: basic string",
input: BASIC_STRING,
expectedOutput: "bf4b739c",
recipeConfig: [
{
"op": "CRC-32 Checksum",
"args": []
}
]
},
{
name: "CRC-32: UTF-8",
input: UTF8_STR,
expectedOutput: "87553290",
recipeConfig: [
{
"op": "CRC-32 Checksum",
"args": []
}
]
},
{
name: "CRC-32: all bytes",
input: ALL_BYTES,
expectedOutput: "29058c73",
recipeConfig: [
{
"op": "CRC-32 Checksum",
"args": []
}
]
}
]);

View File

@@ -28,28 +28,6 @@ TestRegister.addTests([
args: ["From Leet Speak"]
}
]
},
{
name: "Convert to Leet Speak: basic text, keep case",
input: "HELLO",
expectedOutput: "H3LL0",
recipeConfig: [
{
op: "Convert Leet Speak",
args: ["To Leet Speak"]
}
]
},
{
name: "Convert from Leet Speak: basic leet, keep case",
input: "H3LL0",
expectedOutput: "HeLLo",
recipeConfig: [
{
op: "Convert Leet Speak",
args: ["From Leet Speak"]
}
]
}
]);

View File

@@ -1,41 +0,0 @@
/**
* YAML tests.
*
* @author ccarpo [ccarpo@gmx.net]
*
* @copyright Crown Copyright 2021
* @license Apache-2.0
*/
import TestRegister from "../../lib/TestRegister.mjs";
const EXAMPLE_YAML = `number: 3\nplain: string\nblock: |\n two\n lines`;
const EXAMPLE_JSON = `{ "number": 3, "plain": "string" }`;
TestRegister.addTests([
{
name: "YAML to JSON",
input: EXAMPLE_YAML,
expectedOutput: JSON.stringify({
"number": 3,
"plain": "string",
"block": "two\nlines\n"
}, null, 4),
recipeConfig: [
{
op: "YAML to JSON",
args: [],
}
],
},
{
name: "JSON to YAML",
input: EXAMPLE_JSON,
expectedOutput: `number: 3\nplain: string\n`,
recipeConfig: [
{
op: "JSON to YAML",
args: [],
}
],
},
]);

View File

@@ -1,135 +0,0 @@
/**
* SM2 Tests
*
* @author flakjacket95 [dflack95@gmail.com]
* @copyright Crown Copyright 2024
* @license Apache-2.0
*/
import TestRegister from "../../lib/TestRegister.mjs";
/* Plaintexts */
const SMALL_PLAIN = "I am a small plaintext";
const LARGE_PLAIN = "I am a larger plaintext, that will require the encryption KDF to generate a much larger key to properly encrypt me";
/* Test Key Parameters */
const PUBLIC_X = "f7d903cab7925066c31150a92b31e548e63f954f92d01eaa0271fb2a336baef8";
const PUBLIC_Y = "fb0c45e410ef7a6cdae724e6a78dbff52562e97ede009e762b667d9b14adea6c";
const PRIVATE_K = "e74a72505084c3269aa9b696d603e3e08c74c6740212c11a31e26cdfe08bdf6a";
const CURVE = "sm2p256v1";
/* Decryption Test Ciphertext*/
const CIPHERTEXT_1 = "9a31bc0adb4677cdc4141479e3949572a55c3e6fb52094721f741c2bd2e179aaa87be6263bc1be602e473be3d5de5dce97f8248948b3a7e15f9f67f64aef21575e0c05e6171870a10ff9ab778dbef24267ad90e1a9d47d68f757d57c4816612e9829f804025dea05a511cda39371c22a2828f976f72e";
const CIPHERTEXT_2 = "d3647d68568a2e7a4f8e843286be7bf2b4d80256697d19a73df306ae1a7e6d0364d942e23d2340606e7a2502a838b132f9242587b2ea7e4c207e87242eea8cae68f5ff4da2a95a7f6d350608ae5b6777e1d925bf9c560087af84aba7befba713130106ddb4082d803811bca3864594722f3198d58257fe4ba37f4aa540adf4cb0568bddd2d8140ad3030deea0a87e3198655cc4d22bfc3d73b1c4afec2ff15d68c8d1298d97132cace922ee8a4e41ca288a7e748b77ca94aa81dc283439923ae7939e00898e16fe5111fbe1d928d152b216a";
const CIPHERTEXT_3 = "5f340eeb4398fa8950ee3408d0e3fe34bf7728c9fdb060c94b916891b5c693610274160b52a7132a2bf16ad5cdb57d1e00da2f3ddbd55350729aa9c268b53e40c05ccce9912daa14406e8c132e389484e69757350be25351755dcc6c25c94b3c1a448b2cf8c2017582125eb6cf782055b199a875e966";
const CIPHERTEXT_4 = "0649bac46c3f9fd7fb3b2be4bff27414d634651efd02ca67d8c802bbc5468e77d035c39b581d6b56227f5d87c0b4efbea5032c0761139295ae194b9f1fce698f2f4b51d89fa5554171a1aad2e61fe9de89831aec472ecc5ab178ebf4d2230c1fb94fca03e536b87b9eba6db71ba9939260a08ffd230ca86cb45cf754854222364231bdb8b873791d63ad57a4b3fa5b6375388dc879373f5f1be9051bc5072a8afbec5b7b034e4907aa5bb4b6b1f50e725d09cb6a02e07ce20263005f6c9157ce05d3ea739d231d4f09396fb72aa680884d78";
TestRegister.addTests([
{
name: "SM2 Decrypt: Small Input; Format One",
input: CIPHERTEXT_1,
expectedOutput: SMALL_PLAIN,
recipeConfig: [
{
"op": "SM2 Decrypt",
"args": [PRIVATE_K, "C1C3C2", CURVE]
}
]
},
{
name: "SM2 Decrypt: Large Input; Format One",
input: CIPHERTEXT_2,
expectedOutput: LARGE_PLAIN,
recipeConfig: [
{
"op": "SM2 Decrypt",
"args": [PRIVATE_K, "C1C3C2", CURVE]
}
]
},
{
name: "SM2 Decrypt: Small Input; Format Two",
input: CIPHERTEXT_3,
expectedOutput: SMALL_PLAIN,
recipeConfig: [
{
"op": "SM2 Decrypt",
"args": [PRIVATE_K, "C1C2C3", CURVE]
}
]
},
{
name: "SM2 Decrypt: Large Input; Format Two",
input: CIPHERTEXT_4,
expectedOutput: LARGE_PLAIN,
recipeConfig: [
{
"op": "SM2 Decrypt",
"args": [PRIVATE_K, "C1C2C3", CURVE]
}
]
},
{
name: "SM2 Encrypt And Decrypt: Small Input; Format One",
input: SMALL_PLAIN,
expectedOutput: SMALL_PLAIN,
recipeConfig: [
{
"op": "SM2 Encrypt",
"args": [PUBLIC_X, PUBLIC_Y, "C1C3C2", CURVE],
},
{
"op": "SM2 Decrypt",
"args": [PRIVATE_K, "C1C3C2", CURVE]
}
]
},
{
name: "SM2 Encrypt And Decrypt: Large Input; Format One",
input: LARGE_PLAIN,
expectedOutput: LARGE_PLAIN,
recipeConfig: [
{
"op": "SM2 Encrypt",
"args": [PUBLIC_X, PUBLIC_Y, "C1C3C2", CURVE],
},
{
"op": "SM2 Decrypt",
"args": [PRIVATE_K, "C1C3C2", CURVE]
}
]
},
{
name: "SM2 Encrypt And Decrypt: Small Input; Format Two",
input: SMALL_PLAIN,
expectedOutput: SMALL_PLAIN,
recipeConfig: [
{
"op": "SM2 Encrypt",
"args": [PUBLIC_X, PUBLIC_Y, "C1C2C3", CURVE],
},
{
"op": "SM2 Decrypt",
"args": [PRIVATE_K, "C1C2C2", CURVE]
}
]
},
{
name: "SM2 Encrypt And Decrypt: Large Input; Format Two",
input: LARGE_PLAIN,
expectedOutput: LARGE_PLAIN,
recipeConfig: [
{
"op": "SM2 Encrypt",
"args": [PUBLIC_X, PUBLIC_Y, "C1C2C3", CURVE],
},
{
"op": "SM2 Decrypt",
"args": [PRIVATE_K, "C1C2C3", CURVE]
}
]
},
]);

88
vigenere.js Normal file
View File

@@ -0,0 +1,88 @@
function cleanText(text) {
const textNoSpaces = text.replace(/ /g, "");
if (/[^A-Za-z0-9]/.test(textNoSpaces)) {
throw new Error("Special characters detected. They must be removed.");
}
return textNoSpaces;
}
function encrypt(message, key) {
message = message.toLowerCase();
key = key.toLowerCase();
const combinedAlphabet = "abcdefghijklmnopqrstuvwxyz0123456789";
const n = combinedAlphabet.length;
const encrypted = [];
let keyIndex = 0;
try {
for (const char of message) {
if (combinedAlphabet.includes(char)) {
const mIndex = combinedAlphabet.indexOf(char);
const keyChar = key[keyIndex % key.length];
const shift = combinedAlphabet.indexOf(keyChar);
const newIndex = (mIndex + shift) % n;
encrypted.push(combinedAlphabet[newIndex]);
keyIndex++;
}
}
return encrypted.join("");
} catch (e) {
throw new Error("Encryption error: " + e.message);
}
}
function decrypt(cipherText, key) {
cipherText = cipherText.toLowerCase();
key = key.toLowerCase();
const combinedAlphabet = "abcdefghijklmnopqrstuvwxyz0123456789";
const n = combinedAlphabet.length;
const decrypted = [];
let keyIndex = 0;
try {
for (const char of cipherText) {
if (combinedAlphabet.includes(char)) {
const cIndex = combinedAlphabet.indexOf(char);
const keyChar = key[keyIndex % key.length];
const shift = combinedAlphabet.indexOf(keyChar);
const originalIndex = (cIndex - shift + n) % n;
decrypted.push(combinedAlphabet[originalIndex]);
keyIndex++;
}
}
return decrypted.join("");
} catch (e) {
throw new Error("Decryption error: " + e.message);
}
}
function main() {
try {
const rawMessage = prompt("Enter the message: ");
const rawKey = prompt("Enter the key: ");
try {
const cleanedMessage = cleanText(rawMessage);
const cleanedKey = cleanText(rawKey);
if (!cleanedMessage) {
throw new Error("Message is empty after cleaning!");
}
if (!cleanedKey) {
throw new Error("Key is empty after cleaning!");
}
const encryptedMsg = encrypt(cleanedMessage, cleanedKey);
console.log("\nEncrypted Message:");
console.log(encryptedMsg);
const decryptedMsg = decrypt(encryptedMsg, cleanedKey);
console.log("\nDecrypted Message:");
console.log(decryptedMsg);
} catch (ve) {
console.log("Input error:", ve.message);
return;
}
} catch (e) {
console.log("An error occurred:", e.message);
}
}
main();