소스 검색

Merge branch 'feature-hashing'

n1474335 7 년 전
부모
커밋
81acb5bdab
12개의 변경된 파일740개의 추가작업 그리고 197개의 파일을 삭제
  1. 1 1
      .travis.yml
  2. 22 8
      Gruntfile.js
  3. BIN
      docs/favicon.ico
  4. 1 1
      docs/jsdoc.conf.json
  5. 103 42
      package-lock.json
  6. 24 21
      package.json
  7. 6 5
      src/core/config/Categories.js
  8. 82 29
      src/core/config/OperationConfig.js
  9. 13 29
      src/core/operations/Checksum.js
  10. 179 61
      src/core/operations/Hash.js
  11. 1 0
      test/index.js
  12. 308 0
      test/tests/operations/Hash.js

+ 1 - 1
.travis.yml

@@ -1,6 +1,6 @@
 language: node_js
 node_js:
-  - node
+  - "8.4"
 install: npm install
 before_script:
   - npm install -g grunt

+ 22 - 8
Gruntfile.js

@@ -111,7 +111,7 @@ module.exports = function (grunt) {
             prod: ["build/prod/*"],
             test: ["build/test/*"],
             node: ["build/node/*"],
-            docs: ["docs/*", "!docs/*.conf.json", "!docs/*.ico"],
+            docs: ["docs/*", "!docs/*.conf.json", "!docs/*.ico", "!docs/*.png"],
         },
         eslint: {
             options: {
@@ -319,15 +319,29 @@ module.exports = function (grunt) {
         copy: {
             ghPages: {
                 options: {
-                    process: function (content) {
+                    process: function (content, srcpath) {
                         // Add Google Analytics code to index.html
-                        content = content.replace("</body></html>",
-                            grunt.file.read("src/web/static/ga.html") + "</body></html>");
-                        return grunt.template.process(content);
-                    }
+                        if (srcpath.indexOf("index.html") >= 0) {
+                            content = content.replace("</body></html>",
+                                grunt.file.read("src/web/static/ga.html") + "</body></html>");
+                            return grunt.template.process(content, srcpath);
+                        } else {
+                            return content;
+                        }
+                    },
+                    noProcess: ["**", "!**/*.html"]
                 },
-                src: "build/prod/index.html",
-                dest: "build/prod/index.html"
+                files: [
+                    {
+                        src: "build/prod/index.html",
+                        dest: "build/prod/index.html"
+                    },
+                    {
+                        expand: true,
+                        src: "docs/**",
+                        dest: "build/prod/"
+                    }
+                ]
             }
         },
         chmod: {

BIN
docs/favicon.ico


+ 1 - 1
docs/jsdoc.conf.json

@@ -19,7 +19,7 @@
         "outputSourcePath": true,
         "dateFormat": "ddd MMM Do YYYY",
         "sort": false,
-        "logoFile": "../build/prod/images/cyberchef-32x32.png",
+        "logoFile": "cyberchef-32x32.png",
         "cleverLinks": false,
         "monospaceLinks": false,
         "protocol": "html://",

+ 103 - 42
package-lock.json

@@ -1661,9 +1661,9 @@
       }
     },
     "crypto-api": {
-      "version": "0.6.2",
-      "resolved": "https://registry.npmjs.org/crypto-api/-/crypto-api-0.6.2.tgz",
-      "integrity": "sha1-TplNAoOiuDsm+3aMKr32hMK/iLc="
+      "version": "0.7.3",
+      "resolved": "https://registry.npmjs.org/crypto-api/-/crypto-api-0.7.3.tgz",
+      "integrity": "sha1-nHMgTE73lxYjIkOYuDS6fJ2B9uU="
     },
     "crypto-browserify": {
       "version": "3.11.1",
@@ -1678,7 +1678,7 @@
         "create-hmac": "1.1.6",
         "diffie-hellman": "5.0.2",
         "inherits": "2.0.3",
-        "pbkdf2": "3.0.13",
+        "pbkdf2": "3.0.14",
         "public-encrypt": "4.0.0",
         "randombytes": "2.0.5"
       }
@@ -2250,21 +2250,27 @@
       "dev": true
     },
     "escodegen": {
-      "version": "1.8.1",
-      "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.8.1.tgz",
-      "integrity": "sha1-WltTr0aTEQvrsIZ6o0MN07cKEBg=",
+      "version": "1.9.0",
+      "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.9.0.tgz",
+      "integrity": "sha512-v0MYvNQ32bzwoG2OSFzWAkuahDQHK92JBN0pTAALJ4RIxEZe766QJPDR8Hqy7XNUy5K3fnVL76OqYAdc4TZEIw==",
       "requires": {
-        "esprima": "2.7.3",
-        "estraverse": "1.9.3",
+        "esprima": "3.1.3",
+        "estraverse": "4.2.0",
         "esutils": "2.0.2",
         "optionator": "0.8.2",
-        "source-map": "0.2.0"
+        "source-map": "0.5.7"
       },
       "dependencies": {
         "esprima": {
-          "version": "2.7.3",
-          "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz",
-          "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE="
+          "version": "3.1.3",
+          "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz",
+          "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM="
+        },
+        "source-map": {
+          "version": "0.5.7",
+          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
+          "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
+          "optional": true
         }
       }
     },
@@ -2593,9 +2599,9 @@
       }
     },
     "estraverse": {
-      "version": "1.9.3",
-      "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz",
-      "integrity": "sha1-r2fy3JIlgkFZUJJgkaQAXSnJu0Q="
+      "version": "4.2.0",
+      "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz",
+      "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM="
     },
     "esutils": {
       "version": "2.0.2",
@@ -4193,6 +4199,16 @@
       "integrity": "sha1-8OgK4DmkvWVLXygfyT8EqRSn/M4=",
       "dev": true
     },
+    "js-crc": {
+      "version": "0.2.0",
+      "resolved": "https://registry.npmjs.org/js-crc/-/js-crc-0.2.0.tgz",
+      "integrity": "sha1-9yxcdhgXa/91zIEqHO2949jraDk="
+    },
+    "js-sha3": {
+      "version": "0.6.1",
+      "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.6.1.tgz",
+      "integrity": "sha1-W4n3enR3Z5h39YxKB1JAk0sflcA="
+    },
     "js-tokens": {
       "version": "3.0.2",
       "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz",
@@ -4306,7 +4322,7 @@
         "content-type-parser": "1.0.1",
         "cssom": "0.3.2",
         "cssstyle": "0.2.37",
-        "escodegen": "1.8.1",
+        "escodegen": "1.9.0",
         "html-encoding-sniffer": "1.0.1",
         "nwmatcher": "1.4.1",
         "parse5": "1.5.1",
@@ -4924,6 +4940,11 @@
         }
       }
     },
+    "node-md6": {
+      "version": "0.1.0",
+      "resolved": "https://registry.npmjs.org/node-md6/-/node-md6-0.1.0.tgz",
+      "integrity": "sha1-9WH0WyszY1K4KXbFHMoRR9U5N/U="
+    },
     "nomnom": {
       "version": "1.5.2",
       "resolved": "https://registry.npmjs.org/nomnom/-/nomnom-1.5.2.tgz",
@@ -5160,7 +5181,7 @@
         "browserify-aes": "1.0.8",
         "create-hash": "1.1.3",
         "evp_bytestokey": "1.0.3",
-        "pbkdf2": "3.0.13"
+        "pbkdf2": "3.0.14"
       }
     },
     "parse-glob": {
@@ -5232,9 +5253,9 @@
       }
     },
     "pbkdf2": {
-      "version": "3.0.13",
-      "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.13.tgz",
-      "integrity": "sha512-+dCHxDH+djNtjgWmvVC/my3SYBAKpKNqKSjLkp+GtWWYe4XPE+e/PSD2aCanlEZZnqPk2uekTKNC/ccbwd2X2Q==",
+      "version": "3.0.14",
+      "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.14.tgz",
+      "integrity": "sha512-gjsZW9O34fm0R7PaLHRJmLLVfSoesxztjPjE9o6R+qtVJij90ltg1joIovN9GKrRW3t1PzhDDG3UMEMFfZ+1wA==",
       "dev": true,
       "requires": {
         "create-hash": "1.1.3",
@@ -5371,21 +5392,67 @@
       }
     },
     "postcss-css-variables": {
-      "version": "0.7.0",
-      "resolved": "https://registry.npmjs.org/postcss-css-variables/-/postcss-css-variables-0.7.0.tgz",
-      "integrity": "sha1-SqWO6zyFmm8JCQE6sXvspWZSh/0=",
+      "version": "0.8.0",
+      "resolved": "https://registry.npmjs.org/postcss-css-variables/-/postcss-css-variables-0.8.0.tgz",
+      "integrity": "sha512-ilcsJMhq09HOsQ2RzXm+fPQNEwMN3kLab6IYpcL5EH8E1EKvBrWQRsiWONWqjWPAKHFMWkEvJTHJJzP9m1E0yQ==",
       "dev": true,
       "requires": {
         "escape-string-regexp": "1.0.5",
-        "extend": "2.0.1",
-        "postcss": "5.2.17"
+        "extend": "3.0.1",
+        "postcss": "6.0.11"
       },
       "dependencies": {
-        "extend": {
-          "version": "2.0.1",
-          "resolved": "https://registry.npmjs.org/extend/-/extend-2.0.1.tgz",
-          "integrity": "sha1-HugBBonnOV/5RIJByYZSvHWagmA=",
+        "ansi-styles": {
+          "version": "3.2.0",
+          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz",
+          "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==",
+          "dev": true,
+          "requires": {
+            "color-convert": "1.9.0"
+          }
+        },
+        "chalk": {
+          "version": "2.1.0",
+          "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.1.0.tgz",
+          "integrity": "sha512-LUHGS/dge4ujbXMJrnihYMcL4AoOweGnw9Tp3kQuqy1Kx5c1qKjqvMJZ6nVJPMWJtKCTN72ZogH3oeSO9g9rXQ==",
+          "dev": true,
+          "requires": {
+            "ansi-styles": "3.2.0",
+            "escape-string-regexp": "1.0.5",
+            "supports-color": "4.4.0"
+          }
+        },
+        "has-flag": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz",
+          "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=",
+          "dev": true
+        },
+        "postcss": {
+          "version": "6.0.11",
+          "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.11.tgz",
+          "integrity": "sha512-DsnIzznNRQprsGTALpkC0xjDygo+QcOd+qVjP9+RjyzrPiyYOXBGOwoJ4rAiiE4lu6JggQ/jW4niY24WLxuncg==",
+          "dev": true,
+          "requires": {
+            "chalk": "2.1.0",
+            "source-map": "0.5.7",
+            "supports-color": "4.4.0"
+          }
+        },
+        "source-map": {
+          "version": "0.5.7",
+          "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
+          "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
           "dev": true
+        },
+        "supports-color": {
+          "version": "4.4.0",
+          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz",
+          "integrity": "sha512-rKC3+DyXWgK0ZLKwmRsrkyHVZAjNkfzeehuFWdGGcqGDTZFH73+RH6S/RDAAxl9GusSjZSUWYLmT9N5pzXFOXQ==",
+          "dev": true,
+          "requires": {
+            "has-flag": "2.0.0"
+          }
         }
       }
     },
