├── .codecov.yml ├── .eslintrc.js ├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md ├── lerna.json ├── package.json ├── packages ├── aes │ ├── .npmignore │ ├── README.md │ ├── jest.config.js │ ├── package.json │ ├── rollup.config.js │ ├── src │ │ ├── aes.ts │ │ ├── index.ts │ │ ├── modes │ │ │ ├── ctr.ts │ │ │ └── ige.ts │ │ └── utils │ │ │ ├── precompute.ts │ │ │ ├── tables.ts │ │ │ └── words.ts │ └── tests │ │ ├── aes-ctr.test.ts │ │ ├── aes-ige.test.ts │ │ ├── aes.test.ts │ │ └── precompute.test.ts ├── hmac │ ├── .npmignore │ ├── jest.config.js │ ├── package.json │ ├── rollup.config.js │ ├── src │ │ └── index.ts │ └── tests │ │ └── index.test.ts ├── pbkdf2 │ ├── .npmignore │ ├── jest.config.js │ ├── package.json │ ├── rollup.config.js │ ├── src │ │ └── index.ts │ └── tests │ │ └── index.test.ts ├── sha1 │ ├── .npmignore │ ├── README.md │ ├── jest.config.js │ ├── package.json │ ├── rollup.config.js │ ├── src │ │ └── index.ts │ └── tests │ │ └── index.test.ts ├── sha256 │ ├── .npmignore │ ├── README.md │ ├── files │ │ ├── perf_iphone.png │ │ └── perf_macbook.png │ ├── jest.config.js │ ├── package.json │ ├── rollup.config.js │ ├── src │ │ └── index.ts │ └── tests │ │ └── index.test.ts ├── sha512 │ ├── .npmignore │ ├── README.md │ ├── jest.config.js │ ├── package.json │ ├── rollup.config.js │ ├── src │ │ └── index.ts │ └── tests │ │ └── index.test.ts └── utils │ ├── package.json │ ├── rollup.config.js │ └── src │ ├── converters.ts │ └── index.ts ├── scripts ├── eslint.config.js └── rollup.js ├── tsconfig.json └── yarn.lock /.codecov.yml: -------------------------------------------------------------------------------- 1 | comment: off 2 | 3 | coverage: 4 | status: 5 | patch: 6 | default: 7 | target: 80% 8 | project: 9 | default: 10 | target: auto 11 | sha256: 12 | flags: 13 | - sha256 14 | sha512: 15 | flags: 16 | - sha512 17 | flags: 18 | sha256: 19 | paths: 20 | - packages/sha256/src 21 | sha512: 22 | paths: 23 | - packages/sha512 -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['./scripts/eslint.config.js'], 3 | settings: { 4 | 'import/resolver': { 5 | webpack: {}, 6 | }, 7 | }, 8 | }; 9 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | *.log 3 | .DS_Store 4 | dist/ 5 | coverage/ 6 | .vscode/ -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - '10' 4 | cache: 5 | yarn: true 6 | directories: 7 | - "node_modules" 8 | before_install: 9 | - curl -o- -L https://yarnpkg.com/install.sh | bash -s 10 | - export PATH="$HOME/.yarn/bin:$PATH" 11 | before_script: 12 | - yarn run lerna run build --scope @cryptography/utils 13 | - yarn run lerna run build --scope @cryptography/hmac 14 | script: 15 | - yarn run lerna run prepublish 16 | after_success: 17 | - codecov -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Cryptography JS 2 | [![Coverage](https://img.shields.io/codecov/c/github/spalt08/cryptography?token=617017dc35344eb6b4637420457746c8)](https://codecov.io/gh/spalt08/cryptography) 3 | 4 | High-performance cryptographic packages for JavaScript. Optimized for browsers. 5 | 6 | ## Packages & Documentation 7 | * [[@cryptography/sha1](./packages/sha1)] SHA-1 implementation for JavaScript 8 | * [[@cryptography/sha256](./packages/sha256)] SHA-256 implementation for JavaScript 9 | * [[@cryptography/sha512](./packages/sha512)] SHA-512 implementation for JavaScript 10 | 11 | Beta: 12 | * [[@cryptography/aes](./packages/aes)] AES (IGE & CTR modes) implementation for JavaScript 13 | * [[@cryptography/pbkdf2](./packages/pbkdf2)] pbkdf2 14 | 15 | ## Contribution 16 | 17 | As this project is a monorepo it is extremely important to write correct commit messages and keep git history clean. All commits made in this repository are divided in two groups: core commits (those that are only related to core repository and are not related to any package) and package commits (those that are related to particular package). Examples of core commit contents: update this readme, update lerna configuration, update scripts in core package.json. Examples of package commits: update eslint configuration in @cryptography/eslint-config package, fix issues in @cryptography/sha256 package. 18 | 19 | When writing commit message start with `[core]` prefix if it is a core commit and with `[@cryptography/package-name]` prefix if it is a package commit. After prefix write commit message as you usually do. For example, 20 | 21 | - `[core] feat: git commits documentation to readme` 22 | - `[core] feat: @cryptography/sha256 publishing script` 23 | - `[@cryptography/eslint-config] fix: rules to work with prettier` 24 | - `[@cryptography/sha256] feat: stream hashing` 25 | -------------------------------------------------------------------------------- /lerna.json: -------------------------------------------------------------------------------- 1 | { 2 | "packages": ["packages/*"], 3 | "version": "0.0.0", 4 | "npmClient": "yarn", 5 | "useWorkspaces": true 6 | } 7 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "workspaces": [ 4 | "packages/*" 5 | ], 6 | "scripts": { 7 | "build:utils": "cd packages/utils && yarn build", 8 | "build:sha256": "yarn build:utils && cd packages/sha256 && yarn build", 9 | "build:sha512": "yarn build:utils && cd packages/sha512 && yarn build", 10 | "build:hmac": "yarn build:utils && cd packages/hmac && yarn build", 11 | "build:pbkdf2": "yarn build:hmac && cd packages/pbkdf2 && yarn build", 12 | "build:aes": "cd packages/aes && yarn build", 13 | "build": "yarn build:hmac && yarn build:sha256 && yarn build:sha512 && yarn build:hmac && yarn build:pbkdf2", 14 | "lint:utils": "eslint --ext ts ./packages/utils/src", 15 | "lint:sha256": "eslint --ext ts ./packages/sha256/src", 16 | "lint:hmac": "eslint --ext ts ./packages/hmac/src", 17 | "test:sha1": "cd packages/sha1 && yarn test", 18 | "test:sha256": "cd packages/sha256 && yarn test", 19 | "test:sha512": "cd packages/sha512 && yarn test", 20 | "test:hmac": "cd packages/hmac && yarn test", 21 | "test:pbkdf2": "cd packages/pbkdf2 && yarn test", 22 | "test:aes": "cd packages/aes && yarn test", 23 | "test": "yarn test:sha256 && yarn test:sha512 && yarn test:hmac && yarn test:pbkdf2", 24 | "publish:sha256": "yarn build:utils && cd packages/sha256 && yarn publish", 25 | "publish:sha1": "yarn build:utils && cd packages/sha1 && yarn publish", 26 | "publish:sha512": "yarn build:utils && cd packages/sha512 && yarn publish", 27 | "publish:aes": "cd packages/aes && yarn publish", 28 | "publish:pbkdf2": "yarn build:hmac && cd packages/pbkdf2 && yarn publish" 29 | }, 30 | "devDependencies": { 31 | "@rollup/plugin-node-resolve": "^7.1.1", 32 | "@rollup/plugin-typescript": "^4.0.0", 33 | "@types/jest": "^25.1.4", 34 | "@typescript-eslint/eslint-plugin": "^2.6.1", 35 | "@typescript-eslint/parser": "^2.6.1", 36 | "codecov": "^3.6.5", 37 | "eslint": "^6.7.2", 38 | "eslint-config-airbnb-typescript": "^6.0.0", 39 | "eslint-import-resolver-webpack": "^0.11.1", 40 | "eslint-plugin-import": "^2.18.2", 41 | "eslint-plugin-jest": "^23.0.2", 42 | "eslint-plugin-jsx-a11y": "^6.2.3", 43 | "eslint-plugin-react": "^7.17.0", 44 | "jest": "^25.2.3", 45 | "jest-config": "^25.2.3", 46 | "lerna": "^3.20.2", 47 | "rollup": "^2.2.0", 48 | "rollup-plugin-terser": "^5.3.0", 49 | "ts-jest": "^25.2.1", 50 | "tslib": "^1.11.1", 51 | "typescript": "^3.8.3" 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /packages/aes/.npmignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | 6 | # Runtime data 7 | pids 8 | *.pid 9 | *.seed 10 | 11 | # Directory for instrumented libs generated by jscoverage/JSCover 12 | lib-cov 13 | 14 | # Coverage directory used by tools like istanbul 15 | coverage 16 | 17 | # nyc test coverage 18 | .nyc_output 19 | 20 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 21 | .grunt 22 | 23 | # node-waf configuration 24 | .lock-wscript 25 | 26 | # Compiled binary addons (http://nodejs.org/api/addons.html) 27 | build/Release 28 | 29 | # Dependency directories 30 | node_modules 31 | jspm_packages 32 | 33 | # Optional npm cache directory 34 | .npm 35 | 36 | # Optional REPL history 37 | .node_repl_history 38 | 39 | # Project 40 | tests 41 | src 42 | .travis.yml 43 | .codecov.yml 44 | rollup.config.js -------------------------------------------------------------------------------- /packages/aes/README.md: -------------------------------------------------------------------------------- 1 | # @cryptography/aes 2 | Still under development 3 | 4 | Implemented modes: IGE, CTR -------------------------------------------------------------------------------- /packages/aes/jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | roots: [ 3 | '/tests', 4 | ], 5 | transform: { 6 | '^.+\\.ts$': 'ts-jest', 7 | }, 8 | testPathIgnorePatterns: ['/dist/', '/node_modules/'], 9 | collectCoverage: true, 10 | }; 11 | -------------------------------------------------------------------------------- /packages/aes/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@cryptography/aes", 3 | "description": "High-performance synchronous AES implementation for JavaScript", 4 | "version": "0.1.1", 5 | "author": "Konstantin Darutkin", 6 | "scripts": { 7 | "test": "jest --coverage", 8 | "build": "rm -rf dist/* && rollup -c", 9 | "analyze": "npm run build -- --analyze", 10 | "prepublish": "npm test", 11 | "pretest": "npm run build", 12 | "publish": "npm publish" 13 | }, 14 | "devDependencies": {}, 15 | "main": "dist/cjs/aes.min.js", 16 | "module": "dist/es/aes.js", 17 | "types": "dist/typings/index.d.ts", 18 | "repository": { 19 | "type": "git", 20 | "url": "git+https://github.com/spalt08/cryptography.git", 21 | "directory": "packages/aes" 22 | }, 23 | "publishConfig": { 24 | "access": "public" 25 | }, 26 | "lint-staged": { 27 | "*.{ts}": [ 28 | "eslint" 29 | ] 30 | }, 31 | "keywords": [ 32 | "aes", 33 | "javascript", 34 | "crypto" 35 | ], 36 | "bugs": { 37 | "url": "https://github.com/spalt08/cryptography/issues" 38 | }, 39 | "homepage": "https://github.com/spalt08/cryptography/tree/master/packages/aes", 40 | "files": [ 41 | "dist/*", 42 | "package.json" 43 | ], 44 | "license": "GPL-3.0-or-later" 45 | } 46 | -------------------------------------------------------------------------------- /packages/aes/rollup.config.js: -------------------------------------------------------------------------------- 1 | import getTypeScriptConfig from '../../scripts/rollup'; 2 | 3 | export default getTypeScriptConfig({ 4 | packageName: 'aes', 5 | entryFile: 'src/index.ts', 6 | inlineDynamicImports: true, 7 | }); 8 | -------------------------------------------------------------------------------- /packages/aes/src/aes.ts: -------------------------------------------------------------------------------- 1 | import computeTables, { 2 | S, T1, T2, T5, T6, T7, T8, T3, T4, Si, 3 | } from './utils/precompute'; 4 | import { getWords } from './utils/words'; 5 | 6 | computeTables(); 7 | 8 | /** 9 | * Low-level AES Cipher 10 | */ 11 | export default class AES { 12 | encKey: Uint32Array; 13 | decKey: Uint32Array; 14 | 15 | constructor(_key: string | Uint8Array | Uint32Array) { 16 | const key = getWords(_key); 17 | 18 | if (key.length !== 4 && key.length !== 6 && key.length !== 8) { 19 | throw new Error('Invalid key size'); 20 | } 21 | 22 | this.encKey = new Uint32Array(4 * key.length + 28); 23 | this.decKey = new Uint32Array(4 * key.length + 28); 24 | 25 | this.encKey.set(key); 26 | 27 | let rcon = 1; 28 | let i = key.length; 29 | let tmp; 30 | 31 | // schedule encryption keys 32 | for (; i < 4 * key.length + 28; i++) { 33 | tmp = this.encKey[i - 1]; 34 | 35 | // apply sbox 36 | if (i % key.length === 0 || (key.length === 8 && i % key.length === 4)) { 37 | tmp = S[tmp >>> 24] << 24 ^ S[(tmp >> 16) & 255] << 16 ^ S[(tmp >> 8) & 255] << 8 ^ S[tmp & 255]; 38 | 39 | // shift rows and add rcon 40 | if (i % key.length === 0) { 41 | tmp = tmp << 8 ^ tmp >>> 24 ^ (rcon << 24); 42 | rcon = rcon << 1 ^ (rcon >> 7) * 283; 43 | } 44 | } 45 | 46 | this.encKey[i] = this.encKey[i - key.length] ^ tmp; 47 | } 48 | 49 | // schedule decryption keys 50 | for (let j = 0; i; j++, i--) { 51 | tmp = this.encKey[j & 3 ? i : i - 4]; 52 | if (i <= 4 || j < 4) { 53 | this.decKey[j] = tmp; 54 | } else { 55 | this.decKey[j] = ( 56 | T5[S[tmp >>> 24]] 57 | ^ T6[S[(tmp >> 16) & 255]] 58 | ^ T7[S[(tmp >> 8) & 255]] 59 | ^ T8[S[tmp & 255]] 60 | ); 61 | } 62 | } 63 | } 64 | 65 | encrypt(_message: string | Uint32Array | Uint8Array) { 66 | const message = getWords(_message); 67 | const out = new Uint32Array(4); 68 | 69 | let a = message[0] ^ this.encKey[0]; 70 | let b = message[1] ^ this.encKey[1]; 71 | let c = message[2] ^ this.encKey[2]; 72 | let d = message[3] ^ this.encKey[3]; 73 | 74 | const rounds = this.encKey.length / 4 - 2; 75 | 76 | let k = 4; 77 | 78 | let a2; let b2; let c2; 79 | 80 | // Inner rounds. Cribbed from OpenSSL. 81 | for (let i = 0; i < rounds; i++) { 82 | a2 = T1[a >>> 24] ^ T2[(b >> 16) & 255] ^ T3[(c >> 8) & 255] ^ T4[d & 255] ^ this.encKey[k]; 83 | b2 = T1[b >>> 24] ^ T2[(c >> 16) & 255] ^ T3[(d >> 8) & 255] ^ T4[a & 255] ^ this.encKey[k + 1]; 84 | c2 = T1[c >>> 24] ^ T2[(d >> 16) & 255] ^ T3[(a >> 8) & 255] ^ T4[b & 255] ^ this.encKey[k + 2]; 85 | d = T1[d >>> 24] ^ T2[(a >> 16) & 255] ^ T3[(b >> 8) & 255] ^ T4[c & 255] ^ this.encKey[k + 3]; 86 | a = a2; b = b2; c = c2; 87 | k += 4; 88 | // console.log(a, b, c, d); 89 | } 90 | 91 | // Last round. 92 | for (let i = 0; i < 4; i++) { 93 | out[i] = ( 94 | S[a >>> 24] << 24 95 | ^ S[(b >> 16) & 255] << 16 96 | ^ S[(c >> 8) & 255] << 8 97 | ^ S[d & 255] 98 | ^ this.encKey[k++] 99 | ); 100 | a2 = a; a = b; b = c; c = d; d = a2; 101 | } 102 | 103 | return out; 104 | } 105 | 106 | decrypt(_message: string | Uint32Array | Uint8Array) { 107 | const message = getWords(_message); 108 | const out = new Uint32Array(4); 109 | 110 | let a = message[0] ^ this.decKey[0]; 111 | let b = message[3] ^ this.decKey[1]; 112 | let c = message[2] ^ this.decKey[2]; 113 | let d = message[1] ^ this.decKey[3]; 114 | 115 | const rounds = this.decKey.length / 4 - 2; 116 | 117 | let a2; let b2; let c2; 118 | 119 | let k = 4; 120 | 121 | // Inner rounds. Cribbed from OpenSSL. 122 | for (let i = 0; i < rounds; i++) { 123 | a2 = T5[a >>> 24] ^ T6[(b >> 16) & 255] ^ T7[(c >> 8) & 255] ^ T8[d & 255] ^ this.decKey[k]; 124 | b2 = T5[b >>> 24] ^ T6[(c >> 16) & 255] ^ T7[(d >> 8) & 255] ^ T8[a & 255] ^ this.decKey[k + 1]; 125 | c2 = T5[c >>> 24] ^ T6[(d >> 16) & 255] ^ T7[(a >> 8) & 255] ^ T8[b & 255] ^ this.decKey[k + 2]; 126 | d = T5[d >>> 24] ^ T6[(a >> 16) & 255] ^ T7[(b >> 8) & 255] ^ T8[c & 255] ^ this.decKey[k + 3]; 127 | a = a2; b = b2; c = c2; 128 | k += 4; 129 | } 130 | 131 | // Last round. 132 | for (let i = 0; i < 4; i++) { 133 | out[3 & -i] = ( 134 | Si[a >>> 24] << 24 135 | ^ Si[(b >> 16) & 255] << 16 136 | ^ Si[(c >> 8) & 255] << 8 137 | ^ Si[d & 255] 138 | ^ this.decKey[k++] 139 | ); 140 | a2 = a; a = b; b = c; c = d; d = a2; 141 | } 142 | 143 | return out; 144 | } 145 | } 146 | -------------------------------------------------------------------------------- /packages/aes/src/index.ts: -------------------------------------------------------------------------------- 1 | import AES from './aes'; 2 | 3 | export { default as IGE } from './modes/ige'; 4 | export { default as CTR } from './modes/ctr'; 5 | 6 | export default AES; 7 | -------------------------------------------------------------------------------- /packages/aes/src/modes/ctr.ts: -------------------------------------------------------------------------------- 1 | import AES from '../aes'; 2 | import { getWords } from '../utils/words'; 3 | 4 | /** 5 | * AES-IGE mode. 6 | */ 7 | export default class AES_IGE { 8 | cipher: AES; 9 | key: Uint32Array; 10 | counter: Uint32Array; 11 | blockSize: number; 12 | offset = 0; 13 | 14 | constructor(key: string | Uint32Array | Uint8Array, counter: string | Uint32Array | Uint8Array, blockSize = 16) { 15 | this.key = getWords(key); 16 | this.counter = getWords(counter); 17 | this.cipher = new AES(key); 18 | this.blockSize = blockSize / 4; 19 | 20 | if (this.counter.length !== 4) { 21 | throw new Error('AES-CTR mode counter must be 16 bytes length'); 22 | } 23 | } 24 | 25 | /** 26 | * Encrypts plain text with AES-IGE mode. 27 | */ 28 | encrypt(message: string | Uint32Array | Uint8Array, buf?: Uint32Array) { 29 | const text = getWords(message); 30 | const cipherText = buf || new Uint32Array(text.length); 31 | 32 | let offset = this.offset; 33 | for (let i = 0; i < text.length; i += this.blockSize) { 34 | const x = this.cipher.encrypt(this.counter); 35 | for (let j = i, k = offset; j < text.length && k < this.blockSize; j++, k++) cipherText[j] = x[k] ^ text[j]; 36 | 37 | if (text.length - i >= this.blockSize) this.incrementCounter(); 38 | if (offset) { 39 | i -= offset; 40 | offset = 0; 41 | } 42 | } 43 | 44 | this.offset = (this.offset + (text.length % 4)) % 4; 45 | 46 | return cipherText; 47 | } 48 | 49 | /** 50 | * Decrypts cipher text with AES-IGE mode. 51 | */ 52 | decrypt(message: string | Uint32Array | Uint8Array, buf?: Uint32Array) { 53 | return this.encrypt(message, buf); 54 | } 55 | 56 | incrementCounter() { 57 | // increment counter 58 | for (let carry = this.counter.length - 1; carry >= 0; carry--) { 59 | if (++this.counter[carry] < 0xFFFFFFFF) break; // If overflowing, it'll be 0 and we'll have to continue propagating the carry 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /packages/aes/src/modes/ige.ts: -------------------------------------------------------------------------------- 1 | import AES from '../aes'; 2 | import { getWords, xor } from '../utils/words'; 3 | 4 | /** 5 | * AES-IGE mode. 6 | */ 7 | export default class AES_IGE { 8 | cipher: AES; 9 | key: Uint32Array; 10 | iv: Uint32Array; 11 | blockSize: number; 12 | 13 | constructor(key: string | Uint32Array | Uint8Array, iv: string | Uint32Array | Uint8Array, blockSize = 16) { 14 | this.key = getWords(key); 15 | this.iv = getWords(iv); 16 | this.cipher = new AES(key); 17 | this.blockSize = blockSize / 4; 18 | } 19 | 20 | /** 21 | * Encrypts plain text with AES-IGE mode. 22 | */ 23 | encrypt(message: string | Uint32Array | Uint8Array, buf?: Uint32Array) { 24 | const text = getWords(message); 25 | const cipherText = buf || new Uint32Array(text.length); 26 | 27 | let prevX = this.iv.subarray(this.blockSize, this.iv.length); 28 | let prevY = this.iv.subarray(0, this.blockSize); 29 | const yXOR = new Uint32Array(this.blockSize); 30 | 31 | for (let i = 0; i < text.length; i += this.blockSize) { 32 | const x = text.subarray(i, i + this.blockSize); 33 | xor(x, prevY, yXOR); 34 | 35 | const y = this.cipher.encrypt(yXOR); 36 | xor(y, prevX); 37 | 38 | prevX = x; 39 | prevY = y; 40 | 41 | for (let j = i, k = 0; j < text.length && k < 4; j++, k++) cipherText[j] = y[k]; 42 | } 43 | 44 | return cipherText; 45 | } 46 | 47 | /** 48 | * Decrypts cipher text with AES-IGE mode. 49 | */ 50 | decrypt(message: string | Uint32Array | Uint8Array, buf?: Uint32Array) { 51 | const cipherText = getWords(message); 52 | const text = buf || new Uint32Array(cipherText.length); 53 | 54 | let prevY = this.iv.subarray(this.blockSize, this.iv.length); 55 | let prevX = this.iv.subarray(0, this.blockSize); 56 | const yXOR = new Uint32Array(this.blockSize); 57 | 58 | for (let i = 0; i < text.length; i += this.blockSize) { 59 | const x = cipherText.subarray(i, i + this.blockSize); 60 | xor(x, prevY, yXOR); 61 | 62 | const y = this.cipher.decrypt(yXOR); 63 | xor(y, prevX); 64 | 65 | prevX = x; 66 | prevY = y; 67 | 68 | for (let j = i, k = 0; j < text.length && k < 4; j++, k++) text[j] = y[k]; 69 | } 70 | 71 | return text; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /packages/aes/src/utils/precompute.ts: -------------------------------------------------------------------------------- 1 | 2 | export const S = new Uint8Array(256); 3 | export const Si = new Uint8Array(256); 4 | 5 | export const T1 = new Uint32Array(256); 6 | export const T2 = new Uint32Array(256); 7 | export const T3 = new Uint32Array(256); 8 | export const T4 = new Uint32Array(256); 9 | 10 | export const T5 = new Uint32Array(256); 11 | export const T6 = new Uint32Array(256); 12 | export const T7 = new Uint32Array(256); 13 | export const T8 = new Uint32Array(256); 14 | 15 | export default function computeTables() { 16 | const d = new Uint8Array(256); 17 | const t = new Uint8Array(256); 18 | 19 | let x2; let x4; let x8; let s; let tEnc; let 20 | tDec; 21 | 22 | let x = 0; 23 | let xInv = 0; 24 | 25 | // Compute double and third tables 26 | for (let i = 0; i < 256; i++) { 27 | d[i] = i << 1 ^ (i >> 7) * 283; 28 | t[d[i] ^ i] = i; 29 | } 30 | 31 | for (; !S[x]; x ^= x2 || 1) { 32 | // Compute sbox 33 | s = xInv ^ xInv << 1 ^ xInv << 2 ^ xInv << 3 ^ xInv << 4; 34 | s = s >> 8 ^ s & 255 ^ 99; 35 | 36 | S[x] = s; 37 | Si[s] = x; 38 | 39 | // Compute MixColumns 40 | x8 = d[x4 = d[x2 = d[x]]]; 41 | tDec = x8 * 0x1010101 ^ x4 * 0x10001 ^ x2 * 0x101 ^ x * 0x1010100; 42 | tEnc = d[s] * 0x101 ^ s * 0x1010100; 43 | 44 | T1[x] = tEnc = tEnc << 24 ^ tEnc >>> 8; 45 | T2[x] = tEnc = tEnc << 24 ^ tEnc >>> 8; 46 | T3[x] = tEnc = tEnc << 24 ^ tEnc >>> 8; 47 | T4[x] = tEnc = tEnc << 24 ^ tEnc >>> 8; 48 | 49 | T5[s] = tDec = tDec << 24 ^ tDec >>> 8; 50 | T6[s] = tDec = tDec << 24 ^ tDec >>> 8; 51 | T7[s] = tDec = tDec << 24 ^ tDec >>> 8; 52 | T8[s] = tDec = tDec << 24 ^ tDec >>> 8; 53 | 54 | xInv = t[xInv] || 1; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /packages/aes/src/utils/tables.ts: -------------------------------------------------------------------------------- 1 | // S-box and Inverse S-box (S is for Substitution) 2 | export const S = new Uint8Array([ 3 | 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 4 | 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, 0x04, 0xc7, 5 | 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 6 | 0xb3, 0x29, 0xe3, 0x2f, 0x84, 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, 0xd0, 0xef, 0xaa, 0xfb, 7 | 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 8 | 0xff, 0xf3, 0xd2, 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 9 | 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 10 | 0x79, 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 11 | 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, 0xe1, 12 | 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 13 | 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16, 14 | ]); 15 | 16 | export const Si = new Uint8Array([ 17 | 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb, 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 18 | 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, 0x08, 0x2e, 19 | 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25, 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 20 | 0xcc, 0x5d, 0x65, 0xb6, 0x92, 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84, 0x90, 0xd8, 0xab, 0x00, 21 | 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06, 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 22 | 0x13, 0x8a, 0x6b, 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 23 | 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e, 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 24 | 0x1b, 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 25 | 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f, 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, 0xa0, 26 | 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 27 | 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d, 28 | ]); 29 | 30 | // Transformations for encryption 31 | export const T1 = new Uint32Array([ 32 | 0xc66363a5, 0xf87c7c84, 0xee777799, 0xf67b7b8d, 0xfff2f20d, 0xd66b6bbd, 0xde6f6fb1, 0x91c5c554, 0x60303050, 0x02010103, 0xce6767a9, 0x562b2b7d, 33 | 0xe7fefe19, 0xb5d7d762, 0x4dababe6, 0xec76769a, 0x8fcaca45, 0x1f82829d, 0x89c9c940, 0xfa7d7d87, 0xeffafa15, 0xb25959eb, 0x8e4747c9, 0xfbf0f00b, 34 | 0x41adadec, 0xb3d4d467, 0x5fa2a2fd, 0x45afafea, 0x239c9cbf, 0x53a4a4f7, 0xe4727296, 0x9bc0c05b, 0x75b7b7c2, 0xe1fdfd1c, 0x3d9393ae, 0x4c26266a, 35 | 0x6c36365a, 0x7e3f3f41, 0xf5f7f702, 0x83cccc4f, 0x6834345c, 0x51a5a5f4, 0xd1e5e534, 0xf9f1f108, 0xe2717193, 0xabd8d873, 0x62313153, 0x2a15153f, 36 | 0x0804040c, 0x95c7c752, 0x46232365, 0x9dc3c35e, 0x30181828, 0x379696a1, 0x0a05050f, 0x2f9a9ab5, 0x0e070709, 0x24121236, 0x1b80809b, 0xdfe2e23d, 37 | 0xcdebeb26, 0x4e272769, 0x7fb2b2cd, 0xea75759f, 0x1209091b, 0x1d83839e, 0x582c2c74, 0x341a1a2e, 0x361b1b2d, 0xdc6e6eb2, 0xb45a5aee, 0x5ba0a0fb, 38 | 0xa45252f6, 0x763b3b4d, 0xb7d6d661, 0x7db3b3ce, 0x5229297b, 0xdde3e33e, 0x5e2f2f71, 0x13848497, 0xa65353f5, 0xb9d1d168, 0x00000000, 0xc1eded2c, 39 | 0x40202060, 0xe3fcfc1f, 0x79b1b1c8, 0xb65b5bed, 0xd46a6abe, 0x8dcbcb46, 0x67bebed9, 0x7239394b, 0x944a4ade, 0x984c4cd4, 0xb05858e8, 0x85cfcf4a, 40 | 0xbbd0d06b, 0xc5efef2a, 0x4faaaae5, 0xedfbfb16, 0x864343c5, 0x9a4d4dd7, 0x66333355, 0x11858594, 0x8a4545cf, 0xe9f9f910, 0x04020206, 0xfe7f7f81, 41 | 0xa05050f0, 0x783c3c44, 0x259f9fba, 0x4ba8a8e3, 0xa25151f3, 0x5da3a3fe, 0x804040c0, 0x058f8f8a, 0x3f9292ad, 0x219d9dbc, 0x70383848, 0xf1f5f504, 42 | 0x63bcbcdf, 0x77b6b6c1, 0xafdada75, 0x42212163, 0x20101030, 0xe5ffff1a, 0xfdf3f30e, 0xbfd2d26d, 0x81cdcd4c, 0x180c0c14, 0x26131335, 0xc3ecec2f, 43 | 0xbe5f5fe1, 0x359797a2, 0x884444cc, 0x2e171739, 0x93c4c457, 0x55a7a7f2, 0xfc7e7e82, 0x7a3d3d47, 0xc86464ac, 0xba5d5de7, 0x3219192b, 0xe6737395, 44 | 0xc06060a0, 0x19818198, 0x9e4f4fd1, 0xa3dcdc7f, 0x44222266, 0x542a2a7e, 0x3b9090ab, 0x0b888883, 0x8c4646ca, 0xc7eeee29, 0x6bb8b8d3, 0x2814143c, 45 | 0xa7dede79, 0xbc5e5ee2, 0x160b0b1d, 0xaddbdb76, 0xdbe0e03b, 0x64323256, 0x743a3a4e, 0x140a0a1e, 0x924949db, 0x0c06060a, 0x4824246c, 0xb85c5ce4, 46 | 0x9fc2c25d, 0xbdd3d36e, 0x43acacef, 0xc46262a6, 0x399191a8, 0x319595a4, 0xd3e4e437, 0xf279798b, 0xd5e7e732, 0x8bc8c843, 0x6e373759, 0xda6d6db7, 47 | 0x018d8d8c, 0xb1d5d564, 0x9c4e4ed2, 0x49a9a9e0, 0xd86c6cb4, 0xac5656fa, 0xf3f4f407, 0xcfeaea25, 0xca6565af, 0xf47a7a8e, 0x47aeaee9, 0x10080818, 48 | 0x6fbabad5, 0xf0787888, 0x4a25256f, 0x5c2e2e72, 0x381c1c24, 0x57a6a6f1, 0x73b4b4c7, 0x97c6c651, 0xcbe8e823, 0xa1dddd7c, 0xe874749c, 0x3e1f1f21, 49 | 0x964b4bdd, 0x61bdbddc, 0x0d8b8b86, 0x0f8a8a85, 0xe0707090, 0x7c3e3e42, 0x71b5b5c4, 0xcc6666aa, 0x904848d8, 0x06030305, 0xf7f6f601, 0x1c0e0e12, 50 | 0xc26161a3, 0x6a35355f, 0xae5757f9, 0x69b9b9d0, 0x17868691, 0x99c1c158, 0x3a1d1d27, 0x279e9eb9, 0xd9e1e138, 0xebf8f813, 0x2b9898b3, 0x22111133, 51 | 0xd26969bb, 0xa9d9d970, 0x078e8e89, 0x339494a7, 0x2d9b9bb6, 0x3c1e1e22, 0x15878792, 0xc9e9e920, 0x87cece49, 0xaa5555ff, 0x50282878, 0xa5dfdf7a, 52 | 0x038c8c8f, 0x59a1a1f8, 0x09898980, 0x1a0d0d17, 0x65bfbfda, 0xd7e6e631, 0x844242c6, 0xd06868b8, 0x824141c3, 0x299999b0, 0x5a2d2d77, 0x1e0f0f11, 53 | 0x7bb0b0cb, 0xa85454fc, 0x6dbbbbd6, 0x2c16163a, 54 | ]); 55 | 56 | export const T2 = new Uint32Array([ 57 | 0xa5c66363, 0x84f87c7c, 0x99ee7777, 0x8df67b7b, 0x0dfff2f2, 0xbdd66b6b, 0xb1de6f6f, 0x5491c5c5, 0x50603030, 0x03020101, 0xa9ce6767, 0x7d562b2b, 58 | 0x19e7fefe, 0x62b5d7d7, 0xe64dabab, 0x9aec7676, 0x458fcaca, 0x9d1f8282, 0x4089c9c9, 0x87fa7d7d, 0x15effafa, 0xebb25959, 0xc98e4747, 0x0bfbf0f0, 59 | 0xec41adad, 0x67b3d4d4, 0xfd5fa2a2, 0xea45afaf, 0xbf239c9c, 0xf753a4a4, 0x96e47272, 0x5b9bc0c0, 0xc275b7b7, 0x1ce1fdfd, 0xae3d9393, 0x6a4c2626, 60 | 0x5a6c3636, 0x417e3f3f, 0x02f5f7f7, 0x4f83cccc, 0x5c683434, 0xf451a5a5, 0x34d1e5e5, 0x08f9f1f1, 0x93e27171, 0x73abd8d8, 0x53623131, 0x3f2a1515, 61 | 0x0c080404, 0x5295c7c7, 0x65462323, 0x5e9dc3c3, 0x28301818, 0xa1379696, 0x0f0a0505, 0xb52f9a9a, 0x090e0707, 0x36241212, 0x9b1b8080, 0x3ddfe2e2, 62 | 0x26cdebeb, 0x694e2727, 0xcd7fb2b2, 0x9fea7575, 0x1b120909, 0x9e1d8383, 0x74582c2c, 0x2e341a1a, 0x2d361b1b, 0xb2dc6e6e, 0xeeb45a5a, 0xfb5ba0a0, 63 | 0xf6a45252, 0x4d763b3b, 0x61b7d6d6, 0xce7db3b3, 0x7b522929, 0x3edde3e3, 0x715e2f2f, 0x97138484, 0xf5a65353, 0x68b9d1d1, 0x00000000, 0x2cc1eded, 64 | 0x60402020, 0x1fe3fcfc, 0xc879b1b1, 0xedb65b5b, 0xbed46a6a, 0x468dcbcb, 0xd967bebe, 0x4b723939, 0xde944a4a, 0xd4984c4c, 0xe8b05858, 0x4a85cfcf, 65 | 0x6bbbd0d0, 0x2ac5efef, 0xe54faaaa, 0x16edfbfb, 0xc5864343, 0xd79a4d4d, 0x55663333, 0x94118585, 0xcf8a4545, 0x10e9f9f9, 0x06040202, 0x81fe7f7f, 66 | 0xf0a05050, 0x44783c3c, 0xba259f9f, 0xe34ba8a8, 0xf3a25151, 0xfe5da3a3, 0xc0804040, 0x8a058f8f, 0xad3f9292, 0xbc219d9d, 0x48703838, 0x04f1f5f5, 67 | 0xdf63bcbc, 0xc177b6b6, 0x75afdada, 0x63422121, 0x30201010, 0x1ae5ffff, 0x0efdf3f3, 0x6dbfd2d2, 0x4c81cdcd, 0x14180c0c, 0x35261313, 0x2fc3ecec, 68 | 0xe1be5f5f, 0xa2359797, 0xcc884444, 0x392e1717, 0x5793c4c4, 0xf255a7a7, 0x82fc7e7e, 0x477a3d3d, 0xacc86464, 0xe7ba5d5d, 0x2b321919, 0x95e67373, 69 | 0xa0c06060, 0x98198181, 0xd19e4f4f, 0x7fa3dcdc, 0x66442222, 0x7e542a2a, 0xab3b9090, 0x830b8888, 0xca8c4646, 0x29c7eeee, 0xd36bb8b8, 0x3c281414, 70 | 0x79a7dede, 0xe2bc5e5e, 0x1d160b0b, 0x76addbdb, 0x3bdbe0e0, 0x56643232, 0x4e743a3a, 0x1e140a0a, 0xdb924949, 0x0a0c0606, 0x6c482424, 0xe4b85c5c, 71 | 0x5d9fc2c2, 0x6ebdd3d3, 0xef43acac, 0xa6c46262, 0xa8399191, 0xa4319595, 0x37d3e4e4, 0x8bf27979, 0x32d5e7e7, 0x438bc8c8, 0x596e3737, 0xb7da6d6d, 72 | 0x8c018d8d, 0x64b1d5d5, 0xd29c4e4e, 0xe049a9a9, 0xb4d86c6c, 0xfaac5656, 0x07f3f4f4, 0x25cfeaea, 0xafca6565, 0x8ef47a7a, 0xe947aeae, 0x18100808, 73 | 0xd56fbaba, 0x88f07878, 0x6f4a2525, 0x725c2e2e, 0x24381c1c, 0xf157a6a6, 0xc773b4b4, 0x5197c6c6, 0x23cbe8e8, 0x7ca1dddd, 0x9ce87474, 0x213e1f1f, 74 | 0xdd964b4b, 0xdc61bdbd, 0x860d8b8b, 0x850f8a8a, 0x90e07070, 0x427c3e3e, 0xc471b5b5, 0xaacc6666, 0xd8904848, 0x05060303, 0x01f7f6f6, 0x121c0e0e, 75 | 0xa3c26161, 0x5f6a3535, 0xf9ae5757, 0xd069b9b9, 0x91178686, 0x5899c1c1, 0x273a1d1d, 0xb9279e9e, 0x38d9e1e1, 0x13ebf8f8, 0xb32b9898, 0x33221111, 76 | 0xbbd26969, 0x70a9d9d9, 0x89078e8e, 0xa7339494, 0xb62d9b9b, 0x223c1e1e, 0x92158787, 0x20c9e9e9, 0x4987cece, 0xffaa5555, 0x78502828, 0x7aa5dfdf, 77 | 0x8f038c8c, 0xf859a1a1, 0x80098989, 0x171a0d0d, 0xda65bfbf, 0x31d7e6e6, 0xc6844242, 0xb8d06868, 0xc3824141, 0xb0299999, 0x775a2d2d, 0x111e0f0f, 78 | 0xcb7bb0b0, 0xfca85454, 0xd66dbbbb, 0x3a2c1616, 79 | ]); 80 | 81 | export const T3 = new Uint32Array([ 82 | 0x63a5c663, 0x7c84f87c, 0x7799ee77, 0x7b8df67b, 0xf20dfff2, 0x6bbdd66b, 0x6fb1de6f, 0xc55491c5, 0x30506030, 0x01030201, 0x67a9ce67, 0x2b7d562b, 83 | 0xfe19e7fe, 0xd762b5d7, 0xabe64dab, 0x769aec76, 0xca458fca, 0x829d1f82, 0xc94089c9, 0x7d87fa7d, 0xfa15effa, 0x59ebb259, 0x47c98e47, 0xf00bfbf0, 84 | 0xadec41ad, 0xd467b3d4, 0xa2fd5fa2, 0xafea45af, 0x9cbf239c, 0xa4f753a4, 0x7296e472, 0xc05b9bc0, 0xb7c275b7, 0xfd1ce1fd, 0x93ae3d93, 0x266a4c26, 85 | 0x365a6c36, 0x3f417e3f, 0xf702f5f7, 0xcc4f83cc, 0x345c6834, 0xa5f451a5, 0xe534d1e5, 0xf108f9f1, 0x7193e271, 0xd873abd8, 0x31536231, 0x153f2a15, 86 | 0x040c0804, 0xc75295c7, 0x23654623, 0xc35e9dc3, 0x18283018, 0x96a13796, 0x050f0a05, 0x9ab52f9a, 0x07090e07, 0x12362412, 0x809b1b80, 0xe23ddfe2, 87 | 0xeb26cdeb, 0x27694e27, 0xb2cd7fb2, 0x759fea75, 0x091b1209, 0x839e1d83, 0x2c74582c, 0x1a2e341a, 0x1b2d361b, 0x6eb2dc6e, 0x5aeeb45a, 0xa0fb5ba0, 88 | 0x52f6a452, 0x3b4d763b, 0xd661b7d6, 0xb3ce7db3, 0x297b5229, 0xe33edde3, 0x2f715e2f, 0x84971384, 0x53f5a653, 0xd168b9d1, 0x00000000, 0xed2cc1ed, 89 | 0x20604020, 0xfc1fe3fc, 0xb1c879b1, 0x5bedb65b, 0x6abed46a, 0xcb468dcb, 0xbed967be, 0x394b7239, 0x4ade944a, 0x4cd4984c, 0x58e8b058, 0xcf4a85cf, 90 | 0xd06bbbd0, 0xef2ac5ef, 0xaae54faa, 0xfb16edfb, 0x43c58643, 0x4dd79a4d, 0x33556633, 0x85941185, 0x45cf8a45, 0xf910e9f9, 0x02060402, 0x7f81fe7f, 91 | 0x50f0a050, 0x3c44783c, 0x9fba259f, 0xa8e34ba8, 0x51f3a251, 0xa3fe5da3, 0x40c08040, 0x8f8a058f, 0x92ad3f92, 0x9dbc219d, 0x38487038, 0xf504f1f5, 92 | 0xbcdf63bc, 0xb6c177b6, 0xda75afda, 0x21634221, 0x10302010, 0xff1ae5ff, 0xf30efdf3, 0xd26dbfd2, 0xcd4c81cd, 0x0c14180c, 0x13352613, 0xec2fc3ec, 93 | 0x5fe1be5f, 0x97a23597, 0x44cc8844, 0x17392e17, 0xc45793c4, 0xa7f255a7, 0x7e82fc7e, 0x3d477a3d, 0x64acc864, 0x5de7ba5d, 0x192b3219, 0x7395e673, 94 | 0x60a0c060, 0x81981981, 0x4fd19e4f, 0xdc7fa3dc, 0x22664422, 0x2a7e542a, 0x90ab3b90, 0x88830b88, 0x46ca8c46, 0xee29c7ee, 0xb8d36bb8, 0x143c2814, 95 | 0xde79a7de, 0x5ee2bc5e, 0x0b1d160b, 0xdb76addb, 0xe03bdbe0, 0x32566432, 0x3a4e743a, 0x0a1e140a, 0x49db9249, 0x060a0c06, 0x246c4824, 0x5ce4b85c, 96 | 0xc25d9fc2, 0xd36ebdd3, 0xacef43ac, 0x62a6c462, 0x91a83991, 0x95a43195, 0xe437d3e4, 0x798bf279, 0xe732d5e7, 0xc8438bc8, 0x37596e37, 0x6db7da6d, 97 | 0x8d8c018d, 0xd564b1d5, 0x4ed29c4e, 0xa9e049a9, 0x6cb4d86c, 0x56faac56, 0xf407f3f4, 0xea25cfea, 0x65afca65, 0x7a8ef47a, 0xaee947ae, 0x08181008, 98 | 0xbad56fba, 0x7888f078, 0x256f4a25, 0x2e725c2e, 0x1c24381c, 0xa6f157a6, 0xb4c773b4, 0xc65197c6, 0xe823cbe8, 0xdd7ca1dd, 0x749ce874, 0x1f213e1f, 99 | 0x4bdd964b, 0xbddc61bd, 0x8b860d8b, 0x8a850f8a, 0x7090e070, 0x3e427c3e, 0xb5c471b5, 0x66aacc66, 0x48d89048, 0x03050603, 0xf601f7f6, 0x0e121c0e, 100 | 0x61a3c261, 0x355f6a35, 0x57f9ae57, 0xb9d069b9, 0x86911786, 0xc15899c1, 0x1d273a1d, 0x9eb9279e, 0xe138d9e1, 0xf813ebf8, 0x98b32b98, 0x11332211, 101 | 0x69bbd269, 0xd970a9d9, 0x8e89078e, 0x94a73394, 0x9bb62d9b, 0x1e223c1e, 0x87921587, 0xe920c9e9, 0xce4987ce, 0x55ffaa55, 0x28785028, 0xdf7aa5df, 102 | 0x8c8f038c, 0xa1f859a1, 0x89800989, 0x0d171a0d, 0xbfda65bf, 0xe631d7e6, 0x42c68442, 0x68b8d068, 0x41c38241, 0x99b02999, 0x2d775a2d, 0x0f111e0f, 103 | 0xb0cb7bb0, 0x54fca854, 0xbbd66dbb, 0x163a2c16, 104 | ]); 105 | 106 | export const T4 = new Uint32Array([ 107 | 0x6363a5c6, 0x7c7c84f8, 0x777799ee, 0x7b7b8df6, 0xf2f20dff, 0x6b6bbdd6, 0x6f6fb1de, 0xc5c55491, 0x30305060, 0x01010302, 0x6767a9ce, 0x2b2b7d56, 108 | 0xfefe19e7, 0xd7d762b5, 0xababe64d, 0x76769aec, 0xcaca458f, 0x82829d1f, 0xc9c94089, 0x7d7d87fa, 0xfafa15ef, 0x5959ebb2, 0x4747c98e, 0xf0f00bfb, 109 | 0xadadec41, 0xd4d467b3, 0xa2a2fd5f, 0xafafea45, 0x9c9cbf23, 0xa4a4f753, 0x727296e4, 0xc0c05b9b, 0xb7b7c275, 0xfdfd1ce1, 0x9393ae3d, 0x26266a4c, 110 | 0x36365a6c, 0x3f3f417e, 0xf7f702f5, 0xcccc4f83, 0x34345c68, 0xa5a5f451, 0xe5e534d1, 0xf1f108f9, 0x717193e2, 0xd8d873ab, 0x31315362, 0x15153f2a, 111 | 0x04040c08, 0xc7c75295, 0x23236546, 0xc3c35e9d, 0x18182830, 0x9696a137, 0x05050f0a, 0x9a9ab52f, 0x0707090e, 0x12123624, 0x80809b1b, 0xe2e23ddf, 112 | 0xebeb26cd, 0x2727694e, 0xb2b2cd7f, 0x75759fea, 0x09091b12, 0x83839e1d, 0x2c2c7458, 0x1a1a2e34, 0x1b1b2d36, 0x6e6eb2dc, 0x5a5aeeb4, 0xa0a0fb5b, 113 | 0x5252f6a4, 0x3b3b4d76, 0xd6d661b7, 0xb3b3ce7d, 0x29297b52, 0xe3e33edd, 0x2f2f715e, 0x84849713, 0x5353f5a6, 0xd1d168b9, 0x00000000, 0xeded2cc1, 114 | 0x20206040, 0xfcfc1fe3, 0xb1b1c879, 0x5b5bedb6, 0x6a6abed4, 0xcbcb468d, 0xbebed967, 0x39394b72, 0x4a4ade94, 0x4c4cd498, 0x5858e8b0, 0xcfcf4a85, 115 | 0xd0d06bbb, 0xefef2ac5, 0xaaaae54f, 0xfbfb16ed, 0x4343c586, 0x4d4dd79a, 0x33335566, 0x85859411, 0x4545cf8a, 0xf9f910e9, 0x02020604, 0x7f7f81fe, 116 | 0x5050f0a0, 0x3c3c4478, 0x9f9fba25, 0xa8a8e34b, 0x5151f3a2, 0xa3a3fe5d, 0x4040c080, 0x8f8f8a05, 0x9292ad3f, 0x9d9dbc21, 0x38384870, 0xf5f504f1, 117 | 0xbcbcdf63, 0xb6b6c177, 0xdada75af, 0x21216342, 0x10103020, 0xffff1ae5, 0xf3f30efd, 0xd2d26dbf, 0xcdcd4c81, 0x0c0c1418, 0x13133526, 0xecec2fc3, 118 | 0x5f5fe1be, 0x9797a235, 0x4444cc88, 0x1717392e, 0xc4c45793, 0xa7a7f255, 0x7e7e82fc, 0x3d3d477a, 0x6464acc8, 0x5d5de7ba, 0x19192b32, 0x737395e6, 119 | 0x6060a0c0, 0x81819819, 0x4f4fd19e, 0xdcdc7fa3, 0x22226644, 0x2a2a7e54, 0x9090ab3b, 0x8888830b, 0x4646ca8c, 0xeeee29c7, 0xb8b8d36b, 0x14143c28, 120 | 0xdede79a7, 0x5e5ee2bc, 0x0b0b1d16, 0xdbdb76ad, 0xe0e03bdb, 0x32325664, 0x3a3a4e74, 0x0a0a1e14, 0x4949db92, 0x06060a0c, 0x24246c48, 0x5c5ce4b8, 121 | 0xc2c25d9f, 0xd3d36ebd, 0xacacef43, 0x6262a6c4, 0x9191a839, 0x9595a431, 0xe4e437d3, 0x79798bf2, 0xe7e732d5, 0xc8c8438b, 0x3737596e, 0x6d6db7da, 122 | 0x8d8d8c01, 0xd5d564b1, 0x4e4ed29c, 0xa9a9e049, 0x6c6cb4d8, 0x5656faac, 0xf4f407f3, 0xeaea25cf, 0x6565afca, 0x7a7a8ef4, 0xaeaee947, 0x08081810, 123 | 0xbabad56f, 0x787888f0, 0x25256f4a, 0x2e2e725c, 0x1c1c2438, 0xa6a6f157, 0xb4b4c773, 0xc6c65197, 0xe8e823cb, 0xdddd7ca1, 0x74749ce8, 0x1f1f213e, 124 | 0x4b4bdd96, 0xbdbddc61, 0x8b8b860d, 0x8a8a850f, 0x707090e0, 0x3e3e427c, 0xb5b5c471, 0x6666aacc, 0x4848d890, 0x03030506, 0xf6f601f7, 0x0e0e121c, 125 | 0x6161a3c2, 0x35355f6a, 0x5757f9ae, 0xb9b9d069, 0x86869117, 0xc1c15899, 0x1d1d273a, 0x9e9eb927, 0xe1e138d9, 0xf8f813eb, 0x9898b32b, 0x11113322, 126 | 0x6969bbd2, 0xd9d970a9, 0x8e8e8907, 0x9494a733, 0x9b9bb62d, 0x1e1e223c, 0x87879215, 0xe9e920c9, 0xcece4987, 0x5555ffaa, 0x28287850, 0xdfdf7aa5, 127 | 0x8c8c8f03, 0xa1a1f859, 0x89898009, 0x0d0d171a, 0xbfbfda65, 0xe6e631d7, 0x4242c684, 0x6868b8d0, 0x4141c382, 0x9999b029, 0x2d2d775a, 0x0f0f111e, 128 | 0xb0b0cb7b, 0x5454fca8, 0xbbbbd66d, 0x16163a2c, 129 | ]); 130 | 131 | // Transformations for decryption 132 | export const T5 = new Uint32Array([ 133 | 0x51f4a750, 0x7e416553, 0x1a17a4c3, 0x3a275e96, 0x3bab6bcb, 0x1f9d45f1, 0xacfa58ab, 0x4be30393, 0x2030fa55, 0xad766df6, 0x88cc7691, 0xf5024c25, 134 | 0x4fe5d7fc, 0xc52acbd7, 0x26354480, 0xb562a38f, 0xdeb15a49, 0x25ba1b67, 0x45ea0e98, 0x5dfec0e1, 0xc32f7502, 0x814cf012, 0x8d4697a3, 0x6bd3f9c6, 135 | 0x038f5fe7, 0x15929c95, 0xbf6d7aeb, 0x955259da, 0xd4be832d, 0x587421d3, 0x49e06929, 0x8ec9c844, 0x75c2896a, 0xf48e7978, 0x99583e6b, 0x27b971dd, 136 | 0xbee14fb6, 0xf088ad17, 0xc920ac66, 0x7dce3ab4, 0x63df4a18, 0xe51a3182, 0x97513360, 0x62537f45, 0xb16477e0, 0xbb6bae84, 0xfe81a01c, 0xf9082b94, 137 | 0x70486858, 0x8f45fd19, 0x94de6c87, 0x527bf8b7, 0xab73d323, 0x724b02e2, 0xe31f8f57, 0x6655ab2a, 0xb2eb2807, 0x2fb5c203, 0x86c57b9a, 0xd33708a5, 138 | 0x302887f2, 0x23bfa5b2, 0x02036aba, 0xed16825c, 0x8acf1c2b, 0xa779b492, 0xf307f2f0, 0x4e69e2a1, 0x65daf4cd, 0x0605bed5, 0xd134621f, 0xc4a6fe8a, 139 | 0x342e539d, 0xa2f355a0, 0x058ae132, 0xa4f6eb75, 0x0b83ec39, 0x4060efaa, 0x5e719f06, 0xbd6e1051, 0x3e218af9, 0x96dd063d, 0xdd3e05ae, 0x4de6bd46, 140 | 0x91548db5, 0x71c45d05, 0x0406d46f, 0x605015ff, 0x1998fb24, 0xd6bde997, 0x894043cc, 0x67d99e77, 0xb0e842bd, 0x07898b88, 0xe7195b38, 0x79c8eedb, 141 | 0xa17c0a47, 0x7c420fe9, 0xf8841ec9, 0x00000000, 0x09808683, 0x322bed48, 0x1e1170ac, 0x6c5a724e, 0xfd0efffb, 0x0f853856, 0x3daed51e, 0x362d3927, 142 | 0x0a0fd964, 0x685ca621, 0x9b5b54d1, 0x24362e3a, 0x0c0a67b1, 0x9357e70f, 0xb4ee96d2, 0x1b9b919e, 0x80c0c54f, 0x61dc20a2, 0x5a774b69, 0x1c121a16, 143 | 0xe293ba0a, 0xc0a02ae5, 0x3c22e043, 0x121b171d, 0x0e090d0b, 0xf28bc7ad, 0x2db6a8b9, 0x141ea9c8, 0x57f11985, 0xaf75074c, 0xee99ddbb, 0xa37f60fd, 144 | 0xf701269f, 0x5c72f5bc, 0x44663bc5, 0x5bfb7e34, 0x8b432976, 0xcb23c6dc, 0xb6edfc68, 0xb8e4f163, 0xd731dcca, 0x42638510, 0x13972240, 0x84c61120, 145 | 0x854a247d, 0xd2bb3df8, 0xaef93211, 0xc729a16d, 0x1d9e2f4b, 0xdcb230f3, 0x0d8652ec, 0x77c1e3d0, 0x2bb3166c, 0xa970b999, 0x119448fa, 0x47e96422, 146 | 0xa8fc8cc4, 0xa0f03f1a, 0x567d2cd8, 0x223390ef, 0x87494ec7, 0xd938d1c1, 0x8ccaa2fe, 0x98d40b36, 0xa6f581cf, 0xa57ade28, 0xdab78e26, 0x3fadbfa4, 147 | 0x2c3a9de4, 0x5078920d, 0x6a5fcc9b, 0x547e4662, 0xf68d13c2, 0x90d8b8e8, 0x2e39f75e, 0x82c3aff5, 0x9f5d80be, 0x69d0937c, 0x6fd52da9, 0xcf2512b3, 148 | 0xc8ac993b, 0x10187da7, 0xe89c636e, 0xdb3bbb7b, 0xcd267809, 0x6e5918f4, 0xec9ab701, 0x834f9aa8, 0xe6956e65, 0xaaffe67e, 0x21bccf08, 0xef15e8e6, 149 | 0xbae79bd9, 0x4a6f36ce, 0xea9f09d4, 0x29b07cd6, 0x31a4b2af, 0x2a3f2331, 0xc6a59430, 0x35a266c0, 0x744ebc37, 0xfc82caa6, 0xe090d0b0, 0x33a7d815, 150 | 0xf104984a, 0x41ecdaf7, 0x7fcd500e, 0x1791f62f, 0x764dd68d, 0x43efb04d, 0xccaa4d54, 0xe49604df, 0x9ed1b5e3, 0x4c6a881b, 0xc12c1fb8, 0x4665517f, 151 | 0x9d5eea04, 0x018c355d, 0xfa877473, 0xfb0b412e, 0xb3671d5a, 0x92dbd252, 0xe9105633, 0x6dd64713, 0x9ad7618c, 0x37a10c7a, 0x59f8148e, 0xeb133c89, 152 | 0xcea927ee, 0xb761c935, 0xe11ce5ed, 0x7a47b13c, 0x9cd2df59, 0x55f2733f, 0x1814ce79, 0x73c737bf, 0x53f7cdea, 0x5ffdaa5b, 0xdf3d6f14, 0x7844db86, 153 | 0xcaaff381, 0xb968c43e, 0x3824342c, 0xc2a3405f, 0x161dc372, 0xbce2250c, 0x283c498b, 0xff0d9541, 0x39a80171, 0x080cb3de, 0xd8b4e49c, 0x6456c190, 154 | 0x7bcb8461, 0xd532b670, 0x486c5c74, 0xd0b85742, 155 | ]); 156 | 157 | export const T6 = new Uint32Array([ 158 | 0x5051f4a7, 0x537e4165, 0xc31a17a4, 0x963a275e, 0xcb3bab6b, 0xf11f9d45, 0xabacfa58, 0x934be303, 0x552030fa, 0xf6ad766d, 0x9188cc76, 0x25f5024c, 159 | 0xfc4fe5d7, 0xd7c52acb, 0x80263544, 0x8fb562a3, 0x49deb15a, 0x6725ba1b, 0x9845ea0e, 0xe15dfec0, 0x02c32f75, 0x12814cf0, 0xa38d4697, 0xc66bd3f9, 160 | 0xe7038f5f, 0x9515929c, 0xebbf6d7a, 0xda955259, 0x2dd4be83, 0xd3587421, 0x2949e069, 0x448ec9c8, 0x6a75c289, 0x78f48e79, 0x6b99583e, 0xdd27b971, 161 | 0xb6bee14f, 0x17f088ad, 0x66c920ac, 0xb47dce3a, 0x1863df4a, 0x82e51a31, 0x60975133, 0x4562537f, 0xe0b16477, 0x84bb6bae, 0x1cfe81a0, 0x94f9082b, 162 | 0x58704868, 0x198f45fd, 0x8794de6c, 0xb7527bf8, 0x23ab73d3, 0xe2724b02, 0x57e31f8f, 0x2a6655ab, 0x07b2eb28, 0x032fb5c2, 0x9a86c57b, 0xa5d33708, 163 | 0xf2302887, 0xb223bfa5, 0xba02036a, 0x5ced1682, 0x2b8acf1c, 0x92a779b4, 0xf0f307f2, 0xa14e69e2, 0xcd65daf4, 0xd50605be, 0x1fd13462, 0x8ac4a6fe, 164 | 0x9d342e53, 0xa0a2f355, 0x32058ae1, 0x75a4f6eb, 0x390b83ec, 0xaa4060ef, 0x065e719f, 0x51bd6e10, 0xf93e218a, 0x3d96dd06, 0xaedd3e05, 0x464de6bd, 165 | 0xb591548d, 0x0571c45d, 0x6f0406d4, 0xff605015, 0x241998fb, 0x97d6bde9, 0xcc894043, 0x7767d99e, 0xbdb0e842, 0x8807898b, 0x38e7195b, 0xdb79c8ee, 166 | 0x47a17c0a, 0xe97c420f, 0xc9f8841e, 0x00000000, 0x83098086, 0x48322bed, 0xac1e1170, 0x4e6c5a72, 0xfbfd0eff, 0x560f8538, 0x1e3daed5, 0x27362d39, 167 | 0x640a0fd9, 0x21685ca6, 0xd19b5b54, 0x3a24362e, 0xb10c0a67, 0x0f9357e7, 0xd2b4ee96, 0x9e1b9b91, 0x4f80c0c5, 0xa261dc20, 0x695a774b, 0x161c121a, 168 | 0x0ae293ba, 0xe5c0a02a, 0x433c22e0, 0x1d121b17, 0x0b0e090d, 0xadf28bc7, 0xb92db6a8, 0xc8141ea9, 0x8557f119, 0x4caf7507, 0xbbee99dd, 0xfda37f60, 169 | 0x9ff70126, 0xbc5c72f5, 0xc544663b, 0x345bfb7e, 0x768b4329, 0xdccb23c6, 0x68b6edfc, 0x63b8e4f1, 0xcad731dc, 0x10426385, 0x40139722, 0x2084c611, 170 | 0x7d854a24, 0xf8d2bb3d, 0x11aef932, 0x6dc729a1, 0x4b1d9e2f, 0xf3dcb230, 0xec0d8652, 0xd077c1e3, 0x6c2bb316, 0x99a970b9, 0xfa119448, 0x2247e964, 171 | 0xc4a8fc8c, 0x1aa0f03f, 0xd8567d2c, 0xef223390, 0xc787494e, 0xc1d938d1, 0xfe8ccaa2, 0x3698d40b, 0xcfa6f581, 0x28a57ade, 0x26dab78e, 0xa43fadbf, 172 | 0xe42c3a9d, 0x0d507892, 0x9b6a5fcc, 0x62547e46, 0xc2f68d13, 0xe890d8b8, 0x5e2e39f7, 0xf582c3af, 0xbe9f5d80, 0x7c69d093, 0xa96fd52d, 0xb3cf2512, 173 | 0x3bc8ac99, 0xa710187d, 0x6ee89c63, 0x7bdb3bbb, 0x09cd2678, 0xf46e5918, 0x01ec9ab7, 0xa8834f9a, 0x65e6956e, 0x7eaaffe6, 0x0821bccf, 0xe6ef15e8, 174 | 0xd9bae79b, 0xce4a6f36, 0xd4ea9f09, 0xd629b07c, 0xaf31a4b2, 0x312a3f23, 0x30c6a594, 0xc035a266, 0x37744ebc, 0xa6fc82ca, 0xb0e090d0, 0x1533a7d8, 175 | 0x4af10498, 0xf741ecda, 0x0e7fcd50, 0x2f1791f6, 0x8d764dd6, 0x4d43efb0, 0x54ccaa4d, 0xdfe49604, 0xe39ed1b5, 0x1b4c6a88, 0xb8c12c1f, 0x7f466551, 176 | 0x049d5eea, 0x5d018c35, 0x73fa8774, 0x2efb0b41, 0x5ab3671d, 0x5292dbd2, 0x33e91056, 0x136dd647, 0x8c9ad761, 0x7a37a10c, 0x8e59f814, 0x89eb133c, 177 | 0xeecea927, 0x35b761c9, 0xede11ce5, 0x3c7a47b1, 0x599cd2df, 0x3f55f273, 0x791814ce, 0xbf73c737, 0xea53f7cd, 0x5b5ffdaa, 0x14df3d6f, 0x867844db, 178 | 0x81caaff3, 0x3eb968c4, 0x2c382434, 0x5fc2a340, 0x72161dc3, 0x0cbce225, 0x8b283c49, 0x41ff0d95, 0x7139a801, 0xde080cb3, 0x9cd8b4e4, 0x906456c1, 179 | 0x617bcb84, 0x70d532b6, 0x74486c5c, 0x42d0b857, 180 | ]); 181 | 182 | export const T7 = new Uint32Array([ 183 | 0xa75051f4, 0x65537e41, 0xa4c31a17, 0x5e963a27, 0x6bcb3bab, 0x45f11f9d, 0x58abacfa, 0x03934be3, 0xfa552030, 0x6df6ad76, 0x769188cc, 0x4c25f502, 184 | 0xd7fc4fe5, 0xcbd7c52a, 0x44802635, 0xa38fb562, 0x5a49deb1, 0x1b6725ba, 0x0e9845ea, 0xc0e15dfe, 0x7502c32f, 0xf012814c, 0x97a38d46, 0xf9c66bd3, 185 | 0x5fe7038f, 0x9c951592, 0x7aebbf6d, 0x59da9552, 0x832dd4be, 0x21d35874, 0x692949e0, 0xc8448ec9, 0x896a75c2, 0x7978f48e, 0x3e6b9958, 0x71dd27b9, 186 | 0x4fb6bee1, 0xad17f088, 0xac66c920, 0x3ab47dce, 0x4a1863df, 0x3182e51a, 0x33609751, 0x7f456253, 0x77e0b164, 0xae84bb6b, 0xa01cfe81, 0x2b94f908, 187 | 0x68587048, 0xfd198f45, 0x6c8794de, 0xf8b7527b, 0xd323ab73, 0x02e2724b, 0x8f57e31f, 0xab2a6655, 0x2807b2eb, 0xc2032fb5, 0x7b9a86c5, 0x08a5d337, 188 | 0x87f23028, 0xa5b223bf, 0x6aba0203, 0x825ced16, 0x1c2b8acf, 0xb492a779, 0xf2f0f307, 0xe2a14e69, 0xf4cd65da, 0xbed50605, 0x621fd134, 0xfe8ac4a6, 189 | 0x539d342e, 0x55a0a2f3, 0xe132058a, 0xeb75a4f6, 0xec390b83, 0xefaa4060, 0x9f065e71, 0x1051bd6e, 0x8af93e21, 0x063d96dd, 0x05aedd3e, 0xbd464de6, 190 | 0x8db59154, 0x5d0571c4, 0xd46f0406, 0x15ff6050, 0xfb241998, 0xe997d6bd, 0x43cc8940, 0x9e7767d9, 0x42bdb0e8, 0x8b880789, 0x5b38e719, 0xeedb79c8, 191 | 0x0a47a17c, 0x0fe97c42, 0x1ec9f884, 0x00000000, 0x86830980, 0xed48322b, 0x70ac1e11, 0x724e6c5a, 0xfffbfd0e, 0x38560f85, 0xd51e3dae, 0x3927362d, 192 | 0xd9640a0f, 0xa621685c, 0x54d19b5b, 0x2e3a2436, 0x67b10c0a, 0xe70f9357, 0x96d2b4ee, 0x919e1b9b, 0xc54f80c0, 0x20a261dc, 0x4b695a77, 0x1a161c12, 193 | 0xba0ae293, 0x2ae5c0a0, 0xe0433c22, 0x171d121b, 0x0d0b0e09, 0xc7adf28b, 0xa8b92db6, 0xa9c8141e, 0x198557f1, 0x074caf75, 0xddbbee99, 0x60fda37f, 194 | 0x269ff701, 0xf5bc5c72, 0x3bc54466, 0x7e345bfb, 0x29768b43, 0xc6dccb23, 0xfc68b6ed, 0xf163b8e4, 0xdccad731, 0x85104263, 0x22401397, 0x112084c6, 195 | 0x247d854a, 0x3df8d2bb, 0x3211aef9, 0xa16dc729, 0x2f4b1d9e, 0x30f3dcb2, 0x52ec0d86, 0xe3d077c1, 0x166c2bb3, 0xb999a970, 0x48fa1194, 0x642247e9, 196 | 0x8cc4a8fc, 0x3f1aa0f0, 0x2cd8567d, 0x90ef2233, 0x4ec78749, 0xd1c1d938, 0xa2fe8cca, 0x0b3698d4, 0x81cfa6f5, 0xde28a57a, 0x8e26dab7, 0xbfa43fad, 197 | 0x9de42c3a, 0x920d5078, 0xcc9b6a5f, 0x4662547e, 0x13c2f68d, 0xb8e890d8, 0xf75e2e39, 0xaff582c3, 0x80be9f5d, 0x937c69d0, 0x2da96fd5, 0x12b3cf25, 198 | 0x993bc8ac, 0x7da71018, 0x636ee89c, 0xbb7bdb3b, 0x7809cd26, 0x18f46e59, 0xb701ec9a, 0x9aa8834f, 0x6e65e695, 0xe67eaaff, 0xcf0821bc, 0xe8e6ef15, 199 | 0x9bd9bae7, 0x36ce4a6f, 0x09d4ea9f, 0x7cd629b0, 0xb2af31a4, 0x23312a3f, 0x9430c6a5, 0x66c035a2, 0xbc37744e, 0xcaa6fc82, 0xd0b0e090, 0xd81533a7, 200 | 0x984af104, 0xdaf741ec, 0x500e7fcd, 0xf62f1791, 0xd68d764d, 0xb04d43ef, 0x4d54ccaa, 0x04dfe496, 0xb5e39ed1, 0x881b4c6a, 0x1fb8c12c, 0x517f4665, 201 | 0xea049d5e, 0x355d018c, 0x7473fa87, 0x412efb0b, 0x1d5ab367, 0xd25292db, 0x5633e910, 0x47136dd6, 0x618c9ad7, 0x0c7a37a1, 0x148e59f8, 0x3c89eb13, 202 | 0x27eecea9, 0xc935b761, 0xe5ede11c, 0xb13c7a47, 0xdf599cd2, 0x733f55f2, 0xce791814, 0x37bf73c7, 0xcdea53f7, 0xaa5b5ffd, 0x6f14df3d, 0xdb867844, 203 | 0xf381caaf, 0xc43eb968, 0x342c3824, 0x405fc2a3, 0xc372161d, 0x250cbce2, 0x498b283c, 0x9541ff0d, 0x017139a8, 0xb3de080c, 0xe49cd8b4, 0xc1906456, 204 | 0x84617bcb, 0xb670d532, 0x5c74486c, 0x5742d0b8, 205 | ]); 206 | 207 | export const T8 = new Uint32Array([ 208 | 0xf4a75051, 0x4165537e, 0x17a4c31a, 0x275e963a, 0xab6bcb3b, 0x9d45f11f, 0xfa58abac, 0xe303934b, 0x30fa5520, 0x766df6ad, 0xcc769188, 0x024c25f5, 209 | 0xe5d7fc4f, 0x2acbd7c5, 0x35448026, 0x62a38fb5, 0xb15a49de, 0xba1b6725, 0xea0e9845, 0xfec0e15d, 0x2f7502c3, 0x4cf01281, 0x4697a38d, 0xd3f9c66b, 210 | 0x8f5fe703, 0x929c9515, 0x6d7aebbf, 0x5259da95, 0xbe832dd4, 0x7421d358, 0xe0692949, 0xc9c8448e, 0xc2896a75, 0x8e7978f4, 0x583e6b99, 0xb971dd27, 211 | 0xe14fb6be, 0x88ad17f0, 0x20ac66c9, 0xce3ab47d, 0xdf4a1863, 0x1a3182e5, 0x51336097, 0x537f4562, 0x6477e0b1, 0x6bae84bb, 0x81a01cfe, 0x082b94f9, 212 | 0x48685870, 0x45fd198f, 0xde6c8794, 0x7bf8b752, 0x73d323ab, 0x4b02e272, 0x1f8f57e3, 0x55ab2a66, 0xeb2807b2, 0xb5c2032f, 0xc57b9a86, 0x3708a5d3, 213 | 0x2887f230, 0xbfa5b223, 0x036aba02, 0x16825ced, 0xcf1c2b8a, 0x79b492a7, 0x07f2f0f3, 0x69e2a14e, 0xdaf4cd65, 0x05bed506, 0x34621fd1, 0xa6fe8ac4, 214 | 0x2e539d34, 0xf355a0a2, 0x8ae13205, 0xf6eb75a4, 0x83ec390b, 0x60efaa40, 0x719f065e, 0x6e1051bd, 0x218af93e, 0xdd063d96, 0x3e05aedd, 0xe6bd464d, 215 | 0x548db591, 0xc45d0571, 0x06d46f04, 0x5015ff60, 0x98fb2419, 0xbde997d6, 0x4043cc89, 0xd99e7767, 0xe842bdb0, 0x898b8807, 0x195b38e7, 0xc8eedb79, 216 | 0x7c0a47a1, 0x420fe97c, 0x841ec9f8, 0x00000000, 0x80868309, 0x2bed4832, 0x1170ac1e, 0x5a724e6c, 0x0efffbfd, 0x8538560f, 0xaed51e3d, 0x2d392736, 217 | 0x0fd9640a, 0x5ca62168, 0x5b54d19b, 0x362e3a24, 0x0a67b10c, 0x57e70f93, 0xee96d2b4, 0x9b919e1b, 0xc0c54f80, 0xdc20a261, 0x774b695a, 0x121a161c, 218 | 0x93ba0ae2, 0xa02ae5c0, 0x22e0433c, 0x1b171d12, 0x090d0b0e, 0x8bc7adf2, 0xb6a8b92d, 0x1ea9c814, 0xf1198557, 0x75074caf, 0x99ddbbee, 0x7f60fda3, 219 | 0x01269ff7, 0x72f5bc5c, 0x663bc544, 0xfb7e345b, 0x4329768b, 0x23c6dccb, 0xedfc68b6, 0xe4f163b8, 0x31dccad7, 0x63851042, 0x97224013, 0xc6112084, 220 | 0x4a247d85, 0xbb3df8d2, 0xf93211ae, 0x29a16dc7, 0x9e2f4b1d, 0xb230f3dc, 0x8652ec0d, 0xc1e3d077, 0xb3166c2b, 0x70b999a9, 0x9448fa11, 0xe9642247, 221 | 0xfc8cc4a8, 0xf03f1aa0, 0x7d2cd856, 0x3390ef22, 0x494ec787, 0x38d1c1d9, 0xcaa2fe8c, 0xd40b3698, 0xf581cfa6, 0x7ade28a5, 0xb78e26da, 0xadbfa43f, 222 | 0x3a9de42c, 0x78920d50, 0x5fcc9b6a, 0x7e466254, 0x8d13c2f6, 0xd8b8e890, 0x39f75e2e, 0xc3aff582, 0x5d80be9f, 0xd0937c69, 0xd52da96f, 0x2512b3cf, 223 | 0xac993bc8, 0x187da710, 0x9c636ee8, 0x3bbb7bdb, 0x267809cd, 0x5918f46e, 0x9ab701ec, 0x4f9aa883, 0x956e65e6, 0xffe67eaa, 0xbccf0821, 0x15e8e6ef, 224 | 0xe79bd9ba, 0x6f36ce4a, 0x9f09d4ea, 0xb07cd629, 0xa4b2af31, 0x3f23312a, 0xa59430c6, 0xa266c035, 0x4ebc3774, 0x82caa6fc, 0x90d0b0e0, 0xa7d81533, 225 | 0x04984af1, 0xecdaf741, 0xcd500e7f, 0x91f62f17, 0x4dd68d76, 0xefb04d43, 0xaa4d54cc, 0x9604dfe4, 0xd1b5e39e, 0x6a881b4c, 0x2c1fb8c1, 0x65517f46, 226 | 0x5eea049d, 0x8c355d01, 0x877473fa, 0x0b412efb, 0x671d5ab3, 0xdbd25292, 0x105633e9, 0xd647136d, 0xd7618c9a, 0xa10c7a37, 0xf8148e59, 0x133c89eb, 227 | 0xa927eece, 0x61c935b7, 0x1ce5ede1, 0x47b13c7a, 0xd2df599c, 0xf2733f55, 0x14ce7918, 0xc737bf73, 0xf7cdea53, 0xfdaa5b5f, 0x3d6f14df, 0x44db8678, 228 | 0xaff381ca, 0x68c43eb9, 0x24342c38, 0xa3405fc2, 0x1dc37216, 0xe2250cbc, 0x3c498b28, 0x0d9541ff, 0xa8017139, 0x0cb3de08, 0xb4e49cd8, 0x56c19064, 229 | 0xcb84617b, 0x32b670d5, 0x6c5c7448, 0xb85742d0, 230 | ]); 231 | 232 | // Transformations for decryption key expansion 233 | export const U1 = new Uint32Array([ 234 | 0x00000000, 0x0e090d0b, 0x1c121a16, 0x121b171d, 0x3824342c, 0x362d3927, 0x24362e3a, 0x2a3f2331, 0x70486858, 0x7e416553, 0x6c5a724e, 0x62537f45, 235 | 0x486c5c74, 0x4665517f, 0x547e4662, 0x5a774b69, 0xe090d0b0, 0xee99ddbb, 0xfc82caa6, 0xf28bc7ad, 0xd8b4e49c, 0xd6bde997, 0xc4a6fe8a, 0xcaaff381, 236 | 0x90d8b8e8, 0x9ed1b5e3, 0x8ccaa2fe, 0x82c3aff5, 0xa8fc8cc4, 0xa6f581cf, 0xb4ee96d2, 0xbae79bd9, 0xdb3bbb7b, 0xd532b670, 0xc729a16d, 0xc920ac66, 237 | 0xe31f8f57, 0xed16825c, 0xff0d9541, 0xf104984a, 0xab73d323, 0xa57ade28, 0xb761c935, 0xb968c43e, 0x9357e70f, 0x9d5eea04, 0x8f45fd19, 0x814cf012, 238 | 0x3bab6bcb, 0x35a266c0, 0x27b971dd, 0x29b07cd6, 0x038f5fe7, 0x0d8652ec, 0x1f9d45f1, 0x119448fa, 0x4be30393, 0x45ea0e98, 0x57f11985, 0x59f8148e, 239 | 0x73c737bf, 0x7dce3ab4, 0x6fd52da9, 0x61dc20a2, 0xad766df6, 0xa37f60fd, 0xb16477e0, 0xbf6d7aeb, 0x955259da, 0x9b5b54d1, 0x894043cc, 0x87494ec7, 240 | 0xdd3e05ae, 0xd33708a5, 0xc12c1fb8, 0xcf2512b3, 0xe51a3182, 0xeb133c89, 0xf9082b94, 0xf701269f, 0x4de6bd46, 0x43efb04d, 0x51f4a750, 0x5ffdaa5b, 241 | 0x75c2896a, 0x7bcb8461, 0x69d0937c, 0x67d99e77, 0x3daed51e, 0x33a7d815, 0x21bccf08, 0x2fb5c203, 0x058ae132, 0x0b83ec39, 0x1998fb24, 0x1791f62f, 242 | 0x764dd68d, 0x7844db86, 0x6a5fcc9b, 0x6456c190, 0x4e69e2a1, 0x4060efaa, 0x527bf8b7, 0x5c72f5bc, 0x0605bed5, 0x080cb3de, 0x1a17a4c3, 0x141ea9c8, 243 | 0x3e218af9, 0x302887f2, 0x223390ef, 0x2c3a9de4, 0x96dd063d, 0x98d40b36, 0x8acf1c2b, 0x84c61120, 0xaef93211, 0xa0f03f1a, 0xb2eb2807, 0xbce2250c, 244 | 0xe6956e65, 0xe89c636e, 0xfa877473, 0xf48e7978, 0xdeb15a49, 0xd0b85742, 0xc2a3405f, 0xccaa4d54, 0x41ecdaf7, 0x4fe5d7fc, 0x5dfec0e1, 0x53f7cdea, 245 | 0x79c8eedb, 0x77c1e3d0, 0x65daf4cd, 0x6bd3f9c6, 0x31a4b2af, 0x3fadbfa4, 0x2db6a8b9, 0x23bfa5b2, 0x09808683, 0x07898b88, 0x15929c95, 0x1b9b919e, 246 | 0xa17c0a47, 0xaf75074c, 0xbd6e1051, 0xb3671d5a, 0x99583e6b, 0x97513360, 0x854a247d, 0x8b432976, 0xd134621f, 0xdf3d6f14, 0xcd267809, 0xc32f7502, 247 | 0xe9105633, 0xe7195b38, 0xf5024c25, 0xfb0b412e, 0x9ad7618c, 0x94de6c87, 0x86c57b9a, 0x88cc7691, 0xa2f355a0, 0xacfa58ab, 0xbee14fb6, 0xb0e842bd, 248 | 0xea9f09d4, 0xe49604df, 0xf68d13c2, 0xf8841ec9, 0xd2bb3df8, 0xdcb230f3, 0xcea927ee, 0xc0a02ae5, 0x7a47b13c, 0x744ebc37, 0x6655ab2a, 0x685ca621, 249 | 0x42638510, 0x4c6a881b, 0x5e719f06, 0x5078920d, 0x0a0fd964, 0x0406d46f, 0x161dc372, 0x1814ce79, 0x322bed48, 0x3c22e043, 0x2e39f75e, 0x2030fa55, 250 | 0xec9ab701, 0xe293ba0a, 0xf088ad17, 0xfe81a01c, 0xd4be832d, 0xdab78e26, 0xc8ac993b, 0xc6a59430, 0x9cd2df59, 0x92dbd252, 0x80c0c54f, 0x8ec9c844, 251 | 0xa4f6eb75, 0xaaffe67e, 0xb8e4f163, 0xb6edfc68, 0x0c0a67b1, 0x02036aba, 0x10187da7, 0x1e1170ac, 0x342e539d, 0x3a275e96, 0x283c498b, 0x26354480, 252 | 0x7c420fe9, 0x724b02e2, 0x605015ff, 0x6e5918f4, 0x44663bc5, 0x4a6f36ce, 0x587421d3, 0x567d2cd8, 0x37a10c7a, 0x39a80171, 0x2bb3166c, 0x25ba1b67, 253 | 0x0f853856, 0x018c355d, 0x13972240, 0x1d9e2f4b, 0x47e96422, 0x49e06929, 0x5bfb7e34, 0x55f2733f, 0x7fcd500e, 0x71c45d05, 0x63df4a18, 0x6dd64713, 254 | 0xd731dcca, 0xd938d1c1, 0xcb23c6dc, 0xc52acbd7, 0xef15e8e6, 0xe11ce5ed, 0xf307f2f0, 0xfd0efffb, 0xa779b492, 0xa970b999, 0xbb6bae84, 0xb562a38f, 255 | 0x9f5d80be, 0x91548db5, 0x834f9aa8, 0x8d4697a3, 256 | ]); 257 | 258 | export const U2 = new Uint32Array([ 259 | 0x00000000, 0x0b0e090d, 0x161c121a, 0x1d121b17, 0x2c382434, 0x27362d39, 0x3a24362e, 0x312a3f23, 0x58704868, 0x537e4165, 0x4e6c5a72, 0x4562537f, 260 | 0x74486c5c, 0x7f466551, 0x62547e46, 0x695a774b, 0xb0e090d0, 0xbbee99dd, 0xa6fc82ca, 0xadf28bc7, 0x9cd8b4e4, 0x97d6bde9, 0x8ac4a6fe, 0x81caaff3, 261 | 0xe890d8b8, 0xe39ed1b5, 0xfe8ccaa2, 0xf582c3af, 0xc4a8fc8c, 0xcfa6f581, 0xd2b4ee96, 0xd9bae79b, 0x7bdb3bbb, 0x70d532b6, 0x6dc729a1, 0x66c920ac, 262 | 0x57e31f8f, 0x5ced1682, 0x41ff0d95, 0x4af10498, 0x23ab73d3, 0x28a57ade, 0x35b761c9, 0x3eb968c4, 0x0f9357e7, 0x049d5eea, 0x198f45fd, 0x12814cf0, 263 | 0xcb3bab6b, 0xc035a266, 0xdd27b971, 0xd629b07c, 0xe7038f5f, 0xec0d8652, 0xf11f9d45, 0xfa119448, 0x934be303, 0x9845ea0e, 0x8557f119, 0x8e59f814, 264 | 0xbf73c737, 0xb47dce3a, 0xa96fd52d, 0xa261dc20, 0xf6ad766d, 0xfda37f60, 0xe0b16477, 0xebbf6d7a, 0xda955259, 0xd19b5b54, 0xcc894043, 0xc787494e, 265 | 0xaedd3e05, 0xa5d33708, 0xb8c12c1f, 0xb3cf2512, 0x82e51a31, 0x89eb133c, 0x94f9082b, 0x9ff70126, 0x464de6bd, 0x4d43efb0, 0x5051f4a7, 0x5b5ffdaa, 266 | 0x6a75c289, 0x617bcb84, 0x7c69d093, 0x7767d99e, 0x1e3daed5, 0x1533a7d8, 0x0821bccf, 0x032fb5c2, 0x32058ae1, 0x390b83ec, 0x241998fb, 0x2f1791f6, 267 | 0x8d764dd6, 0x867844db, 0x9b6a5fcc, 0x906456c1, 0xa14e69e2, 0xaa4060ef, 0xb7527bf8, 0xbc5c72f5, 0xd50605be, 0xde080cb3, 0xc31a17a4, 0xc8141ea9, 268 | 0xf93e218a, 0xf2302887, 0xef223390, 0xe42c3a9d, 0x3d96dd06, 0x3698d40b, 0x2b8acf1c, 0x2084c611, 0x11aef932, 0x1aa0f03f, 0x07b2eb28, 0x0cbce225, 269 | 0x65e6956e, 0x6ee89c63, 0x73fa8774, 0x78f48e79, 0x49deb15a, 0x42d0b857, 0x5fc2a340, 0x54ccaa4d, 0xf741ecda, 0xfc4fe5d7, 0xe15dfec0, 0xea53f7cd, 270 | 0xdb79c8ee, 0xd077c1e3, 0xcd65daf4, 0xc66bd3f9, 0xaf31a4b2, 0xa43fadbf, 0xb92db6a8, 0xb223bfa5, 0x83098086, 0x8807898b, 0x9515929c, 0x9e1b9b91, 271 | 0x47a17c0a, 0x4caf7507, 0x51bd6e10, 0x5ab3671d, 0x6b99583e, 0x60975133, 0x7d854a24, 0x768b4329, 0x1fd13462, 0x14df3d6f, 0x09cd2678, 0x02c32f75, 272 | 0x33e91056, 0x38e7195b, 0x25f5024c, 0x2efb0b41, 0x8c9ad761, 0x8794de6c, 0x9a86c57b, 0x9188cc76, 0xa0a2f355, 0xabacfa58, 0xb6bee14f, 0xbdb0e842, 273 | 0xd4ea9f09, 0xdfe49604, 0xc2f68d13, 0xc9f8841e, 0xf8d2bb3d, 0xf3dcb230, 0xeecea927, 0xe5c0a02a, 0x3c7a47b1, 0x37744ebc, 0x2a6655ab, 0x21685ca6, 274 | 0x10426385, 0x1b4c6a88, 0x065e719f, 0x0d507892, 0x640a0fd9, 0x6f0406d4, 0x72161dc3, 0x791814ce, 0x48322bed, 0x433c22e0, 0x5e2e39f7, 0x552030fa, 275 | 0x01ec9ab7, 0x0ae293ba, 0x17f088ad, 0x1cfe81a0, 0x2dd4be83, 0x26dab78e, 0x3bc8ac99, 0x30c6a594, 0x599cd2df, 0x5292dbd2, 0x4f80c0c5, 0x448ec9c8, 276 | 0x75a4f6eb, 0x7eaaffe6, 0x63b8e4f1, 0x68b6edfc, 0xb10c0a67, 0xba02036a, 0xa710187d, 0xac1e1170, 0x9d342e53, 0x963a275e, 0x8b283c49, 0x80263544, 277 | 0xe97c420f, 0xe2724b02, 0xff605015, 0xf46e5918, 0xc544663b, 0xce4a6f36, 0xd3587421, 0xd8567d2c, 0x7a37a10c, 0x7139a801, 0x6c2bb316, 0x6725ba1b, 278 | 0x560f8538, 0x5d018c35, 0x40139722, 0x4b1d9e2f, 0x2247e964, 0x2949e069, 0x345bfb7e, 0x3f55f273, 0x0e7fcd50, 0x0571c45d, 0x1863df4a, 0x136dd647, 279 | 0xcad731dc, 0xc1d938d1, 0xdccb23c6, 0xd7c52acb, 0xe6ef15e8, 0xede11ce5, 0xf0f307f2, 0xfbfd0eff, 0x92a779b4, 0x99a970b9, 0x84bb6bae, 0x8fb562a3, 280 | 0xbe9f5d80, 0xb591548d, 0xa8834f9a, 0xa38d4697, 281 | ]); 282 | 283 | export const U3 = new Uint32Array([ 284 | 0x00000000, 0x0d0b0e09, 0x1a161c12, 0x171d121b, 0x342c3824, 0x3927362d, 0x2e3a2436, 0x23312a3f, 0x68587048, 0x65537e41, 0x724e6c5a, 0x7f456253, 285 | 0x5c74486c, 0x517f4665, 0x4662547e, 0x4b695a77, 0xd0b0e090, 0xddbbee99, 0xcaa6fc82, 0xc7adf28b, 0xe49cd8b4, 0xe997d6bd, 0xfe8ac4a6, 0xf381caaf, 286 | 0xb8e890d8, 0xb5e39ed1, 0xa2fe8cca, 0xaff582c3, 0x8cc4a8fc, 0x81cfa6f5, 0x96d2b4ee, 0x9bd9bae7, 0xbb7bdb3b, 0xb670d532, 0xa16dc729, 0xac66c920, 287 | 0x8f57e31f, 0x825ced16, 0x9541ff0d, 0x984af104, 0xd323ab73, 0xde28a57a, 0xc935b761, 0xc43eb968, 0xe70f9357, 0xea049d5e, 0xfd198f45, 0xf012814c, 288 | 0x6bcb3bab, 0x66c035a2, 0x71dd27b9, 0x7cd629b0, 0x5fe7038f, 0x52ec0d86, 0x45f11f9d, 0x48fa1194, 0x03934be3, 0x0e9845ea, 0x198557f1, 0x148e59f8, 289 | 0x37bf73c7, 0x3ab47dce, 0x2da96fd5, 0x20a261dc, 0x6df6ad76, 0x60fda37f, 0x77e0b164, 0x7aebbf6d, 0x59da9552, 0x54d19b5b, 0x43cc8940, 0x4ec78749, 290 | 0x05aedd3e, 0x08a5d337, 0x1fb8c12c, 0x12b3cf25, 0x3182e51a, 0x3c89eb13, 0x2b94f908, 0x269ff701, 0xbd464de6, 0xb04d43ef, 0xa75051f4, 0xaa5b5ffd, 291 | 0x896a75c2, 0x84617bcb, 0x937c69d0, 0x9e7767d9, 0xd51e3dae, 0xd81533a7, 0xcf0821bc, 0xc2032fb5, 0xe132058a, 0xec390b83, 0xfb241998, 0xf62f1791, 292 | 0xd68d764d, 0xdb867844, 0xcc9b6a5f, 0xc1906456, 0xe2a14e69, 0xefaa4060, 0xf8b7527b, 0xf5bc5c72, 0xbed50605, 0xb3de080c, 0xa4c31a17, 0xa9c8141e, 293 | 0x8af93e21, 0x87f23028, 0x90ef2233, 0x9de42c3a, 0x063d96dd, 0x0b3698d4, 0x1c2b8acf, 0x112084c6, 0x3211aef9, 0x3f1aa0f0, 0x2807b2eb, 0x250cbce2, 294 | 0x6e65e695, 0x636ee89c, 0x7473fa87, 0x7978f48e, 0x5a49deb1, 0x5742d0b8, 0x405fc2a3, 0x4d54ccaa, 0xdaf741ec, 0xd7fc4fe5, 0xc0e15dfe, 0xcdea53f7, 295 | 0xeedb79c8, 0xe3d077c1, 0xf4cd65da, 0xf9c66bd3, 0xb2af31a4, 0xbfa43fad, 0xa8b92db6, 0xa5b223bf, 0x86830980, 0x8b880789, 0x9c951592, 0x919e1b9b, 296 | 0x0a47a17c, 0x074caf75, 0x1051bd6e, 0x1d5ab367, 0x3e6b9958, 0x33609751, 0x247d854a, 0x29768b43, 0x621fd134, 0x6f14df3d, 0x7809cd26, 0x7502c32f, 297 | 0x5633e910, 0x5b38e719, 0x4c25f502, 0x412efb0b, 0x618c9ad7, 0x6c8794de, 0x7b9a86c5, 0x769188cc, 0x55a0a2f3, 0x58abacfa, 0x4fb6bee1, 0x42bdb0e8, 298 | 0x09d4ea9f, 0x04dfe496, 0x13c2f68d, 0x1ec9f884, 0x3df8d2bb, 0x30f3dcb2, 0x27eecea9, 0x2ae5c0a0, 0xb13c7a47, 0xbc37744e, 0xab2a6655, 0xa621685c, 299 | 0x85104263, 0x881b4c6a, 0x9f065e71, 0x920d5078, 0xd9640a0f, 0xd46f0406, 0xc372161d, 0xce791814, 0xed48322b, 0xe0433c22, 0xf75e2e39, 0xfa552030, 300 | 0xb701ec9a, 0xba0ae293, 0xad17f088, 0xa01cfe81, 0x832dd4be, 0x8e26dab7, 0x993bc8ac, 0x9430c6a5, 0xdf599cd2, 0xd25292db, 0xc54f80c0, 0xc8448ec9, 301 | 0xeb75a4f6, 0xe67eaaff, 0xf163b8e4, 0xfc68b6ed, 0x67b10c0a, 0x6aba0203, 0x7da71018, 0x70ac1e11, 0x539d342e, 0x5e963a27, 0x498b283c, 0x44802635, 302 | 0x0fe97c42, 0x02e2724b, 0x15ff6050, 0x18f46e59, 0x3bc54466, 0x36ce4a6f, 0x21d35874, 0x2cd8567d, 0x0c7a37a1, 0x017139a8, 0x166c2bb3, 0x1b6725ba, 303 | 0x38560f85, 0x355d018c, 0x22401397, 0x2f4b1d9e, 0x642247e9, 0x692949e0, 0x7e345bfb, 0x733f55f2, 0x500e7fcd, 0x5d0571c4, 0x4a1863df, 0x47136dd6, 304 | 0xdccad731, 0xd1c1d938, 0xc6dccb23, 0xcbd7c52a, 0xe8e6ef15, 0xe5ede11c, 0xf2f0f307, 0xfffbfd0e, 0xb492a779, 0xb999a970, 0xae84bb6b, 0xa38fb562, 305 | 0x80be9f5d, 0x8db59154, 0x9aa8834f, 0x97a38d46, 306 | ]); 307 | 308 | export const U4 = new Uint32Array([ 309 | 0x00000000, 0x090d0b0e, 0x121a161c, 0x1b171d12, 0x24342c38, 0x2d392736, 0x362e3a24, 0x3f23312a, 0x48685870, 0x4165537e, 0x5a724e6c, 0x537f4562, 310 | 0x6c5c7448, 0x65517f46, 0x7e466254, 0x774b695a, 0x90d0b0e0, 0x99ddbbee, 0x82caa6fc, 0x8bc7adf2, 0xb4e49cd8, 0xbde997d6, 0xa6fe8ac4, 0xaff381ca, 311 | 0xd8b8e890, 0xd1b5e39e, 0xcaa2fe8c, 0xc3aff582, 0xfc8cc4a8, 0xf581cfa6, 0xee96d2b4, 0xe79bd9ba, 0x3bbb7bdb, 0x32b670d5, 0x29a16dc7, 0x20ac66c9, 312 | 0x1f8f57e3, 0x16825ced, 0x0d9541ff, 0x04984af1, 0x73d323ab, 0x7ade28a5, 0x61c935b7, 0x68c43eb9, 0x57e70f93, 0x5eea049d, 0x45fd198f, 0x4cf01281, 313 | 0xab6bcb3b, 0xa266c035, 0xb971dd27, 0xb07cd629, 0x8f5fe703, 0x8652ec0d, 0x9d45f11f, 0x9448fa11, 0xe303934b, 0xea0e9845, 0xf1198557, 0xf8148e59, 314 | 0xc737bf73, 0xce3ab47d, 0xd52da96f, 0xdc20a261, 0x766df6ad, 0x7f60fda3, 0x6477e0b1, 0x6d7aebbf, 0x5259da95, 0x5b54d19b, 0x4043cc89, 0x494ec787, 315 | 0x3e05aedd, 0x3708a5d3, 0x2c1fb8c1, 0x2512b3cf, 0x1a3182e5, 0x133c89eb, 0x082b94f9, 0x01269ff7, 0xe6bd464d, 0xefb04d43, 0xf4a75051, 0xfdaa5b5f, 316 | 0xc2896a75, 0xcb84617b, 0xd0937c69, 0xd99e7767, 0xaed51e3d, 0xa7d81533, 0xbccf0821, 0xb5c2032f, 0x8ae13205, 0x83ec390b, 0x98fb2419, 0x91f62f17, 317 | 0x4dd68d76, 0x44db8678, 0x5fcc9b6a, 0x56c19064, 0x69e2a14e, 0x60efaa40, 0x7bf8b752, 0x72f5bc5c, 0x05bed506, 0x0cb3de08, 0x17a4c31a, 0x1ea9c814, 318 | 0x218af93e, 0x2887f230, 0x3390ef22, 0x3a9de42c, 0xdd063d96, 0xd40b3698, 0xcf1c2b8a, 0xc6112084, 0xf93211ae, 0xf03f1aa0, 0xeb2807b2, 0xe2250cbc, 319 | 0x956e65e6, 0x9c636ee8, 0x877473fa, 0x8e7978f4, 0xb15a49de, 0xb85742d0, 0xa3405fc2, 0xaa4d54cc, 0xecdaf741, 0xe5d7fc4f, 0xfec0e15d, 0xf7cdea53, 320 | 0xc8eedb79, 0xc1e3d077, 0xdaf4cd65, 0xd3f9c66b, 0xa4b2af31, 0xadbfa43f, 0xb6a8b92d, 0xbfa5b223, 0x80868309, 0x898b8807, 0x929c9515, 0x9b919e1b, 321 | 0x7c0a47a1, 0x75074caf, 0x6e1051bd, 0x671d5ab3, 0x583e6b99, 0x51336097, 0x4a247d85, 0x4329768b, 0x34621fd1, 0x3d6f14df, 0x267809cd, 0x2f7502c3, 322 | 0x105633e9, 0x195b38e7, 0x024c25f5, 0x0b412efb, 0xd7618c9a, 0xde6c8794, 0xc57b9a86, 0xcc769188, 0xf355a0a2, 0xfa58abac, 0xe14fb6be, 0xe842bdb0, 323 | 0x9f09d4ea, 0x9604dfe4, 0x8d13c2f6, 0x841ec9f8, 0xbb3df8d2, 0xb230f3dc, 0xa927eece, 0xa02ae5c0, 0x47b13c7a, 0x4ebc3774, 0x55ab2a66, 0x5ca62168, 324 | 0x63851042, 0x6a881b4c, 0x719f065e, 0x78920d50, 0x0fd9640a, 0x06d46f04, 0x1dc37216, 0x14ce7918, 0x2bed4832, 0x22e0433c, 0x39f75e2e, 0x30fa5520, 325 | 0x9ab701ec, 0x93ba0ae2, 0x88ad17f0, 0x81a01cfe, 0xbe832dd4, 0xb78e26da, 0xac993bc8, 0xa59430c6, 0xd2df599c, 0xdbd25292, 0xc0c54f80, 0xc9c8448e, 326 | 0xf6eb75a4, 0xffe67eaa, 0xe4f163b8, 0xedfc68b6, 0x0a67b10c, 0x036aba02, 0x187da710, 0x1170ac1e, 0x2e539d34, 0x275e963a, 0x3c498b28, 0x35448026, 327 | 0x420fe97c, 0x4b02e272, 0x5015ff60, 0x5918f46e, 0x663bc544, 0x6f36ce4a, 0x7421d358, 0x7d2cd856, 0xa10c7a37, 0xa8017139, 0xb3166c2b, 0xba1b6725, 328 | 0x8538560f, 0x8c355d01, 0x97224013, 0x9e2f4b1d, 0xe9642247, 0xe0692949, 0xfb7e345b, 0xf2733f55, 0xcd500e7f, 0xc45d0571, 0xdf4a1863, 0xd647136d, 329 | 0x31dccad7, 0x38d1c1d9, 0x23c6dccb, 0x2acbd7c5, 0x15e8e6ef, 0x1ce5ede1, 0x07f2f0f3, 0x0efffbfd, 0x79b492a7, 0x70b999a9, 0x6bae84bb, 0x62a38fb5, 330 | 0x5d80be9f, 0x548db591, 0x4f9aa883, 0x4697a38d, 331 | ]); 332 | -------------------------------------------------------------------------------- /packages/aes/src/utils/words.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable import/prefer-default-export */ 2 | import { s2i } from '@cryptography/utils'; 3 | 4 | /** 5 | * Helper function for transforming string key to Uint32Array 6 | */ 7 | export function getWords(key: string | Uint8Array | Uint32Array) { 8 | if (key instanceof Uint32Array) { 9 | return key; 10 | } 11 | 12 | if (typeof key === 'string') { 13 | if (key.length % 4 !== 0) for (let i = key.length % 4; i <= 4; i++) key += '\0x00'; 14 | 15 | const buf = new Uint32Array(key.length / 4); 16 | for (let i = 0; i < key.length; i += 4) buf[i / 4] = s2i(key, i); 17 | 18 | return buf; 19 | } 20 | 21 | if (key instanceof Uint8Array) { 22 | const buf = new Uint32Array(key.length / 4); 23 | 24 | for (let i = 0; i < key.length; i += 4) { 25 | buf[i / 4] = ( 26 | key[i] << 24 27 | ^ key[i + 1] << 16 28 | ^ key[i + 2] << 8 29 | ^ key[i + 3] 30 | ); 31 | } 32 | 33 | return buf; 34 | } 35 | 36 | throw new Error('Unable to create 32-bit words'); 37 | } 38 | 39 | export function xor(left: Uint32Array, right: Uint32Array, to = left) { 40 | for (let i = 0; i < left.length; i++) to[i] = left[i] ^ right[i]; 41 | } 42 | -------------------------------------------------------------------------------- /packages/aes/tests/aes-ctr.test.ts: -------------------------------------------------------------------------------- 1 | import AES_CTR from "../src/modes/ctr"; 2 | 3 | test('aes | ctr', () => { 4 | // const key = 'testtesttesttest' 5 | // const counter = 'testtesttesttest'; 6 | 7 | // expect(new AES_CTR(key, counter).encrypt('Test')).toEqual(new Uint32Array([0x5167b3e6])); 8 | 9 | // expect( 10 | // new AES_CTR(key, counter).encrypt('Javascript Typed Arrays and Endianness - Stack Overflow!test') 11 | // ).toEqual( 12 | // new Uint32Array([ 13 | // 0x4f63b6f3, 0x1daa3400, 0xa71454fd, 0xbf65fa3e, 0xa75f0c3a, 0xf8644319, 14 | // 0x793565fa, 0xb5e85b07, 0x06b68603, 0x6cb4c721, 0x3719832f, 0xf1b02dbc, 15 | // 0xa75f582b, 0x111e928a, 0xe531a534 16 | // ]) 17 | // ); 18 | 19 | let cipher = new AES_CTR( 20 | new Uint32Array ([ 21 | 1788317955, 22 | 2186783659, 23 | 320254335, 24 | 2679080564, 25 | 795180033, 26 | 2779527514, 27 | 1148959518, 28 | 736706189 ]), 29 | new Uint32Array([3377455170, 2985956257, 1123921776, 2235831598]), 30 | ); 31 | 32 | expect( 33 | cipher.encrypt( 34 | new Uint32Array([ 35 | 4289449455, 36 | 3452546079, 37 | 1788317955, 38 | 2186783659, 39 | 320254335, 40 | 2679080564, 41 | 795180033, 42 | 2779527514, 43 | 1148959518, 44 | 736706189, 45 | 3377455170, 46 | 2985956257, 47 | 1123921776, 48 | 2235831598, 49 | 4008636142, 50 | 4248711487]) 51 | ), 52 | ).toEqual( 53 | new Uint32Array([ 54 | 3104947641, 55 | 4025765386, 56 | 792916097, 57 | 2328624627, 58 | 217146860, 59 | 1131069589, 60 | 494887085, 61 | 3339099703, 62 | 2049780877, 63 | 3298816209, 64 | 1125950272, 65 | 3213816239, 66 | 319267503, 67 | 770190830, 68 | 2220500043, 69 | 3775205634]), 70 | ); 71 | 72 | expect( 73 | cipher.encrypt(new Uint32Array([671088640, 0, 0, 77873706, 3853029726, 335544320, 4052647614, 3755301650, 592405371, 3797949043, 1402297070])), 74 | ).toEqual( 75 | new Uint32Array([2008889190, 3509792512, 4091984948, 3521999420, 2529971718, 1205528763, 1158985946, 3976017160, 2076128840, 3080983806, 2286077413]), 76 | ); 77 | 78 | expect( 79 | cipher.encrypt( 80 | new Uint32Array([ 81 | 1409351680, 0, 0, 70672387, 3869806942, 1073807360, 3202618071, 3755301650, 592405371, 3797949043, 1402297070, 1027755695, 2135311949, 82 | 4083347418, 1657121488, 72641170, 1291845632, 73842036, 2164260864, 560719980, 36418755, 4261413120, 1753347076, 3386287094, 19513172, 83 | 2558587879, 412040485, 2271866144, 3966353970, 4048855205, 2660874261, 4020745895, 793715613, 2238751313, 2919011912, 3624684386, 3548187467, 84 | 1130638591, 3351311194, 2431808512, 1930060847, 618172853, 2070217423, 3624798428, 484182776, 1955608522, 1111368254, 241628998, 1272946250, 85 | 1025562619, 3057733875, 1784312177, 4248472052, 1141020165, 3742838675, 3192907011, 3409833521, 1496641646, 1068361129, 926712687, 2482178215, 86 | 497924140, 2499582337, 3571737140, 601735830, 3861368028, 220579825, 4248810120, 3375258187, 4224623473, 3903275922, 1786253618, 1973256157, 87 | 2137854466, 2492982480, 3176117278, 2908993134, 3238478242, 4184997019, 1580782463, 4106181212, 1115171113, 1172500778, 2722345488, 4049367689, 88 | 2702742698, 89 | ]), 90 | ), 91 | ).toEqual( 92 | new Uint32Array([ 93 | 2933758984, 3076772971, 3273730404, 1272467913, 1947033079, 4004041343, 214513336, 2931120849, 1329742486, 3320522041, 1622095874, 1468018437, 94 | 3138923650, 1306503232, 4165922476, 3334540055, 3277938038, 3116881664, 2506302216, 4062891733, 3883149607, 2929703082, 4258744472, 442795141, 95 | 2616202819, 2940217043, 1040114950, 2119475754, 2822538337, 4125978214, 82947669, 1565639524, 585964677, 3822822402, 3157028117, 751086742, 96 | 1139952331, 115603980, 1236812231, 2019074651, 4221551635, 2664048697, 2113442491, 364496710, 3864335587, 2472242944, 2248281848, 3013608888, 97 | 981677968, 2526156500, 1904063347, 4264737492, 4198691072, 2991100821, 1419956102, 1593042988, 1602918114, 3293224993, 2453079527, 3845468421, 98 | 3968420646, 1996064586, 3331745222, 1981367209, 4191140963, 57025877, 1080372714, 2537970219, 2401826148, 3552611344, 1147844775, 618273734, 99 | 480378443, 416885094, 2321304757, 3981169777, 3962474541, 4096157063, 2778246840, 2415751217, 3198724611, 2860169670, 3175692240, 2443224797, 100 | 4236927080, 3447377821, 101 | ]), 102 | ); 103 | 104 | expect( 105 | cipher.encrypt( 106 | new Uint32Array([ 107 | 2348875776, 0, 0, 80736540, 3869806942, 2013331456, 526320885, 3755301650, 592405371, 3797949043, 1402297070, 1027755695, 2135311949, 108 | 4083347418, 1657121488, 4266656000, 2969343097, 2813990996, 3550379277, 1018692917, 1125614469, 2755878047, 2066881117, 3314673065, 109 | 3808812164, 4266725261, 3527968112, 158124639, 3255597124, 676347237, 3783581280, 3599034104, 3674670481, 1602698694, 3153513449, 1504264447, 110 | 1006639820, 116214419, 2322143494, 2815879709, 987876500, 241295355, 420563528, 3432257161, 4240035643, 3706996855, 4269166646, 2340278220, 111 | 648092869, 2771119028, 940149317, 2895106964, 945124724, 3536174676, 578947834, 1216200046, 2117928173, 3868430735, 4029597941, 715684260, 112 | 4274148334, 364385784, 4081669749, 2194523889, 1387050469, 3958251158, 2442241337, 1673071051, 2580685890, 4259991483, 2835587417, 3548847196, 113 | 3150677073, 3532736921, 168164719, 2720525604, 3508837869, 4258151087, 1834947869, 1105394374, 1309219200, 3202676998, 1714469930, 2648106133, 114 | 197240124, 281303751, 2174617750, 1208979965, 3124216217, 4085667971, 1465655262, 980440705, 4118424989, 2744524611, 2457297867, 2558396341, 115 | 333021346, 1701499759, 3041865568, 3858274447, 116 | ]), 117 | ), 118 | ).toEqual( 119 | new Uint32Array([ 120 | 798722726, 4011341536, 4286966340, 2368747607, 1035600324, 601466937, 1697150819, 17044685, 3938003480, 400869975, 2009976707, 2313090146, 121 | 3811973511, 1870931787, 2968545854, 465785826, 612294244, 2173343977, 2742135926, 165719635, 437468914, 1232068292, 4154325744, 574565466, 122 | 1142118994, 3111507152, 1365496553, 173739929, 2971467673, 1458951079, 556831006, 1222142986, 705886902, 1290815168, 3416367036, 2497987921, 123 | 1201507815, 2147383587, 3601632734, 3657651522, 1723810095, 3018551831, 3093034658, 1645389520, 1480743724, 1327414654, 2438517111, 3945386452, 124 | 2645148194, 2047233375, 4158530410, 3577025531, 633682261, 536860384, 2273652164, 3176664111, 1597185823, 2871286829, 3812561599, 2549712077, 125 | 1664736838, 1929433536, 1953520023, 711311794, 488679944, 1024438486, 2058582718, 423401757, 2676673537, 806154661, 196546409, 4006472528, 126 | 4287775770, 1326999937, 2391876748, 618548550, 3661660869, 1226608160, 1570235091, 1322894122, 4259131942, 1063319854, 1040781954, 2028463519, 127 | 2535289713, 1026491231, 3679955260, 1781353782, 470173948, 1568135357, 3526414144, 3801776996, 2857725332, 2526362690, 1733717812, 961183303, 128 | 4011578101, 3880698698, 3055551088, 3135261831, 129 | ]), 130 | ); 131 | }); 132 | -------------------------------------------------------------------------------- /packages/aes/tests/aes-ige.test.ts: -------------------------------------------------------------------------------- 1 | import AES_IGE from "../src/modes/ige"; 2 | 3 | test('aes | IGE', () => { 4 | const cipherText = new Uint32Array([ 5 | 0x28A92FE2, 0x0173B347, 0xA8BB324B, 0x5FAB2667, 0xC9A8BBCE, 0x6468D5B5, 0x09A4CBDD, 0xC186240A, 0xC912CF70, 0x06AF8926, 0xDE606A2E, 6 | 0x74C0493C, 0xAA57741E, 0x6C82451F, 0x54D3E068, 0xF5CCC49B, 0x4444124B, 0x9666FFB4, 0x05AAB564, 0xA3D01E67, 0xF6E91286, 0x7C8D20D9, 7 | 0x882707DC, 0x330B17B4, 0xE0DD57CB, 0x53BFAAFA, 0x9EF5BE76, 0xAE6C1B9B, 0x6C51E2D6, 0x502A47C8, 0x83095C46, 0xC81E3BE2, 0x5F62427B, 8 | 0x585488BB, 0x3BF23921, 0x3BF48EB8, 0xFE34C9A0, 0x26CC8413, 0x93404397, 0x4DB03556, 0x63303839, 0x2CECB51F, 0x94824E14, 0x0B986377, 9 | 0x30A4BE79, 0xA8F9DAFA, 0x39BAE81E, 0x1095849E, 0xA4C83467, 0xC92A3A17, 0xD997817C, 0x8A7AC61C, 0x3FF414DA, 0x37B7D66E, 0x949C0AEC, 10 | 0x858F0482, 0x24210FCC, 0x61F11C3A, 0x910B431C, 0xCBD104CC, 0xCC8DC6D2, 0x9D4A5D13, 0x3BE639A4, 0xC32BBFF1, 0x53E63ACA, 0x3AC52F2E, 11 | 0x4709B8AE, 0x01844B14, 0x2C1EE89D, 0x075D64F6, 0x9A399FEB, 0x04E656FE, 0x3675A6F8, 0xF412078F, 0x3D0B58DA, 0x15311C1A, 0x9F8E53B3, 12 | 0xCD6BB557, 0x2C294904, 0xB726D0BE, 0x337E2E21, 0x977DA26D, 0xD6E33270, 0x251C2CA2, 0x9DFCC702, 0x27F0755F, 0x84CFDA9A, 0xC4B8DD5F, 13 | 0x84F1D1EB, 0x36BA45CD, 0xDC70444D, 0x8C213E4B, 0xD8F63B8A, 0xB95A2D0B, 0x4180DC91, 0x283DC063, 0xACFB92D6, 0xA4E407CD, 0xE7C8C696, 14 | 0x89F77A00, 0x7441D4A6, 0xA8384B66, 0x6502D9B7, 0x7FC68B5B, 0x43CC607E, 0x60A14622, 0x3E110FCB, 0x43BC3C94, 0x2EF98193, 0x0CDC4A1D, 15 | 0x310C0B64, 0xD5E55D30, 0x8D863251, 0xAB90502C, 0x3E46CC59, 0x9E886A92, 0x7CDA963B, 0x9EB16CE6, 0x2603B685, 0x29EE98F9, 0xF5206419, 16 | 0xE03FB458, 0xEC4BD945, 0x4AA8F6BA, 0x777573CC, 0x54B32889, 0x5B1DF25E, 0xAD9FB4CD, 0x5198EE02, 0x2B2B81F3, 0x88D281D5, 0xE5BC5801, 17 | 0x07CA01A5, 0x0665C32B, 0x552715F3, 0x35FD7626, 0x4FAD00DD, 0xD5AE45B9, 0x4832AC79, 0xCE7C511D, 0x194BC42B, 0x70EFA850, 0xBB15C201, 18 | 0x2C5215CA, 0xBFE97CE6, 0x6B8D8734, 0xD0EE759A, 0x638AF013 19 | ]); 20 | 21 | const key = new Uint32Array([0xF0112808, 0x87C7BB01, 0xDF0FC4E1, 0x7830E0B9, 0x1FBB8BE4, 0xB2267CB9, 0x85AE25F3, 0x3B527253]); 22 | const iv = new Uint32Array([0x3212D579, 0xEE35452E, 0xD23E0D0C, 0x92841AA7, 0xD31B2E9B, 0xDEF2151E, 0x80D15860, 0x311C85DB]); 23 | 24 | const plainText = new Uint32Array([ 25 | 0x4b0af668, 0xcf60a358, 0x233f93b7, 0x341fca7e, 0x7f02a8c2, 0xba0d89b5, 0x3e054982, 0x8cca27e9, 0x66b301a4, 0x8fece2fc, 0xa5cf4d33, 26 | 0xf4a11ea8, 0x77ba4aa5, 0x73907330, 0x02000000, 0xfe000100, 0xc71caeb9, 0xc6b1c904, 0x8e6c522f, 0x70f13f73, 0x980d4023, 0x8e3e21c1, 27 | 0x4934d037, 0x563d930f, 0x48198a0a, 0xa7c14058, 0x229493d2, 0x2530f4db, 0xfa336f6e, 0x0ac92513, 0x9543aed4, 0x4cce7c37, 0x20fd51f6, 28 | 0x9458705a, 0xc68cd4fe, 0x6b6b13ab, 0xdc974651, 0x29693284, 0x54f18faf, 0x8c595f64, 0x2477fe96, 0xbb2a941d, 0x5bcd1d4a, 0xc8cc4988, 29 | 0x0708fa9b, 0x378e3c4f, 0x3a9060be, 0xe67cf9a4, 0xa4a69581, 0x1051907e, 0x162753b5, 0x6b0f6b41, 0x0dba74d8, 0xa84b2a14, 0xb3144e0e, 30 | 0xf1284754, 0xfd17ed95, 0x0d5965b4, 0xb9dd4658, 0x2db1178d, 0x169c6bc4, 0x65b0d6ff, 0x9ca3928f, 0xef5b9ae4, 0xe418fc15, 0xe83ebea0, 31 | 0xf87fa9ff, 0x5eed7005, 0x0ded2849, 0xf47bf959, 0xd956850c, 0xe929851f, 0x0d8115f6, 0x35b105ee, 0x2e4e15d0, 0x4b2454bf, 0x6f4fadf0, 32 | 0x34b10403, 0x119cd8e3, 0xb92fcc5b, 0xfe000100, 0x262aaba6, 0x21cc4df5, 0x87dc94cf, 0x8252258c, 0x0b9337df, 0xb47545a4, 0x9cdd5c9b, 33 | 0x8eae7236, 0xc6cadc40, 0xb24e8859, 0x0f1cc2cc, 0x762ebf1c, 0xf11dcc0b, 0x393caad6, 0xcee4ee58, 0x48001c73, 0xacbb1d12, 0x7e4cb930, 34 | 0x72aa3d1c, 0x8151b6fb, 0x6aa6124b, 0x7cd782ea, 0xf981bdcf, 0xce9d7a00, 0xe423bd9d, 0x194e8af7, 0x8ef6501f, 0x415522e4, 0x4522281c, 35 | 0x79d906dd, 0xb79c72e9, 0xc63d83fb, 0x2a940ff7, 0x79dfb5f2, 0xfd786fb4, 0xad71c9f0, 0x8cf48758, 0xe534e981, 0x5f634f1e, 0x3a80a5e1, 36 | 0xc2af210c, 0x5ab76275, 0x5ad4b212, 0x6dfa61a7, 0x7fa9da96, 0x7d65dfd0, 0xafb5cdf2, 0x6c4d4e1a, 0x88b180f4, 0xe0d0b45b, 0xa1484f95, 37 | 0xcb2712b5, 0x0bf3f596, 0x8d9d55c9, 0x9c0fb9fb, 0x67bff56d, 0x7d4481b6, 0x34514fba, 0x3488c4cd, 0xa2fc0659, 0x990e8e86, 0x8b286328, 38 | 0x75a9aa70, 0x3bcdce8f, 0xcb7ae551, 0x99e2dddd, 0x536648d8, 39 | ]); 40 | 41 | const cipher = new AES_IGE(key, iv); 42 | expect(cipher.decrypt(cipherText)).toEqual(plainText); 43 | expect(cipher.encrypt(plainText)).toEqual(cipherText); 44 | }); 45 | -------------------------------------------------------------------------------- /packages/aes/tests/aes.test.ts: -------------------------------------------------------------------------------- 1 | import AES from '../src/aes'; 2 | 3 | test('aes | encrypt', () => { 4 | expect( 5 | new AES(new Uint32Array([0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF])).encrypt('testtesttesttest') 6 | ).toEqual( 7 | new Uint32Array([-1580214082, -549871682, 1135529346, 460977466]) 8 | ) 9 | }); 10 | 11 | test('aes | decrypt', () => { 12 | expect( 13 | new AES(new Uint32Array([0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF])).decrypt('testtesttesttest') 14 | ).toEqual( 15 | new Uint32Array([-17607495, -1722016620, -19737959, -1060255347]) 16 | ) 17 | }); 18 | -------------------------------------------------------------------------------- /packages/aes/tests/precompute.test.ts: -------------------------------------------------------------------------------- 1 | import computeTables, { S, Si, T1, T2, T3, T4, T5, T6, T7, T8 } from '../src/utils/precompute'; 2 | import * as TABLES from '../src/utils/tables'; 3 | 4 | test('aes | precompute tables', () => { 5 | computeTables(); 6 | 7 | expect(S).toEqual(TABLES.S); 8 | expect(Si).toEqual(TABLES.Si); 9 | expect(T1).toEqual(TABLES.T1); 10 | expect(T2).toEqual(TABLES.T2); 11 | expect(T3).toEqual(TABLES.T3); 12 | expect(T4).toEqual(TABLES.T4); 13 | expect(T5).toEqual(TABLES.T5); 14 | expect(T6).toEqual(TABLES.T6); 15 | expect(T7).toEqual(TABLES.T7); 16 | expect(T8).toEqual(TABLES.T8); 17 | }); 18 | -------------------------------------------------------------------------------- /packages/hmac/.npmignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | 6 | # Runtime data 7 | pids 8 | *.pid 9 | *.seed 10 | 11 | # Directory for instrumented libs generated by jscoverage/JSCover 12 | lib-cov 13 | 14 | # Coverage directory used by tools like istanbul 15 | coverage 16 | 17 | # nyc test coverage 18 | .nyc_output 19 | 20 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 21 | .grunt 22 | 23 | # node-waf configuration 24 | .lock-wscript 25 | 26 | # Compiled binary addons (http://nodejs.org/api/addons.html) 27 | build/Release 28 | 29 | # Dependency directories 30 | node_modules 31 | jspm_packages 32 | 33 | # Optional npm cache directory 34 | .npm 35 | 36 | # Optional REPL history 37 | .node_repl_history 38 | 39 | # Project 40 | tests 41 | src 42 | .travis.yml 43 | .codecov.yml 44 | rollup.config.js -------------------------------------------------------------------------------- /packages/hmac/jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | roots: [ 3 | '/tests', 4 | ], 5 | transform: { 6 | '^.+\\.ts$': 'ts-jest', 7 | }, 8 | testPathIgnorePatterns: ['/dist/', '/node_modules/'], 9 | collectCoverage: true, 10 | }; 11 | -------------------------------------------------------------------------------- /packages/hmac/package.json: -------------------------------------------------------------------------------- 1 | 2 | { 3 | "name": "@cryptography/hmac", 4 | "description": "Shared internal hmac for external packages", 5 | "version": "1.0.0", 6 | "author": "Konstantin Darutkin ", 7 | "dependencies": {}, 8 | "devDependencies": {}, 9 | "license": "MIT", 10 | "main": "dist/cjs/hmac.min.js", 11 | "module": "dist/es/hmac.js", 12 | "types": "dist/typings/index.d.ts", 13 | "scripts": { 14 | "test": "jest --coverage", 15 | "build": "rm -rf dist/* && rollup -c" 16 | }, 17 | "files": [ 18 | "dist/*", 19 | "package.json" 20 | ] 21 | } -------------------------------------------------------------------------------- /packages/hmac/rollup.config.js: -------------------------------------------------------------------------------- 1 | import getTypeScriptConfig from '../../scripts/rollup'; 2 | 3 | export default getTypeScriptConfig({ 4 | packageName: 'hmac', 5 | entryFile: 'src/index.ts', 6 | }); 7 | -------------------------------------------------------------------------------- /packages/hmac/src/index.ts: -------------------------------------------------------------------------------- 1 | import { s2i } from '@cryptography/utils'; 2 | 3 | export interface HashStream { 4 | update(chunk: string | Uint32Array): HashStream; 5 | digest(): Uint32Array; 6 | digest(format: 'hex' | 'binary'): string; 7 | } 8 | 9 | export interface HashFunction { 10 | (message: string | Uint32Array): Uint32Array; 11 | (message: string | Uint32Array, format: 'hex' | 'binary'): string; 12 | stream(buf?: Uint32Array): HashStream; 13 | blockLength: number; 14 | digestLength: number; 15 | } 16 | 17 | /** 18 | * Produces the Message Authentication Code (MAC). 19 | */ 20 | function hmac(message: string | Uint32Array, key: Uint32Array, digest: HashFunction, formay?: 'array', buf?: Uint32Array): Uint32Array; 21 | function hmac(message: string | Uint32Array, key: Uint32Array, digest: HashFunction, format: 'hex' | 'binary', buf?: Uint32Array): string; 22 | function hmac(message: string | Uint32Array, key: Uint32Array, digest: HashFunction, format?: any, buf?: Uint32Array): string | Uint32Array { 23 | const ilen = digest.blockLength / 4; 24 | const ipad = new Uint32Array(ilen); 25 | const opad = new Uint32Array(ilen); 26 | 27 | // mix key into inner and outer padding 28 | // ipadding = [0x36 * blocksize] ^ key 29 | // opadding = [0x5C * blocksize] ^ key 30 | for (let i = 0; i < ilen; i += 1) { 31 | ipad[i] = 0x36363636 ^ key[i]; 32 | opad[i] = 0x5C5C5C5C ^ key[i]; 33 | } 34 | 35 | // digest is done like so: hash(opadding | hash(ipadding | message)) 36 | const inner = digest.stream().update(ipad).update(message).digest(); 37 | return digest.stream(buf).update(opad).update(inner).digest(format); 38 | } 39 | 40 | /** 41 | * Prepare string key for hmac 42 | */ 43 | hmac.key = (src: string | Uint32Array, digest: HashFunction) => { 44 | if (src instanceof Uint32Array) { 45 | if (src.length > digest.blockLength / 4) return digest(src); 46 | return src; 47 | } 48 | 49 | // if key is longer than blocksize, hash it 50 | if (src.length > digest.blockLength) return digest(src); 51 | 52 | const key = new Uint32Array(digest.blockLength); 53 | for (let i = 0; i < src.length; i += 4) key[i / 4] = s2i(src, i); 54 | 55 | return key; 56 | }; 57 | 58 | export default hmac; 59 | -------------------------------------------------------------------------------- /packages/hmac/tests/index.test.ts: -------------------------------------------------------------------------------- 1 | import sha256 from '@cryptography/sha256'; 2 | import hmac from '../src'; 3 | 4 | test('hmac | string -> array', () => { 5 | expect( 6 | hmac('Test', hmac.key('\x63\x72\x79\x70\x74\x69\x69', sha256), sha256) 7 | ).toEqual( 8 | new Uint32Array([0x69f9d988, 0x4f360ec0, 0x27e59c03, 0x23761b7b, 0x912d3620, 0x8f07c3bb, 0x259b80da, 0x80ec65bb]) 9 | ); 10 | 11 | expect( 12 | hmac( 13 | 'Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo.', 14 | hmac.key('\x63\x72\x79\x70\x74\x69\x69\x69\x69', sha256), 15 | sha256 16 | ) 17 | ).toEqual( 18 | new Uint32Array([0x0ea63456, 0x25f57cf9, 0x153dc7d8, 0xf393446e, 0x2c568e43, 0xe31014ef, 0xf1c921e7, 0xc4f29f0a]) 19 | ); 20 | 21 | expect( 22 | hmac( 23 | 'Sed', 24 | hmac.key('\x63\x72\x79\x70\x74\x69\x69'.repeat(8), sha256), 25 | sha256 26 | ) 27 | ).toEqual( 28 | new Uint32Array([0xfcaf946b, 0xb269387e, 0x24f92cae, 0x9a477320, 0x5d0cfa2c, 0xb6a8d30a, 0x986f238d, 0x9d749df4]) 29 | ); 30 | 31 | expect( 32 | hmac( 33 | 'Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo.', 34 | hmac.key('\x63\x72\x79\x70\x74\x69\x69'.repeat(8), sha256), 35 | sha256 36 | ) 37 | ).toEqual( 38 | new Uint32Array([0xcc4c4689, 0xb5cbaa55, 0x81a853e3, 0xc4a588e2, 0xc263fece, 0x504e1738, 0xf4887c71, 0x7247d477]) 39 | ); 40 | 41 | expect( 42 | hmac( 43 | 'Sed', 44 | hmac.key('\x63\x72\x79\x70\x74\x69\x69'.repeat(10), sha256), 45 | sha256 46 | ) 47 | ).toEqual( 48 | new Uint32Array([0x6051bc8b, 0x126df300, 0x6654a259, 0x12da168b, 0xb7819ed1, 0xee4bf855, 0x9254c349, 0x5c478961]) 49 | ); 50 | 51 | }); -------------------------------------------------------------------------------- /packages/pbkdf2/.npmignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | 6 | # Runtime data 7 | pids 8 | *.pid 9 | *.seed 10 | 11 | # Directory for instrumented libs generated by jscoverage/JSCover 12 | lib-cov 13 | 14 | # Coverage directory used by tools like istanbul 15 | coverage 16 | 17 | # nyc test coverage 18 | .nyc_output 19 | 20 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 21 | .grunt 22 | 23 | # node-waf configuration 24 | .lock-wscript 25 | 26 | # Compiled binary addons (http://nodejs.org/api/addons.html) 27 | build/Release 28 | 29 | # Dependency directories 30 | node_modules 31 | jspm_packages 32 | 33 | # Optional npm cache directory 34 | .npm 35 | 36 | # Optional REPL history 37 | .node_repl_history 38 | 39 | # Project 40 | tests 41 | src 42 | .travis.yml 43 | .codecov.yml 44 | rollup.config.js -------------------------------------------------------------------------------- /packages/pbkdf2/jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | roots: [ 3 | '/tests', 4 | ], 5 | transform: { 6 | '^.+\\.ts$': 'ts-jest', 7 | }, 8 | testPathIgnorePatterns: ['/dist/', '/node_modules/'], 9 | collectCoverage: true, 10 | }; 11 | -------------------------------------------------------------------------------- /packages/pbkdf2/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@cryptography/pbkdf2", 3 | "description": "https://github.com/spalt08/cryptography", 4 | "version": "0.1.1", 5 | "author": "Konstantin Darutkin", 6 | "scripts": { 7 | "test": "jest --coverage", 8 | "build": "rm -rf dist/* && rollup -c", 9 | "analyze": "npm run build -- --analyze", 10 | "prepublish": "npm test", 11 | "pretest": "npm run build", 12 | "publish": "npm publish" 13 | }, 14 | "dependencies": {}, 15 | "devDependencies": {}, 16 | "main": "dist/cjs/pbkdf2.min.js", 17 | "module": "dist/es/pbkdf2.js", 18 | "types": "dist/typings/index.d.ts", 19 | "repository": { 20 | "type": "git", 21 | "url": "git+https://github.com/spalt08/cryptography.git", 22 | "directory": "packages/pbkdf2" 23 | }, 24 | "lint-staged": { 25 | "*.{ts}": [ 26 | "eslint" 27 | ] 28 | }, 29 | "keywords": [ 30 | "pbkdf2", 31 | "javascript", 32 | "crypto" 33 | ], 34 | "publishConfig": { 35 | "access": "public" 36 | }, 37 | "bugs": { 38 | "url": "https://github.com/spalt08/cryptography/issues" 39 | }, 40 | "homepage": "https://github.com/spalt08/cryptography/tree/master/packages/pbkdf2", 41 | "files": [ 42 | "dist/*", 43 | "package.json" 44 | ], 45 | "license": "GPL-3.0-or-later" 46 | } 47 | -------------------------------------------------------------------------------- /packages/pbkdf2/rollup.config.js: -------------------------------------------------------------------------------- 1 | import getTypeScriptConfig from '../../scripts/rollup'; 2 | 3 | export default getTypeScriptConfig({ 4 | packageName: 'pbkdf2', 5 | entryFile: 'src/index.ts', 6 | }); 7 | -------------------------------------------------------------------------------- /packages/pbkdf2/src/index.ts: -------------------------------------------------------------------------------- 1 | import hmac from '@cryptography/hmac'; 2 | import { i2s } from '@cryptography/utils'; 3 | 4 | export interface HashStream { 5 | update(chunk: string | Uint32Array): HashStream; 6 | digest(): Uint32Array; 7 | digest(format: 'hex' | 'binary'): string; 8 | } 9 | 10 | export interface HashFunction { 11 | (message: string | Uint32Array): Uint32Array; 12 | (message: string | Uint32Array, format: 'hex' | 'binary'): string; 13 | stream(buf?: Uint32Array): HashStream; 14 | blockLength: number; 15 | digestLength: number; 16 | } 17 | 18 | export default function pbkdf2(pwd: string | Uint32Array, salt: string, iter: number, digest: HashFunction, out: number = 64) { 19 | const parts = Math.ceil(out / digest.digestLength); 20 | const round = (out - (parts - 1) * digest.digestLength) / 4; 21 | 22 | const pwdkey = hmac.key(pwd, digest); 23 | const u = new Uint32Array(digest.digestLength / 4); 24 | const xor = new Uint32Array(digest.digestLength / 4); 25 | const dk = new Uint32Array(out / 4); 26 | 27 | let offset = 0; 28 | 29 | for (let i = 1; i <= parts; i += 1) { 30 | // PRF(P, S || INT(i)) (first iteration) 31 | hmac(salt + i2s(i), pwdkey, digest, 'array', u); 32 | xor.set(u); 33 | 34 | // PRF(P, u_{c-1}) (other iterations) 35 | for (let j = 2; j <= iter; j += 1) { 36 | u.set(hmac(u, pwdkey, digest)); 37 | 38 | // F(p, s, c, i) 39 | for (let k = 0; k < xor.length; k++) xor[k] ^= u[k]; 40 | } 41 | 42 | dk.set(i < parts ? xor : xor.subarray(0, round), offset); 43 | offset += xor.length; 44 | } 45 | 46 | return dk; 47 | } 48 | -------------------------------------------------------------------------------- /packages/pbkdf2/tests/index.test.ts: -------------------------------------------------------------------------------- 1 | import pbkdf2 from '../src/index'; 2 | import sha512 from '@cryptography/sha512'; 3 | 4 | test('pbkdf2', () => { 5 | expect( 6 | pbkdf2('Test', 'Hallo', 1000, sha512, 64), 7 | ).toEqual( 8 | new Uint32Array([ 9 | 0x217ba952, 0xda0c37f5, 0x1a31fc2d, 0xecc0b6f0, 0x661c36b2, 0x64795dde, 0x323933be, 0xea8ee3ea, 0xb3fb1747, 0xc779cb9f, 0xea529b44, 0xcc9d21a3, 0x23d82147, 0x4e3b950e, 0x1fe780ce, 0x8daae14f 10 | ]), 11 | //'\x21\x7b\xa9\x52\xda\x0c\x37\xf5\x1a\x31\xfc\x2d\xec\xc0\xb6\xf0\x66\x1c\x36\xb2\x64\x79\x5d\xde\x32\x39\x33\xbe\xea\x8e\xe3\xea\xb3\xfb\x17\x47\xc7\x79\xcb\x9f\xea\x52\x9b\x44\xcc\x9d\x21\xa3\x23\xd8\x21\x47\x4e\x3b\x95\x0e\x1f\xe7\x80\xce\x8d\xaa\xe1\x4f', 12 | ) 13 | 14 | expect( 15 | pbkdf2('Testdsdsfsdds', 'Hallodsds', 100, sha512, 32), 16 | ).toEqual( 17 | new Uint32Array([0xd2f26352, 0x3575927a, 0xf455d809, 0x031ea95c, 0x45f30273, 0x1295eef2, 0x53232a33, 0xbaa5fcaf]), 18 | ); 19 | 20 | expect( 21 | pbkdf2('Testdsdsfsddsdsfsdsdfsf', 'Hallodsds34424232dsfsdfsdfefwerwerr', 100000, sha512, 64), 22 | ).toEqual( 23 | new Uint32Array([ 24 | 0xc91489de, 0xeae689bd, 0x09c141d6, 0x7bd3af51, 0x86098b4d, 0x8012e774, 0xbee7cc38, 0x0a1ee37d, 0x5534a6ab, 0x4c554b06, 0xf282e3f8, 0x8b3c0cbc, 0x914716a4, 0x99035e65, 0x3ad7f9d2, 0xf24732ee 25 | ]), 26 | ); 27 | }); -------------------------------------------------------------------------------- /packages/sha1/.npmignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | 6 | # Runtime data 7 | pids 8 | *.pid 9 | *.seed 10 | 11 | # Directory for instrumented libs generated by jscoverage/JSCover 12 | lib-cov 13 | 14 | # Coverage directory used by tools like istanbul 15 | coverage 16 | 17 | # nyc test coverage 18 | .nyc_output 19 | 20 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 21 | .grunt 22 | 23 | # node-waf configuration 24 | .lock-wscript 25 | 26 | # Compiled binary addons (http://nodejs.org/api/addons.html) 27 | build/Release 28 | 29 | # Dependency directories 30 | node_modules 31 | jspm_packages 32 | 33 | # Optional npm cache directory 34 | .npm 35 | 36 | # Optional REPL history 37 | .node_repl_history 38 | 39 | # Project 40 | tests 41 | src 42 | .travis.yml 43 | .codecov.yml 44 | rollup.config.js -------------------------------------------------------------------------------- /packages/sha1/README.md: -------------------------------------------------------------------------------- 1 | # @cryptography/sha1 2 | [![Bundlephobia](https://img.shields.io/bundlephobia/minzip/@cryptography/sha256)](https://bundlephobia.com/result?p=@cryptography/sha1@0.2.0) 3 | [![Coverage](https://img.shields.io/codecov/c/github/spalt08/cryptography?token=617017dc35344eb6b4637420457746c8)](https://codecov.io/gh/spalt08/cryptography) 4 | [![Travis CI](https://img.shields.io/travis/spalt08/cryptography)](https://travis-ci.com/spalt08/cryptography) 5 | 6 | High-performance synchronous SHA-1 implementation for JavaScript. Optimized for browsers. 7 | 8 | ## Features 9 | * Blazing fast 10 | * Ultra lightweight 11 | * ECMAScript 3-6 12 | * Typed 13 | * Tested` 14 | 15 | ## Setup 16 | [Package](https://www.npmjs.com/package/@cryptography/sha1) is available through `npm` and `yarn` 17 | ``` 18 | npm install @cryptography/sha1 19 | ``` 20 | ``` 21 | yarn add @cryptography/sha1 22 | ```` 23 | 24 | ### When you should use @cryptography/sha1 25 | * Hashing small inputs (< 5kb) 26 | * Key derivation functions 27 | * 100% browser support required 28 | 29 | ### ⚠️ When you should not use this (WebCrypto API preferred cases) 30 | * Hashing files (> 5kb) 31 | * Concurrent hashing large amount of messages 32 | 33 | ## Usage 34 | This package is optimized for small byte inputs (<10kb). 35 | 36 | Also, it is highly recommended to run CPU-intensive tasks in a [Web Worker](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers). 37 | ```js 38 | import sha1 from '@cryptography/sha1' 39 | 40 | // as Uint32Array([0xa8d627d9, 0x3f518e90, 0x96b6f40e, 0x36d27b76, 0x60fa26d3]) 41 | const array = sha1('Hello World!') 42 | 43 | // as hex-string: "a8d627d93f518e9096b6f4...." 44 | const hex = sha1('Hello World!', 'hex') 45 | 46 | // as binary string: "ÄïükYo‡UH½LÛ,Zß..." 47 | const raw = sha1('Hello World!', 'binary') 48 | 49 | // UInt32Array as input 50 | const buf = new Uint32Array([0xa8d627d9, 0x3f518e90, 0x96b6f40e, 0x36d27b76, 0x60fa26d3, 0x18ef1adc, 0x43da750e, 0x49ebe4be]); 51 | sha1(buf) 52 | ``` 53 | For hashing large files or other data chuncks use `stream()` to create a hashing stream. 54 | ```js 55 | sha1.stream().update('Hello World!').digest(); 56 | ``` 57 | 58 | ## Benchmarks 59 | Faster than [forge](https://github.com/digitalbazaar/forge), [sjcl](https://github.com/bitwiseshiftleft/sjcl), Rusha and [WebCrypto API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Crypto_API) in **sequence** mode. 60 | 61 | ### Try yourself 62 | * https://jsbench.me/k8k3b15kg0 63 | 64 | ## Contributing 65 | Contributions are welcome! Contribution guidelines will be published soon. -------------------------------------------------------------------------------- /packages/sha1/jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | roots: [ 3 | '/tests', 4 | ], 5 | transform: { 6 | '^.+\\.ts$': 'ts-jest', 7 | }, 8 | testPathIgnorePatterns: ['/dist/', '/node_modules/'], 9 | collectCoverage: true, 10 | }; 11 | -------------------------------------------------------------------------------- /packages/sha1/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@cryptography/sha1", 3 | "description": "High-performance synchronous SHA-1 implementation for JavaScript", 4 | "version": "0.2.0", 5 | "author": "Konstantin Darutkin", 6 | "scripts": { 7 | "test": "jest --coverage", 8 | "build": "rm -rf dist/* && rollup -c", 9 | "analyze": "npm run build -- --analyze", 10 | "prepublish": "npm test", 11 | "pretest": "npm run build", 12 | "publish": "npm publish" 13 | }, 14 | "devDependencies": { 15 | "@cryptography/utils": "^1.0.0" 16 | }, 17 | "main": "dist/cjs/sha1.min.js", 18 | "module": "dist/es/sha1.js", 19 | "types": "dist/typings/index.d.ts", 20 | "repository": { 21 | "type": "git", 22 | "url": "git+https://github.com/spalt08/cryptography.git", 23 | "directory": "packages/sha1" 24 | }, 25 | "publishConfig": { 26 | "access": "public" 27 | }, 28 | "lint-staged": { 29 | "*.{ts}": [ 30 | "eslint" 31 | ] 32 | }, 33 | "keywords": [ 34 | "sha1", 35 | "javascript", 36 | "crypto" 37 | ], 38 | "bugs": { 39 | "url": "https://github.com/spalt08/cryptography/issues" 40 | }, 41 | "homepage": "https://github.com/spalt08/cryptography/tree/master/packages/sha1", 42 | "files": [ 43 | "dist/*", 44 | "package.json" 45 | ], 46 | "license": "GPL-3.0-or-later" 47 | } -------------------------------------------------------------------------------- /packages/sha1/rollup.config.js: -------------------------------------------------------------------------------- 1 | import getTypeScriptConfig from '../../scripts/rollup'; 2 | 3 | export default getTypeScriptConfig({ 4 | packageName: 'sha1', 5 | entryFile: 'src/index.ts', 6 | inlineDynamicImports: true, 7 | }); 8 | -------------------------------------------------------------------------------- /packages/sha1/src/index.ts: -------------------------------------------------------------------------------- 1 | import { s2i, i2s, i2h } from '@cryptography/utils'; 2 | 3 | /** 4 | * Creates new SHA-1 state 5 | */ 6 | function init(h?: Uint32Array): Uint32Array { 7 | if (!h) h = new Uint32Array(5); 8 | 9 | // SHA-1 state contains five 32-bit integers 10 | h[0] = 0x67452301; 11 | h[1] = 0xEFCDAB89; 12 | h[2] = 0x98BADCFE; 13 | h[3] = 0x10325476; 14 | h[4] = 0xC3D2E1F0; 15 | 16 | return h; 17 | } 18 | 19 | /** Array to use to store round words. */ 20 | const words = new Uint32Array(80); 21 | 22 | /** 23 | * Perform round function 24 | */ 25 | function round(state: Uint32Array, data: Uint32Array) { 26 | let i = 0; let t = 0; let f = 0; 27 | 28 | // initialize hash value for this chunk 29 | let a = state[0]; 30 | let b = state[1]; 31 | let c = state[2]; 32 | let d = state[3]; 33 | let e = state[4]; 34 | 35 | // round 1 36 | for (i = 0; i < 16; i += 1) { 37 | words[i] = data[i]; 38 | 39 | f = d ^ (b & (c ^ d)); 40 | t = ((a << 5) | (a >>> 27)) + f + e + 0x5A827999 + words[i]; 41 | e = d; 42 | d = c; 43 | c = ((b << 30) | (b >>> 2)) >>> 0; 44 | b = a; 45 | a = t; 46 | } 47 | 48 | for (; i < 20; i += 1) { 49 | t = (words[i - 3] ^ words[i - 8] ^ words[i - 14] ^ words[i - 16]); 50 | t = (t << 1) | (t >>> 31); 51 | words[i] = t; 52 | 53 | f = d ^ (b & (c ^ d)); 54 | t = ((a << 5) | (a >>> 27)) + f + e + 0x5A827999 + t; 55 | e = d; 56 | d = c; 57 | // `>>> 0` necessary to avoid iOS/Safari 10 optimization bug 58 | c = ((b << 30) | (b >>> 2)) >>> 0; 59 | b = a; 60 | a = t; 61 | } 62 | 63 | // round 2 64 | for (; i < 32; i += 1) { 65 | t = (words[i - 3] ^ words[i - 8] ^ words[i - 14] ^ words[i - 16]); 66 | t = (t << 1) | (t >>> 31); 67 | words[i] = t; 68 | f = b ^ c ^ d; 69 | t = ((a << 5) | (a >>> 27)) + f + e + 0x6ED9EBA1 + t; 70 | e = d; 71 | d = c; 72 | // `>>> 0` necessary to avoid iOS/Safari 10 optimization bug 73 | c = ((b << 30) | (b >>> 2)) >>> 0; 74 | b = a; 75 | a = t; 76 | } 77 | 78 | for (; i < 40; i += 1) { 79 | t = (words[i - 6] ^ words[i - 16] ^ words[i - 28] ^ words[i - 32]); 80 | t = (t << 2) | (t >>> 30); 81 | words[i] = t; 82 | f = b ^ c ^ d; 83 | t = ((a << 5) | (a >>> 27)) + f + e + 0x6ED9EBA1 + t; 84 | e = d; 85 | d = c; 86 | // `>>> 0` necessary to avoid iOS/Safari 10 optimization bug 87 | c = ((b << 30) | (b >>> 2)) >>> 0; 88 | b = a; 89 | a = t; 90 | } 91 | 92 | // round 3 93 | for (; i < 60; i += 1) { 94 | t = (words[i - 6] ^ words[i - 16] ^ words[i - 28] ^ words[i - 32]); 95 | t = (t << 2) | (t >>> 30); 96 | words[i] = t; 97 | f = (b & c) | (d & (b ^ c)); 98 | t = ((a << 5) | (a >>> 27)) + f + e + 0x8F1BBCDC + t; 99 | e = d; 100 | d = c; 101 | // `>>> 0` necessary to avoid iOS/Safari 10 optimization bug 102 | c = ((b << 30) | (b >>> 2)) >>> 0; 103 | b = a; 104 | a = t; 105 | } 106 | 107 | // round 4 108 | for (; i < 80; i += 1) { 109 | t = (words[i - 6] ^ words[i - 16] ^ words[i - 28] ^ words[i - 32]); 110 | t = (t << 2) | (t >>> 30); 111 | words[i] = t; 112 | f = b ^ c ^ d; 113 | t = ((a << 5) | (a >>> 27)) + f + e + 0xCA62C1D6 + t; 114 | e = d; 115 | d = c; 116 | // `>>> 0` necessary to avoid iOS/Safari 10 optimization bug 117 | c = ((b << 30) | (b >>> 2)) >>> 0; 118 | b = a; 119 | a = t; 120 | } 121 | 122 | // update hash state 123 | state[0] += a; 124 | state[1] += b; 125 | state[2] += c; 126 | state[3] += d; 127 | state[4] += e; 128 | } 129 | 130 | /** 131 | * Pre-processing round buffer for string input 132 | */ 133 | function preprocess(str: string, buf: Uint32Array, state: Uint32Array, offset: number = 0) { 134 | while (str.length >= 64) { 135 | for (let i = offset; i < 16; i++) buf[i] = s2i(str, i * 4); 136 | str = str.slice(64 - offset * 4); 137 | offset = 0; 138 | 139 | round(state, buf); 140 | } 141 | 142 | return str; 143 | } 144 | 145 | /** 146 | * Process input buffer 147 | */ 148 | function process(input: Uint32Array, buf: Uint32Array, state: Uint32Array, offset: number = 0) { 149 | while (input.length >= buf.length - offset) { 150 | for (let i = 0; i < buf.length - offset; i++) buf[offset + i] = input[i]; 151 | input = input.subarray(buf.length - offset); 152 | offset = 0; 153 | 154 | round(state, buf); 155 | } 156 | 157 | if (input.length > 0) { 158 | for (let i = 0; i < input.length; i++) buf[offset + i] = input[i]; 159 | offset += input.length; 160 | } 161 | 162 | return offset; 163 | } 164 | 165 | /** 166 | * Repeatable part 167 | */ 168 | function finish(len: number, buf: Uint32Array, state: Uint32Array, offset: number = 0) { 169 | const len64hi = (len / 0x100000000) >>> 0; 170 | const len64lo = len >>> 0; 171 | 172 | for (let i = offset + 1; i < buf.length; i++) buf[i] = 0; 173 | 174 | if (offset >= 14) { 175 | round(state, buf); 176 | for (let i = 0; i < buf.length; i++) buf[i] = 0; 177 | } 178 | 179 | buf[14] = (len64hi << 3) + ((len64lo << 3) / 0x100000000 >>> 0); 180 | buf[15] = len64lo << 3; 181 | 182 | round(state, buf); 183 | } 184 | 185 | /** 186 | * Adds padding to message 187 | */ 188 | function finalizestr(chunk: string, len: number, buf: Uint32Array, state: Uint32Array, offset: number = 0) { 189 | for (; chunk.length >= 4; offset++) { 190 | buf[offset] = s2i(chunk, 0); 191 | chunk = chunk.slice(4); 192 | } 193 | 194 | if (offset >= 16) { 195 | round(state, buf); 196 | offset = 0; 197 | } 198 | 199 | buf[offset] = s2i(`${chunk}\x80\x00\x00\x00`, 0); 200 | finish(len, buf, state, offset); 201 | } 202 | 203 | /** 204 | * Adds padding to buffer 205 | */ 206 | function finalize(len: number, buf: Uint32Array, state: Uint32Array, offset: number = 0) { 207 | buf[offset] = 0x80000000; 208 | finish(len, buf, state, offset); 209 | } 210 | 211 | /** 212 | * Output depending on format 213 | */ 214 | function out(state: Uint32Array, format: 'array'): Uint32Array; 215 | function out(state: Uint32Array, format: 'hex' | 'binary'): string; 216 | function out(state: Uint32Array, format: any = 'array') { 217 | switch (format) { 218 | case 'hex': return ( 219 | i2h(state[0]) 220 | + i2h(state[1]) 221 | + i2h(state[2]) 222 | + i2h(state[3]) 223 | + i2h(state[4]) 224 | ); 225 | 226 | case 'binary': return ( 227 | i2s(state[0]) 228 | + i2s(state[1]) 229 | + i2s(state[2]) 230 | + i2s(state[3]) 231 | + i2s(state[4]) 232 | ); 233 | 234 | default: return state; 235 | } 236 | } 237 | /** 238 | * Stream handler for hashing 239 | */ 240 | class Stream { 241 | buffer: Uint32Array; 242 | state: Uint32Array; 243 | length: number; 244 | offset: number; 245 | tail: string; 246 | 247 | constructor(buf?: Uint32Array) { 248 | this.buffer = new Uint32Array(16); 249 | this.state = init(buf); 250 | this.length = 0; 251 | this.offset = 0; 252 | this.tail = ''; 253 | } 254 | 255 | update(chunk: string | Uint32Array) { 256 | if (typeof chunk === 'string') { 257 | this.length += chunk.length; 258 | this.tail = preprocess(this.tail + chunk, this.buffer, this.state, this.offset); 259 | this.offset = 0; 260 | } else { 261 | if (this.tail.length > 0) throw new Error('Unable to update hash-stream with array'); 262 | 263 | this.length += chunk.length * 4; 264 | this.offset = process(chunk, this.buffer, this.state, this.offset); 265 | } 266 | 267 | return this; 268 | } 269 | 270 | digest(): Uint32Array; 271 | digest(format: 'hex' | 'binary'): string; 272 | digest(format: any = 'array'): any { 273 | if (this.tail.length > 0) { 274 | finalizestr(this.tail, this.length, this.buffer, this.state, this.offset); 275 | } else { 276 | finalize(this.length, this.buffer, this.state, this.offset); 277 | } 278 | 279 | return out(this.state, format); 280 | } 281 | 282 | clear() { 283 | this.state = init(); 284 | this.length = 0; 285 | this.offset = 0; 286 | this.tail = ''; 287 | } 288 | } 289 | 290 | /** 291 | * Hash as single function 292 | */ 293 | function sha1(message: string | Uint32Array): Uint32Array; 294 | function sha1(message: string | Uint32Array, format: 'hex' | 'binary'): string; 295 | function sha1(message: string | Uint32Array, format: any = 'array'): string | Uint32Array { 296 | const buf = new Uint32Array(16); 297 | const state = init(); 298 | 299 | if (typeof message === 'string') finalizestr(preprocess(message, buf, state), message.length, buf, state); 300 | else finalize(message.length * 4, buf, state, process(message, buf, state)); 301 | 302 | return out(state, format); 303 | } 304 | 305 | /** 306 | * Hash with stream constructor 307 | */ 308 | sha1.stream = (buf?: Uint32Array) => new Stream(buf); 309 | sha1.blockLength = 64; 310 | sha1.digestLength = 20; 311 | 312 | export default sha1; 313 | -------------------------------------------------------------------------------- /packages/sha1/tests/index.test.ts: -------------------------------------------------------------------------------- 1 | import sha1 from '../src/index'; 2 | 3 | test('sha1 | function output length', () => { 4 | expect(sha1('Hello world!', 'hex').length).toEqual(40); 5 | expect(sha1('Hello world!', 'binary').length).toEqual(20); 6 | expect(sha1('Hello world!').length).toEqual(5); 7 | }); 8 | 9 | test('sha1 | function (string -> hex)', () => { 10 | expect(sha1('', 'hex')).toEqual('da39a3ee5e6b4b0d3255bfef95601890afd80709'); 11 | expect(sha1('Hello world!', 'hex')).toEqual('d3486ae9136e7856bc42212385ea797094475802'); 12 | expect( 13 | sha1( 14 | 'Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo ' 15 | + 'inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo.', 16 | 'hex' 17 | ) 18 | ).toEqual('e607a674e3c8454398a7d33a28268f44719af694'); 19 | }); 20 | 21 | test('sha1 | function result (string -> binary)', () => { 22 | expect(sha1('Test Input', 'binary')).toEqual('\x65\x83\x28\x19\xbb\xcf\x7e\x58\x83\x61\x6c\x62\x59\xb3\xda\x34\xae\x6a\x0d\x84'); 23 | 24 | expect( 25 | sha1( 26 | 'More generally, cryptography is about constructing and analyzing protocols that prevent third parties or the public from reading private ' 27 | + 'messages;[3] various aspects in information security such as data confidentiality, data integrity, authentication, and non-repudiation[4] ' 28 | + 'are central to modern cryptography. Modern cryptography exists at the intersection of the disciplines of mathematics, computer science, ' 29 | + 'electrical engineering, communication science, and physics. Applications of cryptography include electronic commerce, chip-based payment cards, ' 30 | + 'digital currencies, computer passwords, and military communications.', 31 | 'binary' 32 | ) 33 | ).toEqual('\x3d\x17\xba\x26\x43\x81\x8c\x1a\x96\x79\xf6\xb9\x74\x3a\xde\x1e\xc6\xe0\xd3\xe1') 34 | }); 35 | 36 | test('sha1 | function (string -> array)', () => { 37 | expect(sha1('JavaScript Monorepo')).toEqual( 38 | new Uint32Array([0x0c66cacb, 0xeb061a37, 0xadb2e204, 0xf6b4c9c0, 0x9f1f142d]) 39 | ); 40 | }); 41 | 42 | test('sha256 | function (array -> array)', () => { 43 | expect( 44 | sha1(new Uint32Array([0x54657374, 0x54657374])) 45 | ).toEqual( 46 | new Uint32Array([0x7df71b73, 0x819f2e0c, 0x618339a2, 0xa45308a9, 0x775e3c6f]) 47 | ); 48 | }); 49 | 50 | test('sha256 | stream', () => { 51 | let stream = sha1.stream(); 52 | 53 | stream.update(new Uint32Array([0x54657374])); 54 | stream.update(new Uint32Array([0x54657374])); 55 | expect(stream.digest()).toEqual(new Uint32Array([0x7df71b73, 0x819f2e0c, 0x618339a2, 0xa45308a9, 0x775e3c6f])); 56 | stream.clear(); 57 | 58 | stream.update('More generally, cryptography is about constructing and analyzing protocols that prevent third parties or the public from reading private '); 59 | stream.update('messages;[3] various aspects in information security such as data confidentiality, data integrity, authentication, and non-repudiation[4] '); 60 | stream.update('are central to modern cryptography. Modern cryptography exists at the intersection of the disciplines of mathematics, computer science, '); 61 | stream.update('electrical engineering, communication science, and physics. Applications of cryptography include electronic commerce, chip-based payment cards, '); 62 | stream.update('digital currencies, computer passwords, and military communications.'); 63 | expect(stream.digest('binary')).toEqual('\x3d\x17\xba\x26\x43\x81\x8c\x1a\x96\x79\xf6\xb9\x74\x3a\xde\x1e\xc6\xe0\xd3\xe1') 64 | }); 65 | -------------------------------------------------------------------------------- /packages/sha256/.npmignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | 6 | # Runtime data 7 | pids 8 | *.pid 9 | *.seed 10 | 11 | # Directory for instrumented libs generated by jscoverage/JSCover 12 | lib-cov 13 | 14 | # Coverage directory used by tools like istanbul 15 | coverage 16 | 17 | # nyc test coverage 18 | .nyc_output 19 | 20 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 21 | .grunt 22 | 23 | # node-waf configuration 24 | .lock-wscript 25 | 26 | # Compiled binary addons (http://nodejs.org/api/addons.html) 27 | build/Release 28 | 29 | # Dependency directories 30 | node_modules 31 | jspm_packages 32 | 33 | # Optional npm cache directory 34 | .npm 35 | 36 | # Optional REPL history 37 | .node_repl_history 38 | 39 | # Project 40 | tests 41 | src 42 | .travis.yml 43 | .codecov.yml 44 | rollup.config.js -------------------------------------------------------------------------------- /packages/sha256/README.md: -------------------------------------------------------------------------------- 1 | # @cryptography/sha256 2 | [![Bundlephobia](https://img.shields.io/bundlephobia/minzip/@cryptography/sha256)](https://bundlephobia.com/result?p=@cryptography/sha256@0.2.0) 3 | [![Coverage](https://img.shields.io/codecov/c/github/spalt08/cryptography?token=617017dc35344eb6b4637420457746c8)](https://codecov.io/gh/spalt08/cryptography) 4 | [![Travis CI](https://img.shields.io/travis/spalt08/cryptography)](https://travis-ci.com/spalt08/cryptography) 5 | 6 | High-performance synchronous SHA-256 implementation for JavaScript. Optimized for browsers. 7 | 8 | ## Features 9 | * Blazing fast 10 | * Ultra lightweight 11 | * ECMAScript 3-6 12 | * Typed 13 | * Tested` 14 | 15 | ## Setup 16 | [Package](https://www.npmjs.com/package/@cryptography/sha256) is available through `npm` and `yarn` 17 | ``` 18 | npm install @cryptography/sha256 19 | ``` 20 | ``` 21 | yarn add @cryptography/sha256 22 | ```` 23 | 24 | ### When you should use @cryptography/sha256 25 | * Hashing small inputs (< 5kb) 26 | * Key derivation functions 27 | * 100% browser support required 28 | 29 | ### ⚠️ When you should not use this (WebCrypto API preferred cases) 30 | * Hashing files (> 5kb) 31 | * Concurrent hashing large amount of messages 32 | 33 | ## Usage 34 | This package is optimized for small byte inputs (<10kb). 35 | 36 | Also, it is highly recommended to run CPU-intensive tasks in a [Web Worker](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers). 37 | ```js 38 | import sha256 from '@cryptography/sha256' 39 | 40 | // as Uint32Array([0xa8d627d9, 0x3f518e90, 0x96b6f40e, 0x36d27b76, 0x60fa26d3, 0x18ef1adc, 0x43da750e, 0x49ebe4be]) 41 | const array = sha256('Hello World!') 42 | 43 | // as hex-string: "a8d627d93f518e9096b6f40e36d27b7660fa26d318ef1adc43da750e49ebe4be" 44 | const hex = sha256('Hello World!', 'hex') 45 | 46 | // as binary string: "ÄïükYo‡UH½LÛ,Zß\nNÆêE©¡‡`M¢" 47 | const raw = sha256('Hello World!', 'binary') 48 | 49 | // UInt32Array as input 50 | const buf = new Uint32Array([0xa8d627d9, 0x3f518e90, 0x96b6f40e, 0x36d27b76, 0x60fa26d3, 0x18ef1adc, 0x43da750e, 0x49ebe4be]); 51 | sha256(buf) 52 | ``` 53 | For hashing large files or other data chuncks use `stream()` to create a hashing stream. 54 | ```js 55 | sha256.stream().update('Hello World!').digest(); 56 | ``` 57 | 58 | ## Benchmarks 59 | Faster than [forge](https://github.com/digitalbazaar/forge), [sjcl](https://github.com/bitwiseshiftleft/sjcl) and [WebCrypto API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Crypto_API) in **sequence** mode. 60 | 61 | ### 2x faster at desktop browsers (benchmarked with Macbook Pro 2016) 62 | ![Macbook 2016 perfromance](./files/perf_macbook.png) 63 | 64 | ### 4x faster at mobile browsers (benchmarked with iPhone 6S 13.2) 65 | ![iPhone 6S perfromance](./files/perf_iphone.png) 66 | 67 | ### Try yourself 68 | * http://jsben.ch/Um0Uc 69 | * https://jsbench.me/i1k3b0xrvy/4 70 | 71 | ## Contributing 72 | Contributions are welcome! Contribution guidelines will be published soon. -------------------------------------------------------------------------------- /packages/sha256/files/perf_iphone.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spalt08/cryptography/3809cc8c81e1f1157326a912cb08852bdad7a1e0/packages/sha256/files/perf_iphone.png -------------------------------------------------------------------------------- /packages/sha256/files/perf_macbook.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spalt08/cryptography/3809cc8c81e1f1157326a912cb08852bdad7a1e0/packages/sha256/files/perf_macbook.png -------------------------------------------------------------------------------- /packages/sha256/jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | roots: [ 3 | '/tests', 4 | ], 5 | transform: { 6 | '^.+\\.ts$': 'ts-jest', 7 | }, 8 | testPathIgnorePatterns: ['/dist/', '/node_modules/'], 9 | collectCoverage: true, 10 | }; 11 | -------------------------------------------------------------------------------- /packages/sha256/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@cryptography/sha256", 3 | "description": "High-performance synchronous SHA-256 implementation for JavaScript", 4 | "version": "0.2.0", 5 | "author": "Konstantin Darutkin", 6 | "scripts": { 7 | "test": "jest --coverage", 8 | "build": "rm -rf dist/* && rollup -c", 9 | "analyze": "npm run build -- --analyze", 10 | "prepublish": "npm test", 11 | "pretest": "npm run build", 12 | "publish": "npm publish" 13 | }, 14 | "devDependencies": { 15 | "@cryptography/utils": "^1.0.0" 16 | }, 17 | "main": "dist/cjs/sha256.min.js", 18 | "module": "dist/es/sha256.js", 19 | "types": "dist/typings/index.d.ts", 20 | "repository": { 21 | "type": "git", 22 | "url": "git+https://github.com/spalt08/cryptography.git", 23 | "directory": "packages/sha256" 24 | }, 25 | "publishConfig": { 26 | "access": "public" 27 | }, 28 | "lint-staged": { 29 | "*.{ts}": [ 30 | "eslint" 31 | ] 32 | }, 33 | "keywords": [ 34 | "sha256", 35 | "javascript", 36 | "crypto" 37 | ], 38 | "bugs": { 39 | "url": "https://github.com/spalt08/cryptography/issues" 40 | }, 41 | "homepage": "https://github.com/spalt08/cryptography/tree/master/packages/sha256", 42 | "files": [ 43 | "dist/*", 44 | "package.json" 45 | ], 46 | "license": "GPL-3.0-or-later" 47 | } -------------------------------------------------------------------------------- /packages/sha256/rollup.config.js: -------------------------------------------------------------------------------- 1 | import getTypeScriptConfig from '../../scripts/rollup'; 2 | 3 | export default getTypeScriptConfig({ 4 | packageName: 'sha256', 5 | entryFile: 'src/index.ts', 6 | inlineDynamicImports: true, 7 | }); 8 | -------------------------------------------------------------------------------- /packages/sha256/src/index.ts: -------------------------------------------------------------------------------- 1 | import { s2i, i2s, i2h } from '@cryptography/utils'; 2 | 3 | /** 4 | * Creates new SHA-256 state 5 | */ 6 | function init(h?: Uint32Array): Uint32Array { 7 | if (!h) h = new Uint32Array(8); 8 | 9 | // SHA-256 state contains eight 32-bit integers 10 | h[0] = 0x6A09E667; 11 | h[1] = 0xBB67AE85; 12 | h[2] = 0x3C6EF372; 13 | h[3] = 0xA54FF53A; 14 | h[4] = 0x510E527F; 15 | h[5] = 0x9B05688C; 16 | h[6] = 0x1F83D9AB; 17 | h[7] = 0x5BE0CD19; 18 | 19 | return h; 20 | } 21 | 22 | /** Array to use to store round words. */ 23 | const words = new Uint32Array(64); 24 | 25 | /** K table for SHA-256 */ 26 | const _k = new Uint32Array([ 27 | 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 28 | 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, 29 | 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 30 | 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 31 | 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 32 | 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 33 | 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 34 | 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, 35 | 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 36 | 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 37 | 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 38 | 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, 39 | 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 40 | 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, 41 | 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 42 | 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2, 43 | ]); 44 | 45 | /** 46 | * Perform round function 47 | */ 48 | function round(state: Uint32Array, data: Uint32Array) { 49 | // initialize hash value for this chunk 50 | let a = state[0]; 51 | let b = state[1]; 52 | let c = state[2]; 53 | let d = state[3]; 54 | let e = state[4]; 55 | let f = state[5]; 56 | let g = state[6]; 57 | let h = state[7]; 58 | 59 | words.set(data); 60 | 61 | for (let i = 16; i < 64; i += 1) { 62 | // XOR word 2 words ago rot right 17, rot right 19, shft right 10 63 | let t1 = words[i - 2]; 64 | t1 = ((t1 >>> 17) | (t1 << 15)) 65 | ^ ((t1 >>> 19) | (t1 << 13)) 66 | ^ (t1 >>> 10); 67 | 68 | // XOR word 15 words ago rot right 7, rot right 18, shft right 3 69 | let t2 = words[i - 15]; 70 | t2 = ((t2 >>> 7) | (t2 << 25)) 71 | ^ ((t2 >>> 18) | (t2 << 14)) 72 | ^ (t2 >>> 3); 73 | 74 | // sum(t1, word 7 ago, t2, word 16 ago) modulo 2^32 75 | words[i] = (t1 + words[i - 7] + t2 + words[i - 16]); 76 | } 77 | 78 | // Round Function 79 | for (let i = 0; i < 64; i += 1) { 80 | // Sum1(e) 81 | const s1 = ((e >>> 6) | (e << 26)) 82 | ^ ((e >>> 11) | (e << 21)) 83 | ^ ((e >>> 25) | (e << 7)); 84 | 85 | // Ch(e, f, g) (optimized the same way as SHA-1) 86 | const ch = g ^ (e & (f ^ g)); 87 | 88 | // Sum0(a) 89 | const s0 = ((a >>> 2) | (a << 30)) 90 | ^ ((a >>> 13) | (a << 19)) 91 | ^ ((a >>> 22) | (a << 10)); 92 | 93 | // Maj(a, b, c) (optimized the same way as SHA-1) 94 | const maj = (a & b) | (c & (a ^ b)); 95 | 96 | // main algorithm 97 | const t1 = h + s1 + ch + _k[i] + words[i]; 98 | const t2 = s0 + maj; 99 | 100 | h = g; 101 | g = f; 102 | f = e; 103 | e = (d + t1) | 0; 104 | d = c; 105 | c = b; 106 | b = a; 107 | a = (t1 + t2) | 0; 108 | } 109 | 110 | // update hash state 111 | state[0] += a; 112 | state[1] += b; 113 | state[2] += c; 114 | state[3] += d; 115 | state[4] += e; 116 | state[5] += f; 117 | state[6] += g; 118 | state[7] += h; 119 | } 120 | 121 | /** 122 | * Pre-processing round buffer for string input 123 | */ 124 | function preprocess(str: string, buf: Uint32Array, state: Uint32Array, offset: number = 0) { 125 | while (str.length >= 64) { 126 | for (let i = offset; i < 16; i++) buf[i] = s2i(str, i * 4); 127 | str = str.slice(64 - offset * 4); 128 | offset = 0; 129 | 130 | round(state, buf); 131 | } 132 | 133 | return str; 134 | } 135 | 136 | /** 137 | * Process input buffer 138 | */ 139 | function process(input: Uint32Array, buf: Uint32Array, state: Uint32Array, offset: number = 0) { 140 | while (input.length >= buf.length - offset) { 141 | buf.set(input.subarray(0, buf.length - offset), offset); 142 | input = input.subarray(buf.length - offset); 143 | offset = 0; 144 | 145 | round(state, buf); 146 | } 147 | 148 | if (input.length > 0) { 149 | buf.set(input, offset); 150 | offset += input.length; 151 | } 152 | 153 | return offset; 154 | } 155 | 156 | /** 157 | * Repeatable part 158 | */ 159 | function finish(len: number, buf: Uint32Array, state: Uint32Array, offset: number = 0) { 160 | const len64hi = (len / 0x100000000) >>> 0; 161 | const len64lo = len >>> 0; 162 | 163 | for (let i = offset + 1; i < buf.length; i++) buf[i] = 0; 164 | 165 | if (offset >= 14) { 166 | round(state, buf); 167 | for (let i = 0; i < buf.length; i++) buf[i] = 0; 168 | } 169 | 170 | buf[14] = (len64hi << 3) | (len64hi >>> 28); 171 | buf[15] = len64lo << 3; 172 | 173 | round(state, buf); 174 | } 175 | 176 | /** 177 | * Adds padding to message 178 | */ 179 | function finalizestr(chunk: string, len: number, buf: Uint32Array, state: Uint32Array, offset: number = 0) { 180 | for (; chunk.length >= 4; offset++) { 181 | buf[offset] = s2i(chunk, 0); 182 | chunk = chunk.slice(4); 183 | } 184 | 185 | if (offset >= 16) { 186 | round(state, buf); 187 | offset = 0; 188 | } 189 | 190 | buf[offset] = s2i(`${chunk}\x80\x00\x00\x00`, 0); 191 | finish(len, buf, state, offset); 192 | } 193 | 194 | /** 195 | * Adds padding to buffer 196 | */ 197 | function finalize(len: number, buf: Uint32Array, state: Uint32Array, offset: number = 0) { 198 | buf[offset] = 0x80000000; 199 | finish(len, buf, state, offset); 200 | } 201 | 202 | /** 203 | * Output depending on format 204 | */ 205 | function out(state: Uint32Array, format: 'array'): Uint32Array; 206 | function out(state: Uint32Array, format: 'hex' | 'binary'): string; 207 | function out(state: Uint32Array, format: any = 'array') { 208 | switch (format) { 209 | case 'hex': return ( 210 | i2h(state[0]) 211 | + i2h(state[1]) 212 | + i2h(state[2]) 213 | + i2h(state[3]) 214 | + i2h(state[4]) 215 | + i2h(state[5]) 216 | + i2h(state[6]) 217 | + i2h(state[7]) 218 | ); 219 | 220 | case 'binary': return ( 221 | i2s(state[0]) 222 | + i2s(state[1]) 223 | + i2s(state[2]) 224 | + i2s(state[3]) 225 | + i2s(state[4]) 226 | + i2s(state[5]) 227 | + i2s(state[6]) 228 | + i2s(state[7]) 229 | ); 230 | 231 | default: return state; 232 | } 233 | } 234 | /** 235 | * Stream handler for hashing 236 | */ 237 | class Stream { 238 | buffer: Uint32Array; 239 | state: Uint32Array; 240 | length: number; 241 | offset: number; 242 | tail: string; 243 | 244 | constructor(buf?: Uint32Array) { 245 | this.buffer = new Uint32Array(16); 246 | this.state = init(buf); 247 | this.length = 0; 248 | this.offset = 0; 249 | this.tail = ''; 250 | } 251 | 252 | update(chunk: string | Uint32Array) { 253 | if (typeof chunk === 'string') { 254 | this.length += chunk.length; 255 | this.tail = preprocess(this.tail + chunk, this.buffer, this.state, this.offset); 256 | this.offset = 0; 257 | } else { 258 | if (this.tail.length > 0) throw new Error('Unable to update hash-stream with array'); 259 | 260 | this.length += chunk.length * 4; 261 | this.offset = process(chunk, this.buffer, this.state, this.offset); 262 | } 263 | 264 | return this; 265 | } 266 | 267 | digest(): Uint32Array; 268 | digest(format: 'hex' | 'binary'): string; 269 | digest(format: any = 'array'): any { 270 | if (this.tail.length > 0) { 271 | finalizestr(this.tail, this.length, this.buffer, this.state, this.offset); 272 | } else { 273 | finalize(this.length, this.buffer, this.state, this.offset); 274 | } 275 | 276 | return out(this.state, format); 277 | } 278 | 279 | clear() { 280 | this.state = init(); 281 | this.length = 0; 282 | this.offset = 0; 283 | this.tail = ''; 284 | } 285 | } 286 | 287 | /** 288 | * Hash as single function 289 | */ 290 | function sha256(message: string | Uint32Array): Uint32Array; 291 | function sha256(message: string | Uint32Array, format: 'hex' | 'binary'): string; 292 | function sha256(message: string | Uint32Array, format: any = 'array'): string | Uint32Array { 293 | const buf = new Uint32Array(16); 294 | const state = init(); 295 | 296 | if (typeof message === 'string') finalizestr(preprocess(message, buf, state), message.length, buf, state); 297 | else finalize(message.length * 4, buf, state, process(message, buf, state)); 298 | 299 | return out(state, format); 300 | } 301 | 302 | /** 303 | * Hash with stream constructor 304 | */ 305 | sha256.stream = (buf?: Uint32Array) => new Stream(buf); 306 | sha256.blockLength = 64; 307 | sha256.digestLength = 32; 308 | 309 | export default sha256; 310 | -------------------------------------------------------------------------------- /packages/sha256/tests/index.test.ts: -------------------------------------------------------------------------------- 1 | import sha256 from '../src/index'; 2 | 3 | test('sha256 | function output length', () => { 4 | expect(sha256('Hello world!', 'hex').length).toEqual(64); 5 | expect(sha256('Hello world!', 'binary').length).toEqual(32); 6 | expect(sha256('Hello world!').length).toEqual(8); 7 | }); 8 | 9 | test('sha256 | function (string -> hex)', () => { 10 | expect(sha256('', 'hex')).toEqual('e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855'); 11 | expect(sha256('Hello world!', 'hex')).toEqual('c0535e4be2b79ffd93291305436bf889314e4a3faec05ecffcbb7df31ad9e51a'); 12 | expect(sha256('305436bf889314e4a3faec05ecffcbb7df31ad9e51f1312233123df1', 'hex')).toEqual('277b8bfc3330dffeab6b28dcfaab0d0c691e32e3069a32b35b7c692091e60808'); 13 | 14 | expect( 15 | sha256( 16 | 'Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo ' 17 | + 'inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo.', 18 | 'hex' 19 | ) 20 | ).toEqual('e68fe78e064700fe6b98e47dc0758a4f966bd027299b685642c607ea376b7d47'); 21 | 22 | expect(sha256('Hello world!', 'hex')).toEqual('c0535e4be2b79ffd93291305436bf889314e4a3faec05ecffcbb7df31ad9e51a'); 23 | 24 | expect(sha256('testtesttesttesttesttesttesttesttesttesttesttesttesttesttesttest', 'hex')).toEqual('3e2b0a3dc3503d99e14cf834a3be419c4729fe32ee5fd037407f81f4d73aa619'); 25 | }); 26 | 27 | test('sha256 | function result (string -> binary)', () => { 28 | expect(sha256('Test Input', 'binary')).toEqual('\x15\x4b\x35\xc3\x5f\xae\xc1\x79\xa7\x21\xcb\xae\xe3\x03\xcd\x9b\x74\x60\xd3\xda\x94\xf4\xaf\xd1\xd5\x9c\x9f\xa5\x0a\x8c\xff\x87'); 29 | expect(sha256('Hello world!', 'binary')).toEqual('\xc0\x53\x5e\x4b\xe2\xb7\x9f\xfd\x93\x29\x13\x05\x43\x6b\xf8\x89\x31\x4e\x4a\x3f\xae\xc0\x5e\xcf\xfc\xbb\x7d\xf3\x1a\xd9\xe5\x1a'); 30 | 31 | expect( 32 | sha256( 33 | 'More generally, cryptography is about constructing and analyzing protocols that prevent third parties or the public from reading private ' 34 | + 'messages;[3] various aspects in information security such as data confidentiality, data integrity, authentication, and non-repudiation[4] ' 35 | + 'are central to modern cryptography. Modern cryptography exists at the intersection of the disciplines of mathematics, computer science, ' 36 | + 'electrical engineering, communication science, and physics. Applications of cryptography include electronic commerce, chip-based payment cards, ' 37 | + 'digital currencies, computer passwords, and military communications.', 38 | 'binary' 39 | ) 40 | ).toEqual('\xc4\xef\x15\xfc\x11\x6b\x59\x6f\x87\x55\x48\x01\xbd\x4c\x9d\xdb\x2c\x5a\xdf\x0d\x4e\x06\xc6\xea\x45\xa9\xa1\x87\x03\x60\x4d\xa2') 41 | }); 42 | 43 | test('sha256 | function (string -> array)', () => { 44 | expect(sha256('JavaScript Monorepo')).toEqual( 45 | new Uint32Array([0x1285536b, 0xba487a50, 0xf2cd054a, 0x21ccc0a2, 0xf6da1fad, 0x096797bc, 0x56fe67da, 0x726e20ae]) 46 | ); 47 | 48 | expect(sha256('Yet Another Test Long Case + Yet Another Test Long Case!')).toEqual( 49 | new Uint32Array([0x4aaf1da2, 0x344b7690, 0x30212e7e, 0x44136cc8, 0x59d88afd, 0xf992b635, 0xa0f3ecc5, 0x659efca8]) 50 | ); 51 | }); 52 | 53 | test('sha256 | function (array -> array)', () => { 54 | expect( 55 | sha256(new Uint32Array([0x54657374, 0x54657374])) 56 | ).toEqual( 57 | new Uint32Array([0xa8d627d9, 0x3f518e90, 0x96b6f40e, 0x36d27b76, 0x60fa26d3, 0x18ef1adc, 0x43da750e, 0x49ebe4be]) 58 | ); 59 | 60 | expect( 61 | sha256(new Uint32Array([0x59657420, 0x416e6f74, 0x68657220, 0x54657374, 0x204c6f6e, 0x67204361, 0x73653132])) 62 | ).toEqual( 63 | new Uint32Array([0x8c8814c1, 0x4c3b3526, 0x75179536, 0x1188e795, 0x474be238, 0xb3cfe2d3, 0x790ace4f, 0xcb818651]) 64 | ); 65 | 66 | expect( 67 | sha256(new Uint32Array([ 68 | 0x59657420, 0x416e6f74, 0x68657220, 0x54657374, 0x204c6f6e, 0x67204361, 0x7365202b, 69 | 0x20596574, 0x20416e6f, 0x74686572, 0x20546573, 0x74204c6f, 0x6e672043, 0x61736511 70 | ])) 71 | ).toEqual( 72 | new Uint32Array([0xe25034d2, 0xc2ff6f9a, 0x997c9f52, 0x6bc4802e, 0xa9804134, 0x17366d37, 0xbd64e675, 0x8a38bc70]) 73 | ); 74 | 75 | expect( 76 | sha256(new Uint32Array([ 77 | 0x59657420, 0x416e6f74, 0x68657220, 0x54657374, 0x204c6f6e, 0x67204361, 0x7365202b, 78 | 0x20596574, 0x20416e6f, 0x74686572, 0x20546573, 0x74204c6f, 0x6e672043, 0x61736511, 79 | 0x59657420, 0x416e6f74, 0x68657220, 0x54657374, 0x204c6f6e, 0x67204361, 0x7365202b, 80 | 0x20596574, 0x20416e6f, 0x74686572, 0x20546573, 0x74204c6f, 0x6e672043, 0x61736511 81 | ])) 82 | ).toEqual( 83 | new Uint32Array([0x4dfd8cab, 0x67d30f01, 0xc7bf1b10, 0x4cb5abbd, 0x1dd836ff, 0x345a47dc, 0xc30599aa, 0xa1d80b9f]) 84 | ); 85 | }); 86 | 87 | test('sha256 | stream', () => { 88 | let stream = sha256.stream(); 89 | 90 | stream.update(new Uint32Array([0x54657374])); 91 | stream.update(new Uint32Array([0x54657374])); 92 | expect(stream.digest()).toEqual(new Uint32Array([0xa8d627d9, 0x3f518e90, 0x96b6f40e, 0x36d27b76, 0x60fa26d3, 0x18ef1adc, 0x43da750e, 0x49ebe4be])); 93 | stream.clear(); 94 | 95 | stream.update(new Uint32Array([ 96 | 0x59657420, 0x416e6f74, 0x68657220, 0x54657374, 0x204c6f6e, 0x67204361, 0x7365202b, 97 | 0x20596574, 0x20416e6f, 0x74686572, 0x20546573, 0x74204c6f, 0x6e672043, 0x61736511 98 | ])); 99 | stream.update(new Uint32Array([ 100 | 0x59657420, 0x416e6f74, 0x68657220, 0x54657374, 0x204c6f6e, 0x67204361, 0x7365202b, 101 | 0x20596574, 0x20416e6f, 0x74686572, 0x20546573, 0x74204c6f, 0x6e672043, 0x61736511 102 | ])); 103 | expect(stream.digest('hex')).toEqual('4dfd8cab67d30f01c7bf1b104cb5abbd1dd836ff345a47dcc30599aaa1d80b9f'); 104 | stream.clear(); 105 | 106 | stream.update('More generally, cryptography is about constructing and analyzing protocols that prevent third parties or the public from reading private '); 107 | stream.update('messages;[3] various aspects in information security such as data confidentiality, data integrity, authentication, and non-repudiation[4] '); 108 | stream.update('are central to modern cryptography. Modern cryptography exists at the intersection of the disciplines of mathematics, computer science, '); 109 | stream.update('electrical engineering, communication science, and physics. Applications of cryptography include electronic commerce, chip-based payment cards, '); 110 | stream.update('digital currencies, computer passwords, and military communications.'); 111 | expect(stream.digest('binary')).toEqual('\xc4\xef\x15\xfc\x11\x6b\x59\x6f\x87\x55\x48\x01\xbd\x4c\x9d\xdb\x2c\x5a\xdf\x0d\x4e\x06\xc6\xea\x45\xa9\xa1\x87\x03\x60\x4d\xa2') 112 | }); 113 | 114 | test('sha256 | error', () => { 115 | const stream = sha256.stream(); 116 | let raised = false; 117 | 118 | try { 119 | stream.update('test'); 120 | stream.update(new Uint32Array([0x54657374])); 121 | stream.digest(); 122 | } catch (e) { 123 | raised = true; 124 | expect(e.message).toEqual('Unable to update hash-stream with array'); 125 | } 126 | 127 | expect(raised).toBeTruthy(); 128 | }); -------------------------------------------------------------------------------- /packages/sha512/.npmignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | 6 | # Runtime data 7 | pids 8 | *.pid 9 | *.seed 10 | 11 | # Directory for instrumented libs generated by jscoverage/JSCover 12 | lib-cov 13 | 14 | # Coverage directory used by tools like istanbul 15 | coverage 16 | 17 | # nyc test coverage 18 | .nyc_output 19 | 20 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 21 | .grunt 22 | 23 | # node-waf configuration 24 | .lock-wscript 25 | 26 | # Compiled binary addons (http://nodejs.org/api/addons.html) 27 | build/Release 28 | 29 | # Dependency directories 30 | node_modules 31 | jspm_packages 32 | 33 | # Optional npm cache directory 34 | .npm 35 | 36 | # Optional REPL history 37 | .node_repl_history 38 | 39 | # Project 40 | tests 41 | src 42 | .travis.yml 43 | .codecov.yml 44 | rollup.config.js -------------------------------------------------------------------------------- /packages/sha512/README.md: -------------------------------------------------------------------------------- 1 | # @cryptography/sha512 2 | [![Bundlephobia](https://img.shields.io/bundlephobia/minzip/@cryptography/sha512)](https://bundlephobia.com/result?p=@cryptography/sha512@0.1.0) 3 | [![Coverage](https://img.shields.io/codecov/c/github/spalt08/cryptography?token=617017dc35344eb6b4637420457746c8)](https://codecov.io/gh/spalt08/cryptography) 4 | [![Travis CI](https://img.shields.io/travis/spalt08/cryptography)](https://travis-ci.com/spalt08/cryptography) 5 | 6 | High-performance synchronous SHA-512 implementation for JavaScript. Optimized for browsers. 7 | 8 | ## Features 9 | * Blazing fast 10 | * Ultra lightweight 11 | * ECMAScript 3-6 12 | * Typed 13 | * Tested 14 | 15 | ## Setup 16 | [Package](https://www.npmjs.com/package/@cryptography/sha512) is available through `npm` and `yarn` 17 | ``` 18 | npm install @cryptography/sha512 19 | ``` 20 | ``` 21 | yarn add @cryptography/sha512 22 | ``` 23 | 24 | ### When you should use @cryptography/sha512 25 | * Hashing small inputs (< 5kb) 26 | * Key derivation functions 27 | * 100% browser support required 28 | 29 | ### ⚠️ When you should not use this (WebCrypto API preferred cases) 30 | * Hashing files (> 5kb) 31 | * Concurrent hashing large amount of messages 32 | 33 | ## Usage 34 | This package is optimized for small byte inputs (<10kb). 35 | 36 | Also, it is highly recommended to run CPU-intensive tasks in a [Web Worker](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers). 37 | 38 | 39 | ```js 40 | import sha512 from '@cryptography/sha512' 41 | 42 | // as Uint32Array([0xa8d627d9, ...]) 43 | const array = sha512('Hello World!') 44 | 45 | // as hex-string: "a8d627d9..." 46 | const hex = sha512('Hello World!', 'hex') 47 | 48 | // as binary string: "Äïük..." 49 | const raw = sha512('Hello World!', 'binary') 50 | 51 | // UInt32Array as input 52 | const buf = new Uint32Array([0xa8d627d9, ...]); 53 | sha512(buf) 54 | ``` 55 | For hashing large files or other data chuncks use `stream()` to create a hashing stream. 56 | ```js 57 | sha512.stream().update('Hello World!').digest(); 58 | ``` 59 | 60 | ## Performance 61 | Benchmarks: 62 | * https://jsbench.me/gak3pyle85/3 63 | 64 | ## Contributing 65 | Contributions are welcome! Contribution guidelines will be published later. -------------------------------------------------------------------------------- /packages/sha512/jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | roots: [ 3 | '/tests', 4 | ], 5 | transform: { 6 | '^.+\\.ts$': 'ts-jest', 7 | }, 8 | testPathIgnorePatterns: ['/dist/', '/node_modules/'], 9 | collectCoverage: true, 10 | }; 11 | -------------------------------------------------------------------------------- /packages/sha512/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@cryptography/sha512", 3 | "description": "High-performance synchronous SHA-512 implementation for JavaScript", 4 | "version": "0.2.0", 5 | "author": "Konstantin Darutkin", 6 | "scripts": { 7 | "test": "jest --coverage", 8 | "build": "rm -rf dist/* && rollup -c", 9 | "analyze": "npm run build -- --analyze", 10 | "prepublish": "npm test", 11 | "pretest": "npm run build", 12 | "publish": "npm publish" 13 | }, 14 | "devDependencies": { 15 | "@cryptography/utils": "^1.0.0" 16 | }, 17 | "main": "dist/cjs/sha512.min.js", 18 | "module": "dist/es/sha512.js", 19 | "types": "dist/typings/index.d.ts", 20 | "repository": { 21 | "type": "git", 22 | "url": "git+https://github.com/spalt08/cryptography.git", 23 | "directory": "packages/sha512" 24 | }, 25 | "publishConfig": { 26 | "access": "public" 27 | }, 28 | "lint-staged": { 29 | "*.{ts}": [ 30 | "eslint" 31 | ] 32 | }, 33 | "keywords": [ 34 | "sha512", 35 | "SHA-512", 36 | "javascript", 37 | "crypto" 38 | ], 39 | "bugs": { 40 | "url": "https://github.com/spalt08/cryptography/issues" 41 | }, 42 | "homepage": "https://github.com/spalt08/cryptography/tree/master/packages/sha512", 43 | "files": [ 44 | "dist/*", 45 | "package.json" 46 | ], 47 | "license": "GPL-3.0-or-later" 48 | } -------------------------------------------------------------------------------- /packages/sha512/rollup.config.js: -------------------------------------------------------------------------------- 1 | import getTypeScriptConfig from '../../scripts/rollup'; 2 | 3 | export default getTypeScriptConfig({ 4 | packageName: 'sha512', 5 | entryFile: 'src/index.ts', 6 | inlineDynamicImports: true, 7 | }); 8 | -------------------------------------------------------------------------------- /packages/sha512/src/index.ts: -------------------------------------------------------------------------------- 1 | import { s2i, i2s, i2h } from '@cryptography/utils'; 2 | 3 | /** 4 | * Creates new SHA-256 state 5 | */ 6 | function init(state?: Uint32Array): Uint32Array { 7 | if (!state) state = new Uint32Array(16); 8 | 9 | // SHA-512 state contains eight 64-bit integers 10 | state[0] = 0x6a09e667; state[1] = 0xf3bcc908; 11 | state[2] = 0xbb67ae85; state[3] = 0x84caa73b; 12 | state[4] = 0x3c6ef372; state[5] = 0xfe94f82b; 13 | state[6] = 0xa54ff53a; state[7] = 0x5f1d36f1; 14 | state[8] = 0x510e527f; state[9] = 0xade682d1; 15 | state[10] = 0x9b05688c; state[11] = 0x2b3e6c1f; 16 | state[12] = 0x1f83d9ab; state[13] = 0xfb41bd6b; 17 | state[14] = 0x5be0cd19; state[15] = 0x137e2179; 18 | 19 | return state; 20 | } 21 | 22 | /** Array to use to store round words. */ 23 | const words = new Uint32Array(160); 24 | 25 | // K table for SHA-512 26 | const _k = new Uint32Array([ 27 | 0x428a2f98, 0xd728ae22, 0x71374491, 0x23ef65cd, 28 | 0xb5c0fbcf, 0xec4d3b2f, 0xe9b5dba5, 0x8189dbbc, 29 | 0x3956c25b, 0xf348b538, 0x59f111f1, 0xb605d019, 30 | 0x923f82a4, 0xaf194f9b, 0xab1c5ed5, 0xda6d8118, 31 | 0xd807aa98, 0xa3030242, 0x12835b01, 0x45706fbe, 32 | 0x243185be, 0x4ee4b28c, 0x550c7dc3, 0xd5ffb4e2, 33 | 0x72be5d74, 0xf27b896f, 0x80deb1fe, 0x3b1696b1, 34 | 0x9bdc06a7, 0x25c71235, 0xc19bf174, 0xcf692694, 35 | 0xe49b69c1, 0x9ef14ad2, 0xefbe4786, 0x384f25e3, 36 | 0x0fc19dc6, 0x8b8cd5b5, 0x240ca1cc, 0x77ac9c65, 37 | 0x2de92c6f, 0x592b0275, 0x4a7484aa, 0x6ea6e483, 38 | 0x5cb0a9dc, 0xbd41fbd4, 0x76f988da, 0x831153b5, 39 | 0x983e5152, 0xee66dfab, 0xa831c66d, 0x2db43210, 40 | 0xb00327c8, 0x98fb213f, 0xbf597fc7, 0xbeef0ee4, 41 | 0xc6e00bf3, 0x3da88fc2, 0xd5a79147, 0x930aa725, 42 | 0x06ca6351, 0xe003826f, 0x14292967, 0x0a0e6e70, 43 | 0x27b70a85, 0x46d22ffc, 0x2e1b2138, 0x5c26c926, 44 | 0x4d2c6dfc, 0x5ac42aed, 0x53380d13, 0x9d95b3df, 45 | 0x650a7354, 0x8baf63de, 0x766a0abb, 0x3c77b2a8, 46 | 0x81c2c92e, 0x47edaee6, 0x92722c85, 0x1482353b, 47 | 0xa2bfe8a1, 0x4cf10364, 0xa81a664b, 0xbc423001, 48 | 0xc24b8b70, 0xd0f89791, 0xc76c51a3, 0x0654be30, 49 | 0xd192e819, 0xd6ef5218, 0xd6990624, 0x5565a910, 50 | 0xf40e3585, 0x5771202a, 0x106aa070, 0x32bbd1b8, 51 | 0x19a4c116, 0xb8d2d0c8, 0x1e376c08, 0x5141ab53, 52 | 0x2748774c, 0xdf8eeb99, 0x34b0bcb5, 0xe19b48a8, 53 | 0x391c0cb3, 0xc5c95a63, 0x4ed8aa4a, 0xe3418acb, 54 | 0x5b9cca4f, 0x7763e373, 0x682e6ff3, 0xd6b2b8a3, 55 | 0x748f82ee, 0x5defb2fc, 0x78a5636f, 0x43172f60, 56 | 0x84c87814, 0xa1f0ab72, 0x8cc70208, 0x1a6439ec, 57 | 0x90befffa, 0x23631e28, 0xa4506ceb, 0xde82bde9, 58 | 0xbef9a3f7, 0xb2c67915, 0xc67178f2, 0xe372532b, 59 | 0xca273ece, 0xea26619c, 0xd186b8c7, 0x21c0c207, 60 | 0xeada7dd6, 0xcde0eb1e, 0xf57d4f7f, 0xee6ed178, 61 | 0x06f067aa, 0x72176fba, 0x0a637dc5, 0xa2c898a6, 62 | 0x113f9804, 0xbef90dae, 0x1b710b35, 0x131c471b, 63 | 0x28db77f5, 0x23047d84, 0x32caab7b, 0x40c72493, 64 | 0x3c9ebe0a, 0x15c9bebc, 0x431d67c4, 0x9c100d4c, 65 | 0x4cc5d4be, 0xcb3e42b6, 0x597f299c, 0xfc657e2a, 66 | 0x5fcb6fab, 0x3ad6faec, 0x6c44198c, 0x4a475817, 67 | ]); 68 | 69 | /** 70 | * Perform round function 71 | */ 72 | function round(state: Uint32Array, data: Uint32Array) { 73 | // initialize hash value for this chunk 74 | let ahi = state[0]; let alo = state[1]; 75 | let bhi = state[2]; let blo = state[3]; 76 | let chi = state[4]; let clo = state[5]; 77 | let dhi = state[6]; let dlo = state[7]; 78 | let ehi = state[8]; let elo = state[9]; 79 | let fhi = state[10]; let flo = state[11]; 80 | let ghi = state[12]; let glo = state[13]; 81 | let hhi = state[14]; let hlo = state[15]; 82 | 83 | words.set(data); 84 | 85 | for (let i = 32; i < 160; i += 2) { 86 | // for word 2 words ago: ROTR 19(x) ^ ROTR 61(x) ^ SHR 6(x) 87 | let hi = words[i - 4]; 88 | let lo = words[i - 3]; 89 | 90 | // high bits 91 | const t1hi = ( 92 | ((hi >>> 19) | (lo << 13)) // ROTR 19 93 | ^ ((lo >>> 29) | (hi << 3)) // ROTR 61/(swap + ROTR 29) 94 | ^ (hi >>> 6)) >>> 0; // SHR 6 95 | 96 | // low bits 97 | const t1lo = ( 98 | ((hi << 13) | (lo >>> 19)) // ROTR 19 99 | ^ ((lo << 3) | (hi >>> 29)) // ROTR 61/(swap + ROTR 29) 100 | ^ ((hi << 26) | (lo >>> 6))) >>> 0; // SHR 6 101 | 102 | // for word 15 words ago: ROTR 1(x) ^ ROTR 8(x) ^ SHR 7(x) 103 | hi = words[i - 30]; 104 | lo = words[i - 29]; 105 | 106 | // high bits 107 | const t2hi = ( 108 | ((hi >>> 1) | (lo << 31)) // ROTR 1 109 | ^ ((hi >>> 8) | (lo << 24)) // ROTR 8 110 | ^ (hi >>> 7)) >>> 0; // SHR 7 111 | 112 | // low bits 113 | const t2lo = ( 114 | ((hi << 31) | (lo >>> 1)) // ROTR 1 115 | ^ ((hi << 24) | (lo >>> 8)) // ROTR 8 116 | ^ ((hi << 25) | (lo >>> 7))) >>> 0; // SHR 7 117 | 118 | // sum(t1, word 7 ago, t2, word 16 ago) modulo 2^64 (carry lo overflow) 119 | lo = t1lo + words[i - 13] + t2lo + words[i - 31]; 120 | words[i] = t1hi + words[i - 14] + t2hi + words[i - 32] + ((lo / 0x100000000) >>> 0); 121 | words[i + 1] = lo; 122 | } 123 | 124 | // Round function 125 | for (let i = 0; i < 160; i += 2) { 126 | // Sum1(e) = ROTR 14(e) ^ ROTR 18(e) ^ ROTR 41(e) 127 | const s1hi = ( 128 | ((ehi >>> 14) | (elo << 18)) // ROTR 14 129 | ^ ((ehi >>> 18) | (elo << 14)) // ROTR 18 130 | ^ ((elo >>> 9) | (ehi << 23))) >>> 0; // ROTR 41/(swap + ROTR 9) 131 | 132 | const s1lo = ( 133 | ((ehi << 18) | (elo >>> 14)) // ROTR 14 134 | ^ ((ehi << 14) | (elo >>> 18)) // ROTR 18 135 | ^ ((elo << 23) | (ehi >>> 9))) >>> 0; // ROTR 41/(swap + ROTR 9) 136 | 137 | // Ch(e, f, g) (optimized the same way as SHA-1) 138 | const chhi = (ghi ^ (ehi & (fhi ^ ghi))) >>> 0; 139 | const chlo = (glo ^ (elo & (flo ^ glo))) >>> 0; 140 | 141 | // Sum0(a) = ROTR 28(a) ^ ROTR 34(a) ^ ROTR 39(a) 142 | const s0hi = ( 143 | ((ahi >>> 28) | (alo << 4)) // ROTR 28 144 | ^ ((alo >>> 2) | (ahi << 30)) // ROTR 34/(swap + ROTR 2) 145 | ^ ((alo >>> 7) | (ahi << 25))) >>> 0; // ROTR 39/(swap + ROTR 7) 146 | 147 | const s0lo = ( 148 | ((ahi << 4) | (alo >>> 28)) // ROTR 28 149 | ^ ((alo << 30) | (ahi >>> 2)) // ROTR 34/(swap + ROTR 2) 150 | ^ ((alo << 25) | (ahi >>> 7))) >>> 0; // ROTR 39/(swap + ROTR 7) 151 | 152 | // Maj(a, b, c) (optimized the same way as SHA-1) 153 | const majhi = ((ahi & bhi) | (chi & (ahi ^ bhi))) >>> 0; 154 | const majlo = ((alo & blo) | (clo & (alo ^ blo))) >>> 0; 155 | 156 | // main algorithm 157 | // t1 = (h + s1 + ch + _k[i] + _w[i]) modulo 2^64 (carry lo overflow) 158 | let t1lo = (hlo + s1lo + chlo + _k[i + 1] + words[i + 1]); 159 | const t1hi = (hhi + s1hi + chhi + _k[i] + words[i] + ((t1lo / 0x100000000) >>> 0)) >>> 0; 160 | t1lo >>>= 0; 161 | 162 | // t2 = s0 + maj modulo 2^64 (carry lo overflow) 163 | let t2lo = s0lo + majlo; 164 | const t2hi = (s0hi + majhi + ((t2lo / 0x100000000) >>> 0)) >>> 0; 165 | t2lo >>>= 0; 166 | 167 | // Update working variables 168 | hhi = ghi; 169 | hlo = glo; 170 | 171 | ghi = fhi; 172 | glo = flo; 173 | 174 | fhi = ehi; 175 | flo = elo; 176 | 177 | // e = (d + t1) modulo 2^64 (carry lo overflow) 178 | elo = dlo + t1lo; 179 | ehi = (dhi + t1hi + ((elo / 0x100000000) >>> 0)) >>> 0; 180 | elo >>>= 0; 181 | 182 | dhi = chi; 183 | dlo = clo; 184 | 185 | chi = bhi; 186 | clo = blo; 187 | 188 | bhi = ahi; 189 | blo = alo; 190 | 191 | // a = (t1 + t2) modulo 2^64 (carry lo overflow) 192 | alo = t1lo + t2lo; 193 | ahi = (t1hi + t2hi + ((alo / 0x100000000) >>> 0)) >>> 0; 194 | alo >>>= 0; 195 | } 196 | 197 | // update hash state (additional modulo 2^64) 198 | let lo = state[1] + alo; 199 | state[0] = state[0] + ahi + ((lo / 0x100000000) >>> 0); 200 | state[1] = lo; 201 | 202 | lo = state[3] + blo; 203 | state[2] = state[2] + bhi + ((lo / 0x100000000) >>> 0); 204 | state[3] = lo; 205 | 206 | lo = state[5] + clo; 207 | state[4] = state[4] + chi + ((lo / 0x100000000) >>> 0); 208 | state[5] = lo; 209 | 210 | lo = state[7] + dlo; 211 | state[6] = state[6] + dhi + ((lo / 0x100000000) >>> 0); 212 | state[7] = lo; 213 | 214 | lo = state[9] + elo; 215 | state[8] = state[8] + ehi + ((lo / 0x100000000) >>> 0); 216 | state[9] = lo; 217 | 218 | lo = state[11] + flo; 219 | state[10] = state[10] + fhi + ((lo / 0x100000000) >>> 0); 220 | state[11] = lo; 221 | 222 | lo = state[13] + glo; 223 | state[12] = state[12] + ghi + ((lo / 0x100000000) >>> 0); 224 | state[13] = lo; 225 | 226 | lo = state[15] + hlo; 227 | state[14] = state[14] + hhi + ((lo / 0x100000000) >>> 0); 228 | state[15] = lo; 229 | } 230 | 231 | /** 232 | * Pre-processing round buffer for string input 233 | */ 234 | function preprocess(str: string, buf: Uint32Array, state: Uint32Array, offset: number = 0) { 235 | while (str.length >= 128) { 236 | for (let i = offset; i < 32; i++) buf[i] = s2i(str, i * 4); 237 | 238 | str = str.slice(128 - offset * 4); 239 | offset = 0; 240 | 241 | round(state, buf); 242 | } 243 | 244 | return str; 245 | } 246 | 247 | /** 248 | * Process input buffer 249 | */ 250 | function process(input: Uint32Array, buf: Uint32Array, state: Uint32Array, offset: number = 0) { 251 | while (input.length >= buf.length - offset) { 252 | buf.set(input.subarray(0, buf.length - offset), offset); 253 | input = input.subarray(buf.length - offset); 254 | offset = 0; 255 | 256 | round(state, buf); 257 | } 258 | 259 | if (input.length > 0) { 260 | buf.set(input, offset); 261 | offset += input.length; 262 | } 263 | 264 | return offset; 265 | } 266 | 267 | /** 268 | * Repeatable part 269 | */ 270 | function finish(len: number, buf: Uint32Array, state: Uint32Array, offset: number = 0) { 271 | for (let i = offset + 1; i < buf.length; i++) buf[i] = 0; 272 | 273 | if (offset >= 28) { 274 | round(state, buf); 275 | for (let i = 0; i < buf.length; i++) buf[i] = 0; 276 | } 277 | 278 | buf[30] = ((len * 8) / 0x100000000) >>> 0; 279 | buf[31] = (len * 8) | 0; 280 | 281 | round(state, buf); 282 | } 283 | 284 | /** 285 | * Adds padding to message 286 | */ 287 | function finalizestr(chunk: string, len: number, buf: Uint32Array, state: Uint32Array, offset: number = 0) { 288 | for (; chunk.length >= 4; offset++) { 289 | buf[offset] = s2i(chunk, 0); 290 | chunk = chunk.slice(4); 291 | } 292 | 293 | if (offset >= 32) { 294 | round(state, buf); 295 | offset = 0; 296 | } 297 | 298 | buf[offset] = s2i(`${chunk}\x80\x00\x00\x00`, 0); 299 | finish(len, buf, state, offset); 300 | } 301 | 302 | /** 303 | * Adds padding to buffer 304 | */ 305 | function finalize(len: number, buf: Uint32Array, state: Uint32Array, offset: number = 0) { 306 | buf[offset] = 0x80000000; 307 | finish(len, buf, state, offset); 308 | } 309 | 310 | /** 311 | * Output depending on format 312 | */ 313 | function out(state: Uint32Array, format: 'array'): Uint32Array; 314 | function out(state: Uint32Array, format: 'hex' | 'binary'): string; 315 | function out(state: Uint32Array, format: any = 'array') { 316 | switch (format) { 317 | case 'hex': return ( 318 | i2h(state[0]) + i2h(state[1]) 319 | + i2h(state[2]) + i2h(state[3]) 320 | + i2h(state[4]) + i2h(state[5]) 321 | + i2h(state[6]) + i2h(state[7]) 322 | + i2h(state[8]) + i2h(state[9]) 323 | + i2h(state[10]) + i2h(state[11]) 324 | + i2h(state[12]) + i2h(state[13]) 325 | + i2h(state[14]) + i2h(state[15]) 326 | ); 327 | 328 | case 'binary': return ( 329 | i2s(state[0]) + i2s(state[1]) 330 | + i2s(state[2]) + i2s(state[3]) 331 | + i2s(state[4]) + i2s(state[5]) 332 | + i2s(state[6]) + i2s(state[7]) 333 | + i2s(state[8]) + i2s(state[9]) 334 | + i2s(state[10]) + i2s(state[11]) 335 | + i2s(state[12]) + i2s(state[13]) 336 | + i2s(state[14]) + i2s(state[15]) 337 | ); 338 | 339 | default: return state; 340 | } 341 | } 342 | /** 343 | * Stream handler for hashing 344 | */ 345 | class Stream { 346 | buffer: Uint32Array; 347 | state: Uint32Array; 348 | length: number; 349 | offset: number; 350 | tail: string; 351 | 352 | constructor(buf?: Uint32Array) { 353 | this.buffer = new Uint32Array(32); 354 | this.state = init(buf); 355 | this.length = 0; 356 | this.offset = 0; 357 | this.tail = ''; 358 | } 359 | 360 | update(chunk: string | Uint32Array) { 361 | if (typeof chunk === 'string') { 362 | this.length += chunk.length; 363 | this.tail = preprocess(this.tail + chunk, this.buffer, this.state, this.offset); 364 | this.offset = 0; 365 | } else { 366 | if (this.tail.length > 0) throw new Error('Unable to update hash-stream with array'); 367 | 368 | this.length += chunk.length * 4; 369 | this.offset = process(chunk, this.buffer, this.state, this.offset); 370 | } 371 | 372 | return this; 373 | } 374 | 375 | digest(): Uint32Array; 376 | digest(format: 'hex' | 'binary'): string; 377 | digest(format: any = 'array'): any { 378 | if (this.tail.length > 0) { 379 | finalizestr(this.tail, this.length, this.buffer, this.state, this.offset); 380 | } else { 381 | finalize(this.length, this.buffer, this.state, this.offset); 382 | } 383 | 384 | return out(this.state, format); 385 | } 386 | 387 | clear() { 388 | this.state = init(); 389 | this.length = 0; 390 | this.offset = 0; 391 | this.tail = ''; 392 | } 393 | } 394 | 395 | /** 396 | * Hash as single function 397 | */ 398 | function sha512(message: string | Uint32Array): Uint32Array; 399 | function sha512(message: string | Uint32Array, format: 'hex' | 'binary'): string; 400 | function sha512(message: string | Uint32Array, format: any = 'array'): string | Uint32Array { 401 | const buf = new Uint32Array(32); 402 | const state = init(); 403 | 404 | if (typeof message === 'string') finalizestr(preprocess(message, buf, state), message.length, buf, state); 405 | else finalize(message.length * 4, buf, state, process(message, buf, state)); 406 | 407 | return out(state, format); 408 | } 409 | 410 | /** 411 | * Hash with stream constructor 412 | */ 413 | sha512.stream = (buf?: Uint32Array) => new Stream(buf); 414 | sha512.blockLength = 128; 415 | sha512.digestLength = 64; 416 | 417 | export default sha512; 418 | -------------------------------------------------------------------------------- /packages/sha512/tests/index.test.ts: -------------------------------------------------------------------------------- 1 | import sha512 from '../src/index'; 2 | 3 | test('sha512 | function output length', () => { 4 | expect(sha512('Hello world!', 'hex').length).toEqual(128); 5 | expect(sha512('Hello world!', 'binary').length).toEqual(64); 6 | expect(sha512('Hello world!').length).toEqual(16); 7 | }); 8 | 9 | test('sha512 | function (string -> hex)', () => { 10 | expect(sha512('', 'hex')).toEqual('cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e'); 11 | expect(sha512('Hello world!', 'hex')).toEqual('f6cde2a0f819314cdde55fc227d8d7dae3d28cc556222a0a8ad66d91ccad4aad6094f517a2182360c9aacf6a3dc323162cb6fd8cdffedb0fe038f55e85ffb5b6'); 12 | 13 | expect( 14 | sha512( 15 | 'Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo ' 16 | + 'inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo.', 17 | 'hex' 18 | ) 19 | ).toEqual('425286c1dc4db148139bd3c2adda330677f43e5e0505ef703f7802986d946d4e59306e537aaa22a257f78ee954060cbab059b429e16a0177252f1d30108c9eb6'); 20 | 21 | expect( 22 | sha512( 23 | 'testtesttesttesttesttesttesttesttesttesttesttesttesttesttesttest' 24 | + 'testtesttesttesttesttesttesttesttesttesttesttesttesttesttesttest', 25 | 'hex' 26 | ) 27 | ).toEqual('32b9fc99e66d8a66c3c0b8ee6ee7554a3fc152d0b0820af25371b175078b6d0fb7825626cc84453026e540d60ebeabbfd9e3eeb3fd590deb2787fe6cd8a2946f'); 28 | }); 29 | 30 | test('sha512 | function result (string -> binary)', () => { 31 | expect(sha512('Test Input', 'hex')).toEqual('91585ef48a0baad22ec820744a75450bce80519171d41ce039a723e7bae09fe3e82c09c4fed8a5e77094347460cc3970e261b5238969b1e2adbc3fa6841cdb1e'); 32 | expect(sha512('Test Input', 'binary')).toEqual('\x91\x58\x5e\xf4\x8a\x0b\xaa\xd2\x2e\xc8\x20\x74\x4a\x75\x45\x0b\xce\x80\x51\x91\x71\xd4\x1c\xe0\x39\xa7\x23\xe7\xba\xe0\x9f\xe3\xe8\x2c\x09\xc4\xfe\xd8\xa5\xe7\x70\x94\x34\x74\x60\xcc\x39\x70\xe2\x61\xb5\x23\x89\x69\xb1\xe2\xad\xbc\x3f\xa6\x84\x1c\xdb\x1e'); 33 | }); 34 | 35 | test('sha512 | function (string -> array)', () => { 36 | expect(sha512('JavaScript Monorepo')).toEqual( 37 | new Uint32Array([ 38 | 0x0f5410d2, 0xcf8b8718, 0xddeb1a69, 0xe224db23, 0x4cc4960c, 0x0dff2dcb, 0xe02820c8, 0xbc3ba027, 39 | 0x6299199c, 0x644a81bc, 0x22c739bd, 0x8378f263, 0x708ef589, 0xeb054d75, 0xd6a2297b, 0x3f5272ee 40 | ]) 41 | ); 42 | }); 43 | 44 | test('sha512 | function (array -> array)', () => { 45 | expect( 46 | sha512(new Uint32Array([0x54657374, 0x54657374])) 47 | ).toEqual( 48 | new Uint32Array([ 49 | 0xf7c87428, 0xfadda0a5, 0x5c3cd42f, 0x353eb173, 0x4eb0e3d1, 0x8f3a46db, 0xc535f8c6, 0x53418a91, 50 | 0x52e74de7, 0x40270498, 0x35f1491f, 0x43ce5368, 0xbbbffe18, 0xd853bce9, 0xb6414c52, 0x0b7d6bc6 51 | ]) 52 | ); 53 | }); 54 | 55 | test('sha512 | stream', () => { 56 | let stream = sha512.stream(); 57 | 58 | stream.update(new Uint32Array([0x54657374])); 59 | stream.update(new Uint32Array([0x54657374])); 60 | expect(stream.digest()).toEqual(new Uint32Array([ 61 | 0xf7c87428, 0xfadda0a5, 0x5c3cd42f, 0x353eb173, 0x4eb0e3d1, 0x8f3a46db, 0xc535f8c6, 0x53418a91, 62 | 0x52e74de7, 0x40270498, 0x35f1491f, 0x43ce5368, 0xbbbffe18, 0xd853bce9, 0xb6414c52, 0x0b7d6bc6 63 | ])); 64 | stream.clear(); 65 | 66 | stream.update('More generally, cryptography is about constructing and analyzing protocols that prevent third parties or the public from reading private '); 67 | stream.update('messages;[3] various aspects in information security such as data confidentiality, data integrity, authentication, and non-repudiation[4] '); 68 | stream.update('are central to modern cryptography. Modern cryptography exists at the intersection of the disciplines of mathematics, computer science, '); 69 | stream.update('electrical engineering, communication science, and physics. Applications of cryptography include electronic commerce, chip-based payment cards, '); 70 | stream.update('digital currencies, computer passwords, and military communications.'); 71 | 72 | expect(stream.digest('binary')).toEqual('\xd2\x20\x9e\x52\xf5\x31\x95\x33\x14\x9a\x51\x3e\x5a\x2d\x76\x28\x46\x60\x63\xd2\xd1\x52\x35\x1d\x7c\xab\xc2\x94\x84\x4d\x66\x69\x4d\x8e\xc3\x1e\xbf\x54\xc3\xb3\x0c\xe1\x7c\x53\xe6\x6e\x9c\xcb\xbb\x4f\x71\x97\xef\xb9\x59\x89\xb2\x18\x18\x3a\xf2\x26\xd5\xa7') 73 | }); 74 | 75 | test('sha512 | error', () => { 76 | const stream = sha512.stream(); 77 | let raised = false; 78 | 79 | try { 80 | stream.update('test'); 81 | stream.update(new Uint32Array([0x54657374])); 82 | stream.digest(); 83 | } catch (e) { 84 | raised = true; 85 | expect(e.message).toEqual('Unable to update hash-stream with array'); 86 | } 87 | 88 | expect(raised).toBeTruthy(); 89 | }); -------------------------------------------------------------------------------- /packages/utils/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@cryptography/utils", 3 | "description": "Shared internal utils for external packages", 4 | "version": "1.0.0", 5 | "author": "Konstantin Darutkin ", 6 | "dependencies": {}, 7 | "devDependencies": {}, 8 | "license": "MIT", 9 | "main": "dist/cjs/utils.min.js", 10 | "module": "dist/es/utils.js", 11 | "types": "dist/typings/index.d.ts", 12 | "scripts": { 13 | "build": "rm -rf dist/* && rollup -c" 14 | }, 15 | "files": [ 16 | "dist/*", 17 | "package.json" 18 | ] 19 | } 20 | -------------------------------------------------------------------------------- /packages/utils/rollup.config.js: -------------------------------------------------------------------------------- 1 | import getTypeScriptConfig from '../../scripts/rollup'; 2 | 3 | export default getTypeScriptConfig({ 4 | packageName: 'utils', 5 | entryFile: 'src/index.ts', 6 | }); 7 | -------------------------------------------------------------------------------- /packages/utils/src/converters.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Gets a uint32 from string in big-endian order order 3 | */ 4 | export function s2i(str: string, pos: number) { 5 | return ( 6 | str.charCodeAt(pos) << 24 7 | ^ str.charCodeAt(pos + 1) << 16 8 | ^ str.charCodeAt(pos + 2) << 8 9 | ^ str.charCodeAt(pos + 3) 10 | ); 11 | } 12 | 13 | /** 14 | * Returns a uint32 as a string in big-endian order order 15 | */ 16 | export function i2s(data: number) { 17 | return ( 18 | String.fromCharCode((data >> 24) & 0xFF) 19 | + String.fromCharCode((data >> 16) & 0xFF) 20 | + String.fromCharCode((data >> 8) & 0xFF) 21 | + String.fromCharCode(data & 0xFF) 22 | ); 23 | } 24 | 25 | /** 26 | * Returns a uint32 as a hex-string in big-endian order order 27 | */ 28 | export function i2h(data: number) { 29 | return `00000000${data.toString(16)}`.slice(-8); 30 | } 31 | -------------------------------------------------------------------------------- /packages/utils/src/index.ts: -------------------------------------------------------------------------------- 1 | export { i2h, i2s, s2i } from './converters'; 2 | 3 | export interface HashStream { 4 | update(chunk: string | Uint32Array): HashStream; 5 | digest(): Uint32Array; 6 | digest(format: 'hex' | 'binary'): string; 7 | } 8 | 9 | export interface HashFunction { 10 | (message: string | Uint32Array): Uint32Array; 11 | (message: string | Uint32Array, format: 'hex' | 'binary'): string; 12 | stream(buf?: Uint32Array): HashStream; 13 | blockLength: number; 14 | digestLength: number; 15 | } 16 | -------------------------------------------------------------------------------- /scripts/eslint.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | env: { 3 | browser: true, 4 | 'jest/globals': true, 5 | }, 6 | extends: [ 7 | 'airbnb-typescript', 8 | ], 9 | globals: { 10 | Atomics: 'readonly', 11 | SharedArrayBuffer: 'readonly', 12 | }, 13 | parser: '@typescript-eslint/parser', 14 | parserOptions: { 15 | ecmaVersion: 2018, 16 | sourceType: 'module', 17 | }, 18 | plugins: [ 19 | '@typescript-eslint', 20 | 'jest', 21 | ], 22 | rules: { 23 | 'no-bitwise': 'off', 24 | 'no-underscore-dangle': 'off', 25 | 'no-plusplus': 'off', 26 | 'max-len': ['error', { code: 160 }], 27 | 'import/export': 'off', 28 | 'prefer-destructuring': 'off', 29 | 'no-multi-assign': 'off', 30 | 'no-param-reassign': 'off', 31 | 'func-names': 'off', 32 | 'lines-between-class-members': 'off', 33 | }, 34 | ignorePatterns: [ 35 | 'dist/', 36 | 'tests/', 37 | 'node_modules/', 38 | ], 39 | }; 40 | -------------------------------------------------------------------------------- /scripts/rollup.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable import/no-extraneous-dependencies */ 2 | /* eslint-disable global-require */ 3 | /* eslint-disable import/no-dynamic-require */ 4 | import typescript from '@rollup/plugin-typescript'; 5 | import resolve from '@rollup/plugin-node-resolve'; 6 | import { terser } from 'rollup-plugin-terser'; 7 | 8 | export default function getTypeScriptConfig({ 9 | packageName, 10 | entryFile, 11 | formats = ['cjs', 'umd', 'es'], 12 | inlineDynamicImports = false, 13 | }) { 14 | return [ 15 | // js only 16 | { 17 | input: entryFile, 18 | inlineDynamicImports, 19 | output: [ 20 | ...formats.map((format) => ({ 21 | name: packageName, 22 | file: `dist/${format}/${packageName}.js`, 23 | format, 24 | })), 25 | ...formats.map((format) => ({ 26 | name: packageName, 27 | file: `dist/${format}/${packageName}.min.js`, 28 | format, 29 | plugins: [terser()], 30 | })), 31 | ], 32 | plugins: [ 33 | typescript({ 34 | typescript: require('typescript'), 35 | exclude: ['tests/*'], 36 | }), 37 | resolve({ 38 | jsnext: true, 39 | main: false, 40 | }), 41 | ], 42 | }, 43 | 44 | // declaration 45 | { 46 | input: entryFile, 47 | output: { 48 | dir: 'dist/typings', 49 | }, 50 | plugins: [ 51 | typescript({ 52 | emitDeclarationOnly: true, 53 | declaration: true, 54 | outDir: 'dist/typings', 55 | target: 'es5', 56 | rootDir: 'src', 57 | composite: true, 58 | exclude: ['tests/*'], 59 | include: ['src/**/*'], 60 | }), 61 | ], 62 | }, 63 | ]; 64 | } 65 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "noErrorTruncation": true, 4 | "strict": true, 5 | "strictFunctionTypes": true, 6 | "noUnusedLocals": true, 7 | "noUnusedParameters": true, 8 | "importHelpers": false, 9 | "declaration": true, 10 | "moduleResolution": "node", 11 | "sourceMap": false, 12 | "esModuleInterop": true, 13 | "target": "es5", 14 | "lib": ["es5", "es6", "es7", "es2017", "dom"], 15 | } 16 | } 17 | --------------------------------------------------------------------------------