diff --git a/app/components/AppHeader.vue b/app/components/AppHeader.vue index cc0bec1..bbe4248 100644 --- a/app/components/AppHeader.vue +++ b/app/components/AppHeader.vue @@ -117,6 +117,12 @@ const items = computed(() => [ icon: 'i-lucide-cloud', description: '灵活、可靠、安全,有效降低成本', to: '/IoTSolutions/iotCloudPlatform', + }, + { + label: '蓝牙测试', + icon: 'i-lucide-bluetooth', + description: '测试', + to: '/IoTSolutions/blueToothTest', } ] }, diff --git a/app/components/blueToothTest/item1.vue b/app/components/blueToothTest/item1.vue new file mode 100644 index 0000000..2303a7a --- /dev/null +++ b/app/components/blueToothTest/item1.vue @@ -0,0 +1,1284 @@ + + + + + \ No newline at end of file diff --git a/app/components/blueToothTest/item2.vue b/app/components/blueToothTest/item2.vue new file mode 100644 index 0000000..27324a8 --- /dev/null +++ b/app/components/blueToothTest/item2.vue @@ -0,0 +1,11 @@ + + + + + \ No newline at end of file diff --git a/app/components/blufi/crypto/aes.js b/app/components/blufi/crypto/aes.js new file mode 100644 index 0000000..03d90a3 --- /dev/null +++ b/app/components/blufi/crypto/aes.js @@ -0,0 +1,1165 @@ +;(function (root) { + 'use strict' + + const checkInt = value => parseInt(value) === value + + const checkInts = arrayish => { + if (!checkInt(arrayish.length)) { + return false + } + + for (let i = 0; i < arrayish.length; i++) { + if (!checkInt(arrayish[i]) || arrayish[i] < 0 || arrayish[i] > 255) { + return false + } + } + + return true + } + + const coerceArray = (arg, copy) => { + // ArrayBuffer view + if (arg.buffer && ArrayBuffer.isView(arg) && arg.name === 'Uint8Array') { + if (copy) { + if (arg.slice) { + arg = arg.slice() + } else { + arg = Array.prototype.slice.call(arg) + } + } + return arg + } + + // It's an array; check it is a valid representation of a byte + if (Array.isArray(arg)) { + if (!checkInts(arg)) { + throw new Error(`Array contains invalid value: ${arg}`) + } + return new Uint8Array(arg) + } + + // Something else, but behaves like an array (maybe a Buffer? Arguments?) + if (checkInt(arg.length) && checkInts(arg)) { + return new Uint8Array(arg) + } + + throw new Error('unsupported array-like object') + } + + const createArray = length => new Uint8Array(length) + + const copyArray = (sourceArray, targetArray, targetStart, sourceStart, sourceEnd) => { + if (sourceStart != null || sourceEnd != null) { + sourceArray = sourceArray.slice + ? sourceArray.slice(sourceStart, sourceEnd) + : Array.prototype.slice.call(sourceArray, sourceStart, sourceEnd) + } + targetArray.set(sourceArray, targetStart) + } + + const convertUtf8 = (() => { + const toBytes = text => { + const result = [] + let i = 0 + text = encodeURI(text) + + while (i < text.length) { + const c = text.charCodeAt(i++) + // if it is a % sign, encode the following 2 bytes as a hex value + if (c === 37) { + result.push(parseInt(text.substr(i, 2), 16)) + i += 2 + } else { + result.push(c) + } + } + return coerceArray(result) + } + + const fromBytes = bytes => { + const result = [] + let i = 0 + + while (i < bytes.length) { + const c = bytes[i] + if (c < 128) { + result.push(String.fromCharCode(c)) + i++ + } else if (c > 191 && c < 224) { + result.push(String.fromCharCode(((c & 0x1f) << 6) | (bytes[i + 1] & 0x3f))) + i += 2 + } else { + result.push( + String.fromCharCode( + ((c & 0x0f) << 12) | ((bytes[i + 1] & 0x3f) << 6) | (bytes[i + 2] & 0x3f) + ) + ) + i += 3 + } + } + return result.join('') + } + + return { toBytes, fromBytes } + })() + + const convertHex = (() => { + const toBytes = text => { + const result = [] + for (let i = 0; i < text.length; i += 2) { + result.push(parseInt(text.substr(i, 2), 16)) + } + return result + } + + const Hex = '0123456789abcdef' + const fromBytes = bytes => { + const result = [] + for (let i = 0; i < bytes.length; i++) { + const v = bytes[i] + result.push(Hex[(v & 0xf0) >> 4] + Hex[v & 0x0f]) + } + return result.join('') + } + + return { toBytes, fromBytes } + })() + const numberOfRounds = { + 16: 10, + 24: 12, + 32: 14, + } // Round constant words + + const rcon = [ + 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, + 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, + ] // S-box and Inverse S-box (S is for Substitution) + + const S = [ + 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, + 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, + 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, + 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, + 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, + 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, + 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, + 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, + 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, + 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, + 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, + 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, + 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, + 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, + 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, + 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16, + ] + const Si = [ + 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb, + 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, + 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, + 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25, + 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, + 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84, + 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06, + 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, + 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, + 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e, + 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, + 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, + 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f, + 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, + 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, + 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d, + ] // Transformations for encryption + + const T1 = [ + 0xc66363a5, 0xf87c7c84, 0xee777799, 0xf67b7b8d, 0xfff2f20d, 0xd66b6bbd, 0xde6f6fb1, 0x91c5c554, + 0x60303050, 0x02010103, 0xce6767a9, 0x562b2b7d, 0xe7fefe19, 0xb5d7d762, 0x4dababe6, 0xec76769a, + 0x8fcaca45, 0x1f82829d, 0x89c9c940, 0xfa7d7d87, 0xeffafa15, 0xb25959eb, 0x8e4747c9, 0xfbf0f00b, + 0x41adadec, 0xb3d4d467, 0x5fa2a2fd, 0x45afafea, 0x239c9cbf, 0x53a4a4f7, 0xe4727296, 0x9bc0c05b, + 0x75b7b7c2, 0xe1fdfd1c, 0x3d9393ae, 0x4c26266a, 0x6c36365a, 0x7e3f3f41, 0xf5f7f702, 0x83cccc4f, + 0x6834345c, 0x51a5a5f4, 0xd1e5e534, 0xf9f1f108, 0xe2717193, 0xabd8d873, 0x62313153, 0x2a15153f, + 0x0804040c, 0x95c7c752, 0x46232365, 0x9dc3c35e, 0x30181828, 0x379696a1, 0x0a05050f, 0x2f9a9ab5, + 0x0e070709, 0x24121236, 0x1b80809b, 0xdfe2e23d, 0xcdebeb26, 0x4e272769, 0x7fb2b2cd, 0xea75759f, + 0x1209091b, 0x1d83839e, 0x582c2c74, 0x341a1a2e, 0x361b1b2d, 0xdc6e6eb2, 0xb45a5aee, 0x5ba0a0fb, + 0xa45252f6, 0x763b3b4d, 0xb7d6d661, 0x7db3b3ce, 0x5229297b, 0xdde3e33e, 0x5e2f2f71, 0x13848497, + 0xa65353f5, 0xb9d1d168, 0x00000000, 0xc1eded2c, 0x40202060, 0xe3fcfc1f, 0x79b1b1c8, 0xb65b5bed, + 0xd46a6abe, 0x8dcbcb46, 0x67bebed9, 0x7239394b, 0x944a4ade, 0x984c4cd4, 0xb05858e8, 0x85cfcf4a, + 0xbbd0d06b, 0xc5efef2a, 0x4faaaae5, 0xedfbfb16, 0x864343c5, 0x9a4d4dd7, 0x66333355, 0x11858594, + 0x8a4545cf, 0xe9f9f910, 0x04020206, 0xfe7f7f81, 0xa05050f0, 0x783c3c44, 0x259f9fba, 0x4ba8a8e3, + 0xa25151f3, 0x5da3a3fe, 0x804040c0, 0x058f8f8a, 0x3f9292ad, 0x219d9dbc, 0x70383848, 0xf1f5f504, + 0x63bcbcdf, 0x77b6b6c1, 0xafdada75, 0x42212163, 0x20101030, 0xe5ffff1a, 0xfdf3f30e, 0xbfd2d26d, + 0x81cdcd4c, 0x180c0c14, 0x26131335, 0xc3ecec2f, 0xbe5f5fe1, 0x359797a2, 0x884444cc, 0x2e171739, + 0x93c4c457, 0x55a7a7f2, 0xfc7e7e82, 0x7a3d3d47, 0xc86464ac, 0xba5d5de7, 0x3219192b, 0xe6737395, + 0xc06060a0, 0x19818198, 0x9e4f4fd1, 0xa3dcdc7f, 0x44222266, 0x542a2a7e, 0x3b9090ab, 0x0b888883, + 0x8c4646ca, 0xc7eeee29, 0x6bb8b8d3, 0x2814143c, 0xa7dede79, 0xbc5e5ee2, 0x160b0b1d, 0xaddbdb76, + 0xdbe0e03b, 0x64323256, 0x743a3a4e, 0x140a0a1e, 0x924949db, 0x0c06060a, 0x4824246c, 0xb85c5ce4, + 0x9fc2c25d, 0xbdd3d36e, 0x43acacef, 0xc46262a6, 0x399191a8, 0x319595a4, 0xd3e4e437, 0xf279798b, + 0xd5e7e732, 0x8bc8c843, 0x6e373759, 0xda6d6db7, 0x018d8d8c, 0xb1d5d564, 0x9c4e4ed2, 0x49a9a9e0, + 0xd86c6cb4, 0xac5656fa, 0xf3f4f407, 0xcfeaea25, 0xca6565af, 0xf47a7a8e, 0x47aeaee9, 0x10080818, + 0x6fbabad5, 0xf0787888, 0x4a25256f, 0x5c2e2e72, 0x381c1c24, 0x57a6a6f1, 0x73b4b4c7, 0x97c6c651, + 0xcbe8e823, 0xa1dddd7c, 0xe874749c, 0x3e1f1f21, 0x964b4bdd, 0x61bdbddc, 0x0d8b8b86, 0x0f8a8a85, + 0xe0707090, 0x7c3e3e42, 0x71b5b5c4, 0xcc6666aa, 0x904848d8, 0x06030305, 0xf7f6f601, 0x1c0e0e12, + 0xc26161a3, 0x6a35355f, 0xae5757f9, 0x69b9b9d0, 0x17868691, 0x99c1c158, 0x3a1d1d27, 0x279e9eb9, + 0xd9e1e138, 0xebf8f813, 0x2b9898b3, 0x22111133, 0xd26969bb, 0xa9d9d970, 0x078e8e89, 0x339494a7, + 0x2d9b9bb6, 0x3c1e1e22, 0x15878792, 0xc9e9e920, 0x87cece49, 0xaa5555ff, 0x50282878, 0xa5dfdf7a, + 0x038c8c8f, 0x59a1a1f8, 0x09898980, 0x1a0d0d17, 0x65bfbfda, 0xd7e6e631, 0x844242c6, 0xd06868b8, + 0x824141c3, 0x299999b0, 0x5a2d2d77, 0x1e0f0f11, 0x7bb0b0cb, 0xa85454fc, 0x6dbbbbd6, 0x2c16163a, + ] + const T2 = [ + 0xa5c66363, 0x84f87c7c, 0x99ee7777, 0x8df67b7b, 0x0dfff2f2, 0xbdd66b6b, 0xb1de6f6f, 0x5491c5c5, + 0x50603030, 0x03020101, 0xa9ce6767, 0x7d562b2b, 0x19e7fefe, 0x62b5d7d7, 0xe64dabab, 0x9aec7676, + 0x458fcaca, 0x9d1f8282, 0x4089c9c9, 0x87fa7d7d, 0x15effafa, 0xebb25959, 0xc98e4747, 0x0bfbf0f0, + 0xec41adad, 0x67b3d4d4, 0xfd5fa2a2, 0xea45afaf, 0xbf239c9c, 0xf753a4a4, 0x96e47272, 0x5b9bc0c0, + 0xc275b7b7, 0x1ce1fdfd, 0xae3d9393, 0x6a4c2626, 0x5a6c3636, 0x417e3f3f, 0x02f5f7f7, 0x4f83cccc, + 0x5c683434, 0xf451a5a5, 0x34d1e5e5, 0x08f9f1f1, 0x93e27171, 0x73abd8d8, 0x53623131, 0x3f2a1515, + 0x0c080404, 0x5295c7c7, 0x65462323, 0x5e9dc3c3, 0x28301818, 0xa1379696, 0x0f0a0505, 0xb52f9a9a, + 0x090e0707, 0x36241212, 0x9b1b8080, 0x3ddfe2e2, 0x26cdebeb, 0x694e2727, 0xcd7fb2b2, 0x9fea7575, + 0x1b120909, 0x9e1d8383, 0x74582c2c, 0x2e341a1a, 0x2d361b1b, 0xb2dc6e6e, 0xeeb45a5a, 0xfb5ba0a0, + 0xf6a45252, 0x4d763b3b, 0x61b7d6d6, 0xce7db3b3, 0x7b522929, 0x3edde3e3, 0x715e2f2f, 0x97138484, + 0xf5a65353, 0x68b9d1d1, 0x00000000, 0x2cc1eded, 0x60402020, 0x1fe3fcfc, 0xc879b1b1, 0xedb65b5b, + 0xbed46a6a, 0x468dcbcb, 0xd967bebe, 0x4b723939, 0xde944a4a, 0xd4984c4c, 0xe8b05858, 0x4a85cfcf, + 0x6bbbd0d0, 0x2ac5efef, 0xe54faaaa, 0x16edfbfb, 0xc5864343, 0xd79a4d4d, 0x55663333, 0x94118585, + 0xcf8a4545, 0x10e9f9f9, 0x06040202, 0x81fe7f7f, 0xf0a05050, 0x44783c3c, 0xba259f9f, 0xe34ba8a8, + 0xf3a25151, 0xfe5da3a3, 0xc0804040, 0x8a058f8f, 0xad3f9292, 0xbc219d9d, 0x48703838, 0x04f1f5f5, + 0xdf63bcbc, 0xc177b6b6, 0x75afdada, 0x63422121, 0x30201010, 0x1ae5ffff, 0x0efdf3f3, 0x6dbfd2d2, + 0x4c81cdcd, 0x14180c0c, 0x35261313, 0x2fc3ecec, 0xe1be5f5f, 0xa2359797, 0xcc884444, 0x392e1717, + 0x5793c4c4, 0xf255a7a7, 0x82fc7e7e, 0x477a3d3d, 0xacc86464, 0xe7ba5d5d, 0x2b321919, 0x95e67373, + 0xa0c06060, 0x98198181, 0xd19e4f4f, 0x7fa3dcdc, 0x66442222, 0x7e542a2a, 0xab3b9090, 0x830b8888, + 0xca8c4646, 0x29c7eeee, 0xd36bb8b8, 0x3c281414, 0x79a7dede, 0xe2bc5e5e, 0x1d160b0b, 0x76addbdb, + 0x3bdbe0e0, 0x56643232, 0x4e743a3a, 0x1e140a0a, 0xdb924949, 0x0a0c0606, 0x6c482424, 0xe4b85c5c, + 0x5d9fc2c2, 0x6ebdd3d3, 0xef43acac, 0xa6c46262, 0xa8399191, 0xa4319595, 0x37d3e4e4, 0x8bf27979, + 0x32d5e7e7, 0x438bc8c8, 0x596e3737, 0xb7da6d6d, 0x8c018d8d, 0x64b1d5d5, 0xd29c4e4e, 0xe049a9a9, + 0xb4d86c6c, 0xfaac5656, 0x07f3f4f4, 0x25cfeaea, 0xafca6565, 0x8ef47a7a, 0xe947aeae, 0x18100808, + 0xd56fbaba, 0x88f07878, 0x6f4a2525, 0x725c2e2e, 0x24381c1c, 0xf157a6a6, 0xc773b4b4, 0x5197c6c6, + 0x23cbe8e8, 0x7ca1dddd, 0x9ce87474, 0x213e1f1f, 0xdd964b4b, 0xdc61bdbd, 0x860d8b8b, 0x850f8a8a, + 0x90e07070, 0x427c3e3e, 0xc471b5b5, 0xaacc6666, 0xd8904848, 0x05060303, 0x01f7f6f6, 0x121c0e0e, + 0xa3c26161, 0x5f6a3535, 0xf9ae5757, 0xd069b9b9, 0x91178686, 0x5899c1c1, 0x273a1d1d, 0xb9279e9e, + 0x38d9e1e1, 0x13ebf8f8, 0xb32b9898, 0x33221111, 0xbbd26969, 0x70a9d9d9, 0x89078e8e, 0xa7339494, + 0xb62d9b9b, 0x223c1e1e, 0x92158787, 0x20c9e9e9, 0x4987cece, 0xffaa5555, 0x78502828, 0x7aa5dfdf, + 0x8f038c8c, 0xf859a1a1, 0x80098989, 0x171a0d0d, 0xda65bfbf, 0x31d7e6e6, 0xc6844242, 0xb8d06868, + 0xc3824141, 0xb0299999, 0x775a2d2d, 0x111e0f0f, 0xcb7bb0b0, 0xfca85454, 0xd66dbbbb, 0x3a2c1616, + ] + const T3 = [ + 0x63a5c663, 0x7c84f87c, 0x7799ee77, 0x7b8df67b, 0xf20dfff2, 0x6bbdd66b, 0x6fb1de6f, 0xc55491c5, + 0x30506030, 0x01030201, 0x67a9ce67, 0x2b7d562b, 0xfe19e7fe, 0xd762b5d7, 0xabe64dab, 0x769aec76, + 0xca458fca, 0x829d1f82, 0xc94089c9, 0x7d87fa7d, 0xfa15effa, 0x59ebb259, 0x47c98e47, 0xf00bfbf0, + 0xadec41ad, 0xd467b3d4, 0xa2fd5fa2, 0xafea45af, 0x9cbf239c, 0xa4f753a4, 0x7296e472, 0xc05b9bc0, + 0xb7c275b7, 0xfd1ce1fd, 0x93ae3d93, 0x266a4c26, 0x365a6c36, 0x3f417e3f, 0xf702f5f7, 0xcc4f83cc, + 0x345c6834, 0xa5f451a5, 0xe534d1e5, 0xf108f9f1, 0x7193e271, 0xd873abd8, 0x31536231, 0x153f2a15, + 0x040c0804, 0xc75295c7, 0x23654623, 0xc35e9dc3, 0x18283018, 0x96a13796, 0x050f0a05, 0x9ab52f9a, + 0x07090e07, 0x12362412, 0x809b1b80, 0xe23ddfe2, 0xeb26cdeb, 0x27694e27, 0xb2cd7fb2, 0x759fea75, + 0x091b1209, 0x839e1d83, 0x2c74582c, 0x1a2e341a, 0x1b2d361b, 0x6eb2dc6e, 0x5aeeb45a, 0xa0fb5ba0, + 0x52f6a452, 0x3b4d763b, 0xd661b7d6, 0xb3ce7db3, 0x297b5229, 0xe33edde3, 0x2f715e2f, 0x84971384, + 0x53f5a653, 0xd168b9d1, 0x00000000, 0xed2cc1ed, 0x20604020, 0xfc1fe3fc, 0xb1c879b1, 0x5bedb65b, + 0x6abed46a, 0xcb468dcb, 0xbed967be, 0x394b7239, 0x4ade944a, 0x4cd4984c, 0x58e8b058, 0xcf4a85cf, + 0xd06bbbd0, 0xef2ac5ef, 0xaae54faa, 0xfb16edfb, 0x43c58643, 0x4dd79a4d, 0x33556633, 0x85941185, + 0x45cf8a45, 0xf910e9f9, 0x02060402, 0x7f81fe7f, 0x50f0a050, 0x3c44783c, 0x9fba259f, 0xa8e34ba8, + 0x51f3a251, 0xa3fe5da3, 0x40c08040, 0x8f8a058f, 0x92ad3f92, 0x9dbc219d, 0x38487038, 0xf504f1f5, + 0xbcdf63bc, 0xb6c177b6, 0xda75afda, 0x21634221, 0x10302010, 0xff1ae5ff, 0xf30efdf3, 0xd26dbfd2, + 0xcd4c81cd, 0x0c14180c, 0x13352613, 0xec2fc3ec, 0x5fe1be5f, 0x97a23597, 0x44cc8844, 0x17392e17, + 0xc45793c4, 0xa7f255a7, 0x7e82fc7e, 0x3d477a3d, 0x64acc864, 0x5de7ba5d, 0x192b3219, 0x7395e673, + 0x60a0c060, 0x81981981, 0x4fd19e4f, 0xdc7fa3dc, 0x22664422, 0x2a7e542a, 0x90ab3b90, 0x88830b88, + 0x46ca8c46, 0xee29c7ee, 0xb8d36bb8, 0x143c2814, 0xde79a7de, 0x5ee2bc5e, 0x0b1d160b, 0xdb76addb, + 0xe03bdbe0, 0x32566432, 0x3a4e743a, 0x0a1e140a, 0x49db9249, 0x060a0c06, 0x246c4824, 0x5ce4b85c, + 0xc25d9fc2, 0xd36ebdd3, 0xacef43ac, 0x62a6c462, 0x91a83991, 0x95a43195, 0xe437d3e4, 0x798bf279, + 0xe732d5e7, 0xc8438bc8, 0x37596e37, 0x6db7da6d, 0x8d8c018d, 0xd564b1d5, 0x4ed29c4e, 0xa9e049a9, + 0x6cb4d86c, 0x56faac56, 0xf407f3f4, 0xea25cfea, 0x65afca65, 0x7a8ef47a, 0xaee947ae, 0x08181008, + 0xbad56fba, 0x7888f078, 0x256f4a25, 0x2e725c2e, 0x1c24381c, 0xa6f157a6, 0xb4c773b4, 0xc65197c6, + 0xe823cbe8, 0xdd7ca1dd, 0x749ce874, 0x1f213e1f, 0x4bdd964b, 0xbddc61bd, 0x8b860d8b, 0x8a850f8a, + 0x7090e070, 0x3e427c3e, 0xb5c471b5, 0x66aacc66, 0x48d89048, 0x03050603, 0xf601f7f6, 0x0e121c0e, + 0x61a3c261, 0x355f6a35, 0x57f9ae57, 0xb9d069b9, 0x86911786, 0xc15899c1, 0x1d273a1d, 0x9eb9279e, + 0xe138d9e1, 0xf813ebf8, 0x98b32b98, 0x11332211, 0x69bbd269, 0xd970a9d9, 0x8e89078e, 0x94a73394, + 0x9bb62d9b, 0x1e223c1e, 0x87921587, 0xe920c9e9, 0xce4987ce, 0x55ffaa55, 0x28785028, 0xdf7aa5df, + 0x8c8f038c, 0xa1f859a1, 0x89800989, 0x0d171a0d, 0xbfda65bf, 0xe631d7e6, 0x42c68442, 0x68b8d068, + 0x41c38241, 0x99b02999, 0x2d775a2d, 0x0f111e0f, 0xb0cb7bb0, 0x54fca854, 0xbbd66dbb, 0x163a2c16, + ] + const T4 = [ + 0x6363a5c6, 0x7c7c84f8, 0x777799ee, 0x7b7b8df6, 0xf2f20dff, 0x6b6bbdd6, 0x6f6fb1de, 0xc5c55491, + 0x30305060, 0x01010302, 0x6767a9ce, 0x2b2b7d56, 0xfefe19e7, 0xd7d762b5, 0xababe64d, 0x76769aec, + 0xcaca458f, 0x82829d1f, 0xc9c94089, 0x7d7d87fa, 0xfafa15ef, 0x5959ebb2, 0x4747c98e, 0xf0f00bfb, + 0xadadec41, 0xd4d467b3, 0xa2a2fd5f, 0xafafea45, 0x9c9cbf23, 0xa4a4f753, 0x727296e4, 0xc0c05b9b, + 0xb7b7c275, 0xfdfd1ce1, 0x9393ae3d, 0x26266a4c, 0x36365a6c, 0x3f3f417e, 0xf7f702f5, 0xcccc4f83, + 0x34345c68, 0xa5a5f451, 0xe5e534d1, 0xf1f108f9, 0x717193e2, 0xd8d873ab, 0x31315362, 0x15153f2a, + 0x04040c08, 0xc7c75295, 0x23236546, 0xc3c35e9d, 0x18182830, 0x9696a137, 0x05050f0a, 0x9a9ab52f, + 0x0707090e, 0x12123624, 0x80809b1b, 0xe2e23ddf, 0xebeb26cd, 0x2727694e, 0xb2b2cd7f, 0x75759fea, + 0x09091b12, 0x83839e1d, 0x2c2c7458, 0x1a1a2e34, 0x1b1b2d36, 0x6e6eb2dc, 0x5a5aeeb4, 0xa0a0fb5b, + 0x5252f6a4, 0x3b3b4d76, 0xd6d661b7, 0xb3b3ce7d, 0x29297b52, 0xe3e33edd, 0x2f2f715e, 0x84849713, + 0x5353f5a6, 0xd1d168b9, 0x00000000, 0xeded2cc1, 0x20206040, 0xfcfc1fe3, 0xb1b1c879, 0x5b5bedb6, + 0x6a6abed4, 0xcbcb468d, 0xbebed967, 0x39394b72, 0x4a4ade94, 0x4c4cd498, 0x5858e8b0, 0xcfcf4a85, + 0xd0d06bbb, 0xefef2ac5, 0xaaaae54f, 0xfbfb16ed, 0x4343c586, 0x4d4dd79a, 0x33335566, 0x85859411, + 0x4545cf8a, 0xf9f910e9, 0x02020604, 0x7f7f81fe, 0x5050f0a0, 0x3c3c4478, 0x9f9fba25, 0xa8a8e34b, + 0x5151f3a2, 0xa3a3fe5d, 0x4040c080, 0x8f8f8a05, 0x9292ad3f, 0x9d9dbc21, 0x38384870, 0xf5f504f1, + 0xbcbcdf63, 0xb6b6c177, 0xdada75af, 0x21216342, 0x10103020, 0xffff1ae5, 0xf3f30efd, 0xd2d26dbf, + 0xcdcd4c81, 0x0c0c1418, 0x13133526, 0xecec2fc3, 0x5f5fe1be, 0x9797a235, 0x4444cc88, 0x1717392e, + 0xc4c45793, 0xa7a7f255, 0x7e7e82fc, 0x3d3d477a, 0x6464acc8, 0x5d5de7ba, 0x19192b32, 0x737395e6, + 0x6060a0c0, 0x81819819, 0x4f4fd19e, 0xdcdc7fa3, 0x22226644, 0x2a2a7e54, 0x9090ab3b, 0x8888830b, + 0x4646ca8c, 0xeeee29c7, 0xb8b8d36b, 0x14143c28, 0xdede79a7, 0x5e5ee2bc, 0x0b0b1d16, 0xdbdb76ad, + 0xe0e03bdb, 0x32325664, 0x3a3a4e74, 0x0a0a1e14, 0x4949db92, 0x06060a0c, 0x24246c48, 0x5c5ce4b8, + 0xc2c25d9f, 0xd3d36ebd, 0xacacef43, 0x6262a6c4, 0x9191a839, 0x9595a431, 0xe4e437d3, 0x79798bf2, + 0xe7e732d5, 0xc8c8438b, 0x3737596e, 0x6d6db7da, 0x8d8d8c01, 0xd5d564b1, 0x4e4ed29c, 0xa9a9e049, + 0x6c6cb4d8, 0x5656faac, 0xf4f407f3, 0xeaea25cf, 0x6565afca, 0x7a7a8ef4, 0xaeaee947, 0x08081810, + 0xbabad56f, 0x787888f0, 0x25256f4a, 0x2e2e725c, 0x1c1c2438, 0xa6a6f157, 0xb4b4c773, 0xc6c65197, + 0xe8e823cb, 0xdddd7ca1, 0x74749ce8, 0x1f1f213e, 0x4b4bdd96, 0xbdbddc61, 0x8b8b860d, 0x8a8a850f, + 0x707090e0, 0x3e3e427c, 0xb5b5c471, 0x6666aacc, 0x4848d890, 0x03030506, 0xf6f601f7, 0x0e0e121c, + 0x6161a3c2, 0x35355f6a, 0x5757f9ae, 0xb9b9d069, 0x86869117, 0xc1c15899, 0x1d1d273a, 0x9e9eb927, + 0xe1e138d9, 0xf8f813eb, 0x9898b32b, 0x11113322, 0x6969bbd2, 0xd9d970a9, 0x8e8e8907, 0x9494a733, + 0x9b9bb62d, 0x1e1e223c, 0x87879215, 0xe9e920c9, 0xcece4987, 0x5555ffaa, 0x28287850, 0xdfdf7aa5, + 0x8c8c8f03, 0xa1a1f859, 0x89898009, 0x0d0d171a, 0xbfbfda65, 0xe6e631d7, 0x4242c684, 0x6868b8d0, + 0x4141c382, 0x9999b029, 0x2d2d775a, 0x0f0f111e, 0xb0b0cb7b, 0x5454fca8, 0xbbbbd66d, 0x16163a2c, + ] // Transformations for decryption + + const T5 = [ + 0x51f4a750, 0x7e416553, 0x1a17a4c3, 0x3a275e96, 0x3bab6bcb, 0x1f9d45f1, 0xacfa58ab, 0x4be30393, + 0x2030fa55, 0xad766df6, 0x88cc7691, 0xf5024c25, 0x4fe5d7fc, 0xc52acbd7, 0x26354480, 0xb562a38f, + 0xdeb15a49, 0x25ba1b67, 0x45ea0e98, 0x5dfec0e1, 0xc32f7502, 0x814cf012, 0x8d4697a3, 0x6bd3f9c6, + 0x038f5fe7, 0x15929c95, 0xbf6d7aeb, 0x955259da, 0xd4be832d, 0x587421d3, 0x49e06929, 0x8ec9c844, + 0x75c2896a, 0xf48e7978, 0x99583e6b, 0x27b971dd, 0xbee14fb6, 0xf088ad17, 0xc920ac66, 0x7dce3ab4, + 0x63df4a18, 0xe51a3182, 0x97513360, 0x62537f45, 0xb16477e0, 0xbb6bae84, 0xfe81a01c, 0xf9082b94, + 0x70486858, 0x8f45fd19, 0x94de6c87, 0x527bf8b7, 0xab73d323, 0x724b02e2, 0xe31f8f57, 0x6655ab2a, + 0xb2eb2807, 0x2fb5c203, 0x86c57b9a, 0xd33708a5, 0x302887f2, 0x23bfa5b2, 0x02036aba, 0xed16825c, + 0x8acf1c2b, 0xa779b492, 0xf307f2f0, 0x4e69e2a1, 0x65daf4cd, 0x0605bed5, 0xd134621f, 0xc4a6fe8a, + 0x342e539d, 0xa2f355a0, 0x058ae132, 0xa4f6eb75, 0x0b83ec39, 0x4060efaa, 0x5e719f06, 0xbd6e1051, + 0x3e218af9, 0x96dd063d, 0xdd3e05ae, 0x4de6bd46, 0x91548db5, 0x71c45d05, 0x0406d46f, 0x605015ff, + 0x1998fb24, 0xd6bde997, 0x894043cc, 0x67d99e77, 0xb0e842bd, 0x07898b88, 0xe7195b38, 0x79c8eedb, + 0xa17c0a47, 0x7c420fe9, 0xf8841ec9, 0x00000000, 0x09808683, 0x322bed48, 0x1e1170ac, 0x6c5a724e, + 0xfd0efffb, 0x0f853856, 0x3daed51e, 0x362d3927, 0x0a0fd964, 0x685ca621, 0x9b5b54d1, 0x24362e3a, + 0x0c0a67b1, 0x9357e70f, 0xb4ee96d2, 0x1b9b919e, 0x80c0c54f, 0x61dc20a2, 0x5a774b69, 0x1c121a16, + 0xe293ba0a, 0xc0a02ae5, 0x3c22e043, 0x121b171d, 0x0e090d0b, 0xf28bc7ad, 0x2db6a8b9, 0x141ea9c8, + 0x57f11985, 0xaf75074c, 0xee99ddbb, 0xa37f60fd, 0xf701269f, 0x5c72f5bc, 0x44663bc5, 0x5bfb7e34, + 0x8b432976, 0xcb23c6dc, 0xb6edfc68, 0xb8e4f163, 0xd731dcca, 0x42638510, 0x13972240, 0x84c61120, + 0x854a247d, 0xd2bb3df8, 0xaef93211, 0xc729a16d, 0x1d9e2f4b, 0xdcb230f3, 0x0d8652ec, 0x77c1e3d0, + 0x2bb3166c, 0xa970b999, 0x119448fa, 0x47e96422, 0xa8fc8cc4, 0xa0f03f1a, 0x567d2cd8, 0x223390ef, + 0x87494ec7, 0xd938d1c1, 0x8ccaa2fe, 0x98d40b36, 0xa6f581cf, 0xa57ade28, 0xdab78e26, 0x3fadbfa4, + 0x2c3a9de4, 0x5078920d, 0x6a5fcc9b, 0x547e4662, 0xf68d13c2, 0x90d8b8e8, 0x2e39f75e, 0x82c3aff5, + 0x9f5d80be, 0x69d0937c, 0x6fd52da9, 0xcf2512b3, 0xc8ac993b, 0x10187da7, 0xe89c636e, 0xdb3bbb7b, + 0xcd267809, 0x6e5918f4, 0xec9ab701, 0x834f9aa8, 0xe6956e65, 0xaaffe67e, 0x21bccf08, 0xef15e8e6, + 0xbae79bd9, 0x4a6f36ce, 0xea9f09d4, 0x29b07cd6, 0x31a4b2af, 0x2a3f2331, 0xc6a59430, 0x35a266c0, + 0x744ebc37, 0xfc82caa6, 0xe090d0b0, 0x33a7d815, 0xf104984a, 0x41ecdaf7, 0x7fcd500e, 0x1791f62f, + 0x764dd68d, 0x43efb04d, 0xccaa4d54, 0xe49604df, 0x9ed1b5e3, 0x4c6a881b, 0xc12c1fb8, 0x4665517f, + 0x9d5eea04, 0x018c355d, 0xfa877473, 0xfb0b412e, 0xb3671d5a, 0x92dbd252, 0xe9105633, 0x6dd64713, + 0x9ad7618c, 0x37a10c7a, 0x59f8148e, 0xeb133c89, 0xcea927ee, 0xb761c935, 0xe11ce5ed, 0x7a47b13c, + 0x9cd2df59, 0x55f2733f, 0x1814ce79, 0x73c737bf, 0x53f7cdea, 0x5ffdaa5b, 0xdf3d6f14, 0x7844db86, + 0xcaaff381, 0xb968c43e, 0x3824342c, 0xc2a3405f, 0x161dc372, 0xbce2250c, 0x283c498b, 0xff0d9541, + 0x39a80171, 0x080cb3de, 0xd8b4e49c, 0x6456c190, 0x7bcb8461, 0xd532b670, 0x486c5c74, 0xd0b85742, + ] + const T6 = [ + 0x5051f4a7, 0x537e4165, 0xc31a17a4, 0x963a275e, 0xcb3bab6b, 0xf11f9d45, 0xabacfa58, 0x934be303, + 0x552030fa, 0xf6ad766d, 0x9188cc76, 0x25f5024c, 0xfc4fe5d7, 0xd7c52acb, 0x80263544, 0x8fb562a3, + 0x49deb15a, 0x6725ba1b, 0x9845ea0e, 0xe15dfec0, 0x02c32f75, 0x12814cf0, 0xa38d4697, 0xc66bd3f9, + 0xe7038f5f, 0x9515929c, 0xebbf6d7a, 0xda955259, 0x2dd4be83, 0xd3587421, 0x2949e069, 0x448ec9c8, + 0x6a75c289, 0x78f48e79, 0x6b99583e, 0xdd27b971, 0xb6bee14f, 0x17f088ad, 0x66c920ac, 0xb47dce3a, + 0x1863df4a, 0x82e51a31, 0x60975133, 0x4562537f, 0xe0b16477, 0x84bb6bae, 0x1cfe81a0, 0x94f9082b, + 0x58704868, 0x198f45fd, 0x8794de6c, 0xb7527bf8, 0x23ab73d3, 0xe2724b02, 0x57e31f8f, 0x2a6655ab, + 0x07b2eb28, 0x032fb5c2, 0x9a86c57b, 0xa5d33708, 0xf2302887, 0xb223bfa5, 0xba02036a, 0x5ced1682, + 0x2b8acf1c, 0x92a779b4, 0xf0f307f2, 0xa14e69e2, 0xcd65daf4, 0xd50605be, 0x1fd13462, 0x8ac4a6fe, + 0x9d342e53, 0xa0a2f355, 0x32058ae1, 0x75a4f6eb, 0x390b83ec, 0xaa4060ef, 0x065e719f, 0x51bd6e10, + 0xf93e218a, 0x3d96dd06, 0xaedd3e05, 0x464de6bd, 0xb591548d, 0x0571c45d, 0x6f0406d4, 0xff605015, + 0x241998fb, 0x97d6bde9, 0xcc894043, 0x7767d99e, 0xbdb0e842, 0x8807898b, 0x38e7195b, 0xdb79c8ee, + 0x47a17c0a, 0xe97c420f, 0xc9f8841e, 0x00000000, 0x83098086, 0x48322bed, 0xac1e1170, 0x4e6c5a72, + 0xfbfd0eff, 0x560f8538, 0x1e3daed5, 0x27362d39, 0x640a0fd9, 0x21685ca6, 0xd19b5b54, 0x3a24362e, + 0xb10c0a67, 0x0f9357e7, 0xd2b4ee96, 0x9e1b9b91, 0x4f80c0c5, 0xa261dc20, 0x695a774b, 0x161c121a, + 0x0ae293ba, 0xe5c0a02a, 0x433c22e0, 0x1d121b17, 0x0b0e090d, 0xadf28bc7, 0xb92db6a8, 0xc8141ea9, + 0x8557f119, 0x4caf7507, 0xbbee99dd, 0xfda37f60, 0x9ff70126, 0xbc5c72f5, 0xc544663b, 0x345bfb7e, + 0x768b4329, 0xdccb23c6, 0x68b6edfc, 0x63b8e4f1, 0xcad731dc, 0x10426385, 0x40139722, 0x2084c611, + 0x7d854a24, 0xf8d2bb3d, 0x11aef932, 0x6dc729a1, 0x4b1d9e2f, 0xf3dcb230, 0xec0d8652, 0xd077c1e3, + 0x6c2bb316, 0x99a970b9, 0xfa119448, 0x2247e964, 0xc4a8fc8c, 0x1aa0f03f, 0xd8567d2c, 0xef223390, + 0xc787494e, 0xc1d938d1, 0xfe8ccaa2, 0x3698d40b, 0xcfa6f581, 0x28a57ade, 0x26dab78e, 0xa43fadbf, + 0xe42c3a9d, 0x0d507892, 0x9b6a5fcc, 0x62547e46, 0xc2f68d13, 0xe890d8b8, 0x5e2e39f7, 0xf582c3af, + 0xbe9f5d80, 0x7c69d093, 0xa96fd52d, 0xb3cf2512, 0x3bc8ac99, 0xa710187d, 0x6ee89c63, 0x7bdb3bbb, + 0x09cd2678, 0xf46e5918, 0x01ec9ab7, 0xa8834f9a, 0x65e6956e, 0x7eaaffe6, 0x0821bccf, 0xe6ef15e8, + 0xd9bae79b, 0xce4a6f36, 0xd4ea9f09, 0xd629b07c, 0xaf31a4b2, 0x312a3f23, 0x30c6a594, 0xc035a266, + 0x37744ebc, 0xa6fc82ca, 0xb0e090d0, 0x1533a7d8, 0x4af10498, 0xf741ecda, 0x0e7fcd50, 0x2f1791f6, + 0x8d764dd6, 0x4d43efb0, 0x54ccaa4d, 0xdfe49604, 0xe39ed1b5, 0x1b4c6a88, 0xb8c12c1f, 0x7f466551, + 0x049d5eea, 0x5d018c35, 0x73fa8774, 0x2efb0b41, 0x5ab3671d, 0x5292dbd2, 0x33e91056, 0x136dd647, + 0x8c9ad761, 0x7a37a10c, 0x8e59f814, 0x89eb133c, 0xeecea927, 0x35b761c9, 0xede11ce5, 0x3c7a47b1, + 0x599cd2df, 0x3f55f273, 0x791814ce, 0xbf73c737, 0xea53f7cd, 0x5b5ffdaa, 0x14df3d6f, 0x867844db, + 0x81caaff3, 0x3eb968c4, 0x2c382434, 0x5fc2a340, 0x72161dc3, 0x0cbce225, 0x8b283c49, 0x41ff0d95, + 0x7139a801, 0xde080cb3, 0x9cd8b4e4, 0x906456c1, 0x617bcb84, 0x70d532b6, 0x74486c5c, 0x42d0b857, + ] + const T7 = [ + 0xa75051f4, 0x65537e41, 0xa4c31a17, 0x5e963a27, 0x6bcb3bab, 0x45f11f9d, 0x58abacfa, 0x03934be3, + 0xfa552030, 0x6df6ad76, 0x769188cc, 0x4c25f502, 0xd7fc4fe5, 0xcbd7c52a, 0x44802635, 0xa38fb562, + 0x5a49deb1, 0x1b6725ba, 0x0e9845ea, 0xc0e15dfe, 0x7502c32f, 0xf012814c, 0x97a38d46, 0xf9c66bd3, + 0x5fe7038f, 0x9c951592, 0x7aebbf6d, 0x59da9552, 0x832dd4be, 0x21d35874, 0x692949e0, 0xc8448ec9, + 0x896a75c2, 0x7978f48e, 0x3e6b9958, 0x71dd27b9, 0x4fb6bee1, 0xad17f088, 0xac66c920, 0x3ab47dce, + 0x4a1863df, 0x3182e51a, 0x33609751, 0x7f456253, 0x77e0b164, 0xae84bb6b, 0xa01cfe81, 0x2b94f908, + 0x68587048, 0xfd198f45, 0x6c8794de, 0xf8b7527b, 0xd323ab73, 0x02e2724b, 0x8f57e31f, 0xab2a6655, + 0x2807b2eb, 0xc2032fb5, 0x7b9a86c5, 0x08a5d337, 0x87f23028, 0xa5b223bf, 0x6aba0203, 0x825ced16, + 0x1c2b8acf, 0xb492a779, 0xf2f0f307, 0xe2a14e69, 0xf4cd65da, 0xbed50605, 0x621fd134, 0xfe8ac4a6, + 0x539d342e, 0x55a0a2f3, 0xe132058a, 0xeb75a4f6, 0xec390b83, 0xefaa4060, 0x9f065e71, 0x1051bd6e, + 0x8af93e21, 0x063d96dd, 0x05aedd3e, 0xbd464de6, 0x8db59154, 0x5d0571c4, 0xd46f0406, 0x15ff6050, + 0xfb241998, 0xe997d6bd, 0x43cc8940, 0x9e7767d9, 0x42bdb0e8, 0x8b880789, 0x5b38e719, 0xeedb79c8, + 0x0a47a17c, 0x0fe97c42, 0x1ec9f884, 0x00000000, 0x86830980, 0xed48322b, 0x70ac1e11, 0x724e6c5a, + 0xfffbfd0e, 0x38560f85, 0xd51e3dae, 0x3927362d, 0xd9640a0f, 0xa621685c, 0x54d19b5b, 0x2e3a2436, + 0x67b10c0a, 0xe70f9357, 0x96d2b4ee, 0x919e1b9b, 0xc54f80c0, 0x20a261dc, 0x4b695a77, 0x1a161c12, + 0xba0ae293, 0x2ae5c0a0, 0xe0433c22, 0x171d121b, 0x0d0b0e09, 0xc7adf28b, 0xa8b92db6, 0xa9c8141e, + 0x198557f1, 0x074caf75, 0xddbbee99, 0x60fda37f, 0x269ff701, 0xf5bc5c72, 0x3bc54466, 0x7e345bfb, + 0x29768b43, 0xc6dccb23, 0xfc68b6ed, 0xf163b8e4, 0xdccad731, 0x85104263, 0x22401397, 0x112084c6, + 0x247d854a, 0x3df8d2bb, 0x3211aef9, 0xa16dc729, 0x2f4b1d9e, 0x30f3dcb2, 0x52ec0d86, 0xe3d077c1, + 0x166c2bb3, 0xb999a970, 0x48fa1194, 0x642247e9, 0x8cc4a8fc, 0x3f1aa0f0, 0x2cd8567d, 0x90ef2233, + 0x4ec78749, 0xd1c1d938, 0xa2fe8cca, 0x0b3698d4, 0x81cfa6f5, 0xde28a57a, 0x8e26dab7, 0xbfa43fad, + 0x9de42c3a, 0x920d5078, 0xcc9b6a5f, 0x4662547e, 0x13c2f68d, 0xb8e890d8, 0xf75e2e39, 0xaff582c3, + 0x80be9f5d, 0x937c69d0, 0x2da96fd5, 0x12b3cf25, 0x993bc8ac, 0x7da71018, 0x636ee89c, 0xbb7bdb3b, + 0x7809cd26, 0x18f46e59, 0xb701ec9a, 0x9aa8834f, 0x6e65e695, 0xe67eaaff, 0xcf0821bc, 0xe8e6ef15, + 0x9bd9bae7, 0x36ce4a6f, 0x09d4ea9f, 0x7cd629b0, 0xb2af31a4, 0x23312a3f, 0x9430c6a5, 0x66c035a2, + 0xbc37744e, 0xcaa6fc82, 0xd0b0e090, 0xd81533a7, 0x984af104, 0xdaf741ec, 0x500e7fcd, 0xf62f1791, + 0xd68d764d, 0xb04d43ef, 0x4d54ccaa, 0x04dfe496, 0xb5e39ed1, 0x881b4c6a, 0x1fb8c12c, 0x517f4665, + 0xea049d5e, 0x355d018c, 0x7473fa87, 0x412efb0b, 0x1d5ab367, 0xd25292db, 0x5633e910, 0x47136dd6, + 0x618c9ad7, 0x0c7a37a1, 0x148e59f8, 0x3c89eb13, 0x27eecea9, 0xc935b761, 0xe5ede11c, 0xb13c7a47, + 0xdf599cd2, 0x733f55f2, 0xce791814, 0x37bf73c7, 0xcdea53f7, 0xaa5b5ffd, 0x6f14df3d, 0xdb867844, + 0xf381caaf, 0xc43eb968, 0x342c3824, 0x405fc2a3, 0xc372161d, 0x250cbce2, 0x498b283c, 0x9541ff0d, + 0x017139a8, 0xb3de080c, 0xe49cd8b4, 0xc1906456, 0x84617bcb, 0xb670d532, 0x5c74486c, 0x5742d0b8, + ] + const T8 = [ + 0xf4a75051, 0x4165537e, 0x17a4c31a, 0x275e963a, 0xab6bcb3b, 0x9d45f11f, 0xfa58abac, 0xe303934b, + 0x30fa5520, 0x766df6ad, 0xcc769188, 0x024c25f5, 0xe5d7fc4f, 0x2acbd7c5, 0x35448026, 0x62a38fb5, + 0xb15a49de, 0xba1b6725, 0xea0e9845, 0xfec0e15d, 0x2f7502c3, 0x4cf01281, 0x4697a38d, 0xd3f9c66b, + 0x8f5fe703, 0x929c9515, 0x6d7aebbf, 0x5259da95, 0xbe832dd4, 0x7421d358, 0xe0692949, 0xc9c8448e, + 0xc2896a75, 0x8e7978f4, 0x583e6b99, 0xb971dd27, 0xe14fb6be, 0x88ad17f0, 0x20ac66c9, 0xce3ab47d, + 0xdf4a1863, 0x1a3182e5, 0x51336097, 0x537f4562, 0x6477e0b1, 0x6bae84bb, 0x81a01cfe, 0x082b94f9, + 0x48685870, 0x45fd198f, 0xde6c8794, 0x7bf8b752, 0x73d323ab, 0x4b02e272, 0x1f8f57e3, 0x55ab2a66, + 0xeb2807b2, 0xb5c2032f, 0xc57b9a86, 0x3708a5d3, 0x2887f230, 0xbfa5b223, 0x036aba02, 0x16825ced, + 0xcf1c2b8a, 0x79b492a7, 0x07f2f0f3, 0x69e2a14e, 0xdaf4cd65, 0x05bed506, 0x34621fd1, 0xa6fe8ac4, + 0x2e539d34, 0xf355a0a2, 0x8ae13205, 0xf6eb75a4, 0x83ec390b, 0x60efaa40, 0x719f065e, 0x6e1051bd, + 0x218af93e, 0xdd063d96, 0x3e05aedd, 0xe6bd464d, 0x548db591, 0xc45d0571, 0x06d46f04, 0x5015ff60, + 0x98fb2419, 0xbde997d6, 0x4043cc89, 0xd99e7767, 0xe842bdb0, 0x898b8807, 0x195b38e7, 0xc8eedb79, + 0x7c0a47a1, 0x420fe97c, 0x841ec9f8, 0x00000000, 0x80868309, 0x2bed4832, 0x1170ac1e, 0x5a724e6c, + 0x0efffbfd, 0x8538560f, 0xaed51e3d, 0x2d392736, 0x0fd9640a, 0x5ca62168, 0x5b54d19b, 0x362e3a24, + 0x0a67b10c, 0x57e70f93, 0xee96d2b4, 0x9b919e1b, 0xc0c54f80, 0xdc20a261, 0x774b695a, 0x121a161c, + 0x93ba0ae2, 0xa02ae5c0, 0x22e0433c, 0x1b171d12, 0x090d0b0e, 0x8bc7adf2, 0xb6a8b92d, 0x1ea9c814, + 0xf1198557, 0x75074caf, 0x99ddbbee, 0x7f60fda3, 0x01269ff7, 0x72f5bc5c, 0x663bc544, 0xfb7e345b, + 0x4329768b, 0x23c6dccb, 0xedfc68b6, 0xe4f163b8, 0x31dccad7, 0x63851042, 0x97224013, 0xc6112084, + 0x4a247d85, 0xbb3df8d2, 0xf93211ae, 0x29a16dc7, 0x9e2f4b1d, 0xb230f3dc, 0x8652ec0d, 0xc1e3d077, + 0xb3166c2b, 0x70b999a9, 0x9448fa11, 0xe9642247, 0xfc8cc4a8, 0xf03f1aa0, 0x7d2cd856, 0x3390ef22, + 0x494ec787, 0x38d1c1d9, 0xcaa2fe8c, 0xd40b3698, 0xf581cfa6, 0x7ade28a5, 0xb78e26da, 0xadbfa43f, + 0x3a9de42c, 0x78920d50, 0x5fcc9b6a, 0x7e466254, 0x8d13c2f6, 0xd8b8e890, 0x39f75e2e, 0xc3aff582, + 0x5d80be9f, 0xd0937c69, 0xd52da96f, 0x2512b3cf, 0xac993bc8, 0x187da710, 0x9c636ee8, 0x3bbb7bdb, + 0x267809cd, 0x5918f46e, 0x9ab701ec, 0x4f9aa883, 0x956e65e6, 0xffe67eaa, 0xbccf0821, 0x15e8e6ef, + 0xe79bd9ba, 0x6f36ce4a, 0x9f09d4ea, 0xb07cd629, 0xa4b2af31, 0x3f23312a, 0xa59430c6, 0xa266c035, + 0x4ebc3774, 0x82caa6fc, 0x90d0b0e0, 0xa7d81533, 0x04984af1, 0xecdaf741, 0xcd500e7f, 0x91f62f17, + 0x4dd68d76, 0xefb04d43, 0xaa4d54cc, 0x9604dfe4, 0xd1b5e39e, 0x6a881b4c, 0x2c1fb8c1, 0x65517f46, + 0x5eea049d, 0x8c355d01, 0x877473fa, 0x0b412efb, 0x671d5ab3, 0xdbd25292, 0x105633e9, 0xd647136d, + 0xd7618c9a, 0xa10c7a37, 0xf8148e59, 0x133c89eb, 0xa927eece, 0x61c935b7, 0x1ce5ede1, 0x47b13c7a, + 0xd2df599c, 0xf2733f55, 0x14ce7918, 0xc737bf73, 0xf7cdea53, 0xfdaa5b5f, 0x3d6f14df, 0x44db8678, + 0xaff381ca, 0x68c43eb9, 0x24342c38, 0xa3405fc2, 0x1dc37216, 0xe2250cbc, 0x3c498b28, 0x0d9541ff, + 0xa8017139, 0x0cb3de08, 0xb4e49cd8, 0x56c19064, 0xcb84617b, 0x32b670d5, 0x6c5c7448, 0xb85742d0, + ] // Transformations for decryption key expansion + + const U1 = [ + 0x00000000, 0x0e090d0b, 0x1c121a16, 0x121b171d, 0x3824342c, 0x362d3927, 0x24362e3a, 0x2a3f2331, + 0x70486858, 0x7e416553, 0x6c5a724e, 0x62537f45, 0x486c5c74, 0x4665517f, 0x547e4662, 0x5a774b69, + 0xe090d0b0, 0xee99ddbb, 0xfc82caa6, 0xf28bc7ad, 0xd8b4e49c, 0xd6bde997, 0xc4a6fe8a, 0xcaaff381, + 0x90d8b8e8, 0x9ed1b5e3, 0x8ccaa2fe, 0x82c3aff5, 0xa8fc8cc4, 0xa6f581cf, 0xb4ee96d2, 0xbae79bd9, + 0xdb3bbb7b, 0xd532b670, 0xc729a16d, 0xc920ac66, 0xe31f8f57, 0xed16825c, 0xff0d9541, 0xf104984a, + 0xab73d323, 0xa57ade28, 0xb761c935, 0xb968c43e, 0x9357e70f, 0x9d5eea04, 0x8f45fd19, 0x814cf012, + 0x3bab6bcb, 0x35a266c0, 0x27b971dd, 0x29b07cd6, 0x038f5fe7, 0x0d8652ec, 0x1f9d45f1, 0x119448fa, + 0x4be30393, 0x45ea0e98, 0x57f11985, 0x59f8148e, 0x73c737bf, 0x7dce3ab4, 0x6fd52da9, 0x61dc20a2, + 0xad766df6, 0xa37f60fd, 0xb16477e0, 0xbf6d7aeb, 0x955259da, 0x9b5b54d1, 0x894043cc, 0x87494ec7, + 0xdd3e05ae, 0xd33708a5, 0xc12c1fb8, 0xcf2512b3, 0xe51a3182, 0xeb133c89, 0xf9082b94, 0xf701269f, + 0x4de6bd46, 0x43efb04d, 0x51f4a750, 0x5ffdaa5b, 0x75c2896a, 0x7bcb8461, 0x69d0937c, 0x67d99e77, + 0x3daed51e, 0x33a7d815, 0x21bccf08, 0x2fb5c203, 0x058ae132, 0x0b83ec39, 0x1998fb24, 0x1791f62f, + 0x764dd68d, 0x7844db86, 0x6a5fcc9b, 0x6456c190, 0x4e69e2a1, 0x4060efaa, 0x527bf8b7, 0x5c72f5bc, + 0x0605bed5, 0x080cb3de, 0x1a17a4c3, 0x141ea9c8, 0x3e218af9, 0x302887f2, 0x223390ef, 0x2c3a9de4, + 0x96dd063d, 0x98d40b36, 0x8acf1c2b, 0x84c61120, 0xaef93211, 0xa0f03f1a, 0xb2eb2807, 0xbce2250c, + 0xe6956e65, 0xe89c636e, 0xfa877473, 0xf48e7978, 0xdeb15a49, 0xd0b85742, 0xc2a3405f, 0xccaa4d54, + 0x41ecdaf7, 0x4fe5d7fc, 0x5dfec0e1, 0x53f7cdea, 0x79c8eedb, 0x77c1e3d0, 0x65daf4cd, 0x6bd3f9c6, + 0x31a4b2af, 0x3fadbfa4, 0x2db6a8b9, 0x23bfa5b2, 0x09808683, 0x07898b88, 0x15929c95, 0x1b9b919e, + 0xa17c0a47, 0xaf75074c, 0xbd6e1051, 0xb3671d5a, 0x99583e6b, 0x97513360, 0x854a247d, 0x8b432976, + 0xd134621f, 0xdf3d6f14, 0xcd267809, 0xc32f7502, 0xe9105633, 0xe7195b38, 0xf5024c25, 0xfb0b412e, + 0x9ad7618c, 0x94de6c87, 0x86c57b9a, 0x88cc7691, 0xa2f355a0, 0xacfa58ab, 0xbee14fb6, 0xb0e842bd, + 0xea9f09d4, 0xe49604df, 0xf68d13c2, 0xf8841ec9, 0xd2bb3df8, 0xdcb230f3, 0xcea927ee, 0xc0a02ae5, + 0x7a47b13c, 0x744ebc37, 0x6655ab2a, 0x685ca621, 0x42638510, 0x4c6a881b, 0x5e719f06, 0x5078920d, + 0x0a0fd964, 0x0406d46f, 0x161dc372, 0x1814ce79, 0x322bed48, 0x3c22e043, 0x2e39f75e, 0x2030fa55, + 0xec9ab701, 0xe293ba0a, 0xf088ad17, 0xfe81a01c, 0xd4be832d, 0xdab78e26, 0xc8ac993b, 0xc6a59430, + 0x9cd2df59, 0x92dbd252, 0x80c0c54f, 0x8ec9c844, 0xa4f6eb75, 0xaaffe67e, 0xb8e4f163, 0xb6edfc68, + 0x0c0a67b1, 0x02036aba, 0x10187da7, 0x1e1170ac, 0x342e539d, 0x3a275e96, 0x283c498b, 0x26354480, + 0x7c420fe9, 0x724b02e2, 0x605015ff, 0x6e5918f4, 0x44663bc5, 0x4a6f36ce, 0x587421d3, 0x567d2cd8, + 0x37a10c7a, 0x39a80171, 0x2bb3166c, 0x25ba1b67, 0x0f853856, 0x018c355d, 0x13972240, 0x1d9e2f4b, + 0x47e96422, 0x49e06929, 0x5bfb7e34, 0x55f2733f, 0x7fcd500e, 0x71c45d05, 0x63df4a18, 0x6dd64713, + 0xd731dcca, 0xd938d1c1, 0xcb23c6dc, 0xc52acbd7, 0xef15e8e6, 0xe11ce5ed, 0xf307f2f0, 0xfd0efffb, + 0xa779b492, 0xa970b999, 0xbb6bae84, 0xb562a38f, 0x9f5d80be, 0x91548db5, 0x834f9aa8, 0x8d4697a3, + ] + const U2 = [ + 0x00000000, 0x0b0e090d, 0x161c121a, 0x1d121b17, 0x2c382434, 0x27362d39, 0x3a24362e, 0x312a3f23, + 0x58704868, 0x537e4165, 0x4e6c5a72, 0x4562537f, 0x74486c5c, 0x7f466551, 0x62547e46, 0x695a774b, + 0xb0e090d0, 0xbbee99dd, 0xa6fc82ca, 0xadf28bc7, 0x9cd8b4e4, 0x97d6bde9, 0x8ac4a6fe, 0x81caaff3, + 0xe890d8b8, 0xe39ed1b5, 0xfe8ccaa2, 0xf582c3af, 0xc4a8fc8c, 0xcfa6f581, 0xd2b4ee96, 0xd9bae79b, + 0x7bdb3bbb, 0x70d532b6, 0x6dc729a1, 0x66c920ac, 0x57e31f8f, 0x5ced1682, 0x41ff0d95, 0x4af10498, + 0x23ab73d3, 0x28a57ade, 0x35b761c9, 0x3eb968c4, 0x0f9357e7, 0x049d5eea, 0x198f45fd, 0x12814cf0, + 0xcb3bab6b, 0xc035a266, 0xdd27b971, 0xd629b07c, 0xe7038f5f, 0xec0d8652, 0xf11f9d45, 0xfa119448, + 0x934be303, 0x9845ea0e, 0x8557f119, 0x8e59f814, 0xbf73c737, 0xb47dce3a, 0xa96fd52d, 0xa261dc20, + 0xf6ad766d, 0xfda37f60, 0xe0b16477, 0xebbf6d7a, 0xda955259, 0xd19b5b54, 0xcc894043, 0xc787494e, + 0xaedd3e05, 0xa5d33708, 0xb8c12c1f, 0xb3cf2512, 0x82e51a31, 0x89eb133c, 0x94f9082b, 0x9ff70126, + 0x464de6bd, 0x4d43efb0, 0x5051f4a7, 0x5b5ffdaa, 0x6a75c289, 0x617bcb84, 0x7c69d093, 0x7767d99e, + 0x1e3daed5, 0x1533a7d8, 0x0821bccf, 0x032fb5c2, 0x32058ae1, 0x390b83ec, 0x241998fb, 0x2f1791f6, + 0x8d764dd6, 0x867844db, 0x9b6a5fcc, 0x906456c1, 0xa14e69e2, 0xaa4060ef, 0xb7527bf8, 0xbc5c72f5, + 0xd50605be, 0xde080cb3, 0xc31a17a4, 0xc8141ea9, 0xf93e218a, 0xf2302887, 0xef223390, 0xe42c3a9d, + 0x3d96dd06, 0x3698d40b, 0x2b8acf1c, 0x2084c611, 0x11aef932, 0x1aa0f03f, 0x07b2eb28, 0x0cbce225, + 0x65e6956e, 0x6ee89c63, 0x73fa8774, 0x78f48e79, 0x49deb15a, 0x42d0b857, 0x5fc2a340, 0x54ccaa4d, + 0xf741ecda, 0xfc4fe5d7, 0xe15dfec0, 0xea53f7cd, 0xdb79c8ee, 0xd077c1e3, 0xcd65daf4, 0xc66bd3f9, + 0xaf31a4b2, 0xa43fadbf, 0xb92db6a8, 0xb223bfa5, 0x83098086, 0x8807898b, 0x9515929c, 0x9e1b9b91, + 0x47a17c0a, 0x4caf7507, 0x51bd6e10, 0x5ab3671d, 0x6b99583e, 0x60975133, 0x7d854a24, 0x768b4329, + 0x1fd13462, 0x14df3d6f, 0x09cd2678, 0x02c32f75, 0x33e91056, 0x38e7195b, 0x25f5024c, 0x2efb0b41, + 0x8c9ad761, 0x8794de6c, 0x9a86c57b, 0x9188cc76, 0xa0a2f355, 0xabacfa58, 0xb6bee14f, 0xbdb0e842, + 0xd4ea9f09, 0xdfe49604, 0xc2f68d13, 0xc9f8841e, 0xf8d2bb3d, 0xf3dcb230, 0xeecea927, 0xe5c0a02a, + 0x3c7a47b1, 0x37744ebc, 0x2a6655ab, 0x21685ca6, 0x10426385, 0x1b4c6a88, 0x065e719f, 0x0d507892, + 0x640a0fd9, 0x6f0406d4, 0x72161dc3, 0x791814ce, 0x48322bed, 0x433c22e0, 0x5e2e39f7, 0x552030fa, + 0x01ec9ab7, 0x0ae293ba, 0x17f088ad, 0x1cfe81a0, 0x2dd4be83, 0x26dab78e, 0x3bc8ac99, 0x30c6a594, + 0x599cd2df, 0x5292dbd2, 0x4f80c0c5, 0x448ec9c8, 0x75a4f6eb, 0x7eaaffe6, 0x63b8e4f1, 0x68b6edfc, + 0xb10c0a67, 0xba02036a, 0xa710187d, 0xac1e1170, 0x9d342e53, 0x963a275e, 0x8b283c49, 0x80263544, + 0xe97c420f, 0xe2724b02, 0xff605015, 0xf46e5918, 0xc544663b, 0xce4a6f36, 0xd3587421, 0xd8567d2c, + 0x7a37a10c, 0x7139a801, 0x6c2bb316, 0x6725ba1b, 0x560f8538, 0x5d018c35, 0x40139722, 0x4b1d9e2f, + 0x2247e964, 0x2949e069, 0x345bfb7e, 0x3f55f273, 0x0e7fcd50, 0x0571c45d, 0x1863df4a, 0x136dd647, + 0xcad731dc, 0xc1d938d1, 0xdccb23c6, 0xd7c52acb, 0xe6ef15e8, 0xede11ce5, 0xf0f307f2, 0xfbfd0eff, + 0x92a779b4, 0x99a970b9, 0x84bb6bae, 0x8fb562a3, 0xbe9f5d80, 0xb591548d, 0xa8834f9a, 0xa38d4697, + ] + const U3 = [ + 0x00000000, 0x0d0b0e09, 0x1a161c12, 0x171d121b, 0x342c3824, 0x3927362d, 0x2e3a2436, 0x23312a3f, + 0x68587048, 0x65537e41, 0x724e6c5a, 0x7f456253, 0x5c74486c, 0x517f4665, 0x4662547e, 0x4b695a77, + 0xd0b0e090, 0xddbbee99, 0xcaa6fc82, 0xc7adf28b, 0xe49cd8b4, 0xe997d6bd, 0xfe8ac4a6, 0xf381caaf, + 0xb8e890d8, 0xb5e39ed1, 0xa2fe8cca, 0xaff582c3, 0x8cc4a8fc, 0x81cfa6f5, 0x96d2b4ee, 0x9bd9bae7, + 0xbb7bdb3b, 0xb670d532, 0xa16dc729, 0xac66c920, 0x8f57e31f, 0x825ced16, 0x9541ff0d, 0x984af104, + 0xd323ab73, 0xde28a57a, 0xc935b761, 0xc43eb968, 0xe70f9357, 0xea049d5e, 0xfd198f45, 0xf012814c, + 0x6bcb3bab, 0x66c035a2, 0x71dd27b9, 0x7cd629b0, 0x5fe7038f, 0x52ec0d86, 0x45f11f9d, 0x48fa1194, + 0x03934be3, 0x0e9845ea, 0x198557f1, 0x148e59f8, 0x37bf73c7, 0x3ab47dce, 0x2da96fd5, 0x20a261dc, + 0x6df6ad76, 0x60fda37f, 0x77e0b164, 0x7aebbf6d, 0x59da9552, 0x54d19b5b, 0x43cc8940, 0x4ec78749, + 0x05aedd3e, 0x08a5d337, 0x1fb8c12c, 0x12b3cf25, 0x3182e51a, 0x3c89eb13, 0x2b94f908, 0x269ff701, + 0xbd464de6, 0xb04d43ef, 0xa75051f4, 0xaa5b5ffd, 0x896a75c2, 0x84617bcb, 0x937c69d0, 0x9e7767d9, + 0xd51e3dae, 0xd81533a7, 0xcf0821bc, 0xc2032fb5, 0xe132058a, 0xec390b83, 0xfb241998, 0xf62f1791, + 0xd68d764d, 0xdb867844, 0xcc9b6a5f, 0xc1906456, 0xe2a14e69, 0xefaa4060, 0xf8b7527b, 0xf5bc5c72, + 0xbed50605, 0xb3de080c, 0xa4c31a17, 0xa9c8141e, 0x8af93e21, 0x87f23028, 0x90ef2233, 0x9de42c3a, + 0x063d96dd, 0x0b3698d4, 0x1c2b8acf, 0x112084c6, 0x3211aef9, 0x3f1aa0f0, 0x2807b2eb, 0x250cbce2, + 0x6e65e695, 0x636ee89c, 0x7473fa87, 0x7978f48e, 0x5a49deb1, 0x5742d0b8, 0x405fc2a3, 0x4d54ccaa, + 0xdaf741ec, 0xd7fc4fe5, 0xc0e15dfe, 0xcdea53f7, 0xeedb79c8, 0xe3d077c1, 0xf4cd65da, 0xf9c66bd3, + 0xb2af31a4, 0xbfa43fad, 0xa8b92db6, 0xa5b223bf, 0x86830980, 0x8b880789, 0x9c951592, 0x919e1b9b, + 0x0a47a17c, 0x074caf75, 0x1051bd6e, 0x1d5ab367, 0x3e6b9958, 0x33609751, 0x247d854a, 0x29768b43, + 0x621fd134, 0x6f14df3d, 0x7809cd26, 0x7502c32f, 0x5633e910, 0x5b38e719, 0x4c25f502, 0x412efb0b, + 0x618c9ad7, 0x6c8794de, 0x7b9a86c5, 0x769188cc, 0x55a0a2f3, 0x58abacfa, 0x4fb6bee1, 0x42bdb0e8, + 0x09d4ea9f, 0x04dfe496, 0x13c2f68d, 0x1ec9f884, 0x3df8d2bb, 0x30f3dcb2, 0x27eecea9, 0x2ae5c0a0, + 0xb13c7a47, 0xbc37744e, 0xab2a6655, 0xa621685c, 0x85104263, 0x881b4c6a, 0x9f065e71, 0x920d5078, + 0xd9640a0f, 0xd46f0406, 0xc372161d, 0xce791814, 0xed48322b, 0xe0433c22, 0xf75e2e39, 0xfa552030, + 0xb701ec9a, 0xba0ae293, 0xad17f088, 0xa01cfe81, 0x832dd4be, 0x8e26dab7, 0x993bc8ac, 0x9430c6a5, + 0xdf599cd2, 0xd25292db, 0xc54f80c0, 0xc8448ec9, 0xeb75a4f6, 0xe67eaaff, 0xf163b8e4, 0xfc68b6ed, + 0x67b10c0a, 0x6aba0203, 0x7da71018, 0x70ac1e11, 0x539d342e, 0x5e963a27, 0x498b283c, 0x44802635, + 0x0fe97c42, 0x02e2724b, 0x15ff6050, 0x18f46e59, 0x3bc54466, 0x36ce4a6f, 0x21d35874, 0x2cd8567d, + 0x0c7a37a1, 0x017139a8, 0x166c2bb3, 0x1b6725ba, 0x38560f85, 0x355d018c, 0x22401397, 0x2f4b1d9e, + 0x642247e9, 0x692949e0, 0x7e345bfb, 0x733f55f2, 0x500e7fcd, 0x5d0571c4, 0x4a1863df, 0x47136dd6, + 0xdccad731, 0xd1c1d938, 0xc6dccb23, 0xcbd7c52a, 0xe8e6ef15, 0xe5ede11c, 0xf2f0f307, 0xfffbfd0e, + 0xb492a779, 0xb999a970, 0xae84bb6b, 0xa38fb562, 0x80be9f5d, 0x8db59154, 0x9aa8834f, 0x97a38d46, + ] + const U4 = [ + 0x00000000, 0x090d0b0e, 0x121a161c, 0x1b171d12, 0x24342c38, 0x2d392736, 0x362e3a24, 0x3f23312a, + 0x48685870, 0x4165537e, 0x5a724e6c, 0x537f4562, 0x6c5c7448, 0x65517f46, 0x7e466254, 0x774b695a, + 0x90d0b0e0, 0x99ddbbee, 0x82caa6fc, 0x8bc7adf2, 0xb4e49cd8, 0xbde997d6, 0xa6fe8ac4, 0xaff381ca, + 0xd8b8e890, 0xd1b5e39e, 0xcaa2fe8c, 0xc3aff582, 0xfc8cc4a8, 0xf581cfa6, 0xee96d2b4, 0xe79bd9ba, + 0x3bbb7bdb, 0x32b670d5, 0x29a16dc7, 0x20ac66c9, 0x1f8f57e3, 0x16825ced, 0x0d9541ff, 0x04984af1, + 0x73d323ab, 0x7ade28a5, 0x61c935b7, 0x68c43eb9, 0x57e70f93, 0x5eea049d, 0x45fd198f, 0x4cf01281, + 0xab6bcb3b, 0xa266c035, 0xb971dd27, 0xb07cd629, 0x8f5fe703, 0x8652ec0d, 0x9d45f11f, 0x9448fa11, + 0xe303934b, 0xea0e9845, 0xf1198557, 0xf8148e59, 0xc737bf73, 0xce3ab47d, 0xd52da96f, 0xdc20a261, + 0x766df6ad, 0x7f60fda3, 0x6477e0b1, 0x6d7aebbf, 0x5259da95, 0x5b54d19b, 0x4043cc89, 0x494ec787, + 0x3e05aedd, 0x3708a5d3, 0x2c1fb8c1, 0x2512b3cf, 0x1a3182e5, 0x133c89eb, 0x082b94f9, 0x01269ff7, + 0xe6bd464d, 0xefb04d43, 0xf4a75051, 0xfdaa5b5f, 0xc2896a75, 0xcb84617b, 0xd0937c69, 0xd99e7767, + 0xaed51e3d, 0xa7d81533, 0xbccf0821, 0xb5c2032f, 0x8ae13205, 0x83ec390b, 0x98fb2419, 0x91f62f17, + 0x4dd68d76, 0x44db8678, 0x5fcc9b6a, 0x56c19064, 0x69e2a14e, 0x60efaa40, 0x7bf8b752, 0x72f5bc5c, + 0x05bed506, 0x0cb3de08, 0x17a4c31a, 0x1ea9c814, 0x218af93e, 0x2887f230, 0x3390ef22, 0x3a9de42c, + 0xdd063d96, 0xd40b3698, 0xcf1c2b8a, 0xc6112084, 0xf93211ae, 0xf03f1aa0, 0xeb2807b2, 0xe2250cbc, + 0x956e65e6, 0x9c636ee8, 0x877473fa, 0x8e7978f4, 0xb15a49de, 0xb85742d0, 0xa3405fc2, 0xaa4d54cc, + 0xecdaf741, 0xe5d7fc4f, 0xfec0e15d, 0xf7cdea53, 0xc8eedb79, 0xc1e3d077, 0xdaf4cd65, 0xd3f9c66b, + 0xa4b2af31, 0xadbfa43f, 0xb6a8b92d, 0xbfa5b223, 0x80868309, 0x898b8807, 0x929c9515, 0x9b919e1b, + 0x7c0a47a1, 0x75074caf, 0x6e1051bd, 0x671d5ab3, 0x583e6b99, 0x51336097, 0x4a247d85, 0x4329768b, + 0x34621fd1, 0x3d6f14df, 0x267809cd, 0x2f7502c3, 0x105633e9, 0x195b38e7, 0x024c25f5, 0x0b412efb, + 0xd7618c9a, 0xde6c8794, 0xc57b9a86, 0xcc769188, 0xf355a0a2, 0xfa58abac, 0xe14fb6be, 0xe842bdb0, + 0x9f09d4ea, 0x9604dfe4, 0x8d13c2f6, 0x841ec9f8, 0xbb3df8d2, 0xb230f3dc, 0xa927eece, 0xa02ae5c0, + 0x47b13c7a, 0x4ebc3774, 0x55ab2a66, 0x5ca62168, 0x63851042, 0x6a881b4c, 0x719f065e, 0x78920d50, + 0x0fd9640a, 0x06d46f04, 0x1dc37216, 0x14ce7918, 0x2bed4832, 0x22e0433c, 0x39f75e2e, 0x30fa5520, + 0x9ab701ec, 0x93ba0ae2, 0x88ad17f0, 0x81a01cfe, 0xbe832dd4, 0xb78e26da, 0xac993bc8, 0xa59430c6, + 0xd2df599c, 0xdbd25292, 0xc0c54f80, 0xc9c8448e, 0xf6eb75a4, 0xffe67eaa, 0xe4f163b8, 0xedfc68b6, + 0x0a67b10c, 0x036aba02, 0x187da710, 0x1170ac1e, 0x2e539d34, 0x275e963a, 0x3c498b28, 0x35448026, + 0x420fe97c, 0x4b02e272, 0x5015ff60, 0x5918f46e, 0x663bc544, 0x6f36ce4a, 0x7421d358, 0x7d2cd856, + 0xa10c7a37, 0xa8017139, 0xb3166c2b, 0xba1b6725, 0x8538560f, 0x8c355d01, 0x97224013, 0x9e2f4b1d, + 0xe9642247, 0xe0692949, 0xfb7e345b, 0xf2733f55, 0xcd500e7f, 0xc45d0571, 0xdf4a1863, 0xd647136d, + 0x31dccad7, 0x38d1c1d9, 0x23c6dccb, 0x2acbd7c5, 0x15e8e6ef, 0x1ce5ede1, 0x07f2f0f3, 0x0efffbfd, + 0x79b492a7, 0x70b999a9, 0x6bae84bb, 0x62a38fb5, 0x5d80be9f, 0x548db591, 0x4f9aa883, 0x4697a38d, + ] + + const convertToInt32 = bytes => { + const result = [] + for (let i = 0; i < bytes.length; i += 4) { + result.push((bytes[i] << 24) | (bytes[i + 1] << 16) | (bytes[i + 2] << 8) | bytes[i + 3]) + } + return result + } + + class AES { + constructor(key) { + if (!(this instanceof AES)) { + throw new Error('AES must be instantiated with `new`') + } + + Object.defineProperty(this, 'key', { + value: coerceArray(key, true), + }) + + this._prepare() + } + + _prepare() { + const rounds = numberOfRounds[this.key.length] + + if (rounds == null) { + throw new Error('invalid key size (must be 16, 24 or 32 bytes)') + } + + this._Ke = [] + this._Kd = [] + + for (let i = 0; i <= rounds; i++) { + this._Ke.push([0, 0, 0, 0]) + this._Kd.push([0, 0, 0, 0]) + } + + const roundKeyCount = (rounds + 1) * 4 + const KC = this.key.length / 4 + const tk = convertToInt32(this.key) + + for (let i = 0; i < KC; i++) { + const index = i >> 2 + this._Ke[index][i % 4] = tk[i] + this._Kd[rounds - index][i % 4] = tk[i] + } + + let rconpointer = 0 + let t = KC, + tt + + while (t < roundKeyCount) { + tt = tk[KC - 1] + tk[0] ^= + (S[(tt >> 16) & 0xff] << 24) ^ + (S[(tt >> 8) & 0xff] << 16) ^ + (S[tt & 0xff] << 8) ^ + S[(tt >> 24) & 0xff] ^ + (rcon[rconpointer] << 24) + rconpointer += 1 + + if (KC != 8) { + for (let i = 1; i < KC; i++) { + tk[i] ^= tk[i - 1] + } + } else { + for (let i = 1; i < KC / 2; i++) { + tk[i] ^= tk[i - 1] + } + + tt = tk[KC / 2 - 1] + tk[KC / 2] ^= + S[tt & 0xff] ^ + (S[(tt >> 8) & 0xff] << 8) ^ + (S[(tt >> 16) & 0xff] << 16) ^ + (S[(tt >> 24) & 0xff] << 24) + + for (let i = KC / 2 + 1; i < KC; i++) { + tk[i] ^= tk[i - 1] + } + } + + let i = 0, + r, + c + while (i < KC && t < roundKeyCount) { + r = t >> 2 + c = t % 4 + this._Ke[r][c] = tk[i] + this._Kd[rounds - r][c] = tk[i++] + t++ + } + } + + for (let r = 1; r < rounds; r++) { + for (let c = 0; c < 4; c++) { + tt = this._Kd[r][c] + this._Kd[r][c] = + U1[(tt >> 24) & 0xff] ^ U2[(tt >> 16) & 0xff] ^ U3[(tt >> 8) & 0xff] ^ U4[tt & 0xff] + } + } + } + + encrypt(plaintext) { + if (plaintext.length != 16) { + throw new Error('invalid plaintext size (must be 16 bytes)') + } + + const rounds = this._Ke.length - 1 + const a = [0, 0, 0, 0] + let t = convertToInt32(plaintext) + + for (let i = 0; i < 4; i++) { + t[i] ^= this._Ke[0][i] + } + + for (let r = 1; r < rounds; r++) { + for (let i = 0; i < 4; i++) { + a[i] = + T1[(t[i] >> 24) & 0xff] ^ + T2[(t[(i + 1) % 4] >> 16) & 0xff] ^ + T3[(t[(i + 2) % 4] >> 8) & 0xff] ^ + T4[t[(i + 3) % 4] & 0xff] ^ + this._Ke[r][i] + } + t = a.slice() + } + + const result = createArray(16) + let tt + + for (let i = 0; i < 4; i++) { + tt = this._Ke[rounds][i] + result[4 * i] = (S[(t[i] >> 24) & 0xff] ^ (tt >> 24)) & 0xff + result[4 * i + 1] = (S[(t[(i + 1) % 4] >> 16) & 0xff] ^ (tt >> 16)) & 0xff + result[4 * i + 2] = (S[(t[(i + 2) % 4] >> 8) & 0xff] ^ (tt >> 8)) & 0xff + result[4 * i + 3] = (S[t[(i + 3) % 4] & 0xff] ^ tt) & 0xff + } + + return result + } + + decrypt(ciphertext) { + if (ciphertext.length != 16) { + throw new Error('invalid ciphertext size (must be 16 bytes)') + } + + const rounds = this._Kd.length - 1 + const a = [0, 0, 0, 0] + let t = convertToInt32(ciphertext) + + for (let i = 0; i < 4; i++) { + t[i] ^= this._Kd[0][i] + } + + for (let r = 1; r < rounds; r++) { + for (let i = 0; i < 4; i++) { + a[i] = + T5[(t[i] >> 24) & 0xff] ^ + T6[(t[(i + 3) % 4] >> 16) & 0xff] ^ + T7[(t[(i + 2) % 4] >> 8) & 0xff] ^ + T8[t[(i + 1) % 4] & 0xff] ^ + this._Kd[r][i] + } + t = a.slice() + } + + const result = createArray(16) + let tt + + for (let i = 0; i < 4; i++) { + tt = this._Kd[rounds][i] + result[4 * i] = (Si[(t[i] >> 24) & 0xff] ^ (tt >> 24)) & 0xff + result[4 * i + 1] = (Si[(t[(i + 3) % 4] >> 16) & 0xff] ^ (tt >> 16)) & 0xff + result[4 * i + 2] = (Si[(t[(i + 2) % 4] >> 8) & 0xff] ^ (tt >> 8)) & 0xff + result[4 * i + 3] = (Si[t[(i + 1) % 4] & 0xff] ^ tt) & 0xff + } + + return result + } + } + + class ModeOfOperationECB { + constructor(key) { + if (!(this instanceof ModeOfOperationECB)) { + throw new Error('AES must be instantiated with `new`') + } + + this.description = 'Electronic Code Block' + this.name = 'ecb' + this._aes = new AES(key) + } + + encrypt(plaintext) { + plaintext = coerceArray(plaintext) + + if (plaintext.length % 16 !== 0) { + throw new Error('invalid plaintext size (must be multiple of 16 bytes)') + } + + const ciphertext = createArray(plaintext.length) + const block = createArray(16) + + for (let i = 0; i < plaintext.length; i += 16) { + copyArray(plaintext, block, 0, i, i + 16) + const encryptedBlock = this._aes.encrypt(block) + copyArray(encryptedBlock, ciphertext, i) + } + + return ciphertext + } + + decrypt(ciphertext) { + ciphertext = coerceArray(ciphertext) + + if (ciphertext.length % 16 !== 0) { + throw new Error('invalid ciphertext size (must be multiple of 16 bytes)') + } + + const plaintext = createArray(ciphertext.length) + const block = createArray(16) + + for (let i = 0; i < ciphertext.length; i += 16) { + copyArray(ciphertext, block, 0, i, i + 16) + const decryptedBlock = this._aes.decrypt(block) + copyArray(decryptedBlock, plaintext, i) + } + + return plaintext + } + } + + class ModeOfOperationCBC { + constructor(key, iv) { + if (!(this instanceof ModeOfOperationCBC)) { + throw new Error('AES must be instantiated with `new`') + } + + this.description = 'Cipher Block Chaining' + this.name = 'cbc' + + if (!iv) { + iv = createArray(16) + } else if (iv.length != 16) { + throw new Error('invalid initialization vector size (must be 16 bytes)') + } + + this._lastCipherblock = coerceArray(iv, true) + this._aes = new AES(key) + } + + encrypt(plaintext) { + plaintext = coerceArray(plaintext) + + if (plaintext.length % 16 !== 0) { + throw new Error('invalid plaintext size (must be multiple of 16 bytes)') + } + + const ciphertext = createArray(plaintext.length) + const block = createArray(16) + + for (let i = 0; i < plaintext.length; i += 16) { + copyArray(plaintext, block, 0, i, i + 16) + + for (let j = 0; j < 16; j++) { + block[j] ^= this._lastCipherblock[j] + } + + this._lastCipherblock = this._aes.encrypt(block) + copyArray(this._lastCipherblock, ciphertext, i) + } + + return ciphertext + } + + decrypt(ciphertext) { + ciphertext = coerceArray(ciphertext) + + if (ciphertext.length % 16 !== 0) { + throw new Error('invalid ciphertext size (must be multiple of 16 bytes)') + } + + const plaintext = createArray(ciphertext.length) + const block = createArray(16) + const temp = createArray(16) + + for (let i = 0; i < ciphertext.length; i += 16) { + copyArray(ciphertext, block, 0, i, i + 16) + copyArray(block, temp) + + const decryptedBlock = this._aes.decrypt(block) + + for (let j = 0; j < 16; j++) { + plaintext[i + j] = decryptedBlock[j] ^ this._lastCipherblock[j] + } + + copyArray(temp, this._lastCipherblock) + } + + return plaintext + } + } + + class ModeOfOperationCFB { + constructor(key, iv, segmentSize = 1) { + if (!(this instanceof ModeOfOperationCFB)) { + throw new Error('AES must be instantiated with `new`') + } + + this.description = 'Cipher Feedback' + this.name = 'cfb' + + if (!iv) { + iv = createArray(16) + } else if (iv.length != 16) { + throw new Error('invalid initialization vector size (must be 16 size)') + } + + this.segmentSize = segmentSize + this._shiftRegister = coerceArray(iv, true) + this._aes = new AES(key) + } + + encrypt(plaintext) { + if (plaintext.length % this.segmentSize != 0) { + throw new Error('invalid plaintext size (must be segmentSize bytes)') + } + + const encrypted = coerceArray(plaintext, true) + let xorSegment + + for (let i = 0; i < encrypted.length; i += this.segmentSize) { + xorSegment = this._aes.encrypt(this._shiftRegister) + + for (let j = 0; j < this.segmentSize; j++) { + encrypted[i + j] ^= xorSegment[j] + } + + copyArray(this._shiftRegister, this._shiftRegister, 0, this.segmentSize) + copyArray(encrypted, this._shiftRegister, 16 - this.segmentSize, i, i + this.segmentSize) + } + + return encrypted + } + + decrypt(ciphertext) { + if (ciphertext.length % this.segmentSize != 0) { + throw new Error('invalid ciphertext size (must be segmentSize bytes)') + } + + const plaintext = coerceArray(ciphertext, true) + let xorSegment + + for (let i = 0; i < plaintext.length; i += this.segmentSize) { + xorSegment = this._aes.encrypt(this._shiftRegister) + + for (let j = 0; j < this.segmentSize; j++) { + plaintext[i + j] ^= xorSegment[j] + } + + copyArray(this._shiftRegister, this._shiftRegister, 0, this.segmentSize) + copyArray(ciphertext, this._shiftRegister, 16 - this.segmentSize, i, i + this.segmentSize) + } + + return plaintext + } + } + + class ModeOfOperationOFB { + constructor(key, iv) { + if (!(this instanceof ModeOfOperationOFB)) { + throw new Error('AES must be instantiated with `new`') + } + + this.description = 'Output Feedback' + this.name = 'ofb' + + if (!iv) { + iv = createArray(16) + } else if (iv.length != 16) { + throw new Error('invalid initialization vector size (must be 16 bytes)') + } + + this._lastPrecipher = coerceArray(iv, true) + this._lastPrecipherIndex = 16 + this._aes = new AES(key) + } + + encrypt(plaintext) { + const encrypted = coerceArray(plaintext, true) + + for (let i = 0; i < encrypted.length; i++) { + if (this._lastPrecipherIndex === 16) { + this._lastPrecipher = this._aes.encrypt(this._lastPrecipher) + this._lastPrecipherIndex = 0 + } + + encrypted[i] ^= this._lastPrecipher[this._lastPrecipherIndex++] + } + + return encrypted + } + + decrypt(ciphertext) { + return this.encrypt(ciphertext) + } + } + + class Counter { + constructor(initialValue) { + if (!(this instanceof Counter)) { + throw new Error('Counter must be instantiated with `new`') + } + + if (initialValue !== 0 && !initialValue) { + initialValue = 1 + } + + if (typeof initialValue === 'number') { + this._counter = createArray(16) + this.setValue(initialValue) + } else { + this.setBytes(initialValue) + } + } + + setValue(value) { + if (typeof value !== 'number' || parseInt(value) != value) { + throw new Error('invalid counter value (must be an integer)') + } + + if (value > Number.MAX_SAFE_INTEGER) { + throw new Error('integer value out of safe range') + } + + for (let index = 15; index >= 0; --index) { + this._counter[index] = value % 256 + value = parseInt(value / 256) + } + } + + setBytes(bytes) { + bytes = coerceArray(bytes, true) + + if (bytes.length != 16) { + throw new Error('invalid counter bytes size (must be 16 bytes)') + } + + this._counter = bytes + } + + increment() { + for (let i = 15; i >= 0; i--) { + if (this._counter[i] === 255) { + this._counter[i] = 0 + } else { + this._counter[i]++ + break + } + } + } + } + + class ModeOfOperationCTR { + constructor(key, counter) { + if (!(this instanceof ModeOfOperationCTR)) { + throw new Error('AES must be instantiated with `new`') + } + + this.description = 'Counter' + this.name = 'ctr' + + if (!(counter instanceof Counter)) { + counter = new Counter(counter) + } + + this._counter = counter + this._remainingCounter = null + this._remainingCounterIndex = 16 + this._aes = new AES(key) + } + + encrypt(plaintext) { + const encrypted = coerceArray(plaintext, true) + + for (let i = 0; i < encrypted.length; i++) { + if (this._remainingCounterIndex === 16) { + this._remainingCounter = this._aes.encrypt(this._counter._counter) + this._remainingCounterIndex = 0 + this._counter.increment() + } + + encrypted[i] ^= this._remainingCounter[this._remainingCounterIndex++] + } + + return encrypted + } + + decrypt(ciphertext) { + return this.encrypt(ciphertext) + } + } + + const pkcs7pad = data => { + data = coerceArray(data, true) + const padder = 16 - (data.length % 16) + const result = createArray(data.length + padder) + copyArray(data, result) + + for (let i = data.length; i < result.length; i++) { + result[i] = padder + } + + return result + } + + const pkcs7strip = data => { + data = coerceArray(data, true) + + if (data.length < 16) { + throw new Error('PKCS#7 invalid length') + } + + const padder = data[data.length - 1] + + if (padder > 16) { + throw new Error('PKCS#7 padding byte out of range') + } + + const length = data.length - padder + + for (let i = 0; i < padder; i++) { + if (data[length + i] !== padder) { + throw new Error('PKCS#7 invalid padding byte') + } + } + + const result = createArray(length) + copyArray(data, result, 0, 0, length) + return result + } + + const aesjs = { + AES, + Counter, + ModeOfOperation: { + ecb: ModeOfOperationECB, + cbc: ModeOfOperationCBC, + cfb: ModeOfOperationCFB, + ofb: ModeOfOperationOFB, + ctr: ModeOfOperationCTR, + }, + utils: { + hex: convertHex, + utf8: convertUtf8, + }, + padding: { + pkcs7: { + pad: pkcs7pad, + strip: pkcs7strip, + }, + }, + _arrayTest: { + coerceArray: coerceArray, + createArray: createArray, + copyArray: copyArray, + }, + } + + // Export for different environments + if (typeof exports !== 'undefined') { + module.exports = aesjs + } else if (typeof define === 'function' && define.amd) { + define(aesjs) + } else { + if (root.aesjs) { + aesjs._aesjs = root.aesjs + } + root.aesjs = aesjs + } +})(this) diff --git a/app/components/blufi/crypto/crypto-dh.js b/app/components/blufi/crypto/crypto-dh.js new file mode 100644 index 0000000..0a966ff --- /dev/null +++ b/app/components/blufi/crypto/crypto-dh.js @@ -0,0 +1,44 @@ +var generatePrime = require("./lib/generatePrime.js"); + +var DH = require("./lib/dh.js"); + +var Buffer = require("./lib/safe-buffer.js").Buffer; + +function getDiffieHellman(mod) { + var prime = new Buffer(primes[mod].prime, 'hex'); + var gen = new Buffer(primes[mod].gen, 'hex'); + return new DH(prime, gen); +} + +var ENCODINGS = { + 'binary': true, + 'hex': true, + 'base64': true +}; + +function createDiffieHellman(prime, enc, generator, genc) { + if (Buffer.isBuffer(enc) || ENCODINGS[enc] === undefined) { + return createDiffieHellman(prime, 'binary', enc, generator); + } + + enc = enc || 'binary'; + genc = genc || 'binary'; + generator = generator || new Buffer([2]); + + if (!Buffer.isBuffer(generator)) { + generator = new Buffer(generator, genc); + } + + if (typeof prime === 'number') { + return new DH(generatePrime(prime, generator), generator, true); + } + + if (!Buffer.isBuffer(prime)) { + prime = new Buffer(prime, enc); + } + + return new DH(prime, generator, true); +} + +exports.DiffieHellmanGroup = exports.createDiffieHellmanGroup = exports.getDiffieHellman = getDiffieHellman; +exports.createDiffieHellman = exports.DiffieHellman = createDiffieHellman; \ No newline at end of file diff --git a/app/components/blufi/crypto/lib/base64-js.js b/app/components/blufi/crypto/lib/base64-js.js new file mode 100644 index 0000000..bba7212 --- /dev/null +++ b/app/components/blufi/crypto/lib/base64-js.js @@ -0,0 +1,118 @@ +'use strict'; + +exports.byteLength = byteLength; +exports.toByteArray = toByteArray; +exports.fromByteArray = fromByteArray; +var lookup = []; +var revLookup = []; +var Arr = typeof Uint8Array !== 'undefined' ? Uint8Array : Array; +var code = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; + +for (var i = 0, len = code.length; i < len; ++i) { + lookup[i] = code[i]; + revLookup[code.charCodeAt(i)] = i; +} // Support decoding URL-safe base64 strings, as Node.js does. +// See: https://en.wikipedia.org/wiki/Base64#URL_applications + + +revLookup['-'.charCodeAt(0)] = 62; +revLookup['_'.charCodeAt(0)] = 63; + +function getLens(b64) { + var len = b64.length; + + if (len % 4 > 0) { + throw new Error('Invalid string. Length must be a multiple of 4'); + } // Trim off extra bytes after placeholder bytes are found + // See: https://github.com/beatgammit/base64-js/issues/42 + + + var validLen = b64.indexOf('='); + if (validLen === -1) validLen = len; + var placeHoldersLen = validLen === len ? 0 : 4 - validLen % 4; + return [validLen, placeHoldersLen]; +} // base64 is 4/3 + up to two characters of the original data + + +function byteLength(b64) { + var lens = getLens(b64); + var validLen = lens[0]; + var placeHoldersLen = lens[1]; + return (validLen + placeHoldersLen) * 3 / 4 - placeHoldersLen; +} + +function _byteLength(b64, validLen, placeHoldersLen) { + return (validLen + placeHoldersLen) * 3 / 4 - placeHoldersLen; +} + +function toByteArray(b64) { + var tmp; + var lens = getLens(b64); + var validLen = lens[0]; + var placeHoldersLen = lens[1]; + var arr = new Arr(_byteLength(b64, validLen, placeHoldersLen)); + var curByte = 0; // if there are placeholders, only get up to the last complete 4 chars + + var len = placeHoldersLen > 0 ? validLen - 4 : validLen; + + for (var i = 0; i < len; i += 4) { + tmp = revLookup[b64.charCodeAt(i)] << 18 | revLookup[b64.charCodeAt(i + 1)] << 12 | revLookup[b64.charCodeAt(i + 2)] << 6 | revLookup[b64.charCodeAt(i + 3)]; + arr[curByte++] = tmp >> 16 & 0xFF; + arr[curByte++] = tmp >> 8 & 0xFF; + arr[curByte++] = tmp & 0xFF; + } + + if (placeHoldersLen === 2) { + tmp = revLookup[b64.charCodeAt(i)] << 2 | revLookup[b64.charCodeAt(i + 1)] >> 4; + arr[curByte++] = tmp & 0xFF; + } + + if (placeHoldersLen === 1) { + tmp = revLookup[b64.charCodeAt(i)] << 10 | revLookup[b64.charCodeAt(i + 1)] << 4 | revLookup[b64.charCodeAt(i + 2)] >> 2; + arr[curByte++] = tmp >> 8 & 0xFF; + arr[curByte++] = tmp & 0xFF; + } + + return arr; +} + +function tripletToBase64(num) { + return lookup[num >> 18 & 0x3F] + lookup[num >> 12 & 0x3F] + lookup[num >> 6 & 0x3F] + lookup[num & 0x3F]; +} + +function encodeChunk(uint8, start, end) { + var tmp; + var output = []; + + for (var i = start; i < end; i += 3) { + tmp = (uint8[i] << 16 & 0xFF0000) + (uint8[i + 1] << 8 & 0xFF00) + (uint8[i + 2] & 0xFF); + output.push(tripletToBase64(tmp)); + } + + return output.join(''); +} + +function fromByteArray(uint8) { + var tmp; + var len = uint8.length; + var extraBytes = len % 3; // if we have 1 byte left, pad 2 bytes + + var parts = []; + var maxChunkLength = 16383; // must be multiple of 3 + // go through the array every three bytes, we'll deal with trailing stuff later + + for (var i = 0, len2 = len - extraBytes; i < len2; i += maxChunkLength) { + parts.push(encodeChunk(uint8, i, i + maxChunkLength > len2 ? len2 : i + maxChunkLength)); + } // pad the end with zeros, but make sure to not forget the extra bytes + + + if (extraBytes === 1) { + tmp = uint8[len - 1]; + parts.push(lookup[tmp >> 2] + lookup[tmp << 4 & 0x3F] + '=='); + } else if (extraBytes === 2) { + tmp = (uint8[len - 2] << 8) + uint8[len - 1]; + parts.push(lookup[tmp >> 10] + lookup[tmp >> 4 & 0x3F] + lookup[tmp << 2 & 0x3F] + '='); + } + + return parts.join(''); +} \ No newline at end of file diff --git a/app/components/blufi/crypto/lib/blelib.js b/app/components/blufi/crypto/lib/blelib.js new file mode 100644 index 0000000..6f6f03f --- /dev/null +++ b/app/components/blufi/crypto/lib/blelib.js @@ -0,0 +1,404 @@ +function BLEDevice(arg) { + this.deviceId = ""; + this.serviceId = ""; + this.debug = arg ? (arg['debug'] || false) : false; + this.connectTimeout = arg ? (arg['connectTimeout'] || 10000) : 10000; + this.onBLECharacteristicValueChange = {} +}; + +/** + * 日志输出 + * + * @param {msg} String + * 输出的信息 + * @param {Array} args + * 辅助输出信息 + */ +BLEDevice.prototype.log = function (msg, ...args) { + if (this.debug) { + console.log(msg, ...args) + } +}; + +BLEDevice.prototype.setStateCallBack = function (cb) { + wx.onBluetoothAdapterStateChange((res) => { + cb(res); + }); +} + +/** + * 初始化蓝牙模块 + * + * @return + * 返回蓝牙模块Promise + */ +BLEDevice.prototype.openBluetoothAdapter = function() { + return new Promise((resolve, reject) => { + wx.openBluetoothAdapter({ + success: (res) => { + this.log("openBluetoothAdapter", res); + resolve(res); + }, + fail: (res) => { + this.log("openBluetoothAdapter failed", res) + reject(res); + } + }) + }) +}; + +/** + * 关闭蓝牙模块 + */ +BLEDevice.prototype.closeBluetoothAdapter = function() { + wx.closeBluetoothAdapter(); +}; + +/** + * 获取本机蓝牙适配器状态 + */ +BLEDevice.prototype.getBluetoothAdapterState = function () { + wx.getBluetoothAdapterState({ + success: (res) => { + if (res.discovering) { + this.onBluetoothDeviceFound() + } else if (res.available) { + setTimeout(()=>{ + this.startBluetoothDevicesDiscovery(state.servicesId, state.key); + },500) + } + } + }) +}; + +/** + * 开始搜寻附近的蓝牙外围设备 + * + * @param {String} servicesId + * 要搜索的蓝牙设备主服务的uuid列表 + * @param {Function} cb + * 发现设备后的回调 + * 若发现成功,参数success为true,foundDevices:发现的设备列表 + * 若发现失败,参数success为false + * @return + * 返回搜索蓝牙设备Promise + */ +BLEDevice.prototype.startBluetoothDevicesDiscovery = function (servicesId, cb) { + let foundDevices = []; + wx.onBluetoothDeviceFound((res) => { + res.devices.forEach(device => { + if (!device.name && !device.localName) { + return; + } + + const idx = inArray(foundDevices, 'deviceId', device.deviceId) + + if (idx === -1) { + foundDevices.push(device) + } else { + foundDevices[idx] = device + } + this.log("onBluetoothDeviceFound", foundDevices); + + cb({ success: true, foundDevices: foundDevices}); + }) + }) + + wx.startBluetoothDevicesDiscovery({ + services: servicesId, + allowDuplicatesKey: true, + success: (res) => { + this.log("startBluetoothDevicesDiscovery", res); + }, + fail: (res) => { + cb({ success: false }); + } + }) +}; + +/** + * 停止搜寻附近的蓝牙外围设备 + */ +BLEDevice.prototype.stopBluetoothDevicesDiscovery = function () { + wx.stopBluetoothDevicesDiscovery(); +}; + +/** + * 连接低功耗蓝牙设备 + * + * @param {String} deviceId + * 连接设备的ID + * + * @return + * 返回设备连接的Promise + */ +BLEDevice.prototype.createBLEConnection = function (deviceId) { + this.deviceId = deviceId; + return new Promise((resolve, reject) => { + wx.createBLEConnection({ + deviceId: this.deviceId, + success: (res) => { + this.log("createBLEConnection", res) + this.getBLEDeviceServices() + .then(() => { + resolve(); + }).catch((res) => { + reject(res); + this.closeBLEConnection(); + }) + }, + fail: (res) => { + this.log("createBLEConnection failed", res) + reject(res) + } + }) + this.stopBluetoothDevicesDiscovery(); + + setTimeout(() => { + reject('Connect timeout'); + this.closeBLEConnection(); + }, this.connectTimeout); + }) +}; + +/** + * 断开与低功耗蓝牙设备的连接 + */ +BLEDevice.prototype.closeBLEConnection = function () { + wx.closeBLEConnection({ + deviceId: this.deviceId, + }) +}; + +/** + * 获取蓝牙设备的所有服务 + * + * @param {String} findServicesUUID + * 要查找的主服务uuid + * + * @param {Number} findServicesIndex + * 开始查找的位置 + * + * @return + * 返回获取服务的Promise + */ +BLEDevice.prototype.getBLEDeviceServices = function () { + return new Promise((resolve, reject) => { + wx.getBLEDeviceServices({ + deviceId: this.deviceId, + success: (res) => { + let total = res.services.length + for (let i = 0; i < res.services.length; i++) { + this.log("getBLEDeviceServices", res.services[i]); + this.getBLEDeviceCharacteristics(res.services[i].uuid) + .then(() => { + total --; + if (total === 0) { + resolve(); + } + }) + .catch(res => { + reject(res); + }) + } + }, + fail: (res) => { + reject(res); + } + }) + }) +}; + +/** + * 获取蓝牙设备某个服务中所有特征值 + * + * @param {String} serviceId + * 要查找特征的service uuid + * + * @return + * 返回服务特征值的Promise + */ +BLEDevice.prototype.getBLEDeviceCharacteristics = function (serviceId) { + + return new Promise((resolve, reject) => { + wx.getBLEDeviceCharacteristics({ + deviceId: this.deviceId, + serviceId: serviceId, + success: (res) => { + resolve(res); + + for (let i = 0; i < res.characteristics.length; i++) { + this.log("getBLEDeviceCharacteristics", i, res.characteristics[i]); + let item = res.characteristics[i]; + if (item.properties.read) { + this.log("可读:", res.characteristics[i]); + } + if (item.properties.write) { + this.log("可写:", res.characteristics[i]); + } + if (item.properties.notify || item.properties.indicate) { + this.log("可订阅", res.characteristics[i]); + } + } + }, + fail: (res) => { + reject(res); + }, + complete: (res) => { + } + }) + }) +}; + +/** + * 读取低功耗蓝牙设备的特征值的二进制数据值 + * + * @param {String} serviceId + * 蓝牙可订阅服务的uuid + * + * @param {String} readCharacteristicId + * 蓝牙可读特征值的uuid + * + * @param {Function} callback + * 特征变化的回调函数 + */ +BLEDevice.prototype.readBLECharacteristicValue = function (serviceId, readCharacteristicId, callback) { + wx.onBLECharacteristicValueChange((characteristic) => { + this.log("onBLECharacteristicValueChange", characteristic.value) + let cb = this.onBLECharacteristicValueChange[readCharacteristicId] + if (cb) { + cb(characteristic) + } + }) + + return new Promise((resolve, reject) => { + wx.readBLECharacteristicValue({ + deviceId: this.deviceId, + serviceId: serviceId, + characteristicId: readCharacteristicId, + success: (res) => { + resolve(res) + this.log('readBLECharacteristicValue', res); + this.onBLECharacteristicValueChange[readCharacteristicId] = callback; + }, + fail: (res) => { + reject(res) + } + }) + }) +}; + +/** + * 向低功耗蓝牙设备特征值中写入二进制数据 + * + * @param {String} writeCharacteristicId + * 蓝牙可写特征值的uuid + * + * @param {ArrayBuffer} buffer + * 特征值对应的二进制值 + */ +BLEDevice.prototype.writeBLECharacteristicValue = function (serviceId, writeCharacteristicId, buffer) { + // // 向蓝牙设备发送一个0x00的16进制数据 + this.log("writeBLECharacteristicValue buffer", buffer); + wx.writeBLECharacteristicValue({ + deviceId: this.deviceId, + serviceId: serviceId, + characteristicId: writeCharacteristicId, + value: buffer, + success: (res) => { + this.log('writeBLECharacteristicValue', res); + } + }) +}; + +/** + * 启用低功耗蓝牙设备特征值变化时的notify功能,订阅特征值 + * + * @param {String} serviceId + * 蓝牙可订阅服务的uuid + * + * @param {String} notifyCharacteristicId + * 蓝牙可订阅特征值的uuid + * + * @param {Function} callback + * 特征变化的回调函数 + */ +BLEDevice.prototype.notifyBLECharacteristicValueChange = function (serviceId, notifyCharacteristicId, callback) { + + wx.onBLECharacteristicValueChange((characteristic) => { + this.log("onBLECharacteristicValueChange", characteristic.value) + let cb = this.onBLECharacteristicValueChange[notifyCharacteristicId] + if (cb) { + cb(characteristic) + } + }) + return new Promise((reslove, reject) => { + wx.notifyBLECharacteristicValueChange({ + deviceId: this.deviceId, + serviceId: serviceId, + characteristicId: notifyCharacteristicId, + state: true, + success: (res) => { + reslove(res) + this.log('notifyBLECharacteristicValueChange', res); + this.onBLECharacteristicValueChange[notifyCharacteristicId] = callback + }, + fail: (res) => { + reject(res) + } + }) + }) +}; + +/** + * 关闭低功耗蓝牙设备特征值变化时的notify功能,订阅特征值 + * + * @param {String} serviceId + * 蓝牙可订阅服务的uuid + * + * @param {String} notifyCharacteristicId + * 蓝牙可订阅特征值的uuid + */ +BLEDevice.prototype.unNotifyBLECharacteristicValueChange = function (serviceId, notifyCharacteristicId) { + return new Promise((resolve, reject) => { + delete this.onBLECharacteristicValueChange[notifyCharacteristicId] + + wx.notifyBLECharacteristicValueChange({ + deviceId: this.deviceId, + serviceId: serviceId, + characteristicId: notifyCharacteristicId, + state: false, + success: function (res) { + resolve(res) + }, + fail: function (res) { + reject(res) + } + }) + }) +} + + +const inArray = (arr, key, val) => { + for (let i = 0; i < arr.length; i++) { + if (arr[i][key] === val) { + return i; + } + } + return -1; +}; + +/** + * ArrayBuffer转16进度字符串示例 + */ +const ab2hex = (buffer) => { + var hexArr = Array.prototype.map.call( + new Uint8Array(buffer), + function (bit) { + return ('00' + bit.toString(16)).slice(-2); + } + ) + return hexArr.join(''); +}; + +module.exports = BLEDevice \ No newline at end of file diff --git a/app/components/blufi/crypto/lib/bn.js b/app/components/blufi/crypto/lib/bn.js new file mode 100644 index 0000000..edddb13 --- /dev/null +++ b/app/components/blufi/crypto/lib/bn.js @@ -0,0 +1,3448 @@ +(function (module, exports) { + 'use strict'; // Utils + + function assert(val, msg) { + if (!val) throw new Error(msg || 'Assertion failed'); + } // Could use `inherits` module, but don't want to move from single file + // architecture yet. + + + function inherits(ctor, superCtor) { + ctor.super_ = superCtor; + + var TempCtor = function () {}; + + TempCtor.prototype = superCtor.prototype; + ctor.prototype = new TempCtor(); + ctor.prototype.constructor = ctor; + } // BN + + + function BN(number, base, endian) { + if (BN.isBN(number)) { + return number; + } + + this.negative = 0; + this.words = null; + this.length = 0; // Reduction context + + this.red = null; + + if (number !== null) { + if (base === 'le' || base === 'be') { + endian = base; + base = 10; + } + + this._init(number || 0, base || 10, endian || 'be'); + } + } + + if (typeof module === 'object') { + module.exports = BN; + } else { + exports.BN = BN; + } + + BN.BN = BN; + BN.wordSize = 26; + var Buffer; + + try { + Buffer = require("./buffer.js").Buffer; + } catch (e) {} + + BN.isBN = function isBN(num) { + if (num instanceof BN) { + return true; + } + + return num !== null && typeof num === 'object' && num.constructor.wordSize === BN.wordSize && Array.isArray(num.words); + }; + + BN.max = function max(left, right) { + if (left.cmp(right) > 0) return left; + return right; + }; + + BN.min = function min(left, right) { + if (left.cmp(right) < 0) return left; + return right; + }; + + BN.prototype._init = function init(number, base, endian) { + if (typeof number === 'number') { + return this._initNumber(number, base, endian); + } + + if (typeof number === 'object') { + return this._initArray(number, base, endian); + } + + if (base === 'hex') { + base = 16; + } + + assert(base === (base | 0) && base >= 2 && base <= 36); + number = number.toString().replace(/\s+/g, ''); + var start = 0; + + if (number[0] === '-') { + start++; + } + + if (base === 16) { + this._parseHex(number, start); + } else { + this._parseBase(number, base, start); + } + + if (number[0] === '-') { + this.negative = 1; + } + + this.strip(); + if (endian !== 'le') return; + + this._initArray(this.toArray(), base, endian); + }; + + BN.prototype._initNumber = function _initNumber(number, base, endian) { + if (number < 0) { + this.negative = 1; + number = -number; + } + + if (number < 0x4000000) { + this.words = [number & 0x3ffffff]; + this.length = 1; + } else if (number < 0x10000000000000) { + this.words = [number & 0x3ffffff, number / 0x4000000 & 0x3ffffff]; + this.length = 2; + } else { + assert(number < 0x20000000000000); // 2 ^ 53 (unsafe) + + this.words = [number & 0x3ffffff, number / 0x4000000 & 0x3ffffff, 1]; + this.length = 3; + } + + if (endian !== 'le') return; // Reverse the bytes + + this._initArray(this.toArray(), base, endian); + }; + + BN.prototype._initArray = function _initArray(number, base, endian) { + // Perhaps a Uint8Array + assert(typeof number.length === 'number'); + + if (number.length <= 0) { + this.words = [0]; + this.length = 1; + return this; + } + + this.length = Math.ceil(number.length / 3); + this.words = new Array(this.length); + + for (var i = 0; i < this.length; i++) { + this.words[i] = 0; + } + + var j, w; + var off = 0; + + if (endian === 'be') { + for (i = number.length - 1, j = 0; i >= 0; i -= 3) { + w = number[i] | number[i - 1] << 8 | number[i - 2] << 16; + this.words[j] |= w << off & 0x3ffffff; + this.words[j + 1] = w >>> 26 - off & 0x3ffffff; + off += 24; + + if (off >= 26) { + off -= 26; + j++; + } + } + } else if (endian === 'le') { + for (i = 0, j = 0; i < number.length; i += 3) { + w = number[i] | number[i + 1] << 8 | number[i + 2] << 16; + this.words[j] |= w << off & 0x3ffffff; + this.words[j + 1] = w >>> 26 - off & 0x3ffffff; + off += 24; + + if (off >= 26) { + off -= 26; + j++; + } + } + } + + return this.strip(); + }; + + function parseHex(str, start, end) { + var r = 0; + var len = Math.min(str.length, end); + + for (var i = start; i < len; i++) { + var c = str.charCodeAt(i) - 48; + r <<= 4; // 'a' - 'f' + + if (c >= 49 && c <= 54) { + r |= c - 49 + 0xa; // 'A' - 'F' + } else if (c >= 17 && c <= 22) { + r |= c - 17 + 0xa; // '0' - '9' + } else { + r |= c & 0xf; + } + } + + return r; + } + + BN.prototype._parseHex = function _parseHex(number, start) { + // Create possibly bigger array to ensure that it fits the number + this.length = Math.ceil((number.length - start) / 6); + this.words = new Array(this.length); + + for (var i = 0; i < this.length; i++) { + this.words[i] = 0; + } + + var j, w; // Scan 24-bit chunks and add them to the number + + var off = 0; + + for (i = number.length - 6, j = 0; i >= start; i -= 6) { + w = parseHex(number, i, i + 6); + this.words[j] |= w << off & 0x3ffffff; // NOTE: `0x3fffff` is intentional here, 26bits max shift + 24bit hex limb + + this.words[j + 1] |= w >>> 26 - off & 0x3fffff; + off += 24; + + if (off >= 26) { + off -= 26; + j++; + } + } + + if (i + 6 !== start) { + w = parseHex(number, start, i + 6); + this.words[j] |= w << off & 0x3ffffff; + this.words[j + 1] |= w >>> 26 - off & 0x3fffff; + } + + this.strip(); + }; + + function parseBase(str, start, end, mul) { + var r = 0; + var len = Math.min(str.length, end); + + for (var i = start; i < len; i++) { + var c = str.charCodeAt(i) - 48; + r *= mul; // 'a' + + if (c >= 49) { + r += c - 49 + 0xa; // 'A' + } else if (c >= 17) { + r += c - 17 + 0xa; // '0' - '9' + } else { + r += c; + } + } + + return r; + } + + BN.prototype._parseBase = function _parseBase(number, base, start) { + // Initialize as zero + this.words = [0]; + this.length = 1; // Find length of limb in base + + for (var limbLen = 0, limbPow = 1; limbPow <= 0x3ffffff; limbPow *= base) { + limbLen++; + } + + limbLen--; + limbPow = limbPow / base | 0; + var total = number.length - start; + var mod = total % limbLen; + var end = Math.min(total, total - mod) + start; + var word = 0; + + for (var i = start; i < end; i += limbLen) { + word = parseBase(number, i, i + limbLen, base); + this.imuln(limbPow); + + if (this.words[0] + word < 0x4000000) { + this.words[0] += word; + } else { + this._iaddn(word); + } + } + + if (mod !== 0) { + var pow = 1; + word = parseBase(number, i, number.length, base); + + for (i = 0; i < mod; i++) { + pow *= base; + } + + this.imuln(pow); + + if (this.words[0] + word < 0x4000000) { + this.words[0] += word; + } else { + this._iaddn(word); + } + } + }; + + BN.prototype.copy = function copy(dest) { + dest.words = new Array(this.length); + + for (var i = 0; i < this.length; i++) { + dest.words[i] = this.words[i]; + } + + dest.length = this.length; + dest.negative = this.negative; + dest.red = this.red; + }; + + BN.prototype.clone = function clone() { + var r = new BN(null); + this.copy(r); + return r; + }; + + BN.prototype._expand = function _expand(size) { + while (this.length < size) { + this.words[this.length++] = 0; + } + + return this; + }; // Remove leading `0` from `this` + + + BN.prototype.strip = function strip() { + while (this.length > 1 && this.words[this.length - 1] === 0) { + this.length--; + } + + return this._normSign(); + }; + + BN.prototype._normSign = function _normSign() { + // -0 = 0 + if (this.length === 1 && this.words[0] === 0) { + this.negative = 0; + } + + return this; + }; + + BN.prototype.inspect = function inspect() { + return (this.red ? ''; + }; + /* + var zeros = []; + var groupSizes = []; + var groupBases = []; + var s = ''; + var i = -1; + while (++i < BN.wordSize) { + zeros[i] = s; + s += '0'; + } + groupSizes[0] = 0; + groupSizes[1] = 0; + groupBases[0] = 0; + groupBases[1] = 0; + var base = 2 - 1; + while (++base < 36 + 1) { + var groupSize = 0; + var groupBase = 1; + while (groupBase < (1 << BN.wordSize) / base) { + groupBase *= base; + groupSize += 1; + } + groupSizes[base] = groupSize; + groupBases[base] = groupBase; + } + */ + + + var zeros = ['', '0', '00', '000', '0000', '00000', '000000', '0000000', '00000000', '000000000', '0000000000', '00000000000', '000000000000', '0000000000000', '00000000000000', '000000000000000', '0000000000000000', '00000000000000000', '000000000000000000', '0000000000000000000', '00000000000000000000', '000000000000000000000', '0000000000000000000000', '00000000000000000000000', '000000000000000000000000', '0000000000000000000000000']; + var groupSizes = [0, 0, 25, 16, 12, 11, 10, 9, 8, 8, 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5]; + var groupBases = [0, 0, 33554432, 43046721, 16777216, 48828125, 60466176, 40353607, 16777216, 43046721, 10000000, 19487171, 35831808, 62748517, 7529536, 11390625, 16777216, 24137569, 34012224, 47045881, 64000000, 4084101, 5153632, 6436343, 7962624, 9765625, 11881376, 14348907, 17210368, 20511149, 24300000, 28629151, 33554432, 39135393, 45435424, 52521875, 60466176]; + + BN.prototype.toString = function toString(base, padding) { + base = base || 10; + padding = padding | 0 || 1; + var out; + + if (base === 16 || base === 'hex') { + out = ''; + var off = 0; + var carry = 0; + + for (var i = 0; i < this.length; i++) { + var w = this.words[i]; + var word = ((w << off | carry) & 0xffffff).toString(16); + carry = w >>> 24 - off & 0xffffff; + + if (carry !== 0 || i !== this.length - 1) { + out = zeros[6 - word.length] + word + out; + } else { + out = word + out; + } + + off += 2; + + if (off >= 26) { + off -= 26; + i--; + } + } + + if (carry !== 0) { + out = carry.toString(16) + out; + } + + while (out.length % padding !== 0) { + out = '0' + out; + } + + if (this.negative !== 0) { + out = '-' + out; + } + + return out; + } + + if (base === (base | 0) && base >= 2 && base <= 36) { + // var groupSize = Math.floor(BN.wordSize * Math.LN2 / Math.log(base)); + var groupSize = groupSizes[base]; // var groupBase = Math.pow(base, groupSize); + + var groupBase = groupBases[base]; + out = ''; + var c = this.clone(); + c.negative = 0; + + while (!c.isZero()) { + var r = c.modn(groupBase).toString(base); + c = c.idivn(groupBase); + + if (!c.isZero()) { + out = zeros[groupSize - r.length] + r + out; + } else { + out = r + out; + } + } + + if (this.isZero()) { + out = '0' + out; + } + + while (out.length % padding !== 0) { + out = '0' + out; + } + + if (this.negative !== 0) { + out = '-' + out; + } + + return out; + } + + assert(false, 'Base should be between 2 and 36'); + }; + + BN.prototype.toNumber = function toNumber() { + var ret = this.words[0]; + + if (this.length === 2) { + ret += this.words[1] * 0x4000000; + } else if (this.length === 3 && this.words[2] === 0x01) { + // NOTE: at this stage it is known that the top bit is set + ret += 0x10000000000000 + this.words[1] * 0x4000000; + } else if (this.length > 2) { + assert(false, 'Number can only safely store up to 53 bits'); + } + + return this.negative !== 0 ? -ret : ret; + }; + + BN.prototype.toJSON = function toJSON() { + return this.toString(16); + }; + + BN.prototype.toBuffer = function toBuffer(endian, length) { + assert(typeof Buffer !== 'undefined'); + return this.toArrayLike(Buffer, endian, length); + }; + + BN.prototype.toArray = function toArray(endian, length) { + return this.toArrayLike(Array, endian, length); + }; + + BN.prototype.toArrayLike = function toArrayLike(ArrayType, endian, length) { + var byteLength = this.byteLength(); + var reqLength = length || Math.max(1, byteLength); + assert(byteLength <= reqLength, 'byte array longer than desired length'); + assert(reqLength > 0, 'Requested array length <= 0'); + this.strip(); + var littleEndian = endian === 'le'; + var res = new ArrayType(reqLength); + var b, i; + var q = this.clone(); + + if (!littleEndian) { + // Assume big-endian + for (i = 0; i < reqLength - byteLength; i++) { + res[i] = 0; + } + + for (i = 0; !q.isZero(); i++) { + b = q.andln(0xff); + q.iushrn(8); + res[reqLength - i - 1] = b; + } + } else { + for (i = 0; !q.isZero(); i++) { + b = q.andln(0xff); + q.iushrn(8); + res[i] = b; + } + + for (; i < reqLength; i++) { + res[i] = 0; + } + } + + return res; + }; + + if (Math.clz32) { + BN.prototype._countBits = function _countBits(w) { + return 32 - Math.clz32(w); + }; + } else { + BN.prototype._countBits = function _countBits(w) { + var t = w; + var r = 0; + + if (t >= 0x1000) { + r += 13; + t >>>= 13; + } + + if (t >= 0x40) { + r += 7; + t >>>= 7; + } + + if (t >= 0x8) { + r += 4; + t >>>= 4; + } + + if (t >= 0x02) { + r += 2; + t >>>= 2; + } + + return r + t; + }; + } + + BN.prototype._zeroBits = function _zeroBits(w) { + // Short-cut + if (w === 0) return 26; + var t = w; + var r = 0; + + if ((t & 0x1fff) === 0) { + r += 13; + t >>>= 13; + } + + if ((t & 0x7f) === 0) { + r += 7; + t >>>= 7; + } + + if ((t & 0xf) === 0) { + r += 4; + t >>>= 4; + } + + if ((t & 0x3) === 0) { + r += 2; + t >>>= 2; + } + + if ((t & 0x1) === 0) { + r++; + } + + return r; + }; // Return number of used bits in a BN + + + BN.prototype.bitLength = function bitLength() { + var w = this.words[this.length - 1]; + + var hi = this._countBits(w); + + return (this.length - 1) * 26 + hi; + }; + + function toBitArray(num) { + var w = new Array(num.bitLength()); + + for (var bit = 0; bit < w.length; bit++) { + var off = bit / 26 | 0; + var wbit = bit % 26; + w[bit] = (num.words[off] & 1 << wbit) >>> wbit; + } + + return w; + } // Number of trailing zero bits + + + BN.prototype.zeroBits = function zeroBits() { + if (this.isZero()) return 0; + var r = 0; + + for (var i = 0; i < this.length; i++) { + var b = this._zeroBits(this.words[i]); + + r += b; + if (b !== 26) break; + } + + return r; + }; + + BN.prototype.byteLength = function byteLength() { + return Math.ceil(this.bitLength() / 8); + }; + + BN.prototype.toTwos = function toTwos(width) { + if (this.negative !== 0) { + return this.abs().inotn(width).iaddn(1); + } + + return this.clone(); + }; + + BN.prototype.fromTwos = function fromTwos(width) { + if (this.testn(width - 1)) { + return this.notn(width).iaddn(1).ineg(); + } + + return this.clone(); + }; + + BN.prototype.isNeg = function isNeg() { + return this.negative !== 0; + }; // Return negative clone of `this` + + + BN.prototype.neg = function neg() { + return this.clone().ineg(); + }; + + BN.prototype.ineg = function ineg() { + if (!this.isZero()) { + this.negative ^= 1; + } + + return this; + }; // Or `num` with `this` in-place + + + BN.prototype.iuor = function iuor(num) { + while (this.length < num.length) { + this.words[this.length++] = 0; + } + + for (var i = 0; i < num.length; i++) { + this.words[i] = this.words[i] | num.words[i]; + } + + return this.strip(); + }; + + BN.prototype.ior = function ior(num) { + assert((this.negative | num.negative) === 0); + return this.iuor(num); + }; // Or `num` with `this` + + + BN.prototype.or = function or(num) { + if (this.length > num.length) return this.clone().ior(num); + return num.clone().ior(this); + }; + + BN.prototype.uor = function uor(num) { + if (this.length > num.length) return this.clone().iuor(num); + return num.clone().iuor(this); + }; // And `num` with `this` in-place + + + BN.prototype.iuand = function iuand(num) { + // b = min-length(num, this) + var b; + + if (this.length > num.length) { + b = num; + } else { + b = this; + } + + for (var i = 0; i < b.length; i++) { + this.words[i] = this.words[i] & num.words[i]; + } + + this.length = b.length; + return this.strip(); + }; + + BN.prototype.iand = function iand(num) { + assert((this.negative | num.negative) === 0); + return this.iuand(num); + }; // And `num` with `this` + + + BN.prototype.and = function and(num) { + if (this.length > num.length) return this.clone().iand(num); + return num.clone().iand(this); + }; + + BN.prototype.uand = function uand(num) { + if (this.length > num.length) return this.clone().iuand(num); + return num.clone().iuand(this); + }; // Xor `num` with `this` in-place + + + BN.prototype.iuxor = function iuxor(num) { + // a.length > b.length + var a; + var b; + + if (this.length > num.length) { + a = this; + b = num; + } else { + a = num; + b = this; + } + + for (var i = 0; i < b.length; i++) { + this.words[i] = a.words[i] ^ b.words[i]; + } + + if (this !== a) { + for (; i < a.length; i++) { + this.words[i] = a.words[i]; + } + } + + this.length = a.length; + return this.strip(); + }; + + BN.prototype.ixor = function ixor(num) { + assert((this.negative | num.negative) === 0); + return this.iuxor(num); + }; // Xor `num` with `this` + + + BN.prototype.xor = function xor(num) { + if (this.length > num.length) return this.clone().ixor(num); + return num.clone().ixor(this); + }; + + BN.prototype.uxor = function uxor(num) { + if (this.length > num.length) return this.clone().iuxor(num); + return num.clone().iuxor(this); + }; // Not ``this`` with ``width`` bitwidth + + + BN.prototype.inotn = function inotn(width) { + assert(typeof width === 'number' && width >= 0); + var bytesNeeded = Math.ceil(width / 26) | 0; + var bitsLeft = width % 26; // Extend the buffer with leading zeroes + + this._expand(bytesNeeded); + + if (bitsLeft > 0) { + bytesNeeded--; + } // Handle complete words + + + for (var i = 0; i < bytesNeeded; i++) { + this.words[i] = ~this.words[i] & 0x3ffffff; + } // Handle the residue + + + if (bitsLeft > 0) { + this.words[i] = ~this.words[i] & 0x3ffffff >> 26 - bitsLeft; + } // And remove leading zeroes + + + return this.strip(); + }; + + BN.prototype.notn = function notn(width) { + return this.clone().inotn(width); + }; // Set `bit` of `this` + + + BN.prototype.setn = function setn(bit, val) { + assert(typeof bit === 'number' && bit >= 0); + var off = bit / 26 | 0; + var wbit = bit % 26; + + this._expand(off + 1); + + if (val) { + this.words[off] = this.words[off] | 1 << wbit; + } else { + this.words[off] = this.words[off] & ~(1 << wbit); + } + + return this.strip(); + }; // Add `num` to `this` in-place + + + BN.prototype.iadd = function iadd(num) { + var r; // negative + positive + + if (this.negative !== 0 && num.negative === 0) { + this.negative = 0; + r = this.isub(num); + this.negative ^= 1; + return this._normSign(); // positive + negative + } else if (this.negative === 0 && num.negative !== 0) { + num.negative = 0; + r = this.isub(num); + num.negative = 1; + return r._normSign(); + } // a.length > b.length + + + var a, b; + + if (this.length > num.length) { + a = this; + b = num; + } else { + a = num; + b = this; + } + + var carry = 0; + + for (var i = 0; i < b.length; i++) { + r = (a.words[i] | 0) + (b.words[i] | 0) + carry; + this.words[i] = r & 0x3ffffff; + carry = r >>> 26; + } + + for (; carry !== 0 && i < a.length; i++) { + r = (a.words[i] | 0) + carry; + this.words[i] = r & 0x3ffffff; + carry = r >>> 26; + } + + this.length = a.length; + + if (carry !== 0) { + this.words[this.length] = carry; + this.length++; // Copy the rest of the words + } else if (a !== this) { + for (; i < a.length; i++) { + this.words[i] = a.words[i]; + } + } + + return this; + }; // Add `num` to `this` + + + BN.prototype.add = function add(num) { + var res; + + if (num.negative !== 0 && this.negative === 0) { + num.negative = 0; + res = this.sub(num); + num.negative ^= 1; + return res; + } else if (num.negative === 0 && this.negative !== 0) { + this.negative = 0; + res = num.sub(this); + this.negative = 1; + return res; + } + + if (this.length > num.length) return this.clone().iadd(num); + return num.clone().iadd(this); + }; // Subtract `num` from `this` in-place + + + BN.prototype.isub = function isub(num) { + // this - (-num) = this + num + if (num.negative !== 0) { + num.negative = 0; + var r = this.iadd(num); + num.negative = 1; + return r._normSign(); // -this - num = -(this + num) + } else if (this.negative !== 0) { + this.negative = 0; + this.iadd(num); + this.negative = 1; + return this._normSign(); + } // At this point both numbers are positive + + + var cmp = this.cmp(num); // Optimization - zeroify + + if (cmp === 0) { + this.negative = 0; + this.length = 1; + this.words[0] = 0; + return this; + } // a > b + + + var a, b; + + if (cmp > 0) { + a = this; + b = num; + } else { + a = num; + b = this; + } + + var carry = 0; + + for (var i = 0; i < b.length; i++) { + r = (a.words[i] | 0) - (b.words[i] | 0) + carry; + carry = r >> 26; + this.words[i] = r & 0x3ffffff; + } + + for (; carry !== 0 && i < a.length; i++) { + r = (a.words[i] | 0) + carry; + carry = r >> 26; + this.words[i] = r & 0x3ffffff; + } // Copy rest of the words + + + if (carry === 0 && i < a.length && a !== this) { + for (; i < a.length; i++) { + this.words[i] = a.words[i]; + } + } + + this.length = Math.max(this.length, i); + + if (a !== this) { + this.negative = 1; + } + + return this.strip(); + }; // Subtract `num` from `this` + + + BN.prototype.sub = function sub(num) { + return this.clone().isub(num); + }; + + function smallMulTo(self, num, out) { + out.negative = num.negative ^ self.negative; + var len = self.length + num.length | 0; + out.length = len; + len = len - 1 | 0; // Peel one iteration (compiler can't do it, because of code complexity) + + var a = self.words[0] | 0; + var b = num.words[0] | 0; + var r = a * b; + var lo = r & 0x3ffffff; + var carry = r / 0x4000000 | 0; + out.words[0] = lo; + + for (var k = 1; k < len; k++) { + // Sum all words with the same `i + j = k` and accumulate `ncarry`, + // note that ncarry could be >= 0x3ffffff + var ncarry = carry >>> 26; + var rword = carry & 0x3ffffff; + var maxJ = Math.min(k, num.length - 1); + + for (var j = Math.max(0, k - self.length + 1); j <= maxJ; j++) { + var i = k - j | 0; + a = self.words[i] | 0; + b = num.words[j] | 0; + r = a * b + rword; + ncarry += r / 0x4000000 | 0; + rword = r & 0x3ffffff; + } + + out.words[k] = rword | 0; + carry = ncarry | 0; + } + + if (carry !== 0) { + out.words[k] = carry | 0; + } else { + out.length--; + } + + return out.strip(); + } // TODO(indutny): it may be reasonable to omit it for users who don't need + // to work with 256-bit numbers, otherwise it gives 20% improvement for 256-bit + // multiplication (like elliptic secp256k1). + + + var comb10MulTo = function comb10MulTo(self, num, out) { + var a = self.words; + var b = num.words; + var o = out.words; + var c = 0; + var lo; + var mid; + var hi; + var a0 = a[0] | 0; + var al0 = a0 & 0x1fff; + var ah0 = a0 >>> 13; + var a1 = a[1] | 0; + var al1 = a1 & 0x1fff; + var ah1 = a1 >>> 13; + var a2 = a[2] | 0; + var al2 = a2 & 0x1fff; + var ah2 = a2 >>> 13; + var a3 = a[3] | 0; + var al3 = a3 & 0x1fff; + var ah3 = a3 >>> 13; + var a4 = a[4] | 0; + var al4 = a4 & 0x1fff; + var ah4 = a4 >>> 13; + var a5 = a[5] | 0; + var al5 = a5 & 0x1fff; + var ah5 = a5 >>> 13; + var a6 = a[6] | 0; + var al6 = a6 & 0x1fff; + var ah6 = a6 >>> 13; + var a7 = a[7] | 0; + var al7 = a7 & 0x1fff; + var ah7 = a7 >>> 13; + var a8 = a[8] | 0; + var al8 = a8 & 0x1fff; + var ah8 = a8 >>> 13; + var a9 = a[9] | 0; + var al9 = a9 & 0x1fff; + var ah9 = a9 >>> 13; + var b0 = b[0] | 0; + var bl0 = b0 & 0x1fff; + var bh0 = b0 >>> 13; + var b1 = b[1] | 0; + var bl1 = b1 & 0x1fff; + var bh1 = b1 >>> 13; + var b2 = b[2] | 0; + var bl2 = b2 & 0x1fff; + var bh2 = b2 >>> 13; + var b3 = b[3] | 0; + var bl3 = b3 & 0x1fff; + var bh3 = b3 >>> 13; + var b4 = b[4] | 0; + var bl4 = b4 & 0x1fff; + var bh4 = b4 >>> 13; + var b5 = b[5] | 0; + var bl5 = b5 & 0x1fff; + var bh5 = b5 >>> 13; + var b6 = b[6] | 0; + var bl6 = b6 & 0x1fff; + var bh6 = b6 >>> 13; + var b7 = b[7] | 0; + var bl7 = b7 & 0x1fff; + var bh7 = b7 >>> 13; + var b8 = b[8] | 0; + var bl8 = b8 & 0x1fff; + var bh8 = b8 >>> 13; + var b9 = b[9] | 0; + var bl9 = b9 & 0x1fff; + var bh9 = b9 >>> 13; + out.negative = self.negative ^ num.negative; + out.length = 19; + /* k = 0 */ + + lo = Math.imul(al0, bl0); + mid = Math.imul(al0, bh0); + mid = mid + Math.imul(ah0, bl0) | 0; + hi = Math.imul(ah0, bh0); + var w0 = (c + lo | 0) + ((mid & 0x1fff) << 13) | 0; + c = (hi + (mid >>> 13) | 0) + (w0 >>> 26) | 0; + w0 &= 0x3ffffff; + /* k = 1 */ + + lo = Math.imul(al1, bl0); + mid = Math.imul(al1, bh0); + mid = mid + Math.imul(ah1, bl0) | 0; + hi = Math.imul(ah1, bh0); + lo = lo + Math.imul(al0, bl1) | 0; + mid = mid + Math.imul(al0, bh1) | 0; + mid = mid + Math.imul(ah0, bl1) | 0; + hi = hi + Math.imul(ah0, bh1) | 0; + var w1 = (c + lo | 0) + ((mid & 0x1fff) << 13) | 0; + c = (hi + (mid >>> 13) | 0) + (w1 >>> 26) | 0; + w1 &= 0x3ffffff; + /* k = 2 */ + + lo = Math.imul(al2, bl0); + mid = Math.imul(al2, bh0); + mid = mid + Math.imul(ah2, bl0) | 0; + hi = Math.imul(ah2, bh0); + lo = lo + Math.imul(al1, bl1) | 0; + mid = mid + Math.imul(al1, bh1) | 0; + mid = mid + Math.imul(ah1, bl1) | 0; + hi = hi + Math.imul(ah1, bh1) | 0; + lo = lo + Math.imul(al0, bl2) | 0; + mid = mid + Math.imul(al0, bh2) | 0; + mid = mid + Math.imul(ah0, bl2) | 0; + hi = hi + Math.imul(ah0, bh2) | 0; + var w2 = (c + lo | 0) + ((mid & 0x1fff) << 13) | 0; + c = (hi + (mid >>> 13) | 0) + (w2 >>> 26) | 0; + w2 &= 0x3ffffff; + /* k = 3 */ + + lo = Math.imul(al3, bl0); + mid = Math.imul(al3, bh0); + mid = mid + Math.imul(ah3, bl0) | 0; + hi = Math.imul(ah3, bh0); + lo = lo + Math.imul(al2, bl1) | 0; + mid = mid + Math.imul(al2, bh1) | 0; + mid = mid + Math.imul(ah2, bl1) | 0; + hi = hi + Math.imul(ah2, bh1) | 0; + lo = lo + Math.imul(al1, bl2) | 0; + mid = mid + Math.imul(al1, bh2) | 0; + mid = mid + Math.imul(ah1, bl2) | 0; + hi = hi + Math.imul(ah1, bh2) | 0; + lo = lo + Math.imul(al0, bl3) | 0; + mid = mid + Math.imul(al0, bh3) | 0; + mid = mid + Math.imul(ah0, bl3) | 0; + hi = hi + Math.imul(ah0, bh3) | 0; + var w3 = (c + lo | 0) + ((mid & 0x1fff) << 13) | 0; + c = (hi + (mid >>> 13) | 0) + (w3 >>> 26) | 0; + w3 &= 0x3ffffff; + /* k = 4 */ + + lo = Math.imul(al4, bl0); + mid = Math.imul(al4, bh0); + mid = mid + Math.imul(ah4, bl0) | 0; + hi = Math.imul(ah4, bh0); + lo = lo + Math.imul(al3, bl1) | 0; + mid = mid + Math.imul(al3, bh1) | 0; + mid = mid + Math.imul(ah3, bl1) | 0; + hi = hi + Math.imul(ah3, bh1) | 0; + lo = lo + Math.imul(al2, bl2) | 0; + mid = mid + Math.imul(al2, bh2) | 0; + mid = mid + Math.imul(ah2, bl2) | 0; + hi = hi + Math.imul(ah2, bh2) | 0; + lo = lo + Math.imul(al1, bl3) | 0; + mid = mid + Math.imul(al1, bh3) | 0; + mid = mid + Math.imul(ah1, bl3) | 0; + hi = hi + Math.imul(ah1, bh3) | 0; + lo = lo + Math.imul(al0, bl4) | 0; + mid = mid + Math.imul(al0, bh4) | 0; + mid = mid + Math.imul(ah0, bl4) | 0; + hi = hi + Math.imul(ah0, bh4) | 0; + var w4 = (c + lo | 0) + ((mid & 0x1fff) << 13) | 0; + c = (hi + (mid >>> 13) | 0) + (w4 >>> 26) | 0; + w4 &= 0x3ffffff; + /* k = 5 */ + + lo = Math.imul(al5, bl0); + mid = Math.imul(al5, bh0); + mid = mid + Math.imul(ah5, bl0) | 0; + hi = Math.imul(ah5, bh0); + lo = lo + Math.imul(al4, bl1) | 0; + mid = mid + Math.imul(al4, bh1) | 0; + mid = mid + Math.imul(ah4, bl1) | 0; + hi = hi + Math.imul(ah4, bh1) | 0; + lo = lo + Math.imul(al3, bl2) | 0; + mid = mid + Math.imul(al3, bh2) | 0; + mid = mid + Math.imul(ah3, bl2) | 0; + hi = hi + Math.imul(ah3, bh2) | 0; + lo = lo + Math.imul(al2, bl3) | 0; + mid = mid + Math.imul(al2, bh3) | 0; + mid = mid + Math.imul(ah2, bl3) | 0; + hi = hi + Math.imul(ah2, bh3) | 0; + lo = lo + Math.imul(al1, bl4) | 0; + mid = mid + Math.imul(al1, bh4) | 0; + mid = mid + Math.imul(ah1, bl4) | 0; + hi = hi + Math.imul(ah1, bh4) | 0; + lo = lo + Math.imul(al0, bl5) | 0; + mid = mid + Math.imul(al0, bh5) | 0; + mid = mid + Math.imul(ah0, bl5) | 0; + hi = hi + Math.imul(ah0, bh5) | 0; + var w5 = (c + lo | 0) + ((mid & 0x1fff) << 13) | 0; + c = (hi + (mid >>> 13) | 0) + (w5 >>> 26) | 0; + w5 &= 0x3ffffff; + /* k = 6 */ + + lo = Math.imul(al6, bl0); + mid = Math.imul(al6, bh0); + mid = mid + Math.imul(ah6, bl0) | 0; + hi = Math.imul(ah6, bh0); + lo = lo + Math.imul(al5, bl1) | 0; + mid = mid + Math.imul(al5, bh1) | 0; + mid = mid + Math.imul(ah5, bl1) | 0; + hi = hi + Math.imul(ah5, bh1) | 0; + lo = lo + Math.imul(al4, bl2) | 0; + mid = mid + Math.imul(al4, bh2) | 0; + mid = mid + Math.imul(ah4, bl2) | 0; + hi = hi + Math.imul(ah4, bh2) | 0; + lo = lo + Math.imul(al3, bl3) | 0; + mid = mid + Math.imul(al3, bh3) | 0; + mid = mid + Math.imul(ah3, bl3) | 0; + hi = hi + Math.imul(ah3, bh3) | 0; + lo = lo + Math.imul(al2, bl4) | 0; + mid = mid + Math.imul(al2, bh4) | 0; + mid = mid + Math.imul(ah2, bl4) | 0; + hi = hi + Math.imul(ah2, bh4) | 0; + lo = lo + Math.imul(al1, bl5) | 0; + mid = mid + Math.imul(al1, bh5) | 0; + mid = mid + Math.imul(ah1, bl5) | 0; + hi = hi + Math.imul(ah1, bh5) | 0; + lo = lo + Math.imul(al0, bl6) | 0; + mid = mid + Math.imul(al0, bh6) | 0; + mid = mid + Math.imul(ah0, bl6) | 0; + hi = hi + Math.imul(ah0, bh6) | 0; + var w6 = (c + lo | 0) + ((mid & 0x1fff) << 13) | 0; + c = (hi + (mid >>> 13) | 0) + (w6 >>> 26) | 0; + w6 &= 0x3ffffff; + /* k = 7 */ + + lo = Math.imul(al7, bl0); + mid = Math.imul(al7, bh0); + mid = mid + Math.imul(ah7, bl0) | 0; + hi = Math.imul(ah7, bh0); + lo = lo + Math.imul(al6, bl1) | 0; + mid = mid + Math.imul(al6, bh1) | 0; + mid = mid + Math.imul(ah6, bl1) | 0; + hi = hi + Math.imul(ah6, bh1) | 0; + lo = lo + Math.imul(al5, bl2) | 0; + mid = mid + Math.imul(al5, bh2) | 0; + mid = mid + Math.imul(ah5, bl2) | 0; + hi = hi + Math.imul(ah5, bh2) | 0; + lo = lo + Math.imul(al4, bl3) | 0; + mid = mid + Math.imul(al4, bh3) | 0; + mid = mid + Math.imul(ah4, bl3) | 0; + hi = hi + Math.imul(ah4, bh3) | 0; + lo = lo + Math.imul(al3, bl4) | 0; + mid = mid + Math.imul(al3, bh4) | 0; + mid = mid + Math.imul(ah3, bl4) | 0; + hi = hi + Math.imul(ah3, bh4) | 0; + lo = lo + Math.imul(al2, bl5) | 0; + mid = mid + Math.imul(al2, bh5) | 0; + mid = mid + Math.imul(ah2, bl5) | 0; + hi = hi + Math.imul(ah2, bh5) | 0; + lo = lo + Math.imul(al1, bl6) | 0; + mid = mid + Math.imul(al1, bh6) | 0; + mid = mid + Math.imul(ah1, bl6) | 0; + hi = hi + Math.imul(ah1, bh6) | 0; + lo = lo + Math.imul(al0, bl7) | 0; + mid = mid + Math.imul(al0, bh7) | 0; + mid = mid + Math.imul(ah0, bl7) | 0; + hi = hi + Math.imul(ah0, bh7) | 0; + var w7 = (c + lo | 0) + ((mid & 0x1fff) << 13) | 0; + c = (hi + (mid >>> 13) | 0) + (w7 >>> 26) | 0; + w7 &= 0x3ffffff; + /* k = 8 */ + + lo = Math.imul(al8, bl0); + mid = Math.imul(al8, bh0); + mid = mid + Math.imul(ah8, bl0) | 0; + hi = Math.imul(ah8, bh0); + lo = lo + Math.imul(al7, bl1) | 0; + mid = mid + Math.imul(al7, bh1) | 0; + mid = mid + Math.imul(ah7, bl1) | 0; + hi = hi + Math.imul(ah7, bh1) | 0; + lo = lo + Math.imul(al6, bl2) | 0; + mid = mid + Math.imul(al6, bh2) | 0; + mid = mid + Math.imul(ah6, bl2) | 0; + hi = hi + Math.imul(ah6, bh2) | 0; + lo = lo + Math.imul(al5, bl3) | 0; + mid = mid + Math.imul(al5, bh3) | 0; + mid = mid + Math.imul(ah5, bl3) | 0; + hi = hi + Math.imul(ah5, bh3) | 0; + lo = lo + Math.imul(al4, bl4) | 0; + mid = mid + Math.imul(al4, bh4) | 0; + mid = mid + Math.imul(ah4, bl4) | 0; + hi = hi + Math.imul(ah4, bh4) | 0; + lo = lo + Math.imul(al3, bl5) | 0; + mid = mid + Math.imul(al3, bh5) | 0; + mid = mid + Math.imul(ah3, bl5) | 0; + hi = hi + Math.imul(ah3, bh5) | 0; + lo = lo + Math.imul(al2, bl6) | 0; + mid = mid + Math.imul(al2, bh6) | 0; + mid = mid + Math.imul(ah2, bl6) | 0; + hi = hi + Math.imul(ah2, bh6) | 0; + lo = lo + Math.imul(al1, bl7) | 0; + mid = mid + Math.imul(al1, bh7) | 0; + mid = mid + Math.imul(ah1, bl7) | 0; + hi = hi + Math.imul(ah1, bh7) | 0; + lo = lo + Math.imul(al0, bl8) | 0; + mid = mid + Math.imul(al0, bh8) | 0; + mid = mid + Math.imul(ah0, bl8) | 0; + hi = hi + Math.imul(ah0, bh8) | 0; + var w8 = (c + lo | 0) + ((mid & 0x1fff) << 13) | 0; + c = (hi + (mid >>> 13) | 0) + (w8 >>> 26) | 0; + w8 &= 0x3ffffff; + /* k = 9 */ + + lo = Math.imul(al9, bl0); + mid = Math.imul(al9, bh0); + mid = mid + Math.imul(ah9, bl0) | 0; + hi = Math.imul(ah9, bh0); + lo = lo + Math.imul(al8, bl1) | 0; + mid = mid + Math.imul(al8, bh1) | 0; + mid = mid + Math.imul(ah8, bl1) | 0; + hi = hi + Math.imul(ah8, bh1) | 0; + lo = lo + Math.imul(al7, bl2) | 0; + mid = mid + Math.imul(al7, bh2) | 0; + mid = mid + Math.imul(ah7, bl2) | 0; + hi = hi + Math.imul(ah7, bh2) | 0; + lo = lo + Math.imul(al6, bl3) | 0; + mid = mid + Math.imul(al6, bh3) | 0; + mid = mid + Math.imul(ah6, bl3) | 0; + hi = hi + Math.imul(ah6, bh3) | 0; + lo = lo + Math.imul(al5, bl4) | 0; + mid = mid + Math.imul(al5, bh4) | 0; + mid = mid + Math.imul(ah5, bl4) | 0; + hi = hi + Math.imul(ah5, bh4) | 0; + lo = lo + Math.imul(al4, bl5) | 0; + mid = mid + Math.imul(al4, bh5) | 0; + mid = mid + Math.imul(ah4, bl5) | 0; + hi = hi + Math.imul(ah4, bh5) | 0; + lo = lo + Math.imul(al3, bl6) | 0; + mid = mid + Math.imul(al3, bh6) | 0; + mid = mid + Math.imul(ah3, bl6) | 0; + hi = hi + Math.imul(ah3, bh6) | 0; + lo = lo + Math.imul(al2, bl7) | 0; + mid = mid + Math.imul(al2, bh7) | 0; + mid = mid + Math.imul(ah2, bl7) | 0; + hi = hi + Math.imul(ah2, bh7) | 0; + lo = lo + Math.imul(al1, bl8) | 0; + mid = mid + Math.imul(al1, bh8) | 0; + mid = mid + Math.imul(ah1, bl8) | 0; + hi = hi + Math.imul(ah1, bh8) | 0; + lo = lo + Math.imul(al0, bl9) | 0; + mid = mid + Math.imul(al0, bh9) | 0; + mid = mid + Math.imul(ah0, bl9) | 0; + hi = hi + Math.imul(ah0, bh9) | 0; + var w9 = (c + lo | 0) + ((mid & 0x1fff) << 13) | 0; + c = (hi + (mid >>> 13) | 0) + (w9 >>> 26) | 0; + w9 &= 0x3ffffff; + /* k = 10 */ + + lo = Math.imul(al9, bl1); + mid = Math.imul(al9, bh1); + mid = mid + Math.imul(ah9, bl1) | 0; + hi = Math.imul(ah9, bh1); + lo = lo + Math.imul(al8, bl2) | 0; + mid = mid + Math.imul(al8, bh2) | 0; + mid = mid + Math.imul(ah8, bl2) | 0; + hi = hi + Math.imul(ah8, bh2) | 0; + lo = lo + Math.imul(al7, bl3) | 0; + mid = mid + Math.imul(al7, bh3) | 0; + mid = mid + Math.imul(ah7, bl3) | 0; + hi = hi + Math.imul(ah7, bh3) | 0; + lo = lo + Math.imul(al6, bl4) | 0; + mid = mid + Math.imul(al6, bh4) | 0; + mid = mid + Math.imul(ah6, bl4) | 0; + hi = hi + Math.imul(ah6, bh4) | 0; + lo = lo + Math.imul(al5, bl5) | 0; + mid = mid + Math.imul(al5, bh5) | 0; + mid = mid + Math.imul(ah5, bl5) | 0; + hi = hi + Math.imul(ah5, bh5) | 0; + lo = lo + Math.imul(al4, bl6) | 0; + mid = mid + Math.imul(al4, bh6) | 0; + mid = mid + Math.imul(ah4, bl6) | 0; + hi = hi + Math.imul(ah4, bh6) | 0; + lo = lo + Math.imul(al3, bl7) | 0; + mid = mid + Math.imul(al3, bh7) | 0; + mid = mid + Math.imul(ah3, bl7) | 0; + hi = hi + Math.imul(ah3, bh7) | 0; + lo = lo + Math.imul(al2, bl8) | 0; + mid = mid + Math.imul(al2, bh8) | 0; + mid = mid + Math.imul(ah2, bl8) | 0; + hi = hi + Math.imul(ah2, bh8) | 0; + lo = lo + Math.imul(al1, bl9) | 0; + mid = mid + Math.imul(al1, bh9) | 0; + mid = mid + Math.imul(ah1, bl9) | 0; + hi = hi + Math.imul(ah1, bh9) | 0; + var w10 = (c + lo | 0) + ((mid & 0x1fff) << 13) | 0; + c = (hi + (mid >>> 13) | 0) + (w10 >>> 26) | 0; + w10 &= 0x3ffffff; + /* k = 11 */ + + lo = Math.imul(al9, bl2); + mid = Math.imul(al9, bh2); + mid = mid + Math.imul(ah9, bl2) | 0; + hi = Math.imul(ah9, bh2); + lo = lo + Math.imul(al8, bl3) | 0; + mid = mid + Math.imul(al8, bh3) | 0; + mid = mid + Math.imul(ah8, bl3) | 0; + hi = hi + Math.imul(ah8, bh3) | 0; + lo = lo + Math.imul(al7, bl4) | 0; + mid = mid + Math.imul(al7, bh4) | 0; + mid = mid + Math.imul(ah7, bl4) | 0; + hi = hi + Math.imul(ah7, bh4) | 0; + lo = lo + Math.imul(al6, bl5) | 0; + mid = mid + Math.imul(al6, bh5) | 0; + mid = mid + Math.imul(ah6, bl5) | 0; + hi = hi + Math.imul(ah6, bh5) | 0; + lo = lo + Math.imul(al5, bl6) | 0; + mid = mid + Math.imul(al5, bh6) | 0; + mid = mid + Math.imul(ah5, bl6) | 0; + hi = hi + Math.imul(ah5, bh6) | 0; + lo = lo + Math.imul(al4, bl7) | 0; + mid = mid + Math.imul(al4, bh7) | 0; + mid = mid + Math.imul(ah4, bl7) | 0; + hi = hi + Math.imul(ah4, bh7) | 0; + lo = lo + Math.imul(al3, bl8) | 0; + mid = mid + Math.imul(al3, bh8) | 0; + mid = mid + Math.imul(ah3, bl8) | 0; + hi = hi + Math.imul(ah3, bh8) | 0; + lo = lo + Math.imul(al2, bl9) | 0; + mid = mid + Math.imul(al2, bh9) | 0; + mid = mid + Math.imul(ah2, bl9) | 0; + hi = hi + Math.imul(ah2, bh9) | 0; + var w11 = (c + lo | 0) + ((mid & 0x1fff) << 13) | 0; + c = (hi + (mid >>> 13) | 0) + (w11 >>> 26) | 0; + w11 &= 0x3ffffff; + /* k = 12 */ + + lo = Math.imul(al9, bl3); + mid = Math.imul(al9, bh3); + mid = mid + Math.imul(ah9, bl3) | 0; + hi = Math.imul(ah9, bh3); + lo = lo + Math.imul(al8, bl4) | 0; + mid = mid + Math.imul(al8, bh4) | 0; + mid = mid + Math.imul(ah8, bl4) | 0; + hi = hi + Math.imul(ah8, bh4) | 0; + lo = lo + Math.imul(al7, bl5) | 0; + mid = mid + Math.imul(al7, bh5) | 0; + mid = mid + Math.imul(ah7, bl5) | 0; + hi = hi + Math.imul(ah7, bh5) | 0; + lo = lo + Math.imul(al6, bl6) | 0; + mid = mid + Math.imul(al6, bh6) | 0; + mid = mid + Math.imul(ah6, bl6) | 0; + hi = hi + Math.imul(ah6, bh6) | 0; + lo = lo + Math.imul(al5, bl7) | 0; + mid = mid + Math.imul(al5, bh7) | 0; + mid = mid + Math.imul(ah5, bl7) | 0; + hi = hi + Math.imul(ah5, bh7) | 0; + lo = lo + Math.imul(al4, bl8) | 0; + mid = mid + Math.imul(al4, bh8) | 0; + mid = mid + Math.imul(ah4, bl8) | 0; + hi = hi + Math.imul(ah4, bh8) | 0; + lo = lo + Math.imul(al3, bl9) | 0; + mid = mid + Math.imul(al3, bh9) | 0; + mid = mid + Math.imul(ah3, bl9) | 0; + hi = hi + Math.imul(ah3, bh9) | 0; + var w12 = (c + lo | 0) + ((mid & 0x1fff) << 13) | 0; + c = (hi + (mid >>> 13) | 0) + (w12 >>> 26) | 0; + w12 &= 0x3ffffff; + /* k = 13 */ + + lo = Math.imul(al9, bl4); + mid = Math.imul(al9, bh4); + mid = mid + Math.imul(ah9, bl4) | 0; + hi = Math.imul(ah9, bh4); + lo = lo + Math.imul(al8, bl5) | 0; + mid = mid + Math.imul(al8, bh5) | 0; + mid = mid + Math.imul(ah8, bl5) | 0; + hi = hi + Math.imul(ah8, bh5) | 0; + lo = lo + Math.imul(al7, bl6) | 0; + mid = mid + Math.imul(al7, bh6) | 0; + mid = mid + Math.imul(ah7, bl6) | 0; + hi = hi + Math.imul(ah7, bh6) | 0; + lo = lo + Math.imul(al6, bl7) | 0; + mid = mid + Math.imul(al6, bh7) | 0; + mid = mid + Math.imul(ah6, bl7) | 0; + hi = hi + Math.imul(ah6, bh7) | 0; + lo = lo + Math.imul(al5, bl8) | 0; + mid = mid + Math.imul(al5, bh8) | 0; + mid = mid + Math.imul(ah5, bl8) | 0; + hi = hi + Math.imul(ah5, bh8) | 0; + lo = lo + Math.imul(al4, bl9) | 0; + mid = mid + Math.imul(al4, bh9) | 0; + mid = mid + Math.imul(ah4, bl9) | 0; + hi = hi + Math.imul(ah4, bh9) | 0; + var w13 = (c + lo | 0) + ((mid & 0x1fff) << 13) | 0; + c = (hi + (mid >>> 13) | 0) + (w13 >>> 26) | 0; + w13 &= 0x3ffffff; + /* k = 14 */ + + lo = Math.imul(al9, bl5); + mid = Math.imul(al9, bh5); + mid = mid + Math.imul(ah9, bl5) | 0; + hi = Math.imul(ah9, bh5); + lo = lo + Math.imul(al8, bl6) | 0; + mid = mid + Math.imul(al8, bh6) | 0; + mid = mid + Math.imul(ah8, bl6) | 0; + hi = hi + Math.imul(ah8, bh6) | 0; + lo = lo + Math.imul(al7, bl7) | 0; + mid = mid + Math.imul(al7, bh7) | 0; + mid = mid + Math.imul(ah7, bl7) | 0; + hi = hi + Math.imul(ah7, bh7) | 0; + lo = lo + Math.imul(al6, bl8) | 0; + mid = mid + Math.imul(al6, bh8) | 0; + mid = mid + Math.imul(ah6, bl8) | 0; + hi = hi + Math.imul(ah6, bh8) | 0; + lo = lo + Math.imul(al5, bl9) | 0; + mid = mid + Math.imul(al5, bh9) | 0; + mid = mid + Math.imul(ah5, bl9) | 0; + hi = hi + Math.imul(ah5, bh9) | 0; + var w14 = (c + lo | 0) + ((mid & 0x1fff) << 13) | 0; + c = (hi + (mid >>> 13) | 0) + (w14 >>> 26) | 0; + w14 &= 0x3ffffff; + /* k = 15 */ + + lo = Math.imul(al9, bl6); + mid = Math.imul(al9, bh6); + mid = mid + Math.imul(ah9, bl6) | 0; + hi = Math.imul(ah9, bh6); + lo = lo + Math.imul(al8, bl7) | 0; + mid = mid + Math.imul(al8, bh7) | 0; + mid = mid + Math.imul(ah8, bl7) | 0; + hi = hi + Math.imul(ah8, bh7) | 0; + lo = lo + Math.imul(al7, bl8) | 0; + mid = mid + Math.imul(al7, bh8) | 0; + mid = mid + Math.imul(ah7, bl8) | 0; + hi = hi + Math.imul(ah7, bh8) | 0; + lo = lo + Math.imul(al6, bl9) | 0; + mid = mid + Math.imul(al6, bh9) | 0; + mid = mid + Math.imul(ah6, bl9) | 0; + hi = hi + Math.imul(ah6, bh9) | 0; + var w15 = (c + lo | 0) + ((mid & 0x1fff) << 13) | 0; + c = (hi + (mid >>> 13) | 0) + (w15 >>> 26) | 0; + w15 &= 0x3ffffff; + /* k = 16 */ + + lo = Math.imul(al9, bl7); + mid = Math.imul(al9, bh7); + mid = mid + Math.imul(ah9, bl7) | 0; + hi = Math.imul(ah9, bh7); + lo = lo + Math.imul(al8, bl8) | 0; + mid = mid + Math.imul(al8, bh8) | 0; + mid = mid + Math.imul(ah8, bl8) | 0; + hi = hi + Math.imul(ah8, bh8) | 0; + lo = lo + Math.imul(al7, bl9) | 0; + mid = mid + Math.imul(al7, bh9) | 0; + mid = mid + Math.imul(ah7, bl9) | 0; + hi = hi + Math.imul(ah7, bh9) | 0; + var w16 = (c + lo | 0) + ((mid & 0x1fff) << 13) | 0; + c = (hi + (mid >>> 13) | 0) + (w16 >>> 26) | 0; + w16 &= 0x3ffffff; + /* k = 17 */ + + lo = Math.imul(al9, bl8); + mid = Math.imul(al9, bh8); + mid = mid + Math.imul(ah9, bl8) | 0; + hi = Math.imul(ah9, bh8); + lo = lo + Math.imul(al8, bl9) | 0; + mid = mid + Math.imul(al8, bh9) | 0; + mid = mid + Math.imul(ah8, bl9) | 0; + hi = hi + Math.imul(ah8, bh9) | 0; + var w17 = (c + lo | 0) + ((mid & 0x1fff) << 13) | 0; + c = (hi + (mid >>> 13) | 0) + (w17 >>> 26) | 0; + w17 &= 0x3ffffff; + /* k = 18 */ + + lo = Math.imul(al9, bl9); + mid = Math.imul(al9, bh9); + mid = mid + Math.imul(ah9, bl9) | 0; + hi = Math.imul(ah9, bh9); + var w18 = (c + lo | 0) + ((mid & 0x1fff) << 13) | 0; + c = (hi + (mid >>> 13) | 0) + (w18 >>> 26) | 0; + w18 &= 0x3ffffff; + o[0] = w0; + o[1] = w1; + o[2] = w2; + o[3] = w3; + o[4] = w4; + o[5] = w5; + o[6] = w6; + o[7] = w7; + o[8] = w8; + o[9] = w9; + o[10] = w10; + o[11] = w11; + o[12] = w12; + o[13] = w13; + o[14] = w14; + o[15] = w15; + o[16] = w16; + o[17] = w17; + o[18] = w18; + + if (c !== 0) { + o[19] = c; + out.length++; + } + + return out; + }; // Polyfill comb + + + if (!Math.imul) { + comb10MulTo = smallMulTo; + } + + function bigMulTo(self, num, out) { + out.negative = num.negative ^ self.negative; + out.length = self.length + num.length; + var carry = 0; + var hncarry = 0; + + for (var k = 0; k < out.length - 1; k++) { + // Sum all words with the same `i + j = k` and accumulate `ncarry`, + // note that ncarry could be >= 0x3ffffff + var ncarry = hncarry; + hncarry = 0; + var rword = carry & 0x3ffffff; + var maxJ = Math.min(k, num.length - 1); + + for (var j = Math.max(0, k - self.length + 1); j <= maxJ; j++) { + var i = k - j; + var a = self.words[i] | 0; + var b = num.words[j] | 0; + var r = a * b; + var lo = r & 0x3ffffff; + ncarry = ncarry + (r / 0x4000000 | 0) | 0; + lo = lo + rword | 0; + rword = lo & 0x3ffffff; + ncarry = ncarry + (lo >>> 26) | 0; + hncarry += ncarry >>> 26; + ncarry &= 0x3ffffff; + } + + out.words[k] = rword; + carry = ncarry; + ncarry = hncarry; + } + + if (carry !== 0) { + out.words[k] = carry; + } else { + out.length--; + } + + return out.strip(); + } + + function jumboMulTo(self, num, out) { + var fftm = new FFTM(); + return fftm.mulp(self, num, out); + } + + BN.prototype.mulTo = function mulTo(num, out) { + var res; + var len = this.length + num.length; + + if (this.length === 10 && num.length === 10) { + res = comb10MulTo(this, num, out); + } else if (len < 63) { + res = smallMulTo(this, num, out); + } else if (len < 1024) { + res = bigMulTo(this, num, out); + } else { + res = jumboMulTo(this, num, out); + } + + return res; + }; // Cooley-Tukey algorithm for FFT + // slightly revisited to rely on looping instead of recursion + + + function FFTM(x, y) { + this.x = x; + this.y = y; + } + + FFTM.prototype.makeRBT = function makeRBT(N) { + var t = new Array(N); + var l = BN.prototype._countBits(N) - 1; + + for (var i = 0; i < N; i++) { + t[i] = this.revBin(i, l, N); + } + + return t; + }; // Returns binary-reversed representation of `x` + + + FFTM.prototype.revBin = function revBin(x, l, N) { + if (x === 0 || x === N - 1) return x; + var rb = 0; + + for (var i = 0; i < l; i++) { + rb |= (x & 1) << l - i - 1; + x >>= 1; + } + + return rb; + }; // Performs "tweedling" phase, therefore 'emulating' + // behaviour of the recursive algorithm + + + FFTM.prototype.permute = function permute(rbt, rws, iws, rtws, itws, N) { + for (var i = 0; i < N; i++) { + rtws[i] = rws[rbt[i]]; + itws[i] = iws[rbt[i]]; + } + }; + + FFTM.prototype.transform = function transform(rws, iws, rtws, itws, N, rbt) { + this.permute(rbt, rws, iws, rtws, itws, N); + + for (var s = 1; s < N; s <<= 1) { + var l = s << 1; + var rtwdf = Math.cos(2 * Math.PI / l); + var itwdf = Math.sin(2 * Math.PI / l); + + for (var p = 0; p < N; p += l) { + var rtwdf_ = rtwdf; + var itwdf_ = itwdf; + + for (var j = 0; j < s; j++) { + var re = rtws[p + j]; + var ie = itws[p + j]; + var ro = rtws[p + j + s]; + var io = itws[p + j + s]; + var rx = rtwdf_ * ro - itwdf_ * io; + io = rtwdf_ * io + itwdf_ * ro; + ro = rx; + rtws[p + j] = re + ro; + itws[p + j] = ie + io; + rtws[p + j + s] = re - ro; + itws[p + j + s] = ie - io; + /* jshint maxdepth : false */ + + if (j !== l) { + rx = rtwdf * rtwdf_ - itwdf * itwdf_; + itwdf_ = rtwdf * itwdf_ + itwdf * rtwdf_; + rtwdf_ = rx; + } + } + } + } + }; + + FFTM.prototype.guessLen13b = function guessLen13b(n, m) { + var N = Math.max(m, n) | 1; + var odd = N & 1; + var i = 0; + + for (N = N / 2 | 0; N; N = N >>> 1) { + i++; + } + + return 1 << i + 1 + odd; + }; + + FFTM.prototype.conjugate = function conjugate(rws, iws, N) { + if (N <= 1) return; + + for (var i = 0; i < N / 2; i++) { + var t = rws[i]; + rws[i] = rws[N - i - 1]; + rws[N - i - 1] = t; + t = iws[i]; + iws[i] = -iws[N - i - 1]; + iws[N - i - 1] = -t; + } + }; + + FFTM.prototype.normalize13b = function normalize13b(ws, N) { + var carry = 0; + + for (var i = 0; i < N / 2; i++) { + var w = Math.round(ws[2 * i + 1] / N) * 0x2000 + Math.round(ws[2 * i] / N) + carry; + ws[i] = w & 0x3ffffff; + + if (w < 0x4000000) { + carry = 0; + } else { + carry = w / 0x4000000 | 0; + } + } + + return ws; + }; + + FFTM.prototype.convert13b = function convert13b(ws, len, rws, N) { + var carry = 0; + + for (var i = 0; i < len; i++) { + carry = carry + (ws[i] | 0); + rws[2 * i] = carry & 0x1fff; + carry = carry >>> 13; + rws[2 * i + 1] = carry & 0x1fff; + carry = carry >>> 13; + } // Pad with zeroes + + + for (i = 2 * len; i < N; ++i) { + rws[i] = 0; + } + + assert(carry === 0); + assert((carry & ~0x1fff) === 0); + }; + + FFTM.prototype.stub = function stub(N) { + var ph = new Array(N); + + for (var i = 0; i < N; i++) { + ph[i] = 0; + } + + return ph; + }; + + FFTM.prototype.mulp = function mulp(x, y, out) { + var N = 2 * this.guessLen13b(x.length, y.length); + var rbt = this.makeRBT(N); + + var _ = this.stub(N); + + var rws = new Array(N); + var rwst = new Array(N); + var iwst = new Array(N); + var nrws = new Array(N); + var nrwst = new Array(N); + var niwst = new Array(N); + var rmws = out.words; + rmws.length = N; + this.convert13b(x.words, x.length, rws, N); + this.convert13b(y.words, y.length, nrws, N); + this.transform(rws, _, rwst, iwst, N, rbt); + this.transform(nrws, _, nrwst, niwst, N, rbt); + + for (var i = 0; i < N; i++) { + var rx = rwst[i] * nrwst[i] - iwst[i] * niwst[i]; + iwst[i] = rwst[i] * niwst[i] + iwst[i] * nrwst[i]; + rwst[i] = rx; + } + + this.conjugate(rwst, iwst, N); + this.transform(rwst, iwst, rmws, _, N, rbt); + this.conjugate(rmws, _, N); + this.normalize13b(rmws, N); + out.negative = x.negative ^ y.negative; + out.length = x.length + y.length; + return out.strip(); + }; // Multiply `this` by `num` + + + BN.prototype.mul = function mul(num) { + var out = new BN(null); + out.words = new Array(this.length + num.length); + return this.mulTo(num, out); + }; // Multiply employing FFT + + + BN.prototype.mulf = function mulf(num) { + var out = new BN(null); + out.words = new Array(this.length + num.length); + return jumboMulTo(this, num, out); + }; // In-place Multiplication + + + BN.prototype.imul = function imul(num) { + return this.clone().mulTo(num, this); + }; + + BN.prototype.imuln = function imuln(num) { + assert(typeof num === 'number'); + assert(num < 0x4000000); // Carry + + var carry = 0; + + for (var i = 0; i < this.length; i++) { + var w = (this.words[i] | 0) * num; + var lo = (w & 0x3ffffff) + (carry & 0x3ffffff); + carry >>= 26; + carry += w / 0x4000000 | 0; // NOTE: lo is 27bit maximum + + carry += lo >>> 26; + this.words[i] = lo & 0x3ffffff; + } + + if (carry !== 0) { + this.words[i] = carry; + this.length++; + } + + return this; + }; + + BN.prototype.muln = function muln(num) { + return this.clone().imuln(num); + }; // `this` * `this` + + + BN.prototype.sqr = function sqr() { + return this.mul(this); + }; // `this` * `this` in-place + + + BN.prototype.isqr = function isqr() { + return this.imul(this.clone()); + }; // Math.pow(`this`, `num`) + + + BN.prototype.pow = function pow(num) { + var w = toBitArray(num); + if (w.length === 0) return new BN(1); // Skip leading zeroes + + var res = this; + + for (var i = 0; i < w.length; i++, res = res.sqr()) { + if (w[i] !== 0) break; + } + + if (++i < w.length) { + for (var q = res.sqr(); i < w.length; i++, q = q.sqr()) { + if (w[i] === 0) continue; + res = res.mul(q); + } + } + + return res; + }; // Shift-left in-place + + + BN.prototype.iushln = function iushln(bits) { + assert(typeof bits === 'number' && bits >= 0); + var r = bits % 26; + var s = (bits - r) / 26; + var carryMask = 0x3ffffff >>> 26 - r << 26 - r; + var i; + + if (r !== 0) { + var carry = 0; + + for (i = 0; i < this.length; i++) { + var newCarry = this.words[i] & carryMask; + var c = (this.words[i] | 0) - newCarry << r; + this.words[i] = c | carry; + carry = newCarry >>> 26 - r; + } + + if (carry) { + this.words[i] = carry; + this.length++; + } + } + + if (s !== 0) { + for (i = this.length - 1; i >= 0; i--) { + this.words[i + s] = this.words[i]; + } + + for (i = 0; i < s; i++) { + this.words[i] = 0; + } + + this.length += s; + } + + return this.strip(); + }; + + BN.prototype.ishln = function ishln(bits) { + // TODO(indutny): implement me + assert(this.negative === 0); + return this.iushln(bits); + }; // Shift-right in-place + // NOTE: `hint` is a lowest bit before trailing zeroes + // NOTE: if `extended` is present - it will be filled with destroyed bits + + + BN.prototype.iushrn = function iushrn(bits, hint, extended) { + assert(typeof bits === 'number' && bits >= 0); + var h; + + if (hint) { + h = (hint - hint % 26) / 26; + } else { + h = 0; + } + + var r = bits % 26; + var s = Math.min((bits - r) / 26, this.length); + var mask = 0x3ffffff ^ 0x3ffffff >>> r << r; + var maskedWords = extended; + h -= s; + h = Math.max(0, h); // Extended mode, copy masked part + + if (maskedWords) { + for (var i = 0; i < s; i++) { + maskedWords.words[i] = this.words[i]; + } + + maskedWords.length = s; + } + + if (s === 0) {// No-op, we should not move anything at all + } else if (this.length > s) { + this.length -= s; + + for (i = 0; i < this.length; i++) { + this.words[i] = this.words[i + s]; + } + } else { + this.words[0] = 0; + this.length = 1; + } + + var carry = 0; + + for (i = this.length - 1; i >= 0 && (carry !== 0 || i >= h); i--) { + var word = this.words[i] | 0; + this.words[i] = carry << 26 - r | word >>> r; + carry = word & mask; + } // Push carried bits as a mask + + + if (maskedWords && carry !== 0) { + maskedWords.words[maskedWords.length++] = carry; + } + + if (this.length === 0) { + this.words[0] = 0; + this.length = 1; + } + + return this.strip(); + }; + + BN.prototype.ishrn = function ishrn(bits, hint, extended) { + // TODO(indutny): implement me + assert(this.negative === 0); + return this.iushrn(bits, hint, extended); + }; // Shift-left + + + BN.prototype.shln = function shln(bits) { + return this.clone().ishln(bits); + }; + + BN.prototype.ushln = function ushln(bits) { + return this.clone().iushln(bits); + }; // Shift-right + + + BN.prototype.shrn = function shrn(bits) { + return this.clone().ishrn(bits); + }; + + BN.prototype.ushrn = function ushrn(bits) { + return this.clone().iushrn(bits); + }; // Test if n bit is set + + + BN.prototype.testn = function testn(bit) { + assert(typeof bit === 'number' && bit >= 0); + var r = bit % 26; + var s = (bit - r) / 26; + var q = 1 << r; // Fast case: bit is much higher than all existing words + + if (this.length <= s) return false; // Check bit and return + + var w = this.words[s]; + return !!(w & q); + }; // Return only lowers bits of number (in-place) + + + BN.prototype.imaskn = function imaskn(bits) { + assert(typeof bits === 'number' && bits >= 0); + var r = bits % 26; + var s = (bits - r) / 26; + assert(this.negative === 0, 'imaskn works only with positive numbers'); + + if (this.length <= s) { + return this; + } + + if (r !== 0) { + s++; + } + + this.length = Math.min(s, this.length); + + if (r !== 0) { + var mask = 0x3ffffff ^ 0x3ffffff >>> r << r; + this.words[this.length - 1] &= mask; + } + + return this.strip(); + }; // Return only lowers bits of number + + + BN.prototype.maskn = function maskn(bits) { + return this.clone().imaskn(bits); + }; // Add plain number `num` to `this` + + + BN.prototype.iaddn = function iaddn(num) { + assert(typeof num === 'number'); + assert(num < 0x4000000); + if (num < 0) return this.isubn(-num); // Possible sign change + + if (this.negative !== 0) { + if (this.length === 1 && (this.words[0] | 0) < num) { + this.words[0] = num - (this.words[0] | 0); + this.negative = 0; + return this; + } + + this.negative = 0; + this.isubn(num); + this.negative = 1; + return this; + } // Add without checks + + + return this._iaddn(num); + }; + + BN.prototype._iaddn = function _iaddn(num) { + this.words[0] += num; // Carry + + for (var i = 0; i < this.length && this.words[i] >= 0x4000000; i++) { + this.words[i] -= 0x4000000; + + if (i === this.length - 1) { + this.words[i + 1] = 1; + } else { + this.words[i + 1]++; + } + } + + this.length = Math.max(this.length, i + 1); + return this; + }; // Subtract plain number `num` from `this` + + + BN.prototype.isubn = function isubn(num) { + assert(typeof num === 'number'); + assert(num < 0x4000000); + if (num < 0) return this.iaddn(-num); + + if (this.negative !== 0) { + this.negative = 0; + this.iaddn(num); + this.negative = 1; + return this; + } + + this.words[0] -= num; + + if (this.length === 1 && this.words[0] < 0) { + this.words[0] = -this.words[0]; + this.negative = 1; + } else { + // Carry + for (var i = 0; i < this.length && this.words[i] < 0; i++) { + this.words[i] += 0x4000000; + this.words[i + 1] -= 1; + } + } + + return this.strip(); + }; + + BN.prototype.addn = function addn(num) { + return this.clone().iaddn(num); + }; + + BN.prototype.subn = function subn(num) { + return this.clone().isubn(num); + }; + + BN.prototype.iabs = function iabs() { + this.negative = 0; + return this; + }; + + BN.prototype.abs = function abs() { + return this.clone().iabs(); + }; + + BN.prototype._ishlnsubmul = function _ishlnsubmul(num, mul, shift) { + var len = num.length + shift; + var i; + + this._expand(len); + + var w; + var carry = 0; + + for (i = 0; i < num.length; i++) { + w = (this.words[i + shift] | 0) + carry; + var right = (num.words[i] | 0) * mul; + w -= right & 0x3ffffff; + carry = (w >> 26) - (right / 0x4000000 | 0); + this.words[i + shift] = w & 0x3ffffff; + } + + for (; i < this.length - shift; i++) { + w = (this.words[i + shift] | 0) + carry; + carry = w >> 26; + this.words[i + shift] = w & 0x3ffffff; + } + + if (carry === 0) return this.strip(); // Subtraction overflow + + assert(carry === -1); + carry = 0; + + for (i = 0; i < this.length; i++) { + w = -(this.words[i] | 0) + carry; + carry = w >> 26; + this.words[i] = w & 0x3ffffff; + } + + this.negative = 1; + return this.strip(); + }; + + BN.prototype._wordDiv = function _wordDiv(num, mode) { + var shift = this.length - num.length; + var a = this.clone(); + var b = num; // Normalize + + var bhi = b.words[b.length - 1] | 0; + + var bhiBits = this._countBits(bhi); + + shift = 26 - bhiBits; + + if (shift !== 0) { + b = b.ushln(shift); + a.iushln(shift); + bhi = b.words[b.length - 1] | 0; + } // Initialize quotient + + + var m = a.length - b.length; + var q; + + if (mode !== 'mod') { + q = new BN(null); + q.length = m + 1; + q.words = new Array(q.length); + + for (var i = 0; i < q.length; i++) { + q.words[i] = 0; + } + } + + var diff = a.clone()._ishlnsubmul(b, 1, m); + + if (diff.negative === 0) { + a = diff; + + if (q) { + q.words[m] = 1; + } + } + + for (var j = m - 1; j >= 0; j--) { + var qj = (a.words[b.length + j] | 0) * 0x4000000 + (a.words[b.length + j - 1] | 0); // NOTE: (qj / bhi) is (0x3ffffff * 0x4000000 + 0x3ffffff) / 0x2000000 max + // (0x7ffffff) + + qj = Math.min(qj / bhi | 0, 0x3ffffff); + + a._ishlnsubmul(b, qj, j); + + while (a.negative !== 0) { + qj--; + a.negative = 0; + + a._ishlnsubmul(b, 1, j); + + if (!a.isZero()) { + a.negative ^= 1; + } + } + + if (q) { + q.words[j] = qj; + } + } + + if (q) { + q.strip(); + } + + a.strip(); // Denormalize + + if (mode !== 'div' && shift !== 0) { + a.iushrn(shift); + } + + return { + div: q || null, + mod: a + }; + }; // NOTE: 1) `mode` can be set to `mod` to request mod only, + // to `div` to request div only, or be absent to + // request both div & mod + // 2) `positive` is true if unsigned mod is requested + + + BN.prototype.divmod = function divmod(num, mode, positive) { + assert(!num.isZero()); + + if (this.isZero()) { + return { + div: new BN(0), + mod: new BN(0) + }; + } + + var div, mod, res; + + if (this.negative !== 0 && num.negative === 0) { + res = this.neg().divmod(num, mode); + + if (mode !== 'mod') { + div = res.div.neg(); + } + + if (mode !== 'div') { + mod = res.mod.neg(); + + if (positive && mod.negative !== 0) { + mod.iadd(num); + } + } + + return { + div: div, + mod: mod + }; + } + + if (this.negative === 0 && num.negative !== 0) { + res = this.divmod(num.neg(), mode); + + if (mode !== 'mod') { + div = res.div.neg(); + } + + return { + div: div, + mod: res.mod + }; + } + + if ((this.negative & num.negative) !== 0) { + res = this.neg().divmod(num.neg(), mode); + + if (mode !== 'div') { + mod = res.mod.neg(); + + if (positive && mod.negative !== 0) { + mod.isub(num); + } + } + + return { + div: res.div, + mod: mod + }; + } // Both numbers are positive at this point + // Strip both numbers to approximate shift value + + + if (num.length > this.length || this.cmp(num) < 0) { + return { + div: new BN(0), + mod: this + }; + } // Very short reduction + + + if (num.length === 1) { + if (mode === 'div') { + return { + div: this.divn(num.words[0]), + mod: null + }; + } + + if (mode === 'mod') { + return { + div: null, + mod: new BN(this.modn(num.words[0])) + }; + } + + return { + div: this.divn(num.words[0]), + mod: new BN(this.modn(num.words[0])) + }; + } + + return this._wordDiv(num, mode); + }; // Find `this` / `num` + + + BN.prototype.div = function div(num) { + return this.divmod(num, 'div', false).div; + }; // Find `this` % `num` + + + BN.prototype.mod = function mod(num) { + return this.divmod(num, 'mod', false).mod; + }; + + BN.prototype.umod = function umod(num) { + return this.divmod(num, 'mod', true).mod; + }; // Find Round(`this` / `num`) + + + BN.prototype.divRound = function divRound(num) { + var dm = this.divmod(num); // Fast case - exact division + + if (dm.mod.isZero()) return dm.div; + var mod = dm.div.negative !== 0 ? dm.mod.isub(num) : dm.mod; + var half = num.ushrn(1); + var r2 = num.andln(1); + var cmp = mod.cmp(half); // Round down + + if (cmp < 0 || r2 === 1 && cmp === 0) return dm.div; // Round up + + return dm.div.negative !== 0 ? dm.div.isubn(1) : dm.div.iaddn(1); + }; + + BN.prototype.modn = function modn(num) { + assert(num <= 0x3ffffff); + var p = (1 << 26) % num; + var acc = 0; + + for (var i = this.length - 1; i >= 0; i--) { + acc = (p * acc + (this.words[i] | 0)) % num; + } + + return acc; + }; // In-place division by number + + + BN.prototype.idivn = function idivn(num) { + assert(num <= 0x3ffffff); + var carry = 0; + + for (var i = this.length - 1; i >= 0; i--) { + var w = (this.words[i] | 0) + carry * 0x4000000; + this.words[i] = w / num | 0; + carry = w % num; + } + + return this.strip(); + }; + + BN.prototype.divn = function divn(num) { + return this.clone().idivn(num); + }; + + BN.prototype.egcd = function egcd(p) { + assert(p.negative === 0); + assert(!p.isZero()); + var x = this; + var y = p.clone(); + + if (x.negative !== 0) { + x = x.umod(p); + } else { + x = x.clone(); + } // A * x + B * y = x + + + var A = new BN(1); + var B = new BN(0); // C * x + D * y = y + + var C = new BN(0); + var D = new BN(1); + var g = 0; + + while (x.isEven() && y.isEven()) { + x.iushrn(1); + y.iushrn(1); + ++g; + } + + var yp = y.clone(); + var xp = x.clone(); + + while (!x.isZero()) { + for (var i = 0, im = 1; (x.words[0] & im) === 0 && i < 26; ++i, im <<= 1); + + if (i > 0) { + x.iushrn(i); + + while (i-- > 0) { + if (A.isOdd() || B.isOdd()) { + A.iadd(yp); + B.isub(xp); + } + + A.iushrn(1); + B.iushrn(1); + } + } + + for (var j = 0, jm = 1; (y.words[0] & jm) === 0 && j < 26; ++j, jm <<= 1); + + if (j > 0) { + y.iushrn(j); + + while (j-- > 0) { + if (C.isOdd() || D.isOdd()) { + C.iadd(yp); + D.isub(xp); + } + + C.iushrn(1); + D.iushrn(1); + } + } + + if (x.cmp(y) >= 0) { + x.isub(y); + A.isub(C); + B.isub(D); + } else { + y.isub(x); + C.isub(A); + D.isub(B); + } + } + + return { + a: C, + b: D, + gcd: y.iushln(g) + }; + }; // This is reduced incarnation of the binary EEA + // above, designated to invert members of the + // _prime_ fields F(p) at a maximal speed + + + BN.prototype._invmp = function _invmp(p) { + assert(p.negative === 0); + assert(!p.isZero()); + var a = this; + var b = p.clone(); + + if (a.negative !== 0) { + a = a.umod(p); + } else { + a = a.clone(); + } + + var x1 = new BN(1); + var x2 = new BN(0); + var delta = b.clone(); + + while (a.cmpn(1) > 0 && b.cmpn(1) > 0) { + for (var i = 0, im = 1; (a.words[0] & im) === 0 && i < 26; ++i, im <<= 1); + + if (i > 0) { + a.iushrn(i); + + while (i-- > 0) { + if (x1.isOdd()) { + x1.iadd(delta); + } + + x1.iushrn(1); + } + } + + for (var j = 0, jm = 1; (b.words[0] & jm) === 0 && j < 26; ++j, jm <<= 1); + + if (j > 0) { + b.iushrn(j); + + while (j-- > 0) { + if (x2.isOdd()) { + x2.iadd(delta); + } + + x2.iushrn(1); + } + } + + if (a.cmp(b) >= 0) { + a.isub(b); + x1.isub(x2); + } else { + b.isub(a); + x2.isub(x1); + } + } + + var res; + + if (a.cmpn(1) === 0) { + res = x1; + } else { + res = x2; + } + + if (res.cmpn(0) < 0) { + res.iadd(p); + } + + return res; + }; + + BN.prototype.gcd = function gcd(num) { + if (this.isZero()) return num.abs(); + if (num.isZero()) return this.abs(); + var a = this.clone(); + var b = num.clone(); + a.negative = 0; + b.negative = 0; // Remove common factor of two + + for (var shift = 0; a.isEven() && b.isEven(); shift++) { + a.iushrn(1); + b.iushrn(1); + } + + do { + while (a.isEven()) { + a.iushrn(1); + } + + while (b.isEven()) { + b.iushrn(1); + } + + var r = a.cmp(b); + + if (r < 0) { + // Swap `a` and `b` to make `a` always bigger than `b` + var t = a; + a = b; + b = t; + } else if (r === 0 || b.cmpn(1) === 0) { + break; + } + + a.isub(b); + } while (true); + + return b.iushln(shift); + }; // Invert number in the field F(num) + + + BN.prototype.invm = function invm(num) { + return this.egcd(num).a.umod(num); + }; + + BN.prototype.isEven = function isEven() { + return (this.words[0] & 1) === 0; + }; + + BN.prototype.isOdd = function isOdd() { + return (this.words[0] & 1) === 1; + }; // And first word and num + + + BN.prototype.andln = function andln(num) { + return this.words[0] & num; + }; // Increment at the bit position in-line + + + BN.prototype.bincn = function bincn(bit) { + assert(typeof bit === 'number'); + var r = bit % 26; + var s = (bit - r) / 26; + var q = 1 << r; // Fast case: bit is much higher than all existing words + + if (this.length <= s) { + this._expand(s + 1); + + this.words[s] |= q; + return this; + } // Add bit and propagate, if needed + + + var carry = q; + + for (var i = s; carry !== 0 && i < this.length; i++) { + var w = this.words[i] | 0; + w += carry; + carry = w >>> 26; + w &= 0x3ffffff; + this.words[i] = w; + } + + if (carry !== 0) { + this.words[i] = carry; + this.length++; + } + + return this; + }; + + BN.prototype.isZero = function isZero() { + return this.length === 1 && this.words[0] === 0; + }; + + BN.prototype.cmpn = function cmpn(num) { + var negative = num < 0; + if (this.negative !== 0 && !negative) return -1; + if (this.negative === 0 && negative) return 1; + this.strip(); + var res; + + if (this.length > 1) { + res = 1; + } else { + if (negative) { + num = -num; + } + + assert(num <= 0x3ffffff, 'Number is too big'); + var w = this.words[0] | 0; + res = w === num ? 0 : w < num ? -1 : 1; + } + + if (this.negative !== 0) return -res | 0; + return res; + }; // Compare two numbers and return: + // 1 - if `this` > `num` + // 0 - if `this` == `num` + // -1 - if `this` < `num` + + + BN.prototype.cmp = function cmp(num) { + if (this.negative !== 0 && num.negative === 0) return -1; + if (this.negative === 0 && num.negative !== 0) return 1; + var res = this.ucmp(num); + if (this.negative !== 0) return -res | 0; + return res; + }; // Unsigned comparison + + + BN.prototype.ucmp = function ucmp(num) { + // At this point both numbers have the same sign + if (this.length > num.length) return 1; + if (this.length < num.length) return -1; + var res = 0; + + for (var i = this.length - 1; i >= 0; i--) { + var a = this.words[i] | 0; + var b = num.words[i] | 0; + if (a === b) continue; + + if (a < b) { + res = -1; + } else if (a > b) { + res = 1; + } + + break; + } + + return res; + }; + + BN.prototype.gtn = function gtn(num) { + return this.cmpn(num) === 1; + }; + + BN.prototype.gt = function gt(num) { + return this.cmp(num) === 1; + }; + + BN.prototype.gten = function gten(num) { + return this.cmpn(num) >= 0; + }; + + BN.prototype.gte = function gte(num) { + return this.cmp(num) >= 0; + }; + + BN.prototype.ltn = function ltn(num) { + return this.cmpn(num) === -1; + }; + + BN.prototype.lt = function lt(num) { + return this.cmp(num) === -1; + }; + + BN.prototype.lten = function lten(num) { + return this.cmpn(num) <= 0; + }; + + BN.prototype.lte = function lte(num) { + return this.cmp(num) <= 0; + }; + + BN.prototype.eqn = function eqn(num) { + return this.cmpn(num) === 0; + }; + + BN.prototype.eq = function eq(num) { + return this.cmp(num) === 0; + }; // + // A reduce context, could be using montgomery or something better, depending + // on the `m` itself. + // + + + BN.red = function red(num) { + return new Red(num); + }; + + BN.prototype.toRed = function toRed(ctx) { + assert(!this.red, 'Already a number in reduction context'); + assert(this.negative === 0, 'red works only with positives'); + return ctx.convertTo(this)._forceRed(ctx); + }; + + BN.prototype.fromRed = function fromRed() { + assert(this.red, 'fromRed works only with numbers in reduction context'); + return this.red.convertFrom(this); + }; + + BN.prototype._forceRed = function _forceRed(ctx) { + this.red = ctx; + return this; + }; + + BN.prototype.forceRed = function forceRed(ctx) { + assert(!this.red, 'Already a number in reduction context'); + return this._forceRed(ctx); + }; + + BN.prototype.redAdd = function redAdd(num) { + assert(this.red, 'redAdd works only with red numbers'); + return this.red.add(this, num); + }; + + BN.prototype.redIAdd = function redIAdd(num) { + assert(this.red, 'redIAdd works only with red numbers'); + return this.red.iadd(this, num); + }; + + BN.prototype.redSub = function redSub(num) { + assert(this.red, 'redSub works only with red numbers'); + return this.red.sub(this, num); + }; + + BN.prototype.redISub = function redISub(num) { + assert(this.red, 'redISub works only with red numbers'); + return this.red.isub(this, num); + }; + + BN.prototype.redShl = function redShl(num) { + assert(this.red, 'redShl works only with red numbers'); + return this.red.shl(this, num); + }; + + BN.prototype.redMul = function redMul(num) { + assert(this.red, 'redMul works only with red numbers'); + + this.red._verify2(this, num); + + return this.red.mul(this, num); + }; + + BN.prototype.redIMul = function redIMul(num) { + assert(this.red, 'redMul works only with red numbers'); + + this.red._verify2(this, num); + + return this.red.imul(this, num); + }; + + BN.prototype.redSqr = function redSqr() { + assert(this.red, 'redSqr works only with red numbers'); + + this.red._verify1(this); + + return this.red.sqr(this); + }; + + BN.prototype.redISqr = function redISqr() { + assert(this.red, 'redISqr works only with red numbers'); + + this.red._verify1(this); + + return this.red.isqr(this); + }; // Square root over p + + + BN.prototype.redSqrt = function redSqrt() { + assert(this.red, 'redSqrt works only with red numbers'); + + this.red._verify1(this); + + return this.red.sqrt(this); + }; + + BN.prototype.redInvm = function redInvm() { + assert(this.red, 'redInvm works only with red numbers'); + + this.red._verify1(this); + + return this.red.invm(this); + }; // Return negative clone of `this` % `red modulo` + + + BN.prototype.redNeg = function redNeg() { + assert(this.red, 'redNeg works only with red numbers'); + + this.red._verify1(this); + + return this.red.neg(this); + }; + + BN.prototype.redPow = function redPow(num) { + assert(this.red && !num.red, 'redPow(normalNum)'); + + this.red._verify1(this); + + return this.red.pow(this, num); + }; // Prime numbers with efficient reduction + + + var primes = { + k256: null, + p224: null, + p192: null, + p25519: null + }; // Pseudo-Mersenne prime + + function MPrime(name, p) { + // P = 2 ^ N - K + this.name = name; + this.p = new BN(p, 16); + this.n = this.p.bitLength(); + this.k = new BN(1).iushln(this.n).isub(this.p); + this.tmp = this._tmp(); + } + + MPrime.prototype._tmp = function _tmp() { + var tmp = new BN(null); + tmp.words = new Array(Math.ceil(this.n / 13)); + return tmp; + }; + + MPrime.prototype.ireduce = function ireduce(num) { + // Assumes that `num` is less than `P^2` + // num = HI * (2 ^ N - K) + HI * K + LO = HI * K + LO (mod P) + var r = num; + var rlen; + + do { + this.split(r, this.tmp); + r = this.imulK(r); + r = r.iadd(this.tmp); + rlen = r.bitLength(); + } while (rlen > this.n); + + var cmp = rlen < this.n ? -1 : r.ucmp(this.p); + + if (cmp === 0) { + r.words[0] = 0; + r.length = 1; + } else if (cmp > 0) { + r.isub(this.p); + } else { + r.strip(); + } + + return r; + }; + + MPrime.prototype.split = function split(input, out) { + input.iushrn(this.n, 0, out); + }; + + MPrime.prototype.imulK = function imulK(num) { + return num.imul(this.k); + }; + + function K256() { + MPrime.call(this, 'k256', 'ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffe fffffc2f'); + } + + inherits(K256, MPrime); + + K256.prototype.split = function split(input, output) { + // 256 = 9 * 26 + 22 + var mask = 0x3fffff; + var outLen = Math.min(input.length, 9); + + for (var i = 0; i < outLen; i++) { + output.words[i] = input.words[i]; + } + + output.length = outLen; + + if (input.length <= 9) { + input.words[0] = 0; + input.length = 1; + return; + } // Shift by 9 limbs + + + var prev = input.words[9]; + output.words[output.length++] = prev & mask; + + for (i = 10; i < input.length; i++) { + var next = input.words[i] | 0; + input.words[i - 10] = (next & mask) << 4 | prev >>> 22; + prev = next; + } + + prev >>>= 22; + input.words[i - 10] = prev; + + if (prev === 0 && input.length > 10) { + input.length -= 10; + } else { + input.length -= 9; + } + }; + + K256.prototype.imulK = function imulK(num) { + // K = 0x1000003d1 = [ 0x40, 0x3d1 ] + num.words[num.length] = 0; + num.words[num.length + 1] = 0; + num.length += 2; // bounded at: 0x40 * 0x3ffffff + 0x3d0 = 0x100000390 + + var lo = 0; + + for (var i = 0; i < num.length; i++) { + var w = num.words[i] | 0; + lo += w * 0x3d1; + num.words[i] = lo & 0x3ffffff; + lo = w * 0x40 + (lo / 0x4000000 | 0); + } // Fast length reduction + + + if (num.words[num.length - 1] === 0) { + num.length--; + + if (num.words[num.length - 1] === 0) { + num.length--; + } + } + + return num; + }; + + function P224() { + MPrime.call(this, 'p224', 'ffffffff ffffffff ffffffff ffffffff 00000000 00000000 00000001'); + } + + inherits(P224, MPrime); + + function P192() { + MPrime.call(this, 'p192', 'ffffffff ffffffff ffffffff fffffffe ffffffff ffffffff'); + } + + inherits(P192, MPrime); + + function P25519() { + // 2 ^ 255 - 19 + MPrime.call(this, '25519', '7fffffffffffffff ffffffffffffffff ffffffffffffffff ffffffffffffffed'); + } + + inherits(P25519, MPrime); + + P25519.prototype.imulK = function imulK(num) { + // K = 0x13 + var carry = 0; + + for (var i = 0; i < num.length; i++) { + var hi = (num.words[i] | 0) * 0x13 + carry; + var lo = hi & 0x3ffffff; + hi >>>= 26; + num.words[i] = lo; + carry = hi; + } + + if (carry !== 0) { + num.words[num.length++] = carry; + } + + return num; + }; // Exported mostly for testing purposes, use plain name instead + + + BN._prime = function prime(name) { + // Cached version of prime + if (primes[name]) return primes[name]; + var prime; + + if (name === 'k256') { + prime = new K256(); + } else if (name === 'p224') { + prime = new P224(); + } else if (name === 'p192') { + prime = new P192(); + } else if (name === 'p25519') { + prime = new P25519(); + } else { + throw new Error('Unknown prime ' + name); + } + + primes[name] = prime; + return prime; + }; // + // Base reduction engine + // + + + function Red(m) { + if (typeof m === 'string') { + var prime = BN._prime(m); + + this.m = prime.p; + this.prime = prime; + } else { + assert(m.gtn(1), 'modulus must be greater than 1'); + this.m = m; + this.prime = null; + } + } + + Red.prototype._verify1 = function _verify1(a) { + assert(a.negative === 0, 'red works only with positives'); + assert(a.red, 'red works only with red numbers'); + }; + + Red.prototype._verify2 = function _verify2(a, b) { + assert((a.negative | b.negative) === 0, 'red works only with positives'); + assert(a.red && a.red === b.red, 'red works only with red numbers'); + }; + + Red.prototype.imod = function imod(a) { + if (this.prime) return this.prime.ireduce(a)._forceRed(this); + return a.umod(this.m)._forceRed(this); + }; + + Red.prototype.neg = function neg(a) { + if (a.isZero()) { + return a.clone(); + } + + return this.m.sub(a)._forceRed(this); + }; + + Red.prototype.add = function add(a, b) { + this._verify2(a, b); + + var res = a.add(b); + + if (res.cmp(this.m) >= 0) { + res.isub(this.m); + } + + return res._forceRed(this); + }; + + Red.prototype.iadd = function iadd(a, b) { + this._verify2(a, b); + + var res = a.iadd(b); + + if (res.cmp(this.m) >= 0) { + res.isub(this.m); + } + + return res; + }; + + Red.prototype.sub = function sub(a, b) { + this._verify2(a, b); + + var res = a.sub(b); + + if (res.cmpn(0) < 0) { + res.iadd(this.m); + } + + return res._forceRed(this); + }; + + Red.prototype.isub = function isub(a, b) { + this._verify2(a, b); + + var res = a.isub(b); + + if (res.cmpn(0) < 0) { + res.iadd(this.m); + } + + return res; + }; + + Red.prototype.shl = function shl(a, num) { + this._verify1(a); + + return this.imod(a.ushln(num)); + }; + + Red.prototype.imul = function imul(a, b) { + this._verify2(a, b); + + return this.imod(a.imul(b)); + }; + + Red.prototype.mul = function mul(a, b) { + this._verify2(a, b); + + return this.imod(a.mul(b)); + }; + + Red.prototype.isqr = function isqr(a) { + return this.imul(a, a.clone()); + }; + + Red.prototype.sqr = function sqr(a) { + return this.mul(a, a); + }; + + Red.prototype.sqrt = function sqrt(a) { + if (a.isZero()) return a.clone(); + var mod3 = this.m.andln(3); + assert(mod3 % 2 === 1); // Fast case + + if (mod3 === 3) { + var pow = this.m.add(new BN(1)).iushrn(2); + return this.pow(a, pow); + } // Tonelli-Shanks algorithm (Totally unoptimized and slow) + // + // Find Q and S, that Q * 2 ^ S = (P - 1) + + + var q = this.m.subn(1); + var s = 0; + + while (!q.isZero() && q.andln(1) === 0) { + s++; + q.iushrn(1); + } + + assert(!q.isZero()); + var one = new BN(1).toRed(this); + var nOne = one.redNeg(); // Find quadratic non-residue + // NOTE: Max is such because of generalized Riemann hypothesis. + + var lpow = this.m.subn(1).iushrn(1); + var z = this.m.bitLength(); + z = new BN(2 * z * z).toRed(this); + + while (this.pow(z, lpow).cmp(nOne) !== 0) { + z.redIAdd(nOne); + } + + var c = this.pow(z, q); + var r = this.pow(a, q.addn(1).iushrn(1)); + var t = this.pow(a, q); + var m = s; + + while (t.cmp(one) !== 0) { + var tmp = t; + + for (var i = 0; tmp.cmp(one) !== 0; i++) { + tmp = tmp.redSqr(); + } + + assert(i < m); + var b = this.pow(c, new BN(1).iushln(m - i - 1)); + r = r.redMul(b); + c = b.redSqr(); + t = t.redMul(c); + m = i; + } + + return r; + }; + + Red.prototype.invm = function invm(a) { + var inv = a._invmp(this.m); + + if (inv.negative !== 0) { + inv.negative = 0; + return this.imod(inv).redNeg(); + } else { + return this.imod(inv); + } + }; + + Red.prototype.pow = function pow(a, num) { + if (num.isZero()) return new BN(1).toRed(this); + if (num.cmpn(1) === 0) return a.clone(); + var windowSize = 4; + var wnd = new Array(1 << windowSize); + wnd[0] = new BN(1).toRed(this); + wnd[1] = a; + + for (var i = 2; i < wnd.length; i++) { + wnd[i] = this.mul(wnd[i - 1], a); + } + + var res = wnd[0]; + var current = 0; + var currentLen = 0; + var start = num.bitLength() % 26; + + if (start === 0) { + start = 26; + } + + for (i = num.length - 1; i >= 0; i--) { + var word = num.words[i]; + + for (var j = start - 1; j >= 0; j--) { + var bit = word >> j & 1; + + if (res !== wnd[0]) { + res = this.sqr(res); + } + + if (bit === 0 && current === 0) { + currentLen = 0; + continue; + } + + current <<= 1; + current |= bit; + currentLen++; + if (currentLen !== windowSize && (i !== 0 || j !== 0)) continue; + res = this.mul(res, wnd[current]); + currentLen = 0; + current = 0; + } + + start = 26; + } + + return res; + }; + + Red.prototype.convertTo = function convertTo(num) { + var r = num.umod(this.m); + return r === num ? r.clone() : r; + }; + + Red.prototype.convertFrom = function convertFrom(num) { + var res = num.clone(); + res.red = null; + return res; + }; // + // Montgomery method engine + // + + + BN.mont = function mont(num) { + return new Mont(num); + }; + + function Mont(m) { + Red.call(this, m); + this.shift = this.m.bitLength(); + + if (this.shift % 26 !== 0) { + this.shift += 26 - this.shift % 26; + } + + this.r = new BN(1).iushln(this.shift); + this.r2 = this.imod(this.r.sqr()); + this.rinv = this.r._invmp(this.m); + this.minv = this.rinv.mul(this.r).isubn(1).div(this.m); + this.minv = this.minv.umod(this.r); + this.minv = this.r.sub(this.minv); + } + + inherits(Mont, Red); + + Mont.prototype.convertTo = function convertTo(num) { + return this.imod(num.ushln(this.shift)); + }; + + Mont.prototype.convertFrom = function convertFrom(num) { + var r = this.imod(num.mul(this.rinv)); + r.red = null; + return r; + }; + + Mont.prototype.imul = function imul(a, b) { + if (a.isZero() || b.isZero()) { + a.words[0] = 0; + a.length = 1; + return a; + } + + var t = a.imul(b); + var c = t.maskn(this.shift).mul(this.minv).imaskn(this.shift).mul(this.m); + var u = t.isub(c).iushrn(this.shift); + var res = u; + + if (u.cmp(this.m) >= 0) { + res = u.isub(this.m); + } else if (u.cmpn(0) < 0) { + res = u.iadd(this.m); + } + + return res._forceRed(this); + }; + + Mont.prototype.mul = function mul(a, b) { + if (a.isZero() || b.isZero()) return new BN(0)._forceRed(this); + var t = a.mul(b); + var c = t.maskn(this.shift).mul(this.minv).imaskn(this.shift).mul(this.m); + var u = t.isub(c).iushrn(this.shift); + var res = u; + + if (u.cmp(this.m) >= 0) { + res = u.isub(this.m); + } else if (u.cmpn(0) < 0) { + res = u.iadd(this.m); + } + + return res._forceRed(this); + }; + + Mont.prototype.invm = function invm(a) { + // (AR)^-1 * R^2 = (A^-1 * R^-1) * R^2 = A^-1 * R + var res = this.imod(a._invmp(this.m).mul(this.r2)); + return res._forceRed(this); + }; +})(typeof module === 'undefined' || module, this); \ No newline at end of file diff --git a/app/components/blufi/crypto/lib/brorand.js b/app/components/blufi/crypto/lib/brorand.js new file mode 100644 index 0000000..adcf410 --- /dev/null +++ b/app/components/blufi/crypto/lib/brorand.js @@ -0,0 +1,53 @@ +var r; + +module.exports = function rand(len) { + if (!r) r = new Rand(null); + return r.generate(len); +}; + +function Rand(rand) { + this.rand = rand; +} + +module.exports.Rand = Rand; + +Rand.prototype.generate = function generate(len) { + return this._rand(len); +}; // Emulate crypto API using randy + + +Rand.prototype._rand = function _rand(n) { + console.log(this); + if (this.rand.getBytes) return this.rand.getBytes(n); + var res = new Uint8Array(n); + + for (var i = 0; i < res.length; i++) res[i] = this.rand.getByte(); + + return res; +}; + +if (typeof self === 'object') { + Rand.prototype._rand = function _rand(n) { + var list = []; + + for (var i = 0; i < n; i++) { + list.push(Math.ceil(Math.random() * 255)); + } + + var arr = new Uint8Array(list); + return arr; + }; +} else { + // Node.js or Web worker with no crypto support + try { + // var crypto = require("./crypto.js"); + var crypto = 0; + + if (typeof crypto.randomBytes !== 'function') throw new Error('Not supported'); + + Rand.prototype._rand = function _rand(n) { + // return crypto.randomBytes(n); + return crypto; + }; + } catch (e) {} +} \ No newline at end of file diff --git a/app/components/blufi/crypto/lib/buffer.js b/app/components/blufi/crypto/lib/buffer.js new file mode 100644 index 0000000..314824b --- /dev/null +++ b/app/components/blufi/crypto/lib/buffer.js @@ -0,0 +1,1799 @@ +/*! + * The buffer module from node.js, for the browser. + * + * @author Feross Aboukhadijeh + * @license MIT + */ + +/* eslint-disable no-proto */ +'use strict'; + +var base64 = require("./base64-js.js"); + +var ieee754 = require("./ieee754.js"); + +exports.Buffer = Buffer; +exports.SlowBuffer = SlowBuffer; +exports.INSPECT_MAX_BYTES = 50; +var K_MAX_LENGTH = 0x7fffffff; +exports.kMaxLength = K_MAX_LENGTH; +/** + * If `Buffer.TYPED_ARRAY_SUPPORT`: + * === true Use Uint8Array implementation (fastest) + * === false Print warning and recommend using `buffer` v4.x which has an Object + * implementation (most compatible, even IE6) + * + * Browsers that support typed arrays are IE 10+, Firefox 4+, Chrome 7+, Safari 5.1+, + * Opera 11.6+, iOS 4.2+. + * + * We report that the browser does not support typed arrays if the are not subclassable + * using __proto__. Firefox 4-29 lacks support for adding new properties to `Uint8Array` + * (See: https://bugzilla.mozilla.org/show_bug.cgi?id=695438). IE 10 lacks support + * for __proto__ and has a buggy typed array implementation. + */ + +Buffer.TYPED_ARRAY_SUPPORT = typedArraySupport(); + +if (!Buffer.TYPED_ARRAY_SUPPORT && typeof console !== 'undefined' && typeof console.error === 'function') { + console.error('This browser lacks typed array (Uint8Array) support which is required by ' + '`buffer` v5.x. Use `buffer` v4.x if you require old browser support.'); +} + +function typedArraySupport() { + // Can typed array instances can be augmented? + try { + var arr = new Uint8Array(1); + arr.__proto__ = { + __proto__: Uint8Array.prototype, + foo: function () { + return 42; + } + }; + return arr.foo() === 42; + } catch (e) { + return false; + } +} + +Object.defineProperty(Buffer.prototype, 'parent', { + enumerable: true, + get: function () { + if (!Buffer.isBuffer(this)) return undefined; + return this.buffer; + } +}); +Object.defineProperty(Buffer.prototype, 'offset', { + enumerable: true, + get: function () { + if (!Buffer.isBuffer(this)) return undefined; + return this.byteOffset; + } +}); + +function createBuffer(length) { + if (length > K_MAX_LENGTH) { + throw new RangeError('The value "' + length + '" is invalid for option "size"'); + } // Return an augmented `Uint8Array` instance + + + var buf = new Uint8Array(length); + buf.__proto__ = Buffer.prototype; + return buf; +} +/** + * The Buffer constructor returns instances of `Uint8Array` that have their + * prototype changed to `Buffer.prototype`. Furthermore, `Buffer` is a subclass of + * `Uint8Array`, so the returned instances will have all the node `Buffer` methods + * and the `Uint8Array` methods. Square bracket notation works as expected -- it + * returns a single octet. + * + * The `Uint8Array` prototype remains unmodified. + */ + + +function Buffer(arg, encodingOrOffset, length) { + // Common case. + if (typeof arg === 'number') { + if (typeof encodingOrOffset === 'string') { + throw new TypeError('The "string" argument must be of type string. Received type number'); + } + + return allocUnsafe(arg); + } + + return from(arg, encodingOrOffset, length); +} // Fix subarray() in ES2016. See: https://github.com/feross/buffer/pull/97 + + +if (typeof Symbol !== 'undefined' && Symbol.species != null && Buffer[Symbol.species] === Buffer) { + Object.defineProperty(Buffer, Symbol.species, { + value: null, + configurable: true, + enumerable: false, + writable: false + }); +} + +Buffer.poolSize = 8192; // not used by this implementation + +function from(value, encodingOrOffset, length) { + if (typeof value === 'string') { + return fromString(value, encodingOrOffset); + } + + if (ArrayBuffer.isView(value)) { + return fromArrayLike(value); + } + + if (value == null) { + throw TypeError('The first argument must be one of type string, Buffer, ArrayBuffer, Array, ' + 'or Array-like Object. Received type ' + typeof value); + } + + if (isInstance(value, ArrayBuffer) || value && isInstance(value.buffer, ArrayBuffer)) { + return fromArrayBuffer(value, encodingOrOffset, length); + } + + if (typeof value === 'number') { + throw new TypeError('The "value" argument must not be of type number. Received type number'); + } + + var valueOf = value.valueOf && value.valueOf(); + + if (valueOf != null && valueOf !== value) { + return Buffer.from(valueOf, encodingOrOffset, length); + } + + var b = fromObject(value); + if (b) return b; + + if (typeof Symbol !== 'undefined' && Symbol.toPrimitive != null && typeof value[Symbol.toPrimitive] === 'function') { + return Buffer.from(value[Symbol.toPrimitive]('string'), encodingOrOffset, length); + } + + throw new TypeError('The first argument must be one of type string, Buffer, ArrayBuffer, Array, ' + 'or Array-like Object. Received type ' + typeof value); +} +/** + * Functionally equivalent to Buffer(arg, encoding) but throws a TypeError + * if value is a number. + * Buffer.from(str[, encoding]) + * Buffer.from(array) + * Buffer.from(buffer) + * Buffer.from(arrayBuffer[, byteOffset[, length]]) + **/ + + +Buffer.from = function (value, encodingOrOffset, length) { + return from(value, encodingOrOffset, length); +}; // Note: Change prototype *after* Buffer.from is defined to workaround Chrome bug: +// https://github.com/feross/buffer/pull/148 + + +Buffer.prototype.__proto__ = Uint8Array.prototype; +Buffer.__proto__ = Uint8Array; + +function assertSize(size) { + if (typeof size !== 'number') { + throw new TypeError('"size" argument must be of type number'); + } else if (size < 0) { + throw new RangeError('The value "' + size + '" is invalid for option "size"'); + } +} + +function alloc(size, fill, encoding) { + assertSize(size); + + if (size <= 0) { + return createBuffer(size); + } + + if (fill !== undefined) { + // Only pay attention to encoding if it's a string. This + // prevents accidentally sending in a number that would + // be interpretted as a start offset. + return typeof encoding === 'string' ? createBuffer(size).fill(fill, encoding) : createBuffer(size).fill(fill); + } + + return createBuffer(size); +} +/** + * Creates a new filled Buffer instance. + * alloc(size[, fill[, encoding]]) + **/ + + +Buffer.alloc = function (size, fill, encoding) { + return alloc(size, fill, encoding); +}; + +function allocUnsafe(size) { + assertSize(size); + return createBuffer(size < 0 ? 0 : checked(size) | 0); +} +/** + * Equivalent to Buffer(num), by default creates a non-zero-filled Buffer instance. + * */ + + +Buffer.allocUnsafe = function (size) { + return allocUnsafe(size); +}; +/** + * Equivalent to SlowBuffer(num), by default creates a non-zero-filled Buffer instance. + */ + + +Buffer.allocUnsafeSlow = function (size) { + return allocUnsafe(size); +}; + +function fromString(string, encoding) { + if (typeof encoding !== 'string' || encoding === '') { + encoding = 'utf8'; + } + + if (!Buffer.isEncoding(encoding)) { + throw new TypeError('Unknown encoding: ' + encoding); + } + + var length = byteLength(string, encoding) | 0; + var buf = createBuffer(length); + var actual = buf.write(string, encoding); + + if (actual !== length) { + // Writing a hex string, for example, that contains invalid characters will + // cause everything after the first invalid character to be ignored. (e.g. + // 'abxxcd' will be treated as 'ab') + buf = buf.slice(0, actual); + } + + return buf; +} + +function fromArrayLike(array) { + var length = array.length < 0 ? 0 : checked(array.length) | 0; + var buf = createBuffer(length); + + for (var i = 0; i < length; i += 1) { + buf[i] = array[i] & 255; + } + + return buf; +} + +function fromArrayBuffer(array, byteOffset, length) { + if (byteOffset < 0 || array.byteLength < byteOffset) { + throw new RangeError('"offset" is outside of buffer bounds'); + } + + if (array.byteLength < byteOffset + (length || 0)) { + throw new RangeError('"length" is outside of buffer bounds'); + } + + var buf; + + if (byteOffset === undefined && length === undefined) { + buf = new Uint8Array(array); + } else if (length === undefined) { + buf = new Uint8Array(array, byteOffset); + } else { + buf = new Uint8Array(array, byteOffset, length); + } // Return an augmented `Uint8Array` instance + + + buf.__proto__ = Buffer.prototype; + return buf; +} + +function fromObject(obj) { + if (Buffer.isBuffer(obj)) { + var len = checked(obj.length) | 0; + var buf = createBuffer(len); + + if (buf.length === 0) { + return buf; + } + + obj.copy(buf, 0, 0, len); + return buf; + } + + if (obj.length !== undefined) { + if (typeof obj.length !== 'number' || numberIsNaN(obj.length)) { + return createBuffer(0); + } + + return fromArrayLike(obj); + } + + if (obj.type === 'Buffer' && Array.isArray(obj.data)) { + return fromArrayLike(obj.data); + } +} + +function checked(length) { + // Note: cannot use `length < K_MAX_LENGTH` here because that fails when + // length is NaN (which is otherwise coerced to zero.) + if (length >= K_MAX_LENGTH) { + throw new RangeError('Attempt to allocate Buffer larger than maximum ' + 'size: 0x' + K_MAX_LENGTH.toString(16) + ' bytes'); + } + + return length | 0; +} + +function SlowBuffer(length) { + if (+length != length) { + // eslint-disable-line eqeqeq + length = 0; + } + + return Buffer.alloc(+length); +} + +Buffer.isBuffer = function isBuffer(b) { + return b != null && b._isBuffer === true && b !== Buffer.prototype; // so Buffer.isBuffer(Buffer.prototype) will be false +}; + +Buffer.compare = function compare(a, b) { + if (isInstance(a, Uint8Array)) a = Buffer.from(a, a.offset, a.byteLength); + if (isInstance(b, Uint8Array)) b = Buffer.from(b, b.offset, b.byteLength); + + if (!Buffer.isBuffer(a) || !Buffer.isBuffer(b)) { + throw new TypeError('The "buf1", "buf2" arguments must be one of type Buffer or Uint8Array'); + } + + if (a === b) return 0; + var x = a.length; + var y = b.length; + + for (var i = 0, len = Math.min(x, y); i < len; ++i) { + if (a[i] !== b[i]) { + x = a[i]; + y = b[i]; + break; + } + } + + if (x < y) return -1; + if (y < x) return 1; + return 0; +}; + +Buffer.isEncoding = function isEncoding(encoding) { + switch (String(encoding).toLowerCase()) { + case 'hex': + case 'utf8': + case 'utf-8': + case 'ascii': + case 'latin1': + case 'binary': + case 'base64': + case 'ucs2': + case 'ucs-2': + case 'utf16le': + case 'utf-16le': + return true; + + default: + return false; + } +}; + +Buffer.concat = function concat(list, length) { + if (!Array.isArray(list)) { + throw new TypeError('"list" argument must be an Array of Buffers'); + } + + if (list.length === 0) { + return Buffer.alloc(0); + } + + var i; + + if (length === undefined) { + length = 0; + + for (i = 0; i < list.length; ++i) { + length += list[i].length; + } + } + + var buffer = Buffer.allocUnsafe(length); + var pos = 0; + + for (i = 0; i < list.length; ++i) { + var buf = list[i]; + + if (isInstance(buf, Uint8Array)) { + buf = Buffer.from(buf); + } + + if (!Buffer.isBuffer(buf)) { + throw new TypeError('"list" argument must be an Array of Buffers'); + } + + buf.copy(buffer, pos); + pos += buf.length; + } + + return buffer; +}; + +function byteLength(string, encoding) { + if (Buffer.isBuffer(string)) { + return string.length; + } + + if (ArrayBuffer.isView(string) || isInstance(string, ArrayBuffer)) { + return string.byteLength; + } + + if (typeof string !== 'string') { + throw new TypeError('The "string" argument must be one of type string, Buffer, or ArrayBuffer. ' + 'Received type ' + typeof string); + } + + var len = string.length; + var mustMatch = arguments.length > 2 && arguments[2] === true; + if (!mustMatch && len === 0) return 0; // Use a for loop to avoid recursion + + var loweredCase = false; + + for (;;) { + switch (encoding) { + case 'ascii': + case 'latin1': + case 'binary': + return len; + + case 'utf8': + case 'utf-8': + return utf8ToBytes(string).length; + + case 'ucs2': + case 'ucs-2': + case 'utf16le': + case 'utf-16le': + return len * 2; + + case 'hex': + return len >>> 1; + + case 'base64': + return base64ToBytes(string).length; + + default: + if (loweredCase) { + return mustMatch ? -1 : utf8ToBytes(string).length; // assume utf8 + } + + encoding = ('' + encoding).toLowerCase(); + loweredCase = true; + } + } +} + +Buffer.byteLength = byteLength; + +function slowToString(encoding, start, end) { + var loweredCase = false; // No need to verify that "this.length <= MAX_UINT32" since it's a read-only + // property of a typed array. + // This behaves neither like String nor Uint8Array in that we set start/end + // to their upper/lower bounds if the value passed is out of range. + // undefined is handled specially as per ECMA-262 6th Edition, + // Section 13.3.3.7 Runtime Semantics: KeyedBindingInitialization. + + if (start === undefined || start < 0) { + start = 0; + } // Return early if start > this.length. Done here to prevent potential uint32 + // coercion fail below. + + + if (start > this.length) { + return ''; + } + + if (end === undefined || end > this.length) { + end = this.length; + } + + if (end <= 0) { + return ''; + } // Force coersion to uint32. This will also coerce falsey/NaN values to 0. + + + end >>>= 0; + start >>>= 0; + + if (end <= start) { + return ''; + } + + if (!encoding) encoding = 'utf8'; + + while (true) { + switch (encoding) { + case 'hex': + return hexSlice(this, start, end); + + case 'utf8': + case 'utf-8': + return utf8Slice(this, start, end); + + case 'ascii': + return asciiSlice(this, start, end); + + case 'latin1': + case 'binary': + return latin1Slice(this, start, end); + + case 'base64': + return base64Slice(this, start, end); + + case 'ucs2': + case 'ucs-2': + case 'utf16le': + case 'utf-16le': + return utf16leSlice(this, start, end); + + default: + if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding); + encoding = (encoding + '').toLowerCase(); + loweredCase = true; + } + } +} // This property is used by `Buffer.isBuffer` (and the `is-buffer` npm package) +// to detect a Buffer instance. It's not possible to use `instanceof Buffer` +// reliably in a browserify context because there could be multiple different +// copies of the 'buffer' package in use. This method works even for Buffer +// instances that were created from another copy of the `buffer` package. +// See: https://github.com/feross/buffer/issues/154 + + +Buffer.prototype._isBuffer = true; + +function swap(b, n, m) { + var i = b[n]; + b[n] = b[m]; + b[m] = i; +} + +Buffer.prototype.swap16 = function swap16() { + var len = this.length; + + if (len % 2 !== 0) { + throw new RangeError('Buffer size must be a multiple of 16-bits'); + } + + for (var i = 0; i < len; i += 2) { + swap(this, i, i + 1); + } + + return this; +}; + +Buffer.prototype.swap32 = function swap32() { + var len = this.length; + + if (len % 4 !== 0) { + throw new RangeError('Buffer size must be a multiple of 32-bits'); + } + + for (var i = 0; i < len; i += 4) { + swap(this, i, i + 3); + swap(this, i + 1, i + 2); + } + + return this; +}; + +Buffer.prototype.swap64 = function swap64() { + var len = this.length; + + if (len % 8 !== 0) { + throw new RangeError('Buffer size must be a multiple of 64-bits'); + } + + for (var i = 0; i < len; i += 8) { + swap(this, i, i + 7); + swap(this, i + 1, i + 6); + swap(this, i + 2, i + 5); + swap(this, i + 3, i + 4); + } + + return this; +}; + +Buffer.prototype.toString = function toString() { + var length = this.length; + if (length === 0) return ''; + if (arguments.length === 0) return utf8Slice(this, 0, length); + return slowToString.apply(this, arguments); +}; + +Buffer.prototype.toLocaleString = Buffer.prototype.toString; + +Buffer.prototype.equals = function equals(b) { + if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer'); + if (this === b) return true; + return Buffer.compare(this, b) === 0; +}; + +Buffer.prototype.inspect = function inspect() { + var str = ''; + var max = exports.INSPECT_MAX_BYTES; + str = this.toString('hex', 0, max).replace(/(.{2})/g, '$1 ').trim(); + if (this.length > max) str += ' ... '; + return ''; +}; + +Buffer.prototype.compare = function compare(target, start, end, thisStart, thisEnd) { + if (isInstance(target, Uint8Array)) { + target = Buffer.from(target, target.offset, target.byteLength); + } + + if (!Buffer.isBuffer(target)) { + throw new TypeError('The "target" argument must be one of type Buffer or Uint8Array. ' + 'Received type ' + typeof target); + } + + if (start === undefined) { + start = 0; + } + + if (end === undefined) { + end = target ? target.length : 0; + } + + if (thisStart === undefined) { + thisStart = 0; + } + + if (thisEnd === undefined) { + thisEnd = this.length; + } + + if (start < 0 || end > target.length || thisStart < 0 || thisEnd > this.length) { + throw new RangeError('out of range index'); + } + + if (thisStart >= thisEnd && start >= end) { + return 0; + } + + if (thisStart >= thisEnd) { + return -1; + } + + if (start >= end) { + return 1; + } + + start >>>= 0; + end >>>= 0; + thisStart >>>= 0; + thisEnd >>>= 0; + if (this === target) return 0; + var x = thisEnd - thisStart; + var y = end - start; + var len = Math.min(x, y); + var thisCopy = this.slice(thisStart, thisEnd); + var targetCopy = target.slice(start, end); + + for (var i = 0; i < len; ++i) { + if (thisCopy[i] !== targetCopy[i]) { + x = thisCopy[i]; + y = targetCopy[i]; + break; + } + } + + if (x < y) return -1; + if (y < x) return 1; + return 0; +}; // Finds either the first index of `val` in `buffer` at offset >= `byteOffset`, +// OR the last index of `val` in `buffer` at offset <= `byteOffset`. +// +// Arguments: +// - buffer - a Buffer to search +// - val - a string, Buffer, or number +// - byteOffset - an index into `buffer`; will be clamped to an int32 +// - encoding - an optional encoding, relevant is val is a string +// - dir - true for indexOf, false for lastIndexOf + + +function bidirectionalIndexOf(buffer, val, byteOffset, encoding, dir) { + // Empty buffer means no match + if (buffer.length === 0) return -1; // Normalize byteOffset + + if (typeof byteOffset === 'string') { + encoding = byteOffset; + byteOffset = 0; + } else if (byteOffset > 0x7fffffff) { + byteOffset = 0x7fffffff; + } else if (byteOffset < -0x80000000) { + byteOffset = -0x80000000; + } + + byteOffset = +byteOffset; // Coerce to Number. + + if (numberIsNaN(byteOffset)) { + // byteOffset: it it's undefined, null, NaN, "foo", etc, search whole buffer + byteOffset = dir ? 0 : buffer.length - 1; + } // Normalize byteOffset: negative offsets start from the end of the buffer + + + if (byteOffset < 0) byteOffset = buffer.length + byteOffset; + + if (byteOffset >= buffer.length) { + if (dir) return -1;else byteOffset = buffer.length - 1; + } else if (byteOffset < 0) { + if (dir) byteOffset = 0;else return -1; + } // Normalize val + + + if (typeof val === 'string') { + val = Buffer.from(val, encoding); + } // Finally, search either indexOf (if dir is true) or lastIndexOf + + + if (Buffer.isBuffer(val)) { + // Special case: looking for empty string/buffer always fails + if (val.length === 0) { + return -1; + } + + return arrayIndexOf(buffer, val, byteOffset, encoding, dir); + } else if (typeof val === 'number') { + val = val & 0xFF; // Search for a byte value [0-255] + + if (typeof Uint8Array.prototype.indexOf === 'function') { + if (dir) { + return Uint8Array.prototype.indexOf.call(buffer, val, byteOffset); + } else { + return Uint8Array.prototype.lastIndexOf.call(buffer, val, byteOffset); + } + } + + return arrayIndexOf(buffer, [val], byteOffset, encoding, dir); + } + + throw new TypeError('val must be string, number or Buffer'); +} + +function arrayIndexOf(arr, val, byteOffset, encoding, dir) { + var indexSize = 1; + var arrLength = arr.length; + var valLength = val.length; + + if (encoding !== undefined) { + encoding = String(encoding).toLowerCase(); + + if (encoding === 'ucs2' || encoding === 'ucs-2' || encoding === 'utf16le' || encoding === 'utf-16le') { + if (arr.length < 2 || val.length < 2) { + return -1; + } + + indexSize = 2; + arrLength /= 2; + valLength /= 2; + byteOffset /= 2; + } + } + + function read(buf, i) { + if (indexSize === 1) { + return buf[i]; + } else { + return buf.readUInt16BE(i * indexSize); + } + } + + var i; + + if (dir) { + var foundIndex = -1; + + for (i = byteOffset; i < arrLength; i++) { + if (read(arr, i) === read(val, foundIndex === -1 ? 0 : i - foundIndex)) { + if (foundIndex === -1) foundIndex = i; + if (i - foundIndex + 1 === valLength) return foundIndex * indexSize; + } else { + if (foundIndex !== -1) i -= i - foundIndex; + foundIndex = -1; + } + } + } else { + if (byteOffset + valLength > arrLength) byteOffset = arrLength - valLength; + + for (i = byteOffset; i >= 0; i--) { + var found = true; + + for (var j = 0; j < valLength; j++) { + if (read(arr, i + j) !== read(val, j)) { + found = false; + break; + } + } + + if (found) return i; + } + } + + return -1; +} + +Buffer.prototype.includes = function includes(val, byteOffset, encoding) { + return this.indexOf(val, byteOffset, encoding) !== -1; +}; + +Buffer.prototype.indexOf = function indexOf(val, byteOffset, encoding) { + return bidirectionalIndexOf(this, val, byteOffset, encoding, true); +}; + +Buffer.prototype.lastIndexOf = function lastIndexOf(val, byteOffset, encoding) { + return bidirectionalIndexOf(this, val, byteOffset, encoding, false); +}; + +function hexWrite(buf, string, offset, length) { + offset = Number(offset) || 0; + var remaining = buf.length - offset; + + if (!length) { + length = remaining; + } else { + length = Number(length); + + if (length > remaining) { + length = remaining; + } + } + + var strLen = string.length; + + if (length > strLen / 2) { + length = strLen / 2; + } + + for (var i = 0; i < length; ++i) { + var parsed = parseInt(string.substr(i * 2, 2), 16); + if (numberIsNaN(parsed)) return i; + buf[offset + i] = parsed; + } + + return i; +} + +function utf8Write(buf, string, offset, length) { + return blitBuffer(utf8ToBytes(string, buf.length - offset), buf, offset, length); +} + +function asciiWrite(buf, string, offset, length) { + return blitBuffer(asciiToBytes(string), buf, offset, length); +} + +function latin1Write(buf, string, offset, length) { + return asciiWrite(buf, string, offset, length); +} + +function base64Write(buf, string, offset, length) { + return blitBuffer(base64ToBytes(string), buf, offset, length); +} + +function ucs2Write(buf, string, offset, length) { + return blitBuffer(utf16leToBytes(string, buf.length - offset), buf, offset, length); +} + +Buffer.prototype.write = function write(string, offset, length, encoding) { + // Buffer#write(string) + if (offset === undefined) { + encoding = 'utf8'; + length = this.length; + offset = 0; // Buffer#write(string, encoding) + } else if (length === undefined && typeof offset === 'string') { + encoding = offset; + length = this.length; + offset = 0; // Buffer#write(string, offset[, length][, encoding]) + } else if (isFinite(offset)) { + offset = offset >>> 0; + + if (isFinite(length)) { + length = length >>> 0; + if (encoding === undefined) encoding = 'utf8'; + } else { + encoding = length; + length = undefined; + } + } else { + throw new Error('Buffer.write(string, encoding, offset[, length]) is no longer supported'); + } + + var remaining = this.length - offset; + if (length === undefined || length > remaining) length = remaining; + + if (string.length > 0 && (length < 0 || offset < 0) || offset > this.length) { + throw new RangeError('Attempt to write outside buffer bounds'); + } + + if (!encoding) encoding = 'utf8'; + var loweredCase = false; + + for (;;) { + switch (encoding) { + case 'hex': + return hexWrite(this, string, offset, length); + + case 'utf8': + case 'utf-8': + return utf8Write(this, string, offset, length); + + case 'ascii': + return asciiWrite(this, string, offset, length); + + case 'latin1': + case 'binary': + return latin1Write(this, string, offset, length); + + case 'base64': + // Warning: maxLength not taken into account in base64Write + return base64Write(this, string, offset, length); + + case 'ucs2': + case 'ucs-2': + case 'utf16le': + case 'utf-16le': + return ucs2Write(this, string, offset, length); + + default: + if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding); + encoding = ('' + encoding).toLowerCase(); + loweredCase = true; + } + } +}; + +Buffer.prototype.toJSON = function toJSON() { + return { + type: 'Buffer', + data: Array.prototype.slice.call(this._arr || this, 0) + }; +}; + +function base64Slice(buf, start, end) { + if (start === 0 && end === buf.length) { + return base64.fromByteArray(buf); + } else { + return base64.fromByteArray(buf.slice(start, end)); + } +} + +function utf8Slice(buf, start, end) { + end = Math.min(buf.length, end); + var res = []; + var i = start; + + while (i < end) { + var firstByte = buf[i]; + var codePoint = null; + var bytesPerSequence = firstByte > 0xEF ? 4 : firstByte > 0xDF ? 3 : firstByte > 0xBF ? 2 : 1; + + if (i + bytesPerSequence <= end) { + var secondByte, thirdByte, fourthByte, tempCodePoint; + + switch (bytesPerSequence) { + case 1: + if (firstByte < 0x80) { + codePoint = firstByte; + } + + break; + + case 2: + secondByte = buf[i + 1]; + + if ((secondByte & 0xC0) === 0x80) { + tempCodePoint = (firstByte & 0x1F) << 0x6 | secondByte & 0x3F; + + if (tempCodePoint > 0x7F) { + codePoint = tempCodePoint; + } + } + + break; + + case 3: + secondByte = buf[i + 1]; + thirdByte = buf[i + 2]; + + if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80) { + tempCodePoint = (firstByte & 0xF) << 0xC | (secondByte & 0x3F) << 0x6 | thirdByte & 0x3F; + + if (tempCodePoint > 0x7FF && (tempCodePoint < 0xD800 || tempCodePoint > 0xDFFF)) { + codePoint = tempCodePoint; + } + } + + break; + + case 4: + secondByte = buf[i + 1]; + thirdByte = buf[i + 2]; + fourthByte = buf[i + 3]; + + if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80 && (fourthByte & 0xC0) === 0x80) { + tempCodePoint = (firstByte & 0xF) << 0x12 | (secondByte & 0x3F) << 0xC | (thirdByte & 0x3F) << 0x6 | fourthByte & 0x3F; + + if (tempCodePoint > 0xFFFF && tempCodePoint < 0x110000) { + codePoint = tempCodePoint; + } + } + + } + } + + if (codePoint === null) { + // we did not generate a valid codePoint so insert a + // replacement char (U+FFFD) and advance only 1 byte + codePoint = 0xFFFD; + bytesPerSequence = 1; + } else if (codePoint > 0xFFFF) { + // encode to utf16 (surrogate pair dance) + codePoint -= 0x10000; + res.push(codePoint >>> 10 & 0x3FF | 0xD800); + codePoint = 0xDC00 | codePoint & 0x3FF; + } + + res.push(codePoint); + i += bytesPerSequence; + } + + return decodeCodePointsArray(res); +} // Based on http://stackoverflow.com/a/22747272/680742, the browser with +// the lowest limit is Chrome, with 0x10000 args. +// We go 1 magnitude less, for safety + + +var MAX_ARGUMENTS_LENGTH = 0x1000; + +function decodeCodePointsArray(codePoints) { + var len = codePoints.length; + + if (len <= MAX_ARGUMENTS_LENGTH) { + return String.fromCharCode.apply(String, codePoints); // avoid extra slice() + } // Decode in chunks to avoid "call stack size exceeded". + + + var res = ''; + var i = 0; + + while (i < len) { + res += String.fromCharCode.apply(String, codePoints.slice(i, i += MAX_ARGUMENTS_LENGTH)); + } + + return res; +} + +function asciiSlice(buf, start, end) { + var ret = ''; + end = Math.min(buf.length, end); + + for (var i = start; i < end; ++i) { + ret += String.fromCharCode(buf[i] & 0x7F); + } + + return ret; +} + +function latin1Slice(buf, start, end) { + var ret = ''; + end = Math.min(buf.length, end); + + for (var i = start; i < end; ++i) { + ret += String.fromCharCode(buf[i]); + } + + return ret; +} + +function hexSlice(buf, start, end) { + var len = buf.length; + if (!start || start < 0) start = 0; + if (!end || end < 0 || end > len) end = len; + var out = ''; + + for (var i = start; i < end; ++i) { + out += toHex(buf[i]); + } + + return out; +} + +function utf16leSlice(buf, start, end) { + var bytes = buf.slice(start, end); + var res = ''; + + for (var i = 0; i < bytes.length; i += 2) { + res += String.fromCharCode(bytes[i] + bytes[i + 1] * 256); + } + + return res; +} + +Buffer.prototype.slice = function slice(start, end) { + var len = this.length; + start = ~~start; + end = end === undefined ? len : ~~end; + + if (start < 0) { + start += len; + if (start < 0) start = 0; + } else if (start > len) { + start = len; + } + + if (end < 0) { + end += len; + if (end < 0) end = 0; + } else if (end > len) { + end = len; + } + + if (end < start) end = start; + var newBuf = this.subarray(start, end); // Return an augmented `Uint8Array` instance + + newBuf.__proto__ = Buffer.prototype; + return newBuf; +}; +/* + * Need to make sure that buffer isn't trying to write out of bounds. + */ + + +function checkOffset(offset, ext, length) { + if (offset % 1 !== 0 || offset < 0) throw new RangeError('offset is not uint'); + if (offset + ext > length) throw new RangeError('Trying to access beyond buffer length'); +} + +Buffer.prototype.readUIntLE = function readUIntLE(offset, byteLength, noAssert) { + offset = offset >>> 0; + byteLength = byteLength >>> 0; + if (!noAssert) checkOffset(offset, byteLength, this.length); + var val = this[offset]; + var mul = 1; + var i = 0; + + while (++i < byteLength && (mul *= 0x100)) { + val += this[offset + i] * mul; + } + + return val; +}; + +Buffer.prototype.readUIntBE = function readUIntBE(offset, byteLength, noAssert) { + offset = offset >>> 0; + byteLength = byteLength >>> 0; + + if (!noAssert) { + checkOffset(offset, byteLength, this.length); + } + + var val = this[offset + --byteLength]; + var mul = 1; + + while (byteLength > 0 && (mul *= 0x100)) { + val += this[offset + --byteLength] * mul; + } + + return val; +}; + +Buffer.prototype.readUInt8 = function readUInt8(offset, noAssert) { + offset = offset >>> 0; + if (!noAssert) checkOffset(offset, 1, this.length); + return this[offset]; +}; + +Buffer.prototype.readUInt16LE = function readUInt16LE(offset, noAssert) { + offset = offset >>> 0; + if (!noAssert) checkOffset(offset, 2, this.length); + return this[offset] | this[offset + 1] << 8; +}; + +Buffer.prototype.readUInt16BE = function readUInt16BE(offset, noAssert) { + offset = offset >>> 0; + if (!noAssert) checkOffset(offset, 2, this.length); + return this[offset] << 8 | this[offset + 1]; +}; + +Buffer.prototype.readUInt32LE = function readUInt32LE(offset, noAssert) { + offset = offset >>> 0; + if (!noAssert) checkOffset(offset, 4, this.length); + return (this[offset] | this[offset + 1] << 8 | this[offset + 2] << 16) + this[offset + 3] * 0x1000000; +}; + +Buffer.prototype.readUInt32BE = function readUInt32BE(offset, noAssert) { + offset = offset >>> 0; + if (!noAssert) checkOffset(offset, 4, this.length); + return this[offset] * 0x1000000 + (this[offset + 1] << 16 | this[offset + 2] << 8 | this[offset + 3]); +}; + +Buffer.prototype.readIntLE = function readIntLE(offset, byteLength, noAssert) { + offset = offset >>> 0; + byteLength = byteLength >>> 0; + if (!noAssert) checkOffset(offset, byteLength, this.length); + var val = this[offset]; + var mul = 1; + var i = 0; + + while (++i < byteLength && (mul *= 0x100)) { + val += this[offset + i] * mul; + } + + mul *= 0x80; + if (val >= mul) val -= Math.pow(2, 8 * byteLength); + return val; +}; + +Buffer.prototype.readIntBE = function readIntBE(offset, byteLength, noAssert) { + offset = offset >>> 0; + byteLength = byteLength >>> 0; + if (!noAssert) checkOffset(offset, byteLength, this.length); + var i = byteLength; + var mul = 1; + var val = this[offset + --i]; + + while (i > 0 && (mul *= 0x100)) { + val += this[offset + --i] * mul; + } + + mul *= 0x80; + if (val >= mul) val -= Math.pow(2, 8 * byteLength); + return val; +}; + +Buffer.prototype.readInt8 = function readInt8(offset, noAssert) { + offset = offset >>> 0; + if (!noAssert) checkOffset(offset, 1, this.length); + if (!(this[offset] & 0x80)) return this[offset]; + return (0xff - this[offset] + 1) * -1; +}; + +Buffer.prototype.readInt16LE = function readInt16LE(offset, noAssert) { + offset = offset >>> 0; + if (!noAssert) checkOffset(offset, 2, this.length); + var val = this[offset] | this[offset + 1] << 8; + return val & 0x8000 ? val | 0xFFFF0000 : val; +}; + +Buffer.prototype.readInt16BE = function readInt16BE(offset, noAssert) { + offset = offset >>> 0; + if (!noAssert) checkOffset(offset, 2, this.length); + var val = this[offset + 1] | this[offset] << 8; + return val & 0x8000 ? val | 0xFFFF0000 : val; +}; + +Buffer.prototype.readInt32LE = function readInt32LE(offset, noAssert) { + offset = offset >>> 0; + if (!noAssert) checkOffset(offset, 4, this.length); + return this[offset] | this[offset + 1] << 8 | this[offset + 2] << 16 | this[offset + 3] << 24; +}; + +Buffer.prototype.readInt32BE = function readInt32BE(offset, noAssert) { + offset = offset >>> 0; + if (!noAssert) checkOffset(offset, 4, this.length); + return this[offset] << 24 | this[offset + 1] << 16 | this[offset + 2] << 8 | this[offset + 3]; +}; + +Buffer.prototype.readFloatLE = function readFloatLE(offset, noAssert) { + offset = offset >>> 0; + if (!noAssert) checkOffset(offset, 4, this.length); + return ieee754.read(this, offset, true, 23, 4); +}; + +Buffer.prototype.readFloatBE = function readFloatBE(offset, noAssert) { + offset = offset >>> 0; + if (!noAssert) checkOffset(offset, 4, this.length); + return ieee754.read(this, offset, false, 23, 4); +}; + +Buffer.prototype.readDoubleLE = function readDoubleLE(offset, noAssert) { + offset = offset >>> 0; + if (!noAssert) checkOffset(offset, 8, this.length); + return ieee754.read(this, offset, true, 52, 8); +}; + +Buffer.prototype.readDoubleBE = function readDoubleBE(offset, noAssert) { + offset = offset >>> 0; + if (!noAssert) checkOffset(offset, 8, this.length); + return ieee754.read(this, offset, false, 52, 8); +}; + +function checkInt(buf, value, offset, ext, max, min) { + if (!Buffer.isBuffer(buf)) throw new TypeError('"buffer" argument must be a Buffer instance'); + if (value > max || value < min) throw new RangeError('"value" argument is out of bounds'); + if (offset + ext > buf.length) throw new RangeError('Index out of range'); +} + +Buffer.prototype.writeUIntLE = function writeUIntLE(value, offset, byteLength, noAssert) { + value = +value; + offset = offset >>> 0; + byteLength = byteLength >>> 0; + + if (!noAssert) { + var maxBytes = Math.pow(2, 8 * byteLength) - 1; + checkInt(this, value, offset, byteLength, maxBytes, 0); + } + + var mul = 1; + var i = 0; + this[offset] = value & 0xFF; + + while (++i < byteLength && (mul *= 0x100)) { + this[offset + i] = value / mul & 0xFF; + } + + return offset + byteLength; +}; + +Buffer.prototype.writeUIntBE = function writeUIntBE(value, offset, byteLength, noAssert) { + value = +value; + offset = offset >>> 0; + byteLength = byteLength >>> 0; + + if (!noAssert) { + var maxBytes = Math.pow(2, 8 * byteLength) - 1; + checkInt(this, value, offset, byteLength, maxBytes, 0); + } + + var i = byteLength - 1; + var mul = 1; + this[offset + i] = value & 0xFF; + + while (--i >= 0 && (mul *= 0x100)) { + this[offset + i] = value / mul & 0xFF; + } + + return offset + byteLength; +}; + +Buffer.prototype.writeUInt8 = function writeUInt8(value, offset, noAssert) { + value = +value; + offset = offset >>> 0; + if (!noAssert) checkInt(this, value, offset, 1, 0xff, 0); + this[offset] = value & 0xff; + return offset + 1; +}; + +Buffer.prototype.writeUInt16LE = function writeUInt16LE(value, offset, noAssert) { + value = +value; + offset = offset >>> 0; + if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0); + this[offset] = value & 0xff; + this[offset + 1] = value >>> 8; + return offset + 2; +}; + +Buffer.prototype.writeUInt16BE = function writeUInt16BE(value, offset, noAssert) { + value = +value; + offset = offset >>> 0; + if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0); + this[offset] = value >>> 8; + this[offset + 1] = value & 0xff; + return offset + 2; +}; + +Buffer.prototype.writeUInt32LE = function writeUInt32LE(value, offset, noAssert) { + value = +value; + offset = offset >>> 0; + if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0); + this[offset + 3] = value >>> 24; + this[offset + 2] = value >>> 16; + this[offset + 1] = value >>> 8; + this[offset] = value & 0xff; + return offset + 4; +}; + +Buffer.prototype.writeUInt32BE = function writeUInt32BE(value, offset, noAssert) { + value = +value; + offset = offset >>> 0; + if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0); + this[offset] = value >>> 24; + this[offset + 1] = value >>> 16; + this[offset + 2] = value >>> 8; + this[offset + 3] = value & 0xff; + return offset + 4; +}; + +Buffer.prototype.writeIntLE = function writeIntLE(value, offset, byteLength, noAssert) { + value = +value; + offset = offset >>> 0; + + if (!noAssert) { + var limit = Math.pow(2, 8 * byteLength - 1); + checkInt(this, value, offset, byteLength, limit - 1, -limit); + } + + var i = 0; + var mul = 1; + var sub = 0; + this[offset] = value & 0xFF; + + while (++i < byteLength && (mul *= 0x100)) { + if (value < 0 && sub === 0 && this[offset + i - 1] !== 0) { + sub = 1; + } + + this[offset + i] = (value / mul >> 0) - sub & 0xFF; + } + + return offset + byteLength; +}; + +Buffer.prototype.writeIntBE = function writeIntBE(value, offset, byteLength, noAssert) { + value = +value; + offset = offset >>> 0; + + if (!noAssert) { + var limit = Math.pow(2, 8 * byteLength - 1); + checkInt(this, value, offset, byteLength, limit - 1, -limit); + } + + var i = byteLength - 1; + var mul = 1; + var sub = 0; + this[offset + i] = value & 0xFF; + + while (--i >= 0 && (mul *= 0x100)) { + if (value < 0 && sub === 0 && this[offset + i + 1] !== 0) { + sub = 1; + } + + this[offset + i] = (value / mul >> 0) - sub & 0xFF; + } + + return offset + byteLength; +}; + +Buffer.prototype.writeInt8 = function writeInt8(value, offset, noAssert) { + value = +value; + offset = offset >>> 0; + if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -0x80); + if (value < 0) value = 0xff + value + 1; + this[offset] = value & 0xff; + return offset + 1; +}; + +Buffer.prototype.writeInt16LE = function writeInt16LE(value, offset, noAssert) { + value = +value; + offset = offset >>> 0; + if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000); + this[offset] = value & 0xff; + this[offset + 1] = value >>> 8; + return offset + 2; +}; + +Buffer.prototype.writeInt16BE = function writeInt16BE(value, offset, noAssert) { + value = +value; + offset = offset >>> 0; + if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000); + this[offset] = value >>> 8; + this[offset + 1] = value & 0xff; + return offset + 2; +}; + +Buffer.prototype.writeInt32LE = function writeInt32LE(value, offset, noAssert) { + value = +value; + offset = offset >>> 0; + if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000); + this[offset] = value & 0xff; + this[offset + 1] = value >>> 8; + this[offset + 2] = value >>> 16; + this[offset + 3] = value >>> 24; + return offset + 4; +}; + +Buffer.prototype.writeInt32BE = function writeInt32BE(value, offset, noAssert) { + value = +value; + offset = offset >>> 0; + if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000); + if (value < 0) value = 0xffffffff + value + 1; + this[offset] = value >>> 24; + this[offset + 1] = value >>> 16; + this[offset + 2] = value >>> 8; + this[offset + 3] = value & 0xff; + return offset + 4; +}; + +function checkIEEE754(buf, value, offset, ext, max, min) { + if (offset + ext > buf.length) throw new RangeError('Index out of range'); + if (offset < 0) throw new RangeError('Index out of range'); +} + +function writeFloat(buf, value, offset, littleEndian, noAssert) { + value = +value; + offset = offset >>> 0; + + if (!noAssert) { + checkIEEE754(buf, value, offset, 4, 3.4028234663852886e+38, -3.4028234663852886e+38); + } + + ieee754.write(buf, value, offset, littleEndian, 23, 4); + return offset + 4; +} + +Buffer.prototype.writeFloatLE = function writeFloatLE(value, offset, noAssert) { + return writeFloat(this, value, offset, true, noAssert); +}; + +Buffer.prototype.writeFloatBE = function writeFloatBE(value, offset, noAssert) { + return writeFloat(this, value, offset, false, noAssert); +}; + +function writeDouble(buf, value, offset, littleEndian, noAssert) { + value = +value; + offset = offset >>> 0; + + if (!noAssert) { + checkIEEE754(buf, value, offset, 8, 1.7976931348623157E+308, -1.7976931348623157E+308); + } + + ieee754.write(buf, value, offset, littleEndian, 52, 8); + return offset + 8; +} + +Buffer.prototype.writeDoubleLE = function writeDoubleLE(value, offset, noAssert) { + return writeDouble(this, value, offset, true, noAssert); +}; + +Buffer.prototype.writeDoubleBE = function writeDoubleBE(value, offset, noAssert) { + return writeDouble(this, value, offset, false, noAssert); +}; // copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length) + + +Buffer.prototype.copy = function copy(target, targetStart, start, end) { + if (!Buffer.isBuffer(target)) throw new TypeError('argument should be a Buffer'); + if (!start) start = 0; + if (!end && end !== 0) end = this.length; + if (targetStart >= target.length) targetStart = target.length; + if (!targetStart) targetStart = 0; + if (end > 0 && end < start) end = start; // Copy 0 bytes; we're done + + if (end === start) return 0; + if (target.length === 0 || this.length === 0) return 0; // Fatal error conditions + + if (targetStart < 0) { + throw new RangeError('targetStart out of bounds'); + } + + if (start < 0 || start >= this.length) throw new RangeError('Index out of range'); + if (end < 0) throw new RangeError('sourceEnd out of bounds'); // Are we oob? + + if (end > this.length) end = this.length; + + if (target.length - targetStart < end - start) { + end = target.length - targetStart + start; + } + + var len = end - start; + + if (this === target && typeof Uint8Array.prototype.copyWithin === 'function') { + // Use built-in when available, missing from IE11 + this.copyWithin(targetStart, start, end); + } else if (this === target && start < targetStart && targetStart < end) { + // descending copy from end + for (var i = len - 1; i >= 0; --i) { + target[i + targetStart] = this[i + start]; + } + } else { + Uint8Array.prototype.set.call(target, this.subarray(start, end), targetStart); + } + + return len; +}; // Usage: +// buffer.fill(number[, offset[, end]]) +// buffer.fill(buffer[, offset[, end]]) +// buffer.fill(string[, offset[, end]][, encoding]) + + +Buffer.prototype.fill = function fill(val, start, end, encoding) { + // Handle string cases: + if (typeof val === 'string') { + if (typeof start === 'string') { + encoding = start; + start = 0; + end = this.length; + } else if (typeof end === 'string') { + encoding = end; + end = this.length; + } + + if (encoding !== undefined && typeof encoding !== 'string') { + throw new TypeError('encoding must be a string'); + } + + if (typeof encoding === 'string' && !Buffer.isEncoding(encoding)) { + throw new TypeError('Unknown encoding: ' + encoding); + } + + if (val.length === 1) { + var code = val.charCodeAt(0); + + if (encoding === 'utf8' && code < 128 || encoding === 'latin1') { + // Fast path: If `val` fits into a single byte, use that numeric value. + val = code; + } + } + } else if (typeof val === 'number') { + val = val & 255; + } // Invalid ranges are not set to a default, so can range check early. + + + if (start < 0 || this.length < start || this.length < end) { + throw new RangeError('Out of range index'); + } + + if (end <= start) { + return this; + } + + start = start >>> 0; + end = end === undefined ? this.length : end >>> 0; + if (!val) val = 0; + var i; + + if (typeof val === 'number') { + for (i = start; i < end; ++i) { + this[i] = val; + } + } else { + var bytes = Buffer.isBuffer(val) ? val : Buffer.from(val, encoding); + var len = bytes.length; + + if (len === 0) { + throw new TypeError('The value "' + val + '" is invalid for argument "value"'); + } + + for (i = 0; i < end - start; ++i) { + this[i + start] = bytes[i % len]; + } + } + + return this; +}; // HELPER FUNCTIONS +// ================ + + +var INVALID_BASE64_RE = /[^+/0-9A-Za-z-_]/g; + +function base64clean(str) { + // Node takes equal signs as end of the Base64 encoding + str = str.split('=')[0]; // Node strips out invalid characters like \n and \t from the string, base64-js does not + + str = str.trim().replace(INVALID_BASE64_RE, ''); // Node converts strings with length < 2 to '' + + if (str.length < 2) return ''; // Node allows for non-padded base64 strings (missing trailing ===), base64-js does not + + while (str.length % 4 !== 0) { + str = str + '='; + } + + return str; +} + +function toHex(n) { + if (n < 16) return '0' + n.toString(16); + return n.toString(16); +} + +function utf8ToBytes(string, units) { + units = units || Infinity; + var codePoint; + var length = string.length; + var leadSurrogate = null; + var bytes = []; + + for (var i = 0; i < length; ++i) { + codePoint = string.charCodeAt(i); // is surrogate component + + if (codePoint > 0xD7FF && codePoint < 0xE000) { + // last char was a lead + if (!leadSurrogate) { + // no lead yet + if (codePoint > 0xDBFF) { + // unexpected trail + if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD); + continue; + } else if (i + 1 === length) { + // unpaired lead + if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD); + continue; + } // valid lead + + + leadSurrogate = codePoint; + continue; + } // 2 leads in a row + + + if (codePoint < 0xDC00) { + if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD); + leadSurrogate = codePoint; + continue; + } // valid surrogate pair + + + codePoint = (leadSurrogate - 0xD800 << 10 | codePoint - 0xDC00) + 0x10000; + } else if (leadSurrogate) { + // valid bmp char, but last char was a lead + if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD); + } + + leadSurrogate = null; // encode utf8 + + if (codePoint < 0x80) { + if ((units -= 1) < 0) break; + bytes.push(codePoint); + } else if (codePoint < 0x800) { + if ((units -= 2) < 0) break; + bytes.push(codePoint >> 0x6 | 0xC0, codePoint & 0x3F | 0x80); + } else if (codePoint < 0x10000) { + if ((units -= 3) < 0) break; + bytes.push(codePoint >> 0xC | 0xE0, codePoint >> 0x6 & 0x3F | 0x80, codePoint & 0x3F | 0x80); + } else if (codePoint < 0x110000) { + if ((units -= 4) < 0) break; + bytes.push(codePoint >> 0x12 | 0xF0, codePoint >> 0xC & 0x3F | 0x80, codePoint >> 0x6 & 0x3F | 0x80, codePoint & 0x3F | 0x80); + } else { + throw new Error('Invalid code point'); + } + } + + return bytes; +} + +function asciiToBytes(str) { + var byteArray = []; + + for (var i = 0; i < str.length; ++i) { + // Node's code seems to be doing this and not & 0x7F.. + byteArray.push(str.charCodeAt(i) & 0xFF); + } + + return byteArray; +} + +function utf16leToBytes(str, units) { + var c, hi, lo; + var byteArray = []; + + for (var i = 0; i < str.length; ++i) { + if ((units -= 2) < 0) break; + c = str.charCodeAt(i); + hi = c >> 8; + lo = c % 256; + byteArray.push(lo); + byteArray.push(hi); + } + + return byteArray; +} + +function base64ToBytes(str) { + return base64.toByteArray(base64clean(str)); +} + +function blitBuffer(src, dst, offset, length) { + for (var i = 0; i < length; ++i) { + if (i + offset >= dst.length || i >= src.length) break; + dst[i + offset] = src[i]; + } + + return i; +} // ArrayBuffer or Uint8Array objects from other contexts (i.e. iframes) do not pass +// the `instanceof` check but they should be treated as of that type. +// See: https://github.com/feross/buffer/issues/166 + + +function isInstance(obj, type) { + return obj instanceof type || obj != null && obj.constructor != null && obj.constructor.name != null && obj.constructor.name === type.name; +} + +function numberIsNaN(obj) { + // For IE11 support + return obj !== obj; // eslint-disable-line no-self-compare +} \ No newline at end of file diff --git a/app/components/blufi/crypto/lib/dh.js b/app/components/blufi/crypto/lib/dh.js new file mode 100644 index 0000000..de42b50 --- /dev/null +++ b/app/components/blufi/crypto/lib/dh.js @@ -0,0 +1,195 @@ +var BN = require("./bn.js"); + +var MillerRabin = require("./miller-rabin.js"); + +var millerRabin = new MillerRabin(); +var TWENTYFOUR = new BN(24); +var ELEVEN = new BN(11); +var TEN = new BN(10); +var THREE = new BN(3); +var SEVEN = new BN(7); + +var Buffer = require("./safe-buffer.js").Buffer; + +var primes = require("./generatePrime.js"); + +var randomBytes = require("./randombytes.js"); + +module.exports = DH; + +function setPublicKey(pub, enc) { + enc = enc || 'utf8'; + + if (!Buffer.isBuffer(pub)) { + pub = new Buffer(pub, enc); + } + + this._pub = new BN(pub); + return this; +} + +function setPrivateKey(priv, enc) { + enc = enc || 'utf8'; + + if (!Buffer.isBuffer(priv)) { + priv = new Buffer(priv, enc); + } + + this._priv = new BN(priv); + return this; +} + +var primeCache = {}; + +function checkPrime(prime, generator) { + var gen = generator.toString('hex'); + var hex = [gen, prime.toString(16)].join('_'); + + if (hex in primeCache) { + return primeCache[hex]; + } + + var error = 0; + + if (prime.isEven() || !primes.simpleSieve || !primes.fermatTest(prime) || !millerRabin.test(prime)) { + //not a prime so +1 + error += 1; + + if (gen === '02' || gen === '05') { + // we'd be able to check the generator + // it would fail so +8 + error += 8; + } else { + //we wouldn't be able to test the generator + // so +4 + error += 4; + } + + primeCache[hex] = error; + return error; + } + + if (!millerRabin.test(prime.shrn(1))) { + //not a safe prime + error += 2; + } + + var rem; + + switch (gen) { + case '02': + if (prime.mod(TWENTYFOUR).cmp(ELEVEN)) { + // unsuidable generator + error += 8; + } + + break; + + case '05': + rem = prime.mod(TEN); + + if (rem.cmp(THREE) && rem.cmp(SEVEN)) { + // prime mod 10 needs to equal 3 or 7 + error += 8; + } + + break; + + default: + error += 4; + } + + primeCache[hex] = error; + return error; +} + +function DH(prime, generator, malleable) { + this.setGenerator(generator); + this.__prime = new BN(prime); + this._prime = BN.mont(this.__prime); + this._primeLen = 128; + this._pub = undefined; + this._priv = undefined; + this._primeCode = undefined; + + if (malleable) { + this.setPublicKey = setPublicKey; + this.setPrivateKey = setPrivateKey; + } else { + this._primeCode = 8; + } +} + +Object.defineProperty(DH.prototype, 'verifyError', { + enumerable: true, + get: function () { + if (typeof this._primeCode !== 'number') { + this._primeCode = checkPrime(this.__prime, this.__gen); + } + + return this._primeCode; + } +}); + +DH.prototype.generateKeys = function () { + if (!this._priv) { + this._priv = new BN(randomBytes(this._primeLen)); + } + + this._pub = this._gen.toRed(this._prime).redPow(this._priv).fromRed(); + return this.getPublicKey(); +}; + +DH.prototype.computeSecret = function (other) { + other = new BN(other); + other = other.toRed(this._prime); + var secret = other.redPow(this._priv).fromRed(); + var out = new Buffer(secret.toArray()); + var prime = this.getPrime(); + + if (out.length < prime.length) { + var front = new Buffer(prime.length - out.length); + front.fill(0); + out = Buffer.concat([front, out]); + } + + return out; +}; + +DH.prototype.getPublicKey = function getPublicKey(enc) { + return formatReturnValue(this._pub, enc); +}; + +DH.prototype.getPrivateKey = function getPrivateKey(enc) { + return formatReturnValue(this._priv, enc); +}; + +DH.prototype.getPrime = function (enc) { + return formatReturnValue(this.__prime, enc); +}; + +DH.prototype.getGenerator = function (enc) { + return formatReturnValue(this._gen, enc); +}; + +DH.prototype.setGenerator = function (gen, enc) { + enc = enc || 'utf8'; + + if (!Buffer.isBuffer(gen)) { + gen = new Buffer(gen, enc); + } + + this.__gen = gen; + this._gen = new BN(gen); + return this; +}; + +function formatReturnValue(bn, enc) { + var buf = new Buffer(bn.toArray()); + + if (!enc) { + return buf; + } else { + return buf.toString(enc); + } +} \ No newline at end of file diff --git a/app/components/blufi/crypto/lib/generatePrime.js b/app/components/blufi/crypto/lib/generatePrime.js new file mode 100644 index 0000000..2944136 --- /dev/null +++ b/app/components/blufi/crypto/lib/generatePrime.js @@ -0,0 +1,109 @@ +var randomBytes = require("./randombytes.js"); + +module.exports = findPrime; +findPrime.simpleSieve = simpleSieve; +findPrime.fermatTest = fermatTest; + +var BN = require("./bn.js"); + +var TWENTYFOUR = new BN(24); + +var MillerRabin = require("./miller-rabin.js"); + +var millerRabin = new MillerRabin(); +var ONE = new BN(1); +var TWO = new BN(2); +var FIVE = new BN(5); +var SIXTEEN = new BN(16); +var EIGHT = new BN(8); +var TEN = new BN(10); +var THREE = new BN(3); +var SEVEN = new BN(7); +var ELEVEN = new BN(11); +var FOUR = new BN(4); +var TWELVE = new BN(12); +var primes = null; + +function _getPrimes() { + if (primes !== null) return primes; + var limit = 0x100000; + var res = []; + res[0] = 2; + + for (var i = 1, k = 3; k < limit; k += 2) { + var sqrt = Math.ceil(Math.sqrt(k)); + + for (var j = 0; j < i && res[j] <= sqrt; j++) if (k % res[j] === 0) break; + + if (i !== j && res[j] <= sqrt) continue; + res[i++] = k; + } + + primes = res; + return res; +} + +function simpleSieve(p) { + var primes = _getPrimes(); + + for (var i = 0; i < primes.length; i++) if (p.modn(primes[i]) === 0) { + if (p.cmpn(primes[i]) === 0) { + return true; + } else { + return false; + } + } + + return true; +} + +function fermatTest(p) { + var red = BN.mont(p); + return TWO.toRed(red).redPow(p.subn(1)).fromRed().cmpn(1) === 0; +} + +function findPrime(bits, gen) { + if (bits < 16) { + // this is what openssl does + if (gen === 2 || gen === 5) { + return new BN([0x8c, 0x7b]); + } else { + return new BN([0x8c, 0x27]); + } + } + + gen = new BN(gen); + var num, n2; + + while (true) { + num = new BN(randomBytes(Math.ceil(bits / 8))); + + while (num.bitLength() > bits) { + num.ishrn(1); + } + + if (num.isEven()) { + num.iadd(ONE); + } + + if (!num.testn(1)) { + num.iadd(TWO); + } + + if (!gen.cmp(TWO)) { + while (num.mod(TWENTYFOUR).cmp(ELEVEN)) { + num.iadd(FOUR); + } + } else if (!gen.cmp(FIVE)) { + while (num.mod(TEN).cmp(THREE)) { + num.iadd(FOUR); + } + } + + n2 = num.shrn(1); + + if (simpleSieve(n2) && simpleSieve(num) && fermatTest(n2) && fermatTest(num) && millerRabin.test(n2) && millerRabin.test(num)) { + return num; + } + } +} \ No newline at end of file diff --git a/app/components/blufi/crypto/lib/ieee754.js b/app/components/blufi/crypto/lib/ieee754.js new file mode 100644 index 0000000..9b8d5c9 --- /dev/null +++ b/app/components/blufi/crypto/lib/ieee754.js @@ -0,0 +1,88 @@ +exports.read = function (buffer, offset, isLE, mLen, nBytes) { + var e, m; + var eLen = nBytes * 8 - mLen - 1; + var eMax = (1 << eLen) - 1; + var eBias = eMax >> 1; + var nBits = -7; + var i = isLE ? nBytes - 1 : 0; + var d = isLE ? -1 : 1; + var s = buffer[offset + i]; + i += d; + e = s & (1 << -nBits) - 1; + s >>= -nBits; + nBits += eLen; + + for (; nBits > 0; e = e * 256 + buffer[offset + i], i += d, nBits -= 8) {} + + m = e & (1 << -nBits) - 1; + e >>= -nBits; + nBits += mLen; + + for (; nBits > 0; m = m * 256 + buffer[offset + i], i += d, nBits -= 8) {} + + if (e === 0) { + e = 1 - eBias; + } else if (e === eMax) { + return m ? NaN : (s ? -1 : 1) * Infinity; + } else { + m = m + Math.pow(2, mLen); + e = e - eBias; + } + + return (s ? -1 : 1) * m * Math.pow(2, e - mLen); +}; + +exports.write = function (buffer, value, offset, isLE, mLen, nBytes) { + var e, m, c; + var eLen = nBytes * 8 - mLen - 1; + var eMax = (1 << eLen) - 1; + var eBias = eMax >> 1; + var rt = mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0; + var i = isLE ? 0 : nBytes - 1; + var d = isLE ? 1 : -1; + var s = value < 0 || value === 0 && 1 / value < 0 ? 1 : 0; + value = Math.abs(value); + + if (isNaN(value) || value === Infinity) { + m = isNaN(value) ? 1 : 0; + e = eMax; + } else { + e = Math.floor(Math.log(value) / Math.LN2); + + if (value * (c = Math.pow(2, -e)) < 1) { + e--; + c *= 2; + } + + if (e + eBias >= 1) { + value += rt / c; + } else { + value += rt * Math.pow(2, 1 - eBias); + } + + if (value * c >= 2) { + e++; + c /= 2; + } + + if (e + eBias >= eMax) { + m = 0; + e = eMax; + } else if (e + eBias >= 1) { + m = (value * c - 1) * Math.pow(2, mLen); + e = e + eBias; + } else { + m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen); + e = 0; + } + } + + for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8) {} + + e = e << mLen | m; + eLen += mLen; + + for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8) {} + + buffer[offset + i - d] |= s * 128; +}; \ No newline at end of file diff --git a/app/components/blufi/crypto/lib/miller-rabin.js b/app/components/blufi/crypto/lib/miller-rabin.js new file mode 100644 index 0000000..b8f3802 --- /dev/null +++ b/app/components/blufi/crypto/lib/miller-rabin.js @@ -0,0 +1,98 @@ +var bn = require("./bn.js"); + +var brorand = require("./brorand.js"); + +function MillerRabin(rand) { + this.rand = rand || new brorand.Rand(); +} + +module.exports = MillerRabin; + +MillerRabin.create = function create(rand) { + return new MillerRabin(rand); +}; + +MillerRabin.prototype._randbelow = function _randbelow(n) { + var len = n.bitLength(); + var min_bytes = Math.ceil(len / 8); // Generage random bytes until a number less than n is found. + // This ensures that 0..n-1 have an equal probability of being selected. + + do var a = new bn(this.rand.generate(min_bytes)); while (a.cmp(n) >= 0); + + return a; +}; + +MillerRabin.prototype._randrange = function _randrange(start, stop) { + // Generate a random number greater than or equal to start and less than stop. + var size = stop.sub(start); + return start.add(this._randbelow(size)); +}; + +MillerRabin.prototype.test = function test(n, k, cb) { + var len = n.bitLength(); + var red = bn.mont(n); + var rone = new bn(1).toRed(red); + if (!k) k = Math.max(1, len / 48 | 0); // Find d and s, (n - 1) = (2 ^ s) * d; + + var n1 = n.subn(1); + + for (var s = 0; !n1.testn(s); s++) {} + + var d = n.shrn(s); + var rn1 = n1.toRed(red); + var prime = true; + + for (; k > 0; k--) { + var a = this._randrange(new bn(2), n1); + + if (cb) cb(a); + var x = a.toRed(red).redPow(d); + if (x.cmp(rone) === 0 || x.cmp(rn1) === 0) continue; + + for (var i = 1; i < s; i++) { + x = x.redSqr(); + if (x.cmp(rone) === 0) return false; + if (x.cmp(rn1) === 0) break; + } + + if (i === s) return false; + } + + return prime; +}; + +MillerRabin.prototype.getDivisor = function getDivisor(n, k) { + var len = n.bitLength(); + var red = bn.mont(n); + var rone = new bn(1).toRed(red); + if (!k) k = Math.max(1, len / 48 | 0); // Find d and s, (n - 1) = (2 ^ s) * d; + + var n1 = n.subn(1); + + for (var s = 0; !n1.testn(s); s++) {} + + var d = n.shrn(s); + var rn1 = n1.toRed(red); + + for (; k > 0; k--) { + var a = this._randrange(new bn(2), n1); + + var g = n.gcd(a); + if (g.cmpn(1) !== 0) return g; + var x = a.toRed(red).redPow(d); + if (x.cmp(rone) === 0 || x.cmp(rn1) === 0) continue; + + for (var i = 1; i < s; i++) { + x = x.redSqr(); + if (x.cmp(rone) === 0) return x.fromRed().subn(1).gcd(n); + if (x.cmp(rn1) === 0) break; + } + + if (i === s) { + x = x.redSqr(); + return x.fromRed().subn(1).gcd(n); + } + } + + return false; +}; \ No newline at end of file diff --git a/app/components/blufi/crypto/lib/randombytes.js b/app/components/blufi/crypto/lib/randombytes.js new file mode 100644 index 0000000..0a14a78 --- /dev/null +++ b/app/components/blufi/crypto/lib/randombytes.js @@ -0,0 +1,32 @@ +'use strict'; + +function oldBrowser() { + throw new Error('Secure random number generation is not supported by this browser.\nUse Chrome, Firefox or Internet Explorer 11'); +} + +var Buffer = require("./safe-buffer.js").Buffer; + +module.exports = randomBytes; + +function randomBytes(size, cb) { + // phantomjs needs to throw + if (size > 65536) throw new Error('requested too many random bytes'); // in case browserify isn't using the Uint8Array version + + var arr = []; + + for (var i = 0; i < size; i++) { + arr.push(Math.ceil(Math.random() * 255)); + } + + var rawBytes = new Uint8Array(arr); // XXX: phantomjs doesn't like a buffer being passed here + + var bytes = Buffer.from(rawBytes.buffer); + + if (typeof cb === 'function') { + return process.nextTick(function () { + cb(null, bytes); + }); + } + + return bytes; +} \ No newline at end of file diff --git a/app/components/blufi/crypto/lib/safe-buffer.js b/app/components/blufi/crypto/lib/safe-buffer.js new file mode 100644 index 0000000..aba8a14 --- /dev/null +++ b/app/components/blufi/crypto/lib/safe-buffer.js @@ -0,0 +1,69 @@ +/* eslint-disable node/no-deprecated-api */ +var buffer = require("./buffer.js"); + +var Buffer = buffer.Buffer; // alternative to using Object.keys for old browsers + +function copyProps(src, dst) { + for (var key in src) { + dst[key] = src[key]; + } +} + +if (Buffer.from && Buffer.alloc && Buffer.allocUnsafe && Buffer.allocUnsafeSlow) { + module.exports = buffer; +} else { + // Copy properties from require('buffer') + copyProps(buffer, exports); + exports.Buffer = SafeBuffer; +} + +function SafeBuffer(arg, encodingOrOffset, length) { + return Buffer(arg, encodingOrOffset, length); +} // Copy static methods from Buffer + + +copyProps(Buffer, SafeBuffer); + +SafeBuffer.from = function (arg, encodingOrOffset, length) { + if (typeof arg === 'number') { + throw new TypeError('Argument must not be a number'); + } + + return Buffer(arg, encodingOrOffset, length); +}; + +SafeBuffer.alloc = function (size, fill, encoding) { + if (typeof size !== 'number') { + throw new TypeError('Argument must be a number'); + } + + var buf = Buffer(size); + + if (fill !== undefined) { + if (typeof encoding === 'string') { + buf.fill(fill, encoding); + } else { + buf.fill(fill); + } + } else { + buf.fill(0); + } + + return buf; +}; + +SafeBuffer.allocUnsafe = function (size) { + if (typeof size !== 'number') { + throw new TypeError('Argument must be a number'); + } + + return Buffer(size); +}; + +SafeBuffer.allocUnsafeSlow = function (size) { + if (typeof size !== 'number') { + throw new TypeError('Argument must be a number'); + } + + return buffer.SlowBuffer(size); +}; \ No newline at end of file diff --git a/app/components/blufi/crypto/md5.min.js b/app/components/blufi/crypto/md5.min.js new file mode 100644 index 0000000..cd3a91b --- /dev/null +++ b/app/components/blufi/crypto/md5.min.js @@ -0,0 +1,149 @@ +/** + * [js-md5]{@link https://github.com/emn178/js-md5} + * + * @namespace md5 + * @version 0.7.3 + * @author Chen, Yi-Cyuan [emn178@gmail.com] + * @copyright Chen, Yi-Cyuan 2014-2017 + * @license MIT + */ +!function () { + "use strict"; + + function t(t) { + if (t) d[0] = d[16] = d[1] = d[2] = d[3] = d[4] = d[5] = d[6] = d[7] = d[8] = d[9] = d[10] = d[11] = d[12] = d[13] = d[14] = d[15] = 0, this.blocks = d, this.buffer8 = l;else if (a) { + var r = new ArrayBuffer(68); + this.buffer8 = new Uint8Array(r), this.blocks = new Uint32Array(r); + } else this.blocks = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; + this.h0 = this.h1 = this.h2 = this.h3 = this.start = this.bytes = this.hBytes = 0, this.finalized = this.hashed = !1, this.first = !0; + } + + var r = "input is invalid type", + e = "object" == typeof window, + i = e ? window : {}; + i.JS_MD5_NO_WINDOW && (e = !1); + var s = !e && "object" == typeof self, + h = !i.JS_MD5_NO_NODE_JS && "object" == typeof process && process.versions && process.versions.node; + h ? i = global : s && (i = self); + var f = !i.JS_MD5_NO_COMMON_JS && "object" == typeof module && module.exports, + o = "function" == typeof define && define.amd, + a = !i.JS_MD5_NO_ARRAY_BUFFER && "undefined" != typeof ArrayBuffer, + n = "0123456789abcdef".split(""), + u = [128, 32768, 8388608, -2147483648], + y = [0, 8, 16, 24], + c = ["hex", "array", "digest", "buffer", "arrayBuffer", "base64"], + p = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".split(""), + d = [], + l; + + if (a) { + var A = new ArrayBuffer(68); + l = new Uint8Array(A), d = new Uint32Array(A); + } + + !i.JS_MD5_NO_NODE_JS && Array.isArray || (Array.isArray = function (t) { + return "[object Array]" === Object.prototype.toString.call(t); + }), !a || !i.JS_MD5_NO_ARRAY_BUFFER_IS_VIEW && ArrayBuffer.isView || (ArrayBuffer.isView = function (t) { + return "object" == typeof t && t.buffer && t.buffer.constructor === ArrayBuffer; + }); + + var b = function (r) { + return function (e) { + return new t(!0).update(e)[r](); + }; + }, + v = function () { + var r = b("hex"); + h && (r = w(r)), r.create = function () { + return new t(); + }, r.update = function (t) { + return r.create().update(t); + }; + + for (var e = 0; e < c.length; ++e) { + var i = c[e]; + r[i] = b(i); + } + + return r; + }, + w = function (t) { + var e = eval("require('crypto')"), + i = eval("require('buffer').Buffer"), + s = function (s) { + if ("string" == typeof s) return e.createHash("md5").update(s, "utf8").digest("hex"); + if (null === s || void 0 === s) throw r; + return s.constructor === ArrayBuffer && (s = new Uint8Array(s)), Array.isArray(s) || ArrayBuffer.isView(s) || s.constructor === i ? e.createHash("md5").update(new i(s)).digest("hex") : t(s); + }; + + return s; + }; + + t.prototype.update = function (t) { + if (!this.finalized) { + var e, + i = typeof t; + + if ("string" !== i) { + if ("object" !== i) throw r; + if (null === t) throw r; + if (a && t.constructor === ArrayBuffer) t = new Uint8Array(t);else if (!(Array.isArray(t) || a && ArrayBuffer.isView(t))) throw r; + e = !0; + } + + for (var s, h, f = 0, o = t.length, n = this.blocks, u = this.buffer8; f < o;) { + if (this.hashed && (this.hashed = !1, n[0] = n[16], n[16] = n[1] = n[2] = n[3] = n[4] = n[5] = n[6] = n[7] = n[8] = n[9] = n[10] = n[11] = n[12] = n[13] = n[14] = n[15] = 0), e) { + if (a) for (h = this.start; f < o && h < 64; ++f) u[h++] = t[f];else for (h = this.start; f < o && h < 64; ++f) n[h >> 2] |= t[f] << y[3 & h++]; + } else if (a) for (h = this.start; f < o && h < 64; ++f) (s = t.charCodeAt(f)) < 128 ? u[h++] = s : s < 2048 ? (u[h++] = 192 | s >> 6, u[h++] = 128 | 63 & s) : s < 55296 || s >= 57344 ? (u[h++] = 224 | s >> 12, u[h++] = 128 | s >> 6 & 63, u[h++] = 128 | 63 & s) : (s = 65536 + ((1023 & s) << 10 | 1023 & t.charCodeAt(++f)), u[h++] = 240 | s >> 18, u[h++] = 128 | s >> 12 & 63, u[h++] = 128 | s >> 6 & 63, u[h++] = 128 | 63 & s);else for (h = this.start; f < o && h < 64; ++f) (s = t.charCodeAt(f)) < 128 ? n[h >> 2] |= s << y[3 & h++] : s < 2048 ? (n[h >> 2] |= (192 | s >> 6) << y[3 & h++], n[h >> 2] |= (128 | 63 & s) << y[3 & h++]) : s < 55296 || s >= 57344 ? (n[h >> 2] |= (224 | s >> 12) << y[3 & h++], n[h >> 2] |= (128 | s >> 6 & 63) << y[3 & h++], n[h >> 2] |= (128 | 63 & s) << y[3 & h++]) : (s = 65536 + ((1023 & s) << 10 | 1023 & t.charCodeAt(++f)), n[h >> 2] |= (240 | s >> 18) << y[3 & h++], n[h >> 2] |= (128 | s >> 12 & 63) << y[3 & h++], n[h >> 2] |= (128 | s >> 6 & 63) << y[3 & h++], n[h >> 2] |= (128 | 63 & s) << y[3 & h++]); + this.lastByteIndex = h, this.bytes += h - this.start, h >= 64 ? (this.start = h - 64, this.hash(), this.hashed = !0) : this.start = h; + } + + return this.bytes > 4294967295 && (this.hBytes += this.bytes / 4294967296 << 0, this.bytes = this.bytes % 4294967296), this; + } + }, t.prototype.finalize = function () { + if (!this.finalized) { + this.finalized = !0; + var t = this.blocks, + r = this.lastByteIndex; + t[r >> 2] |= u[3 & r], r >= 56 && (this.hashed || this.hash(), t[0] = t[16], t[16] = t[1] = t[2] = t[3] = t[4] = t[5] = t[6] = t[7] = t[8] = t[9] = t[10] = t[11] = t[12] = t[13] = t[14] = t[15] = 0), t[14] = this.bytes << 3, t[15] = this.hBytes << 3 | this.bytes >>> 29, this.hash(); + } + }, t.prototype.hash = function () { + var t, + r, + e, + i, + s, + h, + f = this.blocks; + this.first ? r = ((r = ((t = ((t = f[0] - 680876937) << 7 | t >>> 25) - 271733879 << 0) ^ (e = ((e = (-271733879 ^ (i = ((i = (-1732584194 ^ 2004318071 & t) + f[1] - 117830708) << 12 | i >>> 20) + t << 0) & (-271733879 ^ t)) + f[2] - 1126478375) << 17 | e >>> 15) + i << 0) & (i ^ t)) + f[3] - 1316259209) << 22 | r >>> 10) + e << 0 : (t = this.h0, r = this.h1, e = this.h2, r = ((r += ((t = ((t += ((i = this.h3) ^ r & (e ^ i)) + f[0] - 680876936) << 7 | t >>> 25) + r << 0) ^ (e = ((e += (r ^ (i = ((i += (e ^ t & (r ^ e)) + f[1] - 389564586) << 12 | i >>> 20) + t << 0) & (t ^ r)) + f[2] + 606105819) << 17 | e >>> 15) + i << 0) & (i ^ t)) + f[3] - 1044525330) << 22 | r >>> 10) + e << 0), r = ((r += ((t = ((t += (i ^ r & (e ^ i)) + f[4] - 176418897) << 7 | t >>> 25) + r << 0) ^ (e = ((e += (r ^ (i = ((i += (e ^ t & (r ^ e)) + f[5] + 1200080426) << 12 | i >>> 20) + t << 0) & (t ^ r)) + f[6] - 1473231341) << 17 | e >>> 15) + i << 0) & (i ^ t)) + f[7] - 45705983) << 22 | r >>> 10) + e << 0, r = ((r += ((t = ((t += (i ^ r & (e ^ i)) + f[8] + 1770035416) << 7 | t >>> 25) + r << 0) ^ (e = ((e += (r ^ (i = ((i += (e ^ t & (r ^ e)) + f[9] - 1958414417) << 12 | i >>> 20) + t << 0) & (t ^ r)) + f[10] - 42063) << 17 | e >>> 15) + i << 0) & (i ^ t)) + f[11] - 1990404162) << 22 | r >>> 10) + e << 0, r = ((r += ((t = ((t += (i ^ r & (e ^ i)) + f[12] + 1804603682) << 7 | t >>> 25) + r << 0) ^ (e = ((e += (r ^ (i = ((i += (e ^ t & (r ^ e)) + f[13] - 40341101) << 12 | i >>> 20) + t << 0) & (t ^ r)) + f[14] - 1502002290) << 17 | e >>> 15) + i << 0) & (i ^ t)) + f[15] + 1236535329) << 22 | r >>> 10) + e << 0, r = ((r += ((i = ((i += (r ^ e & ((t = ((t += (e ^ i & (r ^ e)) + f[1] - 165796510) << 5 | t >>> 27) + r << 0) ^ r)) + f[6] - 1069501632) << 9 | i >>> 23) + t << 0) ^ t & ((e = ((e += (t ^ r & (i ^ t)) + f[11] + 643717713) << 14 | e >>> 18) + i << 0) ^ i)) + f[0] - 373897302) << 20 | r >>> 12) + e << 0, r = ((r += ((i = ((i += (r ^ e & ((t = ((t += (e ^ i & (r ^ e)) + f[5] - 701558691) << 5 | t >>> 27) + r << 0) ^ r)) + f[10] + 38016083) << 9 | i >>> 23) + t << 0) ^ t & ((e = ((e += (t ^ r & (i ^ t)) + f[15] - 660478335) << 14 | e >>> 18) + i << 0) ^ i)) + f[4] - 405537848) << 20 | r >>> 12) + e << 0, r = ((r += ((i = ((i += (r ^ e & ((t = ((t += (e ^ i & (r ^ e)) + f[9] + 568446438) << 5 | t >>> 27) + r << 0) ^ r)) + f[14] - 1019803690) << 9 | i >>> 23) + t << 0) ^ t & ((e = ((e += (t ^ r & (i ^ t)) + f[3] - 187363961) << 14 | e >>> 18) + i << 0) ^ i)) + f[8] + 1163531501) << 20 | r >>> 12) + e << 0, r = ((r += ((i = ((i += (r ^ e & ((t = ((t += (e ^ i & (r ^ e)) + f[13] - 1444681467) << 5 | t >>> 27) + r << 0) ^ r)) + f[2] - 51403784) << 9 | i >>> 23) + t << 0) ^ t & ((e = ((e += (t ^ r & (i ^ t)) + f[7] + 1735328473) << 14 | e >>> 18) + i << 0) ^ i)) + f[12] - 1926607734) << 20 | r >>> 12) + e << 0, r = ((r += ((h = (i = ((i += ((s = r ^ e) ^ (t = ((t += (s ^ i) + f[5] - 378558) << 4 | t >>> 28) + r << 0)) + f[8] - 2022574463) << 11 | i >>> 21) + t << 0) ^ t) ^ (e = ((e += (h ^ r) + f[11] + 1839030562) << 16 | e >>> 16) + i << 0)) + f[14] - 35309556) << 23 | r >>> 9) + e << 0, r = ((r += ((h = (i = ((i += ((s = r ^ e) ^ (t = ((t += (s ^ i) + f[1] - 1530992060) << 4 | t >>> 28) + r << 0)) + f[4] + 1272893353) << 11 | i >>> 21) + t << 0) ^ t) ^ (e = ((e += (h ^ r) + f[7] - 155497632) << 16 | e >>> 16) + i << 0)) + f[10] - 1094730640) << 23 | r >>> 9) + e << 0, r = ((r += ((h = (i = ((i += ((s = r ^ e) ^ (t = ((t += (s ^ i) + f[13] + 681279174) << 4 | t >>> 28) + r << 0)) + f[0] - 358537222) << 11 | i >>> 21) + t << 0) ^ t) ^ (e = ((e += (h ^ r) + f[3] - 722521979) << 16 | e >>> 16) + i << 0)) + f[6] + 76029189) << 23 | r >>> 9) + e << 0, r = ((r += ((h = (i = ((i += ((s = r ^ e) ^ (t = ((t += (s ^ i) + f[9] - 640364487) << 4 | t >>> 28) + r << 0)) + f[12] - 421815835) << 11 | i >>> 21) + t << 0) ^ t) ^ (e = ((e += (h ^ r) + f[15] + 530742520) << 16 | e >>> 16) + i << 0)) + f[2] - 995338651) << 23 | r >>> 9) + e << 0, r = ((r += ((i = ((i += (r ^ ((t = ((t += (e ^ (r | ~i)) + f[0] - 198630844) << 6 | t >>> 26) + r << 0) | ~e)) + f[7] + 1126891415) << 10 | i >>> 22) + t << 0) ^ ((e = ((e += (t ^ (i | ~r)) + f[14] - 1416354905) << 15 | e >>> 17) + i << 0) | ~t)) + f[5] - 57434055) << 21 | r >>> 11) + e << 0, r = ((r += ((i = ((i += (r ^ ((t = ((t += (e ^ (r | ~i)) + f[12] + 1700485571) << 6 | t >>> 26) + r << 0) | ~e)) + f[3] - 1894986606) << 10 | i >>> 22) + t << 0) ^ ((e = ((e += (t ^ (i | ~r)) + f[10] - 1051523) << 15 | e >>> 17) + i << 0) | ~t)) + f[1] - 2054922799) << 21 | r >>> 11) + e << 0, r = ((r += ((i = ((i += (r ^ ((t = ((t += (e ^ (r | ~i)) + f[8] + 1873313359) << 6 | t >>> 26) + r << 0) | ~e)) + f[15] - 30611744) << 10 | i >>> 22) + t << 0) ^ ((e = ((e += (t ^ (i | ~r)) + f[6] - 1560198380) << 15 | e >>> 17) + i << 0) | ~t)) + f[13] + 1309151649) << 21 | r >>> 11) + e << 0, r = ((r += ((i = ((i += (r ^ ((t = ((t += (e ^ (r | ~i)) + f[4] - 145523070) << 6 | t >>> 26) + r << 0) | ~e)) + f[11] - 1120210379) << 10 | i >>> 22) + t << 0) ^ ((e = ((e += (t ^ (i | ~r)) + f[2] + 718787259) << 15 | e >>> 17) + i << 0) | ~t)) + f[9] - 343485551) << 21 | r >>> 11) + e << 0, this.first ? (this.h0 = t + 1732584193 << 0, this.h1 = r - 271733879 << 0, this.h2 = e - 1732584194 << 0, this.h3 = i + 271733878 << 0, this.first = !1) : (this.h0 = this.h0 + t << 0, this.h1 = this.h1 + r << 0, this.h2 = this.h2 + e << 0, this.h3 = this.h3 + i << 0); + }, t.prototype.hex = function () { + this.finalize(); + var t = this.h0, + r = this.h1, + e = this.h2, + i = this.h3; + return n[t >> 4 & 15] + n[15 & t] + n[t >> 12 & 15] + n[t >> 8 & 15] + n[t >> 20 & 15] + n[t >> 16 & 15] + n[t >> 28 & 15] + n[t >> 24 & 15] + n[r >> 4 & 15] + n[15 & r] + n[r >> 12 & 15] + n[r >> 8 & 15] + n[r >> 20 & 15] + n[r >> 16 & 15] + n[r >> 28 & 15] + n[r >> 24 & 15] + n[e >> 4 & 15] + n[15 & e] + n[e >> 12 & 15] + n[e >> 8 & 15] + n[e >> 20 & 15] + n[e >> 16 & 15] + n[e >> 28 & 15] + n[e >> 24 & 15] + n[i >> 4 & 15] + n[15 & i] + n[i >> 12 & 15] + n[i >> 8 & 15] + n[i >> 20 & 15] + n[i >> 16 & 15] + n[i >> 28 & 15] + n[i >> 24 & 15]; + }, t.prototype.toString = t.prototype.hex, t.prototype.digest = function () { + this.finalize(); + var t = this.h0, + r = this.h1, + e = this.h2, + i = this.h3; + return [255 & t, t >> 8 & 255, t >> 16 & 255, t >> 24 & 255, 255 & r, r >> 8 & 255, r >> 16 & 255, r >> 24 & 255, 255 & e, e >> 8 & 255, e >> 16 & 255, e >> 24 & 255, 255 & i, i >> 8 & 255, i >> 16 & 255, i >> 24 & 255]; + }, t.prototype.array = t.prototype.digest, t.prototype.arrayBuffer = function () { + this.finalize(); + var t = new ArrayBuffer(16), + r = new Uint32Array(t); + return r[0] = this.h0, r[1] = this.h1, r[2] = this.h2, r[3] = this.h3, t; + }, t.prototype.buffer = t.prototype.arrayBuffer, t.prototype.base64 = function () { + for (var t, r, e, i = "", s = this.array(), h = 0; h < 15;) t = s[h++], r = s[h++], e = s[h++], i += p[t >>> 2] + p[63 & (t << 4 | r >>> 4)] + p[63 & (r << 2 | e >>> 6)] + p[63 & e]; + + return t = s[h], i += p[t >>> 2] + p[t << 4 & 63] + "=="; + }; + + var _ = v(); + + f ? module.exports = _ : (i.md5 = _, o && define(function () { + return _; + })); +}(); \ No newline at end of file diff --git a/app/components/blufi/other/onfire.js b/app/components/blufi/other/onfire.js new file mode 100644 index 0000000..3a89913 --- /dev/null +++ b/app/components/blufi/other/onfire.js @@ -0,0 +1,113 @@ +/** + Copyright (c) 2016 hustcc http://www.atool.org/ + License: MIT + https://github.com/hustcc/onfire.js + **/ + +const __onfireEvents = {} +let __cnt = 0 // event counter + +const string_str = 'string' +const function_str = 'function' +const hasOwnKey = Function.call.bind(Object.hasOwnProperty) +const slice = Function.call.bind(Array.prototype.slice) + +function _bind(eventName, callback, is_one, context) { + if (typeof eventName !== string_str || typeof callback !== function_str) { + throw new Error('args: ' + string_str + ', ' + function_str + '') + } + + if (!hasOwnKey(__onfireEvents, eventName)) { + __onfireEvents[eventName] = {} + } + + __onfireEvents[eventName][++__cnt] = [callback, is_one, context] + return [eventName, __cnt] +} + +function _each(obj, callback) { + for (const key in obj) { + if (hasOwnKey(obj, key)) callback(key, obj[key]) + } +} + +function on(eventName, callback, context) { + return _bind(eventName, callback, 0, context) +} + +function one(eventName, callback, context) { + return _bind(eventName, callback, 1, context) +} + +function _fire_func(eventName, args) { + if (hasOwnKey(__onfireEvents, eventName)) { + _each(__onfireEvents[eventName], (key, item) => { + item[0].apply(item[2], args) // do the function + if (item[1]) delete __onfireEvents[eventName][key] // when is one, delete it after trigger + }) + } +} + +function fire(eventName) { + // fire events + const args = slice(arguments, 1) + setTimeout(() => { + _fire_func(eventName, args) + }) +} + +function fireSync(eventName) { + _fire_func(eventName, slice(arguments, 1)) +} + +function un(event) { + let eventName, + key, + r = false + const type = typeof event + + if (type === string_str) { + // cancel the event name if exist + if (hasOwnKey(__onfireEvents, event)) { + delete __onfireEvents[event] + return true + } + return false + } else if (type === 'object') { + eventName = event[0] + key = event[1] + + if (hasOwnKey(__onfireEvents, eventName) && hasOwnKey(__onfireEvents[eventName], key)) { + delete __onfireEvents[eventName][key] + return true + } + return false + } else if (type === function_str) { + _each(__onfireEvents, (key1, item1) => { + _each(item1, (key2, item2) => { + if (item2[0] === event) { + delete __onfireEvents[key1][key2] + r = true + } + }) + }) + return r + } + + return true +} + +function clear() { + for (const key in __onfireEvents) { + delete __onfireEvents[key] + } +} + +export default { + on, + one, + un, + fire, + fireSync, + clear, +} diff --git a/app/components/blufi/util.js b/app/components/blufi/util.js new file mode 100644 index 0000000..657a1af --- /dev/null +++ b/app/components/blufi/util.js @@ -0,0 +1,519 @@ +export const SERVICE_TYPE = '_notice_service._tcp.' +export const FACE_DERECT = 'face_detect' +export const FACE_RECOGNIZE = 'face_recognize' +export const FACE_ENROll = 'face_enroll' +export const STOP_STREAM = 'stop_stream' +export const GET_ID = 'get_id' +export const FACE_DELETE = 'face_delete' +export const DELETE_ALL = 'delete_all' +export const ON_STATUS = 1 +export const OFF_STATUS = 0 +export const HTTP_STR = 'http://null:80/control' +export const HTTP_STATUS = 'http://null:80/status' +export const HTTP_STREAM = 'http://null:81/stream' +export const FRAME_CTRL_POSITION_ENCRYPTED = 0 +export const FRAME_CTRL_POSITION_CHECKSUM = 1 +export const FRAME_CTRL_POSITION_DATA_DIRECTION = 2 +export const FRAME_CTRL_POSITION_REQUIRE_ACK = 3 +export const FRAME_CTRL_POSITION_FRAG = 4 +export const DIRECTION_OUTPUT = 0 +export const DIRECTION_INPUT = 1 +export const AES_BASE_IV = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] +export const NEG_SET_SEC_TOTAL_LEN = 0x00 +export const NEG_SET_SEC_ALL_DATA = 0x01 +export const PACKAGE_VALUE = 0x01 +export const SUBTYPE_NEG = 0x00 +export const SUBTYPE_WIFI_MODEl = 0x02 +export const SUBTYPE_END = 0x03 +export const PACKAGE_CONTROL_VALUE = 0x00 +export const SUBTYPE_WIFI_NEG = 0x09 +export const SUBTYPE_SET_SSID = 0x2 +export const SUBTYPE_SET_PWD = 0x3 +export const SUBTYPE_WIFI_LIST_NEG = 11 +export const SUBTYPE_NEGOTIATION_NEG = 0 +export const SUBTYPE_CUSTOM_DATA = 0x13 +export const DH_P = + 'cf5cf5c38419a724957ff5dd323b9c45c3cdd261eb740f69aa94b8bb1a5c96409153bd76b24222d03274e4725a5406092e9e82e9135c643cae98132b0d95f7d65347c68afc1e677da90e51bbab5f5cf429c291b4ba39c6b2dc5e8c7231e46aa7728e87664532cdf547be20c9a3fa8342be6e34371a27c06f7dc0edddd2f86373' +export const DH_G = '02' +export const descSucListEN = [ + 'Bluetooth connecting...', + 'Bluetooth connection successful', + 'Device information is successfully obtained', + 'Attribute information is successfully obtained', + 'Send configuration information...', + 'Configuration information sent successfully', + 'Connection successfully', +] + +export const descFailListEN = [ + 'Bluetooth connection failed', + 'Device information acquisition failed', + 'Attribute information acquisition failed', + 'Configuration information sent failed', + 'Distribution network failed', +] + +export const descSucList = [ + '蓝牙连接...', + '蓝牙连接成功', + '设备信息已成功获取', + '属性信息已成功获取', + '发送配置信息...', + '成功发送配置信息', + '成功连接', +] + +export const descFailList = [ + '蓝牙连接失败', + '设备信息获取失败', + '属性信息获取失败', + '配置信息发送失败', + '网络配置失败', + '蓝牙异常断开', +] + +export const successList = { + 0: 'NULL', + 1: 'STA', + 2: 'SoftAP', + 3: 'SoftAP & STA', +} + +export const failList = { + 0: 'sequence error', + 1: 'checksum error', + 2: 'decrypt error', + 3: 'encrypt error', + 4: 'init security error', + 5: 'dh malloc error', + 6: 'dh param error', + 7: 'read param error', + 8: 'make public error', +} +export const CRC_TB = [ + 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, 0x8108, 0x9129, 0xa14a, 0xb16b, + 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef, 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6, + 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de, 0x2462, 0x3443, 0x0420, 0x1401, + 0x64e6, 0x74c7, 0x44a4, 0x5485, 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d, + 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4, 0xb75b, 0xa77a, 0x9719, 0x8738, + 0xf7df, 0xe7fe, 0xd79d, 0xc7bc, 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823, + 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b, 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, + 0x1a71, 0x0a50, 0x3a33, 0x2a12, 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a, + 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41, 0xedae, 0xfd8f, 0xcdec, 0xddcd, + 0xad2a, 0xbd0b, 0x8d68, 0x9d49, 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70, + 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78, 0x9188, 0x81a9, 0xb1ca, 0xa1eb, + 0xd10c, 0xc12d, 0xf14e, 0xe16f, 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067, + 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e, 0x02b1, 0x1290, 0x22f3, 0x32d2, + 0x4235, 0x5214, 0x6277, 0x7256, 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d, + 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, 0xa7db, 0xb7fa, 0x8799, 0x97b8, + 0xe75f, 0xf77e, 0xc71d, 0xd73c, 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634, + 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab, 0x5844, 0x4865, 0x7806, 0x6827, + 0x18c0, 0x08e1, 0x3882, 0x28a3, 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a, + 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92, 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, + 0xbdaa, 0xad8b, 0x9de8, 0x8dc9, 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1, + 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8, 0x6e17, 0x7e36, 0x4e55, 0x5e74, + 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0, +] //转16进制 +// ArrayBuffer转16进制字符串 +export const ab2hex = buffer => { + const hexArr = Array.from(new Uint8Array(buffer), bit => bit.toString(16).padStart(2, '0')) + return hexArr +} + +// 16进制字符串转普通字符串 +export const hexCharCodeToStr = hexCharCodeStr => { + const trimedStr = hexCharCodeStr.trim() + const rawStr = trimedStr.toLowerCase().startsWith('0x') ? trimedStr.slice(2) : trimedStr + const len = rawStr.length + + if (len % 2 !== 0) { + console.error('Illegal Format ASCII Code!') + return '' + } + + const resultStr = [] + for (let i = 0; i < len; i += 2) { + const curCharCode = parseInt(rawStr.substr(i, 2), 16) + resultStr.push(String.fromCharCode(curCharCode)) + } + + return resultStr.join('') +} + +// 过滤设备列表 +export const filterDevice = (devices, filterName) => { + const re = new RegExp(`^(${filterName})`) + return devices.filter(device => re.test(device.name)) +} + +// 获取类型 +export const getType = (pkgType, subType) => { + return (subType << 2) | pkgType +} + +// Uint8Array转数组 +export const uint8ArrayToArray = uint8Array => { + return Array.from(uint8Array) +} + +// 16进制转二进制数组 +export const hexToBinArray = str => { + const dec = parseInt(str, 16) + let bin = dec.toString(2) + const len = bin.length + + if (len < 8) { + bin = bin.padStart(8, '0') + } + + return bin.split('') +} + +// 16进制字符串转数组 +export const hexByArray = str => { + let formattedStr = str + if (str.length % 2 !== 0) { + formattedStr = '0' + str + } + + const arr = [] + for (let i = 0; i < formattedStr.length; i += 2) { + arr.push(formattedStr.substring(i, i + 2)) + } + + return arr +} + +// 16进制字符串转整型数组 +export const hexByInt = str => { + let formattedStr = str + if (str.length % 2 !== 0) { + formattedStr = '0' + str + } + + const arr = [] + for (let i = 0; i < formattedStr.length; i += 2) { + arr.push(parseInt(formattedStr.substring(i, i + 2), 16)) + } + + return arr +} + +// 排序函数 +export const sortBy = (attr, rev = 1) => { + return (a, b) => { + const aVal = a[attr] + const bVal = b[attr] + + if (aVal < bVal) return rev * -1 + if (aVal > bVal) return rev * 1 + return 0 + } +} + +// 判断是否为空 +export const _isEmpty = str => { + return str === '' || str === null || str === undefined || str === 'null' || str === 'undefined' +} + +// 设置失败背景色 +export const setFailBg = () => { + uni.setNavigationBarColor({ + frontColor: '#ffffff', + backgroundColor: '#737d89', + }) +} + +// 设置成功背景色 +export const setSucBg = () => { + uni.setNavigationBarColor({ + frontColor: '#ffffff', + backgroundColor: '#4d9efb', + }) +} + +// 组装数据格式 +export const writeData = (type, subType, frameCtl, seq, len, data = []) => { + const value = [] + const combinedType = getType(type, subType) + value.push(combinedType, frameCtl, seq, len) + + if (data.length > 0) { + value.push(...data) + } + + return value +} + +// 分包处理 +export const isSubcontractor = (data, checksum, sequence, encrypt) => { + const total = data.length + let lenData = [] + let laveData = [] + let flag = false + + if (total > 16) { + if (checksum) { + lenData = data.slice(0, 12) + laveData = data.slice(12) + } else { + lenData = data.slice(0, 14) + laveData = data.slice(14) + } + + const len1 = (total >> 8) & 0xff + const len2 = total & 0xff + lenData.unshift(len1, len2) + flag = true + } else { + lenData = data + } + + const len = lenData.length + + if (checksum) { + lenData = assemblyChecksum(lenData, len, sequence) + } + + return { + len, + lenData, + laveData, + flag, + } +} + +// 组装校验和 +export const assemblyChecksum = (list, len, sequence) => { + const checkData = [sequence, len, ...list] + const crc = caluCRC(0, checkData) + const checksumByte1 = crc & 0xff + const checksumByte2 = (crc >> 8) & 0xff + + return [...list, checksumByte1, checksumByte2] +} + +// 加密数据 +export const encrypt = (aesjs, md5Key, sequence, data, checksum) => { + const iv = generateAESIV(sequence) + let list = [] + let sumArr = [] + + if (checksum) { + const len = data.length - 2 + list = data.slice(0, len) + sumArr = data.slice(len) + } else { + list = data + } + + const encryptData = uint8ArrayToArray(blueAesEncrypt(aesjs, md5Key, iv, new Uint8Array(list))) + + return [...encryptData, ...sumArr] +} + +// DH加密 +export const blueDH = (p, g, crypto) => { + const client = crypto.createDiffieHellman(p, 'hex', g, 'hex') + client.generateKeys() + return client +} + +// MD5加密 +export const blueMd5 = (md5, key) => { + return md5.array(key) +} + +// AES加密 +export const blueAesEncrypt = (aesjs, mdKey, iv, bytes) => { + const aesOfb = new aesjs.ModeOfOperation.ofb(mdKey, iv) + return aesOfb.encrypt(bytes) +} + +// AES解密 +export const blueAesDecrypt = (aesjs, mdKey, iv, bytes) => { + const aesOfb = new aesjs.ModeOfOperation.ofb(mdKey, iv) + return aesOfb.decrypt(bytes) +} + +// 获取Frame Control值 +export const getFrameCTRLValue = (encrypted, checksum, direction, requireAck, frag) => { + let frame = 0 + + if (encrypted) frame |= 1 << FRAME极狐_CTRL_POSITION_ENCRYPTED + if (checksum) frame |= 1 << FRAME_CTRL_POSITION_CHECKSUM + if (direction === DIRECTION_INPUT) frame |= 1 << FRAME_CTRL_POSITION_DATA_DIRECTION + if (requireAck) frame |= 1 << FRAME_CTRL_POSITION_REQUIRE_ACK + if (frag) frame |= 1 << FRAME_CTRL_POSITION_FRAG + + return frame +} + +// 生成AES IV +export const generateAESIV = sequence => { + return AES_BASE_IV.map((val, i) => (i === 0 ? sequence : val)) +} + +// 计算CRC +export const caluCRC = (crc, pByte) => { + crc = ~crc & 0xffff + + for (const byte of pByte) { + crc = CRC_TB[((crc & 0xffff) >> 8) ^ (byte & 0xff)] ^ ((crc & 0xffff) << 8) + } + + return ~crc & 0xffff +} + +// 发送请求 +export const send = (method, url, data, suc, error) => { + console.log(url) + uni.request({ + url, + data, + header: { + 'Content-Type': 'application/json', + }, + method, + success: res => { + suc?.(res.data) + }, + fail: () => { + error?.() + }, + }) +} + +// 显示加载中 +export const showLoading = msg => { + uni.hideLoading() + uni.showLoading({ + title: msg, + mask: true, + }) +} + +// 显示提示 +export const showToast = msg => { + uni.showToast({ + title: msg, + icon: 'none', + duration: 2000, + }) +} + +// OTA擦除 +export const write_ota_erase = (cmd, len, addr, block_num) => { + return [cmd, 4, 256, 1, 54, 0] +} + +// OTA编程 +export const write_ota_program = (cmd, len, addr, buf) => { + const value = [] + const offest = addr + let sum = 0 + + if (cmd === 0x80) { + for (let i = 0; i < len; i++) { + sum += buf.getUint8(i + offest) + } + } + + let calculatedAddr = addr + 4 * 1024 + calculatedAddr = calculatedAddr / 16 + + value.push(cmd, len, calculatedAddr & 0xff, calculatedAddr >> 8) + + if (cmd === 0x80) { + value.push(sum & 0xff, (sum & 0xff00) >> 8, 0, 0) + } + + for (let i = 0; i < len; i++) { + value.push(buf.getUint8(i + offest)) + } + + return value +} + +// OTA校验和 +export const write_ota_sum = (cmd, len, data) => { + return [ + cmd, + 0, + 0, + 0, + len & 0xff, + (len >> 8) & 0xff, + (len >> 16) & 0xff, + (len >> 24) & 0xff, + data & 0xff, + (data >> 8) & 0xff, + (data >> 16) & 0xff, + (data >> 24) & 0xff, + ] +} + +export default { + _isEmpty, + send, + SERVICE_TYPE, + FACE_DERECT, + FACE_RECOGNIZE, + FACE_ENROll, + STOP_STREAM, + GET_ID, + ON_STATUS, + OFF_STATUS, + HTTP_STR, + HTTP_STATUS, + HTTP_STREAM, + FACE_DELETE, + DELETE_ALL, + ab2hex, + hexCharCodeToStr, + filterDevice, + getType, + hexToBinArray, + hexByArray, + hexByInt, + sortBy, + setFailBg, + setSucBg, + writeData, + isSubcontractor, + getFrameCTRLValue, + blueDH, + blueMd5, + blueAesEncrypt, + blueAesDecrypt, + uint8ArrayToArray, + generateAESIV, + caluCRC, + encrypt, + DH_P, + DH_G, + DIRECTION_OUTPUT, + DIRECTION_INPUT, + NEG_SET_SEC_TOTAL_LEN, + NEG_SET_SEC_ALL_DATA, + PACKAGE_VALUE, + SUBTYPE_NEG, + PACKAGE_CONTROL_VALUE, + SUBTYPE_WIFI_NEG, + SUBTYPE_WIFI_LIST_NEG, + SUBTYPE_NEGOTIATION_NEG, + SUBTYPE_WIFI_MODEl, + SUBTYPE_SET_SSID, + SUBTYPE_SET_PWD, + SUBTYPE_END, + SUBTYPE_CUSTOM_DATA, + descSucList, + descFailList, + successList, + failList, + showToast, + showLoading, + write_ota_sum, + write_ota_program, + write_ota_erase, +} diff --git a/app/components/blufi/xBlufi-wx-impl.js b/app/components/blufi/xBlufi-wx-impl.js new file mode 100644 index 0000000..04ceccf --- /dev/null +++ b/app/components/blufi/xBlufi-wx-impl.js @@ -0,0 +1,1657 @@ +let tempTimer = 0 +let client = null +const timeOut = 20 //超时时间 +let mac_id +var timeId = '' +let sequenceControl = 0 +let sequenceNumber = -1 + +import { mDeviceEvent } from './xBlufi.js' + +import util from './util.js' +import * as aesjs from './crypto/aes.js' + +let self = { + data: { + deviceId: null, + isConnected: false, + failure: false, + value: 0, + desc: '请耐心等待...', + isChecksum: true, + isEncrypt: true, + flagEnd: false, + defaultData: 1, + ssidType: 2, + passwordType: 3, + meshIdType: 3, + ssid: '', + uuid: '', + serviceId: '', + password: '', + meshId: '', + processList: [], + result: [], + service_uuid: '000000FF-0000-1000-8000-00805F9B34FB', + characteristic_write_uuid: '0000FF01-0000-1000-8000-00805F9B34FB', + characteristic_read_uuid: '0000FF02-0000-1000-8000-00805F9B34FB', + customData: null, + md5Key: 0, + }, +} + +function Utf8ArrayToStr(buffer) { + var out, i, len, c + var char2, char3 + var array = new Uint8Array(buffer) + // console.log('array',array); + // console.log('array.ArrayBuffer',array.ArrayBuffer); + // console.log('array[[Uint8Array]]',array.ArrayBuffer); + out = '' + len = array.length + i = 0 + // console.log('len',len); + while (i < len) { + c = array[i++] + switch (c >> 4) { + case 0: + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + // 0xxxxxxx + out += String.fromCharCode(c) + break + case 12: + case 13: + // 110x xxxx 10xx xxxx + char2 = array[i++] + out += String.fromCharCode(((c & 0x1f) << 6) | (char2 & 0x3f)) + break + case 14: + // 1110 xxxx 10xx xxxx 10xx xxxx + char2 = array[i++] + char3 = array[i++] + out += String.fromCharCode( + ((c & 0x0f) << 12) | ((char2 & 0x3f) << 6) | ((char3 & 0x3f) << 0) + ) + break + } + } + // console.log('out',out); + return out +} + +function string2buffer1(str) { + // 首先将字符串转为16进制 + let val = '' + for (let i = 0; i < str.length; i++) { + if (val === '') { + val = str.charCodeAt(i).toString(16) + } else { + val += ',' + str.charCodeAt(i).toString(16) + } + } + // 将16进制转化为ArrayBuffer + return new Uint8Array( + val.match(/[\da-f]{2}/gi).map(function (h) { + return parseInt(h, 16) + }) + ).buffer +} + +function string2buffer(str) { + var bytes = new Array() + for (var i = 0; i < str.length; i++) { + var c = str.charCodeAt(i) + var s = parseInt(c).toString(2) + if (c >= parseInt('000080', 16) && c <= parseInt('0007FF', 16)) { + var af = '' + for (var j = 0; j < 11 - s.length; j++) { + af += '0' + } + af += s + var n1 = parseInt('110' + af.substring(0, 5), 2) + var n2 = parseInt('110' + af.slice(-12), 2) + if (n1 > 127) n1 -= 256 + if (n2 > 127) n2 -= 256 + bytes.push(n1) + bytes.push(n2) + } else if (c >= parseInt('000800', 16) && c <= parseInt('00FFFF', 16)) { + var af = '' + for (var j = 0; j < 16 - s.length; j++) { + af += '0' + } + af += s + var n1 = parseInt('1110' + af.substring(0, 4), 2) + var n2 = parseInt('10' + af.substring(4, 10), 2) + var n3 = parseInt('10' + af.substring(10), 2) + if (n1 > 127) n1 -= 256 + if (n2 > 127) n2 -= 256 + if (n3 > 127) n3 -= 256 + bytes.push(n1) + bytes.push(n2) + bytes.push(n3) + } else if (c >= parseInt('010000', 16) && c <= parseInt('10FFFF', 16)) { + var af = '' + for (var j = 0; j < 21 - s.length; j++) { + af += '0' + } + af += s + var n1 = parseInt('11110' + af.substring(0, 3), 2) + var n2 = parseInt('10' + af.substring(3, 9), 2) + var n3 = parseInt('10' + af.substring(9, 15), 2) + var n4 = parseInt('10' + af.substring(15), 2) + if (n1 > 127) n1 -= 256 + if (n2 > 127) n2 -= 256 + if (n3 > 127) n3 -= 256 + if (n4 > 127) n4 -= 256 + bytes.push(n1) + bytes.push(n2) + bytes.push(n3) + bytes.push(n4) + } else { + bytes.push(c & 0xff) + } + } + + let array = [] + for (let i = 0; i < bytes.length; i++) { + array[i] = bytes[i] + } + let array_int8 = Uint8Array.from(array) + + return array_int8.buffer +} + +function buf2hex(buffer) { + return Array.prototype.map + .call(new Uint8Array(buffer), x => ('00' + x.toString(16)).slice(-2)) + .join('') +} + +function buf2string(buffer) { + var arr = Array.prototype.map.call(new Uint8Array(buffer), x => x) + var str = '' + + for (var i = 0; i < arr.length; i++) { + str += String.fromCharCode(arr[i]) + } + + return str +} + +function getSsids(str) { + var list = [], + strs = str.split(':') + + for (var i = 0; i < strs.length; i++) { + list.push(parseInt(strs[i], 16)) + } + + return list +} + +function getCharCodeat(str) { + var list = [] + + for (var i = 0; i < str.length; i++) { + list.push(str.charCodeAt(i)) + } + + return list +} //判断返回的数据是否加密 + +function isEncrypt(fragNum, list, md5Key) { + var checksum = [], + checkData = [] + + if (fragNum[7] == '1') { + //返回数据加密 + if (fragNum[6] == '1') { + var len = list.length - 2 + list = list.slice(0, len) + } + + var iv = this.generateAESIV(parseInt(list[2], 16)) + + if (fragNum[3] == '0') { + //未分包 + list = list.slice(4) + self.data.flagEnd = true + } else { + //分包 + list = list.slice(6) + } + } else { + //返回数据未加密 + if (fragNum[6] == '1') { + var len = list.length - 2 + list = list.slice(0, len) + } + + if (fragNum[3] == '0') { + //未分包 + list = list.slice(4) + self.data.flagEnd = true + } else { + //分包 + list = list.slice(6) + } + } + + return list +} + +function getSecret(deviceId, serviceId, characteristicId, client, kBytes, pBytes, gBytes, data) { + var obj = [], + frameControl = 0 + sequenceControl = parseInt(sequenceControl) + 1 + + if (!util._isEmpty(data)) { + obj = util.isSubcontractor(data, true, sequenceControl) + frameControl = util.getFrameCTRLValue(false, true, util.DIRECTION_OUTPUT, false, obj.flag) + } else { + data = [] + data.push(util.NEG_SET_SEC_ALL_DATA) + var pLength = pBytes.length + var pLen1 = (pLength >> 8) & 0xff + var pLen2 = pLength & 0xff + data.push(pLen1) + data.push(pLen2) + data = data.concat(pBytes) + var gLength = gBytes.length + var gLen1 = (gLength >> 8) & 0xff + var gLen2 = gLength & 0xff + data.push(gLen1) + data.push(gLen2) + data = data.concat(gBytes) + var kLength = kBytes.length + var kLen1 = (kLength >> 8) & 0xff + var kLen2 = kLength & 0xff + data.push(kLen1) + data.push(kLen2) + data = data.concat(kBytes) + obj = util.isSubcontractor(data, true, sequenceControl) + frameControl = util.getFrameCTRLValue(false, true, util.DIRECTION_OUTPUT, false, obj.flag) + } + + var value = util.writeData( + util.PACKAGE_VALUE, + util.SUBTYPE_NEG, + frameControl, + sequenceControl, + obj.len, + obj.lenData + ) + var typedArray = new Uint8Array(value) + uni.writeBLECharacteristicValue({ + deviceId: deviceId, + serviceId: serviceId, + characteristicId: characteristicId, + value: typedArray.buffer, + success: function (res) { + if (obj.flag) { + getSecret( + deviceId, + serviceId, + characteristicId, + client, + kBytes, + pBytes, + gBytes, + obj.laveData + ) + } + }, + fail: function (res) {}, + }) +} + +function writeDeviceRouterInfoStart(deviceId, serviceId, characteristicId, data) { + // var obj = {}, + // frameControl = 0; + // sequenceControl = parseInt(sequenceControl) + 1; + + // if (!util._isEmpty(data)) { + // obj = util.isSubcontractor(data, self.data.isChecksum, sequenceControl, self.data.isEncrypt); + // frameControl = util.getFrameCTRLValue(self.data.isEncrypt, self.data.isChecksum, util.DIRECTION_OUTPUT, false, obj.flag); + // } else { + // obj = util.isSubcontractor([self.data.defaultData], self.data.isChecksum, sequenceControl, true); + // frameControl = util.getFrameCTRLValue(self.data.isEncrypt, self.data.isChecksum, util.DIRECTION_OUTPUT, false, obj.flag); + // } + + // var defaultData = util.encrypt(aesjs, self.data.md5Key, sequenceControl, obj.lenData, true); + // var value = util.writeData(util.PACKAGE_CONTROL_VALUE, util.SUBTYPE_WIFI_MODEl, frameControl, sequenceControl, obj.len, + // defaultData); + // var typedArray = new Uint8Array(value); + console.log('data.ssid', data.ssid) + console.log('data.password', data.password) + var ssid = string2buffer(data.ssid) + var password = string2buffer(data.password) + console.log('ssid', ssid) + console.log('password', password) + uni.writeBLECharacteristicValue({ + deviceId: deviceId, + serviceId: serviceId, + characteristicId: characteristicId, + value: ssid, + success: function (res) { + uni.writeBLECharacteristicValue({ + deviceId: deviceId, + serviceId: serviceId, + characteristicId: characteristicId, + value: password, + success: function (res) { + // if (obj.flag) { + // writeDeviceRouterInfoStart(deviceId, serviceId, characteristicId, obj.laveData); + // } else { + // writeRouterSsid(deviceId, serviceId, characteristicId, null); + // } + }, + fail: function (res) {}, + }) + + // if (obj.flag) { + // writeDeviceRouterInfoStart(deviceId, serviceId, characteristicId, obj.laveData); + // } else { + // writeRouterSsid(deviceId, serviceId, characteristicId, null); + // } + }, + fail: function (res) {}, + }) +} + +// #define CMD_IAP_PROM 0x80 // IAP编程命令 +// #define CMD_IAP_ERASE 0x81 // IAP擦除命令 +// #define CMD_IAP_VERIFY 0x82 // IAP校验命令 +// #define CMD_IAP_END 0x83 // IAP结束标志 +// #define CMD_IAP_INFO 0x84 // IAP获取设备信息 +// #define CMD_IAP_SUM 0x85 // 校验和 +// #define CMD_OTHER 0xee // 校验和 + +const CMD_IAP_PROM = 0x80 +const CMD_IAP_ERASE = 0x81 +const CMD_IAP_VERIFY = 0x82 +const CMD_IAP_END = 0x83 +const CMD_IAP_INFO = 0x84 +const CMD_IAP_SUM = 0x85 + +function write_cmd_erase(deviceId, serviceId, characteristicId, data) { + var value = util.write_ota_erase(CMD_IAP_ERASE, 4, 0, 0) + var typedArray = new Uint8Array(value) + console.log('送擦除数据') + uni.writeBLECharacteristicValue({ + deviceId: deviceId, + serviceId: serviceId, + characteristicId: characteristicId, + value: typedArray.buffer, + // value: buffer, + success: function (res) { + console.log('送数据成功') + }, + fail: function (res) { + //console.log(257); + }, + }) +} + +function send_ota_data(deviceId, serviceId, characteristicId, data) { + return new Promise(function (resolve, reject) { + uni.writeBLECharacteristicValue({ + deviceId: deviceId, + serviceId: serviceId, + characteristicId: characteristicId, + value: data, + // value: buffer, + success: function (res) { + console.log('送数据成功') + let obj = { + type: mDeviceEvent.XBLUFI_TYPE.TYPE_RECIEVE_MY_DATA, + result: true, + data: 99, + } + mDeviceEvent.notifyDeviceMsgEvent(obj) + + resolve(res) + }, + fail: function (res) { + console.log('送数据失败') + reject(res) + }, + }) + }) +} + +function send_ota_data_num(deviceId, serviceId, characteristicId, data, num) { + return new Promise(function (resolve, reject) { + uni.writeBLECharacteristicValue({ + deviceId: deviceId, + serviceId: serviceId, + characteristicId: characteristicId, + value: data, + // writeType:'writeNoResponse', + // value: buffer, + success: function (res) { + // console.log("送数据成功") + // let obj = { + // 'type': mDeviceEvent + // .XBLUFI_TYPE + // .TYPE_RECIEVE_MY_DATA, + // 'result': true, + // 'data': num + // }; + // mDeviceEvent + // .notifyDeviceMsgEvent( + // obj + // ); + resolve(res) + }, + fail: function (res) { + console.log('送数据失败') + reject(res) + }, + }) + }) +} + +function send_end_data(deviceId, serviceId, characteristicId, data) { + return new Promise(function (resolve, reject) { + uni.writeBLECharacteristicValue({ + deviceId: deviceId, + serviceId: serviceId, + characteristicId: characteristicId, + value: data, + // value: buffer, + success: function (res) { + console.log('送数据成功') + let obj = { + type: mDeviceEvent.XBLUFI_TYPE.TYPE_RECIEVE_MY_DATA, + result: true, + data: 100, + } + mDeviceEvent.notifyDeviceMsgEvent(obj) + resolve(res) + }, + fail: function (res) { + console.log('送数据失败') + reject(res) + }, + }) + }) +} + +function sleep6() { + return new Promise(function (resolve, reject) { + setTimeout(function () { + resolve('ok') + }, 6000) + }) +} + +var StreamBinaryString = function (s) { + this._p = 0 + this._s = this.fromBinaryString(s) +} +StreamBinaryString.prototype = { + constructor: StreamBinaryString, + + fromBinaryString(e) { + var t = e || '' + var f = [] + for (var i = 0; i < t.length; i++) { + f[i] = String.fromCharCode(t.charCodeAt(i) & 255) + } + return f.join('') + }, + + read: function (array, offset, count) { + if (arguments.length == 1) { + var result = this._s.substr(this._p, array) + this._p += array + return result + } else { + var result = 0 + for (var i = 0; i < count; i++) { + array[i] = this._s.charCodeAt(this._p) + this._p += 1 + result++ + } + return result + } + }, + + readByte: function () { + var result = this._s.charCodeAt(this._p) + this._p += 1 + return result + }, + + readInt8: function (signed) { + var result = this._s.charCodeAt(this._p) + if (signed && result > 127) { + result -= 256 + } + this._p += 1 + return result + }, + + readInt16: function () { + var result = (this._s.charCodeAt(this._p) << 8) + this._s.charCodeAt(this._p + 1) + this._p += 2 + return result + }, + + readInt32: function () { + var result = + (this._s.charCodeAt(this._p) << 24) + + (this._s.charCodeAt(this._p + 1) << 16) + + (this._s.charCodeAt(this._p + 2) << 8) + + this._s.charCodeAt(this._p + 3) + this._p += 4 + return result + }, + + eof: function () { + return this._p >= this._s.length + }, +} + +function write_cmd_program(deviceId, serviceId, characteristicId, data) { + var address = 0 + var len = 0 + var buf = 0 + var dv = 0 + let result + console.log('更新122') + const mtu = 212 + uni.setBLEMTU({ + deviceId: self.data.deviceId, + mtu, + success: res => { + console.log('setBLEMTU success>>', res) + }, + fail: res => { + console.log('setBLEMTU fail>>', res) + }, + }) + + var value1 = util.write_ota_erase(CMD_IAP_ERASE, 4, 0, 0) + var typedArray1 = new Uint8Array(value1) + console.log('送擦除数据', result) + send_ota_data(deviceId, serviceId, characteristicId, typedArray1.buffer) + setTimeout(function () { + uni.request({ + // url: 'https://www.zenghi.com/gj/地升幕.bin', //仅为示例,并非真实接口地址。 + //url: 'https://www.zenghi.com/gj/BLE钉钉.bin', //仅为示例,并非真实接口地址。 + // url: 'https://www.zenghi.com/gj/电子秤.bin', //仅为示例,并非真实接口地址。 + responseType: 'arraybuffer', + success: res => { + dv = new DataView(res.data) + var bufferLength = dv.byteLength + var sum = 0 + for (var i = 0; i < bufferLength; i++) { + sum += dv.getUint8(i) + } + result = dv + console.log(result) + console.log('content-length', bufferLength) + console.log('sum', sum) + len = bufferLength + var p_data = 0 + var p_ii = 0 + while (address <= len) { + var offst = 176 + if (address + 176 > len) { + offst = len - address + } + var value = util.write_ota_program(CMD_IAP_PROM, offst, address, result) + var typedArray = new Uint8Array(value) + send_ota_data_num(deviceId, serviceId, characteristicId, typedArray.buffer, address / len) + address = address + 176 + } + + // return new Promise + var value2 = util.write_ota_sum(CMD_IAP_SUM, bufferLength, sum) + var typedArray2 = new Uint8Array(value2) + console.log('送结束数据', value2) + send_ota_data_num(deviceId, serviceId, characteristicId, typedArray2.buffer, 100) + }, + fail: function (res) { + console.log('获取失败') + }, + }) + }, '1000') + + // var requestTask = +} + +function write_cmd_program_zy(deviceId, serviceId, characteristicId, data) { + var address = 0 + var len = 0 + var buf = 0 + var dv = 0 + let result + console.log('更新122') + const mtu = 212 + uni.setBLEMTU({ + deviceId: self.data.deviceId, + mtu, + success: res => { + console.log('setBLEMTU success>>', res) + }, + fail: res => { + console.log('setBLEMTU fail>>', res) + }, + }) + + var value1 = util.write_ota_erase(CMD_IAP_ERASE, 4, 0, 0) + var typedArray1 = new Uint8Array(value1) + console.log('送擦除数据', result) + send_ota_data(deviceId, serviceId, characteristicId, typedArray1.buffer) + setTimeout( + function () { + uni.request({ + url: 'https://www.zenghi.com/gj/地升幕.bin', //仅为示例,并非真实接口地址。 + //url: 'https://www.zenghi.com/gj/BLE钉钉.bin', //仅为示例,并非真实接口地址。 + // url: 'https://www.zenghi.com/gj/电子秤.bin', //仅为示例,并非真实接口地址。 + responseType: 'arraybuffer', + success: res => { + dv = new DataView(res.data) + var bufferLength = dv.byteLength + var sum = 0 + for (var i = 0; i < bufferLength; i++) { + sum += dv.getUint8(i) + } + result = dv + console.log(result) + console.log('content-length', bufferLength) + console.log('sum', sum) + len = bufferLength + var p_data = 0 + var p_ii = 0 + while (address <= len) { + var offst = 176 + if (address + 176 > len) { + offst = len - address + } + var value = util.write_ota_program(CMD_IAP_PROM, offst, address, result) + var typedArray = new Uint8Array(value) + send_ota_data_num( + deviceId, + serviceId, + characteristicId, + typedArray.buffer, + address / len + ) + address = address + 176 + } + + // return new Promise + var value2 = util.write_ota_sum(CMD_IAP_SUM, bufferLength, sum) + var typedArray2 = new Uint8Array(value2) + console.log('送结束数据', value2) + send_ota_data_num(deviceId, serviceId, characteristicId, typedArray2.buffer, 100) + }, + fail: function (res) { + console.log('获取失败') + }, + }) + }, + + '1000' + ) + + // var requestTask = +} + +function write_cmd_program_yk(deviceId, serviceId, characteristicId, data) { + var address = 0 + var len = 0 + var buf = 0 + var dv = 0 + let result + console.log('更新122') + const mtu = 212 + uni.setBLEMTU({ + deviceId: self.data.deviceId, + mtu, + success: res => { + console.log('setBLEMTU success>>', res) + }, + fail: res => { + console.log('setBLEMTU fail>>', res) + }, + }) + + var value1 = util.write_ota_erase(CMD_IAP_ERASE, 4, 0, 0) + var typedArray1 = new Uint8Array(value1) + console.log('送擦除遥控器数据', result) + send_ota_data(deviceId, serviceId, characteristicId, typedArray1.buffer) + setTimeout( + function () { + uni.request({ + url: 'https://www.zenghi.com/gj/遥控器.bin', //仅为示例,并非真实接口地址。 + //url: 'https://www.zenghi.com/gj/BLE钉钉.bin', //仅为示例,并非真实接口地址。 + // url: 'https://www.zenghi.com/gj/电子秤.bin', //仅为示例,并非真实接口地址。 + responseType: 'arraybuffer', + success: res => { + dv = new DataView(res.data) + var bufferLength = dv.byteLength + var sum = 0 + for (var i = 0; i < bufferLength; i++) { + sum += dv.getUint8(i) + } + result = dv + console.log(result) + console.log('content-length', bufferLength) + console.log('sum', sum) + len = bufferLength + var p_data = 0 + var p_ii = 0 + while (address <= len) { + var offst = 176 + if (address + 176 > len) { + offst = len - address + } + var value = util.write_ota_program(CMD_IAP_PROM, offst, address, result) + var typedArray = new Uint8Array(value) + send_ota_data_num( + deviceId, + serviceId, + characteristicId, + typedArray.buffer, + address / len + ) + address = address + 176 + } + + // return new Promise + var value2 = util.write_ota_sum(CMD_IAP_SUM, bufferLength, sum) + var typedArray2 = new Uint8Array(value2) + console.log('送结束数据', value2) + send_ota_data_num(deviceId, serviceId, characteristicId, typedArray2.buffer, 100) + }, + fail: function (res) { + console.log('获取失败') + }, + }) + }, + + '1000' + ) + + // var requestTask = +} + +function write_cmd_program_fg(web, deviceId, serviceId, characteristicId, data) { + var address = 0 + var len = 0 + var buf = 0 + var dv = 0 + let result + console.log('更新122') + const mtu = 212 + uni.setBLEMTU({ + deviceId: self.data.deviceId, + mtu, + success: res => { + console.log('setBLEMTU success>>', res) + }, + fail: res => { + console.log('setBLEMTU fail>>', res) + }, + }) + + var value1 = util.write_ota_erase(CMD_IAP_ERASE, 4, 0, 0) + var typedArray1 = new Uint8Array(value1) + console.log('翻盖柜', web) + send_ota_data(deviceId, serviceId, characteristicId, typedArray1.buffer) + setTimeout( + function () { + uni.request({ + url: web, //仅为示例,并非真实接口地址。 + //url: 'https://www.zenghi.com/gj/BLE钉钉.bin', //仅为示例,并非真实接口地址。 + // url: 'https://www.zenghi.com/gj/电子秤.bin', //仅为示例,并非真实接口地址。 + responseType: 'arraybuffer', + success: res => { + dv = new DataView(res.data) + var bufferLength = dv.byteLength + var sum = 0 + for (var i = 0; i < bufferLength; i++) { + sum += dv.getUint8(i) + } + result = dv + console.log(result) + console.log('content-length', bufferLength) + console.log('sum', sum) + len = bufferLength + var p_data = 0 + var p_ii = 0 + while (address <= len) { + var offst = 176 + if (address + 176 > len) { + offst = len - address + } + var value = util.write_ota_program(CMD_IAP_PROM, offst, address, result) + var typedArray = new Uint8Array(value) + var qq = send_ota_data_num( + deviceId, + serviceId, + characteristicId, + typedArray.buffer, + address / len + ) + + address = address + 176 + console.log('送数据', qq) + } + + // return new Promise + var value2 = util.write_ota_sum(CMD_IAP_SUM, bufferLength, sum) + var typedArray2 = new Uint8Array(value2) + console.log('送结束数据', value2) + send_ota_data_num(deviceId, serviceId, characteristicId, typedArray2.buffer, 100) + }, + fail: function (res) { + console.log('获取失败') + }, + }) + }, + + '1000' + ) + + // var requestTask = +} + +// 模拟一个异步操作,比如网络请求 +function fetchData() { + return new Promise((resolve, reject) => { + setTimeout(() => { + resolve('Data fetched!') + }, 20) // 模拟网络延迟 2 秒 + }) +} + +// 模拟一个异步操作,比如网络请求 +function fetchData2() { + return new Promise((resolve, reject) => { + setTimeout(() => { + resolve('Data fetched!') + }, 2000) // 模拟网络延迟 2 秒 + }) +} + +async function main(res, my_sum, deviceId, serviceId, characteristicId) { + var address = 0 + var len = 0 + var buf = 0 + var dv = 0 + let result + dv = new DataView(res.data) + var bufferLength = dv.byteLength + var sum = 0 + for (var i = 0; i < bufferLength; i++) { + sum += dv.getUint8(i) + } + const data1 = await fetchData2() + result = dv + console.log(result) + console.log('content-length', bufferLength) + console.log('sum', sum) + len = bufferLength + if (sum != my_sum && my_sum != 100) { + console.log('不相等my_sum', my_sum) + return + } + var p_data = 0 + var p_ii = 0 + while (address <= len) { + var offst = 176 + if (address + 176 > len) { + offst = len - address + } + var value = util.write_ota_program(CMD_IAP_PROM, offst, address, result) + var typedArray = new Uint8Array(value) + // console.log("12121") + const data = await fetchData() + + var qq = await send_ota_data_num( + deviceId, + serviceId, + characteristicId, + typedArray.buffer, + address / len + ) + if (qq == false) { + console.log('返回', sum) + return + } + address = address + 176 + // //console.log("送数据", qq) + } + const data = await fetchData() + // return new Promise + var value2 = util.write_ota_sum(CMD_IAP_SUM, bufferLength, sum) + var typedArray2 = new Uint8Array(value2) + // console.log("送结束数据", value2) + send_ota_data_num(deviceId, serviceId, characteristicId, typedArray2.buffer, 100) +} + +function write_cmd_program_sum(web, sum, deviceId, serviceId, characteristicId, data) { + var address = 0 + var len = 0 + var buf = 0 + var dv = 0 + let result + console.log('更新122') + const mtu = 230 + var value1 = util.write_ota_erase(CMD_IAP_ERASE, 4, 0, 0) + var typedArray1 = new Uint8Array(value1) + console.log('翻盖柜', typedArray1) + console.log('翻盖柜', deviceId) + console.log('翻盖柜', serviceId) + console.log('翻盖柜', characteristicId) + send_ota_data(deviceId, serviceId, characteristicId, typedArray1.buffer) + // return; + setTimeout(function () { + uni.request({ + url: web, //仅为示例,并非真实接口地址。 + //url: 'https://www.zenghi.com/gj/BLE钉钉.bin', //仅为示例,并非真实接口地址。 + // url: 'https://www.zenghi.com/gj/电子秤.bin', //仅为示例,并非真实接口地址。 + responseType: 'arraybuffer', + success: res => { + main(res, sum, deviceId, serviceId, characteristicId) + }, + fail: function (res) { + console.log('获取失败') + }, + }) + }, 3000) +} + +function writeCutomsData(deviceId, serviceId, characteristicId, data) { + // var obj = {}, + // frameControl = 0; + // sequenceControl = parseInt(sequenceControl) + 1; + + // if (!util._isEmpty(data)) { + // obj = util.isSubcontractor(data, self.data.isChecksum, sequenceControl, self.data.isEncrypt); + // frameControl = util.getFrameCTRLValue(self.data.isEncrypt, self.data.isChecksum, util.DIRECTION_OUTPUT, false, obj.flag); + // } else { + // var ssidData = getCharCodeat(self.data.customData); + // obj = util.isSubcontractor(ssidData, self.data.isChecksum, sequenceControl, self.data.isEncrypt); + // frameControl = util.getFrameCTRLValue(self.data.isEncrypt, self.data.isChecksum, util.DIRECTION_OUTPUT, false, obj.flag); + // } + + // var defaultData = util.encrypt(aesjs, self.data.md5Key, sequenceControl, obj.lenData, true); + // var value = util.writeData(util.PACKAGE_VALUE, util.SUBTYPE_CUSTOM_DATA, frameControl, sequenceControl, obj.len, + // defaultData); + // var typedArray = new Uint8Array(value); + console.log('开始送数据') + console.log('deviceId', deviceId) + console.log('serviceId', serviceId) + console.log('characteristicId', characteristicId) + // const buffer = new ArrayBuffer(8); + console.log('data', data) + // if (data.indexOf("update") != -1 && data.indexOf("all_update") == -1) { + // console.log("送数update据成功") + // write_cmd_program(deviceId, serviceId, characteristicId, data) + // } + // else if (data.indexOf("upzydsm") != -1 ) { + // console.log("送数upzydsm据成功") + // write_cmd_program_zy(deviceId, serviceId, characteristicId, data) + // } + // else if (data.indexOf("upykdate") != -1 ) { + // console.log("送数upykdate据成功") + // write_cmd_program_yk(deviceId, serviceId, characteristicId, data) + // } + // else if (data.indexOf("fgdate") != -1 ) { + // write_cmd_program_fg('https://fg.zenghi.com/gj/翻盖柜.bin',deviceId, serviceId, characteristicId, data) + // } + + // else if (data.indexOf("ble_go7p") != -1 ) { + // console.log("送数update据成功") + // write_cmd_program7p(deviceId, serviceId, characteristicId, data) + // } + if (data.sum != undefined) { + if (data.http != undefined) { + console.log('升级') + write_cmd_program_sum(data.http, data.sum, deviceId, serviceId, characteristicId, data) + } + } else { + var buffer = string2buffer(data) + uni.writeBLECharacteristicValue({ + deviceId: deviceId, + serviceId: serviceId, + characteristicId: characteristicId, + // value: typedArray.buffer, + value: buffer, + success: function (res) { + console.log('送数据成功') + }, + fail: function (res) { + //console.log(257); + console.log('送数据成功', res) + }, + }) + } +} + +function readCutomsData(deviceId, serviceId, characteristicId) { + console.log('开始送数据') + console.log('deviceId', deviceId) + console.log('serviceId', serviceId) + console.log('characteristicId', characteristicId) + // const buffer = new ArrayBuffer(8); + console.log('buffer', buffer) + var buffer = string2buffer(data) + uni.readBLECharacteristicValue({ + deviceId: deviceId, + serviceId: serviceId, + characteristicId: characteristicId, + // value: typedArray.buffer, + // value: buffer, + success: function (res) { + console.log('读数据成功') + }, + fail: function (res) { + //console.log(257); + }, + }) +} + +function writeRouterSsid(deviceId, serviceId, characteristicId, data) { + var obj = {}, + frameControl = 0 + sequenceControl = parseInt(sequenceControl) + 1 + + if (!util._isEmpty(data)) { + obj = util.isSubcontractor(data, self.data.isChecksum, sequenceControl, self.data.isEncrypt) + frameControl = util.getFrameCTRLValue( + self.data.isEncrypt, + self.data.isChecksum, + util.DIRECTION_OUTPUT, + false, + obj.flag + ) + } else { + var ssidData = getCharCodeat(self.data.ssid) + obj = util.isSubcontractor(ssidData, self.data.isChecksum, sequenceControl, self.data.isEncrypt) + frameControl = util.getFrameCTRLValue( + self.data.isEncrypt, + self.data.isChecksum, + util.DIRECTION_OUTPUT, + false, + obj.flag + ) + } + + var defaultData = util.encrypt(aesjs, self.data.md5Key, sequenceControl, obj.lenData, true) + var value = util.writeData( + util.PACKAGE_VALUE, + util.SUBTYPE_SET_SSID, + frameControl, + sequenceControl, + obj.len, + defaultData + ) + var typedArray = new Uint8Array(value) + uni.writeBLECharacteristicValue({ + deviceId: deviceId, + serviceId: serviceId, + characteristicId: characteristicId, + value: typedArray.buffer, + success: function (res) { + if (obj.flag) { + writeRouterSsid(deviceId, serviceId, characteristicId, obj.laveData) + } else { + writeDevicePwd(deviceId, serviceId, characteristicId, null) + } + }, + fail: function (res) { + //console.log(257); + }, + }) +} + +function writeDevicePwd(deviceId, serviceId, characteristicId, data) { + var obj = {}, + frameControl = 0 + sequenceControl = parseInt(sequenceControl) + 1 + + if (!util._isEmpty(data)) { + obj = util.isSubcontractor(data, self.data.isChecksum, sequenceControl, self.data.isEncrypt) + frameControl = util.getFrameCTRLValue( + self.data.isEncrypt, + self.data.isChecksum, + util.DIRECTION_OUTPUT, + false, + obj.flag + ) + } else { + var pwdData = getCharCodeat(self.data.password) + obj = util.isSubcontractor(pwdData, self.data.isChecksum, sequenceControl, self.data.isEncrypt) + frameControl = util.getFrameCTRLValue( + self.data.isEncrypt, + self.data.isChecksum, + util.DIRECTION_OUTPUT, + false, + obj.flag + ) + } + + var defaultData = util.encrypt(aesjs, self.data.md5Key, sequenceControl, obj.lenData, true) + var value = util.writeData( + util.PACKAGE_VALUE, + util.SUBTYPE_SET_PWD, + frameControl, + sequenceControl, + obj.len, + defaultData + ) + var typedArray = new Uint8Array(value) + uni.writeBLECharacteristicValue({ + deviceId: deviceId, + serviceId: serviceId, + characteristicId: characteristicId, + value: typedArray.buffer, + success: function (res) { + if (obj.flag) { + writeDevicePwd(deviceId, serviceId, characteristicId, obj.laveData) + } else { + writeDeviceEnd(deviceId, serviceId, characteristicId, null) + } + }, + fail: function (res) {}, + }) +} + +function writeDeviceEnd(deviceId, serviceId, characteristicId) { + sequenceControl = parseInt(sequenceControl) + 1 + var frameControl = util.getFrameCTRLValue( + self.data.isEncrypt, + false, + util.DIRECTION_OUTPUT, + false, + false + ) + var value = util.writeData( + self.data.PACKAGE_CONTROL_VALUE, + util.SUBTYPE_END, + frameControl, + sequenceControl, + 0, + null + ) + var typedArray = new Uint8Array(value) + uni.writeBLECharacteristicValue({ + deviceId: deviceId, + serviceId: serviceId, + characteristicId: characteristicId, + value: typedArray.buffer, + success: function (res) {}, + fail: function (res) {}, + }) +} + +function init() { + uni.onBLEConnectionStateChange(function (res) { + let obj = { + type: mDeviceEvent.XBLUFI_TYPE.TYPE_STATUS_CONNECTED, + result: res.connected, + data: res, + } + mDeviceEvent.notifyDeviceMsgEvent(obj) + }) + console.log('初始化!!!!!!!!!!!!') + mDeviceEvent.listenStartDiscoverBle(true, function (options) { + if (options.isStart) { + //第一步检查蓝牙适配器是否可用 + uni.onBluetoothAdapterStateChange(function (res) { + if (!res.available) { + } + }) //第二步关闭适配器,重新来搜索 + + uni.closeBluetoothAdapter({ + complete: function (res) { + console.log('这里蓝牙数据') + wx.openBluetoothAdapter({ + success: function (res) { + uni.getBluetoothAdapterState({ + success: function (res) { + console.log('这里蓝牙数据222') + { + let devicesList = [] + let countsTimes = 0 + uni.onBluetoothDeviceFound(function (devices) { + //剔除重复设备,兼容不同设备API的不同返回值 + var isnotexist = true + + // console.log('devices',devices); + if (devices.deviceId) { + if (devices.advertisData) { + devices.advertisData = buf2hex(devices.advertisData) + } else { + devices.advertisData = '' + } + + for (var i = 0; i < devicesList.length; i++) { + if (devices.deviceId === devicesList[i].deviceId) { + isnotexist = false + } + } + + if (isnotexist) { + devicesList.push(devices) + } + } else if (devices.devices) { + // console.log(devices.devices[0],'4512544') + // if (devices.devices[0].name != '开发板' + // && devices.devices[0].name != 'SMART_R2XS' + // && devices.devices[0].name != 'SMART_R2XS' + // ) + if (devices.devices[0].name.indexOf('CCYK') != -1) { + // if ( devices.devices[0].name.indexOf("gjkg") != -1 ){ + // console.log("跳过",devices.devices[0].name) + // isnotexist = false; + isnotexist = true + } else { + isnotexist = false + } + // isnotexist = true; + + if (devices.devices[0].advertisData) { + devices.devices[0].advertisData = buf2hex(devices.devices[0].advertisData) + } else { + devices.devices[0].advertisData = '' + } + + for (var i = 0; i < devicesList.length; i++) { + if (devices.devices[0].deviceId == devicesList[i].deviceId) { + isnotexist = false + } + } + + if (isnotexist) { + devicesList.push(devices.devices[0]) + // console.log("devicesList",devicesList); + // let obj = { + // 'type': mDeviceEvent.XBLUFI_TYPE.TYPE_GET_DEVICE_LISTS, + // 'result': true, + // 'data': devicesList + // }; + // mDeviceEvent.notifyDeviceMsgEvent(obj); + } + } else if (devices[0]) { + if (devices[0].advertisData) { + devices[0].advertisData = buf2hex(devices[0].advertisData) + } else { + devices[0].advertisData = '' + } + + for (var i = 0; i < devices_list.length; i++) { + if (devices[0].deviceId == devicesList[i].deviceId) { + isnotexist = false + } + } + + if (isnotexist) { + devicesList.push(devices[0]) + // console.log("devicesList",devicesList); + // let obj = { + // 'type': mDeviceEvent.XBLUFI_TYPE.TYPE_GET_DEVICE_LISTS, + // 'result': true, + // 'data': devicesList + // }; + // mDeviceEvent.notifyDeviceMsgEvent(obj); + } + } + + let obj = { + type: mDeviceEvent.XBLUFI_TYPE.TYPE_GET_DEVICE_LISTS, + result: true, + data: devicesList, + } + mDeviceEvent.notifyDeviceMsgEvent(obj) + }) + + uni.startBluetoothDevicesDiscovery({ + allowDuplicatesKey: true, + success: function (res) { + console.log(res, 'true') + let obj = { + type: mDeviceEvent.XBLUFI_TYPE.TYPE_GET_DEVICE_LISTS_START, + result: true, + data: res, + } + mDeviceEvent.notifyDeviceMsgEvent(obj) //开始扫码,清空列表 + + devicesList.length = 0 + }, + fail: function (res) { + console.log(res, 'false') + let obj = { + type: mDeviceEvent.XBLUFI_TYPE.TYPE_GET_DEVICE_LISTS_START, + result: false, + data: res, + } + mDeviceEvent.notifyDeviceMsgEvent(obj) + }, + }) + } + // uni.stopBluetoothDevicesDiscovery({ + // success: function (res) + // fail: function (res) { + // let obj = { + // 'type': mDeviceEvent.XBLUFI_TYPE.TYPE_GET_DEVICE_LISTS_START, + // 'result': false, + // 'data': res + // }; + // mDeviceEvent.notifyDeviceMsgEvent(obj); + // } + // }); + }, + fail: function (res) { + let obj = { + type: mDeviceEvent.XBLUFI_TYPE.TYPE_GET_DEVICE_LISTS_START, + result: false, + data: res, + } + mDeviceEvent.notifyDeviceMsgEvent(obj) + }, + }) + }, + fail: function (res) { + let obj = { + type: mDeviceEvent.XBLUFI_TYPE.TYPE_GET_DEVICE_LISTS_START, + result: false, + data: res, + } + mDeviceEvent.notifyDeviceMsgEvent(obj) + }, + }) + }, + }) + } else { + uni.stopBluetoothDevicesDiscovery({ + success: function (res) { + clearInterval(tempTimer) + let obj = { + type: mDeviceEvent.XBLUFI_TYPE.TYPE_GET_DEVICE_LISTS_STOP, + result: true, + data: res, + } + mDeviceEvent.notifyDeviceMsgEvent(obj) + }, + fail: function (res) { + let obj = { + type: mDeviceEvent.XBLUFI_TYPE.TYPE_GET_DEVICE_LISTS_STOP, + result: false, + data: res, + } + mDeviceEvent.notifyDeviceMsgEvent(obj) + }, + }) + } + }) + mDeviceEvent.listenConnectBle(true, function (options) { + console.log('我要连接?', options.isStart, options) + if (options.isStart) { + uni.createBLEConnection({ + deviceId: options.deviceId, + success: res => { + // console.log(res,'100'); + self.data.deviceId = options.deviceId + mDeviceEvent.notifyDeviceMsgEvent({ + type: mDeviceEvent.XBLUFI_TYPE.TYPE_CONNECTED, + result: true, + data: { + deviceId: options.deviceId, + name: options.name, + }, + }) + }, + fail: res => { + // console.log(res,'1112'); + self.data.deviceId = null + mDeviceEvent.notifyDeviceMsgEvent({ + type: mDeviceEvent.XBLUFI_TYPE.TYPE_CONNECTED, + result: false, + data: res, + }) + }, + }) + } else + uni.closeBLEConnection({ + deviceId: options.deviceId, + success: function (res) { + console.log('断开成功') + self.data.deviceId = null + mDeviceEvent.notifyDeviceMsgEvent({ + type: mDeviceEvent.XBLUFI_TYPE.TYPE_CLOSE_CONNECTED, + result: true, + data: { + deviceId: options.deviceId, + name: options.name, + }, + }) + }, + fail: function (res) { + self.data.deviceId = null + mDeviceEvent.notifyDeviceMsgEvent({ + type: mDeviceEvent.XBLUFI_TYPE.TYPE_CLOSE_CONNECTED, + result: false, + data: res, + }) + }, + }) + }) + mDeviceEvent.listenInitBleEsp32(true, function (options) { + sequenceControl = 0 + sequenceNumber = -1 + self = null + self = { + data: { + deviceId: null, + isConnected: false, + failure: false, + value: 0, + desc: '请耐心等待...', + isChecksum: true, + isEncrypt: true, + flagEnd: false, + defaultData: 1, + ssidType: 2, + passwordType: 3, + meshIdType: 3, + ssid: '', + uuid: '', + serviceId: '', + password: '', + meshId: '', + processList: [], + result: [], + service_uuid: '000000FF-0000-1000-8000-00805F9B34FB', + characteristic_write_uuid: '0000FF01-0000-1000-8000-00805F9B34FB', + characteristic_read_uuid: '0000FF02-0000-1000-8000-00805F9B34FB', + customData: null, + md5Key: 0, + }, + } + let deviceId = options.deviceId + self.data.deviceId = options.deviceId + mac_id = options.deviceId + + setTimeout(() => { + console.log(deviceId, 'deviceIddeviceId') + uni.getBLEDeviceServices({ + // 这里的 deviceId 需要已经通过 createBLEConnection 与对应设备建立链接 + deviceId: deviceId, + success: function (res) { + console.log('服务发现456', res) + var services = res.services + if (services.length > 0) { + for (var i = 0; i < services.length; i++) { + if (services[i].uuid === self.data.service_uuid) { + var serviceId = services[i].uuid + uni.getBLEDeviceCharacteristics({ + // 这里的 deviceId 需要已经通过 createBLEConnection 与对应设备建立链接 + deviceId: deviceId, + serviceId: serviceId, + success: function (res) { + var list = res.characteristics + + if (list.length > 0) { + console.log('list@@@@@@@', list) + for (var i = 0; i < list.length; i++) { + var uuid = list[i].uuid + console.log('uuid', uuid) + if (uuid == self.data.characteristic_write_uuid) { + self.data.serviceId = serviceId + self.data.uuid = uuid + console.log('uuid', uuid) + uni.notifyBLECharacteristicValueChange({ + state: true, + // 启用 notify 功能 + deviceId: deviceId, + serviceId: serviceId, + characteristicId: list[0].uuid, + success: function (res) { + console.log('成功', res) + writeCutomsData( + self.data.deviceId, + self.data.service_uuid, + self.data.characteristic_write_uuid, + 'get_fw' + ) + + setTimeout(() => { + const mtu = 212 + uni.setBLEMTU({ + deviceId: self.data.deviceId, + mtu, + success: res => { + console.log('set1212BLEMTU success>>', res) + }, + fail: res => {}, + }) + }, 1000) + + uni.onBLECharacteristicValueChange(function (res) { + var my_str = Utf8ArrayToStr(res.value) + if (my_str.indexOf('wifi_ok') != -1) { + console.log('获取到wifiok设备数据OK', my_str) + mDeviceEvent.notifyDeviceMsgEvent({ + type: mDeviceEvent.XBLUFI_TYPE.TYPE_CONNECT_ROUTER_RESULT, + result: true, + data: { + progress: 100, + ssid: '', + }, + }) + } else if (my_str.indexOf('wifi_err') != -1) { + console.log('获取到设备数据失败', my_str) + mDeviceEvent.notifyDeviceMsgEvent({ + type: mDeviceEvent.XBLUFI_TYPE.TYPE_CONNECT_ROUTER_RESULT, + result: false, + data: { + progress: 0, + ssid: '', + }, + }) + } else { + let obj = { + type: mDeviceEvent.XBLUFI_TYPE.TYPE_RECIEVE_CUSTON_DATA, + result: true, + data: my_str, + } + mDeviceEvent.notifyDeviceMsgEvent(obj) + } + }) + }, + fail: function (res) { + console.log('监听', res) + uni.onBLECharacteristicValueChange(function (res) { + var my_str = Utf8ArrayToStr(res.value) + { + let obj = { + type: mDeviceEvent.XBLUFI_TYPE.TYPE_RECIEVE_CUSTON_DATA, + result: true, + data: my_str, + } + mDeviceEvent.notifyDeviceMsgEvent(obj) + } + }) + + // let obj = { + // 'type': mDeviceEvent.XBLUFI_TYPE.TYPE_INIT_ESP32_RESULT, + // 'result': false, + // 'data': res + // }; + // mDeviceEvent.notifyDeviceMsgEvent(obj); + }, + }) + } + } + } + }, + fail: function (res) { + // let obj = { + // 'type': mDeviceEvent.XBLUFI_TYPE.TYPE_INIT_ESP32_RESULT, + // 'result': false, + // 'data': res + // }; + // mDeviceEvent.notifyDeviceMsgEvent(obj); + // console.log("fail getBLEDeviceCharacteristics:" + JSON.stringify(res)); + }, + }) + break + } + } + } else { + } + }, + fail: function (res) { + let obj = { + type: mDeviceEvent.XBLUFI_TYPE.TYPE_INIT_ESP32_RESULT, + result: false, + data: res, + } + mDeviceEvent.notifyDeviceMsgEvent(obj) + console.log('fail getBLEDeviceServices:' + JSON.stringify(res)) + }, + }) + }, 2000) + }) + mDeviceEvent.listenSendRouterSsidAndPassword(true, function (options) { + self.data.password = options.password + self.data.ssid = options.ssid + writeDeviceRouterInfoStart( + self.data.deviceId, + self.data.service_uuid, + self.data.characteristic_write_uuid, + self.data + ) + }) + mDeviceEvent.listenSendCustomData(true, function (options) { + self.data.customData = options.customData + // writeCutomsData(self.data.deviceId, self.data.service_uuid, self.data.characteristic_write_uuid, null); + writeCutomsData( + mac_id, + self.data.service_uuid, + self.data.characteristic_write_uuid, + self.data.customData + ) + }) +} + +/****************************** 对外 ***************************************/ + +export default { + init: init, +} diff --git a/app/components/blufi/xBlufi.js b/app/components/blufi/xBlufi.js new file mode 100644 index 0000000..5136cbb --- /dev/null +++ b/app/components/blufi/xBlufi.js @@ -0,0 +1,169 @@ +import mOnFire from './other/onfire.js' +import $wxBlufiImpl from './xBlufi-wx-impl.js' // 0表示阿里支付宝小程序 1表示微信小程序 + +export const XMQTT_SYSTEM = { + Alis: 0, + WeChat: 1, +} + +export const XBLUFI_TYPE = { + TYPE_STATUS_CONNECTED: '-2', // 设备连接状态回调 + TYPE_CLOSE_CONNECTED: '-1', // 主动关闭连接 + TYPE_CONNECTED: '0', // 主动连接 + TYPE_GET_DEVICE_LISTS: '1', // 发现设备列表回调 + TYPE_INIT_ESP32_RESULT: '2', + TYPE_RECIEVE_CUSTON_DATA: '3', // 接收到自定义数据 + TYPE_CONNECT_ROUTER_RESULT: '4', + TYPE_RECIEVE_MY_DATA: '5', + TYPE_GET_DEVICE_LISTS_START: '41', // 发现设备列表回调开始 + TYPE_GET_DEVICE_LISTS_STOP: '42', // 停止发现设备列表回调 +} + +export const OnFireEvent = { + EVENT_START_DISCONORY: '0', // 蓝牙状态事件 发现设备 + EVENT_CONNECT_DISCONNECT: '1', // 通知连接或断开蓝牙 + EVENT_NOFITY_INIT_ESP32: '3', // 通知获取蓝牙设备的服务uuid列表等初始化工作 + ENENT_ALL: '6', + EVENT_NOFITY_SEND_ROUTER_SSID_PASSWORD: '50', // 通知发送路由器的ssid和password + EVENT_NOFITY_SEND_CUSTON_DATA: '51', // 通知发送自定义数据 +} + +let once = 0 +let myPath = '' + +/** + * 初始化 + * @param {number} type 参考 XMQTT_SYSTEM + */ +export const initXBlufi = type => { + if (type === XMQTT_SYSTEM.WeChat && once === 0) { + console.log('初始化@@@@@@@!!!!!!!!!!!!') + once = 1 + $wxBlufiImpl.init() + } +} + +export const setPath = path => { + myPath = path +} + +export const getPath = () => myPath + +export const notifyDeviceMsgEvent = options => { + mOnFire.fire(OnFireEvent.ENENT_ALL, options) +} + +export const listenDeviceMsgEvent = (isSetListener, callback) => { + isSetListener ? mOnFire.on(OnFireEvent.ENENT_ALL, callback) : mOnFire.un(callback) +} + +/** + * 开始或停止发现附近的蓝牙设备 + * @param {Object} options 连接参数 {"isStart":true , "filter":"名字过滤"} :是否开始发现设备 + */ +export const notifyStartDiscoverBle = options => { + mOnFire.fire(OnFireEvent.EVENT_START_DISCONORY, options) +} + +/** + * 监听开始/停止发现设备事件 + * @param {boolean} isSetListener 是否设置监听 + * @param {Function} callback 回调函数 + */ +export const listenStartDiscoverBle = (isSetListener, callback) => { + isSetListener ? mOnFire.on(OnFireEvent.EVENT_START_DISCONORY, callback) : mOnFire.un(callback) +} + +/** + * 连接或断开蓝牙连接 + * @param {Object} options 连接参数 {"connect":true,"deviceID":"设备id,蓝牙发现列表获取"} + */ +export const notifyConnectBle = options => { + mOnFire.fire(OnFireEvent.EVENT_CONNECT_DISCONNECT, options) +} + +export const listenConnectBle = (isSetListener, callback) => { + isSetListener ? mOnFire.on(OnFireEvent.EVENT_CONNECT_DISCONNECT, callback) : mOnFire.un(callback) +} + +/** + * 通知初始化获取设备的服务列表等信息 + * @param {Object} options 连接参数 {"deviceId":"设备的设备id"} + */ +export const notifyInitBleEsp32 = options => { + mOnFire.fire(OnFireEvent.EVENT_NOFITY_INIT_ESP32, options) +} + +export const listenInitBleEsp32 = (isSetListener, callback) => { + isSetListener ? mOnFire.on(OnFireEvent.EVENT_NOFITY_INIT_ESP32, callback) : mOnFire.un(callback) +} + +/** + * 发送要连接的路由器的ssid和密码 + * @param {Object} options 连接参数 {"deviceId":"设备的设备id","serverId":"服务id","characterId":"通道","ssid":"路由器名字","password":"密码"} + */ +export const notifySendRouterSsidAndPassword = options => { + mOnFire.fire(OnFireEvent.EVENT_NOFITY_SEND_ROUTER_SSID_PASSWORD, options) +} + +export const listenSendRouterSsidAndPassword = (isSetListener, callback) => { + isSetListener + ? mOnFire.on(OnFireEvent.EVENT_NOFITY_SEND_ROUTER_SSID_PASSWORD, callback) + : mOnFire.un(callback) +} + +/** + * 发送自定义数据 + * @param {Object} options 连接参数 {"deviceId":"设备的设备id","serverId":"服务id","characterId":"通道","customData":"自定义数据""} + */ +export const notifySendCustomData = options => { + mOnFire.fire(OnFireEvent.EVENT_NOFITY_SEND_CUSTON_DATA, options) +} + +export const listenSendCustomData = (isSetListener, callback) => { + isSetListener + ? mOnFire.on(OnFireEvent.EVENT_NOFITY_SEND_CUSTON_DATA, callback) + : mOnFire.un(callback) +} + +export const mDeviceEvent = { + XMQTT_SYSTEM, + XBLUFI_TYPE, + OnFireEvent, + notifyDeviceMsgEvent, + listenDeviceMsgEvent, + notifyStartDiscoverBle, + listenStartDiscoverBle, + notifyConnectBle, + listenConnectBle, + notifyInitBleEsp32, + listenInitBleEsp32, + notifySendRouterSsidAndPassword, + listenSendRouterSsidAndPassword, + notifySendCustomData, + listenSendCustomData, + initXBlufi, + setPath, + getPath, +} + +export default { + XMQTT_SYSTEM, + XBLUFI_TYPE, + OnFireEvent, + notifyDeviceMsgEvent, + listenDeviceMsgEvent, + notifyStartDiscoverBle, + listenStartDiscoverBle, + notifyConnectBle, + listenConnectBle, + notifyInitBleEsp32, + listenInitBleEsp32, + notifySendRouterSsidAndPassword, + listenSendRouterSsidAndPassword, + notifySendCustomData, + listenSendCustomData, + initXBlufi, + setPath, + getPath, +} diff --git a/app/components/index/item5.vue b/app/components/index/item5.vue index fab157c..6313f66 100644 --- a/app/components/index/item5.vue +++ b/app/components/index/item5.vue @@ -4,14 +4,15 @@
- 技术背景 -
+
- +
@@ -32,38 +33,40 @@
- +
-
-
- +
+ -
- -
+
-
@@ -73,10 +76,10 @@
-

{{ paragraph }}

@@ -86,14 +89,14 @@

主要特性:

    -
  • - {{ feature }}
  • @@ -102,14 +105,14 @@
    - {{ pageData.learnMoreButton.text }} -
    diff --git a/app/layouts/empty.vue b/app/layouts/empty.vue new file mode 100644 index 0000000..1e3ff54 --- /dev/null +++ b/app/layouts/empty.vue @@ -0,0 +1,12 @@ + + + diff --git a/app/pages/IoTSolutions/blueToothTest.vue b/app/pages/IoTSolutions/blueToothTest.vue new file mode 100644 index 0000000..aca7a64 --- /dev/null +++ b/app/pages/IoTSolutions/blueToothTest.vue @@ -0,0 +1,15 @@ + + + + + \ No newline at end of file