Tidied up SM4 ops and NoPadding options for AES, DES and TripleDES

This commit is contained in:
n1474335 2022-03-29 18:01:57 +01:00
parent 31e9d27f1a
commit 8117926ca3
8 changed files with 26 additions and 15 deletions

View file

@ -83,12 +83,12 @@
"RC2 Decrypt",
"RC4",
"RC4 Drop",
"SM4 Encrypt",
"SM4 Decrypt",
"ROT13",
"ROT47",
"XOR",
"XOR Brute Force",
"SM4 Encrypt",
"SM4 Decrypt",
"Vigenère Encode",
"Vigenère Decode",
"To Morse Code",

View file

@ -38,7 +38,8 @@ const Sbox = [
0x8d, 0x1b, 0xaf, 0x92, 0xbb, 0xdd, 0xbc, 0x7f, 0x11, 0xd9, 0x5c, 0x41, 0x1f, 0x10, 0x5a, 0xd8,
0x0a, 0xc1, 0x31, 0x88, 0xa5, 0xcd, 0x7b, 0xbd, 0x2d, 0x74, 0xd0, 0x12, 0xb8, 0xe5, 0xb4, 0xb0,
0x89, 0x69, 0x97, 0x4a, 0x0c, 0x96, 0x77, 0x7e, 0x65, 0xb9, 0xf1, 0x09, 0xc5, 0x6e, 0xc6, 0x84,
0x18, 0xf0, 0x7d, 0xec, 0x3a, 0xdc, 0x4d, 0x20, 0x79, 0xee, 0x5f, 0x3e, 0xd7, 0xcb, 0x39, 0x48];
0x18, 0xf0, 0x7d, 0xec, 0x3a, 0xdc, 0x4d, 0x20, 0x79, 0xee, 0x5f, 0x3e, 0xd7, 0xcb, 0x39, 0x48
];
/** "Fixed parameter CK" used in key expansion */
const CK = [
@ -170,7 +171,7 @@ export function encryptSM4(message, key, iv, mode="ECB", noPadding=false) {
if (mode === "ECB" || mode === "CBC") {
if (noPadding) {
if (nPadding !== 16)
throw new OperationError("No padding requested in "+mode+" mode but input is not a 16-byte multiple.");
throw new OperationError(`No padding requested in ${mode} mode but input is not a 16-byte multiple.`);
nPadding = 0;
} else
padByte = nPadding;
@ -255,10 +256,11 @@ export function decryptSM4(cipherText, key, iv, mode="ECB", ignorePadding=false)
/* Init decryption key */
roundKey = roundKey.reverse();
if ((originalLength & 0xF) !== 0 && !ignorePadding)
throw new OperationError("With ECB or CBC modes, the input must be divisible into 16 byte blocks. ("+(cipherText.length & 0xF)+" bytes extra)");
} else /* Pad dummy bytes for other modes, chop them off at the end */
throw new OperationError(`With ECB or CBC modes, the input must be divisible into 16 byte blocks. (${cipherText.length & 0xF} bytes extra)`);
} else { /* Pad dummy bytes for other modes, chop them off at the end */
while ((cipherText.length & 0xF) !== 0)
cipherText.push(0);
}
const clearText = [];
switch (mode) {
@ -310,7 +312,7 @@ export function decryptSM4(cipherText, key, iv, mode="ECB", ignorePadding=false)
}
break;
default:
throw new OperationError("Invalid block cipher mode: "+mode);
throw new OperationError(`Invalid block cipher mode: ${mode}`);
}
/* Check PKCS#7 padding */
if (mode === "ECB" || mode === "CBC") {

View file

@ -113,6 +113,7 @@ class AESDecrypt extends Operation {
const key = Utils.convertToByteString(args[0].string, args[0].option),
iv = Utils.convertToByteString(args[1].string, args[1].option),
mode = args[2].substring(0, 3),
noPadding = args[2].endsWith("NoPadding"),
inputType = args[3],
outputType = args[4],
gcmTag = Utils.convertToByteString(args[5].string, args[5].option),
@ -130,12 +131,14 @@ The following algorithms will be used based on the size of the key:
input = Utils.convertToByteString(input, inputType);
const decipher = forge.cipher.createDecipher("AES-" + mode, key);
/* Allow for a "no padding" mode */
if (args[2].endsWith("NoPadding")) {
if (noPadding) {
decipher.mode.unpad = function(output, options) {
return true;
};
}
decipher.start({
iv: iv.length === 0 ? "" : iv,
tag: mode === "GCM" ? gcmTag : undefined,

View file

@ -66,6 +66,7 @@ class DESDecrypt extends Operation {
const key = Utils.convertToByteString(args[0].string, args[0].option),
iv = Utils.convertToByteArray(args[1].string, args[1].option),
mode = args[2].substring(0, 3),
noPadding = args[2].endsWith("NoPadding"),
[,,, inputType, outputType] = args;
if (key.length !== 8) {
@ -84,12 +85,14 @@ Make sure you have specified the type correctly (e.g. Hex vs UTF8).`);
input = Utils.convertToByteString(input, inputType);
const decipher = forge.cipher.createDecipher("DES-" + mode, key);
/* Allow for a "no padding" mode */
if (args[2].endsWith("NoPadding")) {
if (noPadding) {
decipher.mode.unpad = function(output, options) {
return true;
};
}
decipher.start({iv: iv});
decipher.update(forge.util.createBuffer(input));
const result = decipher.finish();

View file

@ -24,7 +24,7 @@ class SM4Decrypt extends Operation {
this.name = "SM4 Decrypt";
this.module = "Ciphers";
this.description = "SM4 is a 128-bit block cipher, currently established as a national standard (GB/T 32907-2016) of China.";
this.infoURL = "https://en.wikipedia.org/wiki/SM4_(cipher)";
this.infoURL = "https://wikipedia.org/wiki/SM4_(cipher)";
this.inputType = "string";
this.outputType = "string";
this.args = [

View file

@ -24,7 +24,7 @@ class SM4Encrypt extends Operation {
this.name = "SM4 Encrypt";
this.module = "Ciphers";
this.description = "SM4 is a 128-bit block cipher, currently established as a national standard (GB/T 32907-2016) of China. Multiple block cipher modes are supported. When using CBC or ECB mode, the PKCS#7 padding scheme is used.";
this.infoURL = "https://en.wikipedia.org/wiki/SM4_(cipher)";
this.infoURL = "https://wikipedia.org/wiki/SM4_(cipher)";
this.inputType = "string";
this.outputType = "string";
this.args = [

View file

@ -22,7 +22,7 @@ class TripleDESDecrypt extends Operation {
this.name = "Triple DES Decrypt";
this.module = "Ciphers";
this.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.";
this.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 as a default.";
this.infoURL = "https://wikipedia.org/wiki/Triple_DES";
this.inputType = "string";
this.outputType = "string";
@ -66,6 +66,7 @@ class TripleDESDecrypt extends Operation {
const key = Utils.convertToByteString(args[0].string, args[0].option),
iv = Utils.convertToByteArray(args[1].string, args[1].option),
mode = args[2].substring(0, 3),
noPadding = args[2].endsWith("NoPadding"),
inputType = args[3],
outputType = args[4];
@ -85,12 +86,14 @@ Make sure you have specified the type correctly (e.g. Hex vs UTF8).`);
input = Utils.convertToByteString(input, inputType);
const decipher = forge.cipher.createDecipher("3DES-" + mode, key);
/* Allow for a "no padding" mode */
if (args[2].endsWith("NoPadding")) {
if (noPadding) {
decipher.mode.unpad = function(output, options) {
return true;
};
}
decipher.start({iv: iv});
decipher.update(forge.util.createBuffer(input));
const result = decipher.finish();

View file

@ -119,7 +119,7 @@ TestRegister.addApiTests([
assert.strictEqual(result[0].module, "Ciphers");
assert.strictEqual(result[0].inputType, "string");
assert.strictEqual(result[0].outputType, "string");
assert.strictEqual(result[0].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.");
assert.strictEqual(result[0].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 as a default.");
assert.strictEqual(result[0].args.length, 5);
}),