From 6272d0e8099065594e469bc6d7bc6d1687f675c2 Mon Sep 17 00:00:00 2001 From: MikeCAT Date: Wed, 19 Feb 2025 18:03:31 +0000 Subject: [PATCH] Use byteArray for I/O of cipher operations --- src/core/operations/AESDecrypt.mjs | 12 +++++++----- src/core/operations/AESEncrypt.mjs | 21 +++++++++++++-------- src/core/operations/AESKeyUnwrap.mjs | 15 +++++++-------- src/core/operations/AESKeyWrap.mjs | 15 +++++++-------- src/core/operations/BlowfishDecrypt.mjs | 12 +++++++----- src/core/operations/BlowfishEncrypt.mjs | 16 +++++++--------- src/core/operations/DESDecrypt.mjs | 12 +++++++----- src/core/operations/DESEncrypt.mjs | 12 +++++++----- src/core/operations/RC2Decrypt.mjs | 12 +++++++----- src/core/operations/RC2Encrypt.mjs | 12 +++++++----- src/core/operations/Rabbit.mjs | 22 ++++++++++++---------- src/core/operations/TripleDESDecrypt.mjs | 12 +++++++----- src/core/operations/TripleDESEncrypt.mjs | 12 +++++++----- tests/node/tests/nodeApi.mjs | 4 ++-- 14 files changed, 104 insertions(+), 85 deletions(-) diff --git a/src/core/operations/AESDecrypt.mjs b/src/core/operations/AESDecrypt.mjs index e24a5119..0a474f01 100644 --- a/src/core/operations/AESDecrypt.mjs +++ b/src/core/operations/AESDecrypt.mjs @@ -24,8 +24,8 @@ class AESDecrypt extends Operation { this.module = "Ciphers"; this.description = "Advanced Encryption Standard (AES) is a U.S. Federal Information Processing Standard (FIPS). It was selected after a 5-year process where 15 competing designs were evaluated.

Key: The following algorithms will be used based on the size of the key:

IV: The Initialization Vector should be 16 bytes long. If not entered, it will default to 16 null bytes.

Padding: In CBC and ECB mode, PKCS#7 padding will be used as a default.

GCM Tag: This field is ignored unless 'GCM' mode is used."; this.infoURL = "https://wikipedia.org/wiki/Advanced_Encryption_Standard"; - this.inputType = "string"; - this.outputType = "string"; + this.inputType = "byteArray"; + this.outputType = "byteArray"; this.args = [ { "name": "Key", @@ -103,9 +103,9 @@ class AESDecrypt extends Operation { } /** - * @param {string} input + * @param {byteArray} input * @param {Object[]} args - * @returns {string} + * @returns {byteArray} * * @throws {OperationError} if cannot decrypt input or invalid key length */ @@ -128,6 +128,7 @@ The following algorithms will be used based on the size of the key: 32 bytes = AES-256`); } + input = input.map((c) => String.fromCharCode(c)).join(""); input = Utils.convertToByteString(input, inputType); const decipher = forge.cipher.createDecipher("AES-" + mode, key); @@ -148,7 +149,8 @@ The following algorithms will be used based on the size of the key: const result = decipher.finish(); if (result) { - return outputType === "Hex" ? decipher.output.toHex() : decipher.output.getBytes(); + const output = outputType === "Hex" ? decipher.output.toHex() : decipher.output.getBytes(); + return Array.from(output).map((c) => c.charCodeAt(0)); } else { throw new OperationError("Unable to decrypt input with these parameters."); } diff --git a/src/core/operations/AESEncrypt.mjs b/src/core/operations/AESEncrypt.mjs index 7b52ff03..9b9b32a5 100644 --- a/src/core/operations/AESEncrypt.mjs +++ b/src/core/operations/AESEncrypt.mjs @@ -24,8 +24,8 @@ class AESEncrypt extends Operation { this.module = "Ciphers"; this.description = "Advanced Encryption Standard (AES) is a U.S. Federal Information Processing Standard (FIPS). It was selected after a 5-year process where 15 competing designs were evaluated.

Key: The following algorithms will be used based on the size of the key:You can generate a password-based key using one of the KDF operations.

IV: The Initialization Vector should be 16 bytes long. If not entered, it will default to 16 null bytes.

Padding: In CBC and ECB mode, PKCS#7 padding will be used."; this.infoURL = "https://wikipedia.org/wiki/Advanced_Encryption_Standard"; - this.inputType = "string"; - this.outputType = "string"; + this.inputType = "byteArray"; + this.outputType = "byteArray"; this.args = [ { "name": "Key", @@ -89,9 +89,9 @@ class AESEncrypt extends Operation { } /** - * @param {string} input + * @param {byteArray} input * @param {Object[]} args - * @returns {string} + * @returns {byteArray} * * @throws {OperationError} if invalid key length */ @@ -112,6 +112,7 @@ The following algorithms will be used based on the size of the key: 32 bytes = AES-256`); } + input = input.map((c) => String.fromCharCode(c)).join(""); input = Utils.convertToByteString(input, inputType); const cipher = forge.cipher.createCipher("AES-" + mode, key); @@ -122,19 +123,23 @@ The following algorithms will be used based on the size of the key: cipher.update(forge.util.createBuffer(input)); cipher.finish(); + let output; if (outputType === "Hex") { if (mode === "GCM") { - return cipher.output.toHex() + "\n\n" + + output = cipher.output.toHex() + "\n\n" + "Tag: " + cipher.mode.tag.toHex(); + } else { + output = cipher.output.toHex(); } - return cipher.output.toHex(); } else { if (mode === "GCM") { - return cipher.output.getBytes() + "\n\n" + + output = cipher.output.getBytes() + "\n\n" + "Tag: " + cipher.mode.tag.getBytes(); + } else { + output = cipher.output.getBytes(); } - return cipher.output.getBytes(); } + return Array.from(output).map((c) => c.charCodeAt(0)); } } diff --git a/src/core/operations/AESKeyUnwrap.mjs b/src/core/operations/AESKeyUnwrap.mjs index 1558847a..953a87f6 100644 --- a/src/core/operations/AESKeyUnwrap.mjs +++ b/src/core/operations/AESKeyUnwrap.mjs @@ -25,8 +25,8 @@ class AESKeyUnwrap extends Operation { this.module = "Ciphers"; this.description = "Decryptor for a key wrapping algorithm defined in RFC3394, which is used to protect keys in untrusted storage or communications, using AES.

This algorithm uses an AES key (KEK: key-encryption key) and a 64-bit IV to decrypt 64-bit blocks."; this.infoURL = "https://wikipedia.org/wiki/Key_wrap"; - this.inputType = "string"; - this.outputType = "string"; + this.inputType = "byteArray"; + this.outputType = "byteArray"; this.args = [ { "name": "Key (KEK)", @@ -54,9 +54,9 @@ class AESKeyUnwrap extends Operation { } /** - * @param {string} input + * @param {byteArray} input * @param {Object[]} args - * @returns {string} + * @returns {byteArray} */ run(input, args) { const kek = Utils.convertToByteString(args[0].string, args[0].option), @@ -70,6 +70,7 @@ class AESKeyUnwrap extends Operation { if (iv.length !== 8) { throw new OperationError("IV must be 8 bytes (currently " + iv.length + " bytes)"); } + input = input.map((c) => String.fromCharCode(c)).join(""); const inputData = Utils.convertToByteString(input, inputType); if (inputData.length % 8 !== 0 || inputData.length < 24) { throw new OperationError("input must be 8n (n>=3) bytes (currently " + inputData.length + " bytes)"); @@ -117,10 +118,8 @@ class AESKeyUnwrap extends Operation { } const P = R.join(""); - if (outputType === "Hex") { - return toHexFast(Utils.strToArrayBuffer(P)); - } - return P; + const output = outputType === "Hex" ? toHexFast(Utils.strToArrayBuffer(P)) : P; + return Array.from(output).map((c) => c.charCodeAt(0)); } } diff --git a/src/core/operations/AESKeyWrap.mjs b/src/core/operations/AESKeyWrap.mjs index 38867156..42e9d3f3 100644 --- a/src/core/operations/AESKeyWrap.mjs +++ b/src/core/operations/AESKeyWrap.mjs @@ -25,8 +25,8 @@ class AESKeyWrap extends Operation { this.module = "Ciphers"; this.description = "A key wrapping algorithm defined in RFC3394, which is used to protect keys in untrusted storage or communications, using AES.

This algorithm uses an AES key (KEK: key-encryption key) and a 64-bit IV to encrypt 64-bit blocks."; this.infoURL = "https://wikipedia.org/wiki/Key_wrap"; - this.inputType = "string"; - this.outputType = "string"; + this.inputType = "byteArray"; + this.outputType = "byteArray"; this.args = [ { "name": "Key (KEK)", @@ -54,9 +54,9 @@ class AESKeyWrap extends Operation { } /** - * @param {string} input + * @param {byteArray} input * @param {Object[]} args - * @returns {string} + * @returns {byteArray} */ run(input, args) { const kek = Utils.convertToByteString(args[0].string, args[0].option), @@ -70,6 +70,7 @@ class AESKeyWrap extends Operation { if (iv.length !== 8) { throw new OperationError("IV must be 8 bytes (currently " + iv.length + " bytes)"); } + input = input.map((c) => String.fromCharCode(c)).join(""); const inputData = Utils.convertToByteString(input, inputType); if (inputData.length % 8 !== 0 || inputData.length < 16) { throw new OperationError("input must be 8n (n>=2) bytes (currently " + inputData.length + " bytes)"); @@ -104,10 +105,8 @@ class AESKeyWrap extends Operation { } const C = A + R.join(""); - if (outputType === "Hex") { - return toHexFast(Utils.strToArrayBuffer(C)); - } - return C; + const output = outputType === "Hex" ? toHexFast(Utils.strToArrayBuffer(C)) : C; + return Array.from(output).map((c) => c.charCodeAt(0)); } } diff --git a/src/core/operations/BlowfishDecrypt.mjs b/src/core/operations/BlowfishDecrypt.mjs index afb26007..6a8e876c 100644 --- a/src/core/operations/BlowfishDecrypt.mjs +++ b/src/core/operations/BlowfishDecrypt.mjs @@ -25,8 +25,8 @@ class BlowfishDecrypt extends Operation { this.module = "Ciphers"; this.description = "Blowfish is a symmetric-key block cipher designed in 1993 by Bruce Schneier and included in a large number of cipher suites and encryption products. AES now receives more attention.

IV: The Initialization Vector should be 8 bytes long. If not entered, it will default to 8 null bytes."; this.infoURL = "https://wikipedia.org/wiki/Blowfish_(cipher)"; - this.inputType = "string"; - this.outputType = "string"; + this.inputType = "byteArray"; + this.outputType = "byteArray"; this.args = [ { "name": "Key", @@ -59,9 +59,9 @@ class BlowfishDecrypt extends Operation { } /** - * @param {string} input + * @param {byteArray} input * @param {Object[]} args - * @returns {string} + * @returns {byteArray} */ run(input, args) { const key = Utils.convertToByteString(args[0].string, args[0].option), @@ -80,6 +80,7 @@ Blowfish's key length needs to be between 4 and 56 bytes (32-448 bits).`); throw new OperationError(`Invalid IV length: ${iv.length} bytes. Expected 8 bytes.`); } + input = input.map((c) => String.fromCharCode(c)).join(""); input = Utils.convertToByteString(input, inputType); const decipher = Blowfish.createDecipher(key, mode); @@ -88,7 +89,8 @@ Blowfish's key length needs to be between 4 and 56 bytes (32-448 bits).`); const result = decipher.finish(); if (result) { - return outputType === "Hex" ? decipher.output.toHex() : decipher.output.getBytes(); + const output = outputType === "Hex" ? decipher.output.toHex() : decipher.output.getBytes(); + return Array.from(output).map((c) => c.charCodeAt(0)); } else { throw new OperationError("Unable to decrypt input with these parameters."); } diff --git a/src/core/operations/BlowfishEncrypt.mjs b/src/core/operations/BlowfishEncrypt.mjs index 1d5dcf02..2f6cda73 100644 --- a/src/core/operations/BlowfishEncrypt.mjs +++ b/src/core/operations/BlowfishEncrypt.mjs @@ -25,8 +25,8 @@ class BlowfishEncrypt extends Operation { this.module = "Ciphers"; this.description = "Blowfish is a symmetric-key block cipher designed in 1993 by Bruce Schneier and included in a large number of cipher suites and encryption products. AES now receives more attention.

IV: The Initialization Vector should be 8 bytes long. If not entered, it will default to 8 null bytes."; this.infoURL = "https://wikipedia.org/wiki/Blowfish_(cipher)"; - this.inputType = "string"; - this.outputType = "string"; + this.inputType = "byteArray"; + this.outputType = "byteArray"; this.args = [ { "name": "Key", @@ -59,9 +59,9 @@ class BlowfishEncrypt extends Operation { } /** - * @param {string} input + * @param {byteArray} input * @param {Object[]} args - * @returns {string} + * @returns {byteArray} */ run(input, args) { const key = Utils.convertToByteString(args[0].string, args[0].option), @@ -80,6 +80,7 @@ Blowfish's key length needs to be between 4 and 56 bytes (32-448 bits).`); throw new OperationError(`Invalid IV length: ${iv.length} bytes. Expected 8 bytes.`); } + input = input.map((c) => String.fromCharCode(c)).join(""); input = Utils.convertToByteString(input, inputType); const cipher = Blowfish.createCipher(key, mode); @@ -87,11 +88,8 @@ Blowfish's key length needs to be between 4 and 56 bytes (32-448 bits).`); cipher.update(forge.util.createBuffer(input)); cipher.finish(); - if (outputType === "Hex") { - return cipher.output.toHex(); - } else { - return cipher.output.getBytes(); - } + const output = outputType === "Hex" ? cipher.output.toHex() : cipher.output.getBytes(); + return Array.from(output).map((c) => c.charCodeAt(0)); } } diff --git a/src/core/operations/DESDecrypt.mjs b/src/core/operations/DESDecrypt.mjs index 4b1ab40e..42391b53 100644 --- a/src/core/operations/DESDecrypt.mjs +++ b/src/core/operations/DESDecrypt.mjs @@ -24,8 +24,8 @@ class DESDecrypt extends Operation { this.module = "Ciphers"; this.description = "DES is a previously dominant algorithm for encryption, and was published as an official U.S. Federal Information Processing Standard (FIPS). It is now considered to be insecure due to its small key size.

Key: DES uses a key length of 8 bytes (64 bits).

IV: The Initialization Vector should be 8 bytes long. If not entered, it will default to 8 null bytes.

Padding: In CBC and ECB mode, PKCS#7 padding will be used as a default."; this.infoURL = "https://wikipedia.org/wiki/Data_Encryption_Standard"; - this.inputType = "string"; - this.outputType = "string"; + this.inputType = "byteArray"; + this.outputType = "byteArray"; this.args = [ { "name": "Key", @@ -58,9 +58,9 @@ class DESDecrypt extends Operation { } /** - * @param {string} input + * @param {byteArray} input * @param {Object[]} args - * @returns {string} + * @returns {byteArray} */ run(input, args) { const key = Utils.convertToByteString(args[0].string, args[0].option), @@ -81,6 +81,7 @@ DES uses an IV length of 8 bytes (64 bits). Make sure you have specified the type correctly (e.g. Hex vs UTF8).`); } + input = input.map((c) => String.fromCharCode(c)).join(""); input = Utils.convertToByteString(input, inputType); const decipher = forge.cipher.createDecipher("DES-" + mode, key); @@ -97,7 +98,8 @@ Make sure you have specified the type correctly (e.g. Hex vs UTF8).`); const result = decipher.finish(); if (result) { - return outputType === "Hex" ? decipher.output.toHex() : decipher.output.getBytes(); + const output = outputType === "Hex" ? decipher.output.toHex() : decipher.output.getBytes(); + return Array.from(output).map((c) => c.charCodeAt(0)); } else { throw new OperationError("Unable to decrypt input with these parameters."); } diff --git a/src/core/operations/DESEncrypt.mjs b/src/core/operations/DESEncrypt.mjs index 28d6202a..45606fdd 100644 --- a/src/core/operations/DESEncrypt.mjs +++ b/src/core/operations/DESEncrypt.mjs @@ -24,8 +24,8 @@ class DESEncrypt extends Operation { this.module = "Ciphers"; this.description = "DES is a previously dominant algorithm for encryption, and was published as an official U.S. Federal Information Processing Standard (FIPS). It is now considered to be insecure due to its small key size.

Key: DES uses a key length of 8 bytes (64 bits).

You can generate a password-based key using one of the KDF operations.

IV: The Initialization Vector should be 8 bytes long. If not entered, it will default to 8 null bytes.

Padding: In CBC and ECB mode, PKCS#7 padding will be used."; this.infoURL = "https://wikipedia.org/wiki/Data_Encryption_Standard"; - this.inputType = "string"; - this.outputType = "string"; + this.inputType = "byteArray"; + this.outputType = "byteArray"; this.args = [ { "name": "Key", @@ -58,9 +58,9 @@ class DESEncrypt extends Operation { } /** - * @param {string} input + * @param {byteArray} input * @param {Object[]} args - * @returns {string} + * @returns {byteArray} */ run(input, args) { const key = Utils.convertToByteString(args[0].string, args[0].option), @@ -79,6 +79,7 @@ DES uses an IV length of 8 bytes (64 bits). Make sure you have specified the type correctly (e.g. Hex vs UTF8).`); } + input = input.map((c) => String.fromCharCode(c)).join(""); input = Utils.convertToByteString(input, inputType); const cipher = forge.cipher.createCipher("DES-" + mode, key); @@ -86,7 +87,8 @@ Make sure you have specified the type correctly (e.g. Hex vs UTF8).`); cipher.update(forge.util.createBuffer(input)); cipher.finish(); - return outputType === "Hex" ? cipher.output.toHex() : cipher.output.getBytes(); + const output = outputType === "Hex" ? cipher.output.toHex() : cipher.output.getBytes(); + return Array.from(output).map((c) => c.charCodeAt(0)); } } diff --git a/src/core/operations/RC2Decrypt.mjs b/src/core/operations/RC2Decrypt.mjs index c9ff1bf4..addcd2d1 100644 --- a/src/core/operations/RC2Decrypt.mjs +++ b/src/core/operations/RC2Decrypt.mjs @@ -23,8 +23,8 @@ class RC2Decrypt extends Operation { this.module = "Ciphers"; this.description = "RC2 (also known as ARC2) is a symmetric-key block cipher designed by Ron Rivest in 1987. 'RC' stands for 'Rivest Cipher'.

Key: RC2 uses a variable size key.

IV: To run the cipher in CBC mode, the Initialization Vector should be 8 bytes long. If the IV is left blank, the cipher will run in ECB mode.

Padding: In both CBC and ECB mode, PKCS#7 padding will be used."; this.infoURL = "https://wikipedia.org/wiki/RC2"; - this.inputType = "string"; - this.outputType = "string"; + this.inputType = "byteArray"; + this.outputType = "byteArray"; this.args = [ { "name": "Key", @@ -52,9 +52,9 @@ class RC2Decrypt extends Operation { } /** - * @param {string} input + * @param {byteArray} input * @param {Object[]} args - * @returns {string} + * @returns {byteArray} */ run(input, args) { const key = Utils.convertToByteString(args[0].string, args[0].option), @@ -62,13 +62,15 @@ class RC2Decrypt extends Operation { [,, inputType, outputType] = args, decipher = forge.rc2.createDecryptionCipher(key); + input = input.map((c) => String.fromCharCode(c)).join(""); input = Utils.convertToByteString(input, inputType); decipher.start(iv || null); decipher.update(forge.util.createBuffer(input)); decipher.finish(); - return outputType === "Hex" ? decipher.output.toHex() : decipher.output.getBytes(); + const output = outputType === "Hex" ? decipher.output.toHex() : decipher.output.getBytes(); + return Array.from(output).map((c) => c.charCodeAt(0)); } } diff --git a/src/core/operations/RC2Encrypt.mjs b/src/core/operations/RC2Encrypt.mjs index 88dae5b1..25403001 100644 --- a/src/core/operations/RC2Encrypt.mjs +++ b/src/core/operations/RC2Encrypt.mjs @@ -24,8 +24,8 @@ class RC2Encrypt extends Operation { this.module = "Ciphers"; this.description = "RC2 (also known as ARC2) is a symmetric-key block cipher designed by Ron Rivest in 1987. 'RC' stands for 'Rivest Cipher'.

Key: RC2 uses a variable size key.

You can generate a password-based key using one of the KDF operations.

IV: To run the cipher in CBC mode, the Initialization Vector should be 8 bytes long. If the IV is left blank, the cipher will run in ECB mode.

Padding: In both CBC and ECB mode, PKCS#7 padding will be used."; this.infoURL = "https://wikipedia.org/wiki/RC2"; - this.inputType = "string"; - this.outputType = "string"; + this.inputType = "byteArray"; + this.outputType = "byteArray"; this.args = [ { "name": "Key", @@ -53,9 +53,9 @@ class RC2Encrypt extends Operation { } /** - * @param {string} input + * @param {byteArray} input * @param {Object[]} args - * @returns {string} + * @returns {byteArray} */ run(input, args) { const key = Utils.convertToByteString(args[0].string, args[0].option), @@ -63,13 +63,15 @@ class RC2Encrypt extends Operation { [,, inputType, outputType] = args, cipher = forge.rc2.createEncryptionCipher(key); + input = input.map((c) => String.fromCharCode(c)).join(""); input = Utils.convertToByteString(input, inputType); cipher.start(iv || null); cipher.update(forge.util.createBuffer(input)); cipher.finish(); - return outputType === "Hex" ? cipher.output.toHex() : cipher.output.getBytes(); + const output = outputType === "Hex" ? cipher.output.toHex() : cipher.output.getBytes(); + return Array.from(output).map((c) => c.charCodeAt(0)); } } diff --git a/src/core/operations/Rabbit.mjs b/src/core/operations/Rabbit.mjs index 91ff24a3..00f52e8e 100644 --- a/src/core/operations/Rabbit.mjs +++ b/src/core/operations/Rabbit.mjs @@ -24,8 +24,8 @@ class Rabbit extends Operation { this.module = "Ciphers"; this.description = "Rabbit is a high-speed stream cipher introduced in 2003 and defined in RFC 4503.

The cipher uses a 128-bit key and an optional 64-bit initialization vector (IV).

big-endian: based on RFC4503 and RFC3447
little-endian: compatible with Crypto++"; this.infoURL = "https://wikipedia.org/wiki/Rabbit_(cipher)"; - this.inputType = "string"; - this.outputType = "string"; + this.inputType = "byteArray"; + this.outputType = "byteArray"; this.args = [ { "name": "Key", @@ -58,9 +58,9 @@ class Rabbit extends Operation { } /** - * @param {string} input + * @param {byteArray} input * @param {Object[]} args - * @returns {string} + * @returns {byteArray} */ run(input, args) { const key = Utils.convertToByteArray(args[0].string, args[0].option), @@ -214,12 +214,14 @@ class Rabbit extends Operation { } }; - const data = Utils.convertToByteString(input, inputType); + input = input.map((c) => String.fromCharCode(c)).join(""); + const dataString = Utils.convertToByteString(input, inputType); + const data = Array.from(dataString).map((c) => c.charCodeAt(0)); const result = new Uint8Array(data.length); for (let i = 0; i <= data.length - 16; i += 16) { extract(); for (let j = 0; j < 16; j++) { - result[i + j] = data.charCodeAt(i + j) ^ S[j]; + result[i + j] = data[i + j] ^ S[j]; } } if (data.length % 16 !== 0) { @@ -228,18 +230,18 @@ class Rabbit extends Operation { extract(); if (littleEndian) { for (let j = 0; j < length; j++) { - result[offset + j] = data.charCodeAt(offset + j) ^ S[j]; + result[offset + j] = data[offset + j] ^ S[j]; } } else { for (let j = 0; j < length; j++) { - result[offset + j] = data.charCodeAt(offset + j) ^ S[16 - length + j]; + result[offset + j] = data[offset + j] ^ S[16 - length + j]; } } } if (outputType === "Hex") { - return toHexFast(result); + return Array.from(toHexFast(result)).map((c) => c.charCodeAt(0)); } - return Utils.byteArrayToChars(result); + return Array.from(result); } } diff --git a/src/core/operations/TripleDESDecrypt.mjs b/src/core/operations/TripleDESDecrypt.mjs index 927600de..a1f37a11 100644 --- a/src/core/operations/TripleDESDecrypt.mjs +++ b/src/core/operations/TripleDESDecrypt.mjs @@ -24,8 +24,8 @@ class TripleDESDecrypt extends Operation { this.module = "Ciphers"; this.description = "Triple DES applies DES three times to each block to increase key size.

Key: Triple DES uses a key length of 24 bytes (192 bits).

IV: The Initialization Vector should be 8 bytes long. If not entered, it will default to 8 null bytes.

Padding: In CBC and ECB mode, PKCS#7 padding will be used as a default."; this.infoURL = "https://wikipedia.org/wiki/Triple_DES"; - this.inputType = "string"; - this.outputType = "string"; + this.inputType = "byteArray"; + this.outputType = "byteArray"; this.args = [ { "name": "Key", @@ -58,9 +58,9 @@ class TripleDESDecrypt extends Operation { } /** - * @param {string} input + * @param {byteArray} input * @param {Object[]} args - * @returns {string} + * @returns {byteArray} */ run(input, args) { const key = Utils.convertToByteString(args[0].string, args[0].option), @@ -82,6 +82,7 @@ Triple DES uses an IV length of 8 bytes (64 bits). Make sure you have specified the type correctly (e.g. Hex vs UTF8).`); } + input = input.map((c) => String.fromCharCode(c)).join(""); input = Utils.convertToByteString(input, inputType); const decipher = forge.cipher.createDecipher("3DES-" + mode, @@ -99,7 +100,8 @@ Make sure you have specified the type correctly (e.g. Hex vs UTF8).`); const result = decipher.finish(); if (result) { - return outputType === "Hex" ? decipher.output.toHex() : decipher.output.getBytes(); + const output = outputType === "Hex" ? decipher.output.toHex() : decipher.output.getBytes(); + return Array.from(output).map((c) => c.charCodeAt(0)); } else { throw new OperationError("Unable to decrypt input with these parameters."); } diff --git a/src/core/operations/TripleDESEncrypt.mjs b/src/core/operations/TripleDESEncrypt.mjs index b4a218d0..d532de3c 100644 --- a/src/core/operations/TripleDESEncrypt.mjs +++ b/src/core/operations/TripleDESEncrypt.mjs @@ -24,8 +24,8 @@ class TripleDESEncrypt extends Operation { this.module = "Ciphers"; this.description = "Triple DES applies DES three times to each block to increase key size.

Key: Triple DES uses a key length of 24 bytes (192 bits).

You can generate a password-based key using one of the KDF operations.

IV: The Initialization Vector should be 8 bytes long. If not entered, it will default to 8 null bytes.

Padding: In CBC and ECB mode, PKCS#7 padding will be used."; this.infoURL = "https://wikipedia.org/wiki/Triple_DES"; - this.inputType = "string"; - this.outputType = "string"; + this.inputType = "byteArray"; + this.outputType = "byteArray"; this.args = [ { "name": "Key", @@ -58,9 +58,9 @@ class TripleDESEncrypt extends Operation { } /** - * @param {string} input + * @param {byteArray} input * @param {Object[]} args - * @returns {string} + * @returns {byteArray} */ run(input, args) { const key = Utils.convertToByteString(args[0].string, args[0].option), @@ -81,6 +81,7 @@ Triple DES uses an IV length of 8 bytes (64 bits). Make sure you have specified the type correctly (e.g. Hex vs UTF8).`); } + input = input.map((c) => String.fromCharCode(c)).join(""); input = Utils.convertToByteString(input, inputType); const cipher = forge.cipher.createCipher("3DES-" + mode, @@ -89,7 +90,8 @@ Make sure you have specified the type correctly (e.g. Hex vs UTF8).`); cipher.update(forge.util.createBuffer(input)); cipher.finish(); - return outputType === "Hex" ? cipher.output.toHex() : cipher.output.getBytes(); + const output = outputType === "Hex" ? cipher.output.toHex() : cipher.output.getBytes(); + return Array.from(output).map((c) => c.charCodeAt(0)); } } diff --git a/tests/node/tests/nodeApi.mjs b/tests/node/tests/nodeApi.mjs index 29a47ffc..82a4ce63 100644 --- a/tests/node/tests/nodeApi.mjs +++ b/tests/node/tests/nodeApi.mjs @@ -117,8 +117,8 @@ TestRegister.addApiTests([ const result = chef.help("tripleDESDecrypt"); assert.strictEqual(result[0].name, "Triple DES Decrypt"); assert.strictEqual(result[0].module, "Ciphers"); - assert.strictEqual(result[0].inputType, "string"); - assert.strictEqual(result[0].outputType, "string"); + assert.strictEqual(result[0].inputType, "byteArray"); + assert.strictEqual(result[0].outputType, "byteArray"); assert.strictEqual(result[0].description, "Triple DES applies DES three times to each block to increase key size.

Key: Triple DES uses a key length of 24 bytes (192 bits).

IV: The Initialization Vector should be 8 bytes long. If not entered, it will default to 8 null bytes.

Padding: In CBC and ECB mode, PKCS#7 padding will be used as a default."); assert.strictEqual(result[0].args.length, 5); }),