UNPKG

@miracl/client-js

Version:
1,537 lines (1,273 loc) 739 kB
'use strict'; /* Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ function AES() { var AES = function() { this.Nk = 0; this.Nr = 0; this.mode = 0; this.fkey = []; this.rkey = []; this.f = []; }; // AES constants AES.ECB = 0; AES.CBC = 1; AES.CFB1 = 2; AES.CFB2 = 3; AES.CFB4 = 5; AES.OFB1 = 14; AES.OFB2 = 15; AES.OFB4 = 17; AES.OFB8 = 21; AES.OFB16 = 29; AES.CTR1 = 30; AES.CTR2 = 31; AES.CTR4 = 33; AES.CTR8 = 37; AES.CTR16 = 45; AES.prototype = { /* reset cipher - mode or iv */ reset: function(m, iv) { var i; this.mode = m; for (i = 0; i < 16; i++) { this.f[i] = 0; } if (this.mode != AES.ECB && iv !== null) { for (i = 0; i < 16; i++) { this.f[i] = iv[i]; } } }, getreg: function() { var ir = [], i; for (i = 0; i < 16; i++) { ir[i] = this.f[i]; } return ir; }, increment: function() { var i; for (i = 0; i < 16; i++) { this.f[i]++; if ((this.f[i] & 0xff) != 0) { break; } } }, /* Initialise cipher */ init: function(m, nk, key, iv) { /* Key Scheduler. Create expanded encryption key */ var CipherKey = [], b = [], i, j, k, N, nr; nk /= 4; if (nk != 4 && nk != 6 && nk != 8) { return false; } nr = 6 + nk; this.Nk = nk; this.Nr = nr; this.reset(m, iv); N = 4 * (nr + 1); for (i = j = 0; i < nk; i++, j += 4) { for (k = 0; k < 4; k++) { b[k] = key[j + k]; } CipherKey[i] = AES.pack(b); } for (i = 0; i < nk; i++) { this.fkey[i] = CipherKey[i]; } for (j = nk, k = 0; j < N; j += nk, k++) { this.fkey[j] = this.fkey[j - nk] ^ AES.SubByte(AES.ROTL24(this.fkey[j - 1])) ^ (AES.rco[k]) & 0xff; for (i = 1; i < nk && (i + j) < N; i++) { this.fkey[i + j] = this.fkey[i + j - nk] ^ this.fkey[i + j - 1]; } } /* now for the expanded decrypt key in reverse order */ for (j = 0; j < 4; j++) { this.rkey[j + N - 4] = this.fkey[j]; } for (i = 4; i < N - 4; i += 4) { k = N - 4 - i; for (j = 0; j < 4; j++) { this.rkey[k + j] = AES.InvMixCol(this.fkey[i + j]); } } for (j = N - 4; j < N; j++) { this.rkey[j - N + 4] = this.fkey[j]; } }, /* Encrypt a single block */ ecb_encrypt: function(buff) { var b = [], p = [], q = [], t, i, j, k; for (i = j = 0; i < 4; i++, j += 4) { for (k = 0; k < 4; k++) { b[k] = buff[j + k]; } p[i] = AES.pack(b); p[i] ^= this.fkey[i]; } k = 4; /* State alternates between p and q */ for (i = 1; i < this.Nr; i++) { q[0] = this.fkey[k] ^ AES.ftable[p[0] & 0xff] ^ AES.ROTL8(AES.ftable[(p[1] >>> 8) & 0xff]) ^ AES.ROTL16(AES.ftable[(p[2] >>> 16) & 0xff]) ^ AES.ROTL24(AES.ftable[(p[3] >>> 24) & 0xff]); q[1] = this.fkey[k + 1] ^ AES.ftable[p[1] & 0xff] ^ AES.ROTL8(AES.ftable[(p[2] >>> 8) & 0xff]) ^ AES.ROTL16(AES.ftable[(p[3] >>> 16) & 0xff]) ^ AES.ROTL24(AES.ftable[(p[0] >>> 24) & 0xff]); q[2] = this.fkey[k + 2] ^ AES.ftable[p[2] & 0xff] ^ AES.ROTL8(AES.ftable[(p[3] >>> 8) & 0xff]) ^ AES.ROTL16(AES.ftable[(p[0] >>> 16) & 0xff]) ^ AES.ROTL24(AES.ftable[(p[1] >>> 24) & 0xff]); q[3] = this.fkey[k + 3] ^ AES.ftable[p[3] & 0xff] ^ AES.ROTL8(AES.ftable[(p[0] >>> 8) & 0xff]) ^ AES.ROTL16(AES.ftable[(p[1] >>> 16) & 0xff]) ^ AES.ROTL24(AES.ftable[(p[2] >>> 24) & 0xff]); k += 4; for (j = 0; j < 4; j++) { t = p[j]; p[j] = q[j]; q[j] = t; } } /* Last Round */ q[0] = this.fkey[k] ^ (AES.fbsub[p[0] & 0xff] & 0xff) ^ AES.ROTL8(AES.fbsub[(p[1] >>> 8) & 0xff] & 0xff) ^ AES.ROTL16(AES.fbsub[(p[2] >>> 16) & 0xff] & 0xff) ^ AES.ROTL24(AES.fbsub[(p[3] >>> 24) & 0xff] & 0xff); q[1] = this.fkey[k + 1] ^ (AES.fbsub[p[1] & 0xff] & 0xff) ^ AES.ROTL8(AES.fbsub[(p[2] >>> 8) & 0xff] & 0xff) ^ AES.ROTL16(AES.fbsub[(p[3] >>> 16) & 0xff] & 0xff) ^ AES.ROTL24(AES.fbsub[(p[0] >>> 24) & 0xff] & 0xff); q[2] = this.fkey[k + 2] ^ (AES.fbsub[p[2] & 0xff] & 0xff) ^ AES.ROTL8(AES.fbsub[(p[3] >>> 8) & 0xff] & 0xff) ^ AES.ROTL16(AES.fbsub[(p[0] >>> 16) & 0xff] & 0xff) ^ AES.ROTL24(AES.fbsub[(p[1] >>> 24) & 0xff] & 0xff); q[3] = this.fkey[k + 3] ^ (AES.fbsub[(p[3]) & 0xff] & 0xff) ^ AES.ROTL8(AES.fbsub[(p[0] >>> 8) & 0xff] & 0xff) ^ AES.ROTL16(AES.fbsub[(p[1] >>> 16) & 0xff] & 0xff) ^ AES.ROTL24(AES.fbsub[(p[2] >>> 24) & 0xff] & 0xff); for (i = j = 0; i < 4; i++, j += 4) { b = AES.unpack(q[i]); for (k = 0; k < 4; k++) { buff[j + k] = b[k]; } } }, /* Decrypt a single block */ ecb_decrypt: function(buff) { var b = [], p = [], q = [], t, i, j, k; for (i = j = 0; i < 4; i++, j += 4) { for (k = 0; k < 4; k++) { b[k] = buff[j + k]; } p[i] = AES.pack(b); p[i] ^= this.rkey[i]; } k = 4; /* State alternates between p and q */ for (i = 1; i < this.Nr; i++) { q[0] = this.rkey[k] ^ AES.rtable[p[0] & 0xff] ^ AES.ROTL8(AES.rtable[(p[3] >>> 8) & 0xff]) ^ AES.ROTL16(AES.rtable[(p[2] >>> 16) & 0xff]) ^ AES.ROTL24(AES.rtable[(p[1] >>> 24) & 0xff]); q[1] = this.rkey[k + 1] ^ AES.rtable[p[1] & 0xff] ^ AES.ROTL8(AES.rtable[(p[0] >>> 8) & 0xff]) ^ AES.ROTL16(AES.rtable[(p[3] >>> 16) & 0xff]) ^ AES.ROTL24(AES.rtable[(p[2] >>> 24) & 0xff]); q[2] = this.rkey[k + 2] ^ AES.rtable[p[2] & 0xff] ^ AES.ROTL8(AES.rtable[(p[1] >>> 8) & 0xff]) ^ AES.ROTL16(AES.rtable[(p[0] >>> 16) & 0xff]) ^ AES.ROTL24(AES.rtable[(p[3] >>> 24) & 0xff]); q[3] = this.rkey[k + 3] ^ AES.rtable[p[3] & 0xff] ^ AES.ROTL8(AES.rtable[(p[2] >>> 8) & 0xff]) ^ AES.ROTL16(AES.rtable[(p[1] >>> 16) & 0xff]) ^ AES.ROTL24(AES.rtable[(p[0] >>> 24) & 0xff]); k += 4; for (j = 0; j < 4; j++) { t = p[j]; p[j] = q[j]; q[j] = t; } } /* Last Round */ q[0] = this.rkey[k] ^ (AES.rbsub[p[0] & 0xff] & 0xff) ^ AES.ROTL8(AES.rbsub[(p[3] >>> 8) & 0xff] & 0xff) ^ AES.ROTL16(AES.rbsub[(p[2] >>> 16) & 0xff] & 0xff) ^ AES.ROTL24(AES.rbsub[(p[1] >>> 24) & 0xff] & 0xff); q[1] = this.rkey[k + 1] ^ (AES.rbsub[p[1] & 0xff] & 0xff) ^ AES.ROTL8(AES.rbsub[(p[0] >>> 8) & 0xff] & 0xff) ^ AES.ROTL16(AES.rbsub[(p[3] >>> 16) & 0xff] & 0xff) ^ AES.ROTL24(AES.rbsub[(p[2] >>> 24) & 0xff] & 0xff); q[2] = this.rkey[k + 2] ^ (AES.rbsub[p[2] & 0xff] & 0xff) ^ AES.ROTL8(AES.rbsub[(p[1] >>> 8) & 0xff] & 0xff) ^ AES.ROTL16(AES.rbsub[(p[0] >>> 16) & 0xff] & 0xff) ^ AES.ROTL24(AES.rbsub[(p[3] >>> 24) & 0xff] & 0xff); q[3] = this.rkey[k + 3] ^ (AES.rbsub[p[3] & 0xff] & 0xff) ^ AES.ROTL8(AES.rbsub[(p[2] >>> 8) & 0xff] & 0xff) ^ AES.ROTL16(AES.rbsub[(p[1] >>> 16) & 0xff] & 0xff) ^ AES.ROTL24(AES.rbsub[(p[0] >>> 24) & 0xff] & 0xff); for (i = j = 0; i < 4; i++, j += 4) { b = AES.unpack(q[i]); for (k = 0; k < 4; k++) { buff[j + k] = b[k]; } } }, /* Encrypt using selected mode of operation */ encrypt: function(buff) { var st = [], bytes, fell_off, j; // Supported Modes of Operation fell_off = 0; switch (this.mode) { case AES.ECB: this.ecb_encrypt(buff); return 0; case AES.CBC: for (j = 0; j < 16; j++) { buff[j] ^= this.f[j]; } this.ecb_encrypt(buff); for (j = 0; j < 16; j++) { this.f[j] = buff[j]; } return 0; case AES.CFB1: case AES.CFB2: case AES.CFB4: bytes = this.mode - AES.CFB1 + 1; for (j = 0; j < bytes; j++) { fell_off = (fell_off << 8) | this.f[j]; } for (j = 0; j < 16; j++) { st[j] = this.f[j]; } for (j = bytes; j < 16; j++) { this.f[j - bytes] = this.f[j]; } this.ecb_encrypt(st); for (j = 0; j < bytes; j++) { buff[j] ^= st[j]; this.f[16 - bytes + j] = buff[j]; } return fell_off; case AES.OFB1: case AES.OFB2: case AES.OFB4: case AES.OFB8: case AES.OFB16: bytes = this.mode - AES.OFB1 + 1; this.ecb_encrypt(this.f); for (j = 0; j < bytes; j++) { buff[j] ^= this.f[j]; } return 0; case AES.CTR1: case AES.CTR2: case AES.CTR4: case AES.CTR8: case AES.CTR16: bytes = this.mode - AES.CTR1 + 1; for (j = 0; j < 16; j++) { st[j] = this.f[j]; } this.ecb_encrypt(st); for (j = 0; j < bytes; j++) { buff[j] ^= st[j]; } this.increment(); return 0; default: return 0; } }, /* Decrypt using selected mode of operation */ decrypt: function(buff) { var st = [], bytes,fell_off, j; // Supported modes of operation fell_off = 0; switch (this.mode) { case AES.ECB: this.ecb_decrypt(buff); return 0; case AES.CBC: for (j = 0; j < 16; j++) { st[j] = this.f[j]; this.f[j] = buff[j]; } this.ecb_decrypt(buff); for (j = 0; j < 16; j++) { buff[j] ^= st[j]; st[j] = 0; } return 0; case AES.CFB1: case AES.CFB2: case AES.CFB4: bytes = this.mode - AES.CFB1 + 1; for (j = 0; j < bytes; j++) { fell_off = (fell_off << 8) | this.f[j]; } for (j = 0; j < 16; j++) { st[j] = this.f[j]; } for (j = bytes; j < 16; j++) { this.f[j - bytes] = this.f[j]; } this.ecb_encrypt(st); for (j = 0; j < bytes; j++) { this.f[16 - bytes + j] = buff[j]; buff[j] ^= st[j]; } return fell_off; case AES.OFB1: case AES.OFB2: case AES.OFB4: case AES.OFB8: case AES.OFB16: bytes = this.mode - AES.OFB1 + 1; this.ecb_encrypt(this.f); for (j = 0; j < bytes; j++) { buff[j] ^= this.f[j]; } return 0; case AES.CTR1: case AES.CTR2: case AES.CTR4: case AES.CTR8: case AES.CTR16: bytes = this.mode - AES.CTR1 + 1; for (j = 0; j < 16; j++) { st[j] = this.f[j]; } this.ecb_encrypt(st); for (j = 0; j < bytes; j++) { buff[j] ^= st[j]; } this.increment(); return 0; default: return 0; } }, /* Clean up and delete left-overs */ end: function() { var i; for (i = 0; i < 4 * (this.Nr + 1); i++) { this.fkey[i] = this.rkey[i] = 0; } for (i = 0; i < 16; i++) { this.f[i] = 0; } } }; /* static functions */ AES.ROTL8 = function(x) { return (((x) << 8) | ((x) >>> 24)); }; AES.ROTL16 = function(x) { return (((x) << 16) | ((x) >>> 16)); }; AES.ROTL24 = function(x) { return (((x) << 24) | ((x) >>> 8)); }; /* pack 4 bytes into a 32-bit Word */ AES.pack = function(b) { return (((b[3]) & 0xff) << 24) | ((b[2] & 0xff) << 16) | ((b[1] & 0xff) << 8) | (b[0] & 0xff); }; /* unpack bytes from a word */ AES.unpack = function(a) { var b = []; b[0] = (a & 0xff); b[1] = ((a >>> 8) & 0xff); b[2] = ((a >>> 16) & 0xff); b[3] = ((a >>> 24) & 0xff); return b; }; /* x.y= AntiLog(Log(x) + Log(y)) */ AES.bmul = function(x, y) { var ix = (x & 0xff), iy = (y & 0xff), lx = (AES.ltab[ix]) & 0xff, ly = (AES.ltab[iy]) & 0xff; if (x !== 0 && y !== 0) { return AES.ptab[(lx + ly) % 255]; } else { return 0; } }; // if (x && y) AES.SubByte = function(a) { var b = AES.unpack(a); b[0] = AES.fbsub[b[0] & 0xff]; b[1] = AES.fbsub[b[1] & 0xff]; b[2] = AES.fbsub[b[2] & 0xff]; b[3] = AES.fbsub[b[3] & 0xff]; return AES.pack(b); }; /* dot product of two 4-byte arrays */ AES.product = function(x, y) { var xb = AES.unpack(x), yb = AES.unpack(y); return (AES.bmul(xb[0], yb[0]) ^ AES.bmul(xb[1], yb[1]) ^ AES.bmul(xb[2], yb[2]) ^ AES.bmul(xb[3], yb[3])) & 0xff; }; /* matrix Multiplication */ AES.InvMixCol = function(x) { var b = [], y, m; m = AES.pack(AES.InCo); b[3] = AES.product(m, x); m = AES.ROTL24(m); b[2] = AES.product(m, x); m = AES.ROTL24(m); b[1] = AES.product(m, x); m = AES.ROTL24(m); b[0] = AES.product(m, x); y = AES.pack(b); return y; }; /* Inverse Coefficients */ AES.InCo = [0xB, 0xD, 0x9, 0xE]; AES.rco = [1, 2, 4, 8, 16, 32, 64, 128, 27, 54, 108, 216, 171, 77, 154, 47]; AES.ptab = [ 1, 3, 5, 15, 17, 51, 85, 255, 26, 46, 114, 150, 161, 248, 19, 53, 95, 225, 56, 72, 216, 115, 149, 164, 247, 2, 6, 10, 30, 34, 102, 170, 229, 52, 92, 228, 55, 89, 235, 38, 106, 190, 217, 112, 144, 171, 230, 49, 83, 245, 4, 12, 20, 60, 68, 204, 79, 209, 104, 184, 211, 110, 178, 205, 76, 212, 103, 169, 224, 59, 77, 215, 98, 166, 241, 8, 24, 40, 120, 136, 131, 158, 185, 208, 107, 189, 220, 127, 129, 152, 179, 206, 73, 219, 118, 154, 181, 196, 87, 249, 16, 48, 80, 240, 11, 29, 39, 105, 187, 214, 97, 163, 254, 25, 43, 125, 135, 146, 173, 236, 47, 113, 147, 174, 233, 32, 96, 160, 251, 22, 58, 78, 210, 109, 183, 194, 93, 231, 50, 86, 250, 21, 63, 65, 195, 94, 226, 61, 71, 201, 64, 192, 91, 237, 44, 116, 156, 191, 218, 117, 159, 186, 213, 100, 172, 239, 42, 126, 130, 157, 188, 223, 122, 142, 137, 128, 155, 182, 193, 88, 232, 35, 101, 175, 234, 37, 111, 177, 200, 67, 197, 84, 252, 31, 33, 99, 165, 244, 7, 9, 27, 45, 119, 153, 176, 203, 70, 202, 69, 207, 74, 222, 121, 139, 134, 145, 168, 227, 62, 66, 198, 81, 243, 14, 18, 54, 90, 238, 41, 123, 141, 140, 143, 138, 133, 148, 167, 242, 13, 23, 57, 75, 221, 124, 132, 151, 162, 253, 28, 36, 108, 180, 199, 82, 246, 1 ]; AES.ltab = [ 0, 255, 25, 1, 50, 2, 26, 198, 75, 199, 27, 104, 51, 238, 223, 3, 100, 4, 224, 14, 52, 141, 129, 239, 76, 113, 8, 200, 248, 105, 28, 193, 125, 194, 29, 181, 249, 185, 39, 106, 77, 228, 166, 114, 154, 201, 9, 120, 101, 47, 138, 5, 33, 15, 225, 36, 18, 240, 130, 69, 53, 147, 218, 142, 150, 143, 219, 189, 54, 208, 206, 148, 19, 92, 210, 241, 64, 70, 131, 56, 102, 221, 253, 48, 191, 6, 139, 98, 179, 37, 226, 152, 34, 136, 145, 16, 126, 110, 72, 195, 163, 182, 30, 66, 58, 107, 40, 84, 250, 133, 61, 186, 43, 121, 10, 21, 155, 159, 94, 202, 78, 212, 172, 229, 243, 115, 167, 87, 175, 88, 168, 80, 244, 234, 214, 116, 79, 174, 233, 213, 231, 230, 173, 232, 44, 215, 117, 122, 235, 22, 11, 245, 89, 203, 95, 176, 156, 169, 81, 160, 127, 12, 246, 111, 23, 196, 73, 236, 216, 67, 31, 45, 164, 118, 123, 183, 204, 187, 62, 90, 251, 96, 177, 134, 59, 82, 161, 108, 170, 85, 41, 157, 151, 178, 135, 144, 97, 190, 220, 252, 188, 149, 207, 205, 55, 63, 91, 209, 83, 57, 132, 60, 65, 162, 109, 71, 20, 42, 158, 93, 86, 242, 211, 171, 68, 17, 146, 217, 35, 32, 46, 137, 180, 124, 184, 38, 119, 153, 227, 165, 103, 74, 237, 222, 197, 49, 254, 24, 13, 99, 140, 128, 192, 247, 112, 7 ]; AES.fbsub = [ 99, 124, 119, 123, 242, 107, 111, 197, 48, 1, 103, 43, 254, 215, 171, 118, 202, 130, 201, 125, 250, 89, 71, 240, 173, 212, 162, 175, 156, 164, 114, 192, 183, 253, 147, 38, 54, 63, 247, 204, 52, 165, 229, 241, 113, 216, 49, 21, 4, 199, 35, 195, 24, 150, 5, 154, 7, 18, 128, 226, 235, 39, 178, 117, 9, 131, 44, 26, 27, 110, 90, 160, 82, 59, 214, 179, 41, 227, 47, 132, 83, 209, 0, 237, 32, 252, 177, 91, 106, 203, 190, 57, 74, 76, 88, 207, 208, 239, 170, 251, 67, 77, 51, 133, 69, 249, 2, 127, 80, 60, 159, 168, 81, 163, 64, 143, 146, 157, 56, 245, 188, 182, 218, 33, 16, 255, 243, 210, 205, 12, 19, 236, 95, 151, 68, 23, 196, 167, 126, 61, 100, 93, 25, 115, 96, 129, 79, 220, 34, 42, 144, 136, 70, 238, 184, 20, 222, 94, 11, 219, 224, 50, 58, 10, 73, 6, 36, 92, 194, 211, 172, 98, 145, 149, 228, 121, 231, 200, 55, 109, 141, 213, 78, 169, 108, 86, 244, 234, 101, 122, 174, 8, 186, 120, 37, 46, 28, 166, 180, 198, 232, 221, 116, 31, 75, 189, 139, 138, 112, 62, 181, 102, 72, 3, 246, 14, 97, 53, 87, 185, 134, 193, 29, 158, 225, 248, 152, 17, 105, 217, 142, 148, 155, 30, 135, 233, 206, 85, 40, 223, 140, 161, 137, 13, 191, 230, 66, 104, 65, 153, 45, 15, 176, 84, 187, 22 ]; AES.rbsub = [ 82, 9, 106, 213, 48, 54, 165, 56, 191, 64, 163, 158, 129, 243, 215, 251, 124, 227, 57, 130, 155, 47, 255, 135, 52, 142, 67, 68, 196, 222, 233, 203, 84, 123, 148, 50, 166, 194, 35, 61, 238, 76, 149, 11, 66, 250, 195, 78, 8, 46, 161, 102, 40, 217, 36, 178, 118, 91, 162, 73, 109, 139, 209, 37, 114, 248, 246, 100, 134, 104, 152, 22, 212, 164, 92, 204, 93, 101, 182, 146, 108, 112, 72, 80, 253, 237, 185, 218, 94, 21, 70, 87, 167, 141, 157, 132, 144, 216, 171, 0, 140, 188, 211, 10, 247, 228, 88, 5, 184, 179, 69, 6, 208, 44, 30, 143, 202, 63, 15, 2, 193, 175, 189, 3, 1, 19, 138, 107, 58, 145, 17, 65, 79, 103, 220, 234, 151, 242, 207, 206, 240, 180, 230, 115, 150, 172, 116, 34, 231, 173, 53, 133, 226, 249, 55, 232, 28, 117, 223, 110, 71, 241, 26, 113, 29, 41, 197, 137, 111, 183, 98, 14, 170, 24, 190, 27, 252, 86, 62, 75, 198, 210, 121, 32, 154, 219, 192, 254, 120, 205, 90, 244, 31, 221, 168, 51, 136, 7, 199, 49, 177, 18, 16, 89, 39, 128, 236, 95, 96, 81, 127, 169, 25, 181, 74, 13, 45, 229, 122, 159, 147, 201, 156, 239, 160, 224, 59, 77, 174, 42, 245, 176, 200, 235, 187, 60, 131, 83, 153, 97, 23, 43, 4, 126, 186, 119, 214, 38, 225, 105, 20, 99, 85, 33, 12, 125 ]; AES.ftable = [ 0xa56363c6, 0x847c7cf8, 0x997777ee, 0x8d7b7bf6, 0xdf2f2ff, 0xbd6b6bd6, 0xb16f6fde, 0x54c5c591, 0x50303060, 0x3010102, 0xa96767ce, 0x7d2b2b56, 0x19fefee7, 0x62d7d7b5, 0xe6abab4d, 0x9a7676ec, 0x45caca8f, 0x9d82821f, 0x40c9c989, 0x877d7dfa, 0x15fafaef, 0xeb5959b2, 0xc947478e, 0xbf0f0fb, 0xecadad41, 0x67d4d4b3, 0xfda2a25f, 0xeaafaf45, 0xbf9c9c23, 0xf7a4a453, 0x967272e4, 0x5bc0c09b, 0xc2b7b775, 0x1cfdfde1, 0xae93933d, 0x6a26264c, 0x5a36366c, 0x413f3f7e, 0x2f7f7f5, 0x4fcccc83, 0x5c343468, 0xf4a5a551, 0x34e5e5d1, 0x8f1f1f9, 0x937171e2, 0x73d8d8ab, 0x53313162, 0x3f15152a, 0xc040408, 0x52c7c795, 0x65232346, 0x5ec3c39d, 0x28181830, 0xa1969637, 0xf05050a, 0xb59a9a2f, 0x907070e, 0x36121224, 0x9b80801b, 0x3de2e2df, 0x26ebebcd, 0x6927274e, 0xcdb2b27f, 0x9f7575ea, 0x1b090912, 0x9e83831d, 0x742c2c58, 0x2e1a1a34, 0x2d1b1b36, 0xb26e6edc, 0xee5a5ab4, 0xfba0a05b, 0xf65252a4, 0x4d3b3b76, 0x61d6d6b7, 0xceb3b37d, 0x7b292952, 0x3ee3e3dd, 0x712f2f5e, 0x97848413, 0xf55353a6, 0x68d1d1b9, 0x0, 0x2cededc1, 0x60202040, 0x1ffcfce3, 0xc8b1b179, 0xed5b5bb6, 0xbe6a6ad4, 0x46cbcb8d, 0xd9bebe67, 0x4b393972, 0xde4a4a94, 0xd44c4c98, 0xe85858b0, 0x4acfcf85, 0x6bd0d0bb, 0x2aefefc5, 0xe5aaaa4f, 0x16fbfbed, 0xc5434386, 0xd74d4d9a, 0x55333366, 0x94858511, 0xcf45458a, 0x10f9f9e9, 0x6020204, 0x817f7ffe, 0xf05050a0, 0x443c3c78, 0xba9f9f25, 0xe3a8a84b, 0xf35151a2, 0xfea3a35d, 0xc0404080, 0x8a8f8f05, 0xad92923f, 0xbc9d9d21, 0x48383870, 0x4f5f5f1, 0xdfbcbc63, 0xc1b6b677, 0x75dadaaf, 0x63212142, 0x30101020, 0x1affffe5, 0xef3f3fd, 0x6dd2d2bf, 0x4ccdcd81, 0x140c0c18, 0x35131326, 0x2fececc3, 0xe15f5fbe, 0xa2979735, 0xcc444488, 0x3917172e, 0x57c4c493, 0xf2a7a755, 0x827e7efc, 0x473d3d7a, 0xac6464c8, 0xe75d5dba, 0x2b191932, 0x957373e6, 0xa06060c0, 0x98818119, 0xd14f4f9e, 0x7fdcdca3, 0x66222244, 0x7e2a2a54, 0xab90903b, 0x8388880b, 0xca46468c, 0x29eeeec7, 0xd3b8b86b, 0x3c141428, 0x79dedea7, 0xe25e5ebc, 0x1d0b0b16, 0x76dbdbad, 0x3be0e0db, 0x56323264, 0x4e3a3a74, 0x1e0a0a14, 0xdb494992, 0xa06060c, 0x6c242448, 0xe45c5cb8, 0x5dc2c29f, 0x6ed3d3bd, 0xefacac43, 0xa66262c4, 0xa8919139, 0xa4959531, 0x37e4e4d3, 0x8b7979f2, 0x32e7e7d5, 0x43c8c88b, 0x5937376e, 0xb76d6dda, 0x8c8d8d01, 0x64d5d5b1, 0xd24e4e9c, 0xe0a9a949, 0xb46c6cd8, 0xfa5656ac, 0x7f4f4f3, 0x25eaeacf, 0xaf6565ca, 0x8e7a7af4, 0xe9aeae47, 0x18080810, 0xd5baba6f, 0x887878f0, 0x6f25254a, 0x722e2e5c, 0x241c1c38, 0xf1a6a657, 0xc7b4b473, 0x51c6c697, 0x23e8e8cb, 0x7cdddda1, 0x9c7474e8, 0x211f1f3e, 0xdd4b4b96, 0xdcbdbd61, 0x868b8b0d, 0x858a8a0f, 0x907070e0, 0x423e3e7c, 0xc4b5b571, 0xaa6666cc, 0xd8484890, 0x5030306, 0x1f6f6f7, 0x120e0e1c, 0xa36161c2, 0x5f35356a, 0xf95757ae, 0xd0b9b969, 0x91868617, 0x58c1c199, 0x271d1d3a, 0xb99e9e27, 0x38e1e1d9, 0x13f8f8eb, 0xb398982b, 0x33111122, 0xbb6969d2, 0x70d9d9a9, 0x898e8e07, 0xa7949433, 0xb69b9b2d, 0x221e1e3c, 0x92878715, 0x20e9e9c9, 0x49cece87, 0xff5555aa, 0x78282850, 0x7adfdfa5, 0x8f8c8c03, 0xf8a1a159, 0x80898909, 0x170d0d1a, 0xdabfbf65, 0x31e6e6d7, 0xc6424284, 0xb86868d0, 0xc3414182, 0xb0999929, 0x772d2d5a, 0x110f0f1e, 0xcbb0b07b, 0xfc5454a8, 0xd6bbbb6d, 0x3a16162c ]; AES.rtable = [ 0x50a7f451, 0x5365417e, 0xc3a4171a, 0x965e273a, 0xcb6bab3b, 0xf1459d1f, 0xab58faac, 0x9303e34b, 0x55fa3020, 0xf66d76ad, 0x9176cc88, 0x254c02f5, 0xfcd7e54f, 0xd7cb2ac5, 0x80443526, 0x8fa362b5, 0x495ab1de, 0x671bba25, 0x980eea45, 0xe1c0fe5d, 0x2752fc3, 0x12f04c81, 0xa397468d, 0xc6f9d36b, 0xe75f8f03, 0x959c9215, 0xeb7a6dbf, 0xda595295, 0x2d83bed4, 0xd3217458, 0x2969e049, 0x44c8c98e, 0x6a89c275, 0x78798ef4, 0x6b3e5899, 0xdd71b927, 0xb64fe1be, 0x17ad88f0, 0x66ac20c9, 0xb43ace7d, 0x184adf63, 0x82311ae5, 0x60335197, 0x457f5362, 0xe07764b1, 0x84ae6bbb, 0x1ca081fe, 0x942b08f9, 0x58684870, 0x19fd458f, 0x876cde94, 0xb7f87b52, 0x23d373ab, 0xe2024b72, 0x578f1fe3, 0x2aab5566, 0x728ebb2, 0x3c2b52f, 0x9a7bc586, 0xa50837d3, 0xf2872830, 0xb2a5bf23, 0xba6a0302, 0x5c8216ed, 0x2b1ccf8a, 0x92b479a7, 0xf0f207f3, 0xa1e2694e, 0xcdf4da65, 0xd5be0506, 0x1f6234d1, 0x8afea6c4, 0x9d532e34, 0xa055f3a2, 0x32e18a05, 0x75ebf6a4, 0x39ec830b, 0xaaef6040, 0x69f715e, 0x51106ebd, 0xf98a213e, 0x3d06dd96, 0xae053edd, 0x46bde64d, 0xb58d5491, 0x55dc471, 0x6fd40604, 0xff155060, 0x24fb9819, 0x97e9bdd6, 0xcc434089, 0x779ed967, 0xbd42e8b0, 0x888b8907, 0x385b19e7, 0xdbeec879, 0x470a7ca1, 0xe90f427c, 0xc91e84f8, 0x0, 0x83868009, 0x48ed2b32, 0xac70111e, 0x4e725a6c, 0xfbff0efd, 0x5638850f, 0x1ed5ae3d, 0x27392d36, 0x64d90f0a, 0x21a65c68, 0xd1545b9b, 0x3a2e3624, 0xb1670a0c, 0xfe75793, 0xd296eeb4, 0x9e919b1b, 0x4fc5c080, 0xa220dc61, 0x694b775a, 0x161a121c, 0xaba93e2, 0xe52aa0c0, 0x43e0223c, 0x1d171b12, 0xb0d090e, 0xadc78bf2, 0xb9a8b62d, 0xc8a91e14, 0x8519f157, 0x4c0775af, 0xbbdd99ee, 0xfd607fa3, 0x9f2601f7, 0xbcf5725c, 0xc53b6644, 0x347efb5b, 0x7629438b, 0xdcc623cb, 0x68fcedb6, 0x63f1e4b8, 0xcadc31d7, 0x10856342, 0x40229713, 0x2011c684, 0x7d244a85, 0xf83dbbd2, 0x1132f9ae, 0x6da129c7, 0x4b2f9e1d, 0xf330b2dc, 0xec52860d, 0xd0e3c177, 0x6c16b32b, 0x99b970a9, 0xfa489411, 0x2264e947, 0xc48cfca8, 0x1a3ff0a0, 0xd82c7d56, 0xef903322, 0xc74e4987, 0xc1d138d9, 0xfea2ca8c, 0x360bd498, 0xcf81f5a6, 0x28de7aa5, 0x268eb7da, 0xa4bfad3f, 0xe49d3a2c, 0xd927850, 0x9bcc5f6a, 0x62467e54, 0xc2138df6, 0xe8b8d890, 0x5ef7392e, 0xf5afc382, 0xbe805d9f, 0x7c93d069, 0xa92dd56f, 0xb31225cf, 0x3b99acc8, 0xa77d1810, 0x6e639ce8, 0x7bbb3bdb, 0x97826cd, 0xf418596e, 0x1b79aec, 0xa89a4f83, 0x656e95e6, 0x7ee6ffaa, 0x8cfbc21, 0xe6e815ef, 0xd99be7ba, 0xce366f4a, 0xd4099fea, 0xd67cb029, 0xafb2a431, 0x31233f2a, 0x3094a5c6, 0xc066a235, 0x37bc4e74, 0xa6ca82fc, 0xb0d090e0, 0x15d8a733, 0x4a9804f1, 0xf7daec41, 0xe50cd7f, 0x2ff69117, 0x8dd64d76, 0x4db0ef43, 0x544daacc, 0xdf0496e4, 0xe3b5d19e, 0x1b886a4c, 0xb81f2cc1, 0x7f516546, 0x4ea5e9d, 0x5d358c01, 0x737487fa, 0x2e410bfb, 0x5a1d67b3, 0x52d2db92, 0x335610e9, 0x1347d66d, 0x8c61d79a, 0x7a0ca137, 0x8e14f859, 0x893c13eb, 0xee27a9ce, 0x35c961b7, 0xede51ce1, 0x3cb1477a, 0x59dfd29c, 0x3f73f255, 0x79ce1418, 0xbf37c773, 0xeacdf753, 0x5baafd5f, 0x146f3ddf, 0x86db4478, 0x81f3afca, 0x3ec468b9, 0x2c342438, 0x5f40a3c2, 0x72c31d16, 0xc25e2bc, 0x8b493c28, 0x41950dff, 0x7101a839, 0xdeb30c08, 0x9ce4b4d8, 0x90c15664, 0x6184cb7b, 0x70b632d5, 0x745c6c48, 0x4257b8d0 ]; return AES; } /* Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* AMCL BIG number class */ function BIG(ctx) { /* General purpose Constructor */ var BIG = function(x) { this.w = new Array(BIG.NLEN); switch (typeof(x)) { case "object": this.copy(x); break; case "number": this.zero(); this.w[0] = x; break; default: this.zero(); } }; BIG.CHUNK = 32; BIG.MODBYTES = ctx.config["@NB"]; BIG.BASEBITS = ctx.config["@BASE"]; BIG.NLEN = (1 + (Math.floor((8 * BIG.MODBYTES - 1) / BIG.BASEBITS))); BIG.DNLEN = 2 * BIG.NLEN; BIG.BMASK = (1 << BIG.BASEBITS) - 1; BIG.BIGBITS = (8 * BIG.MODBYTES); BIG.NEXCESS = (1 << (BIG.CHUNK - BIG.BASEBITS - 1)); BIG.MODINV = (Math.pow(2, -BIG.BASEBITS)); BIG.prototype = { /* set to zero */ zero: function() { var i; for (i = 0; i < BIG.NLEN; i++) { this.w[i] = 0; } return this; }, /* set to one */ one: function() { var i; this.w[0] = 1; for (i = 1; i < BIG.NLEN; i++) { this.w[i] = 0; } return this; }, get: function(i) { return this.w[i]; }, set: function(i, x) { this.w[i] = x; }, /* test for zero */ iszilch: function() { var i; for (i = 0; i < BIG.NLEN; i++) { if (this.w[i] !== 0) { return false; } } return true; }, /* test for unity */ isunity: function() { var i; for (i = 1; i < BIG.NLEN; i++) { if (this.w[i] !== 0) { return false; } } if (this.w[0] != 1) { return false; } return true; }, /* Conditional swap of two BIGs depending on d using XOR - no branches */ cswap: function(b, d) { var c = d, t, i; c = ~(c - 1); for (i = 0; i < BIG.NLEN; i++) { t = c & (this.w[i] ^ b.w[i]); this.w[i] ^= t; b.w[i] ^= t; } }, /* Conditional move of BIG depending on d using XOR - no branches */ cmove: function(b, d) { var c = d, i; c = ~(c - 1); for (i = 0; i < BIG.NLEN; i++) { this.w[i] ^= (this.w[i] ^ b.w[i]) & c; } }, /* copy from another BIG */ copy: function(y) { var i; for (i = 0; i < BIG.NLEN; i++) { this.w[i] = y.w[i]; } return this; }, /* copy from bottom half of ctx.DBIG */ hcopy: function(y) { var i; for (i = 0; i < BIG.NLEN; i++) { this.w[i] = y.w[i]; } return this; }, /* copy from ROM */ rcopy: function(y) { var i; for (i = 0; i < BIG.NLEN; i++) { this.w[i] = y[i]; } return this; }, xortop: function(x) { this.w[BIG.NLEN - 1] ^= x; }, ortop: function(x) { this.w[BIG.NLEN - 1] |= x; }, /* normalise BIG - force all digits < 2^BASEBITS */ norm: function() { var carry = 0, d, i; for (i = 0; i < BIG.NLEN - 1; i++) { d = this.w[i] + carry; this.w[i] = d & BIG.BMASK; carry = d >> BIG.BASEBITS; } this.w[BIG.NLEN - 1] = (this.w[BIG.NLEN - 1] + carry); return (this.w[BIG.NLEN - 1] >> ((8 * BIG.MODBYTES) % BIG.BASEBITS)); }, /* quick shift right by less than a word */ fshr: function(k) { var r, i; /* shifted out part */ r = this.w[0] & ((1 << k) - 1); for (i = 0; i < BIG.NLEN - 1; i++) { this.w[i] = (this.w[i] >> k) | ((this.w[i + 1] << (BIG.BASEBITS - k)) & BIG.BMASK); } this.w[BIG.NLEN - 1] = this.w[BIG.NLEN - 1] >> k; return r; }, /* General shift right by k bits */ shr: function(k) { var n = k % BIG.BASEBITS, m = Math.floor(k / BIG.BASEBITS), i; for (i = 0; i < BIG.NLEN - m - 1; i++) { this.w[i] = (this.w[m + i] >> n) | ((this.w[m + i + 1] << (BIG.BASEBITS - n)) & BIG.BMASK); } this.w[BIG.NLEN - m - 1] = this.w[BIG.NLEN - 1] >> n; for (i = BIG.NLEN - m; i < BIG.NLEN; i++) { this.w[i] = 0; } return this; }, /* quick shift left by less than a word */ fshl: function(k) { var i; this.w[BIG.NLEN - 1] = ((this.w[BIG.NLEN - 1] << k)) | (this.w[BIG.NLEN - 2] >> (BIG.BASEBITS - k)); for (i = BIG.NLEN - 2; i > 0; i--) { this.w[i] = ((this.w[i] << k) & BIG.BMASK) | (this.w[i - 1] >> (BIG.BASEBITS - k)); } this.w[0] = (this.w[0] << k) & BIG.BMASK; /* return excess - only used in ff.js */ return (this.w[BIG.NLEN - 1] >> ((8 * BIG.MODBYTES) % BIG.BASEBITS)); }, /* General shift left by k bits */ shl: function(k) { var n = k % BIG.BASEBITS, m = Math.floor(k / BIG.BASEBITS), i; this.w[BIG.NLEN - 1] = (this.w[BIG.NLEN - 1 - m] << n); if (BIG.NLEN > m + 2) { this.w[BIG.NLEN - 1] |= (this.w[BIG.NLEN - m - 2] >> (BIG.BASEBITS - n)); } for (i = BIG.NLEN - 2; i > m; i--) { this.w[i] = ((this.w[i - m] << n) & BIG.BMASK) | (this.w[i - m - 1] >> (BIG.BASEBITS - n)); } this.w[m] = (this.w[0] << n) & BIG.BMASK; for (i = 0; i < m; i++) { this.w[i] = 0; } return this; }, /* return length in bits */ nbits: function() { var k = BIG.NLEN - 1, bts, c; this.norm(); while (k >= 0 && this.w[k] === 0) { k--; } if (k < 0) { return 0; } bts = BIG.BASEBITS * k; c = this.w[k]; while (c !== 0) { c = Math.floor(c / 2); bts++; } return bts; }, /* convert this to string */ toString: function() { var s = "", len = this.nbits(), b, i; if (len % 4 === 0) { len = Math.floor(len / 4); } else { len = Math.floor(len / 4); len++; } if (len < BIG.MODBYTES * 2) { len = BIG.MODBYTES * 2; } for (i = len - 1; i >= 0; i--) { b = new BIG(0); b.copy(this); b.shr(i * 4); s += (b.w[0] & 15).toString(16); } return s; }, /* this+=y */ add: function(y) { var i; for (i = 0; i < BIG.NLEN; i++) { this.w[i] += y.w[i]; } return this; }, /* this|=y */ or: function(y) { var i; for (i = 0; i < BIG.NLEN; i++) { this.w[i] |= y.w[i]; } return this; }, /* return this+x */ plus: function(x) { var s = new BIG(0), i; for (i = 0; i < BIG.NLEN; i++) { s.w[i] = this.w[i] + x.w[i]; } return s; }, /* this+=i, where i is int */ inc: function(i) { this.norm(); this.w[0] += i; return this; }, /* this-=y */ sub: function(y) { var i; for (i = 0; i < BIG.NLEN; i++) { this.w[i] -= y.w[i]; } return this; }, /* reverse subtract this=x-this */ rsub: function(x) { var i; for (i = 0; i < BIG.NLEN; i++) { this.w[i] = x.w[i] - this.w[i]; } return this; }, /* this-=i, where i is int */ dec: function(i) { this.norm(); this.w[0] -= i; return this; }, /* return this-x */ minus: function(x) { var d = new BIG(0), i; for (i = 0; i < BIG.NLEN; i++) { d.w[i] = this.w[i] - x.w[i]; } return d; }, /* multiply by small integer */ imul: function(c) { var i; for (i = 0; i < BIG.NLEN; i++) { this.w[i] *= c; } return this; }, /* convert this BIG to byte array */ tobytearray: function(b, n) { var c = new BIG(0), i; this.norm(); c.copy(this); for (i = BIG.MODBYTES - 1; i >= 0; i--) { b[i + n] = c.w[0] & 0xff; c.fshr(8); } return this; }, /* convert this to byte array */ toBytes: function(b) { this.tobytearray(b, 0); }, /* set this[i]+=x*y+c, and return high part */ muladd: function(x, y, c, i) { var prod = x * y + c + this.w[i]; this.w[i] = prod & BIG.BMASK; return ((prod - this.w[i]) * BIG.MODINV); }, /* multiply by larger int */ pmul: function(c) { var carry = 0, ak, i; for (i = 0; i < BIG.NLEN; i++) { ak = this.w[i]; this.w[i] = 0; carry = this.muladd(ak, c, carry, i); } return carry; }, /* multiply by still larger int - results requires a ctx.DBIG */ pxmul: function(c) { var m = new ctx.DBIG(0), carry = 0, j; for (j = 0; j < BIG.NLEN; j++) { carry = m.muladd(this.w[j], c, carry, j); } m.w[BIG.NLEN] = carry; return m; }, /* divide by 3 */ div3: function() { var carry = 0, ak, base, i; this.norm(); base = (1 << BIG.BASEBITS); for (i = BIG.NLEN - 1; i >= 0; i--) { ak = (carry * base + this.w[i]); this.w[i] = Math.floor(ak / 3); carry = ak % 3; } return carry; }, /* set x = x mod 2^m */ mod2m: function(m) { var i, wd, bt, msk; wd = Math.floor(m / BIG.BASEBITS); bt = m % BIG.BASEBITS; msk = (1 << bt) - 1; this.w[wd] &= msk; for (i = wd + 1; i < BIG.NLEN; i++) { this.w[i] = 0; } }, /* a=1/a mod 2^256. This is very fast! */ invmod2m: function() { var U = new BIG(0), b = new BIG(0), c = new BIG(0), i, t1, t2; U.inc(BIG.invmod256(this.lastbits(8))); for (i = 8; i < BIG.BIGBITS; i <<= 1) { U.norm(); b.copy(this); b.mod2m(i); t1 = BIG.smul(U, b); t1.shr(i); c.copy(this); c.shr(i); c.mod2m(i); t2 = BIG.smul(U, c); t2.mod2m(i); t1.add(t2); t1.norm(); b = BIG.smul(t1, U); t1.copy(b); t1.mod2m(i); t2.one(); t2.shl(i); t1.rsub(t2); t1.norm(); t1.shl(i); U.add(t1); } U.mod2m(BIG.BIGBITS); this.copy(U); this.norm(); }, /* reduce this mod m */ mod: function(m) { var k = 0, r = new BIG(0); this.norm(); if (BIG.comp(this, m) < 0) { return; } do { m.fshl(1); k++; } while (BIG.comp(this, m) >= 0); while (k > 0) { m.fshr(1); r.copy(this); r.sub(m); r.norm(); this.cmove(r, (1 - ((r.w[BIG.NLEN - 1] >> (BIG.CHUNK - 1)) & 1))); k--; } }, /* this/=m */ div: function(m) { var k = 0, d = 0, e = new BIG(1), b = new BIG(0), r = new BIG(0); this.norm(); b.copy(this); this.zero(); while (BIG.comp(b, m) >= 0) { e.fshl(1); m.fshl(1); k++; } while (k > 0) { m.fshr(1); e.fshr(1); r.copy(b); r.sub(m); r.norm(); d = (1 - ((r.w[BIG.NLEN - 1] >> (BIG.CHUNK - 1)) & 1)); b.cmove(r, d); r.copy(this); r.add(e); r.norm(); this.cmove(r, d); k--; } }, /* return parity of this */ parity: function() { return this.w[0] % 2; }, /* return n-th bit of this */ bit: function(n) { if ((this.w[Math.floor(n / BIG.BASEBITS)] & (1 << (n % BIG.BASEBITS))) > 0) { return 1; } else { return 0; } }, /* return last n bits of this */ lastbits: function(n) { var msk = (1 << n) - 1; this.norm(); return (this.w[0]) & msk; }, isok: function() { var ok = true, i; for (i = 0; i < BIG.NLEN; i++) { if ((this.w[i] >> BIG.BASEBITS) != 0) { ok = false; } } return ok; }, /* Jacobi Symbol (this/p). Returns 0, 1 or -1 */ jacobi: function(p) { var m = 0, t = new BIG(0), x = new BIG(0), n = new BIG(0), zilch = new BIG(0), one = new BIG(1), n8, k; if (p.parity() === 0 || BIG.comp(this, zilch) === 0 || BIG.comp(p, one) <= 0) { return 0; } this.norm(); x.copy(this); n.copy(p); x.mod(p); while (BIG.comp(n, one) > 0) { if (BIG.comp(x, zilch) === 0) { return 0; } n8 = n.lastbits(3); k = 0; while (x.parity() === 0) { k++; x.shr(1); } if (k % 2 == 1) { m += (n8 * n8 - 1) / 8; } m += (n8 - 1) * (x.lastbits(2) - 1) / 4; t.copy(n); t.mod(x); n.copy(x); x.copy(t); m %= 2; } if (m === 0) { return 1; } else { return -1; } }, /* this=1/this mod p. Binary method */ invmodp: function(p) { var u = new BIG(0), v = new BIG(0), x1 = new BIG(1), x2 = new BIG(0), t = new BIG(0), one = new BIG(1); this.mod(p); u.copy(this); v.copy(p); while (BIG.comp(u, one) !== 0 && BIG.comp(v, one) !== 0) { while (u.parity() === 0) { u.fshr(1); if (x1.parity() !== 0) { x1.add(p); x1.norm(); } x1.fshr(1); } while (v.parity() === 0) { v.fshr(1); if (x2.parity() !== 0) { x2.add(p); x2.norm(); } x2.fshr(1); } if (BIG.comp(u, v) >= 0) { u.sub(v); u.norm(); if (BIG.comp(x1, x2) >= 0) { x1.sub(x2); } else { t.copy(p); t.sub(x2); x1.add(t); } x1.norm(); } else { v.sub(u); v.norm(); if (BIG.comp(x2, x1) >= 0) { x2.sub(x1); } else { t.copy(p); t.sub(x1); x2.add(t); } x2.norm(); } } if (BIG.comp(u, one) === 0) { this.copy(x1); } else { this.copy(x2); } }, /* return this^e mod m */ powmod: function(e, m) { var a = new BIG(1), z = new BIG(0), s = new BIG(0), bt; this.norm(); e.norm(); z.copy(e); s.copy(this); for (;;) { bt = z.parity(); z.fshr(1); if (bt == 1) { a = BIG.modmul(a, s, m); } if (z.iszilch()) { break; } s = BIG.modsqr(s, m); } return a; } }; /* convert from byte array to BIG */ BIG.frombytearray = function(b, n) { var m = new BIG(0), i; for (i = 0; i < BIG.MODBYTES; i++) { m.fshl(8); m.w[0] += b[i + n] & 0xff; } return m; }; BIG.fromBytes = function(b) { return BIG.frombytearray(b, 0); }; /* return a*b where product fits a BIG */ BIG.smul = function(a, b) { var c = new BIG(0), carry, i, j; for (i = 0; i < BIG.NLEN; i++) { carry = 0; for (j = 0; j < BIG.NLEN; j++) { if (i + j < BIG.NLEN) { carry = c.muladd(a.w[i], b.w[j], carry, i + j); } } } return c; }; /* Compare a and b, return 0