Tidied up and added tests for RSA operations

This commit is contained in:
n1474335 2021-02-01 19:15:32 +00:00
parent 99eb1cced5
commit 74ae77f17a
11 changed files with 70 additions and 50 deletions

View File

@ -105,11 +105,6 @@
"Derive EVP key",
"Bcrypt",
"Scrypt",
"Generate RSA Key Pair",
"RSA Sign",
"RSA Verify",
"RSA Encrypt",
"RSA Decrypt",
"JWT Sign",
"JWT Verify",
"JWT Decode",
@ -139,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"
]
},

View File

@ -1,4 +1,12 @@
import forge from "node-forge/dist/forge.min.js";
/**
* 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,

View File

@ -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";

View File

@ -5,8 +5,8 @@
* @license Apache-2.0
*/
import Operation from "../Operation";
import forge from "node-forge/dist/forge.min.js";
import Operation from "../Operation.mjs";
import forge from "node-forge";
/**
* Generate RSA Key Pair operation
@ -21,7 +21,7 @@ class GenerateRSAKeyPair extends Operation {
this.name = "Generate RSA Key Pair";
this.module = "Ciphers";
this.description = "Generate an RSA key pair with a given number of bits";
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";
@ -56,7 +56,11 @@ 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;

View File

@ -6,8 +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 forge from "node-forge";
import { MD_ALGORITHMS } from "../lib/RSA.mjs";
/**
@ -25,7 +24,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 = "ArrayBuffer";
this.inputType = "string";
this.outputType = "string";
this.args = [
{
@ -75,8 +74,8 @@ class RSADecrypt extends Operation {
}
try {
const privKey = forge.pki.decryptRsaPrivateKey(pemKey, password);
const dMsg = privKey.decrypt(Utils.arrayBufferToStr(input), scheme, {md: MD_ALGORITHMS[md].create()});
return dMsg;
const dMsg = privKey.decrypt(input, scheme, {md: MD_ALGORITHMS[md].create()});
return forge.util.decodeUtf8(dMsg);
} catch (err) {
throw new OperationError(err);
}

View File

@ -6,8 +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 forge from "node-forge";
import { MD_ALGORITHMS } from "../lib/RSA.mjs";
/**
@ -26,7 +25,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 = "ArrayBuffer";
this.outputType = "string";
this.args = [
{
name: "RSA Public Key (PEM)",
@ -72,9 +71,11 @@ class RSAEncrypt extends Operation {
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(input, scheme, {md: MD_ALGORITHMS[md].create()});
return Utils.strToArrayBuffer(eMsg);
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}).`);

View File

@ -5,9 +5,9 @@
* @license Apache-2.0
*/
import Operation from "../Operation";
import OperationError from "../errors/OperationError";
import forge from "node-forge/dist/forge.min.js";
import Operation from "../Operation.mjs";
import OperationError from "../errors/OperationError.mjs";
import forge from "node-forge";
import { MD_ALGORITHMS } from "../lib/RSA.mjs";
/**

View File

@ -6,7 +6,7 @@
import Operation from "../Operation.mjs";
import OperationError from "../errors/OperationError.mjs";
import forge from "node-forge/dist/forge.min.js";
import forge from "node-forge";
import { MD_ALGORITHMS } from "../lib/RSA.mjs";
/**

View File

@ -101,12 +101,11 @@ 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";
// Cannot test as minified forge does not support node
// import "./tests/RSA.mjs";
const testStatus = {
allTestsPassing: true,
counts: {

View File

@ -1,3 +1,12 @@
/**
* 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 = "Шанцы на высвятленне таго, што адбываецца на самай справе ў сусвеце настолькі выдаленыя, адзінае, што трэба зрабіць, гэта павесіць пачуццё яго і трымаць сябе занятымі.";

View File

@ -79,8 +79,8 @@ TestRegister.addTests([
},
{
name: "RSA Encrypt/Decrypt: RSA-OAEP/SHA-1, UTF-8",
input: UTF8_TEXT,
expectedOutput: UTF8_TEXT,
input: UTF8_TEXT.substr(0, 100),
expectedOutput: UTF8_TEXT.substr(0, 100),
recipeConfig: [
{
"op": "RSA Encrypt",
@ -94,8 +94,8 @@ TestRegister.addTests([
},
{
name: "RSA Encrypt/Decrypt: RSA-OAEP/SHA-1, All bytes",
input: ALL_BYTES,
expectedOutput: ALL_BYTES,
input: ALL_BYTES.substr(0, 100),
expectedOutput: ALL_BYTES.substr(0, 100),
recipeConfig: [
{
"op": "RSA Encrypt",
@ -139,8 +139,8 @@ TestRegister.addTests([
},
{
name: "RSA Encrypt/Decrypt: RSA-OAEP/MD5, UTF-8",
input: UTF8_TEXT,
expectedOutput: UTF8_TEXT,
input: UTF8_TEXT.substr(0, 100),
expectedOutput: UTF8_TEXT.substr(0, 100),
recipeConfig: [
{
"op": "RSA Encrypt",
@ -154,8 +154,8 @@ TestRegister.addTests([
},
{
name: "RSA Encrypt/Decrypt: RSA-OAEP/MD5, All bytes",
input: ALL_BYTES,
expectedOutput: ALL_BYTES,
input: ALL_BYTES.substr(0, 100),
expectedOutput: ALL_BYTES.substr(0, 100),
recipeConfig: [
{
"op": "RSA Encrypt",
@ -199,8 +199,8 @@ TestRegister.addTests([
},
{
name: "RSA Encrypt/Decrypt: RSA-OAEP/SHA-256, UTF-8",
input: UTF8_TEXT,
expectedOutput: UTF8_TEXT,
input: UTF8_TEXT.substr(0, 100),
expectedOutput: UTF8_TEXT.substr(0, 100),
recipeConfig: [
{
"op": "RSA Encrypt",
@ -214,8 +214,8 @@ TestRegister.addTests([
},
{
name: "RSA Encrypt/Decrypt: RSA-OAEP/SHA-256, All bytes",
input: ALL_BYTES,
expectedOutput: ALL_BYTES,
input: ALL_BYTES.substr(0, 100),
expectedOutput: ALL_BYTES.substr(0, 100),
recipeConfig: [
{
"op": "RSA Encrypt",
@ -259,8 +259,8 @@ TestRegister.addTests([
},
{
name: "RSA Encrypt/Decrypt: RSA-OAEP/SHA-384, UTF-8",
input: UTF8_TEXT,
expectedOutput: UTF8_TEXT,
input: UTF8_TEXT.substr(0, 80),
expectedOutput: UTF8_TEXT.substr(0, 80),
recipeConfig: [
{
"op": "RSA Encrypt",
@ -274,8 +274,8 @@ TestRegister.addTests([
},
{
name: "RSA Encrypt/Decrypt: RSA-OAEP/SHA-384, All bytes",
input: ALL_BYTES,
expectedOutput: ALL_BYTES,
input: ALL_BYTES.substr(0, 100),
expectedOutput: ALL_BYTES.substr(0, 100),
recipeConfig: [
{
"op": "RSA Encrypt",
@ -304,8 +304,8 @@ TestRegister.addTests([
},
{
name: "RSA Encrypt/Decrypt: RSA-OAEP/SHA-512, ASCII",
input: ASCII_TEXT,
expectedOutput: ASCII_TEXT,
input: ASCII_TEXT.substr(0, 100),
expectedOutput: ASCII_TEXT.substr(0, 100),
recipeConfig: [
{
"op": "RSA Encrypt",
@ -319,8 +319,8 @@ TestRegister.addTests([
},
{
name: "RSA Encrypt/Decrypt: RSA-OAEP/SHA-512, UTF-8",
input: UTF8_TEXT,
expectedOutput: UTF8_TEXT,
input: UTF8_TEXT.substr(0, 60),
expectedOutput: UTF8_TEXT.substr(0, 60),
recipeConfig: [
{
"op": "RSA Encrypt",
@ -334,8 +334,8 @@ TestRegister.addTests([
},
{
name: "RSA Encrypt/Decrypt: RSA-OAEP/SHA-512, All bytes",
input: ALL_BYTES,
expectedOutput: ALL_BYTES,
input: ALL_BYTES.substr(0, 100),
expectedOutput: ALL_BYTES.substr(0, 100),
recipeConfig: [
{
"op": "RSA Encrypt",