Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use byteArray for I/O of cipher operations #1983

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 7 additions & 5 deletions src/core/operations/AESDecrypt.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -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.<br><br><b>Key:</b> The following algorithms will be used based on the size of the key:<ul><li>16 bytes = AES-128</li><li>24 bytes = AES-192</li><li>32 bytes = AES-256</li></ul><br><br><b>IV:</b> The Initialization Vector should be 16 bytes long. If not entered, it will default to 16 null bytes.<br><br><b>Padding:</b> In CBC and ECB mode, PKCS#7 padding will be used as a default.<br><br><b>GCM Tag:</b> 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",
Expand Down Expand Up @@ -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
*/
Expand All @@ -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);
Expand All @@ -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.");
}
Expand Down
21 changes: 13 additions & 8 deletions src/core/operations/AESEncrypt.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -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.<br><br><b>Key:</b> The following algorithms will be used based on the size of the key:<ul><li>16 bytes = AES-128</li><li>24 bytes = AES-192</li><li>32 bytes = AES-256</li></ul>You can generate a password-based key using one of the KDF operations.<br><br><b>IV:</b> The Initialization Vector should be 16 bytes long. If not entered, it will default to 16 null bytes.<br><br><b>Padding:</b> 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",
Expand Down Expand Up @@ -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
*/
Expand All @@ -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);
Expand All @@ -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));
}

}
Expand Down
15 changes: 7 additions & 8 deletions src/core/operations/AESKeyUnwrap.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -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.<br><br>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)",
Expand Down Expand Up @@ -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),
Expand All @@ -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)");
Expand Down Expand Up @@ -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));
}

}
Expand Down
15 changes: 7 additions & 8 deletions src/core/operations/AESKeyWrap.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -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.<br><br>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)",
Expand Down Expand Up @@ -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),
Expand All @@ -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)");
Expand Down Expand Up @@ -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));
}

}
Expand Down
12 changes: 7 additions & 5 deletions src/core/operations/BlowfishDecrypt.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -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.<br><br><b>IV:</b> 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",
Expand Down Expand Up @@ -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),
Expand All @@ -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);
Expand All @@ -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.");
}
Expand Down
16 changes: 7 additions & 9 deletions src/core/operations/BlowfishEncrypt.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -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.<br><br><b>IV:</b> 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",
Expand Down Expand Up @@ -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),
Expand All @@ -80,18 +80,16 @@ 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);
cipher.start({iv: iv});
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));
}

}
Expand Down
12 changes: 7 additions & 5 deletions src/core/operations/DESDecrypt.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -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.<br><br><b>Key:</b> DES uses a key length of 8 bytes (64 bits).<br><br><b>IV:</b> The Initialization Vector should be 8 bytes long. If not entered, it will default to 8 null bytes.<br><br><b>Padding:</b> 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",
Expand Down Expand Up @@ -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),
Expand All @@ -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);
Expand All @@ -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.");
}
Expand Down
12 changes: 7 additions & 5 deletions src/core/operations/DESEncrypt.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -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.<br><br><b>Key:</b> DES uses a key length of 8 bytes (64 bits).<br><br>You can generate a password-based key using one of the KDF operations.<br><br><b>IV:</b> The Initialization Vector should be 8 bytes long. If not entered, it will default to 8 null bytes.<br><br><b>Padding:</b> 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",
Expand Down Expand Up @@ -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),
Expand All @@ -79,14 +79,16 @@ 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);
cipher.start({iv: iv});
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));
}

}
Expand Down
12 changes: 7 additions & 5 deletions src/core/operations/RC2Decrypt.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -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'.<br><br><b>Key:</b> RC2 uses a variable size key.<br><br><b>IV:</b> 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.<br><br><b>Padding:</b> 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",
Expand Down Expand Up @@ -52,23 +52,25 @@ 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),
iv = Utils.convertToByteString(args[1].string, args[1].option),
[,, 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));
}

}
Expand Down
Loading
Loading