mirror of
https://github.com/gchq/CyberChef.git
synced 2024-11-02 14:11:02 +01:00
Merge branch 'mattnotmitt-rsa'
This commit is contained in:
commit
66c533431d
@ -134,6 +134,11 @@
|
||||
"PGP Verify",
|
||||
"PGP Encrypt and Sign",
|
||||
"PGP Decrypt and Verify",
|
||||
"Generate RSA Key Pair",
|
||||
"RSA Sign",
|
||||
"RSA Verify",
|
||||
"RSA Encrypt",
|
||||
"RSA Decrypt",
|
||||
"Parse SSH Host Key"
|
||||
]
|
||||
},
|
||||
|
17
src/core/lib/RSA.mjs
Normal file
17
src/core/lib/RSA.mjs
Normal file
@ -0,0 +1,17 @@
|
||||
/**
|
||||
* RSA resources.
|
||||
*
|
||||
* @author Matt C [me@mitt.dev]
|
||||
* @copyright Crown Copyright 2021
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import forge from "node-forge";
|
||||
|
||||
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,
|
||||
};
|
@ -25,7 +25,7 @@ class GeneratePGPKeyPair extends Operation {
|
||||
|
||||
this.name = "Generate PGP Key Pair";
|
||||
this.module = "PGP";
|
||||
this.description = "Generates a new public/private PGP key pair. Supports RSA and Eliptic Curve (EC) keys.";
|
||||
this.description = "Generates a new public/private PGP key pair. Supports RSA and Eliptic Curve (EC) keys.<br><br>WARNING: Cryptographic operations in CyberChef should not be relied upon to provide security in any situation. No guarantee is offered for their correctness. We advise you not to use keys generated from CyberChef in operational contexts.";
|
||||
this.infoURL = "https://wikipedia.org/wiki/Pretty_Good_Privacy";
|
||||
this.inputType = "string";
|
||||
this.outputType = "string";
|
||||
|
87
src/core/operations/GenerateRSAKeyPair.mjs
Normal file
87
src/core/operations/GenerateRSAKeyPair.mjs
Normal file
@ -0,0 +1,87 @@
|
||||
/**
|
||||
* @author Matt C [me@mitt.dev]
|
||||
* @author gchq77703 []
|
||||
* @copyright Crown Copyright 2018
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import Operation from "../Operation.mjs";
|
||||
import forge from "node-forge";
|
||||
|
||||
/**
|
||||
* 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.<br><br>WARNING: Cryptographic operations in CyberChef should not be relied upon to provide security in any situation. No guarantee is offered for their correctness. We advise you not to use keys generated from CyberChef in operational contexts.";
|
||||
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: -1,
|
||||
workerScript: "assets/forge/prime.worker.min.js"
|
||||
}, (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;
|
86
src/core/operations/RSADecrypt.mjs
Normal file
86
src/core/operations/RSADecrypt.mjs
Normal file
@ -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";
|
||||
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 forge.util.decodeUtf8(dMsg);
|
||||
} catch (err) {
|
||||
throw new OperationError(err);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default RSADecrypt;
|
89
src/core/operations/RSAEncrypt.mjs
Normal file
89
src/core/operations/RSAEncrypt.mjs
Normal file
@ -0,0 +1,89 @@
|
||||
/**
|
||||
* @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";
|
||||
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);
|
||||
// https://github.com/digitalbazaar/forge/issues/465#issuecomment-271097600
|
||||
const plaintextBytes = forge.util.encodeUtf8(input);
|
||||
// Encrypt message
|
||||
const eMsg = pubKey.encrypt(plaintextBytes, scheme, {md: MD_ALGORITHMS[md].create()});
|
||||
return 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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default RSAEncrypt;
|
74
src/core/operations/RSASign.mjs
Normal file
74
src/core/operations/RSASign.mjs
Normal file
@ -0,0 +1,74 @@
|
||||
/**
|
||||
* @author Matt C [me@mitt.dev]
|
||||
* @author gchq77703 []
|
||||
* @copyright Crown Copyright 2020
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import Operation from "../Operation.mjs";
|
||||
import OperationError from "../errors/OperationError.mjs";
|
||||
import forge from "node-forge";
|
||||
import { MD_ALGORITHMS } from "../lib/RSA.mjs";
|
||||
|
||||
/**
|
||||
* 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 = "string";
|
||||
this.args = [
|
||||
{
|
||||
name: "RSA Private Key (PEM)",
|
||||
type: "text",
|
||||
value: "-----BEGIN RSA PRIVATE KEY-----"
|
||||
},
|
||||
{
|
||||
name: "Key Password",
|
||||
type: "text",
|
||||
value: ""
|
||||
},
|
||||
{
|
||||
name: "Message Digest Algorithm",
|
||||
type: "option",
|
||||
value: Object.keys(MD_ALGORITHMS)
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run(input, args) {
|
||||
const [key, password, mdAlgo] = args;
|
||||
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");
|
||||
// Sign message hash
|
||||
const sig = privateKey.sign(md);
|
||||
return sig;
|
||||
} catch (err) {
|
||||
throw new OperationError(err);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default RSASign;
|
77
src/core/operations/RSAVerify.mjs
Normal file
77
src/core/operations/RSAVerify.mjs
Normal file
@ -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";
|
||||
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 = "string";
|
||||
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 {string} 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;
|
@ -101,7 +101,7 @@ import "./tests/CipherSaber2.mjs";
|
||||
import "./tests/Colossus.mjs";
|
||||
import "./tests/ParseObjectIDTimestamp.mjs";
|
||||
import "./tests/Unicode.mjs";
|
||||
|
||||
import "./tests/RSA.mjs";
|
||||
|
||||
// Cannot test operations that use the File type yet
|
||||
// import "./tests/SplitColourChannels.mjs";
|
||||
|
31
tests/operations/samples/Ciphers.mjs
Normal file
31
tests/operations/samples/Ciphers.mjs
Normal file
@ -0,0 +1,31 @@
|
||||
/**
|
||||
* Various types of input data for use in tests
|
||||
*
|
||||
* @author n1474335 [n1474335@gmail.com]
|
||||
* @author Matt C [me@mitt.dev]
|
||||
* @copyright Crown Copyright 2020
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
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("");
|
@ -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-----
|
||||
|
350
tests/operations/tests/RSA.mjs
Normal file
350
tests/operations/tests/RSA.mjs
Normal file
@ -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.substr(0, 100),
|
||||
expectedOutput: UTF8_TEXT.substr(0, 100),
|
||||
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.substr(0, 100),
|
||||
expectedOutput: ALL_BYTES.substr(0, 100),
|
||||
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.substr(0, 100),
|
||||
expectedOutput: UTF8_TEXT.substr(0, 100),
|
||||
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.substr(0, 100),
|
||||
expectedOutput: ALL_BYTES.substr(0, 100),
|
||||
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.substr(0, 100),
|
||||
expectedOutput: UTF8_TEXT.substr(0, 100),
|
||||
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.substr(0, 100),
|
||||
expectedOutput: ALL_BYTES.substr(0, 100),
|
||||
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.substr(0, 80),
|
||||
expectedOutput: UTF8_TEXT.substr(0, 80),
|
||||
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.substr(0, 100),
|
||||
expectedOutput: ALL_BYTES.substr(0, 100),
|
||||
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.substr(0, 100),
|
||||
expectedOutput: ASCII_TEXT.substr(0, 100),
|
||||
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.substr(0, 60),
|
||||
expectedOutput: UTF8_TEXT.substr(0, 60),
|
||||
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.substr(0, 100),
|
||||
expectedOutput: ALL_BYTES.substr(0, 100),
|
||||
recipeConfig: [
|
||||
{
|
||||
"op": "RSA Encrypt",
|
||||
"args": [PEM_PUB_2048, "RSA-OAEP", "SHA-512"]
|
||||
},
|
||||
{
|
||||
"op": "RSA Decrypt",
|
||||
"args": [PEM_PRIV_2048, "", "RSA-OAEP", "SHA-512"]
|
||||
}
|
||||
]
|
||||
},
|
||||
]);
|
@ -75,6 +75,10 @@ module.exports = {
|
||||
context: "node_modules/tesseract.js-core/",
|
||||
from: "tesseract-core.wasm.js",
|
||||
to: "assets/tesseract"
|
||||
}, {
|
||||
context: "node_modules/node-forge/dist",
|
||||
from: "prime.worker.min.js",
|
||||
to: "assets/forge/"
|
||||
}
|
||||
]
|
||||
})
|
||||
@ -116,6 +120,10 @@ module.exports = {
|
||||
additionalCode: "var jQuery = false;"
|
||||
}
|
||||
},
|
||||
{
|
||||
test: /prime.worker.min.js$/,
|
||||
use: "raw-loader"
|
||||
},
|
||||
{
|
||||
test: /bootstrap-material-design/,
|
||||
loader: "imports-loader",
|
||||
|
Loading…
Reference in New Issue
Block a user