Showing preview only (569K chars total). Download the full file or copy to clipboard to get everything.
Repository: vibornoff/asmcrypto.js
Branch: master
Commit: f3bd6c6a4b0f
Files: 61
Total size: 546.2 KB
Directory structure:
gitextract_csuw1e3z/
├── .editorconfig
├── .esmrc
├── .gitignore
├── .npmignore
├── .prettierignore
├── .prettierrc
├── .travis.yml
├── LICENSE
├── README.md
├── build.js
├── package.json
├── src/
│ ├── aes/
│ │ ├── aes.asm.d.ts
│ │ ├── aes.asm.js
│ │ ├── aes.ts
│ │ ├── cbc.ts
│ │ ├── ccm.ts
│ │ ├── cfb.ts
│ │ ├── cmac.ts
│ │ ├── ctr.ts
│ │ ├── ecb.ts
│ │ ├── exports.ts
│ │ ├── gcm.ts
│ │ └── ofb.ts
│ ├── bignum/
│ │ ├── bigint.asm.d.ts
│ │ ├── bigint.asm.js
│ │ ├── bignum.ts
│ │ └── extgcd.ts
│ ├── entry-default.ts
│ ├── entry-export_all.ts
│ ├── hash/
│ │ ├── hash.ts
│ │ ├── sha1/
│ │ │ ├── sha1.asm.d.ts
│ │ │ ├── sha1.asm.js
│ │ │ └── sha1.ts
│ │ ├── sha256/
│ │ │ ├── sha256.asm.d.ts
│ │ │ ├── sha256.asm.js
│ │ │ └── sha256.ts
│ │ └── sha512/
│ │ ├── sha512.asm.d.ts
│ │ ├── sha512.asm.js
│ │ └── sha512.ts
│ ├── hmac/
│ │ ├── hmac-sha1.ts
│ │ ├── hmac-sha256.ts
│ │ ├── hmac-sha512.ts
│ │ └── hmac.ts
│ ├── other/
│ │ ├── errors.ts
│ │ ├── exportedUtils.ts
│ │ ├── get-random-values.ts
│ │ └── utils.ts
│ ├── pbkdf2/
│ │ ├── pbkdf2-core.ts
│ │ ├── pbkdf2-hmac-sha1.ts
│ │ ├── pbkdf2-hmac-sha256.ts
│ │ └── pbkdf2-hmac-sha512.ts
│ └── rsa/
│ ├── pkcs1.ts
│ └── rsa.ts
├── test/
│ ├── aes.js
│ ├── bignum.js
│ ├── rsa.js
│ ├── sha1.js
│ ├── sha256.js
│ └── sha512.js
├── tsconfig.json
└── tslint.json
================================================
FILE CONTENTS
================================================
================================================
FILE: .editorconfig
================================================
[*]
end_of_line = lf
insert_final_newline = true
charset = utf-8
indent_style = space
indent_size = 2
================================================
FILE: .esmrc
================================================
{
"mode": "all",
"cjs": {
"namedExports": true,
"vars": true,
"interop": true
}
}
================================================
FILE: .gitignore
================================================
asmcrypto*.js
asmcrypto*.mjs
asmcrypto*.map
test/aes.asm.js
test/aes.asm.js.map
doc/
node_modules/
.idea/
dist_es5
dist_es8
================================================
FILE: .npmignore
================================================
doc/
node_modules/
.idea/
package-lock.json
*.ts
!*.d.ts
================================================
FILE: .prettierignore
================================================
*.asm.*
================================================
FILE: .prettierrc
================================================
{
"printWidth": 120,
"singleQuote": true,
"trailingComma": "all"
}
================================================
FILE: .travis.yml
================================================
language: node_js
node_js:
- '10'
- '12'
- '14'
script:
npm test
================================================
FILE: LICENSE
================================================
The MIT License (MIT)
Copyright (c) 2013 Artem S Vybornov
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
================================================
FILE: README.md
================================================
asmCrypto
=========
Not maintained anymore, use a native or WASM implementation instead.
================================================
FILE: build.js
================================================
import * as fs from 'fs-extra';
import ts from 'typescript';
import * as rollup from 'rollup';
(async function() {
// Delete old
await fs.remove('dist_es5');
await fs.remove('dist_es8');
// Run ts
const raw_config = await fs.readFile('tsconfig.json', 'utf8');
const options_es5_raw = JSON.parse(raw_config).compilerOptions;
options_es5_raw.target = 'es5';
options_es5_raw.outDir = 'dist_es5';
const options_es8_raw = JSON.parse(raw_config).compilerOptions;
const options_es5 = ts.convertCompilerOptionsFromJson(options_es5_raw, '.');
const options_es8 = ts.convertCompilerOptionsFromJson(options_es8_raw, '.');
const program_es5 = ts.createProgram(['src/entry-export_all.ts'], options_es5.options);
const program_es8 = ts.createProgram(['src/entry-export_all.ts'], options_es8.options);
const result_es5 = program_es5.emit();
if (result_es5.emitSkipped) {
throw new Error(result_es5.diagnostics[0].messageText);
}
const result_es8 = program_es8.emit();
if (result_es8.emitSkipped) {
throw new Error(result_es8.diagnostics[0].messageText);
}
// Copy non-ts resources
await fs.copy('src/aes/aes.asm.js', 'dist_es5/aes/aes.asm.js');
await fs.copy('src/aes/aes.asm.d.ts', 'dist_es5/aes/aes.asm.d.ts');
await fs.copy('src/aes/aes.asm.js', 'dist_es8/aes/aes.asm.js');
await fs.copy('src/aes/aes.asm.d.ts', 'dist_es8/aes/aes.asm.d.ts');
await fs.copy('src/bignum/bigint.asm.js', 'dist_es5/bignum/bigint.asm.js');
await fs.copy('src/bignum/bigint.asm.d.ts', 'dist_es5/bignum/bigint.asm.d.ts');
await fs.copy('src/bignum/bigint.asm.js', 'dist_es8/bignum/bigint.asm.js');
await fs.copy('src/bignum/bigint.asm.d.ts', 'dist_es8/bignum/bigint.asm.d.ts');
await fs.copy('src/hash/sha1/sha1.asm.js', 'dist_es5/hash/sha1/sha1.asm.js');
await fs.copy('src/hash/sha1/sha1.asm.d.ts', 'dist_es5/hash/sha1/sha1.asm.d.ts');
await fs.copy('src/hash/sha1/sha1.asm.js', 'dist_es8/hash/sha1/sha1.asm.js');
await fs.copy('src/hash/sha1/sha1.asm.d.ts', 'dist_es8/hash/sha1/sha1.asm.d.ts');
await fs.copy('src/hash/sha256/sha256.asm.js', 'dist_es5/hash/sha256/sha256.asm.js');
await fs.copy('src/hash/sha256/sha256.asm.d.ts', 'dist_es5/hash/sha256/sha256.asm.d.ts');
await fs.copy('src/hash/sha256/sha256.asm.js', 'dist_es8/hash/sha256/sha256.asm.js');
await fs.copy('src/hash/sha256/sha256.asm.d.ts', 'dist_es8/hash/sha256/sha256.asm.d.ts');
await fs.copy('src/hash/sha512/sha512.asm.js', 'dist_es5/hash/sha512/sha512.asm.js');
await fs.copy('src/hash/sha512/sha512.asm.d.ts', 'dist_es5/hash/sha512/sha512.asm.d.ts');
await fs.copy('src/hash/sha512/sha512.asm.js', 'dist_es8/hash/sha512/sha512.asm.js');
await fs.copy('src/hash/sha512/sha512.asm.d.ts', 'dist_es8/hash/sha512/sha512.asm.d.ts');
const es5bundle = await rollup.rollup({
input: 'dist_es5/entry-export_all.js',
onwarn(warning, warn) {
if (warning.code === 'THIS_IS_UNDEFINED') return;
warn(warning); // this requires Rollup 0.46
},
});
// Legacy browser export, as a bundle
await es5bundle.write({
file: 'asmcrypto.all.es5.js',
format: 'iife',
name: 'asmCrypto',
});
// Legacy browser export, as a bundle
await es5bundle.write({
file: 'asmcrypto.all.es5.mjs',
format: 'es',
});
// NodeJS old
await es5bundle.write({
file: 'asmcrypto.all.js',
format: 'cjs',
});
// Modern export, eg. Chrome or NodeJS 10 with ESM
const es8bundle = await rollup.rollup({
input: 'dist_es8/entry-export_all.js',
onwarn(warning, warn) {
if (warning.code === 'THIS_IS_UNDEFINED') return;
warn(warning); // this requires Rollup 0.46
},
});
await es8bundle.write({
file: 'asmcrypto.all.es8.js',
format: 'es',
});
console.log('Build complete');
})();
================================================
FILE: package.json
================================================
{
"name": "asmcrypto.js",
"version": "2.3.2",
"description": "Asm.js implementation of WebCrypto API",
"homepage": "https://github.com/asmcrypto/asmcrypto.js",
"main": "asmcrypto.all.js",
"module": "asmcrypto.all.es8.js",
"license": "MIT",
"author": {
"name": "Ádám Lippai",
"email": "adam@rigo.sk",
"web": "https://github.com/alippai"
},
"contributors": [
{
"name": "Artem S Vybornov",
"email": "vybornov@gmail.com",
"web": "https://github.com/vibornoff"
},
{
"name": "Ximin Luo",
"email": "infinity0@pwned.gg",
"web": "https://github.com/infinity0"
}
],
"repository": {
"type": "git",
"url": "https://github.com/asmcrypto/asmcrypto.js.git"
},
"devDependencies": {
"@types/chai": "^4.1.7",
"@types/mocha": "^8.0.3",
"@types/node": "^10.12.2",
"chai": "^4.2.0",
"esm": "3.2.25",
"fs-extra": "^9.0.1",
"mocha": "^8.1.3",
"prettier": "^1.14.3",
"rollup": "2.28.1",
"ts-node": "^7.0.1",
"tslint": "^5.11.0",
"tslint-plugin-prettier": "^2.0.1",
"typescript": "^3.1.6"
},
"scripts": {
"prepare": "node -r esm build.js",
"test": "node -r esm build.js && mocha -r esm test/*.js",
"prettier": "prettier --single-quote --trailing-comma all --write \"src/**/*.js\" \"src/**/*.ts\" --print-width 120"
},
"typings": "./dist_es8/entry-export_all.d.ts",
"dependencies": {}
}
================================================
FILE: src/aes/aes.asm.d.ts
================================================
declare type AES_mode = 'ECB' | 'CBC' | 'CFB' | 'OFB' | 'CTR' | 'CCM';
export class AES_asm {
constructor(foreign: any, heap: ArrayBuffer);
/**
* @param ks - key size, 4/6/8 (for 128/192/256-bit key correspondingly)
* @param k0 - key vector components
* @param k1 - key vector components
* @param k2 - key vector components
* @param k3 - key vector components
* @param k4 - key vector components
* @param k5 - key vector components
* @param k6 - key vector components
* @param k7 - key vector components
*/
set_key(
ks: number,
k0: number,
k1: number,
k2: number,
k3: number,
k4: number,
k5: number,
k6: number,
k7: number,
): void;
/**
* Populate the internal iv of the module
*/
set_iv(i0: number, i1: number, i2: number, i3: number): void;
/**
* Set counter mask for CTR-family modes
*/
set_mask(m0: number, m1: number, m2: number, m3: number): void;
/**
* Set nonce for CTR-family modes
*/
set_nonce(n0: number, n1: number, n2: number, n3: number): void;
/**
* Set counter for CTR-family modes
*/
set_counter(c0: number, c1: number, c2: number, c3: number): void;
/**
* Perform ciphering operation on the supplied data
*
* @param mode - block cipher mode (see {@link AES_asm} mode constants)
* @param pos - offset of the data being processed
* @param len - length of the data being processed
* @return Actual amount of data have been processed
*/
cipher(mode: number, pos: number, len: number): number;
/**
* GCM initialization
*/
gcm_init(): void;
/**
* Store the internal iv vector into the heap
*
* @returns The number of bytes have been written into the heap, always 16
*/
get_iv(pos: number): 16;
/**
* Calculates MAC of the supplied data
*
* @param mode - block cipher mode (see {@link AES_asm} mode constants)
* @param pos - offset of the data being processed
* @param len - length of the data being processed
* @return Actual amount of data have been processed
*/
mac(mode: number, pos: number, len: number): number;
/**
* Store the internal state vector into the heap.
*
* @param pos - offset where to put the data
* @return The number of bytes have been written into the heap, always 16.
*/
get_state(pos: number): 16;
/**
* AES enciphering mode constants
*/
static ENC: {
ECB: 0;
CBC: 2;
CFB: 4;
OFB: 6;
CTR: 7;
[key: string]: number;
};
/**
* AES deciphering mode constants
*/
static DEC: {
ECB: 1;
CBC: 3;
CFB: 5;
OFB: 6;
CTR: 7;
[key: string]: number;
};
/**
* AES MAC mode constants
*/
static MAC: {
CBC: 0;
GCM: 1;
[key: string]: number;
};
static HEAP_DATA: number;
}
================================================
FILE: src/aes/aes.asm.js
================================================
/**
* @file {@link http://asmjs.org Asm.js} implementation of the {@link https://en.wikipedia.org/wiki/Advanced_Encryption_Standard Advanced Encryption Standard}.
* @author Artem S Vybornov <vybornov@gmail.com>
* @license MIT
*/
export var AES_asm = function () {
"use strict";
/**
* Galois Field stuff init flag
*/
var ginit_done = false;
/**
* Galois Field exponentiation and logarithm tables for 3 (the generator)
*/
var gexp3, glog3;
/**
* Init Galois Field tables
*/
function ginit() {
gexp3 = [],
glog3 = [];
var a = 1, c, d;
for (c = 0; c < 255; c++) {
gexp3[c] = a;
// Multiply by three
d = a & 0x80, a <<= 1, a &= 255;
if (d === 0x80) a ^= 0x1b;
a ^= gexp3[c];
// Set the log table value
glog3[gexp3[c]] = c;
}
gexp3[255] = gexp3[0];
glog3[0] = 0;
ginit_done = true;
}
/**
* Galois Field multiplication
* @param {number} a
* @param {number} b
* @return {number}
*/
function gmul(a, b) {
var c = gexp3[(glog3[a] + glog3[b]) % 255];
if (a === 0 || b === 0) c = 0;
return c;
}
/**
* Galois Field reciprocal
* @param {number} a
* @return {number}
*/
function ginv(a) {
var i = gexp3[255 - glog3[a]];
if (a === 0) i = 0;
return i;
}
/**
* AES stuff init flag
*/
var aes_init_done = false;
/**
* Encryption, Decryption, S-Box and KeyTransform tables
*
* @type {number[]}
*/
var aes_sbox;
/**
* @type {number[]}
*/
var aes_sinv;
/**
* @type {number[][]}
*/
var aes_enc;
/**
* @type {number[][]}
*/
var aes_dec;
/**
* Init AES tables
*/
function aes_init() {
if (!ginit_done) ginit();
// Calculates AES S-Box value
function _s(a) {
var c, s, x;
s = x = ginv(a);
for (c = 0; c < 4; c++) {
s = ((s << 1) | (s >>> 7)) & 255;
x ^= s;
}
x ^= 99;
return x;
}
// Tables
aes_sbox = [],
aes_sinv = [],
aes_enc = [[], [], [], []],
aes_dec = [[], [], [], []];
for (var i = 0; i < 256; i++) {
var s = _s(i);
// S-Box and its inverse
aes_sbox[i] = s;
aes_sinv[s] = i;
// Ecryption and Decryption tables
aes_enc[0][i] = (gmul(2, s) << 24) | (s << 16) | (s << 8) | gmul(3, s);
aes_dec[0][s] = (gmul(14, i) << 24) | (gmul(9, i) << 16) | (gmul(13, i) << 8) | gmul(11, i);
// Rotate tables
for (var t = 1; t < 4; t++) {
aes_enc[t][i] = (aes_enc[t - 1][i] >>> 8) | (aes_enc[t - 1][i] << 24);
aes_dec[t][s] = (aes_dec[t - 1][s] >>> 8) | (aes_dec[t - 1][s] << 24);
}
}
aes_init_done = true;
}
/**
* Asm.js module constructor.
*
* <p>
* Heap buffer layout by offset:
* <pre>
* 0x0000 encryption key schedule
* 0x0400 decryption key schedule
* 0x0800 sbox
* 0x0c00 inv sbox
* 0x1000 encryption tables
* 0x2000 decryption tables
* 0x3000 reserved (future GCM multiplication lookup table)
* 0x4000 data
* </pre>
* Don't touch anything before <code>0x400</code>.
* </p>
*
* @alias AES_asm
* @class
* @param foreign - <i>ignored</i>
* @param buffer - heap buffer to link with
*/
var wrapper = function (foreign, buffer) {
// Init AES stuff for the first time
if (!aes_init_done) aes_init();
// Fill up AES tables
var heap = new Uint32Array(buffer);
heap.set(aes_sbox, 0x0800 >> 2);
heap.set(aes_sinv, 0x0c00 >> 2);
for (var i = 0; i < 4; i++) {
heap.set(aes_enc[i], (0x1000 + 0x400 * i) >> 2);
heap.set(aes_dec[i], (0x2000 + 0x400 * i) >> 2);
}
/**
* Calculate AES key schedules.
* @instance
* @memberof AES_asm
* @param {number} ks - key size, 4/6/8 (for 128/192/256-bit key correspondingly)
* @param {number} k0 - key vector components
* @param {number} k1 - key vector components
* @param {number} k2 - key vector components
* @param {number} k3 - key vector components
* @param {number} k4 - key vector components
* @param {number} k5 - key vector components
* @param {number} k6 - key vector components
* @param {number} k7 - key vector components
*/
function set_key(ks, k0, k1, k2, k3, k4, k5, k6, k7) {
var ekeys = heap.subarray(0x000, 60),
dkeys = heap.subarray(0x100, 0x100 + 60);
// Encryption key schedule
ekeys.set([k0, k1, k2, k3, k4, k5, k6, k7]);
for (var i = ks, rcon = 1; i < 4 * ks + 28; i++) {
var k = ekeys[i - 1];
if ((i % ks === 0) || (ks === 8 && i % ks === 4)) {
k = aes_sbox[k >>> 24] << 24 ^ aes_sbox[k >>> 16 & 255] << 16 ^ aes_sbox[k >>> 8 & 255] << 8 ^ aes_sbox[k & 255];
}
if (i % ks === 0) {
k = (k << 8) ^ (k >>> 24) ^ (rcon << 24);
rcon = (rcon << 1) ^ ((rcon & 0x80) ? 0x1b : 0);
}
ekeys[i] = ekeys[i - ks] ^ k;
}
// Decryption key schedule
for (var j = 0; j < i; j += 4) {
for (var jj = 0; jj < 4; jj++) {
var k = ekeys[i - (4 + j) + (4 - jj) % 4];
if (j < 4 || j >= i - 4) {
dkeys[j + jj] = k;
} else {
dkeys[j + jj] = aes_dec[0][aes_sbox[k >>> 24]]
^ aes_dec[1][aes_sbox[k >>> 16 & 255]]
^ aes_dec[2][aes_sbox[k >>> 8 & 255]]
^ aes_dec[3][aes_sbox[k & 255]];
}
}
}
// Set rounds number
asm.set_rounds(ks + 5);
}
// create library object with necessary properties
var stdlib = {Uint8Array: Uint8Array, Uint32Array: Uint32Array};
var asm = function (stdlib, foreign, buffer) {
"use asm";
var S0 = 0, S1 = 0, S2 = 0, S3 = 0,
I0 = 0, I1 = 0, I2 = 0, I3 = 0,
N0 = 0, N1 = 0, N2 = 0, N3 = 0,
M0 = 0, M1 = 0, M2 = 0, M3 = 0,
H0 = 0, H1 = 0, H2 = 0, H3 = 0,
R = 0;
var HEAP = new stdlib.Uint32Array(buffer),
DATA = new stdlib.Uint8Array(buffer);
/**
* AES core
* @param {number} k - precomputed key schedule offset
* @param {number} s - precomputed sbox table offset
* @param {number} t - precomputed round table offset
* @param {number} r - number of inner rounds to perform
* @param {number} x0 - 128-bit input block vector
* @param {number} x1 - 128-bit input block vector
* @param {number} x2 - 128-bit input block vector
* @param {number} x3 - 128-bit input block vector
*/
function _core(k, s, t, r, x0, x1, x2, x3) {
k = k | 0;
s = s | 0;
t = t | 0;
r = r | 0;
x0 = x0 | 0;
x1 = x1 | 0;
x2 = x2 | 0;
x3 = x3 | 0;
var t1 = 0, t2 = 0, t3 = 0,
y0 = 0, y1 = 0, y2 = 0, y3 = 0,
i = 0;
t1 = t | 0x400, t2 = t | 0x800, t3 = t | 0xc00;
// round 0
x0 = x0 ^ HEAP[(k | 0) >> 2],
x1 = x1 ^ HEAP[(k | 4) >> 2],
x2 = x2 ^ HEAP[(k | 8) >> 2],
x3 = x3 ^ HEAP[(k | 12) >> 2];
// round 1..r
for (i = 16; (i | 0) <= (r << 4); i = (i + 16) | 0) {
y0 = HEAP[(t | x0 >> 22 & 1020) >> 2] ^ HEAP[(t1 | x1 >> 14 & 1020) >> 2] ^ HEAP[(t2 | x2 >> 6 & 1020) >> 2] ^ HEAP[(t3 | x3 << 2 & 1020) >> 2] ^ HEAP[(k | i | 0) >> 2],
y1 = HEAP[(t | x1 >> 22 & 1020) >> 2] ^ HEAP[(t1 | x2 >> 14 & 1020) >> 2] ^ HEAP[(t2 | x3 >> 6 & 1020) >> 2] ^ HEAP[(t3 | x0 << 2 & 1020) >> 2] ^ HEAP[(k | i | 4) >> 2],
y2 = HEAP[(t | x2 >> 22 & 1020) >> 2] ^ HEAP[(t1 | x3 >> 14 & 1020) >> 2] ^ HEAP[(t2 | x0 >> 6 & 1020) >> 2] ^ HEAP[(t3 | x1 << 2 & 1020) >> 2] ^ HEAP[(k | i | 8) >> 2],
y3 = HEAP[(t | x3 >> 22 & 1020) >> 2] ^ HEAP[(t1 | x0 >> 14 & 1020) >> 2] ^ HEAP[(t2 | x1 >> 6 & 1020) >> 2] ^ HEAP[(t3 | x2 << 2 & 1020) >> 2] ^ HEAP[(k | i | 12) >> 2];
x0 = y0, x1 = y1, x2 = y2, x3 = y3;
}
// final round
S0 = HEAP[(s | x0 >> 22 & 1020) >> 2] << 24 ^ HEAP[(s | x1 >> 14 & 1020) >> 2] << 16 ^ HEAP[(s | x2 >> 6 & 1020) >> 2] << 8 ^ HEAP[(s | x3 << 2 & 1020) >> 2] ^ HEAP[(k | i | 0) >> 2],
S1 = HEAP[(s | x1 >> 22 & 1020) >> 2] << 24 ^ HEAP[(s | x2 >> 14 & 1020) >> 2] << 16 ^ HEAP[(s | x3 >> 6 & 1020) >> 2] << 8 ^ HEAP[(s | x0 << 2 & 1020) >> 2] ^ HEAP[(k | i | 4) >> 2],
S2 = HEAP[(s | x2 >> 22 & 1020) >> 2] << 24 ^ HEAP[(s | x3 >> 14 & 1020) >> 2] << 16 ^ HEAP[(s | x0 >> 6 & 1020) >> 2] << 8 ^ HEAP[(s | x1 << 2 & 1020) >> 2] ^ HEAP[(k | i | 8) >> 2],
S3 = HEAP[(s | x3 >> 22 & 1020) >> 2] << 24 ^ HEAP[(s | x0 >> 14 & 1020) >> 2] << 16 ^ HEAP[(s | x1 >> 6 & 1020) >> 2] << 8 ^ HEAP[(s | x2 << 2 & 1020) >> 2] ^ HEAP[(k | i | 12) >> 2];
}
/**
* ECB mode encryption
* @param {number} x0 - 128-bit input block vector
* @param {number} x1 - 128-bit input block vector
* @param {number} x2 - 128-bit input block vector
* @param {number} x3 - 128-bit input block vector
*/
function _ecb_enc(x0, x1, x2, x3) {
x0 = x0 | 0;
x1 = x1 | 0;
x2 = x2 | 0;
x3 = x3 | 0;
_core(
0x0000, 0x0800, 0x1000,
R,
x0,
x1,
x2,
x3
);
}
/**
* ECB mode decryption
* @param {number} x0 - 128-bit input block vector
* @param {number} x1 - 128-bit input block vector
* @param {number} x2 - 128-bit input block vector
* @param {number} x3 - 128-bit input block vector
*/
function _ecb_dec(x0, x1, x2, x3) {
x0 = x0 | 0;
x1 = x1 | 0;
x2 = x2 | 0;
x3 = x3 | 0;
var t = 0;
_core(
0x0400, 0x0c00, 0x2000,
R,
x0,
x3,
x2,
x1
);
t = S1, S1 = S3, S3 = t;
}
/**
* CBC mode encryption
* @param {number} x0 - 128-bit input block vector
* @param {number} x1 - 128-bit input block vector
* @param {number} x2 - 128-bit input block vector
* @param {number} x3 - 128-bit input block vector
*/
function _cbc_enc(x0, x1, x2, x3) {
x0 = x0 | 0;
x1 = x1 | 0;
x2 = x2 | 0;
x3 = x3 | 0;
_core(
0x0000, 0x0800, 0x1000,
R,
I0 ^ x0,
I1 ^ x1,
I2 ^ x2,
I3 ^ x3
);
I0 = S0,
I1 = S1,
I2 = S2,
I3 = S3;
}
/**
* CBC mode decryption
* @param {number} x0 - 128-bit input block vector
* @param {number} x1 - 128-bit input block vector
* @param {number} x2 - 128-bit input block vector
* @param {number} x3 - 128-bit input block vector
*/
function _cbc_dec(x0, x1, x2, x3) {
x0 = x0 | 0;
x1 = x1 | 0;
x2 = x2 | 0;
x3 = x3 | 0;
var t = 0;
_core(
0x0400, 0x0c00, 0x2000,
R,
x0,
x3,
x2,
x1
);
t = S1, S1 = S3, S3 = t;
S0 = S0 ^ I0,
S1 = S1 ^ I1,
S2 = S2 ^ I2,
S3 = S3 ^ I3;
I0 = x0,
I1 = x1,
I2 = x2,
I3 = x3;
}
/**
* CFB mode encryption
* @param {number} x0 - 128-bit input block vector
* @param {number} x1 - 128-bit input block vector
* @param {number} x2 - 128-bit input block vector
* @param {number} x3 - 128-bit input block vector
*/
function _cfb_enc(x0, x1, x2, x3) {
x0 = x0 | 0;
x1 = x1 | 0;
x2 = x2 | 0;
x3 = x3 | 0;
_core(
0x0000, 0x0800, 0x1000,
R,
I0,
I1,
I2,
I3
);
I0 = S0 = S0 ^ x0,
I1 = S1 = S1 ^ x1,
I2 = S2 = S2 ^ x2,
I3 = S3 = S3 ^ x3;
}
/**
* CFB mode decryption
* @param {number} x0 - 128-bit input block vector
* @param {number} x1 - 128-bit input block vector
* @param {number} x2 - 128-bit input block vector
* @param {number} x3 - 128-bit input block vector
*/
function _cfb_dec(x0, x1, x2, x3) {
x0 = x0 | 0;
x1 = x1 | 0;
x2 = x2 | 0;
x3 = x3 | 0;
_core(
0x0000, 0x0800, 0x1000,
R,
I0,
I1,
I2,
I3
);
S0 = S0 ^ x0,
S1 = S1 ^ x1,
S2 = S2 ^ x2,
S3 = S3 ^ x3;
I0 = x0,
I1 = x1,
I2 = x2,
I3 = x3;
}
/**
* OFB mode encryption / decryption
* @param {number} x0 - 128-bit input block vector
* @param {number} x1 - 128-bit input block vector
* @param {number} x2 - 128-bit input block vector
* @param {number} x3 - 128-bit input block vector
*/
function _ofb(x0, x1, x2, x3) {
x0 = x0 | 0;
x1 = x1 | 0;
x2 = x2 | 0;
x3 = x3 | 0;
_core(
0x0000, 0x0800, 0x1000,
R,
I0,
I1,
I2,
I3
);
I0 = S0,
I1 = S1,
I2 = S2,
I3 = S3;
S0 = S0 ^ x0,
S1 = S1 ^ x1,
S2 = S2 ^ x2,
S3 = S3 ^ x3;
}
/**
* CTR mode encryption / decryption
* @param {number} x0 - 128-bit input block vector
* @param {number} x1 - 128-bit input block vector
* @param {number} x2 - 128-bit input block vector
* @param {number} x3 - 128-bit input block vector
*/
function _ctr(x0, x1, x2, x3) {
x0 = x0 | 0;
x1 = x1 | 0;
x2 = x2 | 0;
x3 = x3 | 0;
_core(
0x0000, 0x0800, 0x1000,
R,
N0,
N1,
N2,
N3
);
N3 = (~M3 & N3) | M3 & (N3 + 1);
N2 = (~M2 & N2) | M2 & (N2 + ((N3 | 0) == 0));
N1 = (~M1 & N1) | M1 & (N1 + ((N2 | 0) == 0));
N0 = (~M0 & N0) | M0 & (N0 + ((N1 | 0) == 0));
S0 = S0 ^ x0;
S1 = S1 ^ x1;
S2 = S2 ^ x2;
S3 = S3 ^ x3;
}
/**
* GCM mode MAC calculation
* @param {number} x0 - 128-bit input block vector
* @param {number} x1 - 128-bit input block vector
* @param {number} x2 - 128-bit input block vector
* @param {number} x3 - 128-bit input block vector
*/
function _gcm_mac(x0, x1, x2, x3) {
x0 = x0 | 0;
x1 = x1 | 0;
x2 = x2 | 0;
x3 = x3 | 0;
var y0 = 0, y1 = 0, y2 = 0, y3 = 0,
z0 = 0, z1 = 0, z2 = 0, z3 = 0,
i = 0, c = 0;
x0 = x0 ^ I0,
x1 = x1 ^ I1,
x2 = x2 ^ I2,
x3 = x3 ^ I3;
y0 = H0 | 0,
y1 = H1 | 0,
y2 = H2 | 0,
y3 = H3 | 0;
for (; (i | 0) < 128; i = (i + 1) | 0) {
if (y0 >>> 31) {
z0 = z0 ^ x0,
z1 = z1 ^ x1,
z2 = z2 ^ x2,
z3 = z3 ^ x3;
}
y0 = (y0 << 1) | (y1 >>> 31),
y1 = (y1 << 1) | (y2 >>> 31),
y2 = (y2 << 1) | (y3 >>> 31),
y3 = (y3 << 1);
c = x3 & 1;
x3 = (x3 >>> 1) | (x2 << 31),
x2 = (x2 >>> 1) | (x1 << 31),
x1 = (x1 >>> 1) | (x0 << 31),
x0 = (x0 >>> 1);
if (c) x0 = x0 ^ 0xe1000000;
}
I0 = z0,
I1 = z1,
I2 = z2,
I3 = z3;
}
/**
* Set the internal rounds number.
* @instance
* @memberof AES_asm
* @param {number} r - number if inner AES rounds
*/
function set_rounds(r) {
r = r | 0;
R = r;
}
/**
* Populate the internal state of the module.
* @instance
* @memberof AES_asm
* @param {number} s0 - state vector
* @param {number} s1 - state vector
* @param {number} s2 - state vector
* @param {number} s3 - state vector
*/
function set_state(s0, s1, s2, s3) {
s0 = s0 | 0;
s1 = s1 | 0;
s2 = s2 | 0;
s3 = s3 | 0;
S0 = s0,
S1 = s1,
S2 = s2,
S3 = s3;
}
/**
* Populate the internal iv of the module.
* @instance
* @memberof AES_asm
* @param {number} i0 - iv vector
* @param {number} i1 - iv vector
* @param {number} i2 - iv vector
* @param {number} i3 - iv vector
*/
function set_iv(i0, i1, i2, i3) {
i0 = i0 | 0;
i1 = i1 | 0;
i2 = i2 | 0;
i3 = i3 | 0;
I0 = i0,
I1 = i1,
I2 = i2,
I3 = i3;
}
/**
* Set nonce for CTR-family modes.
* @instance
* @memberof AES_asm
* @param {number} n0 - nonce vector
* @param {number} n1 - nonce vector
* @param {number} n2 - nonce vector
* @param {number} n3 - nonce vector
*/
function set_nonce(n0, n1, n2, n3) {
n0 = n0 | 0;
n1 = n1 | 0;
n2 = n2 | 0;
n3 = n3 | 0;
N0 = n0,
N1 = n1,
N2 = n2,
N3 = n3;
}
/**
* Set counter mask for CTR-family modes.
* @instance
* @memberof AES_asm
* @param {number} m0 - counter mask vector
* @param {number} m1 - counter mask vector
* @param {number} m2 - counter mask vector
* @param {number} m3 - counter mask vector
*/
function set_mask(m0, m1, m2, m3) {
m0 = m0 | 0;
m1 = m1 | 0;
m2 = m2 | 0;
m3 = m3 | 0;
M0 = m0,
M1 = m1,
M2 = m2,
M3 = m3;
}
/**
* Set counter for CTR-family modes.
* @instance
* @memberof AES_asm
* @param {number} c0 - counter vector
* @param {number} c1 - counter vector
* @param {number} c2 - counter vector
* @param {number} c3 - counter vector
*/
function set_counter(c0, c1, c2, c3) {
c0 = c0 | 0;
c1 = c1 | 0;
c2 = c2 | 0;
c3 = c3 | 0;
N3 = (~M3 & N3) | M3 & c3,
N2 = (~M2 & N2) | M2 & c2,
N1 = (~M1 & N1) | M1 & c1,
N0 = (~M0 & N0) | M0 & c0;
}
/**
* Store the internal state vector into the heap.
* @instance
* @memberof AES_asm
* @param {number} pos - offset where to put the data
* @return {number} The number of bytes have been written into the heap, always 16.
*/
function get_state(pos) {
pos = pos | 0;
if (pos & 15) return -1;
DATA[pos | 0] = S0 >>> 24,
DATA[pos | 1] = S0 >>> 16 & 255,
DATA[pos | 2] = S0 >>> 8 & 255,
DATA[pos | 3] = S0 & 255,
DATA[pos | 4] = S1 >>> 24,
DATA[pos | 5] = S1 >>> 16 & 255,
DATA[pos | 6] = S1 >>> 8 & 255,
DATA[pos | 7] = S1 & 255,
DATA[pos | 8] = S2 >>> 24,
DATA[pos | 9] = S2 >>> 16 & 255,
DATA[pos | 10] = S2 >>> 8 & 255,
DATA[pos | 11] = S2 & 255,
DATA[pos | 12] = S3 >>> 24,
DATA[pos | 13] = S3 >>> 16 & 255,
DATA[pos | 14] = S3 >>> 8 & 255,
DATA[pos | 15] = S3 & 255;
return 16;
}
/**
* Store the internal iv vector into the heap.
* @instance
* @memberof AES_asm
* @param {number} pos - offset where to put the data
* @return {number} The number of bytes have been written into the heap, always 16.
*/
function get_iv(pos) {
pos = pos | 0;
if (pos & 15) return -1;
DATA[pos | 0] = I0 >>> 24,
DATA[pos | 1] = I0 >>> 16 & 255,
DATA[pos | 2] = I0 >>> 8 & 255,
DATA[pos | 3] = I0 & 255,
DATA[pos | 4] = I1 >>> 24,
DATA[pos | 5] = I1 >>> 16 & 255,
DATA[pos | 6] = I1 >>> 8 & 255,
DATA[pos | 7] = I1 & 255,
DATA[pos | 8] = I2 >>> 24,
DATA[pos | 9] = I2 >>> 16 & 255,
DATA[pos | 10] = I2 >>> 8 & 255,
DATA[pos | 11] = I2 & 255,
DATA[pos | 12] = I3 >>> 24,
DATA[pos | 13] = I3 >>> 16 & 255,
DATA[pos | 14] = I3 >>> 8 & 255,
DATA[pos | 15] = I3 & 255;
return 16;
}
/**
* GCM initialization.
* @instance
* @memberof AES_asm
*/
function gcm_init() {
_ecb_enc(0, 0, 0, 0);
H0 = S0,
H1 = S1,
H2 = S2,
H3 = S3;
}
/**
* Perform ciphering operation on the supplied data.
* @instance
* @memberof AES_asm
* @param {number} mode - block cipher mode (see {@link AES_asm} mode constants)
* @param {number} pos - offset of the data being processed
* @param {number} len - length of the data being processed
* @return {number} Actual amount of data have been processed.
*/
function cipher(mode, pos, len) {
mode = mode | 0;
pos = pos | 0;
len = len | 0;
var ret = 0;
if (pos & 15) return -1;
while ((len | 0) >= 16) {
_cipher_modes[mode & 7](
DATA[pos | 0] << 24 | DATA[pos | 1] << 16 | DATA[pos | 2] << 8 | DATA[pos | 3],
DATA[pos | 4] << 24 | DATA[pos | 5] << 16 | DATA[pos | 6] << 8 | DATA[pos | 7],
DATA[pos | 8] << 24 | DATA[pos | 9] << 16 | DATA[pos | 10] << 8 | DATA[pos | 11],
DATA[pos | 12] << 24 | DATA[pos | 13] << 16 | DATA[pos | 14] << 8 | DATA[pos | 15]
);
DATA[pos | 0] = S0 >>> 24,
DATA[pos | 1] = S0 >>> 16 & 255,
DATA[pos | 2] = S0 >>> 8 & 255,
DATA[pos | 3] = S0 & 255,
DATA[pos | 4] = S1 >>> 24,
DATA[pos | 5] = S1 >>> 16 & 255,
DATA[pos | 6] = S1 >>> 8 & 255,
DATA[pos | 7] = S1 & 255,
DATA[pos | 8] = S2 >>> 24,
DATA[pos | 9] = S2 >>> 16 & 255,
DATA[pos | 10] = S2 >>> 8 & 255,
DATA[pos | 11] = S2 & 255,
DATA[pos | 12] = S3 >>> 24,
DATA[pos | 13] = S3 >>> 16 & 255,
DATA[pos | 14] = S3 >>> 8 & 255,
DATA[pos | 15] = S3 & 255;
ret = (ret + 16) | 0,
pos = (pos + 16) | 0,
len = (len - 16) | 0;
}
return ret | 0;
}
/**
* Calculates MAC of the supplied data.
* @instance
* @memberof AES_asm
* @param {number} mode - block cipher mode (see {@link AES_asm} mode constants)
* @param {number} pos - offset of the data being processed
* @param {number} len - length of the data being processed
* @return {number} Actual amount of data have been processed.
*/
function mac(mode, pos, len) {
mode = mode | 0;
pos = pos | 0;
len = len | 0;
var ret = 0;
if (pos & 15) return -1;
while ((len | 0) >= 16) {
_mac_modes[mode & 1](
DATA[pos | 0] << 24 | DATA[pos | 1] << 16 | DATA[pos | 2] << 8 | DATA[pos | 3],
DATA[pos | 4] << 24 | DATA[pos | 5] << 16 | DATA[pos | 6] << 8 | DATA[pos | 7],
DATA[pos | 8] << 24 | DATA[pos | 9] << 16 | DATA[pos | 10] << 8 | DATA[pos | 11],
DATA[pos | 12] << 24 | DATA[pos | 13] << 16 | DATA[pos | 14] << 8 | DATA[pos | 15]
);
ret = (ret + 16) | 0,
pos = (pos + 16) | 0,
len = (len - 16) | 0;
}
return ret | 0;
}
/**
* AES cipher modes table (virual methods)
*/
var _cipher_modes = [_ecb_enc, _ecb_dec, _cbc_enc, _cbc_dec, _cfb_enc, _cfb_dec, _ofb, _ctr];
/**
* AES MAC modes table (virual methods)
*/
var _mac_modes = [_cbc_enc, _gcm_mac];
/**
* Asm.js module exports
*/
return {
set_rounds: set_rounds,
set_state: set_state,
set_iv: set_iv,
set_nonce: set_nonce,
set_mask: set_mask,
set_counter: set_counter,
get_state: get_state,
get_iv: get_iv,
gcm_init: gcm_init,
cipher: cipher,
mac: mac,
};
}(stdlib, foreign, buffer);
asm.set_key = set_key;
return asm;
};
/**
* AES enciphering mode constants
* @enum {number}
* @const
*/
wrapper.ENC = {
ECB: 0,
CBC: 2,
CFB: 4,
OFB: 6,
CTR: 7,
},
/**
* AES deciphering mode constants
* @enum {number}
* @const
*/
wrapper.DEC = {
ECB: 1,
CBC: 3,
CFB: 5,
OFB: 6,
CTR: 7,
},
/**
* AES MAC mode constants
* @enum {number}
* @const
*/
wrapper.MAC = {
CBC: 0,
GCM: 1,
};
/**
* Heap data offset
* @type {number}
* @const
*/
wrapper.HEAP_DATA = 0x4000;
return wrapper;
}();
================================================
FILE: src/aes/aes.ts
================================================
import { AES_asm, AES_mode } from './aes.asm';
import { _heap_init, _heap_write, is_bytes } from '../other/utils';
import { IllegalArgumentError, SecurityError } from '../other/errors';
export class AES {
public readonly heap: Uint8Array;
public readonly asm: AES_asm;
private readonly mode: string;
public padding: boolean; // TODO: This should be `private readonly`, hacking for AES-CFB?!
public pos: number = 0;
public len: number = 0;
constructor(key: Uint8Array, iv: Uint8Array | undefined, padding = true, mode: AES_mode, heap?: Uint8Array, asm?: AES_asm) {
this.mode = mode;
// The AES "worker"
this.heap = heap ? heap : _heap_init().subarray(AES_asm.HEAP_DATA);
this.asm = asm ? asm : new AES_asm(null, this.heap.buffer);
// The AES object state
this.pos = 0;
this.len = 0;
// Key
const keylen = key.length;
if (keylen !== 16 && keylen !== 24 && keylen !== 32) throw new IllegalArgumentError('illegal key size');
const keyview = new DataView(key.buffer, key.byteOffset, key.byteLength);
this.asm.set_key(
keylen >> 2,
keyview.getUint32(0),
keyview.getUint32(4),
keyview.getUint32(8),
keyview.getUint32(12),
keylen > 16 ? keyview.getUint32(16) : 0,
keylen > 16 ? keyview.getUint32(20) : 0,
keylen > 24 ? keyview.getUint32(24) : 0,
keylen > 24 ? keyview.getUint32(28) : 0,
);
// IV
if (iv !== undefined) {
if (iv.length !== 16) throw new IllegalArgumentError('illegal iv size');
let ivview = new DataView(iv.buffer, iv.byteOffset, iv.byteLength);
this.asm.set_iv(ivview.getUint32(0), ivview.getUint32(4), ivview.getUint32(8), ivview.getUint32(12));
} else {
this.asm.set_iv(0, 0, 0, 0);
}
this.padding = padding;
}
AES_Encrypt_process(data: Uint8Array): Uint8Array {
if (!is_bytes(data)) throw new TypeError("data isn't of expected type");
let asm = this.asm;
let heap = this.heap;
let amode = AES_asm.ENC[this.mode];
let hpos = AES_asm.HEAP_DATA;
let pos = this.pos;
let len = this.len;
let dpos = 0;
let dlen = data.length || 0;
let rpos = 0;
let rlen = (len + dlen) & -16;
let wlen = 0;
let result = new Uint8Array(rlen);
while (dlen > 0) {
wlen = _heap_write(heap, pos + len, data, dpos, dlen);
len += wlen;
dpos += wlen;
dlen -= wlen;
wlen = asm.cipher(amode, hpos + pos, len);
if (wlen) result.set(heap.subarray(pos, pos + wlen), rpos);
rpos += wlen;
if (wlen < len) {
pos += wlen;
len -= wlen;
} else {
pos = 0;
len = 0;
}
}
this.pos = pos;
this.len = len;
return result;
}
AES_Encrypt_finish(): Uint8Array {
let asm = this.asm;
let heap = this.heap;
let amode = AES_asm.ENC[this.mode];
let hpos = AES_asm.HEAP_DATA;
let pos = this.pos;
let len = this.len;
let plen = 16 - (len % 16);
let rlen = len;
if (this.hasOwnProperty('padding')) {
if (this.padding) {
for (let p = 0; p < plen; ++p) {
heap[pos + len + p] = plen;
}
len += plen;
rlen = len;
} else if (len % 16) {
throw new IllegalArgumentError('data length must be a multiple of the block size');
}
} else {
len += plen;
}
const result = new Uint8Array(rlen);
if (len) asm.cipher(amode, hpos + pos, len);
if (rlen) result.set(heap.subarray(pos, pos + rlen));
this.pos = 0;
this.len = 0;
return result;
}
AES_Decrypt_process(data: Uint8Array): Uint8Array {
if (!is_bytes(data)) throw new TypeError("data isn't of expected type");
let asm = this.asm;
let heap = this.heap;
let amode = AES_asm.DEC[this.mode];
let hpos = AES_asm.HEAP_DATA;
let pos = this.pos;
let len = this.len;
let dpos = 0;
let dlen = data.length || 0;
let rpos = 0;
let rlen = (len + dlen) & -16;
let plen = 0;
let wlen = 0;
if (this.padding) {
plen = len + dlen - rlen || 16;
rlen -= plen;
}
const result = new Uint8Array(rlen);
while (dlen > 0) {
wlen = _heap_write(heap, pos + len, data, dpos, dlen);
len += wlen;
dpos += wlen;
dlen -= wlen;
wlen = asm.cipher(amode, hpos + pos, len - (!dlen ? plen : 0));
if (wlen) result.set(heap.subarray(pos, pos + wlen), rpos);
rpos += wlen;
if (wlen < len) {
pos += wlen;
len -= wlen;
} else {
pos = 0;
len = 0;
}
}
this.pos = pos;
this.len = len;
return result;
}
AES_Decrypt_finish(): Uint8Array {
let asm = this.asm;
let heap = this.heap;
let amode = AES_asm.DEC[this.mode];
let hpos = AES_asm.HEAP_DATA;
let pos = this.pos;
let len = this.len;
let rlen = len;
if (len > 0) {
if (len % 16) {
if (this.hasOwnProperty('padding')) {
throw new IllegalArgumentError('data length must be a multiple of the block size');
} else {
len += 16 - (len % 16);
}
}
asm.cipher(amode, hpos + pos, len);
if (this.hasOwnProperty('padding') && this.padding) {
let pad = heap[pos + rlen - 1];
if (pad < 1 || pad > 16 || pad > rlen) throw new SecurityError('bad padding');
let pcheck = 0;
for (let i = pad; i > 1; i--) pcheck |= pad ^ heap[pos + rlen - i];
if (pcheck) throw new SecurityError('bad padding');
rlen -= pad;
}
}
const result = new Uint8Array(rlen);
if (rlen > 0) {
result.set(heap.subarray(pos, pos + rlen));
}
this.pos = 0;
this.len = 0;
return result;
}
}
================================================
FILE: src/aes/cbc.ts
================================================
import { AES } from './aes';
import { joinBytes } from '../other/utils';
export class AES_CBC {
private aes: AES;
static encrypt(data: Uint8Array, key: Uint8Array, padding: boolean = true, iv?: Uint8Array): Uint8Array {
return new AES_CBC(key, iv, padding).encrypt(data);
}
static decrypt(data: Uint8Array, key: Uint8Array, padding: boolean = true, iv?: Uint8Array): Uint8Array {
return new AES_CBC(key, iv, padding).decrypt(data);
}
constructor(key: Uint8Array, iv?: Uint8Array, padding: boolean = true, aes?: AES) {
this.aes = aes ? aes : new AES(key, iv, padding, 'CBC');
}
encrypt(data: Uint8Array): Uint8Array {
const r1 = this.aes.AES_Encrypt_process(data);
const r2 = this.aes.AES_Encrypt_finish();
return joinBytes(r1, r2);
}
decrypt(data: Uint8Array): Uint8Array {
const r1 = this.aes.AES_Decrypt_process(data);
const r2 = this.aes.AES_Decrypt_finish();
return joinBytes(r1, r2);
}
}
================================================
FILE: src/aes/ccm.ts
================================================
/**
* Counter with CBC-MAC (CCM)
*
* Due to JS limitations (52 bits of Number precision) maximum encrypted message length
* is limited to ~4 PiB ( 2^52 - 16 ) per `nonce`-`key` pair.
* That also limits `lengthSize` parameter maximum value to 7 (not 8 as described in RFC3610).
*
* Additional authenticated data `adata` maximum length is chosen to be no more than 65279 bytes ( 2^16 - 2^8 ),
* which is considered enough for the most of use-cases.
*
* And one more important thing: in case of progressive ciphering of a data stream (in other
* words when data can't be held in-memory at a whole and are ciphered chunk-by-chunk)
* you have to know the `dataLength` in advance and pass that value to the cipher options.
*/
import { AES_asm } from './aes.asm';
import { AES } from './aes';
import { _heap_write } from '../other/utils';
import { IllegalArgumentError, IllegalStateError, SecurityError } from '../other/errors';
const _AES_CCM_adata_maxLength = 65279; // 2^16 - 2^8
const _AES_CCM_data_maxLength = 4503599627370480; // 2^52 - 2^4
export class AES_CCM {
private readonly tagSize: number;
private readonly lengthSize: number;
private nonce: Uint8Array;
private readonly adata: Uint8Array | undefined;
private counter: number = 1;
private dataLength: number = -1;
private aes: AES;
static encrypt(
clear: Uint8Array,
key: Uint8Array,
nonce: Uint8Array,
adata: Uint8Array | undefined,
tagsize: number = 16,
): Uint8Array {
return new AES_CCM(key, nonce, adata, tagsize, clear.length).encrypt(clear);
}
static decrypt(
cipher: Uint8Array,
key: Uint8Array,
nonce: Uint8Array,
adata: Uint8Array | undefined,
tagsize: number = 16,
): Uint8Array {
return new AES_CCM(key, nonce, adata, tagsize, cipher.length - tagsize).decrypt(cipher);
}
constructor(
key: Uint8Array,
nonce: Uint8Array,
adata: Uint8Array | undefined,
tagSize: number = 16,
dataLength: number,
aes?: AES,
) {
this.aes = aes ? aes : new AES(key, undefined, undefined, 'CCM');
// Tag size
if (tagSize < 4 || tagSize > 16 || tagSize & 1) throw new IllegalArgumentError('illegal tagSize value');
this.tagSize = tagSize;
// Nonce
this.nonce = nonce;
if (nonce.length < 8 || nonce.length > 13) throw new IllegalArgumentError('illegal nonce length');
this.lengthSize = 15 - nonce.length;
nonce = new Uint8Array(nonce.length + 1);
nonce[0] = this.lengthSize - 1;
nonce.set(this.nonce, 1);
if (dataLength < 0 || dataLength > _AES_CCM_data_maxLength || dataLength > Math.pow(2, 8 * this.lengthSize) - 16)
throw new IllegalArgumentError('illegal dataLength value');
if (adata !== undefined) {
if (adata.length > _AES_CCM_adata_maxLength) throw new IllegalArgumentError('illegal adata length');
this.adata = adata.length ? adata : undefined;
}
this.dataLength = dataLength;
this.counter = 1;
this.AES_CCM_calculate_iv();
this.AES_CTR_set_options(nonce, this.counter, 8 * this.lengthSize);
}
encrypt(data: Uint8Array): Uint8Array {
this.dataLength = data.length || 0;
const result1 = this.AES_CCM_Encrypt_process(data);
const result2 = this.AES_CCM_Encrypt_finish();
const result = new Uint8Array(result1.length + result2.length);
if (result1.length) result.set(result1);
if (result2.length) result.set(result2, result1.length);
return result;
}
decrypt(data: Uint8Array): Uint8Array {
this.dataLength = data.length || 0;
const result1 = this.AES_CCM_Decrypt_process(data);
const result2 = this.AES_CCM_Decrypt_finish();
const result = new Uint8Array(result1.length + result2.length);
if (result1.length) result.set(result1);
if (result2.length) result.set(result2, result1.length);
return result;
}
AES_CCM_calculate_iv(): void {
const nonce = this.nonce;
const adata = this.adata;
const tagSize = this.tagSize;
const lengthSize = this.lengthSize;
const dataLength = this.dataLength;
const data = new Uint8Array(16 + (adata ? 2 + adata.length : 0));
// B0: flags(adata?, M', L'), nonce, len(data)
data[0] = (adata ? 64 : 0) | ((tagSize - 2) << 2) | (lengthSize - 1);
data.set(nonce, 1);
if (lengthSize > 6) data[9] = ((dataLength / 0x100000000) >>> 16) & 15;
if (lengthSize > 5) data[10] = ((dataLength / 0x100000000) >>> 8) & 255;
if (lengthSize > 4) data[11] = (dataLength / 0x100000000) & 255;
if (lengthSize > 3) data[12] = dataLength >>> 24;
if (lengthSize > 2) data[13] = (dataLength >>> 16) & 255;
data[14] = (dataLength >>> 8) & 255;
data[15] = dataLength & 255;
// B*: len(adata), adata
if (adata) {
data[16] = (adata.length >>> 8) & 255;
data[17] = adata.length & 255;
data.set(adata, 18);
}
this._cbc_mac_process(data);
this.aes.asm.get_state(AES_asm.HEAP_DATA);
const iv = new Uint8Array(this.aes.heap.subarray(0, 16));
const ivview = new DataView(iv.buffer, iv.byteOffset, iv.byteLength);
this.aes.asm.set_iv(ivview.getUint32(0), ivview.getUint32(4), ivview.getUint32(8), ivview.getUint32(12));
}
_cbc_mac_process(data: Uint8Array): void {
const heap = this.aes.heap;
const asm = this.aes.asm;
let dpos = 0;
let dlen = data.length || 0;
let wlen = 0;
while (dlen > 0) {
wlen = _heap_write(heap, 0, data, dpos, dlen);
while (wlen & 15) heap[wlen++] = 0;
dpos += wlen;
dlen -= wlen;
asm.mac(AES_asm.MAC.CBC, AES_asm.HEAP_DATA, wlen);
}
}
AES_CCM_Encrypt_process(data: Uint8Array): Uint8Array {
const asm = this.aes.asm;
const heap = this.aes.heap;
let dpos = 0;
let dlen = data.length || 0;
let counter = this.counter;
let pos = this.aes.pos;
let len = this.aes.len;
const rlen = (len + dlen) & -16;
let rpos = 0;
let wlen = 0;
if (((counter - 1) << 4) + len + dlen > _AES_CCM_data_maxLength)
// ??? should check against lengthSize
throw new RangeError('counter overflow');
const result = new Uint8Array(rlen);
while (dlen > 0) {
wlen = _heap_write(heap, pos + len, data, dpos, dlen);
len += wlen;
dpos += wlen;
dlen -= wlen;
wlen = asm.mac(AES_asm.MAC.CBC, AES_asm.HEAP_DATA + pos, len);
wlen = asm.cipher(AES_asm.ENC.CTR, AES_asm.HEAP_DATA + pos, wlen);
if (wlen) result.set(heap.subarray(pos, pos + wlen), rpos);
counter += wlen >>> 4;
rpos += wlen;
if (wlen < len) {
pos += wlen;
len -= wlen;
} else {
pos = 0;
len = 0;
}
}
this.counter = counter;
this.aes.pos = pos;
this.aes.len = len;
return result;
}
AES_CCM_Encrypt_finish(): Uint8Array {
const asm = this.aes.asm;
const heap = this.aes.heap;
const tagSize = this.tagSize;
const pos = this.aes.pos;
const len = this.aes.len;
const result = new Uint8Array(len + tagSize);
let i = len;
for (; i & 15; i++) heap[pos + i] = 0;
asm.mac(AES_asm.MAC.CBC, AES_asm.HEAP_DATA + pos, i);
asm.cipher(AES_asm.ENC.CTR, AES_asm.HEAP_DATA + pos, i);
if (len) result.set(heap.subarray(pos, pos + len));
asm.set_counter(0, 0, 0, 0);
asm.get_iv(AES_asm.HEAP_DATA);
asm.cipher(AES_asm.ENC.CTR, AES_asm.HEAP_DATA, 16);
result.set(heap.subarray(0, tagSize), len);
this.counter = 1;
this.aes.pos = 0;
this.aes.len = 0;
return result;
}
AES_CCM_Decrypt_process(data: Uint8Array): Uint8Array {
let dpos = 0;
let dlen = data.length || 0;
const asm = this.aes.asm;
const heap = this.aes.heap;
let counter = this.counter;
const tagSize = this.tagSize;
let pos = this.aes.pos;
let len = this.aes.len;
let rpos = 0;
const rlen = len + dlen > tagSize ? (len + dlen - tagSize) & -16 : 0;
const tlen = len + dlen - rlen;
let wlen = 0;
if (((counter - 1) << 4) + len + dlen > _AES_CCM_data_maxLength) throw new RangeError('counter overflow');
const result = new Uint8Array(rlen);
while (dlen > tlen) {
wlen = _heap_write(heap, pos + len, data, dpos, dlen - tlen);
len += wlen;
dpos += wlen;
dlen -= wlen;
wlen = asm.cipher(AES_asm.DEC.CTR, AES_asm.HEAP_DATA + pos, wlen);
wlen = asm.mac(AES_asm.MAC.CBC, AES_asm.HEAP_DATA + pos, wlen);
if (wlen) result.set(heap.subarray(pos, pos + wlen), rpos);
counter += wlen >>> 4;
rpos += wlen;
pos = 0;
len = 0;
}
if (dlen > 0) {
len += _heap_write(heap, 0, data, dpos, dlen);
}
this.counter = counter;
this.aes.pos = pos;
this.aes.len = len;
return result;
}
AES_CCM_Decrypt_finish(): Uint8Array {
const asm = this.aes.asm;
const heap = this.aes.heap;
const tagSize = this.tagSize;
const pos = this.aes.pos;
const len = this.aes.len;
const rlen = len - tagSize;
if (len < tagSize) throw new IllegalStateError('authentication tag not found');
const result = new Uint8Array(rlen);
const atag = new Uint8Array(heap.subarray(pos + rlen, pos + len));
asm.cipher(AES_asm.DEC.CTR, AES_asm.HEAP_DATA + pos, (rlen + 15) & -16);
result.set(heap.subarray(pos, pos + rlen));
let i = rlen;
for (; i & 15; i++) heap[pos + i] = 0;
asm.mac(AES_asm.MAC.CBC, AES_asm.HEAP_DATA + pos, i);
asm.set_counter(0, 0, 0, 0);
asm.get_iv(AES_asm.HEAP_DATA);
asm.cipher(AES_asm.ENC.CTR, AES_asm.HEAP_DATA, 16);
let acheck = 0;
for (let j = 0; j < tagSize; ++j) acheck |= atag[j] ^ heap[j];
if (acheck) throw new SecurityError('data integrity check failed');
this.counter = 1;
this.aes.pos = 0;
this.aes.len = 0;
return result;
}
private AES_CTR_set_options(nonce: Uint8Array, counter: number, size: number): void {
if (size < 8 || size > 48) throw new IllegalArgumentError('illegal counter size');
const mask = Math.pow(2, size) - 1;
this.aes.asm.set_mask(0, 0, (mask / 0x100000000) | 0, mask | 0);
const len = nonce.length;
if (!len || len > 16) throw new IllegalArgumentError('illegal nonce size');
this.nonce = nonce;
const view = new DataView(new ArrayBuffer(16));
new Uint8Array(view.buffer).set(nonce);
this.aes.asm.set_nonce(view.getUint32(0), view.getUint32(4), view.getUint32(8), view.getUint32(12));
if (counter < 0 || counter >= Math.pow(2, size)) throw new IllegalArgumentError('illegal counter value');
this.counter = counter;
this.aes.asm.set_counter(0, 0, (counter / 0x100000000) | 0, counter | 0);
}
}
================================================
FILE: src/aes/cfb.ts
================================================
import { AES } from './aes';
import { joinBytes } from '../other/utils';
export class AES_CFB {
private aes: AES;
static encrypt(data: Uint8Array, key: Uint8Array, iv?: Uint8Array): Uint8Array {
return new AES_CFB(key, iv).encrypt(data);
}
static decrypt(data: Uint8Array, key: Uint8Array, iv?: Uint8Array): Uint8Array {
return new AES_CFB(key, iv).decrypt(data);
}
constructor(key: Uint8Array, iv?: Uint8Array, aes?: AES) {
this.aes = aes ? aes : new AES(key, iv, true, 'CFB');
delete this.aes.padding;
}
encrypt(data: Uint8Array): Uint8Array {
const r1 = this.aes.AES_Encrypt_process(data);
const r2 = this.aes.AES_Encrypt_finish();
return joinBytes(r1, r2);
}
decrypt(data: Uint8Array): Uint8Array {
const r1 = this.aes.AES_Decrypt_process(data);
const r2 = this.aes.AES_Decrypt_finish();
return joinBytes(r1, r2);
}
}
================================================
FILE: src/aes/cmac.ts
================================================
import { AES_ECB } from './ecb';
import { AES_CBC } from './cbc';
function mul2(data: Uint8Array): void {
const t = data[0] & 0x80;
for (let i = 0; i < 15; i++) {
data[i] = (data[i] << 1) ^ (data[i + 1] & 0x80 ? 1 : 0);
}
data[15] = (data[15] << 1) ^ (t ? 0x87 : 0);
}
export class AES_CMAC {
private readonly k: Uint8Array;
private readonly cbc: AES_CBC;
private readonly buffer: Uint8Array;
private bufferLength = 0;
public result!: Uint8Array | null;
static bytes(data: Uint8Array, key: Uint8Array): Uint8Array {
return new AES_CMAC(key).process(data).finish().result as Uint8Array;
}
constructor(key: Uint8Array) {
this.k = new AES_ECB(key).encrypt(new Uint8Array(16));
mul2(this.k);
this.cbc = new AES_CBC(key, new Uint8Array(16), false);
this.buffer = new Uint8Array(16);
this.result = null;
}
process(data: Uint8Array): this {
if (this.bufferLength + data.length > 16) {
this.cbc.encrypt(this.buffer.subarray(0, this.bufferLength));
const offset = ((this.bufferLength + data.length - 1) & ~15) - this.bufferLength;
this.cbc.encrypt(data.subarray(0, offset));
this.buffer.set(data.subarray(offset));
this.bufferLength = data.length - offset;
} else {
this.buffer.set(data, this.bufferLength);
this.bufferLength += data.length;
}
return this;
}
finish(): this {
if (this.bufferLength !== 16) {
this.buffer[this.bufferLength] = 0x80;
for (let i = this.bufferLength + 1; i < 16; i++) {
this.buffer[i] = 0;
}
mul2(this.k);
}
for (let i = 0; i < 16; i++) {
this.buffer[i] ^= this.k[i];
}
this.result = this.cbc.encrypt(this.buffer);
return this;
}
}
================================================
FILE: src/aes/ctr.ts
================================================
import { AES } from './aes';
import { IllegalArgumentError } from '../other/errors';
import { joinBytes } from '../other/utils';
export class AES_CTR {
private aes: AES;
static encrypt(data: Uint8Array, key: Uint8Array, nonce: Uint8Array): Uint8Array {
return new AES_CTR(key, nonce).encrypt(data);
}
static decrypt(data: Uint8Array, key: Uint8Array, nonce: Uint8Array): Uint8Array {
return new AES_CTR(key, nonce).encrypt(data);
}
constructor(key: Uint8Array, nonce: Uint8Array, aes?: AES) {
this.aes = aes ? aes : new AES(key, undefined, false, 'CTR');
delete this.aes.padding;
this.AES_CTR_set_options(nonce);
}
encrypt(data: Uint8Array): Uint8Array {
const r1 = this.aes.AES_Encrypt_process(data);
const r2 = this.aes.AES_Encrypt_finish();
return joinBytes(r1, r2);
}
decrypt(data: Uint8Array): Uint8Array {
const r1 = this.aes.AES_Encrypt_process(data);
const r2 = this.aes.AES_Encrypt_finish();
return joinBytes(r1, r2);
}
private AES_CTR_set_options(nonce: Uint8Array, counter?: number, size?: number): void {
if (size !== undefined) {
if (size < 8 || size > 48) throw new IllegalArgumentError('illegal counter size');
let mask = Math.pow(2, size) - 1;
this.aes.asm.set_mask(0, 0, (mask / 0x100000000) | 0, mask | 0);
} else {
size = 48;
this.aes.asm.set_mask(0, 0, 0xffff, 0xffffffff);
}
if (nonce !== undefined) {
let len = nonce.length;
if (!len || len > 16) throw new IllegalArgumentError('illegal nonce size');
let view = new DataView(new ArrayBuffer(16));
new Uint8Array(view.buffer).set(nonce);
this.aes.asm.set_nonce(view.getUint32(0), view.getUint32(4), view.getUint32(8), view.getUint32(12));
} else {
throw new Error('nonce is required');
}
if (counter !== undefined) {
if (counter < 0 || counter >= Math.pow(2, size)) throw new IllegalArgumentError('illegal counter value');
this.aes.asm.set_counter(0, 0, (counter / 0x100000000) | 0, counter | 0);
}
}
}
================================================
FILE: src/aes/ecb.ts
================================================
import { AES } from './aes';
import { joinBytes } from '../other/utils';
export class AES_ECB {
private aes: AES;
static encrypt(data: Uint8Array, key: Uint8Array, padding: boolean = false): Uint8Array {
return new AES_ECB(key, padding).encrypt(data);
}
static decrypt(data: Uint8Array, key: Uint8Array, padding: boolean = false): Uint8Array {
return new AES_ECB(key, padding).decrypt(data);
}
constructor(key: Uint8Array, padding: boolean = false, aes?: AES) {
this.aes = aes ? aes : new AES(key, undefined, padding, 'ECB');
}
encrypt(data: Uint8Array): Uint8Array {
const r1 = this.aes.AES_Encrypt_process(data);
const r2 = this.aes.AES_Encrypt_finish();
return joinBytes(r1, r2);
}
decrypt(data: Uint8Array): Uint8Array {
const r1 = this.aes.AES_Decrypt_process(data);
const r2 = this.aes.AES_Decrypt_finish();
return joinBytes(r1, r2);
}
}
================================================
FILE: src/aes/exports.ts
================================================
// shared asm.js module and heap
import { AES_asm } from './aes.asm';
export var _AES_heap_instance = new Uint8Array(0x100000); // 1MB
export var _AES_asm_instance = new AES_asm(null, _AES_heap_instance.buffer);
================================================
FILE: src/aes/gcm.ts
================================================
import { IllegalArgumentError, IllegalStateError, SecurityError } from '../other/errors';
import { _heap_write } from '../other/utils';
import { AES } from './aes';
import { AES_asm } from './aes.asm';
const _AES_GCM_data_maxLength = 68719476704; // 2^36 - 2^5
export class AES_GCM {
private readonly adata: Uint8Array | undefined;
private readonly gamma0: number = 0;
private aes: AES;
private counter: number = 1;
static encrypt(
cleartext: Uint8Array,
key: Uint8Array,
nonce: Uint8Array,
adata?: Uint8Array,
tagsize?: number,
): Uint8Array {
return new AES_GCM(key, nonce, adata, tagsize).encrypt(cleartext);
}
static decrypt(
ciphertext: Uint8Array,
key: Uint8Array,
nonce: Uint8Array,
adata?: Uint8Array,
tagsize?: number,
): Uint8Array {
return new AES_GCM(key, nonce, adata, tagsize).decrypt(ciphertext);
}
constructor(
key: Uint8Array,
nonce: Uint8Array,
adata?: Uint8Array,
private readonly tagSize: number = 16,
aes?: AES,
) {
this.aes = aes ? aes : new AES(key, undefined, false, 'CTR');
// Init GCM
this.aes.asm.gcm_init();
// Tag size
if (this.tagSize < 4 || this.tagSize > 16) throw new IllegalArgumentError('illegal tagSize value');
// Nonce
const noncelen = nonce.length || 0;
const noncebuf = new Uint8Array(16);
if (noncelen !== 12) {
this._gcm_mac_process(nonce);
this.aes.heap[0] = 0;
this.aes.heap[1] = 0;
this.aes.heap[2] = 0;
this.aes.heap[3] = 0;
this.aes.heap[4] = 0;
this.aes.heap[5] = 0;
this.aes.heap[6] = 0;
this.aes.heap[7] = 0;
this.aes.heap[8] = 0;
this.aes.heap[9] = 0;
this.aes.heap[10] = 0;
this.aes.heap[11] = noncelen >>> 29;
this.aes.heap[12] = (noncelen >>> 21) & 255;
this.aes.heap[13] = (noncelen >>> 13) & 255;
this.aes.heap[14] = (noncelen >>> 5) & 255;
this.aes.heap[15] = (noncelen << 3) & 255;
this.aes.asm.mac(AES_asm.MAC.GCM, AES_asm.HEAP_DATA, 16);
this.aes.asm.get_iv(AES_asm.HEAP_DATA);
this.aes.asm.set_iv(0, 0, 0, 0);
noncebuf.set(this.aes.heap.subarray(0, 16));
} else {
noncebuf.set(nonce);
noncebuf[15] = 1;
}
const nonceview = new DataView(noncebuf.buffer);
this.gamma0 = nonceview.getUint32(12);
this.aes.asm.set_nonce(nonceview.getUint32(0), nonceview.getUint32(4), nonceview.getUint32(8), 0);
this.aes.asm.set_mask(0, 0, 0, 0xffffffff);
// Associated data
if (adata !== undefined) {
if (adata.length > _AES_GCM_data_maxLength) throw new IllegalArgumentError('illegal adata length');
if (adata.length) {
this.adata = adata;
this._gcm_mac_process(adata);
} else {
this.adata = undefined;
}
} else {
this.adata = undefined;
}
// Counter
if (this.counter < 1 || this.counter > 0xffffffff)
throw new RangeError('counter must be a positive 32-bit integer');
this.aes.asm.set_counter(0, 0, 0, (this.gamma0 + this.counter) | 0);
}
encrypt(data: Uint8Array) {
return this.AES_GCM_encrypt(data);
}
decrypt(data: Uint8Array) {
return this.AES_GCM_decrypt(data);
}
AES_GCM_Encrypt_process(data: Uint8Array): Uint8Array {
let dpos = 0;
let dlen = data.length || 0;
let asm = this.aes.asm;
let heap = this.aes.heap;
let counter = this.counter;
let pos = this.aes.pos;
let len = this.aes.len;
let rpos = 0;
let rlen = (len + dlen) & -16;
let wlen = 0;
if (((counter - 1) << 4) + len + dlen > _AES_GCM_data_maxLength) throw new RangeError('counter overflow');
const result = new Uint8Array(rlen);
while (dlen > 0) {
wlen = _heap_write(heap, pos + len, data, dpos, dlen);
len += wlen;
dpos += wlen;
dlen -= wlen;
wlen = asm.cipher(AES_asm.ENC.CTR, AES_asm.HEAP_DATA + pos, len);
wlen = asm.mac(AES_asm.MAC.GCM, AES_asm.HEAP_DATA + pos, wlen);
if (wlen) result.set(heap.subarray(pos, pos + wlen), rpos);
counter += wlen >>> 4;
rpos += wlen;
if (wlen < len) {
pos += wlen;
len -= wlen;
} else {
pos = 0;
len = 0;
}
}
this.counter = counter;
this.aes.pos = pos;
this.aes.len = len;
return result;
}
AES_GCM_Encrypt_finish(): Uint8Array {
let asm = this.aes.asm;
let heap = this.aes.heap;
let counter = this.counter;
let tagSize = this.tagSize;
let adata = this.adata;
let pos = this.aes.pos;
let len = this.aes.len;
const result = new Uint8Array(len + tagSize);
asm.cipher(AES_asm.ENC.CTR, AES_asm.HEAP_DATA + pos, (len + 15) & -16);
if (len) result.set(heap.subarray(pos, pos + len));
let i = len;
for (; i & 15; i++) heap[pos + i] = 0;
asm.mac(AES_asm.MAC.GCM, AES_asm.HEAP_DATA + pos, i);
const alen = adata !== undefined ? adata.length : 0;
const clen = ((counter - 1) << 4) + len;
heap[0] = 0;
heap[1] = 0;
heap[2] = 0;
heap[3] = alen >>> 29;
heap[4] = alen >>> 21;
heap[5] = (alen >>> 13) & 255;
heap[6] = (alen >>> 5) & 255;
heap[7] = (alen << 3) & 255;
heap[8] = heap[9] = heap[10] = 0;
heap[11] = clen >>> 29;
heap[12] = (clen >>> 21) & 255;
heap[13] = (clen >>> 13) & 255;
heap[14] = (clen >>> 5) & 255;
heap[15] = (clen << 3) & 255;
asm.mac(AES_asm.MAC.GCM, AES_asm.HEAP_DATA, 16);
asm.get_iv(AES_asm.HEAP_DATA);
asm.set_counter(0, 0, 0, this.gamma0);
asm.cipher(AES_asm.ENC.CTR, AES_asm.HEAP_DATA, 16);
result.set(heap.subarray(0, tagSize), len);
this.counter = 1;
this.aes.pos = 0;
this.aes.len = 0;
return result;
}
AES_GCM_Decrypt_process(data: Uint8Array): Uint8Array {
let dpos = 0;
let dlen = data.length || 0;
let asm = this.aes.asm;
let heap = this.aes.heap;
let counter = this.counter;
let tagSize = this.tagSize;
let pos = this.aes.pos;
let len = this.aes.len;
let rpos = 0;
let rlen = len + dlen > tagSize ? (len + dlen - tagSize) & -16 : 0;
let tlen = len + dlen - rlen;
let wlen = 0;
if (((counter - 1) << 4) + len + dlen > _AES_GCM_data_maxLength) throw new RangeError('counter overflow');
const result = new Uint8Array(rlen);
while (dlen > tlen) {
wlen = _heap_write(heap, pos + len, data, dpos, dlen - tlen);
len += wlen;
dpos += wlen;
dlen -= wlen;
wlen = asm.mac(AES_asm.MAC.GCM, AES_asm.HEAP_DATA + pos, wlen);
wlen = asm.cipher(AES_asm.DEC.CTR, AES_asm.HEAP_DATA + pos, wlen);
if (wlen) result.set(heap.subarray(pos, pos + wlen), rpos);
counter += wlen >>> 4;
rpos += wlen;
pos = 0;
len = 0;
}
if (dlen > 0) {
len += _heap_write(heap, 0, data, dpos, dlen);
}
this.counter = counter;
this.aes.pos = pos;
this.aes.len = len;
return result;
}
AES_GCM_Decrypt_finish() {
let asm = this.aes.asm;
let heap = this.aes.heap;
let tagSize = this.tagSize;
let adata = this.adata;
let counter = this.counter;
let pos = this.aes.pos;
let len = this.aes.len;
let rlen = len - tagSize;
if (len < tagSize) throw new IllegalStateError('authentication tag not found');
const result = new Uint8Array(rlen);
const atag = new Uint8Array(heap.subarray(pos + rlen, pos + len));
let i = rlen;
for (; i & 15; i++) heap[pos + i] = 0;
asm.mac(AES_asm.MAC.GCM, AES_asm.HEAP_DATA + pos, i);
asm.cipher(AES_asm.DEC.CTR, AES_asm.HEAP_DATA + pos, i);
if (rlen) result.set(heap.subarray(pos, pos + rlen));
const alen = adata !== undefined ? adata.length : 0;
const clen = ((counter - 1) << 4) + len - tagSize;
heap[0] = 0;
heap[1] = 0;
heap[2] = 0;
heap[3] = alen >>> 29;
heap[4] = alen >>> 21;
heap[5] = (alen >>> 13) & 255;
heap[6] = (alen >>> 5) & 255;
heap[7] = (alen << 3) & 255;
heap[8] = heap[9] = heap[10] = 0;
heap[11] = clen >>> 29;
heap[12] = (clen >>> 21) & 255;
heap[13] = (clen >>> 13) & 255;
heap[14] = (clen >>> 5) & 255;
heap[15] = (clen << 3) & 255;
asm.mac(AES_asm.MAC.GCM, AES_asm.HEAP_DATA, 16);
asm.get_iv(AES_asm.HEAP_DATA);
asm.set_counter(0, 0, 0, this.gamma0);
asm.cipher(AES_asm.ENC.CTR, AES_asm.HEAP_DATA, 16);
let acheck = 0;
for (let i = 0; i < tagSize; ++i) acheck |= atag[i] ^ heap[i];
if (acheck) throw new SecurityError('data integrity check failed');
this.counter = 1;
this.aes.pos = 0;
this.aes.len = 0;
return result;
}
private AES_GCM_decrypt(data: Uint8Array): Uint8Array {
const result1 = this.AES_GCM_Decrypt_process(data);
const result2 = this.AES_GCM_Decrypt_finish();
const result = new Uint8Array(result1.length + result2.length);
if (result1.length) result.set(result1);
if (result2.length) result.set(result2, result1.length);
return result;
}
private AES_GCM_encrypt(data: Uint8Array): Uint8Array {
const result1 = this.AES_GCM_Encrypt_process(data);
const result2 = this.AES_GCM_Encrypt_finish();
const result = new Uint8Array(result1.length + result2.length);
if (result1.length) result.set(result1);
if (result2.length) result.set(result2, result1.length);
return result;
}
_gcm_mac_process(data: Uint8Array) {
const heap = this.aes.heap;
const asm = this.aes.asm;
let dpos = 0;
let dlen = data.length || 0;
let wlen = 0;
while (dlen > 0) {
wlen = _heap_write(heap, 0, data, dpos, dlen);
dpos += wlen;
dlen -= wlen;
while (wlen & 15) heap[wlen++] = 0;
asm.mac(AES_asm.MAC.GCM, AES_asm.HEAP_DATA, wlen);
}
}
}
================================================
FILE: src/aes/ofb.ts
================================================
import { AES } from './aes';
import { joinBytes } from '../other/utils';
export class AES_OFB {
private aes: AES;
static encrypt(data: Uint8Array, key: Uint8Array, iv?: Uint8Array): Uint8Array {
return new AES_OFB(key, iv).encrypt(data);
}
static decrypt(data: Uint8Array, key: Uint8Array, iv?: Uint8Array): Uint8Array {
return new AES_OFB(key, iv).decrypt(data);
}
constructor(key: Uint8Array, iv?: Uint8Array, aes?: AES) {
this.aes = aes ? aes : new AES(key, iv, false, 'OFB');
}
encrypt(data: Uint8Array): Uint8Array {
const r1 = this.aes.AES_Encrypt_process(data);
const r2 = this.aes.AES_Encrypt_finish();
return joinBytes(r1, r2);
}
decrypt(data: Uint8Array): Uint8Array {
const r1 = this.aes.AES_Decrypt_process(data);
const r2 = this.aes.AES_Decrypt_finish();
return joinBytes(r1, r2);
}
}
================================================
FILE: src/bignum/bigint.asm.d.ts
================================================
declare interface bigintresult {
sreset: (n?: number) => number;
salloc: (n?: number) => number;
sfree: (n?: number) => void;
z: (l?: number, z?: number, A?: number) => void;
tst: (A?: number, lA?: number) => 0;
neg: (A?: number, lA?: number, R?: number, lR?: number) => number;
cmp: (A?: number, lA?: number, B?: number, lB?: number) => 0;
add: (
A?: number,
lA?: number,
B?: number,
lB?: number,
R?: number,
lR?: number,
) => number;
sub: (
A?: number,
lA?: number,
B?: number,
lB?: number,
R?: number,
lR?: number,
) => number;
mul: (
A?: number,
lA?: number,
B?: number,
lB?: number,
R?: number,
lR?: number,
) => void;
sqr: (A?: number, lA?: number, R?: number) => void;
div: (
N?: number,
lN?: number,
D?: number,
lD?: number,
Q?: number,
) => void;
mredc: (
A?: number,
lA?: number,
N?: number,
lN?: number,
y?: number,
R?: number,
) => void;
}
export function bigint_asm(stdlib: any, foreign: any, buffer: ArrayBuffer): bigintresult;
================================================
FILE: src/bignum/bigint.asm.js
================================================
/**
* Integers are represented as little endian array of 32-bit limbs.
* Limbs number is a power of 2 and a multiple of 8 (256 bits).
* Negative values use two's complement representation.
*/
export var bigint_asm = function ( stdlib, foreign, buffer ) {
"use asm";
var SP = 0;
var HEAP32 = new stdlib.Uint32Array(buffer);
var imul = stdlib.Math.imul;
/**
* Simple stack memory allocator
*
* Methods:
* sreset
* salloc
* sfree
*/
function sreset ( p ) {
p = p|0;
SP = p = (p + 31) & -32;
return p|0;
}
function salloc ( l ) {
l = l|0;
var p = 0; p = SP;
SP = p + ((l + 31) & -32)|0;
return p|0;
}
function sfree ( l ) {
l = l|0;
SP = SP - ((l + 31) & -32)|0;
}
/**
* Utility functions:
* cp
* z
*/
function cp ( l, A, B ) {
l = l|0;
A = A|0;
B = B|0;
var i = 0;
if ( (A|0) > (B|0) ) {
for ( ; (i|0) < (l|0); i = (i+4)|0 ) {
HEAP32[(B+i)>>2] = HEAP32[(A+i)>>2];
}
}
else {
for ( i = (l-4)|0; (i|0) >= 0; i = (i-4)|0 ) {
HEAP32[(B+i)>>2] = HEAP32[(A+i)>>2];
}
}
}
function z ( l, z, A ) {
l = l|0;
z = z|0;
A = A|0;
var i = 0;
for ( ; (i|0) < (l|0); i = (i+4)|0 ) {
HEAP32[(A+i)>>2] = z;
}
}
/**
* Negate the argument
*
* Perform two's complement transformation:
*
* -A = ~A + 1
*
* @param A offset of the argment being negated, 32-byte aligned
* @param lA length of the argument, multiple of 32
*
* @param R offset where to place the result to, 32-byte aligned
* @param lR length to truncate the result to, multiple of 32
*/
function neg ( A, lA, R, lR ) {
A = A|0;
lA = lA|0;
R = R|0;
lR = lR|0;
var a = 0, c = 0, t = 0, r = 0, i = 0;
if ( (lR|0) <= 0 )
lR = lA;
if ( (lR|0) < (lA|0) )
lA = lR;
c = 1;
for ( ; (i|0) < (lA|0); i = (i+4)|0 ) {
a = ~HEAP32[(A+i)>>2];
t = (a & 0xffff) + c|0;
r = (a >>> 16) + (t >>> 16)|0;
HEAP32[(R+i)>>2] = (r << 16) | (t & 0xffff);
c = r >>> 16;
}
for ( ; (i|0) < (lR|0); i = (i+4)|0 ) {
HEAP32[(R+i)>>2] = (c-1)|0;
}
return c|0;
}
function cmp ( A, lA, B, lB ) {
A = A|0;
lA = lA|0;
B = B|0;
lB = lB|0;
var a = 0, b = 0, i = 0;
if ( (lA|0) > (lB|0) ) {
for ( i = (lA-4)|0; (i|0) >= (lB|0); i = (i-4)|0 ) {
if ( HEAP32[(A+i)>>2]|0 ) return 1;
}
}
else {
for ( i = (lB-4)|0; (i|0) >= (lA|0); i = (i-4)|0 ) {
if ( HEAP32[(B+i)>>2]|0 ) return -1;
}
}
for ( ; (i|0) >= 0; i = (i-4)|0 ) {
a = HEAP32[(A+i)>>2]|0, b = HEAP32[(B+i)>>2]|0;
if ( (a>>>0) < (b>>>0) ) return -1;
if ( (a>>>0) > (b>>>0) ) return 1;
}
return 0;
}
/**
* Test the argument
*
* Same as `cmp` with zero.
*/
function tst ( A, lA ) {
A = A|0;
lA = lA|0;
var i = 0;
for ( i = (lA-4)|0; (i|0) >= 0; i = (i-4)|0 ) {
if ( HEAP32[(A+i)>>2]|0 ) return (i+4)|0;
}
return 0;
}
/**
* Conventional addition
*
* @param A offset of the first argument, 32-byte aligned
* @param lA length of the first argument, multiple of 32
*
* @param B offset of the second argument, 32-bit aligned
* @param lB length of the second argument, multiple of 32
*
* @param R offset where to place the result to, 32-byte aligned
* @param lR length to truncate the result to, multiple of 32
*/
function add ( A, lA, B, lB, R, lR ) {
A = A|0;
lA = lA|0;
B = B|0;
lB = lB|0;
R = R|0;
lR = lR|0;
var a = 0, b = 0, c = 0, t = 0, r = 0, i = 0;
if ( (lA|0) < (lB|0) ) {
t = A, A = B, B = t;
t = lA, lA = lB, lB = t;
}
if ( (lR|0) <= 0 )
lR = lA+4|0;
if ( (lR|0) < (lB|0) )
lA = lB = lR;
for ( ; (i|0) < (lB|0); i = (i+4)|0 ) {
a = HEAP32[(A+i)>>2]|0;
b = HEAP32[(B+i)>>2]|0;
t = ( (a & 0xffff) + (b & 0xffff)|0 ) + c|0;
r = ( (a >>> 16) + (b >>> 16)|0 ) + (t >>> 16)|0;
HEAP32[(R+i)>>2] = (t & 0xffff) | (r << 16);
c = r >>> 16;
}
for ( ; (i|0) < (lA|0); i = (i+4)|0 ) {
a = HEAP32[(A+i)>>2]|0;
t = (a & 0xffff) + c|0;
r = (a >>> 16) + (t >>> 16)|0;
HEAP32[(R+i)>>2] = (t & 0xffff) | (r << 16);
c = r >>> 16;
}
for ( ; (i|0) < (lR|0); i = (i+4)|0 ) {
HEAP32[(R+i)>>2] = c|0;
c = 0;
}
return c|0;
}
/**
* Conventional subtraction
*
* @param A offset of the first argument, 32-byte aligned
* @param lA length of the first argument, multiple of 32
*
* @param B offset of the second argument, 32-bit aligned
* @param lB length of the second argument, multiple of 32
*
* @param R offset where to place the result to, 32-byte aligned
* @param lR length to truncate the result to, multiple of 32
*/
function sub ( A, lA, B, lB, R, lR ) {
A = A|0;
lA = lA|0;
B = B|0;
lB = lB|0;
R = R|0;
lR = lR|0;
var a = 0, b = 0, c = 0, t = 0, r = 0, i = 0;
if ( (lR|0) <= 0 )
lR = (lA|0) > (lB|0) ? lA+4|0 : lB+4|0;
if ( (lR|0) < (lA|0) )
lA = lR;
if ( (lR|0) < (lB|0) )
lB = lR;
if ( (lA|0) < (lB|0) ) {
for ( ; (i|0) < (lA|0); i = (i+4)|0 ) {
a = HEAP32[(A+i)>>2]|0;
b = HEAP32[(B+i)>>2]|0;
t = ( (a & 0xffff) - (b & 0xffff)|0 ) + c|0;
r = ( (a >>> 16) - (b >>> 16)|0 ) + (t >> 16)|0;
HEAP32[(R+i)>>2] = (t & 0xffff) | (r << 16);
c = r >> 16;
}
for ( ; (i|0) < (lB|0); i = (i+4)|0 ) {
b = HEAP32[(B+i)>>2]|0;
t = c - (b & 0xffff)|0;
r = (t >> 16) - (b >>> 16)|0;
HEAP32[(R+i)>>2] = (t & 0xffff) | (r << 16);
c = r >> 16;
}
}
else {
for ( ; (i|0) < (lB|0); i = (i+4)|0 ) {
a = HEAP32[(A+i)>>2]|0;
b = HEAP32[(B+i)>>2]|0;
t = ( (a & 0xffff) - (b & 0xffff)|0 ) + c|0;
r = ( (a >>> 16) - (b >>> 16)|0 ) + (t >> 16)|0;
HEAP32[(R+i)>>2] = (t & 0xffff) | (r << 16);
c = r >> 16;
}
for ( ; (i|0) < (lA|0); i = (i+4)|0 ) {
a = HEAP32[(A+i)>>2]|0;
t = (a & 0xffff) + c|0;
r = (a >>> 16) + (t >> 16)|0;
HEAP32[(R+i)>>2] = (t & 0xffff) | (r << 16);
c = r >> 16;
}
}
for ( ; (i|0) < (lR|0); i = (i+4)|0 ) {
HEAP32[(R+i)>>2] = c|0;
}
return c|0;
}
/**
* Conventional multiplication
*
* TODO implement Karatsuba algorithm for large multiplicands
*
* @param A offset of the first argument, 32-byte aligned
* @param lA length of the first argument, multiple of 32
*
* @param B offset of the second argument, 32-byte aligned
* @param lB length of the second argument, multiple of 32
*
* @param R offset where to place the result to, 32-byte aligned
* @param lR length to truncate the result to, multiple of 32
*/
function mul ( A, lA, B, lB, R, lR ) {
A = A|0;
lA = lA|0;
B = B|0;
lB = lB|0;
R = R|0;
lR = lR|0;
var al0 = 0, al1 = 0, al2 = 0, al3 = 0, al4 = 0, al5 = 0, al6 = 0, al7 = 0, ah0 = 0, ah1 = 0, ah2 = 0, ah3 = 0, ah4 = 0, ah5 = 0, ah6 = 0, ah7 = 0,
bl0 = 0, bl1 = 0, bl2 = 0, bl3 = 0, bl4 = 0, bl5 = 0, bl6 = 0, bl7 = 0, bh0 = 0, bh1 = 0, bh2 = 0, bh3 = 0, bh4 = 0, bh5 = 0, bh6 = 0, bh7 = 0,
r0 = 0, r1 = 0, r2 = 0, r3 = 0, r4 = 0, r5 = 0, r6 = 0, r7 = 0, r8 = 0, r9 = 0, r10 = 0, r11 = 0, r12 = 0, r13 = 0, r14 = 0, r15 = 0,
u = 0, v = 0, w = 0, m = 0,
i = 0, Ai = 0, j = 0, Bj = 0, Rk = 0;
if ( (lA|0) > (lB|0) ) {
u = A, v = lA;
A = B, lA = lB;
B = u, lB = v;
}
m = (lA+lB)|0;
if ( ( (lR|0) > (m|0) ) | ( (lR|0) <= 0 ) )
lR = m;
if ( (lR|0) < (lA|0) )
lA = lR;
if ( (lR|0) < (lB|0) )
lB = lR;
for ( ; (i|0) < (lA|0); i = (i+32)|0 ) {
Ai = (A+i)|0;
ah0 = HEAP32[(Ai|0)>>2]|0,
ah1 = HEAP32[(Ai|4)>>2]|0,
ah2 = HEAP32[(Ai|8)>>2]|0,
ah3 = HEAP32[(Ai|12)>>2]|0,
ah4 = HEAP32[(Ai|16)>>2]|0,
ah5 = HEAP32[(Ai|20)>>2]|0,
ah6 = HEAP32[(Ai|24)>>2]|0,
ah7 = HEAP32[(Ai|28)>>2]|0,
al0 = ah0 & 0xffff,
al1 = ah1 & 0xffff,
al2 = ah2 & 0xffff,
al3 = ah3 & 0xffff,
al4 = ah4 & 0xffff,
al5 = ah5 & 0xffff,
al6 = ah6 & 0xffff,
al7 = ah7 & 0xffff,
ah0 = ah0 >>> 16,
ah1 = ah1 >>> 16,
ah2 = ah2 >>> 16,
ah3 = ah3 >>> 16,
ah4 = ah4 >>> 16,
ah5 = ah5 >>> 16,
ah6 = ah6 >>> 16,
ah7 = ah7 >>> 16;
r8 = r9 = r10 = r11 = r12 = r13 = r14 = r15 = 0;
for ( j = 0; (j|0) < (lB|0); j = (j+32)|0 ) {
Bj = (B+j)|0;
Rk = (R+(i+j|0))|0;
bh0 = HEAP32[(Bj|0)>>2]|0,
bh1 = HEAP32[(Bj|4)>>2]|0,
bh2 = HEAP32[(Bj|8)>>2]|0,
bh3 = HEAP32[(Bj|12)>>2]|0,
bh4 = HEAP32[(Bj|16)>>2]|0,
bh5 = HEAP32[(Bj|20)>>2]|0,
bh6 = HEAP32[(Bj|24)>>2]|0,
bh7 = HEAP32[(Bj|28)>>2]|0,
bl0 = bh0 & 0xffff,
bl1 = bh1 & 0xffff,
bl2 = bh2 & 0xffff,
bl3 = bh3 & 0xffff,
bl4 = bh4 & 0xffff,
bl5 = bh5 & 0xffff,
bl6 = bh6 & 0xffff,
bl7 = bh7 & 0xffff,
bh0 = bh0 >>> 16,
bh1 = bh1 >>> 16,
bh2 = bh2 >>> 16,
bh3 = bh3 >>> 16,
bh4 = bh4 >>> 16,
bh5 = bh5 >>> 16,
bh6 = bh6 >>> 16,
bh7 = bh7 >>> 16;
r0 = HEAP32[(Rk|0)>>2]|0,
r1 = HEAP32[(Rk|4)>>2]|0,
r2 = HEAP32[(Rk|8)>>2]|0,
r3 = HEAP32[(Rk|12)>>2]|0,
r4 = HEAP32[(Rk|16)>>2]|0,
r5 = HEAP32[(Rk|20)>>2]|0,
r6 = HEAP32[(Rk|24)>>2]|0,
r7 = HEAP32[(Rk|28)>>2]|0;
u = ((imul(al0, bl0)|0) + (r8 & 0xffff)|0) + (r0 & 0xffff)|0;
v = ((imul(ah0, bl0)|0) + (r8 >>> 16)|0) + (r0 >>> 16)|0;
w = ((imul(al0, bh0)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah0, bh0)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r0 = (w << 16) | (u & 0xffff);
u = ((imul(al0, bl1)|0) + (m & 0xffff)|0) + (r1 & 0xffff)|0;
v = ((imul(ah0, bl1)|0) + (m >>> 16)|0) + (r1 >>> 16)|0;
w = ((imul(al0, bh1)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah0, bh1)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r1 = (w << 16) | (u & 0xffff);
u = ((imul(al0, bl2)|0) + (m & 0xffff)|0) + (r2 & 0xffff)|0;
v = ((imul(ah0, bl2)|0) + (m >>> 16)|0) + (r2 >>> 16)|0;
w = ((imul(al0, bh2)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah0, bh2)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r2 = (w << 16) | (u & 0xffff);
u = ((imul(al0, bl3)|0) + (m & 0xffff)|0) + (r3 & 0xffff)|0;
v = ((imul(ah0, bl3)|0) + (m >>> 16)|0) + (r3 >>> 16)|0;
w = ((imul(al0, bh3)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah0, bh3)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r3 = (w << 16) | (u & 0xffff);
u = ((imul(al0, bl4)|0) + (m & 0xffff)|0) + (r4 & 0xffff)|0;
v = ((imul(ah0, bl4)|0) + (m >>> 16)|0) + (r4 >>> 16)|0;
w = ((imul(al0, bh4)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah0, bh4)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r4 = (w << 16) | (u & 0xffff);
u = ((imul(al0, bl5)|0) + (m & 0xffff)|0) + (r5 & 0xffff)|0;
v = ((imul(ah0, bl5)|0) + (m >>> 16)|0) + (r5 >>> 16)|0;
w = ((imul(al0, bh5)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah0, bh5)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r5 = (w << 16) | (u & 0xffff);
u = ((imul(al0, bl6)|0) + (m & 0xffff)|0) + (r6 & 0xffff)|0;
v = ((imul(ah0, bl6)|0) + (m >>> 16)|0) + (r6 >>> 16)|0;
w = ((imul(al0, bh6)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah0, bh6)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r6 = (w << 16) | (u & 0xffff);
u = ((imul(al0, bl7)|0) + (m & 0xffff)|0) + (r7 & 0xffff)|0;
v = ((imul(ah0, bl7)|0) + (m >>> 16)|0) + (r7 >>> 16)|0;
w = ((imul(al0, bh7)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah0, bh7)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r7 = (w << 16) | (u & 0xffff);
r8 = m;
u = ((imul(al1, bl0)|0) + (r9 & 0xffff)|0) + (r1 & 0xffff)|0;
v = ((imul(ah1, bl0)|0) + (r9 >>> 16)|0) + (r1 >>> 16)|0;
w = ((imul(al1, bh0)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah1, bh0)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r1 = (w << 16) | (u & 0xffff);
u = ((imul(al1, bl1)|0) + (m & 0xffff)|0) + (r2 & 0xffff)|0;
v = ((imul(ah1, bl1)|0) + (m >>> 16)|0) + (r2 >>> 16)|0;
w = ((imul(al1, bh1)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah1, bh1)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r2 = (w << 16) | (u & 0xffff);
u = ((imul(al1, bl2)|0) + (m & 0xffff)|0) + (r3 & 0xffff)|0;
v = ((imul(ah1, bl2)|0) + (m >>> 16)|0) + (r3 >>> 16)|0;
w = ((imul(al1, bh2)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah1, bh2)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r3 = (w << 16) | (u & 0xffff);
u = ((imul(al1, bl3)|0) + (m & 0xffff)|0) + (r4 & 0xffff)|0;
v = ((imul(ah1, bl3)|0) + (m >>> 16)|0) + (r4 >>> 16)|0;
w = ((imul(al1, bh3)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah1, bh3)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r4 = (w << 16) | (u & 0xffff);
u = ((imul(al1, bl4)|0) + (m & 0xffff)|0) + (r5 & 0xffff)|0;
v = ((imul(ah1, bl4)|0) + (m >>> 16)|0) + (r5 >>> 16)|0;
w = ((imul(al1, bh4)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah1, bh4)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r5 = (w << 16) | (u & 0xffff);
u = ((imul(al1, bl5)|0) + (m & 0xffff)|0) + (r6 & 0xffff)|0;
v = ((imul(ah1, bl5)|0) + (m >>> 16)|0) + (r6 >>> 16)|0;
w = ((imul(al1, bh5)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah1, bh5)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r6 = (w << 16) | (u & 0xffff);
u = ((imul(al1, bl6)|0) + (m & 0xffff)|0) + (r7 & 0xffff)|0;
v = ((imul(ah1, bl6)|0) + (m >>> 16)|0) + (r7 >>> 16)|0;
w = ((imul(al1, bh6)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah1, bh6)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r7 = (w << 16) | (u & 0xffff);
u = ((imul(al1, bl7)|0) + (m & 0xffff)|0) + (r8 & 0xffff)|0;
v = ((imul(ah1, bl7)|0) + (m >>> 16)|0) + (r8 >>> 16)|0;
w = ((imul(al1, bh7)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah1, bh7)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r8 = (w << 16) | (u & 0xffff);
r9 = m;
u = ((imul(al2, bl0)|0) + (r10 & 0xffff)|0) + (r2 & 0xffff)|0;
v = ((imul(ah2, bl0)|0) + (r10 >>> 16)|0) + (r2 >>> 16)|0;
w = ((imul(al2, bh0)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah2, bh0)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r2 = (w << 16) | (u & 0xffff);
u = ((imul(al2, bl1)|0) + (m & 0xffff)|0) + (r3 & 0xffff)|0;
v = ((imul(ah2, bl1)|0) + (m >>> 16)|0) + (r3 >>> 16)|0;
w = ((imul(al2, bh1)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah2, bh1)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r3 = (w << 16) | (u & 0xffff);
u = ((imul(al2, bl2)|0) + (m & 0xffff)|0) + (r4 & 0xffff)|0;
v = ((imul(ah2, bl2)|0) + (m >>> 16)|0) + (r4 >>> 16)|0;
w = ((imul(al2, bh2)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah2, bh2)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r4 = (w << 16) | (u & 0xffff);
u = ((imul(al2, bl3)|0) + (m & 0xffff)|0) + (r5 & 0xffff)|0;
v = ((imul(ah2, bl3)|0) + (m >>> 16)|0) + (r5 >>> 16)|0;
w = ((imul(al2, bh3)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah2, bh3)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r5 = (w << 16) | (u & 0xffff);
u = ((imul(al2, bl4)|0) + (m & 0xffff)|0) + (r6 & 0xffff)|0;
v = ((imul(ah2, bl4)|0) + (m >>> 16)|0) + (r6 >>> 16)|0;
w = ((imul(al2, bh4)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah2, bh4)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r6 = (w << 16) | (u & 0xffff);
u = ((imul(al2, bl5)|0) + (m & 0xffff)|0) + (r7 & 0xffff)|0;
v = ((imul(ah2, bl5)|0) + (m >>> 16)|0) + (r7 >>> 16)|0;
w = ((imul(al2, bh5)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah2, bh5)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r7 = (w << 16) | (u & 0xffff);
u = ((imul(al2, bl6)|0) + (m & 0xffff)|0) + (r8 & 0xffff)|0;
v = ((imul(ah2, bl6)|0) + (m >>> 16)|0) + (r8 >>> 16)|0;
w = ((imul(al2, bh6)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah2, bh6)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r8 = (w << 16) | (u & 0xffff);
u = ((imul(al2, bl7)|0) + (m & 0xffff)|0) + (r9 & 0xffff)|0;
v = ((imul(ah2, bl7)|0) + (m >>> 16)|0) + (r9 >>> 16)|0;
w = ((imul(al2, bh7)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah2, bh7)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r9 = (w << 16) | (u & 0xffff);
r10 = m;
u = ((imul(al3, bl0)|0) + (r11 & 0xffff)|0) + (r3 & 0xffff)|0;
v = ((imul(ah3, bl0)|0) + (r11 >>> 16)|0) + (r3 >>> 16)|0;
w = ((imul(al3, bh0)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah3, bh0)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r3 = (w << 16) | (u & 0xffff);
u = ((imul(al3, bl1)|0) + (m & 0xffff)|0) + (r4 & 0xffff)|0;
v = ((imul(ah3, bl1)|0) + (m >>> 16)|0) + (r4 >>> 16)|0;
w = ((imul(al3, bh1)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah3, bh1)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r4 = (w << 16) | (u & 0xffff);
u = ((imul(al3, bl2)|0) + (m & 0xffff)|0) + (r5 & 0xffff)|0;
v = ((imul(ah3, bl2)|0) + (m >>> 16)|0) + (r5 >>> 16)|0;
w = ((imul(al3, bh2)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah3, bh2)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r5 = (w << 16) | (u & 0xffff);
u = ((imul(al3, bl3)|0) + (m & 0xffff)|0) + (r6 & 0xffff)|0;
v = ((imul(ah3, bl3)|0) + (m >>> 16)|0) + (r6 >>> 16)|0;
w = ((imul(al3, bh3)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah3, bh3)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r6 = (w << 16) | (u & 0xffff);
u = ((imul(al3, bl4)|0) + (m & 0xffff)|0) + (r7 & 0xffff)|0;
v = ((imul(ah3, bl4)|0) + (m >>> 16)|0) + (r7 >>> 16)|0;
w = ((imul(al3, bh4)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah3, bh4)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r7 = (w << 16) | (u & 0xffff);
u = ((imul(al3, bl5)|0) + (m & 0xffff)|0) + (r8 & 0xffff)|0;
v = ((imul(ah3, bl5)|0) + (m >>> 16)|0) + (r8 >>> 16)|0;
w = ((imul(al3, bh5)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah3, bh5)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r8 = (w << 16) | (u & 0xffff);
u = ((imul(al3, bl6)|0) + (m & 0xffff)|0) + (r9 & 0xffff)|0;
v = ((imul(ah3, bl6)|0) + (m >>> 16)|0) + (r9 >>> 16)|0;
w = ((imul(al3, bh6)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah3, bh6)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r9 = (w << 16) | (u & 0xffff);
u = ((imul(al3, bl7)|0) + (m & 0xffff)|0) + (r10 & 0xffff)|0;
v = ((imul(ah3, bl7)|0) + (m >>> 16)|0) + (r10 >>> 16)|0;
w = ((imul(al3, bh7)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah3, bh7)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r10 = (w << 16) | (u & 0xffff);
r11 = m;
u = ((imul(al4, bl0)|0) + (r12 & 0xffff)|0) + (r4 & 0xffff)|0;
v = ((imul(ah4, bl0)|0) + (r12 >>> 16)|0) + (r4 >>> 16)|0;
w = ((imul(al4, bh0)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah4, bh0)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r4 = (w << 16) | (u & 0xffff);
u = ((imul(al4, bl1)|0) + (m & 0xffff)|0) + (r5 & 0xffff)|0;
v = ((imul(ah4, bl1)|0) + (m >>> 16)|0) + (r5 >>> 16)|0;
w = ((imul(al4, bh1)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah4, bh1)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r5 = (w << 16) | (u & 0xffff);
u = ((imul(al4, bl2)|0) + (m & 0xffff)|0) + (r6 & 0xffff)|0;
v = ((imul(ah4, bl2)|0) + (m >>> 16)|0) + (r6 >>> 16)|0;
w = ((imul(al4, bh2)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah4, bh2)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r6 = (w << 16) | (u & 0xffff);
u = ((imul(al4, bl3)|0) + (m & 0xffff)|0) + (r7 & 0xffff)|0;
v = ((imul(ah4, bl3)|0) + (m >>> 16)|0) + (r7 >>> 16)|0;
w = ((imul(al4, bh3)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah4, bh3)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r7 = (w << 16) | (u & 0xffff);
u = ((imul(al4, bl4)|0) + (m & 0xffff)|0) + (r8 & 0xffff)|0;
v = ((imul(ah4, bl4)|0) + (m >>> 16)|0) + (r8 >>> 16)|0;
w = ((imul(al4, bh4)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah4, bh4)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r8 = (w << 16) | (u & 0xffff);
u = ((imul(al4, bl5)|0) + (m & 0xffff)|0) + (r9 & 0xffff)|0;
v = ((imul(ah4, bl5)|0) + (m >>> 16)|0) + (r9 >>> 16)|0;
w = ((imul(al4, bh5)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah4, bh5)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r9 = (w << 16) | (u & 0xffff);
u = ((imul(al4, bl6)|0) + (m & 0xffff)|0) + (r10 & 0xffff)|0;
v = ((imul(ah4, bl6)|0) + (m >>> 16)|0) + (r10 >>> 16)|0;
w = ((imul(al4, bh6)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah4, bh6)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r10 = (w << 16) | (u & 0xffff);
u = ((imul(al4, bl7)|0) + (m & 0xffff)|0) + (r11 & 0xffff)|0;
v = ((imul(ah4, bl7)|0) + (m >>> 16)|0) + (r11 >>> 16)|0;
w = ((imul(al4, bh7)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah4, bh7)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r11 = (w << 16) | (u & 0xffff);
r12 = m;
u = ((imul(al5, bl0)|0) + (r13 & 0xffff)|0) + (r5 & 0xffff)|0;
v = ((imul(ah5, bl0)|0) + (r13 >>> 16)|0) + (r5 >>> 16)|0;
w = ((imul(al5, bh0)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah5, bh0)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r5 = (w << 16) | (u & 0xffff);
u = ((imul(al5, bl1)|0) + (m & 0xffff)|0) + (r6 & 0xffff)|0;
v = ((imul(ah5, bl1)|0) + (m >>> 16)|0) + (r6 >>> 16)|0;
w = ((imul(al5, bh1)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah5, bh1)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r6 = (w << 16) | (u & 0xffff);
u = ((imul(al5, bl2)|0) + (m & 0xffff)|0) + (r7 & 0xffff)|0;
v = ((imul(ah5, bl2)|0) + (m >>> 16)|0) + (r7 >>> 16)|0;
w = ((imul(al5, bh2)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah5, bh2)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r7 = (w << 16) | (u & 0xffff);
u = ((imul(al5, bl3)|0) + (m & 0xffff)|0) + (r8 & 0xffff)|0;
v = ((imul(ah5, bl3)|0) + (m >>> 16)|0) + (r8 >>> 16)|0;
w = ((imul(al5, bh3)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah5, bh3)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r8 = (w << 16) | (u & 0xffff);
u = ((imul(al5, bl4)|0) + (m & 0xffff)|0) + (r9 & 0xffff)|0;
v = ((imul(ah5, bl4)|0) + (m >>> 16)|0) + (r9 >>> 16)|0;
w = ((imul(al5, bh4)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah5, bh4)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r9 = (w << 16) | (u & 0xffff);
u = ((imul(al5, bl5)|0) + (m & 0xffff)|0) + (r10 & 0xffff)|0;
v = ((imul(ah5, bl5)|0) + (m >>> 16)|0) + (r10 >>> 16)|0;
w = ((imul(al5, bh5)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah5, bh5)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r10 = (w << 16) | (u & 0xffff);
u = ((imul(al5, bl6)|0) + (m & 0xffff)|0) + (r11 & 0xffff)|0;
v = ((imul(ah5, bl6)|0) + (m >>> 16)|0) + (r11 >>> 16)|0;
w = ((imul(al5, bh6)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah5, bh6)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r11 = (w << 16) | (u & 0xffff);
u = ((imul(al5, bl7)|0) + (m & 0xffff)|0) + (r12 & 0xffff)|0;
v = ((imul(ah5, bl7)|0) + (m >>> 16)|0) + (r12 >>> 16)|0;
w = ((imul(al5, bh7)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah5, bh7)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r12 = (w << 16) | (u & 0xffff);
r13 = m;
u = ((imul(al6, bl0)|0) + (r14 & 0xffff)|0) + (r6 & 0xffff)|0;
v = ((imul(ah6, bl0)|0) + (r14 >>> 16)|0) + (r6 >>> 16)|0;
w = ((imul(al6, bh0)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah6, bh0)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r6 = (w << 16) | (u & 0xffff);
u = ((imul(al6, bl1)|0) + (m & 0xffff)|0) + (r7 & 0xffff)|0;
v = ((imul(ah6, bl1)|0) + (m >>> 16)|0) + (r7 >>> 16)|0;
w = ((imul(al6, bh1)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah6, bh1)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r7 = (w << 16) | (u & 0xffff);
u = ((imul(al6, bl2)|0) + (m & 0xffff)|0) + (r8 & 0xffff)|0;
v = ((imul(ah6, bl2)|0) + (m >>> 16)|0) + (r8 >>> 16)|0;
w = ((imul(al6, bh2)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah6, bh2)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r8 = (w << 16) | (u & 0xffff);
u = ((imul(al6, bl3)|0) + (m & 0xffff)|0) + (r9 & 0xffff)|0;
v = ((imul(ah6, bl3)|0) + (m >>> 16)|0) + (r9 >>> 16)|0;
w = ((imul(al6, bh3)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah6, bh3)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r9 = (w << 16) | (u & 0xffff);
u = ((imul(al6, bl4)|0) + (m & 0xffff)|0) + (r10 & 0xffff)|0;
v = ((imul(ah6, bl4)|0) + (m >>> 16)|0) + (r10 >>> 16)|0;
w = ((imul(al6, bh4)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah6, bh4)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r10 = (w << 16) | (u & 0xffff);
u = ((imul(al6, bl5)|0) + (m & 0xffff)|0) + (r11 & 0xffff)|0;
v = ((imul(ah6, bl5)|0) + (m >>> 16)|0) + (r11 >>> 16)|0;
w = ((imul(al6, bh5)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah6, bh5)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r11 = (w << 16) | (u & 0xffff);
u = ((imul(al6, bl6)|0) + (m & 0xffff)|0) + (r12 & 0xffff)|0;
v = ((imul(ah6, bl6)|0) + (m >>> 16)|0) + (r12 >>> 16)|0;
w = ((imul(al6, bh6)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah6, bh6)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r12 = (w << 16) | (u & 0xffff);
u = ((imul(al6, bl7)|0) + (m & 0xffff)|0) + (r13 & 0xffff)|0;
v = ((imul(ah6, bl7)|0) + (m >>> 16)|0) + (r13 >>> 16)|0;
w = ((imul(al6, bh7)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah6, bh7)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r13 = (w << 16) | (u & 0xffff);
r14 = m;
u = ((imul(al7, bl0)|0) + (r15 & 0xffff)|0) + (r7 & 0xffff)|0;
v = ((imul(ah7, bl0)|0) + (r15 >>> 16)|0) + (r7 >>> 16)|0;
w = ((imul(al7, bh0)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah7, bh0)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r7 = (w << 16) | (u & 0xffff);
u = ((imul(al7, bl1)|0) + (m & 0xffff)|0) + (r8 & 0xffff)|0;
v = ((imul(ah7, bl1)|0) + (m >>> 16)|0) + (r8 >>> 16)|0;
w = ((imul(al7, bh1)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah7, bh1)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r8 = (w << 16) | (u & 0xffff);
u = ((imul(al7, bl2)|0) + (m & 0xffff)|0) + (r9 & 0xffff)|0;
v = ((imul(ah7, bl2)|0) + (m >>> 16)|0) + (r9 >>> 16)|0;
w = ((imul(al7, bh2)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah7, bh2)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r9 = (w << 16) | (u & 0xffff);
u = ((imul(al7, bl3)|0) + (m & 0xffff)|0) + (r10 & 0xffff)|0;
v = ((imul(ah7, bl3)|0) + (m >>> 16)|0) + (r10 >>> 16)|0;
w = ((imul(al7, bh3)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah7, bh3)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r10 = (w << 16) | (u & 0xffff);
u = ((imul(al7, bl4)|0) + (m & 0xffff)|0) + (r11 & 0xffff)|0;
v = ((imul(ah7, bl4)|0) + (m >>> 16)|0) + (r11 >>> 16)|0;
w = ((imul(al7, bh4)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah7, bh4)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r11 = (w << 16) | (u & 0xffff);
u = ((imul(al7, bl5)|0) + (m & 0xffff)|0) + (r12 & 0xffff)|0;
v = ((imul(ah7, bl5)|0) + (m >>> 16)|0) + (r12 >>> 16)|0;
w = ((imul(al7, bh5)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah7, bh5)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r12 = (w << 16) | (u & 0xffff);
u = ((imul(al7, bl6)|0) + (m & 0xffff)|0) + (r13 & 0xffff)|0;
v = ((imul(ah7, bl6)|0) + (m >>> 16)|0) + (r13 >>> 16)|0;
w = ((imul(al7, bh6)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah7, bh6)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r13 = (w << 16) | (u & 0xffff);
u = ((imul(al7, bl7)|0) + (m & 0xffff)|0) + (r14 & 0xffff)|0;
v = ((imul(ah7, bl7)|0) + (m >>> 16)|0) + (r14 >>> 16)|0;
w = ((imul(al7, bh7)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah7, bh7)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r14 = (w << 16) | (u & 0xffff);
r15 = m;
HEAP32[(Rk|0)>>2] = r0,
HEAP32[(Rk|4)>>2] = r1,
HEAP32[(Rk|8)>>2] = r2,
HEAP32[(Rk|12)>>2] = r3,
HEAP32[(Rk|16)>>2] = r4,
HEAP32[(Rk|20)>>2] = r5,
HEAP32[(Rk|24)>>2] = r6,
HEAP32[(Rk|28)>>2] = r7;
}
Rk = (R+(i+j|0))|0;
HEAP32[(Rk|0)>>2] = r8,
HEAP32[(Rk|4)>>2] = r9,
HEAP32[(Rk|8)>>2] = r10,
HEAP32[(Rk|12)>>2] = r11,
HEAP32[(Rk|16)>>2] = r12,
HEAP32[(Rk|20)>>2] = r13,
HEAP32[(Rk|24)>>2] = r14,
HEAP32[(Rk|28)>>2] = r15;
}
/*
for ( i = lA & -32; (i|0) < (lA|0); i = (i+4)|0 ) {
Ai = (A+i)|0;
ah0 = HEAP32[Ai>>2]|0,
al0 = ah0 & 0xffff,
ah0 = ah0 >>> 16;
r1 = 0;
for ( j = 0; (j|0) < (lB|0); j = (j+4)|0 ) {
Bj = (B+j)|0;
Rk = (R+(i+j|0))|0;
bh0 = HEAP32[Bj>>2]|0,
bl0 = bh0 & 0xffff,
bh0 = bh0 >>> 16;
r0 = HEAP32[Rk>>2]|0;
u = ((imul(al0, bl0)|0) + (r1 & 0xffff)|0) + (r0 & 0xffff)|0;
v = ((imul(ah0, bl0)|0) + (r1 >>> 16)|0) + (r0 >>> 16)|0;
w = ((imul(al0, bh0)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah0, bh0)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r0 = (w << 16) | (u & 0xffff);
r1 = m;
HEAP32[Rk>>2] = r0;
}
Rk = (R+(i+j|0))|0;
HEAP32[Rk>>2] = r1;
}
*/
}
/**
* Fast squaring
*
* Exploits the fact:
*
* X² = ( X0 + X1*B )² = X0² + 2*X0*X1*B + X1²*B²,
*
* where B is a power of 2, so:
*
* 2*X0*X1*B = (X0*X1 << 1)*B
*
* @param A offset of the argument being squared, 32-byte aligned
* @param lA length of the argument, multiple of 32
*
* @param R offset where to place the result to, 32-byte aligned
*/
function sqr ( A, lA, R ) {
A = A|0;
lA = lA|0;
R = R|0;
var al0 = 0, al1 = 0, al2 = 0, al3 = 0, al4 = 0, al5 = 0, al6 = 0, al7 = 0, ah0 = 0, ah1 = 0, ah2 = 0, ah3 = 0, ah4 = 0, ah5 = 0, ah6 = 0, ah7 = 0,
bl0 = 0, bl1 = 0, bl2 = 0, bl3 = 0, bl4 = 0, bl5 = 0, bl6 = 0, bl7 = 0, bh0 = 0, bh1 = 0, bh2 = 0, bh3 = 0, bh4 = 0, bh5 = 0, bh6 = 0, bh7 = 0,
r0 = 0, r1 = 0, r2 = 0, r3 = 0, r4 = 0, r5 = 0, r6 = 0, r7 = 0, r8 = 0, r9 = 0, r10 = 0, r11 = 0, r12 = 0, r13 = 0, r14 = 0, r15 = 0,
u = 0, v = 0, w = 0, c = 0, h = 0, m = 0, r = 0,
d = 0, dd = 0, p = 0, i = 0, j = 0, k = 0, Ai = 0, Aj = 0, Rk = 0;
// prepare for iterations
for ( ; (i|0) < (lA|0); i = (i+4)|0 ) {
Rk = R+(i<<1)|0;
ah0 = HEAP32[(A+i)>>2]|0, al0 = ah0 & 0xffff, ah0 = ah0 >>> 16;
u = imul(al0,al0)|0;
v = (imul(al0,ah0)|0) + (u >>> 17)|0;
w = (imul(ah0,ah0)|0) + (v >>> 15)|0;
HEAP32[(Rk)>>2] = (v << 17) | (u & 0x1ffff);
HEAP32[(Rk|4)>>2] = w;
}
// unrolled 1st iteration
for ( p = 0; (p|0) < (lA|0); p = (p+8)|0 ) {
Ai = A+p|0, Rk = R+(p<<1)|0;
ah0 = HEAP32[(Ai)>>2]|0, al0 = ah0 & 0xffff, ah0 = ah0 >>> 16;
bh0 = HEAP32[(Ai|4)>>2]|0, bl0 = bh0 & 0xffff, bh0 = bh0 >>> 16;
u = imul(al0,bl0)|0;
v = (imul(al0,bh0)|0) + (u >>> 16)|0;
w = (imul(ah0,bl0)|0) + (v & 0xffff)|0;
m = ((imul(ah0,bh0)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r = HEAP32[(Rk|4)>>2]|0;
u = (r & 0xffff) + ((u & 0xffff) << 1)|0;
w = ((r >>> 16) + ((w & 0xffff) << 1)|0) + (u >>> 16)|0;
HEAP32[(Rk|4)>>2] = (w << 16) | (u & 0xffff);
c = w >>> 16;
r = HEAP32[(Rk|8)>>2]|0;
u = ((r & 0xffff) + ((m & 0xffff) << 1)|0) + c|0;
w = ((r >>> 16) + ((m >>> 16) << 1)|0) + (u >>> 16)|0;
HEAP32[(Rk|8)>>2] = (w << 16) | (u & 0xffff);
c = w >>> 16;
if ( c ) {
r = HEAP32[(Rk|12)>>2]|0;
u = (r & 0xffff) + c|0;
w = (r >>> 16) + (u >>> 16)|0;
HEAP32[(Rk|12)>>2] = (w << 16) | (u & 0xffff);
}
}
// unrolled 2nd iteration
for ( p = 0; (p|0) < (lA|0); p = (p+16)|0 ) {
Ai = A+p|0, Rk = R+(p<<1)|0;
ah0 = HEAP32[(Ai)>>2]|0, al0 = ah0 & 0xffff, ah0 = ah0 >>> 16,
ah1 = HEAP32[(Ai|4)>>2]|0, al1 = ah1 & 0xffff, ah1 = ah1 >>> 16;
bh0 = HEAP32[(Ai|8)>>2]|0, bl0 = bh0 & 0xffff, bh0 = bh0 >>> 16,
bh1 = HEAP32[(Ai|12)>>2]|0, bl1 = bh1 & 0xffff, bh1 = bh1 >>> 16;
u = imul(al0, bl0)|0;
v = imul(ah0, bl0)|0;
w = ((imul(al0, bh0)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah0, bh0)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r0 = (w << 16) | (u & 0xffff);
u = (imul(al0, bl1)|0) + (m & 0xffff)|0;
v = (imul(ah0, bl1)|0) + (m >>> 16)|0;
w = ((imul(al0, bh1)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah0, bh1)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r1 = (w << 16) | (u & 0xffff);
r2 = m;
u = (imul(al1, bl0)|0) + (r1 & 0xffff)|0;
v = (imul(ah1, bl0)|0) + (r1 >>> 16)|0;
w = ((imul(al1, bh0)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah1, bh0)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r1 = (w << 16) | (u & 0xffff);
u = ((imul(al1, bl1)|0) + (r2 & 0xffff)|0) + (m & 0xffff)|0;
v = ((imul(ah1, bl1)|0) + (r2 >>> 16)|0) + (m >>> 16)|0;
w = ((imul(al1, bh1)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah1, bh1)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r2 = (w << 16) | (u & 0xffff);
r3 = m;
r = HEAP32[(Rk|8)>>2]|0;
u = (r & 0xffff) + ((r0 & 0xffff) << 1)|0;
w = ((r >>> 16) + ((r0 >>> 16) << 1)|0) + (u >>> 16)|0;
HEAP32[(Rk|8)>>2] = (w << 16) | (u & 0xffff);
c = w >>> 16;
r = HEAP32[(Rk|12)>>2]|0;
u = ((r & 0xffff) + ((r1 & 0xffff) << 1)|0) + c|0;
w = ((r >>> 16) + ((r1 >>> 16) << 1)|0) + (u >>> 16)|0;
HEAP32[(Rk|12)>>2] = (w << 16) | (u & 0xffff);
c = w >>> 16;
r = HEAP32[(Rk|16)>>2]|0;
u = ((r & 0xffff) + ((r2 & 0xffff) << 1)|0) + c|0;
w = ((r >>> 16) + ((r2 >>> 16) << 1)|0) + (u >>> 16)|0;
HEAP32[(Rk|16)>>2] = (w << 16) | (u & 0xffff);
c = w >>> 16;
r = HEAP32[(Rk|20)>>2]|0;
u = ((r & 0xffff) + ((r3 & 0xffff) << 1)|0) + c|0;
w = ((r >>> 16) + ((r3 >>> 16) << 1)|0) + (u >>> 16)|0;
HEAP32[(Rk|20)>>2] = (w << 16) | (u & 0xffff);
c = w >>> 16;
for ( k = 24; !!c & ( (k|0) < 32 ); k = (k+4)|0 ) {
r = HEAP32[(Rk|k)>>2]|0;
u = (r & 0xffff) + c|0;
w = (r >>> 16) + (u >>> 16)|0;
HEAP32[(Rk|k)>>2] = (w << 16) | (u & 0xffff);
c = w >>> 16;
}
}
// unrolled 3rd iteration
for ( p = 0; (p|0) < (lA|0); p = (p+32)|0 ) {
Ai = A+p|0, Rk = R+(p<<1)|0;
ah0 = HEAP32[(Ai)>>2]|0, al0 = ah0 & 0xffff, ah0 = ah0 >>> 16,
ah1 = HEAP32[(Ai|4)>>2]|0, al1 = ah1 & 0xffff, ah1 = ah1 >>> 16,
ah2 = HEAP32[(Ai|8)>>2]|0, al2 = ah2 & 0xffff, ah2 = ah2 >>> 16,
ah3 = HEAP32[(Ai|12)>>2]|0, al3 = ah3 & 0xffff, ah3 = ah3 >>> 16;
bh0 = HEAP32[(Ai|16)>>2]|0, bl0 = bh0 & 0xffff, bh0 = bh0 >>> 16,
bh1 = HEAP32[(Ai|20)>>2]|0, bl1 = bh1 & 0xffff, bh1 = bh1 >>> 16,
bh2 = HEAP32[(Ai|24)>>2]|0, bl2 = bh2 & 0xffff, bh2 = bh2 >>> 16,
bh3 = HEAP32[(Ai|28)>>2]|0, bl3 = bh3 & 0xffff, bh3 = bh3 >>> 16;
u = imul(al0, bl0)|0;
v = imul(ah0, bl0)|0;
w = ((imul(al0, bh0)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah0, bh0)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r0 = (w << 16) | (u & 0xffff);
u = (imul(al0, bl1)|0) + (m & 0xffff)|0;
v = (imul(ah0, bl1)|0) + (m >>> 16)|0;
w = ((imul(al0, bh1)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah0, bh1)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r1 = (w << 16) | (u & 0xffff);
u = (imul(al0, bl2)|0) + (m & 0xffff)|0;
v = (imul(ah0, bl2)|0) + (m >>> 16)|0;
w = ((imul(al0, bh2)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah0, bh2)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r2 = (w << 16) | (u & 0xffff);
u = (imul(al0, bl3)|0) + (m & 0xffff)|0;
v = (imul(ah0, bl3)|0) + (m >>> 16)|0;
w = ((imul(al0, bh3)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah0, bh3)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r3 = (w << 16) | (u & 0xffff);
r4 = m;
u = (imul(al1, bl0)|0) + (r1 & 0xffff)|0;
v = (imul(ah1, bl0)|0) + (r1 >>> 16)|0;
w = ((imul(al1, bh0)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah1, bh0)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r1 = (w << 16) | (u & 0xffff);
u = ((imul(al1, bl1)|0) + (r2 & 0xffff)|0) + (m & 0xffff)|0;
v = ((imul(ah1, bl1)|0) + (r2 >>> 16)|0) + (m >>> 16)|0;
w = ((imul(al1, bh1)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah1, bh1)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r2 = (w << 16) | (u & 0xffff);
u = ((imul(al1, bl2)|0) + (r3 & 0xffff)|0) + (m & 0xffff)|0;
v = ((imul(ah1, bl2)|0) + (r3 >>> 16)|0) + (m >>> 16)|0;
w = ((imul(al1, bh2)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah1, bh2)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r3 = (w << 16) | (u & 0xffff);
u = ((imul(al1, bl3)|0) + (r4 & 0xffff)|0) + (m & 0xffff)|0;
v = ((imul(ah1, bl3)|0) + (r4 >>> 16)|0) + (m >>> 16)|0;
w = ((imul(al1, bh3)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah1, bh3)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r4 = (w << 16) | (u & 0xffff);
r5 = m;
u = (imul(al2, bl0)|0) + (r2 & 0xffff)|0;
v = (imul(ah2, bl0)|0) + (r2 >>> 16)|0;
w = ((imul(al2, bh0)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah2, bh0)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r2 = (w << 16) | (u & 0xffff);
u = ((imul(al2, bl1)|0) + (r3 & 0xffff)|0) + (m & 0xffff)|0;
v = ((imul(ah2, bl1)|0) + (r3 >>> 16)|0) + (m >>> 16)|0;
w = ((imul(al2, bh1)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah2, bh1)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r3 = (w << 16) | (u & 0xffff);
u = ((imul(al2, bl2)|0) + (r4 & 0xffff)|0) + (m & 0xffff)|0;
v = ((imul(ah2, bl2)|0) + (r4 >>> 16)|0) + (m >>> 16)|0;
w = ((imul(al2, bh2)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah2, bh2)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r4 = (w << 16) | (u & 0xffff);
u = ((imul(al2, bl3)|0) + (r5 & 0xffff)|0) + (m & 0xffff)|0;
v = ((imul(ah2, bl3)|0) + (r5 >>> 16)|0) + (m >>> 16)|0;
w = ((imul(al2, bh3)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah2, bh3)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r5 = (w << 16) | (u & 0xffff);
r6 = m;
u = (imul(al3, bl0)|0) + (r3 & 0xffff)|0;
v = (imul(ah3, bl0)|0) + (r3 >>> 16)|0;
w = ((imul(al3, bh0)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah3, bh0)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r3 = (w << 16) | (u & 0xffff);
u = ((imul(al3, bl1)|0) + (r4 & 0xffff)|0) + (m & 0xffff)|0;
v = ((imul(ah3, bl1)|0) + (r4 >>> 16)|0) + (m >>> 16)|0;
w = ((imul(al3, bh1)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah3, bh1)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r4 = (w << 16) | (u & 0xffff);
u = ((imul(al3, bl2)|0) + (r5 & 0xffff)|0) + (m & 0xffff)|0;
v = ((imul(ah3, bl2)|0) + (r5 >>> 16)|0) + (m >>> 16)|0;
w = ((imul(al3, bh2)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah3, bh2)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r5 = (w << 16) | (u & 0xffff);
u = ((imul(al3, bl3)|0) + (r6 & 0xffff)|0) + (m & 0xffff)|0;
v = ((imul(ah3, bl3)|0) + (r6 >>> 16)|0) + (m >>> 16)|0;
w = ((imul(al3, bh3)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah3, bh3)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r6 = (w << 16) | (u & 0xffff);
r7 = m;
r = HEAP32[(Rk|16)>>2]|0;
u = (r & 0xffff) + ((r0 & 0xffff) << 1)|0;
w = ((r >>> 16) + ((r0 >>> 16) << 1)|0) + (u >>> 16)|0;
HEAP32[(Rk|16)>>2] = (w << 16) | (u & 0xffff);
c = w >>> 16;
r = HEAP32[(Rk|20)>>2]|0;
u = ((r & 0xffff) + ((r1 & 0xffff) << 1)|0) + c|0;
w = ((r >>> 16) + ((r1 >>> 16) << 1)|0) + (u >>> 16)|0;
HEAP32[(Rk|20)>>2] = (w << 16) | (u & 0xffff);
c = w >>> 16;
r = HEAP32[(Rk|24)>>2]|0;
u = ((r & 0xffff) + ((r2 & 0xffff) << 1)|0) + c|0;
w = ((r >>> 16) + ((r2 >>> 16) << 1)|0) + (u >>> 16)|0;
HEAP32[(Rk|24)>>2] = (w << 16) | (u & 0xffff);
c = w >>> 16;
r = HEAP32[(Rk|28)>>2]|0;
u = ((r & 0xffff) + ((r3 & 0xffff) << 1)|0) + c|0;
w = ((r >>> 16) + ((r3 >>> 16) << 1)|0) + (u >>> 16)|0;
HEAP32[(Rk|28)>>2] = (w << 16) | (u & 0xffff);
c = w >>> 16;
r = HEAP32[(Rk+32)>>2]|0;
u = ((r & 0xffff) + ((r4 & 0xffff) << 1)|0) + c|0;
w = ((r >>> 16) + ((r4 >>> 16) << 1)|0) + (u >>> 16)|0;
HEAP32[(Rk+32)>>2] = (w << 16) | (u & 0xffff);
c = w >>> 16;
r = HEAP32[(Rk+36)>>2]|0;
u = ((r & 0xffff) + ((r5 & 0xffff) << 1)|0) + c|0;
w = ((r >>> 16) + ((r5 >>> 16) << 1)|0) + (u >>> 16)|0;
HEAP32[(Rk+36)>>2] = (w << 16) | (u & 0xffff);
c = w >>> 16;
r = HEAP32[(Rk+40)>>2]|0;
u = ((r & 0xffff) + ((r6 & 0xffff) << 1)|0) + c|0;
w = ((r >>> 16) + ((r6 >>> 16) << 1)|0) + (u >>> 16)|0;
HEAP32[(Rk+40)>>2] = (w << 16) | (u & 0xffff);
c = w >>> 16;
r = HEAP32[(Rk+44)>>2]|0;
u = ((r & 0xffff) + ((r7 & 0xffff) << 1)|0) + c|0;
w = ((r >>> 16) + ((r7 >>> 16) << 1)|0) + (u >>> 16)|0;
HEAP32[(Rk+44)>>2] = (w << 16) | (u & 0xffff);
c = w >>> 16;
for ( k = 48; !!c & ( (k|0) < 64 ); k = (k+4)|0 ) {
r = HEAP32[(Rk+k)>>2]|0;
u = (r & 0xffff) + c|0;
w = (r >>> 16) + (u >>> 16)|0;
HEAP32[(Rk+k)>>2] = (w << 16) | (u & 0xffff);
c = w >>> 16;
}
}
// perform iterations
for ( d = 32; (d|0) < (lA|0); d = d << 1 ) { // depth loop
dd = d << 1;
for ( p = 0; (p|0) < (lA|0); p = (p+dd)|0 ) { // part loop
Rk = R+(p<<1)|0;
h = 0;
for ( i = 0; (i|0) < (d|0); i = (i+32)|0 ) { // multiply-and-add loop
Ai = (A+p|0)+i|0;
ah0 = HEAP32[(Ai)>>2]|0, al0 = ah0 & 0xffff, ah0 = ah0 >>> 16,
ah1 = HEAP32[(Ai|4)>>2]|0, al1 = ah1 & 0xffff, ah1 = ah1 >>> 16,
ah2 = HEAP32[(Ai|8)>>2]|0, al2 = ah2 & 0xffff, ah2 = ah2 >>> 16,
ah3 = HEAP32[(Ai|12)>>2]|0, al3 = ah3 & 0xffff, ah3 = ah3 >>> 16,
ah4 = HEAP32[(Ai|16)>>2]|0, al4 = ah4 & 0xffff, ah4 = ah4 >>> 16,
ah5 = HEAP32[(Ai|20)>>2]|0, al5 = ah5 & 0xffff, ah5 = ah5 >>> 16,
ah6 = HEAP32[(Ai|24)>>2]|0, al6 = ah6 & 0xffff, ah6 = ah6 >>> 16,
ah7 = HEAP32[(Ai|28)>>2]|0, al7 = ah7 & 0xffff, ah7 = ah7 >>> 16;
r8 = r9 = r10 = r11 = r12 = r13 = r14 = r15 = c = 0;
for ( j = 0; (j|0) < (d|0); j = (j+32)|0 ) {
Aj = ((A+p|0)+d|0)+j|0;
bh0 = HEAP32[(Aj)>>2]|0, bl0 = bh0 & 0xffff, bh0 = bh0 >>> 16,
bh1 = HEAP32[(Aj|4)>>2]|0, bl1 = bh1 & 0xffff, bh1 = bh1 >>> 16,
bh2 = HEAP32[(Aj|8)>>2]|0, bl2 = bh2 & 0xffff, bh2 = bh2 >>> 16,
bh3 = HEAP32[(Aj|12)>>2]|0, bl3 = bh3 & 0xffff, bh3 = bh3 >>> 16,
bh4 = HEAP32[(Aj|16)>>2]|0, bl4 = bh4 & 0xffff, bh4 = bh4 >>> 16,
bh5 = HEAP32[(Aj|20)>>2]|0, bl5 = bh5 & 0xffff, bh5 = bh5 >>> 16,
bh6 = HEAP32[(Aj|24)>>2]|0, bl6 = bh6 & 0xffff, bh6 = bh6 >>> 16,
bh7 = HEAP32[(Aj|28)>>2]|0, bl7 = bh7 & 0xffff, bh7 = bh7 >>> 16;
r0 = r1 = r2 = r3 = r4 = r5 = r6 = r7 = 0;
u = ((imul(al0, bl0)|0) + (r0 & 0xffff)|0) + (r8 & 0xffff)|0;
v = ((imul(ah0, bl0)|0) + (r0 >>> 16)|0) + (r8 >>> 16)|0;
w = ((imul(al0, bh0)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah0, bh0)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r0 = (w << 16) | (u & 0xffff);
u = ((imul(al0, bl1)|0) + (r1 & 0xffff)|0) + (m & 0xffff)|0;
v = ((imul(ah0, bl1)|0) + (r1 >>> 16)|0) + (m >>> 16)|0;
w = ((imul(al0, bh1)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah0, bh1)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r1 = (w << 16) | (u & 0xffff);
u = ((imul(al0, bl2)|0) + (r2 & 0xffff)|0) + (m & 0xffff)|0;
v = ((imul(ah0, bl2)|0) + (r2 >>> 16)|0) + (m >>> 16)|0;
w = ((imul(al0, bh2)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah0, bh2)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r2 = (w << 16) | (u & 0xffff);
u = ((imul(al0, bl3)|0) + (r3 & 0xffff)|0) + (m & 0xffff)|0;
v = ((imul(ah0, bl3)|0) + (r3 >>> 16)|0) + (m >>> 16)|0;
w = ((imul(al0, bh3)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah0, bh3)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r3 = (w << 16) | (u & 0xffff);
u = ((imul(al0, bl4)|0) + (r4 & 0xffff)|0) + (m & 0xffff)|0;
v = ((imul(ah0, bl4)|0) + (r4 >>> 16)|0) + (m >>> 16)|0;
w = ((imul(al0, bh4)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah0, bh4)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r4 = (w << 16) | (u & 0xffff);
u = ((imul(al0, bl5)|0) + (r5 & 0xffff)|0) + (m & 0xffff)|0;
v = ((imul(ah0, bl5)|0) + (r5 >>> 16)|0) + (m >>> 16)|0;
w = ((imul(al0, bh5)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah0, bh5)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r5 = (w << 16) | (u & 0xffff);
u = ((imul(al0, bl6)|0) + (r6 & 0xffff)|0) + (m & 0xffff)|0;
v = ((imul(ah0, bl6)|0) + (r6 >>> 16)|0) + (m >>> 16)|0;
w = ((imul(al0, bh6)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah0, bh6)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r6 = (w << 16) | (u & 0xffff);
u = ((imul(al0, bl7)|0) + (r7 & 0xffff)|0) + (m & 0xffff)|0;
v = ((imul(ah0, bl7)|0) + (r7 >>> 16)|0) + (m >>> 16)|0;
w = ((imul(al0, bh7)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah0, bh7)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r7 = (w << 16) | (u & 0xffff);
r8 = m;
u = ((imul(al1, bl0)|0) + (r1 & 0xffff)|0) + (r9 & 0xffff)|0;
v = ((imul(ah1, bl0)|0) + (r1 >>> 16)|0) + (r9 >>> 16)|0;
w = ((imul(al1, bh0)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah1, bh0)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r1 = (w << 16) | (u & 0xffff);
u = ((imul(al1, bl1)|0) + (r2 & 0xffff)|0) + (m & 0xffff)|0;
v = ((imul(ah1, bl1)|0) + (r2 >>> 16)|0) + (m >>> 16)|0;
w = ((imul(al1, bh1)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah1, bh1)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r2 = (w << 16) | (u & 0xffff);
u = ((imul(al1, bl2)|0) + (r3 & 0xffff)|0) + (m & 0xffff)|0;
v = ((imul(ah1, bl2)|0) + (r3 >>> 16)|0) + (m >>> 16)|0;
w = ((imul(al1, bh2)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah1, bh2)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r3 = (w << 16) | (u & 0xffff);
u = ((imul(al1, bl3)|0) + (r4 & 0xffff)|0) + (m & 0xffff)|0;
v = ((imul(ah1, bl3)|0) + (r4 >>> 16)|0) + (m >>> 16)|0;
w = ((imul(al1, bh3)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah1, bh3)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r4 = (w << 16) | (u & 0xffff);
u = ((imul(al1, bl4)|0) + (r5 & 0xffff)|0) + (m & 0xffff)|0;
v = ((imul(ah1, bl4)|0) + (r5 >>> 16)|0) + (m >>> 16)|0;
w = ((imul(al1, bh4)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah1, bh4)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r5 = (w << 16) | (u & 0xffff);
u = ((imul(al1, bl5)|0) + (r6 & 0xffff)|0) + (m & 0xffff)|0;
v = ((imul(ah1, bl5)|0) + (r6 >>> 16)|0) + (m >>> 16)|0;
w = ((imul(al1, bh5)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah1, bh5)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r6 = (w << 16) | (u & 0xffff);
u = ((imul(al1, bl6)|0) + (r7 & 0xffff)|0) + (m & 0xffff)|0;
v = ((imul(ah1, bl6)|0) + (r7 >>> 16)|0) + (m >>> 16)|0;
w = ((imul(al1, bh6)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah1, bh6)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r7 = (w << 16) | (u & 0xffff);
u = ((imul(al1, bl7)|0) + (r8 & 0xffff)|0) + (m & 0xffff)|0;
v = ((imul(ah1, bl7)|0) + (r8 >>> 16)|0) + (m >>> 16)|0;
w = ((imul(al1, bh7)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah1, bh7)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r8 = (w << 16) | (u & 0xffff);
r9 = m;
u = ((imul(al2, bl0)|0) + (r2 & 0xffff)|0) + (r10 & 0xffff)|0;
v = ((imul(ah2, bl0)|0) + (r2 >>> 16)|0) + (r10 >>> 16)|0;
w = ((imul(al2, bh0)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah2, bh0)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r2 = (w << 16) | (u & 0xffff);
u = ((imul(al2, bl1)|0) + (r3 & 0xffff)|0) + (m & 0xffff)|0;
v = ((imul(ah2, bl1)|0) + (r3 >>> 16)|0) + (m >>> 16)|0;
w = ((imul(al2, bh1)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah2, bh1)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r3 = (w << 16) | (u & 0xffff);
u = ((imul(al2, bl2)|0) + (r4 & 0xffff)|0) + (m & 0xffff)|0;
v = ((imul(ah2, bl2)|0) + (r4 >>> 16)|0) + (m >>> 16)|0;
w = ((imul(al2, bh2)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah2, bh2)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r4 = (w << 16) | (u & 0xffff);
u = ((imul(al2, bl3)|0) + (r5 & 0xffff)|0) + (m & 0xffff)|0;
v = ((imul(ah2, bl3)|0) + (r5 >>> 16)|0) + (m >>> 16)|0;
w = ((imul(al2, bh3)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah2, bh3)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r5 = (w << 16) | (u & 0xffff);
u = ((imul(al2, bl4)|0) + (r6 & 0xffff)|0) + (m & 0xffff)|0;
v = ((imul(ah2, bl4)|0) + (r6 >>> 16)|0) + (m >>> 16)|0;
w = ((imul(al2, bh4)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah2, bh4)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r6 = (w << 16) | (u & 0xffff);
u = ((imul(al2, bl5)|0) + (r7 & 0xffff)|0) + (m & 0xffff)|0;
v = ((imul(ah2, bl5)|0) + (r7 >>> 16)|0) + (m >>> 16)|0;
w = ((imul(al2, bh5)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah2, bh5)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r7 = (w << 16) | (u & 0xffff);
u = ((imul(al2, bl6)|0) + (r8 & 0xffff)|0) + (m & 0xffff)|0;
v = ((imul(ah2, bl6)|0) + (r8 >>> 16)|0) + (m >>> 16)|0;
w = ((imul(al2, bh6)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah2, bh6)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r8 = (w << 16) | (u & 0xffff);
u = ((imul(al2, bl7)|0) + (r9 & 0xffff)|0) + (m & 0xffff)|0;
v = ((imul(ah2, bl7)|0) + (r9 >>> 16)|0) + (m >>> 16)|0;
w = ((imul(al2, bh7)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah2, bh7)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r9 = (w << 16) | (u & 0xffff);
r10 = m;
u = ((imul(al3, bl0)|0) + (r3 & 0xffff)|0) + (r11 & 0xffff)|0;
v = ((imul(ah3, bl0)|0) + (r3 >>> 16)|0) + (r11 >>> 16)|0;
w = ((imul(al3, bh0)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah3, bh0)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r3 = (w << 16) | (u & 0xffff);
u = ((imul(al3, bl1)|0) + (r4 & 0xffff)|0) + (m & 0xffff)|0;
v = ((imul(ah3, bl1)|0) + (r4 >>> 16)|0) + (m >>> 16)|0;
w = ((imul(al3, bh1)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah3, bh1)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r4 = (w << 16) | (u & 0xffff);
u = ((imul(al3, bl2)|0) + (r5 & 0xffff)|0) + (m & 0xffff)|0;
v = ((imul(ah3, bl2)|0) + (r5 >>> 16)|0) + (m >>> 16)|0;
w = ((imul(al3, bh2)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah3, bh2)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r5 = (w << 16) | (u & 0xffff);
u = ((imul(al3, bl3)|0) + (r6 & 0xffff)|0) + (m & 0xffff)|0;
v = ((imul(ah3, bl3)|0) + (r6 >>> 16)|0) + (m >>> 16)|0;
w = ((imul(al3, bh3)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah3, bh3)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r6 = (w << 16) | (u & 0xffff);
u = ((imul(al3, bl4)|0) + (r7 & 0xffff)|0) + (m & 0xffff)|0;
v = ((imul(ah3, bl4)|0) + (r7 >>> 16)|0) + (m >>> 16)|0;
w = ((imul(al3, bh4)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah3, bh4)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r7 = (w << 16) | (u & 0xffff);
u = ((imul(al3, bl5)|0) + (r8 & 0xffff)|0) + (m & 0xffff)|0;
v = ((imul(ah3, bl5)|0) + (r8 >>> 16)|0) + (m >>> 16)|0;
w = ((imul(al3, bh5)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah3, bh5)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r8 = (w << 16) | (u & 0xffff);
u = ((imul(al3, bl6)|0) + (r9 & 0xffff)|0) + (m & 0xffff)|0;
v = ((imul(ah3, bl6)|0) + (r9 >>> 16)|0) + (m >>> 16)|0;
w = ((imul(al3, bh6)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah3, bh6)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r9 = (w << 16) | (u & 0xffff);
u = ((imul(al3, bl7)|0) + (r10 & 0xffff)|0) + (m & 0xffff)|0;
v = ((imul(ah3, bl7)|0) + (r10 >>> 16)|0) + (m >>> 16)|0;
w = ((imul(al3, bh7)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah3, bh7)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r10 = (w << 16) | (u & 0xffff);
r11 = m;
u = ((imul(al4, bl0)|0) + (r4 & 0xffff)|0) + (r12 & 0xffff)|0;
v = ((imul(ah4, bl0)|0) + (r4 >>> 16)|0) + (r12 >>> 16)|0;
w = ((imul(al4, bh0)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah4, bh0)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r4 = (w << 16) | (u & 0xffff);
u = ((imul(al4, bl1)|0) + (r5 & 0xffff)|0) + (m & 0xffff)|0;
v = ((imul(ah4, bl1)|0) + (r5 >>> 16)|0) + (m >>> 16)|0;
w = ((imul(al4, bh1)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah4, bh1)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r5 = (w << 16) | (u & 0xffff);
u = ((imul(al4, bl2)|0) + (r6 & 0xffff)|0) + (m & 0xffff)|0;
v = ((imul(ah4, bl2)|0) + (r6 >>> 16)|0) + (m >>> 16)|0;
w = ((imul(al4, bh2)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah4, bh2)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r6 = (w << 16) | (u & 0xffff);
u = ((imul(al4, bl3)|0) + (r7 & 0xffff)|0) + (m & 0xffff)|0;
v = ((imul(ah4, bl3)|0) + (r7 >>> 16)|0) + (m >>> 16)|0;
w = ((imul(al4, bh3)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah4, bh3)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r7 = (w << 16) | (u & 0xffff);
u = ((imul(al4, bl4)|0) + (r8 & 0xffff)|0) + (m & 0xffff)|0;
v = ((imul(ah4, bl4)|0) + (r8 >>> 16)|0) + (m >>> 16)|0;
w = ((imul(al4, bh4)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah4, bh4)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r8 = (w << 16) | (u & 0xffff);
u = ((imul(al4, bl5)|0) + (r9 & 0xffff)|0) + (m & 0xffff)|0;
v = ((imul(ah4, bl5)|0) + (r9 >>> 16)|0) + (m >>> 16)|0;
w = ((imul(al4, bh5)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah4, bh5)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r9 = (w << 16) | (u & 0xffff);
u = ((imul(al4, bl6)|0) + (r10 & 0xffff)|0) + (m & 0xffff)|0;
v = ((imul(ah4, bl6)|0) + (r10 >>> 16)|0) + (m >>> 16)|0;
w = ((imul(al4, bh6)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah4, bh6)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r10 = (w << 16) | (u & 0xffff);
u = ((imul(al4, bl7)|0) + (r11 & 0xffff)|0) + (m & 0xffff)|0;
v = ((imul(ah4, bl7)|0) + (r11 >>> 16)|0) + (m >>> 16)|0;
w = ((imul(al4, bh7)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah4, bh7)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r11 = (w << 16) | (u & 0xffff);
r12 = m;
u = ((imul(al5, bl0)|0) + (r5 & 0xffff)|0) + (r13 & 0xffff)|0;
v = ((imul(ah5, bl0)|0) + (r5 >>> 16)|0) + (r13 >>> 16)|0;
w = ((imul(al5, bh0)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah5, bh0)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r5 = (w << 16) | (u & 0xffff);
u = ((imul(al5, bl1)|0) + (r6 & 0xffff)|0) + (m & 0xffff)|0;
v = ((imul(ah5, bl1)|0) + (r6 >>> 16)|0) + (m >>> 16)|0;
w = ((imul(al5, bh1)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah5, bh1)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r6 = (w << 16) | (u & 0xffff);
u = ((imul(al5, bl2)|0) + (r7 & 0xffff)|0) + (m & 0xffff)|0;
v = ((imul(ah5, bl2)|0) + (r7 >>> 16)|0) + (m >>> 16)|0;
w = ((imul(al5, bh2)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah5, bh2)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r7 = (w << 16) | (u & 0xffff);
u = ((imul(al5, bl3)|0) + (r8 & 0xffff)|0) + (m & 0xffff)|0;
v = ((imul(ah5, bl3)|0) + (r8 >>> 16)|0) + (m >>> 16)|0;
w = ((imul(al5, bh3)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah5, bh3)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r8 = (w << 16) | (u & 0xffff);
u = ((imul(al5, bl4)|0) + (r9 & 0xffff)|0) + (m & 0xffff)|0;
v = ((imul(ah5, bl4)|0) + (r9 >>> 16)|0) + (m >>> 16)|0;
w = ((imul(al5, bh4)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah5, bh4)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r9 = (w << 16) | (u & 0xffff);
u = ((imul(al5, bl5)|0) + (r10 & 0xffff)|0) + (m & 0xffff)|0;
v = ((imul(ah5, bl5)|0) + (r10 >>> 16)|0) + (m >>> 16)|0;
w = ((imul(al5, bh5)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah5, bh5)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r10 = (w << 16) | (u & 0xffff);
u = ((imul(al5, bl6)|0) + (r11 & 0xffff)|0) + (m & 0xffff)|0;
v = ((imul(ah5, bl6)|0) + (r11 >>> 16)|0) + (m >>> 16)|0;
w = ((imul(al5, bh6)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah5, bh6)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r11 = (w << 16) | (u & 0xffff);
u = ((imul(al5, bl7)|0) + (r12 & 0xffff)|0) + (m & 0xffff)|0;
v = ((imul(ah5, bl7)|0) + (r12 >>> 16)|0) + (m >>> 16)|0;
w = ((imul(al5, bh7)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah5, bh7)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r12 = (w << 16) | (u & 0xffff);
r13 = m;
u = ((imul(al6, bl0)|0) + (r6 & 0xffff)|0) + (r14 & 0xffff)|0;
v = ((imul(ah6, bl0)|0) + (r6 >>> 16)|0) + (r14 >>> 16)|0;
w = ((imul(al6, bh0)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah6, bh0)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r6 = (w << 16) | (u & 0xffff);
u = ((imul(al6, bl1)|0) + (r7 & 0xffff)|0) + (m & 0xffff)|0;
v = ((imul(ah6, bl1)|0) + (r7 >>> 16)|0) + (m >>> 16)|0;
w = ((imul(al6, bh1)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah6, bh1)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r7 = (w << 16) | (u & 0xffff);
u = ((imul(al6, bl2)|0) + (r8 & 0xffff)|0) + (m & 0xffff)|0;
v = ((imul(ah6, bl2)|0) + (r8 >>> 16)|0) + (m >>> 16)|0;
w = ((imul(al6, bh2)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah6, bh2)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r8 = (w << 16) | (u & 0xffff);
u = ((imul(al6, bl3)|0) + (r9 & 0xffff)|0) + (m & 0xffff)|0;
v = ((imul(ah6, bl3)|0) + (r9 >>> 16)|0) + (m >>> 16)|0;
w = ((imul(al6, bh3)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah6, bh3)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r9 = (w << 16) | (u & 0xffff);
u = ((imul(al6, bl4)|0) + (r10 & 0xffff)|0) + (m & 0xffff)|0;
v = ((imul(ah6, bl4)|0) + (r10 >>> 16)|0) + (m >>> 16)|0;
w = ((imul(al6, bh4)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah6, bh4)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r10 = (w << 16) | (u & 0xffff);
u = ((imul(al6, bl5)|0) + (r11 & 0xffff)|0) + (m & 0xffff)|0;
v = ((imul(ah6, bl5)|0) + (r11 >>> 16)|0) + (m >>> 16)|0;
w = ((imul(al6, bh5)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah6, bh5)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r11 = (w << 16) | (u & 0xffff);
u = ((imul(al6, bl6)|0) + (r12 & 0xffff)|0) + (m & 0xffff)|0;
v = ((imul(ah6, bl6)|0) + (r12 >>> 16)|0) + (m >>> 16)|0;
w = ((imul(al6, bh6)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah6, bh6)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r12 = (w << 16) | (u & 0xffff);
u = ((imul(al6, bl7)|0) + (r13 & 0xffff)|0) + (m & 0xffff)|0;
v = ((imul(ah6, bl7)|0) + (r13 >>> 16)|0) + (m >>> 16)|0;
w = ((imul(al6, bh7)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah6, bh7)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r13 = (w << 16) | (u & 0xffff);
r14 = m;
u = ((imul(al7, bl0)|0) + (r7 & 0xffff)|0) + (r15 & 0xffff)|0;
v = ((imul(ah7, bl0)|0) + (r7 >>> 16)|0) + (r15 >>> 16)|0;
w = ((imul(al7, bh0)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah7, bh0)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r7 = (w << 16) | (u & 0xffff);
u = ((imul(al7, bl1)|0) + (r8 & 0xffff)|0) + (m & 0xffff)|0;
v = ((imul(ah7, bl1)|0) + (r8 >>> 16)|0) + (m >>> 16)|0;
w = ((imul(al7, bh1)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah7, bh1)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r8 = (w << 16) | (u & 0xffff);
u = ((imul(al7, bl2)|0) + (r9 & 0xffff)|0) + (m & 0xffff)|0;
v = ((imul(ah7, bl2)|0) + (r9 >>> 16)|0) + (m >>> 16)|0;
w = ((imul(al7, bh2)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah7, bh2)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r9 = (w << 16) | (u & 0xffff);
u = ((imul(al7, bl3)|0) + (r10 & 0xffff)|0) + (m & 0xffff)|0;
v = ((imul(ah7, bl3)|0) + (r10 >>> 16)|0) + (m >>> 16)|0;
w = ((imul(al7, bh3)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah7, bh3)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r10 = (w << 16) | (u & 0xffff);
u = ((imul(al7, bl4)|0) + (r11 & 0xffff)|0) + (m & 0xffff)|0;
v = ((imul(ah7, bl4)|0) + (r11 >>> 16)|0) + (m >>> 16)|0;
w = ((imul(al7, bh4)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah7, bh4)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r11 = (w << 16) | (u & 0xffff);
u = ((imul(al7, bl5)|0) + (r12 & 0xffff)|0) + (m & 0xffff)|0;
v = ((imul(ah7, bl5)|0) + (r12 >>> 16)|0) + (m >>> 16)|0;
w = ((imul(al7, bh5)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah7, bh5)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r12 = (w << 16) | (u & 0xffff);
u = ((imul(al7, bl6)|0) + (r13 & 0xffff)|0) + (m & 0xffff)|0;
v = ((imul(ah7, bl6)|0) + (r13 >>> 16)|0) + (m >>> 16)|0;
w = ((imul(al7, bh6)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah7, bh6)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r13 = (w << 16) | (u & 0xffff);
u = ((imul(al7, bl7)|0) + (r14 & 0xffff)|0) + (m & 0xffff)|0;
v = ((imul(ah7, bl7)|0) + (r14 >>> 16)|0) + (m >>> 16)|0;
w = ((imul(al7, bh7)|0) + (v & 0xffff)|0) + (u >>> 16)|0;
m = ((imul(ah7, bh7)|0) + (v >>> 16)|0) + (w >>> 16)|0;
r14 = (w << 16) | (u & 0xffff);
r15 = m;
k = d+(i+j|0)|0;
r = HEAP32[(Rk+k)>>2]|0;
u = ((r & 0xffff) + ((r0 & 0xffff) << 1)|0) + c|0;
w = ((r >>> 16) + ((r0 >>> 16) << 1)|0) + (u >>> 16)|0;
HEAP32[(Rk+k)>>2] = (w << 16) | (u & 0xffff);
c = w >>> 16;
k = k+4|0;
r = HEAP32[(Rk+k)>>2]|0;
u = ((r & 0xffff) + ((r1 & 0xffff) << 1)|0) + c|0;
w = ((r >>> 16) + ((r1 >>> 16) << 1)|0) + (u >>> 16)|0;
HEAP32[(Rk+k)>>2] = (w << 16) | (u & 0xffff);
c = w >>> 16;
k = k+4|0;
r = HEAP32[(Rk+k)>>2]|0;
u = ((r & 0xffff) + ((r2 & 0xffff) << 1)|0) + c|0;
w = ((r >>> 16) + ((r2 >>> 16) << 1)|0) + (u >>> 16)|0;
HEAP32[(Rk+k)>>2] = (w << 16) | (u & 0xffff);
c = w >>> 16;
k = k+4|0;
r = HEAP32[(Rk+k)>>2]|0;
u = ((r & 0xffff) + ((r3 & 0xffff) << 1)|0) + c|0;
w = ((r >>> 16) + ((r3 >>> 16) << 1)|0) + (u >>> 16)|0;
HEAP32[(Rk+k)>>2] = (w << 16) | (u & 0xffff);
c = w >>> 16;
k = k+4|0;
r = HEAP32[(Rk+k)>>2]|0;
u = ((r & 0xffff) + ((r4 & 0xffff) << 1)|0) + c|0;
w = ((r >>> 16) + ((r4 >>> 16) << 1)|0) + (u >>> 16)|0;
HEAP32[(Rk+k)>>2] = (w << 16) | (u & 0xffff);
c = w >>> 16;
k = k+4|0;
r = HEAP32[(Rk+k)>>2]|0;
u = ((r & 0xffff) + ((r5 & 0xffff) << 1)|0) + c|0;
w = ((r >>> 16) + ((r5 >>> 16) << 1)|0) + (u >>> 16)|0;
HEAP32[(Rk+k)>>2] = (w << 16) | (u & 0xffff);
c = w >>> 16;
k = k+4|0;
r = HEAP32[(Rk+k)>>2]|0;
u = ((r & 0xffff) + ((r6 & 0xffff) << 1)|0) + c|0;
w = ((r >>> 16) + ((r6 >>> 16) << 1)|0) + (u >>> 16)|0;
HEAP32[(Rk+k)>>2] = (w << 16) | (u & 0xffff);
c = w >>> 16;
k = k+4|0;
r = HEAP32[(Rk+k)>>2]|0;
u = ((r & 0xffff) + ((r7 & 0xffff) << 1)|0) + c|0;
w = ((r >>> 16) + ((r7 >>> 16) << 1)|0) + (u >>> 16)|0;
HEAP32[(Rk+k)>>2] = (w << 16) | (u & 0xffff);
c = w >>> 16;
}
k = d+(i+j|0)|0;
r = HEAP32[(Rk+k)>>2]|0;
u = (((r & 0xffff) + ((r8 & 0xffff) << 1)|0) + c|0) + h|0;
w = ((r >>> 16) + ((r8 >>> 16) << 1)|0) + (u >>> 16)|0;
HEAP32[(Rk+k)>>2] = (w << 16) | (u & 0xffff);
c = w >>> 16;
k = k+4|0;
r = HEAP32[(Rk+k)>>2]|0;
u = ((r & 0xffff) + ((r9 & 0xffff) << 1)|0) + c|0;
w = ((r >>> 16) + ((r9 >>> 16) << 1)|0) + (u >>> 16)|0;
HEAP32[(Rk+k)>>2] = (w << 16) | (u & 0xffff);
c = w >>> 16;
k = k+4|0;
r = HEAP32[(Rk+k)>>2]|0;
u = ((r & 0xffff) + ((r10 & 0xffff) << 1)|0) + c|0;
w = ((r >>> 16) + ((r10 >>> 16) << 1)|0) + (u >>> 16)|0;
HEAP32[(Rk+k)>>2] = (w << 16) | (u & 0xffff);
c = w >>> 16;
k = k+4|0;
r = HEAP32[(Rk+k)>>2]|0;
u = ((r & 0xffff) + ((r11 & 0xffff) << 1)|0) + c|0;
w = ((r >>> 16) + ((r11 >>> 16) << 1)|0) + (u >>> 16)|0;
HEAP32[(Rk+k)>>2] = (w << 16) | (u & 0xffff);
c = w >>> 16;
k = k+4|0;
r = HEAP32[(Rk+k)>>2]|0;
u = ((r & 0xffff) + ((r12 & 0xffff) << 1)|0) + c|0;
w = ((r >>> 16) + ((r12 >>> 16) << 1)|0) + (u >>> 16)|0;
HEAP32[(Rk+k)>>2] = (w << 16) | (u & 0xffff);
c = w >>> 16;
k = k+4|0;
r = HEAP32[(Rk+k)>>2]|0;
u = ((r & 0xffff) + ((r13 & 0xffff) << 1)|0) + c|0;
w = ((r >>> 16) + ((r13 >>> 16) << 1)|0) + (u >>> 16)|0;
HEAP32[(Rk+k)>>2] = (w << 16) | (u & 0xffff);
c = w >>> 16;
k = k+4|0;
r = HEAP32[(Rk+k)>>2]|0;
u = ((r & 0xffff) + ((r14 & 0xffff) << 1)|0) + c|0;
w = ((r >>> 16) + ((r14 >>> 16) << 1)|0) + (u >>> 16)|0;
HEAP32[(Rk+k)>>2] = (w << 16) | (u & 0xffff);
c = w >>> 16;
k = k+4|0;
r = HEAP32[(Rk+k)>>2]|0;
u = ((r & 0xffff) + ((r15 & 0xffff) << 1)|0) + c|0;
w = ((r >>> 16) + ((r15 >>> 16) << 1)|0) + (u >>> 16)|0;
HEAP32[(Rk+k)>>2] = (w << 16) | (u & 0xffff);
h = w >>> 16;
}
for ( k = k+4|0; !!h & ( (k|0) < (dd<<1) ); k = (k+4)|0 ) { // carry propagation loop
r = HEAP32[(Rk+k)>>2]|0;
u = (r & 0xffff) + h|0;
w = (r >>> 16) + (u >>> 16)|0;
HEAP32[(Rk+k)>>2] = (w << 16) | (u & 0xffff);
h = w >>> 16;
}
}
}
}
/**
* Conventional division
*
* @param A offset of the numerator, 32-byte aligned
* @param lA length of the numerator, multiple of 32
*
* @param B offset of the divisor, 32-byte aligned
* @param lB length of the divisor, multiple of 32
*
* @param R offset where to place the remainder to, 32-byte aligned
*
* @param Q offser where to place the quotient to, 32-byte aligned
*/
function div ( N, lN, D, lD, Q ) {
N = N|0;
lN = lN|0
D = D|0;
lD = lD|0
Q = Q|0;
var n = 0, d = 0, e = 0,
u1 = 0, u0 = 0,
v0 = 0, vh = 0, vl = 0,
qh = 0, ql = 0, rh = 0, rl = 0,
t1 = 0, t2 = 0, m = 0, c = 0,
i = 0, j = 0, k = 0;
// number of significant limbs in `N` (multiplied by 4)
for ( i = (lN-1) & -4; (i|0) >= 0; i = (i-4)|0 ) {
n = HEAP32[(N+i)>>2]|0;
if ( n ) {
lN = i;
break;
}
}
// number of significant limbs in `D` (multiplied by 4)
for ( i = (lD-1) & -4; (i|0) >= 0; i = (i-4)|0 ) {
d = HEAP32[(D+i)>>2]|0;
if ( d ) {
lD = i;
break;
}
}
// `D` is zero? WTF?!
// calculate `e` — the power of 2 of the normalization factor
while ( (d & 0x80000000) == 0 ) {
d = d << 1;
e = e + 1|0;
}
// normalize `N` in place
u0 = HEAP32[(N+lN)>>2]|0;
if ( e ) {
u1 = u0>>>(32-e|0);
for ( i = (lN-4)|0; (i|0) >= 0; i = (i-4)|0 ) {
n = HEAP32[(N+i)>>2]|0;
HEAP32[(N+i+4)>>2] = (u0 << e) | ( e ? n >>> (32-e|0) : 0 );
u0 = n;
}
HEAP32[N>>2] = u0 << e;
}
// normalize `D` in place
if ( e ) {
v0 = HEAP32[(D+lD)>>2]|0;
for ( i = (lD-4)|0; (i|0) >= 0; i = (i-4)|0 ) {
d = HEAP32[(D+i)>>2]|0;
HEAP32[(D+i+4)>>2] = (v0 << e) | ( d >>> (32-e|0) );
v0 = d;
}
HEAP32[D>>2] = v0 << e;
}
// divisor parts won't change
v0 = HEAP32[(D+lD)>>2]|0;
vh = v0 >>> 16, vl = v0 & 0xffff;
// perform division
for ( i = lN; (i|0) >= (lD|0); i = (i-4)|0 ) {
j = (i-lD)|0;
// estimate high part of the quotient
u0 = HEAP32[(N+i)>>2]|0;
qh = ( (u1>>>0) / (vh>>>0) )|0, rh = ( (u1>>>0) % (vh>>>0) )|0, t1 = imul(qh, vl)|0;
while ( ( (qh|0) == 0x10000 ) | ( (t1>>>0) > (((rh << 16)|(u0 >>> 16))>>>0) ) ) {
qh = (qh-1)|0, rh = (rh+vh)|0, t1 = (t1-vl)|0;
if ( (rh|0) >= 0x10000 ) break;
}
// bulk multiply-and-subtract
// m - multiplication carry, c - subtraction carry
m = 0, c = 0;
for ( k = 0; (k|0) <= (lD|0); k = (k+4)|0 ) {
d = HEAP32[(D+k)>>2]|0;
t1 = (imul(qh, d & 0xffff)|0) + (m >>> 16)|0;
t2 = (imul(qh, d >>> 16)|0) + (t1 >>> 16)|0;
d = (m & 0xffff) | (t1 << 16);
m = t2;
n = HEAP32[(N+j+k)>>2]|0;
t1 = ((n & 0xffff) - (d & 0xffff)|0) + c|0;
t2 = ((n >>> 16) - (d >>> 16)|0) + (t1 >> 16)|0;
HEAP32[(N+j+k)>>2] = (t2 << 16) | (t1 & 0xffff);
c = t2 >> 16;
}
t1 = ((u1 & 0xffff) - (m & 0xffff)|0) + c|0;
t2 = ((u1 >>> 16) - (m >>> 16)|0) + (t1 >> 16)|0;
u1 = (t2 << 16) | (t1 & 0xffff);
c = t2 >> 16;
// add `D` back if got carry-out
if ( c ) {
qh = (qh-1)|0;
c = 0;
for ( k = 0; (k|0) <= (lD|0); k = (k+4)|0 ) {
d = HEAP32[(D+k)>>2]|0;
n = HEAP32[(N+j+k)>>2]|0;
t1 = (n & 0xffff) + c|0;
t2 = (n >>> 16) + d + (t1 >>> 16)|0;
HEAP32[(N+j+k)>>2] = (t2 << 16) | (t1 & 0xffff);
c = t2 >>> 16;
}
u1 = (u1+c)|0;
}
// estimate low part of the quotient
u0 = HEAP32[(N+i)>>2]|0;
n = (u1 << 16) | (u0 >>> 16);
ql = ( (n>>>0) / (vh>>>0) )|0, rl = ( (n>>>0) % (vh>>>0) )|0, t1 = imul(ql, vl)|0;
while ( ( (ql|0) == 0x10000 ) | ( (t1>>>0) > (((rl << 16)|(u0 & 0xffff))>>>0) ) ) {
ql = (ql-1)|0, rl = (rl+vh)|0, t1 = (t1-vl)|0;
if ( (rl|0) >= 0x10000 ) break;
}
// bulk multiply-and-subtract
// m - multiplication carry, c - subtraction carry
m = 0, c = 0;
for ( k = 0; (k|0) <= (lD|0); k = (k+4)|0 ) {
d = HEAP32[(D+k)>>2]|0;
t1 = (imul(ql, d & 0xffff)|0) + (m & 0xffff)|0;
t2 = ((imul(ql, d >>> 16)|0) + (t1 >>> 16)|0) + (m >>> 16)|0;
d = (t1 & 0xffff) | (t2 << 16);
m = t2 >>> 16;
n = HEAP32[(N+j+k)>>2]|0;
t1 = ((n & 0xffff) - (d & 0xffff)|0) + c|0;
t2 = ((n >>> 16) - (d >>> 16)|0) + (t1 >> 16)|0;
c = t2 >> 16;
HEAP32[(N+j+k)>>2] = (t2 << 16) | (t1 & 0xffff);
}
t1 = ((u1 & 0xffff) - (m & 0xffff)|0) + c|0;
t2 = ((u1 >>> 16) - (m >>> 16)|0) + (t1 >> 16)|0;
c = t2 >> 16;
// add `D` back if got carry-out
if ( c ) {
ql = (ql-1)|0;
c = 0;
for ( k = 0; (k|0) <= (lD|0); k = (k+4)|0 ) {
d = HEAP32[(D+k)>>2]|0;
n = HEAP32[(N+j+k)>>2]|0;
t1 = ((n & 0xffff) + (d & 0xffff)|0) + c|0;
t2 = ((n >>> 16) + (d >>> 16)|0) + (t1 >>> 16)|0;
c = t2 >>> 16;
HEAP32[(N+j+k)>>2] = (t1 & 0xffff) | (t2 << 16);
}
}
// got quotient limb
HEAP32[(Q+j)>>2] = (qh << 16) | ql;
u1 = HEAP32[(N+i)>>2]|0;
}
if ( e ) {
// TODO denormalize `D` in place
// denormalize `N` in place
u0 = HEAP32[N>>2]|0;
for ( i = 4; (i|0) <= (lD|0); i = (i+4)|0 ) {
n = HEAP32[(N+i)>>2]|0;
HEAP32[(N+i-4)>>2] = ( n << (32-e|0) ) | (u0 >>> e);
u0 = n;
}
HEAP32[(N+lD)>>2] = u0 >>> e;
}
}
/**
* Montgomery modular reduction
*
* Definition:
*
* MREDC(A) = A × X (mod N),
* M × X = N × Y + 1,
*
* where M = 2^(32*m) such that N < M and A < N×M
*
* Numbers `X` and `Y` can be calculated using Extended Euclidean Algorithm.
*/
function mredc ( A, lA, N, lN, y, R ) {
A = A|0;
lA = lA|0;
N = N|0;
lN = lN|0;
y = y|0;
R = R|0;
var T = 0,
c = 0, uh = 0, ul = 0, vl = 0, vh = 0, w0 = 0, w1 = 0, w2 = 0, r0 = 0, r1 = 0,
i = 0, j = 0, k = 0;
T = salloc(lN<<1)|0;
z(lN<<1, 0, T);
cp( lA, A, T );
// HAC 14.32
for ( i = 0; (i|0) < (lN|0); i = (i+4)|0 ) {
uh = HEAP32[(T+i)>>2]|0, ul = uh & 0xffff, uh = uh >>> 16;
vh = y >>> 16, vl = y & 0xffff;
w0 = imul(ul,vl)|0, w1 = ( (imul(ul,vh)|0) + (imul(uh,vl)|0) | 0 ) + (w0 >>> 16) | 0;
ul = w0 & 0xffff, uh = w1 & 0xffff;
r1 = 0;
for ( j = 0; (j|0) < (lN|0); j = (j+4)|0 ) {
k = (i+j)|0;
vh = HEAP32[(N+j)>>2]|0, vl = vh & 0xffff, vh = vh >>> 16;
r0 = HEAP32[(T+k)>>2]|0;
w0 = ((imul(ul, vl)|0) + (r1 & 0xffff)|0) + (r0 & 0xffff)|0;
w1 = ((imul(ul, vh)|0) + (r1 >>> 16)|0) + (r0 >>> 16)|0;
w2 = ((imul(uh, vl)|0) + (w1 & 0xffff)|0) + (w0 >>> 16)|0;
r1 = ((imul(uh, vh)|0) + (w2 >>> 16)|0) + (w1 >>> 16)|0;
r0 = (w2 << 16) | (w0 & 0xffff);
HEAP32[(T+k)>>2] = r0;
}
k = (i+j)|0;
r0 = HEAP32[(T+k)>>2]|0;
w0 = ((r0 & 0xffff) + (r1 & 0xffff)|0) + c|0;
w1 = ((r0 >>> 16) + (r1 >>> 16)|0) + (w0 >>> 16)|0;
HEAP32[(T+k)>>2] = (w1 << 16) | (w0 & 0xffff);
c = w1 >>> 16;
}
cp( lN, (T+lN)|0, R );
sfree(lN<<1);
if ( c | ( (cmp( N, lN, R, lN )|0) <= 0 ) ) {
sub( R, lN, N, lN, R, lN )|0;
}
}
return {
sreset: sreset,
salloc: salloc,
sfree: sfree,
z: z,
tst: tst,
neg: neg,
cmp: cmp,
add: add,
sub: sub,
mul: mul,
sqr: sqr,
div: div,
mredc: mredc
};
}
================================================
FILE: src/bignum/bignum.ts
================================================
import { bigint_asm, bigintresult } from './bigint.asm';
import { string_to_bytes } from '../other/utils';
import { IllegalArgumentError } from '../other/errors';
import { BigNumber_extGCD, Number_extGCD } from './extgcd';
import { getRandomValues } from '../other/get-random-values';
///////////////////////////////////////////////////////////////////////////////
export const _bigint_stdlib = { Uint32Array: Uint32Array, Math: Math };
export const _bigint_heap = new Uint32Array(0x100000);
export let _bigint_asm: bigintresult;
function _half_imul(a: number, b: number) {
return (a * b) | 0;
}
if (_bigint_stdlib.Math.imul === undefined) {
_bigint_stdlib.Math.imul = _half_imul;
_bigint_asm = bigint_asm(_bigint_stdlib, null, _bigint_heap.buffer);
delete _bigint_stdlib.Math.imul;
} else {
_bigint_asm = bigint_asm(_bigint_stdlib, null, _bigint_heap.buffer);
}
///////////////////////////////////////////////////////////////////////////////
const _BigNumber_ZERO_limbs = new Uint32Array(0);
export class BigNumber {
public limbs!: Uint32Array;
public bitLength!: number;
public sign!: number;
static extGCD = BigNumber_extGCD;
static ZERO = BigNumber.fromNumber(0);
static ONE = BigNumber.fromNumber(1);
static fromString(str: string): BigNumber {
const bytes = string_to_bytes(str);
return new BigNumber(bytes);
}
static fromNumber(num: number): BigNumber {
let limbs = _BigNumber_ZERO_limbs;
let bitlen = 0;
let sign = 0;
var absnum = Math.abs(num);
if (absnum > 0xffffffff) {
limbs = new Uint32Array(2);
limbs[0] = absnum | 0;
limbs[1] = (absnum / 0x100000000) | 0;
bitlen = 52;
} else if (absnum > 0) {
limbs = new Uint32Array(1);
limbs[0] = absnum;
bitlen = 32;
} else {
limbs = _BigNumber_ZERO_limbs;
bitlen = 0;
}
sign = num < 0 ? -1 : 1;
return BigNumber.fromConfig({ limbs, bitLength: bitlen, sign });
}
static fromArrayBuffer(buffer: ArrayBuffer): BigNumber {
return new BigNumber(new Uint8Array(buffer));
}
static fromConfig(obj: { limbs: Uint32Array; bitLength: number; sign: number }): BigNumber {
const bn = new BigNumber();
bn.limbs = new Uint32Array(obj.limbs);
bn.bitLength = obj.bitLength;
bn.sign = obj.sign;
return bn;
}
constructor(num?: Uint8Array) {
let limbs = _BigNumber_ZERO_limbs;
let bitlen = 0;
let sign = 0;
if (num === undefined) {
// do nothing
} else {
for (var i = 0; !num[i]; i++);
bitlen = (num.length - i) * 8;
if (!bitlen) return BigNumber.ZERO;
limbs = new Uint32Array((bitlen + 31) >> 5);
for (var j = num.length - 4; j >= i; j -= 4) {
limbs[(num.length - 4 - j) >> 2] = (num[j] << 24) | (num[j + 1] << 16) | (num[j + 2] << 8) | num[j + 3];
}
if (i - j === 3) {
limbs[limbs.length - 1] = num[i];
} else if (i - j === 2) {
limbs[limbs.length - 1] = (num[i] << 8) | num[i + 1];
} else if (i - j === 1) {
limbs[limbs.length - 1] = (num[i] << 16) | (num[i + 1] << 8) | num[i + 2];
}
sign = 1;
}
this.limbs = limbs;
this.bitLength = bitlen;
this.sign = sign;
}
toString(radix: number): string {
radix = radix || 16;
const limbs = this.limbs;
const bitlen = this.bitLength;
let str = '';
if (radix === 16) {
// FIXME clamp last limb to (bitlen % 32)
for (var i = ((bitlen + 31) >> 5) - 1; i >= 0; i--) {
var h = limbs[i].toString(16);
str += '00000000'.substr(h.length);
str += h;
}
str = str.replace(/^0+/, '');
if (!str.length) str = '0';
} else {
throw new IllegalArgumentError('bad radix');
}
if (this.sign < 0) str = '-' + str;
return str;
}
toBytes(): Uint8Array {
const bitlen = this.bitLength;
const limbs = this.limbs;
if (bitlen === 0) return new Uint8Array(0);
const bytelen = (bitlen + 7) >> 3;
const bytes = new Uint8Array(bytelen);
for (let i = 0; i < bytelen; i++) {
let j = bytelen - i - 1;
bytes[i] = limbs[j >> 2] >> ((j & 3) << 3);
}
return bytes;
}
/**
* Downgrade to Number
*/
valueOf(): number {
const limbs = this.limbs;
const bits = this.bitLength;
const sign = this.sign;
if (!sign) return 0;
if (bits <= 32) return sign * (limbs[0] >>> 0);
if (bits <= 52) return sign * (0x100000000 * (limbs[1] >>> 0) + (limbs[0] >>> 0));
// normalization
let i,
l,
e = 0;
for (i = limbs.length - 1; i >= 0; i--) {
if ((l = limbs[i]) === 0) continue;
while (((l << e) & 0x80000000) === 0) e++;
break;
}
if (i === 0) return sign * (limbs[0] >>> 0);
return (
sign *
(0x100000 * (((limbs[i] << e) | (e ? limbs[i - 1] >>> (32 - e) : 0)) >>> 0) +
(((limbs[i - 1] << e) | (e && i > 1 ? limbs[i - 2] >>> (32 - e) : 0)) >>> 12)) *
Math.pow(2, 32 * i - e - 52)
);
}
clamp(b: number): BigNumber {
const limbs = this.limbs;
const bitlen = this.bitLength;
// FIXME check b is number and in a valid range
if (b >= bitlen) return this;
const clamped = new BigNumber();
let n = (b + 31) >> 5;
let k = b % 32;
clamped.limbs = new Uint32Array(limbs.subarray(0, n));
clamped.bitLength = b;
clamped.sign = this.sign;
if (k) clamped.limbs[n - 1] &= -1 >>> (32 - k);
return clamped;
}
slice(f: number, b?: number): BigNumber {
const limbs = this.limbs;
const bitlen = this.bitLength;
if (f < 0) throw new RangeError('TODO');
if (f >= bitlen) return BigNumber.ZERO;
if (b === undefined || b > bitlen - f) b = bitlen - f;
const sliced = new BigNumber();
let n = f >> 5;
let m = (f + b + 31) >> 5;
let l = (b + 31) >> 5;
let t = f % 32;
let k = b % 32;
const slimbs = new Uint32Array(l);
if (t) {
for (var i = 0; i < m - n - 1; i++) {
slimbs[i] = (limbs[n + i] >>> t) | (limbs[n + i + 1] << (32 - t));
}
slimbs[i] = limbs[n + i] >>> t;
} else {
slimbs.set(limbs.subarray(n, m));
}
if (k) {
slimbs[l - 1] &= -1 >>> (32 - k);
}
sliced.limbs = slimbs;
sliced.bitLength = b;
sliced.sign = this.sign;
return sliced;
}
negate(): BigNumber {
const negative = new BigNumber();
negative.limbs = this.limbs;
negative.bitLength = this.bitLength;
negative.sign = -1 * this.sign;
return negative;
}
compare(that: BigNumber): number {
var alimbs = this.limbs,
alimbcnt = alimbs.length,
blimbs = that.limbs,
blimbcnt = blimbs.length,
z = 0;
if (this.sign < that.sign) return -1;
if (this.sign > that.sign) return 1;
_bigint_heap.set(alimbs, 0);
_bigint_heap.set(blimbs, alimbcnt);
z = _bigint_asm.cmp(0, alimbcnt << 2, alimbcnt << 2, blimbcnt << 2);
return z * this.sign;
}
add(that: BigNumber): BigNumber {
if (!this.sign) return that;
if (!that.sign) return this;
var abitlen = this.bitLength,
alimbs = this.limbs,
alimbcnt = alimbs.length,
asign = this.sign,
bbitlen = that.bitLength,
blimbs = that.limbs,
blimbcnt = blimbs.length,
bsign = that.sign,
rbitlen,
rlimbcnt,
rsign,
rof,
result = new BigNumber();
rbitlen = (abitlen > bbitlen ? abitlen : bbitlen) + (asign * bsign > 0 ? 1 : 0);
rlimbcnt = (rbitlen + 31) >> 5;
_bigint_asm.sreset();
var pA = _bigint_asm.salloc(alimbcnt << 2),
pB = _bigint_asm.salloc(blimbcnt << 2),
pR = _bigint_asm.salloc(rlimbcnt << 2);
_bigint_asm.z(pR - pA + (rlimbcnt << 2), 0, pA);
_bigint_heap.set(alimbs, pA >> 2);
_bigint_heap.set(blimbs, pB >> 2);
if (asign * bsign > 0) {
_bigint_asm.add(pA, alimbcnt << 2, pB, blimbcnt << 2, pR, rlimbcnt << 2);
rsign = asign;
} else if (asign > bsign) {
rof = _bigint_asm.sub(pA, alimbcnt << 2, pB, blimbcnt << 2, pR, rlimbcnt << 2);
rsign = rof ? bsign : asign;
} else {
rof = _bigint_asm.sub(pB, blimbcnt << 2, pA, alimbcnt << 2, pR, rlimbcnt << 2);
rsign = rof ? asign : bsign;
}
if (rof) _bigint_asm.neg(pR, rlimbcnt << 2, pR, rlimbcnt << 2);
if (_bigint_asm.tst(pR, rlimbcnt << 2) === 0) return BigNumber.ZERO;
result.limbs = new Uint32Array(_bigint_heap.subarray(pR >> 2, (pR >> 2) + rlimbcnt));
result.bitLength = rbitlen;
result.sign = rsign;
return result;
}
subtract(that: BigNumber): BigNumber {
return this.add(that.negate());
}
square(): BigNumber {
if (!this.sign) return BigNumber.ZERO;
var abitlen = this.bitLength,
alimbs = this.limbs,
alimbcnt = alimbs.length,
rbitlen,
rlimbcnt,
result = new BigNumber();
rbitlen = abitlen << 1;
rlimbcnt = (rbitlen + 31) >> 5;
_bigint_asm.sreset();
var pA = _bigint_asm.salloc(alimbcnt << 2),
pR = _bigint_asm.salloc(rlimbcnt << 2);
_bigint_asm.z(pR - pA + (rlimbcnt << 2), 0, pA);
_bigint_heap.set(alimbs, pA >> 2);
_bigint_asm.sqr(pA, alimbcnt << 2, pR);
result.limbs = new Uint32Array(_bigint_heap.subarray(pR >> 2, (pR >> 2) + rlimbcnt));
result.bitLength = rbitlen;
result.sign = 1;
return result;
}
divide(that: BigNumber): { quotient: BigNumber; remainder: BigNumber } {
var abitlen = this.bitLength,
alimbs = this.limbs,
alimbcnt = alimbs.length,
bbitlen = that.bitLength,
blimbs = that.limbs,
blimbcnt = blimbs.length,
qlimbcnt,
rlimbcnt,
quotient = BigNumber.ZERO,
remainder = BigNumber.ZERO;
_bigint_asm.sreset();
var pA = _bigint_asm.salloc(alimbcnt << 2),
pB = _bigint_asm.salloc(blimbcnt << 2),
pQ = _bigint_asm.salloc(alimbcnt << 2);
_bigint_asm.z(pQ - pA + (alimbcnt << 2), 0, pA);
_bigint_heap.set(alimbs, pA >> 2);
_bigint_heap.set(blimbs, pB >> 2);
_bigint_asm.div(pA, alimbcnt << 2, pB, blimbcnt << 2, pQ);
qlimbcnt = _bigint_asm.tst(pQ, alimbcnt << 2) >> 2;
if (qlimbcnt) {
quotient = new BigNumber();
quotient.limbs = new Uint32Array(_bigint_heap.subarray(pQ >> 2, (pQ >> 2) + qlimbcnt));
quotient.bitLength = abitlen < qlimbcnt << 5 ? abitlen : qlimbcnt << 5;
quotient.sign = this.sign * that.sign;
}
rlimbcnt = _bigint_asm.tst(pA, blimbcnt << 2) >> 2;
if (rlimbcnt) {
remainder = new BigNumber();
remainder.limbs = new Uint32Array(_bigint_heap.subarray(pA >> 2, (pA >> 2) + rlimbcnt));
remainder.bitLength = bbitlen < rlimbcnt << 5 ? bbitlen : rlimbcnt << 5;
remainder.sign = this.sign;
}
return {
quotient: quotient,
remainder: remainder,
};
}
multiply(that: BigNumber): BigNumber {
if (!this.sign || !that.sign) return BigNumber.ZERO;
var abitlen = this.bitLength,
alimbs = this.limbs,
alimbcnt = alimbs.length,
bbitlen = that.bitLength,
blimbs = that.limbs,
blimbcnt = blimbs.length,
rbitlen,
rlimbcnt,
result = new BigNumber();
rbitlen = abitlen + bbitlen;
rlimbcnt = (rbitlen + 31) >> 5;
_bigint_asm.sreset();
var pA = _bigint_asm.salloc(alimbcnt << 2),
pB = _bigint_asm.salloc(blimbcnt << 2),
pR = _bigint_asm.salloc(rlimbcnt << 2);
_bigint_asm.z(pR - pA + (rlimbcnt << 2), 0, pA);
_bigint_heap.set(alimbs, pA >> 2);
_bigint_heap.set(blimbs, pB >> 2);
_bigint_asm.mul(pA, alimbcnt << 2, pB, blimbcnt << 2, pR, rlimbcnt << 2);
result.limbs = new Uint32Array(_bigint_heap.subarray(pR >> 2, (pR >> 2) + rlimbcnt));
result.sign = this.sign * that.sign;
result.bitLength = rbitlen;
return result;
}
public isMillerRabinProbablePrime(rounds: number): boolean {
var t = BigNumber.fromConfig(this),
s = 0;
t.limbs[0] -= 1;
while (t.limbs[s >> 5] === 0) s += 32;
while (((t.limbs[s >> 5] >> (s & 31)) & 1) === 0) s++;
t = t.slice(s);
var m = new Modulus(this),
m1 = this.subtract(BigNumber.ONE),
a = BigNumber.fromConfig(this),
l = this.limbs.length - 1;
while (a.limbs[l] === 0) l--;
while (--rounds >= 0) {
getRandomValues(a.limbs);
if (a.limbs[0] < 2) a.limbs[0] += 2;
while (a.compare(m1) >= 0) a.limbs[l] >>>= 1;
var x = m.power(a, t);
if (x.compare(BigNumber.ONE) === 0) continue;
if (x.compare(m1) === 0) continue;
var c = s;
while (--c > 0) {
x = x.square().divide(m).remainder;
if (x.compare(BigNumber.ONE) === 0) return false;
if (x.compare(m1) === 0) break;
}
if (c === 0) return false;
}
return true;
}
isProbablePrime(paranoia: number = 80): boolean {
var limbs = this.limbs;
var i = 0;
// Oddity test
// (50% false positive probability)
if ((limbs[0] & 1) === 0) return false;
if (paranoia <= 1) return true;
// Magic divisors (3, 5, 17) test
// (~25% false positive probability)
var s3 = 0,
s5 = 0,
s17 = 0;
for (i = 0; i < limbs.length; i++) {
var l3 = limbs[i];
while (l3) {
s3 += l3 & 3;
l3 >>>= 2;
}
var l5 = limbs[i];
while (l5) {
s5 += l5 & 3;
l5 >>>= 2;
s5 -= l5 & 3;
l5 >>>= 2;
}
var l17 = limbs[i];
while (l17) {
s17 += l17 & 15;
l17 >>>= 4;
s17 -= l17 & 15;
l17 >>>= 4;
}
}
if (!(s3 % 3) || !(s5 % 5) || !(s17 % 17)) return false;
if (paranoia <= 2) return true;
// Miller-Rabin test
// (≤ 4^(-k) false positive probability)
return this.isMillerRabinProbablePrime(paranoia >>> 1);
}
}
export class Modulus extends BigNumber {
// @ts-ignore
private comodulus!: BigNumber;
private comodulusRemainder!: BigNumber;
private comodulusRemainderSquare!: BigNumber;
private coefficient!: number;
constructor(number: BigNumber) {
super();
this.limbs = number.limbs;
this.bitLength = number.bitLength;
this.sign = number.sign;
if (this.valueOf() < 1) throw new RangeError();
if (this.bitLength <= 32) return;
let comodulus: BigNumber;
if (this.limbs[0] & 1) {
const bitlen = ((this.bitLength + 31) & -32) + 1;
const limbs = new Uint32Array((bitlen + 31) >> 5);
limbs[limbs.length - 1] = 1;
comodulus = new BigNumber();
comodulus.sign = 1;
comodulus.bitLength = bitlen;
comodulus.limbs = limbs;
const k = Number_extGCD(0x100000000, this.limbs[0]).y;
this.coefficient = k < 0 ? -k : 0x100000000 - k;
} else {
/**
* TODO even modulus reduction
* Modulus represented as `N = 2^U * V`, where `V` is odd and thus `GCD(2^U, V) = 1`.
* Calculation `A = TR' mod V` is made as for odd modulo using Montgomery method.
* Calculation `B = TR' mod 2^U` is easy as modulus is a power of 2.
* Using Chinese Remainder Theorem and Garner's Algorithm restore `TR' mod N` from `A` and `B`.
*/
return;
}
this.comodulus = comodulus;
this.comodulusRemainder = comodulus.divide(this).remainder;
this.comodulusRemainderSquare = comodulus.square().divide(this).remainder;
}
/**
* Modular reduction
*/
reduce(a: BigNumber): BigNumber {
if (a.bitLength <= 32 && this.bitLength <= 32) return BigNumber.fromNumber(a.valueOf() % this.valueOf());
if (a.compare(this) < 0) return a;
return a.divide(this).remainder;
}
/**
* Modular inverse
*/
inverse(a: BigNumber): BigNumber {
a = this.reduce(a);
const r = BigNumber_extGCD(this, a);
if (r.gcd.valueOf() !== 1) throw new Error('GCD is not 1');
if (r.y.sign < 0) return r.y.add(this).clamp(this.bitLength);
return r.y;
}
/**
* Modular exponentiation
*/
power(g: BigNumber, e: BigNumber): BigNumber {
// count exponent set bits
let c = 0;
for (let i = 0; i < e.limbs.length; i++) {
let t = e.limbs[i];
while (t) {
if (t & 1) c++;
t >>>= 1;
}
}
// window size parameter
let k = 8;
if (e.bitLength <= 4536) k = 7;
if (e.bitLength <= 1736) k = 6;
if (e.bitLength <= 630) k = 5;
if (e.bitLength <= 210) k = 4;
if (e.bitLength <= 60) k = 3;
if (e.bitLength <= 12) k = 2;
if (c <= 1 << (k - 1)) k = 1;
// montgomerize base
g = Modulus._Montgomery_reduce(this.reduce(g).multiply(this.comodulusRemainderSquare), this);
// precompute odd powers
const g2 = Modulus._Montgomery_reduce(g.square(), this),
gn = new Array(1 << (k - 1));
gn[0] = g;
gn[1] = Modulus._Montgomery_reduce(g.multiply(g2), this);
for (let i = 2; i < 1 << (k - 1); i++) {
gn[i] = Modulus._Montgomery_reduce(gn[i - 1].multiply(g2), this);
}
// perform exponentiation
const u = this.comodulusRemainder;
let r = u;
for (let i = e.limbs.length - 1; i >= 0; i--) {
let t = e.limbs[i];
for (let j = 32; j > 0; ) {
if (t & 0x80000000) {
let n = t >>> (32 - k),
l = k;
while ((n & 1) === 0) {
n >>>= 1;
l--;
}
var m = gn[n >>> 1];
while (n) {
n >>>= 1;
if (r !== u) r = Modulus._Montgomery_reduce(r.square(), this);
}
r = r !== u ? Modulus._Montgomery_reduce(r.multiply(m), this) : m;
(t <<= l), (j -= l);
} else {
if (r !== u) r = Modulus._Montgomery_reduce(r.square(), this);
(t <<= 1), j--;
}
}
}
// de-montgomerize result
return Modulus._Montgomery_reduce(r, this);
}
static _Montgomery_reduce(a: BigNumber, n: Modulus): BigNumber {
const alimbs = a.limbs;
const alimbcnt = alimbs.length;
const nlimbs = n.limbs;
const nlimbcnt = nlimbs.length;
const y = n.coefficient;
_bigint_asm.sreset();
const pA = _bigint_asm.salloc(alimbcnt << 2),
pN = _bigint_asm.salloc(nlimbcnt << 2),
pR = _bigint_asm.salloc(nlimbcnt << 2);
_bigint_asm.z(pR - pA + (nlimbcnt << 2), 0, pA);
_bigint_heap.set(alimbs, pA >> 2);
_bigint_heap.set(nlimbs, pN >> 2);
_bigint_asm.mredc(pA, alimbcnt << 2, pN, nlimbcnt << 2, y, pR);
const result = new BigNumber();
result.limbs = new Uint32Array(_bigint_heap.subarray(pR >> 2, (pR >> 2) + nlimbcnt));
result.bitLength = n.bitLength;
result.sign = 1;
return result;
}
}
================================================
FILE: src/bignum/extgcd.ts
================================================
import { BigNumber } from './bignum';
export function Number_extGCD(a: number, b: number): { gcd: number; x: number; y: number } {
var sa = a < 0 ? -1 : 1,
sb = b < 0 ? -1 : 1,
xi = 1,
xj = 0,
yi = 0,
yj = 1,
r,
q,
t,
a_cmp_b;
a *= sa;
b *= sb;
a_cmp_b = a < b;
if (a_cmp_b) {
t = a;
(a = b), (b = t);
t = sa;
sa = sb;
sb = t;
}
(q = Math.floor(a / b)), (r = a - q * b);
while (r) {
(t = xi - q * xj), (xi = xj), (xj = t);
(t = yi - q * yj), (yi = yj), (yj = t);
(a = b), (b = r);
(q = Math.floor(a / b)), (r = a - q * b);
}
xj *= sa;
yj *= sb;
if (a_cmp_b) {
t = xj;
(xj = yj), (yj = t);
}
return {
gcd: b,
x: xj,
y: yj,
};
}
export function BigNumber_extGCD(a: BigNumber, b: BigNumber): { gcd: BigNumber; x: BigNumber; y: BigNumber } {
let sa = a.sign;
let sb = b.sign;
if (sa < 0) a = a.negate();
if (sb < 0) b = b.negate();
const a_cmp_b = a.compare(b);
if (a_cmp_b < 0) {
let t = a;
(a = b), (b = t);
let t2 = sa;
sa = sb;
sb = t2;
}
var xi = BigNumber.ONE,
xj = BigNumber.ZERO,
lx = b.bitLength,
yi = BigNumber.ZERO,
yj = BigNumber.ONE,
ly = a.bitLength,
z,
r,
q;
z = a.divide(b);
while ((r = z.remainder) !== BigNumber.ZERO) {
q = z.quotient;
(z = xi.subtract(q.multiply(xj).clamp(lx)).clamp(lx)), (xi = xj), (xj = z);
(z = yi.subtract(q.multiply(yj).clamp(ly)).clamp(ly)), (yi = yj), (yj = z);
(a = b), (b = r);
z = a.divide(b);
}
if (sa < 0) xj = xj.negate();
if (sb < 0) yj = yj.negate();
if (a_cmp_b < 0) {
let t = xj;
(xj = yj), (yj = t);
}
return {
gcd: b,
x: xj,
y: yj,
};
}
================================================
FILE: src/entry-default.ts
================================================
export * from './other/exportedUtils';
export * from './other/errors';
export * from './aes/cbc';
export * from './aes/gcm';
export * from './hash/sha1/sha1';
export * from './hash/sha256/sha256';
export * from './hmac/hmac-sha1';
export * from './hmac/hmac-sha256';
export * from './pbkdf2/pbkdf2-hmac-sha1';
export * from './pbkdf2/pbkdf2-hmac-sha256';
export * from './bignum/bignum';
export * from './rsa/pkcs1';
================================================
FILE: src/entry-export_all.ts
================================================
export {
string_to_bytes,
hex_to_bytes,
base64_to_bytes,
bytes_to_string,
bytes_to_hex,
bytes_to_base64,
} from './other/exportedUtils';
export { IllegalStateError, IllegalArgumentError, SecurityError } from './other/errors';
export { AES_CBC } from './aes/cbc';
export { AES_CCM } from './aes/ccm';
export { AES_CFB } from './aes/cfb';
export { AES_CMAC } from './aes/cmac';
export { AES_CTR } from './aes/ctr';
export { AES_ECB } from './aes/ecb';
export { AES_GCM } from './aes/gcm';
export { AES_OFB } from './aes/ofb';
export { BigNumber, Modulus } from './bignum/bignum';
export { Sha1 } from './hash/sha1/sha1';
export { Sha256 } from './hash/sha256/sha256';
export { Sha512 } from './hash/sha512/sha512';
export { HmacSha1 } from './hmac/hmac-sha1';
export { HmacSha256 } from './hmac/hmac-sha256';
export { HmacSha512 } from './hmac/hmac-sha512';
export { Pbkdf2HmacSha1 } from './pbkdf2/pbkdf2-hmac-sha1';
export { Pbkdf2HmacSha256 } from './pbkdf2/pbkdf2-hmac-sha256';
export { Pbkdf2HmacSha512 } from './pbkdf2/pbkdf2-hmac-sha512';
export { RSA_OAEP, RSA_PKCS1_v1_5, RSA_PSS } from './rsa/pkcs1';
export { RSA } from './rsa/rsa';
================================================
FILE: src/hash/hash.ts
================================================
import { _heap_write } from '../other/utils';
import { IllegalStateError } from '../other/errors';
import { sha1result } from './sha1/sha1.asm';
import { sha256result } from './sha256/sha256.asm';
import { sha512result } from './sha512/sha512.asm';
export abstract class Hash<T extends sha1result | sha256result | sha512result> {
public result!: Uint8Array | null;
public pos: number = 0;
public len: number = 0;
public asm!: T;
public heap!: Uint8Array;
public BLOCK_SIZE!: number;
public HASH_SIZE!: number;
reset() {
this.result = null;
this.pos = 0;
this.len = 0;
this.asm.reset();
return this;
}
process(data: Uint8Array) {
if (this.result !== null) throw new IllegalStateError('state must be reset before processing new data');
let asm = this.asm;
let heap = this.heap;
let hpos = this.pos;
let hlen = this.len;
let dpos = 0;
let dlen = data.length;
let wlen = 0;
while (dlen > 0) {
wlen = _heap_write(heap, hpos + hlen, data, dpos, dlen);
hlen += wlen;
dpos += wlen;
dlen -= wlen;
wlen = asm.process(hpos, hlen);
hpos += wlen;
hlen -= wlen;
if (!hlen) hpos = 0;
}
this.pos = hpos;
this.len = hlen;
return this;
}
finish() {
if (this.result !== null) throw new IllegalStateError('state must be reset before processing new data');
this.asm.finish(this.pos, this.len, 0);
this.result = new Uint8Array(this.HASH_SIZE);
this.result.set(this.heap.subarray(0, this.HASH_SIZE));
this.pos = 0;
this.len = 0;
return this;
}
}
================================================
FILE: src/hash/sha1/sha1.asm.d.ts
================================================
declare interface sha1result {
// SHA1
reset: () => void;
init: (h0: number, h1: number, h2: number, h3: number, h4: number, total0: number, total1: number) => void;
/**
* @param offset - multiple of 64
* @param length
* @returns hashed
*/
process: (offset: number, length: number) => number;
/**
* @param offset - multiple of 64
* @param length
* @param output - multiple of 32
* @returns hashed
*/
finish: (offset: number, length: number, output: number) => number;
// HMAC-SHA;
hmac_reset: () => void;
hmac_init: (
p0: number,
p1: number,
p2: number,
p3: number,
p4: number,
p5: number,
p6: number,
p7: number,
p8: number,
p9: number,
p10: number,
p11: number,
p12: number,
p13: number,
p14: number,
p15: number,
) => void;
/**
* @param offset - multiple of 64
* @param length
* @param output - multiple of 32
* @returns hashed
*/
hmac_finish: (offset: number, length: number, output: number) => number;
// ;
/**
* PBKDF2-HMAC-SHA
* @param offset - multiple of 64
* @param length
* @param block
* @param count
* @param output - multiple of 32
*/
pbkdf2_generate_block: (offset: number, length: number, block: number, count: number, output: number) => 0 | -1;
}
export function sha1_asm(stdlib: any, foreign: any, buffer: ArrayBuffer): sha1result;
================================================
FILE: src/hash/sha1/sha1.asm.js
================================================
export var sha1_asm = function ( stdlib, foreign, buffer ) {
"use asm";
// SHA256 state
var H0 = 0, H1 = 0, H2 = 0, H3 = 0, H4 = 0,
TOTAL0 = 0, TOTAL1 = 0;
// HMAC state
var I0 = 0, I1 = 0, I2 = 0, I3 = 0, I4 = 0,
O0 = 0, O1 = 0, O2 = 0, O3 = 0, O4 = 0;
// I/O buffer
var HEAP = new stdlib.Uint8Array(buffer);
function _core ( w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15 ) {
w0 = w0|0;
w1 = w1|0;
w2 = w2|0;
w3 = w3|0;
w4 = w4|0;
w5 = w5|0;
w6 = w6|0;
w7 = w7|0;
w8 = w8|0;
w9 = w9|0;
w10 = w10|0;
w11 = w11|0;
w12 = w12|0;
w13 = w13|0;
w14 = w14|0;
w15 = w15|0;
var a = 0, b = 0, c = 0, d = 0, e = 0, n = 0, t = 0,
w16 = 0, w17 = 0, w18 = 0, w19 = 0,
w20 = 0, w21 = 0, w22 = 0, w23 = 0, w24 = 0, w25 = 0, w26 = 0, w27 = 0, w28 = 0, w29 = 0,
w30 = 0, w31 = 0, w32 = 0, w33 = 0, w34 = 0, w35 = 0, w36 = 0, w37 = 0, w38 = 0, w39 = 0,
w40 = 0, w41 = 0, w42 = 0, w43 = 0, w44 = 0, w45 = 0, w46 = 0, w47 = 0, w48 = 0, w49 = 0,
w50 = 0, w51 = 0, w52 = 0, w53 = 0, w54 = 0, w55 = 0, w56 = 0, w57 = 0, w58 = 0, w59 = 0,
w60 = 0, w61 = 0, w62 = 0, w63 = 0, w64 = 0, w65 = 0, w66 = 0, w67 = 0, w68 = 0, w69 = 0,
w70 = 0, w71 = 0, w72 = 0, w73 = 0, w74 = 0, w75 = 0, w76 = 0, w77 = 0, w78 = 0, w79 = 0;
a = H0;
b = H1;
c = H2;
d = H3;
e = H4;
// 0
t = ( w0 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0;
e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t;
// 1
t = ( w1 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0;
e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t;
// 2
t = ( w2 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0;
e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t;
// 3
t = ( w3 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0;
e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t;
// 4
t = ( w4 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0;
e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t;
// 5
t = ( w5 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0;
e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t;
// 6
t = ( w6 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0;
e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t;
// 7
t = ( w7 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0;
e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t;
// 8
t = ( w8 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0;
e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t;
// 9
t = ( w9 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0;
e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t;
// 10
t = ( w10 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0;
e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t;
// 11
t = ( w11 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0;
e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t;
// 12
t = ( w12 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0;
e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t;
// 13
t = ( w13 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0;
e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t;
// 14
t = ( w14 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0;
e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t;
// 15
t = ( w15 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0;
e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t;
// 16
n = w13 ^ w8 ^ w2 ^ w0;
w16 = (n << 1) | (n >>> 31);
t = (w16 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0;
e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t;
// 17
n = w14 ^ w9 ^ w3 ^ w1;
w17 = (n << 1) | (n >>> 31);
t = (w17 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0;
e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t;
// 18
n = w15 ^ w10 ^ w4 ^ w2;
w18 = (n << 1) | (n >>> 31);
t = (w18 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0;
e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t;
// 19
n = w16 ^ w11 ^ w5 ^ w3;
w19 = (n << 1) | (n >>> 31);
t = (w19 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (~b & d)) + 0x5a827999 )|0;
e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t;
// 20
n = w17 ^ w12 ^ w6 ^ w4;
w20 = (n << 1) | (n >>> 31);
t = (w20 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0;
e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t;
// 21
n = w18 ^ w13 ^ w7 ^ w5;
w21 = (n << 1) | (n >>> 31);
t = (w21 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0;
e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t;
// 22
n = w19 ^ w14 ^ w8 ^ w6;
w22 = (n << 1) | (n >>> 31);
t = (w22 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0;
e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t;
// 23
n = w20 ^ w15 ^ w9 ^ w7;
w23 = (n << 1) | (n >>> 31);
t = (w23 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0;
e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t;
// 24
n = w21 ^ w16 ^ w10 ^ w8;
w24 = (n << 1) | (n >>> 31);
t = (w24 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0;
e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t;
// 25
n = w22 ^ w17 ^ w11 ^ w9;
w25 = (n << 1) | (n >>> 31);
t = (w25 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0;
e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t;
// 26
n = w23 ^ w18 ^ w12 ^ w10;
w26 = (n << 1) | (n >>> 31);
t = (w26 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0;
e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t;
// 27
n = w24 ^ w19 ^ w13 ^ w11;
w27 = (n << 1) | (n >>> 31);
t = (w27 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0;
e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t;
// 28
n = w25 ^ w20 ^ w14 ^ w12;
w28 = (n << 1) | (n >>> 31);
t = (w28 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0;
e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t;
// 29
n = w26 ^ w21 ^ w15 ^ w13;
w29 = (n << 1) | (n >>> 31);
t = (w29 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0;
e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t;
// 30
n = w27 ^ w22 ^ w16 ^ w14;
w30 = (n << 1) | (n >>> 31);
t = (w30 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0;
e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t;
// 31
n = w28 ^ w23 ^ w17 ^ w15;
w31 = (n << 1) | (n >>> 31);
t = (w31 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0;
e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t;
// 32
n = w29 ^ w24 ^ w18 ^ w16;
w32 = (n << 1) | (n >>> 31);
t = (w32 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0;
e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t;
// 33
n = w30 ^ w25 ^ w19 ^ w17;
w33 = (n << 1) | (n >>> 31);
t = (w33 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0;
e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t;
// 34
n = w31 ^ w26 ^ w20 ^ w18;
w34 = (n << 1) | (n >>> 31);
t = (w34 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0;
e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t;
// 35
n = w32 ^ w27 ^ w21 ^ w19;
w35 = (n << 1) | (n >>> 31);
t = (w35 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0;
e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t;
// 36
n = w33 ^ w28 ^ w22 ^ w20;
w36 = (n << 1) | (n >>> 31);
t = (w36 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0;
e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t;
// 37
n = w34 ^ w29 ^ w23 ^ w21;
w37 = (n << 1) | (n >>> 31);
t = (w37 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0;
e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t;
// 38
n = w35 ^ w30 ^ w24 ^ w22;
w38 = (n << 1) | (n >>> 31);
t = (w38 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0;
e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t;
// 39
n = w36 ^ w31 ^ w25 ^ w23;
w39 = (n << 1) | (n >>> 31);
t = (w39 + ((a << 5) | (a >>> 27)) + e + (b ^ c ^ d) + 0x6ed9eba1 )|0;
e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t;
// 40
n = w37 ^ w32 ^ w26 ^ w24;
w40 = (n << 1) | (n >>> 31);
t = (w40 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0;
e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t;
// 41
n = w38 ^ w33 ^ w27 ^ w25;
w41 = (n << 1) | (n >>> 31);
t = (w41 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0;
e = d; d = c; c = (b << 30) | (b >>> 2); b = a; a = t;
// 42
n = w39 ^ w34 ^ w28 ^ w26;
w42 = (n << 1) | (n >>> 31);
t = (w42 + ((a << 5) | (a >>> 27)) + e + ((b & c) | (b & d) | (c & d)) - 0x70e44324 )|0;
e = d;
gitextract_csuw1e3z/ ├── .editorconfig ├── .esmrc ├── .gitignore ├── .npmignore ├── .prettierignore ├── .prettierrc ├── .travis.yml ├── LICENSE ├── README.md ├── build.js ├── package.json ├── src/ │ ├── aes/ │ │ ├── aes.asm.d.ts │ │ ├── aes.asm.js │ │ ├── aes.ts │ │ ├── cbc.ts │ │ ├── ccm.ts │ │ ├── cfb.ts │ │ ├── cmac.ts │ │ ├── ctr.ts │ │ ├── ecb.ts │ │ ├── exports.ts │ │ ├── gcm.ts │ │ └── ofb.ts │ ├── bignum/ │ │ ├── bigint.asm.d.ts │ │ ├── bigint.asm.js │ │ ├── bignum.ts │ │ └── extgcd.ts │ ├── entry-default.ts │ ├── entry-export_all.ts │ ├── hash/ │ │ ├── hash.ts │ │ ├── sha1/ │ │ │ ├── sha1.asm.d.ts │ │ │ ├── sha1.asm.js │ │ │ └── sha1.ts │ │ ├── sha256/ │ │ │ ├── sha256.asm.d.ts │ │ │ ├── sha256.asm.js │ │ │ └── sha256.ts │ │ └── sha512/ │ │ ├── sha512.asm.d.ts │ │ ├── sha512.asm.js │ │ └── sha512.ts │ ├── hmac/ │ │ ├── hmac-sha1.ts │ │ ├── hmac-sha256.ts │ │ ├── hmac-sha512.ts │ │ └── hmac.ts │ ├── other/ │ │ ├── errors.ts │ │ ├── exportedUtils.ts │ │ ├── get-random-values.ts │ │ └── utils.ts │ ├── pbkdf2/ │ │ ├── pbkdf2-core.ts │ │ ├── pbkdf2-hmac-sha1.ts │ │ ├── pbkdf2-hmac-sha256.ts │ │ └── pbkdf2-hmac-sha512.ts │ └── rsa/ │ ├── pkcs1.ts │ └── rsa.ts ├── test/ │ ├── aes.js │ ├── bignum.js │ ├── rsa.js │ ├── sha1.js │ ├── sha256.js │ └── sha512.js ├── tsconfig.json └── tslint.json
SYMBOL INDEX (255 symbols across 39 files)
FILE: build.js
method onwarn (line 59) | onwarn(warning, warn) {
method onwarn (line 87) | onwarn(warning, warn) {
FILE: src/aes/aes.asm.d.ts
type AES_mode (line 1) | type AES_mode = 'ECB' | 'CBC' | 'CFB' | 'OFB' | 'CTR' | 'CCM';
class AES_asm (line 2) | class AES_asm {
FILE: src/aes/aes.asm.js
function ginit (line 22) | function ginit() {
function gmul (line 50) | function gmul(a, b) {
function ginv (line 61) | function ginv(a) {
function aes_init (line 97) | function aes_init() {
function set_key (line 188) | function set_key(ks, k0, k1, k2, k3, k4, k5, k6, k7) {
function _core (line 252) | function _core(k, s, t, r, x0, x1, x2, x3) {
function _ecb_enc (line 297) | function _ecb_enc(x0, x1, x2, x3) {
function _ecb_dec (line 320) | function _ecb_dec(x0, x1, x2, x3) {
function _cbc_enc (line 348) | function _cbc_enc(x0, x1, x2, x3) {
function _cbc_dec (line 376) | function _cbc_dec(x0, x1, x2, x3) {
function _cfb_enc (line 413) | function _cfb_enc(x0, x1, x2, x3) {
function _cfb_dec (line 442) | function _cfb_dec(x0, x1, x2, x3) {
function _ofb (line 475) | function _ofb(x0, x1, x2, x3) {
function _ctr (line 508) | function _ctr(x0, x1, x2, x3) {
function _gcm_mac (line 541) | function _gcm_mac(x0, x1, x2, x3) {
function set_rounds (line 596) | function set_rounds(r) {
function set_state (line 610) | function set_state(s0, s1, s2, s3) {
function set_iv (line 631) | function set_iv(i0, i1, i2, i3) {
function set_nonce (line 652) | function set_nonce(n0, n1, n2, n3) {
function set_mask (line 673) | function set_mask(m0, m1, m2, m3) {
function set_counter (line 694) | function set_counter(c0, c1, c2, c3) {
function get_state (line 713) | function get_state(pos) {
function get_iv (line 745) | function get_iv(pos) {
function gcm_init (line 775) | function gcm_init() {
function cipher (line 792) | function cipher(mode, pos, len) {
function mac (line 843) | function mac(mode, pos, len) {
FILE: src/aes/aes.ts
class AES (line 5) | class AES {
method constructor (line 13) | constructor(key: Uint8Array, iv: Uint8Array | undefined, padding = tru...
method AES_Encrypt_process (line 55) | AES_Encrypt_process(data: Uint8Array): Uint8Array {
method AES_Encrypt_finish (line 98) | AES_Encrypt_finish(): Uint8Array {
method AES_Decrypt_process (line 134) | AES_Decrypt_process(data: Uint8Array): Uint8Array {
method AES_Decrypt_finish (line 183) | AES_Decrypt_finish(): Uint8Array {
FILE: src/aes/cbc.ts
class AES_CBC (line 4) | class AES_CBC {
method encrypt (line 7) | static encrypt(data: Uint8Array, key: Uint8Array, padding: boolean = t...
method decrypt (line 11) | static decrypt(data: Uint8Array, key: Uint8Array, padding: boolean = t...
method constructor (line 15) | constructor(key: Uint8Array, iv?: Uint8Array, padding: boolean = true,...
method encrypt (line 19) | encrypt(data: Uint8Array): Uint8Array {
method decrypt (line 26) | decrypt(data: Uint8Array): Uint8Array {
FILE: src/aes/ccm.ts
class AES_CCM (line 24) | class AES_CCM {
method encrypt (line 33) | static encrypt(
method decrypt (line 42) | static decrypt(
method constructor (line 52) | constructor(
method encrypt (line 91) | encrypt(data: Uint8Array): Uint8Array {
method decrypt (line 104) | decrypt(data: Uint8Array): Uint8Array {
method AES_CCM_calculate_iv (line 117) | AES_CCM_calculate_iv(): void {
method _cbc_mac_process (line 152) | _cbc_mac_process(data: Uint8Array): void {
method AES_CCM_Encrypt_process (line 169) | AES_CCM_Encrypt_process(data: Uint8Array): Uint8Array {
method AES_CCM_Encrypt_finish (line 218) | AES_CCM_Encrypt_finish(): Uint8Array {
method AES_CCM_Decrypt_process (line 246) | AES_CCM_Decrypt_process(data: Uint8Array): Uint8Array {
method AES_CCM_Decrypt_finish (line 292) | AES_CCM_Decrypt_finish(): Uint8Array {
method AES_CTR_set_options (line 327) | private AES_CTR_set_options(nonce: Uint8Array, counter: number, size: ...
FILE: src/aes/cfb.ts
class AES_CFB (line 4) | class AES_CFB {
method encrypt (line 7) | static encrypt(data: Uint8Array, key: Uint8Array, iv?: Uint8Array): Ui...
method decrypt (line 11) | static decrypt(data: Uint8Array, key: Uint8Array, iv?: Uint8Array): Ui...
method constructor (line 15) | constructor(key: Uint8Array, iv?: Uint8Array, aes?: AES) {
method encrypt (line 20) | encrypt(data: Uint8Array): Uint8Array {
method decrypt (line 27) | decrypt(data: Uint8Array): Uint8Array {
FILE: src/aes/cmac.ts
function mul2 (line 4) | function mul2(data: Uint8Array): void {
class AES_CMAC (line 12) | class AES_CMAC {
method bytes (line 19) | static bytes(data: Uint8Array, key: Uint8Array): Uint8Array {
method constructor (line 23) | constructor(key: Uint8Array) {
method process (line 32) | process(data: Uint8Array): this {
method finish (line 46) | finish(): this {
FILE: src/aes/ctr.ts
class AES_CTR (line 5) | class AES_CTR {
method encrypt (line 8) | static encrypt(data: Uint8Array, key: Uint8Array, nonce: Uint8Array): ...
method decrypt (line 12) | static decrypt(data: Uint8Array, key: Uint8Array, nonce: Uint8Array): ...
method constructor (line 16) | constructor(key: Uint8Array, nonce: Uint8Array, aes?: AES) {
method encrypt (line 23) | encrypt(data: Uint8Array): Uint8Array {
method decrypt (line 30) | decrypt(data: Uint8Array): Uint8Array {
method AES_CTR_set_options (line 37) | private AES_CTR_set_options(nonce: Uint8Array, counter?: number, size?...
FILE: src/aes/ecb.ts
class AES_ECB (line 4) | class AES_ECB {
method encrypt (line 6) | static encrypt(data: Uint8Array, key: Uint8Array, padding: boolean = f...
method decrypt (line 10) | static decrypt(data: Uint8Array, key: Uint8Array, padding: boolean = f...
method constructor (line 14) | constructor(key: Uint8Array, padding: boolean = false, aes?: AES) {
method encrypt (line 18) | encrypt(data: Uint8Array): Uint8Array {
method decrypt (line 25) | decrypt(data: Uint8Array): Uint8Array {
FILE: src/aes/gcm.ts
class AES_GCM (line 8) | class AES_GCM {
method encrypt (line 15) | static encrypt(
method decrypt (line 25) | static decrypt(
method constructor (line 35) | constructor(
method encrypt (line 109) | encrypt(data: Uint8Array) {
method decrypt (line 113) | decrypt(data: Uint8Array) {
method AES_GCM_Encrypt_process (line 117) | AES_GCM_Encrypt_process(data: Uint8Array): Uint8Array {
method AES_GCM_Encrypt_finish (line 162) | AES_GCM_Encrypt_finish(): Uint8Array {
method AES_GCM_Decrypt_process (line 212) | AES_GCM_Decrypt_process(data: Uint8Array): Uint8Array {
method AES_GCM_Decrypt_finish (line 258) | AES_GCM_Decrypt_finish() {
method AES_GCM_decrypt (line 314) | private AES_GCM_decrypt(data: Uint8Array): Uint8Array {
method AES_GCM_encrypt (line 325) | private AES_GCM_encrypt(data: Uint8Array): Uint8Array {
method _gcm_mac_process (line 336) | _gcm_mac_process(data: Uint8Array) {
FILE: src/aes/ofb.ts
class AES_OFB (line 4) | class AES_OFB {
method encrypt (line 7) | static encrypt(data: Uint8Array, key: Uint8Array, iv?: Uint8Array): Ui...
method decrypt (line 11) | static decrypt(data: Uint8Array, key: Uint8Array, iv?: Uint8Array): Ui...
method constructor (line 15) | constructor(key: Uint8Array, iv?: Uint8Array, aes?: AES) {
method encrypt (line 19) | encrypt(data: Uint8Array): Uint8Array {
method decrypt (line 26) | decrypt(data: Uint8Array): Uint8Array {
FILE: src/bignum/bigint.asm.d.ts
type bigintresult (line 1) | interface bigintresult {
FILE: src/bignum/bigint.asm.js
function sreset (line 24) | function sreset ( p ) {
function salloc (line 30) | function salloc ( l ) {
function sfree (line 37) | function sfree ( l ) {
function cp (line 48) | function cp ( l, A, B ) {
function z (line 67) | function z ( l, z, A ) {
function neg (line 92) | function neg ( A, lA, R, lR ) {
function cmp (line 122) | function cmp ( A, lA, B, lB ) {
function tst (line 155) | function tst ( A, lA ) {
function add (line 180) | function add ( A, lA, B, lB, R, lR ) {
function sub (line 238) | function sub ( A, lA, B, lB, R, lR ) {
function mul (line 315) | function mul ( A, lA, B, lB, R, lR ) {
function sqr (line 886) | function sqr ( A, lA, R ) {
function div (line 1762) | function div ( N, lN, D, lD, Q ) {
function mredc (line 1950) | function mredc ( A, lA, N, lN, y, R ) {
FILE: src/bignum/bignum.ts
function _half_imul (line 13) | function _half_imul(a: number, b: number) {
class BigNumber (line 29) | class BigNumber {
method fromString (line 38) | static fromString(str: string): BigNumber {
method fromNumber (line 43) | static fromNumber(num: number): BigNumber {
method fromArrayBuffer (line 67) | static fromArrayBuffer(buffer: ArrayBuffer): BigNumber {
method fromConfig (line 71) | static fromConfig(obj: { limbs: Uint32Array; bitLength: number; sign: ...
method constructor (line 79) | constructor(num?: Uint8Array) {
method toString (line 112) | toString(radix: number): string {
method toBytes (line 139) | toBytes(): Uint8Array {
method valueOf (line 158) | valueOf(): number {
method clamp (line 189) | clamp(b: number): BigNumber {
method slice (line 210) | slice(f: number, b?: number): BigNumber {
method negate (line 248) | negate(): BigNumber {
method compare (line 258) | compare(that: BigNumber): number {
method add (line 276) | add(that: BigNumber): BigNumber {
method subtract (line 331) | subtract(that: BigNumber): BigNumber {
method square (line 335) | square(): BigNumber {
method divide (line 366) | divide(that: BigNumber): { quotient: BigNumber; remainder: BigNumber } {
method multiply (line 413) | multiply(that: BigNumber): BigNumber {
method isMillerRabinProbablePrime (line 449) | public isMillerRabinProbablePrime(rounds: number): boolean {
method isProbablePrime (line 485) | isProbablePrime(paranoia: number = 80): boolean {
class Modulus (line 531) | class Modulus extends BigNumber {
method constructor (line 538) | constructor(number: BigNumber) {
method reduce (line 580) | reduce(a: BigNumber): BigNumber {
method inverse (line 591) | inverse(a: BigNumber): BigNumber {
method power (line 605) | power(g: BigNumber, e: BigNumber): BigNumber {
method _Montgomery_reduce (line 669) | static _Montgomery_reduce(a: BigNumber, n: Modulus): BigNumber {
FILE: src/bignum/extgcd.ts
function Number_extGCD (line 3) | function Number_extGCD(a: number, b: number): { gcd: number; x: number; ...
function BigNumber_extGCD (line 51) | function BigNumber_extGCD(a: BigNumber, b: BigNumber): { gcd: BigNumber;...
FILE: src/hash/hash.ts
method reset (line 16) | reset() {
method process (line 26) | process(data: Uint8Array) {
method finish (line 57) | finish() {
FILE: src/hash/sha1/sha1.asm.d.ts
type sha1result (line 1) | interface sha1result {
FILE: src/hash/sha1/sha1.asm.js
function _core (line 15) | function _core ( w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, ...
function _core_heap (line 504) | function _core_heap ( offset ) {
function _state_to_heap (line 528) | function _state_to_heap ( output ) {
function reset (line 553) | function reset () {
function init (line 562) | function init ( h0, h1, h2, h3, h4, total0, total1 ) {
function process (line 581) | function process ( offset, length ) {
function finish (line 607) | function finish ( offset, length, output ) {
function hmac_reset (line 666) | function hmac_reset () {
function _hmac_opad (line 676) | function _hmac_opad () {
function hmac_init (line 686) | function hmac_init ( p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p...
function hmac_finish (line 762) | function hmac_finish ( offset, length, output ) {
function pbkdf2_generate_block (line 791) | function pbkdf2_generate_block ( offset, length, block, count, output ) {
FILE: src/hash/sha1/sha1.ts
class Sha1 (line 8) | class Sha1 extends Hash<sha1result> {
method constructor (line 14) | constructor() {
FILE: src/hash/sha256/sha256.asm.d.ts
type sha256result (line 1) | interface sha256result {
FILE: src/hash/sha256/sha256.asm.js
function _core (line 15) | function _core ( w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, ...
function _core_heap (line 422) | function _core_heap ( offset ) {
function _state_to_heap (line 446) | function _state_to_heap ( output ) {
function reset (line 483) | function reset () {
function init (line 495) | function init ( h0, h1, h2, h3, h4, h5, h6, h7, total0, total1 ) {
function process (line 520) | function process ( offset, length ) {
function finish (line 546) | function finish ( offset, length, output ) {
function hmac_reset (line 606) | function hmac_reset () {
function _hmac_opad (line 619) | function _hmac_opad () {
function hmac_init (line 632) | function hmac_init ( p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p...
function hmac_finish (line 714) | function hmac_finish ( offset, length, output ) {
function pbkdf2_generate_block (line 744) | function pbkdf2_generate_block ( offset, length, block, count, output ) {
FILE: src/hash/sha256/sha256.ts
class Sha256 (line 8) | class Sha256 extends Hash<sha256result> {
method constructor (line 14) | constructor() {
FILE: src/hash/sha512/sha512.asm.d.ts
type sha512result (line 1) | interface sha512result {
FILE: src/hash/sha512/sha512.asm.js
function _core (line 18) | function _core ( w0h, w0l, w1h, w1l, w2h, w2l, w3h, w3l, w4h, w4l, w5h, ...
function _core_heap (line 2522) | function _core_heap ( offset ) {
function _state_to_heap (line 2562) | function _state_to_heap ( output ) {
function reset (line 2631) | function reset () {
function init (line 2652) | function init ( h0h, h0l, h1h, h1l, h2h, h2l, h3h, h3l, h4h, h4l, h5h, h...
function process (line 2693) | function process ( offset, length ) {
function finish (line 2719) | function finish ( offset, length, output ) {
function hmac_reset (line 2779) | function hmac_reset () {
function _hmac_opad (line 2800) | function _hmac_opad () {
function hmac_init (line 2821) | function hmac_init ( p0h, p0l, p1h, p1l, p2h, p2l, p3h, p3l, p4h, p4l, p...
function hmac_finish (line 2967) | function hmac_finish ( offset, length, output ) {
function pbkdf2_generate_block (line 3013) | function pbkdf2_generate_block ( offset, length, block, count, output ) {
FILE: src/hash/sha512/sha512.ts
class Sha512 (line 8) | class Sha512 extends Hash<sha512result> {
method constructor (line 14) | constructor() {
FILE: src/hmac/hmac-sha1.ts
class HmacSha1 (line 7) | class HmacSha1 extends Hmac<Hash<sha1result>> {
method constructor (line 10) | constructor(password: Uint8Array, verify?: Uint8Array) {
method reset (line 27) | reset(): this {
method finish (line 53) | finish(): this {
FILE: src/hmac/hmac-sha256.ts
class HmacSha256 (line 7) | class HmacSha256 extends Hmac<Hash<sha256result>> {
method constructor (line 10) | constructor(password: Uint8Array, verify?: Uint8Array) {
method reset (line 27) | reset(): this {
method finish (line 54) | finish(): this {
FILE: src/hmac/hmac-sha512.ts
class HmacSha512 (line 7) | class HmacSha512 extends Hmac<Hash<sha512result>> {
method constructor (line 10) | constructor(password: Uint8Array, verify?: Uint8Array) {
method reset (line 27) | reset(): this {
method finish (line 68) | finish() {
FILE: src/hmac/hmac.ts
method constructor (line 15) | protected constructor(hash: T, password: Uint8Array, verify?: Uint8Array) {
method process (line 38) | process(data: Uint8Array): this {
method finish (line 46) | finish(): this {
method _hmac_init_verify (line 78) | _hmac_init_verify(verify: Uint8Array): void {
function _hmac_key (line 85) | function _hmac_key(hash: Hash<sha1result | sha256result | sha512result>,...
FILE: src/other/errors.ts
class IllegalStateError (line 1) | class IllegalStateError extends Error {
method constructor (line 2) | constructor(...args: any[]) {
class IllegalArgumentError (line 8) | class IllegalArgumentError extends Error {
method constructor (line 9) | constructor(...args: any[]) {
class SecurityError (line 15) | class SecurityError extends Error {
method constructor (line 16) | constructor(...args: any[]) {
FILE: src/other/get-random-values.ts
function getRandomValues (line 1) | function getRandomValues(buf: Uint32Array | Uint8Array): void {
FILE: src/other/utils.ts
function string_to_bytes (line 4) | function string_to_bytes(str: string, utf8: boolean = false): Uint8Array {
function hex_to_bytes (line 38) | function hex_to_bytes(str: string): Uint8Array {
function base64_to_bytes (line 51) | function base64_to_bytes(str: string): Uint8Array {
function bytes_to_string (line 55) | function bytes_to_string(bytes: Uint8Array, utf8: boolean = false): stri...
function bytes_to_hex (line 90) | function bytes_to_hex(arr: Uint8Array): string {
function bytes_to_base64 (line 100) | function bytes_to_base64(arr: Uint8Array): string {
function pow2_ceil (line 104) | function pow2_ceil(a: number): number {
function is_number (line 115) | function is_number(a: number): boolean {
function is_string (line 119) | function is_string(a: string): boolean {
function is_buffer (line 123) | function is_buffer(a: ArrayBuffer): boolean {
function is_bytes (line 127) | function is_bytes(a: Uint8Array): boolean {
function is_typed_array (line 131) | function is_typed_array(a: any): boolean {
function _heap_init (line 144) | function _heap_init(heap?: Uint8Array, heapSize?: number): Uint8Array {
function _heap_write (line 154) | function _heap_write(heap: Uint8Array, hpos: number, data: Uint8Array, d...
function joinBytes (line 163) | function joinBytes(...arg: Uint8Array[]): Uint8Array {
FILE: src/pbkdf2/pbkdf2-core.ts
function pbkdf2core (line 5) | function pbkdf2core(hmac: HmacSha1 | HmacSha256 | HmacSha512, salt: Uint...
FILE: src/pbkdf2/pbkdf2-hmac-sha1.ts
function Pbkdf2HmacSha1 (line 4) | function Pbkdf2HmacSha1(password: Uint8Array, salt: Uint8Array, count: n...
FILE: src/pbkdf2/pbkdf2-hmac-sha256.ts
function Pbkdf2HmacSha256 (line 4) | function Pbkdf2HmacSha256(password: Uint8Array, salt: Uint8Array, count:...
FILE: src/pbkdf2/pbkdf2-hmac-sha512.ts
function Pbkdf2HmacSha512 (line 4) | function Pbkdf2HmacSha512(password: Uint8Array, salt: Uint8Array, count:...
FILE: src/rsa/pkcs1.ts
class RSA_OAEP (line 9) | class RSA_OAEP {
method constructor (line 14) | constructor(key: Uint8Array[], hash: Sha1 | Sha256 | Sha512, label?: U...
method encrypt (line 26) | encrypt(data: Uint8Array, random?: Uint8Array): Uint8Array {
method decrypt (line 61) | decrypt(data: Uint8Array): Uint8Array {
method RSA_MGF1_generate (line 105) | RSA_MGF1_generate(seed: Uint8Array, length: number = 0): Uint8Array {
class RSA_PSS (line 132) | class RSA_PSS {
method constructor (line 137) | constructor(key: Uint8Array[], hash: Sha1 | Sha256 | Sha512, saltLengt...
method sign (line 152) | sign(data: Uint8Array, random?: Uint8Array): Uint8Array {
method verify (line 200) | verify(signature: Uint8Array, data: Uint8Array): void {
method RSA_MGF1_generate (line 248) | RSA_MGF1_generate(seed: Uint8Array, length: number = 0): Uint8Array {
class RSA_PKCS1_v1_5 (line 275) | class RSA_PKCS1_v1_5 {
method constructor (line 278) | constructor(key: Uint8Array[], hash: Sha1 | Sha256 | Sha512) {
method sign (line 283) | sign(data: Uint8Array): Uint8Array {
method verify (line 318) | verify(signature: Uint8Array, data: Uint8Array): void {
constant HASH_PREFIXES (line 364) | const HASH_PREFIXES: {
function getHashPrefix (line 437) | function getHashPrefix(hash: Sha1 | Sha256 | Sha512): Uint8Array {
FILE: src/rsa/rsa.ts
type key (line 4) | type key = {
class RSA (line 15) | class RSA {
method constructor (line 19) | constructor(key: Uint8Array[]) {
method encrypt (line 41) | encrypt(msg: BigNumber): this {
method decrypt (line 63) | decrypt(msg: BigNumber): this {
Condensed preview — 61 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (576K chars).
[
{
"path": ".editorconfig",
"chars": 102,
"preview": "[*]\nend_of_line = lf\ninsert_final_newline = true\ncharset = utf-8\nindent_style = space\nindent_size = 2\n"
},
{
"path": ".esmrc",
"chars": 100,
"preview": "{\n \"mode\": \"all\",\n \"cjs\": {\n \"namedExports\": true,\n \"vars\": true,\n \"interop\": true\n }\n}\n"
},
{
"path": ".gitignore",
"chars": 124,
"preview": "asmcrypto*.js\nasmcrypto*.mjs\nasmcrypto*.map\ntest/aes.asm.js\ntest/aes.asm.js.map\ndoc/\nnode_modules/\n.idea/\ndist_es5\ndist_"
},
{
"path": ".npmignore",
"chars": 57,
"preview": "doc/\nnode_modules/\n.idea/\npackage-lock.json\n*.ts\n!*.d.ts\n"
},
{
"path": ".prettierignore",
"chars": 8,
"preview": "*.asm.*\n"
},
{
"path": ".prettierrc",
"chars": 73,
"preview": "{\n \"printWidth\": 120,\n \"singleQuote\": true,\n \"trailingComma\": \"all\"\n}\n"
},
{
"path": ".travis.yml",
"chars": 67,
"preview": "language: node_js\nnode_js:\n- '10'\n- '12'\n- '14'\nscript:\n npm test\n"
},
{
"path": "LICENSE",
"chars": 1083,
"preview": "The MIT License (MIT)\n\nCopyright (c) 2013 Artem S Vybornov\n\nPermission is hereby granted, free of charge, to any person "
},
{
"path": "README.md",
"chars": 91,
"preview": "asmCrypto \n=========\n\nNot maintained anymore, use a native or WASM implementation instead.\n"
},
{
"path": "build.js",
"chars": 3780,
"preview": "import * as fs from 'fs-extra';\nimport ts from 'typescript';\nimport * as rollup from 'rollup';\n\n(async function() {\n //"
},
{
"path": "package.json",
"chars": 1435,
"preview": "{\n \"name\": \"asmcrypto.js\",\n \"version\": \"2.3.2\",\n \"description\": \"Asm.js implementation of WebCrypto API\",\n \"homepage"
},
{
"path": "src/aes/aes.asm.d.ts",
"chars": 2810,
"preview": "declare type AES_mode = 'ECB' | 'CBC' | 'CFB' | 'OFB' | 'CTR' | 'CCM';\nexport class AES_asm {\n constructor(foreign: any"
},
{
"path": "src/aes/aes.asm.js",
"chars": 25099,
"preview": "/**\n * @file {@link http://asmjs.org Asm.js} implementation of the {@link https://en.wikipedia.org/wiki/Advanced_Encrypt"
},
{
"path": "src/aes/aes.ts",
"chars": 5744,
"preview": "import { AES_asm, AES_mode } from './aes.asm';\nimport { _heap_init, _heap_write, is_bytes } from '../other/utils';\nimpor"
},
{
"path": "src/aes/cbc.ts",
"chars": 959,
"preview": "import { AES } from './aes';\nimport { joinBytes } from '../other/utils';\n\nexport class AES_CBC {\n private aes: AES;\n\n "
},
{
"path": "src/aes/ccm.ts",
"chars": 10636,
"preview": "/**\n * Counter with CBC-MAC (CCM)\n *\n * Due to JS limitations (52 bits of Number precision) maximum encrypted message le"
},
{
"path": "src/aes/cfb.ts",
"chars": 892,
"preview": "import { AES } from './aes';\nimport { joinBytes } from '../other/utils';\n\nexport class AES_CFB {\n private aes: AES;\n\n "
},
{
"path": "src/aes/cmac.ts",
"chars": 1742,
"preview": "import { AES_ECB } from './ecb';\nimport { AES_CBC } from './cbc';\n\nfunction mul2(data: Uint8Array): void {\n const t = d"
},
{
"path": "src/aes/ctr.ts",
"chars": 2070,
"preview": "import { AES } from './aes';\nimport { IllegalArgumentError } from '../other/errors';\nimport { joinBytes } from '../other"
},
{
"path": "src/aes/ecb.ts",
"chars": 909,
"preview": "import { AES } from './aes';\nimport { joinBytes } from '../other/utils';\n\nexport class AES_ECB {\n private aes: AES;\n s"
},
{
"path": "src/aes/exports.ts",
"chars": 213,
"preview": "// shared asm.js module and heap\nimport { AES_asm } from './aes.asm';\n\nexport var _AES_heap_instance = new Uint8Array(0x"
},
{
"path": "src/aes/gcm.ts",
"chars": 9758,
"preview": "import { IllegalArgumentError, IllegalStateError, SecurityError } from '../other/errors';\nimport { _heap_write } from '."
},
{
"path": "src/aes/ofb.ts",
"chars": 864,
"preview": "import { AES } from './aes';\nimport { joinBytes } from '../other/utils';\n\nexport class AES_OFB {\n private aes: AES;\n\n "
},
{
"path": "src/bignum/bigint.asm.d.ts",
"chars": 1095,
"preview": "declare interface bigintresult {\n sreset: (n?: number) => number;\n salloc: (n?: number) => number;\n sfree: (n?: numbe"
},
{
"path": "src/bignum/bigint.asm.js",
"chars": 91010,
"preview": "/**\n * Integers are represented as little endian array of 32-bit limbs.\n * Limbs number is a power of 2 and a multiple o"
},
{
"path": "src/bignum/bignum.ts",
"chars": 18575,
"preview": "import { bigint_asm, bigintresult } from './bigint.asm';\nimport { string_to_bytes } from '../other/utils';\nimport { Ille"
},
{
"path": "src/bignum/extgcd.ts",
"chars": 1758,
"preview": "import { BigNumber } from './bignum';\n\nexport function Number_extGCD(a: number, b: number): { gcd: number; x: number; y:"
},
{
"path": "src/entry-default.ts",
"chars": 418,
"preview": "export * from './other/exportedUtils';\n\nexport * from './other/errors';\nexport * from './aes/cbc';\nexport * from './aes/"
},
{
"path": "src/entry-export_all.ts",
"chars": 1154,
"preview": "export {\n string_to_bytes,\n hex_to_bytes,\n base64_to_bytes,\n bytes_to_string,\n bytes_to_hex,\n bytes_to_base64,\n} f"
},
{
"path": "src/hash/hash.ts",
"chars": 1614,
"preview": "import { _heap_write } from '../other/utils';\nimport { IllegalStateError } from '../other/errors';\nimport { sha1result }"
},
{
"path": "src/hash/sha1/sha1.asm.d.ts",
"chars": 1415,
"preview": "declare interface sha1result {\n // SHA1\n reset: () => void;\n init: (h0: number, h1: number, h2: number, h3: number, h"
},
{
"path": "src/hash/sha1/sha1.asm.js",
"chars": 29294,
"preview": "export var sha1_asm = function ( stdlib, foreign, buffer ) {\n \"use asm\";\n\n // SHA256 state\n var H0 = 0, H1 = 0,"
},
{
"path": "src/hash/sha1/sha1.ts",
"chars": 540,
"preview": "import { sha1_asm, sha1result } from './sha1.asm';\nimport { Hash } from '../hash';\nimport { _heap_init } from '../../oth"
},
{
"path": "src/hash/sha256/sha256.asm.d.ts",
"chars": 1421,
"preview": "declare interface sha256result {\n // SHA1\n reset: () => void;\n init: (h0: number, h1: number, h2: number, h3: number,"
},
{
"path": "src/hash/sha256/sha256.asm.js",
"chars": 35582,
"preview": "export var sha256_asm = function ( stdlib, foreign, buffer ) {\n \"use asm\";\n\n // SHA256 state\n var H0 = 0, H1 = "
},
{
"path": "src/hash/sha256/sha256.ts",
"chars": 564,
"preview": "import { sha256_asm, sha256result } from './sha256.asm';\nimport { Hash } from '../hash';\nimport { _heap_init } from '../"
},
{
"path": "src/hash/sha512/sha512.asm.d.ts",
"chars": 1715,
"preview": "declare interface sha512result {\n // SHA1\n reset: () => void;\n init: (h0: number, h1: number, h2: number, h3: number,"
},
{
"path": "src/hash/sha512/sha512.asm.js",
"chars": 170151,
"preview": "export var sha512_asm = function ( stdlib, foreign, buffer ) {\n \"use asm\";\n\n // SHA512 state\n var H0h = 0, H0l "
},
{
"path": "src/hash/sha512/sha512.ts",
"chars": 565,
"preview": "import { sha512_asm, sha512result } from './sha512.asm';\nimport { Hash } from '../hash';\nimport { _heap_init } from '../"
},
{
"path": "src/hmac/hmac-sha1.ts",
"chars": 2792,
"preview": "import { Hmac } from './hmac';\nimport { _sha1_hash_size, Sha1 } from '../hash/sha1/sha1';\nimport { IllegalStateError } f"
},
{
"path": "src/hmac/hmac-sha256.ts",
"chars": 2893,
"preview": "import { Hmac } from './hmac';\nimport { IllegalStateError } from '../other/errors';\nimport { _sha256_hash_size, Sha256 }"
},
{
"path": "src/hmac/hmac-sha512.ts",
"chars": 4033,
"preview": "import { Hmac } from './hmac';\nimport { IllegalStateError } from '../other/errors';\nimport { _sha512_hash_size, Sha512 }"
},
{
"path": "src/hmac/hmac.ts",
"chars": 2847,
"preview": "import { IllegalArgumentError, IllegalStateError } from '../other/errors';\nimport { Hash } from '../hash/hash';\nimport {"
},
{
"path": "src/other/errors.ts",
"chars": 549,
"preview": "export class IllegalStateError extends Error {\n constructor(...args: any[]) {\n super(...args);\n Object.create(Err"
},
{
"path": "src/other/exportedUtils.ts",
"chars": 160,
"preview": "/**\n * Util exports\n */\n\nexport {\n string_to_bytes,\n hex_to_bytes,\n base64_to_bytes,\n bytes_to_string,\n bytes_to_he"
},
{
"path": "src/other/get-random-values.ts",
"chars": 682,
"preview": "export function getRandomValues(buf: Uint32Array | Uint8Array): void {\n if (typeof process !== 'undefined') {\n const"
},
{
"path": "src/other/utils.ts",
"chars": 4896,
"preview": "const local_atob = typeof atob === 'undefined' ? (str: string) => Buffer.from(str, 'base64').toString('binary') : atob;\n"
},
{
"path": "src/pbkdf2/pbkdf2-core.ts",
"chars": 721,
"preview": "import { HmacSha1 } from \"../hmac/hmac-sha1\";\nimport { HmacSha256 } from \"../hmac/hmac-sha256\";\nimport { HmacSha512 } fr"
},
{
"path": "src/pbkdf2/pbkdf2-hmac-sha1.ts",
"chars": 297,
"preview": "import { HmacSha1 } from '../hmac/hmac-sha1';\nimport { pbkdf2core } from './pbkdf2-core';\n\nexport function Pbkdf2HmacSha"
},
{
"path": "src/pbkdf2/pbkdf2-hmac-sha256.ts",
"chars": 305,
"preview": "import { HmacSha256 } from '../hmac/hmac-sha256';\nimport { pbkdf2core } from './pbkdf2-core';\n\nexport function Pbkdf2Hma"
},
{
"path": "src/pbkdf2/pbkdf2-hmac-sha512.ts",
"chars": 305,
"preview": "import { HmacSha512 } from '../hmac/hmac-sha512';\nimport { pbkdf2core } from './pbkdf2-core';\n\nexport function Pbkdf2Hma"
},
{
"path": "src/rsa/pkcs1.ts",
"chars": 13157,
"preview": "import { RSA } from './rsa';\nimport { IllegalArgumentError, IllegalStateError, SecurityError } from '../other/errors';\ni"
},
{
"path": "src/rsa/rsa.ts",
"chars": 2577,
"preview": "import { BigNumber, Modulus } from '../bignum/bignum';\nimport { IllegalStateError } from '../other/errors';\n\nexport type"
},
{
"path": "test/aes.js",
"chars": 37182,
"preview": "import * as asmCrypto from '../asmcrypto.all.es8';\nimport chai from 'chai';\nconst expect = chai.expect;\n\ndescribe('AES',"
},
{
"path": "test/bignum.js",
"chars": 35573,
"preview": "import * as asmCrypto from '../asmcrypto.all.es8';\nimport chai from 'chai';\nconst expect = chai.expect;\n\ndescribe('Bignu"
},
{
"path": "test/rsa.js",
"chars": 9157,
"preview": "import * as asmCrypto from '../asmcrypto.all.es8';\nimport chai from 'chai';\nconst expect = chai.expect;\n\nconst pubKey = "
},
{
"path": "test/sha1.js",
"chars": 4620,
"preview": "import * as asmCrypto from '../asmcrypto.all.es8';\nimport chai from 'chai';\nconst expect = chai.expect;\n\ndescribe('SHA1'"
},
{
"path": "test/sha256.js",
"chars": 5058,
"preview": "import * as asmCrypto from '../asmcrypto.all.es8';\nimport chai from 'chai';\nconst expect = chai.expect;\n\ndescribe('SHA25"
},
{
"path": "test/sha512.js",
"chars": 5492,
"preview": "import * as asmCrypto from '../asmcrypto.all.es8';\nimport chai from 'chai';\nconst expect = chai.expect;\n\ndescribe('SHA51"
},
{
"path": "tsconfig.json",
"chars": 453,
"preview": "{\n \"compilerOptions\": {\n \"module\": \"ES6\",\n \"target\": \"es2017\",\n \"lib\": [\"es5\", \"dom\", \"dom.iterable\", \"es6\"],\n"
},
{
"path": "tslint.json",
"chars": 83,
"preview": "{\n \"extends\": [\"tslint-plugin-prettier\"],\n \"rules\": {\n \"prettier\": true\n }\n}\n"
}
]
About this extraction
This page contains the full source code of the vibornoff/asmcrypto.js GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 61 files (546.2 KB), approximately 236.1k tokens, and a symbol index with 255 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.