From f81ca3ba605687ccb1b2b76d700a03f7dc4d370f Mon Sep 17 00:00:00 2001 From: GCHQ 77703 Date: Thu, 30 Aug 2018 22:38:01 +0100 Subject: [PATCH 01/10] Implement RSA generation and signing of messages --- src/core/config/Categories.json | 2 + src/core/operations/GenerateRSAKeyPair.mjs | 82 ++++++++++++++++++++++ src/core/operations/RSASign.mjs | 60 ++++++++++++++++ 3 files changed, 144 insertions(+) create mode 100644 src/core/operations/GenerateRSAKeyPair.mjs create mode 100644 src/core/operations/RSASign.mjs diff --git a/src/core/config/Categories.json b/src/core/config/Categories.json index ab3bc4864..68e17294d 100755 --- a/src/core/config/Categories.json +++ b/src/core/config/Categories.json @@ -89,6 +89,8 @@ "Derive EVP key", "Bcrypt", "Scrypt", + "Generate RSA Key Pair", + "RSA Sign", "Pseudo-Random Number Generator" ] }, diff --git a/src/core/operations/GenerateRSAKeyPair.mjs b/src/core/operations/GenerateRSAKeyPair.mjs new file mode 100644 index 000000000..9d7a88d84 --- /dev/null +++ b/src/core/operations/GenerateRSAKeyPair.mjs @@ -0,0 +1,82 @@ +/** + * @author gchq77703 [] + * @copyright Crown Copyright 2018 + ` * @license Apache-2.0 + */ + +import Operation from "../Operation"; +import forge from "node-forge/dist/forge.min.js"; + +/** + * Generate RSA Key Pair operation + */ +class GenerateRSAKeyPair extends Operation { + + /** + * GenerateRSAKeyPair constructor + */ + constructor() { + super(); + + this.name = "Generate RSA Key Pair"; + this.module = "Ciphers"; + this.description = "Generate an RSA key pair with a given number of bits"; + this.infoURL = "https://wikipedia.org/wiki/RSA_(cryptosystem)"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + name: "RSA Key Length", + type: "option", + value: [ + "1024", + "2048", + "4096" + ] + }, + { + name: "Output Format", + type: "option", + value: [ + "PEM", + "JSON", + "DER" + ] + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + async run(input, args) { + const [keyLength, outputFormat] = args + + return new Promise((resolve, reject) => { + forge.pki.rsa.generateKeyPair({ bits: Number(keyLength), workers: 2 }, (err, keypair) => { + if (err) return reject(err) + + let result; + + switch(outputFormat) { + case "PEM": + result = forge.pki.publicKeyToPem(keypair.publicKey) + "\n" + forge.pki.privateKeyToPem(keypair.privateKey); + break; + case "JSON": + result = JSON.stringify(keypair); + break; + case "DER": + result = forge.asn1.toDer(forge.pki.privateKeyToAsn1(keypair.privateKey)).getBytes(); + break; + }; + + resolve(result); + }) + }) + } + +} + +export default GenerateRSAKeyPair; diff --git a/src/core/operations/RSASign.mjs b/src/core/operations/RSASign.mjs new file mode 100644 index 000000000..fb3e4bbd8 --- /dev/null +++ b/src/core/operations/RSASign.mjs @@ -0,0 +1,60 @@ +/** + * @author gchq77703 [] + * @copyright Crown Copyright 2018 + * @license Apache-2.0 + */ + +import Operation from "../Operation"; +import forge from "node-forge/dist/forge.min.js"; + +/** + * RSA Sign operation + */ +class RSASign extends Operation { + + /** + * RSASign constructor + */ + constructor() { + super(); + + this.name = "RSA Sign"; + this.module = "Ciphers"; + this.description = "Sign a plaintext message with a PEM encoded RSA key."; + this.infoURL = "https://wikipedia.org/wiki/RSA_(cryptosystem)"; + this.inputType = "string"; + this.outputType = "byteArray"; + this.args = [ + { + name: "RSA Private Key (PEM)", + type: "text", + value: "-----BEGIN RSA PRIVATE KEY-----" + }, + { + name: "Password", + type: "text", + value: "" + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const [key, password] = args; + + const privateKey = forge.pki.decryptRsaPrivateKey(key, password); + + const md = forge.md.sha1.create(); + md.update(input, 'utf8'); + const signature = privateKey.sign(md); + + return signature.split('').map(char => char.charCodeAt()); + } + +} + +export default RSASign; From 31e758ca45667125feb52707762ead91d7969a08 Mon Sep 17 00:00:00 2001 From: Matt C Date: Fri, 31 Aug 2018 11:25:05 +0100 Subject: [PATCH 02/10] Attempt to make RSA key generation functional --- package-lock.json | 6 ++++++ package.json | 1 + src/core/operations/GenerateRSAKeyPair.mjs | 19 ++++++++++++------- src/core/operations/RSASign.mjs | 4 ++-- webpack.config.js | 4 ++++ 5 files changed, 25 insertions(+), 9 deletions(-) diff --git a/package-lock.json b/package-lock.json index d98140938..e7ce7f623 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8573,6 +8573,12 @@ } } }, + "raw-loader": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/raw-loader/-/raw-loader-0.5.1.tgz", + "integrity": "sha1-DD0L6u2KAclm2Xh793goElKpeao=", + "dev": true + }, "rc": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", diff --git a/package.json b/package.json index 5ff508f63..6805c5225 100644 --- a/package.json +++ b/package.json @@ -62,6 +62,7 @@ "postcss-import": "^12.0.0", "postcss-loader": "^2.1.6", "prompt": "^1.0.0", + "raw-loader": "^0.5.1", "sass-loader": "^7.1.0", "sitemap": "^1.13.0", "style-loader": "^0.21.0", diff --git a/src/core/operations/GenerateRSAKeyPair.mjs b/src/core/operations/GenerateRSAKeyPair.mjs index 9d7a88d84..64ff29d26 100644 --- a/src/core/operations/GenerateRSAKeyPair.mjs +++ b/src/core/operations/GenerateRSAKeyPair.mjs @@ -6,6 +6,7 @@ import Operation from "../Operation"; import forge from "node-forge/dist/forge.min.js"; +import PrimeWorker from "node-forge/dist/prime.worker.min.js"; /** * Generate RSA Key Pair operation @@ -52,15 +53,19 @@ class GenerateRSAKeyPair extends Operation { * @returns {string} */ async run(input, args) { - const [keyLength, outputFormat] = args + const [keyLength, outputFormat] = args; + let workerScript; return new Promise((resolve, reject) => { - forge.pki.rsa.generateKeyPair({ bits: Number(keyLength), workers: 2 }, (err, keypair) => { - if (err) return reject(err) + if (ENVIRONMENT_IS_WORKER || window) { + workerScript = ENVIRONMENT_IS_WORKER() ? self.URL.createObjectURL(new Blob([PrimeWorker])) : window.URL.createObjectURL(new Blob([PrimeWorker])); + } + forge.pki.rsa.generateKeyPair({ bits: Number(keyLength), workers: 2, workerScript}, (err, keypair) => { + if (err) return reject(err); let result; - switch(outputFormat) { + switch (outputFormat) { case "PEM": result = forge.pki.publicKeyToPem(keypair.publicKey) + "\n" + forge.pki.privateKeyToPem(keypair.privateKey); break; @@ -70,11 +75,11 @@ class GenerateRSAKeyPair extends Operation { case "DER": result = forge.asn1.toDer(forge.pki.privateKeyToAsn1(keypair.privateKey)).getBytes(); break; - }; + } resolve(result); - }) - }) + }); + }); } } diff --git a/src/core/operations/RSASign.mjs b/src/core/operations/RSASign.mjs index fb3e4bbd8..c0b4ccdf4 100644 --- a/src/core/operations/RSASign.mjs +++ b/src/core/operations/RSASign.mjs @@ -49,10 +49,10 @@ class RSASign extends Operation { const privateKey = forge.pki.decryptRsaPrivateKey(key, password); const md = forge.md.sha1.create(); - md.update(input, 'utf8'); + md.update(input, "utf8"); const signature = privateKey.sign(md); - return signature.split('').map(char => char.charCodeAt()); + return signature.split("").map(char => char.charCodeAt()); } } diff --git a/webpack.config.js b/webpack.config.js index 89a36f698..1a4f5a2d5 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -61,6 +61,10 @@ module.exports = { test: /forge.min.js$/, loader: "imports-loader?jQuery=>null" }, + { + test: /prime.worker.min.js$/, + use: "raw-loader" + }, { test: /bootstrap-material-design/, loader: "imports-loader?Popper=popper.js/dist/umd/popper.js" From 4d7988b78ebe0d8ab3238c3f30efb673e80ca4fb Mon Sep 17 00:00:00 2001 From: Matt Date: Mon, 30 Sep 2019 13:12:10 +0100 Subject: [PATCH 03/10] Fixed RSA key generation --- src/core/operations/GenerateRSAKeyPair.mjs | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/core/operations/GenerateRSAKeyPair.mjs b/src/core/operations/GenerateRSAKeyPair.mjs index 64ff29d26..951c2667c 100644 --- a/src/core/operations/GenerateRSAKeyPair.mjs +++ b/src/core/operations/GenerateRSAKeyPair.mjs @@ -1,12 +1,11 @@ /** * @author gchq77703 [] * @copyright Crown Copyright 2018 - ` * @license Apache-2.0 + * @license Apache-2.0 */ import Operation from "../Operation"; import forge from "node-forge/dist/forge.min.js"; -import PrimeWorker from "node-forge/dist/prime.worker.min.js"; /** * Generate RSA Key Pair operation @@ -54,13 +53,9 @@ class GenerateRSAKeyPair extends Operation { */ async run(input, args) { const [keyLength, outputFormat] = args; - let workerScript; return new Promise((resolve, reject) => { - if (ENVIRONMENT_IS_WORKER || window) { - workerScript = ENVIRONMENT_IS_WORKER() ? self.URL.createObjectURL(new Blob([PrimeWorker])) : window.URL.createObjectURL(new Blob([PrimeWorker])); - } - forge.pki.rsa.generateKeyPair({ bits: Number(keyLength), workers: 2, workerScript}, (err, keypair) => { + forge.pki.rsa.generateKeyPair({ bits: Number(keyLength), workers: -1}, (err, keypair) => { if (err) return reject(err); let result; From e0f000b913d2c092d7744e2f4f52476ce11056b6 Mon Sep 17 00:00:00 2001 From: Matt Date: Mon, 6 Apr 2020 13:35:14 +0100 Subject: [PATCH 04/10] Fixed RSA generation and added digest option to verify --- src/core/lib/RSA.mjs | 9 +++++++++ src/core/operations/GenerateRSAKeyPair.mjs | 3 ++- src/core/operations/RSASign.mjs | 16 +++++++++++----- webpack.config.js | 5 +++++ 4 files changed, 27 insertions(+), 6 deletions(-) create mode 100644 src/core/lib/RSA.mjs diff --git a/src/core/lib/RSA.mjs b/src/core/lib/RSA.mjs new file mode 100644 index 000000000..0dab67a36 --- /dev/null +++ b/src/core/lib/RSA.mjs @@ -0,0 +1,9 @@ +import forge from "node-forge/dist/forge.min.js"; + +export const MD_ALGORITHMS = { + "SHA-1": forge.md.sha1, + "MD5": forge.md.md5, + "SHA-256": forge.md.sha256, + "SHA-384": forge.md.sha384, + "SHA-512": forge.md.sha512, +}; diff --git a/src/core/operations/GenerateRSAKeyPair.mjs b/src/core/operations/GenerateRSAKeyPair.mjs index 951c2667c..a96948f23 100644 --- a/src/core/operations/GenerateRSAKeyPair.mjs +++ b/src/core/operations/GenerateRSAKeyPair.mjs @@ -1,4 +1,5 @@ /** + * @author Matt C [me@mitt.dev] * @author gchq77703 [] * @copyright Crown Copyright 2018 * @license Apache-2.0 @@ -55,7 +56,7 @@ class GenerateRSAKeyPair extends Operation { const [keyLength, outputFormat] = args; return new Promise((resolve, reject) => { - forge.pki.rsa.generateKeyPair({ bits: Number(keyLength), workers: -1}, (err, keypair) => { + forge.pki.rsa.generateKeyPair({ bits: Number(keyLength), workers: -1, workerScript: "./assets/forge/prime.worker.min.js"}, (err, keypair) => { if (err) return reject(err); let result; diff --git a/src/core/operations/RSASign.mjs b/src/core/operations/RSASign.mjs index c0b4ccdf4..980d59b35 100644 --- a/src/core/operations/RSASign.mjs +++ b/src/core/operations/RSASign.mjs @@ -1,11 +1,13 @@ /** + * @author Matt C [me@mitt.dev] * @author gchq77703 [] - * @copyright Crown Copyright 2018 + * @copyright Crown Copyright 2020 * @license Apache-2.0 */ import Operation from "../Operation"; import forge from "node-forge/dist/forge.min.js"; +import { MD_ALGORITHMS } from "../lib/RSA.mjs"; /** * RSA Sign operation @@ -31,9 +33,14 @@ class RSASign extends Operation { value: "-----BEGIN RSA PRIVATE KEY-----" }, { - name: "Password", + name: "Key Password", type: "text", value: "" + }, + { + name: "Message Digest Algorithm", + type: "option", + value: Object.keys(MD_ALGORITHMS) } ]; } @@ -44,11 +51,10 @@ class RSASign extends Operation { * @returns {string} */ run(input, args) { - const [key, password] = args; + const [key, password, mdAlgo] = args; const privateKey = forge.pki.decryptRsaPrivateKey(key, password); - - const md = forge.md.sha1.create(); + const md = MD_ALGORITHMS[mdAlgo].create(); md.update(input, "utf8"); const signature = privateKey.sign(md); diff --git a/webpack.config.js b/webpack.config.js index a14d8e7e4..c4ba416cb 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -56,6 +56,11 @@ module.exports = { context: "src/core/vendor/", from: "tesseract/**/*", to: "assets/" + }, + { + context: "node_modules/node-forge/dist", + from: "prime.worker.min.js", + to: "assets/forge/" } ]) ], From 2233b9a0949f50bdd974a2dcb4d76a54f9605d75 Mon Sep 17 00:00:00 2001 From: Matt Date: Mon, 6 Apr 2020 15:24:06 +0100 Subject: [PATCH 05/10] Comment and add error handling to generate and sign --- src/core/operations/GenerateRSAKeyPair.mjs | 2 +- src/core/operations/RSASign.mjs | 23 +++++++++++++++------- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/src/core/operations/GenerateRSAKeyPair.mjs b/src/core/operations/GenerateRSAKeyPair.mjs index a96948f23..57cfcdd09 100644 --- a/src/core/operations/GenerateRSAKeyPair.mjs +++ b/src/core/operations/GenerateRSAKeyPair.mjs @@ -56,7 +56,7 @@ class GenerateRSAKeyPair extends Operation { const [keyLength, outputFormat] = args; return new Promise((resolve, reject) => { - forge.pki.rsa.generateKeyPair({ bits: Number(keyLength), workers: -1, workerScript: "./assets/forge/prime.worker.min.js"}, (err, keypair) => { + forge.pki.rsa.generateKeyPair({ bits: Number(keyLength), workers: -1, workerScript: "assets/forge/prime.worker.min.js"}, (err, keypair) => { if (err) return reject(err); let result; diff --git a/src/core/operations/RSASign.mjs b/src/core/operations/RSASign.mjs index 980d59b35..812de813c 100644 --- a/src/core/operations/RSASign.mjs +++ b/src/core/operations/RSASign.mjs @@ -6,6 +6,7 @@ */ import Operation from "../Operation"; +import OperationError from "../errors/OperationError"; import forge from "node-forge/dist/forge.min.js"; import { MD_ALGORITHMS } from "../lib/RSA.mjs"; @@ -52,13 +53,21 @@ class RSASign extends Operation { */ run(input, args) { const [key, password, mdAlgo] = args; - - const privateKey = forge.pki.decryptRsaPrivateKey(key, password); - const md = MD_ALGORITHMS[mdAlgo].create(); - md.update(input, "utf8"); - const signature = privateKey.sign(md); - - return signature.split("").map(char => char.charCodeAt()); + if (key.replace("-----BEGIN RSA PRIVATE KEY-----", "").length === 0) { + throw new OperationError("Please enter a private key."); + } + try { + const privateKey = forge.pki.decryptRsaPrivateKey(key, password); + // Generate message hash + const md = MD_ALGORITHMS[mdAlgo].create(); + md.update(input, "utf8"); + // Convert signature UTF-16 string to byteArray + const encoder = new TextEncoder(); + const signature = encoder.encode(privateKey.sign(md)); + return signature; + } catch (err) { + throw new OperationError(err); + } } } From 18c6b9bc09e07ea2dba33b98d556a7902b6bd4dd Mon Sep 17 00:00:00 2001 From: Matt Date: Mon, 6 Apr 2020 15:24:22 +0100 Subject: [PATCH 06/10] Add RSA Verify operation --- src/core/operations/RSAVerify.mjs | 77 +++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 src/core/operations/RSAVerify.mjs diff --git a/src/core/operations/RSAVerify.mjs b/src/core/operations/RSAVerify.mjs new file mode 100644 index 000000000..2041e3410 --- /dev/null +++ b/src/core/operations/RSAVerify.mjs @@ -0,0 +1,77 @@ +/** + * @author Matt C [me@mitt.dev] + * @copyright Crown Copyright 2020 + * @license Apache-2.0 + */ + +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; +import forge from "node-forge/dist/forge.min.js"; +import { MD_ALGORITHMS } from "../lib/RSA.mjs"; + +/** + * RSA Verify operation + */ +class RSAVerify extends Operation { + + /** + * RSAVerify constructor + */ + constructor() { + super(); + + this.name = "RSA Verify"; + this.module = "Ciphers"; + this.description = "Verify a message against a signature and a public PEM encoded RSA key."; + this.infoURL = "https://wikipedia.org/wiki/RSA_(cryptosystem)"; + this.inputType = "byteArray"; + this.outputType = "string"; + this.args = [ + { + name: "RSA Public Key (PEM)", + type: "text", + value: "-----BEGIN RSA PUBLIC KEY-----" + }, + { + name: "Message", + type: "text", + value: "" + }, + { + name: "Message Digest Algorithm", + type: "option", + value: Object.keys(MD_ALGORITHMS) + } + ]; + } + + /** + * @param {byteArray} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const [pemKey, message, mdAlgo] = args; + if (pemKey.replace("-----BEGIN RSA PUBLIC KEY-----", "").length === 0) { + throw new OperationError("Please enter a public key."); + } + try { + // Load public key + const pubKey = forge.pki.publicKeyFromPem(pemKey); + // Generate message digest + const md = MD_ALGORITHMS[mdAlgo].create(); + md.update(message, "utf8"); + // Compare signed message digest and generated message digest + const result = pubKey.verify(md.digest().bytes(), input); + return result ? "Verified OK" : "Verification Failure"; + } catch (err) { + if (err.message === "Encrypted message length is invalid.") { + throw new OperationError(`Signature length (${err.length}) does not match expected length based on key (${err.expected}).`); + } + throw new OperationError(err); + } + } + +} + +export default RSAVerify; From 1c0ecd29c24b85bf2f37cfb097ddb46f5a95fc69 Mon Sep 17 00:00:00 2001 From: Matt Date: Tue, 7 Apr 2020 11:45:54 +0100 Subject: [PATCH 07/10] Fix RSA operations --- src/core/operations/RSASign.mjs | 10 +++++----- src/core/operations/RSAVerify.mjs | 3 ++- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/core/operations/RSASign.mjs b/src/core/operations/RSASign.mjs index 812de813c..1c2696e32 100644 --- a/src/core/operations/RSASign.mjs +++ b/src/core/operations/RSASign.mjs @@ -8,6 +8,7 @@ import Operation from "../Operation"; import OperationError from "../errors/OperationError"; import forge from "node-forge/dist/forge.min.js"; +import Utils from "../Utils.mjs"; import { MD_ALGORITHMS } from "../lib/RSA.mjs"; /** @@ -26,7 +27,7 @@ class RSASign extends Operation { this.description = "Sign a plaintext message with a PEM encoded RSA key."; this.infoURL = "https://wikipedia.org/wiki/RSA_(cryptosystem)"; this.inputType = "string"; - this.outputType = "byteArray"; + this.outputType = "string"; this.args = [ { name: "RSA Private Key (PEM)", @@ -61,10 +62,9 @@ class RSASign extends Operation { // Generate message hash const md = MD_ALGORITHMS[mdAlgo].create(); md.update(input, "utf8"); - // Convert signature UTF-16 string to byteArray - const encoder = new TextEncoder(); - const signature = encoder.encode(privateKey.sign(md)); - return signature; + // Sign message hash + const sig = privateKey.sign(md); + return sig; } catch (err) { throw new OperationError(err); } diff --git a/src/core/operations/RSAVerify.mjs b/src/core/operations/RSAVerify.mjs index 2041e3410..94ca42206 100644 --- a/src/core/operations/RSAVerify.mjs +++ b/src/core/operations/RSAVerify.mjs @@ -6,6 +6,7 @@ import Operation from "../Operation.mjs"; import OperationError from "../errors/OperationError.mjs"; +import Utils from "../Utils.mjs"; import forge from "node-forge/dist/forge.min.js"; import { MD_ALGORITHMS } from "../lib/RSA.mjs"; @@ -24,7 +25,7 @@ class RSAVerify extends Operation { this.module = "Ciphers"; this.description = "Verify a message against a signature and a public PEM encoded RSA key."; this.infoURL = "https://wikipedia.org/wiki/RSA_(cryptosystem)"; - this.inputType = "byteArray"; + this.inputType = "string"; this.outputType = "string"; this.args = [ { From e7b5c0e37c96f449efd7d1021bc8bd8e967c83ec Mon Sep 17 00:00:00 2001 From: Matt Date: Tue, 7 Apr 2020 13:31:17 +0100 Subject: [PATCH 08/10] Add RSA Encrypt Operation --- src/core/operations/RSAEncrypt.mjs | 84 ++++++++++++++++++++++++++++++ src/core/operations/RSASign.mjs | 1 - src/core/operations/RSAVerify.mjs | 3 +- 3 files changed, 85 insertions(+), 3 deletions(-) create mode 100644 src/core/operations/RSAEncrypt.mjs diff --git a/src/core/operations/RSAEncrypt.mjs b/src/core/operations/RSAEncrypt.mjs new file mode 100644 index 000000000..b7d5026bd --- /dev/null +++ b/src/core/operations/RSAEncrypt.mjs @@ -0,0 +1,84 @@ +/** + * @author Matt C [me@mitt.dev] + * @copyright Crown Copyright 2020 + * @license Apache-2.0 + */ + +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; +import forge from "node-forge/dist/forge.min.js"; +import { MD_ALGORITHMS } from "../lib/RSA.mjs"; + +/** + * RSA Encrypt operation + */ +class RSAEncrypt extends Operation { + + /** + * RSAEncrypt constructor + */ + constructor() { + super(); + + this.name = "RSA Encrypt"; + this.module = "Ciphers"; + this.description = "Encrypt a message with a PEM encoded RSA public key."; + this.infoURL = "https://wikipedia.org/wiki/RSA_(cryptosystem)"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + name: "RSA Public Key (PEM)", + type: "text", + value: "-----BEGIN RSA PUBLIC KEY-----" + }, + { + name: "Encryption Scheme", + type: "argSelector", + value: [ + { + name: "RSA-OAEP", + on: [2] + }, + { + name: "RSAES-PKCS1-V1_5", + off: [2] + }, + { + name: "RAW", + off: [2] + }] + }, + { + name: "Message Digest Algorithm", + type: "option", + value: Object.keys(MD_ALGORITHMS) + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const [pemKey, scheme, md] = args; + + if (pemKey.replace("-----BEGIN RSA PUBLIC KEY-----", "").length === 0) { + throw new OperationError("Please enter a public key."); + } + try { + // Load public key + const pubKey = forge.pki.publicKeyFromPem(pemKey); + // Encrypt message + const eMsg = pubKey.encrypt(input, scheme, {md: MD_ALGORITHMS[md].create()}); + return eMsg; + } catch (err) { + throw new OperationError(err); + } + } + +} + +export default RSAEncrypt; diff --git a/src/core/operations/RSASign.mjs b/src/core/operations/RSASign.mjs index 1c2696e32..6161c5fe5 100644 --- a/src/core/operations/RSASign.mjs +++ b/src/core/operations/RSASign.mjs @@ -8,7 +8,6 @@ import Operation from "../Operation"; import OperationError from "../errors/OperationError"; import forge from "node-forge/dist/forge.min.js"; -import Utils from "../Utils.mjs"; import { MD_ALGORITHMS } from "../lib/RSA.mjs"; /** diff --git a/src/core/operations/RSAVerify.mjs b/src/core/operations/RSAVerify.mjs index 94ca42206..e1a8b0cb1 100644 --- a/src/core/operations/RSAVerify.mjs +++ b/src/core/operations/RSAVerify.mjs @@ -6,7 +6,6 @@ import Operation from "../Operation.mjs"; import OperationError from "../errors/OperationError.mjs"; -import Utils from "../Utils.mjs"; import forge from "node-forge/dist/forge.min.js"; import { MD_ALGORITHMS } from "../lib/RSA.mjs"; @@ -47,7 +46,7 @@ class RSAVerify extends Operation { } /** - * @param {byteArray} input + * @param {string} input * @param {Object[]} args * @returns {string} */ From 7ad3992bd14e3f063a0b19fc7bba8ad2baf59c56 Mon Sep 17 00:00:00 2001 From: Matt Date: Tue, 7 Apr 2020 13:31:33 +0100 Subject: [PATCH 09/10] Add RSA Decrypt Operation --- src/core/operations/RSADecrypt.mjs | 86 ++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 src/core/operations/RSADecrypt.mjs diff --git a/src/core/operations/RSADecrypt.mjs b/src/core/operations/RSADecrypt.mjs new file mode 100644 index 000000000..0b0670e6e --- /dev/null +++ b/src/core/operations/RSADecrypt.mjs @@ -0,0 +1,86 @@ +/** + * @author Matt C [me@mitt.dev] + * @copyright Crown Copyright 2020 + * @license Apache-2.0 + */ + +import Operation from "../Operation.mjs"; +import OperationError from "../errors/OperationError.mjs"; +import forge from "node-forge/dist/forge.min.js"; +import { MD_ALGORITHMS } from "../lib/RSA.mjs"; + +/** + * RSA Decrypt operation + */ +class RSADecrypt extends Operation { + + /** + * RSADecrypt constructor + */ + constructor() { + super(); + + this.name = "RSA Decrypt"; + this.module = "Ciphers"; + this.description = "Decrypt an RSA encrypted message with a PEM encoded private key."; + this.infoURL = "https://wikipedia.org/wiki/RSA_(cryptosystem)"; + this.inputType = "string"; + this.outputType = "string"; + this.args = [ + { + name: "RSA Private Key (PEM)", + type: "text", + value: "-----BEGIN RSA PRIVATE KEY-----" + }, + { + name: "Key Password", + type: "text", + value: "" + }, + { + name: "Encryption Scheme", + type: "argSelector", + value: [ + { + name: "RSA-OAEP", + on: [3] + }, + { + name: "RSAES-PKCS1-V1_5", + off: [3] + }, + { + name: "RAW", + off: [3] + }] + }, + { + name: "Message Digest Algorithm", + type: "option", + value: Object.keys(MD_ALGORITHMS) + } + ]; + } + + /** + * @param {string} input + * @param {Object[]} args + * @returns {string} + */ + run(input, args) { + const [pemKey, password, scheme, md] = args; + if (pemKey.replace("-----BEGIN RSA PRIVATE KEY-----", "").length === 0) { + throw new OperationError("Please enter a private key."); + } + try { + const privKey = forge.pki.decryptRsaPrivateKey(pemKey, password); + const dMsg = privKey.decrypt(input, scheme, {md: MD_ALGORITHMS[md].create()}); + return dMsg; + } catch (err) { + throw new OperationError(err); + } + } + +} + +export default RSADecrypt; From fad163e0eb009ce5159b1ea68ca649679ace29a4 Mon Sep 17 00:00:00 2001 From: Matt Date: Tue, 7 Apr 2020 21:16:29 +0100 Subject: [PATCH 10/10] Added tests (that can't be run) --- src/core/config/Categories.json | 3 + src/core/operations/RSADecrypt.mjs | 5 +- src/core/operations/RSAEncrypt.mjs | 8 +- tests/operations/index.mjs | 3 +- tests/operations/samples/Ciphers.mjs | 22 ++ tests/operations/tests/PGP.mjs | 25 +- tests/operations/tests/RSA.mjs | 350 +++++++++++++++++++++++++++ 7 files changed, 387 insertions(+), 29 deletions(-) create mode 100644 tests/operations/samples/Ciphers.mjs create mode 100644 tests/operations/tests/RSA.mjs diff --git a/src/core/config/Categories.json b/src/core/config/Categories.json index 3b4d2c803..393a88a3b 100755 --- a/src/core/config/Categories.json +++ b/src/core/config/Categories.json @@ -107,6 +107,9 @@ "Scrypt", "Generate RSA Key Pair", "RSA Sign", + "RSA Verify", + "RSA Encrypt", + "RSA Decrypt", "JWT Sign", "JWT Verify", "JWT Decode", diff --git a/src/core/operations/RSADecrypt.mjs b/src/core/operations/RSADecrypt.mjs index 0b0670e6e..eb24aeabc 100644 --- a/src/core/operations/RSADecrypt.mjs +++ b/src/core/operations/RSADecrypt.mjs @@ -6,6 +6,7 @@ import Operation from "../Operation.mjs"; import OperationError from "../errors/OperationError.mjs"; +import Utils from "../Utils.mjs"; import forge from "node-forge/dist/forge.min.js"; import { MD_ALGORITHMS } from "../lib/RSA.mjs"; @@ -24,7 +25,7 @@ class RSADecrypt extends Operation { this.module = "Ciphers"; this.description = "Decrypt an RSA encrypted message with a PEM encoded private key."; this.infoURL = "https://wikipedia.org/wiki/RSA_(cryptosystem)"; - this.inputType = "string"; + this.inputType = "ArrayBuffer"; this.outputType = "string"; this.args = [ { @@ -74,7 +75,7 @@ class RSADecrypt extends Operation { } try { const privKey = forge.pki.decryptRsaPrivateKey(pemKey, password); - const dMsg = privKey.decrypt(input, scheme, {md: MD_ALGORITHMS[md].create()}); + const dMsg = privKey.decrypt(Utils.arrayBufferToStr(input), scheme, {md: MD_ALGORITHMS[md].create()}); return dMsg; } catch (err) { throw new OperationError(err); diff --git a/src/core/operations/RSAEncrypt.mjs b/src/core/operations/RSAEncrypt.mjs index b7d5026bd..e788a668b 100644 --- a/src/core/operations/RSAEncrypt.mjs +++ b/src/core/operations/RSAEncrypt.mjs @@ -6,6 +6,7 @@ import Operation from "../Operation.mjs"; import OperationError from "../errors/OperationError.mjs"; +import Utils from "../Utils.mjs"; import forge from "node-forge/dist/forge.min.js"; import { MD_ALGORITHMS } from "../lib/RSA.mjs"; @@ -25,7 +26,7 @@ class RSAEncrypt extends Operation { this.description = "Encrypt a message with a PEM encoded RSA public key."; this.infoURL = "https://wikipedia.org/wiki/RSA_(cryptosystem)"; this.inputType = "string"; - this.outputType = "string"; + this.outputType = "ArrayBuffer"; this.args = [ { name: "RSA Public Key (PEM)", @@ -73,8 +74,11 @@ class RSAEncrypt extends Operation { const pubKey = forge.pki.publicKeyFromPem(pemKey); // Encrypt message const eMsg = pubKey.encrypt(input, scheme, {md: MD_ALGORITHMS[md].create()}); - return eMsg; + return Utils.strToArrayBuffer(eMsg); } catch (err) { + if (err.message === "RSAES-OAEP input message length is too long.") { + throw new OperationError(`RSAES-OAEP input message length (${err.length}) is longer than the maximum allowed length (${err.maxLength}).`); + } throw new OperationError(err); } } diff --git a/tests/operations/index.mjs b/tests/operations/index.mjs index 8d3cd623d..18d120322 100644 --- a/tests/operations/index.mjs +++ b/tests/operations/index.mjs @@ -105,7 +105,8 @@ import "./tests/ParseObjectIDTimestamp.mjs"; // Cannot test operations that use the File type yet // import "./tests/SplitColourChannels.mjs"; - +// Cannot test as minified forge does not support node +// import "./tests/RSA.mjs"; const testStatus = { allTestsPassing: true, counts: { diff --git a/tests/operations/samples/Ciphers.mjs b/tests/operations/samples/Ciphers.mjs new file mode 100644 index 000000000..a1363d834 --- /dev/null +++ b/tests/operations/samples/Ciphers.mjs @@ -0,0 +1,22 @@ +export const ASCII_TEXT = "A common mistake that people make when trying to design something completely foolproof is to underestimate the ingenuity of complete fools."; + +export const UTF8_TEXT = "Шанцы на высвятленне таго, што адбываецца на самай справе ў сусвеце настолькі выдаленыя, адзінае, што трэба зрабіць, гэта павесіць пачуццё яго і трымаць сябе занятымі."; + +export 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(""); diff --git a/tests/operations/tests/PGP.mjs b/tests/operations/tests/PGP.mjs index 18e2e7eda..9748f937b 100644 --- a/tests/operations/tests/PGP.mjs +++ b/tests/operations/tests/PGP.mjs @@ -6,30 +6,7 @@ * @license Apache-2.0 */ import TestRegister from "../../lib/TestRegister.mjs"; - -const ASCII_TEXT = "A common mistake that people make when trying to design something completely foolproof is to underestimate the ingenuity of complete fools."; - -const UTF8_TEXT = "Шанцы на высвятленне таго, што адбываецца на самай справе ў сусвеце настолькі выдаленыя, адзінае, што трэба зрабіць, гэта павесіць пачуццё яго і трымаць сябе занятымі."; - -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(""); - +import {ASCII_TEXT, UTF8_TEXT, ALL_BYTES} from "../samples/Ciphers.mjs"; // RSA-1024 const ALICE_PRIVATE = `-----BEGIN PGP PRIVATE KEY BLOCK----- diff --git a/tests/operations/tests/RSA.mjs b/tests/operations/tests/RSA.mjs new file mode 100644 index 000000000..2ade56478 --- /dev/null +++ b/tests/operations/tests/RSA.mjs @@ -0,0 +1,350 @@ +/** + * RSA tests. + * + * @author Matt C [me@mitt.dev] + * @copyright Crown Copyright 2020 + * @license Apache-2.0 + */ +import TestRegister from "../../lib/TestRegister.mjs"; +import {ASCII_TEXT, UTF8_TEXT, ALL_BYTES} from "../samples/Ciphers.mjs"; + +const PEM_PRIV_2048 = `-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEAwfaUOpUEutKyU3wkCv6kYunz4MqxzSuTSckRz1IxwZtwIiqq ++ejkM6ioXPyGadfFNvG0JVOgr1q4KQglq0vXaYG57HZ8iinXnHgy1vr8i+fWYITB +RMrEDySaQh3sxVj8NudPDoTIxZwUcIUu/N53pUmI08ADxXPA+ZymPyZhZyxrj5Jq +2O2QuRu+R7K44NDweP/rETbGo5+QAPydm6UqBzTky/ohv6EGhjyqnaskTWwLWK6P +dKva8rEMb8nNJvhoTJDLYUfNjB7DFnWxgWuR/KVkXGAHX99J/wh6QTS+bsyJ2/Mw +Df6NWdh3iP7msLNl/GqL+HunhHjrthvvWlODDwIDAQABAoIBAApKwLvJC3q0UmUO +qcTxlRxwiJHNf5jA7qxUIH9NP7mju1P8ypy/KFi7Ys+oUKOOIPdU5Pe0E8sqN6pp +tcH8oL4G9awf72TPapLxZ9UzdTIhR6VQdgbl8XhSO2M1vkoMejmZlX7SOesOaKE9 +1+vwDA43tCx0PF7+UOeN0d549WMphvw3VkSInO/MYpobCGra4YdrhYOhFMyLEGgA +zCyVUOxi538tyyFtK2EEQdcMtvVA6SECjF4xD/qrme0LelIj/L1Uhiu+SOzYt4y+ +QLHL6zhJVfOejWxjeI7BhodkTV2D53n4svfizRgyYEb6iLPW3nlMYIlAksYaxxB9 +nR3sMHECgYEA9RU+8J5A8RnBcwnlc2X1xEW2PN7+A1MeWPQwFqRwIokgvGbCtwjG +PwwNUYJCTBhfGhsISeCBOSYrDGTHsNH+tqFW2zlq61BolYl56jb1KgWzMOX8dak4 +sgXIuBbvyuFNk08VMIzwcA76ka/Iuu/nN9ZOM2UYpdpGG+CTOoIFULECgYEAyppm +I+yAtrUn/BFmwmC8va4vqXlBFjvdkfX/71ywCpHIouLucMV7bILJu0nSCpmL1A7R +DT6qo0p5g+Dxl/+O2VyC5D89PBvcuT1+HtEZGLOoKZnojbSrwDApGbzQi57GoQR6 +/SRjsdAmoelY8PFz2s2ZLJ4NkrZXYvkT1Tu8/78CgYEA4MAvC/HUlEWORbTZmk3y +Z5+WU5QbVWkv91tXjiwWOVWPk7aY8ck2JDMlM45ExgvDiuknXLhpSMNbzu3MwraQ +42JpiHjLOChxAFEmYEct5O99OGZwcmZQ+9CaFVfTZzXeMizfvbpB9EGIP3n4lpXS +cD4zUKZxSAc3K/FyksERpsECgYEAhQPXeVBltQ68oKaAE6/VWqcIjbiY/dLyBkk+ +7dSpk1bhJefdadaN0NERRtARgXoLrn7Hy21QNILJwsaldwiGrbgqC1Zlipg0Ur3H +ls3rLyeMiTuNzbNHa5dy9H3dYT0t5Tr+0EHa3jvtkTGVfiLX0FhZb0yZVrA2MTmc +RsvAqxsCgYAgXy4qytgfzo5/bBt306NbtMEW3dWBWF77HAz4N1LynKZRUrAAK4rz +BVmXFUaNQOg0q8WJG+iFF79u2UnL8iZ5GoPMcpvifsZgef1OHnQnFrfyXSr0fXIm +xq8eZS0DpLvKGffCW03B9VDRHanE37Tng8lbgOtaufuVzFa1bCuLUA== +-----END RSA PRIVATE KEY-----`; + +const PEM_PUB_2048 = `-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwfaUOpUEutKyU3wkCv6k +Yunz4MqxzSuTSckRz1IxwZtwIiqq+ejkM6ioXPyGadfFNvG0JVOgr1q4KQglq0vX +aYG57HZ8iinXnHgy1vr8i+fWYITBRMrEDySaQh3sxVj8NudPDoTIxZwUcIUu/N53 +pUmI08ADxXPA+ZymPyZhZyxrj5Jq2O2QuRu+R7K44NDweP/rETbGo5+QAPydm6Uq +BzTky/ohv6EGhjyqnaskTWwLWK6PdKva8rEMb8nNJvhoTJDLYUfNjB7DFnWxgWuR +/KVkXGAHX99J/wh6QTS+bsyJ2/MwDf6NWdh3iP7msLNl/GqL+HunhHjrthvvWlOD +DwIDAQAB +-----END PUBLIC KEY-----`; + +TestRegister.addTests([ + { + name: "RSA Encrypt/Decrypt: RSA-OAEP/SHA-1, nothing", + input: "", + expectedOutput: "", + recipeConfig: [ + { + "op": "RSA Encrypt", + "args": [PEM_PUB_2048, "RSA-OAEP", "SHA-1"] + }, + { + "op": "RSA Decrypt", + "args": [PEM_PRIV_2048, "", "RSA-OAEP", "SHA-1"] + } + ] + }, + { + name: "RSA Encrypt/Decrypt: RSA-OAEP/SHA-1, ASCII", + input: ASCII_TEXT, + expectedOutput: ASCII_TEXT, + recipeConfig: [ + { + "op": "RSA Encrypt", + "args": [PEM_PUB_2048, "RSA-OAEP", "SHA-1"] + }, + { + "op": "RSA Decrypt", + "args": [PEM_PRIV_2048, "", "RSA-OAEP", "SHA-1"] + } + ] + }, + { + name: "RSA Encrypt/Decrypt: RSA-OAEP/SHA-1, UTF-8", + input: UTF8_TEXT, + expectedOutput: UTF8_TEXT, + recipeConfig: [ + { + "op": "RSA Encrypt", + "args": [PEM_PUB_2048, "RSA-OAEP", "SHA-1"] + }, + { + "op": "RSA Decrypt", + "args": [PEM_PRIV_2048, "", "RSA-OAEP", "SHA-1"] + } + ] + }, + { + name: "RSA Encrypt/Decrypt: RSA-OAEP/SHA-1, All bytes", + input: ALL_BYTES, + expectedOutput: ALL_BYTES, + recipeConfig: [ + { + "op": "RSA Encrypt", + "args": [PEM_PUB_2048, "RSA-OAEP", "SHA-1"] + }, + { + "op": "RSA Decrypt", + "args": [PEM_PRIV_2048, "", "RSA-OAEP", "SHA-1"] + } + ] + }, + { + name: "RSA Encrypt/Decrypt: RSA-OAEP/MD5, nothing", + input: "", + expectedOutput: "", + recipeConfig: [ + { + "op": "RSA Encrypt", + "args": [PEM_PUB_2048, "RSA-OAEP", "MD5"] + }, + { + "op": "RSA Decrypt", + "args": [PEM_PRIV_2048, "", "RSA-OAEP", "MD5"] + } + ] + }, + { + name: "RSA Encrypt/Decrypt: RSA-OAEP/MD5, ASCII", + input: ASCII_TEXT, + expectedOutput: ASCII_TEXT, + recipeConfig: [ + { + "op": "RSA Encrypt", + "args": [PEM_PUB_2048, "RSA-OAEP", "MD5"] + }, + { + "op": "RSA Decrypt", + "args": [PEM_PRIV_2048, "", "RSA-OAEP", "MD5"] + } + ] + }, + { + name: "RSA Encrypt/Decrypt: RSA-OAEP/MD5, UTF-8", + input: UTF8_TEXT, + expectedOutput: UTF8_TEXT, + recipeConfig: [ + { + "op": "RSA Encrypt", + "args": [PEM_PUB_2048, "RSA-OAEP", "MD5"] + }, + { + "op": "RSA Decrypt", + "args": [PEM_PRIV_2048, "", "RSA-OAEP", "MD5"] + } + ] + }, + { + name: "RSA Encrypt/Decrypt: RSA-OAEP/MD5, All bytes", + input: ALL_BYTES, + expectedOutput: ALL_BYTES, + recipeConfig: [ + { + "op": "RSA Encrypt", + "args": [PEM_PUB_2048, "RSA-OAEP", "MD5"] + }, + { + "op": "RSA Decrypt", + "args": [PEM_PRIV_2048, "", "RSA-OAEP", "MD5"] + } + ] + }, + { + name: "RSA Encrypt/Decrypt: RSA-OAEP/SHA-256, nothing", + input: "", + expectedOutput: "", + recipeConfig: [ + { + "op": "RSA Encrypt", + "args": [PEM_PUB_2048, "RSA-OAEP", "SHA-256"] + }, + { + "op": "RSA Decrypt", + "args": [PEM_PRIV_2048, "", "RSA-OAEP", "SHA-256"] + } + ] + }, + { + name: "RSA Encrypt/Decrypt: RSA-OAEP/SHA-256, ASCII", + input: ASCII_TEXT, + expectedOutput: ASCII_TEXT, + recipeConfig: [ + { + "op": "RSA Encrypt", + "args": [PEM_PUB_2048, "RSA-OAEP", "SHA-256"] + }, + { + "op": "RSA Decrypt", + "args": [PEM_PRIV_2048, "", "RSA-OAEP", "SHA-256"] + } + ] + }, + { + name: "RSA Encrypt/Decrypt: RSA-OAEP/SHA-256, UTF-8", + input: UTF8_TEXT, + expectedOutput: UTF8_TEXT, + recipeConfig: [ + { + "op": "RSA Encrypt", + "args": [PEM_PUB_2048, "RSA-OAEP", "SHA-256"] + }, + { + "op": "RSA Decrypt", + "args": [PEM_PRIV_2048, "", "RSA-OAEP", "SHA-256"] + } + ] + }, + { + name: "RSA Encrypt/Decrypt: RSA-OAEP/SHA-256, All bytes", + input: ALL_BYTES, + expectedOutput: ALL_BYTES, + recipeConfig: [ + { + "op": "RSA Encrypt", + "args": [PEM_PUB_2048, "RSA-OAEP", "SHA-256"] + }, + { + "op": "RSA Decrypt", + "args": [PEM_PRIV_2048, "", "RSA-OAEP", "SHA-256"] + } + ] + }, + { + name: "RSA Encrypt/Decrypt: RSA-OAEP/SHA-384, nothing", + input: "", + expectedOutput: "", + recipeConfig: [ + { + "op": "RSA Encrypt", + "args": [PEM_PUB_2048, "RSA-OAEP", "SHA-384"] + }, + { + "op": "RSA Decrypt", + "args": [PEM_PRIV_2048, "", "RSA-OAEP", "SHA-384"] + } + ] + }, + { + name: "RSA Encrypt/Decrypt: RSA-OAEP/SHA-384, ASCII", + input: ASCII_TEXT, + expectedOutput: ASCII_TEXT, + recipeConfig: [ + { + "op": "RSA Encrypt", + "args": [PEM_PUB_2048, "RSA-OAEP", "SHA-384"] + }, + { + "op": "RSA Decrypt", + "args": [PEM_PRIV_2048, "", "RSA-OAEP", "SHA-384"] + } + ] + }, + { + name: "RSA Encrypt/Decrypt: RSA-OAEP/SHA-384, UTF-8", + input: UTF8_TEXT, + expectedOutput: UTF8_TEXT, + recipeConfig: [ + { + "op": "RSA Encrypt", + "args": [PEM_PUB_2048, "RSA-OAEP", "SHA-384"] + }, + { + "op": "RSA Decrypt", + "args": [PEM_PRIV_2048, "", "RSA-OAEP", "SHA-384"] + } + ] + }, + { + name: "RSA Encrypt/Decrypt: RSA-OAEP/SHA-384, All bytes", + input: ALL_BYTES, + expectedOutput: ALL_BYTES, + recipeConfig: [ + { + "op": "RSA Encrypt", + "args": [PEM_PUB_2048, "RSA-OAEP", "SHA-384"] + }, + { + "op": "RSA Decrypt", + "args": [PEM_PRIV_2048, "", "RSA-OAEP", "SHA-384"] + } + ] + }, + { + name: "RSA Encrypt/Decrypt: RSA-OAEP/SHA-512, nothing", + input: "", + expectedOutput: "", + recipeConfig: [ + { + "op": "RSA Encrypt", + "args": [PEM_PUB_2048, "RSA-OAEP", "SHA-512"] + }, + { + "op": "RSA Decrypt", + "args": [PEM_PRIV_2048, "", "RSA-OAEP", "SHA-512"] + } + ] + }, + { + name: "RSA Encrypt/Decrypt: RSA-OAEP/SHA-512, ASCII", + input: ASCII_TEXT, + expectedOutput: ASCII_TEXT, + recipeConfig: [ + { + "op": "RSA Encrypt", + "args": [PEM_PUB_2048, "RSA-OAEP", "SHA-512"] + }, + { + "op": "RSA Decrypt", + "args": [PEM_PRIV_2048, "", "RSA-OAEP", "SHA-512"] + } + ] + }, + { + name: "RSA Encrypt/Decrypt: RSA-OAEP/SHA-512, UTF-8", + input: UTF8_TEXT, + expectedOutput: UTF8_TEXT, + recipeConfig: [ + { + "op": "RSA Encrypt", + "args": [PEM_PUB_2048, "RSA-OAEP", "SHA-512"] + }, + { + "op": "RSA Decrypt", + "args": [PEM_PRIV_2048, "", "RSA-OAEP", "SHA-512"] + } + ] + }, + { + name: "RSA Encrypt/Decrypt: RSA-OAEP/SHA-512, All bytes", + input: ALL_BYTES, + expectedOutput: ALL_BYTES, + recipeConfig: [ + { + "op": "RSA Encrypt", + "args": [PEM_PUB_2048, "RSA-OAEP", "SHA-512"] + }, + { + "op": "RSA Decrypt", + "args": [PEM_PRIV_2048, "", "RSA-OAEP", "SHA-512"] + } + ] + }, +]);