mirror of
https://github.com/gchq/CyberChef.git
synced 2025-04-20 14:56:19 -04:00
Tidied up and added tests for RSA operations
This commit is contained in:
parent
99eb1cced5
commit
74ae77f17a
11 changed files with 70 additions and 50 deletions
|
@ -105,11 +105,6 @@
|
||||||
"Derive EVP key",
|
"Derive EVP key",
|
||||||
"Bcrypt",
|
"Bcrypt",
|
||||||
"Scrypt",
|
"Scrypt",
|
||||||
"Generate RSA Key Pair",
|
|
||||||
"RSA Sign",
|
|
||||||
"RSA Verify",
|
|
||||||
"RSA Encrypt",
|
|
||||||
"RSA Decrypt",
|
|
||||||
"JWT Sign",
|
"JWT Sign",
|
||||||
"JWT Verify",
|
"JWT Verify",
|
||||||
"JWT Decode",
|
"JWT Decode",
|
||||||
|
@ -139,6 +134,11 @@
|
||||||
"PGP Verify",
|
"PGP Verify",
|
||||||
"PGP Encrypt and Sign",
|
"PGP Encrypt and Sign",
|
||||||
"PGP Decrypt and Verify",
|
"PGP Decrypt and Verify",
|
||||||
|
"Generate RSA Key Pair",
|
||||||
|
"RSA Sign",
|
||||||
|
"RSA Verify",
|
||||||
|
"RSA Encrypt",
|
||||||
|
"RSA Decrypt",
|
||||||
"Parse SSH Host Key"
|
"Parse SSH Host Key"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
|
@ -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 = {
|
export const MD_ALGORITHMS = {
|
||||||
"SHA-1": forge.md.sha1,
|
"SHA-1": forge.md.sha1,
|
||||||
|
|
|
@ -25,7 +25,7 @@ class GeneratePGPKeyPair extends Operation {
|
||||||
|
|
||||||
this.name = "Generate PGP Key Pair";
|
this.name = "Generate PGP Key Pair";
|
||||||
this.module = "PGP";
|
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.infoURL = "https://wikipedia.org/wiki/Pretty_Good_Privacy";
|
||||||
this.inputType = "string";
|
this.inputType = "string";
|
||||||
this.outputType = "string";
|
this.outputType = "string";
|
||||||
|
|
|
@ -5,8 +5,8 @@
|
||||||
* @license Apache-2.0
|
* @license Apache-2.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import Operation from "../Operation";
|
import Operation from "../Operation.mjs";
|
||||||
import forge from "node-forge/dist/forge.min.js";
|
import forge from "node-forge";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate RSA Key Pair operation
|
* Generate RSA Key Pair operation
|
||||||
|
@ -21,7 +21,7 @@ class GenerateRSAKeyPair extends Operation {
|
||||||
|
|
||||||
this.name = "Generate RSA Key Pair";
|
this.name = "Generate RSA Key Pair";
|
||||||
this.module = "Ciphers";
|
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.infoURL = "https://wikipedia.org/wiki/RSA_(cryptosystem)";
|
||||||
this.inputType = "string";
|
this.inputType = "string";
|
||||||
this.outputType = "string";
|
this.outputType = "string";
|
||||||
|
@ -56,7 +56,11 @@ class GenerateRSAKeyPair extends Operation {
|
||||||
const [keyLength, outputFormat] = args;
|
const [keyLength, outputFormat] = args;
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
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);
|
if (err) return reject(err);
|
||||||
|
|
||||||
let result;
|
let result;
|
||||||
|
|
|
@ -6,8 +6,7 @@
|
||||||
|
|
||||||
import Operation from "../Operation.mjs";
|
import Operation from "../Operation.mjs";
|
||||||
import OperationError from "../errors/OperationError.mjs";
|
import OperationError from "../errors/OperationError.mjs";
|
||||||
import Utils from "../Utils.mjs";
|
import forge from "node-forge";
|
||||||
import forge from "node-forge/dist/forge.min.js";
|
|
||||||
import { MD_ALGORITHMS } from "../lib/RSA.mjs";
|
import { MD_ALGORITHMS } from "../lib/RSA.mjs";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -25,7 +24,7 @@ class RSADecrypt extends Operation {
|
||||||
this.module = "Ciphers";
|
this.module = "Ciphers";
|
||||||
this.description = "Decrypt an RSA encrypted message with a PEM encoded private key.";
|
this.description = "Decrypt an RSA encrypted message with a PEM encoded private key.";
|
||||||
this.infoURL = "https://wikipedia.org/wiki/RSA_(cryptosystem)";
|
this.infoURL = "https://wikipedia.org/wiki/RSA_(cryptosystem)";
|
||||||
this.inputType = "ArrayBuffer";
|
this.inputType = "string";
|
||||||
this.outputType = "string";
|
this.outputType = "string";
|
||||||
this.args = [
|
this.args = [
|
||||||
{
|
{
|
||||||
|
@ -75,8 +74,8 @@ class RSADecrypt extends Operation {
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
const privKey = forge.pki.decryptRsaPrivateKey(pemKey, password);
|
const privKey = forge.pki.decryptRsaPrivateKey(pemKey, password);
|
||||||
const dMsg = privKey.decrypt(Utils.arrayBufferToStr(input), scheme, {md: MD_ALGORITHMS[md].create()});
|
const dMsg = privKey.decrypt(input, scheme, {md: MD_ALGORITHMS[md].create()});
|
||||||
return dMsg;
|
return forge.util.decodeUtf8(dMsg);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
throw new OperationError(err);
|
throw new OperationError(err);
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,8 +6,7 @@
|
||||||
|
|
||||||
import Operation from "../Operation.mjs";
|
import Operation from "../Operation.mjs";
|
||||||
import OperationError from "../errors/OperationError.mjs";
|
import OperationError from "../errors/OperationError.mjs";
|
||||||
import Utils from "../Utils.mjs";
|
import forge from "node-forge";
|
||||||
import forge from "node-forge/dist/forge.min.js";
|
|
||||||
import { MD_ALGORITHMS } from "../lib/RSA.mjs";
|
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.description = "Encrypt a message with a PEM encoded RSA public key.";
|
||||||
this.infoURL = "https://wikipedia.org/wiki/RSA_(cryptosystem)";
|
this.infoURL = "https://wikipedia.org/wiki/RSA_(cryptosystem)";
|
||||||
this.inputType = "string";
|
this.inputType = "string";
|
||||||
this.outputType = "ArrayBuffer";
|
this.outputType = "string";
|
||||||
this.args = [
|
this.args = [
|
||||||
{
|
{
|
||||||
name: "RSA Public Key (PEM)",
|
name: "RSA Public Key (PEM)",
|
||||||
|
@ -72,9 +71,11 @@ class RSAEncrypt extends Operation {
|
||||||
try {
|
try {
|
||||||
// Load public key
|
// Load public key
|
||||||
const pubKey = forge.pki.publicKeyFromPem(pemKey);
|
const pubKey = forge.pki.publicKeyFromPem(pemKey);
|
||||||
|
// https://github.com/digitalbazaar/forge/issues/465#issuecomment-271097600
|
||||||
|
const plaintextBytes = forge.util.encodeUtf8(input);
|
||||||
// Encrypt message
|
// Encrypt message
|
||||||
const eMsg = pubKey.encrypt(input, scheme, {md: MD_ALGORITHMS[md].create()});
|
const eMsg = pubKey.encrypt(plaintextBytes, scheme, {md: MD_ALGORITHMS[md].create()});
|
||||||
return Utils.strToArrayBuffer(eMsg);
|
return eMsg;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (err.message === "RSAES-OAEP input message length is too long.") {
|
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(`RSAES-OAEP input message length (${err.length}) is longer than the maximum allowed length (${err.maxLength}).`);
|
||||||
|
|
|
@ -5,9 +5,9 @@
|
||||||
* @license Apache-2.0
|
* @license Apache-2.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import Operation from "../Operation";
|
import Operation from "../Operation.mjs";
|
||||||
import OperationError from "../errors/OperationError";
|
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";
|
import { MD_ALGORITHMS } from "../lib/RSA.mjs";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
import Operation from "../Operation.mjs";
|
import Operation from "../Operation.mjs";
|
||||||
import OperationError from "../errors/OperationError.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";
|
import { MD_ALGORITHMS } from "../lib/RSA.mjs";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -101,12 +101,11 @@ import "./tests/CipherSaber2.mjs";
|
||||||
import "./tests/Colossus.mjs";
|
import "./tests/Colossus.mjs";
|
||||||
import "./tests/ParseObjectIDTimestamp.mjs";
|
import "./tests/ParseObjectIDTimestamp.mjs";
|
||||||
import "./tests/Unicode.mjs";
|
import "./tests/Unicode.mjs";
|
||||||
|
import "./tests/RSA.mjs";
|
||||||
|
|
||||||
// Cannot test operations that use the File type yet
|
// Cannot test operations that use the File type yet
|
||||||
// import "./tests/SplitColourChannels.mjs";
|
// import "./tests/SplitColourChannels.mjs";
|
||||||
// Cannot test as minified forge does not support node
|
|
||||||
// import "./tests/RSA.mjs";
|
|
||||||
const testStatus = {
|
const testStatus = {
|
||||||
allTestsPassing: true,
|
allTestsPassing: true,
|
||||||
counts: {
|
counts: {
|
||||||
|
|
|
@ -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 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 UTF8_TEXT = "Шанцы на высвятленне таго, што адбываецца на самай справе ў сусвеце настолькі выдаленыя, адзінае, што трэба зрабіць, гэта павесіць пачуццё яго і трымаць сябе занятымі.";
|
||||||
|
|
|
@ -79,8 +79,8 @@ TestRegister.addTests([
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "RSA Encrypt/Decrypt: RSA-OAEP/SHA-1, UTF-8",
|
name: "RSA Encrypt/Decrypt: RSA-OAEP/SHA-1, UTF-8",
|
||||||
input: UTF8_TEXT,
|
input: UTF8_TEXT.substr(0, 100),
|
||||||
expectedOutput: UTF8_TEXT,
|
expectedOutput: UTF8_TEXT.substr(0, 100),
|
||||||
recipeConfig: [
|
recipeConfig: [
|
||||||
{
|
{
|
||||||
"op": "RSA Encrypt",
|
"op": "RSA Encrypt",
|
||||||
|
@ -94,8 +94,8 @@ TestRegister.addTests([
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "RSA Encrypt/Decrypt: RSA-OAEP/SHA-1, All bytes",
|
name: "RSA Encrypt/Decrypt: RSA-OAEP/SHA-1, All bytes",
|
||||||
input: ALL_BYTES,
|
input: ALL_BYTES.substr(0, 100),
|
||||||
expectedOutput: ALL_BYTES,
|
expectedOutput: ALL_BYTES.substr(0, 100),
|
||||||
recipeConfig: [
|
recipeConfig: [
|
||||||
{
|
{
|
||||||
"op": "RSA Encrypt",
|
"op": "RSA Encrypt",
|
||||||
|
@ -139,8 +139,8 @@ TestRegister.addTests([
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "RSA Encrypt/Decrypt: RSA-OAEP/MD5, UTF-8",
|
name: "RSA Encrypt/Decrypt: RSA-OAEP/MD5, UTF-8",
|
||||||
input: UTF8_TEXT,
|
input: UTF8_TEXT.substr(0, 100),
|
||||||
expectedOutput: UTF8_TEXT,
|
expectedOutput: UTF8_TEXT.substr(0, 100),
|
||||||
recipeConfig: [
|
recipeConfig: [
|
||||||
{
|
{
|
||||||
"op": "RSA Encrypt",
|
"op": "RSA Encrypt",
|
||||||
|
@ -154,8 +154,8 @@ TestRegister.addTests([
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "RSA Encrypt/Decrypt: RSA-OAEP/MD5, All bytes",
|
name: "RSA Encrypt/Decrypt: RSA-OAEP/MD5, All bytes",
|
||||||
input: ALL_BYTES,
|
input: ALL_BYTES.substr(0, 100),
|
||||||
expectedOutput: ALL_BYTES,
|
expectedOutput: ALL_BYTES.substr(0, 100),
|
||||||
recipeConfig: [
|
recipeConfig: [
|
||||||
{
|
{
|
||||||
"op": "RSA Encrypt",
|
"op": "RSA Encrypt",
|
||||||
|
@ -199,8 +199,8 @@ TestRegister.addTests([
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "RSA Encrypt/Decrypt: RSA-OAEP/SHA-256, UTF-8",
|
name: "RSA Encrypt/Decrypt: RSA-OAEP/SHA-256, UTF-8",
|
||||||
input: UTF8_TEXT,
|
input: UTF8_TEXT.substr(0, 100),
|
||||||
expectedOutput: UTF8_TEXT,
|
expectedOutput: UTF8_TEXT.substr(0, 100),
|
||||||
recipeConfig: [
|
recipeConfig: [
|
||||||
{
|
{
|
||||||
"op": "RSA Encrypt",
|
"op": "RSA Encrypt",
|
||||||
|
@ -214,8 +214,8 @@ TestRegister.addTests([
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "RSA Encrypt/Decrypt: RSA-OAEP/SHA-256, All bytes",
|
name: "RSA Encrypt/Decrypt: RSA-OAEP/SHA-256, All bytes",
|
||||||
input: ALL_BYTES,
|
input: ALL_BYTES.substr(0, 100),
|
||||||
expectedOutput: ALL_BYTES,
|
expectedOutput: ALL_BYTES.substr(0, 100),
|
||||||
recipeConfig: [
|
recipeConfig: [
|
||||||
{
|
{
|
||||||
"op": "RSA Encrypt",
|
"op": "RSA Encrypt",
|
||||||
|
@ -259,8 +259,8 @@ TestRegister.addTests([
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "RSA Encrypt/Decrypt: RSA-OAEP/SHA-384, UTF-8",
|
name: "RSA Encrypt/Decrypt: RSA-OAEP/SHA-384, UTF-8",
|
||||||
input: UTF8_TEXT,
|
input: UTF8_TEXT.substr(0, 80),
|
||||||
expectedOutput: UTF8_TEXT,
|
expectedOutput: UTF8_TEXT.substr(0, 80),
|
||||||
recipeConfig: [
|
recipeConfig: [
|
||||||
{
|
{
|
||||||
"op": "RSA Encrypt",
|
"op": "RSA Encrypt",
|
||||||
|
@ -274,8 +274,8 @@ TestRegister.addTests([
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "RSA Encrypt/Decrypt: RSA-OAEP/SHA-384, All bytes",
|
name: "RSA Encrypt/Decrypt: RSA-OAEP/SHA-384, All bytes",
|
||||||
input: ALL_BYTES,
|
input: ALL_BYTES.substr(0, 100),
|
||||||
expectedOutput: ALL_BYTES,
|
expectedOutput: ALL_BYTES.substr(0, 100),
|
||||||
recipeConfig: [
|
recipeConfig: [
|
||||||
{
|
{
|
||||||
"op": "RSA Encrypt",
|
"op": "RSA Encrypt",
|
||||||
|
@ -304,8 +304,8 @@ TestRegister.addTests([
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "RSA Encrypt/Decrypt: RSA-OAEP/SHA-512, ASCII",
|
name: "RSA Encrypt/Decrypt: RSA-OAEP/SHA-512, ASCII",
|
||||||
input: ASCII_TEXT,
|
input: ASCII_TEXT.substr(0, 100),
|
||||||
expectedOutput: ASCII_TEXT,
|
expectedOutput: ASCII_TEXT.substr(0, 100),
|
||||||
recipeConfig: [
|
recipeConfig: [
|
||||||
{
|
{
|
||||||
"op": "RSA Encrypt",
|
"op": "RSA Encrypt",
|
||||||
|
@ -319,8 +319,8 @@ TestRegister.addTests([
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "RSA Encrypt/Decrypt: RSA-OAEP/SHA-512, UTF-8",
|
name: "RSA Encrypt/Decrypt: RSA-OAEP/SHA-512, UTF-8",
|
||||||
input: UTF8_TEXT,
|
input: UTF8_TEXT.substr(0, 60),
|
||||||
expectedOutput: UTF8_TEXT,
|
expectedOutput: UTF8_TEXT.substr(0, 60),
|
||||||
recipeConfig: [
|
recipeConfig: [
|
||||||
{
|
{
|
||||||
"op": "RSA Encrypt",
|
"op": "RSA Encrypt",
|
||||||
|
@ -334,8 +334,8 @@ TestRegister.addTests([
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "RSA Encrypt/Decrypt: RSA-OAEP/SHA-512, All bytes",
|
name: "RSA Encrypt/Decrypt: RSA-OAEP/SHA-512, All bytes",
|
||||||
input: ALL_BYTES,
|
input: ALL_BYTES.substr(0, 100),
|
||||||
expectedOutput: ALL_BYTES,
|
expectedOutput: ALL_BYTES.substr(0, 100),
|
||||||
recipeConfig: [
|
recipeConfig: [
|
||||||
{
|
{
|
||||||
"op": "RSA Encrypt",
|
"op": "RSA Encrypt",
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue