├── .babelrc ├── .eslintignore ├── .eslintrc.js ├── .github └── workflows │ ├── ci.yml │ └── nightly.yml ├── .gitignore ├── CHANGELOG.md ├── LICENSE ├── README-CN.md ├── README.md ├── benchmark ├── benchmark_chrome.png ├── benchmark_chrome_rsa.png ├── benchmark_firefox.png └── benchmark_nodejs.png ├── build ├── build.js ├── config.js └── rollup.config.js ├── docs ├── rsa-CN.md └── rsa.md ├── jest.config.js ├── package-lock.json ├── package.json ├── rust ├── README.md ├── aes │ ├── Cargo.toml │ └── src │ │ ├── lib.rs │ │ └── utils.rs ├── blowfish │ ├── Cargo.toml │ └── src │ │ ├── lib.rs │ │ └── utils.rs ├── build-rust.js ├── des │ ├── Cargo.toml │ └── src │ │ ├── lib.rs │ │ └── utils.rs ├── md5 │ ├── Cargo.toml │ └── src │ │ ├── lib.rs │ │ └── utils.rs ├── package.json ├── rabbit │ ├── Cargo.toml │ └── src │ │ └── lib.rs ├── rc4 │ ├── Cargo.toml │ └── src │ │ └── lib.rs ├── ripemd160 │ ├── Cargo.toml │ └── src │ │ ├── lib.rs │ │ └── utils.rs ├── rsa │ ├── Cargo.toml │ ├── package.json │ ├── pkgs_template │ │ └── rsa_rust.js │ ├── scripts │ │ └── build.js │ └── src │ │ ├── lib.rs │ │ ├── rsa_private.rs │ │ ├── rsa_public.rs │ │ └── utils.rs ├── sha1 │ ├── Cargo.toml │ └── src │ │ └── lib.rs ├── sha256 │ ├── Cargo.toml │ └── src │ │ ├── lib.rs │ │ └── utils.rs ├── sha3 │ ├── Cargo.toml │ └── src │ │ ├── lib.rs │ │ └── utils.rs └── sha512 │ ├── Cargo.toml │ └── src │ ├── lib.rs │ └── utils.rs ├── src ├── algo │ ├── hash │ │ ├── md5.js │ │ ├── md5_bg.js │ │ ├── md5_wasm.js │ │ ├── ripemd160.js │ │ ├── ripemd160_bg.js │ │ ├── ripemd160_wasm.js │ │ ├── sha1.js │ │ ├── sha1_bg.js │ │ ├── sha1_wasm.js │ │ ├── sha224.js │ │ ├── sha256.js │ │ ├── sha256_bg.js │ │ ├── sha256_wasm.js │ │ ├── sha3.js │ │ ├── sha384.js │ │ ├── sha3_bg.js │ │ ├── sha3_wasm.js │ │ ├── sha512.js │ │ ├── sha512_bg.js │ │ └── sha512_wasm.js │ ├── hmac │ │ └── hmac.js │ └── pbkdf2 │ │ └── pbkdf2.js ├── core │ ├── cipher-core.js │ ├── core.js │ ├── hasher.js │ └── x64-core.js ├── encoding │ ├── enc-base64.js │ ├── enc-base64url.js │ ├── enc-hax.js │ ├── enc-latin1.js │ ├── enc-utf16.js │ └── enc-utf8.js ├── encryption │ ├── aes.js │ ├── aes_bg.js │ ├── aes_wasm.js │ ├── blowfish.js │ ├── blowfish_bg.js │ ├── blowfish_wasm.js │ ├── des_bg.js │ ├── des_wasm.js │ ├── evpkdf.js │ ├── rabbit-legacy.js │ ├── rabbit.js │ ├── rabbit_bg.js │ ├── rabbit_wasm.js │ ├── rc4.js │ ├── rc4_bg.js │ ├── rc4_wasm.js │ ├── rsa.js │ ├── rsa_bg.js │ ├── rsa_wasm.js │ └── tripledes.js ├── format │ └── format-hex.js ├── index.js ├── mode │ ├── mode-cfb.js │ ├── mode-ctr-gladman.js │ ├── mode-ctr.js │ ├── mode-ecb.js │ └── mode-ofb.js ├── pad │ ├── pad-ansix923.js │ ├── pad-iso10126.js │ ├── pad-iso97971.js │ ├── pad-nopadding.js │ ├── pad-pkcs7.js │ └── pad-zeropadding.js ├── utils.js └── utils │ └── wasm-utils.js ├── test ├── aes.profile.test.js ├── aes.test.js ├── algo.blowfish.test.js ├── algo.pbkdf2.profile.test.js ├── algo.pbkdf2.test.js ├── algo.rabbit.legacy.test.js ├── algo.rabbit.profile.test.js ├── algo.rabbit.test.js ├── algo.rc4.profile.test.js ├── algo.rc4.test.js ├── algo.ripemd160.test.js ├── algo.rsa.test.js ├── algo.sha1.profile.test.js ├── algo.sha1.test.js ├── algo.sha224.test.js ├── algo.sha256.profile.test.js ├── algo.sha256.test.js ├── algo.sha3.profile.test.js ├── algo.sha3.test.js ├── algo.sha384.test.js ├── algo.sha512.profile.test.js ├── algo.sha512.test.js ├── algo.tripledes.profile.test.js ├── algo.tripledes.test.js ├── cipher.test.js ├── config.test.js ├── crypto-js-test │ ├── algo.aes.test.js │ ├── algo.des.test.js │ ├── algo.md5.test.js │ ├── algo.rabbit-legacy.test.js │ ├── algo.rabbit.test.js │ ├── algo.rc4.test.js │ ├── algo.ripemd160.test.js │ ├── algo.sha1.test.js │ ├── algo.sha224.test.js │ ├── algo.sha256.test.js │ ├── algo.sha3.test.js │ ├── algo.sha384.test.js │ ├── algo.sha512.test.js │ └── algo.tripledes.test.js ├── des.profile.test.js ├── des.test.js ├── enc.base64.test.js ├── enc.hex.test.js ├── enc.latain1.test.js ├── enc.utf16.test.js ├── enc.utf8.test.js ├── evpkdf.profile.test.js ├── evpkdf.test.js ├── format.openssl.test.js ├── hmac.md5.profile.test.js ├── hmac.md5.test.js ├── hmac.sha224.test.js ├── hmac.sha256.test.js ├── hmac.sha384.test.js ├── hmac.sha512.test.js ├── kdf.openssl.test.js ├── lib.base.test.js ├── lib.cipherparams.test.js ├── lib.passwordbasedcipher.test.js ├── lib.serializablecipher.test.js ├── lib.typedarrays.test.js ├── lib.wordarray.test.js ├── load.all.wasm.test.js ├── md5.profile.test.js ├── md5.test.js ├── mode.cbc.test.js ├── mode.cfb.test.js ├── mode.ctr.test.js ├── mode.ecb.test.js ├── mode.ofb.test.js ├── pad.ansix923.test.js ├── pad.iso10126.test.js ├── pad.iso97971.test.js ├── pad.pkcs7.test.js ├── pad.zeropadding.test.js ├── x64.word.test.js └── x64.wordarray.test.js └── types └── index.d.ts /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "test": { 4 | "plugins": ["@babel/plugin-transform-modules-commonjs"] 5 | } 6 | } 7 | } -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | /lib 2 | /build -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | 'env': { 3 | 'browser': true, 4 | 'es6': true, 5 | 'node': true, 6 | 'jest': true 7 | }, 8 | 'parser': '@babel/eslint-parser', 9 | 'extends': 'eslint:recommended', 10 | 'globals': { 11 | 'Atomics': 'readonly', 12 | 'SharedArrayBuffer': 'readonly' 13 | }, 14 | 'parserOptions': { 15 | 'ecmaVersion': 6, 16 | 'sourceType': 'module', 17 | 'ecmaFeatures': { 18 | 'impliedStrict': true 19 | }, 20 | 'requireConfigFile': false 21 | }, 22 | 'rules': { 23 | 'quotes': ['warn', 'single'], 24 | 'linebreak-style': [0, 'error', 'windows'], 25 | 'indent': ['error', 2], 26 | 'semi': ['error', 'always'], 27 | 'comma-dangle': ['warn', 'never'], 28 | 'no-cond-assign': ['error', 'always'], 29 | 'no-console': 'off', 30 | 'accessor-pairs': 'error', 31 | 'default-case':'error', 32 | 'no-eval': 'error', 33 | 'no-use-before-define': 'warn', 34 | 'max-len': 'off', 35 | 'object-curly-spacing': ['warn', 'always', { 'arraysInObjects': false, 'objectsInObjects': false }] 36 | } 37 | }; 38 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | branches: 6 | - '**' 7 | pull_request: 8 | branches: 9 | - main 10 | 11 | jobs: 12 | build: 13 | runs-on: ${{ matrix.os }} 14 | strategy: 15 | matrix: 16 | os: [ubuntu-latest] 17 | node_version: [12, 14, 16] 18 | include: 19 | - os: macos-latest 20 | node_version: 16 21 | - os: windows-latest 22 | node_version: 14 23 | fail-fast: false 24 | 25 | name: "Build&Test: node-${{ matrix.node_version }}, ${{ matrix.os }}" 26 | steps: 27 | - name: Checkout 28 | uses: actions/checkout@v2 29 | 30 | - name: Set node version to ${{ matrix.node_version }} 31 | uses: actions/setup-node@v2 32 | with: 33 | node-version: ${{ matrix.node_version }} 34 | 35 | - name: Get yarn cache directory 36 | id: yarn-cache 37 | run: echo "::set-output name=dir::$(yarn cache dir)" 38 | 39 | - name: Set dependencies cache 40 | uses: actions/cache@v2 41 | with: 42 | path: ${{ steps.yarn-cache.outputs.dir }} 43 | key: ${{ runner.os }}-${{ matrix.node_version }}-${{ hashFiles('yarn.lock') }} 44 | restore-keys: | 45 | ${{ runner.os }}-${{ matrix.node_version }}-${{ hashFiles('yarn.lock') }} 46 | ${{ runner.os }}-${{ matrix.node_version }}- 47 | 48 | - name: Versions 49 | run: yarn versions 50 | 51 | - name: Install dependencies 52 | run: yarn install --frozen-lockfile 53 | 54 | - name: Build 55 | run: yarn build 56 | 57 | - name: Test 58 | run: yarn test 59 | 60 | -------------------------------------------------------------------------------- /.github/workflows/nightly.yml: -------------------------------------------------------------------------------- 1 | name: nightly 2 | 3 | on: 4 | schedule: 5 | - cron: '0 0 * * *' 6 | 7 | jobs: 8 | nightly: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions/checkout@v2 12 | with: 13 | ref: 'refs/heads/main' 14 | fetch-depth: 0 # All history 15 | - name: fetch tags 16 | run: git fetch --depth=1 origin "+refs/tags/*:refs/tags/*" 17 | - uses: actions/setup-node@v2 18 | with: 19 | node-version: 14 20 | registry-url: 'https://registry.npmjs.org' 21 | - name: install 22 | run: yarn --check-files --frozen-lockfile --non-interactive 23 | - name: build 24 | run: PACKAGE_SUFFIX=edge yarn build 25 | - name: test 26 | run: yarn test 27 | 28 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | /lib 3 | .svn 4 | coverage 5 | .idea 6 | pnpm-lock.yaml 7 | Cargo.lock 8 | rust/*/pkg/* 9 | rust/*/target/* 10 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 1.1.1 2 | 3 | ### Bug fixes: 4 | 5 | * Add and fix types for static WordArray.create()(contributed by asivery, [#2](https://github.com/originjs/crypto-js-wasm/pull/2)) 6 | * Fix the library for Webpack(contributed by asivery [#3](https://github.com/originjs/crypto-js-wasm/pull/3)) 7 | * Use sha256 with iterations of 250000 as default hasher of PBKDF2 to prevent weak security problem. Related to CVE-2023-46233 of crypto-js 8 | 9 | ### Features: 10 | 11 | -------------------------------------------------------------------------------- /benchmark/benchmark_chrome.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/originjs/crypto-js-wasm/4b1c151a708a5f712f34843a331a1ee586a97efc/benchmark/benchmark_chrome.png -------------------------------------------------------------------------------- /benchmark/benchmark_chrome_rsa.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/originjs/crypto-js-wasm/4b1c151a708a5f712f34843a331a1ee586a97efc/benchmark/benchmark_chrome_rsa.png -------------------------------------------------------------------------------- /benchmark/benchmark_firefox.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/originjs/crypto-js-wasm/4b1c151a708a5f712f34843a331a1ee586a97efc/benchmark/benchmark_firefox.png -------------------------------------------------------------------------------- /benchmark/benchmark_nodejs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/originjs/crypto-js-wasm/4b1c151a708a5f712f34843a331a1ee586a97efc/benchmark/benchmark_nodejs.png -------------------------------------------------------------------------------- /build/build.js: -------------------------------------------------------------------------------- 1 | const chalk = require('chalk'); 2 | const ora = require('ora'); 3 | const path = require('path'); 4 | const fs = require('fs'); 5 | const rollup = require('rollup'); 6 | const zlib = require('zlib'); 7 | const terser = require('terser'); 8 | const config = require('./config'); 9 | const rollupConfig = require('./rollup.config'); 10 | 11 | const spinner = ora('building for crypto-js-wasm...\n'); 12 | spinner.start() 13 | 14 | if (!fs.existsSync(config.build.assetsRootPath)) { 15 | fs.mkdirSync(config.build.assetsRootPath); 16 | } 17 | 18 | build(rollupConfig); 19 | 20 | function build(config) { 21 | buildEntry(config).then(() => { 22 | console.log(chalk.cyan('Build Complete.\n')); 23 | spinner.stop(); 24 | process.exit(0); 25 | }).catch((err) => { 26 | console.log(chalk.yellow('build failed with errors.\n')); 27 | spinner.stop(); 28 | process.exit(1); 29 | }) 30 | } 31 | 32 | function buildEntry(config) { 33 | const output = config.output; 34 | const file = output.file; 35 | const isProd = /(min)\.js$/.test(file); 36 | return rollup.rollup(config) 37 | .then((bundle) => { 38 | return bundle.generate(output); 39 | }) 40 | .then(({ 41 | output: [{ 42 | code 43 | }] 44 | }) => { 45 | if (isProd) { 46 | const options = { 47 | toplevel: 'true', 48 | } 49 | const miniCode = terser.minify(code, options).code; 50 | return writeFile(file, miniCode, isProd); 51 | } else { 52 | return writeFile(file, code); 53 | } 54 | }) 55 | } 56 | 57 | function writeFile(dest, code, isMin) { 58 | return new Promise((resolve, reject) => { 59 | function exportInfo(info = '') { 60 | console.log(`${chalk.cyan(path.relative(process.cwd(), dest))} ${getFileSize(code)}${info}`); 61 | resolve(); 62 | } 63 | fs.writeFile(dest, code, (err) => { 64 | if (err) throw err; 65 | if (isMin) { 66 | zlib.gzip(code, (err, zipped) => { 67 | if (err) { 68 | return reject(err); 69 | }; 70 | exportInfo(` (gzipped ${getFileSize(zipped)})`); 71 | }) 72 | } else { 73 | exportInfo(); 74 | } 75 | }) 76 | }) 77 | } 78 | 79 | function getFileSize(code) { 80 | return `${(code.length / 1024).toFixed(2)}kb`; 81 | } 82 | -------------------------------------------------------------------------------- /build/config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | 3 | module.exports = { 4 | build: { 5 | index: path.resolve(__dirname, '../lib/index.js'), 6 | assetsRootPath: path.resolve(__dirname, '../lib'), 7 | assetsPublicPath: './' 8 | } 9 | } -------------------------------------------------------------------------------- /build/rollup.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const pkg = require('../package.json'); 3 | const babel = require('@rollup/plugin-babel'); 4 | const commonjs = require('@rollup/plugin-commonjs'); 5 | 6 | const banner = `/* 7 | @license 8 | crypto-js-wasm v${pkg.version} 9 | (c) 2022-${new Date().getFullYear()} ${pkg.author.name} 10 | ${pkg.repository.url} 11 | Released under the MulanPSL2 License. 12 | */`; 13 | 14 | const uniqResolve = (p) => { 15 | return path.resolve(__dirname, './', p); 16 | }; 17 | 18 | module.exports = { 19 | input: uniqResolve('../src/index.js'), 20 | output: { 21 | file: uniqResolve('../lib/index.js'), 22 | format: 'umd', 23 | name: 'CryptoJSWasm', 24 | banner 25 | }, 26 | plugins: [ 27 | babel.babel({ 28 | exclude: 'node_modules/**', 29 | plugins: ['@babel/plugin-proposal-class-properties'] 30 | }), 31 | commonjs(), 32 | ] 33 | }; 34 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@originjs/crypto-js-wasm", 3 | "version": "1.1.1", 4 | "description": "An alternative to crypto-js implemented with WebAssembly and ESM", 5 | "main": "lib/index.js", 6 | "files": [ 7 | "lib", 8 | "types" 9 | ], 10 | "scripts": { 11 | "build": "npm run clean && node build/build.js", 12 | "clean": "rimraf lib", 13 | "test": "jest", 14 | "coverage": "jest --coverage", 15 | "lint": "eslint src test", 16 | "lint-fix": "eslint --fix src test" 17 | }, 18 | "types": "types/index.d.ts", 19 | "lint-staged": { 20 | "*.js": [ 21 | "eslint --fix", 22 | "git add" 23 | ] 24 | }, 25 | "husky": { 26 | "hooks": { 27 | "pre-commit": "lint-staged" 28 | } 29 | }, 30 | "author": { 31 | "name": "peteralfredlee" 32 | }, 33 | "repository": { 34 | "type": "git", 35 | "url": "https://github.com/originjs/crypto-js-wasm" 36 | }, 37 | "bugs": { 38 | "url": "https://github.com/originjs/crypto-js-wasm/issues" 39 | }, 40 | "license": "MulanPSL2", 41 | "keywords": [ 42 | "security", 43 | "crypto", 44 | "WebAssembly", 45 | "WASM", 46 | "Hash", 47 | "MD5", 48 | "SHA1", 49 | "SHA-1", 50 | "SHA256", 51 | "SHA-256", 52 | "RC4", 53 | "Rabbit", 54 | "AES", 55 | "DES", 56 | "PBKDF2", 57 | "HMAC", 58 | "OFB", 59 | "CFB", 60 | "CTR", 61 | "CBC", 62 | "Base64" 63 | ], 64 | "devDependencies": { 65 | "@babel/core": "^7.6.3", 66 | "@babel/eslint-parser": "^7.18.9", 67 | "@babel/plugin-proposal-class-properties": "^7.16.7", 68 | "@babel/plugin-transform-modules-commonjs": "^7.6.0", 69 | "@babel/preset-env": "^7.6.3", 70 | "@rollup/plugin-babel": "^5.3.1", 71 | "@rollup/plugin-commonjs": "^22.0.2", 72 | "babel-jest": "^24.9.0", 73 | "chalk": "^2.4.2", 74 | "crypto-js": "^4.1.1", 75 | "eslint": "^8.21.0", 76 | "husky": "^3.0.8", 77 | "jest": "^27.5.1", 78 | "lint-staged": "^9.4.2", 79 | "ora": "^4.0.2", 80 | "pre-commit": "^1.2.2", 81 | "rimraf": "^3.0.0", 82 | "rollup": "^2.77.2", 83 | "terser": "^4.3.8", 84 | "zlib": "^1.0.5" 85 | }, 86 | "dependencies": { 87 | "add": "^2.0.6", 88 | "global": "^4.4.0", 89 | "pako": "^2.0.4" 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /rust/README.md: -------------------------------------------------------------------------------- 1 | # Prepare for compiling 2 | 3 | The rust repos require rust toolchains(cargo, rustup, rustc, etc.). You can find the latest rust toolchains [here](https://www.rust-lang.org/tools/install). 4 | Besides the rust toolchains, we also need the [wasm-pack](https://github.com/rustwasm/wasm-pack) to compile our rust code into wasm. 5 | 6 | # How to compile 7 | 8 | With all gear up, you can compile the rust repos like this(take md5 as an example): 9 | ```shell 10 | cd md5 11 | wasm-pack build --release 12 | ``` 13 | The compiled wasm binary(_bg.wasm) and javascript glue code(_bg.js) will be generated in the `pkg` directory if nothing goes wrong. 14 | 15 | # Some extra work 16 | 17 | In `crypto-js-wasm`, we use base64-encoded wasm binary(_bg.wasm). 18 | To get a smaller size, we use `pako` to compress the base64-encoded binary. 19 | You can check the `build_rust.js` for more details. 20 | -------------------------------------------------------------------------------- /rust/aes/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "aes" 3 | version = "0.1.0" 4 | authors = ["Alanscut "] 5 | edition = "2018" 6 | 7 | [lib] 8 | crate-type = ["cdylib", "rlib"] 9 | 10 | [features] 11 | default = ["console_error_panic_hook"] 12 | 13 | [dependencies] 14 | wasm-bindgen = "0.2.63" 15 | 16 | # The `console_error_panic_hook` crate provides better debugging of panics by 17 | # logging them with `console.error`. This is great for development, but requires 18 | # all the `std::fmt` and `std::panicking` infrastructure, so isn't great for 19 | # code size when deploying. 20 | console_error_panic_hook = { version = "0.1.6", optional = true } 21 | 22 | # `wee_alloc` is a tiny allocator for wasm that is only ~1K in code size 23 | # compared to the default allocator's ~10K. It is slower than the default 24 | # allocator, however. 25 | # 26 | # Unfortunately, `wee_alloc` requires nightly Rust when targeting wasm for now. 27 | wee_alloc = { version = "0.4.5", optional = true } 28 | 29 | [dev-dependencies] 30 | wasm-bindgen-test = "0.3.13" 31 | 32 | [profile.release] 33 | lto=true 34 | opt-level = 3 35 | -------------------------------------------------------------------------------- /rust/blowfish/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "blowfish" 3 | version = "0.1.0" 4 | authors = ["Alanscut "] 5 | edition = "2018" 6 | 7 | [lib] 8 | crate-type = ["cdylib", "rlib"] 9 | 10 | [features] 11 | default = ["console_error_panic_hook"] 12 | 13 | [dependencies] 14 | wasm-bindgen = "0.2.63" 15 | 16 | # The `console_error_panic_hook` crate provides better debugging of panics by 17 | # logging them with `console.error`. This is great for development, but requires 18 | # all the `std::fmt` and `std::panicking` infrastructure, so isn't great for 19 | # code size when deploying. 20 | console_error_panic_hook = { version = "0.1.6", optional = true } 21 | 22 | # `wee_alloc` is a tiny allocator for wasm that is only ~1K in code size 23 | # compared to the default allocator's ~10K. It is slower than the default 24 | # allocator, however. 25 | # 26 | # Unfortunately, `wee_alloc` requires nightly Rust when targeting wasm for now. 27 | wee_alloc = { version = "0.4.5", optional = true } 28 | 29 | [dev-dependencies] 30 | wasm-bindgen-test = "0.3.13" 31 | 32 | [profile.release] 33 | lto=true 34 | opt-level = 3 35 | -------------------------------------------------------------------------------- /rust/build-rust.js: -------------------------------------------------------------------------------- 1 | // the file is supposed to be run in node.js 2 | const fs = require('fs'); 3 | const pako = require('pako'); 4 | 5 | const contents = fs.readFileSync('./md5/pkg/md5Rust_bg.wasm', null); 6 | const compressedBytes = pako.deflate(contents); 7 | const base64Encoded = Buffer.from((compressedBytes)).toString('base64'); 8 | console.log(base64Encoded); 9 | -------------------------------------------------------------------------------- /rust/des/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "des" 3 | version = "0.1.0" 4 | authors = ["Alanscut "] 5 | edition = "2018" 6 | 7 | [lib] 8 | crate-type = ["cdylib", "rlib"] 9 | 10 | [features] 11 | default = ["console_error_panic_hook"] 12 | 13 | [dependencies] 14 | wasm-bindgen = "0.2.63" 15 | 16 | # The `console_error_panic_hook` crate provides better debugging of panics by 17 | # logging them with `console.error`. This is great for development, but requires 18 | # all the `std::fmt` and `std::panicking` infrastructure, so isn't great for 19 | # code size when deploying. 20 | console_error_panic_hook = { version = "0.1.6", optional = true } 21 | 22 | # `wee_alloc` is a tiny allocator for wasm that is only ~1K in code size 23 | # compared to the default allocator's ~10K. It is slower than the default 24 | # allocator, however. 25 | # 26 | # Unfortunately, `wee_alloc` requires nightly Rust when targeting wasm for now. 27 | wee_alloc = { version = "0.4.5", optional = true } 28 | 29 | [dev-dependencies] 30 | wasm-bindgen-test = "0.3.13" 31 | 32 | [profile.release] 33 | lto=true 34 | opt-level = 3 35 | -------------------------------------------------------------------------------- /rust/md5/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "md5Rust" 3 | version = "0.1.0" 4 | authors = ["PeterAlfredLee "] 5 | edition = "2018" 6 | 7 | [lib] 8 | crate-type = ["cdylib", "rlib"] 9 | 10 | [dependencies] 11 | wasm-bindgen = { version = "0.2.63", features = ["serde-serialize"] } 12 | serde_json = "1.0.32" 13 | serde_derive = "1.0.80" 14 | serde = "1.0.80" 15 | lazy_static = "1.4.0" 16 | 17 | [dependencies.web-sys] 18 | version = "0.3" 19 | features = [ "console" ] 20 | 21 | # The `console_error_panic_hook` crate provides better debugging of panics by 22 | # logging them with `console.error`. This is great for development, but requires 23 | # all the `std::fmt` and `std::panicking` infrastructure, so isn't great for 24 | # code size when deploying. 25 | console_error_panic_hook = { version = "0.1.6", optional = true } 26 | 27 | # `wee_alloc` is a tiny allocator for wasm that is only ~1K in code size 28 | # compared to the default allocator's ~10K. It is slower than the default 29 | # allocator, however. 30 | # 31 | # Unfortunately, `wee_alloc` requires nightly Rust when targeting wasm for now. 32 | wee_alloc = { version = "0.4.5", optional = true } 33 | 34 | [dev-dependencies] 35 | wasm-bindgen-test = "0.3.13" 36 | 37 | [profile.release] 38 | lto = true 39 | # Tell `rustc` to optimize for small code size. 40 | opt-level = 3 41 | -------------------------------------------------------------------------------- /rust/md5/src/utils.rs: -------------------------------------------------------------------------------- 1 | pub fn getT() -> [u32; 64] { 2 | [3614090360, 3905402710, 606105819, 3250441966, 4118548399, 1200080426, 2821735955, 4249261313, 3 | 1770035416, 2336552879, 4294925233, 2304563134, 1804603682, 4254626195, 2792965006, 1236535329, 4 | 4129170786, 3225465664, 643717713, 3921069994, 3593408605, 38016083, 3634488961, 3889429448, 5 | 568446438, 3275163606, 4107603335, 1163531501, 2850285829, 4243563512, 1735328473, 2368359562, 6 | 4294588738, 2272392833, 1839030562, 4259657740, 2763975236, 1272893353, 4139469664, 3200236656, 7 | 681279174, 3936430074, 3572445317, 76029189, 3654602809, 3873151461, 530742520, 3299628645, 8 | 4096336452, 1126891415, 2878612391, 4237533241, 1700485571, 2399980690, 4293915773, 2240044497, 9 | 1873313359, 4264355552, 2734768916, 1309151649, 4149444226, 3174756917, 718787259, 3951481745] 10 | } -------------------------------------------------------------------------------- /rust/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "crypto-js-wasm-rust", 3 | "version": "1.0.0", 4 | "description": "The rust repos require rust toolchains(cargo, rustup, rustc, etc.). You can find the latest rust toolchains [here](https://www.rust-lang.org/tools/install). Besides the rust toolchains, we also need the [wasm-pack](https://github.com/rustwasm/wasm-pack) to compile our rust code into wasm.", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "dependencies": { 11 | "pako": "^2.0.4" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /rust/rabbit/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "rabbit" 3 | version = "0.1.0" 4 | authors = ["Alanscut "] 5 | edition = "2018" 6 | 7 | [lib] 8 | crate-type = ["cdylib", "rlib"] 9 | 10 | [features] 11 | default = ["console_error_panic_hook"] 12 | 13 | [dependencies] 14 | wasm-bindgen = "0.2.63" 15 | 16 | # The `console_error_panic_hook` crate provides better debugging of panics by 17 | # logging them with `console.error`. This is great for development, but requires 18 | # all the `std::fmt` and `std::panicking` infrastructure, so isn't great for 19 | # code size when deploying. 20 | console_error_panic_hook = { version = "0.1.6", optional = true } 21 | 22 | # `wee_alloc` is a tiny allocator for wasm that is only ~1K in code size 23 | # compared to the default allocator's ~10K. It is slower than the default 24 | # allocator, however. 25 | # 26 | # Unfortunately, `wee_alloc` requires nightly Rust when targeting wasm for now. 27 | wee_alloc = { version = "0.4.5", optional = true } 28 | 29 | [dev-dependencies] 30 | wasm-bindgen-test = "0.3.13" 31 | 32 | [profile.release] 33 | lto = true 34 | opt-level = 3 35 | -------------------------------------------------------------------------------- /rust/rabbit/src/lib.rs: -------------------------------------------------------------------------------- 1 | use wasm_bindgen::prelude::*; 2 | 3 | #[wasm_bindgen] 4 | pub fn doProcess( 5 | nWordsReady: usize, 6 | blockSize: usize, 7 | dataWords: &mut [u32], 8 | X: &mut [u32], 9 | C: &mut [u32], 10 | mut b: u32, 11 | ) -> u32 { 12 | // Process blocks 13 | if nWordsReady > 0 { 14 | let mut offset = 0; 15 | while offset < nWordsReady { 16 | b = doProcessBlock(dataWords, offset, X, C, b); 17 | offset += blockSize; 18 | } 19 | } 20 | 21 | b 22 | } 23 | 24 | fn nextState(X: &mut [u32], C: &mut [u32], mut b: u32) -> u32 { 25 | let mut C_: [u32; 8] = [0; 8]; 26 | // Save old counter values 27 | for i in 0..8 { 28 | C_[i] = C[i]; 29 | } 30 | 31 | // Calculate new counter values 32 | C[0] = (C[0] + 0x4d34d34d + b) | 0; 33 | C[1] = (C[1] + 0xd34d34d3 + (if C[0] < C_[0] { 1 } else { 0 })) | 0; 34 | C[2] = (C[2] + 0x34d34d34 + (if C[1] < C_[1] { 1 } else { 0 })) | 0; 35 | C[3] = (C[3] + 0x4d34d34d + (if C[2] < C_[2] { 1 } else { 0 })) | 0; 36 | C[4] = (C[4] + 0xd34d34d3 + (if C[3] < C_[3] { 1 } else { 0 })) | 0; 37 | C[5] = (C[5] + 0x34d34d34 + (if C[4] < C_[4] { 1 } else { 0 })) | 0; 38 | C[6] = (C[6] + 0x4d34d34d + (if C[5] < C_[5] { 1 } else { 0 })) | 0; 39 | C[7] = (C[7] + 0xd34d34d3 + (if C[6] < C_[6] { 1 } else { 0 })) | 0; 40 | b = if C[7] < C_[7] { 1 } else { 0 }; 41 | 42 | let mut G: [u32; 8] = [0; 8]; 43 | // Calculate the g-values 44 | for i in 0..8 { 45 | let gx = X[i] + C[i]; 46 | 47 | // Construct high and low argument for squaring 48 | let ga = gx & 0xffff; 49 | let gb = gx >> 16; 50 | 51 | // Calculate high and low result of squaring 52 | let gh = ((((ga * ga) >> 17) + ga * gb) >> 15) + gb * gb; 53 | let gl = (((gx & 0xffff0000) * gx) | 0) + (((gx & 0x0000ffff) * gx) | 0); 54 | 55 | // High XOR low 56 | G[i] = gh ^ gl; 57 | } 58 | 59 | // Calculate new state values 60 | X[0] = (G[0] + ((G[7] << 16) | (G[7] >> 16)) + ((G[6] << 16) | (G[6] >> 16))) | 0; 61 | X[1] = (G[1] + ((G[0] << 8) | (G[0] >> 24)) + G[7]) | 0; 62 | X[2] = (G[2] + ((G[1] << 16) | (G[1] >> 16)) + ((G[0] << 16) | (G[0] >> 16))) | 0; 63 | X[3] = (G[3] + ((G[2] << 8) | (G[2] >> 24)) + G[1]) | 0; 64 | X[4] = (G[4] + ((G[3] << 16) | (G[3] >> 16)) + ((G[2] << 16) | (G[2] >> 16))) | 0; 65 | X[5] = (G[5] + ((G[4] << 8) | (G[4] >> 24)) + G[3]) | 0; 66 | X[6] = (G[6] + ((G[5] << 16) | (G[5] >> 16)) + ((G[4] << 16) | (G[4] >> 16))) | 0; 67 | X[7] = (G[7] + ((G[6] << 8) | (G[6] >> 24)) + G[5]) | 0; 68 | 69 | b 70 | } 71 | 72 | fn doProcessBlock( 73 | dataWords: &mut [u32], 74 | offset: usize, 75 | X: &mut [u32], 76 | C: &mut [u32], 77 | mut b: u32, 78 | ) -> u32 { 79 | // Iterate the system 80 | b = nextState(X, C, b); 81 | 82 | let mut S: [u32; 4] = [0; 4]; 83 | // Generate four keystream words 84 | S[0] = X[0] ^ (X[5] >> 16) ^ (X[3] << 16); 85 | S[1] = X[2] ^ (X[7] >> 16) ^ (X[5] << 16); 86 | S[2] = X[4] ^ (X[1] >> 16) ^ (X[7] << 16); 87 | S[3] = X[6] ^ (X[3] >> 16) ^ (X[1] << 16); 88 | 89 | for i in 0..4 { 90 | // Swap endian 91 | S[i] = (((S[i] << 8) | (S[i] >> 24)) & 0x00ff00ff) 92 | | (((S[i] << 24) | (S[i] >> 8)) & 0xff00ff00); 93 | 94 | // Encrypt 95 | dataWords[offset + i] ^= S[i]; 96 | } 97 | 98 | b 99 | } 100 | -------------------------------------------------------------------------------- /rust/rc4/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "rc4" 3 | version = "0.1.0" 4 | authors = ["Alanscut "] 5 | edition = "2018" 6 | 7 | [lib] 8 | crate-type = ["cdylib", "rlib"] 9 | 10 | [features] 11 | default = ["console_error_panic_hook"] 12 | 13 | [dependencies] 14 | wasm-bindgen = "0.2.63" 15 | 16 | # The `console_error_panic_hook` crate provides better debugging of panics by 17 | # logging them with `console.error`. This is great for development, but requires 18 | # all the `std::fmt` and `std::panicking` infrastructure, so isn't great for 19 | # code size when deploying. 20 | console_error_panic_hook = { version = "0.1.6", optional = true } 21 | 22 | # `wee_alloc` is a tiny allocator for wasm that is only ~1K in code size 23 | # compared to the default allocator's ~10K. It is slower than the default 24 | # allocator, however. 25 | # 26 | # Unfortunately, `wee_alloc` requires nightly Rust when targeting wasm for now. 27 | wee_alloc = { version = "0.4.5", optional = true } 28 | 29 | [dev-dependencies] 30 | wasm-bindgen-test = "0.3.13" 31 | 32 | [profile.release] 33 | lto = true 34 | opt-level = 3 35 | -------------------------------------------------------------------------------- /rust/rc4/src/lib.rs: -------------------------------------------------------------------------------- 1 | use wasm_bindgen::prelude::*; 2 | 3 | #[wasm_bindgen] 4 | pub fn doProcess(nWordsReady: usize, blockSize: usize, dataWords: &mut [u32], S: &mut [u32]) { 5 | // Process blocks 6 | if nWordsReady > 0 { 7 | let mut offset = 0; 8 | while offset < nWordsReady { 9 | doProcessBlock(dataWords, offset, S); 10 | offset += blockSize; 11 | } 12 | } 13 | } 14 | 15 | fn generateKeystreamWord(S: &mut [u32]) -> u32 { 16 | let mut i = S[256] as usize; 17 | let mut j = S[257] as usize; 18 | 19 | // Generate keystream word 20 | let mut keystreamWord = 0; 21 | for n in 0..4 { 22 | i = (i + 1) % 256; 23 | j = (j + S[i] as usize) % 256; 24 | 25 | // Swap 26 | let t = S[i]; 27 | S[i] = S[j]; 28 | S[j] = t; 29 | 30 | keystreamWord |= S[((S[i] + S[j]) % 256) as usize] << (24 - n * 8); 31 | } 32 | 33 | // Update counters 34 | S[256] = i as u32; 35 | S[257] = j as u32; 36 | 37 | keystreamWord 38 | } 39 | 40 | fn doProcessBlock(dataWords: &mut [u32], offset: usize, S: &mut [u32]) { 41 | dataWords[offset] ^= generateKeystreamWord(S); 42 | } 43 | -------------------------------------------------------------------------------- /rust/ripemd160/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "ripemd160" 3 | version = "0.1.0" 4 | authors = ["Alanscut "] 5 | edition = "2018" 6 | 7 | [lib] 8 | crate-type = ["cdylib", "rlib"] 9 | 10 | [features] 11 | default = ["console_error_panic_hook"] 12 | 13 | [dependencies] 14 | wasm-bindgen = "0.2.63" 15 | 16 | # The `console_error_panic_hook` crate provides better debugging of panics by 17 | # logging them with `console.error`. This is great for development, but requires 18 | # all the `std::fmt` and `std::panicking` infrastructure, so isn't great for 19 | # code size when deploying. 20 | console_error_panic_hook = { version = "0.1.6", optional = true } 21 | 22 | # `wee_alloc` is a tiny allocator for wasm that is only ~1K in code size 23 | # compared to the default allocator's ~10K. It is slower than the default 24 | # allocator, however. 25 | # 26 | # Unfortunately, `wee_alloc` requires nightly Rust when targeting wasm for now. 27 | wee_alloc = { version = "0.4.5", optional = true } 28 | 29 | [dev-dependencies] 30 | wasm-bindgen-test = "0.3.13" 31 | 32 | [profile.release] 33 | lto = true 34 | opt-level = 3 35 | -------------------------------------------------------------------------------- /rust/ripemd160/src/lib.rs: -------------------------------------------------------------------------------- 1 | mod utils; 2 | 3 | use crate::utils::{getHL, getHR, getSL, getSR, getZL, getZR}; 4 | use wasm_bindgen::prelude::*; 5 | 6 | #[wasm_bindgen] 7 | pub fn doProcess(nWordsReady: usize, blockSize: usize, dataWords: &mut [u32], H: &mut [u32]) { 8 | // Process blocks 9 | if nWordsReady > 0 { 10 | let mut offset = 0; 11 | while offset < nWordsReady { 12 | doProcessBlock(dataWords, offset, H); 13 | offset += blockSize; 14 | } 15 | } 16 | } 17 | 18 | fn doProcessBlock(dataWords: &mut [u32], offset: usize, H: &mut [u32]) { 19 | // Swap endian 20 | for i in 0..16 { 21 | // Shortcuts 22 | let offset_i = offset + i; 23 | let data_offset_i = dataWords[offset_i]; 24 | 25 | // Swap 26 | dataWords[offset_i] = (((data_offset_i << 8) | (data_offset_i >> 24)) & 0x00ff00ff) 27 | | (((data_offset_i << 24) | (data_offset_i >> 8)) & 0xff00ff00); 28 | } 29 | // Shortcut 30 | let hl = getHL(); 31 | let hr = getHR(); 32 | let zl = getZL(); 33 | let zr = getZR(); 34 | let sl = getSL(); 35 | let sr = getSR(); 36 | 37 | // Working letiables 38 | let mut al = H[0]; 39 | let mut ar = H[0]; 40 | let mut bl = H[1]; 41 | let mut br = H[1]; 42 | let mut cl = H[2]; 43 | let mut cr = H[2]; 44 | let mut dl = H[3]; 45 | let mut dr = H[3]; 46 | let mut el = H[4]; 47 | let mut er = H[4]; 48 | 49 | // Computation 50 | let mut t: u32 = 0; 51 | for i in 0..80 { 52 | t = (al + dataWords[offset + zl[i] as usize]) | 0; 53 | if i < 16 { 54 | t += f1(bl, cl, dl) + hl[0]; 55 | } else if i < 32 { 56 | t += f2(bl, cl, dl) + hl[1]; 57 | } else if i < 48 { 58 | t += f3(bl, cl, dl) + hl[2]; 59 | } else if i < 64 { 60 | t += f4(bl, cl, dl) + hl[3]; 61 | } else { 62 | // if (i<80) { 63 | t += f5(bl, cl, dl) + hl[4]; 64 | } 65 | t = t | 0; 66 | t = rotl(t, sl[i]); 67 | t = (t + el) | 0; 68 | al = el; 69 | el = dl; 70 | dl = rotl(cl, 10); 71 | cl = bl; 72 | bl = t; 73 | 74 | t = (ar + dataWords[offset + zr[i] as usize]) | 0; 75 | if i < 16 { 76 | t += f5(br, cr, dr) + hr[0]; 77 | } else if i < 32 { 78 | t += f4(br, cr, dr) + hr[1]; 79 | } else if i < 48 { 80 | t += f3(br, cr, dr) + hr[2]; 81 | } else if i < 64 { 82 | t += f2(br, cr, dr) + hr[3]; 83 | } else { 84 | // if (i<80) { 85 | t += f1(br, cr, dr) + hr[4]; 86 | } 87 | t = t | 0; 88 | t = rotl(t, sr[i]); 89 | t = (t + er) | 0; 90 | ar = er; 91 | er = dr; 92 | dr = rotl(cr, 10); 93 | cr = br; 94 | br = t; 95 | } 96 | // Intermediate hash value 97 | t = (H[1] + cl + dr) | 0; 98 | H[1] = (H[2] + dl + er) | 0; 99 | H[2] = (H[3] + el + ar) | 0; 100 | H[3] = (H[4] + al + br) | 0; 101 | H[4] = (H[0] + bl + cr) | 0; 102 | H[0] = t; 103 | } 104 | 105 | fn f1(x: u32, y: u32, z: u32) -> u32 { 106 | (x) ^ (y) ^ (z) 107 | } 108 | 109 | fn f2(x: u32, y: u32, z: u32) -> u32 { 110 | ((x) & (y)) | ((!x) & (z)) 111 | } 112 | 113 | fn f3(x: u32, y: u32, z: u32) -> u32 { 114 | ((x) | (!(y))) ^ (z) 115 | } 116 | 117 | fn f4(x: u32, y: u32, z: u32) -> u32 { 118 | ((x) & (z)) | ((y) & (!(z))) 119 | } 120 | 121 | fn f5(x: u32, y: u32, z: u32) -> u32 { 122 | (x) ^ ((y) | (!(z))) 123 | } 124 | 125 | fn rotl(x: u32, n: u32) -> u32 { 126 | (x << n) | (x >> (32 - n)) 127 | } 128 | -------------------------------------------------------------------------------- /rust/ripemd160/src/utils.rs: -------------------------------------------------------------------------------- 1 | pub fn getZL() -> [u32; 80] { 2 | [ 3 | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 4 | 5, 2, 14, 11, 8, 3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12, 1, 9, 11, 10, 0, 8, 5 | 12, 4, 13, 3, 7, 15, 14, 5, 6, 2, 4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13, 6 | ] 7 | } 8 | 9 | pub fn getZR() -> [u32; 80] { 10 | [ 11 | 5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12, 6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12 | 12, 4, 9, 1, 2, 15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13, 8, 6, 4, 1, 3, 11, 13 | 15, 0, 5, 12, 2, 13, 9, 7, 10, 14, 12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11, 14 | ] 15 | } 16 | 17 | pub fn getSL() -> [u32; 80] { 18 | [ 19 | 11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8, 7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 20 | 15, 9, 11, 7, 13, 12, 11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5, 11, 12, 14, 21 | 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12, 9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 22 | 8, 5, 6, 23 | ] 24 | } 25 | 26 | pub fn getSR() -> [u32; 80] { 27 | [ 28 | 8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6, 9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 29 | 12, 7, 6, 15, 13, 11, 9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5, 15, 5, 8, 11, 30 | 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8, 8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 31 | 11, 11, 32 | ] 33 | } 34 | 35 | pub fn getHL() -> [u32; 5] { 36 | [0x00000000, 0x5A827999, 0x6ED9EBA1, 0x8F1BBCDC, 0xA953FD4E] 37 | } 38 | 39 | pub fn getHR() -> [u32; 5] { 40 | [0x50A28BE6, 0x5C4DD124, 0x6D703EF3, 0x7A6D76E9, 0x00000000] 41 | } 42 | -------------------------------------------------------------------------------- /rust/rsa/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "rsa_rust" 3 | version = "0.1.0" 4 | authors = ["Carrick "] 5 | edition = "2018" 6 | 7 | [lib] 8 | crate-type = ["cdylib", "rlib"] 9 | 10 | [features] 11 | default = ["console_error_panic_hook"] 12 | 13 | [dependencies] 14 | wasm-bindgen = "0.2.63" 15 | rsa = "0.6.1" 16 | md-5 = "0.10.1" 17 | sha1 = "0.10.0" 18 | sha2 = "0.10.2" 19 | ripemd = "0.1.1" 20 | der = "0.5.0" 21 | base64 = "0.13.0" 22 | 23 | rand = "0.8.4" 24 | js-sys = "0.3.58" 25 | serde-wasm-bindgen = "0.4.3" 26 | getrandom = { version = "0.2.7", features = ["js"] } 27 | 28 | #[dependencies.web-sys] 29 | #version = "0.3" 30 | #features = ["console"] 31 | 32 | # The `console_error_panic_hook` crate provides better debugging of panics by 33 | # logging them with `console.error`. This is great for development, but requires 34 | # all the `std::fmt` and `std::panicking` infrastructure, so isn't great for 35 | # code size when deploying. 36 | console_error_panic_hook = { version = "0.1.6", optional = true } 37 | 38 | # `wee_alloc` is a tiny allocator for wasm that is only ~1K in code size 39 | # compared to the default allocator's ~10K. It is slower than the default 40 | # allocator, however. 41 | # 42 | # Unfortunately, `wee_alloc` requires nightly Rust when targeting wasm for now. 43 | wee_alloc = { version = "0.4.5", optional = true } 44 | 45 | [dev-dependencies] 46 | wasm-bindgen-test = "0.3.13" 47 | 48 | [profile.release] 49 | lto = true 50 | opt-level = 3 51 | -------------------------------------------------------------------------------- /rust/rsa/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "rust-rsa-wasmpack", 3 | "version": "1.0.0", 4 | "directories": { 5 | "test": "tests" 6 | }, 7 | "scripts": { 8 | "build": "node scripts/build.js", 9 | "dev:browser": "http-server pkgs -c-1 -o", 10 | "dev:node": "node js/rsa.js", 11 | "test:rust": "cargo test", 12 | "test:js": "cd js && pnpm install && pnpm test" 13 | }, 14 | "devDependencies": { 15 | "shelljs": "^0.8.5", 16 | "http-server": "^14.1.1" 17 | }, 18 | "author": "Carrick" 19 | } 20 | -------------------------------------------------------------------------------- /rust/rsa/pkgs_template/rsa_rust.js: -------------------------------------------------------------------------------- 1 | let init, RsaPrivate, RsaPublic; 2 | if (typeof window !== 'undefined' && typeof window.document !== 'undefined') { 3 | console.log('Browser detected'); 4 | 5 | await import('./browser/rsa_rust.js').then(RsaBrowser => { 6 | init = RsaBrowser.init; 7 | RsaPrivate = RsaBrowser.RsaPrivate; 8 | RsaPublic = RsaBrowser.RsaPublic; 9 | }); 10 | 11 | await init(); 12 | console.log(new RsaPrivate(1024).getPrivateKeyContent('pem')); 13 | } else if (typeof process !== 'undefined' && process.versions != null && process.versions.node != null) { 14 | console.log('Nodejs detected'); 15 | 16 | await import('./nodejs/rsa_rust.js').then(RsaNode => { 17 | init = RsaNode.init; 18 | RsaPrivate = RsaNode.RsaPrivate; 19 | RsaPublic = RsaNode.RsaPublic; 20 | }); 21 | } else { 22 | throw Error('Only browser and nodejs supported'); 23 | } 24 | 25 | export {init, RsaPrivate, RsaPublic}; 26 | -------------------------------------------------------------------------------- /rust/rsa/scripts/build.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const shell = require('shelljs'); 3 | const pako = require('pako'); 4 | 5 | // create folder 6 | shell.rm('-rf', 'pkg'); 7 | shell.mkdir('pkg'); 8 | 9 | shell.exec('wasm-pack build --target web'); 10 | 11 | // modify content 12 | const bgOld = fs.readFileSync('./pkg/rsa_rust.js', 'utf8'); 13 | const bgTruncated = bgOld.substring(bgOld.indexOf('const heap = new'), bgOld.indexOf('async function load')) + 14 | bgOld.substring(bgOld.indexOf('function getImports'), bgOld.indexOf('function initMemory')); 15 | 16 | const bgSnippet1 = `import { wasmBytes } from './rsa_wasm'; 17 | let wasm; 18 | let globalThis;\n`; 19 | const bgSnippet2 = `async function init() { 20 | await WebAssembly.instantiate(wasmBytes, getImports()).then((wasmInstance) => { 21 | wasm = wasmInstance.instance.exports; 22 | }); 23 | cachedInt32Memory0 = new Int32Array(wasm.memory.buffer); 24 | cachedUint8Memory0 = new Uint8Array(wasm.memory.buffer); 25 | } 26 | 27 | export { init };`; 28 | 29 | const bgFinal = bgSnippet1 + bgTruncated + bgSnippet2; 30 | fs.writeFileSync('./pkg/rsa_bg.js', bgFinal, 'utf8'); 31 | 32 | // save wasm as base64 to js file 33 | const contents = fs.readFileSync('./pkg/rsa_rust_bg.wasm', null); 34 | const compressedBytes = pako.deflate(contents); 35 | const base64Encoded = Buffer.from((compressedBytes)).toString('base64'); 36 | const rsaWasm = `import { generateWasmBytes } from '../utils/wasm-utils';\n 37 | export const wasmBytes = generateWasmBytes('${base64Encoded}');\n`; 38 | fs.writeFileSync('./pkg/rsa_wasm.js', rsaWasm, 'utf8'); 39 | 40 | shell.rm('-rf', ['pkg/rsa_rust.js', 'pkg/.gitignore', 'pkg/rsa_rust_bg.wasm.d.ts', 'pkg/rsa_rust.d.ts', 'pkg/rsa_rust.js', 'pkg/package.json',]); 41 | 42 | console.log('\nBuild complete.'); 43 | -------------------------------------------------------------------------------- /rust/rsa/src/lib.rs: -------------------------------------------------------------------------------- 1 | use wasm_bindgen::prelude::*; 2 | use rsa::pkcs8::LineEnding; 3 | use der::Document; 4 | 5 | pub mod rsa_private; 6 | pub mod rsa_public; 7 | mod utils; 8 | -------------------------------------------------------------------------------- /rust/rsa/src/rsa_private.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | 3 | use rsa::pkcs8::{DecodePrivateKey, EncodePrivateKey, EncodePublicKey}; 4 | use rsa::RsaPrivateKey; 5 | 6 | #[wasm_bindgen] 7 | #[derive(Debug)] 8 | pub struct RsaPrivate { 9 | pri_instance: RsaPrivateKey, 10 | pri_pem: String, 11 | pub_pem: String, 12 | } 13 | 14 | #[wasm_bindgen] 15 | impl RsaPrivate { 16 | #[wasm_bindgen(constructor)] 17 | pub fn new(bits: Option, input_key_pem: Option) -> Self { 18 | utils::set_panic_hook(); 19 | let mut rng = rand::thread_rng(); 20 | 21 | let pri_instance = match input_key_pem { 22 | Some(key_pem) => RsaPrivateKey::from_pkcs8_pem(&key_pem) 23 | .expect("Failed to read private key pem file"), 24 | _ => match bits { 25 | Some(bits) => RsaPrivateKey::new(&mut rng, bits).expect("Fialed to generate keys"), 26 | _ => panic!("Neither bit size nor key file is provided"), 27 | } 28 | }; 29 | 30 | let pri_pem = pri_instance 31 | .to_pkcs8_pem(LineEnding::default()) 32 | .expect("Failed to transform keys to pem") 33 | .to_string(); 34 | let pub_pem = pri_instance 35 | .to_public_key() 36 | .to_public_key_pem(LineEnding::default()) 37 | .expect("Failed to transform keys to pem") 38 | .to_string(); 39 | Self { 40 | pri_instance, 41 | pri_pem, 42 | pub_pem, 43 | } 44 | } 45 | 46 | pub fn decrypt(&self, ciphertext: &[u8], padding_scheme: &str, hash_function: &str) -> Vec { 47 | let padding = utils::padding_util("encrypt", padding_scheme, hash_function, b""); 48 | 49 | self.pri_instance 50 | .decrypt(padding, ciphertext) 51 | .expect("Failed to decrypt the ciphertext!") 52 | } 53 | 54 | pub fn sign(&self, digest: &[u8], padding_scheme: &str, hash_function: &str) -> Vec { 55 | let padding = utils::padding_util("sign", padding_scheme, hash_function, digest); 56 | 57 | self.pri_instance.sign(padding, &digest).expect("Failed to sign digest") 58 | } 59 | 60 | #[wasm_bindgen(js_name = getPrivateKeyContent)] 61 | pub fn get_private_key_content(&self, fmt: &str) -> JsValue { 62 | match fmt { 63 | "pem" => JsValue::from_str(&self.pri_pem), 64 | "der" => { 65 | serde_wasm_bindgen::to_value( 66 | &self.pri_instance 67 | .to_pkcs8_der() 68 | .expect("Failed to transform private key to bytes") 69 | .as_der() 70 | .to_vec() 71 | ).unwrap() 72 | }, 73 | _ => panic!("Only pem and der supported") 74 | } 75 | } 76 | 77 | #[wasm_bindgen(js_name = getPublicKeyPem)] 78 | pub fn get_public_key_pem(&self) -> String { 79 | self.pub_pem.clone() 80 | } 81 | } 82 | 83 | #[cfg(test)] 84 | mod rsa_private_tests { 85 | use super::*; 86 | 87 | #[test] 88 | fn can_new_with_bits() { 89 | let rsa_private = RsaPrivate::new(Some(1024), None); 90 | assert_eq!(rsa_private.pri_pem.is_empty(), false); 91 | } 92 | 93 | #[test] 94 | #[should_panic] 95 | fn cannot_new_with_empty_key() { 96 | RsaPrivate::new(None, Some(String::from(""))); 97 | } 98 | 99 | #[test] 100 | fn can_get_public_content() { 101 | let rsa_private = RsaPrivate::new(Some(1024), None); 102 | assert_ne!(rsa_private.get_public_key_pem(), String::from("")); 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /rust/rsa/src/rsa_public.rs: -------------------------------------------------------------------------------- 1 | use super::*; 2 | 3 | use rsa::pkcs8::{DecodePublicKey, EncodePublicKey}; 4 | use rsa::{PublicKey, RsaPublicKey, PublicKeyParts}; 5 | 6 | #[wasm_bindgen] 7 | #[derive(Debug)] 8 | pub struct RsaPublic { 9 | pub_instance: RsaPublicKey, 10 | pub_pem: String, 11 | } 12 | 13 | #[wasm_bindgen] 14 | impl RsaPublic { 15 | #[wasm_bindgen(constructor)] 16 | // TODO: is n and e needed in struct? 17 | pub fn new(input_key_pem: String) -> Self { 18 | utils::set_panic_hook(); 19 | let pub_instance = RsaPublicKey::from_public_key_pem(&input_key_pem) 20 | .expect("Failed to read public key bytes!"); 21 | let pub_pem = pub_instance 22 | .to_public_key_pem(LineEnding::default()) 23 | .expect("Failed to transform key to pem!"); 24 | 25 | Self { 26 | pub_instance, 27 | pub_pem, 28 | } 29 | } 30 | 31 | pub fn encrypt(&self, msg: &[u8], padding_scheme: &str, hash_function: &str) -> Vec { 32 | let padding = utils::padding_util("encrypt", padding_scheme, hash_function, b""); 33 | let mut rng = rand::thread_rng(); 34 | 35 | self.pub_instance 36 | .encrypt(&mut rng, padding, &msg[..]) 37 | .expect("Failed to encrypt the message!") 38 | } 39 | 40 | pub fn verify(&self, digest: &[u8], sig: Vec, padding_scheme: &str, hash_function: &str) -> bool { 41 | let padding = utils::padding_util("sign", padding_scheme, hash_function, digest); 42 | 43 | self.pub_instance.verify(padding, digest, &sig).is_ok() 44 | } 45 | 46 | #[wasm_bindgen(js_name = getKeySize)] 47 | pub fn get_key_size(&self) -> usize { 48 | self.pub_instance.size() 49 | } 50 | 51 | #[wasm_bindgen(js_name = getPublicKeyContent)] 52 | pub fn get_public_key_content(&self, fmt: &str) -> JsValue { 53 | match fmt { 54 | "pem" => JsValue::from_str(&self.pub_pem), 55 | // TODO: Der generated by this func cannnot be verified by OpenSSL 56 | "der" => { 57 | serde_wasm_bindgen::to_value( 58 | &self.pub_instance 59 | .to_public_key_der() 60 | .expect("Failed to transform public key to der!") 61 | .to_der() 62 | .to_vec() 63 | ).unwrap() 64 | }, 65 | _ => panic!("Only pem and der supported") 66 | } 67 | } 68 | } 69 | 70 | #[cfg(test)] 71 | mod rsa_public_tests { 72 | use super::*; 73 | use super::super::rsa_private::RsaPrivate; 74 | 75 | #[test] 76 | fn can_new_with_rsa_private() { 77 | let rsa_public = RsaPublic::new(RsaPrivate::new(Some(1024), None).get_public_key_pem()); 78 | assert_eq!(rsa_public.pub_pem.is_empty(), false); 79 | } 80 | 81 | #[test] 82 | #[should_panic] 83 | fn cannot_new_with_empty_key() { 84 | RsaPublic::new(String::from("")); 85 | } 86 | 87 | #[test] 88 | fn can_encrypt() { 89 | let rsa_public = RsaPublic::new(RsaPrivate::new(Some(1024), None).get_public_key_pem()); 90 | assert_ne!(rsa_public.encrypt(b"secret", "OAEP", "SHA256"), Vec::::new()); 91 | } 92 | 93 | #[test] 94 | fn can_get_size() { 95 | let rsa_public = RsaPublic::new(RsaPrivate::new(Some(1024), None).get_public_key_pem()); 96 | assert_eq!(rsa_public.get_key_size(), 1024 / 8); 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /rust/rsa/src/utils.rs: -------------------------------------------------------------------------------- 1 | use rsa::{Hash, PaddingScheme}; 2 | use rand::rngs::ThreadRng; 3 | 4 | #[allow(unused)] // allow function unused 5 | pub fn set_panic_hook() { 6 | // When the `console_error_panic_hook` feature is enabled, we can call the 7 | // `set_panic_hook` function at least once during initialization, and then 8 | // we will get better error messages if our code ever panics. 9 | // 10 | // For more details see 11 | // https://github.com/rustwasm/console_error_panic_hook#readme 12 | #[cfg(feature = "console_error_panic_hook")] 13 | console_error_panic_hook::set_once(); 14 | } 15 | 16 | pub fn padding_util(op: &str, padding_scheme: &str, hash_function: &str, digest: &[u8]) -> PaddingScheme { 17 | match padding_scheme { 18 | "PKCS1V15" if op == "encrypt" => PaddingScheme::new_pkcs1v15_encrypt(), 19 | "OAEP" if op == "encrypt" => match hash_function { 20 | "MD5" => PaddingScheme::new_oaep::(), 21 | "SHA1" => PaddingScheme::new_oaep::(), 22 | "SHA224" => PaddingScheme::new_oaep::(), 23 | "SHA256" => PaddingScheme::new_oaep::(), 24 | "SHA384" => PaddingScheme::new_oaep::(), 25 | "SHA512" => PaddingScheme::new_oaep::(), 26 | "RIPEMD160" => PaddingScheme::new_oaep::(), 27 | _ => panic!("The hash function is not supported."), 28 | }, 29 | "PKCS1V15" if op == "sign" => match hash_function { 30 | "MD5" => PaddingScheme::new_pkcs1v15_sign(Some(Hash::MD5)), 31 | "SHA1" => PaddingScheme::new_pkcs1v15_sign(Some(Hash::SHA1)), 32 | "SHA224" => PaddingScheme::new_pkcs1v15_sign(Some(Hash::SHA2_224)), 33 | "SHA256" => PaddingScheme::new_pkcs1v15_sign(Some(Hash::SHA2_256)), 34 | "SHA384" => PaddingScheme::new_pkcs1v15_sign(Some(Hash::SHA2_384)), 35 | "SHA512" => PaddingScheme::new_pkcs1v15_sign(Some(Hash::SHA2_512)), 36 | "RIPEMD160" => PaddingScheme::new_pkcs1v15_sign(Some(Hash::RIPEMD160)), 37 | _ => panic!("The hash function is not supported."), 38 | }, 39 | "PSS" if op == "sign" => match hash_function { 40 | "MD5" => PaddingScheme::new_pss_with_salt::(rand::thread_rng(), digest.len()), 41 | "SHA1" => PaddingScheme::new_pss_with_salt::(rand::thread_rng(), digest.len()), 42 | "SHA224" => PaddingScheme::new_pss_with_salt::(rand::thread_rng(), digest.len()), 43 | "SHA256" => PaddingScheme::new_pss_with_salt::(rand::thread_rng(), digest.len()), 44 | "SHA384" => PaddingScheme::new_pss_with_salt::(rand::thread_rng(), digest.len()), 45 | "SHA512" => PaddingScheme::new_pss_with_salt::(rand::thread_rng(), digest.len()), 46 | "RIPEMD160" => PaddingScheme::new_pss_with_salt::(rand::thread_rng(), digest.len()), 47 | _ => panic!("The hash function is not supported."), 48 | }, 49 | _ => panic!("The padding scheme is not supported."), 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /rust/sha1/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "sha1" 3 | version = "0.1.0" 4 | authors = ["Alanscut "] 5 | edition = "2018" 6 | 7 | [lib] 8 | crate-type = ["cdylib", "rlib"] 9 | 10 | [features] 11 | default = ["console_error_panic_hook"] 12 | 13 | [dependencies] 14 | wasm-bindgen = "0.2.63" 15 | 16 | # The `console_error_panic_hook` crate provides better debugging of panics by 17 | # logging them with `console.error`. This is great for development, but requires 18 | # all the `std::fmt` and `std::panicking` infrastructure, so isn't great for 19 | # code size when deploying. 20 | console_error_panic_hook = { version = "0.1.6", optional = true } 21 | 22 | # `wee_alloc` is a tiny allocator for wasm that is only ~1K in code size 23 | # compared to the default allocator's ~10K. It is slower than the default 24 | # allocator, however. 25 | # 26 | # Unfortunately, `wee_alloc` requires nightly Rust when targeting wasm for now. 27 | wee_alloc = { version = "0.4.5", optional = true } 28 | 29 | [dev-dependencies] 30 | wasm-bindgen-test = "0.3.13" 31 | 32 | [profile.release] 33 | lto = true 34 | # Tell `rustc` to optimize for small code size. 35 | opt-level = 3 36 | -------------------------------------------------------------------------------- /rust/sha1/src/lib.rs: -------------------------------------------------------------------------------- 1 | use std::ptr::null; 2 | use std::cmp; 3 | use wasm_bindgen::prelude::*; 4 | 5 | #[wasm_bindgen] 6 | pub fn doCrypt(doFlush: u8, hashWords: &mut [u32], dataWords: &[u32], dataSigBytes: u32, blockSize: u32, minBufferSize: u32) -> u32 { 7 | let blockSizeBytes = blockSize * 4; 8 | let mut nBlocksReady: f32 = dataSigBytes as f32 / blockSizeBytes as f32; 9 | if doFlush > 0 { 10 | nBlocksReady = nBlocksReady.ceil(); 11 | } else { 12 | nBlocksReady = f32::max(nBlocksReady - minBufferSize as f32, 0_f32); 13 | } 14 | 15 | let nWordsReady = nBlocksReady as u32 * blockSize; 16 | 17 | if nWordsReady > 0 { 18 | let mut offset = 0; 19 | while offset < nWordsReady { 20 | doCryptBlock(dataWords, hashWords, offset); 21 | offset += blockSize; 22 | } 23 | } 24 | 25 | nWordsReady 26 | } 27 | 28 | fn doCryptBlock(data: &[u32], hash: &mut [u32], offsetU32: u32) { 29 | let offset = offsetU32 as usize; 30 | let mut w: [u32; 80] = [0; 80]; 31 | let mut a: u32 = hash[0]; 32 | let mut b: u32 = hash[1]; 33 | let mut c: u32 = hash[2]; 34 | let mut d: u32 = hash[3]; 35 | let mut e: u32 = hash[4]; 36 | 37 | let mut i = 0; 38 | while i < 80 { 39 | if i < 16 { 40 | w[i] = data[offset + i]; 41 | } else { 42 | let n = w[i - 3] ^ w[i - 8] ^ w[i - 14] ^ w[i - 16]; 43 | w[i] = (n << 1) | (n >> 31); 44 | } 45 | 46 | let mut t: u32 = ((a << 5) | (a >> 27)) + e + w[i]; 47 | if i < 20 { 48 | t += ((b & c) | (!b & d)) + 0x5a827999; 49 | } else if i < 40 { 50 | t += (b ^ c ^ d) + 0x6ed9eba1; 51 | } else if i < 60 { 52 | t += ((b & c) | (b & d) | (c & d)) - 0x70e44324; 53 | } else { 54 | t += (b ^ c ^ d) - 0x359d3e2a; 55 | } 56 | 57 | e = d; 58 | d = c; 59 | c = (b << 30) | (b >> 2); 60 | b = a; 61 | a = t; 62 | 63 | i += 1; 64 | } 65 | 66 | // Intermediate hash value 67 | hash[0] = hash[0] + a; 68 | hash[1] = hash[1] + b; 69 | hash[2] = hash[2] + c; 70 | hash[3] = hash[3] + d; 71 | hash[4] = hash[4] + e; 72 | } 73 | -------------------------------------------------------------------------------- /rust/sha256/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "sha256" 3 | version = "0.1.0" 4 | authors = ["Alanscut "] 5 | edition = "2018" 6 | 7 | [lib] 8 | crate-type = ["cdylib", "rlib"] 9 | 10 | [features] 11 | default = ["console_error_panic_hook"] 12 | 13 | [dependencies] 14 | wasm-bindgen = "0.2.63" 15 | 16 | # The `console_error_panic_hook` crate provides better debugging of panics by 17 | # logging them with `console.error`. This is great for development, but requires 18 | # all the `std::fmt` and `std::panicking` infrastructure, so isn't great for 19 | # code size when deploying. 20 | console_error_panic_hook = { version = "0.1.6", optional = true } 21 | 22 | # `wee_alloc` is a tiny allocator for wasm that is only ~1K in code size 23 | # compared to the default allocator's ~10K. It is slower than the default 24 | # allocator, however. 25 | # 26 | # Unfortunately, `wee_alloc` requires nightly Rust when targeting wasm for now. 27 | wee_alloc = { version = "0.4.5", optional = true } 28 | 29 | [dev-dependencies] 30 | wasm-bindgen-test = "0.3.13" 31 | 32 | [profile.release] 33 | lto = true 34 | # Tell `rustc` to optimize for small code size. 35 | opt-level = 3 36 | -------------------------------------------------------------------------------- /rust/sha256/src/lib.rs: -------------------------------------------------------------------------------- 1 | mod utils; 2 | 3 | use std::ptr::null; 4 | use std::cmp; 5 | use wasm_bindgen::prelude::*; 6 | use utils::*; 7 | 8 | #[wasm_bindgen] 9 | pub fn doCrypt(doFlush: u8, dataWords: &[u32], dataSigBytes: u32, blockSize: u32, hash: &mut [u32], minBufferSize: u32) -> u32 { 10 | let blockSizeBytes = blockSize * 4; 11 | let mut nBlocksReady: f32 = dataSigBytes as f32 / blockSizeBytes as f32; 12 | if doFlush > 0 { 13 | nBlocksReady = nBlocksReady.ceil(); 14 | } else { 15 | nBlocksReady = f32::max(nBlocksReady - minBufferSize as f32, 0_f32); 16 | } 17 | 18 | let nWordsReady = nBlocksReady as u32 * blockSize; 19 | 20 | if nWordsReady > 0 { 21 | let mut offset = 0; 22 | while offset < nWordsReady { 23 | doCryptBlock(dataWords, offset, hash); 24 | offset += blockSize; 25 | } 26 | } 27 | 28 | nWordsReady 29 | } 30 | 31 | fn doCryptBlock(data: &[u32], offsetU32: u32, hash: &mut [u32]) { 32 | let K = getK(); 33 | let offset = offsetU32 as usize; 34 | 35 | // Working variables 36 | let mut a = hash[0]; 37 | let mut b = hash[1]; 38 | let mut c = hash[2]; 39 | let mut d = hash[3]; 40 | let mut e = hash[4]; 41 | let mut f = hash[5]; 42 | let mut g = hash[6]; 43 | let mut h = hash[7]; 44 | 45 | let mut W: [u32; 64] = [0; 64]; 46 | // Computation 47 | for i in 0..64 { 48 | if i < 16 { 49 | W[i] = data[offset + i]; 50 | } else { 51 | let gamma0x = W[i - 15]; 52 | let gamma0 = ((gamma0x << 25) | (gamma0x >> 7)) ^ ((gamma0x << 14) | (gamma0x >> 18)) ^ (gamma0x >> 3); 53 | let gamma1x = W[i - 2]; 54 | let gamma1 = ((gamma1x << 15) | (gamma1x >> 17)) ^ ((gamma1x << 13) | (gamma1x >> 19)) ^ (gamma1x >> 10); 55 | W[i] = gamma0 + W[i - 7] + gamma1 + W[i - 16]; 56 | } 57 | 58 | let ch = (e & f) ^ (!e & g); 59 | let maj = (a & b) ^ (a & c) ^ (b & c); 60 | 61 | let sigma0 = ((a << 30) | (a >> 2)) ^ ((a << 19) | (a >> 13)) ^ ((a << 10) | (a >> 22)); 62 | let sigma1 = ((e << 26) | (e >> 6)) ^ ((e << 21) | (e >> 11)) ^ ((e << 7) | (e >> 25)); 63 | 64 | let t1 = h + sigma1 + ch + K[i] + W[i]; 65 | let t2 = sigma0 + maj; 66 | 67 | h = g; 68 | g = f; 69 | f = e; 70 | e = d + t1; 71 | d = c; 72 | c = b; 73 | b = a; 74 | a = t1 + t2; 75 | } 76 | 77 | // Intermediate hash value 78 | hash[0] = hash[0] + a; 79 | hash[1] = hash[1] + b; 80 | hash[2] = hash[2] + c; 81 | hash[3] = hash[3] + d; 82 | hash[4] = hash[4] + e; 83 | hash[5] = hash[5] + f; 84 | hash[6] = hash[6] + g; 85 | hash[7] = hash[7] + h; 86 | } 87 | 88 | -------------------------------------------------------------------------------- /rust/sha256/src/utils.rs: -------------------------------------------------------------------------------- 1 | pub fn getK() -> [u32; 64] { 2 | [1116352408, 1899447441, 3049323471, 3921009573, 961987163, 1508970993, 2453635748, 2870763221, 3 | 3624381080, 310598401, 607225278, 1426881987, 1925078388, 2162078206, 2614888103, 3248222580, 4 | 3835390401, 4022224774, 264347078, 604807628, 770255983, 1249150122, 1555081692, 1996064986, 5 | 2554220882, 2821834349, 2952996808, 3210313671, 3336571891, 3584528711, 113926993, 338241895, 6 | 666307205, 773529912, 1294757372, 1396182291, 1695183700, 1986661051, 2177026350, 2456956037, 7 | 2730485921, 2820302411, 3259730800, 3345764771, 3516065817, 3600352804, 4094571909, 275423344, 8 | 430227734, 506948616, 659060556, 883997877, 958139571, 1322822218, 1537002063, 1747873779, 9 | 1955562222, 2024104815, 2227730452, 2361852424, 2428436474, 2756734187, 3204031479, 3329325298] 10 | } -------------------------------------------------------------------------------- /rust/sha3/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "sha3" 3 | version = "0.1.0" 4 | authors = ["Alanscut "] 5 | edition = "2018" 6 | 7 | [lib] 8 | crate-type = ["cdylib", "rlib"] 9 | 10 | [features] 11 | default = ["console_error_panic_hook"] 12 | 13 | [dependencies] 14 | wasm-bindgen = "0.2.63" 15 | 16 | # The `console_error_panic_hook` crate provides better debugging of panics by 17 | # logging them with `console.error`. This is great for development, but requires 18 | # all the `std::fmt` and `std::panicking` infrastructure, so isn't great for 19 | # code size when deploying. 20 | console_error_panic_hook = { version = "0.1.6", optional = true } 21 | 22 | # `wee_alloc` is a tiny allocator for wasm that is only ~1K in code size 23 | # compared to the default allocator's ~10K. It is slower than the default 24 | # allocator, however. 25 | # 26 | # Unfortunately, `wee_alloc` requires nightly Rust when targeting wasm for now. 27 | wee_alloc = { version = "0.4.5", optional = true } 28 | 29 | [dev-dependencies] 30 | wasm-bindgen-test = "0.3.13" 31 | 32 | [profile.release] 33 | lto = true 34 | # Tell `rustc` to optimize for small code size. 35 | opt-level = 3 36 | -------------------------------------------------------------------------------- /rust/sha3/src/utils.rs: -------------------------------------------------------------------------------- 1 | #[derive(Copy, Clone, Debug)] 2 | pub struct X64Word { 3 | pub high: u32, 4 | pub low: u32, 5 | } 6 | 7 | pub fn getRhoOffsets() -> [u32; 25] { 8 | [0, 1, 62, 28, 27, 36, 44, 6, 55, 20, 3, 10, 43, 25, 39, 41, 45, 15, 21, 8, 18, 2, 61, 56, 14] 9 | } 10 | 11 | pub fn getPiIndexes() -> [u32; 25] { 12 | [0, 10, 20, 5, 15, 16, 1, 11, 21, 6, 7, 17, 2, 12, 22, 23, 8, 18, 3, 13, 14, 24, 9, 19, 4] 13 | } 14 | 15 | pub fn getRoundConstants() -> [X64Word; 24] { 16 | [X64Word { 17 | high: 0, 18 | low: 1, 19 | }, 20 | X64Word { 21 | high: 0, 22 | low: 32898, 23 | }, 24 | X64Word { 25 | high: 2147483648 as u32, 26 | low: 32906, 27 | }, 28 | X64Word { 29 | high: 2147483648, 30 | low: 2147516416, 31 | }, 32 | X64Word { 33 | high: 0, 34 | low: 32907, 35 | }, 36 | X64Word { 37 | high: 0, 38 | low: 2147483649, 39 | }, 40 | X64Word { 41 | high: 2147483648, 42 | low: 2147516545, 43 | }, 44 | X64Word { 45 | high: 2147483648, 46 | low: 32777, 47 | }, 48 | X64Word { 49 | high: 0, 50 | low: 138, 51 | }, 52 | X64Word { 53 | high: 0, 54 | low: 136, 55 | }, 56 | X64Word { 57 | high: 0, 58 | low: 2147516425, 59 | }, 60 | X64Word { 61 | high: 0, 62 | low: 2147483658, 63 | }, 64 | X64Word { 65 | high: 0, 66 | low: 2147516555, 67 | }, 68 | X64Word { 69 | high: 2147483648, 70 | low: 139, 71 | }, 72 | X64Word { 73 | high: 2147483648, 74 | low: 32905, 75 | }, 76 | X64Word { 77 | high: 2147483648, 78 | low: 32771, 79 | }, 80 | X64Word { 81 | high: 2147483648, 82 | low: 32770, 83 | }, 84 | X64Word { 85 | high: 2147483648, 86 | low: 128, 87 | }, 88 | X64Word { 89 | high: 0, 90 | low: 32778, 91 | }, 92 | X64Word { 93 | high: 2147483648, 94 | low: 2147483658, 95 | }, 96 | X64Word { 97 | high: 2147483648, 98 | low: 2147516545, 99 | }, 100 | X64Word { 101 | high: 2147483648, 102 | low: 32896, 103 | }, 104 | X64Word { 105 | high: 0, 106 | low: 2147483649, 107 | }, 108 | X64Word { 109 | high: 2147483648, 110 | low: 2147516424, 111 | }] 112 | } 113 | -------------------------------------------------------------------------------- /rust/sha512/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "sha512" 3 | version = "0.1.0" 4 | authors = ["Alanscut "] 5 | edition = "2018" 6 | 7 | [lib] 8 | crate-type = ["cdylib", "rlib"] 9 | 10 | [features] 11 | default = ["console_error_panic_hook"] 12 | 13 | [dependencies] 14 | wasm-bindgen = "0.2.63" 15 | 16 | # The `console_error_panic_hook` crate provides better debugging of panics by 17 | # logging them with `console.error`. This is great for development, but requires 18 | # all the `std::fmt` and `std::panicking` infrastructure, so isn't great for 19 | # code size when deploying. 20 | console_error_panic_hook = { version = "0.1.6", optional = true } 21 | 22 | # `wee_alloc` is a tiny allocator for wasm that is only ~1K in code size 23 | # compared to the default allocator's ~10K. It is slower than the default 24 | # allocator, however. 25 | # 26 | # Unfortunately, `wee_alloc` requires nightly Rust when targeting wasm for now. 27 | wee_alloc = { version = "0.4.5", optional = true } 28 | 29 | [dev-dependencies] 30 | wasm-bindgen-test = "0.3.13" 31 | 32 | [profile.release] 33 | lto=true 34 | opt-level = 3 35 | -------------------------------------------------------------------------------- /rust/sha512/src/lib.rs: -------------------------------------------------------------------------------- 1 | mod utils; 2 | 3 | use wasm_bindgen::prelude::*; 4 | use utils::*; 5 | 6 | #[wasm_bindgen] 7 | pub fn doCrypt(nWordsReady: u32, blockSize: u32, dataWords: &[u32], hash: &mut [u32]) { 8 | let mut hashU64: [u64; 8] = [0; 8]; 9 | for i in 0..8 { 10 | let hashHigh: u64 = hash[i * 2] as u64; 11 | let hashLow: u64 = hash[i * 2 + 1] as u64; 12 | hashU64[i] = hashHigh << 32 | hashLow; 13 | } 14 | 15 | if nWordsReady > 0 { 16 | let mut offset = 0; 17 | while offset < nWordsReady { 18 | doCryptBlock(dataWords, offset, &mut hashU64); 19 | offset += blockSize; 20 | } 21 | } 22 | for i in 0..8 { 23 | hash[i * 2] = (hashU64[i] >> 32) as u32; 24 | hash[i * 2 + 1] = (hashU64[i] & 0xffffffff) as u32; 25 | } 26 | } 27 | 28 | fn doCryptBlock(data: &[u32], offsetU32: u32, hash: &mut [u64]) { 29 | let K = getK(); 30 | let offset = offsetU32 as usize; 31 | 32 | // Working variables 33 | let mut a = hash[0]; 34 | let mut b = hash[1]; 35 | let mut c = hash[2]; 36 | let mut d = hash[3]; 37 | let mut e = hash[4]; 38 | let mut f = hash[5]; 39 | let mut g = hash[6]; 40 | let mut h = hash[7]; 41 | 42 | let mut W: [u64; 80] = [0; 80]; 43 | // Computation 44 | for i in 0..80 { 45 | if i < 16 { 46 | W[i] = data[offset + i * 2] as u64; 47 | W[i] = W[i] << 32 | data[offset + i * 2 + 1] as u64; 48 | } else { 49 | let gamma0x = W[i - 15]; 50 | let gamma0 = ((gamma0x >> 1) | (gamma0x << 63)) ^ ((gamma0x >> 8) | (gamma0x << 56)) ^ (gamma0x >> 7); 51 | let gamma1x = W[i - 2]; 52 | let gamma1 = ((gamma1x >> 19) | (gamma1x << 45)) ^ ((gamma1x << 3) | (gamma1x >> 61)) ^ (gamma1x >> 6); 53 | W[i] = ((gamma0 as u128) + (W[i - 7] as u128) + (gamma1 as u128) + (W[i - 16] as u128)) as u64; 54 | } 55 | 56 | let ch = (e & f) ^ (!e & g); 57 | let maj = (a & b) ^ (a & c) ^ (b & c); 58 | 59 | let sigma0 = ((a >> 28) | (a << 36)) ^ ((a << 30) | (a >> 34)) ^ ((a << 25) | (a >> 39)); 60 | let sigma1 = ((e >> 14) | (e << 50)) ^ ((e >> 18) | (e << 46)) ^ ((e << 23) | (e >> 41)); 61 | 62 | let t1 = ((h as u128) + (sigma1 as u128) + (ch as u128) + (K[i] as u128) + (W[i] as u128)) as u64; 63 | let t2 = ((sigma0 as u128) + (maj as u128)) as u64; 64 | 65 | h = g; 66 | g = f; 67 | f = e; 68 | e = ((d as u128) + (t1 as u128)) as u64; 69 | d = c; 70 | c = b; 71 | b = a; 72 | a = ((t1 as u128) + (t2 as u128)) as u64; 73 | } 74 | 75 | // Intermediate hash value 76 | hash[0] = ((hash[0] as u128) + (a as u128)) as u64; 77 | hash[1] = ((hash[1] as u128) + (b as u128)) as u64; 78 | hash[2] = ((hash[2] as u128) + (c as u128)) as u64; 79 | hash[3] = ((hash[3] as u128) + (d as u128)) as u64; 80 | hash[4] = ((hash[4] as u128) + (e as u128)) as u64; 81 | hash[5] = ((hash[5] as u128) + (f as u128)) as u64; 82 | hash[6] = ((hash[6] as u128) + (g as u128)) as u64; 83 | hash[7] = ((hash[7] as u128) + (h as u128)) as u64; 84 | } 85 | -------------------------------------------------------------------------------- /rust/sha512/src/utils.rs: -------------------------------------------------------------------------------- 1 | pub fn getK() -> [u64; 80] { 2 | [4794697086780616226, 8158064640168781261, 13096744586834688815, 16840607885511220156, 4131703408338449720, 3 | 6480981068601479193, 10538285296894168987, 12329834152419229976, 15566598209576043074, 1334009975649890238, 4 | 2608012711638119052, 6128411473006802146, 8268148722764581231, 9286055187155687089, 11230858885718282805, 5 | 13951009754708518548, 16472876342353939154, 17275323862435702243, 1135362057144423861, 2597628984639134821, 6 | 3308224258029322869, 5365058923640841347, 6679025012923562964, 8573033837759648693, 10970295158949994411, 7 | 12119686244451234320, 12683024718118986047, 13788192230050041572, 14330467153632333762, 15395433587784984357, 8 | 489312712824947311, 1452737877330783856, 2861767655752347644, 3322285676063803686, 5560940570517711597, 9 | 5996557281743188959, 7280758554555802590, 8532644243296465576, 9350256976987008742, 10552545826968843579, 10 | 11727347734174303076, 12113106623233404929, 14000437183269869457, 14369950271660146224, 15101387698204529176, 11 | 15463397548674623760, 17586052441742319658, 1182934255886127544, 1847814050463011016, 2177327727835720531, 12 | 2830643537854262169, 3796741975233480872, 4115178125766777443, 5681478168544905931, 6601373596472566643, 13 | 7507060721942968483, 8399075790359081724, 8693463985226723168, 9568029438360202098, 10144078919501101548, 14 | 10430055236837252648, 11840083180663258601, 13761210420658862357, 14299343276471374635, 14566680578165727644, 15 | 15097957966210449927, 16922976911328602910, 17689382322260857208, 500013540394364858, 748580250866718886, 16 | 1242879168328830382, 1977374033974150939, 2944078676154940804, 3659926193048069267, 4368137639120453308, 17 | 4836135668995329356, 5532061633213252278, 6448918945643986474, 6902733635092675308, 7801388544844847127] 18 | } -------------------------------------------------------------------------------- /src/algo/hash/md5_bg.js: -------------------------------------------------------------------------------- 1 | export function md5Wasm(wasm) { 2 | let cachegetUint32Memory0 = null; 3 | 4 | function getUint32Memory0() { 5 | if (cachegetUint32Memory0 === null || cachegetUint32Memory0.buffer !== wasm.memory.buffer) { 6 | cachegetUint32Memory0 = new Uint32Array(wasm.memory.buffer); 7 | } 8 | return cachegetUint32Memory0; 9 | } 10 | 11 | let WASM_VECTOR_LEN = 0; 12 | 13 | function passArray32ToWasm0(arg, malloc) { 14 | const ptr = malloc(arg.length * 4); 15 | getUint32Memory0().set(arg, ptr / 4); 16 | WASM_VECTOR_LEN = arg.length; 17 | return ptr; 18 | } 19 | 20 | /** 21 | * @param {number} doFlush 22 | * @param {Uint32Array} hashWords 23 | * @param {Uint32Array} dataWords 24 | * @param {number} dataSigBytes 25 | * @param {number} blockSize 26 | * @param {number} minBufferSize 27 | * @returns {number} 28 | */ 29 | function md5Process(doFlush, hashWords, dataWords, dataSigBytes, blockSize, minBufferSize) { 30 | try { 31 | var ptr0 = passArray32ToWasm0(hashWords, wasm.__wbindgen_malloc); 32 | var len0 = WASM_VECTOR_LEN; 33 | var ptr1 = passArray32ToWasm0(dataWords, wasm.__wbindgen_malloc); 34 | var len1 = WASM_VECTOR_LEN; 35 | var ret = wasm.md5Process(doFlush, ptr0, len0, ptr1, len1, dataSigBytes, blockSize, minBufferSize); 36 | return ret >>> 0; 37 | } finally { 38 | hashWords.set(getUint32Memory0().subarray(ptr0 / 4, ptr0 / 4 + len0)); 39 | wasm.__wbindgen_free(ptr0, len0 * 4); 40 | } 41 | } 42 | 43 | return { 44 | md5Process: md5Process 45 | }; 46 | } 47 | -------------------------------------------------------------------------------- /src/algo/hash/ripemd160_bg.js: -------------------------------------------------------------------------------- 1 | export function ripemd160Wasm(wasm) { 2 | let cachegetUint32Memory0 = null; 3 | function getUint32Memory0() { 4 | if (cachegetUint32Memory0 === null || cachegetUint32Memory0.buffer !== wasm.memory.buffer) { 5 | cachegetUint32Memory0 = new Uint32Array(wasm.memory.buffer); 6 | } 7 | return cachegetUint32Memory0; 8 | } 9 | 10 | let WASM_VECTOR_LEN = 0; 11 | 12 | function passArray32ToWasm0(arg, malloc) { 13 | const ptr = malloc(arg.length * 4); 14 | getUint32Memory0().set(arg, ptr / 4); 15 | WASM_VECTOR_LEN = arg.length; 16 | return ptr; 17 | } 18 | /** 19 | * @param {number} nWordsReady 20 | * @param {number} blockSize 21 | * @param {Uint32Array} dataWords 22 | * @param {Uint32Array} H 23 | */ 24 | function doProcess(nWordsReady, blockSize, dataWords, H) { 25 | try { 26 | var ptr0 = passArray32ToWasm0(dataWords, wasm.__wbindgen_malloc); 27 | var len0 = WASM_VECTOR_LEN; 28 | var ptr1 = passArray32ToWasm0(H, wasm.__wbindgen_malloc); 29 | var len1 = WASM_VECTOR_LEN; 30 | wasm.doProcess(nWordsReady, blockSize, ptr0, len0, ptr1, len1); 31 | } finally { 32 | H.set(getUint32Memory0().subarray(ptr1 / 4, ptr1 / 4 + len1)); 33 | wasm.__wbindgen_free(ptr1, len1 * 4); 34 | } 35 | } 36 | 37 | return { 38 | doProcess: doProcess 39 | }; 40 | } 41 | -------------------------------------------------------------------------------- /src/algo/hash/sha1_bg.js: -------------------------------------------------------------------------------- 1 | export function sha1Wasm(wasm) { 2 | let cachegetUint32Memory0 = null; 3 | function getUint32Memory0() { 4 | if (cachegetUint32Memory0 === null || cachegetUint32Memory0.buffer !== wasm.memory.buffer) { 5 | cachegetUint32Memory0 = new Uint32Array(wasm.memory.buffer); 6 | } 7 | return cachegetUint32Memory0; 8 | } 9 | 10 | let WASM_VECTOR_LEN = 0; 11 | 12 | function passArray32ToWasm0(arg, malloc) { 13 | const ptr = malloc(arg.length * 4); 14 | getUint32Memory0().set(arg, ptr / 4); 15 | WASM_VECTOR_LEN = arg.length; 16 | return ptr; 17 | } 18 | /** 19 | * @param {number} doFlush 20 | * @param {Uint32Array} hashWords 21 | * @param {Uint32Array} dataWords 22 | * @param {number} dataSigBytes 23 | * @param {number} blockSize 24 | * @param {number} minBufferSize 25 | * @returns {number} 26 | */ 27 | function doCrypt(doFlush, hashWords, dataWords, dataSigBytes, blockSize, minBufferSize) { 28 | try { 29 | var ptr0 = passArray32ToWasm0(hashWords, wasm.__wbindgen_malloc); 30 | var len0 = WASM_VECTOR_LEN; 31 | var ptr1 = passArray32ToWasm0(dataWords, wasm.__wbindgen_malloc); 32 | var len1 = WASM_VECTOR_LEN; 33 | var ret = wasm.doCrypt(doFlush, ptr0, len0, ptr1, len1, dataSigBytes, blockSize, minBufferSize); 34 | return ret >>> 0; 35 | } finally { 36 | hashWords.set(getUint32Memory0().subarray(ptr0 / 4, ptr0 / 4 + len0)); 37 | wasm.__wbindgen_free(ptr0, len0 * 4); 38 | } 39 | } 40 | 41 | return { 42 | doCrypt: doCrypt 43 | }; 44 | } 45 | -------------------------------------------------------------------------------- /src/algo/hash/sha224.js: -------------------------------------------------------------------------------- 1 | import { WordArray } from '../../core/core.js'; 2 | import { SHA256Algo } from './sha256.js'; 3 | 4 | /** 5 | * SHA-224 hash algorithm. 6 | */ 7 | export class SHA224Algo extends SHA256Algo { 8 | static outputSize = 224 / 8; 9 | 10 | static async loadWasm() { 11 | return SHA256Algo.loadWasm(); 12 | } 13 | 14 | async loadWasm() { 15 | return SHA224Algo.loadWasm(); 16 | } 17 | 18 | _doReset() { 19 | this._hash = new WordArray([ 20 | 0xc1059ed8, 21 | 0x367cd507, 22 | 0x3070dd17, 23 | 0xf70e5939, 24 | 0xffc00b31, 25 | 0x68581511, 26 | 0x64f98fa7, 27 | 0xbefa4fa4 28 | ]); 29 | } 30 | 31 | _doFinalize() { 32 | const hash = super._doFinalize.call(this); 33 | 34 | hash.sigBytes -= 4; 35 | 36 | return hash; 37 | } 38 | } 39 | 40 | /** 41 | * Shortcut function to the hasher's object interface. 42 | * 43 | * @param {WordArray|string} message The message to hash. 44 | * 45 | * @return {WordArray} The hash. 46 | * 47 | * @static 48 | * 49 | * @example 50 | * 51 | * const hash = CryptoJSW.SHA224('message'); 52 | * const hash = CryptoJSW.SHA224(wordArray); 53 | */ 54 | export const SHA224 = SHA256Algo._createHelper(SHA224Algo); 55 | 56 | /** 57 | * Shortcut function to the HMAC's object interface. 58 | * 59 | * @param {WordArray|string} message The message to hash. 60 | * @param {WordArray|string} key The secret key. 61 | * 62 | * @return {WordArray} The HMAC. 63 | * 64 | * @static 65 | * 66 | * @example 67 | * 68 | * const hmac = CryptoJSW.HmacSHA224(message, key); 69 | */ 70 | export const HmacSHA224 = SHA256Algo._createHmacHelper(SHA224Algo); 71 | -------------------------------------------------------------------------------- /src/algo/hash/sha256_bg.js: -------------------------------------------------------------------------------- 1 | export function sha256Wasm(wasm) { 2 | let cachegetUint32Memory0 = null; 3 | 4 | function getUint32Memory0() { 5 | if (cachegetUint32Memory0 === null || cachegetUint32Memory0.buffer !== wasm.memory.buffer) { 6 | cachegetUint32Memory0 = new Uint32Array(wasm.memory.buffer); 7 | } 8 | return cachegetUint32Memory0; 9 | } 10 | 11 | let WASM_VECTOR_LEN = 0; 12 | 13 | function passArray32ToWasm0(arg, malloc) { 14 | const ptr = malloc(arg.length * 4); 15 | getUint32Memory0().set(arg, ptr / 4); 16 | WASM_VECTOR_LEN = arg.length; 17 | return ptr; 18 | } 19 | 20 | /** 21 | * @param {number} doFlush 22 | * @param {Uint32Array} dataWords 23 | * @param {number} dataSigBytes 24 | * @param {number} blockSize 25 | * @param {Uint32Array} hash 26 | * @param {number} minBufferSize 27 | * @returns {number} 28 | */ 29 | function doCrypt(doFlush, dataWords, dataSigBytes, blockSize, hash, minBufferSize) { 30 | try { 31 | var ptr0 = passArray32ToWasm0(dataWords, wasm.__wbindgen_malloc); 32 | var len0 = WASM_VECTOR_LEN; 33 | var ptr1 = passArray32ToWasm0(hash, wasm.__wbindgen_malloc); 34 | var len1 = WASM_VECTOR_LEN; 35 | var ret = wasm.doCrypt(doFlush, ptr0, len0, dataSigBytes, blockSize, ptr1, len1, minBufferSize); 36 | return ret >>> 0; 37 | } finally { 38 | hash.set(getUint32Memory0().subarray(ptr1 / 4, ptr1 / 4 + len1)); 39 | wasm.__wbindgen_free(ptr1, len1 * 4); 40 | } 41 | } 42 | 43 | return { 44 | doCrypt: doCrypt 45 | }; 46 | } 47 | -------------------------------------------------------------------------------- /src/algo/hash/sha384.js: -------------------------------------------------------------------------------- 1 | import { X64Word, X64WordArray } from '../../core/x64-core.js'; 2 | import { SHA512Algo } from './sha512.js'; 3 | 4 | /** 5 | * SHA-384 hash algorithm. 6 | */ 7 | export class SHA384Algo extends SHA512Algo { 8 | static outputSize = 384 / 8; 9 | 10 | static async loadWasm() { 11 | return SHA512Algo.loadWasm(); 12 | } 13 | 14 | async loadWasm() { 15 | return SHA384Algo.loadWasm(); 16 | } 17 | 18 | _doReset() { 19 | this._hash = new X64WordArray([ 20 | new X64Word(0xcbbb9d5d, 0xc1059ed8), 21 | new X64Word(0x629a292a, 0x367cd507), 22 | new X64Word(0x9159015a, 0x3070dd17), 23 | new X64Word(0x152fecd8, 0xf70e5939), 24 | new X64Word(0x67332667, 0xffc00b31), 25 | new X64Word(0x8eb44a87, 0x68581511), 26 | new X64Word(0xdb0c2e0d, 0x64f98fa7), 27 | new X64Word(0x47b5481d, 0xbefa4fa4) 28 | ]); 29 | } 30 | 31 | _doFinalize() { 32 | const hash = super._doFinalize.call(this); 33 | 34 | hash.sigBytes -= 16; 35 | 36 | return hash; 37 | } 38 | } 39 | 40 | /** 41 | * Shortcut function to the hasher's object interface. 42 | * 43 | * @param {WordArray|string} message The message to hash. 44 | * 45 | * @return {WordArray} The hash. 46 | * 47 | * @static 48 | * 49 | * @example 50 | * 51 | * const hash = CryptoJSW.SHA384('message'); 52 | * const hash = CryptoJSW.SHA384(wordArray); 53 | */ 54 | export const SHA384 = SHA512Algo._createHelper(SHA384Algo); 55 | 56 | /** 57 | * Shortcut function to the HMAC's object interface. 58 | * 59 | * @param {WordArray|string} message The message to hash. 60 | * @param {WordArray|string} key The secret key. 61 | * 62 | * @return {WordArray} The HMAC. 63 | * 64 | * @static 65 | * 66 | * @example 67 | * 68 | * const hmac = CryptoJSW.HmacSHA384(message, key); 69 | */ 70 | export const HmacSHA384 = SHA512Algo._createHmacHelper(SHA384Algo); 71 | -------------------------------------------------------------------------------- /src/algo/hash/sha3_bg.js: -------------------------------------------------------------------------------- 1 | export function sha3Wasm(wasm) { 2 | let cachegetUint32Memory0 = null; 3 | function getUint32Memory0() { 4 | if (cachegetUint32Memory0 === null || cachegetUint32Memory0.buffer !== wasm.memory.buffer) { 5 | cachegetUint32Memory0 = new Uint32Array(wasm.memory.buffer); 6 | } 7 | return cachegetUint32Memory0; 8 | } 9 | 10 | let WASM_VECTOR_LEN = 0; 11 | 12 | function passArray32ToWasm0(arg, malloc) { 13 | const ptr = malloc(arg.length * 4); 14 | getUint32Memory0().set(arg, ptr / 4); 15 | WASM_VECTOR_LEN = arg.length; 16 | return ptr; 17 | } 18 | /** 19 | * @param {number} doFlush 20 | * @param {Uint32Array} dataWords 21 | * @param {number} dataSigBytes 22 | * @param {number} blockSize 23 | * @param {Uint32Array} stateData 24 | * @param {number} minBufferSize 25 | * @returns {number} 26 | */ 27 | function doCrypt(doFlush, dataWords, dataSigBytes, blockSize, stateData, minBufferSize) { 28 | try { 29 | var ptr0 = passArray32ToWasm0(dataWords, wasm.__wbindgen_malloc); 30 | var len0 = WASM_VECTOR_LEN; 31 | var ptr1 = passArray32ToWasm0(stateData, wasm.__wbindgen_malloc); 32 | var len1 = WASM_VECTOR_LEN; 33 | var ret = wasm.doCrypt(doFlush, ptr0, len0, dataSigBytes, blockSize, ptr1, len1, minBufferSize); 34 | return ret >>> 0; 35 | } finally { 36 | stateData.set(getUint32Memory0().subarray(ptr1 / 4, ptr1 / 4 + len1)); 37 | wasm.__wbindgen_free(ptr1, len1 * 4); 38 | } 39 | } 40 | 41 | return { 42 | doCrypt: doCrypt 43 | }; 44 | } 45 | -------------------------------------------------------------------------------- /src/algo/hash/sha512_bg.js: -------------------------------------------------------------------------------- 1 | export function sha512Wasm(wasm) { 2 | let cachegetUint32Memory0 = null; 3 | function getUint32Memory0() { 4 | if (cachegetUint32Memory0 === null || cachegetUint32Memory0.buffer !== wasm.memory.buffer) { 5 | cachegetUint32Memory0 = new Uint32Array(wasm.memory.buffer); 6 | } 7 | return cachegetUint32Memory0; 8 | } 9 | 10 | let WASM_VECTOR_LEN = 0; 11 | 12 | function passArray32ToWasm0(arg, malloc) { 13 | const ptr = malloc(arg.length * 4); 14 | getUint32Memory0().set(arg, ptr / 4); 15 | WASM_VECTOR_LEN = arg.length; 16 | return ptr; 17 | } 18 | /** 19 | * @param {number} nWordsReady 20 | * @param {number} blockSize 21 | * @param {Uint32Array} dataWords 22 | * @param {Uint32Array} hash 23 | */ 24 | function doCrypt(nWordsReady, blockSize, dataWords, hash) { 25 | try { 26 | var ptr0 = passArray32ToWasm0(dataWords, wasm.__wbindgen_malloc); 27 | var len0 = WASM_VECTOR_LEN; 28 | var ptr1 = passArray32ToWasm0(hash, wasm.__wbindgen_malloc); 29 | var len1 = WASM_VECTOR_LEN; 30 | wasm.doCrypt(nWordsReady, blockSize, ptr0, len0, ptr1, len1); 31 | } finally { 32 | hash.set(getUint32Memory0().subarray(ptr1 / 4, ptr1 / 4 + len1)); 33 | wasm.__wbindgen_free(ptr1, len1 * 4); 34 | } 35 | } 36 | 37 | return { 38 | doCrypt: doCrypt 39 | }; 40 | } 41 | -------------------------------------------------------------------------------- /src/algo/hmac/hmac.js: -------------------------------------------------------------------------------- 1 | import { Base } from '../../core/core.js'; 2 | import { Utf8 } from '../../encoding/enc-utf8'; 3 | import { isString } from '../../utils'; 4 | 5 | 6 | /** 7 | * HMAC algorithm. 8 | */ 9 | export class HMAC extends Base { 10 | /** 11 | * Initializes a newly created HMAC. 12 | * 13 | * @param {Hasher} SubHasher The hash algorithm to use. 14 | * @param {WordArray|string} key The secret key. 15 | * 16 | * @example 17 | * 18 | * const hmacHasher = new HMAC(CryptoJSW.algo.SHA256, key); 19 | */ 20 | constructor(SubHasher, key) { 21 | super(); 22 | 23 | const hasher = new SubHasher(); 24 | this._hasher = hasher; 25 | 26 | // Convert string to WordArray, else assume WordArray already 27 | let _key = key; 28 | if (isString(_key)) { 29 | _key = Utf8.parse(_key); 30 | } 31 | 32 | // Shortcuts 33 | const hasherBlockSize = hasher.blockSize; 34 | const hasherBlockSizeBytes = hasherBlockSize * 4; 35 | 36 | // Allow arbitrary length keys 37 | if (_key.sigBytes > hasherBlockSizeBytes) { 38 | _key = hasher.finalize(key); 39 | } 40 | 41 | // Clamp excess bits 42 | _key.clamp(); 43 | 44 | // Clone key for inner and outer pads 45 | const oKey = _key.clone(); 46 | this._oKey = oKey; 47 | const iKey = _key.clone(); 48 | this._iKey = iKey; 49 | 50 | // Shortcuts 51 | const oKeyWords = oKey.words; 52 | const iKeyWords = iKey.words; 53 | 54 | // XOR keys with pad constants 55 | for (let i = 0; i < hasherBlockSize; i++) { 56 | oKeyWords[i] ^= 0x5c5c5c5c; 57 | iKeyWords[i] ^= 0x36363636; 58 | } 59 | oKey.sigBytes = hasherBlockSizeBytes; 60 | iKey.sigBytes = hasherBlockSizeBytes; 61 | 62 | // Set initial values 63 | this.reset(); 64 | } 65 | 66 | /** 67 | * Resets this HMAC to its initial state. 68 | * 69 | * @example 70 | * 71 | * hmacHasher.reset(); 72 | */ 73 | reset() { 74 | // Shortcut 75 | const hasher = this._hasher; 76 | 77 | // Reset 78 | hasher.reset(); 79 | hasher.update(this._iKey); 80 | } 81 | 82 | /** 83 | * Updates this HMAC with a message. 84 | * 85 | * @param {WordArray|string} messageUpdate The message to append. 86 | * 87 | * @return {HMAC} This HMAC instance. 88 | * 89 | * @example 90 | * 91 | * hmacHasher.update('message'); 92 | * hmacHasher.update(wordArray); 93 | */ 94 | update(messageUpdate) { 95 | this._hasher.update(messageUpdate); 96 | 97 | // Chainable 98 | return this; 99 | } 100 | 101 | /** 102 | * Finalizes the HMAC computation. 103 | * Note that the finalize operation is effectively a destructive, read-once operation. 104 | * 105 | * @param {WordArray|string} messageUpdate (Optional) A final message update. 106 | * 107 | * @return {WordArray} The HMAC. 108 | * 109 | * @example 110 | * 111 | * let hmac = hmacHasher.finalize(); 112 | * let hmac = hmacHasher.finalize('message'); 113 | * let hmac = hmacHasher.finalize(wordArray); 114 | */ 115 | finalize(messageUpdate) { 116 | // Shortcut 117 | const hasher = this._hasher; 118 | 119 | // Compute HMAC 120 | const innerHash = hasher.finalize(messageUpdate); 121 | hasher.reset(); 122 | const hmac = hasher.finalize(this._oKey.clone().concat(innerHash)); 123 | 124 | return hmac; 125 | } 126 | } 127 | 128 | -------------------------------------------------------------------------------- /src/core/x64-core.js: -------------------------------------------------------------------------------- 1 | import { 2 | Base, 3 | WordArray 4 | } from '../core/core.js'; 5 | 6 | const X32WordArray = WordArray; 7 | 8 | /** 9 | * A 64-bit word. 10 | */ 11 | export class X64Word extends Base { 12 | /** 13 | * Initializes a newly created 64-bit word. 14 | * 15 | * @param {number} high The high 32 bits. 16 | * @param {number} low The low 32 bits. 17 | * 18 | * @example 19 | * 20 | * let x64Word = new X64Word(0x00010203, 0x04050607); 21 | */ 22 | constructor(high, low) { 23 | super(); 24 | 25 | this.high = high; 26 | this.low = low; 27 | } 28 | } 29 | 30 | /** 31 | * An array of 64-bit words. 32 | * 33 | * @property {Array} words The array of CryptoJSW.x64.Word objects. 34 | * @property {number} sigBytes The number of significant bytes in this word array. 35 | */ 36 | export class X64WordArray extends Base { 37 | /** 38 | * Initializes a newly created word array. 39 | * 40 | * @param {Array} words (Optional) An array of CryptoJSW.x64.Word objects. 41 | * @param {number} sigBytes (Optional) The number of significant bytes in the words. 42 | * 43 | * @example 44 | * 45 | * let wordArray = new X64WordArray(); 46 | * 47 | * let wordArray = new X64WordArray([ 48 | * new x64Word(0x00010203, 0x04050607), 49 | * new x64Word(0x18191a1b, 0x1c1d1e1f) 50 | * ]); 51 | * 52 | * let wordArray = new X64WordArray([ 53 | * new x64Word(0x00010203, 0x04050607), 54 | * new x64Word(0x18191a1b, 0x1c1d1e1f) 55 | * ], 10); 56 | */ 57 | constructor(words = [], sigBytes = words.length * 8) { 58 | super(); 59 | 60 | this.words = words; 61 | this.sigBytes = sigBytes; 62 | } 63 | 64 | /** 65 | * Converts this 64-bit word array to a 32-bit word array. 66 | * 67 | * @return {CryptoJSW.lib.WordArray} This word array's data as a 32-bit word array. 68 | * 69 | * @example 70 | * 71 | * let x32WordArray = x64WordArray.toX32(); 72 | */ 73 | toX32() { 74 | // Shortcuts 75 | const x64Words = this.words; 76 | const x64WordsLength = x64Words.length; 77 | 78 | // Convert 79 | const x32Words = []; 80 | for (let i = 0; i < x64WordsLength; i++) { 81 | const x64Word = x64Words[i]; 82 | x32Words.push(x64Word.high); 83 | x32Words.push(x64Word.low); 84 | } 85 | 86 | return new X32WordArray(x32Words, this.sigBytes); 87 | } 88 | 89 | /** 90 | * Creates a copy of this word array. 91 | * 92 | * @return {X64WordArray} The clone. 93 | * 94 | * @example 95 | * 96 | * let clone = x64WordArray.clone(); 97 | */ 98 | clone() { 99 | const clone = super.clone.call(this); 100 | 101 | // Clone "words" array 102 | clone.words = this.words.slice(0); 103 | const { words } = clone; 104 | 105 | // Clone each X64Word object 106 | const wordsLength = words.length; 107 | for (let i = 0; i < wordsLength; i++) { 108 | words[i] = words[i].clone(); 109 | } 110 | 111 | return clone; 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /src/encoding/enc-hax.js: -------------------------------------------------------------------------------- 1 | import { 2 | WordArray 3 | } from '../core/core.js'; 4 | 5 | /** 6 | * Hex encoding strategy. 7 | */ 8 | export const Hex = { 9 | /** 10 | * Converts a word array to a hex string. 11 | * 12 | * @param {WordArray} wordArray The word array. 13 | * 14 | * @return {string} The hex string. 15 | * 16 | * @static 17 | * 18 | * @example 19 | * 20 | * const hexString = CryptoJSW.enc.Hex.stringify(wordArray); 21 | */ 22 | stringify(wordArray) { 23 | // Shortcuts 24 | const { 25 | words, 26 | sigBytes 27 | } = wordArray; 28 | 29 | // Convert 30 | const hexChars = []; 31 | for (let i = 0; i < sigBytes; i++) { 32 | const bite = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff; 33 | hexChars.push((bite >>> 4).toString(16)); 34 | hexChars.push((bite & 0x0f).toString(16)); 35 | } 36 | 37 | return hexChars.join(''); 38 | }, 39 | 40 | /** 41 | * Converts a hex string to a word array. 42 | * 43 | * @param {string} hexStr The hex string. 44 | * 45 | * @return {WordArray} The word array. 46 | * 47 | * @static 48 | * 49 | * @example 50 | * 51 | * const wordArray = CryptoJSW.enc.Hex.parse(hexString); 52 | */ 53 | parse(hexStr) { 54 | // Shortcut 55 | const hexStrLength = hexStr.length; 56 | 57 | // Convert 58 | const words = []; 59 | for (let i = 0; i < hexStrLength; i += 2) { 60 | words[i >>> 3] |= parseInt(hexStr.substr(i, 2), 16) << (24 - (i % 8) * 4); 61 | } 62 | 63 | return new WordArray(words, hexStrLength / 2); 64 | } 65 | }; 66 | -------------------------------------------------------------------------------- /src/encoding/enc-latin1.js: -------------------------------------------------------------------------------- 1 | import { 2 | WordArray 3 | } from '../core/core.js'; 4 | 5 | /** 6 | * Latin1 encoding strategy. 7 | */ 8 | export const Latin1 = { 9 | /** 10 | * Converts a word array to a Latin1 string. 11 | * 12 | * @param {WordArray} wordArray The word array. 13 | * 14 | * @return {string} The Latin1 string. 15 | * 16 | * @static 17 | * 18 | * @example 19 | * 20 | * const latin1String = CryptoJSW.enc.Latin1.stringify(wordArray); 21 | */ 22 | stringify(wordArray) { 23 | // Shortcuts 24 | const { 25 | words, 26 | sigBytes 27 | } = wordArray; 28 | 29 | // Convert 30 | let latin1Chars = ''; 31 | for (let i = 0; i < sigBytes; i++) { 32 | const byte = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff; 33 | latin1Chars += String.fromCharCode(byte); 34 | } 35 | 36 | return latin1Chars; 37 | }, 38 | 39 | /** 40 | * Converts a Latin1 string to a word array. 41 | * 42 | * @param {string} latin1Str The Latin1 string. 43 | * 44 | * @return {WordArray} The word array. 45 | * 46 | * @static 47 | * 48 | * @example 49 | * 50 | * const wordArray = CryptoJSW.enc.Latin1.parse(latin1String); 51 | */ 52 | parse(latin1Str) { 53 | // Shortcut 54 | const latin1StrLength = latin1Str.length; 55 | 56 | // Convert 57 | const words = []; 58 | let word = 0; 59 | // const words = new Array(latin1StrLength >>> 2); 60 | for (let i = 0; i < latin1StrLength - latin1StrLength % 4; i++) { 61 | word |= (latin1Str.charCodeAt(i) & 0xff) << (24 - (i % 4) * 8); 62 | if (i % 4 == 3) { 63 | words[i >>> 2] = word; 64 | word = 0; 65 | } 66 | } 67 | for (let i = latin1StrLength - latin1StrLength % 4; i < latin1StrLength;i++) { 68 | words[i >>> 2] |= (latin1Str.charCodeAt(i) & 0xff) << (24 - (i % 4) * 8); 69 | } 70 | 71 | return new WordArray(words, latin1StrLength); 72 | } 73 | }; 74 | -------------------------------------------------------------------------------- /src/encoding/enc-utf16.js: -------------------------------------------------------------------------------- 1 | import { 2 | WordArray 3 | } from '../core/core'; 4 | 5 | const swapEndian = word => ((word << 8) & 0xff00ff00) | ((word >>> 8) & 0x00ff00ff); 6 | 7 | /** 8 | * UTF-16 BE encoding strategy. 9 | */ 10 | export const Utf16BE = { 11 | /** 12 | * Converts a word array to a UTF-16 BE string. 13 | * 14 | * @param {WordArray} wordArray The word array. 15 | * 16 | * @return {string} The UTF-16 BE string. 17 | * 18 | * @static 19 | * 20 | * @example 21 | * 22 | * const utf16String = CryptoJSW.enc.Utf16.stringify(wordArray); 23 | */ 24 | stringify(wordArray) { 25 | // Shortcuts 26 | const { words, sigBytes } = wordArray; 27 | 28 | // Convert 29 | const utf16Chars = []; 30 | for (let i = 0; i < sigBytes; i += 2) { 31 | const codePoint = (words[i >>> 2] >>> (16 - (i % 4) * 8)) & 0xffff; 32 | utf16Chars.push(String.fromCharCode(codePoint)); 33 | } 34 | 35 | return utf16Chars.join(''); 36 | }, 37 | 38 | /** 39 | * Converts a UTF-16 BE string to a word array. 40 | * 41 | * @param {string} utf16Str The UTF-16 BE string. 42 | * 43 | * @return {WordArray} The word array. 44 | * 45 | * @static 46 | * 47 | * @example 48 | * 49 | * const wordArray = CryptoJSW.enc.Utf16.parse(utf16String); 50 | */ 51 | parse(utf16Str) { 52 | // Shortcut 53 | const utf16StrLength = utf16Str.length; 54 | 55 | // Convert 56 | const words = []; 57 | for (let i = 0; i < utf16StrLength; i++) { 58 | words[i >>> 1] |= utf16Str.charCodeAt(i) << (16 - (i % 2) * 16); 59 | } 60 | 61 | return new WordArray(words, utf16StrLength * 2); 62 | } 63 | }; 64 | export const Utf16 = Utf16BE; 65 | 66 | /** 67 | * UTF-16 LE encoding strategy. 68 | */ 69 | export const Utf16LE = { 70 | /** 71 | * Converts a word array to a UTF-16 LE string. 72 | * 73 | * @param {WordArray} wordArray The word array. 74 | * 75 | * @return {string} The UTF-16 LE string. 76 | * 77 | * @static 78 | * 79 | * @example 80 | * 81 | * const utf16Str = CryptoJSW.enc.Utf16LE.stringify(wordArray); 82 | */ 83 | stringify(wordArray) { 84 | // Shortcuts 85 | const { words, sigBytes } = wordArray; 86 | 87 | // Convert 88 | const utf16Chars = []; 89 | for (let i = 0; i < sigBytes; i += 2) { 90 | const codePoint = swapEndian((words[i >>> 2] >>> (16 - (i % 4) * 8)) & 0xffff); 91 | utf16Chars.push(String.fromCharCode(codePoint)); 92 | } 93 | 94 | return utf16Chars.join(''); 95 | }, 96 | 97 | /** 98 | * Converts a UTF-16 LE string to a word array. 99 | * 100 | * @param {string} utf16Str The UTF-16 LE string. 101 | * 102 | * @return {WordArray} The word array. 103 | * 104 | * @static 105 | * 106 | * @example 107 | * 108 | * const wordArray = CryptoJSW.enc.Utf16LE.parse(utf16Str); 109 | */ 110 | parse(utf16Str) { 111 | // Shortcut 112 | const utf16StrLength = utf16Str.length; 113 | 114 | // Convert 115 | const words = []; 116 | for (let i = 0; i < utf16StrLength; i++) { 117 | words[i >>> 1] |= swapEndian(utf16Str.charCodeAt(i) << (16 - (i % 2) * 16)); 118 | } 119 | 120 | return new WordArray(words, utf16StrLength * 2); 121 | } 122 | }; 123 | -------------------------------------------------------------------------------- /src/encoding/enc-utf8.js: -------------------------------------------------------------------------------- 1 | import { Latin1 } from './enc-latin1.js'; 2 | 3 | /** 4 | * UTF-8 encoding strategy. 5 | */ 6 | export const Utf8 = { 7 | /** 8 | * Converts a word array to a UTF-8 string. 9 | * 10 | * @param {WordArray} wordArray The word array. 11 | * 12 | * @return {string} The UTF-8 string. 13 | * 14 | * @static 15 | * 16 | * @example 17 | * 18 | * const utf8String = CryptoJSW.enc.Utf8.stringify(wordArray); 19 | */ 20 | stringify(wordArray) { 21 | try { 22 | return decodeURIComponent(escape(Latin1.stringify(wordArray))); 23 | } catch (e) { 24 | throw new Error('Malformed UTF-8 data'); 25 | } 26 | }, 27 | 28 | /** 29 | * Converts a UTF-8 string to a word array. 30 | * 31 | * @param {string} utf8Str The UTF-8 string. 32 | * 33 | * @return {WordArray} The word array. 34 | * 35 | * @static 36 | * 37 | * @example 38 | * 39 | * const wordArray = CryptoJSW.enc.Utf8.parse(utf8String); 40 | */ 41 | parse(utf8Str) { 42 | return Latin1.parse(unescape(encodeURIComponent(utf8Str))); 43 | } 44 | }; 45 | -------------------------------------------------------------------------------- /src/encryption/evpkdf.js: -------------------------------------------------------------------------------- 1 | import { 2 | Base, 3 | WordArray 4 | } from '../core/core.js'; 5 | import { MD5Algo } from '../algo/hash/md5.js'; 6 | 7 | /** 8 | * This key derivation function is meant to conform with EVP_BytesToKey. 9 | * www.openssl.org/docs/crypto/EVP_BytesToKey.html 10 | */ 11 | export class EvpKDFAlgo extends Base { 12 | static async loadWasm() { 13 | return MD5Algo.loadWasm(); 14 | } 15 | 16 | async loadWasm() { 17 | return EvpKDFAlgo.loadWasm(); 18 | } 19 | 20 | /** 21 | * Initializes a newly created key derivation function. 22 | * 23 | * @param {Object} cfg (Optional) The configuration options to use for the derivation. 24 | * 25 | * @example 26 | * 27 | * const kdf = new EvpKDF(); 28 | * const kdf = new EvpKDF({ keySize: 8 }); 29 | * const kdf = new EvpKDF({ keySize: 8, iterations: 1000 }); 30 | */ 31 | constructor(cfg) { 32 | super(); 33 | 34 | /** 35 | * Configuration options. 36 | * 37 | * @property {number} keySize The key size in words to generate. Default: 4 (128 bits) 38 | * @property {Hasher} hasher The hash algorithm to use. Default: MD5 39 | * @property {number} iterations The number of iterations to perform. Default: 1 40 | */ 41 | this.cfg = Object.assign( 42 | new Base(), 43 | { 44 | keySize: 128 / 32, 45 | hasher: MD5Algo, 46 | iterations: 1 47 | }, 48 | cfg 49 | ); 50 | } 51 | 52 | /** 53 | * Derives a key from a password. 54 | * 55 | * @param {WordArray|string} password The password. 56 | * @param {WordArray|string} salt A salt. 57 | * 58 | * @return {WordArray} The derived key. 59 | * 60 | * @example 61 | * 62 | * const key = kdf.compute(password, salt); 63 | */ 64 | compute(password, salt) { 65 | let block; 66 | 67 | // Shortcut 68 | const { cfg } = this; 69 | 70 | // Init hasher 71 | const hasher = new cfg.hasher(); 72 | 73 | // Initial values 74 | const derivedKey = new WordArray(); 75 | 76 | // Shortcuts 77 | const derivedKeyWords = derivedKey.words; 78 | const { keySize, iterations } = cfg; 79 | 80 | // Generate key 81 | while (derivedKeyWords.length < keySize) { 82 | if (block) { 83 | hasher.update(block); 84 | } 85 | block = hasher.update(password).finalize(salt); 86 | hasher.reset(); 87 | 88 | // Iterations 89 | for (let i = 1; i < iterations; i++) { 90 | block = hasher.finalize(block); 91 | hasher.reset(); 92 | } 93 | 94 | derivedKey.concat(block); 95 | } 96 | derivedKey.sigBytes = keySize * 4; 97 | 98 | return derivedKey; 99 | } 100 | } 101 | 102 | /** 103 | * Derives a key from a password. 104 | * 105 | * @param {WordArray|string} password The password. 106 | * @param {WordArray|string} salt A salt. 107 | * @param {Object} cfg (Optional) The configuration options to use for this computation. 108 | * 109 | * @return {WordArray} The derived key. 110 | * 111 | * @static 112 | * 113 | * @example 114 | * 115 | * const key = CryptoJSW.EvpKDF(password, salt); 116 | * const key = CryptoJSW.EvpKDF(password, salt, { keySize: 8 }); 117 | * const key = CryptoJSW.EvpKDF(password, salt, { keySize: 8, iterations: 1000 }); 118 | */ 119 | export const EvpKDF = (password, salt, cfg) => new EvpKDFAlgo(cfg).compute(password, salt); 120 | 121 | EvpKDF.loadWasm = async function() { 122 | return EvpKDFAlgo.loadWasm(); 123 | }; 124 | 125 | -------------------------------------------------------------------------------- /src/encryption/rabbit_bg.js: -------------------------------------------------------------------------------- 1 | export function rabbitWasm(wasm) { 2 | let cachegetUint32Memory0 = null; 3 | function getUint32Memory0() { 4 | if (cachegetUint32Memory0 === null || cachegetUint32Memory0.buffer !== wasm.memory.buffer) { 5 | cachegetUint32Memory0 = new Uint32Array(wasm.memory.buffer); 6 | } 7 | return cachegetUint32Memory0; 8 | } 9 | 10 | let WASM_VECTOR_LEN = 0; 11 | 12 | function passArray32ToWasm0(arg, malloc) { 13 | const ptr = malloc(arg.length * 4); 14 | getUint32Memory0().set(arg, ptr / 4); 15 | WASM_VECTOR_LEN = arg.length; 16 | return ptr; 17 | } 18 | /** 19 | * @param {number} nWordsReady 20 | * @param {number} blockSize 21 | * @param {Uint32Array} dataWords 22 | * @param {Uint32Array} X 23 | * @param {Uint32Array} C 24 | * @param {number} b 25 | * @returns {number} 26 | */ 27 | function doProcess(nWordsReady, blockSize, dataWords, X, C, b) { 28 | try { 29 | var ptr0 = passArray32ToWasm0(dataWords, wasm.__wbindgen_malloc); 30 | var len0 = WASM_VECTOR_LEN; 31 | var ptr1 = passArray32ToWasm0(X, wasm.__wbindgen_malloc); 32 | var len1 = WASM_VECTOR_LEN; 33 | var ptr2 = passArray32ToWasm0(C, wasm.__wbindgen_malloc); 34 | var len2 = WASM_VECTOR_LEN; 35 | var ret = wasm.doProcess(nWordsReady, blockSize, ptr0, len0, ptr1, len1, ptr2, len2, b); 36 | return ret >>> 0; 37 | } finally { 38 | dataWords.set(getUint32Memory0().subarray(ptr0 / 4, ptr0 / 4 + len0)); 39 | wasm.__wbindgen_free(ptr0, len0 * 4); 40 | X.set(getUint32Memory0().subarray(ptr1 / 4, ptr1 / 4 + len1)); 41 | wasm.__wbindgen_free(ptr1, len1 * 4); 42 | C.set(getUint32Memory0().subarray(ptr2 / 4, ptr2 / 4 + len2)); 43 | wasm.__wbindgen_free(ptr2, len2 * 4); 44 | } 45 | } 46 | 47 | return { 48 | doProcess: doProcess 49 | }; 50 | } 51 | 52 | 53 | -------------------------------------------------------------------------------- /src/encryption/rc4_bg.js: -------------------------------------------------------------------------------- 1 | export function rc4Wasm(wasm) { 2 | let cachegetUint32Memory0 = null; 3 | function getUint32Memory0() { 4 | if (cachegetUint32Memory0 === null || cachegetUint32Memory0.buffer !== wasm.memory.buffer) { 5 | cachegetUint32Memory0 = new Uint32Array(wasm.memory.buffer); 6 | } 7 | return cachegetUint32Memory0; 8 | } 9 | 10 | let WASM_VECTOR_LEN = 0; 11 | 12 | function passArray32ToWasm0(arg, malloc) { 13 | const ptr = malloc(arg.length * 4); 14 | getUint32Memory0().set(arg, ptr / 4); 15 | WASM_VECTOR_LEN = arg.length; 16 | return ptr; 17 | } 18 | /** 19 | * @param {number} nWordsReady 20 | * @param {number} blockSize 21 | * @param {Uint32Array} dataWords 22 | * @param {Uint32Array} S 23 | */ 24 | function doProcess(nWordsReady, blockSize, dataWords, S) { 25 | try { 26 | var ptr0 = passArray32ToWasm0(dataWords, wasm.__wbindgen_malloc); 27 | var len0 = WASM_VECTOR_LEN; 28 | var ptr1 = passArray32ToWasm0(S, wasm.__wbindgen_malloc); 29 | var len1 = WASM_VECTOR_LEN; 30 | wasm.doProcess(nWordsReady, blockSize, ptr0, len0, ptr1, len1); 31 | } finally { 32 | dataWords.set(getUint32Memory0().subarray(ptr0 / 4, ptr0 / 4 + len0)); 33 | wasm.__wbindgen_free(ptr0, len0 * 4); 34 | S.set(getUint32Memory0().subarray(ptr1 / 4, ptr1 / 4 + len1)); 35 | wasm.__wbindgen_free(ptr1, len1 * 4); 36 | } 37 | } 38 | 39 | return { 40 | doProcess: doProcess 41 | }; 42 | } 43 | -------------------------------------------------------------------------------- /src/format/format-hex.js: -------------------------------------------------------------------------------- 1 | import { 2 | CipherParams 3 | } from '../core/cipher-core.js'; 4 | import { 5 | Hex 6 | } from '../encoding/enc-hax.js'; 7 | 8 | export const HexFormatter = { 9 | /** 10 | * Converts the ciphertext of a cipher params object to a hexadecimally encoded string. 11 | * 12 | * @param {CipherParams} cipherParams The cipher params object. 13 | * 14 | * @return {string} The hexadecimally encoded string. 15 | * 16 | * @static 17 | * 18 | * @example 19 | * 20 | * const hexString = CryptoJSW.format.Hex.stringify(cipherParams); 21 | */ 22 | stringify(cipherParams) { 23 | return cipherParams.ciphertext.toString(Hex); 24 | }, 25 | 26 | /** 27 | * Converts a hexadecimally encoded ciphertext string to a cipher params object. 28 | * 29 | * @param {string} input The hexadecimally encoded string. 30 | * 31 | * @return {CipherParams} The cipher params object. 32 | * 33 | * @static 34 | * 35 | * @example 36 | * 37 | * const cipherParams = CryptoJSW.format.Hex.parse(hexString); 38 | */ 39 | parse(input) { 40 | const ciphertext = Hex.parse(input); 41 | return new CipherParams({ ciphertext }); 42 | } 43 | }; 44 | -------------------------------------------------------------------------------- /src/mode/mode-cfb.js: -------------------------------------------------------------------------------- 1 | import { 2 | BlockCipherMode 3 | } from '../core/cipher-core.js'; 4 | 5 | function generateKeystreamAndEncrypt(words, offset, blockSize, cipher) { 6 | const _words = words; 7 | let keystream; 8 | 9 | // Shortcut 10 | const iv = this._iv; 11 | 12 | // Generate keystream 13 | if (iv) { 14 | keystream = iv.slice(0); 15 | 16 | // Remove IV for subsequent blocks 17 | this._iv = undefined; 18 | } else { 19 | keystream = this._prevBlock; 20 | } 21 | cipher.encryptBlock(keystream, 0); 22 | 23 | // Encrypt 24 | for (let i = 0; i < blockSize; i++) { 25 | _words[offset + i] ^= keystream[i]; 26 | } 27 | } 28 | 29 | /** 30 | * Cipher Feedback block mode. 31 | */ 32 | export class CFB extends BlockCipherMode { 33 | static _name = 'CFB'; 34 | static Encryptor(){} 35 | 36 | } 37 | CFB.Encryptor = class extends CFB { 38 | processBlock(words, offset) { 39 | // Shortcuts 40 | const cipher = this._cipher; 41 | const { blockSize } = cipher; 42 | 43 | generateKeystreamAndEncrypt.call(this, words, offset, blockSize, cipher); 44 | 45 | // Remember this block to use with next block 46 | this._prevBlock = words.slice(offset, offset + blockSize); 47 | } 48 | }; 49 | CFB.Decryptor = class extends CFB { 50 | processBlock(words, offset) { 51 | // Shortcuts 52 | const cipher = this._cipher; 53 | const { blockSize } = cipher; 54 | 55 | // Remember this block to use with next block 56 | const thisBlock = words.slice(offset, offset + blockSize); 57 | 58 | generateKeystreamAndEncrypt.call(this, words, offset, blockSize, cipher); 59 | 60 | // This block becomes the previous block 61 | this._prevBlock = thisBlock; 62 | } 63 | }; 64 | -------------------------------------------------------------------------------- /src/mode/mode-ctr-gladman.js: -------------------------------------------------------------------------------- 1 | import { 2 | BlockCipherMode 3 | } from '../core/cipher-core.js'; 4 | 5 | const incWord = (word) => { 6 | let _word = word; 7 | 8 | if (((word >> 24) & 0xff) === 0xff) { // overflow 9 | let b1 = (word >> 16) & 0xff; 10 | let b2 = (word >> 8) & 0xff; 11 | let b3 = word & 0xff; 12 | 13 | if (b1 === 0xff) { // overflow b1 14 | b1 = 0; 15 | if (b2 === 0xff) { 16 | b2 = 0; 17 | if (b3 === 0xff) { 18 | b3 = 0; 19 | } else { 20 | b3++; 21 | } 22 | } else { 23 | b2++; 24 | } 25 | } else { 26 | b1++; 27 | } 28 | 29 | _word = 0; 30 | _word += (b1 << 16); 31 | _word += (b2 << 8); 32 | _word += b3; 33 | } else { 34 | _word += (0x01 << 24); 35 | } 36 | return _word; 37 | }; 38 | 39 | const incCounter = (counter) => { 40 | const _counter = counter; 41 | _counter[0] = incWord(_counter[0]); 42 | 43 | if (_counter[0] === 0) { 44 | // encr_data in fileenc.c from Dr Brian Gladman's counts only with DWORD j < 8 45 | _counter[1] = incWord(_counter[1]); 46 | } 47 | return _counter; 48 | }; 49 | 50 | /** @preserve 51 | * Counter block mode compatible with Dr Brian Gladman fileenc.c 52 | * derived from CryptoJS.mode.CTR 53 | * Jan Hruby jhruby.web@gmail.com 54 | */ 55 | export class CTRGladman extends BlockCipherMode { 56 | static _name = 'CTRGladman'; 57 | } 58 | CTRGladman.Encryptor = class extends CTRGladman { 59 | processBlock(words, offset) { 60 | const _words = words; 61 | 62 | // Shortcuts 63 | const cipher = this._cipher; 64 | const { blockSize } = cipher; 65 | const iv = this._iv; 66 | let counter = this._counter; 67 | 68 | // Generate keystream 69 | if (iv) { 70 | this._counter = iv.slice(0); 71 | counter = this._counter; 72 | 73 | // Remove IV for subsequent blocks 74 | this._iv = undefined; 75 | } 76 | 77 | incCounter(counter); 78 | 79 | const keystream = counter.slice(0); 80 | cipher.encryptBlock(keystream, 0); 81 | 82 | // Encrypt 83 | for (let i = 0; i < blockSize; i++) { 84 | _words[offset + i] ^= keystream[i]; 85 | } 86 | } 87 | }; 88 | CTRGladman.Decryptor = CTRGladman.Encryptor; 89 | -------------------------------------------------------------------------------- /src/mode/mode-ctr.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Counter block mode. 3 | */ 4 | import { 5 | BlockCipherMode 6 | } from '../core/cipher-core.js'; 7 | 8 | export class CTR extends BlockCipherMode { 9 | static _name = 'CTR'; 10 | } 11 | CTR.Encryptor = class extends CTR { 12 | processBlock(words, offset) { 13 | const _words = words; 14 | 15 | // Shortcuts 16 | const cipher = this._cipher; 17 | const { blockSize } = cipher; 18 | const iv = this._iv; 19 | let counter = this._counter; 20 | 21 | // Generate keystream 22 | if (iv) { 23 | this._counter = iv.slice(0); 24 | counter = this._counter; 25 | 26 | // Remove IV for subsequent blocks 27 | this._iv = undefined; 28 | } 29 | const keystream = counter.slice(0); 30 | cipher.encryptBlock(keystream, 0); 31 | 32 | // Increment counter 33 | counter[blockSize - 1] = (counter[blockSize - 1] + 1) | 0; 34 | 35 | // Encrypt 36 | for (let i = 0; i < blockSize; i++) { 37 | _words[offset + i] ^= keystream[i]; 38 | } 39 | } 40 | }; 41 | CTR.Decryptor = CTR.Encryptor; 42 | -------------------------------------------------------------------------------- /src/mode/mode-ecb.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Electronic Codebook block mode. 3 | */ 4 | import { 5 | BlockCipherMode 6 | } from '../core/cipher-core.js'; 7 | 8 | export class ECB extends BlockCipherMode { 9 | static _name = 'ECB'; 10 | } 11 | ECB.Encryptor = class extends ECB { 12 | processBlock(words, offset) { 13 | this._cipher.encryptBlock(words, offset); 14 | } 15 | }; 16 | ECB.Decryptor = class extends ECB { 17 | processBlock(words, offset) { 18 | this._cipher.decryptBlock(words, offset); 19 | } 20 | }; 21 | -------------------------------------------------------------------------------- /src/mode/mode-ofb.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Output Feedback block mode. 3 | */ 4 | import { 5 | BlockCipherMode 6 | } from '../core/cipher-core.js'; 7 | 8 | export class OFB extends BlockCipherMode { 9 | static _name = 'OFB'; 10 | } 11 | OFB.Encryptor = class extends OFB { 12 | processBlock(words, offset) { 13 | const _words = words; 14 | 15 | // Shortcuts 16 | const cipher = this._cipher; 17 | const { blockSize } = cipher; 18 | const iv = this._iv; 19 | let keystream = this._keystream; 20 | 21 | // Generate keystream 22 | if (iv) { 23 | this._keystream = iv.slice(0); 24 | keystream = this._keystream; 25 | 26 | // Remove IV for subsequent blocks 27 | this._iv = undefined; 28 | } 29 | cipher.encryptBlock(keystream, 0); 30 | 31 | // Encrypt 32 | for (let i = 0; i < blockSize; i++) { 33 | _words[offset + i] ^= keystream[i]; 34 | } 35 | } 36 | }; 37 | OFB.Decryptor = OFB.Encryptor; 38 | -------------------------------------------------------------------------------- /src/pad/pad-ansix923.js: -------------------------------------------------------------------------------- 1 | /** 2 | * ANSI X.923 padding strategy. 3 | */ 4 | export const AnsiX923 = { 5 | pad(data, blockSize) { 6 | const _data = data; 7 | 8 | // Shortcuts 9 | const dataSigBytes = _data.sigBytes; 10 | const blockSizeBytes = blockSize * 4; 11 | 12 | // Count padding bytes 13 | const nPaddingBytes = blockSizeBytes - (dataSigBytes % blockSizeBytes); 14 | 15 | // Compute last byte position 16 | const lastBytePos = dataSigBytes + nPaddingBytes - 1; 17 | 18 | // Pad 19 | _data.clamp(); 20 | _data.words[lastBytePos >>> 2] |= nPaddingBytes << (24 - (lastBytePos % 4) * 8); 21 | _data.sigBytes += nPaddingBytes; 22 | }, 23 | 24 | unpad(data) { 25 | const _data = data; 26 | 27 | // Get number of padding bytes from last byte 28 | const nPaddingBytes = _data.words[(_data.sigBytes - 1) >>> 2] & 0xff; 29 | 30 | // Remove padding 31 | _data.sigBytes -= nPaddingBytes; 32 | } 33 | }; 34 | -------------------------------------------------------------------------------- /src/pad/pad-iso10126.js: -------------------------------------------------------------------------------- 1 | import { 2 | WordArray 3 | } from '../core/core.js'; 4 | 5 | /** 6 | * ISO 10126 padding strategy. 7 | */ 8 | export const Iso10126 = { 9 | pad(data, blockSize) { 10 | // Shortcut 11 | const blockSizeBytes = blockSize * 4; 12 | 13 | // Count padding bytes 14 | const nPaddingBytes = blockSizeBytes - (data.sigBytes % blockSizeBytes); 15 | 16 | // Pad 17 | data 18 | .concat(WordArray.random(nPaddingBytes - 1)) 19 | .concat(new WordArray([nPaddingBytes << 24], 1)); 20 | }, 21 | 22 | unpad(data) { 23 | const _data = data; 24 | // Get number of padding bytes from last byte 25 | const nPaddingBytes = _data.words[(_data.sigBytes - 1) >>> 2] & 0xff; 26 | 27 | // Remove padding 28 | _data.sigBytes -= nPaddingBytes; 29 | } 30 | }; 31 | -------------------------------------------------------------------------------- /src/pad/pad-iso97971.js: -------------------------------------------------------------------------------- 1 | import { 2 | WordArray 3 | } from '../core/core.js'; 4 | import { 5 | ZeroPadding 6 | } from './pad-zeropadding.js'; 7 | 8 | /** 9 | * ISO/IEC 9797-1 Padding Method 2. 10 | */ 11 | export const Iso97971 = { 12 | pad(data, blockSize) { 13 | // Add 0x80 byte 14 | data.concat(new WordArray([0x80000000], 1)); 15 | 16 | // Zero pad the rest 17 | ZeroPadding.pad(data, blockSize); 18 | }, 19 | 20 | unpad(data) { 21 | const _data = data; 22 | 23 | // Remove zero padding 24 | ZeroPadding.unpad(_data); 25 | 26 | // Remove one more byte -- the 0x80 byte 27 | _data.sigBytes--; 28 | } 29 | }; 30 | -------------------------------------------------------------------------------- /src/pad/pad-nopadding.js: -------------------------------------------------------------------------------- 1 | /** 2 | * A noop padding strategy. 3 | */ 4 | export const NoPadding = { 5 | pad() { 6 | }, 7 | 8 | unpad() { 9 | } 10 | }; 11 | -------------------------------------------------------------------------------- /src/pad/pad-pkcs7.js: -------------------------------------------------------------------------------- 1 | import { WordArray } from '../core/core'; 2 | 3 | /** 4 | * PKCS #5/7 padding strategy. 5 | */ 6 | export const Pkcs7 = { 7 | /** 8 | * Pads data using the algorithm defined in PKCS #5/7. 9 | * 10 | * @param {WordArray} data The data to pad. 11 | * @param {number} blockSize The multiple that the data should be padded to. 12 | * 13 | * @static 14 | * 15 | * @example 16 | * 17 | * CryptoJSW.pad.Pkcs7.pad(wordArray, 4); 18 | */ 19 | pad(data, blockSize) { 20 | // Shortcut 21 | const blockSizeBytes = blockSize * 4; 22 | 23 | // Count padding bytes 24 | const nPaddingBytes = blockSizeBytes - (data.sigBytes % blockSizeBytes); 25 | 26 | // Create padding word 27 | const paddingWord = (nPaddingBytes << 24) | 28 | (nPaddingBytes << 16) | 29 | (nPaddingBytes << 8) | 30 | nPaddingBytes; 31 | 32 | // Create padding 33 | const paddingWords = []; 34 | for (let i = 0; i < nPaddingBytes; i += 4) { 35 | paddingWords.push(paddingWord); 36 | } 37 | const padding = new WordArray(paddingWords, nPaddingBytes); 38 | 39 | // Add padding 40 | data.concat(padding); 41 | }, 42 | 43 | /** 44 | * Unpads data that had been padded using the algorithm defined in PKCS #5/7. 45 | * 46 | * @param {WordArray} data The data to unpad. 47 | * 48 | * @static 49 | * 50 | * @example 51 | * 52 | * CryptoJSW.pad.Pkcs7.unpad(wordArray); 53 | */ 54 | unpad(data) { 55 | const _data = data; 56 | 57 | // Get number of padding bytes from last byte 58 | const nPaddingBytes = _data.words[(_data.sigBytes - 1) >>> 2] & 0xff; 59 | 60 | // Remove padding 61 | _data.sigBytes -= nPaddingBytes; 62 | } 63 | }; 64 | -------------------------------------------------------------------------------- /src/pad/pad-zeropadding.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Zero padding strategy. 3 | */ 4 | export const ZeroPadding = { 5 | pad(data, blockSize) { 6 | const _data = data; 7 | 8 | // Shortcut 9 | const blockSizeBytes = blockSize * 4; 10 | 11 | // Pad 12 | _data.clamp(); 13 | _data.sigBytes += blockSizeBytes - ((data.sigBytes % blockSizeBytes) || blockSizeBytes); 14 | }, 15 | 16 | unpad(data) { 17 | const _data = data; 18 | 19 | // Shortcut 20 | const dataWords = _data.words; 21 | 22 | // Unpad 23 | for (let i = _data.sigBytes - 1; i >= 0; i--) { 24 | if (((dataWords[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff)) { 25 | _data.sigBytes = i + 1; 26 | break; 27 | } 28 | } 29 | } 30 | }; 31 | -------------------------------------------------------------------------------- /src/utils.js: -------------------------------------------------------------------------------- 1 | const toStringPro = Object.prototype.toString; 2 | 3 | /** 4 | * Determine if a value is a String 5 | * 6 | * @param {Object} val The value to test 7 | * @returns {Boolean} True if value is a String, otherwise false 8 | */ 9 | export const isString = (val) => typeof val === 'string'; 10 | 11 | /** 12 | * Determine if a value is a Number 13 | * 14 | * @param {Object} val The value to test 15 | * @returns {Boolean} True if value is a Number, otherwise false 16 | */ 17 | export const isNumber = (val) => typeof val === 'number'; 18 | 19 | /** 20 | * Determine if a value is a undefined 21 | * 22 | * @param {Object} val The value to test 23 | * @returns {Boolean} True if value is a undefined, otherwise false 24 | */ 25 | export const isUndefined = (val) => typeof val === 'undefined'; 26 | 27 | /** 28 | * Determine if a value is a Function 29 | * 30 | * @param {Object} val The value to test 31 | * @returns {Boolean} True if value is a Function, otherwise false 32 | */ 33 | export const isFunction = (val) => toStringPro.call(val) === '[object Function]'; 34 | 35 | /** 36 | * Determine if a value is a Array 37 | * 38 | * @param {Object} val The value to test 39 | * @returns {Boolean} True if value is a Array, otherwise false 40 | */ 41 | export const isArray = (val) => toStringPro.call(val) === '[object, Array]'; 42 | 43 | /** 44 | * Determine if a value is a Object 45 | * 46 | * @param {Object} val The value to test 47 | * @returns {Boolean} True if value is a Object, otherwise false 48 | */ 49 | export const isObject = (val) => toStringPro.call(val) === '[object, object]'; 50 | 51 | /** 52 | * Accepts varargs expecting each argument to be an object, then 53 | * immutably merges the properties of each object and returns result. 54 | * 55 | * When multiple objects contain the same key the later object in 56 | * the arguments list will take precedence. 57 | * 58 | * @param {Object} args Object to merge 59 | * @returns {Object} Result of all merge properties 60 | */ 61 | export const merge = (...args) => args.length && Object.assign(...args); 62 | 63 | /** 64 | * Check if the input parameter is valid 65 | * 66 | * @param parameter {any} input parameter 67 | * @param parameterDesc {string} description input parameter 68 | * @param validTypes {string|array} valid types of parameter 69 | * @param validValues {array} valid values of parameter 70 | * @throws if parameter is invalid 71 | */ 72 | export const parameterCheck = (parameter, parameterDesc, validTypes, ...validValues) => { 73 | let isValid = true; 74 | if (validTypes !== undefined) { 75 | if (typeof validTypes === 'string' && typeof parameter !== validTypes) { 76 | isValid = false; 77 | } 78 | 79 | if (validTypes.indexOf(typeof parameter) < 0) { 80 | isValid = false; 81 | } 82 | } 83 | 84 | if (validValues !== undefined && validValues.length > 0) { 85 | if (validValues.indexOf(parameter) < 0) { 86 | isValid = false; 87 | } 88 | } 89 | 90 | if (!isValid) { 91 | throw TypeError(`The input value ${parameter} of ${parameterDesc} is invalid! The type should be ${validTypes}, and the values should be ${validValues}.`); 92 | } 93 | }; 94 | -------------------------------------------------------------------------------- /src/utils/wasm-utils.js: -------------------------------------------------------------------------------- 1 | import pako from 'pako'; 2 | import index from '../index'; 3 | 4 | /** 5 | * Check if WebAssembly is supported or not 6 | * 7 | * @return {boolean} 8 | */ 9 | export const wasmSupported = function () { 10 | return WebAssembly !== 'undefined'; 11 | }; 12 | 13 | /** 14 | * Decode Base64 encoded .wasm bytes 15 | * 16 | * @param compressedBase64Bytes Base64-encoded pako-compressed .wasm bytes 17 | * @return {Uint8Array|*} .wasm bytes, this is intended to be used by WebAssembly.instantiate 18 | */ 19 | export const generateWasmBytes = function (compressedBase64Bytes) { 20 | function charCodeAt (c) { 21 | return c.charCodeAt(0); 22 | } 23 | 24 | let compressedBytes; 25 | if (typeof atob === 'function') { 26 | // Browser case 27 | compressedBytes = new Uint8Array(atob(compressedBase64Bytes).split('').map(charCodeAt)); 28 | } else { 29 | compressedBytes = (require('buffer').Buffer).from(compressedBase64Bytes, 'base64'); 30 | } 31 | 32 | return pako.inflate(compressedBytes); 33 | }; 34 | 35 | /** 36 | * Load wasm bytes by WebAssembly.instantiate. Note this is async as WebAssembly.instantiate is async. 37 | * The async WebAssembly.instantiate is recommended instead of its sync variant WebAssembly.instance 38 | * 39 | * @param wasmBytes .wasm file bytes 40 | * @param imports configs for WebAssembly.instantiate, this is related to the generated glue code 41 | * @return {Promise} the generated WebAssembly target 42 | */ 43 | export const loadWasm = async function(wasmBytes, imports) { 44 | if (typeof WebAssembly !== 'object' || typeof WebAssembly.instantiate !== 'function') { 45 | throw new Error('WebAssembly is not supported.'); 46 | } 47 | 48 | const loadResult = await WebAssembly.instantiate(wasmBytes, imports); 49 | return loadResult.instance.exports; 50 | }; 51 | 52 | /** 53 | * An async function to load all existing WebAssembly modules. Please note that this only need to be called once. 54 | */ 55 | export const loadAllWasm = async function() { 56 | await Promise.allSettled( 57 | Object.values(index.algo).map(algo => { 58 | if (!algo.loadWasm) { 59 | return; 60 | } 61 | return algo.loadWasm(); 62 | }) 63 | ); 64 | }; 65 | -------------------------------------------------------------------------------- /test/aes.profile.test.js: -------------------------------------------------------------------------------- 1 | import C from '../src/index.js'; 2 | 3 | let data = {}; 4 | beforeAll(async () => { 5 | data.key = C.enc.Hex.parse('000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f'); 6 | data.iv = C.enc.Hex.parse('000102030405060708090a0b0c0d0e0f'); 7 | await C.AES.loadWasm(); 8 | }); 9 | 10 | describe('algo-aes-profile', () => { 11 | 12 | test('profileSinglePartMessage', () => { 13 | let singlePartMessage = ''; 14 | for (let i = 0; i < 500; i++) { 15 | singlePartMessage += '12345678901234567890123456789012345678901234567890'; 16 | } 17 | C.algo.AES.createEncryptor(data.key, { 18 | iv: data.iv 19 | }).finalize(singlePartMessage) + ''; 20 | }); 21 | 22 | test('profileMultiPartMessage', () => { 23 | let aes = C.algo.AES.createEncryptor(data.key, { 24 | iv: data.iv 25 | }); 26 | for (let i = 0; i < 500; i++) { 27 | aes.process('12345678901234567890123456789012345678901234567890') + ''; 28 | } 29 | aes.finalize() + ''; 30 | }); 31 | }); 32 | -------------------------------------------------------------------------------- /test/algo.blowfish.test.js: -------------------------------------------------------------------------------- 1 | import C from '../src/index'; 2 | 3 | let data = {}; 4 | beforeAll(async () => { 5 | await C.SHA256.loadWasm(); 6 | data.saltA = C.enc.Hex.parse('AA00000000000000'); 7 | }); 8 | 9 | beforeAll(async () => { 10 | await C.Blowfish.loadWasm(); 11 | await C.SHA256.loadWasm(); 12 | }); 13 | 14 | describe('algo-blowfish-test', () => { 15 | test('testEncrypt', () => { 16 | let encryptedA = C.Blowfish.encrypt('Test', 17 | 'pass', 18 | { 19 | salt: data.saltA, 20 | hasher: C.algo.SHA256 21 | }).toString(); 22 | expect(encryptedA).toBe('U2FsdGVkX1+qAAAAAAAAAKTIU8MPrBdH'); 23 | }); 24 | 25 | test('testDecrypt', () => { 26 | let encryptedA = C.Blowfish.encrypt('Test', 27 | 'pass', 28 | { 29 | salt: data.saltA, 30 | hasher: C.algo.SHA256 31 | }).toString(); 32 | 33 | expect(C.Blowfish.decrypt(encryptedA, 'pass', { hasher: C.algo.SHA256 }).toString(C.enc.Utf8)).toBe('Test'); 34 | }); 35 | }); 36 | -------------------------------------------------------------------------------- /test/algo.pbkdf2.profile.test.js: -------------------------------------------------------------------------------- 1 | import C from '../src/index'; 2 | 3 | beforeAll(async () => { 4 | await C.SHA256.loadWasm(); 5 | }); 6 | 7 | describe('algo-pbkdf2-profile', () => { 8 | test('profileKeySize256Iterations20', () => { 9 | new C.algo.PBKDF2({ 10 | keySize: 256 / 32, 11 | iterations: 20 12 | }).compute('password', 'ATHENA.MIT.EDUraeburn'); 13 | }); 14 | }); 15 | -------------------------------------------------------------------------------- /test/algo.rabbit.profile.test.js: -------------------------------------------------------------------------------- 1 | import C from '../src/index'; 2 | 3 | const data = {}; 4 | 5 | beforeAll(async () => { 6 | data.key = C.enc.Hex.parse('000102030405060708090a0b0c0d0e0f'); 7 | await C.Rabbit.loadWasm(); 8 | }); 9 | 10 | describe('algo-rabbit-profile', () => { 11 | test('profileSinglePartMessage', () => { 12 | let singlePartMessage = ''; 13 | for (let i = 0; i < 500; i++) { 14 | singlePartMessage += '12345678901234567890123456789012345678901234567890'; 15 | } 16 | 17 | C.algo.Rabbit.createEncryptor(data.key).finalize(singlePartMessage) + ''; 18 | }); 19 | 20 | test('profileMultiPartMessage', () => { 21 | let rabbit = C.algo.Rabbit.createEncryptor(data.key); 22 | for (let i = 0; i < 500; i++) { 23 | rabbit.process('12345678901234567890123456789012345678901234567890') + ''; 24 | } 25 | rabbit.finalize() + ''; 26 | }); 27 | }); 28 | -------------------------------------------------------------------------------- /test/algo.rc4.profile.test.js: -------------------------------------------------------------------------------- 1 | import C from '../src/index'; 2 | 3 | const data = {}; 4 | beforeAll(async () => { 5 | data.key = C.enc.Hex.parse('000102030405060708090a0b0c0d0e0f'); 6 | await C.MD5.loadWasm(); 7 | await C.RC4.loadWasm(); 8 | }); 9 | 10 | describe('algo-rc4-profile', () => { 11 | test('profileSinglePartMessage', () => { 12 | let singlePartMessage = ''; 13 | for (let i = 0; i < 500; i++) { 14 | singlePartMessage += '12345678901234567890123456789012345678901234567890'; 15 | } 16 | C.algo.RC4.createEncryptor(data.key).finalize(singlePartMessage) + ''; 17 | }); 18 | 19 | test('profileMultiPartMessage', () => { 20 | let rc4 = C.algo.RC4.createEncryptor(data.key); 21 | for (let i = 0; i < 500; i++) { 22 | rc4.process('12345678901234567890123456789012345678901234567890') + ''; 23 | } 24 | rc4.finalize() + ''; 25 | }); 26 | }); -------------------------------------------------------------------------------- /test/algo.rc4.test.js: -------------------------------------------------------------------------------- 1 | import C from '../src/index'; 2 | 3 | beforeAll(async () => { 4 | await C.SHA256.loadWasm(); 5 | await C.RC4.loadWasm(); 6 | }); 7 | 8 | describe('rc4', () => { 9 | test('testVector1', () => { 10 | expect(C.RC4.encrypt(C.enc.Hex.parse('0000000000000000'), C.enc.Hex.parse('0123456789abcdef')).ciphertext.toString()) 11 | .toBe('7494c2e7104b0879'); 12 | }); 13 | 14 | test('testVector2', () => { 15 | expect(C.RC4.encrypt(C.enc.Hex.parse('dcee4cf92c'), C.enc.Hex.parse('618a63d2fb')).ciphertext.toString()) 16 | .toBe('f13829c9de'); 17 | }); 18 | 19 | test('drop', () => { 20 | expect(C.RC4Drop.encrypt(C.enc.Hex.parse('0000000000000000'), C.enc.Hex.parse('0123456789abcdef'), { 21 | drop: 2 22 | }).ciphertext.toString()) 23 | .toBe(C.RC4.encrypt(C.enc.Hex.parse('00000000000000000000000000000000'), C.enc.Hex.parse('0123456789abcdef')).ciphertext.toString().substr(16)); 24 | }); 25 | 26 | test('multi part', () => { 27 | const rabbit = C.algo.RC4.createEncryptor(C.enc.Hex.parse('0123456789abcdef')); 28 | const ciphertext1 = rabbit.process(C.enc.Hex.parse('00000000')); 29 | const ciphertext2 = rabbit.process(C.enc.Hex.parse('0000')); 30 | const ciphertext3 = rabbit.process(C.enc.Hex.parse('0000')); 31 | const ciphertext4 = rabbit.finalize(); 32 | 33 | expect(ciphertext1.concat(ciphertext2).concat(ciphertext3).concat(ciphertext4).toString()) 34 | .toBe('7494c2e7104b0879'); 35 | }); 36 | 37 | test('input integrity', () => { 38 | const message = C.enc.Hex.parse('0000000000000000'); 39 | const key = C.enc.Hex.parse('0123456789abcdef'); 40 | 41 | const expectedMessage = message.toString(); 42 | const expectedKey = key.toString(); 43 | 44 | C.RC4.encrypt(message, key); 45 | 46 | expect(message.toString()).toBe(expectedMessage); 47 | expect(key.toString()).toBe(expectedKey); 48 | }); 49 | 50 | test('test helper', () => { 51 | // Save original random method 52 | const { 53 | random 54 | } = C.lib.WordArray; 55 | 56 | // Replace random method with one that returns a predictable value 57 | C.lib.WordArray.random = (nBytes) => { 58 | const words = []; 59 | for (let i = 0; i < nBytes; i += 4) { 60 | words.push([0x11223344]); 61 | } 62 | 63 | return new C.lib.WordArray(words, nBytes); 64 | }; 65 | 66 | expect(C.RC4.encrypt('Hi There', C.SHA256('Jefe'), { 67 | mode: C.mode.ECB, 68 | padding: C.pad.NoPadding 69 | }).ciphertext.toString()) 70 | .toBe(C.algo.RC4.createEncryptor(C.SHA256('Jefe'), { 71 | mode: C.mode.ECB, 72 | padding: C.pad.NoPadding 73 | }).finalize('Hi There').toString()); 74 | expect(C.RC4.encrypt('Hi There', C.SHA256('Jefe'), { 75 | mode: C.mode.ECB, 76 | padding: C.pad.NoPadding 77 | }).toString()) 78 | .toBe(C.lib.SerializableCipher.encrypt(C.algo.RC4, 'Hi There', C.SHA256('Jefe'), { 79 | mode: C.mode.ECB, 80 | padding: C.pad.NoPadding 81 | }).toString()); 82 | expect(C.RC4.encrypt('Hi There', 'Jefe', { 83 | mode: C.mode.ECB, 84 | padding: C.pad.NoPadding 85 | }).toString()) 86 | .toBe(C.lib.PasswordBasedCipher.encrypt(C.algo.RC4, 'Hi There', 'Jefe', { 87 | mode: C.mode.ECB, 88 | padding: C.pad.NoPadding 89 | }).toString()); 90 | 91 | // Restore random method 92 | C.lib.WordArray.random = random; 93 | }); 94 | }); 95 | -------------------------------------------------------------------------------- /test/algo.ripemd160.test.js: -------------------------------------------------------------------------------- 1 | import C from '../src/index'; 2 | 3 | const VERTOR_TEST_CONFIG = [ 4 | [1, 'The quick brown fox jumps over the lazy dog', '37f332f68db77bd9d7edd4969571ad671cf9dd3b'], 5 | [2, 'The quick brown fox jumps over the lazy cog', '132072df690933835eb8b6ad0b77e7b6f14acad7'], 6 | [3, '', '9c1185a5c5e9fc54612808977ee8f548b2258d31'] 7 | ]; 8 | 9 | beforeAll(async () => { 10 | await C.RIPEMD160.loadWasm(); 11 | }); 12 | 13 | describe('algo-ripemd160-test', () => { 14 | test.each(VERTOR_TEST_CONFIG)( 15 | 'testVector%i', 16 | (a, b, expected) => { 17 | expect(C.RIPEMD160(b).toString()).toBe(expected); 18 | } 19 | ); 20 | }); -------------------------------------------------------------------------------- /test/algo.sha1.profile.test.js: -------------------------------------------------------------------------------- 1 | import C from '../src/index'; 2 | 3 | beforeAll(async () => { 4 | await C.SHA1.loadWasm(); 5 | }); 6 | 7 | describe('algo-sha1-profile', () => { 8 | test('profileSinglePartMessage', () => { 9 | let singlePartMessage = ''; 10 | for (let i = 0; i < 500; i++) { 11 | singlePartMessage += '12345678901234567890123456789012345678901234567890'; 12 | } 13 | 14 | new C.algo.SHA1().finalize(singlePartMessage) + ''; 15 | }); 16 | 17 | test('profileMultiPartMessage', () => { 18 | let sha1 = new C.algo.SHA1(); 19 | for (let i = 0; i < 500; i++) { 20 | sha1.update('12345678901234567890123456789012345678901234567890'); 21 | } 22 | sha1.finalize() + ''; 23 | }); 24 | }); 25 | -------------------------------------------------------------------------------- /test/algo.sha1.test.js: -------------------------------------------------------------------------------- 1 | import C from '../src/index'; 2 | 3 | const VECTOR_CONFIG_TEST = [ 4 | [1, '', 'da39a3ee5e6b4b0d3255bfef95601890afd80709'], 5 | [2, 'a', '86f7e437faa5a7fce15d1ddcb9eaeaea377667b8'], 6 | [3, 'abc', 'a9993e364706816aba3e25717850c26c9cd0d89d'], 7 | [4, 'message digest', 'c12252ceda8be8994d5fa0290a47231c1d16aae3'], 8 | [5, 'abcdefghijklmnopqrstuvwxyz', '32d10c7b8cf96570ca04ce37f2a19d84240d3a89'], 9 | [6, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789', '761c457bf73b14d27e9e9265c46f4b4dda11f940'], 10 | [7, '12345678901234567890123456789012345678901234567890123456789012345678901234567890', '50abf5706a150990a08b2c5ea40fa0e585554732'] 11 | ]; 12 | 13 | beforeAll(async () => { 14 | await C.SHA1.loadWasm(); 15 | }); 16 | 17 | describe('algo-sha1-test', () => { 18 | test.each(VECTOR_CONFIG_TEST)( 19 | 'testVector%i', 20 | (a, b, expected) => { 21 | expect(C.SHA1(b).toString()).toBe(expected); 22 | } 23 | ); 24 | 25 | test('testUpdateAndLongMessage', () => { 26 | const sha1 = new C.algo.SHA1(); 27 | for (let i = 0; i < 100; i++) { 28 | sha1.update('12345678901234567890123456789012345678901234567890'); 29 | } 30 | 31 | expect(sha1.finalize().toString()).toBe('85e4c4b3933d5553ebf82090409a9d90226d845c'); 32 | }); 33 | 34 | test('testClone', () => { 35 | const sha1 = new C.algo.SHA1(); 36 | 37 | expect(sha1.update('a').clone().finalize().toString()).toBe(C.SHA1('a').toString()); 38 | expect(sha1.update('b').clone().finalize().toString()).toBe(C.SHA1('ab').toString()); 39 | expect(sha1.update('c').clone().finalize().toString()).toBe(C.SHA1('abc').toString()); 40 | }); 41 | 42 | test('testInputIntegrity', () => { 43 | const message = new C.lib.WordArray([0x12345678]); 44 | 45 | const expected = message.toString(); 46 | 47 | C.SHA1(message); 48 | 49 | expect(message.toString()).toBe(expected); 50 | }); 51 | 52 | test('testHelper', () => { 53 | expect(C.SHA1('').toString()).toBe(new C.algo.SHA1().finalize('').toString()); 54 | }); 55 | 56 | test('testHmacHelper', () => { 57 | expect(C.HmacSHA1('Hi There', C.enc.Hex.parse('0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b')).toString()) 58 | .toBe(new C.algo.HMAC(C.algo.SHA1, C.enc.Hex.parse('0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b')).finalize('Hi There').toString()); 59 | }); 60 | }); 61 | -------------------------------------------------------------------------------- /test/algo.sha224.test.js: -------------------------------------------------------------------------------- 1 | import C from '../src/index'; 2 | 3 | const VECTOR_TEST_CONFIG = [ 4 | [1, '', 'd14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f'], 5 | [1, 'The quick brown fox jumps over the lazy dog', '730e109bd7a8a32b1cb9d9a09aa2325d2430587ddbc0c38bad911525'], 6 | [1, 'The quick brown fox jumps over the lazy dog.', '619cba8e8e05826e9b8c519c0a5c68f4fb653e8a3d8aa04bb2c8cd4c'] 7 | ]; 8 | 9 | beforeAll(async () => { 10 | await C.SHA224.loadWasm(); 11 | }); 12 | 13 | describe('algo-sha224-test', () => { 14 | test.each(VECTOR_TEST_CONFIG)( 15 | 'testVector%i', 16 | (a, b, expected) => { 17 | expect(C.SHA224(b).toString()).toBe(expected); 18 | } 19 | ); 20 | }); 21 | -------------------------------------------------------------------------------- /test/algo.sha256.profile.test.js: -------------------------------------------------------------------------------- 1 | import C from '../src/index'; 2 | 3 | beforeAll(async () => { 4 | await C.SHA256.loadWasm(); 5 | }); 6 | 7 | 8 | describe('algo-sha256-profile', () => { 9 | test('profileSinglePartMessage', () => { 10 | let singlePartMessage = ''; 11 | for (let i = 0; i < 500; i++) { 12 | singlePartMessage += '12345678901234567890123456789012345678901234567890'; 13 | } 14 | new C.algo.SHA256().finalize(singlePartMessage) + ''; 15 | }); 16 | 17 | test('profileMultiPartMessage', () => { 18 | let sha256 = new C.algo.SHA256(); 19 | for (let i = 0; i < 500; i++) { 20 | sha256.update('12345678901234567890123456789012345678901234567890'); 21 | } 22 | sha256.finalize() + ''; 23 | }); 24 | }); 25 | -------------------------------------------------------------------------------- /test/algo.sha256.test.js: -------------------------------------------------------------------------------- 1 | import C from '../src/index'; 2 | 3 | const VECTOR_CONFIG_TEST = [ 4 | [1, '', 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855'], 5 | [2, 'a', 'ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb'], 6 | [3, 'abc', 'ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad'], 7 | [4, 'message digest', 'f7846f55cf23e14eebeab5b4e1550cad5b509e3348fbc4efa3a1413d393cb650'], 8 | [5, 'abcdefghijklmnopqrstuvwxyz', '71c480df93d6ae2f1efad1447c66c9525e316218cf51fc8d9ed832f2daf18b73'], 9 | [6, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789', 'db4bfcbd4da0cd85a60c3c37d3fbd8805c77f15fc6b1fdfe614ee0a7c8fdb4c0'], 10 | [7, '12345678901234567890123456789012345678901234567890123456789012345678901234567890', 'f371bc4a311f2b009eef952dd83ca80e2b60026c8e935592d0f9c308453c813e'] 11 | ]; 12 | 13 | beforeAll(async () => { 14 | await C.SHA256.loadWasm(); 15 | }); 16 | 17 | describe('algo-sha256-test', () => { 18 | test.each(VECTOR_CONFIG_TEST)( 19 | 'testVector%i', 20 | (a, b, expected) => { 21 | expect(C.SHA256(b).toString()).toBe(expected); 22 | } 23 | ); 24 | 25 | test('testUpdateAndLongMessage', () => { 26 | let sha256 = new C.algo.SHA256(); 27 | for (let i = 0; i < 100; i++) { 28 | sha256.update('12345678901234567890123456789012345678901234567890'); 29 | } 30 | expect(sha256.finalize().toString()).toBe('f8146961d9b73d8da49ccd526fca65439cdd5b402f76971556d5f52fd129843e'); 31 | }); 32 | 33 | test('testClone', () => { 34 | let sha256 = new C.algo.SHA256(); 35 | expect(sha256.update('a').clone().finalize().toString()).toBe(C.SHA256('a').toString()); 36 | expect(sha256.update('b').clone().finalize().toString()).toBe(C.SHA256('ab').toString()); 37 | expect(sha256.update('c').clone().finalize().toString()).toBe(C.SHA256('abc').toString()); 38 | }); 39 | 40 | test('testInputIntegrity', () => { 41 | let message = new C.lib.WordArray([0x12345678]); 42 | let expected = message.toString(); 43 | C.SHA256(message); 44 | expect(message.toString()).toBe(expected); 45 | }); 46 | 47 | test('testHelper', () => { 48 | expect(C.SHA256('').toString()).toBe(new C.algo.SHA256().finalize('').toString()); 49 | }); 50 | 51 | test('testHmacHelper', () => { 52 | expect(C.HmacSHA256('Hi There', C.enc.Hex.parse('0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b')).toString()).toBe(new C.algo.HMAC(C.algo.SHA256, C.enc.Hex.parse('0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b')).finalize('Hi There').toString()); 53 | }); 54 | }); 55 | -------------------------------------------------------------------------------- /test/algo.sha3.profile.test.js: -------------------------------------------------------------------------------- 1 | import C from '../src/index'; 2 | 3 | beforeAll(async () => { 4 | await C.SHA3.loadWasm(); 5 | }); 6 | 7 | describe('algo-sha3-profile', () => { 8 | test('profileSinglePartMessage', () => { 9 | let singlePartMessage = ''; 10 | for (let i = 0; i < 500; i++) { 11 | singlePartMessage += '12345678901234567890123456789012345678901234567890'; 12 | } 13 | 14 | new C.algo.SHA3().finalize(singlePartMessage) + ''; 15 | }); 16 | 17 | test('profileMultiPartMessage', () => { 18 | let sha3 = new C.algo.SHA3(); 19 | for (let i = 0; i < 500; i++) { 20 | sha3.update('12345678901234567890123456789012345678901234567890'); 21 | } 22 | sha3.finalize() + ''; 23 | }); 24 | }); 25 | -------------------------------------------------------------------------------- /test/algo.sha384.test.js: -------------------------------------------------------------------------------- 1 | import C from '../src/index'; 2 | 3 | beforeAll(async () => { 4 | await C.SHA384.loadWasm(); 5 | }); 6 | 7 | const VECTOR_CONFIG_TEST = [ 8 | [1, '', '38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b'], 9 | [2, 'The quick brown fox jumps over the lazy dog', 'ca737f1014a48f4c0b6dd43cb177b0afd9e5169367544c494011e3317dbf9a509cb1e5dc1e85a941bbee3d7f2afbc9b1'], 10 | [3, 'The quick brown fox jumps over the lazy dog.', 'ed892481d8272ca6df370bf706e4d7bc1b5739fa2177aae6c50e946678718fc67a7af2819a021c2fc34e91bdb63409d7'] 11 | ]; 12 | 13 | describe('algo-sha384-test', () => { 14 | test.each(VECTOR_CONFIG_TEST)( 15 | 'testVector%i', 16 | (a, b, expected) => { 17 | expect(C.SHA384(b).toString()).toBe(expected); 18 | } 19 | ); 20 | 21 | test('testUpdateAndLongMessage', () => { 22 | const sha384 = new C.algo.SHA384(); 23 | for (let i = 0; i < 100; i++) { 24 | sha384.update('12345678901234567890123456789012345678901234567890'); 25 | } 26 | 27 | expect(sha384.finalize().toString()) 28 | .toBe('297a519246d6f639a4020119e1f03fc8d77171647b2ff75ea4125b7150fed0cdcc93f8dca1c3c6a624d5e88d780d82cd'); 29 | }); 30 | 31 | test('testClone', () => { 32 | const sha384 = new C.algo.SHA384(); 33 | 34 | expect(sha384.update('a').clone().finalize().toString()).toBe(C.SHA384('a').toString()); 35 | expect(sha384.update('b').clone().finalize().toString()).toBe(C.SHA384('ab').toString()); 36 | expect(sha384.update('c').clone().finalize().toString()).toBe(C.SHA384('abc').toString()); 37 | }); 38 | 39 | test('testInputIntegrity', () => { 40 | const message = new C.lib.WordArray([0x12345678]); 41 | 42 | const expected = message.toString(); 43 | 44 | C.SHA384(message); 45 | 46 | expect(message.toString()).toBe(expected); 47 | }); 48 | 49 | test('testHelper', () => { 50 | expect(C.SHA384('').toString()).toBe(new C.algo.SHA384().finalize('').toString()); 51 | }); 52 | 53 | test('testHmacHelper', () => { 54 | expect(C.HmacSHA384('Hi There', C.enc.Hex.parse('0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b')).toString()) 55 | .toBe(new C.algo.HMAC(C.algo.SHA384, C.enc.Hex.parse('0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b')).finalize('Hi There').toString()); 56 | }); 57 | }); 58 | -------------------------------------------------------------------------------- /test/algo.sha512.profile.test.js: -------------------------------------------------------------------------------- 1 | import C from '../src/index'; 2 | 3 | beforeAll(async () => { 4 | await C.SHA512.loadWasm(); 5 | }); 6 | 7 | describe('algo-sha512-profile', () => { 8 | test('profileSinglePartMessage', () => { 9 | let singlePartMessage = ''; 10 | for (let i = 0; i < 500; i++) { 11 | singlePartMessage += '12345678901234567890123456789012345678901234567890'; 12 | } 13 | new C.algo.SHA512().finalize(singlePartMessage) + ''; 14 | }); 15 | 16 | test('profileMultiPartMessage', () => { 17 | let sha512 = new C.algo.SHA512(); 18 | for (let i = 0; i < 500; i++) { 19 | sha512.update('12345678901234567890123456789012345678901234567890'); 20 | } 21 | sha512.finalize() + ''; 22 | }); 23 | }); 24 | -------------------------------------------------------------------------------- /test/algo.sha512.test.js: -------------------------------------------------------------------------------- 1 | import C from '../src/index'; 2 | 3 | const VECTOR_CONFIG_TEST = [ 4 | [1, '', 'cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e'], 5 | [2, 'The quick brown fox jumps over the lazy dog', '07e547d9586f6a73f73fbac0435ed76951218fb7d0c8d788a309d785436bbb642e93a252a954f23912547d1e8a3b5ed6e1bfd7097821233fa0538f3db854fee6'], 6 | [3, 'The quick brown fox jumps over the lazy dog.', '91ea1245f20d46ae9a037a989f54f1f790f0a47607eeb8a14d12890cea77a1bbc6c7ed9cf205e67b7f2b8fd4c7dfd3a7a8617e45f3c463d481c7e586c39ac1ed'] 7 | ]; 8 | 9 | beforeAll(async () => { 10 | await C.SHA512.loadWasm(); 11 | }); 12 | 13 | describe('algo-sha512-test', () => { 14 | test.each(VECTOR_CONFIG_TEST)( 15 | 'testVector%i', 16 | (a, b, expected) => { 17 | expect(C.SHA512(b).toString()).toBe(expected); 18 | } 19 | ); 20 | 21 | test('testUpdateAndLongMessage', () => { 22 | const sha512 = new C.algo.SHA512(); 23 | for (let i = 0; i < 100; i++) { 24 | sha512.update('12345678901234567890123456789012345678901234567890'); 25 | } 26 | 27 | expect(sha512.finalize().toString()) 28 | .toBe('9bc64f37c54606dff234b6607e06683c7ba248558d0ec74a11525d9f59e0be566489cc9413c00ca5e9db705fc52ba71214bcf118f65072fe284af8f8cf9500af'); 29 | }); 30 | 31 | test('testClone', () => { 32 | const sha512 = new C.algo.SHA512(); 33 | 34 | expect(sha512.update('a').clone().finalize().toString()).toBe(C.SHA512('a').toString()); 35 | expect(sha512.update('b').clone().finalize().toString()).toBe(C.SHA512('ab').toString()); 36 | expect(sha512.update('c').clone().finalize().toString()).toBe(C.SHA512('abc').toString()); 37 | }); 38 | 39 | test('testInputIntegrity', () => { 40 | const message = new C.lib.WordArray([0x12345678]); 41 | 42 | const expected = message.toString(); 43 | 44 | C.SHA512(message); 45 | 46 | expect(message.toString()).toBe(expected); 47 | }); 48 | 49 | test('testHelper', () => { 50 | expect(C.SHA512('').toString()).toBe(new C.algo.SHA512().finalize('').toString()); 51 | }); 52 | 53 | test('testHmacHelper', () => { 54 | expect(C.HmacSHA512('Hi There', C.enc.Hex.parse('0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b')).toString()) 55 | .toBe(new C.algo.HMAC(C.algo.SHA512, C.enc.Hex.parse('0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b')).finalize('Hi There').toString()); 56 | }); 57 | }); 58 | -------------------------------------------------------------------------------- /test/algo.tripledes.profile.test.js: -------------------------------------------------------------------------------- 1 | import C from '../src/index'; 2 | 3 | const data = {}; 4 | beforeAll(async () => { 5 | data.key = C.enc.Hex.parse('0001020304050607'); 6 | data.iv = C.enc.Hex.parse('08090a0b0c0d0e0f'); 7 | await C.TripleDES.loadWasm(); 8 | }); 9 | 10 | describe('algo-tripledes-profile', () => { 11 | test('profileSinglePartMessage', () => { 12 | let singlePartMessage = ''; 13 | for (let i = 0; i < 100; i++) { 14 | singlePartMessage += '12345678901234567890123456789012345678901234567890'; 15 | } 16 | 17 | C.algo.TripleDES.createEncryptor(data.key, { 18 | iv: data.iv 19 | }).finalize(singlePartMessage) + ''; 20 | }); 21 | 22 | test('profileMultiPartMessage', () => { 23 | let des = C.algo.TripleDES.createEncryptor(data.key, { 24 | iv: data.iv 25 | }); 26 | for (let i = 0; i < 100; i++) { 27 | des.process('12345678901234567890123456789012345678901234567890') + ''; 28 | } 29 | des.finalize() + ''; 30 | }); 31 | }); 32 | -------------------------------------------------------------------------------- /test/config.test.js: -------------------------------------------------------------------------------- 1 | import C from '../src/index'; 2 | 3 | let data = {}; 4 | beforeAll(async () => { 5 | data.saltA = C.enc.Hex.parse('AA00000000000000'); 6 | data.saltB = C.enc.Hex.parse('BB00000000000000'); 7 | await C.AES.loadWasm(); 8 | await C.SHA1.loadWasm(); 9 | await C.SHA256.loadWasm(); 10 | await C.SHA512.loadWasm(); 11 | await C.MD5.loadWasm(); 12 | }); 13 | 14 | describe('config-test', () => { 15 | test('testEncrypt', () => { 16 | expect(C.AES.encrypt('Test', 'Pass', { salt: data.saltA }).toString()).toBe(C.AES.encrypt('Test', 'Pass', { salt: data.saltA }).toString()); 17 | expect(C.AES.encrypt('Test', 'Pass', { salt: data.saltA }).toString()).not.toBe(C.AES.encrypt('Test', 'Pass', { salt: data.saltB }).toString()); 18 | }); 19 | 20 | test('testDecrypt', () => { 21 | const encryptedA = C.AES.encrypt('Test', 'Pass', { salt: data.saltA }); 22 | const encryptedB = C.AES.encrypt('Test', 'Pass', { salt: data.saltB }); 23 | expect(C.AES.decrypt(encryptedA, 'Pass').toString(C.enc.Utf8)).toBe('Test'); 24 | expect(C.AES.decrypt(encryptedB, 'Pass').toString(C.enc.Utf8)).toBe('Test'); 25 | }); 26 | 27 | test('testCustomKDFHasher', () => { 28 | //SHA1 29 | let encryptedSHA1 = C.AES.encrypt('Test', 'Pass', { salt: data.saltA, hasher: C.algo.SHA1 }).toString(); 30 | expect(C.AES.decrypt(encryptedSHA1, 'Pass', { hasher: C.algo.SHA1 }).toString(C.enc.Utf8)).toBe('Test'); 31 | 32 | //SHA256 33 | let encryptedSHA256 = C.AES.encrypt('Test', 'Pass', { salt: data.saltA, hasher: C.algo.SHA256 }).toString(); 34 | expect(C.AES.decrypt(encryptedSHA256, 'Pass', { hasher: C.algo.SHA256 }).toString(C.enc.Utf8)).toBe('Test'); 35 | 36 | //SHA512 37 | let encryptedSHA512 = C.AES.encrypt('Test', 'Pass', { salt: data.saltA, hasher: C.algo.SHA512 }).toString(); 38 | expect(C.AES.decrypt(encryptedSHA512, 'Pass', { hasher: C.algo.SHA512 }).toString(C.enc.Utf8)).toBe('Test'); 39 | 40 | //Default: MD5 41 | let encryptedDefault = C.AES.encrypt('Test', 'Pass', { salt: data.saltA }).toString(); 42 | let encryptedMD5 = C.AES.encrypt('Test', 'Pass', { salt: data.saltA, hasher: C.algo.MD5 }).toString(); 43 | expect(C.AES.decrypt(encryptedMD5, 'Pass', { hasher: C.algo.MD5 }).toString(C.enc.Utf8)).toBe('Test'); 44 | expect(encryptedMD5).toBe(encryptedDefault); 45 | 46 | //Different KDFHasher 47 | expect(encryptedSHA1).not.toBe(encryptedDefault); 48 | expect(encryptedSHA256).not.toBe(encryptedDefault); 49 | expect(encryptedSHA512).not.toBe(encryptedDefault); 50 | }); 51 | }); 52 | -------------------------------------------------------------------------------- /test/crypto-js-test/algo.md5.test.js: -------------------------------------------------------------------------------- 1 | import cryptoJs from 'crypto-js/crypto-js'; 2 | import cryptoJsWasm from '../../src/index.js'; 3 | 4 | beforeAll(async () => { 5 | await cryptoJsWasm.MD5.loadWasm(); 6 | }); 7 | 8 | const data1 = ''; 9 | const data2 = 'Test'; 10 | const data3 = 'message digest'; 11 | const data4 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; 12 | 13 | test('testHelper', () => { 14 | const md5Wasm = new cryptoJsWasm.algo.MD5(); 15 | const md5 = cryptoJs.algo.MD5.create(); 16 | expect(md5Wasm.finalize(data1).toString()).toEqual(md5.finalize(data1).toString()); 17 | }); 18 | 19 | test('algo-md5-test', () => { 20 | expect(cryptoJsWasm.MD5(data1).toString()).toEqual(cryptoJs.MD5(data1).toString()); 21 | expect(cryptoJsWasm.MD5(data2).toString()).toEqual(cryptoJs.MD5(data2).toString()); 22 | expect(cryptoJsWasm.MD5(data3).toString()).toEqual(cryptoJs.MD5(data3).toString()); 23 | expect(cryptoJsWasm.MD5(data4).toString()).toEqual(cryptoJs.MD5(data4).toString()); 24 | }); 25 | 26 | test('testClone', () => { 27 | const md5Wasm = new cryptoJsWasm.algo.MD5(); 28 | const md5 = cryptoJs.algo.MD5.create(); 29 | expect(md5Wasm.update(data2).clone().finalize().toString()).toEqual(md5.update(data2).clone().finalize().toString()); 30 | }); 31 | 32 | test('testUpdateAndLongMessage', () => { 33 | const md5Wasm = new cryptoJsWasm.algo.MD5(); 34 | const md5 = cryptoJs.algo.MD5.create(); 35 | let i = 0; 36 | while (i < 100) { 37 | md5Wasm.update('12345678901234567890123456789012345678901234567890'); 38 | md5.update('12345678901234567890123456789012345678901234567890'); 39 | i++; 40 | } 41 | expect(md5Wasm.finalize().toString()).toEqual(md5.finalize().toString()); 42 | }); -------------------------------------------------------------------------------- /test/crypto-js-test/algo.rabbit.test.js: -------------------------------------------------------------------------------- 1 | import cryptoJs from 'crypto-js/crypto-js'; 2 | import cryptoJsWasm from '../../src/index.js'; 3 | 4 | beforeAll(async () => { 5 | await cryptoJsWasm.Rabbit.loadWasm(); 6 | await cryptoJsWasm.SHA256.loadWasm(); 7 | }); 8 | 9 | const iv = cryptoJs.enc.Hex.parse('08090a0b0c0d0e0f'); 10 | const data1 = cryptoJs.enc.Hex.parse('001122334455001122334455001122334455001122334455'); 11 | const data2 = cryptoJs.enc.Hex.parse('66778899aa'); 12 | const data3 = cryptoJs.enc.Hex.parse('bbccddeeff'); 13 | const data = cryptoJs.enc.Hex.parse('00112233445500112233445500112233445500112233445566778899aabbccddeeff'); 14 | 15 | test('testHelper', () => { 16 | expect(cryptoJsWasm.algo.Rabbit.createEncryptor(cryptoJsWasm.SHA256('key')).finalize('Test').toString()) 17 | .toEqual(cryptoJs.algo.Rabbit.createEncryptor(cryptoJs.SHA256('key')).finalize('Test').toString()); 18 | expect(cryptoJsWasm.lib.SerializableCipher.encrypt(cryptoJsWasm.algo.Rabbit, 'Test', cryptoJsWasm.SHA256('key')).toString()) 19 | .toEqual(cryptoJs.lib.SerializableCipher.encrypt(cryptoJs.algo.Rabbit, 'Test', cryptoJs.SHA256('key')).toString()); 20 | }); 21 | 22 | test('testEncrypt', () => { 23 | expect(cryptoJsWasm.Rabbit.encrypt('Test', cryptoJsWasm.SHA256('key')).toString()).toEqual(cryptoJs.Rabbit.encrypt('Test', cryptoJs.SHA256('key')).toString()); 24 | expect(cryptoJsWasm.Rabbit.encrypt('Test', cryptoJsWasm.SHA256('key'), { iv: iv }).toString()).toEqual(cryptoJs.Rabbit.encrypt('Test', cryptoJs.SHA256('key'), { iv: iv }).toString()); 25 | }); 26 | 27 | test('testDecrypt', () => { 28 | const encrypted = cryptoJs.Rabbit.encrypt('Test', 'key').toString(); 29 | expect(cryptoJs.Rabbit.decrypt(encrypted, 'key').toString(cryptoJs.enc.Utf8)).toEqual('Test'); 30 | expect(cryptoJsWasm.Rabbit.decrypt(encrypted, 'key').toString(cryptoJsWasm.enc.Utf8)).toEqual('Test'); 31 | const encryptedWithIv = cryptoJs.Rabbit.encrypt('Test', 'key', { iv: iv }).toString(); 32 | expect(cryptoJs.Rabbit.decrypt(encryptedWithIv, 'key').toString(cryptoJs.enc.Utf8)).toEqual('Test'); 33 | expect(cryptoJsWasm.Rabbit.decrypt(encryptedWithIv, 'key').toString(cryptoJsWasm.enc.Utf8)).toEqual('Test'); 34 | }); 35 | 36 | test('testMultiPart', () => { 37 | let rabbit = cryptoJs.algo.Rabbit.createEncryptor(cryptoJs.SHA256('key'), { iv: iv }); 38 | let rabbitWasm = cryptoJsWasm.algo.Rabbit.createEncryptor(cryptoJsWasm.SHA256('key'), { iv: iv }); 39 | let ciphertext1 = rabbit.process(data1); 40 | let ciphertext2 = rabbit.process(data2); 41 | let ciphertext3 = rabbit.process(data3); 42 | let ciphertext4 = rabbit.finalize(); 43 | let ciphertextWasm1 = rabbitWasm.process(data1); 44 | let ciphertextWasm2 = rabbitWasm.process(data2); 45 | let ciphertextWasm3 = rabbitWasm.process(data3); 46 | let ciphertextWasm4 = rabbitWasm.finalize(); 47 | let ciphertext = ciphertext1.concat(ciphertext2).concat(ciphertext3).concat(ciphertext4); 48 | let ciphertextWasm = ciphertextWasm1.concat(ciphertextWasm2).concat(ciphertextWasm3).concat(ciphertextWasm4); 49 | expect(ciphertext1.toString()).toEqual(ciphertextWasm1.toString()); 50 | expect(ciphertext2.toString()).toEqual(ciphertextWasm2.toString()); 51 | expect(ciphertext3.toString()).toEqual(ciphertextWasm3.toString()); 52 | expect(ciphertext4.toString()).toEqual(ciphertextWasm4.toString()); 53 | expect(ciphertext.toString()).toEqual(ciphertextWasm.toString()); 54 | expect(ciphertext.toString(cryptoJs.enc.Base64)).toEqual(cryptoJs.Rabbit.encrypt(data, cryptoJs.SHA256('key'), { iv: iv }).toString()); 55 | expect(ciphertextWasm.toString(cryptoJsWasm.enc.Base64)).toEqual(cryptoJsWasm.Rabbit.encrypt(data, cryptoJsWasm.SHA256('key'), { iv: iv }).toString()); 56 | }); -------------------------------------------------------------------------------- /test/crypto-js-test/algo.rc4.test.js: -------------------------------------------------------------------------------- 1 | import cryptoJs from 'crypto-js/crypto-js'; 2 | import cryptoJsWasm from '../../src/index.js'; 3 | 4 | beforeAll(async () => { 5 | await cryptoJsWasm.RC4.loadWasm(); 6 | }); 7 | 8 | const key = cryptoJs.enc.Hex.parse('000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f'); 9 | const data1 = cryptoJs.enc.Hex.parse('001122334455001122334455001122334455001122334455'); 10 | const data2 = cryptoJs.enc.Hex.parse('66778899aa'); 11 | const data3 = cryptoJs.enc.Hex.parse('bbccddeeff'); 12 | const data = cryptoJs.enc.Hex.parse('00112233445500112233445500112233445500112233445566778899aabbccddeeff'); 13 | 14 | test('testHelper', () => { 15 | expect(cryptoJsWasm.algo.RC4.createEncryptor(key).finalize('Test').toString()) 16 | .toEqual(cryptoJs.algo.RC4.createEncryptor(key).finalize('Test').toString()); 17 | expect(cryptoJsWasm.lib.SerializableCipher.encrypt(cryptoJsWasm.algo.RC4, 'Test', key).toString()) 18 | .toEqual(cryptoJs.lib.SerializableCipher.encrypt(cryptoJs.algo.RC4, 'Test', key).toString()); 19 | }); 20 | 21 | test('testEncrypt', () => { 22 | expect(cryptoJsWasm.RC4.encrypt('Test', key).toString()).toEqual(cryptoJs.RC4.encrypt('Test', key).toString()); 23 | }); 24 | 25 | test('testDecrypt', () => { 26 | const encrypted = cryptoJs.RC4.encrypt('Test', 'key').toString(); 27 | expect(cryptoJs.RC4.decrypt(encrypted, 'key').toString(cryptoJs.enc.Utf8)).toEqual('Test'); 28 | expect(cryptoJsWasm.RC4.decrypt(encrypted, 'key').toString(cryptoJsWasm.enc.Utf8)).toEqual('Test'); 29 | }); 30 | 31 | test('testMultiPart', () => { 32 | let rc4 = cryptoJs.algo.RC4.createEncryptor(key); 33 | let rc4Wasm = cryptoJsWasm.algo.RC4.createEncryptor(key); 34 | let ciphertext1 = rc4.process(data1); 35 | let ciphertext2 = rc4.process(data2); 36 | let ciphertext3 = rc4.process(data3); 37 | let ciphertext4 = rc4.finalize(); 38 | let ciphertextWasm1 = rc4Wasm.process(data1); 39 | let ciphertextWasm2 = rc4Wasm.process(data2); 40 | let ciphertextWasm3 = rc4Wasm.process(data3); 41 | let ciphertextWasm4 = rc4Wasm.finalize(); 42 | let ciphertext = ciphertext1.concat(ciphertext2).concat(ciphertext3).concat(ciphertext4); 43 | let ciphertextWasm = ciphertextWasm1.concat(ciphertextWasm2).concat(ciphertextWasm3).concat(ciphertextWasm4); 44 | expect(ciphertext1.toString()).toEqual(ciphertextWasm1.toString()); 45 | expect(ciphertext2.toString()).toEqual(ciphertextWasm2.toString()); 46 | expect(ciphertext3.toString()).toEqual(ciphertextWasm3.toString()); 47 | expect(ciphertext4.toString()).toEqual(ciphertextWasm4.toString()); 48 | expect(ciphertext.toString()).toEqual(ciphertextWasm.toString()); 49 | expect(ciphertext.toString(cryptoJs.enc.Base64)).toEqual(cryptoJs.RC4.encrypt(data, key).toString()); 50 | expect(ciphertextWasm.toString(cryptoJsWasm.enc.Base64)).toEqual(cryptoJsWasm.RC4.encrypt(data, key).toString()); 51 | }); -------------------------------------------------------------------------------- /test/crypto-js-test/algo.ripemd160.test.js: -------------------------------------------------------------------------------- 1 | import cryptoJs from 'crypto-js/crypto-js'; 2 | import cryptoJsWasm from '../../src/index.js'; 3 | 4 | beforeAll(async () => { 5 | await cryptoJsWasm.RIPEMD160.loadWasm(); 6 | }); 7 | 8 | const data1 = ''; 9 | const data2 = 'Test'; 10 | const data3 = 'message digest'; 11 | const data4 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; 12 | 13 | test('testHelper', () => { 14 | const ripemd160Wasm = new cryptoJsWasm.algo.RIPEMD160(); 15 | const ripemd160 = cryptoJs.algo.RIPEMD160.create(); 16 | expect(ripemd160Wasm.finalize(data1).toString()).toEqual(ripemd160.finalize(data1).toString()); 17 | }); 18 | 19 | test('algo-ripemd160-test', () => { 20 | expect(cryptoJsWasm.RIPEMD160(data1).toString()).toEqual(cryptoJs.RIPEMD160(data1).toString()); 21 | expect(cryptoJsWasm.RIPEMD160(data2).toString()).toEqual(cryptoJs.RIPEMD160(data2).toString()); 22 | expect(cryptoJsWasm.RIPEMD160(data3).toString()).toEqual(cryptoJs.RIPEMD160(data3).toString()); 23 | expect(cryptoJsWasm.RIPEMD160(data4).toString()).toEqual(cryptoJs.RIPEMD160(data4).toString()); 24 | }); 25 | 26 | test('testClone', () => { 27 | const ripemd160Wasm = new cryptoJsWasm.algo.RIPEMD160(); 28 | const ripemd160 = cryptoJs.algo.RIPEMD160.create(); 29 | expect(ripemd160Wasm.update(data2).clone().finalize().toString()).toEqual(ripemd160.update(data2).clone().finalize().toString()); 30 | }); 31 | 32 | test('testUpdateAndLongMessage', () => { 33 | const ripemd160Wasm = new cryptoJsWasm.algo.RIPEMD160(); 34 | const ripemd160 = cryptoJs.algo.RIPEMD160.create(); 35 | let i = 0; 36 | while (i < 100) { 37 | ripemd160Wasm.update('12345678901234567890123456789012345678901234567890'); 38 | ripemd160.update('12345678901234567890123456789012345678901234567890'); 39 | i++; 40 | } 41 | expect(ripemd160Wasm.finalize().toString()).toEqual(ripemd160.finalize().toString()); 42 | }); -------------------------------------------------------------------------------- /test/crypto-js-test/algo.sha1.test.js: -------------------------------------------------------------------------------- 1 | import cryptoJs from 'crypto-js/crypto-js'; 2 | import cryptoJsWasm from '../../src/index.js'; 3 | 4 | beforeAll(async () => { 5 | await cryptoJsWasm.SHA1.loadWasm(); 6 | }); 7 | 8 | const data1 = ''; 9 | const data2 = 'Test'; 10 | const data3 = 'message digest'; 11 | const data4 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; 12 | 13 | test('testHelper', () => { 14 | const sha1Wasm = new cryptoJsWasm.algo.SHA1(); 15 | const sha1 = cryptoJs.algo.SHA1.create(); 16 | expect(sha1Wasm.finalize(data1).toString()).toEqual(sha1.finalize(data1).toString()); 17 | }); 18 | 19 | test('algo-sha1-test', () => { 20 | expect(cryptoJsWasm.SHA1(data1).toString()).toEqual(cryptoJs.SHA1(data1).toString()); 21 | expect(cryptoJsWasm.SHA1(data2).toString()).toEqual(cryptoJs.SHA1(data2).toString()); 22 | expect(cryptoJsWasm.SHA1(data3).toString()).toEqual(cryptoJs.SHA1(data3).toString()); 23 | expect(cryptoJsWasm.SHA1(data4).toString()).toEqual(cryptoJs.SHA1(data4).toString()); 24 | }); 25 | 26 | test('testClone', () => { 27 | const sha1Wasm = new cryptoJsWasm.algo.SHA1(); 28 | const sha1 = cryptoJs.algo.SHA1.create(); 29 | expect(sha1Wasm.update(data2).clone().finalize().toString()).toEqual(sha1.update(data2).clone().finalize().toString()); 30 | }); 31 | 32 | test('testUpdateAndLongMessage', () => { 33 | const sha1Wasm = new cryptoJsWasm.algo.SHA1(); 34 | const sha1 = cryptoJs.algo.SHA1.create(); 35 | let i = 0; 36 | while (i < 100) { 37 | sha1Wasm.update('12345678901234567890123456789012345678901234567890'); 38 | sha1.update('12345678901234567890123456789012345678901234567890'); 39 | i++; 40 | } 41 | expect(sha1Wasm.finalize().toString()).toEqual(sha1.finalize().toString()); 42 | }); -------------------------------------------------------------------------------- /test/crypto-js-test/algo.sha224.test.js: -------------------------------------------------------------------------------- 1 | import cryptoJs from 'crypto-js/crypto-js'; 2 | import cryptoJsWasm from '../../src/index.js'; 3 | 4 | beforeAll(async () => { 5 | await cryptoJsWasm.SHA224.loadWasm(); 6 | }); 7 | 8 | const data1 = ''; 9 | const data2 = 'Test'; 10 | const data3 = 'message digest'; 11 | const data4 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; 12 | 13 | test('testHelper', () => { 14 | const sha224Wasm = new cryptoJsWasm.algo.SHA224(); 15 | const sha224 = cryptoJs.algo.SHA224.create(); 16 | expect(sha224Wasm.finalize(data1).toString()).toEqual(sha224.finalize(data1).toString()); 17 | }); 18 | 19 | test('algo-sha224-test', () => { 20 | expect(cryptoJsWasm.SHA224(data1).toString()).toEqual(cryptoJs.SHA224(data1).toString()); 21 | expect(cryptoJsWasm.SHA224(data2).toString()).toEqual(cryptoJs.SHA224(data2).toString()); 22 | expect(cryptoJsWasm.SHA224(data3).toString()).toEqual(cryptoJs.SHA224(data3).toString()); 23 | expect(cryptoJsWasm.SHA224(data4).toString()).toEqual(cryptoJs.SHA224(data4).toString()); 24 | }); 25 | 26 | test('testClone', () => { 27 | const sha224Wasm = new cryptoJsWasm.algo.SHA224(); 28 | const sha224 = cryptoJs.algo.SHA224.create(); 29 | expect(sha224Wasm.update(data2).clone().finalize().toString()).toEqual(sha224.update(data2).clone().finalize().toString()); 30 | }); 31 | 32 | test('testUpdateAndLongMessage', () => { 33 | const sha224Wasm = new cryptoJsWasm.algo.SHA224(); 34 | const sha224 = cryptoJs.algo.SHA224.create(); 35 | let i = 0; 36 | while (i < 100) { 37 | sha224Wasm.update('12345678901234567890123456789012345678901234567890'); 38 | sha224.update('12345678901234567890123456789012345678901234567890'); 39 | i++; 40 | } 41 | expect(sha224Wasm.finalize().toString()).toEqual(sha224.finalize().toString()); 42 | }); -------------------------------------------------------------------------------- /test/crypto-js-test/algo.sha256.test.js: -------------------------------------------------------------------------------- 1 | import cryptoJs from 'crypto-js/crypto-js'; 2 | import cryptoJsWasm from '../../src/index.js'; 3 | 4 | beforeAll(async () => { 5 | await cryptoJsWasm.SHA256.loadWasm(); 6 | }); 7 | 8 | const data1 = ''; 9 | const data2 = 'Test'; 10 | const data3 = 'message digest'; 11 | const data4 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; 12 | 13 | test('testHelper', () => { 14 | const sha256Wasm = new cryptoJsWasm.algo.SHA256(); 15 | const sha256 = cryptoJs.algo.SHA256.create(); 16 | expect(sha256Wasm.finalize(data1).toString()).toEqual(sha256.finalize(data1).toString()); 17 | }); 18 | 19 | test('algo-sha256-test', () => { 20 | expect(cryptoJsWasm.SHA256(data1).toString()).toEqual(cryptoJs.SHA256(data1).toString()); 21 | expect(cryptoJsWasm.SHA256(data2).toString()).toEqual(cryptoJs.SHA256(data2).toString()); 22 | expect(cryptoJsWasm.SHA256(data3).toString()).toEqual(cryptoJs.SHA256(data3).toString()); 23 | expect(cryptoJsWasm.SHA256(data4).toString()).toEqual(cryptoJs.SHA256(data4).toString()); 24 | }); 25 | 26 | test('testClone', () => { 27 | const sha256Wasm = new cryptoJsWasm.algo.SHA256(); 28 | const sha256 = cryptoJs.algo.SHA256.create(); 29 | expect(sha256Wasm.update(data2).clone().finalize().toString()).toEqual(sha256.update(data2).clone().finalize().toString()); 30 | }); 31 | 32 | test('testUpdateAndLongMessage', () => { 33 | const sha256Wasm = new cryptoJsWasm.algo.SHA256(); 34 | const sha256 = cryptoJs.algo.SHA256.create(); 35 | let i = 0; 36 | while (i < 100) { 37 | sha256Wasm.update('12345678901234567890123456789012345678901234567890'); 38 | sha256.update('12345678901234567890123456789012345678901234567890'); 39 | i++; 40 | } 41 | expect(sha256Wasm.finalize().toString()).toEqual(sha256.finalize().toString()); 42 | }); -------------------------------------------------------------------------------- /test/crypto-js-test/algo.sha3.test.js: -------------------------------------------------------------------------------- 1 | import cryptoJs from 'crypto-js/crypto-js'; 2 | import cryptoJsWasm from '../../src/index.js'; 3 | 4 | beforeAll(async () => { 5 | await cryptoJsWasm.SHA3.loadWasm(); 6 | }); 7 | 8 | const data1 = ''; 9 | const data2 = 'Test'; 10 | const data3 = 'message digest'; 11 | const data4 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; 12 | 13 | test('testHelper', () => { 14 | const sha3Wasm = new cryptoJsWasm.algo.SHA3(); 15 | const sha3 = cryptoJs.algo.SHA3.create(); 16 | expect(sha3Wasm.finalize(data1).toString()).toEqual(sha3.finalize(data1).toString()); 17 | }); 18 | 19 | test('algo-sha3-test', () => { 20 | expect(cryptoJsWasm.SHA3(data1).toString()).toEqual(cryptoJs.SHA3(data1).toString()); 21 | expect(cryptoJsWasm.SHA3(data2).toString()).toEqual(cryptoJs.SHA3(data2).toString()); 22 | expect(cryptoJsWasm.SHA3(data3).toString()).toEqual(cryptoJs.SHA3(data3).toString()); 23 | expect(cryptoJsWasm.SHA3(data4).toString()).toEqual(cryptoJs.SHA3(data4).toString()); 24 | }); 25 | 26 | test('testOutputLength', () => { 27 | expect(cryptoJsWasm.SHA3(data1).toString()).toEqual(cryptoJs.SHA3(data1, { outputLength: 512 }).toString()); 28 | expect(cryptoJsWasm.SHA3(data1, { outputLength: 512 }).toString()).toEqual(cryptoJs.SHA3(data1, { outputLength: 512 }).toString()); 29 | expect(cryptoJsWasm.SHA3(data2, { outputLength: 384 }).toString()).toEqual(cryptoJs.SHA3(data2, { outputLength: 384 }).toString()); 30 | expect(cryptoJsWasm.SHA3(data3, { outputLength: 256 }).toString()).toEqual(cryptoJs.SHA3(data3, { outputLength: 256 }).toString()); 31 | expect(cryptoJsWasm.SHA3(data4, { outputLength: 224 }).toString()).toEqual(cryptoJs.SHA3(data4, { outputLength: 224 }).toString()); 32 | }); 33 | 34 | test('testClone', () => { 35 | const sha3Wasm = new cryptoJsWasm.algo.SHA3(); 36 | const sha3 = cryptoJs.algo.SHA3.create(); 37 | expect(sha3Wasm.update(data2).clone().finalize().toString()).toEqual(sha3.update(data2).clone().finalize().toString()); 38 | }); 39 | 40 | test('testUpdateAndLongMessage', () => { 41 | const sha3Wasm = new cryptoJsWasm.algo.SHA3(); 42 | const sha3 = cryptoJs.algo.SHA3.create(); 43 | let i = 0; 44 | while (i < 100) { 45 | sha3Wasm.update('12345678901234567890123456789012345678901234567890'); 46 | sha3.update('12345678901234567890123456789012345678901234567890'); 47 | i++; 48 | } 49 | expect(sha3Wasm.finalize().toString()).toEqual(sha3.finalize().toString()); 50 | }); -------------------------------------------------------------------------------- /test/crypto-js-test/algo.sha384.test.js: -------------------------------------------------------------------------------- 1 | import cryptoJs from 'crypto-js/crypto-js'; 2 | import cryptoJsWasm from '../../src/index.js'; 3 | 4 | beforeAll(async () => { 5 | await cryptoJsWasm.SHA384.loadWasm(); 6 | }); 7 | 8 | const data1 = ''; 9 | const data2 = 'Test'; 10 | const data3 = 'message digest'; 11 | const data4 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; 12 | 13 | test('testHelper', () => { 14 | const sha384Wasm = new cryptoJsWasm.algo.SHA384(); 15 | const sha384 = cryptoJs.algo.SHA384.create(); 16 | expect(sha384Wasm.finalize(data1).toString()).toEqual(sha384.finalize(data1).toString()); 17 | }); 18 | 19 | test('algo-sha384-test', () => { 20 | expect(cryptoJsWasm.SHA384(data1).toString()).toEqual(cryptoJs.SHA384(data1).toString()); 21 | expect(cryptoJsWasm.SHA384(data2).toString()).toEqual(cryptoJs.SHA384(data2).toString()); 22 | expect(cryptoJsWasm.SHA384(data3).toString()).toEqual(cryptoJs.SHA384(data3).toString()); 23 | expect(cryptoJsWasm.SHA384(data4).toString()).toEqual(cryptoJs.SHA384(data4).toString()); 24 | }); 25 | 26 | test('testClone', () => { 27 | const sha384Wasm = new cryptoJsWasm.algo.SHA384(); 28 | const sha384 = cryptoJs.algo.SHA384.create(); 29 | expect(sha384Wasm.update(data2).clone().finalize().toString()).toEqual(sha384.update(data2).clone().finalize().toString()); 30 | }); 31 | 32 | test('testUpdateAndLongMessage', () => { 33 | const sha384Wasm = new cryptoJsWasm.algo.SHA384(); 34 | const sha384 = cryptoJs.algo.SHA384.create(); 35 | let i = 0; 36 | while (i < 100) { 37 | sha384Wasm.update('12345678901234567890123456789012345678901234567890'); 38 | sha384.update('12345678901234567890123456789012345678901234567890'); 39 | i++; 40 | } 41 | expect(sha384Wasm.finalize().toString()).toEqual(sha384.finalize().toString()); 42 | }); -------------------------------------------------------------------------------- /test/crypto-js-test/algo.sha512.test.js: -------------------------------------------------------------------------------- 1 | import cryptoJs from 'crypto-js/crypto-js'; 2 | import cryptoJsWasm from '../../src/index.js'; 3 | 4 | beforeAll(async () => { 5 | await cryptoJsWasm.SHA512.loadWasm(); 6 | }); 7 | 8 | const data1 = ''; 9 | const data2 = 'Test'; 10 | const data3 = 'message digest'; 11 | const data4 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; 12 | 13 | test('testHelper', () => { 14 | const sha512Wasm = new cryptoJsWasm.algo.SHA512(); 15 | const sha512 = cryptoJs.algo.SHA512.create(); 16 | expect(sha512Wasm.finalize(data1).toString()).toEqual(sha512.finalize(data1).toString()); 17 | }); 18 | 19 | test('algo-sha512-test', () => { 20 | expect(cryptoJsWasm.SHA512(data1).toString()).toEqual(cryptoJs.SHA512(data1).toString()); 21 | expect(cryptoJsWasm.SHA512(data2).toString()).toEqual(cryptoJs.SHA512(data2).toString()); 22 | expect(cryptoJsWasm.SHA512(data3).toString()).toEqual(cryptoJs.SHA512(data3).toString()); 23 | expect(cryptoJsWasm.SHA512(data4).toString()).toEqual(cryptoJs.SHA512(data4).toString()); 24 | }); 25 | 26 | test('testClone', () => { 27 | const sha512Wasm = new cryptoJsWasm.algo.SHA512(); 28 | const sha512 = cryptoJs.algo.SHA512.create(); 29 | expect(sha512Wasm.update(data2).clone().finalize().toString()).toEqual(sha512.update(data2).clone().finalize().toString()); 30 | }); 31 | 32 | test('testUpdateAndLongMessage', () => { 33 | const sha512Wasm = new cryptoJsWasm.algo.SHA512(); 34 | const sha512 = cryptoJs.algo.SHA512.create(); 35 | let i = 0; 36 | while (i < 100) { 37 | sha512Wasm.update('12345678901234567890123456789012345678901234567890'); 38 | sha512.update('12345678901234567890123456789012345678901234567890'); 39 | i++; 40 | } 41 | expect(sha512Wasm.finalize().toString()).toEqual(sha512.finalize().toString()); 42 | }); -------------------------------------------------------------------------------- /test/des.profile.test.js: -------------------------------------------------------------------------------- 1 | import C from '../src/index'; 2 | 3 | let data = {}; 4 | beforeAll(async () => { 5 | data.key = C.enc.Hex.parse('0001020304050607'); 6 | data.iv = C.enc.Hex.parse('08090a0b0c0d0e0f'); 7 | await C.DES.loadWasm(); 8 | }); 9 | 10 | describe('algo-des-profile', () => { 11 | test('profileSinglePartMessage', () => { 12 | let singlePartMessage = ''; 13 | for (let i = 0; i < 100; i++) { 14 | singlePartMessage += '12345678901234567890123456789012345678901234567890'; 15 | } 16 | C.algo.DES.createEncryptor(data.key, { 17 | iv: data.iv 18 | }).finalize(singlePartMessage) + ''; 19 | }); 20 | 21 | test('profileMultiPartMessage', () => { 22 | let des = C.algo.DES.createEncryptor(data.key, { 23 | iv: data.iv 24 | }); 25 | for (let i = 0; i < 100; i++) { 26 | des.process('12345678901234567890123456789012345678901234567890') + ''; 27 | } 28 | des.finalize() + ''; 29 | }); 30 | }); 31 | -------------------------------------------------------------------------------- /test/enc.base64.test.js: -------------------------------------------------------------------------------- 1 | import C from '../src/index'; 2 | 3 | const STRINGFY_TEST_CONFIG = [ 4 | [0, 0, ''], 5 | [1, 1, 'Zg=='], 6 | [2, 2, 'Zm8='], 7 | [3, 3, 'Zm9v'], 8 | [4, 4, 'Zm9vYg=='], 9 | [5, 5, 'Zm9vYmE='], 10 | [6, 6, 'Zm9vYmFy'] 11 | ]; 12 | 13 | const PARSE_TEST_CONFIG = [ 14 | [0, '', 0], 15 | [1, 'Zg==', 1], 16 | [2, 'Zm8=', 2], 17 | [3, 'Zm9v', 3], 18 | [4, 'Zm9vYg==', 4], 19 | [5, 'Zm9vYmE=', 5], 20 | [6, 'Zm9vYmFy', 6] 21 | ]; 22 | 23 | describe('enc-base64-test', () => { 24 | test.each(STRINGFY_TEST_CONFIG)( 25 | 'testStringfy%i', 26 | (a, b, expected) => { 27 | expect(C.enc.Base64.stringify(new C.lib.WordArray([0x666f6f62, 0x61720000], b))).toBe(expected); 28 | } 29 | ); 30 | 31 | test('testStringify15', () => { 32 | expect(C.enc.Base64.stringify(new C.lib.WordArray([0x3e3e3e3f, 0x3f3f3e3e, 0x3e3f3f3f, 0x3d2f2b00], 15))).toBe('Pj4+Pz8/Pj4+Pz8/PS8r'); 33 | }); 34 | 35 | test.each(PARSE_TEST_CONFIG)( 36 | 'testParse%i', 37 | (a, b, expected) => { 38 | expect(C.enc.Base64.parse(b).toString()).toBe(new C.lib.WordArray([0x666f6f62, 0x61720000], expected).toString()); 39 | } 40 | ); 41 | 42 | test('testParse15', () => { 43 | expect(C.enc.Base64.parse('Pj4+Pz8/Pj4+Pz8/PS8r').toString()).toBe(new C.lib.WordArray([0x3e3e3e3f, 0x3f3f3e3e, 0x3e3f3f3f, 0x3d2f2b00], 15).toString()); 44 | }); 45 | }); -------------------------------------------------------------------------------- /test/enc.hex.test.js: -------------------------------------------------------------------------------- 1 | import C from '../src/index'; 2 | 3 | describe('enc-hex-test', () => { 4 | test('testStringify', () => { 5 | expect(C.enc.Hex.stringify(new C.lib.WordArray([0x12345678]))).toBe('12345678'); 6 | }); 7 | 8 | test('testParse', () => { 9 | expect(C.enc.Hex.parse('12345678').toString()).toBe(new C.lib.WordArray([0x12345678]).toString()); 10 | }); 11 | }); -------------------------------------------------------------------------------- /test/enc.latain1.test.js: -------------------------------------------------------------------------------- 1 | import C from '../src/index'; 2 | 3 | describe('enc-latin1-test', () => { 4 | test('testStringify', () => { 5 | expect( C.enc.Latin1.stringify(new C.lib.WordArray([0x12345678]))).toBe('\x12\x34\x56\x78'); 6 | }); 7 | 8 | test('testParse', () => { 9 | expect(C.enc.Latin1.parse('\x12\x34\x56\x78').toString()).toBe(new C.lib.WordArray([0x12345678]).toString()); 10 | }); 11 | }); -------------------------------------------------------------------------------- /test/enc.utf16.test.js: -------------------------------------------------------------------------------- 1 | import C from '../src/index'; 2 | 3 | const STRINGFY_TEST_CONFIG = [ 4 | [1, 0x007a0000, 2, 'z'], 5 | [2, 0x6c340000, 2, '水'], 6 | [3, 0xd800dc00, 4, '𐀀'], 7 | [4, 0xd834dd1e, 4, '𝄞'], 8 | [5, 0xdbffdffd, 4, '􏿽'] 9 | ]; 10 | 11 | const PARSE_TEST_CONFIG = [ 12 | [1, 'z', 0x007a0000, 2], 13 | [2, '水', 0x6c340000, 2], 14 | [3, '𐀀', 0xd800dc00, 4], 15 | [4, '𝄞', 0xd834dd1e, 4], 16 | [5, '􏿽', 0xdbffdffd, 4] 17 | ]; 18 | 19 | describe('enc-utf16-test', () => { 20 | test.each(STRINGFY_TEST_CONFIG)( 21 | 'testString%i', 22 | (a, b, c, expected) => { 23 | expect(C.enc.Utf16.stringify(new C.lib.WordArray([b], c))).toBe(expected); 24 | } 25 | ); 26 | 27 | test('testStringifyLE', () => { 28 | expect(C.enc.Utf16LE.stringify(new C.lib.WordArray([0xffdbfddf], 4))).toBe('􏿽'); 29 | }); 30 | 31 | test.each(PARSE_TEST_CONFIG)( 32 | 'testParse%i', 33 | (a, expected, b, c) => { 34 | expect(C.enc.Utf16.parse(expected).toString()).toBe(new C.lib.WordArray([b], c).toString()); 35 | } 36 | ); 37 | 38 | test('testParseLE', () => { 39 | expect(C.enc.Utf16LE.parse('􏿽').toString()).toBe(new C.lib.WordArray([0xffdbfddf], 4).toString()); 40 | }); 41 | }); 42 | -------------------------------------------------------------------------------- /test/enc.utf8.test.js: -------------------------------------------------------------------------------- 1 | import C from '../src/index'; 2 | 3 | const STRINGFY_TEST_CONFIG = [ 4 | [1, 1, 0x24000000, '$'], 5 | [2, 2, 0xc2a20000, '¢'], 6 | [3, 3, 0xe282ac00, '€'], 7 | [4, 4, 0xf0a4ada2, '𤭢'] 8 | ]; 9 | 10 | const PARSE_TEST_CONFIG = [ 11 | [1, '$', 0x24000000, 1], 12 | [2, '¢', 0xc2a20000, 2], 13 | [3, '€', 0xe282ac00, 3], 14 | [4, '𤭢', 0xf0a4ada2, 4] 15 | ]; 16 | 17 | describe('enc-utf8-tes', () => { 18 | test.each(STRINGFY_TEST_CONFIG)( 19 | 'testStringfy%i', 20 | (a, b, c, expected) => { 21 | expect(C.enc.Utf8.stringify(new C.lib.WordArray([c], b))).toBe(expected); 22 | } 23 | ); 24 | 25 | test.each(PARSE_TEST_CONFIG)( 26 | 'testParse%i', 27 | (a, b, c, expected) => { 28 | expect(C.enc.Utf8.parse(b).toString()).toBe(new C.lib.WordArray([c], expected).toString()); 29 | } 30 | ); 31 | }); -------------------------------------------------------------------------------- /test/evpkdf.profile.test.js: -------------------------------------------------------------------------------- 1 | import C from '../src/index'; 2 | 3 | beforeAll(async () => { 4 | // the default hasher for EvpKDF is md5 5 | await C.algo.EvpKDF.loadWasm(); 6 | }); 7 | 8 | describe('algo-evpkdf-profile', () => { 9 | test('profileKeySize256Iterations20', () => { 10 | new C.algo.EvpKDF({ keySize: 256/32, iterations: 20 }).compute('password', 'ATHENA.MIT.EDUraeburn'); 11 | }); 12 | }); 13 | -------------------------------------------------------------------------------- /test/evpkdf.test.js: -------------------------------------------------------------------------------- 1 | import C from '../src/index'; 2 | 3 | beforeAll(async () => { 4 | // the default hasher for EvpKDF is md5 5 | await C.EvpKDF.loadWasm(); 6 | }); 7 | 8 | describe('algo-evpkdf-test', () => { 9 | test('testVector', () => { 10 | expect(C.EvpKDF('password', 'saltsalt', { keySize: (256+128)/32 }).toString()).toBe('fdbdf3419fff98bdb0241390f62a9db35f4aba29d77566377997314ebfc709f20b5ca7b1081f94b1ac12e3c8ba87d05a'); 11 | }); 12 | 13 | // There are no official test vectors that I could find, and the EVP implementation is short on comments. 14 | // Need to use the C code to generate more test vectors. 15 | // The iteration count in particular needs to be tested. 16 | test('testInputIntegrity', () => { 17 | let password = new C.lib.WordArray([0x12345678]); 18 | let salt = new C.lib.WordArray([0x12345678]); 19 | 20 | let expectedPassword = password.toString(); 21 | let expectedSalt = salt.toString(); 22 | 23 | C.EvpKDF(password, salt); 24 | 25 | expect(password.toString()).toBe(expectedPassword); 26 | expect(salt.toString()).toBe(expectedSalt); 27 | }); 28 | 29 | test('testHelper', () => { 30 | expect(C.EvpKDF('password', 'saltsalt', { keySize: (256+128)/32 }).toString()).toBe(new C.algo.EvpKDF({ keySize: (256+128)/32 }).compute('password', 'saltsalt').toString()); 31 | }); 32 | }); 33 | -------------------------------------------------------------------------------- /test/format.openssl.test.js: -------------------------------------------------------------------------------- 1 | import C from '../src/index'; 2 | 3 | const data = {}; 4 | beforeAll(() => { 5 | data.ciphertext = new C.lib.WordArray([0x00010203, 0x04050607, 0x08090a0b, 0x0c0d0e0f]); 6 | data.salt = new C.lib.WordArray([0x01234567, 0x89abcdef]); 7 | }); 8 | 9 | describe('format-openssl-test', () => { 10 | test('testSaltedToString', () => { 11 | expect(C.format.OpenSSL.stringify(new C.lib.CipherParams({ 12 | ciphertext: data.ciphertext, 13 | salt: data.salt 14 | }))).toBe(C.enc.Latin1.parse('Salted__').concat(data.salt).concat(data.ciphertext).toString(C.enc.Base64)); 15 | }); 16 | 17 | test('testUnsaltedToString', () => { 18 | expect(C.format.OpenSSL.stringify(new C.lib.CipherParams({ 19 | ciphertext: data.ciphertext 20 | }))).toBe(data.ciphertext.toString(C.enc.Base64)); 21 | }); 22 | 23 | test('testSaltedFromString', () => { 24 | let openSSLStr = C.format.OpenSSL.stringify(new C.lib.CipherParams({ 25 | ciphertext: data.ciphertext, 26 | salt: data.salt 27 | })); 28 | let cipherParams = C.format.OpenSSL.parse(openSSLStr); 29 | expect(cipherParams.ciphertext.toString()).toBe(data.ciphertext.toString()); 30 | expect(cipherParams.salt.toString()).toBe(data.salt.toString()); 31 | }); 32 | 33 | test('testUnsaltedFromString', () => { 34 | let openSSLStr = C.format.OpenSSL.stringify(new C.lib.CipherParams({ 35 | ciphertext: data.ciphertext 36 | })); 37 | let cipherParams = C.format.OpenSSL.parse(openSSLStr); 38 | expect(cipherParams.ciphertext.toString()).toBe(data.ciphertext.toString()); 39 | }); 40 | }); -------------------------------------------------------------------------------- /test/hmac.md5.profile.test.js: -------------------------------------------------------------------------------- 1 | import C from '../src/index'; 2 | 3 | let data = {}; 4 | beforeAll(() => { 5 | data.key = C.lib.WordArray.random(128/8); 6 | }); 7 | 8 | beforeAll(async () => { 9 | await C.MD5.loadWasm(); 10 | }); 11 | 12 | describe('algo-hmac-md5-profile', () => { 13 | test('profileSinglePartMessage', () => { 14 | let singlePartMessage = ''; 15 | for (let i = 0; i < 500; i++) { 16 | singlePartMessage += '12345678901234567890123456789012345678901234567890'; 17 | } 18 | new C.algo.HMAC(C.algo.MD5, data.key).finalize(singlePartMessage) + ''; 19 | }); 20 | 21 | test('profileMultiPartMessage', () => { 22 | let hmac = new C.algo.HMAC(C.algo.MD5, data.key); 23 | for (let i = 0; i < 500; i++) { 24 | hmac.update('12345678901234567890123456789012345678901234567890'); 25 | } 26 | hmac.finalize() + ''; 27 | }); 28 | }); 29 | -------------------------------------------------------------------------------- /test/hmac.md5.test.js: -------------------------------------------------------------------------------- 1 | import C from '../src/index'; 2 | 3 | beforeAll(async () => { 4 | await C.HmacMD5.loadWasm(); 5 | }); 6 | 7 | describe('algo-hmac-md5-test', () => { 8 | test('testVector1', () => { 9 | expect(C.HmacMD5('Hi There', C.enc.Hex.parse('0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b')).toString()).toBe('9294727a3638bb1c13f48ef8158bfc9d'); 10 | }); 11 | 12 | test('testVector2', () => { 13 | expect(C.HmacMD5('what do ya want for nothing?', 'Jefe').toString()).toBe('750c783e6ab0b503eaa86e310a5db738'); 14 | }); 15 | 16 | test('testVector3', () => { 17 | expect(C.HmacMD5(C.enc.Hex.parse('dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd'), C.enc.Hex.parse('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa')).toString()).toBe('56be34521d144c88dbb8c733f0e8b3f6'); 18 | }); 19 | 20 | test('testVector4', () => { 21 | expect(C.HmacMD5('ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'A').toString()).toBe('7ee2a3cc979ab19865704644ce13355c'); 22 | }); 23 | 24 | test('testVector5', () => { 25 | expect(C.HmacMD5('abcdefghijklmnopqrstuvwxyz', 'A').toString()).toBe('0e1bd89c43e3e6e3b3f8cf1d5ba4f77a'); 26 | }); 27 | 28 | test('testUpdate', () => { 29 | let hmac = new C.algo.HMAC(C.algo.MD5, C.enc.Hex.parse('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa')); 30 | hmac.update(C.enc.Hex.parse('dddddddddddddddddddddddddddddddddddd')); 31 | hmac.update(C.enc.Hex.parse('dddddddddddddddddddddddddddddddd')); 32 | hmac.update(C.enc.Hex.parse('dddddddddddddddddddddddddddddddd')); 33 | expect(hmac.finalize().toString()).toBe(C.HmacMD5(C.enc.Hex.parse('dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd'), C.enc.Hex.parse('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa')).toString()); 34 | }); 35 | 36 | test('testInputIntegrity', () => { 37 | let message = new C.lib.WordArray([0x12345678]); 38 | let key = new C.lib.WordArray([0x12345678]); 39 | 40 | let expectedMessage = message.toString(); 41 | let expectedKey = key.toString(); 42 | 43 | C.HmacMD5(message, key); 44 | expect(message.toString()).toBe(expectedMessage); 45 | expect(key.toString()).toBe(expectedKey); 46 | }); 47 | 48 | test('testRespectKeySigBytes', () => { 49 | let key = C.lib.WordArray.random(8); 50 | key.sigBytes = 4; 51 | 52 | let keyClamped = key.clone(); 53 | keyClamped.clamp(); 54 | 55 | expect(C.HmacMD5('Message', key).toString()).toBe(C.HmacMD5('Message', keyClamped).toString()); 56 | }); 57 | }); 58 | -------------------------------------------------------------------------------- /test/hmac.sha224.test.js: -------------------------------------------------------------------------------- 1 | import C from '../src/index'; 2 | 3 | beforeAll(async () => { 4 | await C.HmacSHA224.loadWasm(); 5 | }); 6 | 7 | describe('algo-hmac-sha224-test', () => { 8 | test('testVector1', () => { 9 | expect(C.HmacSHA224('Hi There', C.enc.Hex.parse('0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b')).toString()).toBe('4e841ce7a4ae83fbcf71e3cd64bfbf277f73a14680aae8c518ac7861'); 10 | }); 11 | 12 | test('testVector2', () => { 13 | expect(C.HmacSHA224('what do ya want for nothing?', 'Jefe').toString()).toBe('a30e01098bc6dbbf45690f3a7e9e6d0f8bbea2a39e6148008fd05e44'); 14 | }); 15 | 16 | test('testVector3', () => { 17 | expect(C.HmacSHA224(C.enc.Hex.parse('dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd'), C.enc.Hex.parse('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa')).toString()).toBe('cbff7c2716bbaa7c77bed4f491d3e8456cb6c574e92f672b291acf5b'); 18 | }); 19 | 20 | test('testVector4', () => { 21 | expect(C.HmacSHA224('ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'A').toString()).toBe('61bf669da4fdcd8e5c3bd09ebbb4a986d3d1b298d3ca05c511f7aeff'); 22 | }); 23 | 24 | test('testVector5', () => { 25 | expect(C.HmacSHA224('abcdefghijklmnopqrstuvwxyz', 'A').toString()).toBe('16fc69ada3c3edc1fe9144d6b98d93393833ae442bedf681110a1176'); 26 | }); 27 | 28 | test('testUpdate', () => { 29 | let hmac = new C.algo.HMAC(C.algo.SHA224, C.enc.Hex.parse('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa')); 30 | hmac.update(C.enc.Hex.parse('dddddddddddddddddddddddddddddddddddd')); 31 | hmac.update(C.enc.Hex.parse('dddddddddddddddddddddddddddddddd')); 32 | hmac.update(C.enc.Hex.parse('dddddddddddddddddddddddddddddddd')); 33 | expect(hmac.finalize().toString()).toBe(C.HmacSHA224(C.enc.Hex.parse('dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd'), C.enc.Hex.parse('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa')).toString()); 34 | }); 35 | 36 | test('testInputIntegrity', () => { 37 | let message = new C.lib.WordArray([0x12345678]); 38 | let key = new C.lib.WordArray([0x12345678]); 39 | 40 | let expectedMessage = message.toString(); 41 | let expectedKey = key.toString(); 42 | 43 | C.HmacSHA224(message, key); 44 | 45 | expect(message.toString()).toBe(expectedMessage); 46 | expect(key.toString()).toBe(expectedKey); 47 | }); 48 | 49 | test('testRespectKeySigBytes', () => { 50 | let key = C.lib.WordArray.random(8); 51 | key.sigBytes = 4; 52 | 53 | let keyClamped = key.clone(); 54 | keyClamped.clamp(); 55 | 56 | expect(C.HmacSHA224('Message', key).toString()).toBe(C.HmacSHA224('Message', keyClamped).toString()); 57 | }); 58 | }); 59 | -------------------------------------------------------------------------------- /test/hmac.sha256.test.js: -------------------------------------------------------------------------------- 1 | import C from '../src/index'; 2 | 3 | beforeAll(async () => { 4 | await C.HmacSHA256.loadWasm(); 5 | }); 6 | 7 | describe('algo-hmac-sha256-test', () => { 8 | test('testVector1', () => { 9 | expect(C.HmacSHA256('Hi There', C.enc.Hex.parse('0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b')).toString()).toBe('492ce020fe2534a5789dc3848806c78f4f6711397f08e7e7a12ca5a4483c8aa6'); 10 | }); 11 | 12 | test('testVector2', () => { 13 | expect(C.HmacSHA256('what do ya want for nothing?', 'Jefe').toString()).toBe('5bdcc146bf60754e6a042426089575c75a003f089d2739839dec58b964ec3843'); 14 | }); 15 | 16 | test('testVector3', () => { 17 | expect(C.HmacSHA256(C.enc.Hex.parse('dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd'), C.enc.Hex.parse('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa')).toString()).toBe('7dda3cc169743a6484649f94f0eda0f9f2ff496a9733fb796ed5adb40a44c3c1'); 18 | }); 19 | 20 | test('testVector4', () => { 21 | expect(C.HmacSHA256('ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'A').toString()).toBe('a89dc8178c1184a62df87adaa77bf86e93064863d93c5131140b0ae98b866687'); 22 | }); 23 | 24 | test('testVector5', () => { 25 | expect(C.HmacSHA256('abcdefghijklmnopqrstuvwxyz', 'A').toString()).toBe('d8cb78419c02fe20b90f8b77427dd9f81817a751d74c2e484e0ac5fc4e6ca986'); 26 | }); 27 | 28 | test('testUpdate', () => { 29 | let hmac = new C.algo.HMAC(C.algo.SHA256, C.enc.Hex.parse('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa')); 30 | hmac.update(C.enc.Hex.parse('dddddddddddddddddddddddddddddddddddd')); 31 | hmac.update(C.enc.Hex.parse('dddddddddddddddddddddddddddddddd')); 32 | hmac.update(C.enc.Hex.parse('dddddddddddddddddddddddddddddddd')); 33 | 34 | expect(hmac.finalize().toString()).toBe(C.HmacSHA256(C.enc.Hex.parse('dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd'), C.enc.Hex.parse('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa')).toString()); 35 | }); 36 | 37 | test('testInputIntegrity', () => { 38 | let message = new C.lib.WordArray([0x12345678]); 39 | let key = new C.lib.WordArray([0x12345678]); 40 | 41 | let expectedMessage = message.toString(); 42 | let expectedKey = key.toString(); 43 | 44 | C.HmacSHA256(message, key); 45 | 46 | expect(message.toString()).toBe(expectedMessage); 47 | expect(key.toString()).toBe(expectedKey); 48 | }); 49 | 50 | test('testRespectKeySigBytes', () => { 51 | let key = C.lib.WordArray.random(8); 52 | key.sigBytes = 4; 53 | let keyClamped = key.clone(); 54 | keyClamped.clamp(); 55 | expect(C.HmacSHA256('Message', key).toString()).toBe(C.HmacSHA256('Message', keyClamped).toString()); 56 | }); 57 | }); 58 | -------------------------------------------------------------------------------- /test/hmac.sha384.test.js: -------------------------------------------------------------------------------- 1 | import C from '../src/index'; 2 | 3 | beforeAll(async () => { 4 | await C.HmacSHA384.loadWasm(); 5 | }); 6 | 7 | describe('algo-hmac-sha384-test', () => { 8 | test('testVector1', () => { 9 | expect(C.HmacSHA384('Hi There', C.enc.Hex.parse('0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b')).toString()).toBe('7afaa633e20d379b02395915fbc385ff8dc27dcd3885e1068ab942eeab52ec1f20ad382a92370d8b2e0ac8b83c4d53bf'); 10 | }); 11 | test('testVector2', () => { 12 | expect(C.HmacSHA384('what do ya want for nothing?', 'Jefe').toString()).toBe('af45d2e376484031617f78d2b58a6b1b9c7ef464f5a01b47e42ec3736322445e8e2240ca5e69e2c78b3239ecfab21649'); 13 | }); 14 | test('testVector3', () => { 15 | expect(C.HmacSHA384(C.enc.Hex.parse('dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd'), C.enc.Hex.parse('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa')).toString()).toBe('1383e82e28286b91f4cc7afbd13d5b5c6f887c05e7c4542484043a37a5fe45802a9470fb663bd7b6570fe2f503fc92f5'); 16 | }); 17 | test('testVector4', () => { 18 | expect(C.HmacSHA384('ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'A').toString()).toBe('365dfb271adb8e30fe6c74220b75df1b38c2d19b9d37f2e5a0ec2f3f22bd0406bf5b786e98d81b82c36d3d8a1be6cd07'); 19 | }); 20 | test('testVector5', () => { 21 | expect(C.HmacSHA384('abcdefghijklmnopqrstuvwxyz', 'A').toString()).toBe('a8357d5e84da64140e41545562ae0782e2a58e39c6cd98939fad8d9080e774c84b7eaca4ba07f6dbf0f12eab912c5285'); 22 | }); 23 | 24 | test('testUpdate', () => { 25 | let hmac = new C.algo.HMAC(C.algo.SHA384, C.enc.Hex.parse('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa')); 26 | hmac.update(C.enc.Hex.parse('dddddddddddddddddddddddddddddddddddd')); 27 | hmac.update(C.enc.Hex.parse('dddddddddddddddddddddddddddddddd')); 28 | hmac.update(C.enc.Hex.parse('dddddddddddddddddddddddddddddddd')); 29 | expect(hmac.finalize().toString()).toBe(C.HmacSHA384(C.enc.Hex.parse('dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd'), C.enc.Hex.parse('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa')).toString()); 30 | }); 31 | 32 | test('testInputIntegrity', () => { 33 | let message = new C.lib.WordArray([0x12345678]); 34 | let key = new C.lib.WordArray([0x12345678]); 35 | 36 | let expectedMessage = message.toString(); 37 | let expectedKey = key.toString(); 38 | 39 | C.HmacSHA384(message, key); 40 | expect(message.toString()).toBe(expectedMessage); 41 | expect(key.toString()).toBe(expectedKey); 42 | }); 43 | 44 | test('testRespectKeySigBytes', () => { 45 | let key = C.lib.WordArray.random(8); 46 | key.sigBytes = 4; 47 | 48 | let keyClamped = key.clone(); 49 | keyClamped.clamp(); 50 | expect(C.HmacSHA384('Message', key).toString()).toBe(C.HmacSHA384('Message', keyClamped).toString()); 51 | }); 52 | }); 53 | -------------------------------------------------------------------------------- /test/hmac.sha512.test.js: -------------------------------------------------------------------------------- 1 | import C from '../src/index'; 2 | 3 | beforeAll(async () => { 4 | await C.HmacSHA512.loadWasm(); 5 | }); 6 | 7 | describe('algo-hmac-sha512-test', () => { 8 | test('testVector1', () => { 9 | expect(C.HmacSHA512('Hi There', C.enc.Hex.parse('0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b')).toString()).toBe('7641c48a3b4aa8f887c07b3e83f96affb89c978fed8c96fcbbf4ad596eebfe496f9f16da6cd080ba393c6f365ad72b50d15c71bfb1d6b81f66a911786c6ce932'); 10 | }); 11 | test('testVector2', () => { 12 | expect(C.HmacSHA512('what do ya want for nothing?', 'Jefe').toString()).toBe('164b7a7bfcf819e2e395fbe73b56e0a387bd64222e831fd610270cd7ea2505549758bf75c05a994a6d034f65f8f0e6fdcaeab1a34d4a6b4b636e070a38bce737'); 13 | }); 14 | test('testVector3', () => { 15 | expect(C.HmacSHA512(C.enc.Hex.parse('dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd'), C.enc.Hex.parse('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa')).toString()).toBe('ad9b5c7de72693737cd5e9d9f41170d18841fec1201c1c1b02e05cae116718009f771cad9946ddbf7e3cde3e818d9ae85d91b2badae94172d096a44a79c91e86'); 16 | }); 17 | test('testVector4', () => { 18 | expect(C.HmacSHA512('ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'A').toString()).toBe('a303979f7c94bb39a8ab6ce05cdbe28f0255da8bb305263e3478ef7e855f0242729bf1d2be55398f14da8e63f0302465a8a3f76c297bd584ad028d18ed7f0195'); 19 | }); 20 | test('testVector5', () => { 21 | expect(C.HmacSHA512('abcdefghijklmnopqrstuvwxyz', 'A').toString()).toBe('8c2d56f7628325e62124c0a870ad98d101327fc42696899a06ce0d7121454022fae597e42c25ac3a4c380fd514f553702a5b0afaa9b5a22050902f024368e9d9'); 22 | }); 23 | 24 | test('testUpdate', () => { 25 | let hmac = new C.algo.HMAC(C.algo.SHA512, C.enc.Hex.parse('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa')); 26 | hmac.update(C.enc.Hex.parse('dddddddddddddddddddddddddddddddddddd')); 27 | hmac.update(C.enc.Hex.parse('dddddddddddddddddddddddddddddddd')); 28 | hmac.update(C.enc.Hex.parse('dddddddddddddddddddddddddddddddd')); 29 | expect(hmac.finalize().toString()).toBe(C.HmacSHA512(C.enc.Hex.parse('dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd'), C.enc.Hex.parse('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa')).toString()); 30 | }); 31 | 32 | test('testInputIntegrity', () => { 33 | let message = new C.lib.WordArray([0x12345678]); 34 | let key = new C.lib.WordArray([0x12345678]); 35 | 36 | let expectedMessage = message.toString(); 37 | let expectedKey = key.toString(); 38 | 39 | C.HmacSHA512(message, key); 40 | expect(message.toString()).toBe(expectedMessage); 41 | expect(key.toString()).toBe(expectedKey); 42 | }); 43 | 44 | test('testRespectKeySigBytes', () => { 45 | let key = C.lib.WordArray.random(8); 46 | key.sigBytes = 4; 47 | 48 | let keyClamped = key.clone(); 49 | keyClamped.clamp(); 50 | expect(C.HmacSHA512('Message', key).toString()).toBe(C.HmacSHA512('Message', keyClamped).toString()); 51 | }); 52 | }); 53 | -------------------------------------------------------------------------------- /test/kdf.openssl.test.js: -------------------------------------------------------------------------------- 1 | import C from '../src/index'; 2 | 3 | beforeAll(async () => { 4 | // the default hasher for kdf.OpenSSL is md5 5 | await C.kdf.OpenSSL.loadWasm(); 6 | }); 7 | 8 | describe('kdf-openssl-test', () => { 9 | test('testVector', () => { 10 | let derivedParams = C.kdf.OpenSSL.execute('password', 256 / 32, 128 / 32, C.enc.Hex.parse('0a9d8620cf7219f1')); 11 | expect(derivedParams.key.toString()).toBe('50f32e0ec9408e02ff42364a52aac95c3694fc027256c6f488bf84b8e60effcd'); 12 | expect(derivedParams.iv.toString()).toBe('81381e39b94fd692dff7e2239a298cb6'); 13 | expect(derivedParams.salt.toString()).toBe('0a9d8620cf7219f1'); 14 | }); 15 | }); 16 | -------------------------------------------------------------------------------- /test/lib.base.test.js: -------------------------------------------------------------------------------- 1 | import C from '../src/index'; 2 | 3 | let data = {}; 4 | beforeAll(() => { 5 | data.mixins = { 6 | mixinMethod: function () {} 7 | }; 8 | data.Obj = class Obj extends C.lib.Base { 9 | constructor(arg) { 10 | super(); 11 | this.initFired = true; 12 | this.initArg = arg; 13 | } 14 | toString() { 15 | return 'ObjToString'; 16 | } 17 | }; 18 | data.obj = new data.Obj('argValue'); 19 | data.obj.mixIn(data.mixins); 20 | data.objClone = data.obj.clone(); 21 | }); 22 | 23 | describe('lib-base-test', () => { 24 | test('testClassInheritance', () => { 25 | expect(data.Obj.__proto__).toBe(C.lib.Base); 26 | }); 27 | 28 | test('testObjectInheritance', () => { 29 | expect(data.obj.__proto__.__proto__).toBe(C.lib.Base.prototype); 30 | }); 31 | 32 | test('testToString', () => { 33 | expect(data.obj.toString()).toBe('ObjToString'); 34 | }); 35 | 36 | test('testConstructor', () => { 37 | expect(data.obj.initFired).toBeTruthy(); 38 | expect(data.obj.initArg).toBe('argValue'); 39 | }); 40 | 41 | test('testMixIn', () => { 42 | expect(data.obj.mixinMethod).toBe(data.mixins.mixinMethod); 43 | }); 44 | 45 | test('testCloneDistinct', () => { 46 | expect(data.objClone).not.toBe(data.obj); 47 | }); 48 | 49 | test('testCloneCopy', () => { 50 | expect(data.objClone.initArg).toBe(data.obj.initArg); 51 | }); 52 | 53 | test('testCloneIndependent', () => { 54 | data.obj.initArg = 'newValue'; 55 | expect(data.objClone.initArg).not.toBe(data.obj.initArg); 56 | }); 57 | }); -------------------------------------------------------------------------------- /test/lib.cipherparams.test.js: -------------------------------------------------------------------------------- 1 | import C from '../src/index'; 2 | 3 | const data = {}; 4 | beforeAll(() => { 5 | data.ciphertext = C.enc.Hex.parse('000102030405060708090a0b0c0d0e0f'); 6 | data.key = C.enc.Hex.parse('101112131415161718191a1b1c1d1e1f'); 7 | data.iv = C.enc.Hex.parse('202122232425262728292a2b2c2d2e2f'); 8 | data.salt = C.enc.Hex.parse('0123456789abcdef'); 9 | data.algorithm = C.algo.AES; 10 | data.mode = C.mode.CBC; 11 | data.padding = C.pad.PKCS7; 12 | data.blockSize = data.algorithm.blockSize; 13 | data.formatter = C.format.OpenSSL; 14 | data.cipherParams = new C.lib.CipherParams({ 15 | ciphertext: data.ciphertext, 16 | key: data.key, 17 | iv: data.iv, 18 | salt: data.salt, 19 | algorithm: data.algorithm, 20 | mode: data.mode, 21 | padding: data.padding, 22 | blockSize: data.blockSize, 23 | formatter: data.formatter 24 | }); 25 | }); 26 | 27 | describe('lib-cipherparams-test', () => { 28 | test('testInit', () => { 29 | expect(data.cipherParams.ciphertext).toBe(data.ciphertext); 30 | expect(data.cipherParams.key).toBe(data.key); 31 | expect(data.cipherParams.iv).toBe(data.iv); 32 | expect(data.cipherParams.salt).toBe(data.salt); 33 | expect(data.cipherParams.algorithm).toBe(data.algorithm); 34 | expect(data.cipherParams.mode).toBe(data.mode); 35 | expect(data.cipherParams.padding).toBe(data.padding); 36 | expect(data.cipherParams.blockSize).toBe(data.blockSize); 37 | expect(data.cipherParams.formatter).toBe(data.formatter); 38 | }); 39 | 40 | test('testToString0', () => { 41 | expect(data.cipherParams.toString()).toBe(C.format.OpenSSL.stringify(data.cipherParams)); 42 | }); 43 | 44 | test('testToString1', () => { 45 | const JsonFormatter = { 46 | stringify: function (cipherParams) { 47 | return '{ ct: ' + cipherParams.ciphertext + ', iv: ' + cipherParams.iv + ' }'; 48 | } 49 | }; 50 | expect(data.cipherParams.toString(JsonFormatter)).toBe(JsonFormatter.stringify(data.cipherParams)); 51 | }); 52 | }); -------------------------------------------------------------------------------- /test/lib.passwordbasedcipher.test.js: -------------------------------------------------------------------------------- 1 | import C from '../src/index'; 2 | 3 | beforeAll(async () => { 4 | await C.AES.loadWasm(); 5 | await C.lib.PasswordBasedCipher.loadWasm(); 6 | }); 7 | 8 | describe('lib-passwordbasedcipher-test', () => { 9 | test('testEncrypt', () => { 10 | // Compute actual 11 | let actual = C.lib.PasswordBasedCipher.encrypt(C.algo.AES, 'Hello, World!', 'password'); 12 | 13 | // Compute expected 14 | let aes = C.algo.AES.createEncryptor(actual.key, { 15 | iv: actual.iv 16 | }); 17 | let expected = aes.finalize('Hello, World!'); 18 | expect(actual.ciphertext.toString()).toBe(expected.toString()); 19 | }); 20 | 21 | test('testDecrypt', () => { 22 | let ciphertext = C.lib.PasswordBasedCipher.encrypt(C.algo.AES, 'Hello, World!', 'password'); 23 | let plaintext = C.lib.PasswordBasedCipher.decrypt(C.algo.AES, ciphertext, 'password'); 24 | expect(plaintext.toString(C.enc.Utf8)).toBe('Hello, World!'); 25 | }); 26 | }); 27 | -------------------------------------------------------------------------------- /test/lib.serializablecipher.test.js: -------------------------------------------------------------------------------- 1 | import C from '../src/index'; 2 | 3 | let data = {}; 4 | 5 | beforeAll(async () => { 6 | data.message = new C.lib.WordArray([0x00010203, 0x04050607, 0x08090a0b, 0x0c0d0e0f]); 7 | data.key = new C.lib.WordArray([0x10111213, 0x14151617, 0x18191a1b, 0x1c1d1e1f]); 8 | data.iv = new C.lib.WordArray([0x20212223, 0x24252627, 0x28292a2b, 0x2c2d2e2f]); 9 | await C.AES.loadWasm(); 10 | }); 11 | 12 | describe('lib-serializablecipher-test', () => { 13 | test('testEncrypt', () => { 14 | // Compute expected 15 | let aes = C.algo.AES.createEncryptor(data.key, { 16 | iv: data.iv 17 | }); 18 | let ciphertext = aes.finalize(data.message); 19 | let expected = new C.lib.CipherParams({ 20 | ciphertext: ciphertext, 21 | key: data.key, 22 | iv: data.iv, 23 | algorithm: C.algo.AES, 24 | mode: aes.cfg.mode, 25 | padding: aes.cfg.padding, 26 | blockSize: aes.blockSize, 27 | formatter: C.format.OpenSSL 28 | }); 29 | let actual = C.lib.SerializableCipher.encrypt(C.algo.AES, data.message, data.key, { 30 | iv: data.iv 31 | }); 32 | 33 | expect(actual.toString()).toBe(expected.toString()); 34 | expect(actual.ciphertext.toString()).toBe(expected.ciphertext.toString()); 35 | expect(actual.key.toString()).toBe(expected.key.toString()); 36 | expect(actual.iv.toString()).toBe(expected.iv.toString()); 37 | expect(actual.algorithm).toBe(expected.algorithm); 38 | expect(actual.mode).toBe(expected.mode); 39 | expect(actual.padding).toBe(expected.padding); 40 | expect(actual.blockSize).toBe(expected.blockSize); 41 | }); 42 | 43 | test('testDecrypt', () => { 44 | let encrypted = C.lib.SerializableCipher.encrypt(C.algo.AES, data.message, data.key, { 45 | iv: data.iv 46 | }) + ''; 47 | let decrypted = C.lib.SerializableCipher.decrypt(C.algo.AES, encrypted, data.key, { 48 | iv: data.iv 49 | }); 50 | expect(decrypted.toString()).toBe(data.message.toString()); 51 | }); 52 | }); 53 | -------------------------------------------------------------------------------- /test/lib.typedarrays.test.js: -------------------------------------------------------------------------------- 1 | import C from '../src/index'; 2 | 3 | const data = {}; 4 | beforeAll(() => { 5 | data.buffer = new ArrayBuffer(8); 6 | 7 | let uint8View = new Uint8Array(data.buffer); 8 | uint8View[0] = 0x01; 9 | uint8View[1] = 0x23; 10 | uint8View[2] = 0x45; 11 | uint8View[3] = 0x67; 12 | uint8View[4] = 0x89; 13 | uint8View[5] = 0xab; 14 | uint8View[6] = 0xcd; 15 | uint8View[7] = 0xef; 16 | }); 17 | 18 | describe('lib-wordarray-test', () => { 19 | test('testInt8Array', () => { 20 | expect(new C.lib.WordArray(new Int8Array(data.buffer)).toString()).toBe('0123456789abcdef'); 21 | }); 22 | 23 | test('testUint8Array', () => { 24 | expect(new C.lib.WordArray(new Uint8Array(data.buffer)).toString()).toBe('0123456789abcdef'); 25 | }); 26 | 27 | test('testUint8ClampedArray', () => { 28 | expect(new C.lib.WordArray(new Uint8ClampedArray(data.buffer)).toString()).toBe('0123456789abcdef'); 29 | }); 30 | 31 | test('testInt16Array', () => { 32 | expect(new C.lib.WordArray(new Int16Array(data.buffer)).toString()).toBe('0123456789abcdef'); 33 | }); 34 | 35 | test('testUint16Array', () => { 36 | expect(new C.lib.WordArray(new Uint16Array(data.buffer)).toString()).toBe('0123456789abcdef'); 37 | }); 38 | 39 | test('testInt32Array', () => { 40 | expect(new C.lib.WordArray(new Int32Array(data.buffer)).toString()).toBe('0123456789abcdef'); 41 | }); 42 | 43 | test('testUint32Array', () => { 44 | expect(new C.lib.WordArray(new Uint32Array(data.buffer)).toString()).toBe('0123456789abcdef'); 45 | }); 46 | 47 | test('testPartialView', () => { 48 | expect(new C.lib.WordArray(new Int16Array(data.buffer, 2, 2)).toString()).toBe('456789ab'); 49 | }); 50 | }); -------------------------------------------------------------------------------- /test/lib.wordarray.test.js: -------------------------------------------------------------------------------- 1 | import C from '../src/index'; 2 | 3 | describe('lib-wordarray-test', () => { 4 | test('testInit0', () => { 5 | expect(new C.lib.WordArray().toString()).toBe(''); 6 | }); 7 | 8 | test('testInit1', () => { 9 | expect(new C.lib.WordArray([0x12345678]).toString()).toBe('12345678'); 10 | }); 11 | 12 | test('testInit2', () => { 13 | expect(new C.lib.WordArray([0x12345678], 2).toString()).toBe('1234'); 14 | }); 15 | 16 | test('testToStringPassedEncoder', () => { 17 | expect(new C.lib.WordArray([0x12345678]).toString(C.enc.Latin1)).toBe('\x12\x34\x56\x78'); 18 | }); 19 | 20 | test('testToStringDefaultEncoder', () => { 21 | expect(new C.lib.WordArray([0x12345678]).toString()).toBe('12345678'); 22 | }); 23 | 24 | test('testConcat3', () => { 25 | let wordArray1 = new C.lib.WordArray([0x12345678], 3); 26 | let wordArray2 = new C.lib.WordArray([0x12345678], 3); 27 | expect(wordArray1.concat(wordArray2).toString()).toBe('123456123456'); 28 | expect(wordArray1.toString()).toBe('123456123456'); 29 | }); 30 | 31 | test('testConcat4', () => { 32 | let wordArray1 = new C.lib.WordArray([0x12345678], 4); 33 | let wordArray2 = new C.lib.WordArray([0x12345678], 3); 34 | expect(wordArray1.concat(wordArray2).toString()).toBe('12345678123456'); 35 | expect(wordArray1.toString()).toBe('12345678123456'); 36 | }); 37 | 38 | test('testConcat5', () => { 39 | let wordArray1 = new C.lib.WordArray([0x12345678], 5); 40 | let wordArray2 = new C.lib.WordArray([0x12345678], 3); 41 | expect(wordArray1.concat(wordArray2).toString()).toBe('1234567800123456'); 42 | expect(wordArray1.toString()).toBe('1234567800123456'); 43 | }); 44 | 45 | test('testConcatLong', () => { 46 | let wordArray1 = new C.lib.WordArray(); 47 | let wordArray2 = new C.lib.WordArray(); 48 | let wordArray3 = new C.lib.WordArray(); 49 | for (let i = 0; i < 500000; i++) { 50 | wordArray2.words[i] = i; 51 | wordArray3.words[i] = i; 52 | } 53 | wordArray2.sigBytes = 500000; 54 | wordArray3.sigBytes = 500000; 55 | const expected = wordArray2.toString() + wordArray3.toString(); 56 | expect(wordArray1.concat(wordArray2.concat(wordArray3)).toString()).toBe(expected); 57 | }); 58 | 59 | test('testClamp', () => { 60 | let wordArray = new C.lib.WordArray([0x12345678, 0x12345678], 3); 61 | wordArray.clamp(); 62 | expect(wordArray.words.toString()).toBe([0x12345600].toString()); 63 | }); 64 | 65 | test('testClone', () => { 66 | let wordArray = new C.lib.WordArray([0x12345678]); 67 | let clone = wordArray.clone(); 68 | clone.words[0] = 0; 69 | expect(clone.toString()).not.toBe(wordArray.toString()); 70 | }); 71 | 72 | test('testRandom', () => { 73 | expect(C.lib.WordArray.random(8).toString()).not.toBe(C.lib.WordArray.random(8).toString()); 74 | expect(C.lib.WordArray.random(8).sigBytes).toBe(8); 75 | }); 76 | }); -------------------------------------------------------------------------------- /test/md5.profile.test.js: -------------------------------------------------------------------------------- 1 | import C from '../src/index'; 2 | 3 | const WORD_ARRAY_TEST = { 4 | 'sigBytes': 16, 5 | 'words': [1410418970, 1874077036, 1337395728, -598079323] 6 | }; 7 | 8 | beforeAll(async () => { 9 | await C.MD5.loadWasm(); 10 | }); 11 | 12 | describe('algo-md5-profile', () => { 13 | test('profileSinglePartMessage', () => { 14 | let singlePartMessage = ''; 15 | let i = 0; 16 | while (i < 500) { 17 | singlePartMessage += '12345678901234567890123456789012345678901234567890'; 18 | i++; 19 | } 20 | expect(new C.algo.MD5().finalize(singlePartMessage)).toMatchObject(WORD_ARRAY_TEST); 21 | }); 22 | 23 | test('profileMultiPartMessage', () => { 24 | let i = 0; 25 | const md5 = new C.algo.MD5(); 26 | while (i < 500) { 27 | md5.update('12345678901234567890123456789012345678901234567890'); 28 | i++; 29 | } 30 | expect(md5.finalize()).toMatchObject(WORD_ARRAY_TEST); 31 | }); 32 | }); 33 | -------------------------------------------------------------------------------- /test/md5.test.js: -------------------------------------------------------------------------------- 1 | import C from '../src/index'; 2 | 3 | const VECTOR_TEST_CONFIG = [ 4 | [1, '', 'd41d8cd98f00b204e9800998ecf8427e'], 5 | [2, 'a', '0cc175b9c0f1b6a831c399e269772661'], 6 | [3, 'abc', '900150983cd24fb0d6963f7d28e17f72'], 7 | [4, 'message digest', 'f96b697d7cb7938d525a2f31aaf161d0'], 8 | [5, 'abcdefghijklmnopqrstuvwxyz', 'c3fcd3d76192e4007dfb496cca67e13b'], 9 | [6, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789', 'd174ab98d277d9f5a5611c2c9f419d9f'], 10 | [7, '12345678901234567890123456789012345678901234567890123456789012345678901234567890', '57edf4a22be3c955ac49da2e2107b67a'] 11 | ]; 12 | 13 | beforeAll(async () => { 14 | await C.MD5.loadWasm(); 15 | }); 16 | 17 | const CLONE_TEST_CONFIG = [ 18 | ['a', 'a'], 19 | ['b', 'ab'], 20 | ['c', 'abc'] 21 | ]; 22 | 23 | describe('algo-md5-test', () => { 24 | test.each(VECTOR_TEST_CONFIG)( 25 | 'testVector%i', 26 | (a,b, expected) => { 27 | expect(C.MD5(b).toString()).toBe(expected); 28 | } 29 | ); 30 | 31 | describe('testClone', () => { 32 | const md5 = new C.algo.MD5(); 33 | test.each(CLONE_TEST_CONFIG)( 34 | 'return %s, %s', 35 | (a, expected) => { 36 | expect(md5.update(a).clone().finalize().toString()).toBe(C.MD5(expected).toString()); 37 | } 38 | ); 39 | }); 40 | 41 | test('testUpdateAndLongMessage', () => { 42 | let i = 0; 43 | const md5 = new C.algo.MD5(); 44 | while (i < 100) { 45 | md5.update('12345678901234567890123456789012345678901234567890'); 46 | i++; 47 | } 48 | expect(md5.finalize().toString()).toBe('7d017545e0268a6a12f2b507871d0429'); 49 | }); 50 | 51 | test('testCreate', () => { 52 | let i = 0; 53 | const md5 = C.algo.MD5.create(); 54 | while (i < 100) { 55 | md5.update('12345678901234567890123456789012345678901234567890'); 56 | i++; 57 | } 58 | expect(md5.finalize().toString()).toBe('7d017545e0268a6a12f2b507871d0429'); 59 | }); 60 | 61 | test('testInputIntegrity', () => { 62 | const message = new C.lib.WordArray([0x12345678]); 63 | const expected = message.toString(); 64 | C.MD5(message); 65 | expect(message.toString()).toBe(expected); 66 | }); 67 | 68 | test('testHelper', () => { 69 | expect(C.MD5('').toString()).toBe(new C.algo.MD5().finalize('').toString()); 70 | }); 71 | 72 | test('testHmacHelper', () => { 73 | expect(C.HmacMD5('Hi There', C.enc.Hex.parse('0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b')).toString()).toBe(new C.algo.HMAC(C.algo.MD5, C.enc.Hex.parse('0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b')).finalize('Hi There').toString()); 74 | }); 75 | }); 76 | -------------------------------------------------------------------------------- /test/mode.cbc.test.js: -------------------------------------------------------------------------------- 1 | import C from '../src/index'; 2 | 3 | let data = {}; 4 | beforeAll(async () => { 5 | data.message = new C.lib.WordArray([ 6 | 0x00010203, 0x04050607, 0x08090a0b, 0x0c0d0e0f, 7 | 0x10111213, 0x14151617, 0x18191a1b, 0x1c1d1e1f 8 | ]); 9 | data.key = new C.lib.WordArray([0x20212223, 0x24252627, 0x28292a2b, 0x2c2d2e2f]); 10 | data.iv = new C.lib.WordArray([0x30313233, 0x34353637, 0x38393a3b, 0x3c3d3e3f]); 11 | await C.AES.loadWasm(); 12 | }); 13 | 14 | describe('mode-cbc-test', () => { 15 | test('testDecryptor', () => { 16 | let encrypted = C.AES.encrypt(data.message, data.key, { 17 | iv: data.iv, 18 | mode: C.mode.CBC, 19 | padding: C.pad.NoPadding 20 | }); 21 | let decrypted = C.AES.decrypt(encrypted, data.key, { 22 | iv: data.iv, 23 | mode: C.mode.CBC, 24 | padding: C.pad.NoPadding 25 | }); 26 | expect(decrypted.toString()).toBe(data.message.toString()); 27 | }); 28 | }); 29 | -------------------------------------------------------------------------------- /test/mode.cfb.test.js: -------------------------------------------------------------------------------- 1 | import C from '../src/index'; 2 | 3 | const data = {}; 4 | beforeAll(async () => { 5 | data.message = new C.lib.WordArray([ 6 | 0x00010203, 0x04050607, 0x08090a0b, 0x0c0d0e0f, 7 | 0x10111213, 0x14151617, 0x18191a1b, 0x1c1d1e1f 8 | ]); 9 | data.key = new C.lib.WordArray([0x20212223, 0x24252627, 0x28292a2b, 0x2c2d2e2f]); 10 | data.iv = new C.lib.WordArray([0x30313233, 0x34353637, 0x38393a3b, 0x3c3d3e3f]); 11 | await C.AES.loadWasm(); 12 | }); 13 | 14 | describe('mode-cfb-test', () => { 15 | test('testDecryptor', () => { 16 | let encrypted = C.AES.encrypt(data.message, data.key, { 17 | iv: data.iv, 18 | mode: C.mode.CFB, 19 | padding: C.pad.NoPadding 20 | }); 21 | let decrypted = C.AES.decrypt(encrypted, data.key, { 22 | iv: data.iv, 23 | mode: C.mode.CFB, 24 | padding: C.pad.NoPadding 25 | }); 26 | expect(decrypted.toString()).toBe(data.message.toString()); 27 | 28 | }); 29 | }); 30 | -------------------------------------------------------------------------------- /test/mode.ctr.test.js: -------------------------------------------------------------------------------- 1 | import C from '../src/index'; 2 | 3 | const data = {}; 4 | beforeAll(async () => { 5 | data.message = new C.lib.WordArray([ 6 | 0x00010203, 0x04050607, 0x08090a0b, 0x0c0d0e0f, 7 | 0x10111213, 0x14151617, 0x18191a1b, 0x1c1d1e1f 8 | ]); 9 | data.key = new C.lib.WordArray([0x20212223, 0x24252627, 0x28292a2b, 0x2c2d2e2f]); 10 | data.iv = new C.lib.WordArray([0x30313233, 0x34353637, 0x38393a3b, 0x3c3d3e3f]); 11 | await C.AES.loadWasm(); 12 | }); 13 | 14 | describe('mode-ctr-test', () => { 15 | test('testDecryptor', () => { 16 | let encrypted = C.AES.encrypt(data.message, data.key, { 17 | iv: data.iv, 18 | mode: C.mode.CTR, 19 | padding: C.pad.NoPadding 20 | }); 21 | let decrypted = C.AES.decrypt(encrypted, data.key, { 22 | iv: data.iv, 23 | mode: C.mode.CTR, 24 | padding: C.pad.NoPadding 25 | }); 26 | expect(decrypted.toString()).toBe(data.message.toString()); 27 | }); 28 | }); 29 | -------------------------------------------------------------------------------- /test/mode.ecb.test.js: -------------------------------------------------------------------------------- 1 | import C from '../src/index'; 2 | 3 | const data = {}; 4 | 5 | beforeAll(async () => { 6 | data.message = new C.lib.WordArray([ 7 | 0x00010203, 0x04050607, 0x08090a0b, 0x0c0d0e0f, 8 | 0x10111213, 0x14151617, 0x18191a1b, 0x1c1d1e1f 9 | ]); 10 | data.key = new C.lib.WordArray([0x20212223, 0x24252627, 0x28292a2b, 0x2c2d2e2f]); 11 | await C.AES.loadWasm(); 12 | }); 13 | 14 | describe('node-ecb-test', () => { 15 | test('testDecryptor', () => { 16 | let encrypted = C.AES.encrypt(data.message, data.key, { 17 | mode: C.mode.ECB, 18 | padding: C.pad.NoPadding 19 | }); 20 | let decrypted = C.AES.decrypt(encrypted, data.key, { 21 | mode: C.mode.ECB, 22 | padding: C.pad.NoPadding 23 | }); 24 | expect(decrypted.toString()).toBe(data.message.toString()); 25 | }); 26 | }); 27 | -------------------------------------------------------------------------------- /test/mode.ofb.test.js: -------------------------------------------------------------------------------- 1 | import C from '../src/index'; 2 | 3 | const data = {}; 4 | 5 | beforeAll(async () => { 6 | data.message = new C.lib.WordArray([ 7 | 0x00010203, 0x04050607, 0x08090a0b, 0x0c0d0e0f, 8 | 0x10111213, 0x14151617, 0x18191a1b, 0x1c1d1e1f 9 | ]); 10 | data.key = new C.lib.WordArray([0x20212223, 0x24252627, 0x28292a2b, 0x2c2d2e2f]); 11 | data.iv = new C.lib.WordArray([0x30313233, 0x34353637, 0x38393a3b, 0x3c3d3e3f]); 12 | await C.AES.loadWasm(); 13 | }); 14 | 15 | describe('mode-ofb-test', () => { 16 | test('testDecryptor', () => { 17 | let encrypted = C.AES.encrypt(data.message, data.key, { 18 | iv: data.iv, 19 | mode: C.mode.OFB, 20 | padding: C.pad.NoPadding 21 | }); 22 | let decrypted = C.AES.decrypt(encrypted, data.key, { 23 | iv: data.iv, 24 | mode: C.mode.OFB, 25 | padding: C.pad.NoPadding 26 | }); 27 | expect(decrypted.toString()).toBe(data.message.toString()); 28 | }); 29 | }); 30 | -------------------------------------------------------------------------------- /test/pad.ansix923.test.js: -------------------------------------------------------------------------------- 1 | import C from '../src/index'; 2 | 3 | describe('pad-ansix923-test', () => { 4 | test('testPad', () => { 5 | let data = new C.lib.WordArray([0xdddddd00], 3); 6 | C.pad.AnsiX923.pad(data, 2); 7 | expect(data.toString()).toBe(new C.lib.WordArray([0xdddddd00, 0x00000005]).toString()); 8 | }); 9 | 10 | test('testPadClamp', () => { 11 | let data = new C.lib.WordArray([0xdddddddd, 0xdddddddd], 3); 12 | C.pad.AnsiX923.pad(data, 2); 13 | expect(data.toString()).toBe(new C.lib.WordArray([0xdddddd00, 0x00000005]).toString()); 14 | }); 15 | 16 | test('testUnpad', () => { 17 | let data = new C.lib.WordArray([0xdddddd00, 0x00000005]); 18 | C.pad.AnsiX923.unpad(data); 19 | expect(data.toString()).toBe(new C.lib.WordArray([0xdddddd00], 3).toString()); 20 | }); 21 | }); -------------------------------------------------------------------------------- /test/pad.iso10126.test.js: -------------------------------------------------------------------------------- 1 | import C from '../src/index'; 2 | 3 | const _data = {}; 4 | beforeAll(() => { 5 | // Save original random method 6 | _data.random = C.lib.WordArray.random; 7 | 8 | // Replace random method with one that returns a predictable value 9 | C.lib.WordArray.random = function (nBytes) { 10 | let words = []; 11 | for (let i = 0; i < nBytes; i += 4) { 12 | words.push([0x11223344]); 13 | } 14 | 15 | return new C.lib.WordArray(words, nBytes); 16 | }; 17 | }); 18 | 19 | afterAll(() => { 20 | // Restore random method 21 | C.lib.WordArray.random = _data.random; 22 | }); 23 | 24 | describe('pad-iso10126-test', () => { 25 | test('testPad', () => { 26 | let data = new C.lib.WordArray([0xdddddd00], 3); 27 | C.pad.Iso10126.pad(data, 2); 28 | expect(data.toString()).toBe(new C.lib.WordArray([0xdddddd11, 0x22334405]).toString()); 29 | }); 30 | 31 | test('testPadClamp', () => { 32 | let data = new C.lib.WordArray([0xdddddddd, 0xdddddddd], 3); 33 | C.pad.Iso10126.pad(data, 2); 34 | expect(data.toString()).toBe(new C.lib.WordArray([0xdddddd11, 0x22334405]).toString()); 35 | }); 36 | 37 | test('testUnpad', () => { 38 | let data = new C.lib.WordArray([0xdddddd11, 0x22334405]); 39 | C.pad.Iso10126.unpad(data); 40 | expect(data.toString()).toBe(new C.lib.WordArray([0xdddddd00], 3).toString()); 41 | }); 42 | }); -------------------------------------------------------------------------------- /test/pad.iso97971.test.js: -------------------------------------------------------------------------------- 1 | import C from '../src/index'; 2 | 3 | describe('pad-iso97971-test', () => { 4 | test('testPad1', () => { 5 | let data = new C.lib.WordArray([0xdddddd00], 3); 6 | C.pad.Iso97971.pad(data, 1); 7 | expect(data.toString()).toBe(new C.lib.WordArray([0xdddddd80]).toString()); 8 | }); 9 | 10 | test('testPad2', () => { 11 | let data = new C.lib.WordArray([0xdddddd00], 3); 12 | C.pad.Iso97971.pad(data, 2); 13 | expect(data.toString()).toBe(new C.lib.WordArray([0xdddddd80, 0x00000000]).toString()); 14 | }); 15 | 16 | test('testPadClamp', () => { 17 | let data = new C.lib.WordArray([0xdddddddd, 0xdddddddd], 3); 18 | C.pad.Iso97971.pad(data, 2); 19 | expect(data.toString()).toBe(new C.lib.WordArray([0xdddddd80, 0x00000000]).toString()); 20 | }); 21 | 22 | test('testUnpad', () => { 23 | let data = new C.lib.WordArray([0xdddddd80, 0x00000000]); 24 | C.pad.Iso97971.unpad(data); 25 | expect(data.toString()).toBe(new C.lib.WordArray([0xdddddd00], 3).toString()); 26 | }); 27 | }); -------------------------------------------------------------------------------- /test/pad.pkcs7.test.js: -------------------------------------------------------------------------------- 1 | import C from '../src/index'; 2 | 3 | describe('pad-pkcs7-test', () => { 4 | test('testPad', () => { 5 | let data = new C.lib.WordArray([0xdddddd00], 3); 6 | C.pad.Pkcs7.pad(data, 2); 7 | expect(data.toString()).toBe(new C.lib.WordArray([0xdddddd05, 0x05050505]).toString()); 8 | }); 9 | 10 | test('testPadClamp', () => { 11 | const data = new C.lib.WordArray([0xdddddddd, 0xdddddddd], 3); 12 | C.pad.Pkcs7.pad(data, 2); 13 | expect(data.toString()).toBe(new C.lib.WordArray([0xdddddd05, 0x05050505]).toString()); 14 | }); 15 | 16 | test('testUnpad', () => { 17 | let data = new C.lib.WordArray([0xdddddd05, 0x05050505]); 18 | C.pad.Pkcs7.unpad(data); 19 | expect(data.toString()).toBe(new C.lib.WordArray([0xdddddd00], 3).toString()); 20 | }); 21 | }); -------------------------------------------------------------------------------- /test/pad.zeropadding.test.js: -------------------------------------------------------------------------------- 1 | import C from '../src/index'; 2 | 3 | describe('pad-zeropadding-test', () => { 4 | test('testPad', () => { 5 | let data = new C.lib.WordArray([0xdddddd00], 3); 6 | C.pad.ZeroPadding.pad(data, 2); 7 | expect(data.toString()).toBe(new C.lib.WordArray([0xdddddd00, 0x00000000]).toString()); 8 | }); 9 | 10 | test('testPadClamp', () => { 11 | let data = new C.lib.WordArray([0xdddddddd, 0xdddddddd], 3); 12 | C.pad.ZeroPadding.pad(data, 2); 13 | expect(data.toString()).toBe(new C.lib.WordArray([0xdddddd00, 0x00000000]).toString()); 14 | }); 15 | 16 | test('testUnpad', () => { 17 | let data = new C.lib.WordArray([0xdddddd00, 0x00000000]); 18 | C.pad.ZeroPadding.unpad(data); 19 | expect(data.toString()).toBe(new C.lib.WordArray([0xdddddd00], 3).toString()); 20 | }); 21 | }); -------------------------------------------------------------------------------- /test/x64.word.test.js: -------------------------------------------------------------------------------- 1 | import C from '../src/index'; 2 | 3 | describe('x64-word-test', () => { 4 | test('testInit', () => { 5 | let word = new C.x64.Word(0x00010203, 0x04050607); 6 | expect(word.high).toBe(0x00010203); 7 | expect(word.low).toBe(0x04050607); 8 | }); 9 | }); -------------------------------------------------------------------------------- /test/x64.wordarray.test.js: -------------------------------------------------------------------------------- 1 | import C from '../src/index'; 2 | 3 | describe('x64-wordarray-test', () => { 4 | test('testInit0', () => { 5 | expect(new C.x64.WordArray().toX32().toString()).toBe(''); 6 | }); 7 | 8 | test('testInit1', () => { 9 | let wordArray = new C.x64.WordArray([ 10 | new C.x64.Word(0x00010203, 0x04050607), 11 | new C.x64.Word(0x18191a1b, 0x1c1d1e1f) 12 | ]); 13 | expect(wordArray.toX32().toString()).toBe('000102030405060718191a1b1c1d1e1f'); 14 | }); 15 | 16 | test('testInit2', () => { 17 | let wordArray = new C.x64.WordArray([ 18 | new C.x64.Word(0x00010203, 0x04050607), 19 | new C.x64.Word(0x18191a1b, 0x1c1d1e1f) 20 | ], 10); 21 | 22 | expect(wordArray.toX32().toString()).toBe('00010203040506071819'); 23 | }); 24 | }); --------------------------------------------------------------------------------