@@ -7557,9 +7624,9 @@
       }
     },
     "web-resource-inliner": {
-      "version": "4.1.0",
-      "resolved": "https://registry.npmjs.org/web-resource-inliner/-/web-resource-inliner-4.1.0.tgz",
-      "integrity": "sha1-qXrriZw9PH+BLextWRCEMDJmeUM=",
+      "version": "4.1.1",
+      "resolved": "https://registry.npmjs.org/web-resource-inliner/-/web-resource-inliner-4.1.1.tgz",
+      "integrity": "sha512-LZFX/V43wi+opsbw7ymzBNW2f4cplLPCqBvvPTu/gXfFmy2mXcW7P3CF5UYBJEz2ZIe6tQy4xHAjtJLGhEu0Tw==",
       "dev": true,
       "requires": {
         "async": "2.5.0",
@@ -7603,9 +7670,9 @@
       "dev": true
     },
     "webpack": {
-      "version": "3.5.5",
-      "resolved": "https://registry.npmjs.org/webpack/-/webpack-3.5.5.tgz",
-      "integrity": "sha512-qeUx4nIbeLL53qqNTs3kObPBMkUVDrOjEfp/hTvMlx21qL2MsGNr8/tXCoX/lS12dLl9qtZaXv2qfBEctPScDg==",
+      "version": "3.5.6",
+      "resolved": "https://registry.npmjs.org/webpack/-/webpack-3.5.6.tgz",
+      "integrity": "sha512-sXnxfx6KoZVrFAGLjdhCCwDtDwkYMfwm8mJjkQv3thr5pjTlbxopVlr/kJwc9Bz317gL+gNjvz++ir9TgG1MDg==",
       "dev": true,
       "requires": {
         "acorn": "5.1.2",
@@ -7656,12 +7723,6 @@
             "estraverse": "4.2.0"
           }
         },
-        "estraverse": {
-          "version": "4.2.0",
-          "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz",
-          "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=",
-          "dev": true
-        },
         "has-flag": {
           "version": "2.0.0",
           "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz",

+ 24 - 21
package.json

@@ -30,62 +30,65 @@
   "main": "build/node/CyberChef.js",
   "bugs": "https://github.com/gchq/CyberChef/issues",
   "devDependencies": {
-    "babel-core": "^6.24.0",
-    "babel-loader": "^7.1.1",
+    "babel-core": "^6.26.0",
+    "babel-loader": "^7.1.2",
     "babel-preset-env": "^1.6.0",
-    "css-loader": "^0.28.4",
+    "css-loader": "^0.28.7",
     "exports-loader": "^0.6.4",
     "extract-text-webpack-plugin": "^3.0.0",
     "file-loader": "^0.11.2",
-    "grunt": ">=0.4.5",
+    "grunt": ">=1.0.1",
     "grunt-accessibility": "~5.0.0",
     "grunt-chmod": "~1.1.1",
     "grunt-contrib-clean": "~1.1.0",
     "grunt-contrib-copy": "~1.0.0",
-    "grunt-eslint": "^20.0.0",
+    "grunt-eslint": "^20.1.0",
     "grunt-exec": "~3.0.0",
     "grunt-execute": "^0.2.2",
-    "grunt-jsdoc": "^2.1.0",
+    "grunt-jsdoc": "^2.1.1",
     "grunt-webpack": "^3.0.2",
     "html-webpack-plugin": "^2.30.1",
     "imports-loader": "^0.7.1",
-    "ink-docstrap": "^1.1.4",
+    "ink-docstrap": "^1.3.0",
     "jsdoc-babel": "^0.3.0",
     "less": "^2.7.2",
     "less-loader": "^4.0.5",
-    "postcss-css-variables": "^0.7.0",
+    "postcss-css-variables": "^0.8.0",
     "postcss-import": "^10.0.0",
-    "postcss-loader": "^2.0.5",
+    "postcss-loader": "^2.0.6",
     "style-loader": "^0.18.2",
-    "url-loader": "^0.5.8",
-    "web-resource-inliner": "^4.1.0",
-    "webpack": "^3.4.1",
+    "url-loader": "^0.5.9",
+    "web-resource-inliner": "^4.1.1",
+    "webpack": "^3.5.6",
     "webpack-node-externals": "^1.6.0"
   },
   "dependencies": {
-    "babel-polyfill": "^6.23.0",
+    "babel-polyfill": "^6.26.0",
     "bootstrap": "^3.3.7",
     "bootstrap-colorpicker": "^2.5.1",
     "bootstrap-switch": "^3.3.4",
-    "crypto-api": "^0.6.2",
+    "crypto-api": "^0.7.3",
     "crypto-js": "^3.1.9-1",
-    "diff": "^3.3.0",
-    "escodegen": "^1.8.1",
+    "diff": "^3.3.1",
+    "escodegen": "^1.9.0",
     "esmangle": "^1.0.1",
     "esprima": "^4.0.0",
     "exif-parser": "^0.1.12",
     "google-code-prettify": "^1.0.5",
-    "jquery": "^3.1.1",
+    "jquery": "^3.2.1",
+    "js-crc": "^0.2.0",
+    "js-sha3": "^0.6.1",
     "jsbn": "^1.1.0",
     "jsonpath": "^0.2.12",
     "jsrsasign": "8.0.3",
     "lodash": "^4.17.4",
-    "moment": "^2.17.1",
-    "moment-timezone": "^0.5.11",
+    "moment": "^2.18.1",
+    "moment-timezone": "^0.5.13",
+    "node-md6": "^0.1.0",
     "otp": "^0.1.3",
     "sladex-blowfish": "^0.8.1",
-    "sortablejs": "^1.5.1",
-    "split.js": "^1.2.0",
+    "sortablejs": "^1.6.1",
+    "split.js": "^1.3.5",
     "vkbeautify": "^0.99.3",
     "xmldom": "^0.1.27",
     "xpath": "0.0.24",

+ 6 - 5
src/core/config/Categories.js

@@ -247,20 +247,21 @@ const Categories = [
             "MD2",
             "MD4",
             "MD5",
+            "MD6",
             "SHA0",
             "SHA1",
-            "SHA224",
-            "SHA256",
-            "SHA384",
-            "SHA512",
+            "SHA2",
             "SHA3",
-            "RIPEMD-160",
+            "Keccak",
+            "Shake",
+            "RIPEMD",
             "HMAC",
             "Fletcher-8 Checksum",
             "Fletcher-16 Checksum",
             "Fletcher-32 Checksum",
             "Fletcher-64 Checksum",
             "Adler-32 Checksum",
+            "CRC-16 Checksum",
             "CRC-32 Checksum",
             "TCP/IP Checksum",
         ]

+ 82 - 29
src/core/config/OperationConfig.js

@@ -2882,6 +2882,29 @@ const OperationConfig = {
         outputType: "string",
         args: []
     },
+    "MD6": {
+        description: "The MD6 (Message-Digest 6) algorithm is a cryptographic hash function. It uses a Merkle tree-like structure to allow for immense parallel computation of hashes for very long inputs.",
+        run: Hash.runMD6,
+        inputType: "string",
+        outputType: "string",
+        args: [
+            {
+                name: "Size",
+                type: "number",
+                value: Hash.MD6_SIZE
+            },
+            {
+                name: "Levels",
+                type: "number",
+                value: Hash.MD6_LEVELS
+            },
+            {
+                name: "Key",
+                type: "string",
+                value: ""
+            }
+        ]
+    },
     "SHA0": {
         description: "SHA-0 is a retronym applied to the original version of the 160-bit hash function published in 1993 under the name 'SHA'. It was withdrawn shortly after publication due to an undisclosed 'significant flaw' and replaced by the slightly revised version SHA-1.",
         run: Hash.runSHA0,
@@ -2896,53 +2919,76 @@ const OperationConfig = {
         outputType: "string",
         args: []
     },
-    "SHA224": {
-        description: "SHA-224 is largely identical to SHA-256 but is truncated to 224 bytes.",
-        run: Hash.runSHA224,
+    "SHA2": {
+        description: "The SHA-2 (Secure Hash Algorithm 2) hash functions were designed by the NSA. SHA-2 includes significant changes from its predecessor, SHA-1. The SHA-2 family consists of hash functions with digests (hash values) that are 224, 256, 384 or 512 bits: SHA224, SHA256, SHA384, SHA512.<br><br><ul><li>SHA-512 operates on 64-bit words.</li><li>SHA-256 operates on 32-bit words.</li><li>SHA-384 is largely identical to SHA-512 but is truncated to 384 bytes.</li><li>SHA-224 is largely identical to SHA-256 but is truncated to 224 bytes.</li><li>SHA-512/224 and SHA-512/256 are truncated versions of SHA-512, but the initial values are generated using the method described in Federal Information Processing Standards (FIPS) PUB 180-4.</li></ul>",
+        run: Hash.runSHA2,
         inputType: "string",
         outputType: "string",
-        args: []
-    },
-    "SHA256": {
-        description: "SHA-256 is one of the four variants in the SHA-2 set. It isn't as widely used as SHA-1, though it provides much better security.",
-        run: Hash.runSHA256,
-        inputType: "string",
-        outputType: "string",
-        args: []
+        args: [
+            {
+                name: "Size",
+                type: "option",
+                value: Hash.SHA2_SIZE
+            }
+        ]
     },
-    "SHA384": {
-        description: "SHA-384 is largely identical to SHA-512 but is truncated to 384 bytes.",
-        run: Hash.runSHA384,
+    "SHA3": {
+        description: "The SHA-3 (Secure Hash Algorithm 3) hash functions were released by NIST on August 5, 2015. Although part of the same series of standards, SHA-3 is internally quite different from the MD5-like structure of SHA-1 and SHA-2.<br><br>SHA-3 is a subset of the broader cryptographic primitive family Keccak designed by Guido Bertoni, Joan Daemen, Michaël Peeters, and Gilles Van Assche, building upon RadioGatún.",
+        run: Hash.runSHA3,
         inputType: "string",
         outputType: "string",
-        args: []
+        args: [
+            {
+                name: "Size",
+                type: "option",
+                value: Hash.SHA3_SIZE
+            }
+        ]
     },
-    "SHA512": {
-        description: "SHA-512 is largely identical to SHA-256 but operates on 64-bit words rather than 32.",
-        run: Hash.runSHA512,
+    "Keccak": {
+        description: "The Keccak hash algorithm was designed by Guido Bertoni, Joan Daemen, Michaël Peeters, and Gilles Van Assche, building upon RadioGatún. It was selected as the winner of the SHA-3 design competition.<br><br>This version of the algorithm is Keccak[c=2d] and differs from the SHA-3 specification.",
+        run: Hash.runKeccak,
         inputType: "string",
         outputType: "string",
-        args: []
+        args: [
+            {
+                name: "Size",
+                type: "option",
+                value: Hash.KECCAK_SIZE
+            }
+        ]
     },
-    "SHA3": {
-        description: "This is an implementation of Keccak[c=2d]. SHA3 functions based on different implementations of Keccak will give different results.",
-        run: Hash.runSHA3,
+    "Shake": {
+        description: "Shake is an Extendable Output Function (XOF) of the SHA-3 hash algorithm, part of the Keccak family, allowing for variable output length/size.",
+        run: Hash.runShake,
         inputType: "string",
         outputType: "string",
         args: [
             {
-                name: "Output length",
+                name: "Capacity",
                 type: "option",
-                value: Hash.SHA3_LENGTH
+                value: Hash.SHAKE_CAPACITY
+            },
+            {
+                name: "Size",
+                type: "number",
+                value: Hash.SHAKE_SIZE
             }
         ]
+
     },
-    "RIPEMD-160": {
-        description: "RIPEMD (RACE Integrity Primitives Evaluation Message Digest) is a family of cryptographic hash functions developed in Leuven, Belgium, by Hans Dobbertin, Antoon Bosselaers and Bart Preneel at the COSIC research group at the Katholieke Universiteit Leuven, and first published in 1996.<br><br>RIPEMD was based upon the design principles used in MD4, and is similar in performance to the more popular SHA-1.<br><br>RIPEMD-160 is an improved, 160-bit version of the original RIPEMD, and the most common version in the family.",
-        run: Hash.runRIPEMD160,
+    "RIPEMD": {
+        description: "RIPEMD (RACE Integrity Primitives Evaluation Message Digest) is a family of cryptographic hash functions developed in Leuven, Belgium, by Hans Dobbertin, Antoon Bosselaers and Bart Preneel at the COSIC research group at the Katholieke Universiteit Leuven, and first published in 1996.<br><br>RIPEMD was based upon the design principles used in MD4, and is similar in performance to the more popular SHA-1.<br><br>",
+        run: Hash.runRIPEMD,
         inputType: "string",
         outputType: "string",
-        args: []
+        args: [
+            {
+                name: "Size",
+                type: "option",
+                value: Hash.RIPEMD_SIZE
+            }
+        ]
     },
     "HMAC": {
         description: "Keyed-Hash Message Authentication Codes (HMAC) are a mechanism for message authentication using cryptographic hash functions.",
@@ -3000,7 +3046,14 @@ const OperationConfig = {
     "CRC-32 Checksum": {
         description: "A cyclic redundancy check (CRC) is an error-detecting code commonly used in digital networks and storage devices to detect accidental changes to raw data.<br><br>The CRC was invented by W. Wesley Peterson in 1961; the 32-bit CRC function of Ethernet and many other standards is the work of several researchers and was published in 1975.",
         run: Checksum.runCRC32,
-        inputType: "byteArray",
+        inputType: "string",
+        outputType: "string",
+        args: []
+    },
+    "CRC-16 Checksum": {
+        description: "A cyclic redundancy check (CRC) is an error-detecting code commonly used in digital networks and storage devices to detect accidental changes to raw data.<br><br>The CRC was invented by W. Wesley Peterson in 1961.",
+        run: Checksum.runCRC16,
+        inputType: "string",
         outputType: "string",
         args: []
     },

+ 13 - 29
src/core/operations/Checksum.js

@@ -1,3 +1,4 @@
+import * as CRC from "js-crc";
 import Utils from "../Utils.js";
 
 
@@ -119,19 +120,24 @@ const Checksum = {
     /**
      * CRC-32 Checksum operation.
      *
-     * @param {byteArray} input
+     * @param {string} input
      * @param {Object[]} args
      * @returns {string}
      */
     runCRC32: function(input, args) {
-        let crcTable = global.crcTable || (global.crcTable = Checksum._genCRCTable()),
-            crc = 0 ^ (-1);
+        return CRC.crc32(input);
+    },
 
-        for (let i = 0; i < input.length; i++) {
-            crc = (crc >>> 8) ^ crcTable[(crc ^ input[i]) & 0xff];
-        }
 
-        return Utils.hex((crc ^ (-1)) >>> 0);
+    /**
+     * CRC-16 Checksum operation.
+     *
+     * @param {string} input
+     * @param {Object[]} args
+     * @returns {string}
+     */
+    runCRC16: function(input, args) {
+        return CRC.crc16(input);
     },
 
 
@@ -168,28 +174,6 @@ const Checksum = {
         return Utils.hex(0xffff - csum);
     },
 
-
-    /**
-     * Generates a CRC table for use with CRC checksums.
-     *
-     * @private
-     * @returns {array}
-     */
-    _genCRCTable: function() {
-        let c,
-            crcTable = [];
-
-        for (let n = 0; n < 256; n++) {
-            c = n;
-            for (let k = 0; k < 8; k++) {
-                c = ((c & 1) ? (0xEDB88320 ^ (c >>> 1)) : (c >>> 1));
-            }
-            crcTable[n] = c;
-        }
-
-        return crcTable;
-    },
-
 };
 
 export default Checksum;

+ 179 - 61
src/core/operations/Hash.js

@@ -1,6 +1,7 @@
 import Utils from "../Utils.js";
-import CryptoJS from "crypto-js";
 import CryptoApi from "crypto-api";
+import MD6 from "node-md6";
+import * as SHA3 from "js-sha3";
 import Checksum from "./Checksum.js";
 
 
@@ -23,7 +24,7 @@ const Hash = {
      * @returns {string}
      */
     runMD2: function (input, args) {
-        return Utils.toHexFast(CryptoApi.hash("md2", input, {}));
+        return CryptoApi.hash("md2", input, {}).stringify("hex");
     },
 
 
@@ -35,7 +36,7 @@ const Hash = {
      * @returns {string}
      */
     runMD4: function (input, args) {
-        return Utils.toHexFast(CryptoApi.hash("md4", input, {}));
+        return CryptoApi.hash("md4", input, {}).stringify("hex");
     },
 
 
@@ -47,85 +48,158 @@ const Hash = {
      * @returns {string}
      */
     runMD5: function (input, args) {
-        input = CryptoJS.enc.Latin1.parse(input); // Cast to WordArray
-        return CryptoJS.MD5(input).toString(CryptoJS.enc.Hex);
+        return CryptoApi.hash("md5", input, {}).stringify("hex");
     },
 
 
     /**
-     * SHA0 operation.
+     * @constant
+     * @default
+     */
+    MD6_SIZE: 256,
+    /**
+     * @constant
+     * @default
+     */
+    MD6_LEVELS: 64,
+
+    /**
+     * MD6 operation.
      *
      * @param {string} input
      * @param {Object[]} args
      * @returns {string}
      */
-    runSHA0: function (input, args) {
-        return Utils.toHexFast(CryptoApi.hash("sha0", input, {}));
+    runMD6: function (input, args) {
+        const size = args[0],
+            levels = args[1],
+            key = args[2];
+
+        if (size < 0 || size > 512)
+            return "Size must be between 0 and 512";
+        if (levels < 0)
+            return "Levels must be greater than 0";
+
+        return MD6.getHashOfText(input, size, key, levels);
     },
 
 
     /**
-     * SHA1 operation.
+     * SHA0 operation.
      *
      * @param {string} input
      * @param {Object[]} args
      * @returns {string}
      */
-    runSHA1: function (input, args) {
-        input = CryptoJS.enc.Latin1.parse(input);
-        return CryptoJS.SHA1(input).toString(CryptoJS.enc.Hex);
+    runSHA0: function (input, args) {
+        return CryptoApi.hash("sha0", input, {}).stringify("hex");
     },
 
 
     /**
-     * SHA224 operation.
+     * SHA1 operation.
      *
      * @param {string} input
      * @param {Object[]} args
      * @returns {string}
      */
-    runSHA224: function (input, args) {
-        input = CryptoJS.enc.Latin1.parse(input);
-        return CryptoJS.SHA224(input).toString(CryptoJS.enc.Hex);
+    runSHA1: function (input, args) {
+        return CryptoApi.hash("sha1", input, {}).stringify("hex");
     },
 
 
     /**
-     * SHA256 operation.
+     * @constant
+     * @default
+     */
+    SHA2_SIZE: ["512", "256", "384", "224", "512/256", "512/224"],
+
+    /**
+     * SHA2 operation.
      *
      * @param {string} input
      * @param {Object[]} args
      * @returns {string}
      */
-    runSHA256: function (input, args) {
-        input = CryptoJS.enc.Latin1.parse(input);
-        return CryptoJS.SHA256(input).toString(CryptoJS.enc.Hex);
+    runSHA2: function (input, args) {
+        const size = args[0];
+        return CryptoApi.hash("sha" + size, input, {}).stringify("hex");
     },
 
 
     /**
-     * SHA384 operation.
+     * @constant
+     * @default
+     */
+    SHA3_SIZE: ["512", "384", "256", "224"],
+
+    /**
+     * SHA3 operation.
      *
      * @param {string} input
      * @param {Object[]} args
      * @returns {string}
      */
-    runSHA384: function (input, args) {
-        input = CryptoJS.enc.Latin1.parse(input);
-        return CryptoJS.SHA384(input).toString(CryptoJS.enc.Hex);
+    runSHA3: function (input, args) {
+        const size = parseInt(args[0], 10);
+        let algo;
+
+        switch (size) {
+            case 224:
+                algo = SHA3.sha3_224;
+                break;
+            case 384:
+                algo = SHA3.sha3_384;
+                break;
+            case 256:
+                algo = SHA3.sha3_256;
+                break;
+            case 512:
+                algo = SHA3.sha3_512;
+                break;
+            default:
+                return "Invalid size";
+        }
+
+        return algo(input);
     },
 
 
     /**
-     * SHA512 operation.
+     * @constant
+     * @default
+     */
+    KECCAK_SIZE: ["512", "384", "256", "224"],
+
+    /**
+     * Keccak operation.
      *
      * @param {string} input
      * @param {Object[]} args
      * @returns {string}
      */
-    runSHA512: function (input, args) {
-        input = CryptoJS.enc.Latin1.parse(input);
-        return CryptoJS.SHA512(input).toString(CryptoJS.enc.Hex);
+    runKeccak: function (input, args) {
+        const size = parseInt(args[0], 10);
+        let algo;
+
+        switch (size) {
+            case 224:
+                algo = SHA3.keccak224;
+                break;
+            case 384:
+                algo = SHA3.keccak384;
+                break;
+            case 256:
+                algo = SHA3.keccak256;
+                break;
+            case 512:
+                algo = SHA3.keccak512;
+                break;
+            default:
+                return "Invalid size";
+        }
+
+        return algo(input);
     },
 
 
@@ -133,35 +207,59 @@ const Hash = {
      * @constant
      * @default
      */
-    SHA3_LENGTH: ["512", "384", "256", "224"],
+    SHAKE_CAPACITY: ["256", "128"],
+    /**
+     * @constant
+     * @default
+     */
+    SHAKE_SIZE: 512,
 
     /**
-     * SHA3 operation.
+     * Shake operation.
      *
      * @param {string} input
      * @param {Object[]} args
      * @returns {string}
      */
-    runSHA3: function (input, args) {
-        input = CryptoJS.enc.Latin1.parse(input);
-        let sha3Length = args[0],
-            options = {
-                outputLength: parseInt(sha3Length, 10)
-            };
-        return CryptoJS.SHA3(input, options).toString(CryptoJS.enc.Hex);
+    runShake: function (input, args) {
+        const capacity = parseInt(args[0], 10),
+            size = args[1];
+        let algo;
+
+        if (size < 0)
+            return "Size must be greater than 0";
+
+        switch (capacity) {
+            case 128:
+                algo = SHA3.shake128;
+                break;
+            case 256:
+                algo = SHA3.shake256;
+                break;
+            default:
+                return "Invalid size";
+        }
+
+        return algo(input, size);
     },
 
 
     /**
-     * RIPEMD-160 operation.
+     * @constant
+     * @default
+     */
+    RIPEMD_SIZE: ["320", "256", "160", "128"],
+
+    /**
+     * RIPEMD operation.
      *
      * @param {string} input
      * @param {Object[]} args
      * @returns {string}
      */
-    runRIPEMD160: function (input, args) {
-        input = CryptoJS.enc.Latin1.parse(input);
-        return CryptoJS.RIPEMD160(input).toString(CryptoJS.enc.Hex);
+    runRIPEMD: function (input, args) {
+        const size = args[0];
+        return CryptoApi.hash("ripemd" + size, input, {}).stringify("hex");
     },
 
 
@@ -169,7 +267,23 @@ const Hash = {
      * @constant
      * @default
      */
-    HMAC_FUNCTIONS: ["MD5", "SHA1", "SHA224", "SHA256", "SHA384", "SHA512", "SHA3", "RIPEMD-160"],
+    HMAC_FUNCTIONS: [
+        "MD2",
+        "MD4",
+        "MD5",
+        "SHA0",
+        "SHA1",
+        "SHA224",
+        "SHA256",
+        "SHA384",
+        "SHA512",
+        "SHA512/224",
+        "SHA512/256",
+        "RIPEMD128",
+        "RIPEMD160",
+        "RIPEMD256",
+        "RIPEMD320",
+    ],
 
     /**
      * HMAC operation.
@@ -179,19 +293,12 @@ const Hash = {
      * @returns {string}
      */
     runHMAC: function (input, args) {
-        const hashFunc = args[1];
-        input = CryptoJS.enc.Latin1.parse(input);
-        const execute = {
-            "MD5": CryptoJS.HmacMD5(input, args[0]),
-            "SHA1": CryptoJS.HmacSHA1(input, args[0]),
-            "SHA224": CryptoJS.HmacSHA224(input, args[0]),
-            "SHA256": CryptoJS.HmacSHA256(input, args[0]),
-            "SHA384": CryptoJS.HmacSHA384(input, args[0]),
-            "SHA512": CryptoJS.HmacSHA512(input, args[0]),
-            "SHA3": CryptoJS.HmacSHA3(input, args[0]),
-            "RIPEMD-160": CryptoJS.HmacRIPEMD160(input, args[0]),
-        };
-        return execute[hashFunc].toString(CryptoJS.enc.Hex);
+        const password = args[0],
+            hashFunc = args[1].toLowerCase(),
+            hmac = CryptoApi.mac("hmac", password, hashFunc, {});
+
+        hmac.update(input);
+        return hmac.finalize().stringify("hex");
     },
 
 
@@ -207,24 +314,35 @@ const Hash = {
             output = "MD2:         " + Hash.runMD2(input, []) +
                 "\nMD4:         " + Hash.runMD4(input, []) +
                 "\nMD5:         " + Hash.runMD5(input, []) +
+                "\nMD6:         " + Hash.runMD6(input, []) +
                 "\nSHA0:        " + Hash.runSHA0(input, []) +
                 "\nSHA1:        " + Hash.runSHA1(input, []) +
-                "\nSHA2 224:    " + Hash.runSHA224(input, []) +
-                "\nSHA2 256:    " + Hash.runSHA256(input, []) +
-                "\nSHA2 384:    " + Hash.runSHA384(input, []) +
-                "\nSHA2 512:    " + Hash.runSHA512(input, []) +
+                "\nSHA2 224:    " + Hash.runSHA2(input, ["224"]) +
+                "\nSHA2 256:    " + Hash.runSHA2(input, ["256"]) +
+                "\nSHA2 384:    " + Hash.runSHA2(input, ["384"]) +
+                "\nSHA2 512:    " + Hash.runSHA2(input, ["512"]) +
                 "\nSHA3 224:    " + Hash.runSHA3(input, ["224"]) +
                 "\nSHA3 256:    " + Hash.runSHA3(input, ["256"]) +
                 "\nSHA3 384:    " + Hash.runSHA3(input, ["384"]) +
                 "\nSHA3 512:    " + Hash.runSHA3(input, ["512"]) +
-                "\nRIPEMD-160:  " + Hash.runRIPEMD160(input, []) +
+                "\nKeccak 224:  " + Hash.runKeccak(input, ["224"]) +
+                "\nKeccak 256:  " + Hash.runKeccak(input, ["256"]) +
+                "\nKeccak 384:  " + Hash.runKeccak(input, ["384"]) +
+                "\nKeccak 512:  " + Hash.runKeccak(input, ["512"]) +
+                "\nShake 128:   " + Hash.runShake(input, ["128", 256]) +
+                "\nShake 256:   " + Hash.runShake(input, ["256", 512]) +
+                "\nRIPEMD-128:  " + Hash.runRIPEMD(input, ["128"]) +
+                "\nRIPEMD-160:  " + Hash.runRIPEMD(input, ["160"]) +
+                "\nRIPEMD-256:  " + Hash.runRIPEMD(input, ["256"]) +
+                "\nRIPEMD-320:  " + Hash.runRIPEMD(input, ["320"]) +
                 "\n\nChecksums:" +
                 "\nFletcher-8:  " + Checksum.runFletcher8(byteArray, []) +
                 "\nFletcher-16: " + Checksum.runFletcher16(byteArray, []) +
                 "\nFletcher-32: " + Checksum.runFletcher32(byteArray, []) +
                 "\nFletcher-64: " + Checksum.runFletcher64(byteArray, []) +
                 "\nAdler-32:    " + Checksum.runAdler32(byteArray, []) +
-                "\nCRC-32:      " + Checksum.runCRC32(byteArray, []);
+                "\nCRC-16:      " + Checksum.runCRC16(input, []) +
+                "\nCRC-32:      " + Checksum.runCRC32(input, []);
 
         return output;
     },

+ 1 - 0
test/index.js

@@ -21,6 +21,7 @@ import "./tests/operations/Code.js";
 import "./tests/operations/Compress.js";
 import "./tests/operations/DateTime.js";
 import "./tests/operations/FlowControl.js";
+import "./tests/operations/Hash.js";
 import "./tests/operations/Image.js";
 import "./tests/operations/MorseCode.js";
 import "./tests/operations/MS.js";

+ 308 - 0
test/tests/operations/Hash.js

@@ -0,0 +1,308 @@
+/**
+ * Hash tests.
+ *
+ * @author Matt C [matt@artemisbot.uk]
+ * @copyright Crown Copyright 2017
+ * @license Apache-2.0
+ */
+import TestRegister from "../../TestRegister.js";
+
+TestRegister.addTests([
+    {
+        name: "MD2",
+        input: "Hello, World!",
+        expectedOutput: "1c8f1e6a94aaa7145210bf90bb52871a",
+        recipeConfig: [
+            {
+                "op": "MD2",
+                "args": []
+            }
+        ]
+    },
+    {
+        name: "MD4",
+        input: "Hello, World!",
+        expectedOutput: "94e3cb0fa9aa7a5ee3db74b79e915989",
+        recipeConfig: [
+            {
+                "op": "MD4",
+                "args": []
+            }
+        ]
+    },
+    {
+        name: "MD5",
+        input: "Hello, World!",
+        expectedOutput: "65a8e27d8879283831b664bd8b7f0ad4",
+        recipeConfig: [
+            {
+                "op": "MD5",
+                "args": []
+            }
+        ]
+    },
+    {
+        name: "MD6",
+        input: "Hello, World!",
+        expectedOutput: "ce5effce32637e6b8edaacc9284b873c3fd4e66f9779a79df67eb4a82dda8230",
+        recipeConfig: [
+            {
+                "op": "MD6",
+                "args": [256, 64, ""]
+            }
+        ]
+    },
+    {
+        name: "SHA0",
+        input: "Hello, World!",
+        expectedOutput: "5a5588f0407c6ae9a988758e76965f841b299229",
+        recipeConfig: [
+            {
+                "op": "SHA0",
+                "args": []
+            }
+        ]
+    },
+    {
+        name: "SHA1",
+        input: "Hello, World!",
+        expectedOutput: "0a0a9f2a6772942557ab5355d76af442f8f65e01",
+        recipeConfig: [
+            {
+                "op": "SHA1",
+                "args": []
+            }
+        ]
+    },
+    {
+        name: "SHA2 224",
+        input: "Hello, World!",
+        expectedOutput: "72a23dfa411ba6fde01dbfabf3b00a709c93ebf273dc29e2d8b261ff",
+        recipeConfig: [
+            {
+                "op": "SHA2",
+                "args": ["224"]
+            }
+        ]
+    },
+    {
+        name: "SHA2 384",
+        input: "Hello, World!",
+        expectedOutput: "5485cc9b3365b4305dfb4e8337e0a598a574f8242bf17289e0dd6c20a3cd44a089de16ab4ab308f63e44b1170eb5f515",
+        recipeConfig: [
+            {
+                "op": "SHA2",
+                "args": ["384"]
+            }
+        ]
+    },
+    {
+        name: "SHA2 256",
+        input: "Hello, World!",
+        expectedOutput: "dffd6021bb2bd5b0af676290809ec3a53191dd81c7f70a4b28688a362182986f",
+        recipeConfig: [
+            {
+                "op": "SHA2",
+                "args": ["256"]
+            }
+        ]
+    },
+    {
+        name: "SHA2 512",
+        input: "Hello, World!",
+        expectedOutput: "374d794a95cdcfd8b35993185fef9ba368f160d8daf432d08ba9f1ed1e5abe6cc69291e0fa2fe0006a52570ef18c19def4e617c33ce52ef0a6e5fbe318cb0387",
+        recipeConfig: [
+            {
+                "op": "SHA2",
+                "args": ["512"]
+            }
+        ]
+    },
+    {
+        name: "SHA2 512/224",
+        input: "Hello, World!",
+        expectedOutput: "766745f058e8a0438f19de48ae56ea5f123fe738af39bca050a7547a",
+        recipeConfig: [
+            {
+                "op": "SHA2",
+                "args": ["512/224"]
+            }
+        ]
+    },
+    {
+        name: "SHA2 512/256",
+        input: "Hello, World!",
+        expectedOutput: "0686f0a605973dc1bf035d1e2b9bad1985a0bff712ddd88abd8d2593e5f99030",
+        recipeConfig: [
+            {
+                "op": "SHA2",
+                "args": ["512/256"]
+            }
+        ]
+    },
+    {
+        name: "SHA3 224",
+        input: "Hello, World!",
+        expectedOutput: "853048fb8b11462b6100385633c0cc8dcdc6e2b8e376c28102bc84f2",
+        recipeConfig: [
+            {
+                "op": "SHA3",
+                "args": ["224"]
+            }
+        ]
+    },
+    {
+        name: "SHA3 384",
+        input: "Hello, World!",
+        expectedOutput: "aa9ad8a49f31d2ddcabbb7010a1566417cff803fef50eba239558826f872e468c5743e7f026b0a8e5b2d7a1cc465cdbe",
+        recipeConfig: [
+            {
+                "op": "SHA3",
+                "args": ["384"]
+            }
+        ]
+    },
+    {
+        name: "SHA3 256",
+        input: "Hello, World!",
+        expectedOutput: "1af17a664e3fa8e419b8ba05c2a173169df76162a5a286e0c405b460d478f7ef",
+        recipeConfig: [
+            {
+                "op": "SHA3",
+                "args": ["256"]
+            }
+        ]
+    },
+    {
+        name: "SHA3 512",
+        input: "Hello, World!",
+        expectedOutput: "38e05c33d7b067127f217d8c856e554fcff09c9320b8a5979ce2ff5d95dd27ba35d1fba50c562dfd1d6cc48bc9c5baa4390894418cc942d968f97bcb659419ed",
+        recipeConfig: [
+            {
+                "op": "SHA3",
+                "args": ["512"]
+            }
+        ]
+    },
+    {
+        name: "Keccak 224",
+        input: "Hello, World!",
+        expectedOutput: "4eaaf0e7a1e400efba71130722e1cb4d59b32afb400e654afec4f8ce",
+        recipeConfig: [
+            {
+                "op": "Keccak",
+                "args": ["224"]
+            }
+        ]
+    },
+    {
+        name: "Keccak 384",
+        input: "Hello, World!",
+        expectedOutput: "4d60892fde7f967bcabdc47c73122ae6311fa1f9be90d721da32030f7467a2e3db3f9ccb3c746483f9d2b876e39def17",
+        recipeConfig: [
+            {
+                "op": "Keccak",
+                "args": ["384"]
+            }
+        ]
+    },
+    {
+        name: "Keccak 256",
+        input: "Hello, World!",
+        expectedOutput: "acaf3289d7b601cbd114fb36c4d29c85bbfd5e133f14cb355c3fd8d99367964f",
+        recipeConfig: [
+            {
+                "op": "Keccak",
+                "args": ["256"]
+            }
+        ]
+    },
+    {
+        name: "Keccak 512",
+        input: "Hello, World!",
+        expectedOutput: "eda765576c84c600ed7f5d97510e92703b61f5215def2a161037fd9dd1f5b6ed4f86ce46073c0e3f34b52de0289e9c618798fff9dd4b1bfe035bdb8645fc6e37",
+        recipeConfig: [
+            {
+                "op": "Keccak",
+                "args": ["512"]
+            }
+        ]
+    },
+    {
+        name: "Shake 128",
+        input: "Hello, World!",
+        expectedOutput: "2bf5e6dee6079fad604f573194ba8426bd4d30eb13e8ba2edae70e529b570cbd",
+        recipeConfig: [
+            {
+                "op": "Shake",
+                "args": ["128", 256]
+            }
+        ]
+    },
+    {
+        name: "Shake 256",
+        input: "Hello, World!",
+        expectedOutput: "b3be97bfd978833a65588ceae8a34cf59e95585af62063e6b89d0789f372424e8b0d1be4f21b40ce5a83a438473271e0661854f02d431db74e6904d6c347d757",
+        recipeConfig: [
+            {
+                "op": "Shake",
+                "args": ["256", 512]
+            }
+        ]
+    },
+    {
+        name: "RIPEMD 128",
+        input: "Hello, World!",
+        expectedOutput: "67f9fe75ca2886dc76ad00f7276bdeba",
+        recipeConfig: [
+            {
+                "op": "RIPEMD",
+                "args": ["128"]
+            }
+        ]
+    },
+    {
+        name: "RIPEMD 160",
+        input: "Hello, World!",
+        expectedOutput: "527a6a4b9a6da75607546842e0e00105350b1aaf",
+        recipeConfig: [
+            {
+                "op": "RIPEMD",
+                "args": ["160"]
+            }
+        ]
+    },
+    {
+        name: "RIPEMD 256",
+        input: "Hello, World!",
+        expectedOutput: "567750c6d34dcba7ae038a80016f3ca3260ec25bfdb0b68bbb8e730b00b2447d",
+        recipeConfig: [
+            {
+                "op": "RIPEMD",
+                "args": ["256"]
+            }
+        ]
+    },
+    {
+        name: "RIPEMD 320",
+        input: "Hello, World!",
+        expectedOutput: "f9832e5bb00576fc56c2221f404eb77addeafe49843c773f0df3fc5a996d5934f3c96e94aeb80e89",
+        recipeConfig: [
+            {
+                "op": "RIPEMD",
+                "args": ["320"]
+            }
+        ]
+    },
+    {
+        name: "HMAC SHA256",
+        input: "Hello, World!",
+        expectedOutput: "52589bd80ccfa4acbb3f9512dfaf4f700fa5195008aae0b77a9e47dcca75beac",
+        recipeConfig: [
+            {
+                "op": "HMAC",
+                "args": ["test", "SHA256"]
+            }
+        ]
+    },
+]);