diff --git a/.esmrc b/.esmrc
new file mode 100644
index 0000000..2017636
--- /dev/null
+++ b/.esmrc
@@ -0,0 +1,8 @@
+{
+ "mode": "all",
+ "cjs": {
+ "namedExports": true,
+ "vars": true,
+ "interop": true
+ }
+}
diff --git a/.gitignore b/.gitignore
index 4654e5c..dc9feaa 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,4 +6,5 @@ test/aes.asm.js.map
doc/
node_modules/
.idea/
-package-lock.json
+dist_es5
+dist_es8
diff --git a/.npmignore b/.npmignore
index 0ee4f76..47269b6 100644
--- a/.npmignore
+++ b/.npmignore
@@ -2,3 +2,4 @@ doc/
node_modules/
.idea/
package-lock.json
+*.ts
diff --git a/.prettierrc b/.prettierrc
new file mode 100644
index 0000000..4b9a2d9
--- /dev/null
+++ b/.prettierrc
@@ -0,0 +1,5 @@
+{
+ "printWidth": 120,
+ "singleQuote": true,
+ "trailingComma": "all"
+}
diff --git a/.travis.yml b/.travis.yml
index 8f2ca84..92c29d1 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,9 +1,9 @@
language: node_js
node_js:
- '8'
-- '9'
+- '10'
sudo: required
before_install:
export WITH=ALL
script:
- grunt test
+ npm test
diff --git a/Gruntfile.js b/Gruntfile.js
deleted file mode 100644
index af5f7c2..0000000
--- a/Gruntfile.js
+++ /dev/null
@@ -1,120 +0,0 @@
-// Grunt setup
-module.exports = function (grunt) {
- grunt.loadNpmTasks('grunt-contrib-uglify-es');
- grunt.loadNpmTasks('grunt-contrib-concat');
- grunt.loadNpmTasks('grunt-contrib-clean');
- grunt.loadNpmTasks('grunt-contrib-connect');
- grunt.loadNpmTasks('grunt-contrib-watch');
- grunt.loadNpmTasks('grunt-jsdoc');
- grunt.loadNpmTasks('grunt-rollup');
- grunt.loadNpmTasks('grunt-shell');
-
- // Finally, configure
- grunt.initConfig({
- pkg: grunt.file.readJSON('package.json'),
-
- rollup: {
- options: {
- format: 'umd',
- sourceMap: true,
- banner: "/*! asmCrypto<%= pkg.version && ' v'+pkg.version %>, (c) 2018 asmCrypto.js, opensource.org/licenses/<%= pkg.license %> */",
- },
- default: {
- options: {
- moduleName: 'asmCrypto',
- },
- files: {
- 'asmcrypto.js': './src/entry-default.js',
- },
- },
- all: {
- options: {
- moduleName: 'asmCrypto',
- },
- files: {
- 'asmcrypto.all.js': './src/entry-export_all.js',
- },
- },
- all_esm: {
- options: {
- format: 'es',
- },
- files: {
- 'asmcrypto.mjs': './src/entry-export_all.js',
- },
- },
- test_AES_ASM: {
- options: {
- moduleName: 'AES_asm',
- },
- files: {
- 'test/aes.asm.js': './src/aes/aes.asm.js',
- },
- },
- },
-
- shell: {
- test: {
- command: '"./node_modules/.bin/qunit-puppeteer" http://localhost:9999/index.html'
- }
- },
-
- uglify: {
- options: {
- mangle: {},
- compress: {},
- sourceMap: true,
- sourceMapIn: 'asmcrypto.js.map',
- sourceMapIncludeSources: true,
- screwIE8: true,
- banner: "/*! asmCrypto<%= pkg.version && ' v'+pkg.version %>, (c) 2018 asmCrypto.js, opensource.org/licenses/<%= pkg.license %> */",
- },
- all: {
- files: {
- 'asmcrypto.min.js': 'asmcrypto.js',
- },
- },
- },
-
- jsdoc: {
- all: {
- src: ['src/**/*.js', 'README.md'],
- options: {
- destination: 'doc',
- },
- },
- },
-
- connect: {
- all: {
- options: {
- hostname: 'localhost',
- port: 9999,
- base: ['test', '.'],
- directory: 'test',
- },
- },
- },
-
- watch: {
- all: {
- files: 'src/**/*.js',
- tasks: ['rollup:all', 'rollup:test_AES_ASM'],
- },
- },
-
- clean: [
- 'asmcrypto.js',
- 'asmcrypto.js.map',
- 'test/aes.asm.js',
- 'test/aes.asm.js.map',
- 'doc/',
- ],
- });
-
- grunt.registerTask('default', ['rollup:default', 'rollup:test_AES_ASM', 'uglify']);
- grunt.registerTask('all', ['rollup:all']);
- grunt.registerTask('esm', ['rollup:all_esm']);
- grunt.registerTask('devel', ['rollup:all', 'rollup:test_AES_ASM', 'connect', 'watch']);
- grunt.registerTask('test', ['connect', 'shell']);
-};
diff --git a/README.md b/README.md
index c81d44c..51fa9d5 100644
--- a/README.md
+++ b/README.md
@@ -3,58 +3,9 @@ asmCrypto [![Build Status](https://travis-ci.org/asmcrypto/asmcrypto.js.svg?bran
JavaScript implementation of popular cryptographic utilities with performance in mind.
-Synopsis
---------
-
-Add `` into your page.
-
- // Hash whole string at once
- digest = asmCrypto.SHA256.hex("The quick brown fox jumps over the lazy dog");
-
-Index
------
-
-* [Build & Test](#build--test)
-* [Performance](#performance)
-* [API Reference](#api-reference)
- * [Message Digest](#sha256)
- * [SHA1](#sha1)
- * [SHA256](#sha256)
- * [SHA512](#sha512)
- * [Hash-based Message Authentication](#hmac)
- * [HMAC-SHA1](#hmac_sha1)
- * [HMAC-SHA256](#hmac_sha256)
- * [HMAC-SHA512](#hmac_sha512)
- * [Password-based Key Derivation](#pbkdf2)
- * [PBKDF2-HMAC-SHA1](#pbkdf2_hmac_sha1)
- * [PBKDF2-HMAC-SHA256](#pbkdf2_hmac_sha256)
- * [PBKDF2-HMAC-SHA512](#pbkdf2_hmac_sha512)
- * [Block Cipher](#aes)
- * [AES-EBC](#aes_ecb)
- * [AES-CBC](#aes_cbc)
- * [AES-CFB](#aes_cfb)
- * [AES-OFB](#aes_ofb)
- * [AES-CTR](#aes_ctr)
- * [AES-CCM](#aes_ccm)
- * [AES-GCM](#aes_gcm)
- * [Asymmetric encryption](#rsa)
- * [RSA](#rsa)
- * [RSA-OAEP-SHA1](#rsa_oaep_sha1)
- * [RSA-OAEP-SHA256](#rsa_oaep_sha256)
- * [RSA-OAEP-SHA512](#rsa_oaep_sha512)
- * [RSA-PSS-SHA1](#rsa_pss_sha1)
- * [RSA-PSS-SHA256](#rsa_pss_sha256)
- * [RSA-PSS-SHA512](#rsa_pss_sha512)
- * [Cryptographically secure pseudorandom number generator](#cryptographically-secure-pseudorandom-number-generator)
-
-
Build & Test
------------
-Before you start check that [npm](http://npmjs.org/) is installed:
-
- npm --version
-
Then download and build the stuff:
git clone https://github.com/asmcrypto/asmcrypto.js.git
@@ -67,494 +18,18 @@ Running tests is always a good idea:
Congratulations! Now you have your `asmcrypto.js` ready to use ☺
-Performance
------------
-
-In the development of this project, special attention was paid to the performance issues.
-In the result of all the optimizations made this stuff is pretty fast under Firefox and Chrome.
-
Support
-----------
-* NodeJS 8 and NodeJS 9
-* IE11 (temporarily disabled, use previous versions: 0.16.x)
+* NodeJS 10
+* IE11
* last two Chrome versions
* last two Firefox versions and the latest Firefox ESR
* last two Edge versions
* last two Safari versions
-API Reference
--------------
-
-### Message Digest
-
-#### SHA1
-
-[Secure Hash Algorithm](http://en.wikipedia.org/wiki/SHA-1) — a cryptographic hash function with 160-bit output.
-
-A cryptographic hash fuction with 256-bit output.
-
-##### SHA1.BLOCK_SIZE = 64
-
-##### SHA1.HASH_SIZE = 20
-
-##### SHA1.bytes( data )
-
-Calculates message digest of the supplied input `data` (can be a binary string or `ArrayBuffer`/`Uint8Array` object).
-
-Returns raw message digest as an `Uint8Array` object.
-
-Throws
-* `TypeError` when something ridiculous is supplied as input data.
-
-##### SHA1.hex( data )
-
-Calculates message digest of the supplied input `data` (can be a binary string or `ArrayBuffer`/`Uint8Array` object).
-
-Returns a string containing hex-encoded message digest.
-
-Throws
-* `TypeError` when something ridiculous is supplied as input data.
-
-##### SHA1.base64( data )
-
-Calculates message digest of the supplied input `data` (can be a binary string or `ArrayBuffer`/`Uint8Array` object).
-
-Returns a string containing hex-encoded message digest.
-
-Throws
-* `TypeError` when something ridiculous is supplied as input data.
-
-#### SHA256
-
-[Secure Hash Algorithm](http://en.wikipedia.org/wiki/SHA-2) — a cryptographic hash functions family.
-
-A cryptographic hash fuction with 256-bit output.
-
-##### SHA256.BLOCK_SIZE = 64
-
-##### SHA256.HASH_SIZE = 32
-
-##### SHA256.bytes( data )
-
-Calculates message digest of the supplied input `data` (can be a binary string or `ArrayBuffer`/`Uint8Array` object).
-
-Returns raw message digest as an `Uint8Array` object.
-
-Throws
-* `TypeError` when something ridiculous is supplied as input data.
-
-##### SHA256.hex( data )
-
-Calculates message digest of the supplied input `data` (can be a binary string or `ArrayBuffer`/`Uint8Array` object).
-
-Returns a string containing hex-encoded message digest.
-
-Throws
-* `TypeError` when something ridiculous is supplied as input data.
-
-##### SHA256.base64( data )
-
-Calculates message digest of the supplied input `data` (can be a binary string or `ArrayBuffer`/`Uint8Array` object).
-
-Returns a string containing hex-encoded message digest.
-
-Throws
-* `TypeError` when something ridiculous is supplied as input data.
-
-#### SHA512
-
-A cryptographic hash function with 512-bit output.
-
-##### SHA512.BLOCK_SIZE = 128
-
-##### SHA512.HASH_SIZE = 64
-
-##### SHA512.bytes( data )
-
-Calculates message digest of the supplied input `data` (can be a binary string or `ArrayBuffer`/`Uint8Array` object).
-
-Returns raw message digest as an `Uint8Array` object.
-
-Throws
-* `TypeError` when something ridiculous is supplied as input data.
-
-##### SHA512.hex( data )
-
-Calculates message digest of the supplied input `data` (can be a binary string or `ArrayBuffer`/`Uint8Array` object).
-
-Returns a string containing hex-encoded message digest.
-
-Throws
-* `TypeError` when something ridiculous is supplied as input data.
-
-##### SHA512.base64( data )
-
-Calculates message digest of the supplied input `data` (can be a binary string or `ArrayBuffer`/`Uint8Array` object).
-
-Returns a string containing hex-encoded message digest.
-
-Throws
-* `TypeError` when something ridiculous is supplied as input data.
-
-### HMAC
-
-[Hash-based Message Authentication Code](http://en.wikipedia.org/wiki/HMAC)
-
-Used to calculate message authentication code with a cryptographic hash function
-in combination with a secret cryptographic key.
-
-#### HMAC_SHA1
-
-##### HMAC_SHA1.BLOCK_SIZE = 64
-
-##### HMAC_SHA1.HMAC_SIZE = 20
-
-##### HMAC_SHA1.bytes( data, password )
-
-Calculates HMAC-SHA1 of `data` with `password`. Both can be either binary strings or `Uint8Array`/`ArrayBuffer` objects.
-
-Returns araw message authentication code as an `Uint8Array` object.
-
-Throws
-* `TypeError` when something ridiculous is supplied as input data.
-
-##### HMAC_SHA1.hex( data, password )
-
-Calculates HMAC-SHA1 of `data` with `password`. Both can be either binary strings or `Uint8Array`/`ArrayBuffer` objects.
-
-Returns a string containing hex-encoded message authentication code.
-
-Throws
-* `TypeError` when something ridiculous is supplied as input data.
-
-##### HMAC_SHA1.base64( data, password )
-
-Calculates HMAC-SHA1 of `data` with `password`. Both can be either binary strings or `Uint8Array`/`ArrayBuffer` objects.
-
-Returns a string containing base64-encoded message authentication code.
-
-Throws
-* `TypeError` when something ridiculous is supplied as input data.
-
-#### HMAC_SHA256
-
-##### HMAC_SHA256.BLOCK_SIZE = 64
-
-##### HMAC_SHA256.HMAC_SIZE = 32
-
-##### HMAC_SHA256.bytes( data, password )
-
-Calculates HMAC-SHA256 of `data` with `password`. Both can be either binary strings or `Uint8Array`/`ArrayBuffer` objects.
-
-Returns araw message authentication code as an `Uint8Array` object.
-
-Throws
-* `TypeError` when something ridiculous is supplied as input data.
-
-##### HMAC_SHA256.hex( data, password )
-
-Calculates HMAC-SHA256 of `data` with `password`. Both can be either binary strings or `Uint8Array`/`ArrayBuffer` objects.
-
-Returns a string containing hex-encoded message authentication code.
-
-Throws
-* `TypeError` when something ridiculous is supplied as input data.
-
-##### HMAC_SHA256.base64( data, password )
-
-Calculates HMAC-SHA256 of `data` with `password`. Both can be either binary strings or `Uint8Array`/`ArrayBuffer` objects.
-
-Returns a string containing base64-encoded message authentication code.
-
-Throws
-* `TypeError` when something ridiculous is supplied as input data.
-
-#### HMAC_SHA512
-
-##### HMAC_SHA512.BLOCK_SIZE = 128
-
-##### HMAC_SHA512.HMAC_SIZE = 64
-
-##### HMAC_SHA512.bytes( data, password )
-
-Calculates HMAC-SHA512 of `data` with `password`. Both can be either binary strings or `Uint8Array`/`ArrayBuffer` objects.
-
-Returns araw message authentication code as an `Uint8Array` object.
-
-Throws
-* `TypeError` when something ridiculous is supplied as input data.
-
-##### HMAC_SHA512.hex( data, password )
-
-Calculates HMAC-SHA512 of `data` with `password`. Both can be either binary strings or `Uint8Array`/`ArrayBuffer` objects.
-
-Returns a string containing hex-encoded message authentication code.
-
-Throws
-* `TypeError` when something ridiculous is supplied as input data.
-
-##### HMAC_SHA512.base64( data, password )
-
-Calculates HMAC-SHA512 of `data` with `password`. Both can be either binary strings or `Uint8Array`/`ArrayBuffer` objects.
-
-Returns a string containing base64-encoded message authentication code.
-
-Throws
-* `TypeError` when something ridiculous is supplied as input data.
-
-### PBKDF2
-
-[Password-Based Key Derivation Function 2](http://en.wikipedia.org/wiki/PBKDF2)
-
-Applies a cryptographic hash function to the input password or passphrase along with a salt value and repeats the process many times to produce a derived key,
-which can then be used as a cryptographic key in subsequent operations. The added computational work makes password cracking much more difficult.
-
-#### PBKDF2_HMAC_SHA1
-
-##### PBKDF2_HMAC_SHA1.bytes( password, salt, iterations, dklen )
-
-Derive key from the `password` with `salt`. Both can be either binary strings or `Uint8Array`/`ArrayBuffer` objects.
-
-Optional `iterations` (number of key derivatoin rounds) and `dklen` (desired key length) may be supplied.
-
-Throws
-* `TypeError`.
-
-##### PBKDF2_HMAC_SHA1.hex( password, salt, iterations, dklen )
-
-The same as above except returning value type.
-
-##### PBKDF2_HMAC_SHA1.base64( password, salt, iterations, dklen )
-
-The same as above except returning value type.
-
-#### PBKDF2_HMAC_SHA256
-
-##### PBKDF2_HMAC_SHA256.bytes( password, salt, iterations, dklen )
-
-Derive key from the `password` with `salt`. Both can be either binary strings or `Uint8Array`/`ArrayBuffer` objects.
-
-Optional `iterations` (number of key derivatoin rounds) and `dklen` (desired key length) may be supplied.
-
-Throws
-* `TypeError`.
-
-##### PBKDF2_HMAC_SHA256.hex( password, salt, iterations, dklen )
-
-The same as above except returning value type.
-
-##### PBKDF2_HMAC_SHA256.base64( password, salt, iterations, dklen )
-
-The same as above except returning value type.
-
-#### PBKDF2_HMAC_SHA512
-
-##### PBKDF2_HMAC_SHA512.bytes( password, salt, iterations, dklen )
-
-Derive key from the `password` with `salt`. Both can be either binary strings or `Uint8Array`/`ArrayBuffer` objects.
-
-Optional `iterations` (number of key derivatoin rounds) and `dklen` (desired key length) may be supplied.
-
-Throws
-* `TypeError`.
-
-##### PBKDF2_HMAC_SHA512.hex( password, salt, iterations, dklen )
-
-The same as above except returning value type.
-
-##### PBKDF2_HMAC_SHA512.base64( password, salt, iterations, dklen )
-
-The same as above except returning value type.
-
-### AES
-
-Advanced Encryption Standard
-
-#### AES_ECB
-
-TODO
-
-#### AES_CBC
-
-Cipher Block Chaining Mode.
-
-##### AES_CBC.encrypt( data, key, padding, iv )
-
-Encrypts supplied `data` with `key` in CBC mode. Both can be either binary strings or `Uint8Array` objects or `ArrayBuffer` objects.
-
-Optional `padding` and `iv` may be passed to override default settings (PKCS#7 padding is on and iv is zero-vector).
-
-Returns encrypted data as `Uint8Array`.
-
-##### AES_CBC.decrypt( data, key, padding, iv )
-
-Decrypts supplied `data` with `key` in CBC mode. Both can be either binary strings or `Uint8Array` objects or `ArrayBuffer` objects.
-
-Optional `padding` and `iv` may be passed to override default settings (PKCS#7 padding is on and iv is zero-vector).
-
-Returns encrypted data as `Uint8Array`.
-
-#### AES_CFB
-
-Cipher Feedback Mode.
-
-##### AES_CFB.encrypt( data, key, iv )
-
-Encrypts supplied `data` with `key` in CFB mode. Both can be either binary strings or `Uint8Array` objects or `ArrayBuffer` objects.
-
-Optional `iv` may be passed to override default settings (zero-vector `iv`).
-
-Returns encrypted data as `Uint8Array`.
-
-##### AES_CFB.decrypt( data, key, iv )
-
-Decrypts supplied `data` with `key` in CFB mode. Both can be either binary strings or `Uint8Array` objects or `ArrayBuffer` objects.
-
-Optional `iv` may be passed to override default settings (zero-vector `iv`).
-
-Returns encrypted data as `Uint8Array`.
-
-#### AES_OFB
-
-Output Feedback Mode.
-
-##### AES_OFB.encrypt( data, key, iv )
-
-Encrypts supplied `data` with `key` in OFB mode. Both can be either binary strings or `Uint8Array` objects or `ArrayBuffer` objects.
-
-Optional `iv` may be passed to override default settings (zero-vector `iv`).
-
-Returns encrypted data as `Uint8Array`.
-
-##### AES_OFB.decrypt( data, key, iv )
-
-Decrypts supplied `data` with `key` in OFB mode. Both can be either binary strings or `Uint8Array` objects or `ArrayBuffer` objects.
-
-Optional `iv` may be passed to override default settings (zero-vector `iv`).
-
-Returns encrypted data as `Uint8Array`.
-
-#### AES_CTR
-
-TODO
-
-#### AES_CCM
-
-Counter with CBC-MAC mode.
-
-Due to JS limitations (counter is 32-bit unsigned) maximum encrypted message length is limited to near 64 GiB ( 2^36 - 16 ) per `nonce`-`key` pair.
-
-Additional authenticated data `adata` maximum length is limited to 65279 bytes ( 2^16 - 2^8 ),
-wich is considered enough for the most of use-cases.
-
-Optional `tagSize`, the size of the authentication tag, may be 4, 6, 8, 12, 16 (default).
-
-Keep in mind that **same nonce must not be used more than once with the same key**.
-
-##### AES_CCM.encrypt( data, key, nonce, adata, tagsize )
-
-Encrypts supplied `data` with `key`-`nonce` in CCM mode.
-
-Returns encrypted data as `Uint8Array`.
-
-##### AES_CCM.decrypt( data, key, nonce, adata, tagsize )
-
-Decrypts supplied `data` with `key`-`nonce` in CCM mode.
-
-Returns encrypted data as `Uint8Array`.
-
-#### AES_GCM
-
-TODO
-
-### RSA
-
-#### RSA.generateKey( bitlen, pubexp )
-
-Generate RSA private key of `bitlen` length along with the public exponent `pubexp`.
-
-#### RSA_OAEP_SHA1
-
-##### RSA_OAEP_SHA1.encrypt( data, key, label )
-
-TODO
-
-##### RSA_OAEP_SHA1.decrypt( data, key, label )
-
-TODO
-
-#### RSA_OAEP_SHA256
-
-##### RSA_OAEP_SHA256.encrypt( data, key, label )
-
-TODO
-
-##### RSA_OAEP_SHA256.decrypt( data, key, label )
-
-TODO
-
-#### RSA_OAEP_SHA512
-
-##### RSA_OAEP_SHA512.encrypt( data, key, label )
-
-TODO
-
-##### RSA_OAEP_SHA512.decrypt( data, key, label )
-
-TODO
-
-#### RSA_PSS_SHA1
-
-##### RSA_PSS_SHA1.sign( data, key, slen )
-
-TODO
-
-##### RSA_PSS_SHA1.verify( signature, data, key, slen )
-
-TODO
-
-#### RSA_PSS_SHA256
-
-##### RSA_PSS_SHA256.sign( data, key, slen )
-
-TODO
-
-##### RSA_PSS_SHA256.verify( signature, data, key, slen )
-
-TODO
-
-#### RSA_PSS_SHA512
-
-##### RSA_PSS_SHA512.sign( data, key, slen )
-
-TODO
-
-##### RSA_PSS_SHA512.verify( signature, data, key, slen )
-
-TODO
-
-### Cryptographically secure pseudorandom number generator
-
-ISAAC-based CSPRG
-
-##### random.getValues( buffer )
-
-Drop-in replacement for `window.crypto.getRandomValues`
-
-##### random.getValues.seed( seed )
-
-Perform PRNG seeding.
-
-##### random.getValues.allowWeak = false
-
-Allow implicitly-only seeded random output.
-
-##### random.getValues.skipSystemRNGWarning = false
-
-Disable implicit seeding warning when it's not desirable, e.g. at a unit test run.
+AsmCrypto 2.0
+-----------
-Not yet implemented:
-* scrypt,
-* dsa, ecdsa,
-* rsa-pkcs-v1.5
+* Moved to TypeScript
+* I have no confident knowledge on random generation, so I don't feel right maintaining it. As of 2.0 all custom random generation and seeding code is removed, the underlying browsers and environments have to provide secure random.
diff --git a/asmcrypto.js.d.ts b/asmcrypto.js.d.ts
deleted file mode 100644
index 545ed89..0000000
--- a/asmcrypto.js.d.ts
+++ /dev/null
@@ -1,388 +0,0 @@
-declare class BigNumber {
- static ZERO: BigNumber;
- static ONE: BigNumber;
-
- constructor(num?: Uint8Array);
-
- toString(radix?: number): string;
-
- toBytes(): Uint8Array;
-
- valueOf(): number;
-
- clamp(b: number): BigNumber;
-
- slice(f: number, b: number): BigNumber;
-
- negate(): BigNumber;
-
- compare(that: BigNumber): 0 | 1 | -1;
-
- add(that: BigNumber): BigNumber;
-
- subtract(that: BigNumber): BigNumber;
-
- multiply(that: BigNumber): BigNumber;
-
- square(): BigNumber;
-
- divide(that: BigNumber): BigNumber;
-}
-
-declare class AES {
- BLOCK_SIZE: number;
- result: Uint8Array;
-
- constructor(key: Uint8Array, iv?: Uint8Array, padding?: boolean, heap?: Uint8Array, asm?: Uint8Array);
-}
-
-declare interface AES_reset {
- (key: Uint8Array, iv?: Uint8Array, padding?: boolean): M;
-}
-
-declare interface AES_Encrypt_finish {
- (data?: Uint8Array): M;
-}
-
-declare interface AES_Decrypt_finish {
- (data?: Uint8Array): M;
-}
-
-declare interface AES_Encrypt_process {
- (data: Uint8Array): M;
-}
-
-declare interface AES_Decrypt_process {
- (data: Uint8Array): M;
-}
-
-declare interface RSA_OAEP_Encrypt {
- (data: Uint8Array, key: BigNumber[], label?: Uint8Array): Uint8Array;
-}
-
-declare interface RSA_OAEP_Decrypt {
- (data: Uint8Array, key: BigNumber[], label?: Uint8Array): Uint8Array;
-}
-
-declare interface RSA_PSS_Sign {
- (data: Uint8Array, key: BigNumber[], slen?: number): Uint8Array;
-}
-
-declare interface RSA_PSS_Verify {
- (signature: Uint8Array, data: Uint8Array, key: BigNumber[], slen?: number): boolean;
-}
-
-declare class AES_ECB_Encrypt extends AES {
- constructor(key: Uint8Array, heap?: Uint8Array);
-
- reset: AES_reset;
- process: AES_Encrypt_process;
- finish: AES_Encrypt_finish;
-}
-
-declare class AES_ECB extends AES {
- constructor(key: Uint8Array, heap?: Uint8Array, asm?: Uint8Array);
-
- encrypt: AES_Encrypt_finish;
- decrypt: AES_Decrypt_finish;
-}
-
-declare class AES_ECB_Decrypt extends AES {
- constructor(key: Uint8Array, heap?: Uint8Array);
-
- reset: AES_reset;
- process: AES_Encrypt_process;
- finish: AES_Decrypt_finish;
-}
-
-declare class AES_CBC_Encrypt extends AES {
- constructor(key: Uint8Array, iv: Uint8Array, padding?: boolean, heap?: Uint8Array, asm?: Uint8Array);
-
- reset: AES_reset;
- process: AES_Encrypt_process;
- finish: AES_Encrypt_finish;
-}
-
-declare class AES_CBC_Decrypt extends AES {
- constructor(key: Uint8Array, iv: Uint8Array, padding?: boolean, heap?: Uint8Array, asm?: Uint8Array);
-
- reset: AES_reset;
- process: AES_Encrypt_process;
- finish: AES_Decrypt_finish;
-}
-
-declare class AES_CCM_Encrypt extends AES {
- constructor(key: Uint8Array, nonce: Uint8Array, adata?: Uint8Array, dataLength?: number, tagSize?: number, heap?: Uint8Array, asm?: Uint8Array);
-
- reset: AES_reset;
- process: AES_Encrypt_process;
- finish: AES_Encrypt_finish;
-}
-
-declare class AES_CCM_Decrypt extends AES {
- constructor(key: Uint8Array, nonce: Uint8Array, adata?: Uint8Array, dataLength?: number, tagSize?: number, heap?: Uint8Array, asm?: Uint8Array);
-
- reset: AES_reset;
- process: AES_Encrypt_process;
- finish: AES_Decrypt_finish;
-}
-
-declare class AES_CFB_Encrypt extends AES {
- constructor(key: Uint8Array, iv?: Uint8Array, heap?: Uint8Array, asm?: Uint8Array);
-
- reset: AES_reset;
- process: AES_Encrypt_process;
- finish: AES_Encrypt_finish;
-}
-
-declare class AES_CFB_Decrypt extends AES {
- constructor(key: Uint8Array, iv?: Uint8Array, heap?: Uint8Array, asm?: Uint8Array);
-
- reset: AES_reset;
- process: AES_Encrypt_process;
- finish: AES_Decrypt_finish;
-}
-
-declare class AES_GCM_Encrypt extends AES {
- constructor(key: Uint8Array, nonce: Uint8Array, adata?: Uint8Array, tagSize?: number, heap?: Uint8Array, asm?: Uint8Array);
-
- reset: AES_reset;
- process: AES_Encrypt_process;
- finish: AES_Encrypt_finish;
-}
-
-declare class AES_GCM_Decrypt extends AES {
- constructor(key: Uint8Array, nonce: Uint8Array, adata?: Uint8Array, tagSize?: number, heap?: Uint8Array, asm?: Uint8Array);
-
- reset: AES_reset;
- process: AES_Encrypt_process;
- finish: AES_Decrypt_finish;
-}
-
-declare class AES_OFB extends AES {
- constructor(key: Uint8Array, iv?: Uint8Array, heap?: Uint8Array, asm?: Uint8Array);
-
- reset: AES_reset;
- process: AES_Encrypt_process;
- finish: AES_Encrypt_finish;
-}
-
-declare class AES_CTR extends AES {
- constructor(key: Uint8Array, nonce: Uint8Array, heap?: Uint8Array, asm?: Uint8Array);
-
- reset(key: Uint8Array, nonce: Uint8Array, counter?: number, counterSize?: number): AES_CTR;
-
- process: AES_Encrypt_process;
- finish: AES_Encrypt_finish;
-}
-
-declare class AES_CBC {
- static encrypt: (data: Uint8Array, key: Uint8Array, padding?: boolean, iv?: Uint8Array) => Uint8Array;
- static decrypt: (data: Uint8Array, key: Uint8Array, padding?: boolean, iv?: Uint8Array) => Uint8Array;
-}
-
-declare class AES_CCM {
- static encrypt: (data: Uint8Array, key: Uint8Array, nonce: Uint8Array, adata?: Uint8Array, tagSize?: number) => Uint8Array;
- static decrypt: (data: Uint8Array, key: Uint8Array, nonce: Uint8Array, adata?: Uint8Array, tagSize?: number) => Uint8Array;
-}
-
-declare class AES_CFB {
- static encrypt: (data: Uint8Array, key: Uint8Array, iv?: Uint8Array) => Uint8Array;
- static decrypt: (data: Uint8Array, key: Uint8Array, iv?: Uint8Array) => Uint8Array;
-}
-
-declare class AES_CTR {
- static encrypt: (data: Uint8Array, key: Uint8Array, nonce: Uint8Array) => Uint8Array;
- static decrypt: (data: Uint8Array, key: Uint8Array, nonce: Uint8Array) => Uint8Array;
-}
-
-declare class AES_OFB {
- static encrypt: (data: Uint8Array, key: Uint8Array, iv?: Uint8Array) => Uint8Array;
- static decrypt: (data: Uint8Array, key: Uint8Array, iv?: Uint8Array) => Uint8Array;
-}
-
-declare class AES_GCM {
- static encrypt: (data: Uint8Array, key: Uint8Array, nonce: Uint8Array, adata?: Uint8Array, tagSize?: number) => Uint8Array;
- static decrypt: (data: Uint8Array, key: Uint8Array, nonce: Uint8Array, adata?: Uint8Array, tagSize?: number) => Uint8Array;
-}
-
-declare class SHA1 {
- result: Uint8Array;
-
- static bytes(data: Uint8Array): Uint8Array;
-
- static hex(data: Uint8Array): string;
-
- static base64(data: Uint8Array): string;
-
- constructor(options?: { asm?: Uint8Array, heap?: Uint8Array, heapSize?: number });
-
- reset(): SHA1;
-
- process(data: Uint8Array): SHA1;
-
- finish(): SHA1;
-}
-
-declare class SHA256 {
- result: Uint8Array;
-
- static bytes(data: Uint8Array): Uint8Array;
-
- static hex(data: Uint8Array): string;
-
- static base64(data: Uint8Array): string;
-
- constructor(options?: { asm?: Uint8Array, heap?: Uint8Array, heapSize?: number });
-
- reset(): SHA256;
-
- process(data: Uint8Array): SHA256;
-
- finish(): SHA256;
-}
-
-declare class SHA512 {
- result: Uint8Array;
-
- static bytes(data: Uint8Array): Uint8Array;
-
- static hex(data: Uint8Array): string;
-
- static base64(data: Uint8Array): string;
-
- constructor(options?: { asm?: Uint8Array, heap?: Uint8Array, heapSize?: number });
-
- reset(): SHA512;
-
- process(data: Uint8Array): SHA512;
-
- finish(): SHA512;
-}
-
-declare class HMAC_SHA1 {
- result: Uint8Array;
-
- static bytes(data: Uint8Array, password: Uint8Array): Uint8Array;
-
- static hex(data: Uint8Array, password: Uint8Array): string;
-
- static base64(data: Uint8Array, password: Uint8Array): string;
-
- constructor(options?: { asm?: Uint8Array, heap?: Uint8Array, heapSize?: number, password?: Uint8Array, hash?: SHA1 });
-
- reset(options: { password: Uint8Array }): HMAC_SHA1;
-
- process(data: Uint8Array): HMAC_SHA1;
-
- finish(): HMAC_SHA1;
-}
-
-declare class HMAC_SHA256 {
- result: Uint8Array;
-
- static bytes(data: Uint8Array, password: Uint8Array): Uint8Array;
-
- static hex(data: Uint8Array, password: Uint8Array): string;
-
- static base64(data: Uint8Array, password: Uint8Array): string;
-
- constructor(options?: { asm?: Uint8Array, heap?: Uint8Array, heapSize?: number, password?: Uint8Array, hash?: SHA256 });
-
- reset(options: { password: Uint8Array }): HMAC_SHA256;
-
- process(data: Uint8Array): HMAC_SHA256;
-
- finish(): HMAC_SHA256;
-}
-
-declare class HMAC_SHA512 {
- result: Uint8Array;
-
- static bytes(data: Uint8Array, password: Uint8Array): Uint8Array;
-
- static hex(data: Uint8Array, password: Uint8Array): string;
-
- static base64(data: Uint8Array, password: Uint8Array): string;
-
- constructor(options?: { asm?: Uint8Array, heap?: Uint8Array, heapSize?: number, password?: Uint8Array, hash?: SHA512 });
-
- reset(options: { password: Uint8Array }): HMAC_SHA512;
-
- process(data: Uint8Array): HMAC_SHA512;
-
- finish(): HMAC_SHA512;
-}
-
-declare class PBKDF2_HMAC_SHA1 {
- static bytes(password: Uint8Array, salt: Uint8Array, iterations?: number, dklen?: number): Uint8Array;
-
- static hex(password: Uint8Array, salt: Uint8Array, iterations?: number, dklen?: number): Uint8Array;
-
- static base64(password: Uint8Array, salt: Uint8Array, iterations?: number, dklen?: number): Uint8Array;
-}
-
-declare class PBKDF2_HMAC_SHA256 {
- static bytes(password: Uint8Array, salt: Uint8Array, iterations?: number, dklen?: number): Uint8Array;
-
- static hex(password: Uint8Array, salt: Uint8Array, iterations?: number, dklen?: number): Uint8Array;
-
- static base64(password: Uint8Array, salt: Uint8Array, iterations?: number, dklen?: number): Uint8Array;
-}
-
-declare class PBKDF2_HMAC_SHA512 {
- static bytes(password: Uint8Array, salt: Uint8Array, iterations?: number, dklen?: number): Uint8Array;
-
- static hex(password: Uint8Array, salt: Uint8Array, iterations?: number, dklen?: number): Uint8Array;
-
- static base64(password: Uint8Array, salt: Uint8Array, iterations?: number, dklen?: number): Uint8Array;
-}
-
-declare class RSA_OAEP_SHA1 {
- static encrypt: RSA_OAEP_Encrypt;
- static decrypt: RSA_OAEP_Decrypt;
-}
-
-declare class RSA_OAEP_SHA256 {
- static encrypt: RSA_OAEP_Encrypt;
- static decrypt: RSA_OAEP_Decrypt;
-}
-
-declare class RSA_OAEP_SHA512 {
- static encrypt: RSA_OAEP_Encrypt;
- static decrypt: RSA_OAEP_Decrypt;
-}
-
-declare class RSA_PSS_SHA1 {
- static sign: RSA_PSS_Sign;
- static verify: RSA_PSS_Verify;
-}
-
-declare class RSA_PSS_SHA256 {
- static sign: RSA_PSS_Sign;
- static verify: RSA_PSS_Verify;
-}
-
-declare class RSA_PSS_SHA512 {
- static sign: RSA_PSS_Sign;
- static verify: RSA_PSS_Verify;
-}
-
-declare function random(): number;
-
-declare namespace random {
- export function seed(data: Uint8Array): boolean;
-}
-
-
-declare function string_to_bytes(s: string): Uint8Array;
-
-declare function hex_to_bytes(s: string): Uint8Array;
-
-declare function base64_to_bytes(s: string): Uint8Array;
-
-declare function bytes_to_string(bytes: Uint8Array): string;
-
-declare function bytes_to_hex(bytes: Uint8Array): string;
-
-declare function bytes_to_base64(bytes: Uint8Array): string;
diff --git a/bower.json b/bower.json
deleted file mode 100644
index d270ec7..0000000
--- a/bower.json
+++ /dev/null
@@ -1,24 +0,0 @@
-{
- "name": "asmcrypto",
- "main": "asmcrypto.js",
- "license": "MIT",
- "ignore": [
- "**/.*",
- "node_modules",
- "test",
- "test.html",
- "Gruntfile.js",
- "package.json"
- ],
- "keywords": [
- "crypto",
- "asmcrypto",
- "webcrypto",
- "library",
- "sha", "sha1", "sha256", "sha512",
- "hmac",
- "pbkdf", "pbkdf2",
- "aes", "aes256", "cbc", "ccm", "cfb",
- "rsa", "oaep", "pss", "pkcs"
- ]
-}
diff --git a/build.js b/build.js
new file mode 100644
index 0000000..3c89821
--- /dev/null
+++ b/build.js
@@ -0,0 +1,88 @@
+import fs from 'fs-extra';
+import ts from 'typescript';
+import rollup from 'rollup';
+import UglifyJS from 'uglify-js';
+import UglifyES from 'uglify-es';
+
+(async function() {
+ // Delete old
+ await fs.remove('dist_es5');
+ await fs.remove('dist_es8');
+
+ // Run ts
+ const raw_config = await fs.readFile('tsconfig.json', 'utf8');
+ const options_es5_raw = JSON.parse(raw_config).compilerOptions;
+ options_es5_raw.target = 'es5';
+ options_es5_raw.outDir = 'dist_es5';
+ const options_es8_raw = JSON.parse(raw_config).compilerOptions;
+
+ const options_es5 = ts.convertCompilerOptionsFromJson(options_es5_raw, '.');
+ const options_es8 = ts.convertCompilerOptionsFromJson(options_es8_raw, '.');
+
+ const program_es5 = ts.createProgram(['src/entry-export_all.ts'], options_es5.options);
+ const program_es8 = ts.createProgram(['src/entry-export_all.ts'], options_es8.options);
+ program_es5.emit();
+ program_es8.emit();
+
+ // Copy non-ts resources
+ await fs.copy('src/aes/aes.asm.js', 'dist_es5/aes/aes.asm.js');
+ await fs.copy('src/aes/aes.asm.js', 'dist_es8/aes/aes.asm.js');
+
+ await fs.copy('src/bignum/bigint.asm.js', 'dist_es5/bignum/bigint.asm.js');
+ await fs.copy('src/bignum/bigint.asm.js', 'dist_es8/bignum/bigint.asm.js');
+
+ await fs.copy('src/hash/sha1/sha1.asm.js', 'dist_es5/hash/sha1/sha1.asm.js');
+ await fs.copy('src/hash/sha1/sha1.asm.js', 'dist_es8/hash/sha1/sha1.asm.js');
+
+ await fs.copy('src/hash/sha256/sha256.asm.js', 'dist_es5/hash/sha256/sha256.asm.js');
+ await fs.copy('src/hash/sha256/sha256.asm.js', 'dist_es8/hash/sha256/sha256.asm.js');
+
+ await fs.copy('src/hash/sha512/sha512.asm.js', 'dist_es5/hash/sha512/sha512.asm.js');
+ await fs.copy('src/hash/sha512/sha512.asm.js', 'dist_es8/hash/sha512/sha512.asm.js');
+
+ const es5bundle = await rollup.rollup({
+ input: 'dist_es5/entry-export_all.js',
+ onwarn(warning, warn) {
+ if (warning.code === 'THIS_IS_UNDEFINED') return;
+ warn(warning); // this requires Rollup 0.46
+ },
+ });
+
+ // Legacy browser export, as a bundle
+ await es5bundle.write({
+ file: 'asmcrypto.all.es5.js',
+ format: 'iife',
+ name: 'asmCrypto',
+ });
+
+ // NodeJS old
+ await es5bundle.write({
+ file: 'asmcrypto.all.js',
+ format: 'cjs',
+ });
+
+ const legacyCode = await fs.readFile('asmcrypto.all.es5.js', 'utf8');
+ const { error, code } = UglifyJS.minify(legacyCode, { compress: { inline: false } });
+ if (error) throw new Error(`Uglify failed: ${error}`);
+ await fs.writeFile('asmcrypto.all.es5.min.js', code, 'utf8');
+
+ // Modern export, eg. Chrome or NodeJS 10 with ESM
+ const es8bundle = await rollup.rollup({
+ input: 'dist_es8/entry-export_all.js',
+ onwarn(warning, warn) {
+ if (warning.code === 'THIS_IS_UNDEFINED') return;
+ warn(warning); // this requires Rollup 0.46
+ },
+ });
+ await es8bundle.write({
+ file: 'asmcrypto.all.es8.js',
+ format: 'es',
+ });
+
+ const es8Code = await fs.readFile('asmcrypto.all.es8.js', 'utf8');
+ const { error: errorEs8, code: codeEs8 } = UglifyES.minify(es8Code, { compress: { inline: false } });
+ if (errorEs8) throw new Error(`Uglify failed: ${error}`);
+ await fs.writeFile('asmcrypto.all.es8.min.js', codeEs8, 'utf8');
+
+ console.log('Build complete');
+})();
diff --git a/package-lock.json b/package-lock.json
new file mode 100644
index 0000000..24f1104
--- /dev/null
+++ b/package-lock.json
@@ -0,0 +1,659 @@
+{
+ "name": "asmcrypto.js",
+ "version": "2.0.0",
+ "lockfileVersion": 1,
+ "requires": true,
+ "dependencies": {
+ "@types/chai": {
+ "version": "4.1.3",
+ "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.1.3.tgz",
+ "integrity": "sha512-f5dXGzOJycyzSMdaXVhiBhauL4dYydXwVpavfQ1mVCaGjR56a9QfklXObUxlIY9bGTmCPHEEZ04I16BZ/8w5ww==",
+ "dev": true
+ },
+ "@types/estree": {
+ "version": "0.0.39",
+ "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz",
+ "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==",
+ "dev": true
+ },
+ "@types/mocha": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-5.2.1.tgz",
+ "integrity": "sha512-dOrgprHnkDaj1pmrwdcMAf0QRNQzqTB5rxJph+iIQshSmIvtgRqJ0nim8u1vvXU8iOXZrH96+M46JDFTPLingA==",
+ "dev": true
+ },
+ "@types/node": {
+ "version": "10.3.0",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-10.3.0.tgz",
+ "integrity": "sha512-hWzNviaVFIr1TqcRA8ou49JaSHp+Rfabmnqg2kNvusKqLhPU0rIsGPUj5WJJ7ld4Bb7qdgLmIhLfCD1qS08IVA==",
+ "dev": true
+ },
+ "ansi-regex": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
+ "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
+ "dev": true
+ },
+ "ansi-styles": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
+ "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+ "dev": true,
+ "requires": {
+ "color-convert": "^1.9.0"
+ }
+ },
+ "argparse": {
+ "version": "1.0.10",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
+ "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
+ "dev": true,
+ "requires": {
+ "sprintf-js": "~1.0.2"
+ }
+ },
+ "arrify": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz",
+ "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=",
+ "dev": true
+ },
+ "assertion-error": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz",
+ "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==",
+ "dev": true
+ },
+ "babel-code-frame": {
+ "version": "6.26.0",
+ "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz",
+ "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=",
+ "dev": true,
+ "requires": {
+ "chalk": "^1.1.3",
+ "esutils": "^2.0.2",
+ "js-tokens": "^3.0.2"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
+ "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
+ "dev": true
+ },
+ "chalk": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
+ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^2.2.1",
+ "escape-string-regexp": "^1.0.2",
+ "has-ansi": "^2.0.0",
+ "strip-ansi": "^3.0.0",
+ "supports-color": "^2.0.0"
+ }
+ },
+ "supports-color": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
+ "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
+ "dev": true
+ }
+ }
+ },
+ "balanced-match": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
+ "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
+ "dev": true
+ },
+ "brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "dev": true,
+ "requires": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "browser-stdout": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz",
+ "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==",
+ "dev": true
+ },
+ "buffer-from": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.0.tgz",
+ "integrity": "sha512-c5mRlguI/Pe2dSZmpER62rSCu0ryKmWddzRYsuXc50U2/g8jMOulc31VZMa4mYx31U5xsmSOpDCgH88Vl9cDGQ==",
+ "dev": true
+ },
+ "builtin-modules": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz",
+ "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=",
+ "dev": true
+ },
+ "chai": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chai/-/chai-4.1.2.tgz",
+ "integrity": "sha1-D2RYS6ZC8PKs4oBiefTwbKI61zw=",
+ "dev": true,
+ "requires": {
+ "assertion-error": "^1.0.1",
+ "check-error": "^1.0.1",
+ "deep-eql": "^3.0.0",
+ "get-func-name": "^2.0.0",
+ "pathval": "^1.0.0",
+ "type-detect": "^4.0.0"
+ }
+ },
+ "chalk": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz",
+ "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^3.2.1",
+ "escape-string-regexp": "^1.0.5",
+ "supports-color": "^5.3.0"
+ }
+ },
+ "check-error": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz",
+ "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=",
+ "dev": true
+ },
+ "color-convert": {
+ "version": "1.9.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.1.tgz",
+ "integrity": "sha512-mjGanIiwQJskCC18rPR6OmrZ6fm2Lc7PeGFYwCmy5J34wC6F1PzdGL6xeMfmgicfYcNLGuVFA3WzXtIDCQSZxQ==",
+ "dev": true,
+ "requires": {
+ "color-name": "^1.1.1"
+ }
+ },
+ "color-name": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
+ "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
+ "dev": true
+ },
+ "commander": {
+ "version": "2.15.1",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz",
+ "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==",
+ "dev": true
+ },
+ "concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
+ "dev": true
+ },
+ "debug": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
+ "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
+ "dev": true,
+ "requires": {
+ "ms": "2.0.0"
+ }
+ },
+ "deep-eql": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz",
+ "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==",
+ "dev": true,
+ "requires": {
+ "type-detect": "^4.0.0"
+ }
+ },
+ "diff": {
+ "version": "3.5.0",
+ "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz",
+ "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==",
+ "dev": true
+ },
+ "escape-string-regexp": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+ "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
+ "dev": true
+ },
+ "eslint-plugin-prettier": {
+ "version": "2.6.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-2.6.0.tgz",
+ "integrity": "sha512-floiaI4F7hRkTrFe8V2ItOK97QYrX75DjmdzmVITZoAP6Cn06oEDPQRsO6MlHEP/u2SxI3xQ52Kpjw6j5WGfeQ==",
+ "dev": true,
+ "requires": {
+ "fast-diff": "^1.1.1",
+ "jest-docblock": "^21.0.0"
+ }
+ },
+ "esm": {
+ "version": "3.0.36",
+ "resolved": "https://registry.npmjs.org/esm/-/esm-3.0.36.tgz",
+ "integrity": "sha512-TbvRhqBH66jIZS8yIPqWPeX3CD8itgi/BZAoCf9zWn5U/RZ6A7R2X/rrtRJ31NG0Gu71jqP5UmGKKpaYTzx81A==",
+ "dev": true
+ },
+ "esprima": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz",
+ "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==",
+ "dev": true
+ },
+ "esutils": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz",
+ "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=",
+ "dev": true
+ },
+ "fast-diff": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.1.2.tgz",
+ "integrity": "sha512-KaJUt+M9t1qaIteSvjc6P3RbMdXsNhK61GRftR6SNxqmhthcd9MGIi4T+o0jD8LUSpSnSKXE20nLtJ3fOHxQig==",
+ "dev": true
+ },
+ "fs-extra": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-6.0.1.tgz",
+ "integrity": "sha512-GnyIkKhhzXZUWFCaJzvyDLEEgDkPfb4/TPvJCJVuS8MWZgoSsErf++QpiAlDnKFcqhRlm+tIOcencCjyJE6ZCA==",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "^4.1.2",
+ "jsonfile": "^4.0.0",
+ "universalify": "^0.1.0"
+ }
+ },
+ "fs.realpath": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
+ "dev": true
+ },
+ "get-func-name": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz",
+ "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=",
+ "dev": true
+ },
+ "glob": {
+ "version": "7.1.2",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz",
+ "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==",
+ "dev": true,
+ "requires": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.0.4",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ }
+ },
+ "graceful-fs": {
+ "version": "4.1.11",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz",
+ "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=",
+ "dev": true
+ },
+ "growl": {
+ "version": "1.10.5",
+ "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz",
+ "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==",
+ "dev": true
+ },
+ "has-ansi": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz",
+ "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^2.0.0"
+ }
+ },
+ "has-flag": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+ "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
+ "dev": true
+ },
+ "he": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz",
+ "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=",
+ "dev": true
+ },
+ "inflight": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+ "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
+ "dev": true,
+ "requires": {
+ "once": "^1.3.0",
+ "wrappy": "1"
+ }
+ },
+ "inherits": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
+ "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=",
+ "dev": true
+ },
+ "jest-docblock": {
+ "version": "21.2.0",
+ "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-21.2.0.tgz",
+ "integrity": "sha512-5IZ7sY9dBAYSV+YjQ0Ovb540Ku7AO9Z5o2Cg789xj167iQuZ2cG+z0f3Uct6WeYLbU6aQiM2pCs7sZ+4dotydw==",
+ "dev": true
+ },
+ "js-tokens": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz",
+ "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=",
+ "dev": true
+ },
+ "js-yaml": {
+ "version": "3.11.0",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.11.0.tgz",
+ "integrity": "sha512-saJstZWv7oNeOyBh3+Dx1qWzhW0+e6/8eDzo7p5rDFqxntSztloLtuKu+Ejhtq82jsilwOIZYsCz+lIjthg1Hw==",
+ "dev": true,
+ "requires": {
+ "argparse": "^1.0.7",
+ "esprima": "^4.0.0"
+ }
+ },
+ "jsonfile": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
+ "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "^4.1.6"
+ }
+ },
+ "make-error": {
+ "version": "1.3.4",
+ "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.4.tgz",
+ "integrity": "sha512-0Dab5btKVPhibSalc9QGXb559ED7G7iLjFXBaj9Wq8O3vorueR5K5jaE3hkG6ZQINyhA/JgG6Qk4qdFQjsYV6g==",
+ "dev": true
+ },
+ "minimatch": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
+ "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
+ "dev": true,
+ "requires": {
+ "brace-expansion": "^1.1.7"
+ }
+ },
+ "minimist": {
+ "version": "0.0.8",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
+ "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=",
+ "dev": true
+ },
+ "mkdirp": {
+ "version": "0.5.1",
+ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
+ "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
+ "dev": true,
+ "requires": {
+ "minimist": "0.0.8"
+ }
+ },
+ "mocha": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/mocha/-/mocha-5.2.0.tgz",
+ "integrity": "sha512-2IUgKDhc3J7Uug+FxMXuqIyYzH7gJjXECKe/w43IGgQHTSj3InJi+yAA7T24L9bQMRKiUEHxEX37G5JpVUGLcQ==",
+ "dev": true,
+ "requires": {
+ "browser-stdout": "1.3.1",
+ "commander": "2.15.1",
+ "debug": "3.1.0",
+ "diff": "3.5.0",
+ "escape-string-regexp": "1.0.5",
+ "glob": "7.1.2",
+ "growl": "1.10.5",
+ "he": "1.1.1",
+ "minimatch": "3.0.4",
+ "mkdirp": "0.5.1",
+ "supports-color": "5.4.0"
+ }
+ },
+ "ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
+ "dev": true
+ },
+ "once": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+ "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
+ "dev": true,
+ "requires": {
+ "wrappy": "1"
+ }
+ },
+ "path-is-absolute": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+ "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
+ "dev": true
+ },
+ "path-parse": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz",
+ "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=",
+ "dev": true
+ },
+ "pathval": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.0.tgz",
+ "integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA=",
+ "dev": true
+ },
+ "prettier": {
+ "version": "1.13.4",
+ "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.13.4.tgz",
+ "integrity": "sha512-emsEZ2bAigL1lq6ssgkpPm1MIBqgeTvcp90NxOP5XDqprub/V/WS2Hfgih3mS7/1dqTUvhG+sxx1Dv8crnVexA==",
+ "dev": true
+ },
+ "resolve": {
+ "version": "1.7.1",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.7.1.tgz",
+ "integrity": "sha512-c7rwLofp8g1U+h1KNyHL/jicrKg1Ek4q+Lr33AL65uZTinUZHe30D5HlyN5V9NW0JX1D5dXQ4jqW5l7Sy/kGfw==",
+ "dev": true,
+ "requires": {
+ "path-parse": "^1.0.5"
+ }
+ },
+ "rollup": {
+ "version": "0.59.4",
+ "resolved": "https://registry.npmjs.org/rollup/-/rollup-0.59.4.tgz",
+ "integrity": "sha512-ISiMqq/aJa+57QxX2MRcvLESHdJ7wSavmr6U1euMr+6UgFe6KM+3QANrYy8LQofwhTC1I7BcAdlLnDiaODs1BA==",
+ "dev": true,
+ "requires": {
+ "@types/estree": "0.0.39",
+ "@types/node": "*"
+ }
+ },
+ "semver": {
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz",
+ "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==",
+ "dev": true
+ },
+ "source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true
+ },
+ "source-map-support": {
+ "version": "0.5.6",
+ "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.6.tgz",
+ "integrity": "sha512-N4KXEz7jcKqPf2b2vZF11lQIz9W5ZMuUcIOGj243lduidkf2fjkVKJS9vNxVWn3u/uxX38AcE8U9nnH9FPcq+g==",
+ "dev": true,
+ "requires": {
+ "buffer-from": "^1.0.0",
+ "source-map": "^0.6.0"
+ }
+ },
+ "sprintf-js": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
+ "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=",
+ "dev": true
+ },
+ "strip-ansi": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
+ "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^2.0.0"
+ }
+ },
+ "supports-color": {
+ "version": "5.4.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz",
+ "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^3.0.0"
+ }
+ },
+ "ts-node": {
+ "version": "6.0.5",
+ "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-6.0.5.tgz",
+ "integrity": "sha512-iNhWu2hli9/1p9PGLJ/4OZS+NR0IVEVk63KCrH3qa7jJZxXa+oPheBj5JyM8tuQM9RkBpw1PrNUEUPJR9wTGDw==",
+ "dev": true,
+ "requires": {
+ "arrify": "^1.0.0",
+ "chalk": "^2.3.0",
+ "diff": "^3.1.0",
+ "make-error": "^1.1.1",
+ "minimist": "^1.2.0",
+ "mkdirp": "^0.5.1",
+ "source-map-support": "^0.5.3",
+ "yn": "^2.0.0"
+ },
+ "dependencies": {
+ "minimist": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
+ "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
+ "dev": true
+ }
+ }
+ },
+ "tslib": {
+ "version": "1.9.2",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.2.tgz",
+ "integrity": "sha512-AVP5Xol3WivEr7hnssHDsaM+lVrVXWUvd1cfXTRkTj80b//6g2wIFEH6hZG0muGZRnHGrfttpdzRk3YlBkWjKw==",
+ "dev": true
+ },
+ "tslint": {
+ "version": "5.10.0",
+ "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.10.0.tgz",
+ "integrity": "sha1-EeJrzLiK+gLdDZlWyuPUVAtfVMM=",
+ "dev": true,
+ "requires": {
+ "babel-code-frame": "^6.22.0",
+ "builtin-modules": "^1.1.1",
+ "chalk": "^2.3.0",
+ "commander": "^2.12.1",
+ "diff": "^3.2.0",
+ "glob": "^7.1.1",
+ "js-yaml": "^3.7.0",
+ "minimatch": "^3.0.4",
+ "resolve": "^1.3.2",
+ "semver": "^5.3.0",
+ "tslib": "^1.8.0",
+ "tsutils": "^2.12.1"
+ }
+ },
+ "tslint-plugin-prettier": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/tslint-plugin-prettier/-/tslint-plugin-prettier-1.3.0.tgz",
+ "integrity": "sha512-6UqeeV6EABp0RdQkW6eC1vwnAXcKMGJgPeJ5soXiKdSm2vv7c3dp+835CM8pjgx9l4uSa7tICm1Kli+SMsADDg==",
+ "dev": true,
+ "requires": {
+ "eslint-plugin-prettier": "^2.2.0",
+ "tslib": "^1.7.1"
+ }
+ },
+ "tsutils": {
+ "version": "2.27.1",
+ "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.27.1.tgz",
+ "integrity": "sha512-AE/7uzp32MmaHvNNFES85hhUDHFdFZp6OAiZcd6y4ZKKIg6orJTm8keYWBhIhrJQH3a4LzNKat7ZPXZt5aTf6w==",
+ "dev": true,
+ "requires": {
+ "tslib": "^1.8.1"
+ }
+ },
+ "type-detect": {
+ "version": "4.0.8",
+ "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz",
+ "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==",
+ "dev": true
+ },
+ "typescript": {
+ "version": "2.9.1",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-2.9.1.tgz",
+ "integrity": "sha512-h6pM2f/GDchCFlldnriOhs1QHuwbnmj6/v7499eMHqPeW4V2G0elua2eIc2nu8v2NdHV0Gm+tzX83Hr6nUFjQA==",
+ "dev": true
+ },
+ "uglify-es": {
+ "version": "3.3.9",
+ "resolved": "https://registry.npmjs.org/uglify-es/-/uglify-es-3.3.9.tgz",
+ "integrity": "sha512-r+MU0rfv4L/0eeW3xZrd16t4NZfK8Ld4SWVglYBb7ez5uXFWHuVRs6xCTrf1yirs9a4j4Y27nn7SRfO6v67XsQ==",
+ "dev": true,
+ "requires": {
+ "commander": "~2.13.0",
+ "source-map": "~0.6.1"
+ },
+ "dependencies": {
+ "commander": {
+ "version": "2.13.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-2.13.0.tgz",
+ "integrity": "sha512-MVuS359B+YzaWqjCL/c+22gfryv+mCBPHAv3zyVI2GN8EY6IRP8VwtasXn8jyyhvvq84R4ImN1OKRtcbIasjYA==",
+ "dev": true
+ }
+ }
+ },
+ "uglify-js": {
+ "version": "3.3.28",
+ "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.3.28.tgz",
+ "integrity": "sha512-68Rc/aA6cswiaQ5SrE979UJcXX+ADA1z33/ZsPd+fbAiVdjZ16OXdbtGO+rJUUBgK6qdf3SOPhQf3K/ybF5Miw==",
+ "dev": true,
+ "requires": {
+ "commander": "~2.15.0",
+ "source-map": "~0.6.1"
+ }
+ },
+ "universalify": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.1.tgz",
+ "integrity": "sha1-+nG63UQ3r0wUiEHjs7Fl+enlkLc=",
+ "dev": true
+ },
+ "wrappy": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+ "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
+ "dev": true
+ },
+ "yn": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/yn/-/yn-2.0.0.tgz",
+ "integrity": "sha1-5a2ryKz0CPY4X8dklWhMiOavaJo=",
+ "dev": true
+ }
+ }
+}
diff --git a/package.json b/package.json
index 2c60d4f..f24a6ad 100644
--- a/package.json
+++ b/package.json
@@ -1,21 +1,21 @@
{
"name": "asmcrypto.js",
- "version": "0.22.0",
+ "version": "2.0.0",
"description": "Asm.js implementation of WebCrypto API",
- "homepage": "https://github.com/vibornoff/asmcrypto.js",
- "main": "asmcrypto.js",
- "module": "asmcrypto.mjs",
+ "homepage": "https://github.com/asmcrypto/asmcrypto.js",
+ "main": "asmcrypto.all.js",
+ "module": "asmcrypto.all.es8.js",
"license": "MIT",
"author": {
- "name": "Artem S Vybornov",
- "email": "vybornov@gmail.com",
- "web": "https://github.com/vibornoff"
+ "name": "Ádám Lippai",
+ "email": "adam@rigo.sk",
+ "web": "https://github.com/alippai"
},
"contributors": [
{
- "name": "Ádám Lippai",
- "email": "adam@rigo.sk",
- "web": "https://github.com/alippai"
+ "name": "Artem S Vybornov",
+ "email": "vybornov@gmail.com",
+ "web": "https://github.com/vibornoff"
},
{
"name": "Ximin Luo",
@@ -25,27 +25,30 @@
],
"repository": {
"type": "git",
- "url": "https://github.com/vibornoff/asmcrypto.js.git"
+ "url": "https://github.com/asmcrypto/asmcrypto.js.git"
},
"devDependencies": {
- "grunt": "~1.0",
- "grunt-cli": "~1.2",
- "grunt-contrib-clean": "~1.1",
- "grunt-contrib-concat": "~1.0",
- "grunt-contrib-connect": "~1.0",
- "grunt-contrib-uglify-es": "git+https://github.com/gruntjs/grunt-contrib-uglify.git#harmony",
- "grunt-contrib-watch": "~1.0",
- "grunt-jsdoc": "~2.2",
- "grunt-rollup": "^9.0.0",
- "grunt-shell": "^2.1.0",
- "prettier": "^1.10.2",
- "qunit-puppeteer": "^1.0.1",
- "uglify-es": "^3.3.4"
+ "@types/chai": "^4.1.3",
+ "@types/mocha": "^5.2.0",
+ "@types/node": "^10.1.2",
+ "chai": "^4.1.2",
+ "esm": "3.0.36",
+ "fs-extra": "^6.0.1",
+ "mocha": "^5.2.0",
+ "prettier": "^1.13.4",
+ "rollup": "^0.59.1",
+ "ts-node": "^6.0.3",
+ "tslint": "^5.10.0",
+ "tslint-plugin-prettier": "^1.3.0",
+ "typescript": "^2.8.3",
+ "uglify-es": "^3.3.9",
+ "uglify-js": "^3.3.25"
},
"scripts": {
- "prepublish": "grunt && grunt esm && grunt all",
- "test": "grunt test",
- "prettier": "prettier --single-quote --trailing-comma all --write \"src/**/*.js\" --print-width 120"
+ "prepublish": "node -r esm build.js",
+ "test": "node -r esm build.js && mocha -r esm test/*.js",
+ "prettier": "prettier --single-quote --trailing-comma all --write \"src/**/*.js\" \"src/**/*.ts\" --print-width 120"
},
- "typings": "./asmcrypto.js.d.ts"
+ "typings": "./dist_es8/entry-export_all.d.ts",
+ "dependencies": {}
}
diff --git a/src/aes/aes.asm.d.ts b/src/aes/aes.asm.d.ts
new file mode 100644
index 0000000..efe0411
--- /dev/null
+++ b/src/aes/aes.asm.d.ts
@@ -0,0 +1,122 @@
+declare type AES_mode = 'ECB' | 'CBC' | 'CFB' | 'OFB' | 'CTR' | 'CCM';
+export class AES_asm {
+ constructor(foreign: any, heap: ArrayBuffer);
+
+ /**
+ * @param ks - key size, 4/6/8 (for 128/192/256-bit key correspondingly)
+ * @param k0 - key vector components
+ * @param k1 - key vector components
+ * @param k2 - key vector components
+ * @param k3 - key vector components
+ * @param k4 - key vector components
+ * @param k5 - key vector components
+ * @param k6 - key vector components
+ * @param k7 - key vector components
+ */
+ set_key(
+ ks: number,
+ k0: number,
+ k1: number,
+ k2: number,
+ k3: number,
+ k4: number,
+ k5: number,
+ k6: number,
+ k7: number,
+ ): void;
+
+ /**
+ * Populate the internal iv of the module
+ */
+ set_iv(i0: number, i1: number, i2: number, i3: number): void;
+
+ /**
+ * Set counter mask for CTR-family modes
+ */
+ set_mask(m0: number, m1: number, m2: number, m3: number): void;
+
+ /**
+ * Set nonce for CTR-family modes
+ */
+ set_nonce(n0: number, n1: number, n2: number, n3: number): void;
+
+ /**
+ * Set counter for CTR-family modes
+ */
+ set_counter(c0: number, c1: number, c2: number, c3: number): void;
+
+ /**
+ * Perform ciphering operation on the supplied data
+ *
+ * @param mode - block cipher mode (see {@link AES_asm} mode constants)
+ * @param pos - offset of the data being processed
+ * @param len - length of the data being processed
+ * @return Actual amount of data have been processed
+ */
+ cipher(mode: number, pos: number, len: number): number;
+
+ /**
+ * GCM initialization
+ */
+ gcm_init(): void;
+
+ /**
+ * Store the internal iv vector into the heap
+ *
+ * @returns The number of bytes have been written into the heap, always 16
+ */
+ get_iv(pos: number): 16;
+
+ /**
+ * Calculates MAC of the supplied data
+ *
+ * @param mode - block cipher mode (see {@link AES_asm} mode constants)
+ * @param pos - offset of the data being processed
+ * @param len - length of the data being processed
+ * @return Actual amount of data have been processed
+ */
+ mac(mode: number, pos: number, len: number): number;
+
+ /**
+ * Store the internal state vector into the heap.
+ *
+ * @param pos - offset where to put the data
+ * @return The number of bytes have been written into the heap, always 16.
+ */
+ get_state(pos: number): 16;
+
+ /**
+ * AES enciphering mode constants
+ */
+ static ENC: {
+ ECB: 0;
+ CBC: 2;
+ CFB: 4;
+ OFB: 6;
+ CTR: 7;
+ [key: string]: number;
+ };
+
+ /**
+ * AES deciphering mode constants
+ */
+ static DEC: {
+ ECB: 1;
+ CBC: 3;
+ CFB: 5;
+ OFB: 6;
+ CTR: 7;
+ [key: string]: number;
+ };
+
+ /**
+ * AES MAC mode constants
+ */
+ static MAC: {
+ CBC: 0;
+ GCM: 1;
+ [key: string]: number;
+ };
+
+ static HEAP_DATA: number;
+}
diff --git a/src/aes/aes.asm.js b/src/aes/aes.asm.js
index 846b3bf..5a5d71e 100644
--- a/src/aes/aes.asm.js
+++ b/src/aes/aes.asm.js
@@ -153,8 +153,8 @@ export var AES_asm = function () {
*
* @alias AES_asm
* @class
- * @param {Object} foreign - ignored
- * @param {ArrayBuffer} buffer - heap buffer to link with
+ * @param foreign - ignored
+ * @param buffer - heap buffer to link with
*/
var wrapper = function (foreign, buffer) {
// Init AES stuff for the first time
@@ -304,7 +304,7 @@ export var AES_asm = function () {
x0,
x1,
x2,
- x3,
+ x3
);
}
@@ -329,7 +329,7 @@ export var AES_asm = function () {
x0,
x3,
x2,
- x1,
+ x1
);
t = S1, S1 = S3, S3 = t;
@@ -355,7 +355,7 @@ export var AES_asm = function () {
I0 ^ x0,
I1 ^ x1,
I2 ^ x2,
- I3 ^ x3,
+ I3 ^ x3
);
I0 = S0,
@@ -385,7 +385,7 @@ export var AES_asm = function () {
x0,
x3,
x2,
- x1,
+ x1
);
t = S1, S1 = S3, S3 = t;
@@ -420,7 +420,7 @@ export var AES_asm = function () {
I0,
I1,
I2,
- I3,
+ I3
);
I0 = S0 = S0 ^ x0,
@@ -449,7 +449,7 @@ export var AES_asm = function () {
I0,
I1,
I2,
- I3,
+ I3
);
S0 = S0 ^ x0,
@@ -482,7 +482,7 @@ export var AES_asm = function () {
I0,
I1,
I2,
- I3,
+ I3
);
I0 = S0,
@@ -515,7 +515,7 @@ export var AES_asm = function () {
N0,
N1,
N2,
- N3,
+ N3
);
N3 = (~M3 & N3) | M3 & (N3 + 1);
@@ -801,7 +801,7 @@ export var AES_asm = function () {
DATA[pos | 0] << 24 | DATA[pos | 1] << 16 | DATA[pos | 2] << 8 | DATA[pos | 3],
DATA[pos | 4] << 24 | DATA[pos | 5] << 16 | DATA[pos | 6] << 8 | DATA[pos | 7],
DATA[pos | 8] << 24 | DATA[pos | 9] << 16 | DATA[pos | 10] << 8 | DATA[pos | 11],
- DATA[pos | 12] << 24 | DATA[pos | 13] << 16 | DATA[pos | 14] << 8 | DATA[pos | 15],
+ DATA[pos | 12] << 24 | DATA[pos | 13] << 16 | DATA[pos | 14] << 8 | DATA[pos | 15]
);
DATA[pos | 0] = S0 >>> 24,
@@ -852,7 +852,7 @@ export var AES_asm = function () {
DATA[pos | 0] << 24 | DATA[pos | 1] << 16 | DATA[pos | 2] << 8 | DATA[pos | 3],
DATA[pos | 4] << 24 | DATA[pos | 5] << 16 | DATA[pos | 6] << 8 | DATA[pos | 7],
DATA[pos | 8] << 24 | DATA[pos | 9] << 16 | DATA[pos | 10] << 8 | DATA[pos | 11],
- DATA[pos | 12] << 24 | DATA[pos | 13] << 16 | DATA[pos | 14] << 8 | DATA[pos | 15],
+ DATA[pos | 12] << 24 | DATA[pos | 13] << 16 | DATA[pos | 14] << 8 | DATA[pos | 15]
);
ret = (ret + 16) | 0,
diff --git a/src/aes/aes.js b/src/aes/aes.js
deleted file mode 100644
index a52d90a..0000000
--- a/src/aes/aes.js
+++ /dev/null
@@ -1,357 +0,0 @@
-import { AES_asm } from './aes.asm';
-import { _heap_init, _heap_write, is_bytes, is_number } from '../utils';
-import { IllegalArgumentError, SecurityError } from '../errors';
-
-export class AES {
- constructor(key, iv, padding, heap, asm) {
- this.nonce = null;
- this.counter = 0;
- this.counterSize = 0;
-
- this.heap = _heap_init(Uint8Array, heap).subarray(AES_asm.HEAP_DATA);
- this.asm = asm || AES_asm(null, this.heap.buffer);
- this.mode = null;
- this.key = null;
-
- this.AES_reset(key, iv, padding);
- }
-
- /**
- * @param {Uint8Array} key
- */
- AES_set_key(key) {
- if (key !== undefined) {
- if (!is_bytes(key)) {
- throw new TypeError('unexpected key type');
- }
-
- var keylen = key.length;
- if (keylen !== 16 && keylen !== 24 && keylen !== 32) throw new IllegalArgumentError('illegal key size');
-
- var keyview = new DataView(key.buffer, key.byteOffset, key.byteLength);
- this.asm.set_key(
- keylen >> 2,
- keyview.getUint32(0),
- keyview.getUint32(4),
- keyview.getUint32(8),
- keyview.getUint32(12),
- keylen > 16 ? keyview.getUint32(16) : 0,
- keylen > 16 ? keyview.getUint32(20) : 0,
- keylen > 24 ? keyview.getUint32(24) : 0,
- keylen > 24 ? keyview.getUint32(28) : 0,
- );
-
- this.key = key;
- } else if (!this.key) {
- throw new Error('key is required');
- }
- }
-
- /**
- * This should be mixin instead of inheritance
- *
- * @param {Uint8Array} nonce
- * @param {number} [counter]
- * @param {number} [size]
- */
- AES_CTR_set_options(nonce, counter, size) {
- if (size !== undefined) {
- if (size < 8 || size > 48) throw new IllegalArgumentError('illegal counter size');
-
- this.counterSize = size;
-
- var mask = Math.pow(2, size) - 1;
- this.asm.set_mask(0, 0, (mask / 0x100000000) | 0, mask | 0);
- } else {
- this.counterSize = size = 48;
- this.asm.set_mask(0, 0, 0xffff, 0xffffffff);
- }
-
- if (nonce !== undefined) {
- if (!is_bytes(nonce)) {
- throw new TypeError('unexpected nonce type');
- }
-
- var len = nonce.length;
- if (!len || len > 16) throw new IllegalArgumentError('illegal nonce size');
-
- this.nonce = nonce;
-
- var view = new DataView(new ArrayBuffer(16));
- new Uint8Array(view.buffer).set(nonce);
-
- this.asm.set_nonce(view.getUint32(0), view.getUint32(4), view.getUint32(8), view.getUint32(12));
- } else {
- throw new Error('nonce is required');
- }
-
- if (counter !== undefined) {
- if (!is_number(counter)) throw new TypeError('unexpected counter type');
-
- if (counter < 0 || counter >= Math.pow(2, size)) throw new IllegalArgumentError('illegal counter value');
-
- this.counter = counter;
-
- this.asm.set_counter(0, 0, (counter / 0x100000000) | 0, counter | 0);
- } else {
- this.counter = 0;
- }
- }
-
- /**
- * @param {Uint8Array} iv
- */
- AES_set_iv(iv) {
- if (iv !== undefined) {
- if (!is_bytes(iv)) {
- throw new TypeError('unexpected iv type');
- }
-
- if (iv.length !== 16) throw new IllegalArgumentError('illegal iv size');
-
- var ivview = new DataView(iv.buffer, iv.byteOffset, iv.byteLength);
-
- this.iv = iv;
- this.asm.set_iv(ivview.getUint32(0), ivview.getUint32(4), ivview.getUint32(8), ivview.getUint32(12));
- } else {
- this.iv = null;
- this.asm.set_iv(0, 0, 0, 0);
- }
- }
-
- /**
- * @param {boolean} padding
- */
- AES_set_padding(padding) {
- if (padding !== undefined) {
- this.padding = !!padding;
- } else {
- this.padding = true;
- }
- }
-
- /**
- * @param {Uint8Array} key
- * @param {Uint8Array} [iv]
- * @param {boolean} [padding]
- */
- AES_reset(key, iv, padding) {
- this.result = null;
- this.pos = 0;
- this.len = 0;
-
- this.AES_set_key(key);
- this.AES_set_iv(iv);
- this.AES_set_padding(padding);
-
- return this;
- }
-
- /**
- * @param {Uint8Array} data
- */
- AES_Encrypt_process(data) {
- if (!is_bytes(data)) throw new TypeError("data isn't of expected type");
-
- var asm = this.asm,
- heap = this.heap,
- amode = AES_asm.ENC[this.mode],
- hpos = AES_asm.HEAP_DATA,
- pos = this.pos,
- len = this.len,
- dpos = 0,
- dlen = data.length || 0,
- rpos = 0,
- rlen = (len + dlen) & -16,
- wlen = 0;
-
- var result = new Uint8Array(rlen);
-
- while (dlen > 0) {
- wlen = _heap_write(heap, pos + len, data, dpos, dlen);
- len += wlen;
- dpos += wlen;
- dlen -= wlen;
-
- wlen = asm.cipher(amode, hpos + pos, len);
-
- if (wlen) result.set(heap.subarray(pos, pos + wlen), rpos);
- rpos += wlen;
-
- if (wlen < len) {
- pos += wlen;
- len -= wlen;
- } else {
- pos = 0;
- len = 0;
- }
- }
-
- this.result = result;
- this.pos = pos;
- this.len = len;
-
- return this;
- }
-
- /**
- * @param {Uint8Array} data
- */
- AES_Encrypt_finish(data) {
- var presult = null,
- prlen = 0;
-
- if (data !== undefined) {
- presult = this.AES_Encrypt_process(data).result;
- prlen = presult.length;
- }
-
- var asm = this.asm,
- heap = this.heap,
- amode = AES_asm.ENC[this.mode],
- hpos = AES_asm.HEAP_DATA,
- pos = this.pos,
- len = this.len,
- plen = 16 - len % 16,
- rlen = len;
-
- if (this.hasOwnProperty('padding')) {
- if (this.padding) {
- for (var p = 0; p < plen; ++p) heap[pos + len + p] = plen;
- len += plen;
- rlen = len;
- } else if (len % 16) {
- throw new IllegalArgumentError('data length must be a multiple of the block size');
- }
- } else {
- len += plen;
- }
-
- var result = new Uint8Array(prlen + rlen);
-
- if (prlen) result.set(presult);
-
- if (len) asm.cipher(amode, hpos + pos, len);
-
- if (rlen) result.set(heap.subarray(pos, pos + rlen), prlen);
-
- this.result = result;
- this.pos = 0;
- this.len = 0;
-
- return this;
- }
-
- /**
- * @param {Uint8Array} data
- */
- AES_Decrypt_process(data) {
- if (!is_bytes(data)) throw new TypeError("data isn't of expected type");
-
- var asm = this.asm,
- heap = this.heap,
- amode = AES_asm.DEC[this.mode],
- hpos = AES_asm.HEAP_DATA,
- pos = this.pos,
- len = this.len,
- dpos = 0,
- dlen = data.length || 0,
- rpos = 0,
- rlen = (len + dlen) & -16,
- plen = 0,
- wlen = 0;
-
- if (this.padding) {
- plen = len + dlen - rlen || 16;
- rlen -= plen;
- }
-
- var result = new Uint8Array(rlen);
-
- while (dlen > 0) {
- wlen = _heap_write(heap, pos + len, data, dpos, dlen);
- len += wlen;
- dpos += wlen;
- dlen -= wlen;
-
- wlen = asm.cipher(amode, hpos + pos, len - (!dlen ? plen : 0));
-
- if (wlen) result.set(heap.subarray(pos, pos + wlen), rpos);
- rpos += wlen;
-
- if (wlen < len) {
- pos += wlen;
- len -= wlen;
- } else {
- pos = 0;
- len = 0;
- }
- }
-
- this.result = result;
- this.pos = pos;
- this.len = len;
-
- return this;
- }
-
- /**
- * @param {Uint8Array} data
- */
- AES_Decrypt_finish(data) {
- var presult = null,
- prlen = 0;
-
- if (data !== undefined) {
- presult = this.AES_Decrypt_process(data).result;
- prlen = presult.length;
- }
-
- var asm = this.asm,
- heap = this.heap,
- amode = AES_asm.DEC[this.mode],
- hpos = AES_asm.HEAP_DATA,
- pos = this.pos,
- len = this.len,
- rlen = len;
-
- if (len > 0) {
- if (len % 16) {
- if (this.hasOwnProperty('padding')) {
- throw new IllegalArgumentError('data length must be a multiple of the block size');
- } else {
- len += 16 - len % 16;
- }
- }
-
- asm.cipher(amode, hpos + pos, len);
-
- if (this.hasOwnProperty('padding') && this.padding) {
- var pad = heap[pos + rlen - 1];
- if (pad < 1 || pad > 16 || pad > rlen) throw new SecurityError('bad padding');
-
- var pcheck = 0;
- for (var i = pad; i > 1; i--) pcheck |= pad ^ heap[pos + rlen - i];
- if (pcheck) throw new SecurityError('bad padding');
-
- rlen -= pad;
- }
- }
-
- var result = new Uint8Array(prlen + rlen);
-
- if (prlen > 0) {
- result.set(presult);
- }
-
- if (rlen > 0) {
- result.set(heap.subarray(pos, pos + rlen), prlen);
- }
-
- this.result = result;
- this.pos = 0;
- this.len = 0;
-
- return this;
- }
-}
diff --git a/src/aes/aes.ts b/src/aes/aes.ts
new file mode 100644
index 0000000..811caff
--- /dev/null
+++ b/src/aes/aes.ts
@@ -0,0 +1,238 @@
+import { AES_asm, AES_mode } from './aes.asm';
+import { _heap_init, _heap_write, is_bytes } from '../other/utils';
+import { IllegalArgumentError, SecurityError } from '../other/errors';
+
+export abstract class AES {
+ protected readonly heap: Uint8Array;
+ protected readonly asm: AES_asm;
+ private readonly mode: string;
+ protected padding: boolean; // TODO: This should be `private readonly`, hacking for AES-CFB?!
+ public result!: Uint8Array | null;
+ protected pos: number = 0;
+ protected len: number = 0;
+
+ protected constructor(key: Uint8Array, iv: Uint8Array | undefined, padding = true, mode: AES_mode) {
+ this.mode = mode;
+
+ // The AES "worker"
+ this.heap = _heap_init().subarray(AES_asm.HEAP_DATA);
+ this.asm = new AES_asm(null, this.heap.buffer);
+
+ // The AES object state
+ this.result = null;
+ this.pos = 0;
+ this.len = 0;
+
+ // Key
+ const keylen = key.length;
+ if (keylen !== 16 && keylen !== 24 && keylen !== 32) throw new IllegalArgumentError('illegal key size');
+
+ const keyview = new DataView(key.buffer, key.byteOffset, key.byteLength);
+ this.asm.set_key(
+ keylen >> 2,
+ keyview.getUint32(0),
+ keyview.getUint32(4),
+ keyview.getUint32(8),
+ keyview.getUint32(12),
+ keylen > 16 ? keyview.getUint32(16) : 0,
+ keylen > 16 ? keyview.getUint32(20) : 0,
+ keylen > 24 ? keyview.getUint32(24) : 0,
+ keylen > 24 ? keyview.getUint32(28) : 0,
+ );
+
+ // IV
+ if (iv !== undefined) {
+ if (iv.length !== 16) throw new IllegalArgumentError('illegal iv size');
+
+ let ivview = new DataView(iv.buffer, iv.byteOffset, iv.byteLength);
+
+ this.asm.set_iv(ivview.getUint32(0), ivview.getUint32(4), ivview.getUint32(8), ivview.getUint32(12));
+ } else {
+ this.asm.set_iv(0, 0, 0, 0);
+ }
+
+ this.padding = padding;
+ }
+
+ AES_Encrypt_process(data: Uint8Array): this {
+ if (!is_bytes(data)) throw new TypeError("data isn't of expected type");
+
+ let asm = this.asm;
+ let heap = this.heap;
+ let amode = AES_asm.ENC[this.mode];
+ let hpos = AES_asm.HEAP_DATA;
+ let pos = this.pos;
+ let len = this.len;
+ let dpos = 0;
+ let dlen = data.length || 0;
+ let rpos = 0;
+ let rlen = (len + dlen) & -16;
+ let wlen = 0;
+
+ let result = new Uint8Array(rlen);
+
+ while (dlen > 0) {
+ wlen = _heap_write(heap, pos + len, data, dpos, dlen);
+ len += wlen;
+ dpos += wlen;
+ dlen -= wlen;
+
+ wlen = asm.cipher(amode, hpos + pos, len);
+
+ if (wlen) result.set(heap.subarray(pos, pos + wlen), rpos);
+ rpos += wlen;
+
+ if (wlen < len) {
+ pos += wlen;
+ len -= wlen;
+ } else {
+ pos = 0;
+ len = 0;
+ }
+ }
+
+ this.result = result;
+ this.pos = pos;
+ this.len = len;
+
+ return this;
+ }
+
+ AES_Encrypt_finish(): this {
+ let asm = this.asm;
+ let heap = this.heap;
+ let amode = AES_asm.ENC[this.mode];
+ let hpos = AES_asm.HEAP_DATA;
+ let pos = this.pos;
+ let len = this.len;
+ let plen = 16 - (len % 16);
+ let rlen = len;
+
+ if (this.hasOwnProperty('padding')) {
+ if (this.padding) {
+ for (let p = 0; p < plen; ++p) {
+ heap[pos + len + p] = plen;
+ }
+ len += plen;
+ rlen = len;
+ } else if (len % 16) {
+ throw new IllegalArgumentError('data length must be a multiple of the block size');
+ }
+ } else {
+ len += plen;
+ }
+
+ if (!this.result) throw new Error('There is no result');
+
+ const result = new Uint8Array(this.result.length + rlen);
+ result.set(this.result, 0);
+
+ if (len) asm.cipher(amode, hpos + pos, len);
+
+ if (rlen) result.set(heap.subarray(pos, pos + rlen), this.result.length);
+
+ this.result = result;
+ this.pos = 0;
+ this.len = 0;
+
+ return this;
+ }
+
+ AES_Decrypt_process(data: Uint8Array): this {
+ if (!is_bytes(data)) throw new TypeError("data isn't of expected type");
+
+ let asm = this.asm;
+ let heap = this.heap;
+ let amode = AES_asm.DEC[this.mode];
+ let hpos = AES_asm.HEAP_DATA;
+ let pos = this.pos;
+ let len = this.len;
+ let dpos = 0;
+ let dlen = data.length || 0;
+ let rpos = 0;
+ let rlen = (len + dlen) & -16;
+ let plen = 0;
+ let wlen = 0;
+
+ if (this.padding) {
+ plen = len + dlen - rlen || 16;
+ rlen -= plen;
+ }
+
+ const result = new Uint8Array(rlen);
+
+ while (dlen > 0) {
+ wlen = _heap_write(heap, pos + len, data, dpos, dlen);
+ len += wlen;
+ dpos += wlen;
+ dlen -= wlen;
+
+ wlen = asm.cipher(amode, hpos + pos, len - (!dlen ? plen : 0));
+
+ if (wlen) result.set(heap.subarray(pos, pos + wlen), rpos);
+ rpos += wlen;
+
+ if (wlen < len) {
+ pos += wlen;
+ len -= wlen;
+ } else {
+ pos = 0;
+ len = 0;
+ }
+ }
+
+ this.result = result;
+ this.pos = pos;
+ this.len = len;
+
+ return this;
+ }
+
+ AES_Decrypt_finish(): this {
+ let asm = this.asm;
+ let heap = this.heap;
+ let amode = AES_asm.DEC[this.mode];
+ let hpos = AES_asm.HEAP_DATA;
+ let pos = this.pos;
+ let len = this.len;
+ let rlen = len;
+
+ if (len > 0) {
+ if (len % 16) {
+ if (this.hasOwnProperty('padding')) {
+ throw new IllegalArgumentError('data length must be a multiple of the block size');
+ } else {
+ len += 16 - (len % 16);
+ }
+ }
+
+ asm.cipher(amode, hpos + pos, len);
+
+ if (this.hasOwnProperty('padding') && this.padding) {
+ let pad = heap[pos + rlen - 1];
+ if (pad < 1 || pad > 16 || pad > rlen) throw new SecurityError('bad padding');
+
+ let pcheck = 0;
+ for (let i = pad; i > 1; i--) pcheck |= pad ^ heap[pos + rlen - i];
+ if (pcheck) throw new SecurityError('bad padding');
+
+ rlen -= pad;
+ }
+ }
+
+ if (!this.result) throw new Error('There is no result');
+
+ const result = new Uint8Array(rlen + this.result.length);
+ result.set(this.result, 0);
+
+ if (rlen > 0) {
+ result.set(heap.subarray(pos, pos + rlen), this.result.length);
+ }
+
+ this.result = result;
+ this.pos = 0;
+ this.len = 0;
+
+ return this;
+ }
+}
diff --git a/src/aes/cbc.ts b/src/aes/cbc.ts
new file mode 100644
index 0000000..95bd3b7
--- /dev/null
+++ b/src/aes/cbc.ts
@@ -0,0 +1,25 @@
+import { AES } from './aes';
+
+export class AES_CBC extends AES {
+ static encrypt(data: Uint8Array, key: Uint8Array, padding: boolean = true, iv?: Uint8Array): Uint8Array {
+ return new AES_CBC(key, iv, padding).encrypt(data).result as Uint8Array;
+ }
+
+ static decrypt(data: Uint8Array, key: Uint8Array, padding: boolean = true, iv?: Uint8Array): Uint8Array {
+ return new AES_CBC(key, iv, padding).decrypt(data).result as Uint8Array;
+ }
+
+ constructor(key: Uint8Array, iv?: Uint8Array, padding: boolean = true) {
+ super(key, iv, padding, 'CBC');
+ }
+
+ encrypt(data: Uint8Array): this {
+ this.AES_Encrypt_process(data);
+ return this.AES_Encrypt_finish();
+ }
+
+ decrypt(data: Uint8Array): this {
+ this.AES_Decrypt_process(data);
+ return this.AES_Decrypt_finish();
+ }
+}
diff --git a/src/aes/cbc/cbc.js b/src/aes/cbc/cbc.js
deleted file mode 100644
index 56e4695..0000000
--- a/src/aes/cbc/cbc.js
+++ /dev/null
@@ -1,102 +0,0 @@
-/**
- * Cipher Block Chaining Mode (CBC)
- */
-import { AES } from '../aes';
-
-export class AES_CBC extends AES {
- /**
- * @param {Uint8Array} key
- * @param {Uint8Array} [iv=null]
- * @param {boolean} [padding=true]
- * @param {Uint8Array} [heap]
- * @param {Uint8Array} [asm]
- */
- constructor(key, iv = null, padding = true, heap, asm) {
- super(key, iv, padding, heap, asm);
-
- this.mode = 'CBC';
- this.BLOCK_SIZE = 16;
- }
-
- encrypt(data) {
- return this.AES_Encrypt_finish(data);
- }
-
- decrypt(data) {
- return this.AES_Decrypt_finish(data);
- }
-}
-
-export class AES_CBC_Encrypt extends AES_CBC {
- /**
- * @param {Uint8Array} key
- * @param {Uint8Array} [iv=null]
- * @param {boolean} [padding=true]
- * @param {Uint8Array} [heap]
- * @param {Uint8Array} [asm]
- */
- constructor(key, iv, padding, heap, asm) {
- super(key, iv, padding, heap, asm);
- }
-
- /**
- * @param {Uint8Array} key
- * @returns {AES_CBC_Encrypt}
- */
- reset(key) {
- return this.AES_reset(key, null, true);
- }
-
- /**
- * @param {Uint8Array} data
- * @returns {AES_CBC_Encrypt}
- */
- process(data) {
- return this.AES_Encrypt_process(data);
- }
-
- /**
- * @param {Uint8Array} data
- * @returns {AES_CBC_Encrypt}
- */
- finish(data) {
- return this.AES_Encrypt_finish(data);
- }
-}
-
-export class AES_CBC_Decrypt extends AES_CBC {
- /**
- * @param {Uint8Array} key
- * @param {Uint8Array} [iv=null]
- * @param {boolean} [padding=true]
- * @param {Uint8Array} [heap]
- * @param {Uint8Array} [asm]
- */
- constructor(key, iv, padding, heap, asm) {
- super(key, iv, padding, heap, asm);
- }
-
- /**
- * @param {Uint8Array} key
- * @returns {AES_CBC_Decrypt}
- */
- reset(key) {
- return this.AES_reset(key, null, true);
- }
-
- /**
- * @param {Uint8Array} data
- * @returns {AES_CBC_Decrypt}
- */
- process(data) {
- return this.AES_Decrypt_process(data);
- }
-
- /**
- * @param {Uint8Array} data
- * @returns {AES_CBC_Decrypt}
- */
- finish(data) {
- return this.AES_Decrypt_finish(data);
- }
-}
diff --git a/src/aes/cbc/exports.js b/src/aes/cbc/exports.js
deleted file mode 100644
index 5b2b318..0000000
--- a/src/aes/cbc/exports.js
+++ /dev/null
@@ -1,33 +0,0 @@
-import { _AES_asm_instance, _AES_heap_instance } from '../exports';
-import { AES_CBC, AES_CBC_Decrypt, AES_CBC_Encrypt } from './cbc';
-
-/**
- * @param {Uint8Array} data
- * @param {Uint8Array} key
- * @param {boolean} [padding]
- * @param {Uint8Array} [iv]
- * @returns {Uint8Array}
- */
-function AES_CBC_encrypt_bytes(data, key, padding, iv) {
- if (data === undefined) throw new SyntaxError('data required');
- if (key === undefined) throw new SyntaxError('key required');
- return new AES_CBC(key, iv, padding, _AES_heap_instance, _AES_asm_instance).encrypt(data).result;
-}
-
-/**
- * @param {Uint8Array} data
- * @param {Uint8Array} key
- * @param {boolean} [padding]
- * @param {Uint8Array} [iv]
- * @returns {Uint8Array}
- */
-function AES_CBC_decrypt_bytes(data, key, padding, iv) {
- if (data === undefined) throw new SyntaxError('data required');
- if (key === undefined) throw new SyntaxError('key required');
- return new AES_CBC(key, iv, padding, _AES_heap_instance, _AES_asm_instance).decrypt(data).result;
-}
-
-AES_CBC.encrypt = AES_CBC_encrypt_bytes;
-AES_CBC.decrypt = AES_CBC_decrypt_bytes;
-
-export { AES_CBC, AES_CBC_Encrypt, AES_CBC_Decrypt };
diff --git a/src/aes/ccm.ts b/src/aes/ccm.ts
new file mode 100644
index 0000000..1d67ace
--- /dev/null
+++ b/src/aes/ccm.ts
@@ -0,0 +1,353 @@
+/**
+ * Counter with CBC-MAC (CCM)
+ *
+ * Due to JS limitations (52 bits of Number precision) maximum encrypted message length
+ * is limited to ~4 PiB ( 2^52 - 16 ) per `nonce`-`key` pair.
+ * That also limits `lengthSize` parameter maximum value to 7 (not 8 as described in RFC3610).
+ *
+ * Additional authenticated data `adata` maximum length is chosen to be no more than 65279 bytes ( 2^16 - 2^8 ),
+ * which is considered enough for the most of use-cases.
+ *
+ * And one more important thing: in case of progressive ciphering of a data stream (in other
+ * words when data can't be held in-memory at a whole and are ciphered chunk-by-chunk)
+ * you have to know the `dataLength` in advance and pass that value to the cipher options.
+ */
+
+import { AES_asm } from './aes.asm';
+import { AES } from './aes';
+import { _heap_write } from '../other/utils';
+import { IllegalArgumentError, IllegalStateError, SecurityError } from '../other/errors';
+
+const _AES_CCM_adata_maxLength = 65279; // 2^16 - 2^8
+const _AES_CCM_data_maxLength = 4503599627370480; // 2^52 - 2^4
+
+export class AES_CCM extends AES {
+ private readonly tagSize: number;
+ private readonly lengthSize: number;
+ private nonce: Uint8Array;
+ private readonly adata: Uint8Array | undefined;
+ private counter: number = 1;
+ private dataLength: number = -1;
+
+ static encrypt(
+ clear: Uint8Array,
+ key: Uint8Array,
+ nonce: Uint8Array,
+ adata: Uint8Array | undefined,
+ tagsize: number = 16,
+ ): Uint8Array {
+ return new AES_CCM(key, nonce, adata, tagsize, clear.length).encrypt(clear).result as Uint8Array;
+ }
+ static decrypt(
+ cipher: Uint8Array,
+ key: Uint8Array,
+ nonce: Uint8Array,
+ adata: Uint8Array | undefined,
+ tagsize: number = 16,
+ ): Uint8Array {
+ return new AES_CCM(key, nonce, adata, tagsize, cipher.length - tagsize).decrypt(cipher).result as Uint8Array;
+ }
+
+ constructor(
+ key: Uint8Array,
+ nonce: Uint8Array,
+ adata: Uint8Array | undefined,
+ tagSize: number = 16,
+ dataLength: number,
+ ) {
+ super(key, undefined, undefined, 'CCM');
+
+ // Tag size
+ if (tagSize < 4 || tagSize > 16 || tagSize & 1) throw new IllegalArgumentError('illegal tagSize value');
+ this.tagSize = tagSize;
+
+ // Nonce
+ this.nonce = nonce;
+
+ if (nonce.length < 8 || nonce.length > 13) throw new IllegalArgumentError('illegal nonce length');
+ this.lengthSize = 15 - nonce.length;
+ nonce = new Uint8Array(nonce.length + 1);
+ nonce[0] = this.lengthSize - 1;
+ nonce.set(this.nonce, 1);
+
+ if (dataLength < 0 || dataLength > _AES_CCM_data_maxLength || dataLength > Math.pow(2, 8 * this.lengthSize) - 16)
+ throw new IllegalArgumentError('illegal dataLength value');
+
+ if (adata !== undefined) {
+ if (adata.length > _AES_CCM_adata_maxLength) throw new IllegalArgumentError('illegal adata length');
+
+ this.adata = adata.length ? adata : undefined;
+ }
+
+ this.dataLength = dataLength;
+ this.counter = 1;
+
+ this.AES_CCM_calculate_iv();
+ this.AES_CTR_set_options(nonce, this.counter, 8 * this.lengthSize);
+ }
+
+ encrypt(data: Uint8Array): this {
+ this.dataLength = data.length || 0;
+
+ const result1 = this.AES_CCM_Encrypt_process(data).result as Uint8Array;
+ const result2 = this.AES_CCM_Encrypt_finish().result as Uint8Array;
+
+ const result = new Uint8Array(result1.length + result2.length);
+ if (result1.length) result.set(result1);
+ if (result2.length) result.set(result2, result1.length);
+ this.result = result;
+
+ return this;
+ }
+
+ decrypt(data: Uint8Array): this {
+ this.dataLength = data.length || 0;
+
+ const result1 = this.AES_CCM_Decrypt_process(data).result as Uint8Array;
+ const result2 = this.AES_CCM_Decrypt_finish().result as Uint8Array;
+
+ const result = new Uint8Array(result1.length + result2.length);
+ if (result1.length) result.set(result1);
+ if (result2.length) result.set(result2, result1.length);
+ this.result = result;
+
+ return this;
+ }
+
+ AES_CCM_calculate_iv(): void {
+ const nonce = this.nonce;
+ const adata = this.adata;
+ const tagSize = this.tagSize;
+ const lengthSize = this.lengthSize;
+ const dataLength = this.dataLength;
+
+ const data = new Uint8Array(16 + (adata ? 2 + adata.length : 0));
+
+ // B0: flags(adata?, M', L'), nonce, len(data)
+ data[0] = (adata ? 64 : 0) | ((tagSize - 2) << 2) | (lengthSize - 1);
+ data.set(nonce, 1);
+ if (lengthSize > 6) data[9] = ((dataLength / 0x100000000) >>> 16) & 15;
+ if (lengthSize > 5) data[10] = ((dataLength / 0x100000000) >>> 8) & 255;
+ if (lengthSize > 4) data[11] = (dataLength / 0x100000000) & 255;
+ if (lengthSize > 3) data[12] = dataLength >>> 24;
+ if (lengthSize > 2) data[13] = (dataLength >>> 16) & 255;
+ data[14] = (dataLength >>> 8) & 255;
+ data[15] = dataLength & 255;
+
+ // B*: len(adata), adata
+ if (adata) {
+ data[16] = (adata.length >>> 8) & 255;
+ data[17] = adata.length & 255;
+ data.set(adata, 18);
+ }
+
+ this._cbc_mac_process(data);
+ this.asm.get_state(AES_asm.HEAP_DATA);
+
+ const iv = new Uint8Array(this.heap.subarray(0, 16));
+ const ivview = new DataView(iv.buffer, iv.byteOffset, iv.byteLength);
+ this.asm.set_iv(ivview.getUint32(0), ivview.getUint32(4), ivview.getUint32(8), ivview.getUint32(12));
+ }
+
+ _cbc_mac_process(data: Uint8Array): void {
+ const heap = this.heap;
+ const asm = this.asm;
+ let dpos = 0;
+ let dlen = data.length || 0;
+ let wlen = 0;
+
+ while (dlen > 0) {
+ wlen = _heap_write(heap, 0, data, dpos, dlen);
+ while (wlen & 15) heap[wlen++] = 0;
+ dpos += wlen;
+ dlen -= wlen;
+
+ asm.mac(AES_asm.MAC.CBC, AES_asm.HEAP_DATA, wlen);
+ }
+ }
+
+ AES_CCM_Encrypt_process(data: Uint8Array): this {
+ const asm = this.asm;
+ const heap = this.heap;
+
+ let dpos = 0;
+ let dlen = data.length || 0;
+ let counter = this.counter;
+ let pos = this.pos;
+ let len = this.len;
+
+ const rlen = (len + dlen) & -16;
+ let rpos = 0;
+ let wlen = 0;
+
+ if (((counter - 1) << 4) + len + dlen > _AES_CCM_data_maxLength)
+ // ??? should check against lengthSize
+ throw new RangeError('counter overflow');
+
+ const result = new Uint8Array(rlen);
+
+ while (dlen > 0) {
+ wlen = _heap_write(heap, pos + len, data, dpos, dlen);
+ len += wlen;
+ dpos += wlen;
+ dlen -= wlen;
+
+ wlen = asm.mac(AES_asm.MAC.CBC, AES_asm.HEAP_DATA + pos, len);
+ wlen = asm.cipher(AES_asm.ENC.CTR, AES_asm.HEAP_DATA + pos, wlen);
+
+ if (wlen) result.set(heap.subarray(pos, pos + wlen), rpos);
+ counter += wlen >>> 4;
+ rpos += wlen;
+
+ if (wlen < len) {
+ pos += wlen;
+ len -= wlen;
+ } else {
+ pos = 0;
+ len = 0;
+ }
+ }
+
+ this.result = result;
+ this.counter = counter;
+ this.pos = pos;
+ this.len = len;
+
+ return this;
+ }
+
+ AES_CCM_Encrypt_finish(): this {
+ const asm = this.asm;
+ const heap = this.heap;
+ const tagSize = this.tagSize;
+ const pos = this.pos;
+ const len = this.len;
+
+ const result = new Uint8Array(len + tagSize);
+
+ let i = len;
+ for (; i & 15; i++) heap[pos + i] = 0;
+
+ asm.mac(AES_asm.MAC.CBC, AES_asm.HEAP_DATA + pos, i);
+ asm.cipher(AES_asm.ENC.CTR, AES_asm.HEAP_DATA + pos, i);
+ if (len) result.set(heap.subarray(pos, pos + len));
+
+ asm.set_counter(0, 0, 0, 0);
+ asm.get_iv(AES_asm.HEAP_DATA);
+ asm.cipher(AES_asm.ENC.CTR, AES_asm.HEAP_DATA, 16);
+ result.set(heap.subarray(0, tagSize), len);
+
+ this.result = result;
+ this.counter = 1;
+ this.pos = 0;
+ this.len = 0;
+
+ return this;
+ }
+
+ AES_CCM_Decrypt_process(data: Uint8Array): this {
+ let dpos = 0;
+ let dlen = data.length || 0;
+ const asm = this.asm;
+ const heap = this.heap;
+ let counter = this.counter;
+ const tagSize = this.tagSize;
+ let pos = this.pos;
+ let len = this.len;
+ let rpos = 0;
+ const rlen = len + dlen > tagSize ? (len + dlen - tagSize) & -16 : 0;
+ const tlen = len + dlen - rlen;
+ let wlen = 0;
+
+ if (((counter - 1) << 4) + len + dlen > _AES_CCM_data_maxLength) throw new RangeError('counter overflow');
+
+ const result = new Uint8Array(rlen);
+
+ while (dlen > tlen) {
+ wlen = _heap_write(heap, pos + len, data, dpos, dlen - tlen);
+ len += wlen;
+ dpos += wlen;
+ dlen -= wlen;
+
+ wlen = asm.cipher(AES_asm.DEC.CTR, AES_asm.HEAP_DATA + pos, wlen);
+ wlen = asm.mac(AES_asm.MAC.CBC, AES_asm.HEAP_DATA + pos, wlen);
+
+ if (wlen) result.set(heap.subarray(pos, pos + wlen), rpos);
+ counter += wlen >>> 4;
+ rpos += wlen;
+
+ pos = 0;
+ len = 0;
+ }
+
+ if (dlen > 0) {
+ len += _heap_write(heap, 0, data, dpos, dlen);
+ }
+
+ this.result = result;
+ this.counter = counter;
+ this.pos = pos;
+ this.len = len;
+
+ return this;
+ }
+
+ AES_CCM_Decrypt_finish(): this {
+ const asm = this.asm;
+ const heap = this.heap;
+ const tagSize = this.tagSize;
+ const pos = this.pos;
+ const len = this.len;
+ const rlen = len - tagSize;
+
+ if (len < tagSize) throw new IllegalStateError('authentication tag not found');
+
+ const result = new Uint8Array(rlen);
+ const atag = new Uint8Array(heap.subarray(pos + rlen, pos + len));
+
+ asm.cipher(AES_asm.DEC.CTR, AES_asm.HEAP_DATA + pos, (rlen + 15) & -16);
+ result.set(heap.subarray(pos, pos + rlen));
+
+ let i = rlen;
+ for (; i & 15; i++) heap[pos + i] = 0;
+ asm.mac(AES_asm.MAC.CBC, AES_asm.HEAP_DATA + pos, i);
+
+ asm.set_counter(0, 0, 0, 0);
+ asm.get_iv(AES_asm.HEAP_DATA);
+ asm.cipher(AES_asm.ENC.CTR, AES_asm.HEAP_DATA, 16);
+
+ let acheck = 0;
+ for (let j = 0; j < tagSize; ++j) acheck |= atag[j] ^ heap[j];
+ if (acheck) throw new SecurityError('data integrity check failed');
+
+ this.result = result;
+ this.counter = 1;
+ this.pos = 0;
+ this.len = 0;
+
+ return this;
+ }
+
+ private AES_CTR_set_options(nonce: Uint8Array, counter: number, size: number): void {
+ if (size < 8 || size > 48) throw new IllegalArgumentError('illegal counter size');
+
+ const mask = Math.pow(2, size) - 1;
+ this.asm.set_mask(0, 0, (mask / 0x100000000) | 0, mask | 0);
+
+ const len = nonce.length;
+ if (!len || len > 16) throw new IllegalArgumentError('illegal nonce size');
+
+ this.nonce = nonce;
+
+ const view = new DataView(new ArrayBuffer(16));
+ new Uint8Array(view.buffer).set(nonce);
+
+ this.asm.set_nonce(view.getUint32(0), view.getUint32(4), view.getUint32(8), view.getUint32(12));
+
+ if (counter < 0 || counter >= Math.pow(2, size)) throw new IllegalArgumentError('illegal counter value');
+
+ this.counter = counter;
+
+ this.asm.set_counter(0, 0, (counter / 0x100000000) | 0, counter | 0);
+ }
+}
diff --git a/src/aes/ccm/ccm.js b/src/aes/ccm/ccm.js
deleted file mode 100644
index 488a29f..0000000
--- a/src/aes/ccm/ccm.js
+++ /dev/null
@@ -1,394 +0,0 @@
-/**
- * Counter with CBC-MAC (CCM)
- *
- * Due to JS limitations (52 bits of Number precision) maximum encrypted message length
- * is limited to ~4 PiB ( 2^52 - 16 ) per `nonce`-`key` pair.
- * That also limits `lengthSize` parameter maximum value to 7 (not 8 as described in RFC3610).
- *
- * Additional authenticated data `adata` maximum length is choosen to be no more than 65279 bytes ( 2^16 - 2^8 ),
- * wich is considered enough for the most of use-cases.
- *
- * And one more important thing: in case of progressive ciphering of a data stream (in other
- * words when data can't be held in-memory at a whole and are ciphered chunk-by-chunk)
- * you have to know the `dataLength` in advance and pass that value to the cipher options.
- */
-
-import { AES_asm } from '../aes.asm';
-import { AES } from '../aes';
-import { _heap_write, is_bytes, is_number } from '../../utils';
-import { IllegalArgumentError, IllegalStateError, SecurityError } from '../../errors';
-
-var _AES_CCM_adata_maxLength = 65279, // 2^16 - 2^8
- _AES_CCM_data_maxLength = 4503599627370480; // 2^52 - 2^4
-
-export class AES_CCM extends AES {
- constructor(key, nonce, adata, tagSize, dataLength, heap, asm) {
- super(key, undefined, undefined, heap, asm);
- this.tagSize = 16;
- this.lengthSize = 4;
- this.nonce = null;
- this.adata = null;
- this.iv = null;
- this.counter = 1;
- this.dataLength = -1;
-
- this.AES_CCM_reset(key, undefined, nonce, adata, undefined, undefined, tagSize, dataLength);
-
- this.mode = 'CCM';
- this.BLOCK_SIZE = 16;
- }
-
- encrypt(data) {
- return this.AES_CCM_encrypt(data);
- }
- decrypt(data) {
- return this.AES_CCM_decrypt(data);
- }
-
- AES_CCM_reset(key, iv, nonce, adata, counter, lengthSize, tagSize, dataLength) {
- this.AES_reset(key, iv);
-
- if (tagSize !== undefined) {
- if (!is_number(tagSize)) throw new TypeError('tagSize must be a number');
-
- if (tagSize < 4 || tagSize > 16 || tagSize & 1) throw new IllegalArgumentError('illegal tagSize value');
-
- this.tagSize = tagSize;
- } else {
- this.tagSize = 16;
- }
-
- if (nonce !== undefined) {
- if (!is_bytes(nonce)) {
- throw new TypeError('unexpected nonce type');
- }
-
- if (nonce.length < 8 || nonce.length > 13) throw new IllegalArgumentError('illegal nonce length');
-
- this.nonce = nonce;
- this.lengthSize = lengthSize = 15 - nonce.length;
-
- nonce = new Uint8Array(nonce.length + 1);
- (nonce[0] = lengthSize - 1), nonce.set(this.nonce, 1);
- } else {
- throw new Error('nonce is required');
- }
-
- // Either counter, iv
- if (iv !== undefined) {
- if (adata !== undefined) throw new IllegalStateError('you should specify either adata or iv, not both');
-
- if (!is_number(counter)) throw new TypeError('counter must be a number');
-
- if (counter < 1 || counter >= Math.pow(2, 8 * lengthSize) - 16)
- throw new IllegalArgumentError('illegal counter value');
-
- this.counter = counter;
- } else if (adata !== undefined && adata !== null) {
- // Or adata, dataLength
- if (!is_bytes(adata)) {
- throw new TypeError('unexpected adata type');
- }
-
- if (adata.length > _AES_CCM_adata_maxLength) throw new IllegalArgumentError('illegal adata length');
-
- if (!is_number(dataLength)) throw new TypeError('dataLength must be a number');
-
- if (dataLength < 0 || dataLength > _AES_CCM_data_maxLength || dataLength > Math.pow(2, 8 * lengthSize) - 16)
- throw new IllegalArgumentError('illegal dataLength value');
-
- this.adata = adata.length ? adata : null;
- this.dataLength = dataLength;
- this.counter = counter = 1;
-
- this.AES_CCM_calculate_iv();
- iv = this.iv;
- } else {
- // Assume adata is empty, check dataLength
- if (!is_number(dataLength)) throw new TypeError('dataLength must be a number');
-
- if (dataLength < 0 || dataLength > _AES_CCM_data_maxLength || dataLength > Math.pow(2, 8 * lengthSize) - 16)
- throw new IllegalArgumentError('illegal dataLength value');
-
- this.adata = null;
- this.dataLength = dataLength;
- this.counter = counter = 1;
-
- this.AES_CCM_calculate_iv();
- iv = this.iv;
- }
-
- this.AES_set_iv(iv);
- this.AES_CTR_set_options(nonce, counter, 8 * lengthSize);
-
- return this;
- }
-
- AES_CCM_calculate_iv() {
- var nonce = this.nonce,
- adata = this.adata,
- tagSize = this.tagSize,
- lengthSize = this.lengthSize,
- dataLength = this.dataLength;
-
- var data = new Uint8Array(16 + (adata ? 2 + adata.length : 0));
-
- // B0: flags(adata?, M', L'), nonce, len(data)
- data[0] = (adata ? 64 : 0) | ((tagSize - 2) << 2) | (lengthSize - 1);
- data.set(nonce, 1);
- if (lengthSize > 6) data[9] = ((dataLength / 0x100000000) >>> 16) & 15;
- if (lengthSize > 5) data[10] = ((dataLength / 0x100000000) >>> 8) & 255;
- if (lengthSize > 4) data[11] = (dataLength / 0x100000000) & 255;
- if (lengthSize > 3) data[12] = dataLength >>> 24;
- if (lengthSize > 2) data[13] = (dataLength >>> 16) & 255;
- data[14] = (dataLength >>> 8) & 255;
- data[15] = dataLength & 255;
-
- // B*: len(adata), adata
- if (adata) {
- data[16] = (adata.length >>> 8) & 255;
- data[17] = adata.length & 255;
- data.set(adata, 18);
- }
-
- this._cbc_mac_process(data);
- this.asm.get_state(AES_asm.HEAP_DATA);
-
- this.iv = new Uint8Array(this.heap.subarray(0, 16));
- }
-
- _cbc_mac_process(data) {
- var heap = this.heap,
- asm = this.asm,
- dpos = 0,
- dlen = data.length || 0,
- wlen = 0;
-
- while (dlen > 0) {
- wlen = _heap_write(heap, 0, data, dpos, dlen);
- while (wlen & 15) heap[wlen++] = 0;
- dpos += wlen;
- dlen -= wlen;
-
- asm.mac(AES_asm.MAC.CBC, AES_asm.HEAP_DATA, wlen);
- }
- }
-
- AES_CCM_decrypt(data) {
- this.dataLength = data.length || 0;
-
- var result1 = this.AES_CCM_Decrypt_process(data).result;
- var result2 = this.AES_CCM_Decrypt_finish().result;
-
- var result = new Uint8Array(result1.length + result2.length);
- if (result1.length) result.set(result1);
- if (result2.length) result.set(result2, result1.length);
- this.result = result;
-
- return this;
- }
-
- AES_CCM_encrypt(data) {
- this.dataLength = data.length || 0;
-
- var result1 = this.AES_CCM_Encrypt_process(data).result;
- var result2 = this.AES_CCM_Encrypt_finish().result;
-
- var result = new Uint8Array(result1.length + result2.length);
- if (result1.length) result.set(result1);
- if (result2.length) result.set(result2, result1.length);
- this.result = result;
-
- return this;
- }
-
- AES_CCM_Encrypt_process(data) {
- if (!is_bytes(data)) throw new TypeError("data isn't of expected type");
-
- var dpos = 0,
- dlen = data.length || 0,
- asm = this.asm,
- heap = this.heap,
- counter = this.counter,
- pos = this.pos,
- len = this.len,
- rpos = 0,
- rlen = (len + dlen) & -16,
- wlen = 0;
-
- if (((counter - 1) << 4) + len + dlen > _AES_CCM_data_maxLength)
- // ??? should check against lengthSize
- throw new RangeError('counter overflow');
-
- var result = new Uint8Array(rlen);
-
- while (dlen > 0) {
- wlen = _heap_write(heap, pos + len, data, dpos, dlen);
- len += wlen;
- dpos += wlen;
- dlen -= wlen;
-
- wlen = asm.mac(AES_asm.MAC.CBC, AES_asm.HEAP_DATA + pos, len);
- wlen = asm.cipher(AES_asm.ENC.CTR, AES_asm.HEAP_DATA + pos, wlen);
-
- if (wlen) result.set(heap.subarray(pos, pos + wlen), rpos);
- counter += wlen >>> 4;
- rpos += wlen;
-
- if (wlen < len) {
- pos += wlen;
- len -= wlen;
- } else {
- pos = 0;
- len = 0;
- }
- }
-
- this.result = result;
- this.counter = counter;
- this.pos = pos;
- this.len = len;
-
- return this;
- }
-
- AES_CCM_Encrypt_finish() {
- var asm = this.asm,
- heap = this.heap,
- tagSize = this.tagSize,
- pos = this.pos,
- len = this.len,
- wlen = 0;
-
- var result = new Uint8Array(len + tagSize);
-
- for (var i = len; i & 15; i++) heap[pos + i] = 0;
-
- wlen = asm.mac(AES_asm.MAC.CBC, AES_asm.HEAP_DATA + pos, i);
- wlen = asm.cipher(AES_asm.ENC.CTR, AES_asm.HEAP_DATA + pos, i);
- if (len) result.set(heap.subarray(pos, pos + len));
-
- asm.set_counter(0, 0, 0, 0);
- asm.get_iv(AES_asm.HEAP_DATA);
- asm.cipher(AES_asm.ENC.CTR, AES_asm.HEAP_DATA, 16);
- result.set(heap.subarray(0, tagSize), len);
-
- this.result = result;
- this.counter = 1;
- this.pos = 0;
- this.len = 0;
-
- return this;
- }
-
- AES_CCM_Decrypt_process(data) {
- if (!is_bytes(data)) throw new TypeError("data isn't of expected type");
-
- var dpos = 0,
- dlen = data.length || 0,
- asm = this.asm,
- heap = this.heap,
- counter = this.counter,
- tagSize = this.tagSize,
- pos = this.pos,
- len = this.len,
- rpos = 0,
- rlen = len + dlen > tagSize ? (len + dlen - tagSize) & -16 : 0,
- tlen = len + dlen - rlen,
- wlen = 0;
-
- if (((counter - 1) << 4) + len + dlen > _AES_CCM_data_maxLength) throw new RangeError('counter overflow');
-
- var result = new Uint8Array(rlen);
-
- while (dlen > tlen) {
- wlen = _heap_write(heap, pos + len, data, dpos, dlen - tlen);
- len += wlen;
- dpos += wlen;
- dlen -= wlen;
-
- wlen = asm.cipher(AES_asm.DEC.CTR, AES_asm.HEAP_DATA + pos, wlen);
- wlen = asm.mac(AES_asm.MAC.CBC, AES_asm.HEAP_DATA + pos, wlen);
-
- if (wlen) result.set(heap.subarray(pos, pos + wlen), rpos);
- counter += wlen >>> 4;
- rpos += wlen;
-
- pos = 0;
- len = 0;
- }
-
- if (dlen > 0) {
- len += _heap_write(heap, 0, data, dpos, dlen);
- }
-
- this.result = result;
- this.counter = counter;
- this.pos = pos;
- this.len = len;
-
- return this;
- }
-
- AES_CCM_Decrypt_finish() {
- var asm = this.asm,
- heap = this.heap,
- tagSize = this.tagSize,
- pos = this.pos,
- len = this.len,
- rlen = len - tagSize,
- wlen = 0;
-
- if (len < tagSize) throw new IllegalStateError('authentication tag not found');
-
- var result = new Uint8Array(rlen),
- atag = new Uint8Array(heap.subarray(pos + rlen, pos + len));
-
- wlen = asm.cipher(AES_asm.DEC.CTR, AES_asm.HEAP_DATA + pos, (rlen + 15) & -16);
- result.set(heap.subarray(pos, pos + rlen));
-
- for (var i = rlen; i & 15; i++) heap[pos + i] = 0;
- wlen = asm.mac(AES_asm.MAC.CBC, AES_asm.HEAP_DATA + pos, i);
-
- asm.set_counter(0, 0, 0, 0);
- asm.get_iv(AES_asm.HEAP_DATA);
- asm.cipher(AES_asm.ENC.CTR, AES_asm.HEAP_DATA, 16);
-
- var acheck = 0;
- for (var i = 0; i < tagSize; ++i) acheck |= atag[i] ^ heap[i];
- if (acheck) throw new SecurityError('data integrity check failed');
-
- this.result = result;
- this.counter = 1;
- this.pos = 0;
- this.len = 0;
-
- return this;
- }
-
- reset() {}
-}
-
-export class AES_CCM_Encrypt extends AES_CCM {
- constructor(key, nonce, adata, tagSize, dataLength, heap, asm) {
- super(key, nonce, adata, tagSize, dataLength, heap, asm);
- }
- process(data) {
- return this.AES_CCM_Encrypt_process(data);
- }
- finish() {
- return this.AES_CCM_Encrypt_finish();
- }
-}
-
-export class AES_CCM_Decrypt extends AES_CCM {
- constructor(key, nonce, adata, tagSize, dataLength, heap, asm) {
- super(key, nonce, adata, tagSize, dataLength, heap, asm);
- }
- process(data) {
- return this.AES_CCM_Decrypt_process(data);
- }
- finish() {
- return this.AES_CCM_Decrypt_finish();
- }
-}
diff --git a/src/aes/ccm/exports.js b/src/aes/ccm/exports.js
deleted file mode 100644
index a1b690e..0000000
--- a/src/aes/ccm/exports.js
+++ /dev/null
@@ -1,45 +0,0 @@
-/**
- * AES-CCM exports
- */
-
-import { _AES_asm_instance, _AES_heap_instance } from '../exports';
-import { AES_CCM, AES_CCM_Decrypt, AES_CCM_Encrypt } from './ccm';
-
-/**
- * @param {Uint8Array} data
- * @param {Uint8Array} key
- * @param {Uint8Array} nonce
- * @param {Uint8Array} [adata]
- * @param {number} [tagSize]
- */
-function AES_CCM_encrypt_bytes(data, key, nonce, adata, tagSize) {
- if (data === undefined) throw new SyntaxError('data required');
- if (key === undefined) throw new SyntaxError('key required');
- if (nonce === undefined) throw new SyntaxError('nonce required');
- var dataLength = data.length || 0;
- return new AES_CCM(key, nonce, adata, tagSize, dataLength, _AES_heap_instance, _AES_asm_instance).encrypt(data)
- .result;
-}
-
-/**
- * @param {Uint8Array} data
- * @param {Uint8Array} key
- * @param {Uint8Array} nonce
- * @param {Uint8Array} [adata]
- * @param {number} [tagSize]
- */
-function AES_CCM_decrypt_bytes(data, key, nonce, adata, tagSize) {
- if (data === undefined) throw new SyntaxError('data required');
- if (key === undefined) throw new SyntaxError('key required');
- if (nonce === undefined) throw new SyntaxError('nonce required');
- var dataLength = data.length || 0;
- tagSize = tagSize || 16;
- return new AES_CCM(key, nonce, adata, tagSize, dataLength - tagSize, _AES_heap_instance, _AES_asm_instance).decrypt(
- data,
- ).result;
-}
-
-AES_CCM.encrypt = AES_CCM_encrypt_bytes;
-AES_CCM.decrypt = AES_CCM_decrypt_bytes;
-
-export { AES_CCM, AES_CCM_Encrypt, AES_CCM_Decrypt };
diff --git a/src/aes/cfb.ts b/src/aes/cfb.ts
new file mode 100644
index 0000000..1702d01
--- /dev/null
+++ b/src/aes/cfb.ts
@@ -0,0 +1,26 @@
+import { AES } from './aes';
+
+export class AES_CFB extends AES {
+ static encrypt(data: Uint8Array, key: Uint8Array, iv?: Uint8Array): Uint8Array {
+ return new AES_CFB(key, iv).encrypt(data).result as Uint8Array;
+ }
+
+ static decrypt(data: Uint8Array, key: Uint8Array, iv?: Uint8Array): Uint8Array {
+ return new AES_CFB(key, iv).decrypt(data).result as Uint8Array;
+ }
+
+ constructor(key: Uint8Array, iv?: Uint8Array) {
+ super(key, iv, true, 'CFB');
+ delete this.padding;
+ }
+
+ encrypt(data: Uint8Array): this {
+ this.AES_Encrypt_process(data);
+ return this.AES_Encrypt_finish();
+ }
+
+ decrypt(data: Uint8Array): this {
+ this.AES_Decrypt_process(data);
+ return this.AES_Decrypt_finish();
+ }
+}
diff --git a/src/aes/cfb/cfb.js b/src/aes/cfb/cfb.js
deleted file mode 100644
index 3cdd4cb..0000000
--- a/src/aes/cfb/cfb.js
+++ /dev/null
@@ -1,105 +0,0 @@
-/**
- * Cipher Feedback Mode (CFB)
- */
-
-import { AES } from '../aes';
-
-export class AES_CFB extends AES {
- /**
- * @param {Uint8Array} key
- * @param {Uint8Array} [iv]
- * @param {Uint8Array} [heap]
- * @param {Uint8Array} [asm]
- */
- constructor(key, iv, heap, asm) {
- super(key, iv, true, heap, asm);
- delete this.padding;
-
- this.mode = 'CFB';
- this.BLOCK_SIZE = 16;
- }
-
- encrypt(data) {
- return this.AES_Encrypt_finish(data);
- }
-
- decrypt(data) {
- return this.AES_Decrypt_finish(data);
- }
-}
-
-export class AES_CFB_Encrypt extends AES_CFB {
- /**
- * @param {Uint8Array} key
- * @param {Uint8Array} [iv=null]
- * @param {Uint8Array} [heap]
- * @param {Uint8Array} [asm]
- */
- constructor(key, iv, heap, asm) {
- super(key, iv, heap, asm);
- }
-
- /**
- * @param {Uint8Array} key
- * @param {Uint8Array} [iv]
- * @param {boolean} [padding]
- * @returns {AES_CFB_Encrypt}
- */
- reset(key, iv, padding) {
- return this.AES_reset(key, iv, padding);
- }
-
- /**
- * @param {Uint8Array} data
- * @returns {AES_CFB_Encrypt}
- */
- process(data) {
- return this.AES_Encrypt_process(data);
- }
-
- /**
- * @param {Uint8Array} data
- * @returns {AES_CFB_Encrypt}
- */
- finish(data) {
- return this.AES_Encrypt_finish(data);
- }
-}
-
-export class AES_CFB_Decrypt extends AES_CFB {
- /**
- * @param {Uint8Array} key
- * @param {Uint8Array} [iv=null]
- * @param {Uint8Array} [heap]
- * @param {Uint8Array} [asm]
- */
- constructor(key, iv, heap, asm) {
- super(key, iv, heap, asm);
- }
-
- /**
- * @param {Uint8Array} key
- * @param {Uint8Array} [iv]
- * @param {boolean} [padding]
- * @returns {AES_CFB_Decrypt}
- */
- reset(key, iv, padding) {
- return this.AES_reset(key, iv, padding);
- }
-
- /**
- * @param {Uint8Array} data
- * @returns {AES_CFB_Decrypt}
- */
- process(data) {
- return this.AES_Decrypt_process(data);
- }
-
- /**
- * @param {Uint8Array} data
- * @returns {AES_CFB_Decrypt}
- */
- finish(data) {
- return this.AES_Decrypt_finish(data);
- }
-}
diff --git a/src/aes/cfb/exports.js b/src/aes/cfb/exports.js
deleted file mode 100644
index 6c2e130..0000000
--- a/src/aes/cfb/exports.js
+++ /dev/null
@@ -1,35 +0,0 @@
-/**
- * AES-CFB exports
- */
-
-import { _AES_asm_instance, _AES_heap_instance } from '../exports';
-import { AES_CFB, AES_CFB_Decrypt, AES_CFB_Encrypt } from './cfb';
-
-/**
- * @param {Uint8Array} data
- * @param {Uint8Array} key
- * @param {Uint8Array} [iv]
- * @returns {Uint8Array}
- */
-function AES_CFB_encrypt_bytes(data, key, iv) {
- if (data === undefined) throw new SyntaxError('data required');
- if (key === undefined) throw new SyntaxError('key required');
- return new AES_CFB(key, iv, _AES_heap_instance, _AES_asm_instance).encrypt(data).result;
-}
-
-/**
- * @param {Uint8Array} data
- * @param {Uint8Array} key
- * @param {Uint8Array} [iv]
- * @returns {Uint8Array}
- */
-function AES_CFB_decrypt_bytes(data, key, iv) {
- if (data === undefined) throw new SyntaxError('data required');
- if (key === undefined) throw new SyntaxError('key required');
- return new AES_CFB(key, iv, _AES_heap_instance, _AES_asm_instance).decrypt(data).result;
-}
-
-AES_CFB.encrypt = AES_CFB_encrypt_bytes;
-AES_CFB.decrypt = AES_CFB_decrypt_bytes;
-
-export { AES_CFB, AES_CFB_Encrypt, AES_CFB_Decrypt };
diff --git a/src/aes/cmac/cmac.js b/src/aes/cmac.ts
similarity index 52%
rename from src/aes/cmac/cmac.js
rename to src/aes/cmac.ts
index 7d52484..67a9b62 100644
--- a/src/aes/cmac/cmac.js
+++ b/src/aes/cmac.ts
@@ -1,40 +1,39 @@
-import { AES_ECB } from '../ecb/ecb';
-import { AES_CBC_Encrypt } from '../cbc/cbc';
-import { bytes_to_hex, hex_to_bytes } from '../../utils';
-
-/**
- * @param {Uint8Array} data
- */
-function mul2(data) {
+import { AES_ECB } from './ecb';
+import { AES_CBC } from './cbc';
+
+function mul2(data: Uint8Array): void {
const t = data[0] & 0x80;
- for (var i = 0; i < 15; i++) {
- data[i] = (data[i] << 1) ^ ((data[i+1] & 0x80) ? 1 : 0);
+ for (let i = 0; i < 15; i++) {
+ data[i] = (data[i] << 1) ^ (data[i + 1] & 0x80 ? 1 : 0);
}
data[15] = (data[15] << 1) ^ (t ? 0x87 : 0);
}
export class AES_CMAC {
- /**
- * @param {Uint8Array} key
- */
- constructor(key) {
- this.k = new AES_ECB(key).encrypt(new Uint8Array(16)).result;
+ private readonly k: Uint8Array;
+ private readonly cbc: AES_CBC;
+ private readonly buffer: Uint8Array;
+ private bufferLength = 0;
+ public result!: Uint8Array | null;
+
+ static bytes(data: Uint8Array, key: Uint8Array): Uint8Array {
+ return new AES_CMAC(key).process(data).finish().result as Uint8Array;
+ }
+
+ constructor(key: Uint8Array) {
+ this.k = new AES_ECB(key).encrypt(new Uint8Array(16)).result as Uint8Array;
mul2(this.k);
- this.cbc = new AES_CBC_Encrypt(key, new Uint8Array(16), false);
+ this.cbc = new AES_CBC(key, new Uint8Array(16), false);
this.buffer = new Uint8Array(16);
- this.bufferLength = 0;
this.result = null;
}
- /**
- * @param {Uint8Array} data
- */
- process(data) {
+ process(data: Uint8Array): this {
if (this.bufferLength + data.length > 16) {
- this.cbc.process(this.buffer.subarray(0, this.bufferLength));
+ this.cbc.encrypt(this.buffer.subarray(0, this.bufferLength));
const offset = ((this.bufferLength + data.length - 1) & ~15) - this.bufferLength;
- this.cbc.process(data.subarray(0, offset));
+ this.cbc.encrypt(data.subarray(0, offset));
this.buffer.set(data.subarray(offset));
this.bufferLength = data.length - offset;
} else {
@@ -44,7 +43,7 @@ export class AES_CMAC {
return this;
}
- finish() {
+ finish(): this {
if (this.bufferLength !== 16) {
this.buffer[this.bufferLength] = 0x80;
for (let i = this.bufferLength + 1; i < 16; i++) {
@@ -57,7 +56,7 @@ export class AES_CMAC {
this.buffer[i] ^= this.k[i];
}
- this.result = this.cbc.process(this.buffer).result;
+ this.result = this.cbc.encrypt(this.buffer).result;
return this;
}
}
diff --git a/src/aes/cmac/exports.js b/src/aes/cmac/exports.js
deleted file mode 100644
index 4009808..0000000
--- a/src/aes/cmac/exports.js
+++ /dev/null
@@ -1,16 +0,0 @@
-import { AES_CMAC } from './cmac';
-
-/**
- * @param {Uint8Array} data
- * @param {Uint8Array} key
- * @returns {Uint8Array}
- */
-function AES_CMAC_bytes(data, key) {
- if (data === undefined) throw new SyntaxError('data required');
- if (key === undefined) throw new SyntaxError('key required');
- return new AES_CMAC(key).process(data).finish().result;
-}
-
-AES_CMAC.bytes = AES_CMAC_bytes;
-
-export { AES_CMAC };
diff --git a/src/aes/ctr.ts b/src/aes/ctr.ts
new file mode 100644
index 0000000..5cd3a87
--- /dev/null
+++ b/src/aes/ctr.ts
@@ -0,0 +1,59 @@
+import { AES } from './aes';
+import { IllegalArgumentError } from '../other/errors';
+
+export class AES_CTR extends AES {
+ static encrypt(data: Uint8Array, key: Uint8Array, nonce: Uint8Array): Uint8Array {
+ return new AES_CTR(key, nonce).encrypt(data).result as Uint8Array;
+ }
+
+ static decrypt(data: Uint8Array, key: Uint8Array, nonce: Uint8Array): Uint8Array {
+ return new AES_CTR(key, nonce).encrypt(data).result as Uint8Array;
+ }
+
+ constructor(key: Uint8Array, nonce: Uint8Array) {
+ super(key, undefined, false, 'CTR');
+ delete this.padding;
+
+ this.AES_CTR_set_options(nonce);
+ }
+
+ encrypt(data: Uint8Array): this {
+ this.AES_Encrypt_process(data);
+ return this.AES_Encrypt_finish();
+ }
+
+ decrypt(data: Uint8Array): this {
+ this.AES_Encrypt_process(data);
+ return this.AES_Encrypt_finish();
+ }
+
+ private AES_CTR_set_options(nonce: Uint8Array, counter?: number, size?: number): void {
+ if (size !== undefined) {
+ if (size < 8 || size > 48) throw new IllegalArgumentError('illegal counter size');
+
+ let mask = Math.pow(2, size) - 1;
+ this.asm.set_mask(0, 0, (mask / 0x100000000) | 0, mask | 0);
+ } else {
+ size = 48;
+ this.asm.set_mask(0, 0, 0xffff, 0xffffffff);
+ }
+
+ if (nonce !== undefined) {
+ let len = nonce.length;
+ if (!len || len > 16) throw new IllegalArgumentError('illegal nonce size');
+
+ let view = new DataView(new ArrayBuffer(16));
+ new Uint8Array(view.buffer).set(nonce);
+
+ this.asm.set_nonce(view.getUint32(0), view.getUint32(4), view.getUint32(8), view.getUint32(12));
+ } else {
+ throw new Error('nonce is required');
+ }
+
+ if (counter !== undefined) {
+ if (counter < 0 || counter >= Math.pow(2, size)) throw new IllegalArgumentError('illegal counter value');
+
+ this.asm.set_counter(0, 0, (counter / 0x100000000) | 0, counter | 0);
+ }
+ }
+}
diff --git a/src/aes/ctr/ctr.js b/src/aes/ctr/ctr.js
deleted file mode 100644
index 763e5fb..0000000
--- a/src/aes/ctr/ctr.js
+++ /dev/null
@@ -1,99 +0,0 @@
-/**
- * Counter Mode (CTR)
- */
-
-import { AES } from '../aes';
-
-export class AES_CTR extends AES {
- /**
- * @param {Uint8Array} key
- * @param {Uint8Array} nonce
- * @param {Uint8Array} [heap]
- * @param {Uint8Array} [asm]
- */
- constructor(key, nonce, heap, asm) {
- super(key, undefined, undefined, heap, asm);
- this.reset(key, nonce);
-
- this.AES_CTR_set_options(nonce);
- delete this.padding;
-
- this.mode = 'CTR';
- this.BLOCK_SIZE = 16;
- }
-
- /**
- * @param {Uint8Array} key
- * @param {Uint8Array} nonce
- * @param {number} [counter]
- * @param {number} [counterSize]
- * @returns {AES_CTR}
- */
- reset(key, nonce, counter, counterSize) {
- this.AES_reset(key, undefined, undefined);
-
- this.AES_CTR_set_options(nonce, counter, counterSize);
-
- return this;
- }
-
- /**
- * @param {Uint8Array} data
- * @returns {AES_CTR}
- */
- encrypt(data) {
- return this.AES_Encrypt_finish(data);
- }
-
- /**
- * @param {Uint8Array} data
- * @returns {AES_CTR}
- */
- decrypt(data) {
- return this.AES_Encrypt_finish(data);
- }
-}
-
-export class AES_CTR_Crypt extends AES_CTR {
- /**
- * @param {Uint8Array} key
- * @param {Uint8Array} nonce
- * @param {Uint8Array} [heap]
- * @param {Uint8Array} [asm]
- */
- constructor(key, nonce, heap, asm) {
- super(key, nonce, heap, asm);
- this.BLOCK_SIZE = 16;
- }
-
- /**
- * @param {Uint8Array} key
- * @param {Uint8Array} nonce
- * @param {number} [counter]
- * @param {number} [counterSize]
- * @returns {AES_CTR_Crypt}
- */
- reset(key, nonce, counter, counterSize) {
- this.AES_reset(key, undefined, undefined);
-
- this.AES_CTR_set_options(nonce, counter, counterSize);
-
- return this;
- }
-
- /**
- * @param {Uint8Array} data
- * @returns {AES_CTR_Crypt}
- */
- process(data) {
- return this.AES_Encrypt_process(data);
- }
-
- /**
- * @param {Uint8Array} data
- * @returns {AES_CTR_Crypt}
- */
- finish(data) {
- return this.AES_Encrypt_finish(data);
- }
-}
diff --git a/src/aes/ctr/exports.js b/src/aes/ctr/exports.js
deleted file mode 100644
index b99dcf1..0000000
--- a/src/aes/ctr/exports.js
+++ /dev/null
@@ -1,24 +0,0 @@
-/**
- * AES-CTR exports
- */
-
-import { _AES_asm_instance, _AES_heap_instance } from '../exports';
-import { AES_CTR } from './ctr';
-
-/**
- * @param {Uint8Array} data
- * @param {Uint8Array} key
- * @param {Uint8Array} nonce
- * @returns {Uint8Array}
- */
-function AES_CTR_crypt_bytes(data, key, nonce) {
- if (data === undefined) throw new SyntaxError('data required');
- if (key === undefined) throw new SyntaxError('key required');
- if (nonce === undefined) throw new SyntaxError('nonce required');
- return new AES_CTR(key, nonce, _AES_heap_instance, _AES_asm_instance).encrypt(data).result;
-}
-
-AES_CTR.encrypt = AES_CTR_crypt_bytes;
-AES_CTR.decrypt = AES_CTR_crypt_bytes;
-
-export { AES_CTR };
diff --git a/src/aes/ecb.ts b/src/aes/ecb.ts
new file mode 100644
index 0000000..33913e0
--- /dev/null
+++ b/src/aes/ecb.ts
@@ -0,0 +1,25 @@
+import { AES } from './aes';
+
+export class AES_ECB extends AES {
+ static encrypt(data: Uint8Array, key: Uint8Array, padding: boolean = false): Uint8Array {
+ return new AES_ECB(key, padding).encrypt(data).result as Uint8Array;
+ }
+
+ static decrypt(data: Uint8Array, key: Uint8Array, padding: boolean = false): Uint8Array {
+ return new AES_ECB(key, padding).decrypt(data).result as Uint8Array;
+ }
+
+ constructor(key: Uint8Array, padding: boolean = false) {
+ super(key, undefined, padding, 'ECB');
+ }
+
+ encrypt(data: Uint8Array): this {
+ this.AES_Encrypt_process(data);
+ return this.AES_Encrypt_finish();
+ }
+
+ decrypt(data: Uint8Array): this {
+ this.AES_Decrypt_process(data);
+ return this.AES_Decrypt_finish();
+ }
+}
diff --git a/src/aes/ecb/ecb.js b/src/aes/ecb/ecb.js
deleted file mode 100644
index 29ff4e7..0000000
--- a/src/aes/ecb/ecb.js
+++ /dev/null
@@ -1,96 +0,0 @@
-import { AES } from '../aes';
-
-/**
- * Electronic Code Book Mode (ECB)
- */
-export class AES_ECB extends AES {
- /**
- * @param {Uint8Array} key
- * @param {Uint8Array} [heap]
- * @param {Uint8Array} [asm]
- */
- constructor(key, heap, asm) {
- super(key, undefined, false, heap, asm);
-
- this.mode = 'ECB';
- this.BLOCK_SIZE = 16;
- }
-
- encrypt(data) {
- return this.AES_Encrypt_finish(data);
- }
-
- decrypt(data) {
- return this.AES_Decrypt_finish(data);
- }
-}
-
-export class AES_ECB_Encrypt extends AES_ECB {
- /**
- * @param {Uint8Array} key
- * @param {Uint8Array} [heap]
- * @param {Uint8Array} [asm]
- */
- constructor(key, heap, asm) {
- super(key, heap, asm);
- }
-
- /**
- * @param {Uint8Array} key
- * @returns {AES_ECB_Encrypt}
- */
- reset(key) {
- return this.AES_reset(key, null, true);
- }
-
- /**
- * @param {Uint8Array} data
- * @returns {AES_ECB_Encrypt}
- */
- process(data) {
- return this.AES_Encrypt_process(data);
- }
-
- /**
- * @param {Uint8Array} data
- * @returns {AES_ECB_Encrypt}
- */
- finish(data) {
- return this.AES_Encrypt_finish(data);
- }
-}
-
-export class AES_ECB_Decrypt extends AES_ECB {
- /**
- * @param {Uint8Array} key
- * @param {Uint8Array} [heap]
- * @param {Uint8Array} [asm]
- */
- constructor(key, heap, asm) {
- super(key, heap, asm);
- }
-
- /**
- * @param {Uint8Array} key
- * @returns {AES_ECB_Decrypt}
- */
- reset(key) {
- return this.AES_reset(key, null, true);
- }
-
- /**
- * @param {Uint8Array} data
- * @returns {AES_ECB_Decrypt}
- */
- process(data) {
- return this.AES_Decrypt_process(data);
- }
-
- /**
- * @param {Uint8Array} data
- * @returns {AES_ECB_Decrypt}
- */
- finish(data) {
- return this.AES_Decrypt_finish(data);
- }
-}
diff --git a/src/aes/ecb/exports.js b/src/aes/ecb/exports.js
deleted file mode 100644
index 6b0966d..0000000
--- a/src/aes/ecb/exports.js
+++ /dev/null
@@ -1,23 +0,0 @@
-/**
- * AES-ECB exports
- */
-
-import { _AES_asm_instance, _AES_heap_instance } from '../exports';
-import { AES_ECB, AES_ECB_Decrypt, AES_ECB_Encrypt } from './ecb';
-
-function AES_ECB_encrypt_bytes(data, key) {
- if (data === undefined) throw new SyntaxError('data required');
- if (key === undefined) throw new SyntaxError('key required');
- return new AES_ECB(key, _AES_heap_instance, _AES_asm_instance).encrypt(data).result;
-}
-
-function AES_ECB_decrypt_bytes(data, key) {
- if (data === undefined) throw new SyntaxError('data required');
- if (key === undefined) throw new SyntaxError('key required');
- return new AES_ECB(key, _AES_heap_instance, _AES_asm_instance).decrypt(data).result;
-}
-
-AES_ECB.encrypt = AES_ECB_encrypt_bytes;
-AES_ECB.decrypt = AES_ECB_decrypt_bytes;
-
-export { AES_ECB, AES_ECB_Encrypt, AES_ECB_Decrypt };
diff --git a/src/aes/exports.js b/src/aes/exports.ts
similarity index 63%
rename from src/aes/exports.js
rename to src/aes/exports.ts
index 179a9b6..809ae54 100644
--- a/src/aes/exports.js
+++ b/src/aes/exports.ts
@@ -2,4 +2,4 @@
import { AES_asm } from './aes.asm';
export var _AES_heap_instance = new Uint8Array(0x100000); // 1MB
-export var _AES_asm_instance = AES_asm(null, _AES_heap_instance.buffer);
+export var _AES_asm_instance = new AES_asm(null, _AES_heap_instance.buffer);
diff --git a/src/aes/gcm.ts b/src/aes/gcm.ts
new file mode 100644
index 0000000..f966a94
--- /dev/null
+++ b/src/aes/gcm.ts
@@ -0,0 +1,352 @@
+import { IllegalArgumentError, IllegalStateError, SecurityError } from '../other/errors';
+import { _heap_write } from '../other/utils';
+import { AES } from './aes';
+import { AES_asm } from './aes.asm';
+
+const _AES_GCM_data_maxLength = 68719476704; // 2^36 - 2^5
+
+export class AES_GCM extends AES {
+ private readonly adata: Uint8Array | undefined;
+ private readonly gamma0: number = 0;
+
+ private counter: number = 1;
+
+ static encrypt(
+ cleartext: Uint8Array,
+ key: Uint8Array,
+ nonce: Uint8Array,
+ adata?: Uint8Array,
+ tagsize?: number,
+ ): Uint8Array {
+ return new AES_GCM(key, nonce, adata, tagsize).encrypt(cleartext).result as Uint8Array;
+ }
+
+ static decrypt(
+ ciphertext: Uint8Array,
+ key: Uint8Array,
+ nonce: Uint8Array,
+ adata?: Uint8Array,
+ tagsize?: number,
+ ): Uint8Array {
+ return new AES_GCM(key, nonce, adata, tagsize).decrypt(ciphertext).result as Uint8Array;
+ }
+
+ constructor(key: Uint8Array, nonce: Uint8Array, adata?: Uint8Array, private readonly tagSize: number = 16) {
+ super(key, undefined, false, 'CTR');
+
+ // Init GCM
+ this.asm.gcm_init();
+
+ // Tag size
+ if (this.tagSize < 4 || this.tagSize > 16) throw new IllegalArgumentError('illegal tagSize value');
+
+ // Nonce
+ const noncelen = nonce.length || 0;
+ const noncebuf = new Uint8Array(16);
+ if (noncelen !== 12) {
+ this._gcm_mac_process(nonce);
+
+ this.heap[0] = 0;
+ this.heap[1] = 0;
+ this.heap[2] = 0;
+ this.heap[3] = 0;
+ this.heap[4] = 0;
+ this.heap[5] = 0;
+ this.heap[6] = 0;
+ this.heap[7] = 0;
+ this.heap[8] = 0;
+ this.heap[9] = 0;
+ this.heap[10] = 0;
+ this.heap[11] = noncelen >>> 29;
+ this.heap[12] = (noncelen >>> 21) & 255;
+ this.heap[13] = (noncelen >>> 13) & 255;
+ this.heap[14] = (noncelen >>> 5) & 255;
+ this.heap[15] = (noncelen << 3) & 255;
+ this.asm.mac(AES_asm.MAC.GCM, AES_asm.HEAP_DATA, 16);
+
+ this.asm.get_iv(AES_asm.HEAP_DATA);
+ this.asm.set_iv(0, 0, 0, 0);
+
+ noncebuf.set(this.heap.subarray(0, 16));
+ } else {
+ noncebuf.set(nonce);
+ noncebuf[15] = 1;
+ }
+
+ const nonceview = new DataView(noncebuf.buffer);
+ this.gamma0 = nonceview.getUint32(12);
+
+ this.asm.set_nonce(nonceview.getUint32(0), nonceview.getUint32(4), nonceview.getUint32(8), 0);
+ this.asm.set_mask(0, 0, 0, 0xffffffff);
+
+ // Associated data
+ if (adata !== undefined) {
+ if (adata.length > _AES_GCM_data_maxLength) throw new IllegalArgumentError('illegal adata length');
+
+ if (adata.length) {
+ this.adata = adata;
+ this._gcm_mac_process(adata);
+ } else {
+ this.adata = undefined;
+ }
+ } else {
+ this.adata = undefined;
+ }
+
+ // Counter
+ if (this.counter < 1 || this.counter > 0xffffffff)
+ throw new RangeError('counter must be a positive 32-bit integer');
+ this.asm.set_counter(0, 0, 0, (this.gamma0 + this.counter) | 0);
+ }
+
+ encrypt(data: Uint8Array) {
+ return this.AES_GCM_encrypt(data);
+ }
+
+ decrypt(data: Uint8Array) {
+ return this.AES_GCM_decrypt(data);
+ }
+
+ AES_GCM_Encrypt_process(data: Uint8Array) {
+ let dpos = 0;
+ let dlen = data.length || 0;
+ let asm = this.asm;
+ let heap = this.heap;
+ let counter = this.counter;
+ let pos = this.pos;
+ let len = this.len;
+ let rpos = 0;
+ let rlen = (len + dlen) & -16;
+ let wlen = 0;
+
+ if (((counter - 1) << 4) + len + dlen > _AES_GCM_data_maxLength) throw new RangeError('counter overflow');
+
+ const result = new Uint8Array(rlen);
+
+ while (dlen > 0) {
+ wlen = _heap_write(heap, pos + len, data, dpos, dlen);
+ len += wlen;
+ dpos += wlen;
+ dlen -= wlen;
+
+ wlen = asm.cipher(AES_asm.ENC.CTR, AES_asm.HEAP_DATA + pos, len);
+ wlen = asm.mac(AES_asm.MAC.GCM, AES_asm.HEAP_DATA + pos, wlen);
+
+ if (wlen) result.set(heap.subarray(pos, pos + wlen), rpos);
+ counter += wlen >>> 4;
+ rpos += wlen;
+
+ if (wlen < len) {
+ pos += wlen;
+ len -= wlen;
+ } else {
+ pos = 0;
+ len = 0;
+ }
+ }
+
+ this.result = result;
+ this.counter = counter;
+ this.pos = pos;
+ this.len = len;
+
+ return this;
+ }
+
+ AES_GCM_Encrypt_finish() {
+ let asm = this.asm;
+ let heap = this.heap;
+ let counter = this.counter;
+ let tagSize = this.tagSize;
+ let adata = this.adata;
+ let pos = this.pos;
+ let len = this.len;
+
+ const result = new Uint8Array(len + tagSize);
+
+ asm.cipher(AES_asm.ENC.CTR, AES_asm.HEAP_DATA + pos, (len + 15) & -16);
+ if (len) result.set(heap.subarray(pos, pos + len));
+
+ let i = len;
+ for (; i & 15; i++) heap[pos + i] = 0;
+ asm.mac(AES_asm.MAC.GCM, AES_asm.HEAP_DATA + pos, i);
+
+ const alen = adata !== undefined ? adata.length : 0;
+ const clen = ((counter - 1) << 4) + len;
+
+ heap[0] = 0;
+ heap[1] = 0;
+ heap[2] = 0;
+ heap[3] = alen >>> 29;
+ heap[4] = alen >>> 21;
+ heap[5] = (alen >>> 13) & 255;
+ heap[6] = (alen >>> 5) & 255;
+ heap[7] = (alen << 3) & 255;
+ heap[8] = heap[9] = heap[10] = 0;
+ heap[11] = clen >>> 29;
+ heap[12] = (clen >>> 21) & 255;
+ heap[13] = (clen >>> 13) & 255;
+ heap[14] = (clen >>> 5) & 255;
+ heap[15] = (clen << 3) & 255;
+
+ asm.mac(AES_asm.MAC.GCM, AES_asm.HEAP_DATA, 16);
+ asm.get_iv(AES_asm.HEAP_DATA);
+
+ asm.set_counter(0, 0, 0, this.gamma0);
+ asm.cipher(AES_asm.ENC.CTR, AES_asm.HEAP_DATA, 16);
+ result.set(heap.subarray(0, tagSize), len);
+
+ this.result = result;
+ this.counter = 1;
+ this.pos = 0;
+ this.len = 0;
+
+ return this;
+ }
+
+ AES_GCM_Decrypt_process(data: Uint8Array) {
+ let dpos = 0;
+ let dlen = data.length || 0;
+ let asm = this.asm;
+ let heap = this.heap;
+ let counter = this.counter;
+ let tagSize = this.tagSize;
+ let pos = this.pos;
+ let len = this.len;
+ let rpos = 0;
+ let rlen = len + dlen > tagSize ? (len + dlen - tagSize) & -16 : 0;
+ let tlen = len + dlen - rlen;
+ let wlen = 0;
+
+ if (((counter - 1) << 4) + len + dlen > _AES_GCM_data_maxLength) throw new RangeError('counter overflow');
+
+ const result = new Uint8Array(rlen);
+
+ while (dlen > tlen) {
+ wlen = _heap_write(heap, pos + len, data, dpos, dlen - tlen);
+ len += wlen;
+ dpos += wlen;
+ dlen -= wlen;
+
+ wlen = asm.mac(AES_asm.MAC.GCM, AES_asm.HEAP_DATA + pos, wlen);
+ wlen = asm.cipher(AES_asm.DEC.CTR, AES_asm.HEAP_DATA + pos, wlen);
+
+ if (wlen) result.set(heap.subarray(pos, pos + wlen), rpos);
+ counter += wlen >>> 4;
+ rpos += wlen;
+
+ pos = 0;
+ len = 0;
+ }
+
+ if (dlen > 0) {
+ len += _heap_write(heap, 0, data, dpos, dlen);
+ }
+
+ this.result = result;
+ this.counter = counter;
+ this.pos = pos;
+ this.len = len;
+
+ return this;
+ }
+
+ AES_GCM_Decrypt_finish() {
+ let asm = this.asm;
+ let heap = this.heap;
+ let tagSize = this.tagSize;
+ let adata = this.adata;
+ let counter = this.counter;
+ let pos = this.pos;
+ let len = this.len;
+ let rlen = len - tagSize;
+
+ if (len < tagSize) throw new IllegalStateError('authentication tag not found');
+
+ const result = new Uint8Array(rlen);
+ const atag = new Uint8Array(heap.subarray(pos + rlen, pos + len));
+
+ let i = rlen;
+ for (; i & 15; i++) heap[pos + i] = 0;
+
+ asm.mac(AES_asm.MAC.GCM, AES_asm.HEAP_DATA + pos, i);
+ asm.cipher(AES_asm.DEC.CTR, AES_asm.HEAP_DATA + pos, i);
+
+ if (rlen) result.set(heap.subarray(pos, pos + rlen));
+
+ const alen = adata !== undefined ? adata.length : 0;
+ const clen = ((counter - 1) << 4) + len - tagSize;
+ heap[0] = 0;
+ heap[1] = 0;
+ heap[2] = 0;
+ heap[3] = alen >>> 29;
+ heap[4] = alen >>> 21;
+ heap[5] = (alen >>> 13) & 255;
+ heap[6] = (alen >>> 5) & 255;
+ heap[7] = (alen << 3) & 255;
+ heap[8] = heap[9] = heap[10] = 0;
+ heap[11] = clen >>> 29;
+ heap[12] = (clen >>> 21) & 255;
+ heap[13] = (clen >>> 13) & 255;
+ heap[14] = (clen >>> 5) & 255;
+ heap[15] = (clen << 3) & 255;
+ asm.mac(AES_asm.MAC.GCM, AES_asm.HEAP_DATA, 16);
+ asm.get_iv(AES_asm.HEAP_DATA);
+
+ asm.set_counter(0, 0, 0, this.gamma0);
+ asm.cipher(AES_asm.ENC.CTR, AES_asm.HEAP_DATA, 16);
+
+ let acheck = 0;
+ for (let i = 0; i < tagSize; ++i) acheck |= atag[i] ^ heap[i];
+ if (acheck) throw new SecurityError('data integrity check failed');
+
+ this.result = result;
+ this.counter = 1;
+ this.pos = 0;
+ this.len = 0;
+
+ return this;
+ }
+
+ private AES_GCM_decrypt(data: Uint8Array) {
+ const result1 = this.AES_GCM_Decrypt_process(data).result as Uint8Array;
+ const result2 = this.AES_GCM_Decrypt_finish().result as Uint8Array;
+
+ const result = new Uint8Array(result1.length + result2.length);
+ if (result1.length) result.set(result1);
+ if (result2.length) result.set(result2, result1.length);
+ this.result = result;
+
+ return this;
+ }
+
+ private AES_GCM_encrypt(data: Uint8Array) {
+ const result1 = this.AES_GCM_Encrypt_process(data).result as Uint8Array;
+ const result2 = this.AES_GCM_Encrypt_finish().result as Uint8Array;
+
+ const result = new Uint8Array(result1.length + result2.length);
+ if (result1.length) result.set(result1);
+ if (result2.length) result.set(result2, result1.length);
+ this.result = result;
+
+ return this;
+ }
+
+ _gcm_mac_process(data: Uint8Array) {
+ const heap = this.heap;
+ const asm = this.asm;
+ let dpos = 0;
+ let dlen = data.length || 0;
+ let wlen = 0;
+
+ while (dlen > 0) {
+ wlen = _heap_write(heap, 0, data, dpos, dlen);
+ dpos += wlen;
+ dlen -= wlen;
+
+ while (wlen & 15) heap[wlen++] = 0;
+
+ asm.mac(AES_asm.MAC.GCM, AES_asm.HEAP_DATA, wlen);
+ }
+ }
+}
diff --git a/src/aes/gcm/exports.js b/src/aes/gcm/exports.js
deleted file mode 100644
index cbee1e8..0000000
--- a/src/aes/gcm/exports.js
+++ /dev/null
@@ -1,41 +0,0 @@
-/**
- * AES-GCM exports
- */
-
-import { _AES_asm_instance, _AES_heap_instance } from '../exports';
-import { AES_GCM, AES_GCM_Decrypt, AES_GCM_Encrypt } from './gcm';
-
-/**
- * @param {Uint8Array} data
- * @param {Uint8Array} key
- * @param {Uint8Array} nonce
- * @param {Uint8Array} [adata]
- * @param {number} [tagSize]
- * @return {Uint8Array}
- */
-function AES_GCM_encrypt_bytes(data, key, nonce, adata, tagSize) {
- if (data === undefined) throw new SyntaxError('data required');
- if (key === undefined) throw new SyntaxError('key required');
- if (nonce === undefined) throw new SyntaxError('nonce required');
- return new AES_GCM(key, nonce, adata, tagSize, _AES_heap_instance, _AES_asm_instance).encrypt(data).result;
-}
-
-/**
- * @param {Uint8Array} data
- * @param {Uint8Array} key
- * @param {Uint8Array} nonce
- * @param {Uint8Array} [adata]
- * @param {number} [tagSize]
- * @return {Uint8Array}
- */
-function AES_GCM_decrypt_bytes(data, key, nonce, adata, tagSize) {
- if (data === undefined) throw new SyntaxError('data required');
- if (key === undefined) throw new SyntaxError('key required');
- if (nonce === undefined) throw new SyntaxError('nonce required');
- return new AES_GCM(key, nonce, adata, tagSize, _AES_heap_instance, _AES_asm_instance).decrypt(data).result;
-}
-
-AES_GCM.encrypt = AES_GCM_encrypt_bytes;
-AES_GCM.decrypt = AES_GCM_decrypt_bytes;
-
-export { AES_GCM, AES_GCM_Encrypt, AES_GCM_Decrypt };
diff --git a/src/aes/gcm/gcm.js b/src/aes/gcm/gcm.js
deleted file mode 100644
index e432410..0000000
--- a/src/aes/gcm/gcm.js
+++ /dev/null
@@ -1,399 +0,0 @@
-/**
- * Galois/Counter mode
- */
-
-import { IllegalArgumentError, IllegalStateError, SecurityError } from '../../errors';
-import { _heap_write, is_bytes, is_number } from '../../utils';
-import { AES } from '../aes';
-import { AES_asm } from '../aes.asm';
-
-var _AES_GCM_data_maxLength = 68719476704; // 2^36 - 2^5
-
-export class AES_GCM extends AES {
- constructor(key, nonce, adata, tagSize, heap, asm) {
- super(key, undefined, false, heap, asm);
-
- this.nonce = null;
- this.adata = null;
- this.iv = null;
- this.counter = 1;
- this.tagSize = 16;
- this.mode = 'GCM';
- this.BLOCK_SIZE = 16;
-
- this.reset(key, tagSize, nonce, adata);
- }
-
- reset(key, tagSize, nonce, adata) {
- return this.AES_GCM_reset(key, tagSize, nonce, adata);
- }
-
- encrypt(data) {
- return this.AES_GCM_encrypt(data);
- }
-
- decrypt(data) {
- return this.AES_GCM_decrypt(data);
- }
-
- AES_GCM_Encrypt_process(data) {
- if (!is_bytes(data)) throw new TypeError("data isn't of expected type");
-
- var dpos = 0,
- dlen = data.length || 0,
- asm = this.asm,
- heap = this.heap,
- counter = this.counter,
- pos = this.pos,
- len = this.len,
- rpos = 0,
- rlen = (len + dlen) & -16,
- wlen = 0;
-
- if (((counter - 1) << 4) + len + dlen > _AES_GCM_data_maxLength) throw new RangeError('counter overflow');
-
- var result = new Uint8Array(rlen);
-
- while (dlen > 0) {
- wlen = _heap_write(heap, pos + len, data, dpos, dlen);
- len += wlen;
- dpos += wlen;
- dlen -= wlen;
-
- wlen = asm.cipher(AES_asm.ENC.CTR, AES_asm.HEAP_DATA + pos, len);
- wlen = asm.mac(AES_asm.MAC.GCM, AES_asm.HEAP_DATA + pos, wlen);
-
- if (wlen) result.set(heap.subarray(pos, pos + wlen), rpos);
- counter += wlen >>> 4;
- rpos += wlen;
-
- if (wlen < len) {
- pos += wlen;
- len -= wlen;
- } else {
- pos = 0;
- len = 0;
- }
- }
-
- this.result = result;
- this.counter = counter;
- this.pos = pos;
- this.len = len;
-
- return this;
- }
-
- AES_GCM_Encrypt_finish() {
- var asm = this.asm,
- heap = this.heap,
- counter = this.counter,
- tagSize = this.tagSize,
- adata = this.adata,
- pos = this.pos,
- len = this.len;
-
- var result = new Uint8Array(len + tagSize);
-
- asm.cipher(AES_asm.ENC.CTR, AES_asm.HEAP_DATA + pos, (len + 15) & -16);
- if (len) result.set(heap.subarray(pos, pos + len));
-
- for (var i = len; i & 15; i++) heap[pos + i] = 0;
- asm.mac(AES_asm.MAC.GCM, AES_asm.HEAP_DATA + pos, i);
-
- var alen = adata !== null ? adata.length : 0,
- clen = ((counter - 1) << 4) + len;
- (heap[0] = heap[1] = heap[2] = 0),
- (heap[3] = alen >>> 29),
- (heap[4] = alen >>> 21),
- (heap[5] = (alen >>> 13) & 255),
- (heap[6] = (alen >>> 5) & 255),
- (heap[7] = (alen << 3) & 255),
- (heap[8] = heap[9] = heap[10] = 0),
- (heap[11] = clen >>> 29),
- (heap[12] = (clen >>> 21) & 255),
- (heap[13] = (clen >>> 13) & 255),
- (heap[14] = (clen >>> 5) & 255),
- (heap[15] = (clen << 3) & 255);
- asm.mac(AES_asm.MAC.GCM, AES_asm.HEAP_DATA, 16);
- asm.get_iv(AES_asm.HEAP_DATA);
-
- asm.set_counter(0, 0, 0, this.gamma0);
- asm.cipher(AES_asm.ENC.CTR, AES_asm.HEAP_DATA, 16);
- result.set(heap.subarray(0, tagSize), len);
-
- this.result = result;
- this.counter = 1;
- this.pos = 0;
- this.len = 0;
-
- return this;
- }
-
- AES_GCM_Decrypt_process(data) {
- if (!is_bytes(data)) throw new TypeError("data isn't of expected type");
-
- var dpos = 0,
- dlen = data.length || 0,
- asm = this.asm,
- heap = this.heap,
- counter = this.counter,
- tagSize = this.tagSize,
- pos = this.pos,
- len = this.len,
- rpos = 0,
- rlen = len + dlen > tagSize ? (len + dlen - tagSize) & -16 : 0,
- tlen = len + dlen - rlen,
- wlen = 0;
-
- if (((counter - 1) << 4) + len + dlen > _AES_GCM_data_maxLength) throw new RangeError('counter overflow');
-
- var result = new Uint8Array(rlen);
-
- while (dlen > tlen) {
- wlen = _heap_write(heap, pos + len, data, dpos, dlen - tlen);
- len += wlen;
- dpos += wlen;
- dlen -= wlen;
-
- wlen = asm.mac(AES_asm.MAC.GCM, AES_asm.HEAP_DATA + pos, wlen);
- wlen = asm.cipher(AES_asm.DEC.CTR, AES_asm.HEAP_DATA + pos, wlen);
-
- if (wlen) result.set(heap.subarray(pos, pos + wlen), rpos);
- counter += wlen >>> 4;
- rpos += wlen;
-
- pos = 0;
- len = 0;
- }
-
- if (dlen > 0) {
- len += _heap_write(heap, 0, data, dpos, dlen);
- }
-
- this.result = result;
- this.counter = counter;
- this.pos = pos;
- this.len = len;
-
- return this;
- }
-
- AES_GCM_Decrypt_finish() {
- var asm = this.asm,
- heap = this.heap,
- tagSize = this.tagSize,
- adata = this.adata,
- counter = this.counter,
- pos = this.pos,
- len = this.len,
- rlen = len - tagSize,
- wlen = 0;
-
- if (len < tagSize) throw new IllegalStateError('authentication tag not found');
-
- var result = new Uint8Array(rlen),
- atag = new Uint8Array(heap.subarray(pos + rlen, pos + len));
-
- for (var i = rlen; i & 15; i++) heap[pos + i] = 0;
-
- wlen = asm.mac(AES_asm.MAC.GCM, AES_asm.HEAP_DATA + pos, i);
- wlen = asm.cipher(AES_asm.DEC.CTR, AES_asm.HEAP_DATA + pos, i);
- if (rlen) result.set(heap.subarray(pos, pos + rlen));
-
- var alen = adata !== null ? adata.length : 0,
- clen = ((counter - 1) << 4) + len - tagSize;
- (heap[0] = heap[1] = heap[2] = 0),
- (heap[3] = alen >>> 29),
- (heap[4] = alen >>> 21),
- (heap[5] = (alen >>> 13) & 255),
- (heap[6] = (alen >>> 5) & 255),
- (heap[7] = (alen << 3) & 255),
- (heap[8] = heap[9] = heap[10] = 0),
- (heap[11] = clen >>> 29),
- (heap[12] = (clen >>> 21) & 255),
- (heap[13] = (clen >>> 13) & 255),
- (heap[14] = (clen >>> 5) & 255),
- (heap[15] = (clen << 3) & 255);
- asm.mac(AES_asm.MAC.GCM, AES_asm.HEAP_DATA, 16);
- asm.get_iv(AES_asm.HEAP_DATA);
-
- asm.set_counter(0, 0, 0, this.gamma0);
- asm.cipher(AES_asm.ENC.CTR, AES_asm.HEAP_DATA, 16);
-
- var acheck = 0;
- for (var i = 0; i < tagSize; ++i) acheck |= atag[i] ^ heap[i];
- if (acheck) throw new SecurityError('data integrity check failed');
-
- this.result = result;
- this.counter = 1;
- this.pos = 0;
- this.len = 0;
-
- return this;
- }
-
- AES_GCM_decrypt(data) {
- var result1 = this.AES_GCM_Decrypt_process(data).result;
- var result2 = this.AES_GCM_Decrypt_finish().result;
-
- var result = new Uint8Array(result1.length + result2.length);
- if (result1.length) result.set(result1);
- if (result2.length) result.set(result2, result1.length);
- this.result = result;
-
- return this;
- }
-
- AES_GCM_encrypt(data) {
- var result1 = this.AES_GCM_Encrypt_process(data).result;
- var result2 = this.AES_GCM_Encrypt_finish().result;
-
- var result = new Uint8Array(result1.length + result2.length);
- if (result1.length) result.set(result1);
- if (result2.length) result.set(result2, result1.length);
- this.result = result;
-
- return this;
- }
-
- AES_GCM_reset(key, tagSize, nonce, adata, counter, iv) {
- this.AES_reset(key, undefined, false);
-
- var asm = this.asm;
- var heap = this.heap;
-
- asm.gcm_init();
-
- var tagSize = tagSize;
- if (tagSize !== undefined) {
- if (!is_number(tagSize)) throw new TypeError('tagSize must be a number');
-
- if (tagSize < 4 || tagSize > 16) throw new IllegalArgumentError('illegal tagSize value');
-
- this.tagSize = tagSize;
- } else {
- this.tagSize = 16;
- }
-
- if (nonce !== undefined) {
- if (!is_bytes(nonce)) {
- throw new TypeError('unexpected nonce type');
- }
-
- this.nonce = nonce;
-
- var noncelen = nonce.length || 0,
- noncebuf = new Uint8Array(16);
- if (noncelen !== 12) {
- this._gcm_mac_process(nonce);
-
- (heap[0] = heap[1] = heap[2] = heap[3] = heap[4] = heap[5] = heap[6] = heap[7] = heap[8] = heap[9] = heap[10] = 0),
- (heap[11] = noncelen >>> 29),
- (heap[12] = (noncelen >>> 21) & 255),
- (heap[13] = (noncelen >>> 13) & 255),
- (heap[14] = (noncelen >>> 5) & 255),
- (heap[15] = (noncelen << 3) & 255);
- asm.mac(AES_asm.MAC.GCM, AES_asm.HEAP_DATA, 16);
-
- asm.get_iv(AES_asm.HEAP_DATA);
- asm.set_iv();
-
- noncebuf.set(heap.subarray(0, 16));
- } else {
- noncebuf.set(nonce);
- noncebuf[15] = 1;
- }
-
- var nonceview = new DataView(noncebuf.buffer);
- this.gamma0 = nonceview.getUint32(12);
-
- asm.set_nonce(nonceview.getUint32(0), nonceview.getUint32(4), nonceview.getUint32(8), 0);
- asm.set_mask(0, 0, 0, 0xffffffff);
- } else {
- throw new Error('nonce is required');
- }
-
- if (adata !== undefined && adata !== null) {
- if (!is_bytes(adata)) {
- throw new TypeError('unexpected adata type');
- }
-
- if (adata.length > _AES_GCM_data_maxLength) throw new IllegalArgumentError('illegal adata length');
-
- if (adata.length) {
- this.adata = adata;
- this._gcm_mac_process(adata);
- } else {
- this.adata = null;
- }
- } else {
- this.adata = null;
- }
-
- if (counter !== undefined) {
- if (!is_number(counter)) throw new TypeError('counter must be a number');
-
- if (counter < 1 || counter > 0xffffffff) throw new RangeError('counter must be a positive 32-bit integer');
-
- this.counter = counter;
- asm.set_counter(0, 0, 0, (this.gamma0 + counter) | 0);
- } else {
- this.counter = 1;
- asm.set_counter(0, 0, 0, (this.gamma0 + 1) | 0);
- }
-
- if (iv !== undefined) {
- if (!is_number(iv)) throw new TypeError('iv must be a number');
-
- this.iv = iv;
-
- this.AES_set_iv(iv);
- }
-
- return this;
- }
-
- _gcm_mac_process(data) {
- var heap = this.heap,
- asm = this.asm,
- dpos = 0,
- dlen = data.length || 0,
- wlen = 0;
-
- while (dlen > 0) {
- wlen = _heap_write(heap, 0, data, dpos, dlen);
- dpos += wlen;
- dlen -= wlen;
-
- while (wlen & 15) heap[wlen++] = 0;
-
- asm.mac(AES_asm.MAC.GCM, AES_asm.HEAP_DATA, wlen);
- }
- }
-}
-
-export class AES_GCM_Encrypt extends AES_GCM {
- constructor(key, nonce, adata, tagSize, heap, asm) {
- super(key, nonce, adata, tagSize, heap, asm);
- }
- process(data) {
- return this.AES_GCM_Encrypt_process(data);
- }
- finish() {
- return this.AES_GCM_Encrypt_finish();
- }
-}
-
-export class AES_GCM_Decrypt extends AES_GCM {
- constructor(key, nonce, adata, tagSize, heap, asm) {
- super(key, nonce, adata, tagSize, heap, asm);
- }
-
- process(data) {
- return this.AES_GCM_Decrypt_process(data);
- }
- finish() {
- return this.AES_GCM_Decrypt_finish();
- }
-}
diff --git a/src/aes/ofb.ts b/src/aes/ofb.ts
new file mode 100644
index 0000000..c2a0411
--- /dev/null
+++ b/src/aes/ofb.ts
@@ -0,0 +1,25 @@
+import { AES } from './aes';
+
+export class AES_OFB extends AES {
+ static encrypt(data: Uint8Array, key: Uint8Array, iv?: Uint8Array): Uint8Array {
+ return new AES_OFB(key, iv).encrypt(data).result as Uint8Array;
+ }
+
+ static decrypt(data: Uint8Array, key: Uint8Array, iv?: Uint8Array): Uint8Array {
+ return new AES_OFB(key, iv).decrypt(data).result as Uint8Array;
+ }
+
+ constructor(key: Uint8Array, iv?: Uint8Array) {
+ super(key, iv, false, 'OFB');
+ }
+
+ encrypt(data: Uint8Array): this {
+ this.AES_Encrypt_process(data);
+ return this.AES_Encrypt_finish();
+ }
+
+ decrypt(data: Uint8Array): this {
+ this.AES_Decrypt_process(data);
+ return this.AES_Decrypt_finish();
+ }
+}
diff --git a/src/aes/ofb/exports.js b/src/aes/ofb/exports.js
deleted file mode 100644
index 4201df4..0000000
--- a/src/aes/ofb/exports.js
+++ /dev/null
@@ -1,22 +0,0 @@
-/**
- * AES-OFB exports
- */
-
-import { _AES_asm_instance, _AES_heap_instance } from '../exports';
-import { AES_OFB, AES_OFB_Crypt } from './ofb';
-
-/**
- * @param {Uint8Array} data
- * @param {Uint8Array} key
- * @param {Uint8Array} iv
- */
-function AES_OFB_crypt_bytes(data, key, iv) {
- if (data === undefined) throw new SyntaxError('data required');
- if (key === undefined) throw new SyntaxError('key required');
- return new AES_OFB(key, iv, _AES_heap_instance, _AES_asm_instance).encrypt(data).result;
-}
-
-AES_OFB.encrypt = AES_OFB_crypt_bytes;
-AES_OFB.decrypt = AES_OFB_crypt_bytes;
-
-export { AES_OFB, AES_OFB_Crypt };
diff --git a/src/aes/ofb/ofb.js b/src/aes/ofb/ofb.js
deleted file mode 100644
index 394fd30..0000000
--- a/src/aes/ofb/ofb.js
+++ /dev/null
@@ -1,65 +0,0 @@
-/**
- * Output Feedback (OFB)
- */
-
-import { AES } from '../aes';
-
-export class AES_OFB extends AES {
- /**
- * @param {Uint8Array} key
- * @param {Uint8Array} iv
- * @param {Uint8Array} [heap]
- * @param {Uint8Array} [asm]
- */
- constructor(key, iv, heap, asm) {
- super(key, iv, false, heap, asm);
-
- this.mode = 'OFB';
- this.BLOCK_SIZE = 16;
- }
-
- /**
- * @param {Uint8Array} data
- * @return {AES_OFB}
- */
- encrypt(data) {
- return this.AES_Encrypt_finish(data);
- }
-
- /**
- * @param {Uint8Array} data
- * @return {AES_OFB}
- */
- decrypt(data) {
- return this.AES_Encrypt_finish(data);
- }
-}
-
-export class AES_OFB_Crypt extends AES_OFB {
- /**
- * @param {Uint8Array} key
- * @param {Uint8Array} iv
- * @param {Uint8Array} [heap]
- * @param {Uint8Array} [asm]
- */
- constructor(key, iv, heap, asm) {
- super(key, iv, heap, asm);
- this.BLOCK_SIZE = 16;
- }
-
- /**
- * @param {Uint8Array} data
- * @return {AES_OFB_Crypt}
- */
- process(data) {
- return this.AES_Encrypt_process(data);
- }
-
- /**
- * @param {Uint8Array} data
- * @return {AES_OFB_Crypt}
- */
- finish(data) {
- return this.AES_Encrypt_finish(data);
- }
-}
diff --git a/src/bignum/bigint.asm.d.ts b/src/bignum/bigint.asm.d.ts
new file mode 100644
index 0000000..9743b67
--- /dev/null
+++ b/src/bignum/bigint.asm.d.ts
@@ -0,0 +1,51 @@
+declare interface bigintresult {
+ sreset: (n?: number) => number;
+ salloc: (n?: number) => number;
+ sfree: (n?: number) => void;
+ z: (l?: number, z?: number, A?: number) => void;
+ tst: (A?: number, lA?: number) => 0;
+ neg: (A?: number, lA?: number, R?: number, lR?: number) => number;
+ cmp: (A?: number, lA?: number, B?: number, lB?: number) => 0;
+ add: (
+ A?: number,
+ lA?: number,
+ B?: number,
+ lB?: number,
+ R?: number,
+ lR?: number,
+ ) => number;
+ sub: (
+ A?: number,
+ lA?: number,
+ B?: number,
+ lB?: number,
+ R?: number,
+ lR?: number,
+ ) => number;
+ mul: (
+ A?: number,
+ lA?: number,
+ B?: number,
+ lB?: number,
+ R?: number,
+ lR?: number,
+ ) => void;
+ sqr: (A?: number, lA?: number, R?: number) => void;
+ div: (
+ N?: number,
+ lN?: number,
+ D?: number,
+ lD?: number,
+ Q?: number,
+ ) => void;
+ mredc: (
+ A?: number,
+ lA?: number,
+ N?: number,
+ lN?: number,
+ y?: number,
+ R?: number,
+ ) => void;
+}
+
+export function bigint_asm(stdlib: any, foreign: any, buffer: ArrayBuffer): bigintresult;
diff --git a/src/bignum/bignum.js b/src/bignum/bignum.ts
similarity index 67%
rename from src/bignum/bignum.js
rename to src/bignum/bignum.ts
index 754691e..2189430 100644
--- a/src/bignum/bignum.js
+++ b/src/bignum/bignum.ts
@@ -1,23 +1,16 @@
-import { Random_getValues } from '../random/random';
-import { bigint_asm } from './bigint.asm';
-import { is_buffer, is_bytes, is_number, is_string, string_to_bytes, pow2_ceil } from '../utils';
-import { IllegalArgumentError } from '../errors';
+import { bigint_asm, bigintresult } from './bigint.asm';
+import { string_to_bytes } from '../other/utils';
+import { IllegalArgumentError } from '../other/errors';
import { BigNumber_extGCD, Number_extGCD } from './extgcd';
-
-export function is_big_number(a) {
- return a instanceof BigNumber;
-}
+import { getRandomValues } from '../other/get-random-values';
///////////////////////////////////////////////////////////////////////////////
-export var _bigint_stdlib = { Uint32Array: Uint32Array, Math: Math };
-export var _bigint_heap = new Uint32Array(0x100000);
-export var _bigint_asm;
-
-// Small primes for trail division
-const _primes = [2, 3 /* and so on, computed lazily */];
+export const _bigint_stdlib = { Uint32Array: Uint32Array, Math: Math };
+export const _bigint_heap = new Uint32Array(0x100000);
+export let _bigint_asm: bigintresult;
-function _half_imul(a, b) {
+function _half_imul(a: number, b: number) {
return (a * b) | 0;
}
@@ -34,20 +27,20 @@ if (_bigint_stdlib.Math.imul === undefined) {
const _BigNumber_ZERO_limbs = new Uint32Array(0);
export class BigNumber {
- /**
- * @param {string} str
- * @return {BigNumber}
- */
- static fromString(str) {
+ public limbs!: Uint32Array;
+ public bitLength!: number;
+ public sign!: number;
+
+ static extGCD = BigNumber_extGCD;
+ static ZERO = BigNumber.fromNumber(0);
+ static ONE = BigNumber.fromNumber(1);
+
+ static fromString(str: string): BigNumber {
const bytes = string_to_bytes(str);
return new BigNumber(bytes);
}
- /**
- * @param {number} num
- * @return {BigNumber}
- */
- static fromNumber(num) {
+ static fromNumber(num: number): BigNumber {
let limbs = _BigNumber_ZERO_limbs;
let bitlen = 0;
let sign = 0;
@@ -71,19 +64,11 @@ export class BigNumber {
return BigNumber.fromConfig({ limbs, bitLength: bitlen, sign });
}
- /**
- * @param {ArrayBuffer} buffer
- * @return {BigNumber}
- */
- static fromArrayBuffer(buffer) {
+ static fromArrayBuffer(buffer: ArrayBuffer): BigNumber {
return new BigNumber(new Uint8Array(buffer));
}
- /**
- * @param {{ limbs: Uint32Array, bitLength: number, sign: number }} obj
- * @return {BigNumber}
- */
- static fromConfig(obj) {
+ static fromConfig(obj: { limbs: Uint32Array; bitLength: number; sign: number }): BigNumber {
const bn = new BigNumber();
bn.limbs = new Uint32Array(obj.limbs);
bn.bitLength = obj.bitLength;
@@ -91,22 +76,18 @@ export class BigNumber {
return bn;
}
- /**
- * @param {Uint8Array} [num]
- * @return {BigNumber}
- */
- constructor(num) {
+ constructor(num?: Uint8Array) {
let limbs = _BigNumber_ZERO_limbs;
let bitlen = 0;
let sign = 0;
if (num === undefined) {
// do nothing
- } else if (is_bytes(num)) {
+ } else {
for (var i = 0; !num[i]; i++);
bitlen = (num.length - i) * 8;
- if (!bitlen) return BigNumber_ZERO;
+ if (!bitlen) return BigNumber.ZERO;
limbs = new Uint32Array((bitlen + 31) >> 5);
for (var j = num.length - 4; j >= i; j -= 4) {
@@ -121,8 +102,6 @@ export class BigNumber {
}
sign = 1;
- } else {
- throw new TypeError('number is of unexpected type');
}
this.limbs = limbs;
@@ -130,11 +109,7 @@ export class BigNumber {
this.sign = sign;
}
- /**
- * @param {number} radix
- * @return {string}
- */
- toString(radix) {
+ toString(radix: number): string {
radix = radix || 16;
const limbs = this.limbs;
@@ -161,10 +136,7 @@ export class BigNumber {
return str;
}
- /**
- * @return {Uint8Array}
- */
- toBytes() {
+ toBytes(): Uint8Array {
const bitlen = this.bitLength;
const limbs = this.limbs;
@@ -182,10 +154,8 @@ export class BigNumber {
/**
* Downgrade to Number
- *
- * @return {number}
*/
- valueOf() {
+ valueOf(): number {
const limbs = this.limbs;
const bits = this.bitLength;
const sign = this.sign;
@@ -216,11 +186,7 @@ export class BigNumber {
);
}
- /**
- * @param {number} b
- * @return {BigNumber}
- */
- clamp(b) {
+ clamp(b: number): BigNumber {
const limbs = this.limbs;
const bitlen = this.bitLength;
@@ -241,22 +207,13 @@ export class BigNumber {
return clamped;
}
- /**
- * @param {number} f
- * @param {number} [b]
- * @return {BigNumber}
- */
- slice(f, b) {
- if (!is_number(f)) throw new TypeError('TODO');
-
- if (b !== undefined && !is_number(b)) throw new TypeError('TODO');
-
+ slice(f: number, b?: number): BigNumber {
const limbs = this.limbs;
const bitlen = this.bitLength;
if (f < 0) throw new RangeError('TODO');
- if (f >= bitlen) return BigNumber_ZERO;
+ if (f >= bitlen) return BigNumber.ZERO;
if (b === undefined || b > bitlen - f) b = bitlen - f;
@@ -288,10 +245,7 @@ export class BigNumber {
return sliced;
}
- /**
- * @return {BigNumber}
- */
- negate() {
+ negate(): BigNumber {
const negative = new BigNumber();
negative.limbs = this.limbs;
@@ -301,11 +255,7 @@ export class BigNumber {
return negative;
}
- /**
- * @param {BigNumber} that
- * @return {number}
- */
- compare(that) {
+ compare(that: BigNumber): number {
var alimbs = this.limbs,
alimbcnt = alimbs.length,
blimbs = that.limbs,
@@ -323,11 +273,7 @@ export class BigNumber {
return z * this.sign;
}
- /**
- * @param {BigNumber} that
- * @return {BigNumber}
- */
- add(that) {
+ add(that: BigNumber): BigNumber {
if (!this.sign) return that;
if (!that.sign) return this;
@@ -373,7 +319,7 @@ export class BigNumber {
if (rof) _bigint_asm.neg(pR, rlimbcnt << 2, pR, rlimbcnt << 2);
- if (_bigint_asm.tst(pR, rlimbcnt << 2) === 0) return BigNumber_ZERO;
+ if (_bigint_asm.tst(pR, rlimbcnt << 2) === 0) return BigNumber.ZERO;
result.limbs = new Uint32Array(_bigint_heap.subarray(pR >> 2, (pR >> 2) + rlimbcnt));
result.bitLength = rbitlen;
@@ -382,19 +328,12 @@ export class BigNumber {
return result;
}
- /**
- * @param {BigNumber} that
- * @return {BigNumber}
- */
- subtract(that) {
+ subtract(that: BigNumber): BigNumber {
return this.add(that.negate());
}
- /**
- * @return {BigNumber}
- */
- square() {
- if (!this.sign) return BigNumber_ZERO;
+ square(): BigNumber {
+ if (!this.sign) return BigNumber.ZERO;
var abitlen = this.bitLength,
alimbs = this.limbs,
@@ -424,11 +363,7 @@ export class BigNumber {
return result;
}
- /**
- * @param {BigNumber} that
- * @return {{quotient: BigNumber, remainder: BigNumber}}
- */
- divide(that) {
+ divide(that: BigNumber): { quotient: BigNumber; remainder: BigNumber } {
var abitlen = this.bitLength,
alimbs = this.limbs,
alimbcnt = alimbs.length,
@@ -437,8 +372,8 @@ export class BigNumber {
blimbcnt = blimbs.length,
qlimbcnt,
rlimbcnt,
- quotient = BigNumber_ZERO,
- remainder = BigNumber_ZERO;
+ quotient = BigNumber.ZERO,
+ remainder = BigNumber.ZERO;
_bigint_asm.sreset();
@@ -475,12 +410,8 @@ export class BigNumber {
};
}
- /**
- * @param {BigNumber} that
- * @return {BigNumber}
- */
- multiply(that) {
- if (!this.sign || !that.sign) return BigNumber_ZERO;
+ multiply(that: BigNumber): BigNumber {
+ if (!this.sign || !that.sign) return BigNumber.ZERO;
var abitlen = this.bitLength,
alimbs = this.limbs,
@@ -515,12 +446,7 @@ export class BigNumber {
return result;
}
- /**
- * @param {number} rounds
- * @return {boolean}
- * @private
- */
- isMillerRabinProbablePrime(rounds) {
+ public isMillerRabinProbablePrime(rounds: number): boolean {
var t = BigNumber.fromConfig(this),
s = 0;
t.limbs[0] -= 1;
@@ -529,24 +455,24 @@ export class BigNumber {
t = t.slice(s);
var m = new Modulus(this),
- m1 = this.subtract(BigNumber_ONE),
+ m1 = this.subtract(BigNumber.ONE),
a = BigNumber.fromConfig(this),
l = this.limbs.length - 1;
while (a.limbs[l] === 0) l--;
while (--rounds >= 0) {
- Random_getValues(a.limbs);
+ getRandomValues(a.limbs);
if (a.limbs[0] < 2) a.limbs[0] += 2;
while (a.compare(m1) >= 0) a.limbs[l] >>>= 1;
var x = m.power(a, t);
- if (x.compare(BigNumber_ONE) === 0) continue;
+ if (x.compare(BigNumber.ONE) === 0) continue;
if (x.compare(m1) === 0) continue;
var c = s;
while (--c > 0) {
x = x.square().divide(m).remainder;
- if (x.compare(BigNumber_ONE) === 0) return false;
+ if (x.compare(BigNumber.ONE) === 0) return false;
if (x.compare(m1) === 0) break;
}
@@ -556,13 +482,7 @@ export class BigNumber {
return true;
}
- /**
- * @param {number} [paranoia]
- * @return {boolean}
- */
- isProbablePrime(paranoia) {
- paranoia = paranoia || 80;
-
+ isProbablePrime(paranoia: number = 80): boolean {
var limbs = this.limbs;
var i = 0;
@@ -608,95 +528,14 @@ export class BigNumber {
}
}
-export const BigNumber_ZERO = BigNumber.fromNumber(0);
-export const BigNumber_ONE = BigNumber.fromNumber(1);
-
-/**
- * Returns an array populated with first n primes.
- *
- * @param {number} n
- * @return {number[]}
- * @private
- */
-function _small_primes(n) {
- if (_primes.length >= n) return _primes.slice(0, n);
-
- for (let p = _primes[_primes.length - 1] + 2; _primes.length < n; p += 2) {
- for (var i = 0, d = _primes[i]; d * d <= p; d = _primes[++i]) {
- if (p % d == 0) break;
- }
- if (d * d > p) _primes.push(p);
- }
-
- return _primes;
-}
-
-/**
- * Returns strong pseudoprime of a specified bit length
- *
- * @param {number} bitlen
- * @param {function(BigNumber): boolean} filter
- * @return {BigNumber}
- */
-export function randomProbablePrime(bitlen, filter) {
- let limbcnt = (bitlen + 31) >> 5;
- const prime = BigNumber.fromConfig({ sign: 1, bitLength: bitlen, limbs: new Uint32Array(limbcnt) });
- const limbs = prime.limbs;
-
- // Number of small divisors to try that minimizes the total cost of the trial division
- // along with the first round of Miller-Rabin test for a certain bit length.
- let k = 10000;
- if (bitlen <= 512) k = 2200;
- if (bitlen <= 256) k = 600;
-
- let divisors = _small_primes(k);
- const remainders = new Uint32Array(k);
-
- // Number of Miller-Rabin iterations for an error rate of less than 2^-80
- // Damgaard, Landrock, Pomerance: Average case error estimates for the strong probable prime test.
- const s = (bitlen * Math.LN2) | 0;
- let r = 27;
- if (bitlen >= 250) r = 12;
- if (bitlen >= 450) r = 6;
- if (bitlen >= 850) r = 3;
- if (bitlen >= 1300) r = 2;
-
- while (true) {
- // populate `prime` with random bits, clamp to the appropriate bit length
- Random_getValues(limbs);
- limbs[0] |= 1;
- limbs[limbcnt - 1] |= 1 << ((bitlen - 1) & 31);
- if (bitlen & 31) limbs[limbcnt - 1] &= pow2_ceil((bitlen + 1) & 31) - 1;
-
- // remainders from division to small primes
- remainders[0] = 1;
- for (let i = 1; i < k; i++) {
- remainders[i] = prime.divide(BigNumber.fromNumber(divisors[i])).remainder.valueOf();
- }
-
- // try no more than `s` subsequent candidates
- seek: for (let j = 0; j < s; j += 2, limbs[0] += 2) {
- // check for small factors
- for (let i = 1; i < k; i++) {
- if ((remainders[i] + j) % divisors[i] === 0) continue seek;
- }
-
- // additional check just before the heavy lifting
- if (typeof filter === 'function' && !filter(prime)) continue;
-
- // proceed to Miller-Rabin test
- if (prime.isMillerRabinProbablePrime(r)) return prime;
- }
- }
-}
-
export class Modulus extends BigNumber {
- /**
- * Modulus
- *
- * @param {BigNumber} number
- */
- constructor(number) {
+ // @ts-ignore
+ private comodulus!: BigNumber;
+ private comodulusRemainder!: BigNumber;
+ private comodulusRemainderSquare!: BigNumber;
+ private coefficient!: number;
+
+ constructor(number: BigNumber) {
super();
this.limbs = number.limbs;
this.bitLength = number.bitLength;
@@ -706,7 +545,7 @@ export class Modulus extends BigNumber {
if (this.bitLength <= 32) return;
- let comodulus;
+ let comodulus: BigNumber;
if (this.limbs[0] & 1) {
const bitlen = ((this.bitLength + 31) & -32) + 1;
@@ -737,12 +576,8 @@ export class Modulus extends BigNumber {
/**
* Modular reduction
- *
- * @param {BigNumber} a
- * @return {BigNumber}
- * @constructor
*/
- reduce(a) {
+ reduce(a: BigNumber): BigNumber {
if (a.bitLength <= 32 && this.bitLength <= 32) return BigNumber.fromNumber(a.valueOf() % this.valueOf());
if (a.compare(this) < 0) return a;
@@ -752,16 +587,12 @@ export class Modulus extends BigNumber {
/**
* Modular inverse
- *
- * @param {BigNumber} a
- * @return {BigNumber}
- * @constructor
*/
- inverse(a) {
+ inverse(a: BigNumber): BigNumber {
a = this.reduce(a);
const r = BigNumber_extGCD(this, a);
- if (r.gcd.valueOf() !== 1) return null;
+ if (r.gcd.valueOf() !== 1) throw new Error('GCD is not 1');
if (r.y.sign < 0) return r.y.add(this).clamp(this.bitLength);
@@ -770,13 +601,8 @@ export class Modulus extends BigNumber {
/**
* Modular exponentiation
- *
- * @param {BigNumber} g
- * @param {BigNumber} e
- * @return {BigNumber}
- * @constructor
*/
- power(g, e) {
+ power(g: BigNumber, e: BigNumber): BigNumber {
// count exponent set bits
let c = 0;
for (let i = 0; i < e.limbs.length; i++) {
@@ -798,15 +624,15 @@ export class Modulus extends BigNumber {
if (c <= 1 << (k - 1)) k = 1;
// montgomerize base
- g = _Montgomery_reduce(this.reduce(g).multiply(this.comodulusRemainderSquare), this);
+ g = Modulus._Montgomery_reduce(this.reduce(g).multiply(this.comodulusRemainderSquare), this);
// precompute odd powers
- const g2 = _Montgomery_reduce(g.square(), this),
+ const g2 = Modulus._Montgomery_reduce(g.square(), this),
gn = new Array(1 << (k - 1));
gn[0] = g;
- gn[1] = _Montgomery_reduce(g.multiply(g2), this);
+ gn[1] = Modulus._Montgomery_reduce(g.multiply(g2), this);
for (let i = 2; i < 1 << (k - 1); i++) {
- gn[i] = _Montgomery_reduce(gn[i - 1].multiply(g2), this);
+ gn[i] = Modulus._Montgomery_reduce(gn[i - 1].multiply(g2), this);
}
// perform exponentiation
@@ -825,52 +651,46 @@ export class Modulus extends BigNumber {
var m = gn[n >>> 1];
while (n) {
n >>>= 1;
- if (r !== u) r = _Montgomery_reduce(r.square(), this);
+ if (r !== u) r = Modulus._Montgomery_reduce(r.square(), this);
}
- r = r !== u ? _Montgomery_reduce(r.multiply(m), this) : m;
+ r = r !== u ? Modulus._Montgomery_reduce(r.multiply(m), this) : m;
(t <<= l), (j -= l);
} else {
- if (r !== u) r = _Montgomery_reduce(r.square(), this);
+ if (r !== u) r = Modulus._Montgomery_reduce(r.square(), this);
(t <<= 1), j--;
}
}
}
// de-montgomerize result
- return _Montgomery_reduce(r, this);
+ return Modulus._Montgomery_reduce(r, this);
}
-}
-/**
- * @param {BigNumber} a
- * @param {Modulus} n
- * @return {BigNumber}
- * @private
- */
-function _Montgomery_reduce(a, n) {
- const alimbs = a.limbs;
- const alimbcnt = alimbs.length;
- const nlimbs = n.limbs;
- const nlimbcnt = nlimbs.length;
- const y = n.coefficient;
+ static _Montgomery_reduce(a: BigNumber, n: Modulus): BigNumber {
+ const alimbs = a.limbs;
+ const alimbcnt = alimbs.length;
+ const nlimbs = n.limbs;
+ const nlimbcnt = nlimbs.length;
+ const y = n.coefficient;
- _bigint_asm.sreset();
+ _bigint_asm.sreset();
- const pA = _bigint_asm.salloc(alimbcnt << 2),
- pN = _bigint_asm.salloc(nlimbcnt << 2),
- pR = _bigint_asm.salloc(nlimbcnt << 2);
+ const pA = _bigint_asm.salloc(alimbcnt << 2),
+ pN = _bigint_asm.salloc(nlimbcnt << 2),
+ pR = _bigint_asm.salloc(nlimbcnt << 2);
- _bigint_asm.z(pR - pA + (nlimbcnt << 2), 0, pA);
+ _bigint_asm.z(pR - pA + (nlimbcnt << 2), 0, pA);
- _bigint_heap.set(alimbs, pA >> 2);
- _bigint_heap.set(nlimbs, pN >> 2);
+ _bigint_heap.set(alimbs, pA >> 2);
+ _bigint_heap.set(nlimbs, pN >> 2);
- _bigint_asm.mredc(pA, alimbcnt << 2, pN, nlimbcnt << 2, y, pR);
+ _bigint_asm.mredc(pA, alimbcnt << 2, pN, nlimbcnt << 2, y, pR);
- const result = new BigNumber();
- result.limbs = new Uint32Array(_bigint_heap.subarray(pR >> 2, (pR >> 2) + nlimbcnt));
- result.bitLength = n.bitLength;
- result.sign = 1;
+ const result = new BigNumber();
+ result.limbs = new Uint32Array(_bigint_heap.subarray(pR >> 2, (pR >> 2) + nlimbcnt));
+ result.bitLength = n.bitLength;
+ result.sign = 1;
- return result;
+ return result;
+ }
}
diff --git a/src/bignum/exports.js b/src/bignum/exports.js
deleted file mode 100644
index 87419c1..0000000
--- a/src/bignum/exports.js
+++ /dev/null
@@ -1,9 +0,0 @@
-import { BigNumber, BigNumber_ONE, BigNumber_ZERO, Modulus } from './bignum';
-import { BigNumber_extGCD } from './extgcd';
-
-BigNumber.ZERO = BigNumber_ZERO;
-BigNumber.ONE = BigNumber_ONE;
-
-BigNumber.extGCD = BigNumber_extGCD;
-
-export { BigNumber, Modulus };
diff --git a/src/bignum/extgcd.js b/src/bignum/extgcd.ts
similarity index 62%
rename from src/bignum/extgcd.js
rename to src/bignum/extgcd.ts
index 995a3f4..1f54f8a 100644
--- a/src/bignum/extgcd.js
+++ b/src/bignum/extgcd.ts
@@ -1,12 +1,6 @@
-import { BigNumber, BigNumber_ONE, BigNumber_ZERO, is_big_number } from './bignum';
-
-/**
- * @param {number} a
- * @param {number} b
- * @return {{gcd: number, x: number, y: number}}
- * @constructor
- */
-export function Number_extGCD(a, b) {
+import { BigNumber } from './bignum';
+
+export function Number_extGCD(a: number, b: number): { gcd: number; x: number; y: number } {
var sa = a < 0 ? -1 : 1,
sb = b < 0 ? -1 : 1,
xi = 1,
@@ -54,45 +48,35 @@ export function Number_extGCD(a, b) {
};
}
-/**
- * @param a
- * @param b
- * @return {{gcd: BigNumber, x: BigNumber, y: BigNumber}}
- * @constructor
- */
-export function BigNumber_extGCD(a, b) {
- if (!is_big_number(a)) a = new BigNumber(a);
-
- if (!is_big_number(b)) b = new BigNumber(b);
-
- var sa = a.sign,
- sb = b.sign;
+export function BigNumber_extGCD(a: BigNumber, b: BigNumber): { gcd: BigNumber; x: BigNumber; y: BigNumber } {
+ let sa = a.sign;
+ let sb = b.sign;
if (sa < 0) a = a.negate();
if (sb < 0) b = b.negate();
- var a_cmp_b = a.compare(b);
+ const a_cmp_b = a.compare(b);
if (a_cmp_b < 0) {
- var t = a;
+ let t = a;
(a = b), (b = t);
- t = sa;
+ let t2 = sa;
sa = sb;
- sb = t;
+ sb = t2;
}
- var xi = BigNumber_ONE,
- xj = BigNumber_ZERO,
+ var xi = BigNumber.ONE,
+ xj = BigNumber.ZERO,
lx = b.bitLength,
- yi = BigNumber_ZERO,
- yj = BigNumber_ONE,
+ yi = BigNumber.ZERO,
+ yj = BigNumber.ONE,
ly = a.bitLength,
z,
r,
q;
z = a.divide(b);
- while ((r = z.remainder) !== BigNumber_ZERO) {
+ while ((r = z.remainder) !== BigNumber.ZERO) {
q = z.quotient;
(z = xi.subtract(q.multiply(xj).clamp(lx)).clamp(lx)), (xi = xj), (xj = z);
@@ -108,7 +92,7 @@ export function BigNumber_extGCD(a, b) {
if (sb < 0) yj = yj.negate();
if (a_cmp_b < 0) {
- var t = xj;
+ let t = xj;
(xj = yj), (yj = t);
}
diff --git a/src/entry-default.js b/src/entry-default.js
deleted file mode 100644
index a9c4f5c..0000000
--- a/src/entry-default.js
+++ /dev/null
@@ -1,16 +0,0 @@
-export * from './exportedUtils';
-
-export * from './errors';
-export * from './aes/cbc/exports';
-export * from './aes/gcm/exports';
-export * from './hash/sha1/exports';
-export * from './hash/sha256/exports';
-export * from './hmac/exports-hmac-sha1';
-export * from './hmac/exports-hmac-sha256';
-export * from './pbkdf2/exports-pbkdf2-hmac-sha1';
-export * from './pbkdf2/exports-pbkdf2-hmac-sha256';
-export * from './random/random';
-export * from './bignum/exports';
-export * from './rsa/pkcs1';
-export * from './random/exports';
-export * from './origin';
diff --git a/src/entry-default.ts b/src/entry-default.ts
new file mode 100644
index 0000000..216f411
--- /dev/null
+++ b/src/entry-default.ts
@@ -0,0 +1,13 @@
+export * from './other/exportedUtils';
+
+export * from './other/errors';
+export * from './aes/cbc';
+export * from './aes/gcm';
+export * from './hash/sha1/sha1';
+export * from './hash/sha256/sha256';
+export * from './hmac/hmac-sha1';
+export * from './hmac/hmac-sha256';
+export * from './pbkdf2/pbkdf2-hmac-sha1';
+export * from './pbkdf2/pbkdf2-hmac-sha256';
+export * from './bignum/bignum';
+export * from './rsa/pkcs1';
diff --git a/src/entry-export_all.js b/src/entry-export_all.js
deleted file mode 100644
index 55f9b1c..0000000
--- a/src/entry-export_all.js
+++ /dev/null
@@ -1,31 +0,0 @@
-export * from './exportedUtils';
-
-export * from './errors';
-export * from './aes/cbc/exports';
-export * from './aes/ccm/exports';
-export * from './aes/cfb/exports';
-export * from './aes/cmac/exports';
-export * from './aes/ctr/exports';
-export * from './aes/ecb/exports';
-export * from './aes/gcm/exports';
-export * from './aes/ofb/exports';
-export * from './bignum/exports';
-export * from './hash/sha1/exports';
-export * from './hash/sha256/exports';
-export * from './hash/sha512/exports';
-export * from './hmac/exports-hmac-sha1';
-export * from './hmac/exports-hmac-sha256';
-export * from './hmac/exports-hmac-sha512';
-export * from './pbkdf2/exports-pbkdf2-hmac-sha1';
-export * from './pbkdf2/exports-pbkdf2-hmac-sha256';
-export * from './pbkdf2/exports-pbkdf2-hmac-sha512';
-export * from './random/exports';
-export * from './rsa/exports-keygen';
-export * from './rsa/exports-oaep-sha1';
-export * from './rsa/exports-oaep-sha256';
-export * from './rsa/exports-oaep-sha512';
-export * from './rsa/exports-pss-sha1';
-export * from './rsa/exports-pss-sha256';
-export * from './rsa/exports-pss-sha512';
-export * from './rsa/exports-raw';
-export * from './origin';
diff --git a/src/entry-export_all.ts b/src/entry-export_all.ts
new file mode 100644
index 0000000..c352d00
--- /dev/null
+++ b/src/entry-export_all.ts
@@ -0,0 +1,29 @@
+export {
+ string_to_bytes,
+ hex_to_bytes,
+ base64_to_bytes,
+ bytes_to_string,
+ bytes_to_hex,
+ bytes_to_base64,
+} from './other/exportedUtils';
+export { IllegalStateError, IllegalArgumentError, SecurityError } from './other/errors';
+export { AES_CBC } from './aes/cbc';
+export { AES_CCM } from './aes/ccm';
+export { AES_CFB } from './aes/cfb';
+export { AES_CMAC } from './aes/cmac';
+export { AES_CTR } from './aes/ctr';
+export { AES_ECB } from './aes/ecb';
+export { AES_GCM } from './aes/gcm';
+export { AES_OFB } from './aes/ofb';
+export { BigNumber, Modulus } from './bignum/bignum';
+export { Sha1 } from './hash/sha1/sha1';
+export { Sha256 } from './hash/sha256/sha256';
+export { Sha512 } from './hash/sha512/sha512';
+export { HmacSha1 } from './hmac/hmac-sha1';
+export { HmacSha256 } from './hmac/hmac-sha256';
+export { HmacSha512 } from './hmac/hmac-sha512';
+export { Pbkdf2HmacSha1 } from './pbkdf2/pbkdf2-hmac-sha1';
+export { Pbkdf2HmacSha256 } from './pbkdf2/pbkdf2-hmac-sha256';
+export { Pbkdf2HmacSha512 } from './pbkdf2/pbkdf2-hmac-sha512';
+export { RSA_OAEP, RSA_PKCS1_v1_5, RSA_PSS } from './rsa/pkcs1';
+export { RSA } from './rsa/rsa';
diff --git a/src/errors.js b/src/errors.js
deleted file mode 100644
index d2a8171..0000000
--- a/src/errors.js
+++ /dev/null
@@ -1,17 +0,0 @@
-export function IllegalStateError() {
- var err = Error.apply(this, arguments);
- (this.message = err.message), (this.stack = err.stack);
-}
-IllegalStateError.prototype = Object.create(Error.prototype, { name: { value: 'IllegalStateError' } });
-
-export function IllegalArgumentError() {
- var err = Error.apply(this, arguments);
- (this.message = err.message), (this.stack = err.stack);
-}
-IllegalArgumentError.prototype = Object.create(Error.prototype, { name: { value: 'IllegalArgumentError' } });
-
-export function SecurityError() {
- var err = Error.apply(this, arguments);
- (this.message = err.message), (this.stack = err.stack);
-}
-SecurityError.prototype = Object.create(Error.prototype, { name: { value: 'SecurityError' } });
diff --git a/src/hash/hash.js b/src/hash/hash.js
deleted file mode 100644
index f55e8ff..0000000
--- a/src/hash/hash.js
+++ /dev/null
@@ -1,63 +0,0 @@
-import { _heap_write, is_buffer, is_bytes, is_string, string_to_bytes } from '../utils';
-import { IllegalStateError } from '../errors';
-
-export function hash_reset() {
- this.result = null;
- this.pos = 0;
- this.len = 0;
-
- this.asm.reset();
-
- return this;
-}
-
-export function hash_process(data) {
- if (this.result !== null) throw new IllegalStateError('state must be reset before processing new data');
-
- if (is_string(data)) data = string_to_bytes(data);
-
- if (is_buffer(data)) data = new Uint8Array(data);
-
- if (!is_bytes(data)) throw new TypeError("data isn't of expected type");
-
- var asm = this.asm,
- heap = this.heap,
- hpos = this.pos,
- hlen = this.len,
- dpos = 0,
- dlen = data.length,
- wlen = 0;
-
- while (dlen > 0) {
- wlen = _heap_write(heap, hpos + hlen, data, dpos, dlen);
- hlen += wlen;
- dpos += wlen;
- dlen -= wlen;
-
- wlen = asm.process(hpos, hlen);
-
- hpos += wlen;
- hlen -= wlen;
-
- if (!hlen) hpos = 0;
- }
-
- this.pos = hpos;
- this.len = hlen;
-
- return this;
-}
-
-export function hash_finish() {
- if (this.result !== null) throw new IllegalStateError('state must be reset before processing new data');
-
- this.asm.finish(this.pos, this.len, 0);
-
- this.result = new Uint8Array(this.HASH_SIZE);
- this.result.set(this.heap.subarray(0, this.HASH_SIZE));
-
- this.pos = 0;
- this.len = 0;
-
- return this;
-}
diff --git a/src/hash/hash.ts b/src/hash/hash.ts
new file mode 100644
index 0000000..52f112e
--- /dev/null
+++ b/src/hash/hash.ts
@@ -0,0 +1,70 @@
+import { _heap_write } from '../other/utils';
+import { IllegalStateError } from '../other/errors';
+import { sha1result } from './sha1/sha1.asm';
+import { sha256result } from './sha256/sha256.asm';
+import { sha512result } from './sha512/sha512.asm';
+
+export abstract class Hash {
+ public result!: Uint8Array | null;
+ public pos: number = 0;
+ public len: number = 0;
+ public asm!: T;
+ public heap!: Uint8Array;
+ public BLOCK_SIZE!: number;
+ public HASH_SIZE!: number;
+
+ reset() {
+ this.result = null;
+ this.pos = 0;
+ this.len = 0;
+
+ this.asm.reset();
+
+ return this;
+ }
+
+ process(data: Uint8Array) {
+ if (this.result !== null) throw new IllegalStateError('state must be reset before processing new data');
+
+ let asm = this.asm;
+ let heap = this.heap;
+ let hpos = this.pos;
+ let hlen = this.len;
+ let dpos = 0;
+ let dlen = data.length;
+ let wlen = 0;
+
+ while (dlen > 0) {
+ wlen = _heap_write(heap, hpos + hlen, data, dpos, dlen);
+ hlen += wlen;
+ dpos += wlen;
+ dlen -= wlen;
+
+ wlen = asm.process(hpos, hlen);
+
+ hpos += wlen;
+ hlen -= wlen;
+
+ if (!hlen) hpos = 0;
+ }
+
+ this.pos = hpos;
+ this.len = hlen;
+
+ return this;
+ }
+
+ finish() {
+ if (this.result !== null) throw new IllegalStateError('state must be reset before processing new data');
+
+ this.asm.finish(this.pos, this.len, 0);
+
+ this.result = new Uint8Array(this.HASH_SIZE);
+ this.result.set(this.heap.subarray(0, this.HASH_SIZE));
+
+ this.pos = 0;
+ this.len = 0;
+
+ return this;
+ }
+}
diff --git a/src/hash/sha1/exports.js b/src/hash/sha1/exports.js
deleted file mode 100644
index 3b49d53..0000000
--- a/src/hash/sha1/exports.js
+++ /dev/null
@@ -1,30 +0,0 @@
-/**
- * SHA1 exports
- */
-
-import { get_sha1_instance, sha1_constructor } from './sha1';
-import { bytes_to_base64, bytes_to_hex } from '../../utils';
-
-function sha1_bytes(data) {
- if (data === undefined) throw new SyntaxError('data required');
- return get_sha1_instance()
- .reset()
- .process(data)
- .finish().result;
-}
-
-function sha1_hex(data) {
- var result = sha1_bytes(data);
- return bytes_to_hex(result);
-}
-
-function sha1_base64(data) {
- var result = sha1_bytes(data);
- return bytes_to_base64(result);
-}
-
-export var SHA1 = sha1_constructor;
-
-SHA1.bytes = sha1_bytes;
-SHA1.hex = sha1_hex;
-SHA1.base64 = sha1_base64;
diff --git a/src/hash/sha1/sha1.asm.d.ts b/src/hash/sha1/sha1.asm.d.ts
new file mode 100644
index 0000000..0ba8dc6
--- /dev/null
+++ b/src/hash/sha1/sha1.asm.d.ts
@@ -0,0 +1,62 @@
+declare interface sha1result {
+ // SHA1
+ reset: () => void;
+ init: (h0: number, h1: number, h2: number, h3: number, h4: number, total0: number, total1: number) => void;
+
+ /**
+ * @param offset - multiple of 64
+ * @param length
+ * @returns hashed
+ */
+ process: (offset: number, length: number) => number;
+
+ /**
+ * @param offset - multiple of 64
+ * @param length
+ * @param output - multiple of 32
+ * @returns hashed
+ */
+ finish: (offset: number, length: number, output: number) => number;
+
+ // HMAC-SHA;
+ hmac_reset: () => void;
+ hmac_init: (
+ p0: number,
+ p1: number,
+ p2: number,
+ p3: number,
+ p4: number,
+ p5: number,
+ p6: number,
+ p7: number,
+ p8: number,
+ p9: number,
+ p10: number,
+ p11: number,
+ p12: number,
+ p13: number,
+ p14: number,
+ p15: number,
+ ) => void;
+
+ /**
+ * @param offset - multiple of 64
+ * @param length
+ * @param output - multiple of 32
+ * @returns hashed
+ */
+ hmac_finish: (offset: number, length: number, output: number) => number;
+
+ // ;
+ /**
+ * PBKDF2-HMAC-SHA
+ * @param offset - multiple of 64
+ * @param length
+ * @param block
+ * @param count
+ * @param output - multiple of 32
+ */
+ pbkdf2_generate_block: (offset: number, length: number, block: number, count: number, output: number) => 0 | -1;
+}
+
+export function sha1_asm(stdlib: any, foreign: any, buffer: ArrayBuffer): sha1result;
diff --git a/src/hash/sha1/sha1.asm.js b/src/hash/sha1/sha1.asm.js
index 0653916..62ff31a 100644
--- a/src/hash/sha1/sha1.asm.js
+++ b/src/hash/sha1/sha1.asm.js
@@ -849,18 +849,18 @@ export function sha1_asm ( stdlib, foreign, buffer ) {
}
return {
- // SHA1
- reset: reset,
- init: init,
- process: process,
- finish: finish,
-
- // HMAC-SHA1
- hmac_reset: hmac_reset,
- hmac_init: hmac_init,
- hmac_finish: hmac_finish,
-
- // PBKDF2-HMAC-SHA1
- pbkdf2_generate_block: pbkdf2_generate_block
+ // SHA1
+ reset: reset,
+ init: init,
+ process: process,
+ finish: finish,
+
+ // HMAC-SHA1
+ hmac_reset: hmac_reset,
+ hmac_init: hmac_init,
+ hmac_finish: hmac_finish,
+
+ // PBKDF2-HMAC-SHA1
+ pbkdf2_generate_block: pbkdf2_generate_block
}
}
diff --git a/src/hash/sha1/sha1.js b/src/hash/sha1/sha1.js
deleted file mode 100644
index b4c3bb1..0000000
--- a/src/hash/sha1/sha1.js
+++ /dev/null
@@ -1,34 +0,0 @@
-import { sha1_asm } from './sha1.asm';
-import { hash_finish, hash_process, hash_reset } from '../hash';
-import { _heap_init } from '../../utils';
-
-export var _sha1_block_size = 64;
-export var _sha1_hash_size = 20;
-
-export function sha1_constructor(options) {
- options = options || {};
-
- this.heap = _heap_init(Uint8Array, options.heap);
- this.asm = options.asm || sha1_asm({ Uint8Array: Uint8Array }, null, this.heap.buffer);
-
- this.BLOCK_SIZE = _sha1_block_size;
- this.HASH_SIZE = _sha1_hash_size;
-
- this.reset();
-}
-
-sha1_constructor.BLOCK_SIZE = _sha1_block_size;
-sha1_constructor.NAME = 'sha1';
-
-sha1_constructor.HASH_SIZE = _sha1_hash_size;
-var sha1_prototype = sha1_constructor.prototype;
-sha1_prototype.reset = hash_reset;
-sha1_prototype.process = hash_process;
-sha1_prototype.finish = hash_finish;
-
-var sha1_instance = null;
-
-export function get_sha1_instance() {
- if (sha1_instance === null) sha1_instance = new sha1_constructor({ heapSize: 0x100000 });
- return sha1_instance;
-}
diff --git a/src/hash/sha1/sha1.ts b/src/hash/sha1/sha1.ts
new file mode 100644
index 0000000..55d1292
--- /dev/null
+++ b/src/hash/sha1/sha1.ts
@@ -0,0 +1,22 @@
+import { sha1_asm, sha1result } from './sha1.asm';
+import { Hash } from '../hash';
+import { _heap_init } from '../../other/utils';
+
+export const _sha1_block_size = 64;
+export const _sha1_hash_size = 20;
+
+export class Sha1 extends Hash {
+ static NAME = 'sha1';
+ public NAME = 'sha1';
+ public BLOCK_SIZE = _sha1_block_size;
+ public HASH_SIZE = _sha1_hash_size;
+
+ constructor() {
+ super();
+
+ this.heap = _heap_init();
+ this.asm = sha1_asm({ Uint8Array: Uint8Array }, null, this.heap.buffer);
+
+ this.reset();
+ }
+}
diff --git a/src/hash/sha256/exports.js b/src/hash/sha256/exports.js
deleted file mode 100644
index 73c9549..0000000
--- a/src/hash/sha256/exports.js
+++ /dev/null
@@ -1,29 +0,0 @@
-/**
- * SHA256 exports
- */
-
-import { get_sha256_instance, sha256_constructor } from './sha256';
-import { bytes_to_base64, bytes_to_hex } from '../../utils';
-
-function sha256_bytes(data) {
- if (data === undefined) throw new SyntaxError('data required');
- return get_sha256_instance()
- .reset()
- .process(data)
- .finish().result;
-}
-
-function sha256_hex(data) {
- var result = sha256_bytes(data);
- return bytes_to_hex(result);
-}
-
-function sha256_base64(data) {
- var result = sha256_bytes(data);
- return bytes_to_base64(result);
-}
-
-export var SHA256 = sha256_constructor;
-SHA256.bytes = sha256_bytes;
-SHA256.hex = sha256_hex;
-SHA256.base64 = sha256_base64;
diff --git a/src/hash/sha256/sha256.asm.d.ts b/src/hash/sha256/sha256.asm.d.ts
new file mode 100644
index 0000000..b68314f
--- /dev/null
+++ b/src/hash/sha256/sha256.asm.d.ts
@@ -0,0 +1,62 @@
+declare interface sha256result {
+ // SHA1
+ reset: () => void;
+ init: (h0: number, h1: number, h2: number, h3: number, h4: number, total0: number, total1: number) => void;
+
+ /**
+ * @param offset - multiple of 64
+ * @param length
+ * @returns hashed
+ */
+ process: (offset: number, length: number) => number;
+
+ /**
+ * @param offset - multiple of 64
+ * @param length
+ * @param output - multiple of 32
+ * @returns hashed
+ */
+ finish: (offset: number, length: number, output: number) => number;
+
+ // HMAC-SHA;
+ hmac_reset: () => void;
+ hmac_init: (
+ p0: number,
+ p1: number,
+ p2: number,
+ p3: number,
+ p4: number,
+ p5: number,
+ p6: number,
+ p7: number,
+ p8: number,
+ p9: number,
+ p10: number,
+ p11: number,
+ p12: number,
+ p13: number,
+ p14: number,
+ p15: number,
+ ) => void;
+
+ /**
+ * @param offset - multiple of 64
+ * @param length
+ * @param output - multiple of 32
+ * @returns hashed
+ */
+ hmac_finish: (offset: number, length: number, output: number) => number;
+
+ // ;
+ /**
+ * PBKDF2-HMAC-SHA
+ * @param offset - multiple of 64
+ * @param length
+ * @param block
+ * @param count
+ * @param output - multiple of 32
+ */
+ pbkdf2_generate_block: (offset: number, length: number, block: number, count: number, output: number) => 0 | -1;
+}
+
+export function sha256_asm(stdlib: any, foreign: any, buffer: ArrayBuffer): sha256result;
diff --git a/src/hash/sha256/sha256.asm.js b/src/hash/sha256/sha256.asm.js
index 088b328..acf6908 100644
--- a/src/hash/sha256/sha256.asm.js
+++ b/src/hash/sha256/sha256.asm.js
@@ -808,18 +808,18 @@ export function sha256_asm ( stdlib, foreign, buffer ) {
}
return {
- // SHA256
- reset: reset,
- init: init,
- process: process,
- finish: finish,
-
- // HMAC-SHA256
- hmac_reset: hmac_reset,
- hmac_init: hmac_init,
- hmac_finish: hmac_finish,
-
- // PBKDF2-HMAC-SHA256
- pbkdf2_generate_block: pbkdf2_generate_block
+ // SHA256
+ reset: reset,
+ init: init,
+ process: process,
+ finish: finish,
+
+ // HMAC-SHA256
+ hmac_reset: hmac_reset,
+ hmac_init: hmac_init,
+ hmac_finish: hmac_finish,
+
+ // PBKDF2-HMAC-SHA256
+ pbkdf2_generate_block: pbkdf2_generate_block
}
}
diff --git a/src/hash/sha256/sha256.js b/src/hash/sha256/sha256.js
deleted file mode 100644
index 126341e..0000000
--- a/src/hash/sha256/sha256.js
+++ /dev/null
@@ -1,34 +0,0 @@
-import { sha256_asm } from './sha256.asm';
-import { hash_finish, hash_process, hash_reset } from '../hash';
-import { _heap_init } from '../../utils';
-
-export var _sha256_block_size = 64;
-export var _sha256_hash_size = 32;
-
-export function sha256_constructor(options) {
- options = options || {};
-
- this.heap = _heap_init(Uint8Array, options.heap);
- this.asm = options.asm || sha256_asm({ Uint8Array: Uint8Array }, null, this.heap.buffer);
-
- this.BLOCK_SIZE = _sha256_block_size;
- this.HASH_SIZE = _sha256_hash_size;
-
- this.reset();
-}
-
-sha256_constructor.BLOCK_SIZE = _sha256_block_size;
-sha256_constructor.HASH_SIZE = _sha256_hash_size;
-sha256_constructor.NAME = 'sha256';
-
-var sha256_prototype = sha256_constructor.prototype;
-sha256_prototype.reset = hash_reset;
-sha256_prototype.process = hash_process;
-sha256_prototype.finish = hash_finish;
-
-var sha256_instance = null;
-
-export function get_sha256_instance() {
- if (sha256_instance === null) sha256_instance = new sha256_constructor({ heapSize: 0x100000 });
- return sha256_instance;
-}
diff --git a/src/hash/sha256/sha256.ts b/src/hash/sha256/sha256.ts
new file mode 100644
index 0000000..885d773
--- /dev/null
+++ b/src/hash/sha256/sha256.ts
@@ -0,0 +1,22 @@
+import { sha256_asm, sha256result } from './sha256.asm';
+import { Hash } from '../hash';
+import { _heap_init } from '../../other/utils';
+
+export const _sha256_block_size = 64;
+export const _sha256_hash_size = 32;
+
+export class Sha256 extends Hash {
+ static NAME = 'sha256';
+ public NAME = 'sha256';
+ public BLOCK_SIZE = _sha256_block_size;
+ public HASH_SIZE = _sha256_hash_size;
+
+ constructor() {
+ super();
+
+ this.heap = _heap_init();
+ this.asm = sha256_asm({ Uint8Array: Uint8Array }, null, this.heap.buffer);
+
+ this.reset();
+ }
+}
diff --git a/src/hash/sha512/exports.js b/src/hash/sha512/exports.js
deleted file mode 100644
index f85706e..0000000
--- a/src/hash/sha512/exports.js
+++ /dev/null
@@ -1,30 +0,0 @@
-/**
- * SHA512 exports
- */
-
-import { get_sha512_instance, sha512_constructor } from './sha512';
-import { bytes_to_base64, bytes_to_hex } from '../../utils';
-
-function sha512_bytes(data) {
- if (data === undefined) throw new SyntaxError('data required');
- return get_sha512_instance()
- .reset()
- .process(data)
- .finish().result;
-}
-
-function sha512_hex(data) {
- var result = sha512_bytes(data);
- return bytes_to_hex(result);
-}
-
-function sha512_base64(data) {
- var result = sha512_bytes(data);
- return bytes_to_base64(result);
-}
-
-export var SHA512 = sha512_constructor;
-
-SHA512.bytes = sha512_bytes;
-SHA512.hex = sha512_hex;
-SHA512.base64 = sha512_base64;
diff --git a/src/hash/sha512/sha512.asm.d.ts b/src/hash/sha512/sha512.asm.d.ts
new file mode 100644
index 0000000..31eceff
--- /dev/null
+++ b/src/hash/sha512/sha512.asm.d.ts
@@ -0,0 +1,78 @@
+declare interface sha512result {
+ // SHA1
+ reset: () => void;
+ init: (h0: number, h1: number, h2: number, h3: number, h4: number, total0: number, total1: number) => void;
+
+ /**
+ * @param offset - multiple of 64
+ * @param length
+ * @returns hashed
+ */
+ process: (offset: number, length: number) => number;
+
+ /**
+ * @param offset - multiple of 64
+ * @param length
+ * @param output - multiple of 32
+ * @returns hashed
+ */
+ finish: (offset: number, length: number, output: number) => number;
+
+ // HMAC-SHA;
+ hmac_reset: () => void;
+ hmac_init: (
+ p0h: number,
+ p0l: number,
+ p1h: number,
+ p1l: number,
+ p2h: number,
+ p2l: number,
+ p3h: number,
+ p3l: number,
+ p4h: number,
+ p4l: number,
+ p5h: number,
+ p5l: number,
+ p6h: number,
+ p6l: number,
+ p7h: number,
+ p7l: number,
+ p8h: number,
+ p8l: number,
+ p9h: number,
+ p9l: number,
+ p10h: number,
+ p10l: number,
+ p11h: number,
+ p11l: number,
+ p12h: number,
+ p12l: number,
+ p13h: number,
+ p13l: number,
+ p14h: number,
+ p14l: number,
+ p15h: number,
+ p15l: number,
+ ) => void;
+
+ /**
+ * @param offset - multiple of 64
+ * @param length
+ * @param output - multiple of 32
+ * @returns hashed
+ */
+ hmac_finish: (offset: number, length: number, output: number) => number;
+
+ // ;
+ /**
+ * PBKDF2-HMAC-SHA
+ * @param offset - multiple of 64
+ * @param length
+ * @param block
+ * @param count
+ * @param output - multiple of 32
+ */
+ pbkdf2_generate_block: (offset: number, length: number, block: number, count: number, output: number) => 0 | -1;
+}
+
+export function sha512_asm(stdlib: any, foreign: any, buffer: ArrayBuffer): sha512result;
diff --git a/src/hash/sha512/sha512.asm.js b/src/hash/sha512/sha512.asm.js
index e86af51..6ace1f3 100644
--- a/src/hash/sha512/sha512.asm.js
+++ b/src/hash/sha512/sha512.asm.js
@@ -3144,18 +3144,18 @@ export function sha512_asm ( stdlib, foreign, buffer ) {
}
return {
- // SHA512
- reset: reset,
- init: init,
- process: process,
- finish: finish,
-
- // HMAC-SHA512
- hmac_reset: hmac_reset,
- hmac_init: hmac_init,
- hmac_finish: hmac_finish,
-
- // PBKDF2-HMAC-SHA512
- pbkdf2_generate_block: pbkdf2_generate_block
+ // SHA512
+ reset: reset,
+ init: init,
+ process: process,
+ finish: finish,
+
+ // HMAC-SHA512
+ hmac_reset: hmac_reset,
+ hmac_init: hmac_init,
+ hmac_finish: hmac_finish,
+
+ // PBKDF2-HMAC-SHA512
+ pbkdf2_generate_block: pbkdf2_generate_block
}
}
diff --git a/src/hash/sha512/sha512.js b/src/hash/sha512/sha512.js
deleted file mode 100644
index 4084d4c..0000000
--- a/src/hash/sha512/sha512.js
+++ /dev/null
@@ -1,34 +0,0 @@
-import { hash_finish, hash_process, hash_reset } from '../hash';
-import { sha512_asm } from './sha512.asm';
-import { _heap_init } from '../../utils';
-
-export var _sha512_block_size = 128;
-export var _sha512_hash_size = 64;
-
-export function sha512_constructor(options) {
- options = options || {};
-
- this.heap = _heap_init(Uint8Array, options.heapx);
- this.asm = options.asm || sha512_asm({ Uint8Array: Uint8Array }, null, this.heap.buffer);
-
- this.BLOCK_SIZE = _sha512_block_size;
- this.HASH_SIZE = _sha512_hash_size;
-
- this.reset();
-}
-
-sha512_constructor.BLOCK_SIZE = _sha512_block_size;
-sha512_constructor.HASH_SIZE = _sha512_hash_size;
-sha512_constructor.NAME = 'sha512';
-
-var sha512_prototype = sha512_constructor.prototype;
-sha512_prototype.reset = hash_reset;
-sha512_prototype.process = hash_process;
-sha512_prototype.finish = hash_finish;
-
-var sha512_instance = null;
-
-export function get_sha512_instance() {
- if (sha512_instance === null) sha512_instance = new sha512_constructor({ heapSize: 0x100000 });
- return sha512_instance;
-}
diff --git a/src/hash/sha512/sha512.ts b/src/hash/sha512/sha512.ts
new file mode 100644
index 0000000..ddaaa42
--- /dev/null
+++ b/src/hash/sha512/sha512.ts
@@ -0,0 +1,22 @@
+import { sha512_asm, sha512result } from './sha512.asm';
+import { Hash } from '../hash';
+import { _heap_init } from '../../other/utils';
+
+export const _sha512_block_size = 128;
+export const _sha512_hash_size = 64;
+
+export class Sha512 extends Hash {
+ static NAME = 'sha512';
+ public NAME = 'sha512';
+ public BLOCK_SIZE = _sha512_block_size;
+ public HASH_SIZE = _sha512_hash_size;
+
+ constructor() {
+ super();
+
+ this.heap = _heap_init();
+ this.asm = sha512_asm({ Uint8Array: Uint8Array }, null, this.heap.buffer);
+
+ this.reset();
+ }
+}
diff --git a/src/hmac/exports-hmac-sha1.js b/src/hmac/exports-hmac-sha1.js
deleted file mode 100644
index 0aeb88c..0000000
--- a/src/hmac/exports-hmac-sha1.js
+++ /dev/null
@@ -1,31 +0,0 @@
-/**
- * HMAC-SHA1 exports
- */
-
-import { get_hmac_sha1_instance, hmac_sha1_constructor } from './hmac-sha1';
-import { bytes_to_base64, bytes_to_hex } from '../utils';
-
-function hmac_sha1_bytes(data, password) {
- if (data === undefined) throw new SyntaxError('data required');
- if (password === undefined) throw new SyntaxError('password required');
- return get_hmac_sha1_instance()
- .reset({ password: password })
- .process(data)
- .finish().result;
-}
-
-function hmac_sha1_hex(data, password) {
- var result = hmac_sha1_bytes(data, password);
- return bytes_to_hex(result);
-}
-
-function hmac_sha1_base64(data, password) {
- var result = hmac_sha1_bytes(data, password);
- return bytes_to_base64(result);
-}
-
-export var HMAC_SHA1 = hmac_sha1_constructor;
-
-HMAC_SHA1.bytes = hmac_sha1_bytes;
-HMAC_SHA1.hex = hmac_sha1_hex;
-HMAC_SHA1.base64 = hmac_sha1_base64;
diff --git a/src/hmac/exports-hmac-sha256.js b/src/hmac/exports-hmac-sha256.js
deleted file mode 100644
index f3181a9..0000000
--- a/src/hmac/exports-hmac-sha256.js
+++ /dev/null
@@ -1,31 +0,0 @@
-/**
- * HMAC-SHA256 exports
- */
-
-import { get_hmac_sha256_instance, hmac_sha256_constructor } from './hmac-sha256';
-import { bytes_to_base64, bytes_to_hex } from '../utils';
-
-function hmac_sha256_bytes(data, password) {
- if (data === undefined) throw new SyntaxError('data required');
- if (password === undefined) throw new SyntaxError('password required');
- return get_hmac_sha256_instance()
- .reset({ password: password })
- .process(data)
- .finish().result;
-}
-
-function hmac_sha256_hex(data, password) {
- var result = hmac_sha256_bytes(data, password);
- return bytes_to_hex(result);
-}
-
-function hmac_sha256_base64(data, password) {
- var result = hmac_sha256_bytes(data, password);
- return bytes_to_base64(result);
-}
-
-export var HMAC_SHA256 = hmac_sha256_constructor;
-
-HMAC_SHA256.bytes = hmac_sha256_bytes;
-HMAC_SHA256.hex = hmac_sha256_hex;
-HMAC_SHA256.base64 = hmac_sha256_base64;
diff --git a/src/hmac/exports-hmac-sha512.js b/src/hmac/exports-hmac-sha512.js
deleted file mode 100644
index 87bf95c..0000000
--- a/src/hmac/exports-hmac-sha512.js
+++ /dev/null
@@ -1,31 +0,0 @@
-/**
- * HMAC-SHA512 exports
- */
-
-import { get_hmac_sha512_instance, hmac_sha512_constructor } from './hmac-sha512';
-import { bytes_to_base64, bytes_to_hex } from '../utils';
-
-function hmac_sha512_bytes(data, password) {
- if (data === undefined) throw new SyntaxError('data required');
- if (password === undefined) throw new SyntaxError('password required');
- return get_hmac_sha512_instance()
- .reset({ password: password })
- .process(data)
- .finish().result;
-}
-
-function hmac_sha512_hex(data, password) {
- var result = hmac_sha512_bytes(data, password);
- return bytes_to_hex(result);
-}
-
-function hmac_sha512_base64(data, password) {
- var result = hmac_sha512_bytes(data, password);
- return bytes_to_base64(result);
-}
-
-export var HMAC_SHA512 = hmac_sha512_constructor;
-
-HMAC_SHA512.bytes = hmac_sha512_bytes;
-HMAC_SHA512.hex = hmac_sha512_hex;
-HMAC_SHA512.base64 = hmac_sha512_base64;
diff --git a/src/hmac/hmac-sha1.js b/src/hmac/hmac-sha1.js
deleted file mode 100644
index 182ed0b..0000000
--- a/src/hmac/hmac-sha1.js
+++ /dev/null
@@ -1,107 +0,0 @@
-import { hmac_constructor, _hmac_key } from './hmac';
-import { _sha1_hash_size, get_sha1_instance, sha1_constructor } from '../hash/sha1/sha1';
-import { is_string, string_to_bytes } from '../utils';
-import { IllegalStateError } from '../errors';
-
-export class hmac_sha1_constructor extends hmac_constructor {
- constructor(options) {
- options = options || {};
-
- if (!(options.hash instanceof sha1_constructor)) options.hash = get_sha1_instance();
-
- super(options);
- }
-
- reset(options) {
- options = options || {};
-
- this.result = null;
- this.hash.reset();
-
- var password = options.password;
- if (password !== undefined) {
- if (is_string(password)) password = string_to_bytes(password);
-
- var key = (this.key = _hmac_key(this.hash, password));
- this.hash
- .reset()
- .asm.hmac_init(
- (key[0] << 24) | (key[1] << 16) | (key[2] << 8) | key[3],
- (key[4] << 24) | (key[5] << 16) | (key[6] << 8) | key[7],
- (key[8] << 24) | (key[9] << 16) | (key[10] << 8) | key[11],
- (key[12] << 24) | (key[13] << 16) | (key[14] << 8) | key[15],
- (key[16] << 24) | (key[17] << 16) | (key[18] << 8) | key[19],
- (key[20] << 24) | (key[21] << 16) | (key[22] << 8) | key[23],
- (key[24] << 24) | (key[25] << 16) | (key[26] << 8) | key[27],
- (key[28] << 24) | (key[29] << 16) | (key[30] << 8) | key[31],
- (key[32] << 24) | (key[33] << 16) | (key[34] << 8) | key[35],
- (key[36] << 24) | (key[37] << 16) | (key[38] << 8) | key[39],
- (key[40] << 24) | (key[41] << 16) | (key[42] << 8) | key[43],
- (key[44] << 24) | (key[45] << 16) | (key[46] << 8) | key[47],
- (key[48] << 24) | (key[49] << 16) | (key[50] << 8) | key[51],
- (key[52] << 24) | (key[53] << 16) | (key[54] << 8) | key[55],
- (key[56] << 24) | (key[57] << 16) | (key[58] << 8) | key[59],
- (key[60] << 24) | (key[61] << 16) | (key[62] << 8) | key[63],
- );
- } else {
- this.hash.asm.hmac_reset();
- }
-
- var verify = options.verify;
- if (verify !== undefined) {
- this._hmac_init_verify(verify);
- } else {
- this.verify = null;
- }
-
- return this;
- }
-
- /**
- * @return {hmac_sha1_constructor}
- */
- finish() {
- if (this.key === null) throw new IllegalStateError('no key is associated with the instance');
-
- if (this.result !== null) throw new IllegalStateError('state must be reset before processing new data');
-
- var hash = this.hash,
- asm = this.hash.asm,
- heap = this.hash.heap;
-
- asm.hmac_finish(hash.pos, hash.len, 0);
-
- var verify = this.verify;
- var result = new Uint8Array(_sha1_hash_size);
- result.set(heap.subarray(0, _sha1_hash_size));
-
- if (verify) {
- if (verify.length === result.length) {
- var diff = 0;
- for (var i = 0; i < verify.length; i++) {
- diff |= verify[i] ^ result[i];
- }
- this.result = !diff;
- } else {
- this.result = false;
- }
- } else {
- this.result = result;
- }
-
- return this;
- }
-}
-
-hmac_sha1_constructor.BLOCK_SIZE = sha1_constructor.BLOCK_SIZE;
-hmac_sha1_constructor.HMAC_SIZE = sha1_constructor.HASH_SIZE;
-
-var hmac_sha1_instance = null;
-
-/**
- * @return {hmac_sha1_constructor}
- */
-export function get_hmac_sha1_instance() {
- if (hmac_sha1_instance === null) hmac_sha1_instance = new hmac_sha1_constructor();
- return hmac_sha1_instance;
-}
diff --git a/src/hmac/hmac-sha1.ts b/src/hmac/hmac-sha1.ts
new file mode 100644
index 0000000..ec6c7c7
--- /dev/null
+++ b/src/hmac/hmac-sha1.ts
@@ -0,0 +1,82 @@
+import { Hmac } from './hmac';
+import { _sha1_hash_size, Sha1 } from '../hash/sha1/sha1';
+import { IllegalStateError } from '../other/errors';
+import { sha1result } from '../hash/sha1/sha1.asm';
+import { Hash } from '../hash/hash';
+
+export class HmacSha1 extends Hmac> {
+ public result!: Uint8Array | null;
+
+ constructor(password: Uint8Array, verify?: Uint8Array) {
+ const hash = new Sha1();
+
+ // Calculate ipad, init the underlying engine, calculate this.key
+ super(hash, password, verify);
+
+ this.reset();
+
+ if (verify !== undefined) {
+ this._hmac_init_verify(verify);
+ } else {
+ this.verify = null;
+ }
+
+ return this;
+ }
+
+ reset(): this {
+ this.result = null;
+ const key = this.key;
+ this.hash
+ .reset()
+ .asm.hmac_init(
+ (key[0] << 24) | (key[1] << 16) | (key[2] << 8) | key[3],
+ (key[4] << 24) | (key[5] << 16) | (key[6] << 8) | key[7],
+ (key[8] << 24) | (key[9] << 16) | (key[10] << 8) | key[11],
+ (key[12] << 24) | (key[13] << 16) | (key[14] << 8) | key[15],
+ (key[16] << 24) | (key[17] << 16) | (key[18] << 8) | key[19],
+ (key[20] << 24) | (key[21] << 16) | (key[22] << 8) | key[23],
+ (key[24] << 24) | (key[25] << 16) | (key[26] << 8) | key[27],
+ (key[28] << 24) | (key[29] << 16) | (key[30] << 8) | key[31],
+ (key[32] << 24) | (key[33] << 16) | (key[34] << 8) | key[35],
+ (key[36] << 24) | (key[37] << 16) | (key[38] << 8) | key[39],
+ (key[40] << 24) | (key[41] << 16) | (key[42] << 8) | key[43],
+ (key[44] << 24) | (key[45] << 16) | (key[46] << 8) | key[47],
+ (key[48] << 24) | (key[49] << 16) | (key[50] << 8) | key[51],
+ (key[52] << 24) | (key[53] << 16) | (key[54] << 8) | key[55],
+ (key[56] << 24) | (key[57] << 16) | (key[58] << 8) | key[59],
+ (key[60] << 24) | (key[61] << 16) | (key[62] << 8) | key[63],
+ );
+ return this;
+ }
+
+ finish(): this {
+ if (this.result !== null) throw new IllegalStateError('state must be reset before processing new data');
+
+ const hash = this.hash;
+ const asm = this.hash.asm;
+ const heap = this.hash.heap;
+
+ asm.hmac_finish(hash.pos, hash.len, 0);
+
+ const verify = this.verify;
+ const result = new Uint8Array(_sha1_hash_size);
+ result.set(heap.subarray(0, _sha1_hash_size));
+
+ if (verify) {
+ if (verify.length === result.length) {
+ let diff = 0;
+ for (let i = 0; i < verify.length; i++) {
+ diff |= verify[i] ^ result[i];
+ }
+ if (diff !== 0) throw new Error("HMAC verification failed, hash value doesn't match");
+ } else {
+ throw new Error("HMAC verification failed, lengths doesn't match");
+ }
+ } else {
+ this.result = result;
+ }
+
+ return this;
+ }
+}
diff --git a/src/hmac/hmac-sha256.js b/src/hmac/hmac-sha256.js
deleted file mode 100644
index a7b18fe..0000000
--- a/src/hmac/hmac-sha256.js
+++ /dev/null
@@ -1,107 +0,0 @@
-import { hmac_constructor, _hmac_key } from './hmac';
-import { _sha256_hash_size, get_sha256_instance, sha256_constructor } from '../hash/sha256/sha256';
-import { is_string, string_to_bytes } from '../utils';
-import { IllegalStateError } from '../errors';
-
-export class hmac_sha256_constructor extends hmac_constructor {
- constructor(options) {
- options = options || {};
-
- if (!(options.hash instanceof sha256_constructor)) options.hash = get_sha256_instance();
-
- super(options);
- }
-
- reset(options) {
- options = options || {};
-
- this.result = null;
- this.hash.reset();
-
- var password = options.password;
- if (password !== undefined) {
- if (is_string(password)) password = string_to_bytes(password);
-
- var key = (this.key = _hmac_key(this.hash, password));
- this.hash
- .reset()
- .asm.hmac_init(
- (key[0] << 24) | (key[1] << 16) | (key[2] << 8) | key[3],
- (key[4] << 24) | (key[5] << 16) | (key[6] << 8) | key[7],
- (key[8] << 24) | (key[9] << 16) | (key[10] << 8) | key[11],
- (key[12] << 24) | (key[13] << 16) | (key[14] << 8) | key[15],
- (key[16] << 24) | (key[17] << 16) | (key[18] << 8) | key[19],
- (key[20] << 24) | (key[21] << 16) | (key[22] << 8) | key[23],
- (key[24] << 24) | (key[25] << 16) | (key[26] << 8) | key[27],
- (key[28] << 24) | (key[29] << 16) | (key[30] << 8) | key[31],
- (key[32] << 24) | (key[33] << 16) | (key[34] << 8) | key[35],
- (key[36] << 24) | (key[37] << 16) | (key[38] << 8) | key[39],
- (key[40] << 24) | (key[41] << 16) | (key[42] << 8) | key[43],
- (key[44] << 24) | (key[45] << 16) | (key[46] << 8) | key[47],
- (key[48] << 24) | (key[49] << 16) | (key[50] << 8) | key[51],
- (key[52] << 24) | (key[53] << 16) | (key[54] << 8) | key[55],
- (key[56] << 24) | (key[57] << 16) | (key[58] << 8) | key[59],
- (key[60] << 24) | (key[61] << 16) | (key[62] << 8) | key[63],
- );
- } else {
- this.hash.asm.hmac_reset();
- }
-
- var verify = options.verify;
- if (verify !== undefined) {
- this._hmac_init_verify(verify);
- } else {
- this.verify = null;
- }
-
- return this;
- }
-
- /**
- * @return {hmac_sha256_constructor}
- */
- finish() {
- if (this.key === null) throw new IllegalStateError('no key is associated with the instance');
-
- if (this.result !== null) throw new IllegalStateError('state must be reset before processing new data');
-
- var hash = this.hash,
- asm = this.hash.asm,
- heap = this.hash.heap;
-
- asm.hmac_finish(hash.pos, hash.len, 0);
-
- var verify = this.verify;
- var result = new Uint8Array(_sha256_hash_size);
- result.set(heap.subarray(0, _sha256_hash_size));
-
- if (verify) {
- if (verify.length === result.length) {
- var diff = 0;
- for (var i = 0; i < verify.length; i++) {
- diff |= verify[i] ^ result[i];
- }
- this.result = !diff;
- } else {
- this.result = false;
- }
- } else {
- this.result = result;
- }
-
- return this;
- }
-}
-
-hmac_sha256_constructor.BLOCK_SIZE = sha256_constructor.BLOCK_SIZE;
-hmac_sha256_constructor.HMAC_SIZE = sha256_constructor.HASH_SIZE;
-
-var hmac_sha256_instance = null;
-
-/**
- * @return {hmac_sha256_constructor}
- */
-export function get_hmac_sha256_instance() {
- if (hmac_sha256_instance === null) hmac_sha256_instance = new hmac_sha256_constructor();
- return hmac_sha256_instance;
-}
diff --git a/src/hmac/hmac-sha256.ts b/src/hmac/hmac-sha256.ts
new file mode 100644
index 0000000..e497903
--- /dev/null
+++ b/src/hmac/hmac-sha256.ts
@@ -0,0 +1,85 @@
+import { Hmac } from './hmac';
+import { IllegalStateError } from '../other/errors';
+import { _sha256_hash_size, Sha256 } from '../hash/sha256/sha256';
+import { sha256result } from '../hash/sha256/sha256.asm';
+import { Hash } from '../hash/hash';
+
+export class HmacSha256 extends Hmac> {
+ public result!: Uint8Array | null;
+
+ constructor(password: Uint8Array, verify?: Uint8Array) {
+ const hash = new Sha256();
+
+ // Calculate ipad, init the underlying engine, calculate this.key
+ super(hash, password, verify);
+
+ this.reset();
+
+ if (verify !== undefined) {
+ this._hmac_init_verify(verify);
+ } else {
+ this.verify = null;
+ }
+
+ return this;
+ }
+
+ reset(): this {
+ const key = this.key;
+
+ this.hash
+ .reset()
+ .asm.hmac_init(
+ (key[0] << 24) | (key[1] << 16) | (key[2] << 8) | key[3],
+ (key[4] << 24) | (key[5] << 16) | (key[6] << 8) | key[7],
+ (key[8] << 24) | (key[9] << 16) | (key[10] << 8) | key[11],
+ (key[12] << 24) | (key[13] << 16) | (key[14] << 8) | key[15],
+ (key[16] << 24) | (key[17] << 16) | (key[18] << 8) | key[19],
+ (key[20] << 24) | (key[21] << 16) | (key[22] << 8) | key[23],
+ (key[24] << 24) | (key[25] << 16) | (key[26] << 8) | key[27],
+ (key[28] << 24) | (key[29] << 16) | (key[30] << 8) | key[31],
+ (key[32] << 24) | (key[33] << 16) | (key[34] << 8) | key[35],
+ (key[36] << 24) | (key[37] << 16) | (key[38] << 8) | key[39],
+ (key[40] << 24) | (key[41] << 16) | (key[42] << 8) | key[43],
+ (key[44] << 24) | (key[45] << 16) | (key[46] << 8) | key[47],
+ (key[48] << 24) | (key[49] << 16) | (key[50] << 8) | key[51],
+ (key[52] << 24) | (key[53] << 16) | (key[54] << 8) | key[55],
+ (key[56] << 24) | (key[57] << 16) | (key[58] << 8) | key[59],
+ (key[60] << 24) | (key[61] << 16) | (key[62] << 8) | key[63],
+ );
+
+ return this;
+ }
+
+ finish(): this {
+ if (this.key === null) throw new IllegalStateError('no key is associated with the instance');
+
+ if (this.result !== null) throw new IllegalStateError('state must be reset before processing new data');
+
+ const hash = this.hash;
+ const asm = this.hash.asm;
+ const heap = this.hash.heap;
+
+ asm.hmac_finish(hash.pos, hash.len, 0);
+
+ const verify = this.verify;
+ const result = new Uint8Array(_sha256_hash_size);
+ result.set(heap.subarray(0, _sha256_hash_size));
+
+ if (verify) {
+ if (verify.length === result.length) {
+ let diff = 0;
+ for (let i = 0; i < verify.length; i++) {
+ diff |= verify[i] ^ result[i];
+ }
+ if (diff !== 0) throw new Error("HMAC verification failed, hash value doesn't match");
+ } else {
+ throw new Error("HMAC verification failed, lengths doesn't match");
+ }
+ } else {
+ this.result = result;
+ }
+
+ return this;
+ }
+}
diff --git a/src/hmac/hmac-sha512.js b/src/hmac/hmac-sha512.js
deleted file mode 100644
index a94f093..0000000
--- a/src/hmac/hmac-sha512.js
+++ /dev/null
@@ -1,123 +0,0 @@
-import { _sha512_hash_size, get_sha512_instance, sha512_constructor } from '../hash/sha512/sha512';
-import { hmac_constructor, _hmac_key } from './hmac';
-import { is_string, string_to_bytes } from '../utils';
-import { IllegalStateError } from '../errors';
-
-export class hmac_sha512_constructor extends hmac_constructor {
- constructor(options) {
- options = options || {};
-
- if (!(options.hash instanceof sha512_constructor)) options.hash = get_sha512_instance();
-
- super(options);
- }
-
- reset(options) {
- options = options || {};
-
- this.result = null;
- this.hash.reset();
-
- var password = options.password;
- if (password !== undefined) {
- if (is_string(password)) password = string_to_bytes(password);
-
- var key = (this.key = _hmac_key(this.hash, password));
- this.hash
- .reset()
- .asm.hmac_init(
- (key[0] << 24) | (key[1] << 16) | (key[2] << 8) | key[3],
- (key[4] << 24) | (key[5] << 16) | (key[6] << 8) | key[7],
- (key[8] << 24) | (key[9] << 16) | (key[10] << 8) | key[11],
- (key[12] << 24) | (key[13] << 16) | (key[14] << 8) | key[15],
- (key[16] << 24) | (key[17] << 16) | (key[18] << 8) | key[19],
- (key[20] << 24) | (key[21] << 16) | (key[22] << 8) | key[23],
- (key[24] << 24) | (key[25] << 16) | (key[26] << 8) | key[27],
- (key[28] << 24) | (key[29] << 16) | (key[30] << 8) | key[31],
- (key[32] << 24) | (key[33] << 16) | (key[34] << 8) | key[35],
- (key[36] << 24) | (key[37] << 16) | (key[38] << 8) | key[39],
- (key[40] << 24) | (key[41] << 16) | (key[42] << 8) | key[43],
- (key[44] << 24) | (key[45] << 16) | (key[46] << 8) | key[47],
- (key[48] << 24) | (key[49] << 16) | (key[50] << 8) | key[51],
- (key[52] << 24) | (key[53] << 16) | (key[54] << 8) | key[55],
- (key[56] << 24) | (key[57] << 16) | (key[58] << 8) | key[59],
- (key[60] << 24) | (key[61] << 16) | (key[62] << 8) | key[63],
- (key[64] << 24) | (key[65] << 16) | (key[66] << 8) | key[67],
- (key[68] << 24) | (key[69] << 16) | (key[70] << 8) | key[71],
- (key[72] << 24) | (key[73] << 16) | (key[74] << 8) | key[75],
- (key[76] << 24) | (key[77] << 16) | (key[78] << 8) | key[79],
- (key[80] << 24) | (key[81] << 16) | (key[82] << 8) | key[83],
- (key[84] << 24) | (key[85] << 16) | (key[86] << 8) | key[87],
- (key[88] << 24) | (key[89] << 16) | (key[90] << 8) | key[91],
- (key[92] << 24) | (key[93] << 16) | (key[94] << 8) | key[95],
- (key[96] << 24) | (key[97] << 16) | (key[98] << 8) | key[99],
- (key[100] << 24) | (key[101] << 16) | (key[102] << 8) | key[103],
- (key[104] << 24) | (key[105] << 16) | (key[106] << 8) | key[107],
- (key[108] << 24) | (key[109] << 16) | (key[110] << 8) | key[111],
- (key[112] << 24) | (key[113] << 16) | (key[114] << 8) | key[115],
- (key[116] << 24) | (key[117] << 16) | (key[118] << 8) | key[119],
- (key[120] << 24) | (key[121] << 16) | (key[122] << 8) | key[123],
- (key[124] << 24) | (key[125] << 16) | (key[126] << 8) | key[127],
- );
- } else {
- this.hash.asm.hmac_reset();
- }
-
- var verify = options.verify;
- if (verify !== undefined) {
- this._hmac_init_verify(verify);
- } else {
- this.verify = null;
- }
-
- return this;
- }
-
- /**
- * @return {hmac_sha512_constructor}
- */
- finish() {
- if (this.key === null) throw new IllegalStateError('no key is associated with the instance');
-
- if (this.result !== null) throw new IllegalStateError('state must be reset before processing new data');
-
- var hash = this.hash,
- asm = this.hash.asm,
- heap = this.hash.heap;
-
- asm.hmac_finish(hash.pos, hash.len, 0);
-
- var verify = this.verify;
- var result = new Uint8Array(_sha512_hash_size);
- result.set(heap.subarray(0, _sha512_hash_size));
-
- if (verify) {
- if (verify.length === result.length) {
- var diff = 0;
- for (var i = 0; i < verify.length; i++) {
- diff |= verify[i] ^ result[i];
- }
- this.result = !diff;
- } else {
- this.result = false;
- }
- } else {
- this.result = result;
- }
-
- return this;
- }
-}
-
-hmac_sha512_constructor.BLOCK_SIZE = sha512_constructor.BLOCK_SIZE;
-hmac_sha512_constructor.HMAC_SIZE = sha512_constructor.HASH_SIZE;
-
-var hmac_sha512_instance = null;
-
-/**
- * @return {get_hmac_sha512_instance}
- */
-export function get_hmac_sha512_instance() {
- if (hmac_sha512_instance === null) hmac_sha512_instance = new hmac_sha512_constructor();
- return hmac_sha512_instance;
-}
diff --git a/src/hmac/hmac-sha512.ts b/src/hmac/hmac-sha512.ts
new file mode 100644
index 0000000..d81fc69
--- /dev/null
+++ b/src/hmac/hmac-sha512.ts
@@ -0,0 +1,99 @@
+import { Hmac } from './hmac';
+import { IllegalStateError } from '../other/errors';
+import { _sha512_hash_size, Sha512 } from '../hash/sha512/sha512';
+import { Hash } from '../hash/hash';
+import { sha512result } from '../hash/sha512/sha512.asm';
+
+export class HmacSha512 extends Hmac> {
+ public result!: Uint8Array | null;
+
+ constructor(password: Uint8Array, verify?: Uint8Array) {
+ const hash = new Sha512();
+
+ // Calculate ipad, init the underlying engine, calculate this.key
+ super(hash, password, verify);
+
+ this.reset();
+
+ if (verify !== undefined) {
+ this._hmac_init_verify(verify);
+ } else {
+ this.verify = null;
+ }
+
+ return this;
+ }
+
+ reset(): this {
+ const key = this.key;
+ this.hash
+ .reset()
+ .asm.hmac_init(
+ (key[0] << 24) | (key[1] << 16) | (key[2] << 8) | key[3],
+ (key[4] << 24) | (key[5] << 16) | (key[6] << 8) | key[7],
+ (key[8] << 24) | (key[9] << 16) | (key[10] << 8) | key[11],
+ (key[12] << 24) | (key[13] << 16) | (key[14] << 8) | key[15],
+ (key[16] << 24) | (key[17] << 16) | (key[18] << 8) | key[19],
+ (key[20] << 24) | (key[21] << 16) | (key[22] << 8) | key[23],
+ (key[24] << 24) | (key[25] << 16) | (key[26] << 8) | key[27],
+ (key[28] << 24) | (key[29] << 16) | (key[30] << 8) | key[31],
+ (key[32] << 24) | (key[33] << 16) | (key[34] << 8) | key[35],
+ (key[36] << 24) | (key[37] << 16) | (key[38] << 8) | key[39],
+ (key[40] << 24) | (key[41] << 16) | (key[42] << 8) | key[43],
+ (key[44] << 24) | (key[45] << 16) | (key[46] << 8) | key[47],
+ (key[48] << 24) | (key[49] << 16) | (key[50] << 8) | key[51],
+ (key[52] << 24) | (key[53] << 16) | (key[54] << 8) | key[55],
+ (key[56] << 24) | (key[57] << 16) | (key[58] << 8) | key[59],
+ (key[60] << 24) | (key[61] << 16) | (key[62] << 8) | key[63],
+ (key[64] << 24) | (key[65] << 16) | (key[66] << 8) | key[67],
+ (key[68] << 24) | (key[69] << 16) | (key[70] << 8) | key[71],
+ (key[72] << 24) | (key[73] << 16) | (key[74] << 8) | key[75],
+ (key[76] << 24) | (key[77] << 16) | (key[78] << 8) | key[79],
+ (key[80] << 24) | (key[81] << 16) | (key[82] << 8) | key[83],
+ (key[84] << 24) | (key[85] << 16) | (key[86] << 8) | key[87],
+ (key[88] << 24) | (key[89] << 16) | (key[90] << 8) | key[91],
+ (key[92] << 24) | (key[93] << 16) | (key[94] << 8) | key[95],
+ (key[96] << 24) | (key[97] << 16) | (key[98] << 8) | key[99],
+ (key[100] << 24) | (key[101] << 16) | (key[102] << 8) | key[103],
+ (key[104] << 24) | (key[105] << 16) | (key[106] << 8) | key[107],
+ (key[108] << 24) | (key[109] << 16) | (key[110] << 8) | key[111],
+ (key[112] << 24) | (key[113] << 16) | (key[114] << 8) | key[115],
+ (key[116] << 24) | (key[117] << 16) | (key[118] << 8) | key[119],
+ (key[120] << 24) | (key[121] << 16) | (key[122] << 8) | key[123],
+ (key[124] << 24) | (key[125] << 16) | (key[126] << 8) | key[127],
+ );
+ return this;
+ }
+
+ finish() {
+ if (this.key === null) throw new IllegalStateError('no key is associated with the instance');
+
+ if (this.result !== null) throw new IllegalStateError('state must be reset before processing new data');
+
+ const hash = this.hash;
+ const asm = this.hash.asm;
+ const heap = this.hash.heap;
+
+ asm.hmac_finish(hash.pos, hash.len, 0);
+
+ const verify = this.verify;
+ const result = new Uint8Array(_sha512_hash_size);
+ result.set(heap.subarray(0, _sha512_hash_size));
+
+ if (verify) {
+ if (verify.length === result.length) {
+ let diff = 0;
+ for (let i = 0; i < verify.length; i++) {
+ diff |= verify[i] ^ result[i];
+ }
+ if (diff !== 0) throw new Error("HMAC verification failed, hash value doesn't match");
+ } else {
+ throw new Error("HMAC verification failed, lengths doesn't match");
+ }
+ } else {
+ this.result = result;
+ }
+
+ return this;
+ }
+}
diff --git a/src/hmac/hmac.js b/src/hmac/hmac.js
deleted file mode 100644
index 2e9395d..0000000
--- a/src/hmac/hmac.js
+++ /dev/null
@@ -1,133 +0,0 @@
-import { is_buffer, is_bytes, is_string, string_to_bytes } from '../utils';
-import { IllegalArgumentError, IllegalStateError } from '../errors';
-
-export class hmac_constructor {
- constructor(options) {
- options = options || {};
-
- if (!options.hash) throw new SyntaxError("option 'hash' is required");
-
- if (!options.hash.HASH_SIZE)
- throw new SyntaxError("option 'hash' supplied doesn't seem to be a valid hash function");
-
- this.hash = options.hash;
- this.BLOCK_SIZE = this.hash.BLOCK_SIZE;
- this.HMAC_SIZE = this.hash.HASH_SIZE;
-
- this.key = null;
- this.verify = null;
- this.result = null;
-
- if (options.password !== undefined || options.verify !== undefined) this.reset(options);
-
- return this;
- }
-
- reset(options) {
- options = options || {};
- var password = options.password;
-
- if (this.key === null && !is_string(password) && !password)
- throw new IllegalStateError('no key is associated with the instance');
-
- this.result = null;
- this.hash.reset();
-
- if (password || is_string(password)) this.key = _hmac_key(this.hash, password);
-
- var ipad = new Uint8Array(this.key);
- for (var i = 0; i < ipad.length; ++i) ipad[i] ^= 0x36;
-
- this.hash.process(ipad);
-
- var verify = options.verify;
- if (verify !== undefined) {
- this._hmac_init_verify(verify);
- } else {
- this.verify = null;
- }
-
- return this;
- }
-
- process(data) {
- if (this.key === null) throw new IllegalStateError('no key is associated with the instance');
-
- if (this.result !== null) throw new IllegalStateError('state must be reset before processing new data');
-
- this.hash.process(data);
-
- return this;
- }
-
- finish() {
- if (this.key === null) throw new IllegalStateError('no key is associated with the instance');
-
- if (this.result !== null) throw new IllegalStateError('state must be reset before processing new data');
-
- var inner_result = this.hash.finish().result;
-
- var opad = new Uint8Array(this.key);
- for (var i = 0; i < opad.length; ++i) opad[i] ^= 0x5c;
-
- var verify = this.verify;
- var result = this.hash
- .reset()
- .process(opad)
- .process(inner_result)
- .finish().result;
-
- if (verify) {
- if (verify.length === result.length) {
- var diff = 0;
- for (var i = 0; i < verify.length; i++) {
- diff |= verify[i] ^ result[i];
- }
- this.result = !diff;
- } else {
- this.result = false;
- }
- } else {
- this.result = result;
- }
-
- return this;
- }
-
- _hmac_init_verify(verify) {
- if (is_buffer(verify) || is_bytes(verify)) {
- verify = new Uint8Array(verify);
- } else if (is_string(verify)) {
- verify = string_to_bytes(verify);
- } else {
- throw new TypeError("verify tag isn't of expected type");
- }
-
- if (verify.length !== this.HMAC_SIZE) throw new IllegalArgumentError('illegal verification tag size');
-
- this.verify = verify;
- }
-}
-
-export function _hmac_key(hash, password) {
- if (is_buffer(password)) password = new Uint8Array(password);
-
- if (is_string(password)) password = string_to_bytes(password);
-
- if (!is_bytes(password)) throw new TypeError("password isn't of expected type");
-
- var key = new Uint8Array(hash.BLOCK_SIZE);
-
- if (password.length > hash.BLOCK_SIZE) {
- key.set(
- hash
- .reset()
- .process(password)
- .finish().result,
- );
- } else {
- key.set(password);
- }
-
- return key;
-}
diff --git a/src/hmac/hmac.ts b/src/hmac/hmac.ts
new file mode 100644
index 0000000..014771a
--- /dev/null
+++ b/src/hmac/hmac.ts
@@ -0,0 +1,98 @@
+import { IllegalArgumentError, IllegalStateError } from '../other/errors';
+import { Hash } from '../hash/hash';
+import { sha1result } from '../hash/sha1/sha1.asm';
+import { sha256result } from '../hash/sha256/sha256.asm';
+import { sha512result } from '../hash/sha512/sha512.asm';
+
+export abstract class Hmac | Hash | Hash> {
+ public hash: T;
+ protected BLOCK_SIZE: number;
+ public HMAC_SIZE: number;
+ protected key: Uint8Array;
+ protected verify!: Uint8Array | null;
+ public result!: Uint8Array | null;
+
+ protected constructor(hash: T, password: Uint8Array, verify?: Uint8Array) {
+ if (!hash.HASH_SIZE) throw new SyntaxError("option 'hash' supplied doesn't seem to be a valid hash function");
+
+ this.hash = hash;
+ this.BLOCK_SIZE = this.hash.BLOCK_SIZE;
+ this.HMAC_SIZE = this.hash.HASH_SIZE;
+
+ this.result = null;
+
+ this.key = _hmac_key(this.hash, password);
+
+ const ipad = new Uint8Array(this.key);
+ for (let i = 0; i < ipad.length; ++i) ipad[i] ^= 0x36;
+
+ this.hash.reset().process(ipad);
+
+ if (verify !== undefined) {
+ this._hmac_init_verify(verify);
+ } else {
+ this.verify = null;
+ }
+ }
+
+ process(data: Uint8Array): this {
+ if (this.result !== null) throw new IllegalStateError('state must be reset before processing new data');
+
+ this.hash.process(data);
+
+ return this;
+ }
+
+ finish(): this {
+ if (this.result !== null) throw new IllegalStateError('state must be reset before processing new data');
+
+ const inner_result = this.hash.finish().result as Uint8Array;
+
+ const opad = new Uint8Array(this.key);
+ for (let i = 0; i < opad.length; ++i) opad[i] ^= 0x5c;
+
+ const verify = this.verify;
+ const result = this.hash
+ .reset()
+ .process(opad)
+ .process(inner_result)
+ .finish().result as Uint8Array;
+
+ if (verify) {
+ if (verify.length === result.length) {
+ let diff = 0;
+ for (let i = 0; i < verify.length; i++) {
+ diff |= verify[i] ^ result[i];
+ }
+ if (diff !== 0) throw new Error("HMAC verification failed, hash value doesn't match");
+ } else {
+ throw new Error("HMAC verification failed, lengths doesn't match");
+ }
+ }
+
+ this.result = result;
+
+ return this;
+ }
+
+ _hmac_init_verify(verify: Uint8Array): void {
+ if (verify.length !== this.HMAC_SIZE) throw new IllegalArgumentError('illegal verification tag size');
+
+ this.verify = verify;
+ }
+}
+
+export function _hmac_key(hash: Hash, password: Uint8Array): Uint8Array {
+ const key = new Uint8Array(hash.BLOCK_SIZE);
+
+ if (password.length > hash.BLOCK_SIZE) {
+ key.set(hash
+ .reset()
+ .process(password)
+ .finish().result as Uint8Array);
+ } else {
+ key.set(password);
+ }
+
+ return key;
+}
diff --git a/src/origin.js b/src/origin.js
deleted file mode 100644
index ed28187..0000000
--- a/src/origin.js
+++ /dev/null
@@ -1,10 +0,0 @@
-var _global_console = typeof console !== 'undefined' ? console : undefined;
-
-var _secure_origin =
- typeof location === 'undefined' || !location.protocol.search(/https:|file:|chrome:|chrome-extension:|moz-extension:/);
-
-if (!_secure_origin && _global_console !== undefined) {
- _global_console.warn(
- 'asmCrypto seems to be load from an insecure origin; this may cause to MitM-attack vulnerability. Consider using secure transport protocol.',
- );
-}
diff --git a/src/other/errors.ts b/src/other/errors.ts
new file mode 100644
index 0000000..74326f3
--- /dev/null
+++ b/src/other/errors.ts
@@ -0,0 +1,20 @@
+export class IllegalStateError extends Error {
+ constructor(...args: any[]) {
+ super(...args);
+ Object.create(Error.prototype, { name: { value: 'IllegalStateError' } });
+ }
+}
+
+export class IllegalArgumentError extends Error {
+ constructor(...args: any[]) {
+ super(...args);
+ Object.create(Error.prototype, { name: { value: 'IllegalArgumentError' } });
+ }
+}
+
+export class SecurityError extends Error {
+ constructor(...args: any[]) {
+ super(...args);
+ Object.create(Error.prototype, { name: { value: 'SecurityError' } });
+ }
+}
diff --git a/src/exportedUtils.js b/src/other/exportedUtils.ts
similarity index 87%
rename from src/exportedUtils.js
rename to src/other/exportedUtils.ts
index 73ceebf..d462dcd 100644
--- a/src/exportedUtils.js
+++ b/src/other/exportedUtils.ts
@@ -9,4 +9,4 @@ export {
bytes_to_string,
bytes_to_hex,
bytes_to_base64,
-} from './utils.js';
+} from './utils';
diff --git a/src/other/get-random-values.ts b/src/other/get-random-values.ts
new file mode 100644
index 0000000..3e78305
--- /dev/null
+++ b/src/other/get-random-values.ts
@@ -0,0 +1,23 @@
+export function getRandomValues(buf: Uint32Array | Uint8Array): void {
+ try {
+ if (typeof window === 'undefined') {
+ const nodeCrypto = require('crypto');
+ const bytes = nodeCrypto.randomBytes(buf.length);
+ buf.set(bytes);
+ return;
+ }
+ } catch (e) {
+ console.error(e);
+ throw new Error('No secure random number generator available.');
+ }
+ if (window.crypto && window.crypto.getRandomValues) {
+ window.crypto.getRandomValues(buf);
+ return;
+ }
+ // @ts-ignore
+ if (window.msCrypto && window.msCrypto.getRandomValues) {
+ // @ts-ignore
+ window.msCrypto.getRandomValues(buf);
+ return;
+ }
+}
diff --git a/src/utils.js b/src/other/utils.ts
similarity index 69%
rename from src/utils.js
rename to src/other/utils.ts
index 3c64ef9..a7f4820 100644
--- a/src/utils.js
+++ b/src/other/utils.ts
@@ -1,13 +1,7 @@
-export var FloatArray = typeof Float64Array !== 'undefined' ? Float64Array : Float32Array; // make PhantomJS happy
-
-/**
- * @param {string} str
- * @param {boolean} [utf8]
- * @return {Uint8Array}
- */
-export function string_to_bytes(str, utf8) {
- utf8 = !!utf8;
+const local_atob = typeof atob === 'undefined' ? (str: string) => Buffer.from(str, 'base64').toString('binary') : atob;
+const local_btoa = typeof btoa === 'undefined' ? (str: string) => Buffer.from(str, 'binary').toString('base64') : btoa;
+export function string_to_bytes(str: string, utf8: boolean = false): Uint8Array {
var len = str.length,
bytes = new Uint8Array(utf8 ? 4 * len : len);
@@ -41,7 +35,7 @@ export function string_to_bytes(str, utf8) {
return bytes.subarray(0, j);
}
-export function hex_to_bytes(str) {
+export function hex_to_bytes(str: string): Uint8Array {
var len = str.length;
if (len & 1) {
str = '0' + str;
@@ -54,13 +48,11 @@ export function hex_to_bytes(str) {
return bytes;
}
-export function base64_to_bytes(str) {
- return string_to_bytes(atob(str));
+export function base64_to_bytes(str: string): Uint8Array {
+ return string_to_bytes(local_atob(str));
}
-export function bytes_to_string(bytes, utf8) {
- utf8 = !!utf8;
-
+export function bytes_to_string(bytes: Uint8Array, utf8: boolean = false): string {
var len = bytes.length,
chars = new Array(len);
@@ -95,7 +87,7 @@ export function bytes_to_string(bytes, utf8) {
return str;
}
-export function bytes_to_hex(arr) {
+export function bytes_to_hex(arr: Uint8Array): string {
var str = '';
for (var i = 0; i < arr.length; i++) {
var h = (arr[i] & 0xff).toString(16);
@@ -105,11 +97,11 @@ export function bytes_to_hex(arr) {
return str;
}
-export function bytes_to_base64(arr) {
- return btoa(bytes_to_string(arr));
+export function bytes_to_base64(arr: Uint8Array): string {
+ return local_btoa(bytes_to_string(arr));
}
-export function pow2_ceil(a) {
+export function pow2_ceil(a: number): number {
a -= 1;
a |= a >>> 1;
a |= a >>> 2;
@@ -120,23 +112,23 @@ export function pow2_ceil(a) {
return a;
}
-export function is_number(a) {
+export function is_number(a: number): boolean {
return typeof a === 'number';
}
-export function is_string(a) {
+export function is_string(a: string): boolean {
return typeof a === 'string';
}
-export function is_buffer(a) {
+export function is_buffer(a: ArrayBuffer): boolean {
return a instanceof ArrayBuffer;
}
-export function is_bytes(a) {
+export function is_bytes(a: Uint8Array): boolean {
return a instanceof Uint8Array;
}
-export function is_typed_array(a) {
+export function is_typed_array(a: any): boolean {
return (
a instanceof Int8Array ||
a instanceof Uint8Array ||
@@ -149,19 +141,19 @@ export function is_typed_array(a) {
);
}
-export function _heap_init(constructor, heap, heapSize) {
- var size = heap ? heap.byteLength : heapSize || 65536;
+export function _heap_init(heap?: Uint8Array, heapSize?: number): Uint8Array {
+ const size = heap ? heap.byteLength : heapSize || 65536;
if (size & 0xfff || size <= 0) throw new Error('heap size must be a positive integer and a multiple of 4096');
- heap = heap || new constructor(new ArrayBuffer(size));
+ heap = heap || new Uint8Array(new ArrayBuffer(size));
return heap;
}
-export function _heap_write(heap, hpos, data, dpos, dlen) {
- var hlen = heap.length - hpos,
- wlen = hlen < dlen ? hlen : dlen;
+export function _heap_write(heap: Uint8Array, hpos: number, data: Uint8Array, dpos: number, dlen: number): number {
+ const hlen = heap.length - hpos;
+ const wlen = hlen < dlen ? hlen : dlen;
heap.set(data.subarray(dpos, dpos + wlen), hpos);
diff --git a/src/pbkdf2/exports-pbkdf2-hmac-sha1.js b/src/pbkdf2/exports-pbkdf2-hmac-sha1.js
deleted file mode 100644
index 5d30996..0000000
--- a/src/pbkdf2/exports-pbkdf2-hmac-sha1.js
+++ /dev/null
@@ -1,36 +0,0 @@
-/**
- * PBKDF2-HMAC-SHA1 exports
- */
-
-import { bytes_to_base64, bytes_to_hex } from '../utils';
-import { get_pbkdf2_hmac_sha1_instance } from './pbkdf2-hmac-sha1';
-
-function pbkdf2_hmac_sha1_bytes(password, salt, iterations, dklen) {
- if (password === undefined) throw new SyntaxError('password required');
- if (salt === undefined) throw new SyntaxError('salt required');
- return get_pbkdf2_hmac_sha1_instance()
- .reset({ password: password })
- .generate(salt, iterations, dklen).result;
-}
-
-function pbkdf2_hmac_sha1_hex(password, salt, iterations, dklen) {
- var result = pbkdf2_hmac_sha1_bytes(password, salt, iterations, dklen);
- return bytes_to_hex(result);
-}
-
-function pbkdf2_hmac_sha1_base64(password, salt, iterations, dklen) {
- var result = pbkdf2_hmac_sha1_bytes(password, salt, iterations, dklen);
- return bytes_to_base64(result);
-}
-
-export var PBKDF2 = {
- bytes: pbkdf2_hmac_sha1_bytes,
- hex: pbkdf2_hmac_sha1_hex,
- base64: pbkdf2_hmac_sha1_base64,
-};
-
-export var PBKDF2_HMAC_SHA1 = {
- bytes: pbkdf2_hmac_sha1_bytes,
- hex: pbkdf2_hmac_sha1_hex,
- base64: pbkdf2_hmac_sha1_base64,
-};
diff --git a/src/pbkdf2/exports-pbkdf2-hmac-sha256.js b/src/pbkdf2/exports-pbkdf2-hmac-sha256.js
deleted file mode 100644
index 9f3e039..0000000
--- a/src/pbkdf2/exports-pbkdf2-hmac-sha256.js
+++ /dev/null
@@ -1,30 +0,0 @@
-/**
- * PBKDF2-HMAC-SHA256 exports
- */
-
-import { get_pbkdf2_hmac_sha256_instance } from './pbkdf2-hmac-sha256';
-import { bytes_to_base64, bytes_to_hex } from '../utils';
-
-function pbkdf2_hmac_sha256_bytes(password, salt, iterations, dklen) {
- if (password === undefined) throw new SyntaxError('password required');
- if (salt === undefined) throw new SyntaxError('salt required');
- return get_pbkdf2_hmac_sha256_instance()
- .reset({ password: password })
- .generate(salt, iterations, dklen).result;
-}
-
-function pbkdf2_hmac_sha256_hex(password, salt, iterations, dklen) {
- var result = pbkdf2_hmac_sha256_bytes(password, salt, iterations, dklen);
- return bytes_to_hex(result);
-}
-
-function pbkdf2_hmac_sha256_base64(password, salt, iterations, dklen) {
- var result = pbkdf2_hmac_sha256_bytes(password, salt, iterations, dklen);
- return bytes_to_base64(result);
-}
-
-export var PBKDF2_HMAC_SHA256 = {
- bytes: pbkdf2_hmac_sha256_bytes,
- hex: pbkdf2_hmac_sha256_hex,
- base64: pbkdf2_hmac_sha256_base64,
-};
diff --git a/src/pbkdf2/exports-pbkdf2-hmac-sha512.js b/src/pbkdf2/exports-pbkdf2-hmac-sha512.js
deleted file mode 100644
index ecb5ac2..0000000
--- a/src/pbkdf2/exports-pbkdf2-hmac-sha512.js
+++ /dev/null
@@ -1,30 +0,0 @@
-/**
- * PBKDF2-HMAC-SHA512 exports
- */
-
-import { get_pbkdf2_hmac_sha512_instance } from './pbkdf2-hmac-sha512';
-import { bytes_to_base64, bytes_to_hex } from '../utils';
-
-function pbkdf2_hmac_sha512_bytes(password, salt, iterations, dklen) {
- if (password === undefined) throw new SyntaxError('password required');
- if (salt === undefined) throw new SyntaxError('salt required');
- return get_pbkdf2_hmac_sha512_instance()
- .reset({ password: password })
- .generate(salt, iterations, dklen).result;
-}
-
-function pbkdf2_hmac_sha512_hex(password, salt, iterations, dklen) {
- var result = pbkdf2_hmac_sha512_bytes(password, salt, iterations, dklen);
- return bytes_to_hex(result);
-}
-
-function pbkdf2_hmac_sha512_base64(password, salt, iterations, dklen) {
- var result = pbkdf2_hmac_sha512_bytes(password, salt, iterations, dklen);
- return bytes_to_base64(result);
-}
-
-export var PBKDF2_HMAC_SHA512 = {
- bytes: pbkdf2_hmac_sha512_bytes,
- hex: pbkdf2_hmac_sha512_hex,
- base64: pbkdf2_hmac_sha512_base64,
-};
diff --git a/src/pbkdf2/pbkdf2-hmac-sha1.js b/src/pbkdf2/pbkdf2-hmac-sha1.js
deleted file mode 100644
index 98a2ff3..0000000
--- a/src/pbkdf2/pbkdf2-hmac-sha1.js
+++ /dev/null
@@ -1,46 +0,0 @@
-import { get_hmac_sha1_instance, hmac_sha1_constructor } from '../hmac/hmac-sha1';
-import { pbkdf2_constructor } from './pbkdf2';
-import { is_string } from '../utils';
-import { IllegalArgumentError, IllegalStateError } from '../errors';
-
-export class pbkdf2_hmac_sha1_constructor extends pbkdf2_constructor {
- constructor(options) {
- options = options || {};
-
- if (!(options.hmac instanceof hmac_sha1_constructor)) options.hmac = get_hmac_sha1_instance();
-
- super(options);
- }
-
- generate(salt, count, length) {
- if (this.result !== null) throw new IllegalStateError('state must be reset before processing new data');
-
- if (!salt && !is_string(salt)) throw new IllegalArgumentError("bad 'salt' value");
-
- count = count || this.count;
- length = length || this.length;
-
- this.result = new Uint8Array(length);
-
- var blocks = Math.ceil(length / this.hmac.HMAC_SIZE);
-
- for (var i = 1; i <= blocks; ++i) {
- var j = (i - 1) * this.hmac.HMAC_SIZE;
- var l = (i < blocks ? 0 : length % this.hmac.HMAC_SIZE) || this.hmac.HMAC_SIZE;
-
- this.hmac.reset().process(salt);
- this.hmac.hash.asm.pbkdf2_generate_block(this.hmac.hash.pos, this.hmac.hash.len, i, count, 0);
-
- this.result.set(this.hmac.hash.heap.subarray(0, l), j);
- }
-
- return this;
- }
-}
-
-var pbkdf2_hmac_sha1_instance = null;
-
-export function get_pbkdf2_hmac_sha1_instance() {
- if (pbkdf2_hmac_sha1_instance === null) pbkdf2_hmac_sha1_instance = new pbkdf2_hmac_sha1_constructor();
- return pbkdf2_hmac_sha1_instance;
-}
diff --git a/src/pbkdf2/pbkdf2-hmac-sha1.ts b/src/pbkdf2/pbkdf2-hmac-sha1.ts
new file mode 100644
index 0000000..4fcba52
--- /dev/null
+++ b/src/pbkdf2/pbkdf2-hmac-sha1.ts
@@ -0,0 +1,21 @@
+import { HmacSha1 } from '../hmac/hmac-sha1';
+
+export function Pbkdf2HmacSha1(password: Uint8Array, salt: Uint8Array, count: number, length: number): Uint8Array {
+ const hmac = new HmacSha1(password);
+
+ const result = new Uint8Array(length);
+
+ const blocks = Math.ceil(length / hmac.HMAC_SIZE);
+
+ for (let i = 1; i <= blocks; ++i) {
+ const j = (i - 1) * hmac.HMAC_SIZE;
+ const l = (i < blocks ? 0 : length % hmac.HMAC_SIZE) || hmac.HMAC_SIZE;
+
+ hmac.reset().process(salt);
+ hmac.hash.asm.pbkdf2_generate_block(hmac.hash.pos, hmac.hash.len, i, count, 0);
+
+ result.set(hmac.hash.heap.subarray(0, l), j);
+ }
+
+ return result;
+}
diff --git a/src/pbkdf2/pbkdf2-hmac-sha256.js b/src/pbkdf2/pbkdf2-hmac-sha256.js
deleted file mode 100644
index 647689e..0000000
--- a/src/pbkdf2/pbkdf2-hmac-sha256.js
+++ /dev/null
@@ -1,46 +0,0 @@
-import { pbkdf2_constructor } from './pbkdf2';
-import { get_hmac_sha256_instance, hmac_sha256_constructor } from '../hmac/hmac-sha256';
-import { is_string } from '../utils';
-import { IllegalArgumentError, IllegalStateError } from '../errors';
-
-export class pbkdf2_hmac_sha256_constructor extends pbkdf2_constructor {
- constructor(options) {
- options = options || {};
-
- if (!(options.hmac instanceof hmac_sha256_constructor)) options.hmac = get_hmac_sha256_instance();
-
- super(options);
- }
-
- generate(salt, count, length) {
- if (this.result !== null) throw new IllegalStateError('state must be reset before processing new data');
-
- if (!salt && !is_string(salt)) throw new IllegalArgumentError("bad 'salt' value");
-
- count = count || this.count;
- length = length || this.length;
-
- this.result = new Uint8Array(length);
-
- var blocks = Math.ceil(length / this.hmac.HMAC_SIZE);
-
- for (var i = 1; i <= blocks; ++i) {
- var j = (i - 1) * this.hmac.HMAC_SIZE;
- var l = (i < blocks ? 0 : length % this.hmac.HMAC_SIZE) || this.hmac.HMAC_SIZE;
-
- this.hmac.reset().process(salt);
- this.hmac.hash.asm.pbkdf2_generate_block(this.hmac.hash.pos, this.hmac.hash.len, i, count, 0);
-
- this.result.set(this.hmac.hash.heap.subarray(0, l), j);
- }
-
- return this;
- }
-}
-
-var pbkdf2_hmac_sha256_instance = null;
-
-export function get_pbkdf2_hmac_sha256_instance() {
- if (pbkdf2_hmac_sha256_instance === null) pbkdf2_hmac_sha256_instance = new pbkdf2_hmac_sha256_constructor();
- return pbkdf2_hmac_sha256_instance;
-}
diff --git a/src/pbkdf2/pbkdf2-hmac-sha256.ts b/src/pbkdf2/pbkdf2-hmac-sha256.ts
new file mode 100644
index 0000000..26bbfde
--- /dev/null
+++ b/src/pbkdf2/pbkdf2-hmac-sha256.ts
@@ -0,0 +1,21 @@
+import { HmacSha256 } from '../hmac/hmac-sha256';
+
+export function Pbkdf2HmacSha256(password: Uint8Array, salt: Uint8Array, count: number, length: number): Uint8Array {
+ const hmac = new HmacSha256(password);
+
+ const result = new Uint8Array(length);
+
+ const blocks = Math.ceil(length / hmac.HMAC_SIZE);
+
+ for (let i = 1; i <= blocks; ++i) {
+ const j = (i - 1) * hmac.HMAC_SIZE;
+ const l = (i < blocks ? 0 : length % hmac.HMAC_SIZE) || hmac.HMAC_SIZE;
+
+ hmac.reset().process(salt);
+ hmac.hash.asm.pbkdf2_generate_block(hmac.hash.pos, hmac.hash.len, i, count, 0);
+
+ result.set(hmac.hash.heap.subarray(0, l), j);
+ }
+
+ return result;
+}
diff --git a/src/pbkdf2/pbkdf2-hmac-sha512.js b/src/pbkdf2/pbkdf2-hmac-sha512.js
deleted file mode 100644
index eb26895..0000000
--- a/src/pbkdf2/pbkdf2-hmac-sha512.js
+++ /dev/null
@@ -1,55 +0,0 @@
-import { pbkdf2_constructor } from './pbkdf2';
-import { get_hmac_sha512_instance, hmac_sha512_constructor } from '../hmac/hmac-sha512';
-import { is_string } from '../utils';
-import { IllegalArgumentError, IllegalStateError } from '../errors';
-
-export class pbkdf2_hmac_sha512_constructor extends pbkdf2_constructor {
- constructor(options) {
- options = options || {};
-
- if (!(options.hmac instanceof hmac_sha512_constructor)) options.hmac = get_hmac_sha512_instance();
-
- super(options);
- }
-
- /**
- * @param {Uint8Array} salt
- * @param {number} count
- * @param {number} length
- * @return {pbkdf2_hmac_sha512_constructor}
- */
- generate(salt, count, length) {
- if (this.result !== null) throw new IllegalStateError('state must be reset before processing new data');
-
- if (!salt && !is_string(salt)) throw new IllegalArgumentError("bad 'salt' value");
-
- count = count || this.count;
- length = length || this.length;
-
- this.result = new Uint8Array(length);
-
- var blocks = Math.ceil(length / this.hmac.HMAC_SIZE);
-
- for (var i = 1; i <= blocks; ++i) {
- var j = (i - 1) * this.hmac.HMAC_SIZE;
- var l = (i < blocks ? 0 : length % this.hmac.HMAC_SIZE) || this.hmac.HMAC_SIZE;
-
- this.hmac.reset().process(salt);
- this.hmac.hash.asm.pbkdf2_generate_block(this.hmac.hash.pos, this.hmac.hash.len, i, count, 0);
-
- this.result.set(this.hmac.hash.heap.subarray(0, l), j);
- }
-
- return this;
- }
-}
-
-var pbkdf2_hmac_sha512_instance = null;
-
-/**
- * @return {get_pbkdf2_hmac_sha512_instance}
- */
-export function get_pbkdf2_hmac_sha512_instance() {
- if (pbkdf2_hmac_sha512_instance === null) pbkdf2_hmac_sha512_instance = new pbkdf2_hmac_sha512_constructor();
- return pbkdf2_hmac_sha512_instance;
-}
diff --git a/src/pbkdf2/pbkdf2-hmac-sha512.ts b/src/pbkdf2/pbkdf2-hmac-sha512.ts
new file mode 100644
index 0000000..bb293ff
--- /dev/null
+++ b/src/pbkdf2/pbkdf2-hmac-sha512.ts
@@ -0,0 +1,21 @@
+import { HmacSha512 } from '../hmac/hmac-sha512';
+
+export function Pbkdf2HmacSha512(password: Uint8Array, salt: Uint8Array, count: number, length: number): Uint8Array {
+ const hmac = new HmacSha512(password);
+
+ const result = new Uint8Array(length);
+
+ const blocks = Math.ceil(length / hmac.HMAC_SIZE);
+
+ for (let i = 1; i <= blocks; ++i) {
+ const j = (i - 1) * hmac.HMAC_SIZE;
+ const l = (i < blocks ? 0 : length % hmac.HMAC_SIZE) || hmac.HMAC_SIZE;
+
+ hmac.reset().process(salt);
+ hmac.hash.asm.pbkdf2_generate_block(hmac.hash.pos, hmac.hash.len, i, count, 0);
+
+ result.set(hmac.hash.heap.subarray(0, l), j);
+ }
+
+ return result;
+}
diff --git a/src/pbkdf2/pbkdf2.js b/src/pbkdf2/pbkdf2.js
deleted file mode 100644
index 3964dc7..0000000
--- a/src/pbkdf2/pbkdf2.js
+++ /dev/null
@@ -1,69 +0,0 @@
-import { is_string } from '../utils';
-import { IllegalArgumentError, IllegalStateError } from '../errors';
-
-export class pbkdf2_constructor {
- constructor(options) {
- options = options || {};
-
- if (!options.hmac) throw new SyntaxError("option 'hmac' is required");
-
- if (!options.hmac.HMAC_SIZE)
- throw new SyntaxError("option 'hmac' supplied doesn't seem to be a valid HMAC function");
-
- this.hmac = options.hmac;
- this.count = options.count || 4096;
- this.length = options.length || this.hmac.HMAC_SIZE;
-
- this.result = null;
-
- var password = options.password;
- if (password || is_string(password)) this.reset(options);
-
- return this;
- }
-
- reset(options) {
- this.result = null;
-
- this.hmac.reset(options);
-
- return this;
- }
-
- generate(salt, count, length) {
- if (this.result !== null) throw new IllegalStateError('state must be reset before processing new data');
-
- if (!salt && !is_string(salt)) throw new IllegalArgumentError("bad 'salt' value");
-
- count = count || this.count;
- length = length || this.length;
-
- this.result = new Uint8Array(length);
-
- var blocks = Math.ceil(length / this.hmac.HMAC_SIZE);
-
- for (var i = 1; i <= blocks; ++i) {
- var j = (i - 1) * this.hmac.HMAC_SIZE;
- var l = (i < blocks ? 0 : length % this.hmac.HMAC_SIZE) || this.hmac.HMAC_SIZE;
- var tmp = new Uint8Array(
- this.hmac
- .reset()
- .process(salt)
- .process(new Uint8Array([(i >>> 24) & 0xff, (i >>> 16) & 0xff, (i >>> 8) & 0xff, i & 0xff]))
- .finish().result,
- );
- this.result.set(tmp.subarray(0, l), j);
- for (var k = 1; k < count; ++k) {
- tmp = new Uint8Array(
- this.hmac
- .reset()
- .process(tmp)
- .finish().result,
- );
- for (var r = 0; r < l; ++r) this.result[j + r] ^= tmp[r];
- }
- }
-
- return this;
- }
-}
diff --git a/src/random/exports.js b/src/random/exports.js
deleted file mode 100644
index a5ca5e1..0000000
--- a/src/random/exports.js
+++ /dev/null
@@ -1 +0,0 @@
-export { Random_getNumber as random, Random_getValues as getRandomValues } from './random';
diff --git a/src/random/globals.js b/src/random/globals.js
deleted file mode 100644
index e4729cf..0000000
--- a/src/random/globals.js
+++ /dev/null
@@ -1,6 +0,0 @@
-import { Random_getNumber, Random_getValues } from './random';
-
-Math.random = Random_getNumber;
-
-if (typeof 'crypto' === 'undefined') var crypto = {};
-crypto.getRandomValues = Random_getValues;
diff --git a/src/random/isaac.js b/src/random/isaac.js
deleted file mode 100644
index a7ab2f4..0000000
--- a/src/random/isaac.js
+++ /dev/null
@@ -1,202 +0,0 @@
-/* ----------------------------------------------------------------------
- * Copyright (c) 2014 Artem S Vybornov
- *
- * Copyright (c) 2012 Yves-Marie K. Rinquin
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- * ----------------------------------------------------------------------
- *
- * ISAAC is a cryptographically secure pseudo-random number generator
- * (or CSPRNG for short) designed by Robert J. Jenkins Jr. in 1996 and
- * based on RC4. It is designed for speed and security.
- *
- * ISAAC's informations & analysis:
- * http://burtleburtle.net/bob/rand/isaac.html
- * ISAAC's implementation details:
- * http://burtleburtle.net/bob/rand/isaacafa.html
- *
- * ISAAC succesfully passed TestU01
- */
-
-import { FloatArray, is_buffer, is_number, is_string, is_typed_array, string_to_bytes } from '../utils';
-
-export var ISAAC = (function() {
- var m = new Uint32Array(256), // internal memory
- r = new Uint32Array(256), // result array
- acc = 0, // accumulator
- brs = 0, // last result
- cnt = 0, // counter
- gnt = 0; // generation counter
-
- /* private: randinit function, same as ISAAC reference implementation */
- function randinit() {
- var a, b, c, d, e, f, g, h;
-
- /* private mixing function */
- function mix() {
- a ^= b << 11;
- d = (d + a) | 0;
- b = (b + c) | 0;
- b ^= c >>> 2;
- e = (e + b) | 0;
- c = (c + d) | 0;
- c ^= d << 8;
- f = (f + c) | 0;
- d = (d + e) | 0;
- d ^= e >>> 16;
- g = (g + d) | 0;
- e = (e + f) | 0;
- e ^= f << 10;
- h = (h + e) | 0;
- f = (f + g) | 0;
- f ^= g >>> 4;
- a = (a + f) | 0;
- g = (g + h) | 0;
- g ^= h << 8;
- b = (b + g) | 0;
- h = (h + a) | 0;
- h ^= a >>> 9;
- c = (c + h) | 0;
- a = (a + b) | 0;
- }
-
- acc = brs = cnt = 0;
-
- // the golden ratio
- a = b = c = d = e = f = g = h = 0x9e3779b9;
-
- // scramble it
- for (var i = 0; i < 4; i++) mix();
-
- // mix it and combine with the internal state
- for (var i = 0; i < 256; i += 8) {
- a = (a + r[i | 0]) | 0;
- b = (b + r[i | 1]) | 0;
- c = (c + r[i | 2]) | 0;
- d = (d + r[i | 3]) | 0;
- e = (e + r[i | 4]) | 0;
- f = (f + r[i | 5]) | 0;
- g = (g + r[i | 6]) | 0;
- h = (h + r[i | 7]) | 0;
- mix();
- m.set([a, b, c, d, e, f, g, h], i);
- }
-
- // mix it again
- for (var i = 0; i < 256; i += 8) {
- a = (a + m[i | 0]) | 0;
- b = (b + m[i | 1]) | 0;
- c = (c + m[i | 2]) | 0;
- d = (d + m[i | 3]) | 0;
- e = (e + m[i | 4]) | 0;
- f = (f + m[i | 5]) | 0;
- g = (g + m[i | 6]) | 0;
- h = (h + m[i | 7]) | 0;
- mix();
- m.set([a, b, c, d, e, f, g, h], i);
- }
-
- // fill in the first set of results
- prng(1), (gnt = 256);
- }
-
- /* public: seeding function */
- function seed(s) {
- var i, j, k, n, l;
-
- if (!is_typed_array(s)) {
- if (is_number(s)) {
- (n = new FloatArray(1)), (n[0] = s);
- s = new Uint8Array(n.buffer);
- } else if (is_string(s)) {
- s = string_to_bytes(s);
- } else if (is_buffer(s)) {
- s = new Uint8Array(s);
- } else {
- throw new TypeError('bad seed type');
- }
- } else {
- s = new Uint8Array(s.buffer);
- }
-
- // preprocess the seed
- l = s.length;
- for (j = 0; j < l; j += 1024) {
- // xor each chunk of 1024 bytes with r, for randinit() to mix in
- for (k = j, i = 0; i < 1024 && k < l; k = j | ++i) {
- r[i >> 2] ^= s[k] << ((i & 3) << 3);
- }
- randinit();
- }
- }
-
- /* public: isaac generator, n = number of run */
- function prng(n) {
- n = n || 1;
-
- var i, x, y;
-
- while (n--) {
- cnt = (cnt + 1) | 0;
- brs = (brs + cnt) | 0;
-
- for (i = 0; i < 256; i += 4) {
- acc ^= acc << 13;
- acc = (m[(i + 128) & 0xff] + acc) | 0;
- x = m[i | 0];
- m[i | 0] = y = (m[(x >>> 2) & 0xff] + ((acc + brs) | 0)) | 0;
- r[i | 0] = brs = (m[(y >>> 10) & 0xff] + x) | 0;
-
- acc ^= acc >>> 6;
- acc = (m[(i + 129) & 0xff] + acc) | 0;
- x = m[i | 1];
- m[i | 1] = y = (m[(x >>> 2) & 0xff] + ((acc + brs) | 0)) | 0;
- r[i | 1] = brs = (m[(y >>> 10) & 0xff] + x) | 0;
-
- acc ^= acc << 2;
- acc = (m[(i + 130) & 0xff] + acc) | 0;
- x = m[i | 2];
- m[i | 2] = y = (m[(x >>> 2) & 0xff] + ((acc + brs) | 0)) | 0;
- r[i | 2] = brs = (m[(y >>> 10) & 0xff] + x) | 0;
-
- acc ^= acc >>> 16;
- acc = (m[(i + 131) & 0xff] + acc) | 0;
- x = m[i | 3];
- m[i | 3] = y = (m[(x >>> 2) & 0xff] + ((acc + brs) | 0)) | 0;
- r[i | 3] = brs = (m[(y >>> 10) & 0xff] + x) | 0;
- }
- }
- }
-
- /* public: return a random number */
- function rand() {
- if (!gnt--) prng(1), (gnt = 255);
-
- return r[gnt];
- }
-
- /* return class object */
- return {
- seed: seed,
- prng: prng,
- rand: rand,
- };
-})();
diff --git a/src/random/random.js b/src/random/random.js
deleted file mode 100644
index c8fbe21..0000000
--- a/src/random/random.js
+++ /dev/null
@@ -1,269 +0,0 @@
-import { ISAAC } from './isaac';
-import { FloatArray, is_buffer, is_typed_array } from '../utils';
-import { get_pbkdf2_hmac_sha256_instance } from '../pbkdf2/pbkdf2-hmac-sha256';
-import { SecurityError } from '../errors';
-
-var _global_console = typeof console !== 'undefined' ? console : undefined,
- _global_date_now = Date.now,
- _global_math_random = Math.random,
- _global_performance = typeof performance !== 'undefined' ? performance : undefined,
- _global_crypto = typeof crypto !== 'undefined' ? crypto : typeof msCrypto !== 'undefined' ? msCrypto : undefined,
- _global_crypto_getRandomValues;
-
-if (_global_crypto !== undefined) _global_crypto_getRandomValues = _global_crypto.getRandomValues;
-
-var _isaac_rand = ISAAC.rand,
- _isaac_seed = ISAAC.seed,
- _isaac_counter = 0,
- _isaac_weak_seeded = false,
- _isaac_seeded = false;
-
-var _random_estimated_entropy = 0,
- _random_required_entropy = 256,
- _random_warn_callstacks = {};
-
-export var _random_skip_system_rng_warning = false;
-export var _random_allow_weak = false;
-
-var _hires_now;
-if (_global_performance !== undefined) {
- _hires_now = function() {
- return (1000 * _global_performance.now()) | 0;
- };
-} else {
- var _hires_epoch = (1000 * _global_date_now()) | 0;
- _hires_now = function() {
- return (1000 * _global_date_now() - _hires_epoch) | 0;
- };
-}
-
-/**
- * weak_seed
- *
- * Seeds RNG with native `crypto.getRandomValues` output or with high-resolution
- * time and single `Math.random()` value, and various other sources.
- *
- * We estimate this may give at least ~50 bits of unpredictableness,
- * but this has not been analysed thoroughly or precisely.
- */
-function Random_weak_seed() {
- if (_global_crypto !== undefined) {
- buffer = new Uint8Array(32);
- _global_crypto_getRandomValues.call(_global_crypto, buffer);
-
- _isaac_seed(buffer);
- } else {
- // Some clarification about brute-force attack cost:
- // - entire bitcoin network operates at ~10^16 hash guesses per second;
- // - each PBKDF2 iteration requires the same number of hashing operations as bitcoin nonce guess;
- // - attacker having such a hashing power is able to break worst-case 50 bits of the randomness in ~3 hours;
- // Sounds sad though attacker having such a hashing power more likely would prefer to mine bitcoins.
- var buffer = new FloatArray(3),
- i,
- t;
-
- buffer[0] = _global_math_random();
- buffer[1] = _global_date_now();
- buffer[2] = _hires_now();
-
- buffer = new Uint8Array(buffer.buffer);
-
- var salt = '';
- if (typeof location !== 'undefined') {
- salt += location.href;
- } else if (typeof process !== 'undefined') {
- salt += process.pid + process.title;
- }
-
- var pbkdf2 = get_pbkdf2_hmac_sha256_instance();
- for (i = 0; i < 100; i++) {
- buffer = pbkdf2.reset({ password: buffer }).generate(salt, 1000, 32).result;
- t = _hires_now();
- (buffer[0] ^= t >>> 24), (buffer[1] ^= t >>> 16), (buffer[2] ^= t >>> 8), (buffer[3] ^= t);
- }
-
- _isaac_seed(buffer);
- }
-
- _isaac_counter = 0;
-
- _isaac_weak_seeded = true;
-}
-
-/**
- * seed
- *
- * Seeds PRNG with supplied random values if these values have enough entropy.
- *
- * A false return value means the RNG is currently insecure; however a true
- * return value does not mean it is necessarily secure (depending on how you
- * collected the seed) though asmCrypto will be forced to assume this.
- *
- * The input buffer will be zeroed to discourage reuse. You should not copy it
- * or use it anywhere else before passing it into this function.
- *
- * **DISCLAIMER!** Seeding with a poor values is an easiest way shoot your legs, so
- * do not seed until you're know what entropy is and how to obtail high-quality random values,
- * **DO NOT SEED WITH CONSTANT VALUE! YOU'LL GET NO RANDOMNESS FROM CONSTANT!**
- */
-export function Random_seed(seed) {
- if (!is_buffer(seed) && !is_typed_array(seed)) throw new TypeError('bad seed type');
-
- var bpos = seed.byteOffset || 0,
- blen = seed.byteLength || seed.length,
- buff = new Uint8Array(seed.buffer || seed, bpos, blen);
-
- _isaac_seed(buff);
-
- _isaac_counter = 0;
-
- // don't let the user use these bytes again
- var nonzero = 0;
- for (var i = 0; i < buff.length; i++) {
- nonzero |= buff[i];
- buff[i] = 0;
- }
-
- if (nonzero !== 0) {
- // TODO we could make a better estimate, but half-length is a prudent
- // simple measure that seems unlikely to over-estimate
- _random_estimated_entropy += 4 * blen;
- }
-
- _isaac_seeded = _random_estimated_entropy >= _random_required_entropy;
-
- return _isaac_seeded;
-}
-
-/**
- * getValues
- *
- * Populates the buffer with cryptographically secure random values. These are
- * calculated using `crypto.getRandomValues` if it is available, as well as our
- * own ISAAC PRNG implementation.
- *
- * If the former is not available (older browsers such as IE10 [1]), then the
- * latter *must* be seeded using `Random.seed`, unless `asmCrypto.random.allowWeak` is true.
- *
- * *We assume the system RNG is strong*; if you cannot afford this risk, then
- * you should also seed ISAAC using `Random.seed`. This is advisable for very
- * important situations, such as generation of long-term secrets. See also [2].
- *
- * [1] https://developer.mozilla.org/en-US/docs/Web/API/window.crypto.getRandomValues
- * [2] https://en.wikipedia.org/wiki/Dual_EC_DRBG
- *
- * In all cases, we opportunistically seed using various arbitrary sources
- * such as high-resolution time and one single value from the insecure
- * Math.random(); however this is not reliable as a strong security measure.
- */
-export function Random_getValues(buffer) {
- // opportunistically seed ISAAC with a weak seed; this hopefully makes an
- // attack harder in the case where the system RNG is weak *and* we haven't
- // seeded ISAAC. but don't make any guarantees to the user about this.
- if (!_isaac_weak_seeded) Random_weak_seed();
-
- // if we have no strong sources then the RNG is weak, handle it
- if (!_isaac_seeded && _global_crypto === undefined) {
- if (!_random_allow_weak) throw new SecurityError('No strong PRNGs available. Use asmCrypto.random.seed().');
-
- if (_global_console !== undefined)
- _global_console.error(
- 'No strong PRNGs available; your security is greatly lowered. Use asmCrypto.random.seed().',
- );
- }
-
- // separate warning about assuming system RNG strong
- if (
- !_random_skip_system_rng_warning &&
- !_isaac_seeded &&
- _global_crypto !== undefined &&
- _global_console !== undefined
- ) {
- // Hacky way to get call stack
- var s = new Error().stack;
- _random_warn_callstacks[s] |= 0;
- if (!_random_warn_callstacks[s]++)
- _global_console.warn(
- 'asmCrypto PRNG not seeded; your security relies on your system PRNG. If this is not acceptable, use asmCrypto.random.seed().',
- );
- }
-
- // proceed to get random values
- if (!is_buffer(buffer) && !is_typed_array(buffer)) throw new TypeError('unexpected buffer type');
-
- var bpos = buffer.byteOffset || 0,
- blen = buffer.byteLength || buffer.length,
- bytes = new Uint8Array(buffer.buffer || buffer, bpos, blen),
- i,
- r;
-
- // apply system rng
- if (_global_crypto !== undefined) _global_crypto_getRandomValues.call(_global_crypto, bytes);
-
- // apply isaac rng
- for (i = 0; i < blen; i++) {
- if ((i & 3) === 0) {
- if (_isaac_counter >= 0x10000000000) Random_weak_seed();
- r = _isaac_rand();
- _isaac_counter++;
- }
- bytes[i] ^= r;
- r >>>= 8;
- }
-
- return buffer;
-}
-
-/**
- * getNumber
- *
- * A drop-in `Math.random` replacement.
- * Intended for prevention of random material leakage out of the user's host.
- */
-export function Random_getNumber() {
- if (!_isaac_weak_seeded || _isaac_counter >= 0x10000000000) Random_weak_seed();
-
- var n = (0x100000 * _isaac_rand() + (_isaac_rand() >>> 12)) / 0x10000000000000;
- _isaac_counter += 2;
-
- return n;
-}
-
-Object.defineProperty(Random_getNumber, 'allowWeak', {
- get: function() {
- return _random_allow_weak;
- },
- set: function(a) {
- _random_allow_weak = a;
- },
-});
-
-Object.defineProperty(Random_getNumber, 'skipSystemRNGWarning', {
- get: function() {
- return _random_skip_system_rng_warning;
- },
- set: function(w) {
- _random_skip_system_rng_warning = w;
- },
-});
-
-Object.defineProperty(Random_getValues, 'allowWeak', {
- get: function() {
- return _random_allow_weak;
- },
- set: function(a) {
- _random_allow_weak = a;
- },
-});
-
-Object.defineProperty(Random_getValues, 'skipSystemRNGWarning', {
- get: function() {
- return _random_skip_system_rng_warning;
- },
- set: function(w) {
- _random_skip_system_rng_warning = w;
- },
-});
-
-Random_getNumber.seed = Random_seed;
-Random_getValues.seed = Random_seed;
diff --git a/src/rsa/exports-keygen.js b/src/rsa/exports-keygen.js
deleted file mode 100644
index 448a01f..0000000
--- a/src/rsa/exports-keygen.js
+++ /dev/null
@@ -1,19 +0,0 @@
-/**
- * RSA keygen exports
- */
-import { is_big_number } from '../bignum/bignum';
-import { RSA_generateKey } from './genkey';
-
-function rsa_generate_key(bitlen, e) {
- if (bitlen === undefined) throw new SyntaxError('bitlen required');
- if (e === undefined) throw new SyntaxError('e required');
- var key = RSA_generateKey(bitlen, e);
- for (var i = 0; i < key.length; i++) {
- if (is_big_number(key[i])) key[i] = key[i].toBytes();
- }
- return key;
-}
-
-export var RSA = {
- generateKey: rsa_generate_key,
-};
diff --git a/src/rsa/exports-oaep-sha1.js b/src/rsa/exports-oaep-sha1.js
deleted file mode 100644
index ae56849..0000000
--- a/src/rsa/exports-oaep-sha1.js
+++ /dev/null
@@ -1,23 +0,0 @@
-/**
- * RSA-OAEP-SHA1 exports
- */
-
-import { RSA_OAEP } from './pkcs1';
-import { get_sha1_instance } from '../hash/sha1/sha1';
-
-function rsa_oaep_sha1_encrypt_bytes(data, key, label) {
- if (data === undefined) throw new SyntaxError('data required');
- if (key === undefined) throw new SyntaxError('key required');
- return new RSA_OAEP({ hash: get_sha1_instance(), key: key, label: label }).encrypt(data).result;
-}
-
-function rsa_oaep_sha1_decrypt_bytes(data, key, label) {
- if (data === undefined) throw new SyntaxError('data required');
- if (key === undefined) throw new SyntaxError('key required');
- return new RSA_OAEP({ hash: get_sha1_instance(), key: key, label: label }).decrypt(data).result;
-}
-
-export var RSA_OAEP_SHA1 = {
- encrypt: rsa_oaep_sha1_encrypt_bytes,
- decrypt: rsa_oaep_sha1_decrypt_bytes,
-};
diff --git a/src/rsa/exports-oaep-sha256.js b/src/rsa/exports-oaep-sha256.js
deleted file mode 100644
index c2ae3a5..0000000
--- a/src/rsa/exports-oaep-sha256.js
+++ /dev/null
@@ -1,23 +0,0 @@
-/**
- * RSA-OAEP-SHA256 exports
- */
-
-import { RSA_OAEP } from './pkcs1';
-import { get_sha256_instance } from '../hash/sha256/sha256';
-
-function rsa_oaep_sha256_encrypt_bytes(data, key, label) {
- if (data === undefined) throw new SyntaxError('data required');
- if (key === undefined) throw new SyntaxError('key required');
- return new RSA_OAEP({ hash: get_sha256_instance(), key: key, label: label }).encrypt(data).result;
-}
-
-function rsa_oaep_sha256_decrypt_bytes(data, key, label) {
- if (data === undefined) throw new SyntaxError('data required');
- if (key === undefined) throw new SyntaxError('key required');
- return new RSA_OAEP({ hash: get_sha256_instance(), key: key, label: label }).decrypt(data).result;
-}
-
-export var RSA_OAEP_SHA256 = {
- encrypt: rsa_oaep_sha256_encrypt_bytes,
- decrypt: rsa_oaep_sha256_decrypt_bytes,
-};
diff --git a/src/rsa/exports-oaep-sha512.js b/src/rsa/exports-oaep-sha512.js
deleted file mode 100644
index 07df8e0..0000000
--- a/src/rsa/exports-oaep-sha512.js
+++ /dev/null
@@ -1,23 +0,0 @@
-/**
- * RSA-OAEP-SHA512 exports
- */
-
-import { RSA_OAEP } from './pkcs1';
-import { get_sha512_instance } from '../hash/sha512/sha512';
-
-function rsa_oaep_sha512_encrypt_bytes(data, key, label) {
- if (data === undefined) throw new SyntaxError('data required');
- if (key === undefined) throw new SyntaxError('key required');
- return new RSA_OAEP({ hash: get_sha512_instance(), key: key, label: label }).encrypt(data).result;
-}
-
-function rsa_oaep_sha512_decrypt_bytes(data, key, label) {
- if (data === undefined) throw new SyntaxError('data required');
- if (key === undefined) throw new SyntaxError('key required');
- return new RSA_OAEP({ hash: get_sha512_instance(), key: key, label: label }).decrypt(data).result;
-}
-
-export var RSA_OAEP_SHA512 = {
- encrypt: rsa_oaep_sha512_encrypt_bytes,
- decrypt: rsa_oaep_sha512_decrypt_bytes,
-};
diff --git a/src/rsa/exports-pkcs1-v1_5-sha1.js b/src/rsa/exports-pkcs1-v1_5-sha1.js
deleted file mode 100644
index 6be89b9..0000000
--- a/src/rsa/exports-pkcs1-v1_5-sha1.js
+++ /dev/null
@@ -1,29 +0,0 @@
-/**
- * RSA-PKCS1-v1_5-SHA1 exports
- */
-
-function rsa_pkcs1_v1_5_sha1_sign_bytes(data, key) {
- if (data === undefined) throw new SyntaxError('data required');
- if (key === undefined) throw new SyntaxError('key required');
- return new RSA_PKCS1_v1_5({ hash: get_sha1_instance(), key: key }).sign(data).result;
-}
-
-function rsa_pkcs1_v1_5_sha1_verify_bytes(signature, data, key) {
- if (signature === undefined) throw new SyntaxError('signature required');
- if (data === undefined) throw new SyntaxError('data required');
- if (key === undefined) throw new SyntaxError('key required');
- try {
- new RSA_PKCS1_v1_5({ hash: get_sha1_instance(), key: key }).verify(signature, data);
- return true;
- } catch (e) {
- if (!(e instanceof SecurityError)) throw e;
- }
- return false;
-}
-
-exports.RSA_PKCS1_v1_5 = RSA_PKCS1_v1_5;
-
-exports.RSA_PKCS1_v1_5_SHA1 = {
- sign: rsa_pkcs1_v1_5_sha1_sign_bytes,
- verify: rsa_pkcs1_v1_5_sha1_verify_bytes,
-};
diff --git a/src/rsa/exports-pkcs1-v1_5-sha256.js b/src/rsa/exports-pkcs1-v1_5-sha256.js
deleted file mode 100644
index 7ecac12..0000000
--- a/src/rsa/exports-pkcs1-v1_5-sha256.js
+++ /dev/null
@@ -1,29 +0,0 @@
-/**
- * RSA-PKCS1-v1_5-SHA256 exports
- */
-
-function rsa_pkcs1_v1_5_sha256_sign_bytes(data, key) {
- if (data === undefined) throw new SyntaxError('data required');
- if (key === undefined) throw new SyntaxError('key required');
- return new RSA_PKCS1_v1_5({ hash: get_sha256_instance(), key: key }).sign(data).result;
-}
-
-function rsa_pkcs1_v1_5_sha256_verify_bytes(signature, data, key) {
- if (signature === undefined) throw new SyntaxError('signature required');
- if (data === undefined) throw new SyntaxError('data required');
- if (key === undefined) throw new SyntaxError('key required');
- try {
- new RSA_PKCS1_v1_5({ hash: get_sha256_instance(), key: key }).verify(signature, data);
- return true;
- } catch (e) {
- if (!(e instanceof SecurityError)) throw e;
- }
- return false;
-}
-
-exports.RSA_PKCS1_v1_5 = RSA_PKCS1_v1_5;
-
-exports.RSA_PKCS1_v1_5_SHA256 = {
- sign: rsa_pkcs1_v1_5_sha256_sign_bytes,
- verify: rsa_pkcs1_v1_5_sha256_verify_bytes,
-};
diff --git a/src/rsa/exports-pkcs1-v1_5-sha512.js b/src/rsa/exports-pkcs1-v1_5-sha512.js
deleted file mode 100644
index af3939d..0000000
--- a/src/rsa/exports-pkcs1-v1_5-sha512.js
+++ /dev/null
@@ -1,29 +0,0 @@
-/**
- * RSA-PKCS1-v1_5-SHA512 exports
- */
-
-function rsa_pkcs1_v1_5_sha512_sign_bytes(data, key) {
- if (data === undefined) throw new SyntaxError('data required');
- if (key === undefined) throw new SyntaxError('key required');
- return new RSA_PKCS1_v1_5({ hash: get_sha512_instance(), key: key }).sign(data).result;
-}
-
-function rsa_pkcs1_v1_5_sha512_verify_bytes(signature, data, key) {
- if (signature === undefined) throw new SyntaxError('signature required');
- if (data === undefined) throw new SyntaxError('data required');
- if (key === undefined) throw new SyntaxError('key required');
- try {
- new RSA_PKCS1_v1_5({ hash: get_sha512_instance(), key: key }).verify(signature, data);
- return true;
- } catch (e) {
- if (!(e instanceof SecurityError)) throw e;
- }
- return false;
-}
-
-exports.RSA_PKCS1_v1_5 = RSA_PKCS1_v1_5;
-
-exports.RSA_PKCS1_v1_5_SHA512 = {
- sign: rsa_pkcs1_v1_5_sha512_sign_bytes,
- verify: rsa_pkcs1_v1_5_sha512_verify_bytes,
-};
diff --git a/src/rsa/exports-pss-sha1.js b/src/rsa/exports-pss-sha1.js
deleted file mode 100644
index 9c46efa..0000000
--- a/src/rsa/exports-pss-sha1.js
+++ /dev/null
@@ -1,31 +0,0 @@
-/**
- * RSA-PSS-SHA1 exports
- */
-
-import { RSA_PSS } from './pkcs1';
-import { get_sha1_instance } from '../hash/sha1/sha1';
-import { SecurityError } from '../errors';
-
-function rsa_pss_sha1_sign_bytes(data, key, slen) {
- if (data === undefined) throw new SyntaxError('data required');
- if (key === undefined) throw new SyntaxError('key required');
- return new RSA_PSS({ hash: get_sha1_instance(), key: key, saltLength: slen }).sign(data).result;
-}
-
-function rsa_pss_sha1_verify_bytes(signature, data, key, slen) {
- if (signature === undefined) throw new SyntaxError('signature required');
- if (data === undefined) throw new SyntaxError('data required');
- if (key === undefined) throw new SyntaxError('key required');
- try {
- new RSA_PSS({ hash: get_sha1_instance(), key: key, saltLength: slen }).verify(signature, data);
- return true;
- } catch (e) {
- if (!(e instanceof SecurityError)) throw e;
- }
- return false;
-}
-
-export var RSA_PSS_SHA1 = {
- sign: rsa_pss_sha1_sign_bytes,
- verify: rsa_pss_sha1_verify_bytes,
-};
diff --git a/src/rsa/exports-pss-sha256.js b/src/rsa/exports-pss-sha256.js
deleted file mode 100644
index 6acc252..0000000
--- a/src/rsa/exports-pss-sha256.js
+++ /dev/null
@@ -1,31 +0,0 @@
-/**
- * RSA-PSS-SHA256 exports
- */
-
-import { get_sha256_instance } from '../hash/sha256/sha256';
-import { RSA_PSS } from './pkcs1';
-import { SecurityError } from '../errors';
-
-function rsa_pss_sha256_sign_bytes(data, key, slen) {
- if (data === undefined) throw new SyntaxError('data required');
- if (key === undefined) throw new SyntaxError('key required');
- return new RSA_PSS({ hash: get_sha256_instance(), key: key, saltLength: slen }).sign(data).result;
-}
-
-function rsa_pss_sha256_verify_bytes(signature, data, key, slen) {
- if (signature === undefined) throw new SyntaxError('signature required');
- if (data === undefined) throw new SyntaxError('data required');
- if (key === undefined) throw new SyntaxError('key required');
- try {
- new RSA_PSS({ hash: get_sha256_instance(), key: key, saltLength: slen }).verify(signature, data);
- return true;
- } catch (e) {
- if (!(e instanceof SecurityError)) throw e;
- }
- return false;
-}
-
-export var RSA_PSS_SHA256 = {
- sign: rsa_pss_sha256_sign_bytes,
- verify: rsa_pss_sha256_verify_bytes,
-};
diff --git a/src/rsa/exports-pss-sha512.js b/src/rsa/exports-pss-sha512.js
deleted file mode 100644
index 54e02ff..0000000
--- a/src/rsa/exports-pss-sha512.js
+++ /dev/null
@@ -1,31 +0,0 @@
-/**
- * RSA-PSS-SHA512 exports
- */
-
-import { RSA_PSS } from './pkcs1';
-import { get_sha512_instance } from '../hash/sha512/sha512';
-import { SecurityError } from '../errors';
-
-function rsa_pss_sha512_sign_bytes(data, key, slen) {
- if (data === undefined) throw new SyntaxError('data required');
- if (key === undefined) throw new SyntaxError('key required');
- return new RSA_PSS({ hash: get_sha512_instance(), key: key, saltLength: slen }).sign(data).result;
-}
-
-function rsa_pss_sha512_verify_bytes(signature, data, key, slen) {
- if (signature === undefined) throw new SyntaxError('signature required');
- if (data === undefined) throw new SyntaxError('data required');
- if (key === undefined) throw new SyntaxError('key required');
- try {
- new RSA_PSS({ hash: get_sha512_instance(), key: key, saltLength: slen }).verify(signature, data);
- return true;
- } catch (e) {
- if (!(e instanceof SecurityError)) throw e;
- }
- return false;
-}
-
-export var RSA_PSS_SHA512 = {
- sign: rsa_pss_sha512_sign_bytes,
- verify: rsa_pss_sha512_verify_bytes,
-};
diff --git a/src/rsa/exports-raw.js b/src/rsa/exports-raw.js
deleted file mode 100644
index f9a2387..0000000
--- a/src/rsa/exports-raw.js
+++ /dev/null
@@ -1,24 +0,0 @@
-/**
- * RSA-RAW exports
- */
-
-import RSA from './raw';
-
-function rsa_raw_encrypt_bytes(data, key) {
- if (data === undefined) throw new SyntaxError('data required');
- if (key === undefined) throw new SyntaxError('key required');
- return new RSA({ key: key }).encrypt(data).result;
-}
-
-function rsa_raw_decrypt_bytes(data, key) {
- if (data === undefined) throw new SyntaxError('data required');
- if (key === undefined) throw new SyntaxError('key required');
- return new RSA({ key: key }).decrypt(data).result;
-}
-
-export var RSA_RAW = RSA;
-
-RSA_RAW.encrypt = rsa_raw_encrypt_bytes;
-RSA_RAW.decrypt = rsa_raw_decrypt_bytes;
-RSA_RAW.sign = rsa_raw_decrypt_bytes;
-RSA_RAW.verify = rsa_raw_encrypt_bytes;
diff --git a/src/rsa/genkey.js b/src/rsa/genkey.js
deleted file mode 100644
index 2532bdb..0000000
--- a/src/rsa/genkey.js
+++ /dev/null
@@ -1,65 +0,0 @@
-/**
- * Generate RSA key pair
- *
- * @param bitlen desired modulus length, default is 2048
- * @param e public exponent, default is 65537
- */
-import { RSA } from './rsa';
-import { randomProbablePrime } from '../bignum/bignum';
-import { BigNumber_extGCD } from '../bignum/extgcd';
-import { BigNumber, is_big_number, Modulus } from '../bignum/bignum';
-import { is_buffer, is_bytes, is_number, is_string, string_to_bytes } from '../utils';
-import { IllegalArgumentError } from '../errors';
-
-export function RSA_generateKey(bitlen, e) {
- bitlen = bitlen || 2048;
- e = e || 65537;
-
- if (bitlen < 512) throw new IllegalArgumentError('bit length is too small');
-
- if (is_string(e)) e = string_to_bytes(e);
-
- if (is_buffer(e)) e = new Uint8Array(e);
-
- if (is_bytes(e)) {
- e = new BigNumber(e);
- } else if (is_number(e)) {
- e = BigNumber.fromNumber(e);
- } else if (is_big_number(e)) {
- e = BigNumber.fromConfig(e);
- } else {
- throw new TypeError('unexpected exponent type');
- }
-
- if ((e.limbs[0] & 1) === 0) throw new IllegalArgumentError('exponent must be an odd number');
-
- var m, e, d, p, q, p1, q1, dp, dq, u;
-
- p = randomProbablePrime(bitlen >> 1, function(p) {
- p1 = BigNumber.fromConfig(p);
- p1.limbs[0] -= 1;
- return BigNumber_extGCD(p1, e).gcd.valueOf() == 1;
- });
-
- q = randomProbablePrime(bitlen - (bitlen >> 1), function(q) {
- m = new Modulus(p.multiply(q));
- if (!(m.limbs[((bitlen + 31) >> 5) - 1] >>> ((bitlen - 1) & 31))) return false;
- q1 = BigNumber.fromConfig(q);
- q1.limbs[0] -= 1;
- return BigNumber_extGCD(q1, e).gcd.valueOf() == 1;
- });
-
- d = new Modulus(p1.multiply(q1)).inverse(e);
-
- (dp = d.divide(p1).remainder), (dq = d.divide(q1).remainder);
-
- (p = new Modulus(p)), (q = new Modulus(q));
-
- var u = p.inverse(q);
-
- return [m, e, d, p, q, dp, dq, u];
-}
-
-RSA.generateKey = RSA_generateKey;
-
-export default RSA;
diff --git a/src/rsa/pkcs1.js b/src/rsa/pkcs1.js
deleted file mode 100644
index 6b0cb8a..0000000
--- a/src/rsa/pkcs1.js
+++ /dev/null
@@ -1,528 +0,0 @@
-import { RSA_reset, RSA_encrypt, RSA_decrypt } from './rsa';
-import { Random_getValues } from '../random/random';
-import { is_buffer, is_bytes, is_number, is_string, string_to_bytes } from '../utils';
-import { IllegalArgumentError, IllegalStateError, SecurityError } from '../errors';
-
-export class RSA_OAEP {
- constructor(options) {
- options = options || {};
-
- if (!options.hash) throw new SyntaxError("option 'hash' is required");
-
- if (!options.hash.HASH_SIZE)
- throw new SyntaxError("option 'hash' supplied doesn't seem to be a valid hash function");
-
- this.hash = options.hash;
-
- this.label = null;
-
- this.reset(options);
- }
-
- reset(options) {
- options = options || {};
-
- var label = options.label;
- if (label !== undefined) {
- if (is_buffer(label) || is_bytes(label)) {
- label = new Uint8Array(label);
- } else if (is_string(label)) {
- label = string_to_bytes(label);
- } else {
- throw new TypeError('unexpected label type');
- }
-
- this.label = label.length > 0 ? label : null;
- } else {
- this.label = null;
- }
-
- RSA_reset.call(this, options);
- }
-
- /**
- * @param {Uint8Array} data
- * @return {RSA_OAEP}
- */
- encrypt(data) {
- if (!this.key) throw new IllegalStateError('no key is associated with the instance');
-
- var key_size = Math.ceil(this.key[0].bitLength / 8),
- hash_size = this.hash.HASH_SIZE,
- data_length = data.byteLength || data.length || 0,
- ps_length = key_size - data_length - 2 * hash_size - 2;
-
- if (data_length > key_size - 2 * this.hash.HASH_SIZE - 2) throw new IllegalArgumentError('data too large');
-
- var message = new Uint8Array(key_size),
- seed = message.subarray(1, hash_size + 1),
- data_block = message.subarray(hash_size + 1);
-
- if (is_bytes(data)) {
- data_block.set(data, hash_size + ps_length + 1);
- } else if (is_buffer(data)) {
- data_block.set(new Uint8Array(data), hash_size + ps_length + 1);
- } else if (is_string(data)) {
- data_block.set(string_to_bytes(data), hash_size + ps_length + 1);
- } else {
- throw new TypeError('unexpected data type');
- }
-
- data_block.set(
- this.hash
- .reset()
- .process(this.label || '')
- .finish().result,
- 0,
- );
- data_block[hash_size + ps_length] = 1;
-
- Random_getValues(seed);
-
- var data_block_mask = RSA_MGF1_generate.call(this, seed, data_block.length);
- for (var i = 0; i < data_block.length; i++) data_block[i] ^= data_block_mask[i];
-
- var seed_mask = RSA_MGF1_generate.call(this, data_block, seed.length);
- for (var i = 0; i < seed.length; i++) seed[i] ^= seed_mask[i];
-
- RSA_encrypt.call(this, message);
-
- return this;
- }
-
- /**
- * @param {Uint8Array} data
- * @return {RSA_OAEP}
- */
- decrypt(data) {
- if (!this.key) throw new IllegalStateError('no key is associated with the instance');
-
- var key_size = Math.ceil(this.key[0].bitLength / 8),
- hash_size = this.hash.HASH_SIZE,
- data_length = data.byteLength || data.length || 0;
-
- if (data_length !== key_size) throw new IllegalArgumentError('bad data');
-
- RSA_decrypt.call(this, data);
-
- var z = this.result[0],
- seed = this.result.subarray(1, hash_size + 1),
- data_block = this.result.subarray(hash_size + 1);
-
- if (z !== 0) throw new SecurityError('decryption failed');
-
- var seed_mask = RSA_MGF1_generate.call(this, data_block, seed.length);
- for (var i = 0; i < seed.length; i++) seed[i] ^= seed_mask[i];
-
- var data_block_mask = RSA_MGF1_generate.call(this, seed, data_block.length);
- for (var i = 0; i < data_block.length; i++) data_block[i] ^= data_block_mask[i];
-
- var lhash = this.hash
- .reset()
- .process(this.label || '')
- .finish().result;
- for (var i = 0; i < hash_size; i++) {
- if (lhash[i] !== data_block[i]) throw new SecurityError('decryption failed');
- }
-
- var ps_end = hash_size;
- for (; ps_end < data_block.length; ps_end++) {
- var psz = data_block[ps_end];
- if (psz === 1) break;
- if (psz !== 0) throw new SecurityError('decryption failed');
- }
- if (ps_end === data_block.length) throw new SecurityError('decryption failed');
-
- this.result = data_block.subarray(ps_end + 1);
-
- return this;
- }
-}
-
-/**
- * @param {Uint8Array} seed
- * @param {number} length
- * @return {Uint8Array}
- * @constructor
- */
-function RSA_MGF1_generate(seed, length) {
- seed = seed || '';
- length = length || 0;
-
- var hash_size = this.hash.HASH_SIZE;
- // if ( length > (hash_size * 0x100000000) )
- // throw new IllegalArgumentError("mask length too large");
-
- var mask = new Uint8Array(length),
- counter = new Uint8Array(4),
- chunks = Math.ceil(length / hash_size);
- for (var i = 0; i < chunks; i++) {
- (counter[0] = i >>> 24), (counter[1] = (i >>> 16) & 255), (counter[2] = (i >>> 8) & 255), (counter[3] = i & 255);
-
- var submask = mask.subarray(i * hash_size);
-
- var chunk = this.hash
- .reset()
- .process(seed)
- .process(counter)
- .finish().result;
- if (chunk.length > submask.length) chunk = chunk.subarray(0, submask.length);
-
- submask.set(chunk);
- }
-
- return mask;
-}
-
-export class RSA_PSS {
- constructor(options) {
- options = options || {};
-
- if (!options.hash) throw new SyntaxError("option 'hash' is required");
-
- if (!options.hash.HASH_SIZE)
- throw new SyntaxError("option 'hash' supplied doesn't seem to be a valid hash function");
-
- this.hash = options.hash;
-
- this.saltLength = 4;
-
- this.reset(options);
- }
-
- reset(options) {
- options = options || {};
-
- RSA_reset.call(this, options);
-
- var slen = options.saltLength;
- if (slen !== undefined) {
- if (!is_number(slen) || slen < 0) throw new TypeError('saltLength should be a non-negative number');
-
- if (this.key !== null && Math.ceil((this.key[0].bitLength - 1) / 8) < this.hash.HASH_SIZE + slen + 2)
- throw new SyntaxError('saltLength is too large');
-
- this.saltLength = slen;
- } else {
- this.saltLength = 4;
- }
- }
-
- /**
- * @param {Uint8Array} data
- * @return {RSA_PSS}
- */
- sign(data) {
- if (!this.key) throw new IllegalStateError('no key is associated with the instance');
-
- var key_bits = this.key[0].bitLength,
- hash_size = this.hash.HASH_SIZE,
- message_length = Math.ceil((key_bits - 1) / 8),
- salt_length = this.saltLength,
- ps_length = message_length - salt_length - hash_size - 2;
-
- var message = new Uint8Array(message_length),
- h_block = message.subarray(message_length - hash_size - 1, message_length - 1),
- d_block = message.subarray(0, message_length - hash_size - 1),
- d_salt = d_block.subarray(ps_length + 1);
-
- var m_block = new Uint8Array(8 + hash_size + salt_length),
- m_hash = m_block.subarray(8, 8 + hash_size),
- m_salt = m_block.subarray(8 + hash_size);
-
- m_hash.set(
- this.hash
- .reset()
- .process(data)
- .finish().result,
- );
-
- if (salt_length > 0) Random_getValues(m_salt);
-
- d_block[ps_length] = 1;
- d_salt.set(m_salt);
-
- h_block.set(
- this.hash
- .reset()
- .process(m_block)
- .finish().result,
- );
-
- var d_block_mask = RSA_MGF1_generate.call(this, h_block, d_block.length);
- for (var i = 0; i < d_block.length; i++) d_block[i] ^= d_block_mask[i];
-
- message[message_length - 1] = 0xbc;
-
- var zbits = 8 * message_length - key_bits + 1;
- if (zbits % 8) message[0] &= 0xff >>> zbits;
-
- RSA_decrypt.call(this, message);
-
- return this;
- }
-
- /**
- * @param {Uint8Array} signature
- * @param {Uint8Array} data
- * @return {RSA_PSS}
- */
- verify(signature, data) {
- if (!this.key) throw new IllegalStateError('no key is associated with the instance');
-
- var key_bits = this.key[0].bitLength,
- hash_size = this.hash.HASH_SIZE,
- message_length = Math.ceil((key_bits - 1) / 8),
- salt_length = this.saltLength,
- ps_length = message_length - salt_length - hash_size - 2;
-
- RSA_encrypt.call(this, signature);
-
- var message = this.result;
- if (message[message_length - 1] !== 0xbc) throw new SecurityError('bad signature');
-
- var h_block = message.subarray(message_length - hash_size - 1, message_length - 1),
- d_block = message.subarray(0, message_length - hash_size - 1),
- d_salt = d_block.subarray(ps_length + 1);
-
- var zbits = 8 * message_length - key_bits + 1;
- if (zbits % 8 && message[0] >>> (8 - zbits)) throw new SecurityError('bad signature');
-
- var d_block_mask = RSA_MGF1_generate.call(this, h_block, d_block.length);
- for (var i = 0; i < d_block.length; i++) d_block[i] ^= d_block_mask[i];
-
- if (zbits % 8) message[0] &= 0xff >>> zbits;
-
- for (var i = 0; i < ps_length; i++) {
- if (d_block[i] !== 0) throw new SecurityError('bad signature');
- }
- if (d_block[ps_length] !== 1) throw new SecurityError('bad signature');
-
- var m_block = new Uint8Array(8 + hash_size + salt_length),
- m_hash = m_block.subarray(8, 8 + hash_size),
- m_salt = m_block.subarray(8 + hash_size);
-
- m_hash.set(
- this.hash
- .reset()
- .process(data)
- .finish().result,
- );
- m_salt.set(d_salt);
-
- var h_block_verify = this.hash
- .reset()
- .process(m_block)
- .finish().result;
- for (var i = 0; i < hash_size; i++) {
- if (h_block[i] !== h_block_verify[i]) throw new SecurityError('bad signature');
- }
-
- return this;
- }
-}
-
-export class RSA_PKCS1_v1_5 {
- constructor(options) {
- options = options || {};
-
- if (!options.hash) throw new SyntaxError("option 'hash' is required");
-
- if (!options.hash.HASH_SIZE)
- throw new SyntaxError("option 'hash' supplied doesn't seem to be a valid hash function");
-
- this.hash = options.hash;
-
- this.reset(options);
- }
-
- reset(options) {
- options = options || {};
-
- RSA_reset.call(this, options);
- }
-
- /**
- * @param {Uint8Array} data
- * @return {RSA_PKCS1_v1_5}
- */
- sign(data) {
- if (!this.key) {
- throw new IllegalStateError('no key is associated with the instance');
- }
- var prefix = getHashPrefix(this.hash);
- var hash_size = this.hash.HASH_SIZE;
-
- var t_len = prefix.length + hash_size;
- var k = (this.key[0].bitLength + 7) >> 3;
- if (k < t_len + 11) {
- throw new Error('Message too long');
- }
-
- var m_hash = new Uint8Array(hash_size);
- m_hash.set(
- this.hash
- .reset()
- .process(data)
- .finish().result,
- );
-
- // EM = 0x00 || 0x01 || PS || 0x00 || T
- var em = new Uint8Array(k);
- var i = 0;
- em[i++] = 0; // 0x00
- em[i++] = 1; // 0x01
- // PS
- for (i; i < k - t_len - 1; i++) {
- em[i] = 0xff;
- }
- em[i++] = 0;
- em.set(prefix, i); // 0x00
- // T
- em.set(m_hash, em.length - hash_size);
-
- RSA_decrypt.call(this, em);
-
- return this;
- }
-
- /**
- * @param {Uint8Array} signature
- * @param {Uint8Array} data
- * @return {RSA_PKCS1_v1_5}
- */
- verify(signature, data) {
- if (!this.key) {
- throw new IllegalStateError('no key is associated with the instance');
- }
- var prefix = getHashPrefix(this.hash);
- var hash_size = this.hash.HASH_SIZE;
-
- var t_len = prefix.length + hash_size;
- var k = (this.key[0].bitLength + 7) >> 3;
- if (k < t_len + 11) {
- throw new SecurityError('Bad signature');
- }
-
- RSA_encrypt.call(this, signature);
-
- var m_hash = new Uint8Array(hash_size);
- m_hash.set(
- this.hash
- .reset()
- .process(data)
- .finish().result,
- );
-
- var res = 1;
- // EM = 0x00 || 0x01 || PS || 0x00 || T
- var decryptedSignature = this.result;
- var i = 0;
- res &= decryptedSignature[i++] === 0; // 0x00
- res &= decryptedSignature[i++] === 1; // 0x01
- // PS
- for (i; i < k - t_len - 1; i++) {
- res &= decryptedSignature[i] === 0xff;
- }
- res &= decryptedSignature[i++] === 0; // 0x00
- // T
- var j = 0;
- var n = i + prefix.length;
- // prefix
- for (i; i < n; i++) {
- res &= decryptedSignature[i] === prefix[j++];
- }
- j = 0;
- n = i + m_hash.length;
- // hash
- for (i; i < n; i++) {
- res &= decryptedSignature[i] === m_hash[j++];
- }
-
- if (!res) {
- throw new SecurityError('Bad signature');
- }
-
- return this;
- }
-}
-
-const HASH_PREFIXES = {
- sha1: new Uint8Array([0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14]),
- sha256: new Uint8Array([
- 0x30,
- 0x31,
- 0x30,
- 0x0d,
- 0x06,
- 0x09,
- 0x60,
- 0x86,
- 0x48,
- 0x01,
- 0x65,
- 0x03,
- 0x04,
- 0x02,
- 0x01,
- 0x05,
- 0x00,
- 0x04,
- 0x20,
- ]),
- sha384: new Uint8Array([
- 0x30,
- 0x41,
- 0x30,
- 0x0d,
- 0x06,
- 0x09,
- 0x60,
- 0x86,
- 0x48,
- 0x01,
- 0x65,
- 0x03,
- 0x04,
- 0x02,
- 0x02,
- 0x05,
- 0x00,
- 0x04,
- 0x30,
- ]),
- sha512: new Uint8Array([
- 0x30,
- 0x51,
- 0x30,
- 0x0d,
- 0x06,
- 0x09,
- 0x60,
- 0x86,
- 0x48,
- 0x01,
- 0x65,
- 0x03,
- 0x04,
- 0x02,
- 0x03,
- 0x05,
- 0x00,
- 0x04,
- 0x40,
- ]),
-};
-
-/**
- * @param hash
- * @return {Uint8Array}
- */
-function getHashPrefix(hash) {
- var hashName = hash.constructor.NAME;
- var prefix = HASH_PREFIXES[hashName];
- if (!prefix) {
- throw new Error("Cannot get hash prefix for hash algorithm '" + hashName + "'");
- }
- return prefix;
-}
diff --git a/src/rsa/pkcs1.ts b/src/rsa/pkcs1.ts
new file mode 100644
index 0000000..47deee2
--- /dev/null
+++ b/src/rsa/pkcs1.ts
@@ -0,0 +1,431 @@
+import { RSA } from './rsa';
+import { IllegalArgumentError, IllegalStateError, SecurityError } from '../other/errors';
+import { Sha512 } from '../hash/sha512/sha512';
+import { Sha1 } from '../hash/sha1/sha1';
+import { Sha256 } from '../hash/sha256/sha256';
+import { BigNumber } from '../bignum/bignum';
+import { getRandomValues } from '../other/get-random-values';
+
+export class RSA_OAEP {
+ private readonly rsa: RSA;
+ private readonly label: Uint8Array | null;
+ private readonly hash: Sha1 | Sha256 | Sha512;
+
+ constructor(key: Uint8Array[], hash: Sha1 | Sha256 | Sha512, label?: Uint8Array) {
+ this.rsa = new RSA(key);
+
+ this.hash = hash;
+
+ if (label !== undefined) {
+ this.label = label.length > 0 ? label : null;
+ } else {
+ this.label = null;
+ }
+ }
+
+ encrypt(data: Uint8Array): Uint8Array {
+ const key_size = Math.ceil(this.rsa.key[0].bitLength / 8);
+ const hash_size = this.hash.HASH_SIZE;
+ const data_length = data.byteLength || data.length || 0;
+ const ps_length = key_size - data_length - 2 * hash_size - 2;
+
+ if (data_length > key_size - 2 * this.hash.HASH_SIZE - 2) throw new IllegalArgumentError('data too large');
+
+ const message = new Uint8Array(key_size);
+ const seed = message.subarray(1, hash_size + 1);
+ const data_block = message.subarray(hash_size + 1);
+
+ data_block.set(data, hash_size + ps_length + 1);
+
+ data_block.set(this.hash.process(this.label || new Uint8Array(0)).finish().result as Uint8Array, 0);
+ data_block[hash_size + ps_length] = 1;
+
+ getRandomValues(seed);
+
+ const data_block_mask = this.RSA_MGF1_generate(seed, data_block.length);
+ for (let i = 0; i < data_block.length; i++) data_block[i] ^= data_block_mask[i];
+
+ const seed_mask = this.RSA_MGF1_generate(data_block, seed.length);
+ for (let i = 0; i < seed.length; i++) seed[i] ^= seed_mask[i];
+
+ this.rsa.encrypt(new BigNumber(message));
+
+ return new Uint8Array(this.rsa.result);
+ }
+
+ decrypt(data: Uint8Array): Uint8Array {
+ if (!this.rsa.key) throw new IllegalStateError('no key is associated with the instance');
+
+ const key_size = Math.ceil(this.rsa.key[0].bitLength / 8);
+ const hash_size = this.hash.HASH_SIZE;
+ const data_length = data.byteLength || data.length || 0;
+
+ if (data_length !== key_size) throw new IllegalArgumentError('bad data');
+
+ this.rsa.decrypt(new BigNumber(data));
+
+ const z = this.rsa.result[0];
+ const seed = this.rsa.result.subarray(1, hash_size + 1);
+ const data_block = this.rsa.result.subarray(hash_size + 1);
+
+ if (z !== 0) throw new SecurityError('decryption failed');
+
+ const seed_mask = this.RSA_MGF1_generate(data_block, seed.length);
+ for (let i = 0; i < seed.length; i++) seed[i] ^= seed_mask[i];
+
+ const data_block_mask = this.RSA_MGF1_generate(seed, data_block.length);
+ for (let i = 0; i < data_block.length; i++) data_block[i] ^= data_block_mask[i];
+
+ const lhash = this.hash
+ .reset()
+ .process(this.label || new Uint8Array(0))
+ .finish().result as Uint8Array;
+ for (let i = 0; i < hash_size; i++) {
+ if (lhash[i] !== data_block[i]) throw new SecurityError('decryption failed');
+ }
+
+ let ps_end = hash_size;
+ for (; ps_end < data_block.length; ps_end++) {
+ const psz = data_block[ps_end];
+ if (psz === 1) break;
+ if (psz !== 0) throw new SecurityError('decryption failed');
+ }
+ if (ps_end === data_block.length) throw new SecurityError('decryption failed');
+
+ this.rsa.result = data_block.subarray(ps_end + 1);
+
+ return new Uint8Array(this.rsa.result);
+ }
+
+ RSA_MGF1_generate(seed: Uint8Array, length: number = 0): Uint8Array {
+ const hash_size = this.hash.HASH_SIZE;
+ // if ( length > (hash_size * 0x100000000) )
+ // throw new IllegalArgumentError("mask length too large");
+
+ const mask = new Uint8Array(length);
+ const counter = new Uint8Array(4);
+ const chunks = Math.ceil(length / hash_size);
+ for (let i = 0; i < chunks; i++) {
+ (counter[0] = i >>> 24), (counter[1] = (i >>> 16) & 255), (counter[2] = (i >>> 8) & 255), (counter[3] = i & 255);
+
+ const submask = mask.subarray(i * hash_size);
+
+ let chunk = this.hash
+ .reset()
+ .process(seed)
+ .process(counter)
+ .finish().result as Uint8Array;
+ if (chunk.length > submask.length) chunk = chunk.subarray(0, submask.length);
+
+ submask.set(chunk);
+ }
+
+ return mask;
+ }
+}
+
+export class RSA_PSS {
+ private readonly rsa: RSA;
+ private readonly saltLength: number;
+ private readonly hash: Sha1 | Sha256 | Sha512;
+
+ constructor(key: Uint8Array[], hash: Sha1 | Sha256 | Sha512, saltLength: number = 4) {
+ this.rsa = new RSA(key);
+
+ this.hash = hash;
+ this.saltLength = saltLength;
+
+ if (this.saltLength < 0) throw new TypeError('saltLength should be a non-negative number');
+
+ if (
+ this.rsa.key !== null &&
+ Math.ceil((this.rsa.key[0].bitLength - 1) / 8) < this.hash.HASH_SIZE + this.saltLength + 2
+ )
+ throw new SyntaxError('saltLength is too large');
+ }
+
+ sign(data: Uint8Array): Uint8Array {
+ const key_bits = this.rsa.key[0].bitLength;
+ const hash_size = this.hash.HASH_SIZE;
+ const message_length = Math.ceil((key_bits - 1) / 8);
+ const salt_length = this.saltLength;
+ const ps_length = message_length - salt_length - hash_size - 2;
+
+ const message = new Uint8Array(message_length);
+ const h_block = message.subarray(message_length - hash_size - 1, message_length - 1);
+ const d_block = message.subarray(0, message_length - hash_size - 1);
+ const d_salt = d_block.subarray(ps_length + 1);
+
+ const m_block = new Uint8Array(8 + hash_size + salt_length);
+ const m_hash = m_block.subarray(8, 8 + hash_size);
+ const m_salt = m_block.subarray(8 + hash_size);
+
+ m_hash.set(this.hash.process(data).finish().result as Uint8Array);
+
+ if (salt_length > 0) getRandomValues(m_salt);
+
+ d_block[ps_length] = 1;
+ d_salt.set(m_salt);
+
+ h_block.set(this.hash
+ .reset()
+ .process(m_block)
+ .finish().result as Uint8Array);
+
+ const d_block_mask = this.RSA_MGF1_generate(h_block, d_block.length);
+ for (let i = 0; i < d_block.length; i++) d_block[i] ^= d_block_mask[i];
+
+ message[message_length - 1] = 0xbc;
+
+ const zbits = 8 * message_length - key_bits + 1;
+ if (zbits % 8) message[0] &= 0xff >>> zbits;
+
+ this.rsa.decrypt(new BigNumber(message));
+
+ return this.rsa.result;
+ }
+
+ verify(signature: Uint8Array, data: Uint8Array): void {
+ const key_bits = this.rsa.key[0].bitLength;
+ const hash_size = this.hash.HASH_SIZE;
+ const message_length = Math.ceil((key_bits - 1) / 8);
+ const salt_length = this.saltLength;
+ const ps_length = message_length - salt_length - hash_size - 2;
+
+ this.rsa.encrypt(new BigNumber(signature));
+
+ const message = this.rsa.result;
+ if (message[message_length - 1] !== 0xbc) throw new SecurityError('bad signature');
+
+ const h_block = message.subarray(message_length - hash_size - 1, message_length - 1);
+ const d_block = message.subarray(0, message_length - hash_size - 1);
+ const d_salt = d_block.subarray(ps_length + 1);
+
+ const zbits = 8 * message_length - key_bits + 1;
+ if (zbits % 8 && message[0] >>> (8 - zbits)) throw new SecurityError('bad signature');
+
+ const d_block_mask = this.RSA_MGF1_generate(h_block, d_block.length);
+ for (let i = 0; i < d_block.length; i++) d_block[i] ^= d_block_mask[i];
+
+ if (zbits % 8) message[0] &= 0xff >>> zbits;
+
+ for (let i = 0; i < ps_length; i++) {
+ if (d_block[i] !== 0) throw new SecurityError('bad signature');
+ }
+ if (d_block[ps_length] !== 1) throw new SecurityError('bad signature');
+
+ const m_block = new Uint8Array(8 + hash_size + salt_length);
+ const m_hash = m_block.subarray(8, 8 + hash_size);
+ const m_salt = m_block.subarray(8 + hash_size);
+
+ m_hash.set(this.hash
+ .reset()
+ .process(data)
+ .finish().result as Uint8Array);
+ m_salt.set(d_salt);
+
+ const h_block_verify = this.hash
+ .reset()
+ .process(m_block)
+ .finish().result as Uint8Array;
+ for (let i = 0; i < hash_size; i++) {
+ if (h_block[i] !== h_block_verify[i]) throw new SecurityError('bad signature');
+ }
+ }
+
+ RSA_MGF1_generate(seed: Uint8Array, length: number = 0): Uint8Array {
+ const hash_size = this.hash.HASH_SIZE;
+ // if ( length > (hash_size * 0x100000000) )
+ // throw new IllegalArgumentError("mask length too large");
+
+ const mask = new Uint8Array(length);
+ const counter = new Uint8Array(4);
+ const chunks = Math.ceil(length / hash_size);
+ for (let i = 0; i < chunks; i++) {
+ (counter[0] = i >>> 24), (counter[1] = (i >>> 16) & 255), (counter[2] = (i >>> 8) & 255), (counter[3] = i & 255);
+
+ const submask = mask.subarray(i * hash_size);
+
+ let chunk = this.hash
+ .reset()
+ .process(seed)
+ .process(counter)
+ .finish().result as Uint8Array;
+ if (chunk.length > submask.length) chunk = chunk.subarray(0, submask.length);
+
+ submask.set(chunk);
+ }
+
+ return mask;
+ }
+}
+
+export class RSA_PKCS1_v1_5 {
+ private readonly rsa: RSA;
+ private readonly hash: Sha1 | Sha256 | Sha512;
+ constructor(key: Uint8Array[], hash: Sha1 | Sha256 | Sha512) {
+ this.rsa = new RSA(key);
+ this.hash = hash;
+ }
+
+ sign(data: Uint8Array): Uint8Array {
+ if (!this.rsa.key) {
+ throw new IllegalStateError('no key is associated with the instance');
+ }
+ const prefix = getHashPrefix(this.hash);
+ const hash_size = this.hash.HASH_SIZE;
+
+ const t_len = prefix.length + hash_size;
+ const k = (this.rsa.key[0].bitLength + 7) >> 3;
+ if (k < t_len + 11) {
+ throw new Error('Message too long');
+ }
+
+ const m_hash = new Uint8Array(hash_size);
+ m_hash.set(this.hash.process(data).finish().result as Uint8Array);
+
+ // EM = 0x00 || 0x01 || PS || 0x00 || T
+ const em = new Uint8Array(k);
+ let i = 0;
+ em[i++] = 0; // 0x00
+ em[i++] = 1; // 0x01
+ // PS
+ for (i; i < k - t_len - 1; i++) {
+ em[i] = 0xff;
+ }
+ em[i++] = 0;
+ em.set(prefix, i); // 0x00
+ // T
+ em.set(m_hash, em.length - hash_size);
+
+ this.rsa.decrypt(new BigNumber(em));
+
+ return this.rsa.result;
+ }
+
+ verify(signature: Uint8Array, data: Uint8Array): void {
+ const prefix = getHashPrefix(this.hash);
+ const hash_size = this.hash.HASH_SIZE;
+
+ const t_len = prefix.length + hash_size;
+ const k = (this.rsa.key[0].bitLength + 7) >> 3;
+ if (k < t_len + 11) {
+ throw new SecurityError('Bad signature');
+ }
+
+ this.rsa.encrypt(new BigNumber(signature));
+
+ const m_hash = new Uint8Array(hash_size);
+ m_hash.set(this.hash.process(data).finish().result as Uint8Array);
+
+ let res = 1;
+ // EM = 0x00 || 0x01 || PS || 0x00 || T
+ const decryptedSignature = this.rsa.result;
+ let i = 0;
+ res &= decryptedSignature[i++] === 0 ? 1 : 0; // 0x00
+ res &= decryptedSignature[i++] === 1 ? 1 : 0; // 0x01
+ // PS
+ for (i; i < k - t_len - 1; i++) {
+ res &= decryptedSignature[i] === 0xff ? 1 : 0;
+ }
+ res &= decryptedSignature[i++] === 0 ? 1 : 0; // 0x00
+ // T
+ let j = 0;
+ let n = i + prefix.length;
+ // prefix
+ for (i; i < n; i++) {
+ res &= decryptedSignature[i] === prefix[j++] ? 1 : 0;
+ }
+ j = 0;
+ n = i + m_hash.length;
+ // hash
+ for (i; i < n; i++) {
+ res &= decryptedSignature[i] === m_hash[j++] ? 1 : 0;
+ }
+
+ if (!res) {
+ throw new SecurityError('Bad signature');
+ }
+ }
+}
+
+const HASH_PREFIXES: {
+ sha1: Uint8Array;
+ sha256: Uint8Array;
+ sha384: Uint8Array;
+ sha512: Uint8Array;
+ [key: string]: Uint8Array;
+} = {
+ sha1: new Uint8Array([0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14]),
+ sha256: new Uint8Array([
+ 0x30,
+ 0x31,
+ 0x30,
+ 0x0d,
+ 0x06,
+ 0x09,
+ 0x60,
+ 0x86,
+ 0x48,
+ 0x01,
+ 0x65,
+ 0x03,
+ 0x04,
+ 0x02,
+ 0x01,
+ 0x05,
+ 0x00,
+ 0x04,
+ 0x20,
+ ]),
+ sha384: new Uint8Array([
+ 0x30,
+ 0x41,
+ 0x30,
+ 0x0d,
+ 0x06,
+ 0x09,
+ 0x60,
+ 0x86,
+ 0x48,
+ 0x01,
+ 0x65,
+ 0x03,
+ 0x04,
+ 0x02,
+ 0x02,
+ 0x05,
+ 0x00,
+ 0x04,
+ 0x30,
+ ]),
+ sha512: new Uint8Array([
+ 0x30,
+ 0x51,
+ 0x30,
+ 0x0d,
+ 0x06,
+ 0x09,
+ 0x60,
+ 0x86,
+ 0x48,
+ 0x01,
+ 0x65,
+ 0x03,
+ 0x04,
+ 0x02,
+ 0x03,
+ 0x05,
+ 0x00,
+ 0x04,
+ 0x40,
+ ]),
+};
+
+function getHashPrefix(hash: Sha1 | Sha256 | Sha512): Uint8Array {
+ const prefix = HASH_PREFIXES[hash.NAME];
+ if (!prefix) {
+ throw new Error("Cannot get hash prefix for hash algorithm '" + hash.NAME + "'");
+ }
+ return prefix;
+}
diff --git a/src/rsa/raw.js b/src/rsa/raw.js
deleted file mode 100644
index 684ec4e..0000000
--- a/src/rsa/raw.js
+++ /dev/null
@@ -1,3 +0,0 @@
-import { RSA } from './rsa';
-
-export default RSA;
diff --git a/src/rsa/rsa.js b/src/rsa/rsa.js
deleted file mode 100644
index 15ebe30..0000000
--- a/src/rsa/rsa.js
+++ /dev/null
@@ -1,147 +0,0 @@
-import { BigNumber, is_big_number, Modulus } from '../bignum/bignum';
-import { is_buffer, is_bytes, is_string, string_to_bytes } from '../utils';
-import { IllegalStateError } from '../errors';
-
-export function RSA(options) {
- options = options || {};
-
- this.key = null;
- this.result = null;
-
- this.reset(options);
-}
-
-export function RSA_reset(options) {
- options = options || {};
-
- this.result = null;
-
- var key = options.key;
- if (key !== undefined) {
- if (key instanceof Array) {
- var l = key.length;
- if (l !== 2 && l !== 3 && l !== 8) throw new SyntaxError('unexpected key type');
-
- var k = [];
- k[0] = new Modulus(new BigNumber(key[0]));
- k[1] = new BigNumber(key[1]);
- if (l > 2) {
- k[2] = new BigNumber(key[2]);
- }
- if (l > 3) {
- k[3] = new Modulus(new BigNumber(key[3]));
- k[4] = new Modulus(new BigNumber(key[4]));
- k[5] = new BigNumber(key[5]);
- k[6] = new BigNumber(key[6]);
- k[7] = new BigNumber(key[7]);
- }
-
- this.key = k;
- } else {
- throw new TypeError('unexpected key type');
- }
- }
-
- return this;
-}
-
-export function RSA_encrypt(data) {
- if (!this.key) throw new IllegalStateError('no key is associated with the instance');
-
- if (is_string(data)) data = string_to_bytes(data);
-
- if (is_buffer(data)) data = new Uint8Array(data);
-
- var msg;
- if (is_bytes(data)) {
- msg = new BigNumber(data);
- } else if (is_big_number(data)) {
- msg = data;
- } else {
- throw new TypeError('unexpected data type');
- }
-
- if (this.key[0].compare(msg) <= 0) throw new RangeError('data too large');
-
- var m = this.key[0],
- e = this.key[1];
-
- var result = m.power(msg, e).toBytes();
-
- var bytelen = (m.bitLength + 7) >> 3;
- if (result.length < bytelen) {
- var r = new Uint8Array(bytelen);
- r.set(result, bytelen - result.length);
- result = r;
- }
-
- this.result = result;
-
- return this;
-}
-
-export function RSA_decrypt(data) {
- if (!this.key) throw new IllegalStateError('no key is associated with the instance');
-
- if (this.key.length < 3) throw new IllegalStateError("key isn't suitable for decription");
-
- if (is_string(data)) data = string_to_bytes(data);
-
- if (is_buffer(data)) data = new Uint8Array(data);
-
- var msg;
- if (is_bytes(data)) {
- msg = new BigNumber(data);
- } else if (is_big_number(data)) {
- msg = data;
- } else {
- throw new TypeError('unexpected data type');
- }
-
- if (this.key[0].compare(msg) <= 0) throw new RangeError('data too large');
-
- var result;
- if (this.key.length > 3) {
- var m = this.key[0],
- p = this.key[3],
- q = this.key[4],
- dp = this.key[5],
- dq = this.key[6],
- u = this.key[7];
-
- var x = p.power(msg, dp),
- y = q.power(msg, dq);
-
- var t = x.subtract(y);
- while (t.sign < 0) t = t.add(p);
-
- var h = p.reduce(u.multiply(t));
-
- result = h
- .multiply(q)
- .add(y)
- .clamp(m.bitLength)
- .toBytes();
- } else {
- var m = this.key[0],
- d = this.key[2];
-
- result = m.power(msg, d).toBytes();
- }
-
- var bytelen = (m.bitLength + 7) >> 3;
- if (result.length < bytelen) {
- var r = new Uint8Array(bytelen);
- r.set(result, bytelen - result.length);
- result = r;
- }
-
- this.result = result;
-
- return this;
-}
-
-var RSA_prototype = RSA.prototype;
-RSA_prototype.reset = RSA_reset;
-RSA_prototype.encrypt = RSA_encrypt;
-RSA_prototype.decrypt = RSA_decrypt;
diff --git a/src/rsa/rsa.ts b/src/rsa/rsa.ts
new file mode 100644
index 0000000..8473866
--- /dev/null
+++ b/src/rsa/rsa.ts
@@ -0,0 +1,107 @@
+import { BigNumber, Modulus } from '../bignum/bignum';
+import { IllegalStateError } from '../other/errors';
+
+export type key = {
+ 0: Modulus;
+ 1: BigNumber;
+ 2?: BigNumber;
+ 3?: Modulus;
+ 4?: Modulus;
+ 5?: BigNumber;
+ 6?: BigNumber;
+ 7?: BigNumber;
+};
+
+export class RSA {
+ public readonly key: key;
+ public result!: Uint8Array;
+
+ constructor(key: Uint8Array[]) {
+ const l = key.length;
+ if (l !== 2 && l !== 3 && l !== 8) throw new SyntaxError('unexpected key type');
+
+ const k0 = new Modulus(new BigNumber(key[0]));
+ const k1 = new BigNumber(key[1]);
+ this.key = {
+ 0: k0,
+ 1: k1,
+ };
+ if (l > 2) {
+ this.key[2] = new BigNumber(key[2]);
+ }
+ if (l > 3) {
+ this.key[3] = new Modulus(new BigNumber(key[3]));
+ this.key[4] = new Modulus(new BigNumber(key[4]));
+ this.key[5] = new BigNumber(key[5]);
+ this.key[6] = new BigNumber(key[6]);
+ this.key[7] = new BigNumber(key[7]);
+ }
+ }
+
+ encrypt(msg: BigNumber): this {
+ if (!this.key) throw new IllegalStateError('no key is associated with the instance');
+
+ if (this.key[0].compare(msg) <= 0) throw new RangeError('data too large');
+
+ const m = this.key[0];
+ const e = this.key[1];
+
+ let result = m.power(msg, e).toBytes();
+
+ const bytelen = (m.bitLength + 7) >> 3;
+ if (result.length < bytelen) {
+ const r = new Uint8Array(bytelen);
+ r.set(result, bytelen - result.length);
+ result = r;
+ }
+
+ this.result = result;
+
+ return this;
+ }
+
+ decrypt(msg: BigNumber): this {
+ if (this.key[0].compare(msg) <= 0) throw new RangeError('data too large');
+
+ let result;
+ let m;
+ if (this.key[3] !== undefined) {
+ m = this.key[0] as BigNumber;
+ const p = this.key[3] as Modulus;
+ const q = this.key[4] as Modulus;
+ const dp = this.key[5] as BigNumber;
+ const dq = this.key[6] as BigNumber;
+ const u = this.key[7] as BigNumber;
+
+ const x = p.power(msg, dp);
+ const y = q.power(msg, dq);
+
+ let t = x.subtract(y);
+ while (t.sign < 0) t = t.add(p);
+
+ const h = p.reduce(u.multiply(t));
+
+ result = h
+ .multiply(q)
+ .add(y)
+ .clamp(m.bitLength)
+ .toBytes();
+ } else {
+ m = this.key[0];
+ const d = this.key[2] as BigNumber;
+
+ result = m.power(msg, d).toBytes();
+ }
+
+ const bytelen = (m.bitLength + 7) >> 3;
+ if (result.length < bytelen) {
+ let r = new Uint8Array(bytelen);
+ r.set(result, bytelen - result.length);
+ result = r;
+ }
+
+ this.result = result;
+
+ return this;
+ }
+}
diff --git a/test/aes.js b/test/aes.js
index 8a8379a..77a62cd 100644
--- a/test/aes.js
+++ b/test/aes.js
@@ -1,1008 +1,708 @@
-module("AES");
-
-Uint32Array.prototype.map = Array.prototype.map;
-
-///////////////////////////////////////////////////////////////////////////////
-
-//
-// Asm.js module test
-//
-
-testIf( typeof AES_asm !== 'undefined', "Asm.js module", function () {
- AES_asm = AES_asm.AES_asm;
- var heap = new Uint8Array(65536);
- var keys = new Uint32Array(heap.buffer);
- var aes = AES_asm( null, heap.buffer );
-
- // data block
- heap.set( asmCrypto.hex_to_bytes('00112233445566778899aabbccddeeff'), AES_asm.HEAP_DATA );
-
- //
- // AES-128
- //
-
- aes.set_key( 4, 0x00010203, 0x04050607, 0x08090a0b, 0x0c0d0e0f );
-
- deepEqual(
- keys.subarray( 0, 44 ).map( function (x) { return x } ),
- [
- 0x00010203, 0x04050607, 0x08090a0b, 0x0c0d0e0f,
- 0xd6aa74fd, 0xd2af72fa, 0xdaa678f1, 0xd6ab76fe,
- 0xb692cf0b, 0x643dbdf1, 0xbe9bc500, 0x6830b3fe,
- 0xb6ff744e, 0xd2c2c9bf, 0x6c590cbf, 0x0469bf41,
- 0x47f7f7bc, 0x95353e03, 0xf96c32bc, 0xfd058dfd,
- 0x3caaa3e8, 0xa99f9deb, 0x50f3af57, 0xadf622aa,
- 0x5e390f7d, 0xf7a69296, 0xa7553dc1, 0x0aa31f6b,
- 0x14f9701a, 0xe35fe28c, 0x440adf4d, 0x4ea9c026,
- 0x47438735, 0xa41c65b9, 0xe016baf4, 0xaebf7ad2,
- 0x549932d1, 0xf0855768, 0x1093ed9c, 0xbe2c974e,
- 0x13111d7f, 0xe3944a17, 0xf307a78b, 0x4d2b30c5
- ],
- "AES-128: encryption key schedule ok"
- );
-
- deepEqual(
- keys.subarray( 0x100, 0x100+44 ).map( function (x) { return x } ),
- [
- 0x13111d7f, 0x4d2b30c5, 0xf307a78b, 0xe3944a17,
- 0x13aa29be, 0x00f7bf03, 0xf770f580, 0x9c8faff6,
- 0x1362a463, 0xf7874a83, 0x6bff5a76, 0x8f258648,
- 0x8d82fc74, 0x9c7810f5, 0xe4dadc3e, 0x9c47222b,
- 0x72e3098d, 0x78a2cccb, 0x789dfe15, 0x11c5de5f,
- 0x2ec41027, 0x003f32de, 0x6958204a, 0x6326d7d2,
- 0xa8a2f504, 0x69671294, 0x0a7ef798, 0x4de2c7f5,
- 0xc7c6e391, 0x6319e50c, 0x479c306d, 0xe54032f1,
- 0xa0db0299, 0x2485d561, 0xa2dc029c, 0x2286d160,
- 0x8c56dff0, 0x8659d7fd, 0x805ad3fc, 0x825dd3f9,
- 0x00010203, 0x0c0d0e0f, 0x08090a0b, 0x04050607
- ],
- "AES-128: decryption key schedule ok"
- );
-
- aes.cipher( AES_asm.ENC.ECB, AES_asm.HEAP_DATA, 16 );
-
- equal(
- asmCrypto.bytes_to_hex( heap.subarray( AES_asm.HEAP_DATA, AES_asm.HEAP_DATA+16 ) ),
- '69c4e0d86a7b0430d8cdb78070b4c55a',
- "AES-128: encrypt ok"
- );
-
- aes.cipher( AES_asm.DEC.ECB, AES_asm.HEAP_DATA, 16 );
-
- equal(
- asmCrypto.bytes_to_hex( heap.subarray( AES_asm.HEAP_DATA, AES_asm.HEAP_DATA+16 ) ),
- '00112233445566778899aabbccddeeff',
- "AES-128: decrypt ok"
- );
-
- //
- // AES-192
- //
-
- aes.set_key( 6, 0x00010203, 0x04050607, 0x08090a0b, 0x0c0d0e0f, 0x10111213, 0x14151617 );
-
- deepEqual(
- keys.subarray( 0, 52 ).map( function (x) { return x } ),
- [
- 0x00010203, 0x04050607, 0x08090a0b, 0x0c0d0e0f,
- 0x10111213, 0x14151617, 0x5846f2f9, 0x5c43f4fe,
- 0x544afef5, 0x5847f0fa, 0x4856e2e9, 0x5c43f4fe,
- 0x40f949b3, 0x1cbabd4d, 0x48f043b8, 0x10b7b342,
- 0x58e151ab, 0x04a2a555, 0x7effb541, 0x6245080c,
- 0x2ab54bb4, 0x3a02f8f6, 0x62e3a95d, 0x66410c08,
- 0xf5018572, 0x97448d7e, 0xbdf1c6ca, 0x87f33e3c,
- 0xe5109761, 0x83519b69, 0x34157c9e, 0xa351f1e0,
- 0x1ea0372a, 0x99530916, 0x7c439e77, 0xff12051e,
- 0xdd7e0e88, 0x7e2fff68, 0x608fc842, 0xf9dcc154,
- 0x859f5f23, 0x7a8d5a3d, 0xc0c02952, 0xbeefd63a,
- 0xde601e78, 0x27bcdf2c, 0xa223800f, 0xd8aeda32,
- 0xa4970a33, 0x1a78dc09, 0xc418c271, 0xe3a41d5d
- ],
- "AES-192: encryption key schedule ok"
- );
-
- deepEqual(
- keys.subarray( 0x100, 0x100+52 ).map( function (x) { return x } ),
- [
- 0xa4970a33, 0xe3a41d5d, 0xc418c271, 0x1a78dc09,
- 0xd6bebd0d, 0x3e021bb9, 0x4db07380, 0xc209ea49,
- 0x8fb999c9, 0x85c68c72, 0xc7f9d89d, 0x73b26839,
- 0xf77d6ec1, 0x14b75744, 0x5378317f, 0x423f54ef,
- 0x11476590, 0xfc0bf1f0, 0x9b0ece8d, 0x47cf663b,
- 0xdcc1a8b6, 0xb5423a2e, 0xcc5c194a, 0x67053f7d,
- 0xc6deb0ab, 0x568803ab, 0xa4055fbe, 0x791e2364,
- 0xdd1b7cda, 0xbbc497cb, 0x8a49ab1d, 0xf28d5c15,
- 0x78c4f708, 0xbfc093cf, 0x9655b701, 0x318d3cd6,
- 0x60dcef10, 0x2f9620cf, 0x62dbef15, 0x299524ce,
- 0x4b4ecbdb, 0x4949cbde, 0x5752d7c7, 0x4d4dcfda,
- 0x1a1f181d, 0x4949cbde, 0x4742c7d7, 0x1e1b1c19,
- 0x00010203, 0x0c0d0e0f, 0x08090a0b, 0x04050607
- ],
- "AES-192: decryption key schedule ok"
- );
-
- aes.cipher( AES_asm.ENC.ECB, AES_asm.HEAP_DATA, 16 );
-
- equal(
- asmCrypto.bytes_to_hex( heap.subarray( AES_asm.HEAP_DATA, AES_asm.HEAP_DATA+16 ) ),
- 'dda97ca4864cdfe06eaf70a0ec0d7191',
- "AES-192: encrypt ok"
- );
-
- aes.cipher( AES_asm.DEC.ECB, AES_asm.HEAP_DATA, 16 );
-
- equal(
- asmCrypto.bytes_to_hex( heap.subarray( AES_asm.HEAP_DATA, AES_asm.HEAP_DATA+16 ) ),
- '00112233445566778899aabbccddeeff',
- "AES-192: decrypt ok"
- );
-
- //
- // AES-256
- //
-
- aes.set_key( 8, 0x00010203, 0x04050607, 0x08090a0b, 0x0c0d0e0f, 0x10111213, 0x14151617, 0x18191a1b, 0x1c1d1e1f );
-
- deepEqual(
- keys.subarray( 0, 60 ).map( function (x) { return x } ),
- [
- 0x00010203, 0x04050607, 0x08090a0b, 0x0c0d0e0f,
- 0x10111213, 0x14151617, 0x18191a1b, 0x1c1d1e1f,
- 0xa573c29f, 0xa176c498, 0xa97fce93, 0xa572c09c,
- 0x1651a8cd, 0x0244beda, 0x1a5da4c1, 0x0640bade,
- 0xae87dff0, 0x0ff11b68, 0xa68ed5fb, 0x03fc1567,
- 0x6de1f148, 0x6fa54f92, 0x75f8eb53, 0x73b8518d,
- 0xc656827f, 0xc9a79917, 0x6f294cec, 0x6cd5598b,
- 0x3de23a75, 0x524775e7, 0x27bf9eb4, 0x5407cf39,
- 0x0bdc905f, 0xc27b0948, 0xad5245a4, 0xc1871c2f,
- 0x45f5a660, 0x17b2d387, 0x300d4d33, 0x640a820a,
- 0x7ccff71c, 0xbeb4fe54, 0x13e6bbf0, 0xd261a7df,
- 0xf01afafe, 0xe7a82979, 0xd7a5644a, 0xb3afe640,
- 0x2541fe71, 0x9bf50025, 0x8813bbd5, 0x5a721c0a,
- 0x4e5a6699, 0xa9f24fe0, 0x7e572baa, 0xcdf8cdea,
- 0x24fc79cc, 0xbf0979e9, 0x371ac23c, 0x6d68de36
- ],
- "AES-256: encryption key schedule ok"
- );
-
- deepEqual(
- keys.subarray( 0x100, 0x100+60 ).map( function (x) { return x } ),
- [
- 0x24fc79cc, 0x6d68de36, 0x371ac23c, 0xbf0979e9,
- 0x34f1d1ff, 0x2558016e, 0xfce9e25f, 0xbfceaa2f,
- 0x5e1648eb, 0xdc80e684, 0x7571b746, 0x384c350a,
- 0xc8a30580, 0xd9b1e331, 0x43274870, 0x8b3f7bd0,
- 0xb5708e13, 0xa9f151c2, 0x4d3d824c, 0x665a7de1,
- 0x74da7ba3, 0x9a96ab41, 0xc81833a0, 0x439c7e50,
- 0x3ca69715, 0xe4ccd38e, 0x2b67ffad, 0xd32af3f2,
- 0xf85fc4f3, 0x528e98e1, 0x8b844df0, 0x374605f3,
- 0xde69409a, 0xcfab2c23, 0xf84d0c5f, 0xef8c64e7,
- 0xaed55816, 0xd90ad511, 0xbcc24803, 0xcf19c100,
- 0x15c668bd, 0x37e6207c, 0x17c168b8, 0x31e5247d,
- 0x7fd7850f, 0x65c89d12, 0x73db8903, 0x61cc9916,
- 0x2a2840c9, 0x202748c4, 0x26244cc5, 0x24234cc0,
- 0x1a1f181d, 0x16131411, 0x12171015, 0x1e1b1c19,
- 0x00010203, 0x0c0d0e0f, 0x08090a0b, 0x04050607
- ],
- "AES-256: decryption key schedule ok"
- );
-
- aes.cipher( AES_asm.ENC.ECB, AES_asm.HEAP_DATA, 16 );
-
- equal(
- asmCrypto.bytes_to_hex( heap.subarray( AES_asm.HEAP_DATA, AES_asm.HEAP_DATA+16 ) ),
- '8ea2b7ca516745bfeafc49904b496089',
- "AES-256: encrypt ok"
- );
-
- aes.cipher( AES_asm.DEC.ECB, AES_asm.HEAP_DATA, 16 );
-
- equal(
- asmCrypto.bytes_to_hex( heap.subarray( AES_asm.HEAP_DATA, AES_asm.HEAP_DATA+16 ) ),
- '00112233445566778899aabbccddeeff',
- "AES-256: decrypt ok"
- );
-});
-
-///////////////////////////////////////////////////////////////////////////////
-
-if ( typeof asmCrypto.AES_ECB !== 'undefined' )
-{
- var ecb_aes_vectors = [
- // AES-ECB-128
- [
- '2b7e151628aed2a6abf7158809cf4f3c', // key
- '6bc1bee22e409f96e93d7e117393172a', // clear text
- '3ad77bb40d7a3660a89ecaf32466ef97' // cipher text
- ],
- [
- '2b7e151628aed2a6abf7158809cf4f3c', // key
- 'ae2d8a571e03ac9c9eb76fac45af8e51', // clear text
- 'f5d3d58503b9699de785895a96fdbaaf' // cipher text
- ],
- [
- '2b7e151628aed2a6abf7158809cf4f3c', // key
- '30c81c46a35ce411e5fbc1191a0a52ef', // clear text
- '43b1cd7f598ece23881b00e3ed030688' // cipher text
- ],
- [
- '2b7e151628aed2a6abf7158809cf4f3c', // key
- 'f69f2445df4f9b17ad2b417be66c3710', // clear text
- '7b0c785e27e8ad3f8223207104725dd4' // cipher text
- ],
- [ // Two blocks
- '2b7e151628aed2a6abf7158809cf4f3c', // key
- 'f69f2445df4f9b17ad2b417be66c3710f69f2445df4f9b17ad2b417be66c3710', // clear text
- '7b0c785e27e8ad3f8223207104725dd47b0c785e27e8ad3f8223207104725dd4' // cipher text
- ],
- // AES-ECB-256
- [
- '603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4', // key
- '6bc1bee22e409f96e93d7e117393172a', // clear text
- 'f3eed1bdb5d2a03c064b5a7e3db181f8' // cipher text
- ],
- [
- '603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4', // key
- 'ae2d8a571e03ac9c9eb76fac45af8e51', // clear text
- '591ccb10d410ed26dc5ba74a31362870' // cipher text
- ],
- [
- '603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4', // key
- '30c81c46a35ce411e5fbc1191a0a52ef', // clear text
- 'b6ed21b99ca6f4f9f153e7b1beafed1d' // cipher text
- ],
- [ // Two blocks
- '603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4', // key
- '30c81c46a35ce411e5fbc1191a0a52ef30c81c46a35ce411e5fbc1191a0a52ef', // clear text
- 'b6ed21b99ca6f4f9f153e7b1beafed1db6ed21b99ca6f4f9f153e7b1beafed1d' // cipher text
- ],
- [
- '603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4', // key
- 'f69f2445df4f9b17ad2b417be66c3710', // clear text
- '23304b7a39f9f3ff067d8d8f9e24ecc7' // cipher text
- ]
- ];
-
- test( "asmCrypto.AES_ECB.encrypt / asmCrypto.AES_ECB.decrypt", function () {
- for ( var i = 0; i < ecb_aes_vectors.length; ++i ) {
- var key = new Uint8Array( asmCrypto.hex_to_bytes(ecb_aes_vectors[i][0]) ),
- clear = new Uint8Array( asmCrypto.hex_to_bytes(ecb_aes_vectors[i][1]) ),
- cipher = new Uint8Array( asmCrypto.hex_to_bytes(ecb_aes_vectors[i][2]) );
-
- equal(
- asmCrypto.bytes_to_hex( asmCrypto.AES_ECB.encrypt( clear, key ) ),
- asmCrypto.bytes_to_hex(cipher),
- "encrypt vector " + i
- );
-
- equal(
- asmCrypto.bytes_to_hex( asmCrypto.AES_ECB.decrypt( cipher, key ) ),
- asmCrypto.bytes_to_hex(clear),
- "decrypt vector " + i
- );
- }
- });
-}
-else
-{
- skip( "asmCrypto.AES_ECB" );
-}
-
-if ( typeof asmCrypto.AES_CBC !== 'undefined' )
-{
- var cbc_aes_vectors = [
- [ // key
- [ 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c ],
- // iv
- [ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f ],
- // clear text
- [ 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
- 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
- 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
- 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10 ],
- // cipher text
- [ 0x76, 0x49, 0xab, 0xac, 0x81, 0x19, 0xb2, 0x46, 0xce, 0xe9, 0x8e, 0x9b, 0x12, 0xe9, 0x19, 0x7d,
- 0x50, 0x86, 0xcb, 0x9b, 0x50, 0x72, 0x19, 0xee, 0x95, 0xdb, 0x11, 0x3a, 0x91, 0x76, 0x78, 0xb2,
- 0x73, 0xbe, 0xd6, 0xb8, 0xe3, 0xc1, 0x74, 0x3b, 0x71, 0x16, 0xe6, 0x9e, 0x22, 0x22, 0x95, 0x16,
- 0x3f, 0xf1, 0xca, 0xa1, 0x68, 0x1f, 0xac, 0x09, 0x12, 0x0e, 0xca, 0x30, 0x75, 0x86, 0xe1, 0xa7 ]
- ],
- [ // key
- [ 0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe, 0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81,
- 0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7, 0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4 ],
- // iv
- [ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f ],
- // clear text
- [ 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
- 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
- 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
- 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10 ],
- // cipher text
- [ 0xf5, 0x8c, 0x4c, 0x04, 0xd6, 0xe5, 0xf1, 0xba, 0x77, 0x9e, 0xab, 0xfb, 0x5f, 0x7b, 0xfb, 0xd6,
- 0x9c, 0xfc, 0x4e, 0x96, 0x7e, 0xdb, 0x80, 0x8d, 0x67, 0x9f, 0x77, 0x7b, 0xc6, 0x70, 0x2c, 0x7d,
- 0x39, 0xf2, 0x33, 0x69, 0xa9, 0xd9, 0xba, 0xcf, 0xa5, 0x30, 0xe2, 0x63, 0x04, 0x23, 0x14, 0x61,
- 0xb2, 0xeb, 0x05, 0xe2, 0xc3, 0x9b, 0xe9, 0xfc, 0xda, 0x6c, 0x19, 0x07, 0x8c, 0x6a, 0x9d, 0x1b ]
- ]
+import * as asmCrypto from '../asmcrypto.all.es8';
+import chai from 'chai';
+const expect = chai.expect;
+
+describe('AES', () => {
+ describe('ECB', () => {
+ const ecb_aes_vectors = [
+ // AES-ECB-128
+ [
+ '2b7e151628aed2a6abf7158809cf4f3c', // key
+ '6bc1bee22e409f96e93d7e117393172a', // clear text
+ '3ad77bb40d7a3660a89ecaf32466ef97', // cipher text
+ ],
+ [
+ '2b7e151628aed2a6abf7158809cf4f3c', // key
+ 'ae2d8a571e03ac9c9eb76fac45af8e51', // clear text
+ 'f5d3d58503b9699de785895a96fdbaaf', // cipher text
+ ],
+ [
+ '2b7e151628aed2a6abf7158809cf4f3c', // key
+ '30c81c46a35ce411e5fbc1191a0a52ef', // clear text
+ '43b1cd7f598ece23881b00e3ed030688', // cipher text
+ ],
+ [
+ '2b7e151628aed2a6abf7158809cf4f3c', // key
+ 'f69f2445df4f9b17ad2b417be66c3710', // clear text
+ '7b0c785e27e8ad3f8223207104725dd4', // cipher text
+ ],
+ [
+ // Two blocks
+ '2b7e151628aed2a6abf7158809cf4f3c', // key
+ 'f69f2445df4f9b17ad2b417be66c3710f69f2445df4f9b17ad2b417be66c3710', // clear text
+ '7b0c785e27e8ad3f8223207104725dd47b0c785e27e8ad3f8223207104725dd4', // cipher text
+ ],
+ // AES-ECB-256
+ [
+ '603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4', // key
+ '6bc1bee22e409f96e93d7e117393172a', // clear text
+ 'f3eed1bdb5d2a03c064b5a7e3db181f8', // cipher text
+ ],
+ [
+ '603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4', // key
+ 'ae2d8a571e03ac9c9eb76fac45af8e51', // clear text
+ '591ccb10d410ed26dc5ba74a31362870', // cipher text
+ ],
+ [
+ '603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4', // key
+ '30c81c46a35ce411e5fbc1191a0a52ef', // clear text
+ 'b6ed21b99ca6f4f9f153e7b1beafed1d', // cipher text
+ ],
+ [
+ // Two blocks
+ '603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4', // key
+ '30c81c46a35ce411e5fbc1191a0a52ef30c81c46a35ce411e5fbc1191a0a52ef', // clear text
+ 'b6ed21b99ca6f4f9f153e7b1beafed1db6ed21b99ca6f4f9f153e7b1beafed1d', // cipher text
+ ],
+ [
+ '603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4', // key
+ 'f69f2445df4f9b17ad2b417be66c3710', // clear text
+ '23304b7a39f9f3ff067d8d8f9e24ecc7', // cipher text
+ ],
];
- test( "asmCrypto.AES_CBC.encrypt / asmCrypto.AES_CBC.decrypt", function () {
- for ( var i = 0; i < cbc_aes_vectors.length; ++i ) {
- var key = new Uint8Array( cbc_aes_vectors[i][0] ),
- iv = new Uint8Array( cbc_aes_vectors[i][1] ),
- clear = new Uint8Array( cbc_aes_vectors[i][2] ),
- cipher = new Uint8Array( cbc_aes_vectors[i][3] );
+ it('asmCrypto.AES_ECB.encrypt / asmCrypto.AES_ECB.decrypt', function () {
+ for (let i = 0; i < ecb_aes_vectors.length; ++i) {
+ const key = new Uint8Array(asmCrypto.hex_to_bytes(ecb_aes_vectors[i][0]));
+ const clear = new Uint8Array(asmCrypto.hex_to_bytes(ecb_aes_vectors[i][1]));
+ const cipher = new Uint8Array(asmCrypto.hex_to_bytes(ecb_aes_vectors[i][2]));
- equal(
- asmCrypto.bytes_to_hex( asmCrypto.AES_CBC.encrypt( clear, key, false, iv ) ),
- asmCrypto.bytes_to_hex(cipher),
- "encrypt vector " + i
- );
+ expect(asmCrypto.AES_ECB.encrypt(clear, key), `encrypt vector ${i}`).to.deep.equal(cipher);
- equal(
- asmCrypto.bytes_to_hex( asmCrypto.AES_CBC.decrypt( cipher, key, false, iv ) ),
- asmCrypto.bytes_to_hex(clear),
- "decrypt vector " + i
- );
- }
+ expect(asmCrypto.AES_ECB.decrypt(cipher, key), `decrypt vector ${i}`).to.deep.equal(clear);
+ }
});
-}
-else
-{
- skip( "asmCrypto.AES_CBC" );
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-if ( typeof asmCrypto.AES_CTR !== 'undefined' )
-{
- var ctr_aes_vectors = [
- [
- // key
- asmCrypto.hex_to_bytes('2b7e151628aed2a6abf7158809cf4f3c'),
- // nonce
- asmCrypto.hex_to_bytes('f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff'),
- // input message
- asmCrypto.hex_to_bytes('6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710'),
- // encrypted message
- asmCrypto.hex_to_bytes('874d6191b620e3261bef6864990db6ce9806f66b7970fdff8617187bb9fffdff5ae4df3edbd5d35e5b4f09020db03eab1e031dda2fbe03d1792170a0f3009cee')
- ],
- [
- // key
- asmCrypto.hex_to_bytes('2b7e151628aed2a6abf7158809cf4f3c'),
- // nonce
- asmCrypto.hex_to_bytes('f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff'),
- // input message
- asmCrypto.hex_to_bytes('6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c'),
- // encrypted message
- asmCrypto.hex_to_bytes('874d6191b620e3261bef6864990db6ce9806f66b7970fdff8617187bb9fffdff5ae4df3edbd5d35e5b4f09020db03eab1e031dda2fbe03d1792170a0f300')
- ],
- [
- // key
- asmCrypto.hex_to_bytes('2b7e151628aed2a6abf7158809cf4f3c'),
- // nonce
- asmCrypto.hex_to_bytes('f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff'),
- // input message
- asmCrypto.hex_to_bytes('6bc1bee22e409f96e93d7e11739317'),
- // encrypted message
- asmCrypto.hex_to_bytes('874d6191b620e3261bef6864990db6')
- ],
- [
- // key
- asmCrypto.hex_to_bytes('603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4'),
- // nonce
- asmCrypto.hex_to_bytes('f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff'),
- // input message
- asmCrypto.hex_to_bytes('6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710'),
- // encrypted message
- asmCrypto.hex_to_bytes('601ec313775789a5b7a7f504bbf3d228f443e3ca4d62b59aca84e990cacaf5c52b0930daa23de94ce87017ba2d84988ddfc9c58db67aada613c2dd08457941a6')
- ]
+ });
+
+ describe('CBC', () => {
+ const cbc_aes_vectors = [
+ [ // key
+ [0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c],
+ // iv
+ [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f],
+ // clear text
+ [0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
+ 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
+ 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
+ 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10],
+ // cipher text
+ [0x76, 0x49, 0xab, 0xac, 0x81, 0x19, 0xb2, 0x46, 0xce, 0xe9, 0x8e, 0x9b, 0x12, 0xe9, 0x19, 0x7d,
+ 0x50, 0x86, 0xcb, 0x9b, 0x50, 0x72, 0x19, 0xee, 0x95, 0xdb, 0x11, 0x3a, 0x91, 0x76, 0x78, 0xb2,
+ 0x73, 0xbe, 0xd6, 0xb8, 0xe3, 0xc1, 0x74, 0x3b, 0x71, 0x16, 0xe6, 0x9e, 0x22, 0x22, 0x95, 0x16,
+ 0x3f, 0xf1, 0xca, 0xa1, 0x68, 0x1f, 0xac, 0x09, 0x12, 0x0e, 0xca, 0x30, 0x75, 0x86, 0xe1, 0xa7]
+ ],
+ [ // key
+ [0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe, 0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81,
+ 0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7, 0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4],
+ // iv
+ [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f],
+ // clear text
+ [0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
+ 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
+ 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
+ 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10],
+ // cipher text
+ [0xf5, 0x8c, 0x4c, 0x04, 0xd6, 0xe5, 0xf1, 0xba, 0x77, 0x9e, 0xab, 0xfb, 0x5f, 0x7b, 0xfb, 0xd6,
+ 0x9c, 0xfc, 0x4e, 0x96, 0x7e, 0xdb, 0x80, 0x8d, 0x67, 0x9f, 0x77, 0x7b, 0xc6, 0x70, 0x2c, 0x7d,
+ 0x39, 0xf2, 0x33, 0x69, 0xa9, 0xd9, 0xba, 0xcf, 0xa5, 0x30, 0xe2, 0x63, 0x04, 0x23, 0x14, 0x61,
+ 0xb2, 0xeb, 0x05, 0xe2, 0xc3, 0x9b, 0xe9, 0xfc, 0xda, 0x6c, 0x19, 0x07, 0x8c, 0x6a, 0x9d, 0x1b]
+ ]
];
- test( "asmCrypto.AES_CTR.encrypt / asmCrypto.AES_CTR.decrypt", function () {
- for ( var i = 0; i < ctr_aes_vectors.length; ++i ) {
- var key = new Uint8Array( ctr_aes_vectors[i][0] ),
- nonce = new Uint8Array( ctr_aes_vectors[i][1] ),
- clear = new Uint8Array( ctr_aes_vectors[i][2] ),
- cipher = new Uint8Array( ctr_aes_vectors[i][3] );
+ it('asmCrypto.AES_CBC.encrypt / asmCrypto.AES_CBC.decrypt', function () {
+ for (let i = 0; i < cbc_aes_vectors.length; ++i) {
+ const key = new Uint8Array(cbc_aes_vectors[i][0]);
+ const iv = new Uint8Array(cbc_aes_vectors[i][1]);
+ const clear = new Uint8Array(cbc_aes_vectors[i][2]);
+ const cipher = new Uint8Array(cbc_aes_vectors[i][3]);
- equal(
- asmCrypto.bytes_to_hex( asmCrypto.AES_CTR.encrypt( clear, key, nonce ) ),
- asmCrypto.bytes_to_hex(cipher),
- "encrypt vector " + i
- );
+ expect(asmCrypto.bytes_to_hex(asmCrypto.AES_CBC.encrypt(clear, key, false, iv)), `encrypt vector ${i}`).to.be.equal(asmCrypto.bytes_to_hex(cipher));
- equal(
- asmCrypto.bytes_to_hex( asmCrypto.AES_CTR.decrypt( cipher, key, nonce ) ),
- asmCrypto.bytes_to_hex(clear),
- "decrypt vector " + i
- );
- }
+ expect(asmCrypto.bytes_to_hex(asmCrypto.AES_CBC.decrypt(cipher, key, false, iv)), `decrypt vector ${i}`).to.be.equal(asmCrypto.bytes_to_hex(clear));
+ }
});
-}
-else
-{
- skip( "asmCrypto.AES_CTR" );
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-if ( typeof asmCrypto.AES_CCM !== 'undefined' )
-{
- var ccm_aes_vectors = [
- [
- // key
- new Uint8Array([ 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf ]),
- // nonce
- new Uint8Array([ 0x00, 0x00, 0x00, 0x03, 0x02, 0x01, 0x00, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5 ]),
- // adata
- new Uint8Array([ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 ]),
- // tagSize
- 8,
- // input message
- new Uint8Array([ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
- 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e ]),
- // encrypted message
- new Uint8Array([ 0x58, 0x8c, 0x97, 0x9a, 0x61, 0xc6, 0x63, 0xd2, 0xf0, 0x66, 0xd0, 0xc2, 0xc0, 0xf9, 0x89, 0x80,
- 0x6d, 0x5f, 0x6b, 0x61, 0xda, 0xc3, 0x84, 0x17, 0xe8, 0xd1, 0x2c, 0xfd, 0xf9, 0x26, 0xe0 ]),
- ],
- [
- // key
- new Uint8Array([ 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf ]),
- // nonce
- new Uint8Array([ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ]),
- // adata
- new Uint8Array([ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x61, 0x75, 0x74, 0x68, 0x69, 0x6e, 0x66, 0x6f, 0x6f ]),
- // tagSize
- 16,
- // input message
- asmCrypto.hex_to_bytes('44696420796f75206b6e6f772e2e2e0d0a46726f6d2057696b6970656469612773206e657720616e6420726563656e746c7920696d70726f76656420636f6e74656e743a0d0a5361696e74204c656f6e61726420436174686f6c69632043687572636820284d616469736f6e2c204e65627261736b61290d0a2e2e2e207468617420746865204a61636f62204d2e204e616368746967616c6c2d64657369676e65642053742e204c656f6e61726420436174686f6c696320436875726368202870696374757265642920696e204d616469736f6e2c204e65627261736b612c20636f6e7461696e73206120626f6e652072656c6963206f6620697473206e616d6573616b653f0d0a2e2e2e2074686174207468652043616e61646196536f757468204b6f72656120467265652054726164652041677265656d656e742077696c6c20656c696d696e61746520393825206f6620616c6c20696d706f72742074617269666673206265747765656e207468652074776f20636f756e74726965733f0d0a2e2e2e207468617420526f7373204d634577616e2c2043454f206f66205242532047726f75702c206f6e63652074686520776f726c642773206c6172676573742062616e6b2c207477696365206661696c656420616e206163636f756e74616e6379206578616d3f0d0a2e2e2e2074686174205475726b69736820776f6d656e2773206e6174696f6e616c2069636520686f636b657920706c617965722047697a656d20d67a74617364656c656e2069732061206d656d626572206f662068657220666174686572277320636c7562204d696c656e79756d20506174656e20534b3f0d0a2e2e2e207468617420566572697a6f6e20762e204643432028323031342920776173207265706f7274656420746f20626520746865206465617468206f66206e6574776f726b206e65757472616c6974792c20686176696e6720766163617465642074776f206f662074686520464343204f70656e20496e7465726e6574204f726465722032303130277320746872656520726567756c6174696f6e733f0d0a2e2e2e207468617420746865206d6f737320737065636965732043686f7269736f646f6e7469756d206163697068796c6c756d2063616e207375727669766520666f72206d6f7265207468616e20312c3530302079656172732066726f7a656e3f'),
- // encrypted message
- asmCrypto.hex_to_bytes('09e3c1f3ba2f40eeca4dd7c27453085c71727d4b452a388dbdafc48a7f1406184b5516ea59d9ece55f347237b440792a4e71d26ee6df2dfcd39aea379080082a67be4d7c1af810181379d3f3a444512468e43494a41e9f968c6fe13f45027a297cc24ba3113a5e1b575fa3e1246004d75264e0960052d4e14b4e1a46b24f644428ef4ad4c50455e7029fa53b4eadbe5934c234043f23296b1c235bc8ffadd28deea7415b4bfd996071179cb361822894ab54078b5ad139a7dea6889a36d1417cbbbb1eb9afa0de88d736bf81e5140df06988f2901c275f63fed880fb6a00e7ebd0d5394360ca67b0680d64cc4ba5f7c69298a265916dc4ef03bb54b5e59c0cc48f83b20cf6ec1180b2423966e78ffd94ad1b74dc6b314802ddea17036d507f44c289effd820cb43d0daac09d3ee20ee41cff1e3f2858dc2643e13fcc481d4b1d36ada547e05f789f0d1067c73949c522fd54dc0240c942cc250af3304173dcbab38f1c8292ce0036c8f0c20ceb3d5cc70cc02e5b07329640dc971a410959e89e24edf15d96a6d2cf81abcb994355051371983533f788c9bd01a8e640b1b733c2b34b7ddf7229cf81d3664d85e0cf14dcfb73f0701939f6929e725de6ea590dc0a4caf5fa6fdacc96590e43b94c6f221a703c1c5073509e6b0700eeafde7ee99e149bdbf34a5acd948a513401ba78c4db7128e1f0aac26767f8a4754ae06a41287a12a7f3059c7a405aceb105b3748264c081240c3aa3f298a0ef5f2ea93151a25a3f746082d352eb3a52fb6f860cdf0f4d2186af5e4aa744893e8a59037daa6c23d8d31d2666c528a4ce4e249a27f7aab2bf14eeb7bf8c617380a34db5b7fade8eca02f1f030a62a2ffc7f2d2b14ec366b2a4269be4c763276195ce4c95b4c77c2cc001aac54dd6496099d7ecfe1f1e316d846ab41c4ef461ae0687588ea45532fe8bf9c91cf0840200a232adaa0b8036eaf3f29e4b2d898e8fb2315c22f4915b5746c7920a0bbc98548076e8f68a2fbf3b84df590d0a3154a66d17a80a115027c066f4d5f6c69769e52268f3cea1ee86150144bc05ba63d526e611a1ef723b0b573b37eb5949dd27875208219a77d5a8f170fcecf452ea1b4c78bc135a6345c853a2621154a664806d9fbb88a61ec7935c3511aa3ede4736ee37027e5f2ef2079447886ed5a30839eee442ff8feb17acfa832a8dedb28cbb52b07a950c5dcb853a32ed2f8c0ff83adea7b060aaf2466d148ad43d8e657')
- ],
- [ // Test case for issue #92 (https://github.com/vibornoff/asmcrypto.js/issues/92#issuecomment-158269407)
- // key
- asmCrypto.base64_to_bytes('dGQhii+B7+eLLHRiOA690w=='),
- // nonce
- asmCrypto.base64_to_bytes('R8q1njARXS7urWv3'),
- // adata
- undefined,
- // tagSize
- 16,
- // plaintext
- asmCrypto.base64_to_bytes('dGQhwoovwoHDr8OnwossdGI4DsK9w5M='),
- // ciphertext
- asmCrypto.base64_to_bytes('kMrwkAdqy9VuEdkUA75K2hxjjy4kyRfDXMGzg+l4CoHga1/Rh49R'),
- ],
- [ // Test case for issue #92 (https://github.com/vibornoff/asmcrypto.js/issues/92#issuecomment-158269407)
- // key
- asmCrypto.base64_to_bytes('dGQhii+B7+eLLHRiOA690w=='),
- // nonce
- asmCrypto.base64_to_bytes('R8q1njARXS7urWv3'),
- // adata
- null,
- // tagSize
- 16,
- // plaintext
- asmCrypto.base64_to_bytes('dGQhwoovwoHDr8OnwossdGI4DsK9w5M='),
- // ciphertext
- asmCrypto.base64_to_bytes('kMrwkAdqy9VuEdkUA75K2hxjjy4kyRfDXMGzg+l4CoHga1/Rh49R'),
- ],
- [ // Test case for issue #92 (https://github.com/vibornoff/asmcrypto.js/issues/92#issuecomment-158269407)
- // key
- asmCrypto.base64_to_bytes('dGQhii+B7+eLLHRiOA690w=='),
- // nonce
- asmCrypto.base64_to_bytes('R8q1njARXS7urWv3'),
- // adata
- asmCrypto.string_to_bytes(''),
- // tagSize
- 16,
- // plaintext
- asmCrypto.base64_to_bytes('dGQhwoovwoHDr8OnwossdGI4DsK9w5M='),
- // ciphertext
- asmCrypto.base64_to_bytes('kMrwkAdqy9VuEdkUA75K2hxjjy4kyRfDXMGzg+l4CoHga1/Rh49R'),
- ],
- [ // Test case for issue #92 (https://github.com/vibornoff/asmcrypto.js/issues/92#issuecomment-158269407)
- // key
- asmCrypto.base64_to_bytes('dGQhii+B7+eLLHRiOA690w=='),
- // nonce
- asmCrypto.base64_to_bytes('R8q1njARXS7urWv3'),
- // adata
- new Uint8Array(0),
- // tagSize
- 16,
- // plaintext
- asmCrypto.base64_to_bytes('dGQhwoovwoHDr8OnwossdGI4DsK9w5M='),
- // ciphertext
- asmCrypto.base64_to_bytes('kMrwkAdqy9VuEdkUA75K2hxjjy4kyRfDXMGzg+l4CoHga1/Rh49R'),
- ],
- [ // Test case for issue #92 (https://github.com/vibornoff/asmcrypto.js/issues/92#issuecomment-158797782)
- // key
- asmCrypto.hex_to_bytes('0f0e0d0c0b0a09080706050403020100'),
- // nonce
- asmCrypto.hex_to_bytes('000102030405060708090a0b'),
- // adata
- undefined,
- // tagSize
- 16,
- // plaintext
- asmCrypto.string_to_bytes('42'),
- // ciphertext
- asmCrypto.hex_to_bytes('28be1ac7b43d8868869b9a45d3de436cd0cc'),
- ],
+ });
+
+ describe('CTR', () => {
+ const ctr_aes_vectors = [
+ [
+ // key
+ asmCrypto.hex_to_bytes('2b7e151628aed2a6abf7158809cf4f3c'),
+ // nonce
+ asmCrypto.hex_to_bytes('f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff'),
+ // input message
+ asmCrypto.hex_to_bytes('6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710'),
+ // encrypted message
+ asmCrypto.hex_to_bytes('874d6191b620e3261bef6864990db6ce9806f66b7970fdff8617187bb9fffdff5ae4df3edbd5d35e5b4f09020db03eab1e031dda2fbe03d1792170a0f3009cee')
+ ],
+ [
+ // key
+ asmCrypto.hex_to_bytes('2b7e151628aed2a6abf7158809cf4f3c'),
+ // nonce
+ asmCrypto.hex_to_bytes('f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff'),
+ // input message
+ asmCrypto.hex_to_bytes('6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c'),
+ // encrypted message
+ asmCrypto.hex_to_bytes('874d6191b620e3261bef6864990db6ce9806f66b7970fdff8617187bb9fffdff5ae4df3edbd5d35e5b4f09020db03eab1e031dda2fbe03d1792170a0f300')
+ ],
+ [
+ // key
+ asmCrypto.hex_to_bytes('2b7e151628aed2a6abf7158809cf4f3c'),
+ // nonce
+ asmCrypto.hex_to_bytes('f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff'),
+ // input message
+ asmCrypto.hex_to_bytes('6bc1bee22e409f96e93d7e11739317'),
+ // encrypted message
+ asmCrypto.hex_to_bytes('874d6191b620e3261bef6864990db6')
+ ],
+ [
+ // key
+ asmCrypto.hex_to_bytes('603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4'),
+ // nonce
+ asmCrypto.hex_to_bytes('f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff'),
+ // input message
+ asmCrypto.hex_to_bytes('6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710'),
+ // encrypted message
+ asmCrypto.hex_to_bytes('601ec313775789a5b7a7f504bbf3d228f443e3ca4d62b59aca84e990cacaf5c52b0930daa23de94ce87017ba2d84988ddfc9c58db67aada613c2dd08457941a6')
+ ]
];
- test( "asmCrypto.AES_CCM.encrypt / asmCrypto.AES_CCM.decrypt", function () {
- for ( var i = 0; i < ccm_aes_vectors.length; ++i ) {
- var key = ccm_aes_vectors[i][0],
- nonce = ccm_aes_vectors[i][1],
- adata = ccm_aes_vectors[i][2],
- tagsize = ccm_aes_vectors[i][3],
- clear = ccm_aes_vectors[i][4],
- cipher = ccm_aes_vectors[i][5];
+ it('asmCrypto.AES_CTR.encrypt / asmCrypto.AES_CTR.decrypt', function () {
+ for (let i = 0; i < ctr_aes_vectors.length; ++i) {
+ const key = new Uint8Array(ctr_aes_vectors[i][0]);
+ const nonce = new Uint8Array(ctr_aes_vectors[i][1]);
+ const clear = new Uint8Array(ctr_aes_vectors[i][2]);
+ const cipher = new Uint8Array(ctr_aes_vectors[i][3]);
- equal(
- asmCrypto.bytes_to_hex( asmCrypto.AES_CCM.encrypt( clear, key, nonce, adata, tagsize ) ),
- asmCrypto.bytes_to_hex(cipher),
- "encrypt vector " + i
- );
+ expect(asmCrypto.bytes_to_hex(asmCrypto.AES_CTR.encrypt(clear, key, nonce)), `encrypt vector ${i}`).to.be.equal(asmCrypto.bytes_to_hex(cipher));
- equal(
- asmCrypto.bytes_to_hex( asmCrypto.AES_CCM.decrypt( cipher, key, nonce, adata, tagsize ) ),
- asmCrypto.bytes_to_hex(clear),
- "decrypt vector " + i
- );
- }
+ expect(asmCrypto.bytes_to_hex(asmCrypto.AES_CTR.decrypt(cipher, key, nonce)), `decrypt vector ${i}`).to.be.equal(asmCrypto.bytes_to_hex(clear));
+ }
});
-}
-else
-{
- skip( "asmCrypto.AES_CCM" );
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-if ( typeof asmCrypto.AES_GCM !== 'undefined' )
-{
-
- var gcm_aes_vectors = [
- [
- // key
- asmCrypto.hex_to_bytes('00000000000000000000000000000000'),
- // nonce
- asmCrypto.hex_to_bytes('000000000000000000000000'),
- // adata
- null,
- // tagSize
- 16,
- // input message
- asmCrypto.string_to_bytes(''),
- // encrypted message
- asmCrypto.hex_to_bytes('58e2fccefa7e3061367f1d57a4e7455a')
- ],
- [
- // key
- asmCrypto.hex_to_bytes('00000000000000000000000000000000'),
- // nonce
- asmCrypto.hex_to_bytes('000000000000000000000000'),
- // adata
- asmCrypto.string_to_bytes(''),
- // tagSize
- 16,
- // input message
- asmCrypto.hex_to_bytes('00000000000000000000000000000000'),
- // encrypted message
- asmCrypto.hex_to_bytes('0388dace60b6a392f328c2b971b2fe78ab6e47d42cec13bdf53a67b21257bddf')
- ],
- [
- // key
- asmCrypto.hex_to_bytes('feffe9928665731c6d6a8f9467308308'),
- // nonce
- asmCrypto.hex_to_bytes('cafebabefacedbaddecaf888'),
- // adata
- asmCrypto.string_to_bytes(''),
- // tagSize
- 16,
- // input message
- asmCrypto.hex_to_bytes('d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255'),
- // encrypted message
- asmCrypto.hex_to_bytes('42831ec2217774244b7221b784d0d49ce3aa212f2c02a4e035c17e2329aca12e21d514b25466931c7d8f6a5aac84aa051ba30b396a0aac973d58e091473f59854d5c2af327cd64a62cf35abd2ba6fab4')
- ],
- [
- // key
- asmCrypto.hex_to_bytes('feffe9928665731c6d6a8f9467308308'),
- // nonce
- asmCrypto.hex_to_bytes('cafebabefacedbaddecaf888'),
- // adata
- asmCrypto.hex_to_bytes('feedfacedeadbeeffeedfacedeadbeefabaddad2'),
- // tagSize
- 16,
- // input message
- asmCrypto.hex_to_bytes('d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39'),
- // encrypted message
- asmCrypto.hex_to_bytes('42831ec2217774244b7221b784d0d49ce3aa212f2c02a4e035c17e2329aca12e21d514b25466931c7d8f6a5aac84aa051ba30b396a0aac973d58e0915bc94fbc3221a5db94fae95ae7121a47')
- ],
- [
- // key
- asmCrypto.hex_to_bytes('feffe9928665731c6d6a8f9467308308'),
- // nonce
- asmCrypto.hex_to_bytes('cafebabefacedbad'),
- // adata
- asmCrypto.hex_to_bytes('feedfacedeadbeeffeedfacedeadbeefabaddad2'),
- // tagSize
- 16,
- // input message
- asmCrypto.hex_to_bytes('d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39'),
- // encrypted message
- asmCrypto.hex_to_bytes('61353b4c2806934a777ff51fa22a4755699b2a714fcdc6f83766e5f97b6c742373806900e49f24b22b097544d4896b424989b5e1ebac0f07c23f45983612d2e79e3b0785561be14aaca2fccb')
- ],
- [
- // key
- asmCrypto.hex_to_bytes('feffe9928665731c6d6a8f9467308308'),
- // nonce
- asmCrypto.hex_to_bytes('9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b525416aedbf5a0de6a57a637b39b'),
- // adata
- asmCrypto.hex_to_bytes('feedfacedeadbeeffeedfacedeadbeefabaddad2'),
- // tagSize
- 16,
- // input message
- asmCrypto.hex_to_bytes('d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39'),
- // encrypted message
- asmCrypto.hex_to_bytes('8ce24998625615b603a033aca13fb894be9112a5c3a211a8ba262a3cca7e2ca701e4a9a4fba43c90ccdcb281d48c7c6fd62875d2aca417034c34aee5619cc5aefffe0bfa462af43c1699d050')
- ],
- [
- // key
- asmCrypto.hex_to_bytes('0000000000000000000000000000000000000000000000000000000000000000'),
- // nonce
- asmCrypto.hex_to_bytes('000000000000000000000000'),
- // adata
- asmCrypto.string_to_bytes(''),
- // tagSize
- 16,
- // input message
- asmCrypto.hex_to_bytes('00000000000000000000000000000000'),
- // encrypted message
- asmCrypto.hex_to_bytes('cea7403d4d606b6e074ec5d3baf39d18d0d1c8a799996bf0265b98b5d48ab919')
- ],
- [
- // key
- asmCrypto.hex_to_bytes('0000000000000000000000000000000000000000000000000000000000000000'),
- // nonce
- asmCrypto.hex_to_bytes('000000000000000000000000'),
- // adata
- asmCrypto.string_to_bytes(''),
- // tagSize
- 16,
- // input message
- asmCrypto.hex_to_bytes(''),
- // encrypted message
- asmCrypto.hex_to_bytes('530f8afbc74536b9a963b4f1c4cb738b')
- ],
- [
- // key
- asmCrypto.hex_to_bytes('0000000000000000000000000000000000000000000000000000000000000000'),
- // nonce
- asmCrypto.hex_to_bytes('000000000000000000000000'),
- // adata
- asmCrypto.string_to_bytes(''),
- // tagSize
- 16,
- // input message
- asmCrypto.string_to_bytes(''),
- // encrypted message
- asmCrypto.hex_to_bytes('530f8afbc74536b9a963b4f1c4cb738b')
- ],
- [
- // key
- asmCrypto.hex_to_bytes('0000000000000000000000000000000000000000000000000000000000000000'),
- // nonce
- asmCrypto.hex_to_bytes('000000000000000000000000'),
- // adata
- asmCrypto.string_to_bytes(''),
- // tagSize
- 16,
- // input message
- asmCrypto.hex_to_bytes('00000000000000000000000000000000'),
- // encrypted message
- asmCrypto.hex_to_bytes('cea7403d4d606b6e074ec5d3baf39d18d0d1c8a799996bf0265b98b5d48ab919')
- ],
- [
- // key
- asmCrypto.hex_to_bytes('feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308'),
- // nonce
- asmCrypto.hex_to_bytes('9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b525416aedbf5a0de6a57a637b39b'),
- // adata
- asmCrypto.hex_to_bytes('feedfacedeadbeeffeedfacedeadbeefabaddad2'),
- // tagSize
- 16,
- // input message
- asmCrypto.hex_to_bytes('d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39'),
- // encrypted message
- asmCrypto.hex_to_bytes('5a8def2f0c9e53f1f75d7853659e2a20eeb2b22aafde6419a058ab4f6f746bf40fc0c3b780f244452da3ebf1c5d82cdea2418997200ef82e44ae7e3fa44a8266ee1c8eb0c8b5d4cf5ae9f19a')
- ],
- [ // Test case for issue #70 (https://github.com/vibornoff/asmcrypto.js/issues/70)
- // key
- asmCrypto.hex_to_bytes('00000000000000000000000000000000'),
- // nonce
- asmCrypto.hex_to_bytes('00'),
- // adata
- asmCrypto.string_to_bytes(''),
- // tagSize
- 16,
- // input message
- asmCrypto.hex_to_bytes('00'),
- // encrypted message
- asmCrypto.hex_to_bytes('e9d60634580263ebab909efa6623dafc61')
- ],
- [ // Test case for issue #70 (https://github.com/vibornoff/asmcrypto.js/issues/92)
- // key
- asmCrypto.base64_to_bytes('dGQhii+B7+eLLHRiOA690w=='),
- // nonce
- asmCrypto.base64_to_bytes('R8q1njARXS7urWv3'),
- // adata
- undefined,
- // tagSize
- 16,
- // input message
- asmCrypto.base64_to_bytes('dGQhwoovwoHDr8OnwossdGI4DsK9w5M='),
- // encrypted message
- asmCrypto.base64_to_bytes('L3zqVYAOsRk7zMg2KsNTVShcad8TjIQ7umfsvia21QO0XTj8vaeR')
- ],
+ });
+ describe('GCM', () => {
+ const gcm_aes_vectors = [
+ [
+ // key
+ asmCrypto.hex_to_bytes('00000000000000000000000000000000'),
+ // nonce
+ asmCrypto.hex_to_bytes('000000000000000000000000'),
+ // adata
+ undefined,
+ // tagSize
+ 16,
+ // input message
+ asmCrypto.string_to_bytes(''),
+ // encrypted message
+ asmCrypto.hex_to_bytes('58e2fccefa7e3061367f1d57a4e7455a')
+ ],
+ [
+ // key
+ asmCrypto.hex_to_bytes('00000000000000000000000000000000'),
+ // nonce
+ asmCrypto.hex_to_bytes('000000000000000000000000'),
+ // adata
+ asmCrypto.string_to_bytes(''),
+ // tagSize
+ 16,
+ // input message
+ asmCrypto.hex_to_bytes('00000000000000000000000000000000'),
+ // encrypted message
+ asmCrypto.hex_to_bytes('0388dace60b6a392f328c2b971b2fe78ab6e47d42cec13bdf53a67b21257bddf')
+ ],
+ [
+ // key
+ asmCrypto.hex_to_bytes('feffe9928665731c6d6a8f9467308308'),
+ // nonce
+ asmCrypto.hex_to_bytes('cafebabefacedbaddecaf888'),
+ // adata
+ asmCrypto.string_to_bytes(''),
+ // tagSize
+ 16,
+ // input message
+ asmCrypto.hex_to_bytes('d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255'),
+ // encrypted message
+ asmCrypto.hex_to_bytes('42831ec2217774244b7221b784d0d49ce3aa212f2c02a4e035c17e2329aca12e21d514b25466931c7d8f6a5aac84aa051ba30b396a0aac973d58e091473f59854d5c2af327cd64a62cf35abd2ba6fab4')
+ ],
+ [
+ // key
+ asmCrypto.hex_to_bytes('feffe9928665731c6d6a8f9467308308'),
+ // nonce
+ asmCrypto.hex_to_bytes('cafebabefacedbaddecaf888'),
+ // adata
+ asmCrypto.hex_to_bytes('feedfacedeadbeeffeedfacedeadbeefabaddad2'),
+ // tagSize
+ 16,
+ // input message
+ asmCrypto.hex_to_bytes('d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39'),
+ // encrypted message
+ asmCrypto.hex_to_bytes('42831ec2217774244b7221b784d0d49ce3aa212f2c02a4e035c17e2329aca12e21d514b25466931c7d8f6a5aac84aa051ba30b396a0aac973d58e0915bc94fbc3221a5db94fae95ae7121a47')
+ ],
+ [
+ // key
+ asmCrypto.hex_to_bytes('feffe9928665731c6d6a8f9467308308'),
+ // nonce
+ asmCrypto.hex_to_bytes('cafebabefacedbad'),
+ // adata
+ asmCrypto.hex_to_bytes('feedfacedeadbeeffeedfacedeadbeefabaddad2'),
+ // tagSize
+ 16,
+ // input message
+ asmCrypto.hex_to_bytes('d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39'),
+ // encrypted message
+ asmCrypto.hex_to_bytes('61353b4c2806934a777ff51fa22a4755699b2a714fcdc6f83766e5f97b6c742373806900e49f24b22b097544d4896b424989b5e1ebac0f07c23f45983612d2e79e3b0785561be14aaca2fccb')
+ ],
+ [
+ // key
+ asmCrypto.hex_to_bytes('feffe9928665731c6d6a8f9467308308'),
+ // nonce
+ asmCrypto.hex_to_bytes('9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b525416aedbf5a0de6a57a637b39b'),
+ // adata
+ asmCrypto.hex_to_bytes('feedfacedeadbeeffeedfacedeadbeefabaddad2'),
+ // tagSize
+ 16,
+ // input message
+ asmCrypto.hex_to_bytes('d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39'),
+ // encrypted message
+ asmCrypto.hex_to_bytes('8ce24998625615b603a033aca13fb894be9112a5c3a211a8ba262a3cca7e2ca701e4a9a4fba43c90ccdcb281d48c7c6fd62875d2aca417034c34aee5619cc5aefffe0bfa462af43c1699d050')
+ ],
+ [
+ // key
+ asmCrypto.hex_to_bytes('0000000000000000000000000000000000000000000000000000000000000000'),
+ // nonce
+ asmCrypto.hex_to_bytes('000000000000000000000000'),
+ // adata
+ asmCrypto.string_to_bytes(''),
+ // tagSize
+ 16,
+ // input message
+ asmCrypto.hex_to_bytes('00000000000000000000000000000000'),
+ // encrypted message
+ asmCrypto.hex_to_bytes('cea7403d4d606b6e074ec5d3baf39d18d0d1c8a799996bf0265b98b5d48ab919')
+ ],
+ [
+ // key
+ asmCrypto.hex_to_bytes('0000000000000000000000000000000000000000000000000000000000000000'),
+ // nonce
+ asmCrypto.hex_to_bytes('000000000000000000000000'),
+ // adata
+ asmCrypto.string_to_bytes(''),
+ // tagSize
+ 16,
+ // input message
+ asmCrypto.hex_to_bytes(''),
+ // encrypted message
+ asmCrypto.hex_to_bytes('530f8afbc74536b9a963b4f1c4cb738b')
+ ],
+ [
+ // key
+ asmCrypto.hex_to_bytes('0000000000000000000000000000000000000000000000000000000000000000'),
+ // nonce
+ asmCrypto.hex_to_bytes('000000000000000000000000'),
+ // adata
+ asmCrypto.string_to_bytes(''),
+ // tagSize
+ 16,
+ // input message
+ asmCrypto.string_to_bytes(''),
+ // encrypted message
+ asmCrypto.hex_to_bytes('530f8afbc74536b9a963b4f1c4cb738b')
+ ],
+ [
+ // key
+ asmCrypto.hex_to_bytes('0000000000000000000000000000000000000000000000000000000000000000'),
+ // nonce
+ asmCrypto.hex_to_bytes('000000000000000000000000'),
+ // adata
+ asmCrypto.string_to_bytes(''),
+ // tagSize
+ 16,
+ // input message
+ asmCrypto.hex_to_bytes('00000000000000000000000000000000'),
+ // encrypted message
+ asmCrypto.hex_to_bytes('cea7403d4d606b6e074ec5d3baf39d18d0d1c8a799996bf0265b98b5d48ab919')
+ ],
+ [
+ // key
+ asmCrypto.hex_to_bytes('feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308'),
+ // nonce
+ asmCrypto.hex_to_bytes('9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b525416aedbf5a0de6a57a637b39b'),
+ // adata
+ asmCrypto.hex_to_bytes('feedfacedeadbeeffeedfacedeadbeefabaddad2'),
+ // tagSize
+ 16,
+ // input message
+ asmCrypto.hex_to_bytes('d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39'),
+ // encrypted message
+ asmCrypto.hex_to_bytes('5a8def2f0c9e53f1f75d7853659e2a20eeb2b22aafde6419a058ab4f6f746bf40fc0c3b780f244452da3ebf1c5d82cdea2418997200ef82e44ae7e3fa44a8266ee1c8eb0c8b5d4cf5ae9f19a')
+ ],
+ [ // Test case for issue #70 (https://github.com/vibornoff/asmcrypto.js/issues/70)
+ // key
+ asmCrypto.hex_to_bytes('00000000000000000000000000000000'),
+ // nonce
+ asmCrypto.hex_to_bytes('00'),
+ // adata
+ asmCrypto.string_to_bytes(''),
+ // tagSize
+ 16,
+ // input message
+ asmCrypto.hex_to_bytes('00'),
+ // encrypted message
+ asmCrypto.hex_to_bytes('e9d60634580263ebab909efa6623dafc61')
+ ],
+ [ // Test case for issue #70 (https://github.com/vibornoff/asmcrypto.js/issues/92)
+ // key
+ asmCrypto.base64_to_bytes('dGQhii+B7+eLLHRiOA690w=='),
+ // nonce
+ asmCrypto.base64_to_bytes('R8q1njARXS7urWv3'),
+ // adata
+ undefined,
+ // tagSize
+ 16,
+ // input message
+ asmCrypto.base64_to_bytes('dGQhwoovwoHDr8OnwossdGI4DsK9w5M='),
+ // encrypted message
+ asmCrypto.base64_to_bytes('L3zqVYAOsRk7zMg2KsNTVShcad8TjIQ7umfsvia21QO0XTj8vaeR')
+ ],
];
- test( "asmCrypto.AES_GCM.encrypt", function () {
- for ( var i = 0; i < gcm_aes_vectors.length; ++i ) {
- var key = gcm_aes_vectors[i][0],
- nonce = gcm_aes_vectors[i][1],
- adata = gcm_aes_vectors[i][2],
- tagsize = gcm_aes_vectors[i][3],
- cleartext = gcm_aes_vectors[i][4],
- ciphertext = gcm_aes_vectors[i][5];
+ it("asmCrypto.AES_GCM.encrypt", function () {
+ for (let i = 0; i < gcm_aes_vectors.length; ++i) {
+ const key = gcm_aes_vectors[i][0];
+ const nonce = gcm_aes_vectors[i][1];
+ const adata = gcm_aes_vectors[i][2];
+ const tagsize = gcm_aes_vectors[i][3];
+ const cleartext = gcm_aes_vectors[i][4];
+ const ciphertext = gcm_aes_vectors[i][5];
- equal(
- asmCrypto.bytes_to_hex( asmCrypto.AES_GCM.encrypt( cleartext, key, nonce, adata, tagsize ) ),
- asmCrypto.bytes_to_hex( ciphertext ),
- "encrypt vector " + i
- );
+ expect(asmCrypto.bytes_to_hex(asmCrypto.AES_GCM.encrypt(cleartext, key, nonce, adata, tagsize)), 'encrypt vector ' + i).to.be.equal(asmCrypto.bytes_to_hex(ciphertext));
- equal(
- asmCrypto.bytes_to_hex( asmCrypto.AES_GCM.decrypt( ciphertext, key, nonce, adata, tagsize ) ),
- asmCrypto.bytes_to_hex( cleartext ),
- "decrypt vector " + i
- );
- }
+ expect(asmCrypto.bytes_to_hex(asmCrypto.AES_GCM.decrypt(ciphertext, key, nonce, adata, tagsize)), 'decrypt vector ' + i).to.be.equal(asmCrypto.bytes_to_hex(cleartext));
+ }
});
-}
-else
-{
- skip( "asmCrypto.AES_GCM" );
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-if ( typeof asmCrypto.AES_CFB !== 'undefined' )
-{
- var cfb_aes_vectors = [
- [ // key
- [ 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c ],
- // iv
- [ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f ],
- // clear text
- [ 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
- 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
- 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
- 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10 ],
- // cipher text
- [ 0x3b, 0x3f, 0xd9, 0x2e, 0xb7, 0x2d, 0xad, 0x20, 0x33, 0x34, 0x49, 0xf8, 0xe8, 0x3c, 0xfb, 0x4a,
- 0xc8, 0xa6, 0x45, 0x37, 0xa0, 0xb3, 0xa9, 0x3f, 0xcd, 0xe3, 0xcd, 0xad, 0x9f, 0x1c, 0xe5, 0x8b,
- 0x26, 0x75, 0x1f, 0x67, 0xa3, 0xcb, 0xb1, 0x40, 0xb1, 0x80, 0x8c, 0xf1, 0x87, 0xa4, 0xf4, 0xdf,
- 0xc0, 0x4b, 0x05, 0x35, 0x7c, 0x5d, 0x1c, 0x0e, 0xea, 0xc4, 0xc6, 0x6f, 0x9f, 0xf7, 0xf2, 0xe6 ]
- ],
- [ // key
- [ 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c ],
- // iv
- [ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f ],
- // clear text
- [ 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
- 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
- 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
- 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, 0xad, 0x2b, 0x41 ],
- // cipher text
- [ 0x3b, 0x3f, 0xd9, 0x2e, 0xb7, 0x2d, 0xad, 0x20, 0x33, 0x34, 0x49, 0xf8, 0xe8, 0x3c, 0xfb, 0x4a,
- 0xc8, 0xa6, 0x45, 0x37, 0xa0, 0xb3, 0xa9, 0x3f, 0xcd, 0xe3, 0xcd, 0xad, 0x9f, 0x1c, 0xe5, 0x8b,
- 0x26, 0x75, 0x1f, 0x67, 0xa3, 0xcb, 0xb1, 0x40, 0xb1, 0x80, 0x8c, 0xf1, 0x87, 0xa4, 0xf4, 0xdf,
- 0xc0, 0x4b, 0x05, 0x35, 0x7c, 0x5d, 0x1c, 0x0e, 0xea, 0xc4, 0xc6 ]
- ],
- [ // key
- [ 0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe, 0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81,
- 0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7, 0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4 ],
- // iv
- [ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f ],
- // clear text
- [ 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
- 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
- 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
- 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10 ],
- // cipher text
- [ 0xdc, 0x7e, 0x84, 0xbf, 0xda, 0x79, 0x16, 0x4b, 0x7e, 0xcd, 0x84, 0x86, 0x98, 0x5d, 0x38, 0x60,
- 0x39, 0xff, 0xed, 0x14, 0x3b, 0x28, 0xb1, 0xc8, 0x32, 0x11, 0x3c, 0x63, 0x31, 0xe5, 0x40, 0x7b,
- 0xdf, 0x10, 0x13, 0x24, 0x15, 0xe5, 0x4b, 0x92, 0xa1, 0x3e, 0xd0, 0xa8, 0x26, 0x7a, 0xe2, 0xf9,
- 0x75, 0xa3, 0x85, 0x74, 0x1a, 0xb9, 0xce, 0xf8, 0x20, 0x31, 0x62, 0x3d, 0x55, 0xb1, 0xe4, 0x71 ]
- ],
- [ // key
- [ 0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe, 0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81,
- 0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7, 0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4 ],
- // iv
- [ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f ],
- // clear text
- [ 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
- 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
- 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
- 0xf6, 0x9f, 0x24 ],
- // cipher text
- [ 0xdc, 0x7e, 0x84, 0xbf, 0xda, 0x79, 0x16, 0x4b, 0x7e, 0xcd, 0x84, 0x86, 0x98, 0x5d, 0x38, 0x60,
- 0x39, 0xff, 0xed, 0x14, 0x3b, 0x28, 0xb1, 0xc8, 0x32, 0x11, 0x3c, 0x63, 0x31, 0xe5, 0x40, 0x7b,
- 0xdf, 0x10, 0x13, 0x24, 0x15, 0xe5, 0x4b, 0x92, 0xa1, 0x3e, 0xd0, 0xa8, 0x26, 0x7a, 0xe2, 0xf9,
- 0x75, 0xa3, 0x85 ]
- ]
+ });
+
+ describe('CFB', () => {
+ const cfb_aes_vectors = [
+ [ // key
+ [0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c],
+ // iv
+ [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f],
+ // clear text
+ [0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
+ 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
+ 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
+ 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10],
+ // cipher text
+ [0x3b, 0x3f, 0xd9, 0x2e, 0xb7, 0x2d, 0xad, 0x20, 0x33, 0x34, 0x49, 0xf8, 0xe8, 0x3c, 0xfb, 0x4a,
+ 0xc8, 0xa6, 0x45, 0x37, 0xa0, 0xb3, 0xa9, 0x3f, 0xcd, 0xe3, 0xcd, 0xad, 0x9f, 0x1c, 0xe5, 0x8b,
+ 0x26, 0x75, 0x1f, 0x67, 0xa3, 0xcb, 0xb1, 0x40, 0xb1, 0x80, 0x8c, 0xf1, 0x87, 0xa4, 0xf4, 0xdf,
+ 0xc0, 0x4b, 0x05, 0x35, 0x7c, 0x5d, 0x1c, 0x0e, 0xea, 0xc4, 0xc6, 0x6f, 0x9f, 0xf7, 0xf2, 0xe6]
+ ],
+ [ // key
+ [0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c],
+ // iv
+ [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f],
+ // clear text
+ [0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
+ 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
+ 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
+ 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, 0xad, 0x2b, 0x41],
+ // cipher text
+ [0x3b, 0x3f, 0xd9, 0x2e, 0xb7, 0x2d, 0xad, 0x20, 0x33, 0x34, 0x49, 0xf8, 0xe8, 0x3c, 0xfb, 0x4a,
+ 0xc8, 0xa6, 0x45, 0x37, 0xa0, 0xb3, 0xa9, 0x3f, 0xcd, 0xe3, 0xcd, 0xad, 0x9f, 0x1c, 0xe5, 0x8b,
+ 0x26, 0x75, 0x1f, 0x67, 0xa3, 0xcb, 0xb1, 0x40, 0xb1, 0x80, 0x8c, 0xf1, 0x87, 0xa4, 0xf4, 0xdf,
+ 0xc0, 0x4b, 0x05, 0x35, 0x7c, 0x5d, 0x1c, 0x0e, 0xea, 0xc4, 0xc6]
+ ],
+ [ // key
+ [0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe, 0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81,
+ 0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7, 0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4],
+ // iv
+ [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f],
+ // clear text
+ [0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
+ 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
+ 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
+ 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10],
+ // cipher text
+ [0xdc, 0x7e, 0x84, 0xbf, 0xda, 0x79, 0x16, 0x4b, 0x7e, 0xcd, 0x84, 0x86, 0x98, 0x5d, 0x38, 0x60,
+ 0x39, 0xff, 0xed, 0x14, 0x3b, 0x28, 0xb1, 0xc8, 0x32, 0x11, 0x3c, 0x63, 0x31, 0xe5, 0x40, 0x7b,
+ 0xdf, 0x10, 0x13, 0x24, 0x15, 0xe5, 0x4b, 0x92, 0xa1, 0x3e, 0xd0, 0xa8, 0x26, 0x7a, 0xe2, 0xf9,
+ 0x75, 0xa3, 0x85, 0x74, 0x1a, 0xb9, 0xce, 0xf8, 0x20, 0x31, 0x62, 0x3d, 0x55, 0xb1, 0xe4, 0x71]
+ ],
+ [ // key
+ [0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe, 0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81,
+ 0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7, 0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4],
+ // iv
+ [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f],
+ // clear text
+ [0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
+ 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51,
+ 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef,
+ 0xf6, 0x9f, 0x24],
+ // cipher text
+ [0xdc, 0x7e, 0x84, 0xbf, 0xda, 0x79, 0x16, 0x4b, 0x7e, 0xcd, 0x84, 0x86, 0x98, 0x5d, 0x38, 0x60,
+ 0x39, 0xff, 0xed, 0x14, 0x3b, 0x28, 0xb1, 0xc8, 0x32, 0x11, 0x3c, 0x63, 0x31, 0xe5, 0x40, 0x7b,
+ 0xdf, 0x10, 0x13, 0x24, 0x15, 0xe5, 0x4b, 0x92, 0xa1, 0x3e, 0xd0, 0xa8, 0x26, 0x7a, 0xe2, 0xf9,
+ 0x75, 0xa3, 0x85]
+ ]
];
- test( "asmCrypto.AES_CFB.encrypt / asmCrypto.AES_CFB.decrypt", function () {
- for ( var i = 0; i < cfb_aes_vectors.length; ++i ) {
- var key = new Uint8Array( cfb_aes_vectors[i][0] ),
- iv = new Uint8Array( cfb_aes_vectors[i][1] ),
- clear = new Uint8Array( cfb_aes_vectors[i][2] ),
- cipher = new Uint8Array( cfb_aes_vectors[i][3] );
+ it('asmCrypto.AES_CFB.encrypt / asmCrypto.AES_CFB.decrypt', function () {
+ for (let i = 0; i < cfb_aes_vectors.length; ++i) {
+ const key = new Uint8Array(cfb_aes_vectors[i][0]);
+ const iv = new Uint8Array(cfb_aes_vectors[i][1]);
+ const clear = new Uint8Array(cfb_aes_vectors[i][2]);
+ const cipher = new Uint8Array(cfb_aes_vectors[i][3]);
- equal(
- asmCrypto.bytes_to_hex( asmCrypto.AES_CFB.encrypt( clear, key, iv ) ),
- asmCrypto.bytes_to_hex(cipher),
- "encrypt vector " + i
- );
+ expect(asmCrypto.bytes_to_hex(asmCrypto.AES_CFB.encrypt(clear, key, iv)), `encrypt vector ${i}`).to.be.equal(asmCrypto.bytes_to_hex(cipher));
- equal(
- asmCrypto.bytes_to_hex( asmCrypto.AES_CFB.decrypt( cipher, key, iv ) ),
- asmCrypto.bytes_to_hex(clear),
- "decrypt vector " + i
- );
- }
+ expect(asmCrypto.bytes_to_hex(asmCrypto.AES_CFB.decrypt(cipher, key, iv)), `decrypt vector ${i}`).to.be.equal(asmCrypto.bytes_to_hex(clear));
+ }
});
-}
-else
-{
- skip( "asmCrypto.AES_CFB" );
-}
-
-testIf( asmCrypto.AES_OFB !== undefined, "asmCrypto.AES_OFB", function () {
+ });
+ describe('OFB', () => {
// key, iv, cleartext, ciphertext
- var ofb_vectors = [
- [
- asmCrypto.hex_to_bytes('2b7e151628aed2a6abf7158809cf4f3c'),
- asmCrypto.hex_to_bytes('000102030405060708090A0B0C0D0E0F'),
- asmCrypto.hex_to_bytes('6bc1bee22e409f96e93d7e117393172a'),
- asmCrypto.hex_to_bytes('3b3fd92eb72dad20333449f8e83cfb4a'),
- ],
- [
- asmCrypto.hex_to_bytes('2b7e151628aed2a6abf7158809cf4f3c'),
- asmCrypto.hex_to_bytes('50FE67CC996D32B6DA0937E99BAFEC60'),
- asmCrypto.hex_to_bytes('ae2d8a571e03ac9c9eb76fac45af8e51'),
- asmCrypto.hex_to_bytes('7789508d16918f03f53c52dac54ed825'),
- ],
- [
- asmCrypto.hex_to_bytes('2b7e151628aed2a6abf7158809cf4f3c'),
- asmCrypto.hex_to_bytes('D9A4DADA0892239F6B8B3D7680E15674'),
- asmCrypto.hex_to_bytes('30c81c46a35ce411e5fbc1191a0a52ef'),
- asmCrypto.hex_to_bytes('9740051e9c5fecf64344f7a82260edcc'),
- ],
- [
- asmCrypto.hex_to_bytes('2b7e151628aed2a6abf7158809cf4f3c'),
- asmCrypto.hex_to_bytes('A78819583F0308E7A6BF36B1386ABF23'),
- asmCrypto.hex_to_bytes('f69f2445df4f9b17ad2b417be66c3710'),
- asmCrypto.hex_to_bytes('304c6528f659c77866a510d9c1d6ae5e'),
- ],
- [
- asmCrypto.hex_to_bytes('8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b'),
- asmCrypto.hex_to_bytes('000102030405060708090A0B0C0D0E0F'),
- asmCrypto.hex_to_bytes('6bc1bee22e409f96e93d7e117393172a'),
- asmCrypto.hex_to_bytes('cdc80d6fddf18cab34c25909c99a4174'),
- ],
- [
- asmCrypto.hex_to_bytes('8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b'),
- asmCrypto.hex_to_bytes('A609B38DF3B1133DDDFF2718BA09565E'),
- asmCrypto.hex_to_bytes('ae2d8a571e03ac9c9eb76fac45af8e51'),
- asmCrypto.hex_to_bytes('fcc28b8d4c63837c09e81700c1100401'),
- ],
- [
- asmCrypto.hex_to_bytes('8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b'),
- asmCrypto.hex_to_bytes('52EF01DA52602FE0975F78AC84BF8A50'),
- asmCrypto.hex_to_bytes('30c81c46a35ce411e5fbc1191a0a52ef'),
- asmCrypto.hex_to_bytes('8d9a9aeac0f6596f559c6d4daf59a5f2'),
- ],
- [
- asmCrypto.hex_to_bytes('8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b'),
- asmCrypto.hex_to_bytes('BD5286AC63AABD7EB067AC54B553F71D'),
- asmCrypto.hex_to_bytes('f69f2445df4f9b17ad2b417be66c3710'),
- asmCrypto.hex_to_bytes('6d9f200857ca6c3e9cac524bd9acc92a'),
- ],
- [
- asmCrypto.hex_to_bytes('603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4'),
- asmCrypto.hex_to_bytes('000102030405060708090A0B0C0D0E0F'),
- asmCrypto.hex_to_bytes('6bc1bee22e409f96e93d7e117393172a'),
- asmCrypto.hex_to_bytes('dc7e84bfda79164b7ecd8486985d3860'),
- ],
- [
- asmCrypto.hex_to_bytes('603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4'),
- asmCrypto.hex_to_bytes('B7BF3A5DF43989DD97F0FA97EBCE2F4A'),
- asmCrypto.hex_to_bytes('ae2d8a571e03ac9c9eb76fac45af8e51'),
- asmCrypto.hex_to_bytes('4febdc6740d20b3ac88f6ad82a4fb08d'),
- ],
- [
- asmCrypto.hex_to_bytes('603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4'),
- asmCrypto.hex_to_bytes('E1C656305ED1A7A6563805746FE03EDC'),
- asmCrypto.hex_to_bytes('30c81c46a35ce411e5fbc1191a0a52ef'),
- asmCrypto.hex_to_bytes('71ab47a086e86eedf39d1c5bba97c408'),
- ],
- [
- asmCrypto.hex_to_bytes('603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4'),
- asmCrypto.hex_to_bytes('41635BE625B48AFC1666DD42A09D96E7'),
- asmCrypto.hex_to_bytes('f69f2445df4f9b17ad2b417be66c3710'),
- asmCrypto.hex_to_bytes('0126141d67f37be8538f5a8be740e484'),
- ],
+ const ofb_vectors = [
+ [
+ asmCrypto.hex_to_bytes('2b7e151628aed2a6abf7158809cf4f3c'),
+ asmCrypto.hex_to_bytes('000102030405060708090A0B0C0D0E0F'),
+ asmCrypto.hex_to_bytes('6bc1bee22e409f96e93d7e117393172a'),
+ asmCrypto.hex_to_bytes('3b3fd92eb72dad20333449f8e83cfb4a'),
+ ],
+ [
+ asmCrypto.hex_to_bytes('2b7e151628aed2a6abf7158809cf4f3c'),
+ asmCrypto.hex_to_bytes('50FE67CC996D32B6DA0937E99BAFEC60'),
+ asmCrypto.hex_to_bytes('ae2d8a571e03ac9c9eb76fac45af8e51'),
+ asmCrypto.hex_to_bytes('7789508d16918f03f53c52dac54ed825'),
+ ],
+ [
+ asmCrypto.hex_to_bytes('2b7e151628aed2a6abf7158809cf4f3c'),
+ asmCrypto.hex_to_bytes('D9A4DADA0892239F6B8B3D7680E15674'),
+ asmCrypto.hex_to_bytes('30c81c46a35ce411e5fbc1191a0a52ef'),
+ asmCrypto.hex_to_bytes('9740051e9c5fecf64344f7a82260edcc'),
+ ],
+ [
+ asmCrypto.hex_to_bytes('2b7e151628aed2a6abf7158809cf4f3c'),
+ asmCrypto.hex_to_bytes('A78819583F0308E7A6BF36B1386ABF23'),
+ asmCrypto.hex_to_bytes('f69f2445df4f9b17ad2b417be66c3710'),
+ asmCrypto.hex_to_bytes('304c6528f659c77866a510d9c1d6ae5e'),
+ ],
+ [
+ asmCrypto.hex_to_bytes('8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b'),
+ asmCrypto.hex_to_bytes('000102030405060708090A0B0C0D0E0F'),
+ asmCrypto.hex_to_bytes('6bc1bee22e409f96e93d7e117393172a'),
+ asmCrypto.hex_to_bytes('cdc80d6fddf18cab34c25909c99a4174'),
+ ],
+ [
+ asmCrypto.hex_to_bytes('8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b'),
+ asmCrypto.hex_to_bytes('A609B38DF3B1133DDDFF2718BA09565E'),
+ asmCrypto.hex_to_bytes('ae2d8a571e03ac9c9eb76fac45af8e51'),
+ asmCrypto.hex_to_bytes('fcc28b8d4c63837c09e81700c1100401'),
+ ],
+ [
+ asmCrypto.hex_to_bytes('8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b'),
+ asmCrypto.hex_to_bytes('52EF01DA52602FE0975F78AC84BF8A50'),
+ asmCrypto.hex_to_bytes('30c81c46a35ce411e5fbc1191a0a52ef'),
+ asmCrypto.hex_to_bytes('8d9a9aeac0f6596f559c6d4daf59a5f2'),
+ ],
+ [
+ asmCrypto.hex_to_bytes('8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b'),
+ asmCrypto.hex_to_bytes('BD5286AC63AABD7EB067AC54B553F71D'),
+ asmCrypto.hex_to_bytes('f69f2445df4f9b17ad2b417be66c3710'),
+ asmCrypto.hex_to_bytes('6d9f200857ca6c3e9cac524bd9acc92a'),
+ ],
+ [
+ asmCrypto.hex_to_bytes('603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4'),
+ asmCrypto.hex_to_bytes('000102030405060708090A0B0C0D0E0F'),
+ asmCrypto.hex_to_bytes('6bc1bee22e409f96e93d7e117393172a'),
+ asmCrypto.hex_to_bytes('dc7e84bfda79164b7ecd8486985d3860'),
+ ],
+ [
+ asmCrypto.hex_to_bytes('603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4'),
+ asmCrypto.hex_to_bytes('B7BF3A5DF43989DD97F0FA97EBCE2F4A'),
+ asmCrypto.hex_to_bytes('ae2d8a571e03ac9c9eb76fac45af8e51'),
+ asmCrypto.hex_to_bytes('4febdc6740d20b3ac88f6ad82a4fb08d'),
+ ],
+ [
+ asmCrypto.hex_to_bytes('603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4'),
+ asmCrypto.hex_to_bytes('E1C656305ED1A7A6563805746FE03EDC'),
+ asmCrypto.hex_to_bytes('30c81c46a35ce411e5fbc1191a0a52ef'),
+ asmCrypto.hex_to_bytes('71ab47a086e86eedf39d1c5bba97c408'),
+ ],
+ [
+ asmCrypto.hex_to_bytes('603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4'),
+ asmCrypto.hex_to_bytes('41635BE625B48AFC1666DD42A09D96E7'),
+ asmCrypto.hex_to_bytes('f69f2445df4f9b17ad2b417be66c3710'),
+ asmCrypto.hex_to_bytes('0126141d67f37be8538f5a8be740e484'),
+ ],
];
-
- for ( var i = 0; i < ofb_vectors.length; ++i ) {
- var key = new Uint8Array( ofb_vectors[i][0] ),
- iv = new Uint8Array( ofb_vectors[i][1] ),
- clear = new Uint8Array( ofb_vectors[i][2] ),
- cipher = new Uint8Array( ofb_vectors[i][3] );
-
- equal(
- asmCrypto.bytes_to_hex( asmCrypto.AES_OFB.encrypt( clear, key, iv ) ),
- asmCrypto.bytes_to_hex( cipher ),
- "encrypt vector " + i
- );
-
- equal(
- asmCrypto.bytes_to_hex( asmCrypto.AES_OFB.decrypt( cipher, key, iv ) ),
- asmCrypto.bytes_to_hex( clear ),
- "decrypt vector " + i
- );
- }
-});
-
-testIf( asmCrypto.AES_CMAC !== undefined, "asmCrypto.AES_CMAC", function () {
+
+ it('asmCrypto.AES_OFB.encrypt / asmCrypto.AES_OFB.decrypt', () => {
+ for (let i = 0; i < ofb_vectors.length; ++i) {
+ const key = new Uint8Array(ofb_vectors[i][0]);
+ const iv = new Uint8Array(ofb_vectors[i][1]);
+ const clear = new Uint8Array(ofb_vectors[i][2]);
+ const cipher = new Uint8Array(ofb_vectors[i][3]);
+
+ expect(asmCrypto.bytes_to_hex(asmCrypto.AES_OFB.encrypt(clear, key, iv)), 'encrypt vector ' + i).to.be.equal(asmCrypto.bytes_to_hex(cipher));
+
+ expect(asmCrypto.bytes_to_hex(asmCrypto.AES_OFB.decrypt(cipher, key, iv)), 'decrypt vector ' + i).to.be.equal(asmCrypto.bytes_to_hex(clear));
+ }
+ });
+ });
+ describe('CMAC', () => {
// key, data, result
- var cmac_vectors = [
- [
- asmCrypto.hex_to_bytes('2b7e151628aed2a6abf7158809cf4f3c'),
- asmCrypto.hex_to_bytes(''),
- asmCrypto.hex_to_bytes('bb1d6929e95937287fa37d129b756746'),
- ],
- [
- asmCrypto.hex_to_bytes('2b7e151628aed2a6abf7158809cf4f3c'),
- asmCrypto.hex_to_bytes('6bc1bee22e409f96e93d7e117393172a'),
- asmCrypto.hex_to_bytes('070a16b46b4d4144f79bdd9dd04a287c'),
- ],
- [
- asmCrypto.hex_to_bytes('2b7e151628aed2a6abf7158809cf4f3c'),
- asmCrypto.hex_to_bytes('6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411'),
- asmCrypto.hex_to_bytes('dfa66747de9ae63030ca32611497c827'),
- ],
- [
- asmCrypto.hex_to_bytes('2b7e151628aed2a6abf7158809cf4f3c'),
- asmCrypto.hex_to_bytes('6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710'),
- asmCrypto.hex_to_bytes('51f0bebf7e3b9d92fc49741779363cfe'),
- ],
+ const cmac_vectors = [
+ [
+ asmCrypto.hex_to_bytes('2b7e151628aed2a6abf7158809cf4f3c'),
+ asmCrypto.hex_to_bytes(''),
+ asmCrypto.hex_to_bytes('bb1d6929e95937287fa37d129b756746'),
+ ],
+ [
+ asmCrypto.hex_to_bytes('2b7e151628aed2a6abf7158809cf4f3c'),
+ asmCrypto.hex_to_bytes('6bc1bee22e409f96e93d7e117393172a'),
+ asmCrypto.hex_to_bytes('070a16b46b4d4144f79bdd9dd04a287c'),
+ ],
+ [
+ asmCrypto.hex_to_bytes('2b7e151628aed2a6abf7158809cf4f3c'),
+ asmCrypto.hex_to_bytes('6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411'),
+ asmCrypto.hex_to_bytes('dfa66747de9ae63030ca32611497c827'),
+ ],
+ [
+ asmCrypto.hex_to_bytes('2b7e151628aed2a6abf7158809cf4f3c'),
+ asmCrypto.hex_to_bytes('6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710'),
+ asmCrypto.hex_to_bytes('51f0bebf7e3b9d92fc49741779363cfe'),
+ ],
+ ];
+
+ it('asmCrypto.AES_CMAC', function() {
+ for (let i = 0; i < cmac_vectors.length; ++i) {
+ const key = new Uint8Array(cmac_vectors[i][0]);
+ const data = new Uint8Array(cmac_vectors[i][1]);
+ const result = new Uint8Array(cmac_vectors[i][2]);
+
+ expect(asmCrypto.bytes_to_hex(asmCrypto.AES_CMAC.bytes(data, key)), 'cmac vector ' + i).to.be.equal(asmCrypto.bytes_to_hex(result));
+ }
+ });
+ });
+ describe('CCM', () => {
+ const ccm_aes_vectors = [
+ [
+ // key
+ new Uint8Array([ 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf ]),
+ // nonce
+ new Uint8Array([ 0x00, 0x00, 0x00, 0x03, 0x02, 0x01, 0x00, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5 ]),
+ // adata
+ new Uint8Array([ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 ]),
+ // tagSize
+ 8,
+ // input message
+ new Uint8Array([ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e ]),
+ // encrypted message
+ new Uint8Array([ 0x58, 0x8c, 0x97, 0x9a, 0x61, 0xc6, 0x63, 0xd2, 0xf0, 0x66, 0xd0, 0xc2, 0xc0, 0xf9, 0x89, 0x80,
+ 0x6d, 0x5f, 0x6b, 0x61, 0xda, 0xc3, 0x84, 0x17, 0xe8, 0xd1, 0x2c, 0xfd, 0xf9, 0x26, 0xe0 ]),
+ ],
+ [
+ // key
+ new Uint8Array([ 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf ]),
+ // nonce
+ new Uint8Array([ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ]),
+ // adata
+ new Uint8Array([ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x61, 0x75, 0x74, 0x68, 0x69, 0x6e, 0x66, 0x6f, 0x6f ]),
+ // tagSize
+ 16,
+ // input message
+ asmCrypto.hex_to_bytes('44696420796f75206b6e6f772e2e2e0d0a46726f6d2057696b6970656469612773206e657720616e6420726563656e746c7920696d70726f76656420636f6e74656e743a0d0a5361696e74204c656f6e61726420436174686f6c69632043687572636820284d616469736f6e2c204e65627261736b61290d0a2e2e2e207468617420746865204a61636f62204d2e204e616368746967616c6c2d64657369676e65642053742e204c656f6e61726420436174686f6c696320436875726368202870696374757265642920696e204d616469736f6e2c204e65627261736b612c20636f6e7461696e73206120626f6e652072656c6963206f6620697473206e616d6573616b653f0d0a2e2e2e2074686174207468652043616e61646196536f757468204b6f72656120467265652054726164652041677265656d656e742077696c6c20656c696d696e61746520393825206f6620616c6c20696d706f72742074617269666673206265747765656e207468652074776f20636f756e74726965733f0d0a2e2e2e207468617420526f7373204d634577616e2c2043454f206f66205242532047726f75702c206f6e63652074686520776f726c642773206c6172676573742062616e6b2c207477696365206661696c656420616e206163636f756e74616e6379206578616d3f0d0a2e2e2e2074686174205475726b69736820776f6d656e2773206e6174696f6e616c2069636520686f636b657920706c617965722047697a656d20d67a74617364656c656e2069732061206d656d626572206f662068657220666174686572277320636c7562204d696c656e79756d20506174656e20534b3f0d0a2e2e2e207468617420566572697a6f6e20762e204643432028323031342920776173207265706f7274656420746f20626520746865206465617468206f66206e6574776f726b206e65757472616c6974792c20686176696e6720766163617465642074776f206f662074686520464343204f70656e20496e7465726e6574204f726465722032303130277320746872656520726567756c6174696f6e733f0d0a2e2e2e207468617420746865206d6f737320737065636965732043686f7269736f646f6e7469756d206163697068796c6c756d2063616e207375727669766520666f72206d6f7265207468616e20312c3530302079656172732066726f7a656e3f'),
+ // encrypted message
+ asmCrypto.hex_to_bytes('09e3c1f3ba2f40eeca4dd7c27453085c71727d4b452a388dbdafc48a7f1406184b5516ea59d9ece55f347237b440792a4e71d26ee6df2dfcd39aea379080082a67be4d7c1af810181379d3f3a444512468e43494a41e9f968c6fe13f45027a297cc24ba3113a5e1b575fa3e1246004d75264e0960052d4e14b4e1a46b24f644428ef4ad4c50455e7029fa53b4eadbe5934c234043f23296b1c235bc8ffadd28deea7415b4bfd996071179cb361822894ab54078b5ad139a7dea6889a36d1417cbbbb1eb9afa0de88d736bf81e5140df06988f2901c275f63fed880fb6a00e7ebd0d5394360ca67b0680d64cc4ba5f7c69298a265916dc4ef03bb54b5e59c0cc48f83b20cf6ec1180b2423966e78ffd94ad1b74dc6b314802ddea17036d507f44c289effd820cb43d0daac09d3ee20ee41cff1e3f2858dc2643e13fcc481d4b1d36ada547e05f789f0d1067c73949c522fd54dc0240c942cc250af3304173dcbab38f1c8292ce0036c8f0c20ceb3d5cc70cc02e5b07329640dc971a410959e89e24edf15d96a6d2cf81abcb994355051371983533f788c9bd01a8e640b1b733c2b34b7ddf7229cf81d3664d85e0cf14dcfb73f0701939f6929e725de6ea590dc0a4caf5fa6fdacc96590e43b94c6f221a703c1c5073509e6b0700eeafde7ee99e149bdbf34a5acd948a513401ba78c4db7128e1f0aac26767f8a4754ae06a41287a12a7f3059c7a405aceb105b3748264c081240c3aa3f298a0ef5f2ea93151a25a3f746082d352eb3a52fb6f860cdf0f4d2186af5e4aa744893e8a59037daa6c23d8d31d2666c528a4ce4e249a27f7aab2bf14eeb7bf8c617380a34db5b7fade8eca02f1f030a62a2ffc7f2d2b14ec366b2a4269be4c763276195ce4c95b4c77c2cc001aac54dd6496099d7ecfe1f1e316d846ab41c4ef461ae0687588ea45532fe8bf9c91cf0840200a232adaa0b8036eaf3f29e4b2d898e8fb2315c22f4915b5746c7920a0bbc98548076e8f68a2fbf3b84df590d0a3154a66d17a80a115027c066f4d5f6c69769e52268f3cea1ee86150144bc05ba63d526e611a1ef723b0b573b37eb5949dd27875208219a77d5a8f170fcecf452ea1b4c78bc135a6345c853a2621154a664806d9fbb88a61ec7935c3511aa3ede4736ee37027e5f2ef2079447886ed5a30839eee442ff8feb17acfa832a8dedb28cbb52b07a950c5dcb853a32ed2f8c0ff83adea7b060aaf2466d148ad43d8e657')
+ ],
+ [ // Test case for issue #92 (https://github.com/vibornoff/asmcrypto.js/issues/92#issuecomment-158269407)
+ // key
+ asmCrypto.base64_to_bytes('dGQhii+B7+eLLHRiOA690w=='),
+ // nonce
+ asmCrypto.base64_to_bytes('R8q1njARXS7urWv3'),
+ // adata
+ undefined,
+ // tagSize
+ 16,
+ // plaintext
+ asmCrypto.base64_to_bytes('dGQhwoovwoHDr8OnwossdGI4DsK9w5M='),
+ // ciphertext
+ asmCrypto.base64_to_bytes('kMrwkAdqy9VuEdkUA75K2hxjjy4kyRfDXMGzg+l4CoHga1/Rh49R'),
+ ],
+ [ // Test case for issue #92 (https://github.com/vibornoff/asmcrypto.js/issues/92#issuecomment-158269407)
+ // key
+ asmCrypto.base64_to_bytes('dGQhii+B7+eLLHRiOA690w=='),
+ // nonce
+ asmCrypto.base64_to_bytes('R8q1njARXS7urWv3'),
+ // adata
+ undefined,
+ // tagSize
+ 16,
+ // plaintext
+ asmCrypto.base64_to_bytes('dGQhwoovwoHDr8OnwossdGI4DsK9w5M='),
+ // ciphertext
+ asmCrypto.base64_to_bytes('kMrwkAdqy9VuEdkUA75K2hxjjy4kyRfDXMGzg+l4CoHga1/Rh49R'),
+ ],
+ [ // Test case for issue #92 (https://github.com/vibornoff/asmcrypto.js/issues/92#issuecomment-158269407)
+ // key
+ asmCrypto.base64_to_bytes('dGQhii+B7+eLLHRiOA690w=='),
+ // nonce
+ asmCrypto.base64_to_bytes('R8q1njARXS7urWv3'),
+ // adata
+ asmCrypto.string_to_bytes(''),
+ // tagSize
+ 16,
+ // plaintext
+ asmCrypto.base64_to_bytes('dGQhwoovwoHDr8OnwossdGI4DsK9w5M='),
+ // ciphertext
+ asmCrypto.base64_to_bytes('kMrwkAdqy9VuEdkUA75K2hxjjy4kyRfDXMGzg+l4CoHga1/Rh49R'),
+ ],
+ [ // Test case for issue #92 (https://github.com/vibornoff/asmcrypto.js/issues/92#issuecomment-158269407)
+ // key
+ asmCrypto.base64_to_bytes('dGQhii+B7+eLLHRiOA690w=='),
+ // nonce
+ asmCrypto.base64_to_bytes('R8q1njARXS7urWv3'),
+ // adata
+ new Uint8Array(0),
+ // tagSize
+ 16,
+ // plaintext
+ asmCrypto.base64_to_bytes('dGQhwoovwoHDr8OnwossdGI4DsK9w5M='),
+ // ciphertext
+ asmCrypto.base64_to_bytes('kMrwkAdqy9VuEdkUA75K2hxjjy4kyRfDXMGzg+l4CoHga1/Rh49R'),
+ ],
+ [ // Test case for issue #92 (https://github.com/vibornoff/asmcrypto.js/issues/92#issuecomment-158797782)
+ // key
+ asmCrypto.hex_to_bytes('0f0e0d0c0b0a09080706050403020100'),
+ // nonce
+ asmCrypto.hex_to_bytes('000102030405060708090a0b'),
+ // adata
+ undefined,
+ // tagSize
+ 16,
+ // plaintext
+ asmCrypto.string_to_bytes('42'),
+ // ciphertext
+ asmCrypto.hex_to_bytes('28be1ac7b43d8868869b9a45d3de436cd0cc'),
+ ],
];
- for ( var i = 0; i < cmac_vectors.length; ++i ) {
- var key = new Uint8Array( cmac_vectors[i][0] ),
- data = new Uint8Array( cmac_vectors[i][1] ),
- result = new Uint8Array( cmac_vectors[i][2] );
+ it('asmCrypto.AES_CCM.encrypt / asmCrypto.AES_CCM.decrypt', function() {
+ for (let i = 0; i < ccm_aes_vectors.length; ++i) {
+ const key = ccm_aes_vectors[i][0];
+ const nonce = ccm_aes_vectors[i][1];
+ const adata = ccm_aes_vectors[i][2];
+ const tagsize = ccm_aes_vectors[i][3];
+ const clear = ccm_aes_vectors[i][4];
+ const cipher = ccm_aes_vectors[i][5];
- equal(
- asmCrypto.bytes_to_hex( asmCrypto.AES_CMAC.bytes( data, key ) ),
- asmCrypto.bytes_to_hex(result),
- "cmac vector " + i
- );
+ expect(asmCrypto.bytes_to_hex(asmCrypto.AES_CCM.encrypt(clear, key, nonce, adata, tagsize)), 'encrypt vector ' + i).to.be.equal(asmCrypto.bytes_to_hex(cipher));
- }
+ expect(asmCrypto.bytes_to_hex(asmCrypto.AES_CCM.decrypt(cipher, key, nonce, adata, tagsize)), 'decrypt vector ' + i).to.be.equal(asmCrypto.bytes_to_hex(clear));
+ }
+ });
+ });
});
diff --git a/test/bignum.js b/test/bignum.js
index 009fe69..be1317d 100644
--- a/test/bignum.js
+++ b/test/bignum.js
@@ -1,287 +1,460 @@
-module("BigNumber");
-
-///////////////////////////////////////////////////////////////////////////////
-
-if ( typeof asmCrypto.BigNumber !== 'undefined' )
-{
- test( "new asmCrypto.BigNumber()", function () {
- var zero = new asmCrypto.BigNumber();
- ok( zero, "zero = new 0" );
- equal( zero.limbs.length, 0, "zero.limbs.length" );
- equal( zero.bitLength, 0, "zero.bitLength" );
- equal( zero.valueOf(), 0, "zero.valueOf()" );
- equal( zero.toString(16), '0', "zero.toString(16)" );
-
- var one = asmCrypto.BigNumber.fromNumber(1);
- ok( one, "one = new 1" );
- equal( one.limbs.length, 1, "one.limbs.length" );
- equal( one.limbs[0], 1, "one.limbs[0]" );
- equal( one.bitLength, 32, "one.bitLength" );
- equal( one.valueOf(), 1, "one.valueOf()" );
- equal( one.toString(16), '1', "one.toString(16)" );
-
- var ten = asmCrypto.BigNumber.fromNumber(10);
- ok( ten, "ten = new 10" );
- equal( ten.limbs.length, 1, "ten.limbs.length" );
- equal( ten.limbs[0], 10, "ten.limbs[0]" );
- equal( ten.bitLength, 32, "ten.bitLength" );
- equal( ten.valueOf(), 10, "ten.valueOf()" );
- equal( ten.toString(16), 'a', "ten.toString(16)" );
-
- var mten = asmCrypto.BigNumber.fromNumber(-10);
- ok( mten, "mten = new -10" );
- equal( mten.limbs.length, 1, "mten.limbs.length" );
- equal( mten.limbs[0], 10, "mten.limbs[0]" );
- equal( mten.bitLength, 32, "mten.bitLength" );
- equal( mten.valueOf(), -10, "mten.valueOf()" );
- equal( mten.toString(16), '-a', "mten.toString(16)" );
-
- var ffffffff = asmCrypto.BigNumber.fromNumber(0xffffffff);
- ok( ffffffff, "ffffffff = new 0xfffffff" );
- equal( ffffffff.limbs.length, 1, "ffffffff.limbs.length" );
- equal( ffffffff.limbs[0], 0xffffffff, "ffffffff.limbs[0]" );
- equal( ffffffff.bitLength, 32, "ffffffff.bitLength" );
- equal( ffffffff.valueOf(), 0xffffffff, "ffffffff.valueOf()" );
- equal( ffffffff.toString(16), 'ffffffff', "ffffffff.toString(16)" );
-
- var deadbeefcafe = asmCrypto.BigNumber.fromNumber(0xdeadbeefcafe);
- ok( deadbeefcafe, "deadbeefcafe = new 0xdeadbeefcafe" );
- equal( deadbeefcafe.limbs.length, 2, "deadbeefcafe.limbs.length" );
- equal( deadbeefcafe.limbs[0], 0xbeefcafe, "deadbeefcafe.limbs[0]" );
- equal( deadbeefcafe.limbs[1], 0xdead, "deadbeefcafe.limbs[1]" );
- equal( deadbeefcafe.bitLength, 52, "deadbeefcafe.bitLength" );
- equal( deadbeefcafe.valueOf(), 0xdeadbeefcafe, "deadbeefcafe.valueOf()" );
- equal( deadbeefcafe.toString(16), 'deadbeefcafe', "deadbeefcafe.toString(16)" );
-
- var verylarge = new asmCrypto.BigNumber(asmCrypto.hex_to_bytes('3f70f29d3f3ae354a6d2536ceafba83cfc787cd91e7acd2b6bde05e62beb8295ae18e3f786726f8d034bbc15bf8331df959f59d431736d5f306aaba63dacec279484e39d76db9b527738072af15730e8b9956a64e8e4dbe868f77d1414a8a8b8bf65380a1f008d39c5fabe1a9f8343929342ab7b4f635bdc52532d764701ff3d8072c475c012ff0c59373e8bc423928d99f58c3a6d9f6ab21ee20bc8e8818fc147db09f60c81906f2c6f73dc69725f075853a89f0cd02a30a8dd86b660ccdeffc292f398efb54088c822774445a6afde471f7dd327ef9996296898a5747726ccaeeceeb2e459df98b4128cb5ab8c7cd20c563f960a1aa770f3c81f13f967b6cc'));
- ok( verylarge, "verylarge = new 3f70f29d…f967b6cc" );
- equal( verylarge.limbs.length, 64, "verylarge.limbs.length" );
- equal( verylarge.limbs[0], 0xf967b6cc, "verylarge.limbs[0]" );
- equal( verylarge.limbs[63], 0x3f70f29d, "verylarge.limbs[63]" );
- equal( verylarge.bitLength, 2048, "verylarge.bitLength" );
- equal( verylarge.valueOf(), Infinity, "verylarge.valueOf()" );
- equal( verylarge.toString(16), '3f70f29d3f3ae354a6d2536ceafba83cfc787cd91e7acd2b6bde05e62beb8295ae18e3f786726f8d034bbc15bf8331df959f59d431736d5f306aaba63dacec279484e39d76db9b527738072af15730e8b9956a64e8e4dbe868f77d1414a8a8b8bf65380a1f008d39c5fabe1a9f8343929342ab7b4f635bdc52532d764701ff3d8072c475c012ff0c59373e8bc423928d99f58c3a6d9f6ab21ee20bc8e8818fc147db09f60c81906f2c6f73dc69725f075853a89f0cd02a30a8dd86b660ccdeffc292f398efb54088c822774445a6afde471f7dd327ef9996296898a5747726ccaeeceeb2e459df98b4128cb5ab8c7cd20c563f960a1aa770f3c81f13f967b6cc', "verylarge.toString()" );
- });
-
- test( "asmCrypto.BigNumber.slice", function () {
- var deadbeefcafe = asmCrypto.BigNumber.fromNumber(0xdeadbeefcafe);
- equal( deadbeefcafe.slice(0).valueOf(), 0xdeadbeefcafe, "slice(0)" );
- equal( deadbeefcafe.slice(52).valueOf(), 0, "slice(bitLength)" );
- equal( deadbeefcafe.slice(24,16).valueOf(), 0xadbe, "slice(middle)" );
- });
-
- test( "asmCrypto.BigNumber.compare", function () {
- var deadbeefcafe = asmCrypto.BigNumber.fromNumber(0xdeadbeefcafe),
- ffffffff = asmCrypto.BigNumber.fromNumber(0xffffffff),
- result = null;
-
- result = ffffffff.compare(asmCrypto.BigNumber.fromNumber(0xffffffff));
- equal( result, 0, "ffffffff == 0xffffffff" );
-
- result = deadbeefcafe.compare(ffffffff);
- equal( result, 1, "deadbeefcafe > ffffffff" );
-
- result = ffffffff.compare(deadbeefcafe);
- equal( result, -1, "ffffffff > deadbeefcafe" );
-
- result = ffffffff.compare(asmCrypto.BigNumber.fromNumber(-10));
- equal( result, 1, "ffffffff > -10" );
- });
-
- test( "asmCrypto.BigNumber.add", function () {
- var deadbeefcafe = asmCrypto.BigNumber.fromNumber(0xdeadbeefcafe),
- ffffffff = asmCrypto.BigNumber.fromNumber(0xffffffff),
- result = null;
-
- result = deadbeefcafe.add(ffffffff);
- equal( result.toString(16), 'deaebeefcafd', "deadbeefcafe + ffffffff" );
-
- result = ffffffff.add(deadbeefcafe);
- equal( result.toString(16), 'deaebeefcafd', "ffffffff + deadbeefcafe" );
-
- result = ffffffff.add(asmCrypto.BigNumber.fromNumber(-4294967295));
- equal( result.valueOf(), 0, "ffffffff + (-ffffffff)" );
-
- result = (new asmCrypto.BigNumber(asmCrypto.hex_to_bytes('ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'))).add(new asmCrypto.BigNumber(asmCrypto.hex_to_bytes('ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff')));
- equal( result.toString(16), '10000000000000000000000000000000000000000000000000000000000000000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe', "large fff…fff" );
- });
-
- test( "asmCrypto.BigNumber.subtract", function () {
- var deadbeefcafe = asmCrypto.BigNumber.fromNumber(0xdeadbeefcafe),
- ffffffff = asmCrypto.BigNumber.fromNumber(0xffffffff),
- result = null;
-
- result = deadbeefcafe.subtract(ffffffff);
- equal( result.toString(16), 'deacbeefcaff', "deadbeefcafe - ffffffff" );
-
- result = ffffffff.subtract(deadbeefcafe);
- equal( result.toString(16), '-deacbeefcaff', "ffffffff - deadbeefcafe" );
-
- result = (new asmCrypto.BigNumber(asmCrypto.hex_to_bytes('ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'))).subtract(new asmCrypto.BigNumber(asmCrypto.hex_to_bytes('ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff')));
- equal( result.toString(16), 'ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000', "large fff…fff" );
- });
-
- test( "asmCrypto.BigNumber.multiply", function () {
- var small = asmCrypto.BigNumber.fromNumber(0xabcdabcd),
- large = new asmCrypto.BigNumber(asmCrypto.hex_to_bytes('322e393f76a1c22b147e7d193c00c023afb7c1500b006ff1bc1cc8d391fc38bd')),
- verylarge = new asmCrypto.BigNumber(asmCrypto.hex_to_bytes('3f70f29d3f3ae354a6d2536ceafba83cfc787cd91e7acd2b6bde05e62beb8295ae18e3f786726f8d034bbc15bf8331df959f59d431736d5f306aaba63dacec279484e39d76db9b527738072af15730e8b9956a64e8e4dbe868f77d1414a8a8b8bf65380a1f008d39c5fabe1a9f8343929342ab7b4f635bdc52532d764701ff3d8072c475c012ff0c59373e8bc423928d99f58c3a6d9f6ab21ee20bc8e8818fc147db09f60c81906f2c6f73dc69725f075853a89f0cd02a30a8dd86b660ccdeffc292f398efb54088c822774445a6afde471f7dd327ef9996296898a5747726ccaeeceeb2e459df98b4128cb5ab8c7cd20c563f960a1aa770f3c81f13f967b6cc')),
- result = null;
-
- result = small.multiply(asmCrypto.BigNumber.fromNumber(0x1000));
- equal( result.toString(16), 'abcdabcd000', "small product is ok" );
-
- result = large.multiply(large);
- equal( result.toString(16), '9d616b569f3248a3e8b0bdcbed25f33122fd4e63f46cdacf664809417b3af1210cfd498deef48381295f067280f14d9ec85fe251e545f5013048853daab3b89', "large product is ok");
-
- result = verylarge.multiply(verylarge);
- equal( result.toString(16), 'fb8c93e94a3fb8c87d267c2550011118c118f0a8ed6b1f2a611a13d05c363e90514fd4e4b4f8485b9113846168ba5cca86bfb8faadd25a5b978da0e95432a4203ca0c58ad4c34a81acb7065dc182a58e5bbca29b1ab195209a48dd6429aaa29ea2109ba8ea28302108b7b1812dcbbf4221e72e7d1283264bf0a2e2cb180e8687892ba428b88b92bcfdc228b733a02dceec5e0ee501b81b4ee68d66e320e3aae26f63cbd2db9f01e43844b1c40c68dfd2f329925cd1334a5af0f33f8ea509c1bb9c810bed4a4e5d0b91504cf56178027af972130bc3eaaac52868b3b0c554204d55470e05ff5dd70d8b70b8c385277329d0d4d0a5aa7a1c555750eaee4f1e1581ab56e3b1210e14d46393539ccb793e3a6a6f15bcf61b1e8a9acdf36db03457a37a1ae522c0129c18d08345ccc2f44352ed159db24272d4ac2de9e5f6c361477826b9d62be54468a9c9949ba0c772548dd28eabb4e195bb87a01244c3d44462aaa0ab3f22b48693650da8a1ffddde979533709f4dfb2b1a7c6fa98646deeb4b97f29d8c79f74f3f537845b99f8564ff046d35fbe108e13cf17c3f1b9390512fc57cd2f66d6ff94a455ba646a3ebc7464376b63126c869e2b722510243ee579882540e3d02e796c997fe1d43e2364314ba3190bc8ff0ba09855df3ef9cd3277b4f4ffeba6aeafc9513d89c012507cc8a471ea2ab91b24898afd6575e572aeb290', "verylarge product is ok");
-
- result = (new asmCrypto.BigNumber(asmCrypto.hex_to_bytes('3f70f29d3f3ae354a6d2536ceafba83cfc787cd91e7acd2b6bde05e62beb8295ae18e3f786726f8d034bbc15bf8331df959f59d431736d5f306aaba63dacec279484e39d76db9b527738072af15730e8b9956a64e8e4dbe868f77d1414a8a8b8bf65380a1f008d39c5fabe1a9f8343929342ab7b4f635bdc52532d764701ff3d8072c475c012ff0c59373e8bc423928d99f58c3a6d9f6ab21ee20bc8e8818fc147db09f60c81906f2c6f73dc69725f075853a89f0cd02a30a8dd86b660ccdeffc292f398efb54088c822774445a6afde471f7dd327ef9996296898a5747726ccaeeceeb2e459df98b4128cb5ab8c7cd20c563f960a1aa770f3c81f13f967b6cc'))).multiply(new asmCrypto.BigNumber(asmCrypto.hex_to_bytes('100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000')));
- equal( result.toString(16), '3f70f29d3f3ae354a6d2536ceafba83cfc787cd91e7acd2b6bde05e62beb8295ae18e3f786726f8d034bbc15bf8331df959f59d431736d5f306aaba63dacec279484e39d76db9b527738072af15730e8b9956a64e8e4dbe868f77d1414a8a8b8bf65380a1f008d39c5fabe1a9f8343929342ab7b4f635bdc52532d764701ff3d8072c475c012ff0c59373e8bc423928d99f58c3a6d9f6ab21ee20bc8e8818fc147db09f60c81906f2c6f73dc69725f075853a89f0cd02a30a8dd86b660ccdeffc292f398efb54088c822774445a6afde471f7dd327ef9996296898a5747726ccaeeceeb2e459df98b4128cb5ab8c7cd20c563f960a1aa770f3c81f13f967b6cc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', "verylarge2 product is ok");
- });
-
- test( "asmCrypto.BigNumber.square", function () {
- var small = new asmCrypto.BigNumber(asmCrypto.hex_to_bytes('ffffffff')),
- medium = new asmCrypto.BigNumber(asmCrypto.hex_to_bytes('ffffffffffffffff')),
- medium2 = new asmCrypto.BigNumber(asmCrypto.hex_to_bytes('ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff')),
- large = new asmCrypto.BigNumber(asmCrypto.hex_to_bytes('322e393f76a1c22b147e7d193c00c023afb7c1500b006ff1bc1cc8d391fc38bd')),
- verylarge = new asmCrypto.BigNumber(asmCrypto.hex_to_bytes('3f70f29d3f3ae354a6d2536ceafba83cfc787cd91e7acd2b6bde05e62beb8295ae18e3f786726f8d034bbc15bf8331df959f59d431736d5f306aaba63dacec279484e39d76db9b527738072af15730e8b9956a64e8e4dbe868f77d1414a8a8b8bf65380a1f008d39c5fabe1a9f8343929342ab7b4f635bdc52532d764701ff3d8072c475c012ff0c59373e8bc423928d99f58c3a6d9f6ab21ee20bc8e8818fc147db09f60c81906f2c6f73dc69725f075853a89f0cd02a30a8dd86b660ccdeffc292f398efb54088c822774445a6afde471f7dd327ef9996296898a5747726ccaeeceeb2e459df98b4128cb5ab8c7cd20c563f960a1aa770f3c81f13f967b6cc')),
- result;
-
- result = small.square();
- equal( result.toString(16), 'fffffffe00000001', "small square is ok" );
-
- result = medium.square();
- equal( result.toString(16), 'fffffffffffffffe0000000000000001', "medium square is ok" );
-
- result = medium2.square();
- equal( result.toString(16), 'fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0000000000000000000000000000000000000000000000000000000000000001', "medium2 square is ok" );
-
- result = large.square();
- equal( result.toString(16), '9d616b569f3248a3e8b0bdcbed25f33122fd4e63f46cdacf664809417b3af1210cfd498deef48381295f067280f14d9ec85fe251e545f5013048853daab3b89', "large square is ok");
-
- result = verylarge.square();
- equal( result.toString(16), 'fb8c93e94a3fb8c87d267c2550011118c118f0a8ed6b1f2a611a13d05c363e90514fd4e4b4f8485b9113846168ba5cca86bfb8faadd25a5b978da0e95432a4203ca0c58ad4c34a81acb7065dc182a58e5bbca29b1ab195209a48dd6429aaa29ea2109ba8ea28302108b7b1812dcbbf4221e72e7d1283264bf0a2e2cb180e8687892ba428b88b92bcfdc228b733a02dceec5e0ee501b81b4ee68d66e320e3aae26f63cbd2db9f01e43844b1c40c68dfd2f329925cd1334a5af0f33f8ea509c1bb9c810bed4a4e5d0b91504cf56178027af972130bc3eaaac52868b3b0c554204d55470e05ff5dd70d8b70b8c385277329d0d4d0a5aa7a1c555750eaee4f1e1581ab56e3b1210e14d46393539ccb793e3a6a6f15bcf61b1e8a9acdf36db03457a37a1ae522c0129c18d08345ccc2f44352ed159db24272d4ac2de9e5f6c361477826b9d62be54468a9c9949ba0c772548dd28eabb4e195bb87a01244c3d44462aaa0ab3f22b48693650da8a1ffddde979533709f4dfb2b1a7c6fa98646deeb4b97f29d8c79f74f3f537845b99f8564ff046d35fbe108e13cf17c3f1b9390512fc57cd2f66d6ff94a455ba646a3ebc7464376b63126c869e2b722510243ee579882540e3d02e796c997fe1d43e2364314ba3190bc8ff0ba09855df3ef9cd3277b4f4ffeba6aeafc9513d89c012507cc8a471ea2ab91b24898afd6575e572aeb290', "verylarge square is ok");
- });
-
- test( "asmCrypto.BigNumber.divide", function () {
- var small = new asmCrypto.BigNumber(asmCrypto.hex_to_bytes('95705fac129de210')),
- small2 = new asmCrypto.BigNumber(asmCrypto.hex_to_bytes('fffffffe00000002')),
- small3 = new asmCrypto.BigNumber(asmCrypto.hex_to_bytes('ffffffff')),
- large = new asmCrypto.BigNumber(asmCrypto.hex_to_bytes('9d616b569f3248a3e8b0bdcbed25f33122fd4e63f46cdacf664809417b3af1210cfd498deef48381295f067280f14d9ec85fe251e545f5013048853daab3b89')),
- large2 = new asmCrypto.BigNumber(asmCrypto.hex_to_bytes('322e393f76a1c22b147e7d193c00c023afb7c1500b006ff1bc1cc8d391fc38bd')),
- result = null;
-
- result = small.divide(asmCrypto.BigNumber.fromNumber(0xabcd));
- equal( result.remainder.toString(16), 'aaaa', "small % 0xabcd" );
- equal( result.quotient.toString(16), 'deadbeefcafe', "floor( small / 0xabcd )" );
-
- result = small2.divide(small3);
- equal( result.remainder.toString(16), '1', "small2 % small3" );
- equal( result.quotient.toString(16), 'ffffffff', "floor( small2 / small3 )" );
-
- result = large.divide(large2);
- equal( result.remainder, asmCrypto.BigNumber.ZERO, "large % large2" );
- equal( result.quotient.toString(16), '322e393f76a1c22b147e7d193c00c023afb7c1500b006ff1bc1cc8d391fc38bd', "floor( large / large2 )" );
-
- result = new asmCrypto.BigNumber(asmCrypto.hex_to_bytes('100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'))
- .divide(new asmCrypto.BigNumber(asmCrypto.hex_to_bytes('c7f1bc1dfb1be82d244aef01228c1409c198894eca9e21430f1669b4aa3864c9f37f3d51b2b4ba1ab9e80f59d267fda1521e88b05117993175e004543c6e3611242f24432ce8efa3b81f0ff660b4f91c5d52f2511a6f38181a7bf9abeef72db056508bbb4eeb5f65f161dd2d5b439655d2ae7081fcc62fdcb281520911d96700c85cdaf12e7d1f15b55ade867240722425198d4ce39019550c4c8a921fc231d3e94297688c2d77cd68ee8fdeda38b7f9a274701fef23b4eaa6c1a9c15b2d77f37634930386fc20ec291be95aed9956801e1c76601b09c413ad915ff03bfdc0b6b233686ae59e8caf11750b509ab4e57ee09202239baee3d6e392d1640185e1cd')));
- equal( result.quotient.toString(16), '1', "q is ok" );
- equal( result.remainder.toString(16), '380e43e204e417d2dbb510fedd73ebf63e6776b13561debcf0e9964b55c79b360c80c2ae4d4b45e54617f0a62d98025eade1774faee866ce8a1ffbabc391c9eedbd0dbbcd317105c47e0f0099f4b06e3a2ad0daee590c7e7e58406541108d24fa9af7444b114a09a0e9e22d2a4bc69aa2d518f7e0339d0234d7eadf6ee2698ff37a3250ed182e0ea4aa521798dbf8ddbdae672b31c6fe6aaf3b3756de03dce2c16bd689773d288329711702125c748065d8b8fe010dc4b15593e563ea4d2880c89cb6cfc7903df13d6e416a51266a97fe1e3899fe4f63bec526ea00fc4023f494dcc97951a617350ee8af4af654b1a811f6dfddc64511c291c6d2e9bfe7a1e33', "r is ok" );
-
- result = new asmCrypto.BigNumber(asmCrypto.hex_to_bytes('ad399e5f74531e554ab7e7130b8ae864c7ea09621f5fff87e07160b080e89cca0bb74448c9e792b53806bce62a0cedfed2184ea47014988c92fdbafe60771d02d5b5dcf7d4f5ac1dc0a1dd010d7ae5672efdb92b38f56b78ac54797d18a6dd363fdac5e58b68321305983c81cf4d627ed2a59c150458999e23d1d2569beb083c67fab925ae495a97acb4465aa6960d1df08a73d3f5362a53c3db3813f006d7bb7a29028d0547e918f2bb407acf60f6391b7862a1db39f26727771c61747a7766619a42864faa21d8d23317e12abbb13e0ba2ad6f7f0e3d08'))
- .divide(new asmCrypto.BigNumber(asmCrypto.hex_to_bytes('a736146b621310f6cd645cb2fefeda223aa7ae33a53ac22e019b6ffb7167d9b29be1aebb3e1a7129ee3a5b4fb1a11660932b9be2b36a6dd3226451d7c4dd79619bdb9aa5596cef4e7b6d91f0e227bba2547b004ded1ed0e06182141dc55e183374fe1d93e23c38fcc81cd8eae82647528dde963cf1ef86f470e69436a2ac0d7fa7161d6fbfd32141217df992002320cb575e8de44c446d73bdf116719d61451c474701e153a01771cb8f070f8241d465d3d0124aed70ec459669bfc4927f941ddac97f4772f8d4d55165d1d06eec147749d0b9fee868ddf3')));
- equal( result.quotient.toString(16), '1', "q is ok" );
- equal( result.remainder.toString(16), '60389f412400d5e7d538a600c8c0e428d425b2e7a253d59ded5f0b50f80c3176fd5958d8bcd218b49cc6196786bd79e3eecb2c1bcaa2ab9709969269b99a3a139da42527b88bccf45344b102b5329c4da82b8dd4bd69a984ad2655f5348c502cadca851a92bf9163d7b6396e7271b2c44c705d8126912a9b2eb3e1ff93efabcc0e49bb5ee7639568b364cc8a672ec52992be5efa8f1bce005ea21a252a5929f32e200abb1a7d1a7272c396b4d1f21d347a85056edc90621910d5c9ce1fae34886d0c33edcb14d0380cd4610bbcf9cc6c1d1f37096a55f15', "r is ok" );
-
- result = new asmCrypto.BigNumber(asmCrypto.hex_to_bytes('ad399e5f74531e554ab7e7130b8ae864c7ea09621f5fff87e07160b080e89cca0bb74448c9e792b53806bce62a0cedfed2184ea47014988c92fdbafe60771d02d5b5dcf7d4f5ac1dc0a1dd010d7ae5672efdb92b38f56b78ac54797d18a6dd363fdac5e58b68321305983c81cf4d627ed2a59c150458999e23d1d2569beb083c67fab925ae495a97acb4465aa6960d1df08a73d3f5362a53c3db3813f006d7bb7a29028d0547e918f2bb407acf60f6391b7862a1db39f26727771c61747a7766619a42864faa21d8d23317e12abbb13e0ba2ad6f7f0e3d08'))
- .divide(new asmCrypto.BigNumber(asmCrypto.hex_to_bytes('a736146b621310f6cd645cb2fefeda223aa7ae33a53ac22e019b6ffb7167d9b29be1aebb3e1a7129ee3a5b4fb1a11660932b9be2b36a6dd3226451d7c4dd79619bdb9aa5596cef4e7b6d91f0e227bba2547b004ded1ed0e06182141dc55e183374fe1d93e23c38fcc81cd8eae82647528dde963cf1ef86f470e69436a2ac0d7fa7161d6fbfd32141217df992002320cb575e8de44c446d73bdf116719d61451c474701e153a01771cb8f070f8241d465d3d0124aed70ec459669bfc4927f941ddac97f4772f8d4d55165d1d06eec147749d0b9fee868ddf3')));
- equal( result.quotient.toString(16), '1', "q is ok" );
- equal( result.remainder.toString(16), '60389f412400d5e7d538a600c8c0e428d425b2e7a253d59ded5f0b50f80c3176fd5958d8bcd218b49cc6196786bd79e3eecb2c1bcaa2ab9709969269b99a3a139da42527b88bccf45344b102b5329c4da82b8dd4bd69a984ad2655f5348c502cadca851a92bf9163d7b6396e7271b2c44c705d8126912a9b2eb3e1ff93efabcc0e49bb5ee7639568b364cc8a672ec52992be5efa8f1bce005ea21a252a5929f32e200abb1a7d1a7272c396b4d1f21d347a85056edc90621910d5c9ce1fae34886d0c33edcb14d0380cd4610bbcf9cc6c1d1f37096a55f15', "r is ok" );
-
- result = new asmCrypto.BigNumber(asmCrypto.hex_to_bytes('8251a22c009e3e37af0a516bbd73662a462531e4886005cec939265e99f177d7812fd7d5df184c5ea8ced1cace7e6724a4c31b1dbdedcd9636acff51936801df9bdf255850896b4da0aebfbc8944da8385a58f47e335ce94fd53ab1b299335c9e242fd89fc87126c11df2e65efa31fc37ce90e454b72afff5db16c271d476054022227c76c039c30feba1a1bd8d62c11b5c8a9e666b7726c4306c1e84f51c6fbe4485a2826cfacaea58d4a522a48a0164aa45df489944822953f860084d34b3ac537e27af0ed95613ffcb7f775832bf3acc7beff1469ed7a28abbff4dbf08859cafc8b8a7b3a2dc02cdff66095f53897ae74d2ce47e5644ea7ac59398a99b55'))
- .divide(new asmCrypto.BigNumber(asmCrypto.hex_to_bytes('4128d116004f1f1bd78528b5deb9b315231298f2443002e7649c932f4cf8bbebc097ebeaef8c262f546768e5673f339252618d8edef6e6cb1b567fa8c9b400efcdef92ac2844b5a6d0575fde44a26d41c2d2c7a3f19ae74a7ea9d58d94c99ae4f1217ec4fe43893608ef9732f7d18fe1be748722a5b957ffaed8b6138ea3b02a011113e3b601ce187f5d0d0dec6b1608dae454f3335bb936218360f427a8e37df2242d141367d65752c6a5291524500b25522efa44ca24114a9fc3004269a59d629bf13d7876cab09ffe5bfbbac195f9d663df7f8a34f6bd1455dffa6df8442ce57e45c53d9d16e0166ffb304afa9c4bd73a696723f2b22753d62c9cc54cdab')));
- equal( result.quotient.toString(16), '1', "q is ok" );
- equal( result.remainder.toString(16), '4128d116004f1f1bd78528b5deb9b315231298f2443002e7649c932f4cf8bbebc097ebeaef8c262f546768e5673f339252618d8edef6e6cb1b567fa8c9b400efcdef92ac2844b5a6d0575fde44a26d41c2d2c7a3f19ae74a7ea9d58d94c99ae4f1217ec4fe43893608ef9732f7d18fe1be748722a5b957ffaed8b6138ea3b02a011113e3b601ce187f5d0d0dec6b1608dae454f3335bb936218360f427a8e37df2242d141367d65752c6a5291524500b25522efa44ca24114a9fc3004269a59d629bf13d7876cab09ffe5bfbbac195f9d663df7f8a34f6bd1455dffa6df8442ce57e45c53d9d16e0166ffb304afa9c4bd73a696723f2b22753d62c9cc54cdaa', "r is ok" );
-
- result = new asmCrypto.BigNumber(asmCrypto.hex_to_bytes('8000000000000000'))
- .divide(new asmCrypto.BigNumber(asmCrypto.hex_to_bytes('80000000ffff')));
- equal( result.quotient.toString(16), 'ffff', "q is ok" );
- equal( result.remainder.toString(16), '7fff0001ffff', "r is ok" );
- });
-
- test( "asmCrypto.BigNumber.extGCD", function () {
- var z;
-
- z = asmCrypto.BigNumber.extGCD(asmCrypto.BigNumber.fromNumber(3), asmCrypto.BigNumber.fromNumber(2));
- equal( z.gcd.valueOf(), 1, "gcd ok" );
- equal( z.x.valueOf(), 1, "x ok" );
- equal( z.y.valueOf(), -1, "y ok" );
-
- z = asmCrypto.BigNumber.extGCD(asmCrypto.BigNumber.fromNumber(240), asmCrypto.BigNumber.fromNumber(46));
- equal( z.gcd.valueOf(), 2, "gcd ok" );
- equal( z.x.valueOf(), -9, "x ok" );
- equal( z.y.valueOf(), 47, "y ok" );
-
- z = asmCrypto.BigNumber.extGCD( new asmCrypto.BigNumber(asmCrypto.hex_to_bytes('abcdabcdabcd')), new asmCrypto.BigNumber(asmCrypto.hex_to_bytes('20000000000000')) );
- equal( z.gcd.valueOf(), 1, "gcd ok" );
- equal( z.x.toString(16), '9b51de3a73905', "x ok" );
- equal( z.y.toString(16), '-341e3c1e3c1e', "y ok" );
-
- z = asmCrypto.BigNumber.extGCD(
- new asmCrypto.BigNumber(asmCrypto.hex_to_bytes('00fcbd95956bea867fe1250b179fb2d4e0c59c4a2fe469a01cd90509d7d7c25cdf84f77eea1fbe509269819a828959b39b8f54a38a6f0290e48c0f3c9c45b78123')),
- new asmCrypto.BigNumber(asmCrypto.hex_to_bytes('00d5176443bebb2a31a44df711ff7c982395c5477365f3618398fd7d37fad4d2394f9458c39dec561dab0bc6c7ced1c76b29cfd2e14ec793d5d300c70d49ada9f1')),
- );
- equal( z.gcd.valueOf(), 1, "gcd ok" );
-
- z = asmCrypto.BigNumber.extGCD(
- new asmCrypto.BigNumber(asmCrypto.hex_to_bytes('100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000')),
- new asmCrypto.BigNumber(asmCrypto.hex_to_bytes('c7f1bc1dfb1be82d244aef01228c1409c198894eca9e21430f1669b4aa3864c9f37f3d51b2b4ba1ab9e80f59d267fda1521e88b05117993175e004543c6e3611242f24432ce8efa3b81f0ff660b4f91c5d52f2511a6f38181a7bf9abeef72db056508bbb4eeb5f65f161dd2d5b439655d2ae7081fcc62fdcb281520911d96700c85cdaf12e7d1f15b55ade867240722425198d4ce39019550c4c8a921fc231d3e94297688c2d77cd68ee8fdeda38b7f9a274701fef23b4eaa6c1a9c15b2d77f37634930386fc20ec291be95aed9956801e1c76601b09c413ad915ff03bfdc0b6b233686ae59e8caf11750b509ab4e57ee09202239baee3d6e392d1640185e1cd'))
- );
- equal( z.gcd.valueOf(), 1, "gcd ok" );
- equal( z.x.toString(16), '-210fc146c2f2919c3e9a4372a7221069fa359d7feba4ecaf765c47f29819a82ebb92c5944f921e090c8f0eee5218d243b35eb488fdef6a2f9712ba887625af9599b2a547595528054f079124831d94872243009cec4e3154199893d700c2a64c3fae1e259bd37b4f88e34a6ff0fcb7c221a9b222df4a74f4d381259c641cef4d05bbbc737ac29f06e050139aa823d00c2af2b484720a58eadc39ea10d53c8664289e5495fcb188abecb167c8b81a267a24fa304b447d484c37af38525f5c1c3c7bc9e614b779e21d582c0222fa8bc13bc37673cefbb60a84a70423dcec8850d6c3c80c244e09cee87e7f6dadaf24a2b9410bc31e1afc588f9d20d769a5c3df71', "x ok" );
- equal( z.y.toString(16), '2a54a02a4b2182e2ea06578065a9608f53c45bd34ab2d3c47c18bca20e2bf9d93f6ac1aecc7a4bf18cfbc073db8cd0829b656bcb1f7a52b10bdc463ac246f11a30c0cc4ea00f093fcb0b4809a2b83bfb627789c6daac33d467a2b7bcda403018b344ca065fecccd2922afd53268ea599b17b96f29fe9fa4487cd0df93db31f3197a1973fafdd5f37a9f80f2554947ed63ffa4f12f0c5eefec24e9192ddcbc19ad179f76d95e361250300f18de3f7c9a067b84ccba3b31e1d1cf4379a492aa916882e09fa6836e3524b9bf750cf8f8dddbb48dd2ac0a9cfdfe6409330c0d62f08d13ec220436482bb39db9b1c595c5e0e0b743344620ac8eb0e18b0d3c641f305', "y ok" );
- });
-
- test( "asmCrypto.Modulus", function () {
- var M = new asmCrypto.Modulus(asmCrypto.BigNumber.fromNumber(123456789));
-
- ok( M, "new Modulus" );
- equal( M.reduce(asmCrypto.BigNumber.fromNumber(987654321)).valueOf(), 9, "Modulus.reduce(small)" );
-
- var M2 = new asmCrypto.Modulus(asmCrypto.BigNumber.fromNumber(0xabcdabcdabcd));
- equal( M2.comodulus.toString(16), '10000000000000000', "M2 comodulus ok" );
- equal( M2.comodulusRemainder.toString(16), '624f6250624f', "M2 comodulus remainder ok" );
- equal( M2.comodulusRemainderSquare.toString(16), '399f399e399e', "M2 comodulus remainder square ok" );
- equal( M2.coefficient.toString(16), '1c58c6fb', "M2 coefficent ok" );
-
- var M3 = new asmCrypto.Modulus(new asmCrypto.BigNumber(asmCrypto.hex_to_bytes('c7f1bc1dfb1be82d244aef01228c1409c198894eca9e21430f1669b4aa3864c9f37f3d51b2b4ba1ab9e80f59d267fda1521e88b05117993175e004543c6e3611242f24432ce8efa3b81f0ff660b4f91c5d52f2511a6f38181a7bf9abeef72db056508bbb4eeb5f65f161dd2d5b439655d2ae7081fcc62fdcb281520911d96700c85cdaf12e7d1f15b55ade867240722425198d4ce39019550c4c8a921fc231d3e94297688c2d77cd68ee8fdeda38b7f9a274701fef23b4eaa6c1a9c15b2d77f37634930386fc20ec291be95aed9956801e1c76601b09c413ad915ff03bfdc0b6b233686ae59e8caf11750b509ab4e57ee09202239baee3d6e392d1640185e1cd')));
- equal( M3.comodulus.toString(16), '100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', "M3 comodulus ok" );
- equal( M3.comodulusRemainder.toString(16), '380e43e204e417d2dbb510fedd73ebf63e6776b13561debcf0e9964b55c79b360c80c2ae4d4b45e54617f0a62d98025eade1774faee866ce8a1ffbabc391c9eedbd0dbbcd317105c47e0f0099f4b06e3a2ad0daee590c7e7e58406541108d24fa9af7444b114a09a0e9e22d2a4bc69aa2d518f7e0339d0234d7eadf6ee2698ff37a3250ed182e0ea4aa521798dbf8ddbdae672b31c6fe6aaf3b3756de03dce2c16bd689773d288329711702125c748065d8b8fe010dc4b15593e563ea4d2880c89cb6cfc7903df13d6e416a51266a97fe1e3899fe4f63bec526ea00fc4023f494dcc97951a617350ee8af4af654b1a811f6dfddc64511c291c6d2e9bfe7a1e33', "M3 comodulus remainder ok" );
- equal( M3.comodulusRemainderSquare.toString(16), 'a8d0cc3c0069b1fe694294247f367071deb9b3fdc80824536f04fae0c3df7fccc9f856aeee2033803b371a3c455522fb288c60f326db2fdcaf7452b48b0f0a29cce2dabe844a63f8077be24d2a0db5051e8a1481c16f0b880819cf8d193adaa79c92f11f1e4a2e89f24bc0ef0e2285ff218a5c058908f6feef024b0c8bfe11d37cba38103339f19ba7466f3070588152f1a008dc454cebcc4f70879e94ac1eb26179833049da7b450fbe93d7d802edc5900b3a973d05ff76c6bbb7914c59b27265222501b14497fe0ef99b7fa67777bf9ab89a8b346aacb6dbf606e68da0ba2a5c4ce3b0f85225292cd1acafebae5f553c03e9c3857730c715017550e4e77a53', "M3 comodulus remainder square ok" );
- equal( M3.coefficient.toString(16), "39be0cfb", "M3 coefficent ok" );
-
- var M4 = new asmCrypto.Modulus( new asmCrypto.BigNumber(asmCrypto.hex_to_bytes('453b5e276054110d94fd7b413ca54e467543c28168730315dae65c6241c847aa7ca16aa99e84e89249addf73bdb326cb7787a667cce65537cd0be7a3564f40fecace8bd6eac901013d5cd5dc28ec9415defff41e30b495bf269472e66e163493403396b14e27c1c9697e90a6274ea8dfda5bcf94d014ed7fa9c64174c78deb2ca1222521f161eafa0752dddecb31c76968929a42669174c9839b97036a2371b5d1466fe5549e53bcc7f30f7ba676950bd7a751e9e916c6525f49bf3046903ff738c5b0514ffe375ba9fe41bb766daf5973ca1d7782d84628e59b3dfa14d7c86fb3d62a219176e84e17d6fae34faa461094ae0ffd9631dd49c9138f6691a1a854') ));
- equal( M4.inverse( new asmCrypto.BigNumber(asmCrypto.hex_to_bytes('145cc156e018b9b8b3599cb8d59a07f69af5cfcbb54f00e84f70edfec80dbab9ac2f79b96adbcbeeca6050c7b043c01db9be7c3ca5ad281f788b07e4bf08404af05addd5cc9578c4211b4df57572c2248ce1de633b806847479512bc3e7f00678b5a779d8f751ae0e2cadf3fed717cf68b846a3ad3c9eb7fe6a3b8e61c93270d2055563728e09067a7cd141459e176e2c4675a8c000ca9e0ea790e4c4c64c7175bab4e16461072fb49de139cd69b59037ba9aeae357f2b456751ecf014c103c12ed0bb6335a51f5731ff7cbeaa5c7ede12ff35d7db308d1b165ad5fe425d954e07b775cda34117260702fe7f176e50d7b34240f03b3bd7ac4a32edf0fda80455') )).toString(16), '11', "M4 inverse OK" );
-
- var M5 = new asmCrypto.Modulus( new asmCrypto.BigNumber(asmCrypto.hex_to_bytes('0aabbccddaabbccdd')) );
- equal( M5.reduce( new asmCrypto.BigNumber(asmCrypto.hex_to_bytes('1aabbccddaabbccdd')) ).toString(16), '5544332255443323', "M5 reduce ok" );
- });
-
- test( "asmCrypto.Modulus.power", function () {
- var base = new asmCrypto.BigNumber(asmCrypto.hex_to_bytes('3f70f29d3f3ae354a6d2536ceafba83cfc787cd91e7acd2b6bde05e62beb8295ae18e3f786726f8d034bbc15bf8331df959f59d431736d5f306aaba63dacec279484e39d76db9b527738072af15730e8b9956a64e8e4dbe868f77d1414a8a8b8bf65380a1f008d39c5fabe1a9f8343929342ab7b4f635bdc52532d764701ff3d8072c475c012ff0c59373e8bc423928d99f58c3a6d9f6ab21ee20bc8e8818fc147db09f60c81906f2c6f73dc69725f075853a89f0cd02a30a8dd86b660ccdeffc292f398efb54088c822774445a6afde471f7dd327ef9996296898a5747726ccaeeceeb2e459df98b4128cb5ab8c7cd20c563f960a1aa770f3c81f13f967b6cc')),
- modulus = new asmCrypto.Modulus(new asmCrypto.BigNumber(asmCrypto.hex_to_bytes('c7f1bc1dfb1be82d244aef01228c1409c198894eca9e21430f1669b4aa3864c9f37f3d51b2b4ba1ab9e80f59d267fda1521e88b05117993175e004543c6e3611242f24432ce8efa3b81f0ff660b4f91c5d52f2511a6f38181a7bf9abeef72db056508bbb4eeb5f65f161dd2d5b439655d2ae7081fcc62fdcb281520911d96700c85cdaf12e7d1f15b55ade867240722425198d4ce39019550c4c8a921fc231d3e94297688c2d77cd68ee8fdeda38b7f9a274701fef23b4eaa6c1a9c15b2d77f37634930386fc20ec291be95aed9956801e1c76601b09c413ad915ff03bfdc0b6b233686ae59e8caf11750b509ab4e57ee09202239baee3d6e392d1640185e1cd'))),
- exponent = new asmCrypto.BigNumber(asmCrypto.hex_to_bytes('322e393f76a1c22b147e7d193c00c023afb7c1500b006ff1bc1cc8d391fc38bd'));
-
- equal( modulus.power( base, exponent ).toString(16), '5b3823974b3eda87286d3f38499de290bd575d8b02f06720acacf3d50950f9ca0ff6b749f3be03913ddca0b291e0b263bdab6c9cb97e4ab47ee9c235ff20931a8ca358726fab93614e2c549594f5c50b1c979b34f840b6d4fc51d6feb2dd072995421d17862cb405e040fc1ed662a3245a1f97bbafa6d1f7f76c7db6a802e3037acdf01ab5053f5da518d6753477193b9c25e1720519dcb9e2f6e70d5786656d356151845a49861dfc40187eff0e85cd18b1f3f3b97c476472edfa090b868b2388edfffecc521c20df8cebb8aacfb3669b020330dd6ea64b2a3067a972b8f249bccc19347eff43893e916f0949bd5789a5cce0f8b7cd87cece909d679345c0d4', "Modulus.power ok" );
- });
-
- test( "asmCrypto.isProbablePrime", function () {
- var p = new asmCrypto.BigNumber(asmCrypto.hex_to_bytes('8844ae66464b4b7db53644be87617124f314a1d8243d347867c8cfd6afb595bdb88ce63538fbd6c3f8461133d77ed4f5ef403f48c65b7340c683839c00bc7874bff3e9ffe7916a3ca085c7096f31871f2d628198f9c1deaeaefa581ebaef834a89afdf663b9570287a257bd6e4f507cede3b31eda6bd7fd4f8ae3c5b8791d89f'));
- ok( p.isProbablePrime(), "p is probable prime" );
- });
-}
-else
-{
- skip( "asmCrypto.BigNumber" );
-}
+import * as asmCrypto from '../asmcrypto.all.es8';
+import chai from 'chai';
+const expect = chai.expect;
+
+describe('Bignum', () => {
+ it('new asmCrypto.BigNumber()', function() {
+ const zero = new asmCrypto.BigNumber();
+ expect(zero.limbs.length, 'zero.limbs.length').to.equal(0);
+ expect(zero.bitLength, 'zero.bitLength').to.equal(0);
+ expect(zero.valueOf(), 'zero.valueOf()').to.equal(0);
+ expect(zero.toString(16), 'zero.toString(16)').to.equal('0');
+
+ const one = asmCrypto.BigNumber.fromNumber(1);
+ expect(one.limbs.length, 'one.limbs.length').to.equal(1);
+ expect(one.limbs[0], 'one.limbs[0]').to.equal(1);
+ expect(one.bitLength, 'one.bitLength').to.equal(32);
+ expect(one.valueOf(), 'one.valueOf()').to.equal(1);
+ expect(one.toString(16), 'one.toString(16)').to.equal('1');
+
+ const ten = asmCrypto.BigNumber.fromNumber(10);
+ expect(ten.limbs.length, 'ten.limbs.length').to.equal(1);
+ expect(ten.limbs[0], 'ten.limbs[0]').to.equal(10);
+ expect(ten.bitLength, 'ten.bitLength').to.equal(32);
+ expect(ten.valueOf(), 'ten.valueOf()').to.equal(10);
+ expect(ten.toString(16), 'ten.toString(16)').to.equal('a');
+
+ const mten = asmCrypto.BigNumber.fromNumber(-10);
+ expect(mten.limbs.length, 'mten.limbs.length').to.equal(1);
+ expect(mten.limbs[0], 'mten.limbs[0]').to.equal(10);
+ expect(mten.bitLength, 'mten.bitLength').to.equal(32);
+ expect(mten.valueOf(), 'mten.valueOf()').to.equal(-10);
+ expect(mten.toString(16), 'mten.toString(16)').to.equal('-a');
+
+ const ffffffff = asmCrypto.BigNumber.fromNumber(0xffffffff);
+ expect(ffffffff.limbs.length, 'ffffffff.limbs.length').to.equal(1);
+ expect(ffffffff.limbs[0], 'ffffffff.limbs[0]').to.equal(0xffffffff);
+ expect(ffffffff.bitLength, 'ffffffff.bitLength').to.equal(32);
+ expect(ffffffff.valueOf(), 'ffffffff.valueOf()').to.equal(0xffffffff);
+ expect(ffffffff.toString(16), 'ffffffff.toString(16)').to.equal('ffffffff');
+
+ const deadbeefcafe = asmCrypto.BigNumber.fromNumber(0xdeadbeefcafe);
+ expect(deadbeefcafe.limbs.length, 'deadbeefcafe.limbs.length').to.equal(2);
+ expect(deadbeefcafe.limbs[0], 'deadbeefcafe.limbs[0]').to.equal(0xbeefcafe);
+ expect(deadbeefcafe.limbs[1], 'deadbeefcafe.limbs[1]').to.equal(0xdead);
+ expect(deadbeefcafe.bitLength, 'deadbeefcafe.bitLength').to.equal(52);
+ expect(deadbeefcafe.valueOf(), 'deadbeefcafe.valueOf()').to.equal(0xdeadbeefcafe);
+ expect(deadbeefcafe.toString(16), 'deadbeefcafe.toString(16)').to.equal('deadbeefcafe');
+
+ const verylarge = new asmCrypto.BigNumber(
+ asmCrypto.hex_to_bytes(
+ '3f70f29d3f3ae354a6d2536ceafba83cfc787cd91e7acd2b6bde05e62beb8295ae18e3f786726f8d034bbc15bf8331df959f59d431736d5f306aaba63dacec279484e39d76db9b527738072af15730e8b9956a64e8e4dbe868f77d1414a8a8b8bf65380a1f008d39c5fabe1a9f8343929342ab7b4f635bdc52532d764701ff3d8072c475c012ff0c59373e8bc423928d99f58c3a6d9f6ab21ee20bc8e8818fc147db09f60c81906f2c6f73dc69725f075853a89f0cd02a30a8dd86b660ccdeffc292f398efb54088c822774445a6afde471f7dd327ef9996296898a5747726ccaeeceeb2e459df98b4128cb5ab8c7cd20c563f960a1aa770f3c81f13f967b6cc',
+ ),
+ );
+ expect(verylarge.limbs.length, 'verylarge.limbs.length').to.equal(64);
+ expect(verylarge.limbs[0], 'verylarge.limbs[0]').to.equal(0xf967b6cc);
+ expect(verylarge.limbs[63], 'verylarge.limbs[63]').to.equal(0x3f70f29d);
+ expect(verylarge.bitLength, 'verylarge.bitLength').to.equal(2048);
+ expect(verylarge.valueOf(), 'verylarge.valueOf()').to.equal(Infinity);
+ expect(verylarge.toString(16), 'verylarge.toString()').to.equal(
+ '3f70f29d3f3ae354a6d2536ceafba83cfc787cd91e7acd2b6bde05e62beb8295ae18e3f786726f8d034bbc15bf8331df959f59d431736d5f306aaba63dacec279484e39d76db9b527738072af15730e8b9956a64e8e4dbe868f77d1414a8a8b8bf65380a1f008d39c5fabe1a9f8343929342ab7b4f635bdc52532d764701ff3d8072c475c012ff0c59373e8bc423928d99f58c3a6d9f6ab21ee20bc8e8818fc147db09f60c81906f2c6f73dc69725f075853a89f0cd02a30a8dd86b660ccdeffc292f398efb54088c822774445a6afde471f7dd327ef9996296898a5747726ccaeeceeb2e459df98b4128cb5ab8c7cd20c563f960a1aa770f3c81f13f967b6cc',
+ );
+ });
+
+ it('asmCrypto.BigNumber.slice', function() {
+ const deadbeefcafe = asmCrypto.BigNumber.fromNumber(0xdeadbeefcafe);
+ expect(deadbeefcafe.slice(0).valueOf(), 'slice(0)').to.equal(0xdeadbeefcafe);
+ expect(deadbeefcafe.slice(52).valueOf(), 'slice(bitLength)').to.equal(0);
+ expect(deadbeefcafe.slice(24, 16).valueOf(), 'slice(middle)').to.equal(0xadbe);
+ });
+
+ it('asmCrypto.BigNumber.compare', function() {
+ const deadbeefcafe = asmCrypto.BigNumber.fromNumber(0xdeadbeefcafe);
+ const ffffffff = asmCrypto.BigNumber.fromNumber(0xffffffff);
+ let result = null;
+
+ result = ffffffff.compare(asmCrypto.BigNumber.fromNumber(0xffffffff));
+ expect(result, 'ffffffff == 0xffffffff').to.equal(0);
+
+ result = deadbeefcafe.compare(ffffffff);
+ expect(result, 'deadbeefcafe > ffffffff').to.equal(1);
+
+ result = ffffffff.compare(deadbeefcafe);
+ expect(result, 'ffffffff > deadbeefcafe').to.equal(-1);
+
+ result = ffffffff.compare(asmCrypto.BigNumber.fromNumber(-10));
+ expect(result, 'ffffffff > -10').to.equal(1);
+ });
+
+ it('asmCrypto.BigNumber.add', function() {
+ const deadbeefcafe = asmCrypto.BigNumber.fromNumber(0xdeadbeefcafe);
+ const ffffffff = asmCrypto.BigNumber.fromNumber(0xffffffff);
+ let result = null;
+
+ result = deadbeefcafe.add(ffffffff);
+ expect(result.toString(16), 'deadbeefcafe + ffffffff').to.equal('deaebeefcafd');
+
+ result = ffffffff.add(deadbeefcafe);
+ expect(result.toString(16), 'ffffffff + deadbeefcafe').to.equal('deaebeefcafd');
+
+ result = ffffffff.add(asmCrypto.BigNumber.fromNumber(-4294967295));
+ expect(result.valueOf(), 'ffffffff + (-ffffffff)').to.equal(0);
+
+ result = new asmCrypto.BigNumber(
+ asmCrypto.hex_to_bytes('ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'),
+ ).add(
+ new asmCrypto.BigNumber(
+ asmCrypto.hex_to_bytes(
+ 'ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff',
+ ),
+ ),
+ );
+ expect(result.toString(16), 'large fff…fff').to.equal(
+ '10000000000000000000000000000000000000000000000000000000000000000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe',
+ );
+ });
+
+ it('asmCrypto.BigNumber.subtract', function() {
+ const deadbeefcafe = asmCrypto.BigNumber.fromNumber(0xdeadbeefcafe);
+ const ffffffff = asmCrypto.BigNumber.fromNumber(0xffffffff);
+ let result = null;
+
+ result = deadbeefcafe.subtract(ffffffff);
+ expect(result.toString(16), 'deadbeefcafe - ffffffff').to.equal('deacbeefcaff');
+
+ result = ffffffff.subtract(deadbeefcafe);
+ expect(result.toString(16), 'ffffffff - deadbeefcafe').to.equal('-deacbeefcaff');
+
+ result = new asmCrypto.BigNumber(
+ asmCrypto.hex_to_bytes(
+ 'ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff',
+ ),
+ ).subtract(
+ new asmCrypto.BigNumber(
+ asmCrypto.hex_to_bytes('ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'),
+ ),
+ );
+ expect(result.toString(16), 'large fff…fff').to.equal(
+ 'ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000',
+ );
+ });
+
+ it('asmCrypto.BigNumber.multiply', function() {
+ const small = asmCrypto.BigNumber.fromNumber(0xabcdabcd);
+ const large = new asmCrypto.BigNumber(
+ asmCrypto.hex_to_bytes('322e393f76a1c22b147e7d193c00c023afb7c1500b006ff1bc1cc8d391fc38bd'),
+ );
+ const verylarge = new asmCrypto.BigNumber(
+ asmCrypto.hex_to_bytes(
+ '3f70f29d3f3ae354a6d2536ceafba83cfc787cd91e7acd2b6bde05e62beb8295ae18e3f786726f8d034bbc15bf8331df959f59d431736d5f306aaba63dacec279484e39d76db9b527738072af15730e8b9956a64e8e4dbe868f77d1414a8a8b8bf65380a1f008d39c5fabe1a9f8343929342ab7b4f635bdc52532d764701ff3d8072c475c012ff0c59373e8bc423928d99f58c3a6d9f6ab21ee20bc8e8818fc147db09f60c81906f2c6f73dc69725f075853a89f0cd02a30a8dd86b660ccdeffc292f398efb54088c822774445a6afde471f7dd327ef9996296898a5747726ccaeeceeb2e459df98b4128cb5ab8c7cd20c563f960a1aa770f3c81f13f967b6cc',
+ ),
+ );
+ let result = null;
+
+ result = small.multiply(asmCrypto.BigNumber.fromNumber(0x1000));
+ expect(result.toString(16), 'small product is ok').to.equal('abcdabcd000');
+
+ result = large.multiply(large);
+ expect(result.toString(16), 'large product is ok').to.equal(
+ '9d616b569f3248a3e8b0bdcbed25f33122fd4e63f46cdacf664809417b3af1210cfd498deef48381295f067280f14d9ec85fe251e545f5013048853daab3b89',
+ );
+
+ result = verylarge.multiply(verylarge);
+ expect(result.toString(16), 'verylarge product is ok').to.equal(
+ 'fb8c93e94a3fb8c87d267c2550011118c118f0a8ed6b1f2a611a13d05c363e90514fd4e4b4f8485b9113846168ba5cca86bfb8faadd25a5b978da0e95432a4203ca0c58ad4c34a81acb7065dc182a58e5bbca29b1ab195209a48dd6429aaa29ea2109ba8ea28302108b7b1812dcbbf4221e72e7d1283264bf0a2e2cb180e8687892ba428b88b92bcfdc228b733a02dceec5e0ee501b81b4ee68d66e320e3aae26f63cbd2db9f01e43844b1c40c68dfd2f329925cd1334a5af0f33f8ea509c1bb9c810bed4a4e5d0b91504cf56178027af972130bc3eaaac52868b3b0c554204d55470e05ff5dd70d8b70b8c385277329d0d4d0a5aa7a1c555750eaee4f1e1581ab56e3b1210e14d46393539ccb793e3a6a6f15bcf61b1e8a9acdf36db03457a37a1ae522c0129c18d08345ccc2f44352ed159db24272d4ac2de9e5f6c361477826b9d62be54468a9c9949ba0c772548dd28eabb4e195bb87a01244c3d44462aaa0ab3f22b48693650da8a1ffddde979533709f4dfb2b1a7c6fa98646deeb4b97f29d8c79f74f3f537845b99f8564ff046d35fbe108e13cf17c3f1b9390512fc57cd2f66d6ff94a455ba646a3ebc7464376b63126c869e2b722510243ee579882540e3d02e796c997fe1d43e2364314ba3190bc8ff0ba09855df3ef9cd3277b4f4ffeba6aeafc9513d89c012507cc8a471ea2ab91b24898afd6575e572aeb290',
+ );
+
+ result = new asmCrypto.BigNumber(
+ asmCrypto.hex_to_bytes(
+ '3f70f29d3f3ae354a6d2536ceafba83cfc787cd91e7acd2b6bde05e62beb8295ae18e3f786726f8d034bbc15bf8331df959f59d431736d5f306aaba63dacec279484e39d76db9b527738072af15730e8b9956a64e8e4dbe868f77d1414a8a8b8bf65380a1f008d39c5fabe1a9f8343929342ab7b4f635bdc52532d764701ff3d8072c475c012ff0c59373e8bc423928d99f58c3a6d9f6ab21ee20bc8e8818fc147db09f60c81906f2c6f73dc69725f075853a89f0cd02a30a8dd86b660ccdeffc292f398efb54088c822774445a6afde471f7dd327ef9996296898a5747726ccaeeceeb2e459df98b4128cb5ab8c7cd20c563f960a1aa770f3c81f13f967b6cc',
+ ),
+ ).multiply(
+ new asmCrypto.BigNumber(
+ asmCrypto.hex_to_bytes(
+ '100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
+ ),
+ ),
+ );
+ expect(result.toString(16), 'verylarge2 product is ok').to.equal(
+ '3f70f29d3f3ae354a6d2536ceafba83cfc787cd91e7acd2b6bde05e62beb8295ae18e3f786726f8d034bbc15bf8331df959f59d431736d5f306aaba63dacec279484e39d76db9b527738072af15730e8b9956a64e8e4dbe868f77d1414a8a8b8bf65380a1f008d39c5fabe1a9f8343929342ab7b4f635bdc52532d764701ff3d8072c475c012ff0c59373e8bc423928d99f58c3a6d9f6ab21ee20bc8e8818fc147db09f60c81906f2c6f73dc69725f075853a89f0cd02a30a8dd86b660ccdeffc292f398efb54088c822774445a6afde471f7dd327ef9996296898a5747726ccaeeceeb2e459df98b4128cb5ab8c7cd20c563f960a1aa770f3c81f13f967b6cc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
+ );
+ });
+
+ it('asmCrypto.BigNumber.square', function() {
+ const small = new asmCrypto.BigNumber(asmCrypto.hex_to_bytes('ffffffff'));
+ const medium = new asmCrypto.BigNumber(asmCrypto.hex_to_bytes('ffffffffffffffff'));
+ const medium2 = new asmCrypto.BigNumber(
+ asmCrypto.hex_to_bytes('ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'),
+ );
+ const large = new asmCrypto.BigNumber(
+ asmCrypto.hex_to_bytes('322e393f76a1c22b147e7d193c00c023afb7c1500b006ff1bc1cc8d391fc38bd'),
+ );
+ const verylarge = new asmCrypto.BigNumber(
+ asmCrypto.hex_to_bytes(
+ '3f70f29d3f3ae354a6d2536ceafba83cfc787cd91e7acd2b6bde05e62beb8295ae18e3f786726f8d034bbc15bf8331df959f59d431736d5f306aaba63dacec279484e39d76db9b527738072af15730e8b9956a64e8e4dbe868f77d1414a8a8b8bf65380a1f008d39c5fabe1a9f8343929342ab7b4f635bdc52532d764701ff3d8072c475c012ff0c59373e8bc423928d99f58c3a6d9f6ab21ee20bc8e8818fc147db09f60c81906f2c6f73dc69725f075853a89f0cd02a30a8dd86b660ccdeffc292f398efb54088c822774445a6afde471f7dd327ef9996296898a5747726ccaeeceeb2e459df98b4128cb5ab8c7cd20c563f960a1aa770f3c81f13f967b6cc',
+ ),
+ );
+ let result;
+
+ result = small.square();
+ expect(result.toString(16), 'small square is ok').to.equal('fffffffe00000001');
+
+ result = medium.square();
+ expect(result.toString(16), 'medium square is ok').to.equal('fffffffffffffffe0000000000000001');
+
+ result = medium2.square();
+ expect(result.toString(16), 'medium2 square is ok').to.equal(
+ 'fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0000000000000000000000000000000000000000000000000000000000000001',
+ );
+
+ result = large.square();
+ expect(result.toString(16), 'large square is ok').to.equal(
+ '9d616b569f3248a3e8b0bdcbed25f33122fd4e63f46cdacf664809417b3af1210cfd498deef48381295f067280f14d9ec85fe251e545f5013048853daab3b89',
+ );
+
+ result = verylarge.square();
+ expect(result.toString(16), 'verylarge square is ok').to.equal(
+ 'fb8c93e94a3fb8c87d267c2550011118c118f0a8ed6b1f2a611a13d05c363e90514fd4e4b4f8485b9113846168ba5cca86bfb8faadd25a5b978da0e95432a4203ca0c58ad4c34a81acb7065dc182a58e5bbca29b1ab195209a48dd6429aaa29ea2109ba8ea28302108b7b1812dcbbf4221e72e7d1283264bf0a2e2cb180e8687892ba428b88b92bcfdc228b733a02dceec5e0ee501b81b4ee68d66e320e3aae26f63cbd2db9f01e43844b1c40c68dfd2f329925cd1334a5af0f33f8ea509c1bb9c810bed4a4e5d0b91504cf56178027af972130bc3eaaac52868b3b0c554204d55470e05ff5dd70d8b70b8c385277329d0d4d0a5aa7a1c555750eaee4f1e1581ab56e3b1210e14d46393539ccb793e3a6a6f15bcf61b1e8a9acdf36db03457a37a1ae522c0129c18d08345ccc2f44352ed159db24272d4ac2de9e5f6c361477826b9d62be54468a9c9949ba0c772548dd28eabb4e195bb87a01244c3d44462aaa0ab3f22b48693650da8a1ffddde979533709f4dfb2b1a7c6fa98646deeb4b97f29d8c79f74f3f537845b99f8564ff046d35fbe108e13cf17c3f1b9390512fc57cd2f66d6ff94a455ba646a3ebc7464376b63126c869e2b722510243ee579882540e3d02e796c997fe1d43e2364314ba3190bc8ff0ba09855df3ef9cd3277b4f4ffeba6aeafc9513d89c012507cc8a471ea2ab91b24898afd6575e572aeb290',
+ );
+ });
+
+ it('asmCrypto.BigNumber.divide', function() {
+ const small = new asmCrypto.BigNumber(asmCrypto.hex_to_bytes('95705fac129de210'));
+ const small2 = new asmCrypto.BigNumber(asmCrypto.hex_to_bytes('fffffffe00000002'));
+ const small3 = new asmCrypto.BigNumber(asmCrypto.hex_to_bytes('ffffffff'));
+ const large = new asmCrypto.BigNumber(
+ asmCrypto.hex_to_bytes(
+ '9d616b569f3248a3e8b0bdcbed25f33122fd4e63f46cdacf664809417b3af1210cfd498deef48381295f067280f14d9ec85fe251e545f5013048853daab3b89',
+ ),
+ );
+ const large2 = new asmCrypto.BigNumber(
+ asmCrypto.hex_to_bytes('322e393f76a1c22b147e7d193c00c023afb7c1500b006ff1bc1cc8d391fc38bd'),
+ );
+ let result = null;
+
+ result = small.divide(asmCrypto.BigNumber.fromNumber(0xabcd));
+ expect(result.remainder.toString(16), 'small % 0xabcd').to.equal('aaaa');
+ expect(result.quotient.toString(16), 'floor( small / 0xabcd )').to.equal('deadbeefcafe');
+
+ result = small2.divide(small3);
+ expect(result.remainder.toString(16), 'small2 % small3').to.equal('1');
+ expect(result.quotient.toString(16), 'floor( small2 / small3 )').to.equal('ffffffff');
+
+ result = large.divide(large2);
+ expect(result.remainder, 'large % large2').to.deep.equal(asmCrypto.BigNumber.ZERO);
+ expect(result.quotient.toString(16), 'floor( large / large2 )').to.equal(
+ '322e393f76a1c22b147e7d193c00c023afb7c1500b006ff1bc1cc8d391fc38bd',
+ );
+
+ result = new asmCrypto.BigNumber(
+ asmCrypto.hex_to_bytes(
+ '100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
+ ),
+ ).divide(
+ new asmCrypto.BigNumber(
+ asmCrypto.hex_to_bytes(
+ 'c7f1bc1dfb1be82d244aef01228c1409c198894eca9e21430f1669b4aa3864c9f37f3d51b2b4ba1ab9e80f59d267fda1521e88b05117993175e004543c6e3611242f24432ce8efa3b81f0ff660b4f91c5d52f2511a6f38181a7bf9abeef72db056508bbb4eeb5f65f161dd2d5b439655d2ae7081fcc62fdcb281520911d96700c85cdaf12e7d1f15b55ade867240722425198d4ce39019550c4c8a921fc231d3e94297688c2d77cd68ee8fdeda38b7f9a274701fef23b4eaa6c1a9c15b2d77f37634930386fc20ec291be95aed9956801e1c76601b09c413ad915ff03bfdc0b6b233686ae59e8caf11750b509ab4e57ee09202239baee3d6e392d1640185e1cd',
+ ),
+ ),
+ );
+ expect(result.quotient.toString(16), 'q is ok').to.equal('1');
+ expect(result.remainder.toString(16), 'r is ok').to.equal(
+ '380e43e204e417d2dbb510fedd73ebf63e6776b13561debcf0e9964b55c79b360c80c2ae4d4b45e54617f0a62d98025eade1774faee866ce8a1ffbabc391c9eedbd0dbbcd317105c47e0f0099f4b06e3a2ad0daee590c7e7e58406541108d24fa9af7444b114a09a0e9e22d2a4bc69aa2d518f7e0339d0234d7eadf6ee2698ff37a3250ed182e0ea4aa521798dbf8ddbdae672b31c6fe6aaf3b3756de03dce2c16bd689773d288329711702125c748065d8b8fe010dc4b15593e563ea4d2880c89cb6cfc7903df13d6e416a51266a97fe1e3899fe4f63bec526ea00fc4023f494dcc97951a617350ee8af4af654b1a811f6dfddc64511c291c6d2e9bfe7a1e33',
+ );
+
+ result = new asmCrypto.BigNumber(
+ asmCrypto.hex_to_bytes(
+ 'ad399e5f74531e554ab7e7130b8ae864c7ea09621f5fff87e07160b080e89cca0bb74448c9e792b53806bce62a0cedfed2184ea47014988c92fdbafe60771d02d5b5dcf7d4f5ac1dc0a1dd010d7ae5672efdb92b38f56b78ac54797d18a6dd363fdac5e58b68321305983c81cf4d627ed2a59c150458999e23d1d2569beb083c67fab925ae495a97acb4465aa6960d1df08a73d3f5362a53c3db3813f006d7bb7a29028d0547e918f2bb407acf60f6391b7862a1db39f26727771c61747a7766619a42864faa21d8d23317e12abbb13e0ba2ad6f7f0e3d08',
+ ),
+ ).divide(
+ new asmCrypto.BigNumber(
+ asmCrypto.hex_to_bytes(
+ 'a736146b621310f6cd645cb2fefeda223aa7ae33a53ac22e019b6ffb7167d9b29be1aebb3e1a7129ee3a5b4fb1a11660932b9be2b36a6dd3226451d7c4dd79619bdb9aa5596cef4e7b6d91f0e227bba2547b004ded1ed0e06182141dc55e183374fe1d93e23c38fcc81cd8eae82647528dde963cf1ef86f470e69436a2ac0d7fa7161d6fbfd32141217df992002320cb575e8de44c446d73bdf116719d61451c474701e153a01771cb8f070f8241d465d3d0124aed70ec459669bfc4927f941ddac97f4772f8d4d55165d1d06eec147749d0b9fee868ddf3',
+ ),
+ ),
+ );
+ expect(result.quotient.toString(16), 'q is ok').to.equal('1');
+ expect(result.remainder.toString(16), 'r is ok').to.equal(
+ '60389f412400d5e7d538a600c8c0e428d425b2e7a253d59ded5f0b50f80c3176fd5958d8bcd218b49cc6196786bd79e3eecb2c1bcaa2ab9709969269b99a3a139da42527b88bccf45344b102b5329c4da82b8dd4bd69a984ad2655f5348c502cadca851a92bf9163d7b6396e7271b2c44c705d8126912a9b2eb3e1ff93efabcc0e49bb5ee7639568b364cc8a672ec52992be5efa8f1bce005ea21a252a5929f32e200abb1a7d1a7272c396b4d1f21d347a85056edc90621910d5c9ce1fae34886d0c33edcb14d0380cd4610bbcf9cc6c1d1f37096a55f15',
+ );
+
+ result = new asmCrypto.BigNumber(
+ asmCrypto.hex_to_bytes(
+ 'ad399e5f74531e554ab7e7130b8ae864c7ea09621f5fff87e07160b080e89cca0bb74448c9e792b53806bce62a0cedfed2184ea47014988c92fdbafe60771d02d5b5dcf7d4f5ac1dc0a1dd010d7ae5672efdb92b38f56b78ac54797d18a6dd363fdac5e58b68321305983c81cf4d627ed2a59c150458999e23d1d2569beb083c67fab925ae495a97acb4465aa6960d1df08a73d3f5362a53c3db3813f006d7bb7a29028d0547e918f2bb407acf60f6391b7862a1db39f26727771c61747a7766619a42864faa21d8d23317e12abbb13e0ba2ad6f7f0e3d08',
+ ),
+ ).divide(
+ new asmCrypto.BigNumber(
+ asmCrypto.hex_to_bytes(
+ 'a736146b621310f6cd645cb2fefeda223aa7ae33a53ac22e019b6ffb7167d9b29be1aebb3e1a7129ee3a5b4fb1a11660932b9be2b36a6dd3226451d7c4dd79619bdb9aa5596cef4e7b6d91f0e227bba2547b004ded1ed0e06182141dc55e183374fe1d93e23c38fcc81cd8eae82647528dde963cf1ef86f470e69436a2ac0d7fa7161d6fbfd32141217df992002320cb575e8de44c446d73bdf116719d61451c474701e153a01771cb8f070f8241d465d3d0124aed70ec459669bfc4927f941ddac97f4772f8d4d55165d1d06eec147749d0b9fee868ddf3',
+ ),
+ ),
+ );
+ expect(result.quotient.toString(16), 'q is ok').to.equal('1');
+ expect(result.remainder.toString(16), 'r is ok').to.equal(
+ '60389f412400d5e7d538a600c8c0e428d425b2e7a253d59ded5f0b50f80c3176fd5958d8bcd218b49cc6196786bd79e3eecb2c1bcaa2ab9709969269b99a3a139da42527b88bccf45344b102b5329c4da82b8dd4bd69a984ad2655f5348c502cadca851a92bf9163d7b6396e7271b2c44c705d8126912a9b2eb3e1ff93efabcc0e49bb5ee7639568b364cc8a672ec52992be5efa8f1bce005ea21a252a5929f32e200abb1a7d1a7272c396b4d1f21d347a85056edc90621910d5c9ce1fae34886d0c33edcb14d0380cd4610bbcf9cc6c1d1f37096a55f15',
+ );
+
+ result = new asmCrypto.BigNumber(
+ asmCrypto.hex_to_bytes(
+ '8251a22c009e3e37af0a516bbd73662a462531e4886005cec939265e99f177d7812fd7d5df184c5ea8ced1cace7e6724a4c31b1dbdedcd9636acff51936801df9bdf255850896b4da0aebfbc8944da8385a58f47e335ce94fd53ab1b299335c9e242fd89fc87126c11df2e65efa31fc37ce90e454b72afff5db16c271d476054022227c76c039c30feba1a1bd8d62c11b5c8a9e666b7726c4306c1e84f51c6fbe4485a2826cfacaea58d4a522a48a0164aa45df489944822953f860084d34b3ac537e27af0ed95613ffcb7f775832bf3acc7beff1469ed7a28abbff4dbf08859cafc8b8a7b3a2dc02cdff66095f53897ae74d2ce47e5644ea7ac59398a99b55',
+ ),
+ ).divide(
+ new asmCrypto.BigNumber(
+ asmCrypto.hex_to_bytes(
+ '4128d116004f1f1bd78528b5deb9b315231298f2443002e7649c932f4cf8bbebc097ebeaef8c262f546768e5673f339252618d8edef6e6cb1b567fa8c9b400efcdef92ac2844b5a6d0575fde44a26d41c2d2c7a3f19ae74a7ea9d58d94c99ae4f1217ec4fe43893608ef9732f7d18fe1be748722a5b957ffaed8b6138ea3b02a011113e3b601ce187f5d0d0dec6b1608dae454f3335bb936218360f427a8e37df2242d141367d65752c6a5291524500b25522efa44ca24114a9fc3004269a59d629bf13d7876cab09ffe5bfbbac195f9d663df7f8a34f6bd1455dffa6df8442ce57e45c53d9d16e0166ffb304afa9c4bd73a696723f2b22753d62c9cc54cdab',
+ ),
+ ),
+ );
+ expect(result.quotient.toString(16), 'q is ok').to.equal('1');
+ expect(result.remainder.toString(16), 'r is ok').to.equal(
+ '4128d116004f1f1bd78528b5deb9b315231298f2443002e7649c932f4cf8bbebc097ebeaef8c262f546768e5673f339252618d8edef6e6cb1b567fa8c9b400efcdef92ac2844b5a6d0575fde44a26d41c2d2c7a3f19ae74a7ea9d58d94c99ae4f1217ec4fe43893608ef9732f7d18fe1be748722a5b957ffaed8b6138ea3b02a011113e3b601ce187f5d0d0dec6b1608dae454f3335bb936218360f427a8e37df2242d141367d65752c6a5291524500b25522efa44ca24114a9fc3004269a59d629bf13d7876cab09ffe5bfbbac195f9d663df7f8a34f6bd1455dffa6df8442ce57e45c53d9d16e0166ffb304afa9c4bd73a696723f2b22753d62c9cc54cdaa',
+ );
+
+ result = new asmCrypto.BigNumber(asmCrypto.hex_to_bytes('8000000000000000')).divide(
+ new asmCrypto.BigNumber(asmCrypto.hex_to_bytes('80000000ffff')),
+ );
+ expect(result.quotient.toString(16), 'q is ok').to.equal('ffff');
+ expect(result.remainder.toString(16), 'r is ok').to.equal('7fff0001ffff');
+ });
+
+ it('asmCrypto.BigNumber.extGCD', function() {
+ let z;
+
+ z = asmCrypto.BigNumber.extGCD(asmCrypto.BigNumber.fromNumber(3), asmCrypto.BigNumber.fromNumber(2));
+ expect(z.gcd.valueOf(), 'gcd ok').to.equal(1);
+ expect(z.x.valueOf(), 'x ok').to.equal(1);
+ expect(z.y.valueOf(), 'y ok').to.equal(-1);
+
+ z = asmCrypto.BigNumber.extGCD(asmCrypto.BigNumber.fromNumber(240), asmCrypto.BigNumber.fromNumber(46));
+ expect(z.gcd.valueOf(), 'gcd ok').to.equal(2);
+ expect(z.x.valueOf(), 'x ok').to.equal(-9);
+ expect(z.y.valueOf(), 'y ok').to.equal(47);
+
+ z = asmCrypto.BigNumber.extGCD(
+ new asmCrypto.BigNumber(asmCrypto.hex_to_bytes('abcdabcdabcd')),
+ new asmCrypto.BigNumber(asmCrypto.hex_to_bytes('20000000000000')),
+ );
+ expect(z.gcd.valueOf(), 'gcd ok').to.equal(1);
+ expect(z.x.toString(16), 'x ok').to.equal('9b51de3a73905');
+ expect(z.y.toString(16), 'y ok').to.equal('-341e3c1e3c1e');
+
+ z = asmCrypto.BigNumber.extGCD(
+ new asmCrypto.BigNumber(
+ asmCrypto.hex_to_bytes(
+ '00fcbd95956bea867fe1250b179fb2d4e0c59c4a2fe469a01cd90509d7d7c25cdf84f77eea1fbe509269819a828959b39b8f54a38a6f0290e48c0f3c9c45b78123',
+ ),
+ ),
+ new asmCrypto.BigNumber(
+ asmCrypto.hex_to_bytes(
+ '00d5176443bebb2a31a44df711ff7c982395c5477365f3618398fd7d37fad4d2394f9458c39dec561dab0bc6c7ced1c76b29cfd2e14ec793d5d300c70d49ada9f1',
+ ),
+ ),
+ );
+ expect(z.gcd.valueOf(), 'gcd ok').to.equal(1);
+
+ z = asmCrypto.BigNumber.extGCD(
+ new asmCrypto.BigNumber(
+ asmCrypto.hex_to_bytes(
+ '100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
+ ),
+ ),
+ new asmCrypto.BigNumber(
+ asmCrypto.hex_to_bytes(
+ 'c7f1bc1dfb1be82d244aef01228c1409c198894eca9e21430f1669b4aa3864c9f37f3d51b2b4ba1ab9e80f59d267fda1521e88b05117993175e004543c6e3611242f24432ce8efa3b81f0ff660b4f91c5d52f2511a6f38181a7bf9abeef72db056508bbb4eeb5f65f161dd2d5b439655d2ae7081fcc62fdcb281520911d96700c85cdaf12e7d1f15b55ade867240722425198d4ce39019550c4c8a921fc231d3e94297688c2d77cd68ee8fdeda38b7f9a274701fef23b4eaa6c1a9c15b2d77f37634930386fc20ec291be95aed9956801e1c76601b09c413ad915ff03bfdc0b6b233686ae59e8caf11750b509ab4e57ee09202239baee3d6e392d1640185e1cd',
+ ),
+ ),
+ );
+ expect(z.gcd.valueOf(), 'gcd ok').to.equal(1);
+ expect(z.x.toString(16), 'x ok').to.equal(
+ '-210fc146c2f2919c3e9a4372a7221069fa359d7feba4ecaf765c47f29819a82ebb92c5944f921e090c8f0eee5218d243b35eb488fdef6a2f9712ba887625af9599b2a547595528054f079124831d94872243009cec4e3154199893d700c2a64c3fae1e259bd37b4f88e34a6ff0fcb7c221a9b222df4a74f4d381259c641cef4d05bbbc737ac29f06e050139aa823d00c2af2b484720a58eadc39ea10d53c8664289e5495fcb188abecb167c8b81a267a24fa304b447d484c37af38525f5c1c3c7bc9e614b779e21d582c0222fa8bc13bc37673cefbb60a84a70423dcec8850d6c3c80c244e09cee87e7f6dadaf24a2b9410bc31e1afc588f9d20d769a5c3df71',
+ );
+ expect(z.y.toString(16), 'y ok').to.equal(
+ '2a54a02a4b2182e2ea06578065a9608f53c45bd34ab2d3c47c18bca20e2bf9d93f6ac1aecc7a4bf18cfbc073db8cd0829b656bcb1f7a52b10bdc463ac246f11a30c0cc4ea00f093fcb0b4809a2b83bfb627789c6daac33d467a2b7bcda403018b344ca065fecccd2922afd53268ea599b17b96f29fe9fa4487cd0df93db31f3197a1973fafdd5f37a9f80f2554947ed63ffa4f12f0c5eefec24e9192ddcbc19ad179f76d95e361250300f18de3f7c9a067b84ccba3b31e1d1cf4379a492aa916882e09fa6836e3524b9bf750cf8f8dddbb48dd2ac0a9cfdfe6409330c0d62f08d13ec220436482bb39db9b1c595c5e0e0b743344620ac8eb0e18b0d3c641f305',
+ );
+ });
+
+ it('asmCrypto.Modulus', function() {
+ const M = new asmCrypto.Modulus(asmCrypto.BigNumber.fromNumber(123456789));
+
+ expect(M.reduce(asmCrypto.BigNumber.fromNumber(987654321)).valueOf(), 'Modulus.reduce(small)').to.equal(9);
+
+ const M2 = new asmCrypto.Modulus(asmCrypto.BigNumber.fromNumber(0xabcdabcdabcd));
+ expect(M2.comodulus.toString(16), 'M2 comodulus ok').to.equal('10000000000000000');
+ expect(M2.comodulusRemainder.toString(16), 'M2 comodulus remainder ok').to.equal('624f6250624f');
+ expect(M2.comodulusRemainderSquare.toString(16), 'M2 comodulus remainder square ok').to.equal('399f399e399e');
+ expect(M2.coefficient.toString(16), 'M2 coefficent ok').to.equal('1c58c6fb');
+
+ const M3 = new asmCrypto.Modulus(
+ new asmCrypto.BigNumber(
+ asmCrypto.hex_to_bytes(
+ 'c7f1bc1dfb1be82d244aef01228c1409c198894eca9e21430f1669b4aa3864c9f37f3d51b2b4ba1ab9e80f59d267fda1521e88b05117993175e004543c6e3611242f24432ce8efa3b81f0ff660b4f91c5d52f2511a6f38181a7bf9abeef72db056508bbb4eeb5f65f161dd2d5b439655d2ae7081fcc62fdcb281520911d96700c85cdaf12e7d1f15b55ade867240722425198d4ce39019550c4c8a921fc231d3e94297688c2d77cd68ee8fdeda38b7f9a274701fef23b4eaa6c1a9c15b2d77f37634930386fc20ec291be95aed9956801e1c76601b09c413ad915ff03bfdc0b6b233686ae59e8caf11750b509ab4e57ee09202239baee3d6e392d1640185e1cd',
+ ),
+ ),
+ );
+ expect(M3.comodulus.toString(16), 'M3 comodulus ok').to.be.equal(
+ '100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
+ );
+ expect(M3.comodulusRemainder.toString(16), 'M3 comodulus remainder ok').to.equal(
+ '380e43e204e417d2dbb510fedd73ebf63e6776b13561debcf0e9964b55c79b360c80c2ae4d4b45e54617f0a62d98025eade1774faee866ce8a1ffbabc391c9eedbd0dbbcd317105c47e0f0099f4b06e3a2ad0daee590c7e7e58406541108d24fa9af7444b114a09a0e9e22d2a4bc69aa2d518f7e0339d0234d7eadf6ee2698ff37a3250ed182e0ea4aa521798dbf8ddbdae672b31c6fe6aaf3b3756de03dce2c16bd689773d288329711702125c748065d8b8fe010dc4b15593e563ea4d2880c89cb6cfc7903df13d6e416a51266a97fe1e3899fe4f63bec526ea00fc4023f494dcc97951a617350ee8af4af654b1a811f6dfddc64511c291c6d2e9bfe7a1e33',
+ );
+ expect(M3.comodulusRemainderSquare.toString(16), 'M3 comodulus remainder square ok').to.equal(
+ 'a8d0cc3c0069b1fe694294247f367071deb9b3fdc80824536f04fae0c3df7fccc9f856aeee2033803b371a3c455522fb288c60f326db2fdcaf7452b48b0f0a29cce2dabe844a63f8077be24d2a0db5051e8a1481c16f0b880819cf8d193adaa79c92f11f1e4a2e89f24bc0ef0e2285ff218a5c058908f6feef024b0c8bfe11d37cba38103339f19ba7466f3070588152f1a008dc454cebcc4f70879e94ac1eb26179833049da7b450fbe93d7d802edc5900b3a973d05ff76c6bbb7914c59b27265222501b14497fe0ef99b7fa67777bf9ab89a8b346aacb6dbf606e68da0ba2a5c4ce3b0f85225292cd1acafebae5f553c03e9c3857730c715017550e4e77a53',
+ );
+ expect(M3.coefficient.toString(16), 'M3 coefficent ok').to.equal('39be0cfb');
+
+ const M4 = new asmCrypto.Modulus(
+ new asmCrypto.BigNumber(
+ asmCrypto.hex_to_bytes(
+ '453b5e276054110d94fd7b413ca54e467543c28168730315dae65c6241c847aa7ca16aa99e84e89249addf73bdb326cb7787a667cce65537cd0be7a3564f40fecace8bd6eac901013d5cd5dc28ec9415defff41e30b495bf269472e66e163493403396b14e27c1c9697e90a6274ea8dfda5bcf94d014ed7fa9c64174c78deb2ca1222521f161eafa0752dddecb31c76968929a42669174c9839b97036a2371b5d1466fe5549e53bcc7f30f7ba676950bd7a751e9e916c6525f49bf3046903ff738c5b0514ffe375ba9fe41bb766daf5973ca1d7782d84628e59b3dfa14d7c86fb3d62a219176e84e17d6fae34faa461094ae0ffd9631dd49c9138f6691a1a854',
+ ),
+ ),
+ );
+ expect(
+ M4.inverse(
+ new asmCrypto.BigNumber(
+ asmCrypto.hex_to_bytes(
+ '145cc156e018b9b8b3599cb8d59a07f69af5cfcbb54f00e84f70edfec80dbab9ac2f79b96adbcbeeca6050c7b043c01db9be7c3ca5ad281f788b07e4bf08404af05addd5cc9578c4211b4df57572c2248ce1de633b806847479512bc3e7f00678b5a779d8f751ae0e2cadf3fed717cf68b846a3ad3c9eb7fe6a3b8e61c93270d2055563728e09067a7cd141459e176e2c4675a8c000ca9e0ea790e4c4c64c7175bab4e16461072fb49de139cd69b59037ba9aeae357f2b456751ecf014c103c12ed0bb6335a51f5731ff7cbeaa5c7ede12ff35d7db308d1b165ad5fe425d954e07b775cda34117260702fe7f176e50d7b34240f03b3bd7ac4a32edf0fda80455',
+ ),
+ ),
+ ).toString(16),
+ 'M4 inverse OK',
+ ).to.equal('11');
+
+ const M5 = new asmCrypto.Modulus(new asmCrypto.BigNumber(asmCrypto.hex_to_bytes('0aabbccddaabbccdd')));
+ expect(
+ M5.reduce(new asmCrypto.BigNumber(asmCrypto.hex_to_bytes('1aabbccddaabbccdd'))).toString(16),
+ 'M5 reduce ok',
+ ).to.equal('5544332255443323');
+ });
+
+ it('asmCrypto.Modulus.power', function() {
+ const base = new asmCrypto.BigNumber(
+ asmCrypto.hex_to_bytes(
+ '3f70f29d3f3ae354a6d2536ceafba83cfc787cd91e7acd2b6bde05e62beb8295ae18e3f786726f8d034bbc15bf8331df959f59d431736d5f306aaba63dacec279484e39d76db9b527738072af15730e8b9956a64e8e4dbe868f77d1414a8a8b8bf65380a1f008d39c5fabe1a9f8343929342ab7b4f635bdc52532d764701ff3d8072c475c012ff0c59373e8bc423928d99f58c3a6d9f6ab21ee20bc8e8818fc147db09f60c81906f2c6f73dc69725f075853a89f0cd02a30a8dd86b660ccdeffc292f398efb54088c822774445a6afde471f7dd327ef9996296898a5747726ccaeeceeb2e459df98b4128cb5ab8c7cd20c563f960a1aa770f3c81f13f967b6cc',
+ ),
+ );
+ const modulus = new asmCrypto.Modulus(
+ new asmCrypto.BigNumber(
+ asmCrypto.hex_to_bytes(
+ 'c7f1bc1dfb1be82d244aef01228c1409c198894eca9e21430f1669b4aa3864c9f37f3d51b2b4ba1ab9e80f59d267fda1521e88b05117993175e004543c6e3611242f24432ce8efa3b81f0ff660b4f91c5d52f2511a6f38181a7bf9abeef72db056508bbb4eeb5f65f161dd2d5b439655d2ae7081fcc62fdcb281520911d96700c85cdaf12e7d1f15b55ade867240722425198d4ce39019550c4c8a921fc231d3e94297688c2d77cd68ee8fdeda38b7f9a274701fef23b4eaa6c1a9c15b2d77f37634930386fc20ec291be95aed9956801e1c76601b09c413ad915ff03bfdc0b6b233686ae59e8caf11750b509ab4e57ee09202239baee3d6e392d1640185e1cd',
+ ),
+ ),
+ ),
+ exponent = new asmCrypto.BigNumber(
+ asmCrypto.hex_to_bytes('322e393f76a1c22b147e7d193c00c023afb7c1500b006ff1bc1cc8d391fc38bd'),
+ );
+
+ expect(modulus.power(base, exponent).toString(16), 'Modulus.power ok').to.equal(
+ '5b3823974b3eda87286d3f38499de290bd575d8b02f06720acacf3d50950f9ca0ff6b749f3be03913ddca0b291e0b263bdab6c9cb97e4ab47ee9c235ff20931a8ca358726fab93614e2c549594f5c50b1c979b34f840b6d4fc51d6feb2dd072995421d17862cb405e040fc1ed662a3245a1f97bbafa6d1f7f76c7db6a802e3037acdf01ab5053f5da518d6753477193b9c25e1720519dcb9e2f6e70d5786656d356151845a49861dfc40187eff0e85cd18b1f3f3b97c476472edfa090b868b2388edfffecc521c20df8cebb8aacfb3669b020330dd6ea64b2a3067a972b8f249bccc19347eff43893e916f0949bd5789a5cce0f8b7cd87cece909d679345c0d4',
+ );
+ });
+
+ it('asmCrypto.isProbablePrime', function() {
+ const p = new asmCrypto.BigNumber(
+ asmCrypto.hex_to_bytes(
+ '8844ae66464b4b7db53644be87617124f314a1d8243d347867c8cfd6afb595bdb88ce63538fbd6c3f8461133d77ed4f5ef403f48c65b7340c683839c00bc7874bff3e9ffe7916a3ca085c7096f31871f2d628198f9c1deaeaefa581ebaef834a89afdf663b9570287a257bd6e4f507cede3b31eda6bd7fd4f8ae3c5b8791d89f',
+ ),
+ );
+ expect(p.isProbablePrime(), 'p is probable prime').to.be.true;
+ });
+});
diff --git a/test/dummy.js b/test/dummy.js
deleted file mode 100644
index ca913bc..0000000
--- a/test/dummy.js
+++ /dev/null
@@ -1,152 +0,0 @@
-module("dummy");
-
-test( "dummy test", function () {
- ok( true, "Passed!" );
-});
-
-test( "add with carry proparation", function () {
- var a = 0xad4e6ae6, b = 0xedfdecc8, c = 1, d = 0x19b4c57af, dc = 1,
- r = 0, rc = 0, u = 0, v = 0;
-
- r = (a + c)|0, rc = (r>>>0) < (a>>>0) ? 1 : 0;
- r = (b + r)|0, rc = (r>>>0) < (b>>>0) ? 1 : rc;
- equal( r>>>0, d>>>0, "adc32 result ok" );
- equal( rc, dc, "adc32 carry ok" );
-
- u = ( (a & 0xffff) + (b & 0xffff)|0 ) + c|0;
- v = ( (a >>> 16) + (b >>> 16)|0 ) + (u >>> 16)|0;
- r = (u & 0xffff) | (v << 16);
- rc = v >>> 16;
- equal( r>>>0, d>>>0, "adc16x2 result ok" );
- equal( rc, dc, "adc16x2 carry ok" );
-});
-
-if ( Math.imul ) {
- test( "multiply and add", function () {
- var imul = Math.imul,
- x = 0xad4e6ae6, y = 0xedfdecc8, z = 0x9b4c57af,
- h = 0xa11d7fc2, l = 0xde69e35f,
- u = 0, v = 0, w = 0,
- rh = 0, rl = 0;
-
- u = imul( x & 0xffff, y & 0xffff ) + (z & 0xffff) | 0;
- v = imul( x & 0xffff, y >>> 16 ) + (z >>> 16) | 0;
- w = ( imul( x >>> 16, y & 0xffff ) + (v & 0xffff) | 0 ) + (u >>> 16) | 0;
- rh = ( imul( x >>> 16, y >>> 16 ) + (v >>> 16) | 0 ) + (w >>> 16) | 0;
- rl = (w << 16) | (u & 0xffff);
-
- equal( h>>>0, rh>>>0, "high part is ok" );
- equal( l>>>0, rl>>>0, "low part is ok" );
- });
-
- test( "divide with remainder", function () {
- var n0 = 0xad4e6ae6, n1 = 0xedfdecc8, d0 = 0xeeddccbb, q0 = 0xff101123, r0 = 0x39b30255;
-
- var qh, ql, rh, rl, w0, w1, n, dh, dl, c, imul = Math.imul;
-
- dh = d0 >>> 16, dl = d0 & 0xffff;
-
- n = n1;
- qh = ( n / dh )|0, rh = n % dh;
- while ( ( (rh|0) < 0x10000 )
- & ( ( qh == 0x10000 ) | ( (imul(qh,dl)>>>0) > (((rh<<16)|(n0>>>16))>>>0) ) ) )
- {
- qh = (qh-1)|0;
- rh = (rh+dh)|0;
- }
- w0 = imul(qh, dl)|0;
- w1 = (w0 >>> 16) + imul(qh, dh)|0;
- w0 = w0 << 16;
- n = (n0-w0)|0, c = ( (n>>>0) > (n0>>>0) )|0, n0 = n;
- n = (n1-c)|0, c = ( (n>>>0) > (n1>>>0) )|0, n1 = (n-w1)|0, c = ( (n1>>>0) > (n>>>0) )|c;
- if ( c ) {
- qh = (qh-1)|0;
- n = (n0+(d0<<16))|0, c = ( (n>>>0) < (n0>>>0) )|0, n0 = n;
- n = (n1+c)|0, c = !n, n1 = (n+dh)|0, c = ( (n1>>>0) < (n>>>0) )|c;
- }
-
- n = (n1 << 16) | (n0 >>> 16);
- ql = ( n / dh )|0, rl = n % dh;
- while ( ( (rl|0) < 0x10000 )
- & ( ( ql == 0x10000 ) | ( (imul(ql,dl)>>>0) > (((rl << 16)|(n0 & 0xffff))>>>0) ) ) )
- {
- ql = (ql-1)|0;
- rl = (rl+dh)|0;
- }
- w0 = imul(ql, dl)|0;
- w1 = (w0 >>> 16) + imul(ql, dh)|0;
- w0 = (w1 << 16) | (w0 & 0xffff);
- w1 = w1 >>> 16;
- n = (n0-w0)|0, c = ( (n>>>0) > (n0>>>0) )|0, n0 = n;
- n = (n1-c)|0, c = ( (n>>>0) > (n1>>>0) )|0, n1 = (n-w1)|0, c = ( (n1>>>0) > (n>>>0) )|c;
- if ( c ) {
- ql = (ql-1)|0;
- n = (n0+d0)|0, c = ( (n>>>0) < (n0>>>0) )|0, n0 = n;
- n1 = (n1+c)|0;
- }
-
- equal( ((qh<<16)|ql)>>>0, q0, "quotient ok" );
- equal( n0>>>0, r0, "remainder ok" );
- });
-
- test( "imul", function () {
- equal( Math.imul(-338592732,968756475)|0, 787375948, "imul works fine" );
- });
-}
-else {
- skip( "multiply and add" );
- skip( "divide with remainder" );
- skip( "imul" );
-}
-
-test( "Math.random()", function () {
- var r = Math.random();
- ok( typeof r === 'number', "r is number" );
- ok( r >= 0 && r < 1, "0 <= r < 1" );
-});
-
-testIf( true, "Conditional test should pass", function () {
- ok( true, "Passed!" );
-});
-
-testIf( false, "Conditional test should skip", function () {
- ok( false, "Failed!" );
-});
-
-testIf( asmCrypto.string_to_bytes, "asmCrypto.string_to_bytes", function ( ) {
- var bytes = asmCrypto.string_to_bytes("String not containing Unicode character");
- ok( bytes, "No exception on non-Unicode string" );
-
- try {
- var bytes = asmCrypto.string_to_bytes("String containing Unicode character: Ͼ");
- ok( false, "No exception on Unicode string")
- }
- catch ( e ) {
- ok( e instanceof Error, "Exception thrown on Unicode string" );
- ok( e.message.match(/wide character/i), "Exception message is about wide character" );
- }
-
- var bytes = asmCrypto.string_to_bytes( "\ud83d\ude80\u2665\u03ffa", true ); // Unicode ROCKET + BLACK HEART SUIT + GREEK CAPITAL REVERSED DOTTED LUNATE SIGMA SYMBOL + LATIN SMALL LETTER A
- equal( asmCrypto.bytes_to_hex(bytes), "f09f9a80e299a5cfbf61", "Encode into UTF8 byte array" );
-});
-
-testIf( asmCrypto.bytes_to_string, "asmCrypto.bytes_to_string", function ( ) {
- var bytes = asmCrypto.hex_to_bytes("f09f9a80e299a5cfbf61");
-
- var str = asmCrypto.bytes_to_string( bytes, false );
- equal( str.length, 10, "Binary string length is ok" );
- equal( str, "\xf0\x9f\x9a\x80\xe2\x99\xa5\xcf\xbf\x61", "Binary string content is ok" );
-
- var str = asmCrypto.bytes_to_string( bytes, true );
- equal( str.length, 5, "Characters string length is ok" );
- equal( str, "\ud83d\ude80\u2665\u03ffa", "Characters string content is ok" );
-
- try {
- var str = asmCrypto.bytes_to_string( bytes.subarray(0,3), true );
- ok( false, "No exception on malformed UTF8 byte array" );
- }
- catch ( e ) {
- ok( e instanceof Error, "Exception thrown on malformed UTF8 byte array" );
- ok( e.message.match(/Malformed UTF8 character/i), "Exception message is about malformed UTF8 character" );
- }
-});
diff --git a/test/index.html b/test/index.html
deleted file mode 100644
index 4174cdc..0000000
--- a/test/index.html
+++ /dev/null
@@ -1,81 +0,0 @@
-
-
-
-
-asmCrypto test suite
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/test/isaac.js b/test/isaac.js
deleted file mode 100644
index f121ece..0000000
--- a/test/isaac.js
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
-module("ISAAC");
-
-///////////////////////////////////////////////////////////////////////////////
-
-// Taken from http://burtleburtle.net/bob/rand/randvect.txt
-
-var isaac_vector = [
- 0x7a68710f, 0x6554abda, 0x90c10757, 0x0b5e435f, 0xaf7d1fb8, 0x01913fd3, 0x6a158d10, 0xb8f6fd4a,
- 0xc2b9aa36, 0x96da2655, 0xfe1e42d5, 0x56e6cd21, 0xd5b2d750, 0x7229ea81, 0x5de87abb, 0xb6b9d766,
- 0x1e16614c, 0x3b708f99, 0x5cf824cd, 0xa4ca0cf1, 0x62d31911, 0x7cdd662f, 0xcb9e1563, 0x79ae4c10,
- 0x080c79ec, 0x18080c8e, 0x4a0a283c, 0x3dde9f39, 0x09c36f90, 0xad567643, 0x08294766, 0xb4415f7d,
- 0x5597ec0f, 0x78ffa568, 0x8bace62e, 0x4188bfcd, 0xc87c8006, 0xafa92a6d, 0x50fc8194, 0xcae8deba,
- 0x33f6d7b1, 0x53245b79, 0x61119a5a, 0x7e315aeb, 0xe75b41c9, 0xd2a93b51, 0xec46b0b6, 0x1ed3ff4e,
- 0x5d023e65, 0xadf6bc23, 0xf7f58f7b, 0xe4f3a26a, 0x0c571a7d, 0xed35e5ee, 0xeadebeac, 0x30bcc764,
- 0x66f1e0ab, 0x826dfa89, 0x0d9c7e7e, 0xe7e26581, 0xd5990dfb, 0x02c9b944, 0x4112d96c, 0x3ff1e524,
- 0xc35e4580, 0xfdfef62d, 0xb83f957a, 0xbfc7f7cc, 0xb510ce0e, 0xcd7411a7, 0x04db4e13, 0x76904b6d,
- 0x08607f04, 0x3718d597, 0x46c0a6f5, 0x8406b137, 0x309bfb78, 0xf7d3f39f, 0x8c2f0d55, 0xc613f157,
- 0x127dd430, 0x72c9137d, 0x68a39358, 0x07c28cd1, 0x848f520a, 0xdd2dc1d5, 0x9388b13b, 0x28e7cb78,
- 0x03fb88f4, 0xb0b84e7b, 0x14c8009b, 0x884d6825, 0x21c171ec, 0x0809e494, 0x6a107589, 0x12595a19,
- 0x0bb3263f, 0x4d8fae82, 0x2a98121a, 0xb00960ba, 0x6708a2bc, 0x35a124b5, 0xbccaaeed, 0x294d37e5,
- 0xd405ded8, 0x9f39e2d9, 0x21835c4d, 0xe89b1a3b, 0x7364944b, 0xbd2e5024, 0x6a123f57, 0x34105a8c,
- 0x5ad0d3b0, 0xcc033ce3, 0xd51f093d, 0x56a001e3, 0x01a9bd70, 0x8891b3db, 0x13add922, 0x3d77d9a2,
- 0x0e7e0e67, 0xd73f72d4, 0x917bdec2, 0xa37f63ff, 0x23d74f4e, 0x3a6ce389, 0x0606cf9f, 0xde11ed34,
- 0x70cc94ae, 0xcb0eee4a, 0x13edc0cb, 0xfe29661c, 0xdb6dbe96, 0xb388d96c, 0x33bc405d, 0xa6d12101,
- 0x2f36fa86, 0x7ded386f, 0xe6344451, 0xcd57c7f7, 0x1b0dcdc1, 0xcd49ebdb, 0x9e8a51da, 0x12a0594b,
- 0x60d4d5f8, 0x91c8d925, 0xe43d0fbb, 0x5d2a542f, 0x451e7ec8, 0x2b36505c, 0x37c0ed05, 0x2364a1aa,
- 0x814bc24c, 0xe3a662d9, 0xf2b5cc05, 0xb8b0ccfc, 0xb058bafb, 0x3aea3dec, 0x0d028684, 0x64af0fef,
- 0x210f3925, 0xb67ec13a, 0x97166d14, 0xf7e1cdd0, 0x5adb60e7, 0xd5295ebc, 0x28833522, 0x60eda8da,
- 0x7bc76811, 0xac9fe69d, 0x30ab93ec, 0x03696614, 0x15e3a5b9, 0xecc5dc91, 0x1d3b8e97, 0x7275e277,
- 0x538e1f4e, 0x6cb167db, 0xa7a2f402, 0x2db35dfe, 0xa8bcc22d, 0xd8c58a6a, 0x6a529b0b, 0x0fd43963,
- 0xafc17a97, 0x943c3c74, 0x95138769, 0x6f4e0772, 0xb143b688, 0x3b18e752, 0x69d2e4ae, 0x8107c9ff,
- 0xcdbc62e2, 0x5781414f, 0x8b87437e, 0xa70e1101, 0x91dabc65, 0x4e232cd0, 0x229749b5, 0xd7386806,
- 0xb3c3f24b, 0x60dc5207, 0x0bdb9c30, 0x1a70e7e9, 0xf37c71d5, 0x44b89b08, 0xb4d2f976, 0xb40e27bc,
- 0xffdf8a80, 0x9c411a2a, 0xd0f7b37d, 0xef53cec4, 0xeca4d58a, 0x0b923200, 0xcf22e064, 0x8ebfa303,
- 0xf7cf814c, 0x32ae2a2b, 0xb5e13dae, 0xc998f9ff, 0x349947b0, 0x29cf72ce, 0x17e38f85, 0xf3b26129,
- 0xd45d6d81, 0x09b3ce98, 0x860536b8, 0xe5792e1b, 0x12ad6419, 0xf5f71c69, 0xcbc8b7c2, 0x8f651659,
- 0xa0cc74f3, 0xd78cb99e, 0x51c08d83, 0x29f55449, 0x002ed713, 0x38a824f3, 0x57161df6, 0x7452e319,
- 0x25890e2e, 0xc7442433, 0x4a5f6355, 0x6a83e1e0, 0x823cedb6, 0xf1d444eb, 0x88381097, 0x5de3743e,
- 0x46ca4f9a, 0xd8370487, 0xedec154a, 0x433f1afb, 0xf5fad54f, 0x98db2fb4, 0xe448e96d, 0xf650e4c8,
-
- 0x4bb5af29, 0x9d855e89, 0xc54cd95b, 0x46d95ca5, 0xef73fbf0, 0xf943f672, 0x86ba527f, 0x9d8d1908,
- 0xf3310c92, 0x05340e15, 0x07cffad9, 0x21e2547e, 0x8c17eff0, 0xd32be060, 0x8aba3ffb, 0x94d40125,
- 0xc5a87748, 0x824c2009, 0x73c0e762, 0xcdfec2af, 0x0e6c51b3, 0xa86f875e, 0xbc6172c7, 0xf7f395f1,
- 0x3f7579b3, 0x7aa114ed, 0x165b1015, 0xd531161a, 0xe36ef5bb, 0xdc153e5f, 0x1d0cb81b, 0xceffc147,
- 0x6079e4ce, 0xc3142d8f, 0xa617a083, 0xb54fed6f, 0xc3c7be2c, 0x02614abf, 0x6fb5ce56, 0xd21e796c,
- 0x2d0985de, 0xe9f84163, 0xc1a71e3c, 0x2887d96f, 0x57c4c925, 0x05efe294, 0x88157153, 0x9a30c4e8,
- 0x8854a0a1, 0x02503f7d, 0x0cd6ef81, 0x1da4f25a, 0xe8fa3860, 0x32e39273, 0x4c8652d6, 0x9ab3a42f,
- 0x9ead7f70, 0x836d8003, 0x6cbe7935, 0x721502dd, 0x5a48755c, 0x07497cae, 0xde462f4d, 0x92f57ea7,
- 0x1fe26ce0, 0x27c82282, 0xd6ec2f2b, 0x80c6e402, 0xce86fdfc, 0x52649d6c, 0xc798f047, 0x45bae606,
- 0x891aec49, 0x66c97340, 0x9ca45e1c, 0x4286619c, 0xf5f9cc3b, 0x4e823ad3, 0xc0d5d42a, 0xaee19096,
- 0x3d469303, 0xfe4cb380, 0xc9cd808c, 0x37a97df6, 0x308f751f, 0x276df0b4, 0xe5fbb9c7, 0x97ca2070,
- 0x88412761, 0x2ce5d3d5, 0xd7b43abe, 0xa30519ad, 0x26414ff3, 0xc5bde908, 0x275ead3a, 0x26ceb003,
- 0xbf1bd691, 0x037464c0, 0xe24124c0, 0x81d4cc5f, 0x484525e4, 0x1c3a4524, 0x9e7e4f04, 0xe1279bff,
- 0x6dd1943a, 0x403dae08, 0x82846526, 0xd5683858, 0x29322d0d, 0xa949bea2, 0x74096ae7, 0x85a13f85,
- 0x68235b9d, 0x8ef4bce6, 0x142a6e85, 0xdad1b22a, 0xb7546681, 0x959e234e, 0xfd8650d8, 0x3e730fa8,
- 0x56f55a71, 0xd20adf03, 0x7cdc78a2, 0x19047c79, 0x253b1d7a, 0x4389a84a, 0x0aeb8165, 0x9c15db3b,
- 0xaafef5a7, 0xbe8b06b2, 0xb5fe87c0, 0xe2a4ef71, 0xd9d711f9, 0xecfcf20b, 0x80fac4c2, 0xbbb8abc4,
- 0x239e3b0a, 0x858129a6, 0xd97cd348, 0x8a30738a, 0xc5b71937, 0xd649a428, 0x18c1ef9a, 0x75c08a36,
- 0xc921f94e, 0xdf9afa29, 0x040f7074, 0x72f5972f, 0x84ef01da, 0x2cb7b77f, 0x867027d7, 0x9ce0199d,
- 0x71865c4c, 0x7a36af93, 0x6c48ddd8, 0x19b48fd0, 0x75f4e9e2, 0x0084cfe5, 0x63bfd4d8, 0x9783cdee,
- 0x64f2632c, 0xf1b20eaf, 0xcc8bfa2d, 0x39ddf25a, 0x740e0066, 0x9ddb477f, 0x12b2cfb6, 0xd067fce5,
- 0x1a4b6a53, 0x001cdb95, 0x12c06908, 0x531ac6bf, 0x513c1764, 0xf7476978, 0x1be79937, 0x8a8dfaa3,
- 0x70a1660e, 0xfb737b1a, 0x3f28ee63, 0xc1a51375, 0x84bd6dd6, 0xe4a51d21, 0xeafed133, 0x22ae0582,
- 0x4d678f26, 0xf854b522, 0x31907d62, 0x4b55dd99, 0x04d3658a, 0x19c1e69c, 0xc6112fdd, 0xc66699fd,
- 0xa0eabe6b, 0x3724d4dc, 0x0d28fe52, 0x46819e2e, 0x96f703ac, 0x21182ca3, 0x2e7b022f, 0x31860f13,
- 0x1956b1e5, 0xe1322228, 0x08063a85, 0x1d964589, 0x94d90481, 0x53c078f3, 0x5afb43ae, 0x1e3437f7,
- 0x877eb7b4, 0x5d67133c, 0xa385cb2c, 0xb82f2703, 0xef05ee06, 0x931dd7e2, 0x10d210aa, 0xe21339cc,
- 0x479c3a22, 0x613b67b2, 0x33c5321c, 0xa5f48ac4, 0xba5590c8, 0xeb244925, 0xd0ef3cc9, 0xd8c423fb,
- 0x15cfcc5c, 0x1feb2e4f, 0x36ec0ea3, 0xdbef7d9f, 0xd5ec6bf4, 0x3d3dff8a, 0x1e04a7f7, 0x8766bb54,
- 0x9a1d7745, 0xc79a1749, 0xb8d2486d, 0x582e3014, 0xa82427f5, 0x65dfa427, 0xbc5654c1, 0xbd086f26,
- 0x0451516d, 0xff4cfc35, 0x81f2864d, 0x31860f05, 0xd0638e1a, 0xb059261d, 0x3d1e9150, 0x21e2a51c,
- 0x82d53d12, 0x1010b275, 0x786b2908, 0x4d3cfbda, 0x94a302f4, 0x95c85eaa, 0xd7e1c7be, 0x82ac484f
-];
-
-test( "prng", function () {
- asmCrypto.ISAAC.seed(0);
- ok( "reset done" );
-
- asmCrypto.ISAAC.prng();
- for ( var i = 0; i < isaac_vector.length; i++ ) {
- equal( asmCrypto.ISAAC.rand(), isaac_vector[i], "isaac_vector["+i+"] is correct" );
- }
-});
-*/
diff --git a/test/rsa.js b/test/rsa.js
index 50e84b9..574a270 100644
--- a/test/rsa.js
+++ b/test/rsa.js
@@ -1,112 +1,107 @@
-module("RSA");
-
-///////////////////////////////////////////////////////////////////////////////
-
-if ( typeof asmCrypto.RSA !== 'undefined' )
-{
- var pubkey = [
- asmCrypto.hex_to_bytes('c13f894819c136381a94c193e619851ddfcde5eca770003ec354f3142e0f61f0676d7d4215cc7a13b06e0744aa8316c9c3766cbefa30b2346fba8f1236d7e6548cf87d9578e6904fc4291e096a2737fcd96624f72e762793505f9dfc5fa17b44611add54f5c00bf54373d720cb6f4e5cabae36c4442b39dbf49158414547f453'),
- asmCrypto.hex_to_bytes('10001')
- ];
-
- var privkey = [
- asmCrypto.hex_to_bytes('c13f894819c136381a94c193e619851ddfcde5eca770003ec354f3142e0f61f0676d7d4215cc7a13b06e0744aa8316c9c3766cbefa30b2346fba8f1236d7e6548cf87d9578e6904fc4291e096a2737fcd96624f72e762793505f9dfc5fa17b44611add54f5c00bf54373d720cb6f4e5cabae36c4442b39dbf49158414547f453'),
- asmCrypto.hex_to_bytes('10001'),
- asmCrypto.hex_to_bytes('75497aa8a7f8fc4f50d2b82a6b9d518db027e7449adaff4b18829685c8eecd227ba3984263b896df1c55ab53a1a9ae4b06b6f9896f8fde98b4b725de882ac13fc11b614cb2cc81bcc69b9ad167dda093c5c6637754acd0ec9e9845b1b2244d597c9f63d7ea076bda19feadcdb3bd1ba9018915fec981657fb7a4301cb87a3e1'),
- asmCrypto.hex_to_bytes('ef2f8d91d7cd96710d6b3b5ea1b6762b4214efe329e7d0609ab8419744ef8620391e423d5890c864aebb36c0daf5035d27f3427e6a84fde36466a14b56ad1cfb'),
- asmCrypto.hex_to_bytes('ced5477e0acb9c836c3c54e33268e064ce8cdfd40452c8b87ab838b36b498ae22fdbdb331f59f61dd3ca1512143e77a68f8f2400dbe9e576a000084e6fcbb689'),
- asmCrypto.hex_to_bytes('227882f9a2d5513a27c9ed7b7ce8d3ecf61018666fb2a5f85633f9d7f82a60f521e6377ba9d8ebd87eca2260f6ed5ab7c13b30b91156eb542b331349cd4b13a3'),
- asmCrypto.hex_to_bytes('4dea2a3460fcb2c90f4ceaed6b5ff6a802e72eaa3fb6afc64ef476e79fd2e46eb078b1ea60351371c906a7495836effbdeb89d67757076f068f59a2b7211db81'),
- asmCrypto.hex_to_bytes('261a93613a93e438fa62858758d1db3b3db8366319517c039acfcc0ce04cd0d7349d7e8d8cb0e8a05ac966d04c18c81c49025de2b50bb87f78facccd19cd8602')
- ];
-
- test( "asmCrypto.RSA", function () {
- equal( typeof asmCrypto.RSA, 'object', "RSA exported" );
- });
-
- test( "asmCrypto.RSA.generateKey", function () {
- var key = asmCrypto.RSA.generateKey( 1024, 3 );
- ok( key, "generateKey" );
-
- var m = new asmCrypto.Modulus( new asmCrypto.BigNumber(key[0]) ),
- e = new asmCrypto.BigNumber( key[1] ),
- d = new asmCrypto.BigNumber( key[2] ),
- p = new asmCrypto.BigNumber( key[3] ),
- q = new asmCrypto.BigNumber( key[4] ),
- dp = new asmCrypto.BigNumber( key[5] ),
- dq = new asmCrypto.BigNumber( key[6] ),
- qi = new asmCrypto.BigNumber( key[7] );
-
- equal( p.multiply(q).toString(16), m.toString(16), "m == p*q" );
- equal( e.multiply(d).divide(p.subtract(asmCrypto.BigNumber.fromNumber(1)).multiply(q.subtract(asmCrypto.BigNumber.fromNumber(1)))).remainder.toString(16), '1', "e*d == 1 mod (p-1)(q-1)" );
- equal( d.divide(p.subtract(asmCrypto.BigNumber.fromNumber(1))).remainder.toString(16), dp.toString(16), "dp == d mod (p-1)" );
- equal( d.divide(q.subtract(asmCrypto.BigNumber.fromNumber(1))).remainder.toString(16), dq.toString(16), "dq == d mod (q-1)" );
- equal( qi.multiply(q).divide(p).remainder.toString(16), '1', "qi*q == 1 mod p" );
- equal( m.slice(m.bitLength-1).valueOf(), 1, "m highest bit is 1" );
- });
-}
-else
-{
- skip( "asmCrypto.RSA" );
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-if ( typeof asmCrypto.RSA_RAW !== 'undefined' )
-{
- test( "asmCrypto.RSA_RAW.encrypt", function () {
- var text = String.fromCharCode(1);
-
- var ciphertext = asmCrypto.RSA_RAW.encrypt( text, pubkey );
- equal( asmCrypto.bytes_to_hex(ciphertext).replace(/^0+/,''), '1', "ident encrypt" );
-
- var result = asmCrypto.RSA_RAW.decrypt( ciphertext, privkey );
- equal( asmCrypto.bytes_to_hex(result).replace(/^0+/,''), '1', "ident decrypt" );
- });
-}
-else
-{
- skip( "asmCrypto.RSA_RAW" );
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-if ( typeof asmCrypto.RSA_OAEP_SHA256 !== 'undefined' )
-{
- test( "asmCrypto.RSA_OAEP_SHA256 encrypt/decrypt", function () {
- var cleartext = asmCrypto.string_to_bytes('HelloWorld!');
-
- var ciphertext = asmCrypto.RSA_OAEP_SHA256.encrypt( cleartext, pubkey, 'test' );
- ok( ciphertext, "encrypt" );
-
- var result = asmCrypto.RSA_OAEP_SHA256.decrypt( ciphertext, privkey, 'test' );
- equal( asmCrypto.bytes_to_string(result), 'HelloWorld!', "decrypt" );
- });
-}
-else
-{
- skip( "asmCrypto.RSA_OAEP_SHA256" );
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-if ( typeof asmCrypto.RSA_PSS_SHA256 !== 'undefined' )
-{
- test( "asmCrypto.RSA_PSS_SHA256 sign/verify", function () {
- var text = 'HelloWorld!HelloWorld!HelloWorld!HelloWorld!HelloWorld!HelloWorld!HelloWorld!HelloWorld!';
-
- var signature = asmCrypto.RSA_PSS_SHA256.sign( text, privkey );
- ok( signature, "sign" );
-
- var result = asmCrypto.RSA_PSS_SHA256.verify( signature, text, pubkey );
- ok( result, "verify" );
- });
-
- test( "asmCrypto.RSA_PSS_SHA256 verify OpenSSL-signed-data", function () {
- var key = [
- asmCrypto.hex_to_bytes('f30be5ce8941c8e6e764c78d12f3ce6e02a0dea03577bc0c16029de258321b74ceb43ea94f768aec900011c78eb247ab0e94b4477ea8f086ba7b5ce4b03c0ad7e0bf2f54ed509a536a0f179e27db539f729b38a279873f7b3a360690c8390e289dedca6da1ba232d8edc3c1eb229e1072716ddf3ef88caf4a824c152d6ad38f1'),
- asmCrypto.hex_to_bytes('10001'),
-/*
+import * as asmCrypto from '../asmcrypto.all.es8';
+import chai from 'chai';
+const expect = chai.expect;
+
+const pubKey = [
+ asmCrypto.hex_to_bytes(
+ 'c13f894819c136381a94c193e619851ddfcde5eca770003ec354f3142e0f61f0676d7d4215cc7a13b06e0744aa8316c9c3766cbefa30b2346fba8f1236d7e6548cf87d9578e6904fc4291e096a2737fcd96624f72e762793505f9dfc5fa17b44611add54f5c00bf54373d720cb6f4e5cabae36c4442b39dbf49158414547f453',
+ ),
+ asmCrypto.hex_to_bytes('10001'),
+];
+
+const privkey = [
+ asmCrypto.hex_to_bytes(
+ 'c13f894819c136381a94c193e619851ddfcde5eca770003ec354f3142e0f61f0676d7d4215cc7a13b06e0744aa8316c9c3766cbefa30b2346fba8f1236d7e6548cf87d9578e6904fc4291e096a2737fcd96624f72e762793505f9dfc5fa17b44611add54f5c00bf54373d720cb6f4e5cabae36c4442b39dbf49158414547f453',
+ ),
+ asmCrypto.hex_to_bytes('10001'),
+ asmCrypto.hex_to_bytes(
+ '75497aa8a7f8fc4f50d2b82a6b9d518db027e7449adaff4b18829685c8eecd227ba3984263b896df1c55ab53a1a9ae4b06b6f9896f8fde98b4b725de882ac13fc11b614cb2cc81bcc69b9ad167dda093c5c6637754acd0ec9e9845b1b2244d597c9f63d7ea076bda19feadcdb3bd1ba9018915fec981657fb7a4301cb87a3e1',
+ ),
+ asmCrypto.hex_to_bytes(
+ 'ef2f8d91d7cd96710d6b3b5ea1b6762b4214efe329e7d0609ab8419744ef8620391e423d5890c864aebb36c0daf5035d27f3427e6a84fde36466a14b56ad1cfb',
+ ),
+ asmCrypto.hex_to_bytes(
+ 'ced5477e0acb9c836c3c54e33268e064ce8cdfd40452c8b87ab838b36b498ae22fdbdb331f59f61dd3ca1512143e77a68f8f2400dbe9e576a000084e6fcbb689',
+ ),
+ asmCrypto.hex_to_bytes(
+ '227882f9a2d5513a27c9ed7b7ce8d3ecf61018666fb2a5f85633f9d7f82a60f521e6377ba9d8ebd87eca2260f6ed5ab7c13b30b91156eb542b331349cd4b13a3',
+ ),
+ asmCrypto.hex_to_bytes(
+ '4dea2a3460fcb2c90f4ceaed6b5ff6a802e72eaa3fb6afc64ef476e79fd2e46eb078b1ea60351371c906a7495836effbdeb89d67757076f068f59a2b7211db81',
+ ),
+ asmCrypto.hex_to_bytes(
+ '261a93613a93e438fa62858758d1db3b3db8366319517c039acfcc0ce04cd0d7349d7e8d8cb0e8a05ac966d04c18c81c49025de2b50bb87f78facccd19cd8602',
+ ),
+];
+
+describe('RSA', () => {
+ it('asmCrypto.RSA.privateKey', function() {
+ const m = new asmCrypto.Modulus(new asmCrypto.BigNumber(privkey[0]));
+ const e = new asmCrypto.BigNumber(privkey[1]);
+ const d = new asmCrypto.BigNumber(privkey[2]);
+ const p = new asmCrypto.BigNumber(privkey[3]);
+ const q = new asmCrypto.BigNumber(privkey[4]);
+ const dp = new asmCrypto.BigNumber(privkey[5]);
+ const dq = new asmCrypto.BigNumber(privkey[6]);
+ const qi = new asmCrypto.BigNumber(privkey[7]);
+
+ expect(p.multiply(q).toString(16), 'm == p*q').to.equal(m.toString(16));
+ expect(
+ e
+ .multiply(d)
+ .divide(p.subtract(asmCrypto.BigNumber.fromNumber(1)).multiply(q.subtract(asmCrypto.BigNumber.fromNumber(1))))
+ .remainder.toString(16),
+ 'e*d == 1 mod (p-1)(q-1)',
+ ).to.equal('1');
+ expect(
+ d.divide(p.subtract(asmCrypto.BigNumber.fromNumber(1))).remainder.toString(16),
+ 'dp == d mod (p-1)',
+ ).to.equal(dp.toString(16));
+ expect(
+ d.divide(q.subtract(asmCrypto.BigNumber.fromNumber(1))).remainder.toString(16),
+ 'dq == d mod (q-1)',
+ ).to.equal(dq.toString(16));
+ expect(
+ qi
+ .multiply(q)
+ .divide(p)
+ .remainder.toString(16),
+ 'qi*q == 1 mod p',
+ ).to.equal('1');
+ expect(m.slice(m.bitLength - 1).valueOf(), 'm highest bit is 1').to.equal(1);
+ });
+});
+
+describe('RSA-OAEP', () => {
+ it('asmCrypto.RSA_OAEP_SHA256 encrypt/decrypt', function() {
+ const cleartext = asmCrypto.string_to_bytes('HelloWorld!');
+ const rsaOaepEnc = new asmCrypto.RSA_OAEP(pubKey, new asmCrypto.Sha256(), asmCrypto.string_to_bytes('test'));
+ const rsaOaepDec = new asmCrypto.RSA_OAEP(privkey, new asmCrypto.Sha256(), asmCrypto.string_to_bytes('test'));
+
+ const ciphertext = rsaOaepEnc.encrypt(cleartext);
+
+ const result = rsaOaepDec.decrypt(ciphertext);
+ expect(asmCrypto.bytes_to_string(result), 'decrypt').to.equal('HelloWorld!');
+ });
+});
+
+describe('RSA-PSS-SHA256', () => {
+ it('asmCrypto.RSA_PSS_SHA256 sign/verify', function() {
+ const text = 'HelloWorld!HelloWorld!HelloWorld!HelloWorld!HelloWorld!HelloWorld!HelloWorld!HelloWorld!';
+ const rsaPssSign = new asmCrypto.RSA_PSS(privkey, new asmCrypto.Sha256());
+ const rsaPssVerify = new asmCrypto.RSA_PSS(pubKey, new asmCrypto.Sha256());
+
+ const signature = rsaPssSign.sign(asmCrypto.string_to_bytes(text));
+ rsaPssVerify.verify(signature, asmCrypto.string_to_bytes(text));
+ });
+
+ it('asmCrypto.RSA_PSS_SHA256 verify OpenSSL-signed-data', function() {
+ const key = [
+ asmCrypto.hex_to_bytes(
+ 'f30be5ce8941c8e6e764c78d12f3ce6e02a0dea03577bc0c16029de258321b74ceb43ea94f768aec900011c78eb247ab0e94b4477ea8f086ba7b5ce4b03c0ad7e0bf2f54ed509a536a0f179e27db539f729b38a279873f7b3a360690c8390e289dedca6da1ba232d8edc3c1eb229e1072716ddf3ef88caf4a824c152d6ad38f1',
+ ),
+ asmCrypto.hex_to_bytes('10001'),
+ /*
asmCrypto.hex_to_bytes('a2f4032c2ad2b4843bf851e2c0263eed7b4da875f9e3416d4904901ec5cb32a56a416711d5794143c278897326b5595fd2f2d8bc66ab96387ea75f6ce4cc1ce7ba0269a49ce03eb4aea16ca914938e88e5398b10b314276ba9f3f2e448a5f643515ee591cb4c4c5270edccacf7e5b88f86a0c08dc05311513a4ed01802de2511'),
asmCrypto.hex_to_bytes('fc592285e370d57900bfd2f8c66b15274b3381ca7ec485091d5aa0092ca8f2b97f8796e608a2fc6aa1df3647b10198c49801e3201fefa72ef9d7ccafcdae5d37'),
asmCrypto.hex_to_bytes('f6904d99d7cf9f1237c6798e5343fe730149be31e0363bf33039af84a09b5e9d0dd71239384b6cf6421e4ad41097b2cd09fd0114eb29a4339c433f37d7286f17'),
@@ -114,19 +109,17 @@ if ( typeof asmCrypto.RSA_PSS_SHA256 !== 'undefined' )
asmCrypto.hex_to_bytes('9f036da89c10208cc53fd14142de0509f278b69abff8fa2cda9b3961159b5e2777b78edf2c3928aaa0f59c58abe2c9c3867f8ee508ccb04340b1f5e17377763d'),
asmCrypto.hex_to_bytes('c07e9ca15c2cc38cc4faab0729403e02b33982b7d1219e15cd74614f3485437d2c800d66a0c368b3cf36513e4b1e05d31d7e0186f00cf036433e35f13b5cfda8')
*/
- ];
+ ];
- var text = 'Hello There!';
+ const text = 'Hello There!';
- var signature = asmCrypto.hex_to_bytes('A68BE713861409B4E536C12066B3D30650C7578F9B7AB61C1A302B42ECA14D58AE11899BC55FCB838F0AE06B99381DE26CE8D6318BD59BBFC4FFF56A995E9EFB0306FF105766F508297D1E74F22648B6BD66C18E06F4748BD258358ECB5BB722AC4AFFA146C04EE7BE84AD77ED2A84B5458D6CA4A7DA4D86DAB3F2B39FD647F4');
+ const signature = asmCrypto.hex_to_bytes(
+ 'A68BE713861409B4E536C12066B3D30650C7578F9B7AB61C1A302B42ECA14D58AE11899BC55FCB838F0AE06B99381DE26CE8D6318BD59BBFC4FFF56A995E9EFB0306FF105766F508297D1E74F22648B6BD66C18E06F4748BD258358ECB5BB722AC4AFFA146C04EE7BE84AD77ED2A84B5458D6CA4A7DA4D86DAB3F2B39FD647F4',
+ );
- var saltlen = 32;
+ const saltlen = 32;
- var result = asmCrypto.RSA_PSS_SHA256.verify( signature, text, key, saltlen );
- ok( result, "verify" );
- });
-}
-else
-{
- skip( "asmCrypto.RSA_PSS_SHA256" );
-}
+ const rsaPss = new asmCrypto.RSA_PSS(key, new asmCrypto.Sha256(), saltlen);
+ rsaPss.verify(signature, asmCrypto.string_to_bytes(text));
+ });
+});
diff --git a/test/sha1.js b/test/sha1.js
index edae9f7..757ff9c 100644
--- a/test/sha1.js
+++ b/test/sha1.js
@@ -1,98 +1,139 @@
-module("SHA1");
+import * as asmCrypto from '../asmcrypto.all.es8';
+import chai from 'chai';
+const expect = chai.expect;
-///////////////////////////////////////////////////////////////////////////////
+describe('SHA1', () => {
+ const sha1_vectors = [
+ ['a9993e364706816aba3e25717850c26c9cd0d89d', asmCrypto.string_to_bytes('abc')],
+ ['84983e441c3bd26ebaae4aa1f95129e5e54670f1', asmCrypto.string_to_bytes('abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq')],
+ [
+ 'a49b2446a02c645bf419f995b67091253a04a259',
+ asmCrypto.string_to_bytes('abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu'),
+ ],
+ ['2fd4e1c67a2d28fced849ee1bb76e7391b93eb12', asmCrypto.string_to_bytes('The quick brown fox jumps over the lazy dog')],
+ ['de9f2c7fd25e1b3afad3e85a0bd17d9b100db4b3', asmCrypto.string_to_bytes('The quick brown fox jumps over the lazy cog')],
+ ];
-if ( typeof asmCrypto.SHA1 !== 'undefined' )
-{
- var sha1_vectors = [
- [ 'a9993e364706816aba3e25717850c26c9cd0d89d', 'abc'],
- [ '84983e441c3bd26ebaae4aa1f95129e5e54670f1', 'abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq'],
- [ 'a49b2446a02c645bf419f995b67091253a04a259', 'abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu'],
- [ '2fd4e1c67a2d28fced849ee1bb76e7391b93eb12', 'The quick brown fox jumps over the lazy dog' ],
- [ 'de9f2c7fd25e1b3afad3e85a0bd17d9b100db4b3', 'The quick brown fox jumps over the lazy cog' ]
- ];
+ it('asmCrypto.SHA1.hex', function() {
+ for (let i = 0; i < sha1_vectors.length; ++i) {
+ const sha1 = new asmCrypto.Sha1();
+ expect(asmCrypto.bytes_to_hex(sha1.process(sha1_vectors[i][1]).finish().result), 'vector ' + i).to.equal(
+ sha1_vectors[i][0],
+ );
+ }
+ });
+});
- test( "asmCrypto.SHA1.hex", function () {
- for ( var i = 0; i < sha1_vectors.length; ++i ) {
- equal(
- asmCrypto.SHA1.hex( sha1_vectors[i][1] ),
- sha1_vectors[i][0],
- "vector " + i
- );
- }
- });
-}
-else
-{
- skip( "asmCrypto.SHA1" );
-}
+describe('HMAC-SHA1', () => {
+ const hmac_sha1_vectors = [
+ [
+ '5fd596ee78d5553c8ff4e72d266dfd192366da29',
+ asmCrypto.hex_to_bytes(
+ '000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f',
+ ),
+ asmCrypto.hex_to_bytes('53616d706c65206d65737361676520666f72206b65796c656e3d626c6f636b6c656e'),
+ ],
+ ['fbdb1d1b18aa6c08324b7d64b71fb76370690e1d', asmCrypto.string_to_bytes(''), asmCrypto.string_to_bytes('')],
+ [
+ 'de7c9b85b8b78aa6bc8a7a36f70a90701c9db4d9',
+ asmCrypto.string_to_bytes('key'),
+ asmCrypto.string_to_bytes('The quick brown fox jumps over the lazy dog'),
+ ],
+ [
+ 'b617318655057264e28bc0b6fb378c8ef146be00',
+ asmCrypto.hex_to_bytes('0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b'),
+ asmCrypto.string_to_bytes('Hi There'),
+ ],
+ [
+ 'effcdf6ae5eb2fa2d27416d5f184df9c259a7c79',
+ asmCrypto.string_to_bytes('Jefe'),
+ asmCrypto.string_to_bytes('what do ya want for nothing?'),
+ ],
+ ];
-///////////////////////////////////////////////////////////////////////////////
+ it('asmCrypto.HMAC_SHA1.hex', function() {
+ for (let i = 0; i < hmac_sha1_vectors.length; ++i) {
+ const hmacSha1 = new asmCrypto.HmacSha1(hmac_sha1_vectors[i][1]);
-if ( typeof asmCrypto.HMAC_SHA1 !== 'undefined' )
-{
- var hmac_sha1_vectors = [
- [ '5fd596ee78d5553c8ff4e72d266dfd192366da29', asmCrypto.hex_to_bytes('000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f'), asmCrypto.hex_to_bytes('53616d706c65206d65737361676520666f72206b65796c656e3d626c6f636b6c656e') ],
- [ 'fbdb1d1b18aa6c08324b7d64b71fb76370690e1d', '', '' ],
- [ 'de7c9b85b8b78aa6bc8a7a36f70a90701c9db4d9', 'key', 'The quick brown fox jumps over the lazy dog' ],
- [ 'b617318655057264e28bc0b6fb378c8ef146be00', asmCrypto.hex_to_bytes('0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b'), 'Hi There' ],
- [ 'effcdf6ae5eb2fa2d27416d5f184df9c259a7c79', 'Jefe', 'what do ya want for nothing?']
- ];
+ expect(asmCrypto.bytes_to_hex(hmacSha1.process(hmac_sha1_vectors[i][2]).finish().result), 'vector ' + i).to.equal(
+ hmac_sha1_vectors[i][0],
+ );
+ }
+ });
+});
- test( "asmCrypto.HMAC_SHA1.hex", function () {
- for ( var i = 0; i < hmac_sha1_vectors.length; ++i ) {
- equal(
- asmCrypto.HMAC_SHA1.hex( hmac_sha1_vectors[i][2], hmac_sha1_vectors[i][1] ),
- hmac_sha1_vectors[i][0],
- "vector " + i
- );
- }
- });
-}
-else
-{
- skip( "asmCrypto.HMAC_SHA1" );
-}
+describe('PBKDF2-HMAC-SHA1', function () {
+ this.timeout(30000);
+ const pbkdf2_hmac_sha1_vectors = [
+ [
+ '0c60c80f961f0e71f3a9b524af6012062fe037a6',
+ asmCrypto.string_to_bytes('password'),
+ asmCrypto.string_to_bytes('salt'),
+ 1,
+ 20,
+ ],
+ [
+ 'ea6c014dc72d6f8ccd1ed92ace1d41f0d8de8957',
+ asmCrypto.string_to_bytes('password'),
+ asmCrypto.string_to_bytes('salt'),
+ 2,
+ 20,
+ ],
+ [
+ '4b007901b765489abead49d926f721d065a429c1',
+ asmCrypto.string_to_bytes('password'),
+ asmCrypto.string_to_bytes('salt'),
+ 4096,
+ 20,
+ ],
+ [
+ 'eefe3d61cd4da4e4e9945b3d6ba2158c2634e984',
+ asmCrypto.string_to_bytes('password'),
+ asmCrypto.string_to_bytes('salt'),
+ 16777216,
+ 20,
+ ],
+ [
+ '3d2eec4fe41c849b80c8d83662c0e44a8b291a964cf2f07038',
+ asmCrypto.string_to_bytes('passwordPASSWORDpassword'),
+ asmCrypto.string_to_bytes('saltSALTsaltSALTsaltSALTsaltSALTsalt'),
+ 4096,
+ 25,
+ ],
+ [
+ '56fa6aa75548099dcc37d7f03425e0c3',
+ asmCrypto.string_to_bytes('pass\0word'),
+ asmCrypto.string_to_bytes('sa\0lt'),
+ 4096,
+ 16,
+ ],
+ ];
-///////////////////////////////////////////////////////////////////////////////
+ it('asmCrypto.PBKDF2_HMAC_SHA1.hex', function() {
+ for (let i = 0; i < pbkdf2_hmac_sha1_vectors.length; ++i) {
+ expect(
+ // got
+ asmCrypto.bytes_to_hex(
+ asmCrypto.Pbkdf2HmacSha1(
+ pbkdf2_hmac_sha1_vectors[i][1], // password
+ pbkdf2_hmac_sha1_vectors[i][2], // salt
+ pbkdf2_hmac_sha1_vectors[i][3], // count
+ pbkdf2_hmac_sha1_vectors[i][4], // dklen
+ ),
+ ),
-if ( typeof asmCrypto.PBKDF2_HMAC_SHA1 !== 'undefined' )
-{
- var pbkdf2_hmac_sha1_vectors = [
- [ '0c60c80f961f0e71f3a9b524af6012062fe037a6', 'password', 'salt', 1, 20 ],
- [ 'ea6c014dc72d6f8ccd1ed92ace1d41f0d8de8957', 'password', 'salt', 2, 20 ],
- [ '4b007901b765489abead49d926f721d065a429c1', 'password', 'salt', 4096, 20 ],
- //[ 'eefe3d61cd4da4e4e9945b3d6ba2158c2634e984', 'password', 'salt', 16777216, 20 ],
- [ '3d2eec4fe41c849b80c8d83662c0e44a8b291a964cf2f07038', 'passwordPASSWORDpassword', 'saltSALTsaltSALTsaltSALTsaltSALTsalt', 4096, 25 ],
- [ '56fa6aa75548099dcc37d7f03425e0c3', "pass\0word", "sa\0lt", 4096, 16 ]
- ];
-
- test( "asmCrypto.PBKDF2_HMAC_SHA1.hex", function () {
- for ( var i = 0; i < pbkdf2_hmac_sha1_vectors.length; ++i ) {
- equal(
- // got
- asmCrypto.PBKDF2_HMAC_SHA1.hex(
- pbkdf2_hmac_sha1_vectors[i][1], // password
- pbkdf2_hmac_sha1_vectors[i][2], // salt
- pbkdf2_hmac_sha1_vectors[i][3], // count
- pbkdf2_hmac_sha1_vectors[i][4] // dklen
- ),
-
- // expect
- pbkdf2_hmac_sha1_vectors[i][0],
-
- // comment
- "asmCrypto.PBKDF2_HMAC_SHA1.hex('"
- +pbkdf2_hmac_sha1_vectors[i][1]+"', '"
- +pbkdf2_hmac_sha1_vectors[i][2]+"', '"
- +pbkdf2_hmac_sha1_vectors[i][3]+"', '"
- +pbkdf2_hmac_sha1_vectors[i][4]
- +"') is equal to '"+pbkdf2_hmac_sha1_vectors[i][0]+"'"
- );
- }
- });
-}
-else
-{
- skip( "asmCrypto.PBKDF2_HMAC_SHA1" );
-}
+ "asmCrypto.PBKDF2_HMAC_SHA1.hex('" +
+ pbkdf2_hmac_sha1_vectors[i][1] +
+ "', '" +
+ pbkdf2_hmac_sha1_vectors[i][2] +
+ "', '" +
+ pbkdf2_hmac_sha1_vectors[i][3] +
+ "', '" +
+ pbkdf2_hmac_sha1_vectors[i][4] +
+ "') is equal to '" +
+ pbkdf2_hmac_sha1_vectors[i][0] +
+ "'",
+ ).to.equal(pbkdf2_hmac_sha1_vectors[i][0]);
+ }
+ });
+});
diff --git a/test/sha256.js b/test/sha256.js
index 917a666..be1fc80 100644
--- a/test/sha256.js
+++ b/test/sha256.js
@@ -1,99 +1,140 @@
-module("SHA256");
+import * as asmCrypto from '../asmcrypto.all.es8';
+import chai from 'chai';
+const expect = chai.expect;
-///////////////////////////////////////////////////////////////////////////////
+describe('SHA256', () => {
+ const sha256_vectors = [
+ ['e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855', asmCrypto.string_to_bytes('')],
+ ['ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad', asmCrypto.string_to_bytes('abc')],
+ ['f7846f55cf23e14eebeab5b4e1550cad5b509e3348fbc4efa3a1413d393cb650', asmCrypto.string_to_bytes('message digest')],
+ [
+ 'f30ceb2bb2829e79e4ca9753d35a8ecc00262d164cc077080295381cbd643f0d',
+ asmCrypto.string_to_bytes('secure hash algorithm'),
+ ],
+ [
+ '6819d915c73f4d1e77e4e1b52d1fa0f9cf9beaead3939f15874bd988e2a23630',
+ asmCrypto.string_to_bytes('SHA256 is considered to be safe'),
+ ],
+ [
+ '248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1',
+ asmCrypto.string_to_bytes('abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq'),
+ ],
+ [
+ 'f08a78cbbaee082b052ae0708f32fa1e50c5c421aa772ba5dbb406a2ea6be342',
+ asmCrypto.string_to_bytes('For this sample, this 63-byte string will be used as input data'),
+ ],
+ [
+ 'ab64eff7e88e2e46165e29f2bce41826bd4c7b3552f6b382a9e7d3af47c245f8',
+ asmCrypto.string_to_bytes('This is exactly 64 bytes long, not counting the terminating byte'),
+ ],
+ ];
-if ( typeof asmCrypto.SHA256 !== 'undefined' )
-{
- var sha256_vectors = [
- [ 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855', '' ],
- [ 'ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad', 'abc' ],
- [ 'f7846f55cf23e14eebeab5b4e1550cad5b509e3348fbc4efa3a1413d393cb650', 'message digest' ],
- [ 'f30ceb2bb2829e79e4ca9753d35a8ecc00262d164cc077080295381cbd643f0d', 'secure hash algorithm' ],
- [ '6819d915c73f4d1e77e4e1b52d1fa0f9cf9beaead3939f15874bd988e2a23630', 'SHA256 is considered to be safe' ],
- [ '248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1', 'abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq' ],
- [ 'f08a78cbbaee082b052ae0708f32fa1e50c5c421aa772ba5dbb406a2ea6be342', 'For this sample, this 63-byte string will be used as input data' ],
- [ 'ab64eff7e88e2e46165e29f2bce41826bd4c7b3552f6b382a9e7d3af47c245f8', 'This is exactly 64 bytes long, not counting the terminating byte' ]
- ];
+ it('asmCrypto.SHA256.hex', function() {
+ for (let i = 0; i < sha256_vectors.length; ++i) {
+ const sha256 = new asmCrypto.Sha256();
+ expect(asmCrypto.bytes_to_hex(sha256.process(sha256_vectors[i][1]).finish().result), 'vector ' + i).to.equal(
+ sha256_vectors[i][0],
+ );
+ }
+ });
+});
+describe('HMAC-SHA256', () => {
+ const hmac_sha256_vectors = [
+ [
+ 'b613679a0814d9ec772f95d778c35fc5ff1697c493715653c6c712144292c5ad',
+ asmCrypto.string_to_bytes(''),
+ asmCrypto.string_to_bytes(''),
+ ],
+ [
+ 'f7bc83f430538424b13298e6aa6fb143ef4d59a14946175997479dbc2d1a3cd8',
+ asmCrypto.string_to_bytes('key'),
+ asmCrypto.string_to_bytes('The quick brown fox jumps over the lazy dog'),
+ ],
+ [
+ 'b54d57e9b21940b6496b58d5ac120eda9f1637788b5df058928637f2eca40cd9',
+ asmCrypto.string_to_bytes('MyVeeeeeeeeeeeeeryVeeeeeeeeeeeeeryVeeeeeeeeeeeeeryLoooooooooongPassword'),
+ asmCrypto.string_to_bytes('Lorem ipsum dolor sit amet, consectetur adipiscing elit.'),
+ ],
+ ];
- test( "asmCrypto.SHA256.hex", function () {
- for ( var i = 0; i < sha256_vectors.length; ++i ) {
- equal(
- asmCrypto.SHA256.hex( sha256_vectors[i][1] ),
- sha256_vectors[i][0],
- "vector " + i
- );
- }
- });
-}
-else
-{
- skip( "asmCrypto.SHA256" );
-}
+ it('asmCrypto.HMAC_SHA256.hex', function() {
+ for (let i = 0; i < hmac_sha256_vectors.length; ++i) {
+ const hmacSha256 = new asmCrypto.HmacSha256(hmac_sha256_vectors[i][1]);
+ expect(
+ asmCrypto.bytes_to_hex(hmacSha256.process(hmac_sha256_vectors[i][2]).finish().result),
+ 'vector ' + i,
+ ).to.equal(hmac_sha256_vectors[i][0]);
+ }
+ });
+});
+describe('PBKDF2-HMAC-SHA256', () => {
+ const pbkdf2_hmac_sha256_vectors = [
+ [
+ '120fb6cffcf8b32c43e7225256c4f837a86548c92ccc35480805987cb70be17b',
+ asmCrypto.string_to_bytes('password'),
+ asmCrypto.string_to_bytes('salt'),
+ 1,
+ 32,
+ ],
+ [
+ 'ae4d0c95af6b46d32d0adff928f06dd02a303f8ef3c251dfd6e2d85a95474c43',
+ asmCrypto.string_to_bytes('password'),
+ asmCrypto.string_to_bytes('salt'),
+ 2,
+ 32,
+ ],
+ [
+ 'c5e478d59288c841aa530db6845c4c8d962893a001ce4e11a4963873aa98134a',
+ asmCrypto.string_to_bytes('password'),
+ asmCrypto.string_to_bytes('salt'),
+ 4096,
+ 32,
+ ],
+ [
+ '348c89dbcbd32b2f32d814b8116e84cf2b17347ebc1800181c4e2a1fb8dd53e1c635518c7dac47e9',
+ asmCrypto.string_to_bytes('passwordPASSWORDpassword'),
+ asmCrypto.string_to_bytes('saltSALTsaltSALTsaltSALTsaltSALTsalt'),
+ 4096,
+ 40,
+ ],
+ [
+ '89b69d0516f829893c696226650a8687',
+ asmCrypto.string_to_bytes('pass\0word'),
+ asmCrypto.string_to_bytes('sa\0lt'),
+ 4096,
+ 16,
+ ],
+ [
+ 'cdc8b1780ca68aba97f1f729c9d281719702eb4b308d7d87409817e60188be0d',
+ asmCrypto.string_to_bytes('MyVeeeeeeeeeeeeeryVeeeeeeeeeeeeeryVeeeeeeeeeeeeeryLoooooooooongPassword'),
+ asmCrypto.string_to_bytes('MyVeeeeeeeeeeeeeryVeeeeeeeeeeeeeryVeeeeeeeeeeeeeryLoooooooooongPassword'),
+ 4096,
+ 32,
+ ],
+ ];
-///////////////////////////////////////////////////////////////////////////////
-
-if ( typeof asmCrypto.HMAC_SHA256 !== 'undefined' )
-{
- var hmac_sha256_vectors = [
- [ 'b613679a0814d9ec772f95d778c35fc5ff1697c493715653c6c712144292c5ad', '', '' ],
- [ 'f7bc83f430538424b13298e6aa6fb143ef4d59a14946175997479dbc2d1a3cd8', 'key', 'The quick brown fox jumps over the lazy dog' ],
- [ 'b54d57e9b21940b6496b58d5ac120eda9f1637788b5df058928637f2eca40cd9', 'MyVeeeeeeeeeeeeeryVeeeeeeeeeeeeeryVeeeeeeeeeeeeeryLoooooooooongPassword', 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.' ]
- ];
-
- test( "asmCrypto.HMAC_SHA256.hex", function () {
- for ( var i = 0; i < hmac_sha256_vectors.length; ++i ) {
- equal(
- asmCrypto.HMAC_SHA256.hex( hmac_sha256_vectors[i][2], hmac_sha256_vectors[i][1] ),
- hmac_sha256_vectors[i][0],
- "vector " + i
- );
- }
- });
-}
-else
-{
- skip( "asmCrypto.HMAC_SHA256" );
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-if ( typeof asmCrypto.PBKDF2_HMAC_SHA256 !== 'undefined' )
-{
- var pbkdf2_hmac_sha256_vectors = [
- [ '120fb6cffcf8b32c43e7225256c4f837a86548c92ccc35480805987cb70be17b', 'password', 'salt', 1, 32 ],
- [ 'ae4d0c95af6b46d32d0adff928f06dd02a303f8ef3c251dfd6e2d85a95474c43', 'password', 'salt', 2, 32 ],
- [ 'c5e478d59288c841aa530db6845c4c8d962893a001ce4e11a4963873aa98134a', 'password', 'salt', 4096, 32 ],
- [ '348c89dbcbd32b2f32d814b8116e84cf2b17347ebc1800181c4e2a1fb8dd53e1c635518c7dac47e9', 'passwordPASSWORDpassword', 'saltSALTsaltSALTsaltSALTsaltSALTsalt', 4096, 40 ],
- [ '89b69d0516f829893c696226650a8687', "pass\0word", "sa\0lt", 4096, 16 ],
- [ 'cdc8b1780ca68aba97f1f729c9d281719702eb4b308d7d87409817e60188be0d', 'MyVeeeeeeeeeeeeeryVeeeeeeeeeeeeeryVeeeeeeeeeeeeeryLoooooooooongPassword', 'MyVeeeeeeeeeeeeeryVeeeeeeeeeeeeeryVeeeeeeeeeeeeeryLoooooooooongPassword', 4096, 32 ]
- ];
-
- test( "asmCrypto.PBKDF2_HMAC_SHA256.hex", function () {
- for ( var i = 0; i < pbkdf2_hmac_sha256_vectors.length; ++i ) {
- equal(
- // got
- asmCrypto.PBKDF2_HMAC_SHA256.hex(
- pbkdf2_hmac_sha256_vectors[i][1], // password
- pbkdf2_hmac_sha256_vectors[i][2], // salt
- pbkdf2_hmac_sha256_vectors[i][3], // count
- pbkdf2_hmac_sha256_vectors[i][4] // dklen
- ),
-
- // expect
- pbkdf2_hmac_sha256_vectors[i][0],
-
- // comment
- "asmCrypto.PBKDF2_HMAC_SHA256.hex('"
- +pbkdf2_hmac_sha256_vectors[i][1]+"', '"
- +pbkdf2_hmac_sha256_vectors[i][2]+"', '"
- +pbkdf2_hmac_sha256_vectors[i][3]+"', '"
- +pbkdf2_hmac_sha256_vectors[i][4]
- +"') is equal to '"+pbkdf2_hmac_sha256_vectors[i][0]+"'"
- );
- }
- });
-}
-else
-{
- skip( "asmCrypto.PBKDF2_HMAC_SHA256" );
-}
+ it('asmCrypto.PBKDF2_HMAC_SHA256.hex', function() {
+ for (let i = 0; i < pbkdf2_hmac_sha256_vectors.length; ++i) {
+ expect(
+ // got
+ asmCrypto.bytes_to_hex(asmCrypto.Pbkdf2HmacSha256(
+ pbkdf2_hmac_sha256_vectors[i][1], // password
+ pbkdf2_hmac_sha256_vectors[i][2], // salt
+ pbkdf2_hmac_sha256_vectors[i][3], // count
+ pbkdf2_hmac_sha256_vectors[i][4], // dklen
+ )),
+ "asmCrypto.PBKDF2_HMAC_SHA256.hex('" +
+ pbkdf2_hmac_sha256_vectors[i][1] +
+ "', '" +
+ pbkdf2_hmac_sha256_vectors[i][2] +
+ "', '" +
+ pbkdf2_hmac_sha256_vectors[i][3] +
+ "', '" +
+ pbkdf2_hmac_sha256_vectors[i][4] +
+ "') is equal to '" +
+ pbkdf2_hmac_sha256_vectors[i][0] +
+ "'",
+ ).to.equal(pbkdf2_hmac_sha256_vectors[i][0]);
+ }
+ });
+});
diff --git a/test/sha512.js b/test/sha512.js
index 973663d..c84ca69 100644
--- a/test/sha512.js
+++ b/test/sha512.js
@@ -1,95 +1,136 @@
-module("SHA512");
+import * as asmCrypto from '../asmcrypto.all.es8';
+import chai from 'chai';
+const expect = chai.expect;
-///////////////////////////////////////////////////////////////////////////////
+describe('SHA512', () => {
+ const sha512_vectors = [
+ [
+ 'cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e',
+ asmCrypto.string_to_bytes(''),
+ ],
+ [
+ 'ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f',
+ asmCrypto.string_to_bytes('abc'),
+ ],
+ [
+ '8e959b75dae313da8cf4f72814fc143f8f7779c6eb9f7fa17299aeadb6889018501d289e4900f7e4331b99dec4b5433ac7d329eeb6dd26545e96e55b874be909',
+ asmCrypto.string_to_bytes(
+ 'abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu',
+ ),
+ ],
+ [
+ '07e547d9586f6a73f73fbac0435ed76951218fb7d0c8d788a309d785436bbb642e93a252a954f23912547d1e8a3b5ed6e1bfd7097821233fa0538f3db854fee6',
+ asmCrypto.string_to_bytes('The quick brown fox jumps over the lazy dog'),
+ ],
+ [
+ '91ea1245f20d46ae9a037a989f54f1f790f0a47607eeb8a14d12890cea77a1bbc6c7ed9cf205e67b7f2b8fd4c7dfd3a7a8617e45f3c463d481c7e586c39ac1ed',
+ asmCrypto.string_to_bytes('The quick brown fox jumps over the lazy dog.'),
+ ],
+ ];
-if ( typeof asmCrypto.SHA512 !== 'undefined' )
-{
- var sha512_vectors = [
- [ 'cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e', '' ],
- [ 'ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f', 'abc' ],
- [ '8e959b75dae313da8cf4f72814fc143f8f7779c6eb9f7fa17299aeadb6889018501d289e4900f7e4331b99dec4b5433ac7d329eeb6dd26545e96e55b874be909', 'abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu' ],
- [ '07e547d9586f6a73f73fbac0435ed76951218fb7d0c8d788a309d785436bbb642e93a252a954f23912547d1e8a3b5ed6e1bfd7097821233fa0538f3db854fee6', 'The quick brown fox jumps over the lazy dog' ],
- [ '91ea1245f20d46ae9a037a989f54f1f790f0a47607eeb8a14d12890cea77a1bbc6c7ed9cf205e67b7f2b8fd4c7dfd3a7a8617e45f3c463d481c7e586c39ac1ed', 'The quick brown fox jumps over the lazy dog.' ]
- ];
+ it('asmCrypto.SHA512.hex', function() {
+ for (let i = 0; i < sha512_vectors.length; ++i) {
+ const sha512 = new asmCrypto.Sha512();
+ expect(asmCrypto.bytes_to_hex(sha512.process(sha512_vectors[i][1]).finish().result), 'vector ' + i).to.equal(
+ sha512_vectors[i][0],
+ );
+ }
+ });
+});
+describe('HMAC-SHA512', () => {
+ const hmac_sha512_vectors = [
+ [
+ '87aa7cdea5ef619d4ff0b4241a1d6cb02379f4e2ce4ec2787ad0b30545e17cdedaa833b7d6b8a702038b274eaea3f4e4be9d914eeb61f1702e696c203a126854',
+ asmCrypto.hex_to_bytes('0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b'),
+ asmCrypto.string_to_bytes('Hi There'),
+ ],
+ [
+ '164b7a7bfcf819e2e395fbe73b56e0a387bd64222e831fd610270cd7ea2505549758bf75c05a994a6d034f65f8f0e6fdcaeab1a34d4a6b4b636e070a38bce737',
+ asmCrypto.string_to_bytes('Jefe'),
+ asmCrypto.string_to_bytes('what do ya want for nothing?'),
+ ],
+ [
+ '80b24263c7c1a3ebb71493c1dd7be8b49b46d1f41b4aeec1121b013783f8f3526b56d037e05f2598bd0fd2215d6a1e5295e64f73f63f0aec8b915a985d786598',
+ asmCrypto.hex_to_bytes(
+ 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
+ ),
+ asmCrypto.string_to_bytes('Test Using Larger Than Block-Size Key - Hash Key First'),
+ ],
+ ];
- test( "asmCrypto.SHA512.hex", function () {
- for ( var i = 0; i < sha512_vectors.length; ++i ) {
- equal(
- asmCrypto.SHA512.hex( sha512_vectors[i][1] ),
- sha512_vectors[i][0],
- "vector " + i
- );
- }
- });
-}
-else
-{
- skip( "asmCrypto.SHA512" );
-}
+ it('asmCrypto.HMAC_SHA512.hex', function() {
+ for (let i = 0; i < hmac_sha512_vectors.length; ++i) {
+ const hmacSha512 = new asmCrypto.HmacSha512(hmac_sha512_vectors[i][1]);
+ expect(
+ asmCrypto.bytes_to_hex(hmacSha512.process(hmac_sha512_vectors[i][2]).finish().result),
+ 'vector ' + i,
+ ).to.equal(hmac_sha512_vectors[i][0]);
+ }
+ });
+});
+describe('PBKDF2-HMAC-SHA512', () => {
+ const pbkdf2_hmac_sha512_vectors = [
+ [
+ '867f70cf1ade02cff3752599a3a53dc4af34c7a669815ae5d513554e1c8cf252c02d470a285a0501bad999bfe943c08f050235d7d68b1da55e63f73b60a57fce',
+ asmCrypto.string_to_bytes('password'),
+ asmCrypto.string_to_bytes('salt'),
+ 1,
+ 64,
+ ],
+ [
+ '867f70cf1ade02cff3752599a3a53dc4af34c7a669815ae5d513554e1c8cf252c02d470a285a0501bad999bfe943c08f050235d7d68b1da55e63f73b60a57fce',
+ asmCrypto.string_to_bytes('password'),
+ asmCrypto.string_to_bytes('salt'),
+ 1,
+ 64,
+ ],
+ [
+ 'e1d9c16aa681708a45f5c7c4e215ceb66e011a2e9f0040713f18aefdb866d53cf76cab2868a39b9f7840edce4fef5a82be67335c77a6068e04112754f27ccf4e',
+ asmCrypto.string_to_bytes('password'),
+ asmCrypto.string_to_bytes('salt'),
+ 2,
+ 64,
+ ],
+ [
+ 'd197b1b33db0143e018b12f3d1d1479e6cdebdcc97c5c0f87f6902e072f457b5143f30602641b3d55cd335988cb36b84376060ecd532e039b742a239434af2d5',
+ asmCrypto.string_to_bytes('password'),
+ asmCrypto.string_to_bytes('salt'),
+ 4096,
+ 64,
+ ],
+ [
+ '8c0511f4c6e597c6ac6315d8f0362e225f3c501495ba23b868c005174dc4ee71115b59f9e60cd9532fa33e0f75aefe30225c583a186cd82bd4daea9724a3d3b8',
+ asmCrypto.string_to_bytes('passwordPASSWORDpassword'),
+ asmCrypto.string_to_bytes('saltSALTsaltSALTsaltSALTsaltSALTsalt'),
+ 4096,
+ 64,
+ ],
+ ];
-///////////////////////////////////////////////////////////////////////////////
-
-if ( typeof asmCrypto.HMAC_SHA512 !== 'undefined' )
-{
- var hmac_sha512_vectors = [
- [ '87aa7cdea5ef619d4ff0b4241a1d6cb02379f4e2ce4ec2787ad0b30545e17cdedaa833b7d6b8a702038b274eaea3f4e4be9d914eeb61f1702e696c203a126854', asmCrypto.hex_to_bytes('0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b'), 'Hi There'],
- [ '164b7a7bfcf819e2e395fbe73b56e0a387bd64222e831fd610270cd7ea2505549758bf75c05a994a6d034f65f8f0e6fdcaeab1a34d4a6b4b636e070a38bce737', 'Jefe', 'what do ya want for nothing?' ],
- [ '80b24263c7c1a3ebb71493c1dd7be8b49b46d1f41b4aeec1121b013783f8f3526b56d037e05f2598bd0fd2215d6a1e5295e64f73f63f0aec8b915a985d786598', asmCrypto.hex_to_bytes('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'), 'Test Using Larger Than Block-Size Key - Hash Key First']
- ];
-
- test( "asmCrypto.HMAC_SHA512.hex", function () {
- for ( var i = 0; i < hmac_sha512_vectors.length; ++i ) {
- equal(
- asmCrypto.HMAC_SHA512.hex( hmac_sha512_vectors[i][2], hmac_sha512_vectors[i][1] ),
- hmac_sha512_vectors[i][0],
- "vector " + i
- );
- }
- });
-}
-else
-{
- skip( "asmCrypto.HMAC_SHA512" );
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-if ( typeof asmCrypto.PBKDF2_HMAC_SHA512 !== 'undefined' )
-{
- var pbkdf2_hmac_sha512_vectors = [
- [ '867f70cf1ade02cff3752599a3a53dc4af34c7a669815ae5d513554e1c8cf252c02d470a285a0501bad999bfe943c08f050235d7d68b1da55e63f73b60a57fce', 'password', 'salt', 1, 64 ],
- [ '867f70cf1ade02cff3752599a3a53dc4af34c7a669815ae5d513554e1c8cf252c02d470a285a0501bad999bfe943c08f050235d7d68b1da55e63f73b60a57fce', asmCrypto.string_to_bytes('password'), asmCrypto.string_to_bytes('salt'), 1, 64 ],
- [ 'e1d9c16aa681708a45f5c7c4e215ceb66e011a2e9f0040713f18aefdb866d53cf76cab2868a39b9f7840edce4fef5a82be67335c77a6068e04112754f27ccf4e', 'password', 'salt', 2, 64 ],
- [ 'd197b1b33db0143e018b12f3d1d1479e6cdebdcc97c5c0f87f6902e072f457b5143f30602641b3d55cd335988cb36b84376060ecd532e039b742a239434af2d5', 'password', 'salt', 4096, 64 ],
- [ '8c0511f4c6e597c6ac6315d8f0362e225f3c501495ba23b868c005174dc4ee71115b59f9e60cd9532fa33e0f75aefe30225c583a186cd82bd4daea9724a3d3b8', 'passwordPASSWORDpassword', 'saltSALTsaltSALTsaltSALTsaltSALTsalt', 4096, 64 ]
- ];
-
- test( "asmCrypto.PBKDF2_HMAC_SHA512.hex", function () {
- for ( var i = 0; i < pbkdf2_hmac_sha512_vectors.length; ++i ) {
- equal(
- // got
- asmCrypto.PBKDF2_HMAC_SHA512.hex(
- pbkdf2_hmac_sha512_vectors[i][1], // password
- pbkdf2_hmac_sha512_vectors[i][2], // salt
- pbkdf2_hmac_sha512_vectors[i][3], // count
- pbkdf2_hmac_sha512_vectors[i][4] // dklen
- ),
-
- // expect
- pbkdf2_hmac_sha512_vectors[i][0],
-
- // comment
- "asmCrypto.PBKDF2_HMAC_SHA512.hex('"
- +pbkdf2_hmac_sha512_vectors[i][1]+"', '"
- +pbkdf2_hmac_sha512_vectors[i][2]+"', '"
- +pbkdf2_hmac_sha512_vectors[i][3]+"', '"
- +pbkdf2_hmac_sha512_vectors[i][4]
- +"') is equal to '"+pbkdf2_hmac_sha512_vectors[i][0]+"'"
- );
- }
- });
-}
-else
-{
- skip( "asmCrypto.PBKDF2_HMAC_SHA512" );
-}
+ it('asmCrypto.PBKDF2_HMAC_SHA512.hex', function() {
+ for (let i = 0; i < pbkdf2_hmac_sha512_vectors.length; ++i) {
+ expect(
+ // got
+ asmCrypto.bytes_to_hex(
+ asmCrypto.Pbkdf2HmacSha512(
+ pbkdf2_hmac_sha512_vectors[i][1], // password
+ pbkdf2_hmac_sha512_vectors[i][2], // salt
+ pbkdf2_hmac_sha512_vectors[i][3], // count
+ pbkdf2_hmac_sha512_vectors[i][4], // dklen
+ ),
+ ),
+ "asmCrypto.PBKDF2_HMAC_SHA512.hex('" +
+ pbkdf2_hmac_sha512_vectors[i][1] +
+ "', '" +
+ pbkdf2_hmac_sha512_vectors[i][2] +
+ "', '" +
+ pbkdf2_hmac_sha512_vectors[i][3] +
+ "', '" +
+ pbkdf2_hmac_sha512_vectors[i][4] +
+ "') is expect to '" +
+ pbkdf2_hmac_sha512_vectors[i][0] +
+ "'",
+ ).to.equal(pbkdf2_hmac_sha512_vectors[i][0]);
+ }
+ });
+});
diff --git a/tsconfig.json b/tsconfig.json
index 953eb19..4b6424b 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -1,16 +1,23 @@
{
"compilerOptions": {
- "module": "es6",
+ "module": "ES6",
"target": "es2017",
- "noEmit": true,
- "allowJs": true,
- "checkJs": true,
- "sourceMap": false
+ "lib": ["es5", "dom", "dom.iterable", "es6"],
+ "noEmit": false,
+ "strict": true,
+ "sourceMap": false,
+ "declaration": true,
+ "noUnusedLocals": true,
+ "noUnusedParameters": true,
+ "outDir": "dist_es8"
},
+ "include": [
+ "src/**/*.ts"
+ ],
"exclude": [
"node_modules"
],
- "include": [
- "src"
+ "files": [
+ "src/entry-export_all.ts"
]
}
diff --git a/tslint.json b/tslint.json
new file mode 100644
index 0000000..d6b2aa2
--- /dev/null
+++ b/tslint.json
@@ -0,0 +1,6 @@
+{
+ "extends": ["tslint-plugin-prettier"],
+ "rules": {
+ "prettier": true
+ }
+}