Browse Source

Rewrote PBKDF2 operation to use Forge instead of CryptoJS and improved the API for both PBKDF2 and EVP operations.

n1474335 7 years ago
parent
commit
b58942f69a
2 changed files with 39 additions and 52 deletions
  1. 22 28
      src/core/config/OperationConfig.js
  2. 17 24
      src/core/operations/Cipher.js

+ 22 - 28
src/core/config/OperationConfig.js

@@ -1445,10 +1445,16 @@ const OperationConfig = {
     },
     "Derive PBKDF2 key": {
         module: "Ciphers",
-        description: "PBKDF2 is a password-based key derivation function. In many applications of cryptography, user security is ultimately dependent on a password, and because a password usually can't be used directly as a cryptographic key, some processing is required.<br><br>A salt provides a large set of keys for any given password, and an iteration count increases the cost of producing keys from a password, thereby also increasing the difficulty of attack.<br><br>Enter your passphrase as the input and then set the relevant options to generate a key.",
+        description: "PBKDF2 is a password-based key derivation function. It is part of RSA Laboratories' Public-Key Cryptography Standards (PKCS) series, specifically PKCS #5 v2.0, also published as Internet Engineering Task Force's RFC 2898.<br><br>In many applications of cryptography, user security is ultimately dependent on a password, and because a password usually can't be used directly as a cryptographic key, some processing is required.<br><br>A salt provides a large set of keys for any given password, and an iteration count increases the cost of producing keys from a password, thereby also increasing the difficulty of attack.<br><br>If you leave the salt argument empty, a random salt will be generated.",
         inputType: "string",
         outputType: "string",
         args: [
+            {
+                name: "Passphrase",
+                type: "toggleString",
+                value: "",
+                toggleValues: Cipher.IO_FORMAT2
+            },
             {
                 name: "Key size",
                 type: "number",
@@ -1465,28 +1471,25 @@ const OperationConfig = {
                 value: Cipher.HASHERS
             },
             {
-                name: "Salt (hex)",
-                type: "string",
-                value: ""
-            },
-            {
-                name: "Input format",
-                type: "option",
-                value: Cipher.CJS_IO_FORMAT
-            },
-            {
-                name: "Output format",
-                type: "option",
-                value: Cipher.IO_FORMAT1
+                name: "Salt",
+                type: "toggleString",
+                value: "",
+                toggleValues: Cipher.IO_FORMAT1
             },
         ]
     },
     "Derive EVP key": {
         module: "Ciphers",
-        description: "EVP is a password-based key derivation function used extensively in OpenSSL. In many applications of cryptography, user security is ultimately dependent on a password, and because a password usually can't be used directly as a cryptographic key, some processing is required.<br><br>A salt provides a large set of keys for any given password, and an iteration count increases the cost of producing keys from a password, thereby also increasing the difficulty of attack.<br><br>Enter your passphrase as the input and then set the relevant options to generate a key.",
+        description: "EVP is a password-based key derivation function (PBKDF) used extensively in OpenSSL. In many applications of cryptography, user security is ultimately dependent on a password, and because a password usually can't be used directly as a cryptographic key, some processing is required.<br><br>A salt provides a large set of keys for any given password, and an iteration count increases the cost of producing keys from a password, thereby also increasing the difficulty of attack.<br><br>If you leave the salt argument empty, a random salt will be generated.",
         inputType: "string",
         outputType: "string",
         args: [
+            {
+                name: "Passphrase",
+                type: "toggleString",
+                value: "",
+                toggleValues: Cipher.IO_FORMAT2
+            },
             {
                 name: "Key size",
                 type: "number",
@@ -1503,19 +1506,10 @@ const OperationConfig = {
                 value: Cipher.HASHERS
             },
             {
-                name: "Salt (hex)",
-                type: "string",
-                value: ""
-            },
-            {
-                name: "Input format",
-                type: "option",
-                value: Cipher.CJS_IO_FORMAT
-            },
-            {
-                name: "Output format",
-                type: "option",
-                value: Cipher.IO_FORMAT1
+                name: "Salt",
+                type: "toggleString",
+                value: "",
+                toggleValues: Cipher.IO_FORMAT1
             },
         ]
     },

+ 17 - 24
src/core/operations/Cipher.js

@@ -361,7 +361,7 @@ DES uses a key length of 8 bytes (64 bits).`;
      * @constant
      * @default
      */
-    KDF_KEY_SIZE: 256,
+    KDF_KEY_SIZE: 128,
     /**
      * @constant
      * @default
@@ -371,7 +371,7 @@ DES uses a key length of 8 bytes (64 bits).`;
      * @constant
      * @default
      */
-    HASHERS: ["MD5", "SHA1", "SHA224", "SHA256", "SHA384", "SHA512", "SHA3", "RIPEMD160"],
+    HASHERS: ["SHA1", "SHA256", "SHA384", "SHA512", "MD5"],
 
     /**
      * Derive PBKDF2 key operation.
@@ -381,20 +381,15 @@ DES uses a key length of 8 bytes (64 bits).`;
      * @returns {string}
      */
     runPbkdf2: function (input, args) {
-        let keySize = args[0] / 32,
-            iterations = args[1],
-            hasher = args[2],
-            salt = CryptoJS.enc.Hex.parse(args[3] || ""),
-            inputFormat = args[4],
-            outputFormat = args[5],
-            passphrase = Cipher._format[inputFormat].parse(input),
-            key = CryptoJS.PBKDF2(passphrase, salt, {
-                keySize: keySize,
-                hasher: CryptoJS.algo[hasher],
-                iterations: iterations,
-            });
-
-        return key.toString(Cipher._format[outputFormat]);
+        const passphrase = Utils.convertToByteString(args[0].string, args[0].option),
+            keySize = args[1],
+            iterations = args[2],
+            hasher = args[3],
+            salt = Utils.convertToByteString(args[4].string, args[4].option) ||
+                forge.random.getBytesSync(keySize),
+            derivedKey = forge.pkcs5.pbkdf2(passphrase, salt, iterations, keySize / 8, hasher.toLowerCase());
+
+        return Utils.toHexFast(Utils.strToCharcode(derivedKey));
     },
 
 
@@ -406,20 +401,18 @@ DES uses a key length of 8 bytes (64 bits).`;
      * @returns {string}
      */
     runEvpkdf: function (input, args) {
-        let keySize = args[0] / 32,
-            iterations = args[1],
-            hasher = args[2],
-            salt = CryptoJS.enc.Hex.parse(args[3] || ""),
-            inputFormat = args[4],
-            outputFormat = args[5],
-            passphrase = Cipher._format[inputFormat].parse(input),
+        const passphrase = Utils.convertToByteString(args[0].string, args[0].option),
+            keySize = args[1] / 32,
+            iterations = args[2],
+            hasher = args[3],
+            salt = Utils.convertToByteString(args[4].string, args[4].option),
             key = CryptoJS.EvpKDF(passphrase, salt, {
                 keySize: keySize,
                 hasher: CryptoJS.algo[hasher],
                 iterations: iterations,
             });
 
-        return key.toString(Cipher._format[outputFormat]);
+        return key.toString(CryptoJS.enc.Hex);
     },