├── src
├── rsa
│ ├── raw.js
│ ├── exports-keygen.js
│ ├── exports-raw.js
│ ├── exports-oaep-sha1.js
│ ├── exports-oaep-sha256.js
│ ├── exports-oaep-sha512.js
│ ├── exports-pss-sha1.js
│ ├── exports-pss-sha256.js
│ ├── exports-pss-sha512.js
│ ├── genkey.js
│ ├── rsa.js
│ └── pkcs1.js
├── random
│ ├── globals.js
│ ├── exports.js
│ ├── isaac.js
│ └── random.js
├── globals.js
├── bignum
│ ├── exports.js
│ ├── extgcd.js
│ ├── modulus.js
│ ├── prime.js
│ └── bignum.js
├── exports.js
├── aes
│ ├── ctr
│ │ ├── exports.js
│ │ └── ctr.js
│ ├── cfb
│ │ ├── exports.js
│ │ └── cfb.js
│ ├── ecb
│ │ ├── exports.js
│ │ └── ecb.js
│ ├── cbc
│ │ ├── exports.js
│ │ └── cbc.js
│ ├── exports-gcm.js
│ ├── exports-ccm.js
│ ├── exports.js
│ ├── aes.js
│ ├── naes.js
│ ├── aes-gcm.js
│ └── aes-ccm.js
├── hash
│ ├── sha1
│ │ ├── exports.js
│ │ └── sha1.js
│ ├── sha256
│ │ ├── exports.js
│ │ └── sha256.js
│ ├── sha512
│ │ ├── exports.js
│ │ └── sha512.js
│ └── hash.js
├── errors.js
├── hmac
│ ├── exports-hmac-sha256.js
│ ├── exports-hmac-sha512.js
│ ├── exports-hmac-sha1.js
│ ├── hmac-sha256.js
│ ├── hmac-sha1.js
│ ├── hmac.js
│ └── hmac-sha512.js
├── pbkdf2
│ ├── exports-pbkdf2-hmac-sha1.js
│ ├── exports-pbkdf2-hmac-sha256.js
│ ├── exports-pbkdf2-hmac-sha512.js
│ ├── pbkdf2-hmac-sha1.js
│ ├── pbkdf2-hmac-sha256.js
│ ├── pbkdf2-hmac-sha512.js
│ └── pbkdf2.js
└── utils.js
├── .gitignore
├── .travis.yml
├── bower.json
├── package.json
├── LICENSE
├── test
├── index.html
├── sha1.js
├── sha256.js
├── dummy.js
├── sha512.js
├── isaac.js
└── rsa.js
└── README.md
/src/rsa/raw.js:
--------------------------------------------------------------------------------
1 |
2 | var RSA_RAW = RSA;
3 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | asmcrypto.js
2 | asmcrypto.js.map
3 | node_modules/
4 | !node_modules/uglify-js/
5 |
--------------------------------------------------------------------------------
/src/random/globals.js:
--------------------------------------------------------------------------------
1 | global.Math.random = Random_getNumber;
2 |
3 | if ( global.crypto === undefined ) global.crypto = {};
4 | global.crypto.getRandomValues = Random_getValues;
5 |
--------------------------------------------------------------------------------
/src/globals.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Error definitions
3 | */
4 |
5 | global.IllegalStateError = IllegalStateError;
6 | global.IllegalArgumentError = IllegalArgumentError;
7 | global.SecurityError = SecurityError;
8 |
--------------------------------------------------------------------------------
/src/bignum/exports.js:
--------------------------------------------------------------------------------
1 | BigNumber.ZERO = BigNumber_ZERO;
2 | BigNumber.ONE = BigNumber_ONE;
3 |
4 | BigNumber.extGCD = BigNumber_extGCD;
5 |
6 | exports.BigNumber = BigNumber;
7 | exports.Modulus = Modulus;
8 |
--------------------------------------------------------------------------------
/src/exports.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Util exports
3 | */
4 |
5 | exports.string_to_bytes = string_to_bytes;
6 | exports.hex_to_bytes = hex_to_bytes;
7 | exports.base64_to_bytes = base64_to_bytes;
8 | exports.bytes_to_string = bytes_to_string;
9 | exports.bytes_to_hex = bytes_to_hex;
10 | exports.bytes_to_base64 = bytes_to_base64;
11 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 | node_js:
3 | - '0.11'
4 | addons:
5 | sauce_connect:
6 | username: vibornoff
7 | access_key:
8 | secure: N5jZowSuf5vPTUSgnYIX4sdFV3u0z/b8DMBSbMzst34VahI428jJlTPfMcswVomflwIA5dO0KgvCvRpKnos4gVIG02PUNYsCSuwg5nBOq025r8PX1nI3tYBK0n1SHHFYQs9swqeiKVVE0bG1AwrIAMNqJS5DnxMBw7z/dM6cPf8=
9 | before_install:
10 | export WITH=ALL
11 | script:
12 | grunt test && grunt sauce
13 |
--------------------------------------------------------------------------------
/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "asmcrypto",
3 | "main": "asmcrypto.js",
4 | "license": "MIT",
5 | "ignore": [
6 | "**/.*",
7 | "node_modules",
8 | "test",
9 | "test.html",
10 | "Gruntfile.js",
11 | "package.json"
12 | ],
13 | "keywords": [
14 | "crypto",
15 | "asmcrypto",
16 | "webcrypto",
17 | "library",
18 | "sha", "sha1", "sha256", "sha512",
19 | "hmac",
20 | "pbkdf", "pbkdf2",
21 | "aes", "aes256", "cbc", "ccm", "cfb",
22 | "rsa", "oaep", "pss", "pkcs"
23 | ]
24 | }
25 |
--------------------------------------------------------------------------------
/src/rsa/exports-keygen.js:
--------------------------------------------------------------------------------
1 | /**
2 | * RSA keygen exports
3 | */
4 | function rsa_generate_key ( bitlen, e ) {
5 | if ( bitlen === undefined ) throw new SyntaxError("bitlen required");
6 | if ( e === undefined ) throw new SyntaxError("e required");
7 | var key = RSA_generateKey( bitlen, e );
8 | for ( var i = 0; i < key.length; i++ ) {
9 | if ( is_big_number(key[i]) )
10 | key[i] = key[i].toBytes();
11 | }
12 | return key;
13 | }
14 |
15 | exports.RSA = {
16 | generateKey: rsa_generate_key
17 | };
18 |
--------------------------------------------------------------------------------
/src/aes/ctr/exports.js:
--------------------------------------------------------------------------------
1 | /**
2 | * AES-CTR exports
3 | */
4 |
5 | function AES_CTR_crypt_bytes ( data, key, iv ) {
6 | if ( data === undefined ) throw new SyntaxError("data required");
7 | if ( key === undefined ) throw new SyntaxError("key required");
8 | return get_AES_CTR_instance( { key: key, iv: iv } ).encrypt(data).result;
9 | }
10 |
11 | exports.AES_CTR = createSimpleCipherInterface( AES_CTR );
12 | exports.AES_CTR.encrypt = AES_CTR_crypt_bytes;
13 | exports.AES_CTR.decrypt = AES_CTR_crypt_bytes;
14 |
15 | exports.AES_CTR.Encrypt =
16 | exports.AES_CTR.Decrypt = createProgressiveCipherInterface( AES_CTR_Crypt );
17 |
--------------------------------------------------------------------------------
/src/hash/sha1/exports.js:
--------------------------------------------------------------------------------
1 | /**
2 | * SHA1 exports
3 | */
4 |
5 | function sha1_bytes ( data ) {
6 | if ( data === undefined ) throw new SyntaxError("data required");
7 | return get_sha1_instance().reset().process(data).finish().result;
8 | }
9 |
10 | function sha1_hex ( data ) {
11 | var result = sha1_bytes(data);
12 | return bytes_to_hex(result);
13 | }
14 |
15 | function sha1_base64 ( data ) {
16 | var result = sha1_bytes(data);
17 | return bytes_to_base64(result);
18 | }
19 |
20 | sha1_constructor.bytes = sha1_bytes;
21 | sha1_constructor.hex = sha1_hex;
22 | sha1_constructor.base64 = sha1_base64;
23 |
24 | exports.SHA1 = sha1_constructor;
25 |
--------------------------------------------------------------------------------
/src/hash/sha256/exports.js:
--------------------------------------------------------------------------------
1 | /**
2 | * SHA256 exports
3 | */
4 |
5 | function sha256_bytes ( data ) {
6 | if ( data === undefined ) throw new SyntaxError("data required");
7 | return get_sha256_instance().reset().process(data).finish().result;
8 | }
9 |
10 | function sha256_hex ( data ) {
11 | var result = sha256_bytes(data);
12 | return bytes_to_hex(result);
13 | }
14 |
15 | function sha256_base64 ( data ) {
16 | var result = sha256_bytes(data);
17 | return bytes_to_base64(result);
18 | }
19 |
20 | sha256_constructor.bytes = sha256_bytes;
21 | sha256_constructor.hex = sha256_hex;
22 | sha256_constructor.base64 = sha256_base64;
23 |
24 | exports.SHA256 = sha256_constructor;
25 |
--------------------------------------------------------------------------------
/src/hash/sha512/exports.js:
--------------------------------------------------------------------------------
1 | /**
2 | * SHA512 exports
3 | */
4 |
5 | function sha512_bytes ( data ) {
6 | if ( data === undefined ) throw new SyntaxError("data required");
7 | return get_sha512_instance().reset().process(data).finish().result;
8 | }
9 |
10 | function sha512_hex ( data ) {
11 | var result = sha512_bytes(data);
12 | return bytes_to_hex(result);
13 | }
14 |
15 | function sha512_base64 ( data ) {
16 | var result = sha512_bytes(data);
17 | return bytes_to_base64(result);
18 | }
19 |
20 | sha512_constructor.bytes = sha512_bytes;
21 | sha512_constructor.hex = sha512_hex;
22 | sha512_constructor.base64 = sha512_base64;
23 |
24 | exports.SHA512 = sha512_constructor;
25 |
--------------------------------------------------------------------------------
/src/errors.js:
--------------------------------------------------------------------------------
1 | function IllegalStateError () { var err = Error.apply( this, arguments ); this.message = err.message, this.stack = err.stack; }
2 | IllegalStateError.prototype = Object.create( Error.prototype, { name: { value: 'IllegalStateError' } } );
3 |
4 | function IllegalArgumentError () { var err = Error.apply( this, arguments ); this.message = err.message, this.stack = err.stack; }
5 | IllegalArgumentError.prototype = Object.create( Error.prototype, { name: { value: 'IllegalArgumentError' } } );
6 |
7 | function SecurityError () { var err = Error.apply( this, arguments ); this.message = err.message, this.stack = err.stack; }
8 | SecurityError.prototype = Object.create( Error.prototype, { name: { value: 'SecurityError' } } );
9 |
--------------------------------------------------------------------------------
/src/rsa/exports-raw.js:
--------------------------------------------------------------------------------
1 | /**
2 | * RSA-RAW exports
3 | */
4 |
5 | function rsa_raw_encrypt_bytes ( data, key ) {
6 | if ( data === undefined ) throw new SyntaxError("data required");
7 | if ( key === undefined ) throw new SyntaxError("key required");
8 | return (new RSA_RAW({ key: key })).encrypt(data).result;
9 | }
10 |
11 | function rsa_raw_decrypt_bytes ( data, key ) {
12 | if ( data === undefined ) throw new SyntaxError("data required");
13 | if ( key === undefined ) throw new SyntaxError("key required");
14 | return (new RSA_RAW({ key: key })).decrypt(data).result;
15 | }
16 |
17 | RSA_RAW.encrypt = rsa_raw_encrypt_bytes;
18 | RSA_RAW.decrypt = rsa_raw_decrypt_bytes;
19 | RSA_RAW.sign = rsa_raw_decrypt_bytes;
20 | RSA_RAW.verify = rsa_raw_encrypt_bytes;
21 |
22 | exports.RSA_RAW = RSA_RAW;
23 |
--------------------------------------------------------------------------------
/src/rsa/exports-oaep-sha1.js:
--------------------------------------------------------------------------------
1 | /**
2 | * RSA-OAEP-SHA1 exports
3 | */
4 |
5 | function rsa_oaep_sha1_encrypt_bytes ( data, key, label ) {
6 | if ( data === undefined ) throw new SyntaxError("data required");
7 | if ( key === undefined ) throw new SyntaxError("key required");
8 | return (new RSA_OAEP({ hash: get_sha1_instance(), key: key, label: label })).encrypt(data).result;
9 | }
10 |
11 | function rsa_oaep_sha1_decrypt_bytes ( data, key, label ) {
12 | if ( data === undefined ) throw new SyntaxError("data required");
13 | if ( key === undefined ) throw new SyntaxError("key required");
14 | return (new RSA_OAEP({ hash: get_sha1_instance(), key: key, label: label })).decrypt(data).result;
15 | }
16 |
17 | exports.RSA_OAEP = RSA_OAEP;
18 |
19 | exports.RSA_OAEP_SHA1 = {
20 | encrypt: rsa_oaep_sha1_encrypt_bytes,
21 | decrypt: rsa_oaep_sha1_decrypt_bytes
22 | };
23 |
--------------------------------------------------------------------------------
/src/rsa/exports-oaep-sha256.js:
--------------------------------------------------------------------------------
1 | /**
2 | * RSA-OAEP-SHA256 exports
3 | */
4 |
5 | function rsa_oaep_sha256_encrypt_bytes ( data, key, label ) {
6 | if ( data === undefined ) throw new SyntaxError("data required");
7 | if ( key === undefined ) throw new SyntaxError("key required");
8 | return (new RSA_OAEP({ hash: get_sha256_instance(), key: key, label: label })).encrypt(data).result;
9 | }
10 |
11 | function rsa_oaep_sha256_decrypt_bytes ( data, key, label ) {
12 | if ( data === undefined ) throw new SyntaxError("data required");
13 | if ( key === undefined ) throw new SyntaxError("key required");
14 | return (new RSA_OAEP({ hash: get_sha256_instance(), key: key, label: label })).decrypt(data).result;
15 | }
16 |
17 | exports.RSA_OAEP = RSA_OAEP;
18 |
19 | exports.RSA_OAEP_SHA256 = {
20 | encrypt: rsa_oaep_sha256_encrypt_bytes,
21 | decrypt: rsa_oaep_sha256_decrypt_bytes
22 | };
23 |
--------------------------------------------------------------------------------
/src/rsa/exports-oaep-sha512.js:
--------------------------------------------------------------------------------
1 | /**
2 | * RSA-OAEP-SHA512 exports
3 | */
4 |
5 | function rsa_oaep_sha512_encrypt_bytes ( data, key, label ) {
6 | if ( data === undefined ) throw new SyntaxError("data required");
7 | if ( key === undefined ) throw new SyntaxError("key required");
8 | return (new RSA_OAEP({ hash: get_sha512_instance(), key: key, label: label })).encrypt(data).result;
9 | }
10 |
11 | function rsa_oaep_sha512_decrypt_bytes ( data, key, label ) {
12 | if ( data === undefined ) throw new SyntaxError("data required");
13 | if ( key === undefined ) throw new SyntaxError("key required");
14 | return (new RSA_OAEP({ hash: get_sha512_instance(), key: key, label: label })).decrypt(data).result;
15 | }
16 |
17 | exports.RSA_OAEP = RSA_OAEP;
18 |
19 | exports.RSA_OAEP_SHA512 = {
20 | encrypt: rsa_oaep_sha512_encrypt_bytes,
21 | decrypt: rsa_oaep_sha512_decrypt_bytes
22 | };
23 |
--------------------------------------------------------------------------------
/src/hash/sha1/sha1.js:
--------------------------------------------------------------------------------
1 | var _sha1_block_size = 64,
2 | _sha1_hash_size = 20;
3 |
4 | function sha1_constructor ( options ) {
5 | options = options || {};
6 |
7 | this.heap = _heap_init( Uint8Array, options );
8 | this.asm = options.asm || sha1_asm( global, null, this.heap.buffer );
9 |
10 | this.BLOCK_SIZE = _sha1_block_size;
11 | this.HASH_SIZE = _sha1_hash_size;
12 |
13 | this.reset();
14 | }
15 |
16 | sha1_constructor.BLOCK_SIZE = _sha1_block_size;
17 | sha1_constructor.HASH_SIZE = _sha1_hash_size;
18 | var sha1_prototype = sha1_constructor.prototype;
19 | sha1_prototype.reset = hash_reset;
20 | sha1_prototype.process = hash_process;
21 | sha1_prototype.finish = hash_finish;
22 |
23 | var sha1_instance = null;
24 |
25 | function get_sha1_instance () {
26 | if ( sha1_instance === null ) sha1_instance = new sha1_constructor( { heapSize: 0x100000 } );
27 | return sha1_instance;
28 | }
29 |
--------------------------------------------------------------------------------
/src/hmac/exports-hmac-sha256.js:
--------------------------------------------------------------------------------
1 | /**
2 | * HMAC-SHA256 exports
3 | */
4 |
5 | function hmac_sha256_bytes ( data, password ) {
6 | if ( data === undefined ) throw new SyntaxError("data required");
7 | if ( password === undefined ) throw new SyntaxError("password required");
8 | return get_hmac_sha256_instance().reset( { password: password } ).process(data).finish().result;
9 | }
10 |
11 | function hmac_sha256_hex ( data, password ) {
12 | var result = hmac_sha256_bytes( data, password );
13 | return bytes_to_hex(result);
14 | }
15 |
16 | function hmac_sha256_base64 ( data, password ) {
17 | var result = hmac_sha256_bytes( data, password );
18 | return bytes_to_base64(result);
19 | }
20 |
21 | hmac_sha256_constructor.bytes = hmac_sha256_bytes;
22 | hmac_sha256_constructor.hex = hmac_sha256_hex;
23 | hmac_sha256_constructor.base64 = hmac_sha256_base64;
24 |
25 | exports.HMAC_SHA256 = hmac_sha256_constructor;
26 |
--------------------------------------------------------------------------------
/src/hmac/exports-hmac-sha512.js:
--------------------------------------------------------------------------------
1 | /**
2 | * HMAC-SHA512 exports
3 | */
4 |
5 | function hmac_sha512_bytes ( data, password ) {
6 | if ( data === undefined ) throw new SyntaxError("data required");
7 | if ( password === undefined ) throw new SyntaxError("password required");
8 | return get_hmac_sha512_instance().reset( { password: password } ).process(data).finish().result;
9 | }
10 |
11 | function hmac_sha512_hex ( data, password ) {
12 | var result = hmac_sha512_bytes( data, password );
13 | return bytes_to_hex(result);
14 | }
15 |
16 | function hmac_sha512_base64 ( data, password ) {
17 | var result = hmac_sha512_bytes( data, password );
18 | return bytes_to_base64(result);
19 | }
20 |
21 | hmac_sha512_constructor.bytes = hmac_sha512_bytes;
22 | hmac_sha512_constructor.hex = hmac_sha512_hex;
23 | hmac_sha512_constructor.base64 = hmac_sha512_base64;
24 |
25 | exports.HMAC_SHA512 = hmac_sha512_constructor;
26 |
--------------------------------------------------------------------------------
/src/hmac/exports-hmac-sha1.js:
--------------------------------------------------------------------------------
1 | /**
2 | * HMAC-SHA1 exports
3 | */
4 |
5 | function hmac_sha1_bytes ( data, password ) {
6 | if ( data === undefined ) throw new SyntaxError("data required");
7 | if ( password === undefined ) throw new SyntaxError("password required");
8 | return get_hmac_sha1_instance().reset( { password: password } ).process(data).finish().result;
9 | }
10 |
11 | function hmac_sha1_hex ( data, password ) {
12 | var result = hmac_sha1_bytes( data, password );
13 | return bytes_to_hex(result);
14 | }
15 |
16 | function hmac_sha1_base64 ( data, password ) {
17 | var result = hmac_sha1_bytes( data, password );
18 | return bytes_to_base64(result);
19 | }
20 |
21 | exports.HMAC = hmac_constructor;
22 |
23 | hmac_sha1_constructor.bytes = hmac_sha1_bytes;
24 | hmac_sha1_constructor.hex = hmac_sha1_hex;
25 | hmac_sha1_constructor.base64 = hmac_sha1_base64;
26 |
27 | exports.HMAC_SHA1 = hmac_sha1_constructor;
28 |
--------------------------------------------------------------------------------
/src/hash/sha256/sha256.js:
--------------------------------------------------------------------------------
1 | var _sha256_block_size = 64,
2 | _sha256_hash_size = 32;
3 |
4 | function sha256_constructor ( options ) {
5 | options = options || {};
6 |
7 | this.heap = _heap_init( Uint8Array, options );
8 | this.asm = options.asm || sha256_asm( global, null, this.heap.buffer );
9 |
10 | this.BLOCK_SIZE = _sha256_block_size;
11 | this.HASH_SIZE = _sha256_hash_size;
12 |
13 | this.reset();
14 | }
15 |
16 | sha256_constructor.BLOCK_SIZE = _sha256_block_size;
17 | sha256_constructor.HASH_SIZE = _sha256_hash_size;
18 | var sha256_prototype = sha256_constructor.prototype;
19 | sha256_prototype.reset = hash_reset;
20 | sha256_prototype.process = hash_process;
21 | sha256_prototype.finish = hash_finish;
22 |
23 | var sha256_instance = null;
24 |
25 | function get_sha256_instance () {
26 | if ( sha256_instance === null ) sha256_instance = new sha256_constructor( { heapSize: 0x100000 } );
27 | return sha256_instance;
28 | }
29 |
--------------------------------------------------------------------------------
/src/hash/sha512/sha512.js:
--------------------------------------------------------------------------------
1 | var _sha512_block_size = 128,
2 | _sha512_hash_size = 64;
3 |
4 | function sha512_constructor ( options ) {
5 | options = options || {};
6 |
7 | this.heap = _heap_init( Uint8Array, options );
8 | this.asm = options.asm || sha512_asm( global, null, this.heap.buffer );
9 |
10 | this.BLOCK_SIZE = _sha512_block_size;
11 | this.HASH_SIZE = _sha512_hash_size;
12 |
13 | this.reset();
14 | }
15 |
16 | sha512_constructor.BLOCK_SIZE = _sha512_block_size;
17 | sha512_constructor.HASH_SIZE = _sha512_hash_size;
18 | var sha512_prototype = sha512_constructor.prototype;
19 | sha512_prototype.reset = hash_reset;
20 | sha512_prototype.process = hash_process;
21 | sha512_prototype.finish = hash_finish;
22 |
23 | var sha512_instance = null;
24 |
25 | function get_sha512_instance () {
26 | if ( sha512_instance === null ) sha512_instance = new sha512_constructor( { heapSize: 0x100000 } );
27 | return sha512_instance;
28 | }
29 |
--------------------------------------------------------------------------------
/src/aes/cfb/exports.js:
--------------------------------------------------------------------------------
1 | /**
2 | * AES-CFB exports
3 | */
4 |
5 | function AES_CFB_encrypt_bytes ( data, key, iv ) {
6 | if ( data === undefined ) throw new SyntaxError("data required");
7 | if ( key === undefined ) throw new SyntaxError("key required");
8 | return get_AES_CFB_instance( { key: key, iv: iv } ).encrypt(data).result;
9 | }
10 |
11 | function AES_CFB_decrypt_bytes ( data, key, iv ) {
12 | if ( data === undefined ) throw new SyntaxError("data required");
13 | if ( key === undefined ) throw new SyntaxError("key required");
14 | return get_AES_CFB_instance( { key: key, iv: iv } ).decrypt(data).result;
15 | }
16 |
17 | exports.AES_CFB = createSimpleCipherInterface( AES_CFB );
18 | exports.AES_CFB.encrypt = AES_CFB_encrypt_bytes;
19 | exports.AES_CFB.decrypt = AES_CFB_decrypt_bytes;
20 |
21 | exports.AES_CFB.Encrypt = createProgressiveCipherInterface( AES_CFB_Encrypt );
22 | exports.AES_CFB.Decrypt = createProgressiveCipherInterface( AES_CFB_Decrypt );
23 |
24 |
--------------------------------------------------------------------------------
/src/aes/ecb/exports.js:
--------------------------------------------------------------------------------
1 | /**
2 | * AES-ECB exports
3 | */
4 |
5 | function AES_ECB_encrypt_bytes ( data, key, padding ) {
6 | if ( data === undefined ) throw new SyntaxError("data required");
7 | if ( key === undefined ) throw new SyntaxError("key required");
8 | return get_AES_ECB_instance( { key: key, padding: padding } ).encrypt(data).result;
9 | }
10 |
11 | function AES_ECB_decrypt_bytes ( data, key, padding ) {
12 | if ( data === undefined ) throw new SyntaxError("data required");
13 | if ( key === undefined ) throw new SyntaxError("key required");
14 | return get_AES_ECB_instance( { key: key, padding: padding } ).decrypt(data).result;
15 | }
16 |
17 | exports.AES_ECB = createSimpleCipherInterface( AES_ECB );
18 | exports.AES_ECB.encrypt = AES_ECB_encrypt_bytes;
19 | exports.AES_ECB.decrypt = AES_ECB_decrypt_bytes;
20 |
21 | exports.AES_ECB.Encrypt = createProgressiveCipherInterface( AES_ECB_Encrypt );
22 | exports.AES_ECB.Decrypt = createProgressiveCipherInterface( AES_ECB_Decrypt );
23 |
24 |
--------------------------------------------------------------------------------
/src/random/exports.js:
--------------------------------------------------------------------------------
1 | exports.random = Random_getNumber;
2 |
3 | exports.random.seed = Random_seed;
4 |
5 | Object.defineProperty( Random_getNumber, 'allowWeak', {
6 | get: function () { return _random_allow_weak; },
7 | set: function ( a ) { _random_allow_weak = a; }
8 | });
9 |
10 | Object.defineProperty( Random_getNumber, 'skipSystemRNGWarning', {
11 | get: function () { return _random_skip_system_rng_warning; },
12 | set: function ( w ) { _random_skip_system_rng_warning = w; }
13 | });
14 |
15 | exports.getRandomValues = Random_getValues;
16 |
17 | exports.getRandomValues.seed = Random_seed;
18 |
19 | Object.defineProperty( Random_getValues, 'allowWeak', {
20 | get: function () { return _random_allow_weak; },
21 | set: function ( a ) { _random_allow_weak = a; }
22 | });
23 |
24 | Object.defineProperty( Random_getValues, 'skipSystemRNGWarning', {
25 | get: function () { return _random_skip_system_rng_warning; },
26 | set: function ( w ) { _random_skip_system_rng_warning = w; }
27 | });
28 |
--------------------------------------------------------------------------------
/src/pbkdf2/exports-pbkdf2-hmac-sha1.js:
--------------------------------------------------------------------------------
1 | /**
2 | * PBKDF2-HMAC-SHA1 exports
3 | */
4 |
5 | function pbkdf2_hmac_sha1_bytes ( password, salt, iterations, dklen ) {
6 | if ( password === undefined ) throw new SyntaxError("password required");
7 | if ( salt === undefined ) throw new SyntaxError("salt required");
8 | return get_pbkdf2_hmac_sha1_instance().reset( { password: password } ).generate( salt, iterations, dklen ).result;
9 | }
10 |
11 | function pbkdf2_hmac_sha1_hex ( password, salt, iterations, dklen ) {
12 | var result = pbkdf2_hmac_sha1_bytes( password, salt, iterations, dklen );
13 | return bytes_to_hex(result);
14 | }
15 |
16 | function pbkdf2_hmac_sha1_base64 ( password, salt, iterations, dklen ) {
17 | var result = pbkdf2_hmac_sha1_bytes( password, salt, iterations, dklen );
18 | return bytes_to_base64(result);
19 | }
20 |
21 | exports.PBKDF2 =
22 | exports.PBKDF2_HMAC_SHA1 = {
23 | bytes: pbkdf2_hmac_sha1_bytes,
24 | hex: pbkdf2_hmac_sha1_hex,
25 | base64: pbkdf2_hmac_sha1_base64
26 | };
27 |
--------------------------------------------------------------------------------
/src/aes/cbc/exports.js:
--------------------------------------------------------------------------------
1 | /**
2 | * AES-CBC exports
3 | */
4 |
5 | function AES_CBC_encrypt_bytes ( data, key, padding, iv ) {
6 | if ( data === undefined ) throw new SyntaxError("data required");
7 | if ( key === undefined ) throw new SyntaxError("key required");
8 | return get_AES_CBC_instance( { key: key, padding: padding, iv: iv } ).encrypt(data).result;
9 | }
10 |
11 | function AES_CBC_decrypt_bytes ( data, key, padding, iv ) {
12 | if ( data === undefined ) throw new SyntaxError("data required");
13 | if ( key === undefined ) throw new SyntaxError("key required");
14 | return get_AES_CBC_instance( { key: key, padding: padding, iv: iv } ).decrypt(data).result;
15 | }
16 |
17 | exports.AES_CBC = createSimpleCipherInterface( AES_CBC );
18 | exports.AES_CBC.encrypt = AES_CBC_encrypt_bytes;
19 | exports.AES_CBC.decrypt = AES_CBC_decrypt_bytes;
20 |
21 | exports.AES_CBC.Encrypt = createProgressiveCipherInterface( AES_CBC_Encrypt );
22 | exports.AES_CBC.Decrypt = createProgressiveCipherInterface( AES_CBC_Decrypt );
23 |
24 |
--------------------------------------------------------------------------------
/src/pbkdf2/exports-pbkdf2-hmac-sha256.js:
--------------------------------------------------------------------------------
1 | /**
2 | * PBKDF2-HMAC-SHA256 exports
3 | */
4 |
5 | function pbkdf2_hmac_sha256_bytes ( password, salt, iterations, dklen ) {
6 | if ( password === undefined ) throw new SyntaxError("password required");
7 | if ( salt === undefined ) throw new SyntaxError("salt required");
8 | return get_pbkdf2_hmac_sha256_instance().reset( { password: password } ).generate( salt, iterations, dklen ).result;
9 | }
10 |
11 | function pbkdf2_hmac_sha256_hex ( password, salt, iterations, dklen ) {
12 | var result = pbkdf2_hmac_sha256_bytes( password, salt, iterations, dklen );
13 | return bytes_to_hex(result);
14 | }
15 |
16 | function pbkdf2_hmac_sha256_base64 ( password, salt, iterations, dklen ) {
17 | var result = pbkdf2_hmac_sha256_bytes( password, salt, iterations, dklen );
18 | return bytes_to_base64(result);
19 | }
20 |
21 | exports.PBKDF2_HMAC_SHA256 = {
22 | bytes: pbkdf2_hmac_sha256_bytes,
23 | hex: pbkdf2_hmac_sha256_hex,
24 | base64: pbkdf2_hmac_sha256_base64
25 | };
26 |
--------------------------------------------------------------------------------
/src/pbkdf2/exports-pbkdf2-hmac-sha512.js:
--------------------------------------------------------------------------------
1 | /**
2 | * PBKDF2-HMAC-SHA512 exports
3 | */
4 |
5 | function pbkdf2_hmac_sha512_bytes ( password, salt, iterations, dklen ) {
6 | if ( password === undefined ) throw new SyntaxError("password required");
7 | if ( salt === undefined ) throw new SyntaxError("salt required");
8 | return get_pbkdf2_hmac_sha512_instance().reset( { password: password } ).generate( salt, iterations, dklen ).result;
9 | }
10 |
11 | function pbkdf2_hmac_sha512_hex ( password, salt, iterations, dklen ) {
12 | var result = pbkdf2_hmac_sha512_bytes( password, salt, iterations, dklen );
13 | return bytes_to_hex(result);
14 | }
15 |
16 | function pbkdf2_hmac_sha512_base64 ( password, salt, iterations, dklen ) {
17 | var result = pbkdf2_hmac_sha512_bytes( password, salt, iterations, dklen );
18 | return bytes_to_base64(result);
19 | }
20 |
21 | exports.PBKDF2_HMAC_SHA512 = {
22 | bytes: pbkdf2_hmac_sha512_bytes,
23 | hex: pbkdf2_hmac_sha512_hex,
24 | base64: pbkdf2_hmac_sha512_base64
25 | };
26 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "asmcrypto.js",
3 | "description": "Asm.js implementation of WebCrypto API",
4 | "homepage": "https://github.com/vibornoff/asmcrypto.js",
5 | "main": "asmcrypto.js",
6 | "version": "0.0.3",
7 | "maintainers": [{
8 | "name": "Artem S Vybornov",
9 | "email": "vybornov@gmail.com",
10 | "web": "http://github.com/vibornoff"
11 | }],
12 | "repository": {
13 | "type": "git",
14 | "url": "https://github.com/vibornoff/asmcrypto.js.git"
15 | },
16 | "devDependencies": {
17 | "uglify-js": "vibornoff/UglifyJS2",
18 | "grunt": "~0.4.2",
19 | "grunt-cli": "~0.1",
20 | "grunt-contrib-uglify": "~0.2.2",
21 | "grunt-contrib-qunit": "~0.4.0",
22 | "grunt-contrib-connect": "~0.7.1",
23 | "grunt-contrib-watch": "~0.2.0",
24 | "grunt-saucelabs": "~8.0.0",
25 | "grunt-contrib-clean": "~0.4.0"
26 | },
27 | "scripts": {
28 | "prepublish": "grunt",
29 | "test": "grunt test"
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/rsa/exports-pss-sha1.js:
--------------------------------------------------------------------------------
1 | /**
2 | * RSA-PSS-SHA1 exports
3 | */
4 |
5 | function rsa_pss_sha1_sign_bytes ( data, key, slen ) {
6 | if ( data === undefined ) throw new SyntaxError("data required");
7 | if ( key === undefined ) throw new SyntaxError("key required");
8 | return (new RSA_PSS({ hash: get_sha1_instance(), key: key, saltLength: slen })).sign(data).result;
9 | }
10 |
11 | function rsa_pss_sha1_verify_bytes ( signature, data, key, slen ) {
12 | if ( signature === undefined ) throw new SyntaxError("signature required");
13 | if ( data === undefined ) throw new SyntaxError("data required");
14 | if ( key === undefined ) throw new SyntaxError("key required");
15 | try {
16 | (new RSA_PSS({ hash: get_sha1_instance(), key: key, saltLength: slen })).verify(signature, data);
17 | return true;
18 | }
19 | catch ( e ) {
20 | if ( !( e instanceof SecurityError ) )
21 | throw e;
22 | }
23 | return false;
24 | }
25 |
26 | exports.RSA_PSS = RSA_PSS;
27 |
28 | exports.RSA_PSS_SHA1 = {
29 | sign: rsa_pss_sha1_sign_bytes,
30 | verify: rsa_pss_sha1_verify_bytes
31 | };
32 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2013 Artem S Vybornov
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy of
6 | this software and associated documentation files (the "Software"), to deal in
7 | the Software without restriction, including without limitation the rights to
8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9 | the Software, and to permit persons to whom the Software is furnished to do so,
10 | subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 |
--------------------------------------------------------------------------------
/src/aes/ctr/ctr.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Counter Mode (CTR)
3 | */
4 |
5 | function AES_CTR ( options ) {
6 | this.iv = null;
7 |
8 | AES.call( this, options );
9 |
10 | this.mode = 'CTR';
11 | }
12 |
13 | function AES_CTR_Crypt ( options ) {
14 | AES_CTR.call( this, options );
15 | }
16 |
17 | var AES_CTR_prototype = AES_CTR.prototype;
18 | AES_CTR_prototype.reset = AES_reset;
19 | AES_CTR_prototype.encrypt = AES_Encrypt_finish;
20 | AES_CTR_prototype.decrypt = AES_Encrypt_finish;
21 |
22 | var AES_CTR_Crypt_prototype = AES_CTR_Crypt.prototype;
23 | AES_CTR_Crypt_prototype.reset = AES_reset;
24 | AES_CTR_Crypt_prototype.process = AES_Encrypt_process;
25 | AES_CTR_Crypt_prototype.finish = AES_Encrypt_finish;
26 |
27 | var get_AES_CTR_instance = function ()
28 | {
29 | var _instance = null;
30 |
31 | return function ( options ) {
32 | if ( _instance ) return _instance.reset(options);
33 |
34 | // options = options || {};
35 | // options.heap = options.heap || _aes_heap_instance;
36 | // options.asm = options.asm || _aes_asm_instance;
37 |
38 | return _instance = new AES_CTR(options);
39 | };
40 | }();
41 |
--------------------------------------------------------------------------------
/src/aes/exports-gcm.js:
--------------------------------------------------------------------------------
1 | /**
2 | * AES-GCM exports
3 | */
4 |
5 | var gcm_aes_instance = new gcm_aes_constructor( { heap: _aes_heap_instance, asm: _aes_asm_instance } );
6 |
7 | function gcm_aes_encrypt_bytes ( data, key, iv, adata, tagSize ) {
8 | if ( data === undefined ) throw new SyntaxError("data required");
9 | if ( key === undefined ) throw new SyntaxError("key required");
10 | if ( iv === undefined ) throw new SyntaxError("iv required");
11 | return gcm_aes_instance.reset( { key: key, iv: iv, adata: adata, tagSize: tagSize } ).encrypt(data).result;
12 | }
13 |
14 | function gcm_aes_decrypt_bytes ( data, key, iv, adata, tagSize ) {
15 | if ( data === undefined ) throw new SyntaxError("data required");
16 | if ( key === undefined ) throw new SyntaxError("key required");
17 | if ( iv === undefined ) throw new SyntaxError("iv required");
18 | return gcm_aes_instance.reset( { key: key, iv: iv, adata: adata, tagSize: tagSize } ).decrypt(data).result;
19 | }
20 |
21 | gcm_aes_constructor.encrypt = gcm_aes_encrypt_bytes;
22 | gcm_aes_constructor.decrypt = gcm_aes_decrypt_bytes;
23 |
24 | exports.AES_GCM = gcm_aes_constructor;
25 |
--------------------------------------------------------------------------------
/src/rsa/exports-pss-sha256.js:
--------------------------------------------------------------------------------
1 | /**
2 | * RSA-PSS-SHA256 exports
3 | */
4 |
5 | function rsa_pss_sha256_sign_bytes ( data, key, slen ) {
6 | if ( data === undefined ) throw new SyntaxError("data required");
7 | if ( key === undefined ) throw new SyntaxError("key required");
8 | return (new RSA_PSS({ hash: get_sha256_instance(), key: key, saltLength: slen })).sign(data).result;
9 | }
10 |
11 | function rsa_pss_sha256_verify_bytes ( signature, data, key, slen ) {
12 | if ( signature === undefined ) throw new SyntaxError("signature required");
13 | if ( data === undefined ) throw new SyntaxError("data required");
14 | if ( key === undefined ) throw new SyntaxError("key required");
15 | try {
16 | (new RSA_PSS({ hash: get_sha256_instance(), key: key, saltLength: slen })).verify(signature, data);
17 | return true;
18 | }
19 | catch ( e ) {
20 | if ( !( e instanceof SecurityError ) )
21 | throw e;
22 | }
23 | return false;
24 | }
25 |
26 | exports.RSA_PSS = RSA_PSS;
27 |
28 | exports.RSA_PSS_SHA256 = {
29 | sign: rsa_pss_sha256_sign_bytes,
30 | verify: rsa_pss_sha256_verify_bytes
31 | };
32 |
--------------------------------------------------------------------------------
/src/rsa/exports-pss-sha512.js:
--------------------------------------------------------------------------------
1 | /**
2 | * RSA-PSS-SHA512 exports
3 | */
4 |
5 | function rsa_pss_sha512_sign_bytes ( data, key, slen ) {
6 | if ( data === undefined ) throw new SyntaxError("data required");
7 | if ( key === undefined ) throw new SyntaxError("key required");
8 | return (new RSA_PSS({ hash: get_sha512_instance(), key: key, saltLength: slen })).sign(data).result;
9 | }
10 |
11 | function rsa_pss_sha512_verify_bytes ( signature, data, key, slen ) {
12 | if ( signature === undefined ) throw new SyntaxError("signature required");
13 | if ( data === undefined ) throw new SyntaxError("data required");
14 | if ( key === undefined ) throw new SyntaxError("key required");
15 | try {
16 | (new RSA_PSS({ hash: get_sha512_instance(), key: key, saltLength: slen })).verify(signature, data);
17 | return true;
18 | }
19 | catch ( e ) {
20 | if ( !( e instanceof SecurityError ) )
21 | throw e;
22 | }
23 | return false;
24 | }
25 |
26 | exports.RSA_PSS = RSA_PSS;
27 |
28 | exports.RSA_PSS_SHA512 = {
29 | sign: rsa_pss_sha512_sign_bytes,
30 | verify: rsa_pss_sha512_verify_bytes
31 | };
32 |
--------------------------------------------------------------------------------
/src/aes/exports-ccm.js:
--------------------------------------------------------------------------------
1 | /**
2 | * AES-CCM exports
3 | */
4 |
5 | var ccm_aes_instance = new ccm_aes_constructor( { heap: _aes_heap_instance, asm: _aes_asm_instance } );
6 |
7 | function ccm_aes_encrypt_bytes ( data, key, nonce, adata, tagSize ) {
8 | if ( data === undefined ) throw new SyntaxError("data required");
9 | if ( key === undefined ) throw new SyntaxError("key required");
10 | if ( nonce === undefined ) throw new SyntaxError("nonce required");
11 | var dataLength = data.length || 0;
12 | return ccm_aes_instance.reset( { key: key, nonce: nonce, adata: adata, tagSize: tagSize, dataLength: dataLength } ).encrypt(data).result;
13 | }
14 |
15 | function ccm_aes_decrypt_bytes ( data, key, nonce, adata, tagSize ) {
16 | if ( data === undefined ) throw new SyntaxError("data required");
17 | if ( key === undefined ) throw new SyntaxError("key required");
18 | if ( nonce === undefined ) throw new SyntaxError("nonce required");
19 | var dataLength = data.length || 0;
20 | tagSize = tagSize || _aes_block_size;
21 | return ccm_aes_instance.reset( { key: key, nonce: nonce, adata: adata, tagSize: tagSize, dataLength: dataLength-tagSize } ).decrypt(data).result;
22 | }
23 |
24 | ccm_aes_constructor.encrypt = ccm_aes_encrypt_bytes;
25 | ccm_aes_constructor.decrypt = ccm_aes_decrypt_bytes;
26 |
27 | exports.AES_CCM = ccm_aes_constructor;
28 |
--------------------------------------------------------------------------------
/src/aes/cfb/cfb.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Cipher Feedback Mode (CFB)
3 | */
4 |
5 | function AES_CFB ( options ) {
6 | this.iv = null;
7 |
8 | AES.call( this, options );
9 |
10 | this.mode = 'CFB';
11 | }
12 |
13 | var AES_CFB_prototype = AES_CFB.prototype;
14 | AES_CFB_prototype.reset = AES_reset;
15 | AES_CFB_prototype.encrypt = AES_Encrypt_finish;
16 | AES_CFB_prototype.decrypt = AES_Decrypt_finish;
17 |
18 | function AES_CFB_Encrypt ( options ) {
19 | AES_CFB.call( this, options );
20 | }
21 |
22 | var AES_CFB_Encrypt_prototype = AES_CFB_Encrypt.prototype;
23 | AES_CFB_Encrypt_prototype.reset = AES_reset;
24 | AES_CFB_Encrypt_prototype.process = AES_Encrypt_process;
25 | AES_CFB_Encrypt_prototype.finish = AES_Encrypt_finish;
26 |
27 | function AES_CFB_Decrypt ( options ) {
28 | AES_CFB.call( this, options );
29 | }
30 |
31 | var AES_CFB_Decrypt_prototype = AES_CFB_Decrypt.prototype;
32 | AES_CFB_Decrypt_prototype.reset = AES_reset;
33 | AES_CFB_Decrypt_prototype.process = AES_Decrypt_process;
34 | AES_CFB_Decrypt_prototype.finish = AES_Decrypt_finish;
35 |
36 | var get_AES_CFB_instance = function ()
37 | {
38 | var _instance = null;
39 |
40 | return function ( options ) {
41 | if ( _instance ) return _instance.reset(options);
42 |
43 | // options = options || {};
44 | // options.heap = options.heap || _aes_heap_instance;
45 | // options.asm = options.asm || _aes_asm_instance;
46 |
47 | return _instance = new AES_CFB(options);
48 | };
49 | }();
50 |
--------------------------------------------------------------------------------
/src/aes/ecb/ecb.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Electronic Code Book Mode (ECB)
3 | */
4 |
5 | function AES_ECB ( options ) {
6 | this.padding = true;
7 |
8 | AES.call( this, options );
9 |
10 | this.mode = 'ECB';
11 | }
12 |
13 | var AES_ECB_prototype = AES_ECB.prototype;
14 | AES_ECB_prototype.reset = AES_reset;
15 | AES_ECB_prototype.encrypt = AES_Encrypt_finish;
16 | AES_ECB_prototype.decrypt = AES_Decrypt_finish;
17 |
18 | function AES_ECB_Encrypt ( options ) {
19 | AES_ECB.call( this, options );
20 | }
21 |
22 | var AES_ECB_Encrypt_prototype = AES_ECB_Encrypt.prototype;
23 | AES_ECB_Encrypt_prototype.reset = AES_reset;
24 | AES_ECB_Encrypt_prototype.process = AES_Encrypt_process;
25 | AES_ECB_Encrypt_prototype.finish = AES_Encrypt_finish;
26 |
27 | function AES_ECB_Decrypt ( options ) {
28 | AES_ECB.call( this, options );
29 | }
30 |
31 | var AES_ECB_Decrypt_prototype = AES_ECB_Decrypt.prototype;
32 | AES_ECB_Decrypt_prototype.reset = AES_reset;
33 | AES_ECB_Decrypt_prototype.process = AES_Decrypt_process;
34 | AES_ECB_Decrypt_prototype.finish = AES_Decrypt_finish;
35 |
36 | var get_AES_ECB_instance = function ()
37 | {
38 | var _instance = null;
39 |
40 | return function ( options ) {
41 | if ( _instance ) return _instance.reset(options);
42 |
43 | // options = options || {};
44 | // options.heap = options.heap || _aes_heap_instance;
45 | // options.asm = options.asm || _aes_asm_instance;
46 |
47 | return _instance = new AES_ECB(options);
48 | };
49 | }();
50 |
--------------------------------------------------------------------------------
/src/aes/cbc/cbc.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Cipher Block Chaining Mode (CBC)
3 | */
4 |
5 | function AES_CBC ( options ) {
6 | this.padding = true;
7 | this.iv = null;
8 |
9 | AES.call( this, options );
10 |
11 | this.mode = 'CBC';
12 | }
13 |
14 | var AES_CBC_prototype = AES_CBC.prototype;
15 | AES_CBC_prototype.reset = AES_reset;
16 | AES_CBC_prototype.encrypt = AES_Encrypt_finish;
17 | AES_CBC_prototype.decrypt = AES_Decrypt_finish;
18 |
19 | function AES_CBC_Encrypt ( options ) {
20 | AES_CBC.call( this, options );
21 | }
22 |
23 | var AES_CBC_Encrypt_prototype = AES_CBC_Encrypt.prototype;
24 | AES_CBC_Encrypt_prototype.reset = AES_reset;
25 | AES_CBC_Encrypt_prototype.process = AES_Encrypt_process;
26 | AES_CBC_Encrypt_prototype.finish = AES_Encrypt_finish;
27 |
28 | function AES_CBC_Decrypt ( options ) {
29 | AES_CBC.call( this, options );
30 | }
31 |
32 | var AES_CBC_Decrypt_prototype = AES_CBC_Decrypt.prototype;
33 | AES_CBC_Decrypt_prototype.reset = AES_reset;
34 | AES_CBC_Decrypt_prototype.process = AES_Decrypt_process;
35 | AES_CBC_Decrypt_prototype.finish = AES_Decrypt_finish;
36 |
37 | var get_AES_CBC_instance = function ()
38 | {
39 | var _instance = null;
40 |
41 | return function ( options ) {
42 | if ( _instance ) return _instance.reset(options);
43 |
44 | // options = options || {};
45 | // options.heap = options.heap || _aes_heap_instance;
46 | // options.asm = options.asm || _aes_asm_instance;
47 |
48 | return _instance = new AES_CBC(options);
49 | };
50 | }();
51 |
--------------------------------------------------------------------------------
/src/hash/hash.js:
--------------------------------------------------------------------------------
1 | function hash_reset () {
2 | this.result = null;
3 | this.pos = 0;
4 | this.len = 0;
5 |
6 | this.asm.reset();
7 |
8 | return this;
9 | }
10 |
11 | function hash_process ( data ) {
12 | if ( this.result !== null )
13 | throw new IllegalStateError("state must be reset before processing new data");
14 |
15 | if ( is_string(data) )
16 | data = string_to_bytes(data);
17 |
18 | if ( is_buffer(data) )
19 | data = new Uint8Array(data);
20 |
21 | if ( !is_bytes(data) )
22 | throw new TypeError("data isn't of expected type");
23 |
24 | var asm = this.asm,
25 | heap = this.heap,
26 | hpos = this.pos,
27 | hlen = this.len,
28 | dpos = 0,
29 | dlen = data.length,
30 | wlen = 0;
31 |
32 | while ( dlen > 0 ) {
33 | wlen = _heap_write( heap, hpos+hlen, data, dpos, dlen );
34 | hlen += wlen;
35 | dpos += wlen;
36 | dlen -= wlen;
37 |
38 | wlen = asm.process( hpos, hlen );
39 |
40 | hpos += wlen;
41 | hlen -= wlen;
42 |
43 | if ( !hlen ) hpos = 0;
44 | }
45 |
46 | this.pos = hpos;
47 | this.len = hlen;
48 |
49 | return this;
50 | }
51 |
52 | function hash_finish () {
53 | if ( this.result !== null )
54 | throw new IllegalStateError("state must be reset before processing new data");
55 |
56 | this.asm.finish( this.pos, this.len, 0 );
57 |
58 | this.result = new Uint8Array(this.HASH_SIZE);
59 | this.result.set( this.heap.subarray( 0, this.HASH_SIZE ) );
60 |
61 | this.pos = 0;
62 | this.len = 0;
63 |
64 | return this;
65 | }
66 |
--------------------------------------------------------------------------------
/src/pbkdf2/pbkdf2-hmac-sha1.js:
--------------------------------------------------------------------------------
1 | function pbkdf2_hmac_sha1_constructor ( options ) {
2 | options = options || {};
3 |
4 | if ( !( options.hmac instanceof hmac_sha1_constructor ) )
5 | options.hmac = get_hmac_sha1_instance();
6 |
7 | pbkdf2_constructor.call( this, options );
8 |
9 | return this;
10 | }
11 |
12 | function pbkdf2_hmac_sha1_generate ( salt, count, length ) {
13 | if ( this.result !== null )
14 | throw new IllegalStateError("state must be reset before processing new data");
15 |
16 | if ( !salt && !is_string(salt) )
17 | throw new IllegalArgumentError("bad 'salt' value");
18 |
19 | count = count || this.count;
20 | length = length || this.length;
21 |
22 | this.result = new Uint8Array(length);
23 |
24 | var blocks = Math.ceil( length / this.hmac.HMAC_SIZE );
25 |
26 | for ( var i = 1; i <= blocks; ++i ) {
27 | var j = ( i - 1 ) * this.hmac.HMAC_SIZE;
28 | var l = ( i < blocks ? 0 : length % this.hmac.HMAC_SIZE ) || this.hmac.HMAC_SIZE;
29 |
30 | this.hmac.reset().process(salt);
31 | this.hmac.hash.asm.pbkdf2_generate_block( this.hmac.hash.pos, this.hmac.hash.len, i, count, 0 );
32 |
33 | this.result.set( this.hmac.hash.heap.subarray( 0, l ), j );
34 | }
35 |
36 | return this;
37 | }
38 |
39 | var pbkdf2_hmac_sha1_prototype = pbkdf2_hmac_sha1_constructor.prototype;
40 | pbkdf2_hmac_sha1_prototype.reset = pbkdf2_reset;
41 | pbkdf2_hmac_sha1_prototype.generate = pbkdf2_hmac_sha1_generate;
42 |
43 | var pbkdf2_hmac_sha1_instance = null;
44 |
45 | function get_pbkdf2_hmac_sha1_instance () {
46 | if ( pbkdf2_hmac_sha1_instance === null ) pbkdf2_hmac_sha1_instance = new pbkdf2_hmac_sha1_constructor();
47 | return pbkdf2_hmac_sha1_instance;
48 | }
49 |
--------------------------------------------------------------------------------
/src/pbkdf2/pbkdf2-hmac-sha256.js:
--------------------------------------------------------------------------------
1 | function pbkdf2_hmac_sha256_constructor ( options ) {
2 | options = options || {};
3 |
4 | if ( !( options.hmac instanceof hmac_sha256_constructor ) )
5 | options.hmac = get_hmac_sha256_instance();
6 |
7 | pbkdf2_constructor.call( this, options );
8 |
9 | return this;
10 | }
11 |
12 | function pbkdf2_hmac_sha256_generate ( salt, count, length ) {
13 | if ( this.result !== null )
14 | throw new IllegalStateError("state must be reset before processing new data");
15 |
16 | if ( !salt && !is_string(salt) )
17 | throw new IllegalArgumentError("bad 'salt' value");
18 |
19 | count = count || this.count;
20 | length = length || this.length;
21 |
22 | this.result = new Uint8Array(length);
23 |
24 | var blocks = Math.ceil( length / this.hmac.HMAC_SIZE );
25 |
26 | for ( var i = 1; i <= blocks; ++i ) {
27 | var j = ( i - 1 ) * this.hmac.HMAC_SIZE;
28 | var l = ( i < blocks ? 0 : length % this.hmac.HMAC_SIZE ) || this.hmac.HMAC_SIZE;
29 |
30 | this.hmac.reset().process(salt);
31 | this.hmac.hash.asm.pbkdf2_generate_block( this.hmac.hash.pos, this.hmac.hash.len, i, count, 0 );
32 |
33 | this.result.set( this.hmac.hash.heap.subarray( 0, l ), j );
34 | }
35 |
36 | return this;
37 | }
38 |
39 | var pbkdf2_hmac_sha256_prototype = pbkdf2_hmac_sha256_constructor.prototype;
40 | pbkdf2_hmac_sha256_prototype.reset = pbkdf2_reset;
41 | pbkdf2_hmac_sha256_prototype.generate = pbkdf2_hmac_sha256_generate;
42 |
43 | var pbkdf2_hmac_sha256_instance = null;
44 |
45 | function get_pbkdf2_hmac_sha256_instance () {
46 | if ( pbkdf2_hmac_sha256_instance === null ) pbkdf2_hmac_sha256_instance = new pbkdf2_hmac_sha256_constructor();
47 | return pbkdf2_hmac_sha256_instance;
48 | }
49 |
--------------------------------------------------------------------------------
/src/pbkdf2/pbkdf2-hmac-sha512.js:
--------------------------------------------------------------------------------
1 | function pbkdf2_hmac_sha512_constructor ( options ) {
2 | options = options || {};
3 |
4 | if ( !( options.hmac instanceof hmac_sha512_constructor ) )
5 | options.hmac = get_hmac_sha512_instance();
6 |
7 | pbkdf2_constructor.call( this, options );
8 |
9 | return this;
10 | }
11 |
12 | function pbkdf2_hmac_sha512_generate ( salt, count, length ) {
13 | if ( this.result !== null )
14 | throw new IllegalStateError("state must be reset before processing new data");
15 |
16 | if ( !salt && !is_string(salt) )
17 | throw new IllegalArgumentError("bad 'salt' value");
18 |
19 | count = count || this.count;
20 | length = length || this.length;
21 |
22 | this.result = new Uint8Array(length);
23 |
24 | var blocks = Math.ceil( length / this.hmac.HMAC_SIZE );
25 |
26 | for ( var i = 1; i <= blocks; ++i ) {
27 | var j = ( i - 1 ) * this.hmac.HMAC_SIZE;
28 | var l = ( i < blocks ? 0 : length % this.hmac.HMAC_SIZE ) || this.hmac.HMAC_SIZE;
29 |
30 | this.hmac.reset().process(salt);
31 | this.hmac.hash.asm.pbkdf2_generate_block( this.hmac.hash.pos, this.hmac.hash.len, i, count, 0 );
32 |
33 | this.result.set( this.hmac.hash.heap.subarray( 0, l ), j );
34 | }
35 |
36 | return this;
37 | }
38 |
39 | var pbkdf2_hmac_sha512_prototype = pbkdf2_hmac_sha512_constructor.prototype;
40 | pbkdf2_hmac_sha512_prototype.reset = pbkdf2_reset;
41 | pbkdf2_hmac_sha512_prototype.generate = pbkdf2_hmac_sha512_generate;
42 |
43 | var pbkdf2_hmac_sha512_instance = null;
44 |
45 | function get_pbkdf2_hmac_sha512_instance () {
46 | if ( pbkdf2_hmac_sha512_instance === null ) pbkdf2_hmac_sha512_instance = new pbkdf2_hmac_sha512_constructor();
47 | return pbkdf2_hmac_sha512_instance;
48 | }
49 |
--------------------------------------------------------------------------------
/src/rsa/genkey.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Generate RSA key pair
3 | *
4 | * @param bitlen desired modulus length, default is 2048
5 | * @param e public exponent, default is 65537
6 | */
7 | function RSA_generateKey ( bitlen, e ) {
8 | bitlen = bitlen || 2048;
9 | e = e || 65537;
10 |
11 | if ( bitlen < 512 )
12 | throw new IllegalArgumentError("bit length is too small");
13 |
14 | if ( is_string(e) )
15 | e = string_to_bytes(e);
16 |
17 | if ( is_buffer(e) )
18 | e = new Uint8Array(e);
19 |
20 | if ( is_bytes(e) || is_number(e) || is_big_number(e) ) {
21 | e = new BigNumber(e);
22 | }
23 | else {
24 | throw new TypeError("unexpected exponent type");
25 | }
26 |
27 | if ( ( e.limbs[0] & 1 ) === 0 )
28 | throw new IllegalArgumentError("exponent must be an odd number");
29 |
30 | var m, e, d, p, q, p1, q1, dp, dq, u;
31 |
32 | p = BigNumber_randomProbablePrime(
33 | bitlen >> 1,
34 | function ( p ) {
35 | p1 = new BigNumber(p); p1.limbs[0] -= 1;
36 | return BigNumber_extGCD( p1, e ).gcd.valueOf() == 1;
37 | }
38 | );
39 |
40 | q = BigNumber_randomProbablePrime(
41 | bitlen - (bitlen >> 1),
42 | function ( q ) {
43 | m = new Modulus( p.multiply(q) );
44 | if ( !( m.limbs[ ( (bitlen + 31) >> 5 ) - 1 ] >>> ( (bitlen - 1) & 31) ) ) return false;
45 | q1 = new BigNumber(q); q1.limbs[0] -= 1;
46 | return BigNumber_extGCD( q1, e ).gcd.valueOf() == 1;
47 | }
48 | );
49 |
50 | d = new Modulus( p1.multiply(q1) ).inverse(e);
51 |
52 | dp = d.divide(p1).remainder,
53 | dq = d.divide(q1).remainder;
54 |
55 | p = new Modulus(p),
56 | q = new Modulus(q);
57 |
58 | var u = p.inverse(q);
59 |
60 | return [ m, e, d, p, q, dp, dq, u ];
61 | }
62 |
63 | RSA.generateKey = RSA_generateKey;
64 |
--------------------------------------------------------------------------------
/src/pbkdf2/pbkdf2.js:
--------------------------------------------------------------------------------
1 | function pbkdf2_constructor ( options ) {
2 | options = options || {};
3 |
4 | if ( !options.hmac )
5 | throw new SyntaxError("option 'hmac' is required");
6 |
7 | if ( !options.hmac.HMAC_SIZE )
8 | throw new SyntaxError("option 'hmac' supplied doesn't seem to be a valid HMAC function");
9 |
10 | this.hmac = options.hmac;
11 | this.count = options.count || 4096;
12 | this.length = options.length || this.hmac.HMAC_SIZE;
13 |
14 | this.result = null;
15 |
16 | var password = options.password;
17 | if ( password || is_string(password) )
18 | this.reset(options);
19 |
20 | return this;
21 | }
22 |
23 | function pbkdf2_reset ( options ) {
24 | this.result = null;
25 |
26 | this.hmac.reset(options);
27 |
28 | return this;
29 | }
30 |
31 | function pbkdf2_generate ( salt, count, length ) {
32 | if ( this.result !== null )
33 | throw new IllegalStateError("state must be reset before processing new data");
34 |
35 | if ( !salt && !is_string(salt) )
36 | throw new IllegalArgumentError("bad 'salt' value");
37 |
38 | count = count || this.count;
39 | length = length || this.length;
40 |
41 | this.result = new Uint8Array(length);
42 |
43 | var blocks = Math.ceil( length / this.hmac.HMAC_SIZE );
44 |
45 | for ( var i = 1; i <= blocks; ++i ) {
46 | var j = ( i - 1 ) * this.hmac.HMAC_SIZE;
47 | var l = ( i < blocks ? 0 : length % this.hmac.HMAC_SIZE ) || this.hmac.HMAC_SIZE;
48 | 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 );
49 | this.result.set( tmp.subarray( 0, l ), j );
50 | for ( var k = 1; k < count; ++k ) {
51 | tmp = new Uint8Array( this.hmac.reset().process(tmp).finish().result );
52 | for ( var r = 0; r < l; ++r ) this.result[j+r] ^= tmp[r];
53 | }
54 | }
55 |
56 | return this;
57 | }
58 |
59 | // methods
60 | var pbkdf2_prototype = pbkdf2_constructor.prototype;
61 | pbkdf2_prototype.reset = pbkdf2_reset;
62 | pbkdf2_prototype.generate = pbkdf2_generate;
63 |
--------------------------------------------------------------------------------
/test/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | asmCrypto test suite
6 |
7 |
8 |
9 |
26 |
27 |
56 |
57 |
58 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
--------------------------------------------------------------------------------
/src/bignum/extgcd.js:
--------------------------------------------------------------------------------
1 | function Number_extGCD ( a, b ) {
2 | var sa = ( a < 0 ) ? -1 : 1,
3 | sb = ( b < 0 ) ? -1 : 1,
4 | xi = 1, xj = 0,
5 | yi = 0, yj = 1,
6 | r, q, t, a_cmp_b;
7 |
8 | a *= sa;
9 | b *= sb;
10 |
11 | a_cmp_b = ( a < b );
12 | if ( a_cmp_b ) {
13 | t = a; a = b, b = t;
14 | t = sa; sa = sb; sb = t;
15 | }
16 |
17 | q = Math.floor( a / b ), r = a - q*b;
18 | while ( r ) {
19 | t = xi - q*xj, xi = xj, xj = t;
20 | t = yi - q*yj, yi = yj, yj = t;
21 | a = b, b = r;
22 |
23 | q = Math.floor( a / b ), r = a - q*b;
24 | }
25 |
26 | xj *= sa;
27 | yj *= sb;
28 |
29 | if ( a_cmp_b ) {
30 | t = xj; xj = yj, yj = t;
31 | }
32 |
33 | return {
34 | gcd: b,
35 | x: xj,
36 | y: yj
37 | };
38 | }
39 |
40 | function BigNumber_extGCD ( a, b ) {
41 | if ( !is_big_number(a) )
42 | a = new BigNumber(a);
43 |
44 | if ( !is_big_number(b) )
45 | b = new BigNumber(b);
46 |
47 | var sa = a.sign, sb = b.sign;
48 |
49 | if ( sa < 0 )
50 | a = a.negate();
51 |
52 | if ( sb < 0 )
53 | b = b.negate();
54 |
55 | var a_cmp_b = a.compare(b);
56 | if ( a_cmp_b < 0 ) {
57 | var t = a; a = b, b = t;
58 | t = sa; sa = sb; sb = t;
59 | }
60 |
61 | var xi = BigNumber_ONE, xj = BigNumber_ZERO, lx = b.bitLength,
62 | yi = BigNumber_ZERO, yj = BigNumber_ONE, ly = a.bitLength,
63 | z, r, q;
64 |
65 | z = a.divide(b);
66 | while ( (r = z.remainder) !== BigNumber_ZERO ) {
67 | q = z.quotient;
68 |
69 | z = xi.subtract( q.multiply(xj).clamp(lx) ).clamp(lx), xi = xj, xj = z;
70 | z = yi.subtract( q.multiply(yj).clamp(ly) ).clamp(ly), yi = yj, yj = z;
71 |
72 | a = b, b = r;
73 |
74 | z = a.divide(b);
75 | }
76 |
77 | if ( sa < 0 )
78 | xj = xj.negate();
79 |
80 | if ( sb < 0 )
81 | yj = yj.negate();
82 |
83 | if ( a_cmp_b < 0 ) {
84 | var t = xj; xj = yj, yj = t;
85 | }
86 |
87 | return {
88 | gcd: b,
89 | x: xj,
90 | y: yj
91 | };
92 | }
93 |
--------------------------------------------------------------------------------
/src/aes/exports.js:
--------------------------------------------------------------------------------
1 | // shared asm.js module and heap
2 | var _aes_heap_instance = new Uint8Array(0x100000),
3 | _aes_asm_instance = aes_asm( global, null, _aes_heap_instance.buffer );
4 |
5 | function createSimpleCipherInterface ( Constructor )
6 | {
7 | return function SimpleCipher ( options ) {
8 | var _instance = new Constructor(options);
9 |
10 | Object.defineProperties( this, {
11 | mode: {
12 | value: _instance.mode
13 | },
14 | encrypt: {
15 | value: function ( data, options ) {
16 | if ( options && options.key !== undefined ) throw new IllegalStateError("'key' option is forbidden on cipher instance");
17 | return _instance.reset(options).encrypt(data).result;
18 | }
19 | },
20 | decrypt: {
21 | value: function ( data, options ) {
22 | if ( options && options.key !== undefined ) throw new IllegalStateError("'key' option is forbidden on cipher instance");
23 | return _instance.reset(options).decrypt(data).result;
24 | }
25 | }
26 | });
27 | };
28 | }
29 |
30 | function createProgressiveCipherInterface ( Constructor )
31 | {
32 | return function ProgressiveCipher ( options ) {
33 | var _instance = new Constructor(options);
34 |
35 | if ( _instance.hasOwnProperty('padding') ) {
36 | Object.defineProperty( this, 'padding', {
37 | value: _instance.padding
38 | });
39 | }
40 |
41 | if ( _instance.hasOwnProperty('iv') ) {
42 | Object.defineProperty( this, 'iv', {
43 | value: _instance.iv
44 | });
45 | }
46 |
47 | Object.defineProperties( this, {
48 | mode: {
49 | value: _instance.mode
50 | },
51 | process: {
52 | value: function ( data ) {
53 | return _instance.process(data).result;
54 | }
55 | },
56 | finish: {
57 | value: function ( data ) {
58 | return _instance.finish(data).result;
59 | }
60 | }
61 | });
62 | };
63 | }
64 |
--------------------------------------------------------------------------------
/src/aes/aes.js:
--------------------------------------------------------------------------------
1 | var _aes_block_size = 16;
2 |
3 | function _aes_constructor ( options ) {
4 | options = options || {};
5 |
6 | this.BLOCK_SIZE = _aes_block_size;
7 |
8 | this.heap = _heap_init( Uint8Array, options );
9 | this.asm = options.asm || aes_asm( global, null, this.heap.buffer );
10 | this.pos = _aes_heap_start;
11 | this.len = 0;
12 |
13 | this.key = null;
14 | this.result = null;
15 |
16 | this.reset( options );
17 | }
18 |
19 | function _aes_reset ( options ) {
20 | options = options || {};
21 |
22 | this.result = null;
23 | this.pos = _aes_heap_start;
24 | this.len = 0;
25 |
26 | var asm = this.asm;
27 |
28 | var key = options.key;
29 | if ( key !== undefined ) {
30 | if ( is_buffer(key) || is_bytes(key) ) {
31 | key = new Uint8Array(key);
32 | }
33 | else if ( is_string(key) ) {
34 | key = string_to_bytes(key);
35 | }
36 | else {
37 | throw new TypeError("unexpected key type");
38 | }
39 |
40 | if ( key.length === 16 ) {
41 | asm.init_key_128( key[0], key[1], key[2], key[3], key[4], key[5], key[6], key[7], key[8], key[9], key[10], key[11], key[12], key[13], key[14], key[15]);
42 | }
43 | else if ( key.length === 24 ) {
44 | // TODO support of 192-bit keys
45 | throw new IllegalArgumentError("illegal key size");
46 | }
47 | else if ( key.length === 32 ) {
48 | asm.init_key_256( key[0], key[1], key[2], key[3], key[4], key[5], key[6], key[7], key[8], key[9], key[10], key[11], key[12], key[13], key[14], key[15], key[16], key[17], key[18], key[19], key[20], key[21], key[22], key[23], key[24], key[25], key[26], key[27], key[28], key[29], key[30], key[31]);
49 | }
50 | else {
51 | throw new IllegalArgumentError("illegal key size");
52 | }
53 |
54 | this.key = key;
55 | }
56 |
57 | return this;
58 | }
59 |
60 | function _aes_init_iv ( iv ) {
61 | var asm = this.asm;
62 |
63 | if ( iv !== undefined ) {
64 | if ( is_buffer(iv) || is_bytes(iv) ) {
65 | iv = new Uint8Array(iv);
66 | }
67 | else if ( is_string(iv) ) {
68 | iv = string_to_bytes(iv);
69 | }
70 | else {
71 | throw new TypeError("unexpected iv type");
72 | }
73 |
74 | if ( iv.length !== _aes_block_size )
75 | throw new IllegalArgumentError("illegal iv size");
76 |
77 | this.iv = iv;
78 | asm.init_state( iv[0], iv[1], iv[2], iv[3], iv[4], iv[5], iv[6], iv[7], iv[8], iv[9], iv[10], iv[11], iv[12], iv[13], iv[14], iv[15] );
79 | }
80 | else {
81 | this.iv = null;
82 | asm.init_state( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 );
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/src/utils.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | var FloatArray = global.Float64Array || global.Float32Array; // make PhantomJS happy
4 |
5 | function string_to_bytes ( str ) {
6 | var len = str.length,
7 | arr = new Uint8Array( len );
8 | for ( var i = 0; i < len; i++ ) {
9 | var c = str.charCodeAt(i);
10 | if ( c >>> 8 ) throw new Error("Wide characters are not allowed");
11 | arr[i] = c;
12 | }
13 | return arr;
14 | }
15 |
16 | function hex_to_bytes ( str ) {
17 | var arr = [],
18 | len = str.length,
19 | i;
20 | if ( len & 1 ) {
21 | str = '0'+str;
22 | len++;
23 | }
24 | for ( i=0; i>> 1;
57 | a |= a >>> 2;
58 | a |= a >>> 4;
59 | a |= a >>> 8;
60 | a |= a >>> 16;
61 | a += 1;
62 | return a;
63 | }
64 |
65 | function is_number ( a ) {
66 | return ( typeof a === 'number' );
67 | }
68 |
69 | function is_string ( a ) {
70 | return ( typeof a === 'string' );
71 | }
72 |
73 | function is_buffer ( a ) {
74 | return ( a instanceof ArrayBuffer );
75 | }
76 |
77 | function is_bytes ( a ) {
78 | return ( a instanceof Uint8Array );
79 | }
80 |
81 | function is_typed_array ( a ) {
82 | return ( a instanceof Int8Array ) || ( a instanceof Uint8Array )
83 | || ( a instanceof Int16Array ) || ( a instanceof Uint16Array )
84 | || ( a instanceof Int32Array ) || ( a instanceof Uint32Array )
85 | || ( a instanceof Float32Array )
86 | || ( a instanceof Float64Array );
87 | }
88 |
89 | function _heap_init ( constructor, options ) {
90 | var heap = options.heap,
91 | size = heap ? heap.byteLength : options.heapSize || 65536;
92 |
93 | if ( size & 0xfff || size <= 0 )
94 | throw new Error("heap size must be a positive integer and a multiple of 4096");
95 |
96 | heap = heap || new constructor( new ArrayBuffer(size) );
97 |
98 | return heap;
99 | }
100 |
101 | function _heap_write ( heap, hpos, data, dpos, dlen ) {
102 | var hlen = heap.length - hpos,
103 | wlen = ( hlen < dlen ) ? hlen : dlen;
104 |
105 | heap.set( data.subarray( dpos, dpos+wlen ), hpos );
106 |
107 | return wlen;
108 | }
109 |
--------------------------------------------------------------------------------
/src/hmac/hmac-sha256.js:
--------------------------------------------------------------------------------
1 | function hmac_sha256_constructor ( options ) {
2 | options = options || {};
3 |
4 | if ( !( options.hash instanceof sha256_constructor ) )
5 | options.hash = get_sha256_instance();
6 |
7 | hmac_constructor.call( this, options );
8 |
9 | return this;
10 | }
11 |
12 | function hmac_sha256_reset ( options ) {
13 | options = options || {};
14 |
15 | this.result = null;
16 | this.hash.reset();
17 |
18 | var password = options.password;
19 | if ( password !== undefined ) {
20 | if ( is_string(password) )
21 | password = string_to_bytes(password);
22 |
23 | var key = this.key = _hmac_key( this.hash, password );
24 | this.hash.reset().asm.hmac_init(
25 | (key[0]<<24)|(key[1]<<16)|(key[2]<<8)|(key[3]),
26 | (key[4]<<24)|(key[5]<<16)|(key[6]<<8)|(key[7]),
27 | (key[8]<<24)|(key[9]<<16)|(key[10]<<8)|(key[11]),
28 | (key[12]<<24)|(key[13]<<16)|(key[14]<<8)|(key[15]),
29 | (key[16]<<24)|(key[17]<<16)|(key[18]<<8)|(key[19]),
30 | (key[20]<<24)|(key[21]<<16)|(key[22]<<8)|(key[23]),
31 | (key[24]<<24)|(key[25]<<16)|(key[26]<<8)|(key[27]),
32 | (key[28]<<24)|(key[29]<<16)|(key[30]<<8)|(key[31]),
33 | (key[32]<<24)|(key[33]<<16)|(key[34]<<8)|(key[35]),
34 | (key[36]<<24)|(key[37]<<16)|(key[38]<<8)|(key[39]),
35 | (key[40]<<24)|(key[41]<<16)|(key[42]<<8)|(key[43]),
36 | (key[44]<<24)|(key[45]<<16)|(key[46]<<8)|(key[47]),
37 | (key[48]<<24)|(key[49]<<16)|(key[50]<<8)|(key[51]),
38 | (key[52]<<24)|(key[53]<<16)|(key[54]<<8)|(key[55]),
39 | (key[56]<<24)|(key[57]<<16)|(key[58]<<8)|(key[59]),
40 | (key[60]<<24)|(key[61]<<16)|(key[62]<<8)|(key[63])
41 | );
42 | }
43 | else {
44 | this.hash.asm.hmac_reset();
45 | }
46 |
47 | var verify = options.verify;
48 | if ( verify !== undefined ) {
49 | _hmac_init_verify.call( this, verify );
50 | }
51 | else {
52 | this.verify = null;
53 | }
54 |
55 | return this;
56 | }
57 |
58 | function hmac_sha256_finish () {
59 | if ( this.key === null )
60 | throw new IllegalStateError("no key is associated with the instance");
61 |
62 | if ( this.result !== null )
63 | throw new IllegalStateError("state must be reset before processing new data");
64 |
65 | var hash = this.hash,
66 | asm = this.hash.asm,
67 | heap = this.hash.heap;
68 |
69 | asm.hmac_finish( hash.pos, hash.len, 0 );
70 |
71 | var verify = this.verify;
72 | var result = new Uint8Array(_sha256_hash_size);
73 | result.set( heap.subarray( 0, _sha256_hash_size ) );
74 |
75 | if ( verify ) {
76 | if ( verify.length === result.length ) {
77 | var diff = 0;
78 | for ( var i = 0; i < verify.length; i++ ) {
79 | diff |= ( verify[i] ^ result[i] );
80 | }
81 | this.result = !diff;
82 | } else {
83 | this.result = false;
84 | }
85 | }
86 | else {
87 | this.result = result;
88 | }
89 |
90 | return this;
91 | }
92 |
93 | hmac_sha256_constructor.BLOCK_SIZE = sha256_constructor.BLOCK_SIZE;
94 | hmac_sha256_constructor.HMAC_SIZE = sha256_constructor.HASH_SIZE;
95 |
96 | var hmac_sha256_prototype = hmac_sha256_constructor.prototype;
97 | hmac_sha256_prototype.reset = hmac_sha256_reset;
98 | hmac_sha256_prototype.process = hmac_process;
99 | hmac_sha256_prototype.finish = hmac_sha256_finish;
100 |
101 | var hmac_sha256_instance = null;
102 |
103 | function get_hmac_sha256_instance () {
104 | if ( hmac_sha256_instance === null ) hmac_sha256_instance = new hmac_sha256_constructor();
105 | return hmac_sha256_instance;
106 | }
107 |
--------------------------------------------------------------------------------
/src/hmac/hmac-sha1.js:
--------------------------------------------------------------------------------
1 | function hmac_sha1_constructor ( options ) {
2 | options = options || {};
3 |
4 | if ( !( options.hash instanceof sha1_constructor ) )
5 | options.hash = get_sha1_instance();
6 |
7 | hmac_constructor.call( this, options );
8 |
9 | return this;
10 | }
11 |
12 | function hmac_sha1_reset ( options ) {
13 | options = options || {};
14 |
15 | this.result = null;
16 | this.hash.reset();
17 |
18 | var password = options.password;
19 | if ( password !== undefined ) {
20 | if ( is_string(password) )
21 | password = string_to_bytes(password);
22 |
23 | var key = this.key = _hmac_key( this.hash, password );
24 | this.hash.reset().asm.hmac_init(
25 | (key[0]<<24)|(key[1]<<16)|(key[2]<<8)|(key[3]),
26 | (key[4]<<24)|(key[5]<<16)|(key[6]<<8)|(key[7]),
27 | (key[8]<<24)|(key[9]<<16)|(key[10]<<8)|(key[11]),
28 | (key[12]<<24)|(key[13]<<16)|(key[14]<<8)|(key[15]),
29 | (key[16]<<24)|(key[17]<<16)|(key[18]<<8)|(key[19]),
30 | (key[20]<<24)|(key[21]<<16)|(key[22]<<8)|(key[23]),
31 | (key[24]<<24)|(key[25]<<16)|(key[26]<<8)|(key[27]),
32 | (key[28]<<24)|(key[29]<<16)|(key[30]<<8)|(key[31]),
33 | (key[32]<<24)|(key[33]<<16)|(key[34]<<8)|(key[35]),
34 | (key[36]<<24)|(key[37]<<16)|(key[38]<<8)|(key[39]),
35 | (key[40]<<24)|(key[41]<<16)|(key[42]<<8)|(key[43]),
36 | (key[44]<<24)|(key[45]<<16)|(key[46]<<8)|(key[47]),
37 | (key[48]<<24)|(key[49]<<16)|(key[50]<<8)|(key[51]),
38 | (key[52]<<24)|(key[53]<<16)|(key[54]<<8)|(key[55]),
39 | (key[56]<<24)|(key[57]<<16)|(key[58]<<8)|(key[59]),
40 | (key[60]<<24)|(key[61]<<16)|(key[62]<<8)|(key[63])
41 | );
42 | }
43 | else {
44 | this.hash.asm.hmac_reset();
45 | }
46 |
47 | var verify = options.verify;
48 | if ( verify !== undefined ) {
49 | _hmac_init_verify.call( this, verify );
50 | }
51 | else {
52 | this.verify = null;
53 | }
54 |
55 | return this;
56 | }
57 |
58 | function hmac_sha1_finish () {
59 | if ( this.key === null )
60 | throw new IllegalStateError("no key is associated with the instance");
61 |
62 | if ( this.result !== null )
63 | throw new IllegalStateError("state must be reset before processing new data");
64 |
65 | var hash = this.hash,
66 | asm = this.hash.asm,
67 | heap = this.hash.heap;
68 |
69 | asm.hmac_finish( hash.pos, hash.len, 0 );
70 |
71 | var verify = this.verify;
72 | var result = new Uint8Array(_sha1_hash_size);
73 | result.set( heap.subarray( 0, _sha1_hash_size ) );
74 |
75 | if ( verify ) {
76 | if ( verify.length === result.length ) {
77 | var diff = 0;
78 | for ( var i = 0; i < verify.length; i++ ) {
79 | diff |= ( verify[i] ^ result[i] );
80 | }
81 | this.result = !diff;
82 | } else {
83 | this.result = false;
84 | }
85 | }
86 | else {
87 | this.result = result;
88 | }
89 |
90 | return this;
91 | }
92 |
93 | hmac_sha1_constructor.BLOCK_SIZE = sha1_constructor.BLOCK_SIZE;
94 | hmac_sha1_constructor.HMAC_SIZE = sha1_constructor.HASH_SIZE;
95 |
96 | var hmac_sha1_prototype = hmac_sha1_constructor.prototype;
97 | hmac_sha1_prototype.reset = hmac_sha1_reset;
98 | hmac_sha1_prototype.process = hmac_process;
99 | hmac_sha1_prototype.finish = hmac_sha1_finish;
100 |
101 | var hmac_sha1_instance = null;
102 |
103 | function get_hmac_sha1_instance () {
104 | if ( hmac_sha1_instance === null ) hmac_sha1_instance = new hmac_sha1_constructor();
105 | return hmac_sha1_instance;
106 | }
107 |
--------------------------------------------------------------------------------
/src/hmac/hmac.js:
--------------------------------------------------------------------------------
1 | function hmac_constructor ( options ) {
2 | options = options || {};
3 |
4 | if ( !options.hash )
5 | throw new SyntaxError("option 'hash' is required");
6 |
7 | if ( !options.hash.HASH_SIZE )
8 | throw new SyntaxError("option 'hash' supplied doesn't seem to be a valid hash function");
9 |
10 | this.hash = options.hash;
11 | this.BLOCK_SIZE = this.hash.BLOCK_SIZE;
12 | this.HMAC_SIZE = this.hash.HASH_SIZE;
13 |
14 | this.key = null;
15 | this.verify = null;
16 | this.result = null;
17 |
18 | if ( options.password !== undefined || options.verify !== undefined )
19 | this.reset(options);
20 |
21 | return this;
22 | }
23 |
24 | function _hmac_key ( hash, password ) {
25 | if ( is_buffer(password) )
26 | password = new Uint8Array(password);
27 |
28 | if ( is_string(password) )
29 | password = string_to_bytes(password);
30 |
31 | if ( !is_bytes(password) )
32 | throw new TypeError("password isn't of expected type");
33 |
34 | var key = new Uint8Array( hash.BLOCK_SIZE );
35 |
36 | if ( password.length > hash.BLOCK_SIZE ) {
37 | key.set( hash.reset().process(password).finish().result );
38 | }
39 | else {
40 | key.set(password);
41 | }
42 |
43 | return key;
44 | }
45 |
46 | function _hmac_init_verify ( verify ) {
47 | if ( is_buffer(verify) || is_bytes(verify) ) {
48 | verify = new Uint8Array(verify);
49 | }
50 | else if ( is_string(verify) ) {
51 | verify = string_to_bytes(verify);
52 | }
53 | else {
54 | throw new TypeError("verify tag isn't of expected type");
55 | }
56 |
57 | if ( verify.length !== this.HMAC_SIZE )
58 | throw new IllegalArgumentError("illegal verification tag size");
59 |
60 | this.verify = verify;
61 | }
62 |
63 | function hmac_reset ( options ) {
64 | options = options || {};
65 | var password = options.password;
66 |
67 | if ( this.key === null && !is_string(password) && !password )
68 | throw new IllegalStateError("no key is associated with the instance");
69 |
70 | this.result = null;
71 | this.hash.reset();
72 |
73 | if ( password || is_string(password) )
74 | this.key = _hmac_key( this.hash, password );
75 |
76 | var ipad = new Uint8Array(this.key);
77 | for ( var i = 0; i < ipad.length; ++i )
78 | ipad[i] ^= 0x36;
79 |
80 | this.hash.process(ipad);
81 |
82 | var verify = options.verify;
83 | if ( verify !== undefined ) {
84 | _hmac_init_verify.call( this, verify );
85 | }
86 | else {
87 | this.verify = null;
88 | }
89 |
90 | return this;
91 | }
92 |
93 | function hmac_process ( data ) {
94 | if ( this.key === null )
95 | throw new IllegalStateError("no key is associated with the instance");
96 |
97 | if ( this.result !== null )
98 | throw new IllegalStateError("state must be reset before processing new data");
99 |
100 | this.hash.process(data);
101 |
102 | return this;
103 | }
104 |
105 | function hmac_finish () {
106 | if ( this.key === null )
107 | throw new IllegalStateError("no key is associated with the instance");
108 |
109 | if ( this.result !== null )
110 | throw new IllegalStateError("state must be reset before processing new data");
111 |
112 | var inner_result = this.hash.finish().result;
113 |
114 | var opad = new Uint8Array(this.key);
115 | for ( var i = 0; i < opad.length; ++i )
116 | opad[i] ^= 0x5c;
117 |
118 | var verify = this.verify;
119 | var result = this.hash.reset().process(opad).process(inner_result).finish().result;
120 |
121 | if ( verify ) {
122 | if ( verify.length === result.length ) {
123 | var diff = 0;
124 | for ( var i = 0; i < verify.length; i++ ) {
125 | diff |= ( verify[i] ^ result[i] );
126 | }
127 | this.result = !diff;
128 | } else {
129 | this.result = false;
130 | }
131 | }
132 | else {
133 | this.result = result;
134 | }
135 |
136 | return this;
137 | }
138 |
139 | var hmac_prototype = hmac_constructor.prototype;
140 | hmac_prototype.reset = hmac_reset;
141 | hmac_prototype.process = hmac_process;
142 | hmac_prototype.finish = hmac_finish;
143 |
--------------------------------------------------------------------------------
/test/sha1.js:
--------------------------------------------------------------------------------
1 | module("SHA1");
2 |
3 | ///////////////////////////////////////////////////////////////////////////////
4 |
5 | if ( typeof asmCrypto.SHA1 !== 'undefined' )
6 | {
7 | var sha1_vectors = [
8 | [ 'a9993e364706816aba3e25717850c26c9cd0d89d', 'abc'],
9 | [ '84983e441c3bd26ebaae4aa1f95129e5e54670f1', 'abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq'],
10 | [ 'a49b2446a02c645bf419f995b67091253a04a259', 'abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu'],
11 | [ '2fd4e1c67a2d28fced849ee1bb76e7391b93eb12', 'The quick brown fox jumps over the lazy dog' ],
12 | [ 'de9f2c7fd25e1b3afad3e85a0bd17d9b100db4b3', 'The quick brown fox jumps over the lazy cog' ]
13 | ];
14 |
15 | test( "asmCrypto.SHA1.hex", function () {
16 | for ( var i = 0; i < sha1_vectors.length; ++i ) {
17 | equal(
18 | asmCrypto.SHA1.hex( sha1_vectors[i][1] ),
19 | sha1_vectors[i][0],
20 | "vector " + i
21 | );
22 | }
23 | });
24 | }
25 | else
26 | {
27 | skip( "asmCrypto.SHA1" );
28 | }
29 |
30 | ///////////////////////////////////////////////////////////////////////////////
31 |
32 | if ( typeof asmCrypto.HMAC_SHA1 !== 'undefined' )
33 | {
34 | var hmac_sha1_vectors = [
35 | [ '5fd596ee78d5553c8ff4e72d266dfd192366da29', asmCrypto.hex_to_bytes('000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f'), asmCrypto.hex_to_bytes('53616d706c65206d65737361676520666f72206b65796c656e3d626c6f636b6c656e') ],
36 | [ 'fbdb1d1b18aa6c08324b7d64b71fb76370690e1d', '', '' ],
37 | [ 'de7c9b85b8b78aa6bc8a7a36f70a90701c9db4d9', 'key', 'The quick brown fox jumps over the lazy dog' ],
38 | [ 'b617318655057264e28bc0b6fb378c8ef146be00', asmCrypto.hex_to_bytes('0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b'), 'Hi There' ],
39 | [ 'effcdf6ae5eb2fa2d27416d5f184df9c259a7c79', 'Jefe', 'what do ya want for nothing?']
40 | ];
41 |
42 | test( "asmCrypto.HMAC_SHA1.hex", function () {
43 | for ( var i = 0; i < hmac_sha1_vectors.length; ++i ) {
44 | equal(
45 | asmCrypto.HMAC_SHA1.hex( hmac_sha1_vectors[i][2], hmac_sha1_vectors[i][1] ),
46 | hmac_sha1_vectors[i][0],
47 | "vector " + i
48 | );
49 | }
50 | });
51 | }
52 | else
53 | {
54 | skip( "asmCrypto.HMAC_SHA1" );
55 | }
56 |
57 | ///////////////////////////////////////////////////////////////////////////////
58 |
59 | if ( typeof asmCrypto.PBKDF2_HMAC_SHA1 !== 'undefined' )
60 | {
61 | var pbkdf2_hmac_sha1_vectors = [
62 | [ '0c60c80f961f0e71f3a9b524af6012062fe037a6', 'password', 'salt', 1, 20 ],
63 | [ 'ea6c014dc72d6f8ccd1ed92ace1d41f0d8de8957', 'password', 'salt', 2, 20 ],
64 | [ '4b007901b765489abead49d926f721d065a429c1', 'password', 'salt', 4096, 20 ],
65 | //[ 'eefe3d61cd4da4e4e9945b3d6ba2158c2634e984', 'password', 'salt', 16777216, 20 ],
66 | [ '3d2eec4fe41c849b80c8d83662c0e44a8b291a964cf2f07038', 'passwordPASSWORDpassword', 'saltSALTsaltSALTsaltSALTsaltSALTsalt', 4096, 25 ],
67 | [ '56fa6aa75548099dcc37d7f03425e0c3', "pass\0word", "sa\0lt", 4096, 16 ]
68 | ];
69 |
70 | test( "asmCrypto.PBKDF2_HMAC_SHA1.hex", function () {
71 | for ( var i = 0; i < pbkdf2_hmac_sha1_vectors.length; ++i ) {
72 | equal(
73 | // got
74 | asmCrypto.PBKDF2_HMAC_SHA1.hex(
75 | pbkdf2_hmac_sha1_vectors[i][1], // password
76 | pbkdf2_hmac_sha1_vectors[i][2], // salt
77 | pbkdf2_hmac_sha1_vectors[i][3], // count
78 | pbkdf2_hmac_sha1_vectors[i][4] // dklen
79 | ),
80 |
81 | // expect
82 | pbkdf2_hmac_sha1_vectors[i][0],
83 |
84 | // comment
85 | "asmCrypto.PBKDF2_HMAC_SHA1.hex('"
86 | +pbkdf2_hmac_sha1_vectors[i][1]+"', '"
87 | +pbkdf2_hmac_sha1_vectors[i][2]+"', '"
88 | +pbkdf2_hmac_sha1_vectors[i][3]+"', '"
89 | +pbkdf2_hmac_sha1_vectors[i][4]
90 | +"') is equal to '"+pbkdf2_hmac_sha1_vectors[i][0]+"'"
91 | );
92 | }
93 | });
94 | }
95 | else
96 | {
97 | skip( "asmCrypto.PBKDF2_HMAC_SHA1" );
98 | }
99 |
--------------------------------------------------------------------------------
/src/rsa/rsa.js:
--------------------------------------------------------------------------------
1 | function RSA ( options ) {
2 | options = options || {};
3 |
4 | this.key = null;
5 | this.result = null;
6 |
7 | this.reset(options);
8 | }
9 |
10 | function RSA_reset ( options ) {
11 | options = options || {};
12 |
13 | this.result = null;
14 |
15 | var key = options.key
16 | if ( key !== undefined ) {
17 | if ( key instanceof Array ) {
18 | var l = key.length;
19 | if ( l !== 2 && l !== 3 && l !== 8 )
20 | throw new SyntaxError("unexpected key type");
21 |
22 | var k = [];
23 | k[0] = new Modulus( key[0] );
24 | k[1] = new BigNumber( key[1] );
25 | if ( l > 2 ) {
26 | k[2] = new BigNumber( key[2] );
27 | }
28 | if ( l > 3 ) {
29 | k[3] = new Modulus( key[3] );
30 | k[4] = new Modulus( key[4] );
31 | k[5] = new BigNumber( key[5] );
32 | k[6] = new BigNumber( key[6] );
33 | k[7] = new BigNumber( key[7] );
34 | }
35 |
36 | this.key = k;
37 | }
38 | else {
39 | throw new TypeError("unexpected key type");
40 | }
41 | }
42 |
43 | return this;
44 | }
45 |
46 | function RSA_encrypt ( data ) {
47 | if ( !this.key )
48 | throw new IllegalStateError("no key is associated with the instance");
49 |
50 | if ( is_string(data) )
51 | data = string_to_bytes(data);
52 |
53 | if ( is_buffer(data) )
54 | data = new Uint8Array(data);
55 |
56 | var msg;
57 | if ( is_bytes(data) ) {
58 | msg = new BigNumber(data);
59 | }
60 | else if ( is_big_number(data) ) {
61 | msg = data;
62 | }
63 | else {
64 | throw new TypeError("unexpected data type");
65 | }
66 |
67 | if ( this.key[0].compare(msg) <= 0 )
68 | throw new RangeError("data too large");
69 |
70 | var m = this.key[0],
71 | e = this.key[1];
72 |
73 | var result = m.power( msg, e ).toBytes();
74 |
75 | var bytelen = m.bitLength + 7 >> 3;
76 | if ( result.length < bytelen ) {
77 | var r = new Uint8Array(bytelen);
78 | r.set( result, bytelen - result.length );
79 | result = r;
80 | }
81 |
82 | this.result = result;
83 |
84 | return this;
85 | }
86 |
87 | function RSA_decrypt ( data ) {
88 | if ( !this.key )
89 | throw new IllegalStateError("no key is associated with the instance");
90 |
91 | if ( this.key.length < 3 )
92 | throw new IllegalStateError("key isn't suitable for decription");
93 |
94 | if ( is_string(data) )
95 | data = string_to_bytes(data);
96 |
97 | if ( is_buffer(data) )
98 | data = new Uint8Array(data);
99 |
100 | var msg;
101 | if ( is_bytes(data) ) {
102 | msg = new BigNumber(data);
103 | }
104 | else if ( is_big_number(data) ) {
105 | msg = data;
106 | }
107 | else {
108 | throw new TypeError("unexpected data type");
109 | }
110 |
111 | if ( this.key[0].compare(msg) <= 0 )
112 | throw new RangeError("data too large");
113 |
114 | var result;
115 | if ( this.key.length > 3 ) {
116 | var m = this.key[0],
117 | p = this.key[3],
118 | q = this.key[4],
119 | dp = this.key[5],
120 | dq = this.key[6],
121 | u = this.key[7];
122 |
123 | var x = p.power( msg, dp ),
124 | y = q.power( msg, dq );
125 |
126 | var t = x.subtract(y);
127 | while ( t.sign < 0 ) t = t.add(p);
128 |
129 | var h = p.reduce( u.multiply(t) );
130 |
131 | result = h.multiply(q).add(y).clamp(m.bitLength).toBytes();
132 | }
133 | else {
134 | var m = this.key[0],
135 | d = this.key[2];
136 |
137 | result = m.power( msg, d ).toBytes();
138 | }
139 |
140 | var bytelen = m.bitLength + 7 >> 3;
141 | if ( result.length < bytelen ) {
142 | var r = new Uint8Array(bytelen);
143 | r.set( result, bytelen - result.length );
144 | result = r;
145 | }
146 |
147 | this.result = result;
148 |
149 | return this;
150 | }
151 |
152 | var RSA_prototype = RSA.prototype;
153 | RSA_prototype.reset = RSA_reset;
154 | RSA_prototype.encrypt = RSA_encrypt;
155 | RSA_prototype.decrypt = RSA_decrypt;
156 |
--------------------------------------------------------------------------------
/test/sha256.js:
--------------------------------------------------------------------------------
1 | module("SHA256");
2 |
3 | ///////////////////////////////////////////////////////////////////////////////
4 |
5 | if ( typeof asmCrypto.SHA256 !== 'undefined' )
6 | {
7 | var sha256_vectors = [
8 | [ 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855', '' ],
9 | [ 'ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad', 'abc' ],
10 | [ 'f7846f55cf23e14eebeab5b4e1550cad5b509e3348fbc4efa3a1413d393cb650', 'message digest' ],
11 | [ 'f30ceb2bb2829e79e4ca9753d35a8ecc00262d164cc077080295381cbd643f0d', 'secure hash algorithm' ],
12 | [ '6819d915c73f4d1e77e4e1b52d1fa0f9cf9beaead3939f15874bd988e2a23630', 'SHA256 is considered to be safe' ],
13 | [ '248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1', 'abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq' ],
14 | [ 'f08a78cbbaee082b052ae0708f32fa1e50c5c421aa772ba5dbb406a2ea6be342', 'For this sample, this 63-byte string will be used as input data' ],
15 | [ 'ab64eff7e88e2e46165e29f2bce41826bd4c7b3552f6b382a9e7d3af47c245f8', 'This is exactly 64 bytes long, not counting the terminating byte' ]
16 | ];
17 |
18 | test( "asmCrypto.SHA256.hex", function () {
19 | for ( var i = 0; i < sha256_vectors.length; ++i ) {
20 | equal(
21 | asmCrypto.SHA256.hex( sha256_vectors[i][1] ),
22 | sha256_vectors[i][0],
23 | "vector " + i
24 | );
25 | }
26 | });
27 | }
28 | else
29 | {
30 | skip( "asmCrypto.SHA256" );
31 | }
32 |
33 | ///////////////////////////////////////////////////////////////////////////////
34 |
35 | if ( typeof asmCrypto.HMAC_SHA256 !== 'undefined' )
36 | {
37 | var hmac_sha256_vectors = [
38 | [ 'b613679a0814d9ec772f95d778c35fc5ff1697c493715653c6c712144292c5ad', '', '' ],
39 | [ 'f7bc83f430538424b13298e6aa6fb143ef4d59a14946175997479dbc2d1a3cd8', 'key', 'The quick brown fox jumps over the lazy dog' ],
40 | [ 'b54d57e9b21940b6496b58d5ac120eda9f1637788b5df058928637f2eca40cd9', 'MyVeeeeeeeeeeeeeryVeeeeeeeeeeeeeryVeeeeeeeeeeeeeryLoooooooooongPassword', 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.' ]
41 | ];
42 |
43 | test( "asmCrypto.HMAC_SHA256.hex", function () {
44 | for ( var i = 0; i < hmac_sha256_vectors.length; ++i ) {
45 | equal(
46 | asmCrypto.HMAC_SHA256.hex( hmac_sha256_vectors[i][2], hmac_sha256_vectors[i][1] ),
47 | hmac_sha256_vectors[i][0],
48 | "vector " + i
49 | );
50 | }
51 | });
52 | }
53 | else
54 | {
55 | skip( "asmCrypto.HMAC_SHA256" );
56 | }
57 |
58 | ///////////////////////////////////////////////////////////////////////////////
59 |
60 | if ( typeof asmCrypto.PBKDF2_HMAC_SHA256 !== 'undefined' )
61 | {
62 | var pbkdf2_hmac_sha256_vectors = [
63 | [ '120fb6cffcf8b32c43e7225256c4f837a86548c92ccc35480805987cb70be17b', 'password', 'salt', 1, 32 ],
64 | [ 'ae4d0c95af6b46d32d0adff928f06dd02a303f8ef3c251dfd6e2d85a95474c43', 'password', 'salt', 2, 32 ],
65 | [ 'c5e478d59288c841aa530db6845c4c8d962893a001ce4e11a4963873aa98134a', 'password', 'salt', 4096, 32 ],
66 | [ '348c89dbcbd32b2f32d814b8116e84cf2b17347ebc1800181c4e2a1fb8dd53e1c635518c7dac47e9', 'passwordPASSWORDpassword', 'saltSALTsaltSALTsaltSALTsaltSALTsalt', 4096, 40 ],
67 | [ '89b69d0516f829893c696226650a8687', "pass\0word", "sa\0lt", 4096, 16 ],
68 | [ 'cdc8b1780ca68aba97f1f729c9d281719702eb4b308d7d87409817e60188be0d', 'MyVeeeeeeeeeeeeeryVeeeeeeeeeeeeeryVeeeeeeeeeeeeeryLoooooooooongPassword', 'MyVeeeeeeeeeeeeeryVeeeeeeeeeeeeeryVeeeeeeeeeeeeeryLoooooooooongPassword', 4096, 32 ]
69 | ];
70 |
71 | test( "asmCrypto.PBKDF2_HMAC_SHA256.hex", function () {
72 | for ( var i = 0; i < pbkdf2_hmac_sha256_vectors.length; ++i ) {
73 | equal(
74 | // got
75 | asmCrypto.PBKDF2_HMAC_SHA256.hex(
76 | pbkdf2_hmac_sha256_vectors[i][1], // password
77 | pbkdf2_hmac_sha256_vectors[i][2], // salt
78 | pbkdf2_hmac_sha256_vectors[i][3], // count
79 | pbkdf2_hmac_sha256_vectors[i][4] // dklen
80 | ),
81 |
82 | // expect
83 | pbkdf2_hmac_sha256_vectors[i][0],
84 |
85 | // comment
86 | "asmCrypto.PBKDF2_HMAC_SHA256.hex('"
87 | +pbkdf2_hmac_sha256_vectors[i][1]+"', '"
88 | +pbkdf2_hmac_sha256_vectors[i][2]+"', '"
89 | +pbkdf2_hmac_sha256_vectors[i][3]+"', '"
90 | +pbkdf2_hmac_sha256_vectors[i][4]
91 | +"') is equal to '"+pbkdf2_hmac_sha256_vectors[i][0]+"'"
92 | );
93 | }
94 | });
95 | }
96 | else
97 | {
98 | skip( "asmCrypto.PBKDF2_HMAC_SHA256" );
99 | }
100 |
--------------------------------------------------------------------------------
/test/dummy.js:
--------------------------------------------------------------------------------
1 | module("dummy");
2 |
3 | test( "dummy test", function () {
4 | ok( true, "Passed!" );
5 | });
6 |
7 | test( "add with carry proparation", function () {
8 | var a = 0xad4e6ae6, b = 0xedfdecc8, c = 1, d = 0x19b4c57af, dc = 1,
9 | r = 0, rc = 0, u = 0, v = 0;
10 |
11 | r = (a + c)|0, rc = (r>>>0) < (a>>>0) ? 1 : 0;
12 | r = (b + r)|0, rc = (r>>>0) < (b>>>0) ? 1 : rc;
13 | equal( r>>>0, d>>>0, "adc32 result ok" );
14 | equal( rc, dc, "adc32 carry ok" );
15 |
16 | u = ( (a & 0xffff) + (b & 0xffff)|0 ) + c|0;
17 | v = ( (a >>> 16) + (b >>> 16)|0 ) + (u >>> 16)|0;
18 | r = (u & 0xffff) | (v << 16);
19 | rc = v >>> 16;
20 | equal( r>>>0, d>>>0, "adc16x2 result ok" );
21 | equal( rc, dc, "adc16x2 carry ok" );
22 | });
23 |
24 | if ( Math.imul ) {
25 | test( "multiply and add", function () {
26 | var imul = Math.imul,
27 | x = 0xad4e6ae6, y = 0xedfdecc8, z = 0x9b4c57af,
28 | h = 0xa11d7fc2, l = 0xde69e35f,
29 | u = 0, v = 0, w = 0,
30 | rh = 0, rl = 0;
31 |
32 | u = imul( x & 0xffff, y & 0xffff ) + (z & 0xffff) | 0;
33 | v = imul( x & 0xffff, y >>> 16 ) + (z >>> 16) | 0;
34 | w = ( imul( x >>> 16, y & 0xffff ) + (v & 0xffff) | 0 ) + (u >>> 16) | 0;
35 | rh = ( imul( x >>> 16, y >>> 16 ) + (v >>> 16) | 0 ) + (w >>> 16) | 0;
36 | rl = (w << 16) | (u & 0xffff);
37 |
38 | equal( h>>>0, rh>>>0, "high part is ok" );
39 | equal( l>>>0, rl>>>0, "low part is ok" );
40 | });
41 |
42 | test( "divide with remainder", function () {
43 | var n0 = 0xad4e6ae6, n1 = 0xedfdecc8, d0 = 0xeeddccbb, q0 = 0xff101123, r0 = 0x39b30255;
44 |
45 | var qh, ql, rh, rl, w0, w1, n, dh, dl, c, imul = Math.imul;
46 |
47 | dh = d0 >>> 16, dl = d0 & 0xffff;
48 |
49 | n = n1;
50 | qh = ( n / dh )|0, rh = n % dh;
51 | while ( ( (rh|0) < 0x10000 )
52 | & ( ( qh == 0x10000 ) | ( (imul(qh,dl)>>>0) > (((rh<<16)|(n0>>>16))>>>0) ) ) )
53 | {
54 | qh = (qh-1)|0;
55 | rh = (rh+dh)|0;
56 | }
57 | w0 = imul(qh, dl)|0;
58 | w1 = (w0 >>> 16) + imul(qh, dh)|0;
59 | w0 = w0 << 16;
60 | n = (n0-w0)|0, c = ( (n>>>0) > (n0>>>0) )|0, n0 = n;
61 | n = (n1-c)|0, c = ( (n>>>0) > (n1>>>0) )|0, n1 = (n-w1)|0, c = ( (n1>>>0) > (n>>>0) )|c;
62 | if ( c ) {
63 | qh = (qh-1)|0;
64 | n = (n0+(d0<<16))|0, c = ( (n>>>0) < (n0>>>0) )|0, n0 = n;
65 | n = (n1+c)|0, c = !n, n1 = (n+dh)|0, c = ( (n1>>>0) < (n>>>0) )|c;
66 | }
67 |
68 | n = (n1 << 16) | (n0 >>> 16);
69 | ql = ( n / dh )|0, rl = n % dh;
70 | while ( ( (rl|0) < 0x10000 )
71 | & ( ( ql == 0x10000 ) | ( (imul(ql,dl)>>>0) > (((rl << 16)|(n0 & 0xffff))>>>0) ) ) )
72 | {
73 | ql = (ql-1)|0;
74 | rl = (rl+dh)|0;
75 | }
76 | w0 = imul(ql, dl)|0;
77 | w1 = (w0 >>> 16) + imul(ql, dh)|0;
78 | w0 = (w1 << 16) | (w0 & 0xffff);
79 | w1 = w1 >>> 16;
80 | n = (n0-w0)|0, c = ( (n>>>0) > (n0>>>0) )|0, n0 = n;
81 | n = (n1-c)|0, c = ( (n>>>0) > (n1>>>0) )|0, n1 = (n-w1)|0, c = ( (n1>>>0) > (n>>>0) )|c;
82 | if ( c ) {
83 | ql = (ql-1)|0;
84 | n = (n0+d0)|0, c = ( (n>>>0) < (n0>>>0) )|0, n0 = n;
85 | n1 = (n1+c)|0;
86 | }
87 |
88 | equal( ((qh<<16)|ql)>>>0, q0, "quotient ok" );
89 | equal( n0>>>0, r0, "remainder ok" );
90 | });
91 |
92 | test( "imul", function () {
93 | equal( Math.imul(-338592732,968756475)|0, 787375948, "imul works fine" );
94 | });
95 | }
96 | else {
97 | skip( "multiply and add" );
98 | skip( "divide with remainder" );
99 | skip( "imul" );
100 | }
101 |
102 | test( "Math.random()", function () {
103 | var r = Math.random();
104 | ok( typeof r === 'number', "r is number" );
105 | ok( r >= 0 && r < 1, "0 <= r < 1" );
106 | });
107 |
108 | if ( asmCrypto.string_to_bytes ) {
109 | test( "asmCrypto.string_to_bytes()", function () {
110 | var bytes = asmCrypto.string_to_bytes("String not containing Unicode character");
111 | ok( bytes, "No exception on non-Unicode string" );
112 |
113 | try {
114 | var bytes = asmCrypto.string_to_bytes("String containing Unicode character: Ͼ");
115 | ok( false, "No exception on Unicode string")
116 | }
117 | catch ( e ) {
118 | ok( e instanceof Error, "Exception thrown on Unicode string" );
119 | ok( e.message.match(/wide character/i), "Exception message is about wide character" );
120 | }
121 | });
122 | }
123 | else {
124 | skip("asmCrypto.string_to_bytes()");
125 | }
126 |
127 | testIf( true, "Conditional test should pass", function () {
128 | ok( true, "Passed!" );
129 | });
130 |
131 | testIf( false, "Conditional test should skip", function () {
132 | ok( false, "Failed!" );
133 | });
134 |
--------------------------------------------------------------------------------
/src/hmac/hmac-sha512.js:
--------------------------------------------------------------------------------
1 | function hmac_sha512_constructor ( options ) {
2 | options = options || {};
3 |
4 | if ( !( options.hash instanceof sha512_constructor ) )
5 | options.hash = get_sha512_instance();
6 |
7 | hmac_constructor.call( this, options );
8 |
9 | return this;
10 | }
11 |
12 | function hmac_sha512_reset ( options ) {
13 | options = options || {};
14 |
15 | this.result = null;
16 | this.hash.reset();
17 |
18 | var password = options.password;
19 | if ( password !== undefined ) {
20 | if ( is_string(password) )
21 | password = string_to_bytes(password);
22 |
23 | var key = this.key = _hmac_key( this.hash, password );
24 | this.hash.reset().asm.hmac_init(
25 | (key[0]<<24)|(key[1]<<16)|(key[2]<<8)|(key[3]),
26 | (key[4]<<24)|(key[5]<<16)|(key[6]<<8)|(key[7]),
27 | (key[8]<<24)|(key[9]<<16)|(key[10]<<8)|(key[11]),
28 | (key[12]<<24)|(key[13]<<16)|(key[14]<<8)|(key[15]),
29 | (key[16]<<24)|(key[17]<<16)|(key[18]<<8)|(key[19]),
30 | (key[20]<<24)|(key[21]<<16)|(key[22]<<8)|(key[23]),
31 | (key[24]<<24)|(key[25]<<16)|(key[26]<<8)|(key[27]),
32 | (key[28]<<24)|(key[29]<<16)|(key[30]<<8)|(key[31]),
33 | (key[32]<<24)|(key[33]<<16)|(key[34]<<8)|(key[35]),
34 | (key[36]<<24)|(key[37]<<16)|(key[38]<<8)|(key[39]),
35 | (key[40]<<24)|(key[41]<<16)|(key[42]<<8)|(key[43]),
36 | (key[44]<<24)|(key[45]<<16)|(key[46]<<8)|(key[47]),
37 | (key[48]<<24)|(key[49]<<16)|(key[50]<<8)|(key[51]),
38 | (key[52]<<24)|(key[53]<<16)|(key[54]<<8)|(key[55]),
39 | (key[56]<<24)|(key[57]<<16)|(key[58]<<8)|(key[59]),
40 | (key[60]<<24)|(key[61]<<16)|(key[62]<<8)|(key[63]),
41 | (key[64]<<24)|(key[65]<<16)|(key[66]<<8)|(key[67]),
42 | (key[68]<<24)|(key[69]<<16)|(key[70]<<8)|(key[71]),
43 | (key[72]<<24)|(key[73]<<16)|(key[74]<<8)|(key[75]),
44 | (key[76]<<24)|(key[77]<<16)|(key[78]<<8)|(key[79]),
45 | (key[80]<<24)|(key[81]<<16)|(key[82]<<8)|(key[83]),
46 | (key[84]<<24)|(key[85]<<16)|(key[86]<<8)|(key[87]),
47 | (key[88]<<24)|(key[89]<<16)|(key[90]<<8)|(key[91]),
48 | (key[92]<<24)|(key[93]<<16)|(key[94]<<8)|(key[95]),
49 | (key[96]<<24)|(key[97]<<16)|(key[98]<<8)|(key[99]),
50 | (key[100]<<24)|(key[101]<<16)|(key[102]<<8)|(key[103]),
51 | (key[104]<<24)|(key[105]<<16)|(key[106]<<8)|(key[107]),
52 | (key[108]<<24)|(key[109]<<16)|(key[110]<<8)|(key[111]),
53 | (key[112]<<24)|(key[113]<<16)|(key[114]<<8)|(key[115]),
54 | (key[116]<<24)|(key[117]<<16)|(key[118]<<8)|(key[119]),
55 | (key[120]<<24)|(key[121]<<16)|(key[122]<<8)|(key[123]),
56 | (key[124]<<24)|(key[125]<<16)|(key[126]<<8)|(key[127])
57 | );
58 | }
59 | else {
60 | this.hash.asm.hmac_reset();
61 | }
62 |
63 | var verify = options.verify;
64 | if ( verify !== undefined ) {
65 | _hmac_init_verify.call( this, verify );
66 | }
67 | else {
68 | this.verify = null;
69 | }
70 |
71 | return this;
72 | }
73 |
74 | function hmac_sha512_finish () {
75 | if ( this.key === null )
76 | throw new IllegalStateError("no key is associated with the instance");
77 |
78 | if ( this.result !== null )
79 | throw new IllegalStateError("state must be reset before processing new data");
80 |
81 | var hash = this.hash,
82 | asm = this.hash.asm,
83 | heap = this.hash.heap;
84 |
85 | asm.hmac_finish( hash.pos, hash.len, 0 );
86 |
87 | var verify = this.verify;
88 | var result = new Uint8Array(_sha512_hash_size);
89 | result.set( heap.subarray( 0, _sha512_hash_size ) );
90 |
91 | if ( verify ) {
92 | if ( verify.length === result.length ) {
93 | var diff = 0;
94 | for ( var i = 0; i < verify.length; i++ ) {
95 | diff |= ( verify[i] ^ result[i] );
96 | }
97 | this.result = !diff;
98 | } else {
99 | this.result = false;
100 | }
101 | }
102 | else {
103 | this.result = result;
104 | }
105 |
106 | return this;
107 | }
108 |
109 | hmac_sha512_constructor.BLOCK_SIZE = sha512_constructor.BLOCK_SIZE;
110 | hmac_sha512_constructor.HMAC_SIZE = sha512_constructor.HASH_SIZE;
111 |
112 | var hmac_sha512_prototype = hmac_sha512_constructor.prototype;
113 | hmac_sha512_prototype.reset = hmac_sha512_reset;
114 | hmac_sha512_prototype.process = hmac_process;
115 | hmac_sha512_prototype.finish = hmac_sha512_finish;
116 |
117 | var hmac_sha512_instance = null;
118 |
119 | function get_hmac_sha512_instance () {
120 | if ( hmac_sha512_instance === null ) hmac_sha512_instance = new hmac_sha512_constructor();
121 | return hmac_sha512_instance;
122 | }
123 |
--------------------------------------------------------------------------------
/test/sha512.js:
--------------------------------------------------------------------------------
1 | module("SHA512");
2 |
3 | ///////////////////////////////////////////////////////////////////////////////
4 |
5 | if ( typeof asmCrypto.SHA512 !== 'undefined' )
6 | {
7 | var sha512_vectors = [
8 | [ 'cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e', '' ],
9 | [ 'ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f', 'abc' ],
10 | [ '8e959b75dae313da8cf4f72814fc143f8f7779c6eb9f7fa17299aeadb6889018501d289e4900f7e4331b99dec4b5433ac7d329eeb6dd26545e96e55b874be909', 'abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu' ],
11 | [ '07e547d9586f6a73f73fbac0435ed76951218fb7d0c8d788a309d785436bbb642e93a252a954f23912547d1e8a3b5ed6e1bfd7097821233fa0538f3db854fee6', 'The quick brown fox jumps over the lazy dog' ],
12 | [ '91ea1245f20d46ae9a037a989f54f1f790f0a47607eeb8a14d12890cea77a1bbc6c7ed9cf205e67b7f2b8fd4c7dfd3a7a8617e45f3c463d481c7e586c39ac1ed', 'The quick brown fox jumps over the lazy dog.' ]
13 | ];
14 |
15 | test( "asmCrypto.SHA512.hex", function () {
16 | for ( var i = 0; i < sha512_vectors.length; ++i ) {
17 | equal(
18 | asmCrypto.SHA512.hex( sha512_vectors[i][1] ),
19 | sha512_vectors[i][0],
20 | "vector " + i
21 | );
22 | }
23 | });
24 | }
25 | else
26 | {
27 | skip( "asmCrypto.SHA512" );
28 | }
29 |
30 | ///////////////////////////////////////////////////////////////////////////////
31 |
32 | if ( typeof asmCrypto.HMAC_SHA512 !== 'undefined' )
33 | {
34 | var hmac_sha512_vectors = [
35 | [ '87aa7cdea5ef619d4ff0b4241a1d6cb02379f4e2ce4ec2787ad0b30545e17cdedaa833b7d6b8a702038b274eaea3f4e4be9d914eeb61f1702e696c203a126854', asmCrypto.hex_to_bytes('0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b'), 'Hi There'],
36 | [ '164b7a7bfcf819e2e395fbe73b56e0a387bd64222e831fd610270cd7ea2505549758bf75c05a994a6d034f65f8f0e6fdcaeab1a34d4a6b4b636e070a38bce737', 'Jefe', 'what do ya want for nothing?' ],
37 | [ '80b24263c7c1a3ebb71493c1dd7be8b49b46d1f41b4aeec1121b013783f8f3526b56d037e05f2598bd0fd2215d6a1e5295e64f73f63f0aec8b915a985d786598', asmCrypto.hex_to_bytes('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'), 'Test Using Larger Than Block-Size Key - Hash Key First']
38 | ];
39 |
40 | test( "asmCrypto.HMAC_SHA512.hex", function () {
41 | for ( var i = 0; i < hmac_sha512_vectors.length; ++i ) {
42 | equal(
43 | asmCrypto.HMAC_SHA512.hex( hmac_sha512_vectors[i][2], hmac_sha512_vectors[i][1] ),
44 | hmac_sha512_vectors[i][0],
45 | "vector " + i
46 | );
47 | }
48 | });
49 | }
50 | else
51 | {
52 | skip( "asmCrypto.HMAC_SHA512" );
53 | }
54 |
55 | ///////////////////////////////////////////////////////////////////////////////
56 |
57 | if ( typeof asmCrypto.PBKDF2_HMAC_SHA512 !== 'undefined' )
58 | {
59 | var pbkdf2_hmac_sha512_vectors = [
60 | [ '867f70cf1ade02cff3752599a3a53dc4af34c7a669815ae5d513554e1c8cf252c02d470a285a0501bad999bfe943c08f050235d7d68b1da55e63f73b60a57fce', 'password', 'salt', 1, 64 ],
61 | [ '867f70cf1ade02cff3752599a3a53dc4af34c7a669815ae5d513554e1c8cf252c02d470a285a0501bad999bfe943c08f050235d7d68b1da55e63f73b60a57fce', asmCrypto.string_to_bytes('password'), asmCrypto.string_to_bytes('salt'), 1, 64 ],
62 | [ 'e1d9c16aa681708a45f5c7c4e215ceb66e011a2e9f0040713f18aefdb866d53cf76cab2868a39b9f7840edce4fef5a82be67335c77a6068e04112754f27ccf4e', 'password', 'salt', 2, 64 ],
63 | [ 'd197b1b33db0143e018b12f3d1d1479e6cdebdcc97c5c0f87f6902e072f457b5143f30602641b3d55cd335988cb36b84376060ecd532e039b742a239434af2d5', 'password', 'salt', 4096, 64 ],
64 | [ '8c0511f4c6e597c6ac6315d8f0362e225f3c501495ba23b868c005174dc4ee71115b59f9e60cd9532fa33e0f75aefe30225c583a186cd82bd4daea9724a3d3b8', 'passwordPASSWORDpassword', 'saltSALTsaltSALTsaltSALTsaltSALTsalt', 4096, 64 ]
65 | ];
66 |
67 | test( "asmCrypto.PBKDF2_HMAC_SHA512.hex", function () {
68 | for ( var i = 0; i < pbkdf2_hmac_sha512_vectors.length; ++i ) {
69 | equal(
70 | // got
71 | asmCrypto.PBKDF2_HMAC_SHA512.hex(
72 | pbkdf2_hmac_sha512_vectors[i][1], // password
73 | pbkdf2_hmac_sha512_vectors[i][2], // salt
74 | pbkdf2_hmac_sha512_vectors[i][3], // count
75 | pbkdf2_hmac_sha512_vectors[i][4] // dklen
76 | ),
77 |
78 | // expect
79 | pbkdf2_hmac_sha512_vectors[i][0],
80 |
81 | // comment
82 | "asmCrypto.PBKDF2_HMAC_SHA512.hex('"
83 | +pbkdf2_hmac_sha512_vectors[i][1]+"', '"
84 | +pbkdf2_hmac_sha512_vectors[i][2]+"', '"
85 | +pbkdf2_hmac_sha512_vectors[i][3]+"', '"
86 | +pbkdf2_hmac_sha512_vectors[i][4]
87 | +"') is equal to '"+pbkdf2_hmac_sha512_vectors[i][0]+"'"
88 | );
89 | }
90 | });
91 | }
92 | else
93 | {
94 | skip( "asmCrypto.PBKDF2_HMAC_SHA512" );
95 | }
96 |
--------------------------------------------------------------------------------
/src/bignum/modulus.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Modulus
3 | */
4 | function Modulus () {
5 | BigNumber.apply( this, arguments );
6 |
7 | if ( this.valueOf() < 1 )
8 | throw new RangeError();
9 |
10 | if ( this.bitLength <= 32 )
11 | return;
12 |
13 | var comodulus;
14 |
15 | if ( this.limbs[0] & 1 ) {
16 | var bitlen = ( (this.bitLength+31) & -32 ) + 1, limbs = new Uint32Array( (bitlen+31) >> 5 );
17 | limbs[limbs.length-1] = 1;
18 | comodulus = new BigNumber();
19 | comodulus.sign = 1;
20 | comodulus.bitLength = bitlen;
21 | comodulus.limbs = limbs;
22 |
23 | var k = Number_extGCD( 0x100000000, this.limbs[0] ).y;
24 | this.coefficient = k < 0 ? -k : 0x100000000-k;
25 | }
26 | else {
27 | /**
28 | * TODO even modulus reduction
29 | * Modulus represented as `N = 2^U * V`, where `V` is odd and thus `GCD(2^U, V) = 1`.
30 | * Calculation `A = TR' mod V` is made as for odd modulo using Montgomery method.
31 | * Calculation `B = TR' mod 2^U` is easy as modulus is a power of 2.
32 | * Using Chinese Remainder Theorem and Garner's Algorithm restore `TR' mod N` from `A` and `B`.
33 | */
34 | return;
35 | }
36 |
37 | this.comodulus = comodulus;
38 | this.comodulusRemainder = comodulus.divide(this).remainder;
39 | this.comodulusRemainderSquare = comodulus.square().divide(this).remainder;
40 | }
41 |
42 | /**
43 | * Modular reduction
44 | */
45 | function Modulus_reduce ( a ) {
46 | if ( !is_big_number(a) )
47 | a = new BigNumber(a);
48 |
49 | if ( a.bitLength <= 32 && this.bitLength <= 32 )
50 | return new BigNumber( a.valueOf() % this.valueOf() );
51 |
52 | if ( a.compare(this) < 0 )
53 | return a;
54 |
55 | return a.divide(this).remainder;
56 | }
57 |
58 | /**
59 | * Modular inverse
60 | */
61 | function Modulus_inverse ( a ) {
62 | a = this.reduce(a);
63 |
64 | var r = BigNumber_extGCD( this, a );
65 | if ( r.gcd.valueOf() !== 1 ) return null;
66 |
67 | r = r.y;
68 | if ( r.sign < 0 ) r = r.add(this).clamp(this.bitLength);
69 |
70 | return r;
71 | }
72 |
73 | /**
74 | * Modular exponentiation
75 | */
76 | function Modulus_power ( g, e ) {
77 | if ( !is_big_number(g) )
78 | g = new BigNumber(g);
79 |
80 | if ( !is_big_number(e) )
81 | e = new BigNumber(e);
82 |
83 | // count exponent set bits
84 | var c = 0;
85 | for ( var i = 0; i < e.limbs.length; i++ ) {
86 | var t = e.limbs[i];
87 | while ( t ) {
88 | if ( t & 1 ) c++;
89 | t >>>= 1;
90 | }
91 | }
92 |
93 | // window size parameter
94 | var k = 8;
95 | if ( e.bitLength <= 4536 ) k = 7;
96 | if ( e.bitLength <= 1736 ) k = 6;
97 | if ( e.bitLength <= 630 ) k = 5;
98 | if ( e.bitLength <= 210 ) k = 4;
99 | if ( e.bitLength <= 60 ) k = 3;
100 | if ( e.bitLength <= 12 ) k = 2;
101 | if ( c <= (1 << (k-1)) ) k = 1;
102 |
103 | // montgomerize base
104 | g = _Montgomery_reduce( this.reduce(g).multiply(this.comodulusRemainderSquare), this );
105 |
106 | // precompute odd powers
107 | var g2 = _Montgomery_reduce( g.square(), this ),
108 | gn = new Array( 1 << (k-1) );
109 | gn[0] = g;
110 | gn[1] = _Montgomery_reduce( g.multiply(g2), this );
111 | for ( var i = 2; i < (1 << (k-1)); i++ ) {
112 | gn[i] = _Montgomery_reduce( gn[i-1].multiply(g2), this );
113 | }
114 |
115 | // perform exponentiation
116 | var u = this.comodulusRemainder,
117 | r = u;
118 | for ( var i = e.limbs.length-1; i >= 0; i-- ) {
119 | var t = e.limbs[i];
120 | for ( var j = 32; j > 0; ) {
121 | if ( t & 0x80000000 ) {
122 | var n = t >>> (32-k), l = k;
123 | while ( (n & 1) === 0 ) { n >>>= 1; l--; }
124 | var m = gn[n>>>1];
125 | while ( n ) { n >>>= 1; if ( r !== u ) r = _Montgomery_reduce( r.square(), this ); }
126 | r = ( r !== u ) ? _Montgomery_reduce( r.multiply(m), this ) : m;
127 | t <<= l, j -= l;
128 | }
129 | else {
130 | if ( r !== u ) r = _Montgomery_reduce( r.square(), this );
131 | t <<= 1, j--;
132 | }
133 | }
134 | }
135 |
136 | // de-montgomerize result
137 | r = _Montgomery_reduce( r, this );
138 |
139 | return r;
140 | }
141 |
142 | function _Montgomery_reduce ( a, n ) {
143 | var alimbs = a.limbs, alimbcnt = alimbs.length,
144 | nlimbs = n.limbs, nlimbcnt = nlimbs.length,
145 | y = n.coefficient;
146 |
147 | _bigint_asm.sreset();
148 |
149 | var pA = _bigint_asm.salloc( alimbcnt<<2 ),
150 | pN = _bigint_asm.salloc( nlimbcnt<<2 ),
151 | pR = _bigint_asm.salloc( nlimbcnt<<2 );
152 |
153 | _bigint_asm.z( pR-pA+(nlimbcnt<<2), 0, pA );
154 |
155 | _bigint_heap.set( alimbs, pA>>2 );
156 | _bigint_heap.set( nlimbs, pN>>2 );
157 |
158 | _bigint_asm.mredc( pA, alimbcnt<<2, pN, nlimbcnt<<2, y, pR );
159 |
160 | var result = new BigNumber();
161 | result.limbs = new Uint32Array( _bigint_heap.subarray( pR>>2, (pR>>2)+nlimbcnt ) );
162 | result.bitLength = n.bitLength;
163 | result.sign = 1;
164 |
165 | return result;
166 | }
167 |
168 | var ModulusPrototype = Modulus.prototype = new BigNumber;
169 | ModulusPrototype.reduce = Modulus_reduce;
170 | ModulusPrototype.inverse = Modulus_inverse;
171 | ModulusPrototype.power = Modulus_power;
172 |
--------------------------------------------------------------------------------
/src/bignum/prime.js:
--------------------------------------------------------------------------------
1 | // Tests if the number supplied is a Miller-Rabin strong probable prime
2 | function _BigNumber_isMillerRabinProbablePrime ( rounds ) {
3 | var t = new BigNumber(this),
4 | s = 0;
5 | t.limbs[0] -= 1;
6 | while ( t.limbs[s>>5] === 0 ) s += 32;
7 | while ( ( ( t.limbs[s>>5] >> (s & 31) ) & 1 ) === 0 ) s++;
8 | t = t.slice(s);
9 |
10 | var m = new Modulus(this),
11 | m1 = this.subtract(BigNumber_ONE),
12 | a = new BigNumber(this),
13 | l = this.limbs.length-1;
14 | while ( a.limbs[l] === 0 ) l--;
15 |
16 | while ( --rounds >= 0 ) {
17 | Random_getValues(a.limbs);
18 | if ( a.limbs[0] < 2 ) a.limbs[0] += 2;
19 | while ( a.compare(m1) >= 0 ) a.limbs[l] >>>= 1;
20 |
21 | var x = m.power( a, t );
22 | if ( x.compare(BigNumber_ONE) === 0 ) continue;
23 | if ( x.compare(m1) === 0 ) continue;
24 |
25 | var c = s;
26 | while ( --c > 0 ) {
27 | x = x.square().divide(m).remainder;
28 | if ( x.compare(BigNumber_ONE) === 0 ) return false;
29 | if ( x.compare(m1) === 0 ) break;
30 | }
31 |
32 | if ( c === 0 ) return false;
33 | }
34 |
35 | return true;
36 | }
37 |
38 | function BigNumber_isProbablePrime ( paranoia ) {
39 | paranoia = paranoia || 80;
40 |
41 | var limbs = this.limbs,
42 | i = 0;
43 |
44 | // Oddity test
45 | // (50% false positive probability)
46 | if ( ( limbs[0] & 1 ) === 0 ) return false;
47 | if ( paranoia <= 1 ) return true;
48 |
49 | // Magic divisors (3, 5, 17) test
50 | // (~25% false positive probability)
51 | var s3 = 0, s5 = 0, s17 = 0;
52 | for ( i = 0; i < limbs.length; i++ ) {
53 | var l3 = limbs[i];
54 | while ( l3 ) {
55 | s3 += (l3 & 3);
56 | l3 >>>= 2;
57 | }
58 |
59 | var l5 = limbs[i];
60 | while ( l5 ) {
61 | s5 += (l5 & 3);
62 | l5 >>>= 2;
63 | s5 -= (l5 & 3);
64 | l5 >>>= 2;
65 | }
66 |
67 | var l17 = limbs[i];
68 | while ( l17 ) {
69 | s17 += (l17 & 15);
70 | l17 >>>= 4;
71 | s17 -= (l17 & 15);
72 | l17 >>>= 4;
73 | }
74 | }
75 | if ( !(s3 % 3) || !(s5 % 5) || !(s17 % 17) ) return false;
76 | if ( paranoia <= 2 ) return true;
77 |
78 | // Miller-Rabin test
79 | // (≤ 4^(-k) false positive probability)
80 | return _BigNumber_isMillerRabinProbablePrime.call( this, paranoia >>> 1 );
81 | }
82 |
83 | // Small primes for trail division
84 | var _primes = [ 2, 3 /* and so on, computed lazily */ ];
85 |
86 | // Returns an array populated with first n primes.
87 | function _small_primes ( n ) {
88 | if ( _primes.length >= n )
89 | return _primes.slice( 0, n );
90 |
91 | for ( var p = _primes[_primes.length-1] + 2; _primes.length < n; p += 2 ) {
92 | for ( var i = 0, d = _primes[i]; d*d <= p; d = _primes[++i] ) {
93 | if ( p % d == 0 ) break;
94 | }
95 | if ( d*d > p ) _primes.push(p);
96 | }
97 |
98 | return _primes;
99 | }
100 |
101 | // Returns strong pseudoprime of a specified bit length
102 | function BigNumber_randomProbablePrime ( bitlen, filter ) {
103 | var limbcnt = (bitlen + 31) >> 5,
104 | prime = new BigNumber({ sign: 1, bitLength: bitlen, limbs: limbcnt }),
105 | limbs = prime.limbs;
106 |
107 | // Number of small divisors to try that minimizes the total cost of the trial division
108 | // along with the first round of Miller-Rabin test for a certain bit length.
109 | var k = 10000;
110 | if ( bitlen <= 512 ) k = 2200;
111 | if ( bitlen <= 256 ) k = 600;
112 |
113 | var divisors = _small_primes(k),
114 | remainders = new Uint32Array(k);
115 |
116 | // Number of Miller-Rabin iterations for an error rate of less than 2^-80
117 | // Damgaard, Landrock, Pomerance: Average case error estimates for the strong probable prime test.
118 | var s = (bitlen * global.Math.LN2) | 0,
119 | r = 27;
120 | if ( bitlen >= 250 ) r = 12;
121 | if ( bitlen >= 450 ) r = 6;
122 | if ( bitlen >= 850 ) r = 3;
123 | if ( bitlen >= 1300 ) r = 2;
124 |
125 | while ( true ) {
126 | // populate `prime` with random bits, clamp to the appropriate bit length
127 | Random_getValues(limbs);
128 | limbs[0] |= 1;
129 | limbs[limbcnt-1] |= 1 << ((bitlen - 1) & 31);
130 | if ( bitlen & 31 ) limbs[limbcnt-1] &= pow2_ceil((bitlen + 1) & 31) - 1;
131 |
132 | // remainders from division to small primes
133 | remainders[0] = 1;
134 | for ( var i = 1; i < k; i++ ) {
135 | remainders[i] = prime.divide( divisors[i] ).remainder.valueOf();
136 | }
137 |
138 | // try no more than `s` subsequent candidates
139 | seek:
140 | for ( var j = 0; j < s; j += 2, limbs[0] += 2 ) {
141 | // check for small factors
142 | for ( var i = 1; i < k; i++ ) {
143 | if ( ( remainders[i] + j ) % divisors[i] === 0 ) continue seek;
144 | }
145 |
146 | // additional check just before the heavy lifting
147 | if ( typeof filter === 'function' && !filter(prime) ) continue;
148 |
149 | // proceed to Miller-Rabin test
150 | if ( _BigNumber_isMillerRabinProbablePrime.call( prime, r ) ) return prime;
151 | }
152 | }
153 | }
154 |
155 | BigNumberPrototype.isProbablePrime = BigNumber_isProbablePrime;
156 |
157 | BigNumber.randomProbablePrime = BigNumber_randomProbablePrime;
158 |
--------------------------------------------------------------------------------
/test/isaac.js:
--------------------------------------------------------------------------------
1 | /*
2 | module("ISAAC");
3 |
4 | ///////////////////////////////////////////////////////////////////////////////
5 |
6 | // Taken from http://burtleburtle.net/bob/rand/randvect.txt
7 |
8 | var isaac_vector = [
9 | 0x7a68710f, 0x6554abda, 0x90c10757, 0x0b5e435f, 0xaf7d1fb8, 0x01913fd3, 0x6a158d10, 0xb8f6fd4a,
10 | 0xc2b9aa36, 0x96da2655, 0xfe1e42d5, 0x56e6cd21, 0xd5b2d750, 0x7229ea81, 0x5de87abb, 0xb6b9d766,
11 | 0x1e16614c, 0x3b708f99, 0x5cf824cd, 0xa4ca0cf1, 0x62d31911, 0x7cdd662f, 0xcb9e1563, 0x79ae4c10,
12 | 0x080c79ec, 0x18080c8e, 0x4a0a283c, 0x3dde9f39, 0x09c36f90, 0xad567643, 0x08294766, 0xb4415f7d,
13 | 0x5597ec0f, 0x78ffa568, 0x8bace62e, 0x4188bfcd, 0xc87c8006, 0xafa92a6d, 0x50fc8194, 0xcae8deba,
14 | 0x33f6d7b1, 0x53245b79, 0x61119a5a, 0x7e315aeb, 0xe75b41c9, 0xd2a93b51, 0xec46b0b6, 0x1ed3ff4e,
15 | 0x5d023e65, 0xadf6bc23, 0xf7f58f7b, 0xe4f3a26a, 0x0c571a7d, 0xed35e5ee, 0xeadebeac, 0x30bcc764,
16 | 0x66f1e0ab, 0x826dfa89, 0x0d9c7e7e, 0xe7e26581, 0xd5990dfb, 0x02c9b944, 0x4112d96c, 0x3ff1e524,
17 | 0xc35e4580, 0xfdfef62d, 0xb83f957a, 0xbfc7f7cc, 0xb510ce0e, 0xcd7411a7, 0x04db4e13, 0x76904b6d,
18 | 0x08607f04, 0x3718d597, 0x46c0a6f5, 0x8406b137, 0x309bfb78, 0xf7d3f39f, 0x8c2f0d55, 0xc613f157,
19 | 0x127dd430, 0x72c9137d, 0x68a39358, 0x07c28cd1, 0x848f520a, 0xdd2dc1d5, 0x9388b13b, 0x28e7cb78,
20 | 0x03fb88f4, 0xb0b84e7b, 0x14c8009b, 0x884d6825, 0x21c171ec, 0x0809e494, 0x6a107589, 0x12595a19,
21 | 0x0bb3263f, 0x4d8fae82, 0x2a98121a, 0xb00960ba, 0x6708a2bc, 0x35a124b5, 0xbccaaeed, 0x294d37e5,
22 | 0xd405ded8, 0x9f39e2d9, 0x21835c4d, 0xe89b1a3b, 0x7364944b, 0xbd2e5024, 0x6a123f57, 0x34105a8c,
23 | 0x5ad0d3b0, 0xcc033ce3, 0xd51f093d, 0x56a001e3, 0x01a9bd70, 0x8891b3db, 0x13add922, 0x3d77d9a2,
24 | 0x0e7e0e67, 0xd73f72d4, 0x917bdec2, 0xa37f63ff, 0x23d74f4e, 0x3a6ce389, 0x0606cf9f, 0xde11ed34,
25 | 0x70cc94ae, 0xcb0eee4a, 0x13edc0cb, 0xfe29661c, 0xdb6dbe96, 0xb388d96c, 0x33bc405d, 0xa6d12101,
26 | 0x2f36fa86, 0x7ded386f, 0xe6344451, 0xcd57c7f7, 0x1b0dcdc1, 0xcd49ebdb, 0x9e8a51da, 0x12a0594b,
27 | 0x60d4d5f8, 0x91c8d925, 0xe43d0fbb, 0x5d2a542f, 0x451e7ec8, 0x2b36505c, 0x37c0ed05, 0x2364a1aa,
28 | 0x814bc24c, 0xe3a662d9, 0xf2b5cc05, 0xb8b0ccfc, 0xb058bafb, 0x3aea3dec, 0x0d028684, 0x64af0fef,
29 | 0x210f3925, 0xb67ec13a, 0x97166d14, 0xf7e1cdd0, 0x5adb60e7, 0xd5295ebc, 0x28833522, 0x60eda8da,
30 | 0x7bc76811, 0xac9fe69d, 0x30ab93ec, 0x03696614, 0x15e3a5b9, 0xecc5dc91, 0x1d3b8e97, 0x7275e277,
31 | 0x538e1f4e, 0x6cb167db, 0xa7a2f402, 0x2db35dfe, 0xa8bcc22d, 0xd8c58a6a, 0x6a529b0b, 0x0fd43963,
32 | 0xafc17a97, 0x943c3c74, 0x95138769, 0x6f4e0772, 0xb143b688, 0x3b18e752, 0x69d2e4ae, 0x8107c9ff,
33 | 0xcdbc62e2, 0x5781414f, 0x8b87437e, 0xa70e1101, 0x91dabc65, 0x4e232cd0, 0x229749b5, 0xd7386806,
34 | 0xb3c3f24b, 0x60dc5207, 0x0bdb9c30, 0x1a70e7e9, 0xf37c71d5, 0x44b89b08, 0xb4d2f976, 0xb40e27bc,
35 | 0xffdf8a80, 0x9c411a2a, 0xd0f7b37d, 0xef53cec4, 0xeca4d58a, 0x0b923200, 0xcf22e064, 0x8ebfa303,
36 | 0xf7cf814c, 0x32ae2a2b, 0xb5e13dae, 0xc998f9ff, 0x349947b0, 0x29cf72ce, 0x17e38f85, 0xf3b26129,
37 | 0xd45d6d81, 0x09b3ce98, 0x860536b8, 0xe5792e1b, 0x12ad6419, 0xf5f71c69, 0xcbc8b7c2, 0x8f651659,
38 | 0xa0cc74f3, 0xd78cb99e, 0x51c08d83, 0x29f55449, 0x002ed713, 0x38a824f3, 0x57161df6, 0x7452e319,
39 | 0x25890e2e, 0xc7442433, 0x4a5f6355, 0x6a83e1e0, 0x823cedb6, 0xf1d444eb, 0x88381097, 0x5de3743e,
40 | 0x46ca4f9a, 0xd8370487, 0xedec154a, 0x433f1afb, 0xf5fad54f, 0x98db2fb4, 0xe448e96d, 0xf650e4c8,
41 |
42 | 0x4bb5af29, 0x9d855e89, 0xc54cd95b, 0x46d95ca5, 0xef73fbf0, 0xf943f672, 0x86ba527f, 0x9d8d1908,
43 | 0xf3310c92, 0x05340e15, 0x07cffad9, 0x21e2547e, 0x8c17eff0, 0xd32be060, 0x8aba3ffb, 0x94d40125,
44 | 0xc5a87748, 0x824c2009, 0x73c0e762, 0xcdfec2af, 0x0e6c51b3, 0xa86f875e, 0xbc6172c7, 0xf7f395f1,
45 | 0x3f7579b3, 0x7aa114ed, 0x165b1015, 0xd531161a, 0xe36ef5bb, 0xdc153e5f, 0x1d0cb81b, 0xceffc147,
46 | 0x6079e4ce, 0xc3142d8f, 0xa617a083, 0xb54fed6f, 0xc3c7be2c, 0x02614abf, 0x6fb5ce56, 0xd21e796c,
47 | 0x2d0985de, 0xe9f84163, 0xc1a71e3c, 0x2887d96f, 0x57c4c925, 0x05efe294, 0x88157153, 0x9a30c4e8,
48 | 0x8854a0a1, 0x02503f7d, 0x0cd6ef81, 0x1da4f25a, 0xe8fa3860, 0x32e39273, 0x4c8652d6, 0x9ab3a42f,
49 | 0x9ead7f70, 0x836d8003, 0x6cbe7935, 0x721502dd, 0x5a48755c, 0x07497cae, 0xde462f4d, 0x92f57ea7,
50 | 0x1fe26ce0, 0x27c82282, 0xd6ec2f2b, 0x80c6e402, 0xce86fdfc, 0x52649d6c, 0xc798f047, 0x45bae606,
51 | 0x891aec49, 0x66c97340, 0x9ca45e1c, 0x4286619c, 0xf5f9cc3b, 0x4e823ad3, 0xc0d5d42a, 0xaee19096,
52 | 0x3d469303, 0xfe4cb380, 0xc9cd808c, 0x37a97df6, 0x308f751f, 0x276df0b4, 0xe5fbb9c7, 0x97ca2070,
53 | 0x88412761, 0x2ce5d3d5, 0xd7b43abe, 0xa30519ad, 0x26414ff3, 0xc5bde908, 0x275ead3a, 0x26ceb003,
54 | 0xbf1bd691, 0x037464c0, 0xe24124c0, 0x81d4cc5f, 0x484525e4, 0x1c3a4524, 0x9e7e4f04, 0xe1279bff,
55 | 0x6dd1943a, 0x403dae08, 0x82846526, 0xd5683858, 0x29322d0d, 0xa949bea2, 0x74096ae7, 0x85a13f85,
56 | 0x68235b9d, 0x8ef4bce6, 0x142a6e85, 0xdad1b22a, 0xb7546681, 0x959e234e, 0xfd8650d8, 0x3e730fa8,
57 | 0x56f55a71, 0xd20adf03, 0x7cdc78a2, 0x19047c79, 0x253b1d7a, 0x4389a84a, 0x0aeb8165, 0x9c15db3b,
58 | 0xaafef5a7, 0xbe8b06b2, 0xb5fe87c0, 0xe2a4ef71, 0xd9d711f9, 0xecfcf20b, 0x80fac4c2, 0xbbb8abc4,
59 | 0x239e3b0a, 0x858129a6, 0xd97cd348, 0x8a30738a, 0xc5b71937, 0xd649a428, 0x18c1ef9a, 0x75c08a36,
60 | 0xc921f94e, 0xdf9afa29, 0x040f7074, 0x72f5972f, 0x84ef01da, 0x2cb7b77f, 0x867027d7, 0x9ce0199d,
61 | 0x71865c4c, 0x7a36af93, 0x6c48ddd8, 0x19b48fd0, 0x75f4e9e2, 0x0084cfe5, 0x63bfd4d8, 0x9783cdee,
62 | 0x64f2632c, 0xf1b20eaf, 0xcc8bfa2d, 0x39ddf25a, 0x740e0066, 0x9ddb477f, 0x12b2cfb6, 0xd067fce5,
63 | 0x1a4b6a53, 0x001cdb95, 0x12c06908, 0x531ac6bf, 0x513c1764, 0xf7476978, 0x1be79937, 0x8a8dfaa3,
64 | 0x70a1660e, 0xfb737b1a, 0x3f28ee63, 0xc1a51375, 0x84bd6dd6, 0xe4a51d21, 0xeafed133, 0x22ae0582,
65 | 0x4d678f26, 0xf854b522, 0x31907d62, 0x4b55dd99, 0x04d3658a, 0x19c1e69c, 0xc6112fdd, 0xc66699fd,
66 | 0xa0eabe6b, 0x3724d4dc, 0x0d28fe52, 0x46819e2e, 0x96f703ac, 0x21182ca3, 0x2e7b022f, 0x31860f13,
67 | 0x1956b1e5, 0xe1322228, 0x08063a85, 0x1d964589, 0x94d90481, 0x53c078f3, 0x5afb43ae, 0x1e3437f7,
68 | 0x877eb7b4, 0x5d67133c, 0xa385cb2c, 0xb82f2703, 0xef05ee06, 0x931dd7e2, 0x10d210aa, 0xe21339cc,
69 | 0x479c3a22, 0x613b67b2, 0x33c5321c, 0xa5f48ac4, 0xba5590c8, 0xeb244925, 0xd0ef3cc9, 0xd8c423fb,
70 | 0x15cfcc5c, 0x1feb2e4f, 0x36ec0ea3, 0xdbef7d9f, 0xd5ec6bf4, 0x3d3dff8a, 0x1e04a7f7, 0x8766bb54,
71 | 0x9a1d7745, 0xc79a1749, 0xb8d2486d, 0x582e3014, 0xa82427f5, 0x65dfa427, 0xbc5654c1, 0xbd086f26,
72 | 0x0451516d, 0xff4cfc35, 0x81f2864d, 0x31860f05, 0xd0638e1a, 0xb059261d, 0x3d1e9150, 0x21e2a51c,
73 | 0x82d53d12, 0x1010b275, 0x786b2908, 0x4d3cfbda, 0x94a302f4, 0x95c85eaa, 0xd7e1c7be, 0x82ac484f
74 | ];
75 |
76 | test( "prng", function () {
77 | asmCrypto.ISAAC.seed(0);
78 | ok( "reset done" );
79 |
80 | asmCrypto.ISAAC.prng();
81 | for ( var i = 0; i < isaac_vector.length; i++ ) {
82 | equal( asmCrypto.ISAAC.rand(), isaac_vector[i], "isaac_vector["+i+"] is correct" );
83 | }
84 | });
85 | */
86 |
--------------------------------------------------------------------------------
/src/random/isaac.js:
--------------------------------------------------------------------------------
1 | /* ----------------------------------------------------------------------
2 | * Copyright (c) 2014 Artem S Vybornov
3 | *
4 | * Copyright (c) 2012 Yves-Marie K. Rinquin
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining
7 | * a copy of this software and associated documentation files (the
8 | * "Software"), to deal in the Software without restriction, including
9 | * without limitation the rights to use, copy, modify, merge, publish,
10 | * distribute, sublicense, and/or sell copies of the Software, and to
11 | * permit persons to whom the Software is furnished to do so, subject to
12 | * the following conditions:
13 | *
14 | * The above copyright notice and this permission notice shall be
15 | * included in all copies or substantial portions of the Software.
16 | *
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21 | * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22 | * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23 | * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 | *
25 | * ----------------------------------------------------------------------
26 | *
27 | * ISAAC is a cryptographically secure pseudo-random number generator
28 | * (or CSPRNG for short) designed by Robert J. Jenkins Jr. in 1996 and
29 | * based on RC4. It is designed for speed and security.
30 | *
31 | * ISAAC's informations & analysis:
32 | * http://burtleburtle.net/bob/rand/isaac.html
33 | * ISAAC's implementation details:
34 | * http://burtleburtle.net/bob/rand/isaacafa.html
35 | *
36 | * ISAAC succesfully passed TestU01
37 | */
38 |
39 | var ISAAC = ( function () {
40 | var m = new Uint32Array(256), // internal memory
41 | r = new Uint32Array(256), // result array
42 | acc = 0, // accumulator
43 | brs = 0, // last result
44 | cnt = 0, // counter
45 | gnt = 0; // generation counter
46 |
47 | /* private: randinit function, same as ISAAC reference implementation */
48 | function randinit() {
49 | var a, b, c, d, e, f, g, h;
50 |
51 | /* private mixing function */
52 | function mix () {
53 | a ^= b << 11; d = (d + a)|0; b = (b + c)|0;
54 | b ^= c >>> 2; e = (e + b)|0; c = (c + d)|0;
55 | c ^= d << 8; f = (f + c)|0; d = (d + e)|0;
56 | d ^= e >>> 16; g = (g + d)|0; e = (e + f)|0;
57 | e ^= f << 10; h = (h + e)|0; f = (f + g)|0;
58 | f ^= g >>> 4; a = (a + f)|0; g = (g + h)|0;
59 | g ^= h << 8; b = (b + g)|0; h = (h + a)|0;
60 | h ^= a >>> 9; c = (c + h)|0; a = (a + b)|0;
61 | }
62 |
63 | acc = brs = cnt = 0;
64 |
65 | // the golden ratio
66 | a = b = c = d = e = f = g = h = 0x9e3779b9;
67 |
68 | // scramble it
69 | for ( var i = 0; i < 4; i++ )
70 | mix();
71 |
72 | // mix it and combine with the internal state
73 | for ( var i = 0; i < 256; i += 8 ) {
74 | a = (a + r[i|0])|0; b = (b + r[i|1])|0;
75 | c = (c + r[i|2])|0; d = (d + r[i|3])|0;
76 | e = (e + r[i|4])|0; f = (f + r[i|5])|0;
77 | g = (g + r[i|6])|0; h = (h + r[i|7])|0;
78 | mix();
79 | m.set([a, b, c, d, e, f, g, h], i);
80 | }
81 |
82 | // mix it again
83 | for ( var i = 0; i < 256; i += 8 ) {
84 | a = (a + m[i|0])|0; b = (b + m[i|1])|0;
85 | c = (c + m[i|2])|0; d = (d + m[i|3])|0;
86 | e = (e + m[i|4])|0; f = (f + m[i|5])|0;
87 | g = (g + m[i|6])|0; h = (h + m[i|7])|0;
88 | mix();
89 | m.set([a, b, c, d, e, f, g, h], i);
90 | }
91 |
92 | // fill in the first set of results
93 | prng(1), gnt = 256;
94 | }
95 |
96 | /* public: seeding function */
97 | function seed ( s ) {
98 | var i, j, k, n, l;
99 |
100 | if ( !is_typed_array(s) ) {
101 | if ( is_number(s) ) {
102 | n = new FloatArray(1), n[0] = s;
103 | s = new Uint8Array(n.buffer);
104 | }
105 | else if ( is_string(s) ) {
106 | s = string_to_bytes(s);
107 | }
108 | else if ( is_buffer(s) ) {
109 | s = new Uint8Array(s);
110 | }
111 | else {
112 | throw new TypeError("bad seed type");
113 | }
114 | }
115 | else {
116 | s = new Uint8Array(s.buffer);
117 | }
118 |
119 | // preprocess the seed
120 | l = s.length;
121 | for ( j = 0; j < l; j += 1024 )
122 | {
123 | // xor each chunk of 1024 bytes with r, for randinit() to mix in
124 | for ( k = j, i = 0; ( i < 1024 ) && ( k < l ); k = j | (++i) ) {
125 | r[i >> 2] ^= ( s[k] << ( (i & 3) << 3 ) );
126 | }
127 | randinit();
128 | }
129 | }
130 |
131 | /* public: isaac generator, n = number of run */
132 | function prng ( n ) {
133 | n = n || 1;
134 |
135 | var i, x, y;
136 |
137 | while ( n-- ) {
138 | cnt = (cnt + 1)|0;
139 | brs = (brs + cnt)|0;
140 |
141 | for ( i = 0; i < 256; i += 4 ) {
142 | acc ^= acc << 13;
143 | acc = m[(i + 128) & 0xff] + acc | 0; x = m[i|0];
144 | m[i|0] = y = m[(x>>>2) & 0xff] + ( acc + brs | 0 ) | 0;
145 | r[i|0] = brs = m[(y>>>10) & 0xff] + x | 0;
146 |
147 | acc ^= acc >>> 6;
148 | acc = m[(i + 129) & 0xff] + acc | 0; x = m[i|1];
149 | m[i|1] = y = m[(x >>> 2) & 0xff] + ( acc + brs | 0 ) | 0;
150 | r[i|1] = brs = m[(y >>> 10) & 0xff] + x | 0;
151 |
152 | acc ^= acc << 2;
153 | acc = m[(i + 130) & 0xff] + acc | 0; x = m[i|2];
154 | m[i|2] = y = m[(x >>> 2) & 0xff] + ( acc + brs | 0 ) | 0;
155 | r[i|2] = brs = m[(y >>> 10) & 0xff] + x | 0;
156 |
157 | acc ^= acc >>> 16;
158 | acc = m[(i + 131) & 0xff] + acc | 0; x = m[i|3];
159 | m[i|3] = y = m[(x >>> 2) & 0xff] + (acc + brs | 0 ) | 0;
160 | r[i|3] = brs = m[(y >>> 10) & 0xff] + x | 0;
161 | }
162 | }
163 | }
164 |
165 | /* public: return a random number */
166 | function rand() {
167 | if ( !gnt-- )
168 | prng(1), gnt = 255;
169 |
170 | return r[gnt];
171 | }
172 |
173 | /* return class object */
174 | return {
175 | 'seed': seed,
176 | 'prng': prng,
177 | 'rand': rand
178 | };
179 | })();
180 |
--------------------------------------------------------------------------------
/test/rsa.js:
--------------------------------------------------------------------------------
1 | module("RSA");
2 |
3 | ///////////////////////////////////////////////////////////////////////////////
4 |
5 | if ( typeof asmCrypto.RSA !== 'undefined' )
6 | {
7 | var pubkey = [
8 | asmCrypto.hex_to_bytes('c13f894819c136381a94c193e619851ddfcde5eca770003ec354f3142e0f61f0676d7d4215cc7a13b06e0744aa8316c9c3766cbefa30b2346fba8f1236d7e6548cf87d9578e6904fc4291e096a2737fcd96624f72e762793505f9dfc5fa17b44611add54f5c00bf54373d720cb6f4e5cabae36c4442b39dbf49158414547f453'),
9 | asmCrypto.hex_to_bytes('10001')
10 | ];
11 |
12 | var privkey = [
13 | asmCrypto.hex_to_bytes('c13f894819c136381a94c193e619851ddfcde5eca770003ec354f3142e0f61f0676d7d4215cc7a13b06e0744aa8316c9c3766cbefa30b2346fba8f1236d7e6548cf87d9578e6904fc4291e096a2737fcd96624f72e762793505f9dfc5fa17b44611add54f5c00bf54373d720cb6f4e5cabae36c4442b39dbf49158414547f453'),
14 | 65537,
15 | asmCrypto.hex_to_bytes('75497aa8a7f8fc4f50d2b82a6b9d518db027e7449adaff4b18829685c8eecd227ba3984263b896df1c55ab53a1a9ae4b06b6f9896f8fde98b4b725de882ac13fc11b614cb2cc81bcc69b9ad167dda093c5c6637754acd0ec9e9845b1b2244d597c9f63d7ea076bda19feadcdb3bd1ba9018915fec981657fb7a4301cb87a3e1'),
16 | asmCrypto.hex_to_bytes('ef2f8d91d7cd96710d6b3b5ea1b6762b4214efe329e7d0609ab8419744ef8620391e423d5890c864aebb36c0daf5035d27f3427e6a84fde36466a14b56ad1cfb'),
17 | asmCrypto.hex_to_bytes('ced5477e0acb9c836c3c54e33268e064ce8cdfd40452c8b87ab838b36b498ae22fdbdb331f59f61dd3ca1512143e77a68f8f2400dbe9e576a000084e6fcbb689'),
18 | asmCrypto.hex_to_bytes('227882f9a2d5513a27c9ed7b7ce8d3ecf61018666fb2a5f85633f9d7f82a60f521e6377ba9d8ebd87eca2260f6ed5ab7c13b30b91156eb542b331349cd4b13a3'),
19 | asmCrypto.hex_to_bytes('4dea2a3460fcb2c90f4ceaed6b5ff6a802e72eaa3fb6afc64ef476e79fd2e46eb078b1ea60351371c906a7495836effbdeb89d67757076f068f59a2b7211db81'),
20 | asmCrypto.hex_to_bytes('261a93613a93e438fa62858758d1db3b3db8366319517c039acfcc0ce04cd0d7349d7e8d8cb0e8a05ac966d04c18c81c49025de2b50bb87f78facccd19cd8602')
21 | ];
22 |
23 | test( "asmCrypto.RSA", function () {
24 | equal( typeof asmCrypto.RSA, 'object', "RSA exported" );
25 | });
26 |
27 | test( "asmCrypto.RSA.generateKey", function () {
28 | var key = asmCrypto.RSA.generateKey( 1024, 3 );
29 | ok( key, "generateKey" );
30 |
31 | var m = new asmCrypto.Modulus( key[0] ),
32 | e = new asmCrypto.BigNumber( key[1] ),
33 | d = new asmCrypto.BigNumber( key[2] ),
34 | p = new asmCrypto.BigNumber( key[3] ),
35 | q = new asmCrypto.BigNumber( key[4] ),
36 | dp = new asmCrypto.BigNumber( key[5] ),
37 | dq = new asmCrypto.BigNumber( key[6] ),
38 | qi = new asmCrypto.BigNumber( key[7] );
39 |
40 | equal( p.multiply(q).toString(16), m.toString(16), "m == p*q" );
41 | equal( e.multiply(d).divide(p.subtract(1).multiply(q.subtract(1))).remainder.toString(16), '1', "e*d == 1 mod (p-1)(q-1)" );
42 | equal( d.divide(p.subtract(1)).remainder.toString(16), dp.toString(16), "dp == d mod (p-1)" );
43 | equal( d.divide(q.subtract(1)).remainder.toString(16), dq.toString(16), "dq == d mod (q-1)" );
44 | equal( qi.multiply(q).divide(p).remainder.toString(16), '1', "qi*q == 1 mod p" );
45 | equal( m.slice(m.bitLength-1).valueOf(), 1, "m highest bit is 1" );
46 | });
47 | }
48 | else
49 | {
50 | skip( "asmCrypto.RSA" );
51 | }
52 |
53 | ///////////////////////////////////////////////////////////////////////////////
54 |
55 | if ( typeof asmCrypto.RSA_RAW !== 'undefined' )
56 | {
57 | test( "asmCrypto.RSA_RAW.encrypt", function () {
58 | var text = String.fromCharCode(1);
59 |
60 | var ciphertext = asmCrypto.RSA_RAW.encrypt( text, pubkey );
61 | equal( asmCrypto.bytes_to_hex(ciphertext).replace(/^0+/,''), '1', "ident encrypt" );
62 |
63 | var result = asmCrypto.RSA_RAW.decrypt( ciphertext, privkey );
64 | equal( asmCrypto.bytes_to_hex(result).replace(/^0+/,''), '1', "ident decrypt" );
65 | });
66 | }
67 | else
68 | {
69 | skip( "asmCrypto.RSA_RAW" );
70 | }
71 |
72 | ///////////////////////////////////////////////////////////////////////////////
73 |
74 | if ( typeof asmCrypto.RSA_OAEP_SHA256 !== 'undefined' )
75 | {
76 | test( "asmCrypto.RSA_OAEP_SHA256 encrypt/decrypt", function () {
77 | var cleartext = asmCrypto.string_to_bytes('HelloWorld!');
78 |
79 | var ciphertext = asmCrypto.RSA_OAEP_SHA256.encrypt( cleartext, pubkey, 'test' );
80 | ok( ciphertext, "encrypt" );
81 |
82 | var result = asmCrypto.RSA_OAEP_SHA256.decrypt( ciphertext, privkey, 'test' );
83 | equal( asmCrypto.bytes_to_string(result), 'HelloWorld!', "decrypt" );
84 | });
85 | }
86 | else
87 | {
88 | skip( "asmCrypto.RSA_OAEP_SHA256" );
89 | }
90 |
91 | ///////////////////////////////////////////////////////////////////////////////
92 |
93 | if ( typeof asmCrypto.RSA_PSS_SHA256 !== 'undefined' )
94 | {
95 | test( "asmCrypto.RSA_PSS_SHA256 sign/verify", function () {
96 | var text = 'HelloWorld!HelloWorld!HelloWorld!HelloWorld!HelloWorld!HelloWorld!HelloWorld!HelloWorld!';
97 |
98 | var signature = asmCrypto.RSA_PSS_SHA256.sign( text, privkey );
99 | ok( signature, "sign" );
100 |
101 | var result = asmCrypto.RSA_PSS_SHA256.verify( signature, text, pubkey );
102 | ok( result, "verify" );
103 | });
104 |
105 | test( "asmCrypto.RSA_PSS_SHA256 verify OpenSSL-signed-data", function () {
106 | var key = [
107 | asmCrypto.hex_to_bytes('f30be5ce8941c8e6e764c78d12f3ce6e02a0dea03577bc0c16029de258321b74ceb43ea94f768aec900011c78eb247ab0e94b4477ea8f086ba7b5ce4b03c0ad7e0bf2f54ed509a536a0f179e27db539f729b38a279873f7b3a360690c8390e289dedca6da1ba232d8edc3c1eb229e1072716ddf3ef88caf4a824c152d6ad38f1'),
108 | 65537
109 | /*
110 | asmCrypto.hex_to_bytes('a2f4032c2ad2b4843bf851e2c0263eed7b4da875f9e3416d4904901ec5cb32a56a416711d5794143c278897326b5595fd2f2d8bc66ab96387ea75f6ce4cc1ce7ba0269a49ce03eb4aea16ca914938e88e5398b10b314276ba9f3f2e448a5f643515ee591cb4c4c5270edccacf7e5b88f86a0c08dc05311513a4ed01802de2511'),
111 | asmCrypto.hex_to_bytes('fc592285e370d57900bfd2f8c66b15274b3381ca7ec485091d5aa0092ca8f2b97f8796e608a2fc6aa1df3647b10198c49801e3201fefa72ef9d7ccafcdae5d37'),
112 | asmCrypto.hex_to_bytes('f6904d99d7cf9f1237c6798e5343fe730149be31e0363bf33039af84a09b5e9d0dd71239384b6cf6421e4ad41097b2cd09fd0114eb29a4339c433f37d7286f17'),
113 | asmCrypto.hex_to_bytes('252e1ce00d3abab9315b12028579918c50902e375fa624d3caf7674cf2bf91c3b2fe8f4525509e5037b9638dfc8e77abbf99c7951c1f7b4a78954b1b3bfaccd1'),
114 | asmCrypto.hex_to_bytes('9f036da89c10208cc53fd14142de0509f278b69abff8fa2cda9b3961159b5e2777b78edf2c3928aaa0f59c58abe2c9c3867f8ee508ccb04340b1f5e17377763d'),
115 | asmCrypto.hex_to_bytes('c07e9ca15c2cc38cc4faab0729403e02b33982b7d1219e15cd74614f3485437d2c800d66a0c368b3cf36513e4b1e05d31d7e0186f00cf036433e35f13b5cfda8')
116 | */
117 | ];
118 |
119 | var text = 'Hello There!';
120 |
121 | var signature = asmCrypto.hex_to_bytes('A68BE713861409B4E536C12066B3D30650C7578F9B7AB61C1A302B42ECA14D58AE11899BC55FCB838F0AE06B99381DE26CE8D6318BD59BBFC4FFF56A995E9EFB0306FF105766F508297D1E74F22648B6BD66C18E06F4748BD258358ECB5BB722AC4AFFA146C04EE7BE84AD77ED2A84B5458D6CA4A7DA4D86DAB3F2B39FD647F4');
122 |
123 | var saltlen = 32;
124 |
125 | var result = asmCrypto.RSA_PSS_SHA256.verify( signature, text, key, saltlen );
126 | ok( result, "verify" );
127 | });
128 | }
129 | else
130 | {
131 | skip( "asmCrypto.RSA_PSS_SHA256" );
132 | }
133 |
--------------------------------------------------------------------------------
/src/random/random.js:
--------------------------------------------------------------------------------
1 | var _global_console = global.console,
2 | _global_date_now = global.Date.now,
3 | _global_math_random = global.Math.random,
4 | _global_performance = global.performance,
5 | _global_crypto = global.crypto || global.msCrypto,
6 | _global_crypto_getRandomValues;
7 |
8 | if ( _global_crypto !== undefined )
9 | _global_crypto_getRandomValues = _global_crypto.getRandomValues;
10 |
11 | var _isaac_rand = ISAAC.rand,
12 | _isaac_seed = ISAAC.seed,
13 | _isaac_counter = 0,
14 | _isaac_weak_seeded = false,
15 | _isaac_seeded = false;
16 |
17 | var _random_estimated_entropy = 0,
18 | _random_required_entropy = 256,
19 | _random_allow_weak = false,
20 | _random_skip_system_rng_warning = false,
21 | _random_warn_callstacks = {};
22 |
23 | var _hires_now;
24 | if ( _global_performance !== undefined ) {
25 | _hires_now = function () { return 1000 * _global_performance.now() | 0 };
26 | }
27 | else {
28 | var _hires_epoch = 1000 * _global_date_now() | 0;
29 | _hires_now = function () { return 1000 * _global_date_now() - _hires_epoch | 0 };
30 | }
31 |
32 | /**
33 | * weak_seed
34 | *
35 | * Seeds RNG with native `crypto.getRandomValues` output or with high-resolution
36 | * time and single `Math.random()` value, and various other sources.
37 | *
38 | * We estimate this may give at least ~50 bits of unpredictableness,
39 | * but this has not been analysed thoroughly or precisely.
40 | */
41 | function Random_weak_seed () {
42 | if ( _global_crypto !== undefined ) {
43 | buffer = new Uint8Array(32);
44 | _global_crypto_getRandomValues.call( _global_crypto, buffer );
45 |
46 | _isaac_seed(buffer);
47 | }
48 | else {
49 | // Some clarification about brute-force attack cost:
50 | // - entire bitcoin network operates at ~10^16 hash guesses per second;
51 | // - each PBKDF2 iteration requires the same number of hashing operations as bitcoin nonce guess;
52 | // - attacker having such a hashing power is able to break worst-case 50 bits of the randomness in ~3 hours;
53 | // Sounds sad though attacker having such a hashing power more likely would prefer to mine bitcoins.
54 | var buffer = new FloatArray(3),
55 | i, t;
56 |
57 | buffer[0] = _global_math_random();
58 | buffer[1] = _global_date_now();
59 | buffer[2] = _hires_now();
60 |
61 | buffer = new Uint8Array(buffer.buffer);
62 |
63 | var pbkdf2 = get_pbkdf2_hmac_sha256_instance();
64 | for ( i = 0; i < 100; i++ ) {
65 | buffer = pbkdf2.reset( { password: buffer } ).generate( global.location.href, 1000, 32 ).result;
66 | t = _hires_now();
67 | buffer[0] ^= t >>> 24, buffer[1] ^= t >>> 16, buffer[2] ^= t >>> 8, buffer[3] ^= t;
68 | }
69 |
70 | _isaac_seed(buffer);
71 | }
72 |
73 | _isaac_counter = 0;
74 |
75 | _isaac_weak_seeded = true;
76 | }
77 |
78 | /**
79 | * seed
80 | *
81 | * Seeds PRNG with supplied random values if these values have enough entropy.
82 | *
83 | * A false return value means the RNG is currently insecure; however a true
84 | * return value does not mean it is necessarily secure (depending on how you
85 | * collected the seed) though asmCrypto will be forced to assume this.
86 | *
87 | * The input buffer will be zeroed to discourage reuse. You should not copy it
88 | * or use it anywhere else before passing it into this function.
89 | *
90 | * **DISCLAIMER!** Seeding with a poor values is an easiest way shoot your legs, so
91 | * do not seed until you're know what entropy is and how to obtail high-quality random values,
92 | * **DO NOT SEED WITH CONSTANT VALUE! YOU'LL GET NO RANDOMNESS FROM CONSTANT!**
93 | */
94 | function Random_seed ( seed ) {
95 | if ( !is_buffer(seed) && !is_typed_array(seed) )
96 | throw new TypeError("bad seed type");
97 |
98 | var bpos = seed.byteOffest || 0,
99 | blen = seed.byteLength || seed.length,
100 | buff = new Uint8Array( ( seed.buffer || seed ), bpos, blen );
101 |
102 | _isaac_seed(buff);
103 |
104 | _isaac_counter = 0;
105 |
106 | // don't let the user use these bytes again
107 | var nonzero = 0;
108 | for ( var i = 0; i < buff.length; i++ ) {
109 | nonzero |= buff[i];
110 | buff[i] = 0;
111 | }
112 |
113 | if ( nonzero !== 0 ) {
114 | // TODO we could make a better estimate, but half-length is a prudent
115 | // simple measure that seems unlikely to over-estimate
116 | _random_estimated_entropy += 4 * blen;
117 | }
118 |
119 | _isaac_seeded = ( _random_estimated_entropy >= _random_required_entropy );
120 |
121 | return _isaac_seeded;
122 | }
123 |
124 | /**
125 | * getValues
126 | *
127 | * Populates the buffer with cryptographically secure random values. These are
128 | * calculated using `crypto.getRandomValues` if it is available, as well as our
129 | * own ISAAC PRNG implementation.
130 | *
131 | * If the former is not available (older browsers such as IE10 [1]), then the
132 | * latter *must* be seeded using `Random.seed`, unless `asmCrypto.random.allowWeak` is true.
133 | *
134 | * *We assume the system RNG is strong*; if you cannot afford this risk, then
135 | * you should also seed ISAAC using `Random.seed`. This is advisable for very
136 | * important situations, such as generation of long-term secrets. See also [2].
137 | *
138 | * [1] https://developer.mozilla.org/en-US/docs/Web/API/window.crypto.getRandomValues
139 | * [2] https://en.wikipedia.org/wiki/Dual_EC_DRBG
140 | *
141 | * In all cases, we opportunistically seed using various arbitrary sources
142 | * such as high-resolution time and one single value from the insecure
143 | * Math.random(); however this is not reliable as a strong security measure.
144 | */
145 | function Random_getValues ( buffer ) {
146 | // opportunistically seed ISAAC with a weak seed; this hopefully makes an
147 | // attack harder in the case where the system RNG is weak *and* we haven't
148 | // seeded ISAAC. but don't make any guarantees to the user about this.
149 | if ( !_isaac_weak_seeded )
150 | Random_weak_seed();
151 |
152 | // if we have no strong sources then the RNG is weak, handle it
153 | if ( !_isaac_seeded && _global_crypto === undefined ) {
154 | if ( !_random_allow_weak )
155 | throw new SecurityError("No strong PRNGs available. Use asmCrypto.random.seed().");
156 |
157 | if ( _global_console !== undefined )
158 | _global_console.error("No strong PRNGs available; your security is greatly lowered. Use asmCrypto.random.seed().");
159 | }
160 |
161 | // separate warning about assuming system RNG strong
162 | if ( !_random_skip_system_rng_warning && !_isaac_seeded && _global_crypto !== undefined && _global_console !== undefined ) {
163 | // Hacky way to get call stack
164 | var s = new Error().stack;
165 | _random_warn_callstacks[s] |= 0;
166 | if ( !_random_warn_callstacks[s]++ )
167 | _global_console.warn("asmCrypto PRNG not seeded; your security relies on your system PRNG. If this is not acceptable, use asmCrypto.random.seed().");
168 | }
169 |
170 | // proceed to get random values
171 | if ( !is_buffer(buffer) && !is_typed_array(buffer) )
172 | throw new TypeError("unexpected buffer type");
173 |
174 | var bpos = buffer.byteOffset || 0,
175 | blen = buffer.byteLength || buffer.length,
176 | bytes = new Uint8Array( ( buffer.buffer || buffer ), bpos, blen ),
177 | i, r;
178 |
179 | // apply system rng
180 | if ( _global_crypto !== undefined )
181 | _global_crypto_getRandomValues.call( _global_crypto, bytes );
182 |
183 | // apply isaac rng
184 | for ( i = 0; i < blen; i++ ) {
185 | if ( (i & 3) === 0 ) {
186 | if ( _isaac_counter >= 0x10000000000 ) Random_weak_seed();
187 | r = _isaac_rand();
188 | _isaac_counter++;
189 | }
190 | bytes[i] ^= r;
191 | r >>>= 8;
192 | }
193 | }
194 |
195 | /**
196 | * getNumber
197 | *
198 | * A drop-in `Math.random` replacement.
199 | * Intended for prevention of random material leakage out of the user's host.
200 | */
201 | function Random_getNumber () {
202 | if ( !_isaac_weak_seeded || _isaac_counter >= 0x10000000000 )
203 | Random_weak_seed();
204 |
205 | var n = ( 0x100000 * _isaac_rand() + ( _isaac_rand() >>> 12 ) ) / 0x10000000000000;
206 | _isaac_counter += 2;
207 |
208 | return n;
209 | }
210 |
--------------------------------------------------------------------------------
/src/aes/naes.js:
--------------------------------------------------------------------------------
1 | function AES ( options ) {
2 | this.BLOCK_SIZE = _aes_block_size;
3 |
4 | options = options || {};
5 |
6 | this.heap = _heap_init( Uint8Array, options ).subarray( AES_asm.HEAP_DATA );
7 | this.asm = options.asm || AES_asm( global, null, this.heap.buffer );
8 | this.mode = null;
9 | this.key = null;
10 |
11 | this.reset( options );
12 | }
13 |
14 | function AES_set_key ( key ) {
15 | if ( key !== undefined ) {
16 | if ( is_buffer(key) || is_bytes(key) ) {
17 | key = new Uint8Array(key);
18 | }
19 | else if ( is_string(key) ) {
20 | key = string_to_bytes(key);
21 | }
22 | else {
23 | throw new TypeError("unexpected key type");
24 | }
25 |
26 | var keylen = key.length;
27 | if ( keylen !== 16 && keylen !== 24 && keylen !== 32 )
28 | throw new IllegalArgumentError("illegal key size");
29 |
30 | var keyview = new DataView( key.buffer, key.byteOffset, key.byteLength );
31 | this.asm.set_key(
32 | keylen >> 2,
33 | keyview.getUint32(0),
34 | keyview.getUint32(4),
35 | keyview.getUint32(8),
36 | keyview.getUint32(12),
37 | keylen > 16 ? keyview.getUint32(16) : 0,
38 | keylen > 16 ? keyview.getUint32(20) : 0,
39 | keylen > 24 ? keyview.getUint32(24) : 0,
40 | keylen > 24 ? keyview.getUint32(28) : 0
41 | );
42 |
43 | this.key = key;
44 | }
45 | else if ( !this.key ) {
46 | throw new Error("key is required");
47 | }
48 | }
49 |
50 | function AES_set_iv ( iv ) {
51 | if ( iv !== undefined ) {
52 | if ( is_buffer(iv) || is_bytes(iv) ) {
53 | iv = new Uint8Array(iv);
54 | }
55 | else if ( is_string(iv) ) {
56 | iv = string_to_bytes(iv);
57 | }
58 | else {
59 | throw new TypeError("unexpected iv type");
60 | }
61 |
62 | if ( iv.length !== _aes_block_size )
63 | throw new IllegalArgumentError("illegal iv size");
64 |
65 | var ivview = new DataView( iv.buffer, iv.byteOffset, iv.byteLength );
66 |
67 | this.iv = iv;
68 | this.asm.set_iv( ivview.getUint32(0), ivview.getUint32(4), ivview.getUint32(8), ivview.getUint32(12) );
69 | }
70 | else {
71 | this.iv = null;
72 | this.asm.set_iv( 0, 0, 0, 0 );
73 | }
74 | }
75 |
76 | function AES_set_padding ( padding ) {
77 | if ( padding !== undefined ) {
78 | this.padding = !!padding;
79 | }
80 | else {
81 | this.padding = true;
82 | }
83 | }
84 |
85 | function AES_reset ( options ) {
86 | options = options || {};
87 |
88 | this.result = null;
89 | this.pos = 0;
90 | this.len = 0;
91 |
92 | AES_set_key.call( this, options.key );
93 | if ( this.hasOwnProperty('iv') ) AES_set_iv.call( this, options.iv );
94 | if ( this.hasOwnProperty('padding') ) AES_set_padding.call( this, options.padding );
95 |
96 | return this;
97 | }
98 |
99 | function AES_Encrypt_process ( data ) {
100 | if ( is_string(data) )
101 | data = string_to_bytes(data);
102 |
103 | if ( is_buffer(data) )
104 | data = new Uint8Array(data);
105 |
106 | if ( !is_bytes(data) )
107 | throw new TypeError("data isn't of expected type");
108 |
109 | var asm = this.asm,
110 | heap = this.heap,
111 | amode = AES_asm[this.mode+'_ENC'],
112 | hpos = AES_asm.HEAP_DATA,
113 | ks = this.key.length >> 2,
114 | pos = this.pos,
115 | len = this.len,
116 | dpos = 0,
117 | dlen = data.length || 0,
118 | rpos = 0,
119 | rlen = _aes_block_size * Math.floor( ( len + dlen ) / _aes_block_size ),
120 | wlen = 0;
121 |
122 | var result = new Uint8Array(rlen);
123 |
124 | while ( dlen > 0 ) {
125 | wlen = _heap_write( heap, pos+len, data, dpos, dlen );
126 | len += wlen;
127 | dpos += wlen;
128 | dlen -= wlen;
129 |
130 | wlen = asm.cipher( ks, amode, hpos + pos, len );
131 |
132 | result.set( heap.subarray( pos, pos + wlen ), rpos );
133 | rpos += wlen;
134 |
135 | if ( wlen < len ) {
136 | pos += wlen;
137 | len -= wlen;
138 | } else {
139 | pos = 0;
140 | len = 0;
141 | }
142 | }
143 |
144 | this.result = result;
145 | this.pos = pos;
146 | this.len = len;
147 |
148 | return this;
149 | }
150 |
151 | function AES_Encrypt_finish ( data ) {
152 | var presult = null,
153 | prlen = 0;
154 |
155 | if ( data !== undefined ) {
156 | presult = AES_Encrypt_process.call( this, data ).result;
157 | prlen = presult.length;
158 | }
159 |
160 | var asm = this.asm,
161 | heap = this.heap,
162 | amode = AES_asm[this.mode+'_ENC'],
163 | hpos = AES_asm.HEAP_DATA,
164 | ks = this.key.length >> 2,
165 | pos = this.pos,
166 | len = this.len,
167 | plen = _aes_block_size - len % _aes_block_size,
168 | rlen = len;
169 |
170 | if ( this.hasOwnProperty('padding') ) {
171 | if ( this.padding ) {
172 | for ( var p = 0; p < plen; ++p ) heap[ pos + len + p ] = plen;
173 | len += plen;
174 | rlen = len;
175 | }
176 | else if ( len % _aes_block_size ) {
177 | throw new IllegalArgumentError("data length must be a multiple of " + _aes_block_size);
178 | }
179 | }
180 | else {
181 | len += plen;
182 | }
183 |
184 | var result = new Uint8Array( prlen + rlen );
185 |
186 | if ( prlen > 0 ) {
187 | result.set( presult );
188 | }
189 |
190 | if ( len > 0 ) {
191 | asm.cipher( ks, amode, hpos + pos, len );
192 | result.set( heap.subarray( pos, pos + rlen ), prlen );
193 | }
194 |
195 | this.result = result;
196 | this.pos = 0;
197 | this.len = 0;
198 |
199 | return this;
200 | }
201 |
202 | function AES_Decrypt_process ( data ) {
203 | if ( is_string(data) )
204 | data = string_to_bytes(data);
205 |
206 | if ( is_buffer(data) )
207 | data = new Uint8Array(data);
208 |
209 | if ( !is_bytes(data) )
210 | throw new TypeError("data isn't of expected type");
211 |
212 | var asm = this.asm,
213 | heap = this.heap,
214 | amode = AES_asm[this.mode+'_DEC'],
215 | hpos = AES_asm.HEAP_DATA,
216 | ks = this.key.length >> 2,
217 | pos = this.pos,
218 | len = this.len,
219 | dpos = 0,
220 | dlen = data.length || 0,
221 | rpos = 0,
222 | rlen = _aes_block_size * Math.floor( ( len + dlen ) / _aes_block_size ),
223 | plen = 0,
224 | wlen = 0;
225 |
226 | if ( this.hasOwnProperty('padding') && this.padding ) {
227 | plen = len + dlen - rlen || _aes_block_size;
228 | rlen -= plen;
229 | }
230 |
231 | var result = new Uint8Array(rlen);
232 |
233 | while ( dlen > 0 ) {
234 | wlen = _heap_write( heap, pos+len, data, dpos, dlen );
235 | len += wlen;
236 | dpos += wlen;
237 | dlen -= wlen;
238 |
239 | wlen = asm.cipher( ks, amode, hpos + pos, len - ( !dlen ? plen : 0 ) );
240 |
241 | result.set( heap.subarray( pos, pos + wlen ), rpos );
242 | rpos += wlen;
243 |
244 | if ( wlen < len ) {
245 | pos += wlen;
246 | len -= wlen;
247 | } else {
248 | pos = 0;
249 | len = 0;
250 | }
251 | }
252 |
253 | this.result = result;
254 | this.pos = pos;
255 | this.len = len;
256 |
257 | return this;
258 | }
259 |
260 | function AES_Decrypt_finish ( data ) {
261 | var presult = null,
262 | prlen = 0;
263 |
264 | if ( data !== undefined ) {
265 | presult = AES_Decrypt_process.call( this, data ).result;
266 | prlen = presult.length;
267 | }
268 |
269 | var asm = this.asm,
270 | heap = this.heap,
271 | amode = AES_asm[this.mode+'_DEC'],
272 | hpos = AES_asm.HEAP_DATA,
273 | ks = this.key.length >> 2,
274 | pos = this.pos,
275 | len = this.len,
276 | rlen = len;
277 |
278 | if ( len > 0 ) {
279 | if ( len % _aes_block_size ) {
280 | if ( this.hasOwnProperty('padding') ) {
281 | throw new IllegalArgumentError("data length must be a multiple of " + _aes_block_size);
282 | } else {
283 | len += _aes_block_size - ( len % _aes_block_size );
284 | }
285 | }
286 |
287 | asm.cipher( ks, amode, hpos + pos, len );
288 |
289 | if ( this.hasOwnProperty('padding') && this.padding ) {
290 | rlen -= heap[ pos + rlen - 1 ]; // FIXME check padding is correct
291 | }
292 | }
293 |
294 | var result = new Uint8Array( prlen + rlen );
295 |
296 | if ( prlen > 0 ) {
297 | result.set( presult );
298 | }
299 |
300 | if ( rlen > 0 ) {
301 | result.set( heap.subarray( pos, pos + rlen ), prlen );
302 | }
303 |
304 | this.result = result;
305 | this.pos = 0;
306 | this.len = 0;
307 |
308 | return this;
309 | }
310 |
--------------------------------------------------------------------------------
/src/rsa/pkcs1.js:
--------------------------------------------------------------------------------
1 | function RSA_OAEP ( options ) {
2 | options = options || {};
3 |
4 | if ( !options.hash )
5 | throw new SyntaxError("option 'hash' is required");
6 |
7 | if ( !options.hash.HASH_SIZE )
8 | throw new SyntaxError("option 'hash' supplied doesn't seem to be a valid hash function");
9 |
10 | this.hash = options.hash;
11 |
12 | this.label = null;
13 |
14 | this.reset(options);
15 | }
16 |
17 | function RSA_OAEP_reset ( options ) {
18 | options = options || {};
19 |
20 | var label = options.label;
21 | if ( label !== undefined ) {
22 | if ( is_buffer(label) || is_bytes(label) ) {
23 | label = new Uint8Array(label);
24 | }
25 | else if ( is_string(label) ) {
26 | label = string_to_bytes(label);
27 | }
28 | else {
29 | throw new TypeError("unexpected label type");
30 | }
31 |
32 | this.label = ( label.length > 0 ) ? label : null;
33 | }
34 | else {
35 | this.label = null;
36 | }
37 |
38 | RSA_reset.call( this, options );
39 | }
40 |
41 | function RSA_OAEP_encrypt ( data ) {
42 | if ( !this.key )
43 | throw new IllegalStateError("no key is associated with the instance");
44 |
45 | var key_size = Math.ceil( this.key[0].bitLength / 8 ),
46 | hash_size = this.hash.HASH_SIZE,
47 | data_length = data.byteLength || data.length || 0,
48 | ps_length = key_size - data_length - 2*hash_size - 2;
49 |
50 | if ( data_length > key_size - 2*this.hash.HASH_SIZE - 2 )
51 | throw new IllegalArgumentError("data too large");
52 |
53 | var message = new Uint8Array(key_size),
54 | seed = message.subarray( 1, hash_size + 1 ),
55 | data_block = message.subarray( hash_size + 1 );
56 |
57 | if ( is_bytes(data) ) {
58 | data_block.set( data, hash_size + ps_length + 1 );
59 | }
60 | else if ( is_buffer(data) ) {
61 | data_block.set( new Uint8Array(data), hash_size + ps_length + 1 );
62 | }
63 | else if ( is_string(data) ) {
64 | data_block.set( string_to_bytes(data), hash_size + ps_length + 1 );
65 | }
66 | else {
67 | throw new TypeError("unexpected data type");
68 | }
69 |
70 | data_block.set( this.hash.reset().process( this.label || '' ).finish().result, 0 );
71 | data_block[ hash_size + ps_length ] = 1;
72 |
73 | Random_getValues(seed);
74 |
75 | var data_block_mask = RSA_MGF1_generate.call( this, seed, data_block.length );
76 | for ( var i = 0; i < data_block.length; i++ )
77 | data_block[i] ^= data_block_mask[i];
78 |
79 | var seed_mask = RSA_MGF1_generate.call( this, data_block, seed.length );
80 | for ( var i = 0; i < seed.length; i++ )
81 | seed[i] ^= seed_mask[i];
82 |
83 | RSA_encrypt.call( this, message );
84 |
85 | return this;
86 | }
87 |
88 | function RSA_OAEP_decrypt ( data ) {
89 | if ( !this.key )
90 | throw new IllegalStateError("no key is associated with the instance");
91 |
92 | var key_size = Math.ceil( this.key[0].bitLength / 8 ),
93 | hash_size = this.hash.HASH_SIZE,
94 | data_length = data.byteLength || data.length || 0;
95 |
96 | if ( data_length !== key_size )
97 | throw new IllegalArgumentError("bad data");
98 |
99 | RSA_decrypt.call( this, data );
100 |
101 | var z = this.result[0],
102 | seed = this.result.subarray( 1, hash_size + 1 ),
103 | data_block = this.result.subarray( hash_size + 1 );
104 |
105 | if ( z !== 0 )
106 | throw new SecurityError("decryption failed");
107 |
108 | var seed_mask = RSA_MGF1_generate.call( this, data_block, seed.length );
109 | for ( var i = 0; i < seed.length; i++ )
110 | seed[i] ^= seed_mask[i];
111 |
112 | var data_block_mask = RSA_MGF1_generate.call( this, seed, data_block.length );
113 | for ( var i = 0; i < data_block.length; i++ )
114 | data_block[i] ^= data_block_mask[i];
115 |
116 | var lhash = this.hash.reset().process( this.label || '' ).finish().result;
117 | for ( var i = 0; i < hash_size; i++ ) {
118 | if ( lhash[i] !== data_block[i] )
119 | throw new SecurityError("decryption failed");
120 | }
121 |
122 | var ps_end = hash_size;
123 | for ( ; ps_end < data_block.length; ps_end++ ) {
124 | var psz = data_block[ps_end];
125 | if ( psz === 1 )
126 | break;
127 | if ( psz !== 0 )
128 | throw new SecurityError("decryption failed");
129 | }
130 | if ( ps_end === data_block.length )
131 | throw new SecurityError("decryption failed");
132 |
133 | this.result = data_block.subarray( ps_end + 1 );
134 |
135 | return this;
136 | }
137 |
138 | function RSA_MGF1_generate( seed, length ) {
139 | seed = seed || '';
140 | length = length || 0;
141 |
142 | var hash_size = this.hash.HASH_SIZE;
143 | // if ( length > (hash_size * 0x100000000) )
144 | // throw new IllegalArgumentError("mask length too large");
145 |
146 | var mask = new Uint8Array(length),
147 | counter = new Uint8Array(4),
148 | chunks = Math.ceil( length / hash_size );
149 | for ( var i = 0; i < chunks; i++ ) {
150 | counter[0] = i >>> 24,
151 | counter[1] = (i >>> 16) & 255,
152 | counter[2] = (i >>> 8) & 255,
153 | counter[3] = i & 255;
154 |
155 | var submask = mask.subarray( i * hash_size );
156 |
157 | var chunk = this.hash.reset().process(seed).process(counter).finish().result;
158 | if ( chunk.length > submask.length ) chunk = chunk.subarray( 0, submask.length );
159 |
160 | submask.set(chunk);
161 | }
162 |
163 | return mask;
164 | }
165 |
166 | function RSA_PSS ( options ) {
167 | options = options || {};
168 |
169 | if ( !options.hash )
170 | throw new SyntaxError("option 'hash' is required");
171 |
172 | if ( !options.hash.HASH_SIZE )
173 | throw new SyntaxError("option 'hash' supplied doesn't seem to be a valid hash function");
174 |
175 | this.hash = options.hash;
176 |
177 | this.saltLength = 4;
178 |
179 | this.reset(options);
180 | }
181 |
182 | function RSA_PSS_reset ( options ) {
183 | options = options || {};
184 |
185 | RSA_reset.call( this, options );
186 |
187 | var slen = options.saltLength;
188 | if ( slen !== undefined ) {
189 | if ( !is_number(slen) || slen < 0 )
190 | throw new TypeError("saltLength should be a non-negative number");
191 |
192 | if ( this.key !== null && Math.ceil( ( this.key[0].bitLength - 1 ) / 8 ) < this.hash.HASH_SIZE + slen + 2 )
193 | throw new SyntaxError("saltLength is too large");
194 |
195 | this.saltLength = slen;
196 | }
197 | else {
198 | this.saltLength = 4;
199 | }
200 | }
201 |
202 | function RSA_PSS_sign ( data ) {
203 | if ( !this.key )
204 | throw new IllegalStateError("no key is associated with the instance");
205 |
206 | var key_bits = this.key[0].bitLength,
207 | hash_size = this.hash.HASH_SIZE,
208 | message_length = Math.ceil( ( key_bits - 1 ) / 8 ),
209 | salt_length = this.saltLength,
210 | ps_length = message_length - salt_length - hash_size - 2;
211 |
212 | var message = new Uint8Array(message_length),
213 | h_block = message.subarray( message_length - hash_size - 1, message_length - 1 ),
214 | d_block = message.subarray( 0, message_length - hash_size - 1 ),
215 | d_salt = d_block.subarray( ps_length + 1 );
216 |
217 | var m_block = new Uint8Array( 8 + hash_size + salt_length ),
218 | m_hash = m_block.subarray( 8, 8 + hash_size ),
219 | m_salt = m_block.subarray( 8 + hash_size );
220 |
221 | m_hash.set( this.hash.reset().process(data).finish().result );
222 |
223 | if ( salt_length > 0 )
224 | Random_getValues(m_salt);
225 |
226 | d_block[ps_length] = 1;
227 | d_salt.set(m_salt);
228 |
229 | h_block.set( this.hash.reset().process(m_block).finish().result );
230 |
231 | var d_block_mask = RSA_MGF1_generate.call( this, h_block, d_block.length );
232 | for ( var i = 0; i < d_block.length; i++ )
233 | d_block[i] ^= d_block_mask[i];
234 |
235 | message[message_length-1] = 0xbc;
236 |
237 | var zbits = 8*message_length - key_bits + 1;
238 | if ( zbits % 8 ) message[0] &= (0xff >>> zbits);
239 |
240 | RSA_decrypt.call( this, message );
241 |
242 | return this;
243 | }
244 |
245 | function RSA_PSS_verify ( signature, data ) {
246 | if ( !this.key )
247 | throw new IllegalStateError("no key is associated with the instance");
248 |
249 | var key_bits = this.key[0].bitLength,
250 | hash_size = this.hash.HASH_SIZE,
251 | message_length = Math.ceil( ( key_bits - 1 ) / 8 ),
252 | salt_length = this.saltLength,
253 | ps_length = message_length - salt_length - hash_size - 2;
254 |
255 | RSA_encrypt.call( this, signature );
256 |
257 | var message = this.result;
258 | if ( message[message_length-1] !== 0xbc )
259 | throw new SecurityError("bad signature");
260 |
261 | var h_block = message.subarray( message_length - hash_size - 1, message_length - 1 ),
262 | d_block = message.subarray( 0, message_length - hash_size - 1 ),
263 | d_salt = d_block.subarray( ps_length + 1 );
264 |
265 | var zbits = 8*message_length - key_bits + 1;
266 | if ( (zbits % 8) && (message[0] >>> (8-zbits)) )
267 | throw new SecurityError("bad signature");
268 |
269 | var d_block_mask = RSA_MGF1_generate.call( this, h_block, d_block.length );
270 | for ( var i = 0; i < d_block.length; i++ )
271 | d_block[i] ^= d_block_mask[i];
272 |
273 | if ( zbits % 8 ) message[0] &= (0xff >>> zbits);
274 |
275 | for ( var i = 0; i < ps_length; i++ ) {
276 | if ( d_block[i] !== 0 )
277 | throw new SecurityError("bad signature");
278 | }
279 | if ( d_block[ps_length] !== 1 )
280 | throw new SecurityError("bad signature");
281 |
282 | var m_block = new Uint8Array( 8 + hash_size + salt_length ),
283 | m_hash = m_block.subarray( 8, 8 + hash_size ),
284 | m_salt = m_block.subarray( 8 + hash_size );
285 |
286 | m_hash.set( this.hash.reset().process(data).finish().result );
287 | m_salt.set( d_salt );
288 |
289 | var h_block_verify = this.hash.reset().process(m_block).finish().result;
290 | for ( var i = 0; i < hash_size; i++ ) {
291 | if ( h_block[i] !== h_block_verify[i] )
292 | throw new SecurityError("bad signature");
293 | }
294 |
295 | return this;
296 | }
297 |
298 | var RSA_OAEP_prototype = RSA_OAEP.prototype;
299 | RSA_OAEP_prototype.reset = RSA_OAEP_reset;
300 | RSA_OAEP_prototype.encrypt = RSA_OAEP_encrypt;
301 | RSA_OAEP_prototype.decrypt = RSA_OAEP_decrypt;
302 |
303 | var RSA_PSS_prototype = RSA_PSS.prototype;
304 | RSA_PSS_prototype.reset = RSA_PSS_reset;
305 | RSA_PSS_prototype.sign = RSA_PSS_sign;
306 | RSA_PSS_prototype.verify = RSA_PSS_verify;
307 |
--------------------------------------------------------------------------------
/src/bignum/bignum.js:
--------------------------------------------------------------------------------
1 | function is_big_number ( a ) {
2 | return ( a instanceof BigNumber );
3 | }
4 |
5 | ///////////////////////////////////////////////////////////////////////////////
6 |
7 | var _bigint_heap = new Uint32Array(0x100000),
8 | _bigint_asm = bigint_asm( global, null, _bigint_heap.buffer );
9 |
10 | ///////////////////////////////////////////////////////////////////////////////
11 |
12 | var _BigNumber_ZERO_limbs = new Uint32Array(0);
13 |
14 | function BigNumber ( num ) {
15 | var limbs = _BigNumber_ZERO_limbs,
16 | bitlen = 0,
17 | sign = 0;
18 |
19 | if ( is_string(num) )
20 | num = string_to_bytes(num);
21 |
22 | if ( is_buffer(num) )
23 | num = new Uint8Array(num);
24 |
25 | if ( num === undefined ) {
26 | // do nothing
27 | }
28 | else if ( is_number(num) ) {
29 | var absnum = Math.abs(num);
30 | if ( absnum > 0xffffffff ) {
31 | limbs = new Uint32Array(2);
32 | limbs[0] = absnum|0;
33 | limbs[1] = (absnum/0x100000000)|0;
34 | bitlen = 52;
35 | }
36 | else if ( absnum > 0 ) {
37 | limbs = new Uint32Array(1);
38 | limbs[0] = absnum;
39 | bitlen = 32;
40 | }
41 | else {
42 | limbs = _BigNumber_ZERO_limbs;
43 | bitlen = 0;
44 | }
45 | sign = num < 0 ? -1 : 1;
46 | }
47 | else if ( is_bytes(num) ) {
48 | bitlen = num.length * 8;
49 | if ( !bitlen )
50 | return BigNumber_ZERO;
51 |
52 | limbs = new Uint32Array( (bitlen + 31) >> 5 );
53 | for ( var i = num.length-4; i >= 0 ; i -= 4 ) {
54 | limbs[(num.length-4-i)>>2] = (num[i] << 24) | (num[i+1] << 16) | (num[i+2] << 8) | num[i+3];
55 | }
56 | if ( i === -3 ) {
57 | limbs[limbs.length-1] = num[0];
58 | }
59 | else if ( i === -2 ) {
60 | limbs[limbs.length-1] = (num[0] << 8) | num[1];
61 | }
62 | else if ( i === -1 ) {
63 | limbs[limbs.length-1] = (num[0] << 16) | (num[1] << 8) | num[2];
64 | }
65 |
66 | sign = 1;
67 | }
68 | else if ( typeof num === 'object' && num !== null ) {
69 | limbs = new Uint32Array( num.limbs );
70 | bitlen = num.bitLength;
71 | sign = num.sign;
72 | }
73 | else {
74 | throw new TypeError("number is of unexpected type");
75 | }
76 |
77 | this.limbs = limbs;
78 | this.bitLength = bitlen;
79 | this.sign = sign;
80 | }
81 |
82 | function BigNumber_toString ( radix ) {
83 | radix = radix || 16;
84 |
85 | var limbs = this.limbs,
86 | bitlen = this.bitLength,
87 | str = '';
88 |
89 | if ( radix === 16 ) {
90 | // FIXME clamp last limb to (bitlen % 32)
91 | for ( var i = (bitlen+31>>5)-1; i >= 0; i-- ) {
92 | var h = limbs[i].toString(16);
93 | str += '00000000'.substr(h.length);
94 | str += h;
95 | }
96 |
97 | str = str.replace( /^0+/, '' );
98 |
99 | if ( !str.length )
100 | str = '0';
101 | }
102 | else {
103 | throw new IllegalArgumentError("bad radix");
104 | }
105 |
106 | if ( this.sign < 0 )
107 | str = '-' + str;
108 |
109 | return str;
110 | }
111 |
112 | function BigNumber_toBytes () {
113 | var bitlen = this.bitLength,
114 | limbs = this.limbs;
115 |
116 | if ( bitlen === 0 )
117 | return new Uint8Array(0);
118 |
119 | var bytelen = ( bitlen + 7 ) >> 3,
120 | bytes = new Uint8Array(bytelen);
121 | for ( var i = 0; i < bytelen; i++ ) {
122 | var j = bytelen - i - 1;
123 | bytes[i] = limbs[j>>2] >> ( (j & 3) << 3 );
124 | }
125 |
126 | return bytes;
127 | }
128 |
129 | // Downgrade to Number
130 | function BigNumber_valueOf () {
131 | var limbs = this.limbs,
132 | bits = this.bitLength,
133 | sign = this.sign;
134 |
135 | if ( !sign )
136 | return 0;
137 |
138 | if ( bits <= 32 )
139 | return sign * (limbs[0]>>>0);
140 |
141 | if ( bits <= 52 )
142 | return sign * ( 0x100000000 * (limbs[1]>>>0) + (limbs[0]>>>0) );
143 |
144 | // normalization
145 | var i, l, e = 0;
146 | for ( i = limbs.length-1; i >= 0; i-- ) {
147 | if ( (l = limbs[i]) === 0 ) continue;
148 | while ( ( (l << e) & 0x80000000 ) === 0 ) e++;
149 | break;
150 | }
151 |
152 | if ( i === 0 )
153 | return sign * (limbs[0]>>>0);
154 |
155 | return sign * ( 0x100000 * (( (limbs[i] << e) | ( e ? limbs[i-1] >>> (32-e) : 0 ) )>>>0)
156 | + (( (limbs[i-1] << e) | ( e && i > 1 ? limbs[i-2] >>> (32-e) : 0 ) )>>>12)
157 | ) * Math.pow( 2, 32*i-e-52 );
158 | }
159 |
160 | function BigNumber_clamp ( b ) {
161 | var limbs = this.limbs,
162 | bitlen = this.bitLength;
163 |
164 | // FIXME check b is number and in a valid range
165 |
166 | if ( b >= bitlen )
167 | return this;
168 |
169 | var clamped = new BigNumber,
170 | n = (b + 31) >> 5,
171 | k = b % 32;
172 |
173 | clamped.limbs = new Uint32Array( limbs.subarray(0,n) );
174 | clamped.bitLength = b;
175 | clamped.sign = this.sign;
176 |
177 | if ( k ) clamped.limbs[n-1] &= (-1 >>> (32-k));
178 |
179 | return clamped;
180 | }
181 |
182 | function BigNumber_slice ( f, b ) {
183 | if ( !is_number(f) )
184 | throw new TypeError("TODO");
185 |
186 | if ( b !== undefined && !is_number(b) )
187 | throw new TypeError("TODO");
188 |
189 | var limbs = this.limbs,
190 | bitlen = this.bitLength;
191 |
192 | if ( f < 0 )
193 | throw new RangeError("TODO");
194 |
195 | if ( f >= bitlen )
196 | return BigNumber_ZERO;
197 |
198 | if ( b === undefined || b > bitlen - f )
199 | b = bitlen - f;
200 |
201 | var sliced = new BigNumber, slimbs,
202 | n = f >> 5, m = (f + b + 31) >> 5, l = (b + 31) >> 5,
203 | t = f % 32, k = b % 32;
204 |
205 | slimbs = new Uint32Array(l);
206 | if ( t ) {
207 | for ( var i = 0; i < m-n-1; i++ ) {
208 | slimbs[i] = (limbs[n+i]>>>t) | ( limbs[n+i+1]<<(32-t) );
209 | }
210 | slimbs[i] = limbs[n+i]>>>t;
211 | }
212 | else {
213 | slimbs.set( limbs.subarray(n, m) );
214 | }
215 |
216 | if ( k ) {
217 | slimbs[l-1] &= (-1 >>> (32-k));
218 | }
219 |
220 | sliced.limbs = slimbs
221 | sliced.bitLength = b;
222 | sliced.sign = this.sign;
223 |
224 | return sliced;
225 | }
226 |
227 | ///////////////////////////////////////////////////////////////////////////////
228 |
229 | function BigNumber_negate () {
230 | var negative = new BigNumber;
231 |
232 | negative.limbs = this.limbs;
233 | negative.bitLength = this.bitLength;
234 | negative.sign = -1 * this.sign;
235 |
236 | return negative;
237 | }
238 |
239 | function BigNumber_compare ( that ) {
240 | if ( !is_big_number(that) )
241 | that = new BigNumber(that);
242 |
243 | var alimbs = this.limbs, alimbcnt = alimbs.length,
244 | blimbs = that.limbs, blimbcnt = blimbs.length,
245 | z = 0;
246 |
247 | if ( this.sign < that.sign )
248 | return -1;
249 |
250 | if ( this.sign > that.sign )
251 | return 1;
252 |
253 | _bigint_heap.set( alimbs, 0 );
254 | _bigint_heap.set( blimbs, alimbcnt );
255 | z = _bigint_asm.cmp( 0, alimbcnt<<2, alimbcnt<<2, blimbcnt<<2 );
256 |
257 | return z * this.sign;
258 | }
259 |
260 | function BigNumber_add ( that ) {
261 | if ( !is_big_number(that) )
262 | that = new BigNumber(that);
263 |
264 | if ( !this.sign )
265 | return that;
266 |
267 | if ( !that.sign )
268 | return this;
269 |
270 | var abitlen = this.bitLength, alimbs = this.limbs, alimbcnt = alimbs.length, asign = this.sign,
271 | bbitlen = that.bitLength, blimbs = that.limbs, blimbcnt = blimbs.length, bsign = that.sign,
272 | rbitlen, rlimbcnt, rsign, rof, result = new BigNumber;
273 |
274 | rbitlen = ( abitlen > bbitlen ? abitlen : bbitlen ) + ( asign * bsign > 0 ? 1 : 0 );
275 | rlimbcnt = ( rbitlen + 31 ) >> 5;
276 |
277 | _bigint_asm.sreset();
278 |
279 | var pA = _bigint_asm.salloc( alimbcnt<<2 ),
280 | pB = _bigint_asm.salloc( blimbcnt<<2 ),
281 | pR = _bigint_asm.salloc( rlimbcnt<<2 );
282 |
283 | _bigint_asm.z( pR-pA+(rlimbcnt<<2), 0, pA );
284 |
285 | _bigint_heap.set( alimbs, pA>>2 );
286 | _bigint_heap.set( blimbs, pB>>2 );
287 |
288 | if ( asign * bsign > 0 ) {
289 | _bigint_asm.add( pA, alimbcnt<<2, pB, blimbcnt<<2, pR, rlimbcnt<<2 );
290 | rsign = asign;
291 | }
292 | else if ( asign > bsign ) {
293 | rof = _bigint_asm.sub( pA, alimbcnt<<2, pB, blimbcnt<<2, pR, rlimbcnt<<2 );
294 | rsign = rof ? bsign : asign;
295 | }
296 | else {
297 | rof = _bigint_asm.sub( pB, blimbcnt<<2, pA, alimbcnt<<2, pR, rlimbcnt<<2 );
298 | rsign = rof ? asign : bsign;
299 | }
300 |
301 | if ( rof )
302 | _bigint_asm.neg( pR, rlimbcnt<<2, pR, rlimbcnt<<2 );
303 |
304 | if ( _bigint_asm.tst( pR, rlimbcnt<<2 ) === 0 )
305 | return BigNumber_ZERO;
306 |
307 | result.limbs = new Uint32Array( _bigint_heap.subarray( pR>>2, (pR>>2)+rlimbcnt ) );
308 | result.bitLength = rbitlen;
309 | result.sign = rsign;
310 |
311 | return result;
312 | }
313 |
314 | function BigNumber_subtract ( that ) {
315 | if ( !is_big_number(that) )
316 | that = new BigNumber(that);
317 |
318 | return this.add( that.negate() );
319 | }
320 |
321 | function BigNumber_multiply ( that ) {
322 | if ( !is_big_number(that) )
323 | that = new BigNumber(that);
324 |
325 | if ( !this.sign || !that.sign )
326 | return BigNumber_ZERO;
327 |
328 | var abitlen = this.bitLength, alimbs = this.limbs, alimbcnt = alimbs.length,
329 | bbitlen = that.bitLength, blimbs = that.limbs, blimbcnt = blimbs.length,
330 | rbitlen, rlimbcnt, result = new BigNumber;
331 |
332 | rbitlen = abitlen + bbitlen;
333 | rlimbcnt = ( rbitlen + 31 ) >> 5;
334 |
335 | _bigint_asm.sreset();
336 |
337 | var pA = _bigint_asm.salloc( alimbcnt<<2 ),
338 | pB = _bigint_asm.salloc( blimbcnt<<2 ),
339 | pR = _bigint_asm.salloc( rlimbcnt<<2 );
340 |
341 | _bigint_asm.z( pR-pA+(rlimbcnt<<2), 0, pA );
342 |
343 | _bigint_heap.set( alimbs, pA>>2 );
344 | _bigint_heap.set( blimbs, pB>>2 );
345 |
346 | _bigint_asm.mul( pA, alimbcnt<<2, pB, blimbcnt<<2, pR, rlimbcnt<<2 );
347 |
348 | result.limbs = new Uint32Array( _bigint_heap.subarray( pR>>2, (pR>>2)+rlimbcnt ) );
349 | result.sign = this.sign * that.sign;
350 | result.bitLength = rbitlen;
351 |
352 | return result;
353 | }
354 |
355 | function BigNumber_square () {
356 | if ( !this.sign )
357 | return BigNumber_ZERO;
358 |
359 | var abitlen = this.bitLength, alimbs = this.limbs, alimbcnt = alimbs.length,
360 | rbitlen, rlimbcnt, result = new BigNumber;
361 |
362 | rbitlen = abitlen << 1;
363 | rlimbcnt = ( rbitlen + 31 ) >> 5;
364 |
365 | _bigint_asm.sreset();
366 |
367 | var pA = _bigint_asm.salloc( alimbcnt<<2 ),
368 | pR = _bigint_asm.salloc( rlimbcnt<<2 );
369 |
370 | _bigint_asm.z( pR-pA+(rlimbcnt<<2), 0, pA );
371 |
372 | _bigint_heap.set( alimbs, pA>>2 );
373 |
374 | _bigint_asm.sqr( pA, alimbcnt<<2, pR );
375 |
376 | result.limbs = new Uint32Array( _bigint_heap.subarray( pR>>2, (pR>>2)+rlimbcnt ) );
377 | result.bitLength = rbitlen;
378 | result.sign = 1;
379 |
380 | return result;
381 | }
382 |
383 | function BigNumber_divide ( that ) {
384 | if ( !is_big_number(that) )
385 | that = new BigNumber(that);
386 |
387 | var abitlen = this.bitLength, alimbs = this.limbs, alimbcnt = alimbs.length,
388 | bbitlen = that.bitLength, blimbs = that.limbs, blimbcnt = blimbs.length,
389 | qlimbcnt, rlimbcnt, quotient = BigNumber_ZERO, remainder = BigNumber_ZERO;
390 |
391 | _bigint_asm.sreset();
392 |
393 | var pA = _bigint_asm.salloc( alimbcnt<<2 ),
394 | pB = _bigint_asm.salloc( blimbcnt<<2 ),
395 | pR = _bigint_asm.salloc( blimbcnt<<2 ),
396 | pQ = _bigint_asm.salloc( alimbcnt<<2 );
397 |
398 | _bigint_asm.z( pQ-pA+(alimbcnt<<2), 0, pA );
399 |
400 | _bigint_heap.set( alimbs, pA>>2 );
401 | _bigint_heap.set( blimbs, pB>>2 );
402 |
403 | _bigint_asm.div( pA, alimbcnt<<2, pB, blimbcnt<<2, pR, pQ );
404 |
405 | qlimbcnt = _bigint_asm.tst( pQ, alimbcnt<<2 )>>2;
406 | if ( qlimbcnt ) {
407 | quotient = new BigNumber;
408 | quotient.limbs = new Uint32Array( _bigint_heap.subarray( pQ>>2, (pQ>>2)+qlimbcnt ) );
409 | quotient.bitLength = abitlen < (qlimbcnt<<5) ? abitlen : (qlimbcnt<<5);
410 | quotient.sign = this.sign * that.sign;
411 | }
412 |
413 | rlimbcnt = _bigint_asm.tst( pR, blimbcnt<<2 )>>2;
414 | if ( rlimbcnt ) {
415 | remainder = new BigNumber;
416 | remainder.limbs = new Uint32Array( _bigint_heap.subarray( pR>>2, (pR>>2)+rlimbcnt ) );;
417 | remainder.bitLength = bbitlen < (rlimbcnt<<5) ? bbitlen : (rlimbcnt<<5);
418 | remainder.sign = this.sign;
419 | }
420 |
421 | return {
422 | quotient: quotient,
423 | remainder: remainder
424 | };
425 | }
426 |
427 | ///////////////////////////////////////////////////////////////////////////////
428 |
429 | var BigNumberPrototype = BigNumber.prototype = new Number;
430 | BigNumberPrototype.toString = BigNumber_toString;
431 | BigNumberPrototype.toBytes = BigNumber_toBytes;
432 | BigNumberPrototype.valueOf = BigNumber_valueOf;
433 | BigNumberPrototype.clamp = BigNumber_clamp;
434 | BigNumberPrototype.slice = BigNumber_slice;
435 |
436 | ///////////////////////////////////////////////////////////////////////////////
437 |
438 | BigNumberPrototype.negate = BigNumber_negate;
439 | BigNumberPrototype.compare = BigNumber_compare;
440 | BigNumberPrototype.add = BigNumber_add;
441 | BigNumberPrototype.subtract = BigNumber_subtract;
442 | BigNumberPrototype.multiply = BigNumber_multiply;
443 | BigNumberPrototype.square = BigNumber_square;
444 | BigNumberPrototype.divide = BigNumber_divide;
445 |
446 | ///////////////////////////////////////////////////////////////////////////////
447 |
448 | var BigNumber_ZERO = new BigNumber(0),
449 | BigNumber_ONE = new BigNumber(1);
450 |
451 | Object.freeze(BigNumber_ZERO);
452 | Object.freeze(BigNumber_ONE);
453 |
--------------------------------------------------------------------------------
/src/aes/aes-gcm.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Galois/Counter mode
3 | */
4 |
5 | var _gcm_data_maxLength = 68719476704; // 2^36 - 2^5
6 |
7 | function gcm_aes_constructor ( options ) {
8 | this.padding = false; // WAT?
9 | this.mode = 'gcm';
10 |
11 | this.tagSize = _aes_block_size;
12 |
13 | this.adata = null;
14 | this.iv = null;
15 | this.counter = 1;
16 |
17 | _aes_constructor.call( this, options );
18 | }
19 |
20 | function gcm_aes_encrypt_constructor ( options ) {
21 | gcm_aes_constructor.call( this, options );
22 | }
23 |
24 | function gcm_aes_decrypt_constructor ( options ) {
25 | gcm_aes_constructor.call( this, options );
26 | }
27 |
28 | function _gcm_ghash ( data ) {
29 | var asm = this.asm,
30 | heap = this.heap,
31 | dpos = 0,
32 | dlen = data.length || 0,
33 | hpos = _aes_heap_start,
34 | hlen = 0,
35 | wlen = 0;
36 |
37 | while ( dlen > 0 ) {
38 | wlen = _heap_write( heap, hpos+hlen, data, dpos, dlen ),
39 | hlen += wlen,
40 | dpos += wlen,
41 | dlen -= wlen;
42 |
43 | wlen = asm.gcm_ghash( hpos, hlen ),
44 | hpos += wlen,
45 | hlen -= wlen;
46 |
47 | if ( !hlen ) hpos = _aes_heap_start;
48 | }
49 |
50 | if ( hlen > 0 ) {
51 | while ( hlen < 16 ) heap[hpos|(hlen++)] = 0;
52 | asm.gcm_ghash( hpos, hlen );
53 | }
54 | }
55 |
56 | function gcm_aes_reset ( options ) {
57 | options = options || {};
58 |
59 | var asm = this.asm,
60 | heap = this.heap;
61 |
62 | _aes_reset.call( this, options );
63 | asm.gcm_init();
64 |
65 | var iv = options.iv;
66 |
67 | if ( iv !== undefined && iv !== null ) {
68 | if ( is_buffer(iv) || is_bytes(iv) ) {
69 | iv = new Uint8Array(iv);
70 | }
71 | else if ( is_string(iv) ) {
72 | iv = string_to_bytes(iv);
73 | }
74 | else {
75 | throw new TypeError("unexpected iv type");
76 | }
77 |
78 | var ivlen = iv.length || 0;
79 | if ( ivlen !== 12 ) {
80 | asm.init_state( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 );
81 |
82 | _gcm_ghash.call( this, iv );
83 |
84 | heap[_aes_heap_start|0] = heap[_aes_heap_start|1] = heap[_aes_heap_start|2] = heap[_aes_heap_start|3] =
85 | heap[_aes_heap_start|4] = heap[_aes_heap_start|5] = heap[_aes_heap_start|6] = heap[_aes_heap_start|7] =
86 | heap[_aes_heap_start|8] = heap[_aes_heap_start|9] = heap[_aes_heap_start|10] = 0,
87 | heap[_aes_heap_start|11] = (ivlen >>> 29),
88 | heap[_aes_heap_start|12] = (ivlen >>> 21) & 255,
89 | heap[_aes_heap_start|13] = (ivlen >>> 13) & 255,
90 | heap[_aes_heap_start|14] = (ivlen >>> 5) & 255,
91 | heap[_aes_heap_start|15] = (ivlen << 3) & 255;
92 | asm.gcm_ghash( _aes_heap_start, _aes_block_size );
93 |
94 | asm.save_state( _aes_heap_start );
95 |
96 | this.iv = new Uint8Array( heap.subarray( _aes_heap_start, _aes_heap_start+_aes_block_size ) );
97 | }
98 | else {
99 | this.iv = new Uint8Array(16);
100 | this.iv.set(iv);
101 | this.iv[15] = 1;
102 | }
103 | }
104 | else {
105 | this.iv = new Uint8Array(16);
106 | this.iv[15] = 1;
107 | }
108 |
109 | var counter = options.counter;
110 | if ( counter !== undefined ) {
111 | if ( !is_number(counter) )
112 | throw new TypeError("counter must be a number");
113 |
114 | if ( counter < 1 || counter > 0xffffffff )
115 | throw new RangeError("counter must be a positive 32-bit integer");
116 |
117 | this.counter = counter;
118 | }
119 | else {
120 | this.counter = 1;
121 | }
122 |
123 | var tagSize = options.tagSize;
124 | if ( tagSize !== undefined ) {
125 | if ( !is_number(tagSize) )
126 | throw new TypeError("tagSize must be a number");
127 |
128 | if ( tagSize < 4 || tagSize > 16 )
129 | throw new IllegalArgumentError("illegal tagSize value");
130 |
131 | this.tagSize = tagSize;
132 | }
133 | else {
134 | this.tagSize = _aes_block_size;
135 | }
136 |
137 | asm.init_state( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 );
138 |
139 | var adata = options.adata;
140 | if ( adata !== undefined && adata !== null ) {
141 | if ( is_buffer(adata) || is_bytes(adata) ) {
142 | adata = new Uint8Array(adata);
143 | }
144 | else if ( is_string(adata) ) {
145 | adata = string_to_bytes(adata);
146 | }
147 | else {
148 | throw new TypeError("unexpected adata type");
149 | }
150 |
151 | if ( adata.length === 0 || adata.length > _gcm_data_maxLength )
152 | throw new IllegalArgumentError("illegal adata length");
153 |
154 | _gcm_ghash.call( this, adata );
155 |
156 | this.adata = adata;
157 | }
158 | else {
159 | this.adata = null;
160 | }
161 |
162 | return this;
163 | }
164 |
165 | function gcm_aes_encrypt_process ( data ) {
166 | if ( !this.key )
167 | throw new IllegalStateError("no key is associated with the instance");
168 |
169 | if ( is_string(data) )
170 | data = string_to_bytes(data);
171 |
172 | if ( is_buffer(data) )
173 | data = new Uint8Array(data);
174 |
175 | if ( !is_bytes(data) )
176 | throw new TypeError("data isn't of expected type");
177 |
178 | var asm = this.asm,
179 | heap = this.heap,
180 | iv = this.iv,
181 | counter = this.counter,
182 | dpos = 0,
183 | dlen = data.length || 0,
184 | hpos = this.pos,
185 | hlen = this.len,
186 | rpos = 0,
187 | rlen = _aes_block_size * Math.floor( ( hlen + dlen ) / _aes_block_size ),
188 | wlen = 0;
189 |
190 | var result = new Uint8Array(rlen);
191 |
192 | if ( ((counter-1)<<4) + hlen + dlen > _gcm_data_maxLength )
193 | throw new IllegalStateError("counter overflow");
194 |
195 | while ( dlen > 0 ) {
196 | wlen = _heap_write( heap, hpos+hlen, data, dpos, dlen );
197 | hlen += wlen;
198 | dpos += wlen;
199 | dlen -= wlen;
200 |
201 | var ivc = (iv[12] << 24) | (iv[13] << 16) | (iv[14] << 8) | iv[15];
202 | wlen = asm.gcm_encrypt( hpos, hlen & -15, iv[0], iv[1], iv[2], iv[3], iv[4], iv[5], iv[6], iv[7], iv[8], iv[9], iv[10], iv[11], (ivc+counter)|0 );
203 | if ( wlen ) result.set( heap.subarray( hpos, hpos+wlen ), rpos );
204 | counter += (wlen>>>4);
205 | rpos += wlen,
206 | hpos += wlen,
207 | hlen -= wlen;
208 |
209 | if ( !hlen ) hpos = _aes_heap_start;
210 | }
211 |
212 | this.result = result;
213 | this.counter = counter;
214 | this.pos = hpos;
215 | this.len = hlen;
216 |
217 | return this;
218 | }
219 |
220 | function gcm_aes_encrypt_finish () {
221 | if ( !this.key )
222 | throw new IllegalStateError("no key is associated with the instance");
223 |
224 | var asm = this.asm,
225 | heap = this.heap,
226 | iv = this.iv,
227 | adata = this.adata,
228 | counter = this.counter,
229 | tagSize = this.tagSize,
230 | pos = this.pos,
231 | hlen = this.len,
232 | wlen = 0;
233 |
234 | var result = new Uint8Array( hlen + tagSize );
235 |
236 | var ivc = (iv[12] << 24) | (iv[13] << 16) | (iv[14] << 8) | iv[15];
237 |
238 | if ( hlen > 0 ) {
239 | wlen = asm.gcm_encrypt( pos, hlen, iv[0], iv[1], iv[2], iv[3], iv[4], iv[5], iv[6], iv[7], iv[8], iv[9], iv[10], iv[11], (ivc+counter)|0 );
240 | if ( wlen ) result.set( heap.subarray( pos, pos+wlen ) );
241 | }
242 |
243 | var alen = ( adata !== null ) ? adata.length || 0 : 0,
244 | clen = ( (counter-1) << 4) + wlen;
245 | heap[_aes_heap_start|0] = heap[_aes_heap_start|1] = heap[_aes_heap_start|2] = 0,
246 | heap[_aes_heap_start|3] = (alen >>> 29),
247 | heap[_aes_heap_start|4] = (alen >>> 21),
248 | heap[_aes_heap_start|5] = (alen >>> 13) & 255,
249 | heap[_aes_heap_start|6] = (alen >>> 5) & 255,
250 | heap[_aes_heap_start|7] = (alen << 3) & 255,
251 | heap[_aes_heap_start|8] = heap[_aes_heap_start|9] = heap[_aes_heap_start|10] = 0,
252 | heap[_aes_heap_start|11] = (clen >>> 29),
253 | heap[_aes_heap_start|12] = (clen >>> 21) & 255,
254 | heap[_aes_heap_start|13] = (clen >>> 13) & 255,
255 | heap[_aes_heap_start|14] = (clen >>> 5) & 255,
256 | heap[_aes_heap_start|15] = (clen << 3) & 255;
257 | asm.gcm_ghash( _aes_heap_start, _aes_block_size );
258 | asm.save_state( _aes_heap_start );
259 |
260 | asm.gcm_encrypt( _aes_heap_start, _aes_block_size, iv[0], iv[1], iv[2], iv[3], iv[4], iv[5], iv[6], iv[7], iv[8], iv[9], iv[10], iv[11], ivc );
261 | result.set( heap.subarray( _aes_heap_start, _aes_heap_start+tagSize ), wlen );
262 |
263 | this.result = result;
264 | this.counter = 1;
265 | this.pos = _aes_heap_start;
266 | this.len = 0;
267 |
268 | return this;
269 | }
270 |
271 | function gcm_aes_encrypt ( data ) {
272 | var result1 = gcm_aes_encrypt_process.call( this, data ).result,
273 | result2 = gcm_aes_encrypt_finish.call(this).result;
274 |
275 | var result = new Uint8Array( result1.length + result2.length );
276 | if ( result1.length ) result.set( result1 );
277 | if ( result2.length ) result.set( result2, result1.length );
278 | this.result = result;
279 |
280 | return this;
281 | }
282 |
283 | function gcm_aes_decrypt_process ( data ) {
284 | if ( !this.key )
285 | throw new IllegalStateError("no key is associated with the instance");
286 |
287 | if ( is_string(data) )
288 | data = string_to_bytes(data);
289 |
290 | if ( is_buffer(data) )
291 | data = new Uint8Array(data);
292 |
293 | if ( !is_bytes(data) )
294 | throw new TypeError("data isn't of expected type");
295 |
296 | var asm = this.asm,
297 | heap = this.heap,
298 | iv = this.iv,
299 | counter = this.counter,
300 | tagSize = this.tagSize,
301 | dpos = 0,
302 | dlen = data.length || 0,
303 | hpos = this.pos,
304 | hlen = this.len,
305 | rpos = 0,
306 | rlen = _aes_block_size * Math.floor( ( hlen + dlen - tagSize ) / _aes_block_size ),
307 | wlen = 0;
308 |
309 | var result = new Uint8Array(rlen);
310 |
311 | if ( ((counter-1)<<4) + hlen + dlen - tagSize > _gcm_data_maxLength )
312 | throw new IllegalStateError("counter overflow");
313 |
314 | while ( dlen > 0 ) {
315 | wlen = _heap_write( heap, hpos+hlen, data, dpos, dlen ),
316 | hlen += wlen,
317 | dpos += wlen,
318 | dlen -= wlen;
319 |
320 | var ivc = (iv[12] << 24) | (iv[13] << 16) | (iv[14] << 8) | iv[15];
321 | wlen = asm.gcm_decrypt( hpos, Math.min( hlen, hlen + dlen - tagSize ) & -15, iv[0], iv[1], iv[2], iv[3], iv[4], iv[5], iv[6], iv[7], iv[8], iv[9], iv[10], iv[11], (ivc+counter)|0 );
322 | if ( wlen ) result.set( heap.subarray( hpos, hpos+wlen ), rpos );
323 | counter += (wlen>>>4);
324 | rpos += wlen,
325 | hpos += wlen,
326 | hlen -= wlen;
327 |
328 | if ( !hlen ) hpos = _aes_heap_start;
329 | }
330 |
331 | this.result = result;
332 | this.counter = counter;
333 | this.pos = hpos;
334 | this.len = hlen;
335 |
336 | return this;
337 | }
338 |
339 | function gcm_aes_decrypt_finish () {
340 | if ( !this.key )
341 | throw new IllegalStateError("no key is associated with the instance");
342 |
343 | var asm = this.asm,
344 | heap = this.heap,
345 | iv = this.iv,
346 | adata = this.adata,
347 | counter = this.counter,
348 | tagSize = this.tagSize,
349 | hpos = this.pos,
350 | hlen = this.len,
351 | rlen = hlen - tagSize,
352 | wlen = 0;
353 |
354 | var result = new Uint8Array(rlen),
355 | atag = new Uint8Array( heap.subarray( hpos+rlen, hpos+hlen ) );
356 |
357 | var ivc = (iv[12] << 24) | (iv[13] << 16) | (iv[14] << 8) | iv[15];
358 |
359 | if ( hlen > 0 ) {
360 | wlen = asm.gcm_decrypt( hpos, rlen, iv[0], iv[1], iv[2], iv[3], iv[4], iv[5], iv[6], iv[7], iv[8], iv[9], iv[10], iv[11], (ivc+counter)|0 );
361 | if ( wlen ) result.set( heap.subarray( hpos, hpos+wlen ) );
362 | }
363 |
364 | var alen = ( adata !== null ) ? adata.length || 0 : 0,
365 | clen = ( (counter-1) << 4) + wlen;
366 | heap[_aes_heap_start|0] = heap[_aes_heap_start|1] = heap[_aes_heap_start|2] = 0,
367 | heap[_aes_heap_start|3] = (alen >>> 29),
368 | heap[_aes_heap_start|4] = (alen >>> 21),
369 | heap[_aes_heap_start|5] = (alen >>> 13) & 255,
370 | heap[_aes_heap_start|6] = (alen >>> 5) & 255,
371 | heap[_aes_heap_start|7] = (alen << 3) & 255,
372 | heap[_aes_heap_start|8] = heap[_aes_heap_start|9] = heap[_aes_heap_start|10] = 0,
373 | heap[_aes_heap_start|11] = (clen >>> 29),
374 | heap[_aes_heap_start|12] = (clen >>> 21) & 255,
375 | heap[_aes_heap_start|13] = (clen >>> 13) & 255,
376 | heap[_aes_heap_start|14] = (clen >>> 5) & 255,
377 | heap[_aes_heap_start|15] = (clen << 3) & 255;
378 | asm.gcm_ghash( _aes_heap_start, _aes_block_size );
379 | asm.save_state( _aes_heap_start );
380 |
381 | asm.gcm_encrypt( _aes_heap_start, _aes_block_size, iv[0], iv[1], iv[2], iv[3], iv[4], iv[5], iv[6], iv[7], iv[8], iv[9], iv[10], iv[11], ivc );
382 |
383 | var acheck = 0;
384 | for ( var i = 0; i < tagSize; ++i ) acheck |= atag[i] ^ heap[_aes_heap_start|i];
385 | if ( acheck )
386 | throw new SecurityError("data integrity check failed");
387 |
388 | this.result = result;
389 | this.counter = 1;
390 | this.pos = _aes_heap_start;
391 | this.len = 0;
392 |
393 | return this;
394 | }
395 |
396 | function gcm_aes_decrypt ( data ) {
397 | var result1 = gcm_aes_decrypt_process.call( this, data ).result,
398 | result2 = gcm_aes_decrypt_finish.call( this ).result;
399 |
400 | var result = new Uint8Array( result1.length + result2.length );
401 | if ( result1.length ) result.set( result1 );
402 | if ( result2.length ) result.set( result2, result1.length );
403 | this.result = result;
404 |
405 | return this;
406 | }
407 |
408 | var gcm_aes_prototype = gcm_aes_constructor.prototype;
409 | gcm_aes_prototype.reset = gcm_aes_reset;
410 | gcm_aes_prototype.encrypt = gcm_aes_encrypt;
411 | gcm_aes_prototype.decrypt = gcm_aes_decrypt;
412 |
413 | var gcm_aes_encrypt_prototype = gcm_aes_encrypt_constructor.prototype;
414 | gcm_aes_encrypt_prototype.reset = gcm_aes_reset;
415 | gcm_aes_encrypt_prototype.process = gcm_aes_encrypt_process;
416 | gcm_aes_encrypt_prototype.finish = gcm_aes_encrypt_finish;
417 |
418 | var gcm_aes_decrypt_prototype = gcm_aes_decrypt_constructor.prototype;
419 | gcm_aes_decrypt_prototype.reset = gcm_aes_reset;
420 | gcm_aes_decrypt_prototype.process = gcm_aes_decrypt_process;
421 | gcm_aes_decrypt_prototype.finish = gcm_aes_decrypt_finish;
422 |
--------------------------------------------------------------------------------
/src/aes/aes-ccm.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Counter with CBC-MAC (CCM)
3 | *
4 | * Due to JS limitations (counter is 32-bit unsigned) maximum encrypted message length
5 | * is limited to ~64 GiB ( 2^36 - 16 ) per `nonce`-`key` pair. That also limits `lengthSize` parameter
6 | * maximum value to 5 (not 8 as described in RFC3610).
7 | *
8 | * Additional authenticated data `adata` maximum length is limited to 65279 bytes ( 2^16 - 2^8 ),
9 | * wich is considered enough for the wast majority of use-cases.
10 | *
11 | * And one more important thing: in case of progressive ciphering of a data stream (in other
12 | * words when data can't be held in-memory at a whole and are ciphered chunk-by-chunk)
13 | * you have to know the `dataLength` in advance and pass that value to the cipher options.
14 | */
15 |
16 | function _cbc_mac_process ( data ) {
17 | var heap = this.heap,
18 | asm = this.asm,
19 | dpos = 0,
20 | dlen = data.length || 0,
21 | wlen = 0;
22 |
23 | while ( dlen > 0 ) {
24 | wlen = _heap_write( heap, _aes_heap_start, data, dpos, dlen );
25 | asm.cbc_mac( _aes_heap_start, wlen, -1 );
26 | dpos += wlen;
27 | dlen -= wlen;
28 | }
29 | }
30 |
31 | var _ccm_adata_maxLength = 65279, // 2^16 - 2^8
32 | _ccm_data_maxLength = 68719476720; // 2^36 - 2^4
33 |
34 | function ccm_aes_constructor ( options ) {
35 | this.padding = false; // WAT?
36 | this.mode = 'ccm';
37 |
38 | this.tagSize = _aes_block_size;
39 | this.lengthSize = 4;
40 |
41 | this.nonce = null;
42 |
43 | this.adata = null;
44 |
45 | this.iv = null;
46 | this.dataLength = -1;
47 | this.dataLeft = -1;
48 |
49 | this.counter = 1;
50 |
51 | _aes_constructor.call( this, options );
52 | }
53 |
54 | function ccm_aes_encrypt_constructor ( options ) {
55 | ccm_aes_constructor.call( this, options );
56 | }
57 |
58 | function ccm_aes_decrypt_constructor ( options ) {
59 | ccm_aes_constructor.call( this, options );
60 | }
61 |
62 | function _ccm_calculate_iv () {
63 | var nonce = this.nonce,
64 | adata = this.adata,
65 | tagSize = this.tagSize,
66 | lengthSize = this.lengthSize,
67 | dataLength = this.dataLength;
68 |
69 | var data = new Uint8Array( _aes_block_size + ( adata ? 2 + adata.length : 0 ) );
70 |
71 | // B0: flags(adata?, M', L'), nonce, len(data)
72 | data[0] = ( adata ? 64 : 0 ) | ( (tagSize-2)<<2 ) | ( lengthSize-1 );
73 | data.set( nonce, 1 );
74 | if (lengthSize > 4) data[11] = ( ( dataLength - (dataLength>>>0) ) / 4294967296 )&15;
75 | if (lengthSize > 3) data[12] = dataLength>>>24;
76 | if (lengthSize > 2) data[13] = dataLength>>>16&255;
77 | data[14] = dataLength>>>8&255;
78 | data[15] = dataLength&255;
79 |
80 | // B*: len(adata), adata
81 | if ( adata ) {
82 | data[16] = adata.length>>>8&255;
83 | data[17] = adata.length&255;
84 | data.set( adata, 18 );
85 | }
86 |
87 | _cbc_mac_process.call( this, data );
88 | this.asm.save_state( _aes_heap_start );
89 |
90 | this.iv = new Uint8Array( this.heap.subarray( _aes_heap_start, _aes_heap_start + _aes_block_size ) );
91 | }
92 |
93 | function ccm_aes_reset ( options ) {
94 | options = options || {};
95 |
96 | _aes_reset.call( this, options );
97 |
98 | _aes_init_iv.call( this, options.iv );
99 |
100 | var tagSize = options.tagSize;
101 | if ( tagSize !== undefined ) {
102 | if ( !is_number(tagSize) )
103 | throw new TypeError("tagSize must be a number");
104 |
105 | if ( tagSize < 4 || tagSize > 16 || tagSize & 1 )
106 | throw new IllegalArgumentError("illegal tagSize value");
107 |
108 | this.tagSize = tagSize;
109 | }
110 | else {
111 | this.tagSize = _aes_block_size;
112 | }
113 |
114 | var lengthSize = options.lengthSize,
115 | nonce = options.nonce;
116 | if ( nonce !== undefined ) {
117 | if ( is_buffer(nonce) || is_bytes(nonce) ) {
118 | nonce = new Uint8Array(nonce);
119 | }
120 | else if ( is_string(nonce) ) {
121 | nonce = string_to_bytes(nonce);
122 | }
123 | else {
124 | throw new TypeError("unexpected nonce type");
125 | }
126 |
127 | if ( nonce.length < 10 || nonce.length > 13 )
128 | throw new IllegalArgumentError("illegal nonce length");
129 |
130 | lengthSize = lengthSize || ( 15 - nonce.length );
131 |
132 | this.nonce = nonce;
133 | }
134 | else {
135 | this.nonce = null;
136 | }
137 |
138 | if ( lengthSize !== undefined ) {
139 | if ( !is_number(lengthSize) )
140 | throw new TypeError("lengthSize must be a number");
141 |
142 | if ( lengthSize < 2 || lengthSize > 5 || nonce.length + lengthSize !== 15 )
143 | throw new IllegalArgumentError("illegal lengthSize value");
144 |
145 | this.lengthSize = lengthSize;
146 | }
147 | else {
148 | this.lengthSize = lengthSize = 4;
149 | }
150 |
151 | var iv = this.iv;
152 |
153 | var counter = options.counter;
154 | if ( counter !== undefined ) {
155 | if ( iv === null )
156 | throw new IllegalStateError("iv is also required");
157 |
158 | if ( !is_number(counter) )
159 | throw new TypeError("counter must be a number");
160 |
161 | this.counter = counter;
162 | }
163 | else {
164 | this.counter = 1;
165 | }
166 |
167 | var dataLength = options.dataLength;
168 | if ( dataLength !== undefined ) {
169 | if ( !is_number(dataLength) )
170 | throw new TypeError("dataLength must be a number");
171 |
172 | if ( dataLength < 0 || dataLength > _ccm_data_maxLength || dataLength > ( Math.pow( 2, 8*lengthSize ) - 1 ) )
173 | throw new IllegalArgumentError("illegal dataLength value");
174 |
175 | this.dataLength = dataLength;
176 |
177 | var dataLeft = options.dataLeft || dataLength;
178 |
179 | if ( !is_number(dataLeft) )
180 | throw new TypeError("dataLeft must be a number");
181 |
182 | if ( dataLeft < 0 || dataLeft > dataLength )
183 | throw new IllegalArgumentError("illegal dataLeft value");
184 |
185 | this.dataLeft = dataLeft;
186 | }
187 | else {
188 | this.dataLength = dataLength = -1;
189 | this.dataLeft = dataLength;
190 | }
191 |
192 | var adata = options.adata;
193 | if ( adata !== undefined ) {
194 | if ( iv !== null )
195 | throw new IllegalStateError("you must specify either adata or iv, not both");
196 |
197 | if ( is_buffer(adata) || is_bytes(adata) ) {
198 | adata = new Uint8Array(adata);
199 | }
200 | else if ( is_string(adata) ) {
201 | adata = string_to_bytes(adata);
202 | }
203 | else {
204 | throw new TypeError("unexpected adata type");
205 | }
206 |
207 | if ( adata.length === 0 || adata.length > _ccm_adata_maxLength )
208 | throw new IllegalArgumentError("illegal adata length");
209 |
210 | this.adata = adata;
211 | this.counter = 1;
212 | }
213 | else {
214 | this.adata = adata = null;
215 | }
216 |
217 | if ( dataLength !== -1 )
218 | _ccm_calculate_iv.call(this);
219 |
220 | return this;
221 | }
222 |
223 | function ccm_aes_encrypt_process ( data ) {
224 | if ( !this.key )
225 | throw new IllegalStateError("no key is associated with the instance");
226 |
227 | if ( is_string(data) )
228 | data = string_to_bytes(data);
229 |
230 | if ( is_buffer(data) )
231 | data = new Uint8Array(data);
232 |
233 | if ( !is_bytes(data) )
234 | throw new TypeError("data isn't of expected type");
235 |
236 | var dpos = 0,
237 | dlen = data.length || 0,
238 | asm = this.asm,
239 | heap = this.heap,
240 | nonce = this.nonce,
241 | counter = this.counter,
242 | pos = this.pos,
243 | len = this.len,
244 | rpos = 0,
245 | rlen = _aes_block_size * Math.floor( ( len + dlen ) / _aes_block_size ),
246 | wlen = 0;
247 |
248 | if ( ((counter-1)<<4) + len + dlen > _ccm_data_maxLength )
249 | throw new RangeError("counter overflow");
250 |
251 | var result = new Uint8Array(rlen);
252 |
253 | var asm_args = [ 0, 0, (this.lengthSize-1), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ];
254 | for ( var i = 0; i < nonce.length; i++ ) asm_args[3+i] = nonce[i];
255 |
256 | while ( dlen > 0 ) {
257 | wlen = _heap_write( heap, pos+len, data, dpos, dlen );
258 | len += wlen;
259 | dpos += wlen;
260 | dlen -= wlen;
261 |
262 | asm_args[0] = pos;
263 | asm_args[1] = len & ~15; // same as (len - (len % 16))
264 | asm_args[16] = (counter/0x100000000)>>>0;
265 | asm_args[17] = counter>>>0;
266 |
267 | wlen = asm.ccm_encrypt.apply( asm, asm_args );
268 | result.set( heap.subarray( pos, pos + wlen ), rpos );
269 | counter += (wlen>>>4);
270 | rpos += wlen;
271 |
272 | if ( wlen < len ) {
273 | pos += wlen;
274 | len -= wlen;
275 | } else {
276 | pos = _aes_heap_start;
277 | len = 0;
278 | }
279 | }
280 |
281 | this.result = result;
282 | this.counter = counter;
283 | this.pos = pos;
284 | this.len = len;
285 |
286 | return this;
287 | }
288 |
289 | function ccm_aes_encrypt_finish () {
290 | if ( !this.key )
291 | throw new IllegalStateError("no key is associated with the instance");
292 |
293 | var asm = this.asm,
294 | heap = this.heap,
295 | nonce = this.nonce,
296 | counter = this.counter,
297 | tagSize = this.tagSize,
298 | pos = this.pos,
299 | len = this.len,
300 | wlen = 0;
301 |
302 | var result = new Uint8Array( len + tagSize );
303 |
304 | var asm_args = [ 0, 0, (this.lengthSize-1), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ];
305 | for ( var i = 0; i < nonce.length; i++ ) asm_args[3+i] = nonce[i];
306 |
307 | asm_args[0] = pos;
308 | asm_args[1] = len;
309 | asm_args[16] = (counter/0x100000000)>>>0;
310 | asm_args[17] = counter>>>0;
311 |
312 | wlen = asm.ccm_encrypt.apply( asm, asm_args );
313 | result.set( heap.subarray( pos, pos + wlen ) );
314 | counter = 1;
315 | pos = _aes_heap_start;
316 | len = 0;
317 |
318 | asm.save_state( _aes_heap_start );
319 |
320 | asm_args[0] = _aes_heap_start,
321 | asm_args[1] = _aes_block_size,
322 | asm_args[16] = 0;
323 | asm_args[17] = 0;
324 | asm.ccm_encrypt.apply( asm, asm_args );
325 |
326 | result.set( heap.subarray( _aes_heap_start, _aes_heap_start + tagSize ), wlen );
327 |
328 | this.result = result;
329 | this.counter = counter;
330 | this.pos = pos;
331 | this.len = len;
332 |
333 | return this;
334 | }
335 |
336 | function ccm_aes_encrypt ( data ) {
337 | this.dataLength = this.dataLeft = data.length || 0;
338 |
339 | var result1 = ccm_aes_encrypt_process.call( this, data ).result,
340 | result2 = ccm_aes_encrypt_finish.call(this).result,
341 | result;
342 |
343 | result = new Uint8Array( result1.length + result2.length );
344 | result.set(result1);
345 | result.set( result2, result1.length );
346 | this.result = result;
347 |
348 | return this;
349 | }
350 |
351 | function ccm_aes_decrypt_process ( data ) {
352 | if ( !this.key )
353 | throw new IllegalStateError("no key is associated with the instance");
354 |
355 | if ( is_string(data) )
356 | data = string_to_bytes(data);
357 |
358 | if ( is_buffer(data) )
359 | data = new Uint8Array(data);
360 |
361 | if ( !is_bytes(data) )
362 | throw new TypeError("data isn't of expected type");
363 |
364 | var dpos = 0,
365 | dlen = data.length || 0,
366 | asm = this.asm,
367 | heap = this.heap,
368 | nonce = this.nonce,
369 | counter = this.counter,
370 | tagSize = this.tagSize,
371 | pos = this.pos,
372 | len = this.len,
373 | rpos = 0,
374 | rlen = _aes_block_size * Math.floor( ( len + dlen ) / _aes_block_size ),
375 | wlen = 0;
376 |
377 | if ( ((counter-1)<<4) + len + dlen > _ccm_data_maxLength )
378 | throw new RangeError("counter overflow");
379 |
380 | var result = new Uint8Array(rlen);
381 |
382 | var asm_args = [ 0, 0, (this.lengthSize-1), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ];
383 | for ( var i = 0; i < nonce.length; i++ ) asm_args[3+i] = nonce[i];
384 |
385 | while ( dlen > 0 ) {
386 | wlen = _heap_write( heap, pos+len, data, dpos, dlen );
387 | len += wlen;
388 | dpos += wlen;
389 | dlen -= wlen;
390 |
391 | asm_args[0] = pos;
392 | asm_args[1] = len + dlen - tagSize >= _aes_block_size ? dlen >= tagSize ? len & ~15 : (len + dlen - tagSize) & ~15 : 0;
393 | asm_args[16] = (counter/0x100000000)>>>0;
394 | asm_args[17] = counter>>>0;
395 |
396 | wlen = asm.ccm_decrypt.apply( asm, asm_args );
397 | result.set( heap.subarray( pos, pos + wlen ), rpos );
398 | counter += (wlen>>>4);
399 | rpos += wlen;
400 |
401 | if ( wlen < len ) {
402 | pos += wlen;
403 | len -= wlen;
404 | } else {
405 | pos = _aes_heap_start;
406 | len = 0;
407 | }
408 | }
409 |
410 | this.result = result.subarray( 0, rpos );
411 | this.counter = counter;
412 | this.pos = pos;
413 | this.len = len;
414 |
415 | return this;
416 | }
417 |
418 | function ccm_aes_decrypt_finish () {
419 | if ( !this.key )
420 | throw new IllegalStateError("no key is associated with the instance");
421 |
422 | var asm = this.asm,
423 | heap = this.heap,
424 | nonce = this.nonce,
425 | counter = this.counter,
426 | tagSize = this.tagSize,
427 | pos = this.pos,
428 | len = this.len,
429 | rlen = len - tagSize,
430 | wlen = 0;
431 |
432 | if ( len < tagSize )
433 | throw new IllegalStateError("authentication tag not found");
434 |
435 | var result = new Uint8Array(rlen),
436 | atag = new Uint8Array( heap.subarray( pos+rlen, pos+len ) );
437 |
438 | var asm_args = [ 0, 0, (this.lengthSize-1), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ];
439 | for ( var i = 0; i < nonce.length; i++ ) asm_args[3+i] = nonce[i];
440 |
441 | asm_args[0] = pos;
442 | asm_args[1] = rlen;
443 | asm_args[16] = (counter/0x100000000)>>>0;
444 | asm_args[17] = counter>>>0;
445 |
446 | wlen = asm.ccm_decrypt.apply( asm, asm_args );
447 | result.set( heap.subarray( pos, pos + wlen ) );
448 | counter = 1;
449 | pos = _aes_heap_start;
450 | len = 0;
451 |
452 | asm.save_state( _aes_heap_start );
453 |
454 | asm_args[0] = _aes_heap_start,
455 | asm_args[1] = _aes_block_size,
456 | asm_args[16] = 0;
457 | asm_args[17] = 0;
458 | asm.ccm_encrypt.apply( asm, asm_args );
459 |
460 | var acheck = 0;
461 | for ( var i = 0; i < tagSize; ++i ) acheck |= atag[i] ^ heap[ _aes_heap_start + i ];
462 | if ( acheck )
463 | throw new SecurityError("data integrity check failed");
464 |
465 | this.result = result;
466 | this.counter = counter;
467 | this.pos = pos;
468 | this.len = len;
469 |
470 | return this;
471 | }
472 |
473 | function ccm_aes_decrypt ( data ) {
474 | this.dataLength = this.dataLeft = data.length || 0;
475 |
476 | var result1 = ccm_aes_decrypt_process.call( this, data ).result,
477 | result2 = ccm_aes_decrypt_finish.call(this).result,
478 | result;
479 |
480 | result = new Uint8Array( result1.length + result2.length );
481 | result.set(result1);
482 | result.set( result2, result1.length );
483 | this.result = result;
484 |
485 | return this;
486 | }
487 |
488 | var ccm_aes_prototype = ccm_aes_constructor.prototype;
489 | ccm_aes_prototype.reset = ccm_aes_reset;
490 | ccm_aes_prototype.encrypt = ccm_aes_encrypt;
491 | ccm_aes_prototype.decrypt = ccm_aes_decrypt;
492 |
493 | var ccm_aes_encrypt_prototype = ccm_aes_encrypt_constructor.prototype;
494 | ccm_aes_encrypt_prototype.reset = ccm_aes_reset;
495 | ccm_aes_encrypt_prototype.process = ccm_aes_encrypt_process;
496 | ccm_aes_encrypt_prototype.finish = ccm_aes_encrypt_finish;
497 |
498 | var ccm_aes_decrypt_prototype = ccm_aes_decrypt_constructor.prototype;
499 | ccm_aes_decrypt_prototype.reset = ccm_aes_reset;
500 | ccm_aes_decrypt_prototype.process = ccm_aes_decrypt_process;
501 | ccm_aes_decrypt_prototype.finish = ccm_aes_decrypt_finish;
502 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | asmCrypto [](https://travis-ci.org/vibornoff/asmcrypto.js) [](https://saucelabs.com/u/vibornoff)
2 | =========
3 |
4 | JavaScript implementation of popular cryptographic utilities with performance in mind.
5 |
6 | Synopsis
7 | --------
8 |
9 | Add `` into your page.
10 |
11 | // Hash whole string at once
12 | digest = asmCrypto.SHA256.hex("The quick brown fox jumps over the lazy dog");
13 |
14 | Index
15 | -----
16 |
17 | * [Download] (#download)
18 | * [Build & Test](#build--test)
19 | * [Performance](#performance)
20 | * [API Reference](#api-reference)
21 | * [Message Digest](#sha256)
22 | * [SHA1](#sha1)
23 | * [SHA256](#sha256)
24 | * [SHA512](#sha512)
25 | * [Hash-based Message Authentication](#hmac)
26 | * [HMAC-SHA1](#hmac_sha1)
27 | * [HMAC-SHA256](#hmac_sha256)
28 | * [HMAC-SHA512](#hmac_sha512)
29 | * [Password-based Key Derivation](#pbkdf2)
30 | * [PBKDF2-HMAC-SHA1](#pbkdf2_hmac_sha1)
31 | * [PBKDF2-HMAC-SHA256](#pbkdf2_hmac_sha256)
32 | * [PBKDF2-HMAC-SHA512](#pbkdf2_hmac_sha512)
33 | * [Block Cipher](#aes)
34 | * [AES-CBC](#aes_cbc)
35 | * [AES-CFB](#aes_cfb)
36 | * [AES-CCM](#aes_ccm)
37 | * [Asymmetric encryption](#rsa)
38 | * [RSA](#rsa)
39 | * [RSA-OAEP-SHA256](#rsa_oaep_sha256)
40 | * [RSA-OAEP-SHA512](#rsa_oaep_sha256)
41 | * [RSA-PSS-SHA256](#rsa_pss_sha512)
42 | * [RSA-PSS-SHA512](#rsa_pss_sha512)
43 | * [Cryptographically secure pseudorandom number generator](#cryptographically-secure-pseudorandom-number-generator)
44 | * [Bugs & TODO](#bugs--todo)
45 | * [Donate](#donate)
46 |
47 | Download
48 | --------
49 |
50 | * [Minified JS file](http://vibornoff.com/asmcrypto.js) 170KB,
51 | * [Source Map file](http://vibornoff.com/asmcrypto.js.map) 313KB,
52 | * [All-in-One archive](http://vibornoff.com/asmcrypto.tar.gz) 178KB.
53 |
54 | Build & Test
55 | ------------
56 |
57 | Before you start check that [npm](http://npmjs.org/) is installed:
58 |
59 | npm --version
60 |
61 | Then download and build the stuff:
62 |
63 | git clone https://github.com/vibornoff/asmcrypto.js.git
64 | cd asmcrypto.js/
65 | npm install
66 |
67 | Running tests is always a good idea:
68 |
69 | npm test
70 |
71 | Congratulations! Now you have your `asmcrypto.js` and `asmcrypto.js.map` ready to use ☺
72 |
73 | Performance
74 | -----------
75 |
76 | In the development of this project, special attention was paid to the performance issues.
77 | In the result of all the optimizations made this stuff is pretty fast under Firefox and Chrome.
78 |
79 | My *Intel® Core™ i7-3770 CPU @ 3.40GHz* typical processing speeds are:
80 | * *Chrome/31.0*
81 | * SHA256: 51 MiB/s (**9 times faster** than *SJCL* and *CryptoJS*)
82 | * AES-CBC: 47 MiB/s (**13 times faster** than *CryptoJS* and **20 times faster** than *SJCL*)
83 | * *Firefox/26.0*
84 | * SHA256: 144 MiB/s (**5 times faster** than *CryptoJS* and **20 times faster** than *SJCL*)
85 | * AES-CBC: 81 MiB/s (**3 times faster** than *CryptoJS* and **8 times faster** than *SJCL*)
86 |
87 | See benchmarks:
88 | * [SHA256](http://jsperf.com/sha256/34),
89 | * [HMAC-SHA256](http://jsperf.com/hmac-sha256/1),
90 | * [PBKDF2-HMAC-SHA256](http://jsperf.com/pbkdf2-hmac-sha256/2),
91 | * [AES](http://jsperf.com/aes),
92 | * [Modular exponentiation (used internally in RSA)](http://jsperf.com/jsbn-vs-bigint-js-modular-exponentiation-montgomery/4).
93 |
94 | API Reference
95 | -------------
96 |
97 | ### Message Digest
98 |
99 | #### SHA1
100 |
101 | [Secure Hash Algorithm](http://en.wikipedia.org/wiki/SHA-1) — a cryptographic hash function with 160-bit output.
102 |
103 | A cryptographic hash fuction with 256-bit output.
104 |
105 | ##### SHA1.BLOCK_SIZE = 64
106 |
107 | ##### SHA1.HASH_SIZE = 20
108 |
109 | ##### SHA1.bytes( data )
110 |
111 | Calculates message digest of the supplied input `data` (can be a binary string or `ArrayBuffer`/`Uint8Array` object).
112 |
113 | Returns raw message digest as an `Uint8Array` object.
114 |
115 | Throws
116 | * `TypeError` when something ridiculous is supplied as input data.
117 |
118 | ##### SHA1.hex( data )
119 |
120 | Calculates message digest of the supplied input `data` (can be a binary string or `ArrayBuffer`/`Uint8Array` object).
121 |
122 | Returns a string containing hex-encoded message digest.
123 |
124 | Throws
125 | * `TypeError` when something ridiculous is supplied as input data.
126 |
127 | ##### SHA1.base64( data )
128 |
129 | Calculates message digest of the supplied input `data` (can be a binary string or `ArrayBuffer`/`Uint8Array` object).
130 |
131 | Returns a string containing hex-encoded message digest.
132 |
133 | Throws
134 | * `TypeError` when something ridiculous is supplied as input data.
135 |
136 | #### SHA256
137 |
138 | [Secure Hash Algorithm](http://en.wikipedia.org/wiki/SHA-2) — a cryptographic hash functions family.
139 |
140 | A cryptographic hash fuction with 256-bit output.
141 |
142 | ##### SHA256.BLOCK_SIZE = 64
143 |
144 | ##### SHA256.HASH_SIZE = 32
145 |
146 | ##### SHA256.bytes( data )
147 |
148 | Calculates message digest of the supplied input `data` (can be a binary string or `ArrayBuffer`/`Uint8Array` object).
149 |
150 | Returns raw message digest as an `Uint8Array` object.
151 |
152 | Throws
153 | * `TypeError` when something ridiculous is supplied as input data.
154 |
155 | ##### SHA256.hex( data )
156 |
157 | Calculates message digest of the supplied input `data` (can be a binary string or `ArrayBuffer`/`Uint8Array` object).
158 |
159 | Returns a string containing hex-encoded message digest.
160 |
161 | Throws
162 | * `TypeError` when something ridiculous is supplied as input data.
163 |
164 | ##### SHA256.base64( data )
165 |
166 | Calculates message digest of the supplied input `data` (can be a binary string or `ArrayBuffer`/`Uint8Array` object).
167 |
168 | Returns a string containing hex-encoded message digest.
169 |
170 | Throws
171 | * `TypeError` when something ridiculous is supplied as input data.
172 |
173 | #### SHA512
174 |
175 | A cryptographic hash function with 512-bit output.
176 |
177 | ##### SHA512.BLOCK_SIZE = 128
178 |
179 | ##### SHA512.HASH_SIZE = 64
180 |
181 | ##### SHA512.bytes( data )
182 |
183 | Calculates message digest of the supplied input `data` (can be a binary string or `ArrayBuffer`/`Uint8Array` object).
184 |
185 | Returns raw message digest as an `Uint8Array` object.
186 |
187 | Throws
188 | * `TypeError` when something ridiculous is supplied as input data.
189 |
190 | ##### SHA512.hex( data )
191 |
192 | Calculates message digest of the supplied input `data` (can be a binary string or `ArrayBuffer`/`Uint8Array` object).
193 |
194 | Returns a string containing hex-encoded message digest.
195 |
196 | Throws
197 | * `TypeError` when something ridiculous is supplied as input data.
198 |
199 | ##### SHA512.base64( data )
200 |
201 | Calculates message digest of the supplied input `data` (can be a binary string or `ArrayBuffer`/`Uint8Array` object).
202 |
203 | Returns a string containing hex-encoded message digest.
204 |
205 | Throws
206 | * `TypeError` when something ridiculous is supplied as input data.
207 |
208 | ### HMAC
209 |
210 | [Hash-based Message Authentication Code](http://en.wikipedia.org/wiki/HMAC)
211 |
212 | Used to calculate message authentication code with a cryptographic hash function
213 | in combination with a secret cryptographic key.
214 |
215 | #### HMAC_SHA1
216 |
217 | ##### HMAC_SHA1.BLOCK_SIZE = 64
218 |
219 | ##### HMAC_SHA1.HMAC_SIZE = 20
220 |
221 | ##### HMAC_SHA1.bytes( password, data )
222 |
223 | Calculates HMAC-SHA1 of `data` with `password`. Both can be either binary strings or `Uint8Array`/`ArrayBuffer` objects.
224 |
225 | Returns araw message authentication code as an `Uint8Array` object.
226 |
227 | Throws
228 | * `TypeError` when something ridiculous is supplied as input data.
229 |
230 | ##### HMAC_SHA1.hex( password, data )
231 |
232 | Calculates HMAC-SHA1 of `data` with `password`. Both can be either binary strings or `Uint8Array`/`ArrayBuffer` objects.
233 |
234 | Returns a string containing hex-encoded message authentication code.
235 |
236 | Throws
237 | * `TypeError` when something ridiculous is supplied as input data.
238 |
239 | ##### HMAC_SHA1.base64( password, data )
240 |
241 | Calculates HMAC-SHA1 of `data` with `password`. Both can be either binary strings or `Uint8Array`/`ArrayBuffer` objects.
242 |
243 | Returns a string containing base64-encoded message authentication code.
244 |
245 | Throws
246 | * `TypeError` when something ridiculous is supplied as input data.
247 |
248 | #### HMAC_SHA256
249 |
250 | ##### HMAC_SHA256.BLOCK_SIZE = 64
251 |
252 | ##### HMAC_SHA256.HMAC_SIZE = 32
253 |
254 | ##### HMAC_SHA256.bytes( password, data )
255 |
256 | Calculates HMAC-SHA256 of `data` with `password`. Both can be either binary strings or `Uint8Array`/`ArrayBuffer` objects.
257 |
258 | Returns araw message authentication code as an `Uint8Array` object.
259 |
260 | Throws
261 | * `TypeError` when something ridiculous is supplied as input data.
262 |
263 | ##### HMAC_SHA256.hex( password, data )
264 |
265 | Calculates HMAC-SHA256 of `data` with `password`. Both can be either binary strings or `Uint8Array`/`ArrayBuffer` objects.
266 |
267 | Returns a string containing hex-encoded message authentication code.
268 |
269 | Throws
270 | * `TypeError` when something ridiculous is supplied as input data.
271 |
272 | ##### HMAC_SHA256.base64( password, data )
273 |
274 | Calculates HMAC-SHA256 of `data` with `password`. Both can be either binary strings or `Uint8Array`/`ArrayBuffer` objects.
275 |
276 | Returns a string containing base64-encoded message authentication code.
277 |
278 | Throws
279 | * `TypeError` when something ridiculous is supplied as input data.
280 |
281 | #### HMAC_SHA512
282 |
283 | ##### HMAC_SHA512.BLOCK_SIZE = 128
284 |
285 | ##### HMAC_SHA512.HMAC_SIZE = 64
286 |
287 | ##### HMAC_SHA512.bytes( password, data )
288 |
289 | Calculates HMAC-SHA512 of `data` with `password`. Both can be either binary strings or `Uint8Array`/`ArrayBuffer` objects.
290 |
291 | Returns araw message authentication code as an `Uint8Array` object.
292 |
293 | Throws
294 | * `TypeError` when something ridiculous is supplied as input data.
295 |
296 | ##### HMAC_SHA512.hex( password, data )
297 |
298 | Calculates HMAC-SHA512 of `data` with `password`. Both can be either binary strings or `Uint8Array`/`ArrayBuffer` objects.
299 |
300 | Returns a string containing hex-encoded message authentication code.
301 |
302 | Throws
303 | * `TypeError` when something ridiculous is supplied as input data.
304 |
305 | ##### HMAC_SHA512.base64( password, data )
306 |
307 | Calculates HMAC-SHA512 of `data` with `password`. Both can be either binary strings or `Uint8Array`/`ArrayBuffer` objects.
308 |
309 | Returns a string containing base64-encoded message authentication code.
310 |
311 | Throws
312 | * `TypeError` when something ridiculous is supplied as input data.
313 |
314 | ### PBKDF2
315 |
316 | [Password-Based Key Derivation Function 2](http://en.wikipedia.org/wiki/PBKDF2)
317 |
318 | 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,
319 | which can then be used as a cryptographic key in subsequent operations. The added computational work makes password cracking much more difficult.
320 |
321 | #### PBKDF2_HMAC_SHA1
322 |
323 | ##### PBKDF2_HMAC_SHA1.bytes( password, salt, iterations, dklen )
324 |
325 | Derive key from the `password` with `salt`. Both can be either binary strings or `Uint8Array`/`ArrayBuffer` objects.
326 |
327 | Optional `iterations` (number of key derivatoin rounds) and `dklen` (desired key length) may be supplied.
328 |
329 | Throws
330 | * `TypeError`.
331 |
332 | ##### PBKDF2_HMAC_SHA1.hex( password, salt, iterations, dklen )
333 |
334 | The same as above except returning value type.
335 |
336 | ##### PBKDF2_HMAC_SHA1.base64( password, salt, iterations, dklen )
337 |
338 | The same as above except returning value type.
339 |
340 | #### PBKDF2_HMAC_SHA526
341 |
342 | ##### PBKDF2_HMAC_SHA256.bytes( password, salt, iterations, dklen )
343 |
344 | Derive key from the `password` with `salt`. Both can be either binary strings or `Uint8Array`/`ArrayBuffer` objects.
345 |
346 | Optional `iterations` (number of key derivatoin rounds) and `dklen` (desired key length) may be supplied.
347 |
348 | Throws
349 | * `TypeError`.
350 |
351 | ##### PBKDF2_HMAC_SHA256.hex( password, salt, iterations, dklen )
352 |
353 | The same as above except returning value type.
354 |
355 | ##### PBKDF2_HMAC_SHA256.base64( password, salt, iterations, dklen )
356 |
357 | The same as above except returning value type.
358 |
359 | #### PBKDF2_HMAC_SHA512
360 |
361 | ##### PBKDF2_HMAC_SHA512.bytes( password, salt, iterations, dklen )
362 |
363 | Derive key from the `password` with `salt`. Both can be either binary strings or `Uint8Array`/`ArrayBuffer` objects.
364 |
365 | Optional `iterations` (number of key derivatoin rounds) and `dklen` (desired key length) may be supplied.
366 |
367 | Throws
368 | * `TypeError`.
369 |
370 | ##### PBKDF2_HMAC_SHA512.hex( password, salt, iterations, dklen )
371 |
372 | The same as above except returning value type.
373 |
374 | ##### PBKDF2_HMAC_SHA512.base64( password, salt, iterations, dklen )
375 |
376 | The same as above except returning value type.
377 |
378 | ### AES
379 |
380 | Advanced Encryption Standard
381 |
382 | #### AES.BLOCK_SIZE = 16
383 |
384 | #### AES_CBC
385 |
386 | Cipher Block Chaining Mode.
387 | s
388 | ##### AES_CBC.encrypt( data, key, padding, iv )
389 |
390 | Encrypts supplied `data` with `key` in CBC mode. Both can be either binary strings or `Uint8Array` objects or `ArrayBuffer` objects.
391 |
392 | Optional `padding` and `iv` may be passed to override default settings (PKCS#7 padding is on and iv is zero-vector).
393 |
394 | Returns encrypted data as `Uint8Array`.
395 |
396 | ##### AES_CBC.decrypt( data, key, padding, iv )
397 |
398 | Decrypts supplied `data` with `key` in CBC mode. Both can be either binary strings or `Uint8Array` objects or `ArrayBuffer` objects.
399 |
400 | Optional `padding` and `iv` may be passed to override default settings (PKCS#7 padding is on and iv is zero-vector).
401 |
402 | Returns encrypted data as `Uint8Array`.
403 |
404 | #### AES_CFB
405 |
406 | Cipher Feedback Mode.
407 |
408 | ##### AES_CFB.encrypt( data, key, padding, iv )
409 |
410 | Encrypts supplied `data` with `key` in CFB mode. Both can be either binary strings or `Uint8Array` objects or `ArrayBuffer` objects.
411 |
412 | Optional `padding` and `iv` may be passed to override default settings (PKCS#7 padding is on and iv is zero-vector).
413 |
414 | Returns encrypted data as `Uint8Array`.
415 |
416 | ##### AES_CFB.decrypt( data, key, padding, iv )
417 |
418 | Decrypts supplied `data` with `key` in CFB mode. Both can be either binary strings or `Uint8Array` objects or `ArrayBuffer` objects.
419 |
420 | Optional `padding` and `iv` may be passed to override default settings (PKCS#7 padding is on and iv is zero-vector).
421 |
422 | Returns encrypted data as `Uint8Array`.
423 |
424 | #### AES_CCM
425 |
426 | Counter with CBC-MAC mode.
427 |
428 | 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.
429 |
430 | Additional authenticated data `adata` maximum length is limited to 65279 bytes ( 2^16 - 2^8 ),
431 | wich is considered enough for the most of use-cases.
432 |
433 | Optional `tagSize`, the size of the authentication tag, may be 4, 6, 8, 12, 16 (default).
434 |
435 | Keep in mind that **same nonce must not be used more than once with the same key**.
436 |
437 | ##### AES_CCM.encrypt( data, key, nonce, adata, tagsize )
438 |
439 | Encrypts supplied `data` with `key`-`nonce` in CCM mode.
440 |
441 | Returns encrypted data as `Uint8Array`.
442 |
443 | ##### AES_CCM.decrypt( data, key, nonce, adata, tagsize )
444 |
445 | Decrypts supplied `data` with `key`-`nonce` in CCM mode.
446 |
447 | Returns encrypted data as `Uint8Array`.
448 |
449 | ### RSA
450 |
451 | #### RSA.generateKey( bitlen, pubexp )
452 |
453 | Generate RSA private key of `bitlen` length along with the public exponent `pubexp`.
454 |
455 | Run 50 rounds of Miller-Rabin test for each prime candidate.
456 |
457 | #### RSA_OAEP_SHA256
458 |
459 | ##### RSA_OAEP_SHA256.encrypt( data, key, label )
460 |
461 | TODO
462 |
463 | ##### RSA_OAEP_SHA256.decrypt( data, key, label )
464 |
465 | TODO
466 |
467 | #### RSA_OAEP_SHA512
468 |
469 | ##### RSA_OAEP_SHA512.encrypt( data, key, label )
470 |
471 | TODO
472 |
473 | ##### RSA_OAEP_SHA512.decrypt( data, key, label )
474 |
475 | TODO
476 |
477 | #### RSA_PSS_SHA256
478 |
479 | ##### RSA_PSS_SHA256.sign( data, key, slen )
480 |
481 | TODO
482 |
483 | ##### RSA_PSS_SHA256.verify( signature, data, key, slen )
484 |
485 | TODO
486 |
487 | #### RSA_PSS_SHA512
488 |
489 | ##### RSA_PSS_SHA512.sign( data, key, slen )
490 |
491 | TODO
492 |
493 | ##### RSA_PSS_SHA512.verify( signature, data, key, slen )
494 |
495 | TODO
496 |
497 | ### Cryptographically secure pseudorandom number generator
498 |
499 | TODO
500 |
501 | Bugs & TODO
502 | -----------
503 |
504 | * Progressive operations are temporary fade out, they'll be back with WebCrypto API;
505 | * Moar docs needed ☺
506 |
507 | Not yet implemented:
508 | * aes-gcm,
509 | * scrypt,
510 | * dsa, ecdsa,
511 | * rsa-pkcs-v1.5
512 |
513 | Donate
514 | ------
515 |
516 | If you like this stuff feel free to donate some funds to `1CiGzP1EFLTftqkfvVtbwvZ9Koiuoc4FSC` ☺
517 |
--------------------------------------------------------------------------------