Rewrote AES, DES and Triple DES operations to use Forge instead of CryptoJS, simplifying their options and adding many tests. Removed Rabbit operations. Fixes #63 and #210.

This commit is contained in:
n1474335 2018-01-01 16:09:58 +00:00
parent 87f346d88c
commit 9fc7e6cd98
9 changed files with 1509 additions and 385 deletions

15
package-lock.json generated
View file

@ -6500,10 +6500,9 @@
} }
}, },
"node-forge": { "node-forge": {
"version": "0.6.33", "version": "0.7.1",
"resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.6.33.tgz", "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.7.1.tgz",
"integrity": "sha1-RjgRh59XPUUVWtap9D3ClujoXrw=", "integrity": "sha1-naYR6giYL0uUIGs760zJZl8gwwA="
"dev": true
}, },
"node-libs-browser": { "node-libs-browser": {
"version": "2.1.0", "version": "2.1.0",
@ -8701,6 +8700,14 @@
"dev": true, "dev": true,
"requires": { "requires": {
"node-forge": "0.6.33" "node-forge": "0.6.33"
},
"dependencies": {
"node-forge": {
"version": "0.6.33",
"resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.6.33.tgz",
"integrity": "sha1-RjgRh59XPUUVWtap9D3ClujoXrw=",
"dev": true
}
} }
}, },
"semver": { "semver": {

View file

@ -91,6 +91,7 @@
"loglevel-message-prefix": "^3.0.0", "loglevel-message-prefix": "^3.0.0",
"moment": "^2.20.1", "moment": "^2.20.1",
"moment-timezone": "^0.5.14", "moment-timezone": "^0.5.14",
"node-forge": "^0.7.1",
"node-md6": "^0.1.0", "node-md6": "^0.1.0",
"nwmatcher": "^1.4.3", "nwmatcher": "^1.4.3",
"otp": "^0.1.3", "otp": "^0.1.3",

View file

@ -313,6 +313,39 @@ const Utils = {
}, },
/**
* Coverts data of varying types to a byte string.
* Accepts hex, Base64, UTF8 and Latin1 strings.
*
* @param {string} str
* @param {string} type - One of "Hex", "Base64", "UTF8" or "Latin1"
* @returns {string}
*
* @example
* // returns [208, 159, 209, 128, 208, 184, 208, 178, 208, 181, 209, 130]
* Utils.convertToByteArray("Привет", "utf8");
*
* // returns [208, 159, 209, 128, 208, 184, 208, 178, 208, 181, 209, 130]
* Utils.convertToByteArray("d097d0b4d180d0b0d0b2d181d182d0b2d183d0b9d182d0b5", "hex");
*
* // returns [208, 159, 209, 128, 208, 184, 208, 178, 208, 181, 209, 130]
* Utils.convertToByteArray("0JfQtNGA0LDQstGB0YLQstGD0LnRgtC1", "base64");
*/
convertToByteString: function(str, type) {
switch (type.toLowerCase()) {
case "hex":
return Utils.byteArrayToChars(Utils.fromHex(str));
case "base64":
return Utils.byteArrayToChars(Utils.fromBase64(str, null, "byteArray"));
case "utf8":
return utf8.encode(str);
case "latin1":
default:
return str;
}
},
/** /**
* Converts a string to a byte array. * Converts a string to a byte array.
* Treats the string as UTF-8 if any values are over 255. * Treats the string as UTF-8 if any values are over 255.

View file

@ -79,8 +79,6 @@ const Categories = [
"DES Decrypt", "DES Decrypt",
"Triple DES Encrypt", "Triple DES Encrypt",
"Triple DES Decrypt", "Triple DES Decrypt",
"Rabbit Encrypt",
"Rabbit Decrypt",
"RC4", "RC4",
"RC4 Drop", "RC4 Drop",
"ROT13", "ROT13",

View file

@ -1102,15 +1102,15 @@ const OperationConfig = {
}, },
"AES Decrypt": { "AES Decrypt": {
module: "Ciphers", module: "Ciphers",
description: "To successfully decrypt AES, you need either:<ul><li>The passphrase</li><li>Or the key and IV</li></ul>The IV should be the first 16 bytes of encrypted material.", description: "Advanced Encryption Standard (AES) is a U.S. Federal Information Processing Standard (FIPS). It was selected after a 5-year process where 15 competing designs were evaluated.<br><br><b>Key:</b> The following algorithms will be used based on the size of the key:<ul><li>16 bytes = AES-128</li><li>24 bytes = AES-192</li><li>32 bytes = AES-256</li></ul><br><br><b>IV:</b> The Initialization Vector should be 16 bytes long. If not entered, it will default to 16 null bytes.<br><br><b>Padding:</b> In CBC and ECB mode, PKCS#7 padding will be used.<br><br><b>GCM Tag:</b> This field is ignored unless 'GCM' mode is used.",
inputType: "string", inputType: "string",
outputType: "string", outputType: "string",
args: [ args: [
{ {
name: "Passphrase/Key", name: "Key",
type: "toggleString", type: "toggleString",
value: "", value: "",
toggleValues: Cipher.IO_FORMAT2 toggleValues: Cipher.IO_FORMAT1
}, },
{ {
name: "IV", name: "IV",
@ -1119,44 +1119,39 @@ const OperationConfig = {
toggleValues: Cipher.IO_FORMAT1 toggleValues: Cipher.IO_FORMAT1
}, },
{ {
name: "Salt", name: "Mode",
type: "option",
value: Cipher.AES_MODES
},
{
name: "Input",
type: "option",
value: Cipher.IO_FORMAT3
},
{
name: "Output",
type: "option",
value: Cipher.IO_FORMAT2
},
{
name: "GCM Tag",
type: "toggleString", type: "toggleString",
value: "", value: "",
toggleValues: Cipher.IO_FORMAT1 toggleValues: Cipher.IO_FORMAT1
}, },
{
name: "Mode",
type: "option",
value: Cipher.MODES
},
{
name: "Padding",
type: "option",
value: Cipher.PADDING
},
{
name: "Input format",
type: "option",
value: Cipher.IO_FORMAT1
},
{
name: "Output format",
type: "option",
value: Cipher.IO_FORMAT2
},
] ]
}, },
"AES Encrypt": { "AES Encrypt": {
module: "Ciphers", module: "Ciphers",
description: "Input: Either enter a passphrase (which will be used to derive a key using the OpenSSL KDF) or both the key and IV.<br><br>Advanced Encryption Standard (AES) is a U.S. Federal Information Processing Standard (FIPS). It was selected after a 5-year process where 15 competing designs were evaluated.<br><br>AES-128, AES-192, and AES-256 are supported. The variant will be chosen based on the size of the key passed in. If a passphrase is used, a 256-bit key will be generated.", description: "Advanced Encryption Standard (AES) is a U.S. Federal Information Processing Standard (FIPS). It was selected after a 5-year process where 15 competing designs were evaluated.<br><br><b>Key:</b> The following algorithms will be used based on the size of the key:<ul><li>16 bytes = AES-128</li><li>24 bytes = AES-192</li><li>32 bytes = AES-256</li></ul>You can generate a password-based key using one of the KDF operations.<br><br><b>IV:</b> The Initialization Vector should be 16 bytes long. If not entered, it will default to 16 null bytes.<br><br><b>Padding:</b> In CBC and ECB mode, PKCS#7 padding will be used.",
inputType: "string", inputType: "string",
outputType: "string", outputType: "string",
args: [ args: [
{ {
name: "Passphrase/Key", name: "Key",
type: "toggleString", type: "toggleString",
value: "", value: "",
toggleValues: Cipher.IO_FORMAT2 toggleValues: Cipher.IO_FORMAT1
}, },
{ {
name: "IV", name: "IV",
@ -1164,55 +1159,37 @@ const OperationConfig = {
value: "", value: "",
toggleValues: Cipher.IO_FORMAT1 toggleValues: Cipher.IO_FORMAT1
}, },
{
name: "Salt",
type: "toggleString",
value: "",
toggleValues: Cipher.IO_FORMAT1
},
{ {
name: "Mode", name: "Mode",
type: "option", type: "option",
value: Cipher.MODES value: Cipher.AES_MODES
}, },
{ {
name: "Padding", name: "Input",
type: "option", type: "option",
value: Cipher.PADDING value: Cipher.IO_FORMAT2
}, },
{ {
name: "Output result", name: "Output",
type: "option", type: "option",
value: Cipher.RESULT_TYPE value: Cipher.IO_FORMAT3
},
{
name: "Output format",
type: "option",
value: Cipher.IO_FORMAT1
}, },
] ]
}, },
"DES Decrypt": { "DES Decrypt": {
module: "Ciphers", module: "Ciphers",
description: "To successfully decrypt DES, you need either:<ul><li>The passphrase</li><li>Or the key and IV</li></ul>The IV should be the first 8 bytes of encrypted material.", description: "DES is a previously dominant algorithm for encryption, and was published as an official U.S. Federal Information Processing Standard (FIPS). It is now considered to be insecure due to its small key size.<br><br><b>Key:</b> DES uses a key length of 8 bytes (64 bits).<br>Triple DES uses a key length of 24 bytes (192 bits).<br><br><b>IV:</b> The Initialization Vector should be 8 bytes long. If not entered, it will default to 8 null bytes.<br><br><b>Padding:</b> In CBC and ECB mode, PKCS#7 padding will be used.",
inputType: "string", inputType: "string",
outputType: "string", outputType: "string",
args: [ args: [
{ {
name: "Passphrase/Key", name: "Key",
type: "toggleString",
value: "",
toggleValues: Cipher.IO_FORMAT2
},
{
name: "IV",
type: "toggleString", type: "toggleString",
value: "", value: "",
toggleValues: Cipher.IO_FORMAT1 toggleValues: Cipher.IO_FORMAT1
}, },
{ {
name: "Salt", name: "IV",
type: "toggleString", type: "toggleString",
value: "", value: "",
toggleValues: Cipher.IO_FORMAT1 toggleValues: Cipher.IO_FORMAT1
@ -1220,20 +1197,15 @@ const OperationConfig = {
{ {
name: "Mode", name: "Mode",
type: "option", type: "option",
value: Cipher.MODES value: Cipher.DES_MODES
}, },
{ {
name: "Padding", name: "Input",
type: "option", type: "option",
value: Cipher.PADDING value: Cipher.IO_FORMAT3
}, },
{ {
name: "Input format", name: "Output",
type: "option",
value: Cipher.IO_FORMAT1
},
{
name: "Output format",
type: "option", type: "option",
value: Cipher.IO_FORMAT2 value: Cipher.IO_FORMAT2
}, },
@ -1241,25 +1213,18 @@ const OperationConfig = {
}, },
"DES Encrypt": { "DES Encrypt": {
module: "Ciphers", module: "Ciphers",
description: "Input: Either enter a passphrase (which will be used to derive a key using the OpenSSL KDF) or both the key and IV.<br><br>DES is a previously dominant algorithm for encryption, and was published as an official U.S. Federal Information Processing Standard (FIPS). It is now considered to be insecure due to its small key size.", description: "DES is a previously dominant algorithm for encryption, and was published as an official U.S. Federal Information Processing Standard (FIPS). It is now considered to be insecure due to its small key size.<br><br><b>Key:</b> DES uses a key length of 8 bytes (64 bits).<br>Triple DES uses a key length of 24 bytes (192 bits).<br><br>You can generate a password-based key using one of the KDF operations.<br><br><b>IV:</b> The Initialization Vector should be 8 bytes long. If not entered, it will default to 8 null bytes.<br><br><b>Padding:</b> In CBC and ECB mode, PKCS#7 padding will be used.",
inputType: "string", inputType: "string",
outputType: "string", outputType: "string",
args: [ args: [
{ {
name: "Passphrase/Key", name: "Key",
type: "toggleString",
value: "",
toggleValues: Cipher.IO_FORMAT2
},
{
name: "IV",
type: "toggleString", type: "toggleString",
value: "", value: "",
toggleValues: Cipher.IO_FORMAT1 toggleValues: Cipher.IO_FORMAT1
}, },
{ {
name: "Salt", name: "IV",
type: "toggleString", type: "toggleString",
value: "", value: "",
toggleValues: Cipher.IO_FORMAT1 toggleValues: Cipher.IO_FORMAT1
@ -1267,46 +1232,34 @@ const OperationConfig = {
{ {
name: "Mode", name: "Mode",
type: "option", type: "option",
value: Cipher.MODES value: Cipher.DES_MODES
}, },
{ {
name: "Padding", name: "Input",
type: "option", type: "option",
value: Cipher.PADDING value: Cipher.IO_FORMAT2
}, },
{ {
name: "Output result", name: "Output",
type: "option", type: "option",
value: Cipher.RESULT_TYPE value: Cipher.IO_FORMAT3
},
{
name: "Output format",
type: "option",
value: Cipher.IO_FORMAT1
}, },
] ]
}, },
"Triple DES Decrypt": { "Triple DES Decrypt": {
module: "Ciphers", module: "Ciphers",
description: "To successfully decrypt Triple DES, you need either:<ul><li>The passphrase</li><li>Or the key and IV</li></ul>The IV should be the first 8 bytes of encrypted material.", description: "Triple DES applies DES three times to each block to increase key size.<br><br><b>Key:</b> Triple DES uses a key length of 24 bytes (192 bits).<br>DES uses a key length of 8 bytes (64 bits).<br><br><b>IV:</b> The Initialization Vector should be 8 bytes long. If not entered, it will default to 8 null bytes.<br><br><b>Padding:</b> In CBC and ECB mode, PKCS#7 padding will be used.",
inputType: "string", inputType: "string",
outputType: "string", outputType: "string",
args: [ args: [
{ {
name: "Passphrase/Key", name: "Key",
type: "toggleString",
value: "",
toggleValues: Cipher.IO_FORMAT2
},
{
name: "IV",
type: "toggleString", type: "toggleString",
value: "", value: "",
toggleValues: Cipher.IO_FORMAT1 toggleValues: Cipher.IO_FORMAT1
}, },
{ {
name: "Salt", name: "IV",
type: "toggleString", type: "toggleString",
value: "", value: "",
toggleValues: Cipher.IO_FORMAT1 toggleValues: Cipher.IO_FORMAT1
@ -1314,20 +1267,15 @@ const OperationConfig = {
{ {
name: "Mode", name: "Mode",
type: "option", type: "option",
value: Cipher.MODES value: Cipher.DES_MODES
}, },
{ {
name: "Padding", name: "Input",
type: "option", type: "option",
value: Cipher.PADDING value: Cipher.IO_FORMAT3
}, },
{ {
name: "Input format", name: "Output",
type: "option",
value: Cipher.IO_FORMAT1
},
{
name: "Output format",
type: "option", type: "option",
value: Cipher.IO_FORMAT2 value: Cipher.IO_FORMAT2
}, },
@ -1335,25 +1283,18 @@ const OperationConfig = {
}, },
"Triple DES Encrypt": { "Triple DES Encrypt": {
module: "Ciphers", module: "Ciphers",
description: "Input: Either enter a passphrase (which will be used to derive a key using the OpenSSL KDF) or both the key and IV.<br><br>Triple DES applies DES three times to each block to increase key size.", description: "Triple DES applies DES three times to each block to increase key size.<br><br><b>Key:</b> Triple DES uses a key length of 24 bytes (192 bits).<br>DES uses a key length of 8 bytes (64 bits).<br><br>You can generate a password-based key using one of the KDF operations.<br><br><b>IV:</b> The Initialization Vector should be 8 bytes long. If not entered, it will default to 8 null bytes.<br><br><b>Padding:</b> In CBC and ECB mode, PKCS#7 padding will be used.",
inputType: "string", inputType: "string",
outputType: "string", outputType: "string",
args: [ args: [
{ {
name: "Passphrase/Key", name: "Key",
type: "toggleString",
value: "",
toggleValues: Cipher.IO_FORMAT2
},
{
name: "IV",
type: "toggleString", type: "toggleString",
value: "", value: "",
toggleValues: Cipher.IO_FORMAT1 toggleValues: Cipher.IO_FORMAT1
}, },
{ {
name: "Salt", name: "IV",
type: "toggleString", type: "toggleString",
value: "", value: "",
toggleValues: Cipher.IO_FORMAT1 toggleValues: Cipher.IO_FORMAT1
@ -1361,22 +1302,17 @@ const OperationConfig = {
{ {
name: "Mode", name: "Mode",
type: "option", type: "option",
value: Cipher.MODES value: Cipher.DES_MODES
}, },
{ {
name: "Padding", name: "Input",
type: "option", type: "option",
value: Cipher.PADDING value: Cipher.IO_FORMAT2
}, },
{ {
name: "Output result", name: "Output",
type: "option", type: "option",
value: Cipher.RESULT_TYPE value: Cipher.IO_FORMAT3
},
{
name: "Output format",
type: "option",
value: Cipher.IO_FORMAT1
}, },
] ]
}, },
@ -1390,7 +1326,7 @@ const OperationConfig = {
name: "Key", name: "Key",
type: "toggleString", type: "toggleString",
value: "", value: "",
toggleValues: Cipher.IO_FORMAT2 toggleValues: Cipher.CJS_IO_FORMAT
}, },
{ {
name: "Mode", name: "Mode",
@ -1400,7 +1336,7 @@ const OperationConfig = {
{ {
name: "Input format", name: "Input format",
type: "option", type: "option",
value: Cipher.IO_FORMAT3 value: Cipher.IO_FORMAT1
}, },
] ]
}, },
@ -1414,107 +1350,13 @@ const OperationConfig = {
name: "Key", name: "Key",
type: "toggleString", type: "toggleString",
value: "", value: "",
toggleValues: Cipher.IO_FORMAT2 toggleValues: Cipher.CJS_IO_FORMAT
}, },
{ {
name: "Mode", name: "Mode",
type: "option", type: "option",
value: Cipher.BLOWFISH_MODES value: Cipher.BLOWFISH_MODES
}, },
{
name: "Output format",
type: "option",
value: Cipher.IO_FORMAT3
},
]
},
"Rabbit Decrypt": {
module: "Ciphers",
description: "To successfully decrypt Rabbit, you need either:<ul><li>The passphrase</li><li>Or the key and IV (This is currently broken. You need the key and salt at the moment.)</li></ul>The IV should be the first 8 bytes of encrypted material.",
inputType: "string",
outputType: "string",
args: [
{
name: "Passphrase/Key",
type: "toggleString",
value: "",
toggleValues: Cipher.IO_FORMAT2
},
{
name: "IV",
type: "toggleString",
value: "",
toggleValues: Cipher.IO_FORMAT1
},
{
name: "Salt",
type: "toggleString",
value: "",
toggleValues: Cipher.IO_FORMAT1
},
{
name: "Mode",
type: "option",
value: Cipher.MODES
},
{
name: "Padding",
type: "option",
value: Cipher.PADDING
},
{
name: "Input format",
type: "option",
value: Cipher.IO_FORMAT1
},
{
name: "Output format",
type: "option",
value: Cipher.IO_FORMAT2
},
]
},
"Rabbit Encrypt": {
module: "Ciphers",
description: "Input: Either enter a passphrase (which will be used to derive a key using the OpenSSL KDF) or both the key and IV.<br><br>Rabbit is a high-performance stream cipher and a finalist in the eSTREAM Portfolio. It is one of the four designs selected after a 3 1/2 year process where 22 designs were evaluated.",
inputType: "string",
outputType: "string",
args: [
{
name: "Passphrase/Key",
type: "toggleString",
value: "",
toggleValues: Cipher.IO_FORMAT2
},
{
name: "IV",
type: "toggleString",
value: "",
toggleValues: Cipher.IO_FORMAT1
},
{
name: "Salt",
type: "toggleString",
value: "",
toggleValues: Cipher.IO_FORMAT1
},
{
name: "Mode",
type: "option",
value: Cipher.MODES
},
{
name: "Padding",
type: "option",
value: Cipher.PADDING
},
{
name: "Output result",
type: "option",
value: Cipher.RESULT_TYPE
},
{ {
name: "Output format", name: "Output format",
type: "option", type: "option",
@ -1534,17 +1376,17 @@ const OperationConfig = {
name: "Passphrase", name: "Passphrase",
type: "toggleString", type: "toggleString",
value: "", value: "",
toggleValues: Cipher.IO_FORMAT2 toggleValues: Cipher.RC4_KEY_FORMAT
}, },
{ {
name: "Input format", name: "Input format",
type: "option", type: "option",
value: Cipher.IO_FORMAT4 value: Cipher.CJS_IO_FORMAT
}, },
{ {
name: "Output format", name: "Output format",
type: "option", type: "option",
value: Cipher.IO_FORMAT4 value: Cipher.CJS_IO_FORMAT
}, },
] ]
}, },
@ -1560,17 +1402,17 @@ const OperationConfig = {
name: "Passphrase", name: "Passphrase",
type: "toggleString", type: "toggleString",
value: "", value: "",
toggleValues: Cipher.IO_FORMAT2 toggleValues: Cipher.RC4_KEY_FORMAT
}, },
{ {
name: "Input format", name: "Input format",
type: "option", type: "option",
value: Cipher.IO_FORMAT4 value: Cipher.CJS_IO_FORMAT
}, },
{ {
name: "Output format", name: "Output format",
type: "option", type: "option",
value: Cipher.IO_FORMAT4 value: Cipher.CJS_IO_FORMAT
}, },
{ {
name: "Number of bytes to drop", name: "Number of bytes to drop",
@ -1608,12 +1450,12 @@ const OperationConfig = {
{ {
name: "Input format", name: "Input format",
type: "option", type: "option",
value: Cipher.IO_FORMAT2 value: Cipher.CJS_IO_FORMAT
}, },
{ {
name: "Output format", name: "Output format",
type: "option", type: "option",
value: Cipher.IO_FORMAT3 value: Cipher.IO_FORMAT1
}, },
] ]
}, },
@ -1646,12 +1488,12 @@ const OperationConfig = {
{ {
name: "Input format", name: "Input format",
type: "option", type: "option",
value: Cipher.IO_FORMAT2 value: Cipher.CJS_IO_FORMAT
}, },
{ {
name: "Output format", name: "Output format",
type: "option", type: "option",
value: Cipher.IO_FORMAT3 value: Cipher.IO_FORMAT1
}, },
] ]
}, },

View file

@ -6,7 +6,6 @@ import CharEnc from "../../operations/CharEnc.js";
* *
* Libraries: * Libraries:
* - cptable * - cptable
* - CryptoJS
* *
* @author n1474335 [n1474335@gmail.com] * @author n1474335 [n1474335@gmail.com]
* @copyright Crown Copyright 2017 * @copyright Crown Copyright 2017

View file

@ -7,6 +7,7 @@ import Cipher from "../../operations/Cipher.js";
* Libraries: * Libraries:
* - CryptoJS * - CryptoJS
* - Blowfish * - Blowfish
* - Forge
* *
* @author n1474335 [n1474335@gmail.com] * @author n1474335 [n1474335@gmail.com]
* @copyright Crown Copyright 2017 * @copyright Crown Copyright 2017
@ -23,8 +24,6 @@ OpModules.Ciphers = {
"DES Decrypt": Cipher.runDesDec, "DES Decrypt": Cipher.runDesDec,
"Triple DES Encrypt": Cipher.runTripleDesEnc, "Triple DES Encrypt": Cipher.runTripleDesEnc,
"Triple DES Decrypt": Cipher.runTripleDesDec, "Triple DES Decrypt": Cipher.runTripleDesDec,
"Rabbit Encrypt": Cipher.runRabbitEnc,
"Rabbit Decrypt": Cipher.runRabbitDec,
"Derive PBKDF2 key": Cipher.runPbkdf2, "Derive PBKDF2 key": Cipher.runPbkdf2,
"Derive EVP key": Cipher.runEvpkdf, "Derive EVP key": Cipher.runEvpkdf,
"RC4": Cipher.runRc4, "RC4": Cipher.runRc4,

View file

@ -1,5 +1,6 @@
import Utils from "../Utils.js"; import Utils from "../Utils.js";
import CryptoJS from "crypto-js"; import CryptoJS from "crypto-js";
import forge from "imports-loader?jQuery=>null!node-forge/dist/forge.min.js";
import {blowfish as Blowfish} from "sladex-blowfish"; import {blowfish as Blowfish} from "sladex-blowfish";
@ -18,132 +19,22 @@ const Cipher = {
* @constant * @constant
* @default * @default
*/ */
IO_FORMAT1: ["Hex", "Base64", "UTF8", "UTF16", "UTF16LE", "UTF16BE", "Latin1"], IO_FORMAT1: ["Hex", "UTF8", "Latin1", "Base64"],
/** /**
* @constant * @constant
* @default * @default
*/ */
IO_FORMAT2: ["UTF8", "UTF16", "UTF16LE", "UTF16BE", "Latin1", "Hex", "Base64"], IO_FORMAT2: ["Raw", "Hex"],
/** /**
* @constant * @constant
* @default * @default
*/ */
IO_FORMAT3: ["Hex", "Base64", "UTF16", "UTF16LE", "UTF16BE", "Latin1"], IO_FORMAT3: ["Hex", "Raw"],
/** /**
* @constant * @constant
* @default * @default
*/ */
IO_FORMAT4: ["Latin1", "UTF8", "UTF16", "UTF16LE", "UTF16BE", "Hex", "Base64"], AES_MODES: ["CBC", "CFB", "OFB", "CTR", "GCM", "ECB"],
/**
* @constant
* @default
*/
MODES: ["CBC", "CFB", "CTR", "OFB", "ECB"],
/**
* @constant
* @default
*/
PADDING: ["Pkcs7", "Iso97971", "AnsiX923", "Iso10126", "ZeroPadding", "NoPadding"],
/**
* @constant
* @default
*/
RESULT_TYPE: ["Show all", "Ciphertext", "Key", "IV", "Salt"],
/**
* Runs encryption operations using the CryptoJS framework.
*
* @private
* @param {function} algo - The CryptoJS algorithm to use
* @param {byteArray} input
* @param {function} args
* @returns {string}
*/
_enc: function (algo, input, args) {
let key = Cipher._format[args[0].option].parse(args[0].string || ""),
iv = Cipher._format[args[1].option].parse(args[1].string || ""),
salt = Cipher._format[args[2].option].parse(args[2].string || ""),
mode = CryptoJS.mode[args[3]],
padding = CryptoJS.pad[args[4]],
resultOption = args[5].toLowerCase(),
outputFormat = args[6];
if (iv.sigBytes === 0) {
// Use passphrase rather than key. Need to convert it to a string.
key = key.toString(CryptoJS.enc.Latin1);
}
const encrypted = algo.encrypt(input, key, {
salt: salt.sigBytes > 0 ? salt : false,
iv: iv.sigBytes > 0 ? iv : null,
mode: mode,
padding: padding
});
let result = "";
if (resultOption === "show all") {
result += "Key: " + encrypted.key.toString(Cipher._format[outputFormat]);
result += "\nIV: " + encrypted.iv.toString(Cipher._format[outputFormat]);
if (encrypted.salt) result += "\nSalt: " + encrypted.salt.toString(Cipher._format[outputFormat]);
result += "\n\nCiphertext: " + encrypted.ciphertext.toString(Cipher._format[outputFormat]);
} else {
result = encrypted[resultOption].toString(Cipher._format[outputFormat]);
}
return result;
},
/**
* Runs decryption operations using the CryptoJS framework.
*
* @private
* @param {function} algo - The CryptoJS algorithm to use
* @param {byteArray} input
* @param {function} args
* @returns {string}
*/
_dec: function (algo, input, args) {
let key = Cipher._format[args[0].option].parse(args[0].string || ""),
iv = Cipher._format[args[1].option].parse(args[1].string || ""),
salt = Cipher._format[args[2].option].parse(args[2].string || ""),
mode = CryptoJS.mode[args[3]],
padding = CryptoJS.pad[args[4]],
inputFormat = args[5],
outputFormat = args[6];
// The ZeroPadding option causes a crash when the input length is 0
if (!input.length) {
return "No input";
}
const ciphertext = Cipher._format[inputFormat].parse(input);
if (iv.sigBytes === 0) {
// Use passphrase rather than key. Need to convert it to a string.
key = key.toString(CryptoJS.enc.Latin1);
}
const decrypted = algo.decrypt({
ciphertext: ciphertext,
salt: salt.sigBytes > 0 ? salt : false
}, key, {
iv: iv.sigBytes > 0 ? iv : null,
mode: mode,
padding: padding
});
let result;
try {
result = decrypted.toString(Cipher._format[outputFormat]);
} catch (err) {
result = "Decrypt error: " + err.message;
}
return result;
},
/** /**
* AES Encrypt operation. * AES Encrypt operation.
@ -153,7 +44,41 @@ const Cipher = {
* @returns {string} * @returns {string}
*/ */
runAesEnc: function (input, args) { runAesEnc: function (input, args) {
return Cipher._enc(CryptoJS.AES, input, args); const key = Utils.convertToByteArray(args[0].string, args[0].option),
iv = Utils.convertToByteArray(args[1].string, args[1].option),
mode = args[2],
inputType = args[3],
outputType = args[4];
if ([16, 24, 32].indexOf(key.length) < 0) {
return `Invalid key length: ${key.length} bytes
The following algorithms will be used based on the size of the key:
16 bytes = AES-128
24 bytes = AES-192
32 bytes = AES-256`;
}
input = Utils.convertToByteString(input, inputType);
const cipher = forge.cipher.createCipher("AES-" + mode, key);
cipher.start({iv: iv});
cipher.update(forge.util.createBuffer(input));
cipher.finish();
if (outputType === "Hex") {
if (mode === "GCM") {
return cipher.output.toHex() + "\n\n" +
"Tag: " + cipher.mode.tag.toHex();
}
return cipher.output.toHex();
} else {
if (mode === "GCM") {
return cipher.output.getBytes() + "\n\n" +
"Tag: " + cipher.mode.tag.getBytes();
}
return cipher.output.getBytes();
}
}, },
@ -165,10 +90,46 @@ const Cipher = {
* @returns {string} * @returns {string}
*/ */
runAesDec: function (input, args) { runAesDec: function (input, args) {
return Cipher._dec(CryptoJS.AES, input, args); const key = Utils.convertToByteArray(args[0].string, args[0].option),
iv = Utils.convertToByteArray(args[1].string, args[1].option),
mode = args[2],
inputType = args[3],
outputType = args[4],
gcmTag = Utils.convertToByteString(args[5].string, args[5].option);
if ([16, 24, 32].indexOf(key.length) < 0) {
return `Invalid key length: ${key.length} bytes
The following algorithms will be used based on the size of the key:
16 bytes = AES-128
24 bytes = AES-192
32 bytes = AES-256`;
}
input = Utils.convertToByteString(input, inputType);
const decipher = forge.cipher.createDecipher("AES-" + mode, key);
decipher.start({
iv: iv,
tag: gcmTag
});
decipher.update(forge.util.createBuffer(input));
const result = decipher.finish();
if (result) {
return outputType === "Hex" ? decipher.output.toHex() : decipher.output.getBytes();
} else {
return "Unable to decrypt input with these parameters.";
}
}, },
/**
* @constant
* @default
*/
DES_MODES: ["CBC", "CFB", "OFB", "CTR", "ECB"],
/** /**
* DES Encrypt operation. * DES Encrypt operation.
* *
@ -177,7 +138,27 @@ const Cipher = {
* @returns {string} * @returns {string}
*/ */
runDesEnc: function (input, args) { runDesEnc: function (input, args) {
return Cipher._enc(CryptoJS.DES, input, args); const key = Utils.convertToByteString(args[0].string, args[0].option),
iv = Utils.convertToByteArray(args[1].string, args[1].option),
mode = args[2],
inputType = args[3],
outputType = args[4];
if (key.length !== 8) {
return `Invalid key length: ${key.length} bytes
DES uses a key length of 8 bytes (64 bits).
Triple DES uses a key length of 24 bytes (192 bits).`;
}
input = Utils.convertToByteString(input, inputType);
const cipher = forge.cipher.createCipher("DES-" + mode, key);
cipher.start({iv: iv});
cipher.update(forge.util.createBuffer(input));
cipher.finish();
return outputType === "Hex" ? cipher.output.toHex() : cipher.output.getBytes();
}, },
@ -189,7 +170,31 @@ const Cipher = {
* @returns {string} * @returns {string}
*/ */
runDesDec: function (input, args) { runDesDec: function (input, args) {
return Cipher._dec(CryptoJS.DES, input, args); const key = Utils.convertToByteString(args[0].string, args[0].option),
iv = Utils.convertToByteArray(args[1].string, args[1].option),
mode = args[2],
inputType = args[3],
outputType = args[4];
if (key.length !== 8) {
return `Invalid key length: ${key.length} bytes
DES uses a key length of 8 bytes (64 bits).
Triple DES uses a key length of 24 bytes (192 bits).`;
}
input = Utils.convertToByteString(input, inputType);
const decipher = forge.cipher.createDecipher("DES-" + mode, key);
decipher.start({iv: iv});
decipher.update(forge.util.createBuffer(input));
const result = decipher.finish();
if (result) {
return outputType === "Hex" ? decipher.output.toHex() : decipher.output.getBytes();
} else {
return "Unable to decrypt input with these parameters.";
}
}, },
@ -201,7 +206,27 @@ const Cipher = {
* @returns {string} * @returns {string}
*/ */
runTripleDesEnc: function (input, args) { runTripleDesEnc: function (input, args) {
return Cipher._enc(CryptoJS.TripleDES, input, args); const key = Utils.convertToByteString(args[0].string, args[0].option),
iv = Utils.convertToByteArray(args[1].string, args[1].option),
mode = args[2],
inputType = args[3],
outputType = args[4];
if (key.length !== 24) {
return `Invalid key length: ${key.length} bytes
Triple DES uses a key length of 24 bytes (192 bits).
DES uses a key length of 8 bytes (64 bits).`;
}
input = Utils.convertToByteString(input, inputType);
const cipher = forge.cipher.createCipher("3DES-" + mode, key);
cipher.start({iv: iv});
cipher.update(forge.util.createBuffer(input));
cipher.finish();
return outputType === "Hex" ? cipher.output.toHex() : cipher.output.getBytes();
}, },
@ -213,31 +238,31 @@ const Cipher = {
* @returns {string} * @returns {string}
*/ */
runTripleDesDec: function (input, args) { runTripleDesDec: function (input, args) {
return Cipher._dec(CryptoJS.TripleDES, input, args); const key = Utils.convertToByteString(args[0].string, args[0].option),
}, iv = Utils.convertToByteArray(args[1].string, args[1].option),
mode = args[2],
inputType = args[3],
outputType = args[4];
if (key.length !== 24) {
return `Invalid key length: ${key.length} bytes
/** Triple DES uses a key length of 24 bytes (192 bits).
* Rabbit Encrypt operation. DES uses a key length of 8 bytes (64 bits).`;
* }
* @param {string} input
* @param {Object[]} args
* @returns {string}
*/
runRabbitEnc: function (input, args) {
return Cipher._enc(CryptoJS.Rabbit, input, args);
},
input = Utils.convertToByteString(input, inputType);
/** const decipher = forge.cipher.createDecipher("3DES-" + mode, key);
* Rabbit Decrypt operation. decipher.start({iv: iv});
* decipher.update(forge.util.createBuffer(input));
* @param {string} input const result = decipher.finish();
* @param {Object[]} args
* @returns {string} if (result) {
*/ return outputType === "Hex" ? decipher.output.toHex() : decipher.output.getBytes();
runRabbitDec: function (input, args) { } else {
return Cipher._dec(CryptoJS.Rabbit, input, args); return "Unable to decrypt input with these parameters.";
}
}, },
@ -365,6 +390,18 @@ const Cipher = {
}, },
/**
* @constant
* @default
*/
RC4_KEY_FORMAT: ["UTF8", "UTF16", "UTF16LE", "UTF16BE", "Latin1", "Hex", "Base64"],
/**
* @constant
* @default
*/
CJS_IO_FORMAT: ["Latin1", "UTF8", "UTF16", "UTF16LE", "UTF16BE", "Hex", "Base64"],
/** /**
* RC4 operation. * RC4 operation.
* *

File diff suppressed because it is too large Load diff