├── .github ├── dependabot.yml └── workflows │ └── nodejs.yml ├── .gitignore ├── LICENSE ├── README.md ├── as-pect.config.js ├── assembly ├── __tests__ │ ├── as-pect.d.ts │ ├── common.include.ts │ ├── faEdPoint.spec.ts │ ├── faRistrettoPoint.spec.ts │ ├── faScalar.spec.ts │ ├── hash.spec.ts │ ├── signEd25519.spec.ts │ ├── signRistretto.spec.ts │ └── utils.spec.ts ├── crypto.ts ├── precomp.ts └── tsconfig.json ├── logo.png ├── package.json ├── tsfmt.json └── tslint.json /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: npm 4 | directory: "/" 5 | schedule: 6 | interval: daily 7 | time: "04:00" 8 | open-pull-requests-limit: 10 9 | -------------------------------------------------------------------------------- /.github/workflows/nodejs.yml: -------------------------------------------------------------------------------- 1 | name: GitHub Actions CI 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | pull_request: 7 | branches: [ master ] 8 | 9 | jobs: 10 | build: 11 | 12 | runs-on: ubuntu-latest 13 | 14 | strategy: 15 | matrix: 16 | node-version: [13.x] 17 | 18 | steps: 19 | - uses: actions/checkout@v2 20 | - name: Use Node.js ${{ matrix.node-version }} 21 | uses: actions/setup-node@v1 22 | with: 23 | node-version: ${{ matrix.node-version }} 24 | - run: npm i 25 | - run: npm ci 26 | - run: npm run build --if-present 27 | - run: npm test 28 | env: 29 | CI: true 30 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | #*# 2 | *~ 3 | build/* 4 | node_modules 5 | 6 | package-lock.json 7 | yarn.lock 8 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018-2021 Frank Denis 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![npm version](https://badge.fury.io/js/wasm-crypto.svg)](https://www.npmjs.com/package/wasm-crypto) 2 | [![GitHub Actions CI](https://github.com/jedisct1/wasm-crypto/workflows/GitHub%20Actions%20CI/badge.svg)](https://github.com/jedisct1/wasm-crypto/actions) 3 | 4 | # ![wasm-crypto](https://raw.github.com/jedisct1/wasm-crypto/master/logo.png) 5 | 6 | A WebAssembly (via AssemblyScript) set of cryptographic primitives for building authentication and key exchange protocols. 7 | 8 | Currently provides: 9 | 10 | - [RFC 8032](https://tools.ietf.org/html/rfc8032)/libsodium-compatible detached [EdDSA signatures](https://doc.libsodium.org/public-key_cryptography/public-key_signatures) 11 | - Ed25519 deterministic and non-deterministic signatures with cofactored verification. 12 | - Deterministic and non-deterministic signatures over the Ristretto group. 13 | - Hashing (simple + multi-parts) 14 | - Authentication (HMAC-SHA-512, HMAC-SHA-256) 15 | - Point validation, point addition, scalar multiplication with and without clamping over Edwards25519 using the standard Ed25519 point encoding. 16 | - Fast encoded element validation, hash-to-group, addition, scalar multiplication over the [Ristretto](https://ristretto.group) prime-order group. 17 | - Scalar reduction, scalar multiplication, scalar inversion mod the order of the prime-order groups for multiparty computation and oblivious pseudorandom functions. 18 | - Constant-time comparison and encoding. 19 | 20 | [Example use case](https://github.com/jedisct1/fastly-terrarium-examples/tree/master/access_control_example). -------------------------------------------------------------------------------- /as-pect.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | /** 3 | * A set of globs passed to the glob package that qualify typescript files for testing. 4 | */ 5 | include: ["assembly/__tests__/**/*.spec.ts"], 6 | /** 7 | * A set of globs passed to the glob package that quality files to be added to each test. 8 | */ 9 | add: ["assembly/__tests__/**/*.include.ts"], 10 | /** 11 | * All the compiler flags needed for this test suite. Make sure that a binary file is output. 12 | */ 13 | flags: { 14 | "--debug": [], 15 | 16 | /** This is required. Do not change this. */ 17 | "--binaryFile": ["output.wasm"], 18 | }, 19 | /** 20 | * A set of regexp that will disclude source files from testing. 21 | */ 22 | disclude: [], 23 | /** 24 | * Add your required AssemblyScript imports here. 25 | */ 26 | imports: {}, 27 | /** 28 | * Add a custom reporter here if you want one 29 | */ 30 | // reporter: new CustomReporter(), 31 | }; 32 | -------------------------------------------------------------------------------- /assembly/__tests__/as-pect.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /assembly/__tests__/common.include.ts: -------------------------------------------------------------------------------- 1 | import "../crypto"; -------------------------------------------------------------------------------- /assembly/__tests__/faEdPoint.spec.ts: -------------------------------------------------------------------------------- 1 | describe("Ed25519 arithmetic", (): void => { 2 | it("should perform operations on Ed25519", (): void => { 3 | let scalar = new Uint8Array(32); 4 | for (let i = 0; i < 32; i++) { 5 | scalar[i] = i; 6 | } 7 | let p = faEdBasePointMult(scalar)!; 8 | expect(faEdPointValidate(p)).toBeTruthy(); 9 | p[0]++; 10 | expect(faEdPointValidate(p)).toBeFalsy(); 11 | p[0]--; 12 | 13 | let scalar2 = new Uint8Array(32); 14 | for (let i = 0; i < 32; i++) { 15 | scalar2[i] = ~i; 16 | } 17 | let p2 = faEdBasePointMult(scalar)!; 18 | expect(faEdPointValidate(p2)).toBeTruthy(); 19 | p2[0]++; 20 | expect(faEdPointValidate(p2)).toBeFalsy(); 21 | p2[0]--; 22 | 23 | let p3 = faEdPointAdd(p, p)!; 24 | p3 = faEdPointAdd(p3, p3)!; 25 | 26 | let scalar3 = new Uint8Array(32); 27 | scalar3[0] = 4; 28 | let p4 = faEdPointMult(scalar3, p)!; 29 | expect(equals(p3, p4)).toBeTruthy(); 30 | 31 | p3 = faEdPointSub(p3, p)!; 32 | p3 = faEdPointSub(p3, p)!; 33 | p3 = faEdPointSub(p3, p)!; 34 | expect(equals(p3, p)).toBeTruthy(); 35 | 36 | let zero = faEdPointSub(p3, p)!; 37 | expect(faEdPointValidate(zero)).toBeFalsy(); 38 | }); 39 | 40 | it("should perform operations on Ed25519 (with clamping)", (): void => { 41 | let scalar = new Uint8Array(32); 42 | for (let i = 0; i < 32; i++) { 43 | scalar[i] = i; 44 | } 45 | let p = faEdBasePointMultClamp(scalar)!; 46 | expect(faEdPointValidate(p)).toBeTruthy(); 47 | p[0]++; 48 | expect(faEdPointValidate(p)).toBeTruthy(); 49 | p[0]--; 50 | 51 | let scalar2 = new Uint8Array(32); 52 | for (let i = 0; i < 32; i++) { 53 | scalar2[i] = ~i; 54 | } 55 | let p2 = faEdBasePointMultClamp(scalar)!; 56 | expect(faEdPointValidate(p2)).toBeTruthy(); 57 | p2[0]++; 58 | expect(faEdPointValidate(p2)).toBeTruthy(); 59 | p2[0]--; 60 | 61 | let p3 = faEdPointAdd(p, p)!; 62 | p3 = faEdPointAdd(p3, p3)!; 63 | 64 | let scalar3 = new Uint8Array(32); 65 | scalar3[0] = 4; 66 | let p4 = faEdPointMultClamp(scalar3, p)!; 67 | expect(equals(p3, p4)).toBeFalsy(); 68 | 69 | p3 = faEdPointSub(p3, p)!; 70 | p3 = faEdPointSub(p3, p)!; 71 | p3 = faEdPointSub(p3, p)!; 72 | expect(equals(p3, p)).toBeTruthy(); 73 | 74 | let zero = faEdPointSub(p3, p)!; 75 | expect(faEdPointValidate(zero)).toBeFalsy(); 76 | }); 77 | }); 78 | -------------------------------------------------------------------------------- /assembly/__tests__/faRistrettoPoint.spec.ts: -------------------------------------------------------------------------------- 1 | describe("Ristretto arithmetic", (): void => { 2 | it("should perform operations on Ristretto", (): void => { 3 | let uniform = new Uint8Array(64); 4 | for (let i = 0; i < 64; i++) { 5 | uniform[i] = i; 6 | } 7 | let p = faPointFromHash(uniform); 8 | expect(faPointValidate(p)).toBeTruthy(); 9 | p[0]++; 10 | expect(faPointValidate(p)).toBeFalsy(); 11 | p[0]--; 12 | 13 | let uniform2 = new Uint8Array(64); 14 | for (let i = 0; i < 64; i++) { 15 | uniform2[i] = ~i; 16 | } 17 | let p2 = faPointFromHash(uniform2); 18 | expect(faPointValidate(p2)).toBeTruthy(); 19 | p2[0]++; 20 | expect(faPointValidate(p2)).toBeFalsy(); 21 | p2[0]--; 22 | 23 | let p3 = faPointAdd(p, p)!; 24 | p3 = faPointAdd(p3, p3)!; 25 | 26 | let scalar3 = new Uint8Array(32); 27 | scalar3[0] = 4; 28 | let p4 = faPointMult(scalar3, p)!; 29 | expect(equals(p3, p4)).toBeTruthy(); 30 | 31 | p3 = faPointSub(p3, p)!; 32 | p3 = faPointSub(p3, p)!; 33 | p3 = faPointSub(p3, p)!; 34 | expect(equals(p3, p)).toBeTruthy(); 35 | 36 | let zero = faPointSub(p3, p)!; 37 | expect(faPointValidate(zero)).toBeFalsy(); 38 | }); 39 | }); 40 | -------------------------------------------------------------------------------- /assembly/__tests__/faScalar.spec.ts: -------------------------------------------------------------------------------- 1 | describe("field arithmetic using scalars", (): void => { 2 | it("should add, sub and multiply", (): void => { 3 | let x = new Uint8Array(32); 4 | let y = new Uint8Array(32); 5 | for (let i = 0; i < 32; i++) { 6 | x[i] = i; 7 | y[i] = i + 0x42; 8 | } 9 | expect(faScalarIsCanonical(x)).toBeFalsy(); 10 | expect(faScalarIsCanonical(y)).toBeFalsy(); 11 | 12 | let x_plus_y_times_10 = faScalarAdd(x, y); 13 | for (let i = 0; i < 9; i++) { 14 | x_plus_y_times_10 = faScalarAdd(x_plus_y_times_10, y); 15 | } 16 | 17 | let _10 = new Uint8Array(32); 18 | _10[0] = 10; 19 | let y10 = faScalarMult(y, _10); 20 | let x_plus_y10 = faScalarAdd(x, y10); 21 | expect(equals(x_plus_y_times_10, x_plus_y10)).toBeTruthy(); 22 | 23 | let one = new Uint8Array(32); 24 | one[0] = 1; 25 | let minus_one = faScalarNegate(one); 26 | expect(minus_one[0]).toBe(236); 27 | expect(minus_one[31]).toBe(16); 28 | 29 | let zero = new Uint8Array(32); 30 | let minus_one2 = faScalarSub(zero, one); 31 | expect(equals(minus_one, minus_one2)).toBeTruthy(); 32 | 33 | let x2 = faScalarSub(x_plus_y10, y10); 34 | expect(faScalarIsCanonical(x2)).toBeTruthy(); 35 | x = faScalarReduce(x); 36 | expect(faScalarIsCanonical(x)).toBeTruthy(); 37 | expect(equals(x, x2)).toBeTruthy(); 38 | 39 | let x_inv = faScalarInverse(x); 40 | let x_x_inv = faScalarMult(x, x_inv); 41 | expect(equals(x_x_inv, one)).toBeTruthy(); 42 | 43 | let x_comp = faScalarComplement(x); 44 | let x_plus_x_comp = faScalarAdd(x, x_comp); 45 | expect(equals(x_plus_x_comp, one)).toBeTruthy(); 46 | 47 | let x_neg = faScalarNegate(x); 48 | let x_plus_x_neg = faScalarAdd(x, x_neg); 49 | expect(equals(x_plus_x_neg, zero)).toBeTruthy(); 50 | 51 | let cof = faScalarCofactorMult(one); 52 | expect(cof[0]).toBe(8); 53 | 54 | expect(faScalarIsCanonical(cof)).toBeTruthy(); 55 | }); 56 | }); 57 | -------------------------------------------------------------------------------- /assembly/__tests__/hash.spec.ts: -------------------------------------------------------------------------------- 1 | import { bin2hex, hash, hashInit, hashUpdate, hashFinal, hmac, sha256Hash, sha256HashInit, sha256HashUpdate, sha256HashFinal, sha256Hmac } from "../crypto"; 2 | 3 | describe("hashing (SHA-512)", (): void => { 4 | it("should compute the hash of an empty string", (): void => { 5 | let h = hashFinal(hashInit()); 6 | let hex = bin2hex(h); 7 | expect(hex).toBe( 8 | "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e" 9 | ); 10 | }); 11 | 12 | it("should compute the hash of a non-empty string (SHA-512)", (): void => { 13 | let msg = Uint8Array.wrap(String.UTF8.encode("*")); 14 | let h = hash(msg) 15 | let hex = bin2hex(h); 16 | expect(hex).toBe( 17 | "7846cdd4c2b9052768b8901640122e5282e0b833a6a58312a7763472d448ee23781c7f08d90793fdfe71ffe74238cf6e4aa778cc9bb8cec03ea7268d4893a502" 18 | ); 19 | }); 20 | 21 | it("should compute the hash of a larger string (SHA-512)", (): void => { 22 | let msg = Uint8Array.wrap(String.UTF8.encode("This is a test vector for the hash function, with an input larger than the block size")); 23 | let h = hash(msg) 24 | let hex = bin2hex(h); 25 | expect(hex).toBe( 26 | "59dac56c13b43989000f645d7f0660500d043c9758d05f0afc104729279e6458a6a4b56bc7f3051342aa38663ae06b3895b65e0512d5c0037c56cc84746d36a3" 27 | ); 28 | }); 29 | 30 | it("should compute the hash of a split string (SHA-512)", (): void => { 31 | let msg1 = Uint8Array.wrap(String.UTF8.encode("This is a test vector for the hash function, ")); 32 | let msg2 = Uint8Array.wrap(String.UTF8.encode("with an input larger than the block size")); 33 | let st = hashInit(); 34 | hashUpdate(st, msg1); 35 | hashUpdate(st, msg2); 36 | let h = hashFinal(st); 37 | let hex = bin2hex(h); 38 | expect(hex).toBe( 39 | "59dac56c13b43989000f645d7f0660500d043c9758d05f0afc104729279e6458a6a4b56bc7f3051342aa38663ae06b3895b65e0512d5c0037c56cc84746d36a3" 40 | ); 41 | }); 42 | 43 | it("should compute the hash of a block-aligned split string (SHA-512)", (): void => { 44 | let msg1 = Uint8Array.wrap(String.UTF8.encode("This is a test vector for the hash function with a length of 64<")); 45 | let msg2 = Uint8Array.wrap(String.UTF8.encode(">This is a test vector for the hash function with a length of 64")); 46 | let st = hashInit(); 47 | hashUpdate(st, msg1); 48 | hashUpdate(st, msg2); 49 | let h = hashFinal(st); 50 | let hex = bin2hex(h); 51 | expect(hex).toBe( 52 | "1d0ad8f26d8df0a560d503d939062b267da4f8a309a3d5a2111609eb553c64d7f7582d10b18b4af31dd1a8ac90d3aaedeb035fb07423377fd6dcaf284ef63930" 53 | ); 54 | }); 55 | 56 | it("should compute a HMAC (SHA-512)", (): void => { 57 | let msg = Uint8Array.wrap(String.UTF8.encode("test")); 58 | let key = Uint8Array.wrap(String.UTF8.encode("test")); 59 | let h = hmac(msg, key); 60 | let hex = bin2hex(h); 61 | expect(hex).toBe( 62 | "9ba1f63365a6caf66e46348f43cdef956015bea997adeb06e69007ee3ff517df10fc5eb860da3d43b82c2a040c931119d2dfc6d08e253742293a868cc2d82015" 63 | ); 64 | }); 65 | }); 66 | 67 | 68 | describe("hashing (SHA-256)", (): void => { 69 | it("should compute the hash of an empty string", (): void => { 70 | let h = sha256HashFinal(sha256HashInit()); 71 | let hex = bin2hex(h); 72 | expect(hex).toBe( 73 | "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" 74 | ); 75 | }); 76 | 77 | it("should compute the hash of a non-empty string (SHA-256)", (): void => { 78 | let msg = Uint8Array.wrap(String.UTF8.encode("*")); 79 | let h = sha256Hash(msg) 80 | let hex = bin2hex(h); 81 | expect(hex).toBe( 82 | "684888c0ebb17f374298b65ee2807526c066094c701bcc7ebbe1c1095f494fc1" 83 | ); 84 | }); 85 | 86 | it("should compute the hash of a larger string (SHA-256)", (): void => { 87 | let msg = Uint8Array.wrap(String.UTF8.encode("This is a test vector for the hash function, with an input larger than the block size")); 88 | let h = sha256Hash(msg) 89 | let hex = bin2hex(h); 90 | expect(hex).toBe( 91 | "e8f6644d4670f6c3d817af6dfcaec03ab6ab58042b03064f4915658e0bc4d443" 92 | ); 93 | }); 94 | 95 | it("should compute the hash of a split string (SHA-256)", (): void => { 96 | let msg1 = Uint8Array.wrap(String.UTF8.encode("This is a test vector for the hash function, ")); 97 | let msg2 = Uint8Array.wrap(String.UTF8.encode("with an input larger than the block size")); 98 | let st = sha256HashInit(); 99 | sha256HashUpdate(st, msg1); 100 | sha256HashUpdate(st, msg2); 101 | let h = sha256HashFinal(st); 102 | let hex = bin2hex(h); 103 | expect(hex).toBe( 104 | "e8f6644d4670f6c3d817af6dfcaec03ab6ab58042b03064f4915658e0bc4d443" 105 | ); 106 | }); 107 | 108 | it("should compute a HMAC (SHA-256)", (): void => { 109 | let msg = Uint8Array.wrap(String.UTF8.encode("test")); 110 | let key = Uint8Array.wrap(String.UTF8.encode("test")); 111 | let h = sha256Hmac(msg, key); 112 | let hex = bin2hex(h); 113 | expect(hex).toBe( 114 | "88cd2108b5347d973cf39cdf9053d7dd42704876d8c9a9bd8e2d168259d3ddf7" 115 | ); 116 | }); 117 | }); 118 | 119 | -------------------------------------------------------------------------------- /assembly/__tests__/signEd25519.spec.ts: -------------------------------------------------------------------------------- 1 | type aisize = i32; 2 | 3 | describe("Ed25529 signature", (): void => { 4 | it("should sign and verify using Ed25519", (): void => { 5 | let seed = new Uint8Array(32); 6 | for (let i = 0; i < 32; i++) { 7 | seed[i] = ~i; 8 | } 9 | let kp = signEdKeypairFromSeed(seed); 10 | let msg = new Uint8Array(42); 11 | for (let i = 0; i < 32; i++) { 12 | msg[i] = i; 13 | } 14 | let signature = signEd(msg, kp); 15 | expect(signature).toHaveLength(SIGN_ED_BYTES); 16 | 17 | let pk = signEdPublicKey(kp); 18 | expect(pk).toHaveLength(SIGN_ED_PUBLICKEYBYTES); 19 | 20 | let verified = signEdVerify(signature, msg, pk); 21 | expect(verified).toBeTruthy(); 22 | 23 | let noise = new Uint8Array(32); 24 | for (let i = 0; i < 32; i++) { 25 | noise[i] = i; 26 | } 27 | let signature2 = signEd(msg, kp, noise); 28 | expect(equals(signature, signature2)).toBeFalsy(); 29 | 30 | let verified2 = signEdVerify(signature2, msg, pk); 31 | expect(verified2).toBeTruthy(); 32 | 33 | pk[0]++; 34 | let verified3 = signEdVerify(signature2, msg, pk); 35 | expect(verified3).toBeFalsy(); 36 | 37 | pk[0]--; 38 | msg[0]++; 39 | let verified4 = signEdVerify(signature2, msg, pk); 40 | expect(verified4).toBeFalsy(); 41 | }); 42 | }); 43 | -------------------------------------------------------------------------------- /assembly/__tests__/signRistretto.spec.ts: -------------------------------------------------------------------------------- 1 | type aisize = i32; 2 | 3 | describe("Ristretto signature", (): void => { 4 | it("should sign and verify using Ristretto", (): void => { 5 | let seed = new Uint8Array(32); 6 | for (let i = 0; i < 32; i++) { 7 | seed[i] = ~i; 8 | } 9 | let kp = signKeypairFromSeed(seed); 10 | let msg = new Uint8Array(42); 11 | for (let i = 0; i < 32; i++) { 12 | msg[i] = i; 13 | } 14 | let signature = sign(msg, kp); 15 | expect(signature).toHaveLength(SIGN_BYTES); 16 | 17 | let pk = signPublicKey(kp); 18 | expect(pk).toHaveLength(SIGN_PUBLICKEYBYTES); 19 | 20 | let verified = signVerify(signature, msg, pk); 21 | expect(verified).toBeTruthy(); 22 | 23 | let noise = new Uint8Array(32); 24 | for (let i = 0; i < 32; i++) { 25 | noise[i] = i; 26 | } 27 | let signature2 = sign(msg, kp, noise); 28 | expect(equals(signature, signature2)).toBeFalsy(); 29 | 30 | let verified2 = signVerify(signature2, msg, pk); 31 | expect(verified2).toBeTruthy(); 32 | 33 | pk[0]++; 34 | let verified3 = signVerify(signature2, msg, pk); 35 | expect(verified3).toBeFalsy(); 36 | 37 | pk[0]--; 38 | msg[0]++; 39 | let verified4 = signVerify(signature2, msg, pk); 40 | expect(verified4).toBeFalsy(); 41 | }); 42 | }); 43 | -------------------------------------------------------------------------------- /assembly/__tests__/utils.spec.ts: -------------------------------------------------------------------------------- 1 | describe("equals", (): void => { 2 | it("should test for equality", (): void => { 3 | let x = new Uint8Array(42); 4 | let y = new Uint8Array(42); 5 | for (let i = 0; i < 42; i++) { 6 | x[i] = y[i] = i; 7 | } 8 | expect(equals(x, y)).toBeTruthy(); 9 | }); 10 | }); 11 | 12 | describe("memzero", (): void => { 13 | it("should zero an array", (): void => { 14 | let x = new Uint8Array(42); 15 | let y = new Uint8Array(42); 16 | for (let i = 0; i < 42; i++) { 17 | x[i] = y[i] = i; 18 | } 19 | memzero(x); 20 | expect(equals(x, y)).toBeFalsy(); 21 | memzero(y); 22 | expect(equals(x, y)).toBeTruthy(); 23 | }); 24 | }); 25 | 26 | describe("bin2hex", (): void => { 27 | it("should encode to hex", (): void => { 28 | let bin = new Uint8Array(25); 29 | for (let i = 0; i < 25; i++) { 30 | bin[i] = i * 5; 31 | } 32 | let hex = bin2hex(bin); 33 | expect(hex).toBe("00050a0f14191e23282d32373c41464b50555a5f64696e7378"); 34 | }) 35 | }) 36 | 37 | describe("hex2bin", (): void => { 38 | it("should decode from hex", (): void => { 39 | let hex = "00050a0f14191e23282d32373c41464b50555a5f64696e7378"; 40 | let bin = hex2bin(hex); 41 | let ref = new Uint8Array(25); 42 | for (let i = 0; i < 25; i++) { 43 | ref[i] = i * 5; 44 | } 45 | expect(equals(ref, bin!)).toBeTruthy(); 46 | }) 47 | }) 48 | -------------------------------------------------------------------------------- /assembly/crypto.ts: -------------------------------------------------------------------------------- 1 | // tslint:disable-next-line:no-reference 2 | /// 3 | 4 | import { precompBase } from './precomp'; 5 | 6 | const RELEASE: bool = true; 7 | 8 | type aisize = i32; 9 | 10 | export const U8ARRAY_ID = idof(); 11 | 12 | // Helpers 13 | 14 | @inline function setU8(t: Uint8Array, s: Uint8Array, o: isize = 0): void { 15 | memory.copy(t.dataStart + o, s.dataStart, s.length); 16 | } 17 | 18 | function load64_be(x: Uint8Array, offset: isize): u64 { 19 | return bswap(load(changetype(x.buffer) + offset)); 20 | } 21 | 22 | function store64_be(x: Uint8Array, offset: isize, u: u64): void { 23 | store(changetype(x.buffer) + offset, bswap(u)); 24 | } 25 | 26 | function load32_be(x: Uint8Array, offset: isize): u32 { 27 | return bswap(load(changetype(x.buffer) + offset)); 28 | } 29 | 30 | function store32_be(x: Uint8Array, offset: isize, u: u32): void { 31 | store(changetype(x.buffer) + offset, bswap(u)); 32 | } 33 | 34 | // SHA256 35 | 36 | class Sha256 { 37 | @inline static Sigma0(x: u32): u32 { 38 | return rotr(x, 2) ^ rotr(x, 13) ^ rotr(x, 22); 39 | } 40 | 41 | @inline static Sigma1(x: u32): u32 { 42 | return rotr(x, 6) ^ rotr(x, 11) ^ rotr(x, 25); 43 | } 44 | 45 | @inline static sigma0(x: u32): u32 { 46 | return rotr(x, 7) ^ rotr(x, 18) ^ (x >> 3); 47 | } 48 | 49 | @inline static sigma1(x: u32): u32 { 50 | return rotr(x, 17) ^ rotr(x, 19) ^ (x >> 10); 51 | } 52 | 53 | @inline static Ch(x: u32, y: u32, z: u32): u32 { 54 | return z ^ (x & (y ^ z)); 55 | } 56 | 57 | @inline static Maj(x: u32, y: u32, z: u32): u32 { 58 | return (x & (y ^ z)) ^ (y & z); 59 | } 60 | 61 | static expand(w: StaticArray): void { 62 | for (let i = 0; i < 16; i++) { 63 | unchecked(w[i] += w[(i + 9) & 15] + Sha256.sigma1(w[(i + 14) & 15]) + Sha256.sigma0(w[(i + 1) & 15])); 64 | } 65 | } 66 | 67 | static handle(r: StaticArray, w: StaticArray, c: u32[]): void { 68 | for (let i = 0; i < 16; i++) { 69 | var x = (r[7 & (7 - i)] + w[i] + c[i]); 70 | x += unchecked(Sha256.Sigma1(r[7 & (4 - i)])); 71 | x += unchecked(Sha256.Ch(r[7 & (4 - i)], r[7 & (5 - i)], r[7 & (6 - i)])); 72 | unchecked(r[7 & (3 - i)] += x); 73 | x += unchecked(Sha256.Sigma0(r[7 & (0 - i)])); 74 | x += unchecked(Sha256.Maj(r[7 & (0 - i)], r[7 & (1 - i)], r[7 & (2 - i)])); 75 | unchecked(r[7 & (7 - i)] = x); 76 | } 77 | } 78 | 79 | static K: u32[] = [ 80 | 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, 81 | 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 82 | 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 83 | 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, 84 | 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 85 | 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, 86 | 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, 87 | 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 88 | ]; 89 | 90 | static _hashblocks(st: Uint8Array, m: Uint8Array, n_: isize): isize { 91 | let z = new StaticArray(8), 92 | r = new StaticArray(8), 93 | w = new StaticArray(16); 94 | for (let i = 0; i < 8; ++i) { 95 | unchecked(z[i] = r[i] = load32_be(st, i << 2)); 96 | } 97 | let pos = 0, n = n_; 98 | while (n >= 64) { 99 | for (let i = 0; i < 16; ++i) { 100 | w[i] = load32_be(m, (i << 2) + pos); 101 | } 102 | Sha256.handle(r, w, Sha256.K.slice(0)); 103 | Sha256.expand(w); 104 | Sha256.handle(r, w, Sha256.K.slice(16)); 105 | Sha256.expand(w); 106 | Sha256.handle(r, w, Sha256.K.slice(32)); 107 | Sha256.expand(w); 108 | Sha256.handle(r, w, Sha256.K.slice(48)); 109 | for (let i = 0; i < 8; ++i) { 110 | let x = unchecked(r[i] + z[i]); 111 | unchecked(z[i] = x); 112 | unchecked(r[i] = x); 113 | } 114 | pos += 64; 115 | n -= 64; 116 | } 117 | for (let i = 0; i < 8; ++i) { 118 | store32_be(st, i << 2, unchecked(z[i])); 119 | } 120 | return n; 121 | } 122 | 123 | static iv: u8[] = [ 124 | 0x6a, 0x09, 0xe6, 0x67, 0xbb, 0x67, 0xae, 0x85, 0x3c, 0x6e, 0xf3, 0x72, 0xa5, 0x4f, 0xf5, 0x3a, 125 | 0x51, 0x0e, 0x52, 0x7f, 0x9b, 0x05, 0x68, 0x8c, 0x1f, 0x83, 0xd9, 0xab, 0x5b, 0xe0, 0xcd, 0x19, 126 | ]; 127 | 128 | static _hashInit(): Uint8Array { 129 | let st = new Uint8Array(32 + 64 + 8 * 2); 130 | 131 | for (let i = 0; i < 32; ++i) { 132 | st[i] = Sha256.iv[i]; 133 | } 134 | return st; 135 | } 136 | 137 | static _hashUpdate(st: Uint8Array, m: Uint8Array, n: isize, r: isize): isize { 138 | let obuffered = st.subarray(32); 139 | let buffered = new Uint8Array(64); 140 | setU8(buffered, obuffered.subarray(0, 64)); // extra copy to work around compiler bugs 141 | 142 | let still_available_in_buffer = 64 - r; 143 | let copiable_to_buffer = min(n, still_available_in_buffer); 144 | setU8(buffered, m.subarray(0, copiable_to_buffer), r); 145 | r += copiable_to_buffer; 146 | n -= copiable_to_buffer; 147 | let pos: isize = 0; 148 | if (r === 64) { 149 | Sha256._hashblocks(st, buffered, 64); 150 | r = 0; 151 | pos = copiable_to_buffer; 152 | } 153 | if (n == 0) { 154 | setU8(obuffered, buffered); 155 | return r; 156 | } 157 | let left = m.subarray(pos); 158 | r = Sha256._hashblocks(st, left, left.length); 159 | if (r > 0) { 160 | setU8(obuffered, left.subarray(left.length - r)); 161 | } 162 | return r; 163 | } 164 | 165 | static _hashFinal(st: Uint8Array, out: Uint8Array, t: isize, r: isize): void { 166 | let buffered = st.subarray(32); 167 | let padded = new Uint8Array(128); 168 | setU8(padded, buffered.subarray(0, r)); 169 | padded[r] = 0x80; 170 | if (r < 56) { 171 | store64_be(padded, 64 - 8, t << 3); 172 | Sha256._hashblocks(st, padded, 64); 173 | } else { 174 | store64_be(padded, 128 - 8, t << 3); 175 | Sha256._hashblocks(st, padded, 128); 176 | } 177 | for (let i = 0; i < 32; ++i) { 178 | out[i] = st[i]; 179 | } 180 | } 181 | 182 | static _hash(out: Uint8Array, m: Uint8Array, n: isize): void { 183 | let st = Sha256._hashInit(); 184 | let r = Sha256._hashUpdate(st, m, n, 0); 185 | 186 | Sha256._hashFinal(st, out, n, r); 187 | } 188 | 189 | // HMAC 190 | 191 | static _hmac(m: Uint8Array, k: Uint8Array): Uint8Array { 192 | if (k.length > 64) { 193 | k = hash(k); 194 | } 195 | let b = new Uint8Array(64); 196 | setU8(b, k); 197 | for (let i = 0; i < b.length; ++i) { 198 | b[i] ^= 0x36; 199 | } 200 | let out = new Uint8Array(32); 201 | let st = Sha256._hashInit(); 202 | let r = Sha256._hashUpdate(st, b, b.length, 0); 203 | r = Sha256._hashUpdate(st, m, m.length, r); 204 | Sha256._hashFinal(st, out, b.length + m.length, r); 205 | for (let i = 0; i < b.length; ++i) { 206 | b[i] ^= 0x6a; 207 | } 208 | st = Sha256._hashInit(); 209 | r = Sha256._hashUpdate(st, b, b.length, 0); 210 | r = Sha256._hashUpdate(st, out, out.length, r); 211 | Sha256._hashFinal(st, out, b.length + out.length, r); 212 | return out; 213 | } 214 | } 215 | 216 | // SHA512 217 | 218 | class Sha512 { 219 | @inline static Sigma0(x: u64): u64 { 220 | return rotr(x, 28) ^ rotr(x, 34) ^ rotr(x, 39); 221 | } 222 | 223 | @inline static Sigma1(x: u64): u64 { 224 | return rotr(x, 14) ^ rotr(x, 18) ^ rotr(x, 41); 225 | } 226 | 227 | @inline static sigma0(x: u64): u64 { 228 | return rotr(x, 1) ^ rotr(x, 8) ^ (x >> 7); 229 | } 230 | 231 | @inline static sigma1(x: u64): u64 { 232 | return rotr(x, 19) ^ rotr(x, 61) ^ (x >> 6); 233 | } 234 | 235 | @inline static Ch(x: u64, y: u64, z: u64): u64 { 236 | return z ^ (x & (y ^ z)); 237 | } 238 | 239 | @inline static Maj(x: u64, y: u64, z: u64): u64 { 240 | return (x & (y ^ z)) ^ (y & z); 241 | } 242 | 243 | static expand(w: StaticArray): void { 244 | for (let i = 0; i < 16; i++) { 245 | unchecked(w[i] += w[(i + 9) & 15] + Sha512.sigma1(w[(i + 14) & 15]) + Sha512.sigma0(w[(i + 1) & 15])); 246 | } 247 | } 248 | 249 | static handle(r: StaticArray, w: StaticArray, c: u64[]): void { 250 | for (let i = 0; i < 16; i++) { 251 | var x = unchecked(r[7 & (7 - i)] + w[i] + c[i]); 252 | x += unchecked(Sha512.Sigma1(r[7 & (4 - i)])); 253 | x += unchecked(Sha512.Ch(r[7 & (4 - i)], r[7 & (5 - i)], r[7 & (6 - i)])); 254 | unchecked(r[7 & (3 - i)] += x); 255 | x += unchecked(Sha512.Sigma0(r[7 & (0 - i)])); 256 | x += unchecked(Sha512.Maj(r[7 & (0 - i)], r[7 & (1 - i)], r[7 & (2 - i)])); 257 | unchecked(r[7 & (7 - i)] = x); 258 | } 259 | } 260 | 261 | static K: u64[] = [ 262 | 0x428a2f98d728ae22, 0x7137449123ef65cd, 0xb5c0fbcfec4d3b2f, 0xe9b5dba58189dbbc, 263 | 0x3956c25bf348b538, 0x59f111f1b605d019, 0x923f82a4af194f9b, 0xab1c5ed5da6d8118, 264 | 0xd807aa98a3030242, 0x12835b0145706fbe, 0x243185be4ee4b28c, 0x550c7dc3d5ffb4e2, 265 | 0x72be5d74f27b896f, 0x80deb1fe3b1696b1, 0x9bdc06a725c71235, 0xc19bf174cf692694, 266 | 0xe49b69c19ef14ad2, 0xefbe4786384f25e3, 0x0fc19dc68b8cd5b5, 0x240ca1cc77ac9c65, 267 | 0x2de92c6f592b0275, 0x4a7484aa6ea6e483, 0x5cb0a9dcbd41fbd4, 0x76f988da831153b5, 268 | 0x983e5152ee66dfab, 0xa831c66d2db43210, 0xb00327c898fb213f, 0xbf597fc7beef0ee4, 269 | 0xc6e00bf33da88fc2, 0xd5a79147930aa725, 0x06ca6351e003826f, 0x142929670a0e6e70, 270 | 0x27b70a8546d22ffc, 0x2e1b21385c26c926, 0x4d2c6dfc5ac42aed, 0x53380d139d95b3df, 271 | 0x650a73548baf63de, 0x766a0abb3c77b2a8, 0x81c2c92e47edaee6, 0x92722c851482353b, 272 | 0xa2bfe8a14cf10364, 0xa81a664bbc423001, 0xc24b8b70d0f89791, 0xc76c51a30654be30, 273 | 0xd192e819d6ef5218, 0xd69906245565a910, 0xf40e35855771202a, 0x106aa07032bbd1b8, 274 | 0x19a4c116b8d2d0c8, 0x1e376c085141ab53, 0x2748774cdf8eeb99, 0x34b0bcb5e19b48a8, 275 | 0x391c0cb3c5c95a63, 0x4ed8aa4ae3418acb, 0x5b9cca4f7763e373, 0x682e6ff3d6b2b8a3, 276 | 0x748f82ee5defb2fc, 0x78a5636f43172f60, 0x84c87814a1f0ab72, 0x8cc702081a6439ec, 277 | 0x90befffa23631e28, 0xa4506cebde82bde9, 0xbef9a3f7b2c67915, 0xc67178f2e372532b, 278 | 0xca273eceea26619c, 0xd186b8c721c0c207, 0xeada7dd6cde0eb1e, 0xf57d4f7fee6ed178, 279 | 0x06f067aa72176fba, 0x0a637dc5a2c898a6, 0x113f9804bef90dae, 0x1b710b35131c471b, 280 | 0x28db77f523047d84, 0x32caab7b40c72493, 0x3c9ebe0a15c9bebc, 0x431d67c49c100d4c, 281 | 0x4cc5d4becb3e42b6, 0x597f299cfc657e2a, 0x5fcb6fab3ad6faec, 0x6c44198c4a475817, 282 | ]; 283 | 284 | static _hashblocks(st: Uint8Array, m: Uint8Array, n_: isize): isize { 285 | let z = new StaticArray(8), 286 | r = new StaticArray(8), 287 | w = new StaticArray(16); 288 | for (let i = 0; i < 8; ++i) { 289 | z[i] = load64_be(st, i << 3); 290 | r[i] = z[i]; 291 | } 292 | let pos = 0, n = n_; 293 | while (n >= 128) { 294 | for (let i = 0; i < 16; ++i) { 295 | w[i] = load64_be(m, (i << 3) + pos); 296 | } 297 | Sha512.handle(r, w, Sha512.K.slice(0)); 298 | Sha512.expand(w); 299 | Sha512.handle(r, w, Sha512.K.slice(16)); 300 | Sha512.expand(w); 301 | Sha512.handle(r, w, Sha512.K.slice(32)); 302 | Sha512.expand(w); 303 | Sha512.handle(r, w, Sha512.K.slice(48)); 304 | Sha512.expand(w); 305 | Sha512.handle(r, w, Sha512.K.slice(64)); 306 | for (let i = 0; i < 8; ++i) { 307 | let x = r[i] + z[i]; 308 | z[i] = x; 309 | r[i] = x; 310 | } 311 | pos += 128; 312 | n -= 128; 313 | } 314 | for (let i = 0; i < 8; ++i) { 315 | store64_be(st, i << 3, z[i]); 316 | } 317 | return n; 318 | } 319 | 320 | static iv: u8[] = [ 321 | 0x6a, 0x09, 0xe6, 0x67, 0xf3, 0xbc, 0xc9, 0x08, 0xbb, 0x67, 0xae, 0x85, 0x84, 0xca, 0xa7, 0x3b, 322 | 0x3c, 0x6e, 0xf3, 0x72, 0xfe, 0x94, 0xf8, 0x2b, 0xa5, 0x4f, 0xf5, 0x3a, 0x5f, 0x1d, 0x36, 0xf1, 323 | 0x51, 0x0e, 0x52, 0x7f, 0xad, 0xe6, 0x82, 0xd1, 0x9b, 0x05, 0x68, 0x8c, 0x2b, 0x3e, 0x6c, 0x1f, 324 | 0x1f, 0x83, 0xd9, 0xab, 0xfb, 0x41, 0xbd, 0x6b, 0x5b, 0xe0, 0xcd, 0x19, 0x13, 0x7e, 0x21, 0x79, 325 | ]; 326 | 327 | static _hashInit(): Uint8Array { 328 | let st = new Uint8Array(64 + 128 + 8 * 2); 329 | 330 | for (let i = 0; i < 64; ++i) { 331 | st[i] = Sha512.iv[i]; 332 | } 333 | return st; 334 | } 335 | 336 | static _hashUpdate(st: Uint8Array, m: Uint8Array, n: isize, r: isize): isize { 337 | let obuffered = st.subarray(64); 338 | let buffered = new Uint8Array(128); 339 | setU8(buffered, obuffered.subarray(0, 128)); // extra copy work around compiler bugs 340 | 341 | let still_available_in_buffer = 128 - r; 342 | let copiable_to_buffer = min(n, still_available_in_buffer); 343 | setU8(buffered, m.subarray(0, copiable_to_buffer), r); 344 | r += copiable_to_buffer; 345 | n -= copiable_to_buffer; 346 | let pos: isize = 0; 347 | if (r === 128) { 348 | Sha512._hashblocks(st, buffered, 128); 349 | r = 0; 350 | pos = copiable_to_buffer; 351 | } 352 | if (n == 0) { 353 | setU8(obuffered, buffered); 354 | return r; 355 | } 356 | let left = m.subarray(pos); 357 | r = Sha512._hashblocks(st, left, left.length); 358 | if (r > 0) { 359 | setU8(obuffered, left.subarray(left.length - r)); 360 | } 361 | return r; 362 | } 363 | 364 | static _hashFinal(st: Uint8Array, out: Uint8Array, t: isize, r: isize): void { 365 | let buffered = st.subarray(64); 366 | let padded = new Uint8Array(256); 367 | setU8(padded, buffered.subarray(0, r)); 368 | padded[r] = 0x80; 369 | if (r < 112) { 370 | store64_be(padded, 128 - 8, t << 3); 371 | Sha512._hashblocks(st, padded, 128); 372 | } else { 373 | store64_be(padded, 256 - 8, t << 3); 374 | Sha512._hashblocks(st, padded, 256); 375 | } 376 | for (let i = 0; i < 64; ++i) { 377 | out[i] = st[i]; 378 | } 379 | } 380 | 381 | static _hash(out: Uint8Array, m: Uint8Array, n: isize): void { 382 | let st = Sha512._hashInit(); 383 | let r = Sha512._hashUpdate(st, m, n, 0); 384 | Sha512._hashFinal(st, out, n, r); 385 | } 386 | 387 | // HMAC 388 | 389 | static _hmac(m: Uint8Array, k: Uint8Array): Uint8Array { 390 | if (k.length > 128) { 391 | k = hash(k); 392 | } 393 | let b = new Uint8Array(128); 394 | setU8(b, k); 395 | for (let i = 0; i < b.length; ++i) { 396 | b[i] ^= 0x36; 397 | } 398 | let out = new Uint8Array(64); 399 | let st = Sha512._hashInit(); 400 | let r = Sha512._hashUpdate(st, b, b.length, 0); 401 | r = Sha512._hashUpdate(st, m, m.length, r); 402 | Sha512._hashFinal(st, out, b.length + m.length, r); 403 | for (let i = 0; i < b.length; ++i) { 404 | b[i] ^= 0x6a; 405 | } 406 | st = Sha512._hashInit(); 407 | r = Sha512._hashUpdate(st, b, b.length, 0); 408 | r = Sha512._hashUpdate(st, out, out.length, r); 409 | Sha512._hashFinal(st, out, b.length + out.length, r); 410 | return out; 411 | } 412 | } 413 | 414 | // helpers 415 | 416 | function verify32(x: Uint8Array, y: Uint8Array): bool { 417 | let d: u8 = 0; 418 | 419 | for (let i = 0; i < 32; ++i) { 420 | d |= x[i] ^ y[i]; 421 | } 422 | return d === 0; 423 | } 424 | 425 | function allZeros(x: Uint8Array): bool { 426 | let len = x.length; 427 | let c: u8 = 0; 428 | for (let i = 0; i < len; ++i) { 429 | c |= x[i]; 430 | } 431 | return c === 0; 432 | } 433 | 434 | // mod(2^252 + 27742317777372353535851937790883648495) field arithmetic 435 | 436 | type Scalar = StaticArray(64); 437 | type ScalarPacked = Uint8Array(32); 438 | type ScalarDouble = Uint8Array(64); 439 | 440 | @inline function newScalar(): Scalar { 441 | return new StaticArray(64); 442 | } 443 | 444 | @inline function newScalarPacked(): ScalarPacked { 445 | return new Uint8Array(32); 446 | } 447 | 448 | @inline function newScalarDouble(): ScalarDouble { 449 | return new Uint8Array(64); 450 | } 451 | 452 | let _L: StaticArray = new StaticArray(32); 453 | _L[0] = 237; 454 | _L[1] = 211; 455 | _L[2] = 245; 456 | _L[3] = 92; 457 | _L[4] = 26; 458 | _L[5] = 99; 459 | _L[6] = 18; 460 | _L[7] = 88; 461 | _L[8] = 214; 462 | _L[9] = 156; 463 | _L[10] = 247; 464 | _L[11] = 162; 465 | _L[12] = 222; 466 | _L[13] = 249; 467 | _L[14] = 222; 468 | _L[15] = 20; 469 | _L[31] = 16; 470 | 471 | function scIsLtL(s: ScalarPacked): bool { 472 | let c: u8 = 0, n: u8 = 1, i = 32; 473 | 474 | if ((unchecked(s[31]) & 0xf0) === 0) { 475 | return true; 476 | } 477 | do { 478 | i--; 479 | let l = unchecked(_L[i]) as u8; 480 | let si = unchecked(s[i]); 481 | c |= ((si - l) >> 8) & n; 482 | n &= ((si ^ l) - 1) >> 8; 483 | } while (i !== 0); 484 | 485 | return c === 0; 486 | } 487 | 488 | function scModL(r: ScalarPacked, x: Scalar): void { 489 | let carry: i64; 490 | 491 | for (let i = 63; i >= 32; --i) { 492 | carry = 0; 493 | let k = i - 12; 494 | let xi = x[i]; 495 | for (let j = i - 32; j < k; ++j) { 496 | let xj = unchecked(x[j] + carry - 16 * xi * _L[j - (i - 32)]); 497 | carry = (xj + 128) >> 8; 498 | x[j] = xj - carry * 256; 499 | } 500 | x[k] += carry; 501 | x[i] = 0; 502 | } 503 | carry = 0; 504 | for (let j = 0; j < 32; ++j) { 505 | let xj = unchecked(x[j] + carry - (x[31] >> 4) * _L[j]); 506 | carry = xj >> 8; 507 | x[j] = xj & 255; 508 | } 509 | for (let j = 0; j < 32; ++j) { 510 | x[j] -= unchecked(carry * _L[j]); 511 | } 512 | for (let i = 0; i < 32; ++i) { 513 | let xi = unchecked(x[i]); 514 | x[i + 1] += xi >> 8; 515 | r[i] = xi as u8; 516 | } 517 | } 518 | 519 | function scReduce(r: ScalarDouble): void { 520 | let x = newScalar(); 521 | 522 | for (let i = 0; i < 64; ++i) { 523 | x[i] = r[i]; 524 | r[i] = 0; 525 | } 526 | scModL(r, x); 527 | } 528 | 529 | function scCarry(a: Scalar): void { 530 | let carry: i64 = 0; 531 | for (let i = 0; i < 64; ++i) { 532 | let c = a[i] + carry; 533 | a[i] = c & 0xff; 534 | carry = (c >>> 8); 535 | } 536 | if (!RELEASE && carry > 0) { 537 | throw new Error('overflow'); 538 | } 539 | } 540 | 541 | function scMult(o: Scalar, a: Scalar, b: Scalar): void { 542 | let r = newScalarPacked(); 543 | let t = newScalar(); 544 | 545 | for (let i = 0; i < 32; ++i) { 546 | let ai = a[i]; 547 | for (let j = 0; j < 32; ++j) { 548 | t[i + j] += ai * unchecked(b[j]); 549 | } 550 | } 551 | scCarry(t); 552 | scModL(r, t); 553 | for (let i = 0; i < 32; ++i) { 554 | o[i] = r[i]; 555 | } 556 | for (let i = 32; i < 64; ++i) { 557 | o[i] = 0; 558 | } 559 | } 560 | 561 | function scSq(o: Scalar, a: Scalar): void { 562 | scMult(o, a, a); 563 | } 564 | 565 | function scSqMult(y: Scalar, squarings: isize, x: Scalar): void { 566 | for (let i = 0; i < squarings; ++i) { 567 | scSq(y, y); 568 | } 569 | scMult(y, y, x); 570 | } 571 | 572 | function scInverse(s: Uint8Array): Uint8Array { 573 | let res = newScalarPacked(); 574 | let _1 = newScalar(); 575 | for (let i = 0; i < 32; ++i) { 576 | _1[i] = s[i]; 577 | } 578 | let _10 = newScalar(), _100 = newScalar(), _1000 = newScalar(), _10000 = newScalar(), _100000 = newScalar(), 579 | _1000000 = newScalar(), _10010011 = newScalar(), _10010111 = newScalar(), _100110 = newScalar(), _1010 = newScalar(), 580 | _1010000 = newScalar(), _1010011 = newScalar(), _1011 = newScalar(), _10110 = newScalar(), _10111101 = newScalar(), 581 | _11 = newScalar(), _1100011 = newScalar(), _1100111 = newScalar(), _11010011 = newScalar(), _1101011 = newScalar(), 582 | _11100111 = newScalar(), _11101011 = newScalar(), _11110101 = newScalar(), recip = newScalar(); 583 | 584 | scSq(_10, _1); 585 | scMult(_11, _1, _10); 586 | scMult(_100, _1, _11); 587 | scSq(_1000, _100); 588 | scMult(_1010, _10, _1000); 589 | scMult(_1011, _1, _1010); 590 | scSq(_10000, _1000); 591 | scSq(_10110, _1011); 592 | scMult(_100000, _1010, _10110); 593 | scMult(_100110, _10000, _10110); 594 | scSq(_1000000, _100000); 595 | scMult(_1010000, _10000, _1000000); 596 | scMult(_1010011, _11, _1010000); 597 | scMult(_1100011, _10000, _1010011); 598 | scMult(_1100111, _100, _1100011); 599 | scMult(_1101011, _100, _1100111); 600 | scMult(_10010011, _1000000, _1010011); 601 | scMult(_10010111, _100, _10010011); 602 | scMult(_10111101, _100110, _10010111); 603 | scMult(_11010011, _10110, _10111101); 604 | scMult(_11100111, _1010000, _10010111); 605 | scMult(_11101011, _100, _11100111); 606 | scMult(_11110101, _1010, _11101011); 607 | 608 | scMult(recip, _1011, _11110101); 609 | scSqMult(recip, 126, _1010011); 610 | scSqMult(recip, 9, _10); 611 | scMult(recip, recip, _11110101); 612 | scSqMult(recip, 7, _1100111); 613 | scSqMult(recip, 9, _11110101); 614 | scSqMult(recip, 11, _10111101); 615 | scSqMult(recip, 8, _11100111); 616 | scSqMult(recip, 9, _1101011); 617 | scSqMult(recip, 6, _1011); 618 | scSqMult(recip, 14, _10010011); 619 | scSqMult(recip, 10, _1100011); 620 | scSqMult(recip, 9, _10010111); 621 | scSqMult(recip, 10, _11110101); 622 | scSqMult(recip, 8, _11010011); 623 | scSqMult(recip, 8, _11101011); 624 | 625 | for (let i = 0; i < 32; ++i) { 626 | recip[i + 1] += recip[i] >> 8; 627 | res[i] = recip[i] as u8; 628 | } 629 | return res; 630 | } 631 | 632 | @inline function scClamp(s: ScalarPacked): void { 633 | s[0] &= 248; 634 | s[31] = (s[31] & 127) | 64; 635 | } 636 | 637 | function scAdd(a: Uint8Array, b: Uint8Array): void { 638 | let c: u32 = 0; 639 | for (let i = 0, len = a.length; i < len; i++) { 640 | c += (a[i] as u32) + (b[i] as u32); 641 | a[i] = c as u8; 642 | c >>= 8; 643 | } 644 | } 645 | 646 | function scSub(a: Uint8Array, b: Uint8Array): void { 647 | let c: u32 = 0; 648 | for (let i = 0, len = a.length; i < len; i++) { 649 | c = (a[i] as u32) - (b[i] as u32) - c; 650 | a[i] = c as u8; 651 | c = (c >> 8) & 1; 652 | } 653 | } 654 | 655 | // mod(2^255-19) field arithmetic - Doesn't use 51-bit limbs yet to keep the 656 | // code short and simple 657 | 658 | type Fe25519 = StaticArray(16); 659 | type Fe25519Packed = Uint8Array(32); 660 | 661 | @inline function newFe25519(): Fe25519 { 662 | return new StaticArray(16); 663 | } 664 | 665 | @inline function newFe25519Packed(): Fe25519Packed { 666 | return new Uint8Array(32); 667 | } 668 | 669 | function fe25519(init: i64[]): Fe25519 { 670 | let r = newFe25519(); 671 | 672 | for (let i = 0, len = init.length; i < len; ++i) { 673 | r[i] = init[i]; 674 | } 675 | return r; 676 | } 677 | 678 | let fe25519_0 = newFe25519(); 679 | let fe25519_1 = fe25519([1]); 680 | 681 | let D = fe25519([ 682 | 0x78a3, 0x1359, 0x4dca, 0x75eb, 0xd8ab, 0x4141, 0x0a4d, 0x0070, 683 | 0xe898, 0x7779, 0x4079, 0x8cc7, 0xfe73, 0x2b6f, 0x6cee, 0x5203, 684 | ]); 685 | 686 | let D2 = fe25519([ 687 | 0xf159, 0x26b2, 0x9b94, 0xebd6, 0xb156, 0x8283, 0x149a, 0x00e0, 688 | 0xd130, 0xeef3, 0x80f2, 0x198e, 0xfce7, 0x56df, 0xd9dc, 0x2406, 689 | ]); 690 | 691 | let SQRTM1 = fe25519([ 692 | 0xa0b0, 0x4a0e, 0x1b27, 0xc4ee, 0xe478, 0xad2f, 0x1806, 0x2f43, 693 | 0xd7a7, 0x3dfb, 0x0099, 0x2b4d, 0xdf0b, 0x4fc1, 0x2480, 0x2b83, 694 | ]); 695 | 696 | let SQRTADM1 = fe25519([ 697 | 0x2e1b, 0x497b, 0xf6a0, 0x7e97, 0x54bd, 0x1b78, 0x8e0c, 0xaf9d, 698 | 0xd1fd, 0x31f5, 0xfcc9, 0x0f3c, 0x48ac, 0x2b83, 0x31bf, 0x3769, 699 | ]); 700 | 701 | let INVSQRTAMD = fe25519([ 702 | 0x40ea, 0x805d, 0xfdaa, 0x99c8, 0x72be, 0x5a41, 0x1617, 0x9d2f, 703 | 0xd840, 0xfe01, 0x7b91, 0x16c2, 0xfca2, 0xcfaf, 0x8905, 0x786c, 704 | ]); 705 | 706 | let ONEMSQD = fe25519([ 707 | 0xc176, 0x945f, 0x09c1, 0xe27c, 0x350f, 0xcd5e, 0xa138, 0x2c81, 708 | 0xdfe4, 0xbe70, 0xabdd, 0x9994, 0xe0d7, 0xb2b3, 0x72a8, 0x0290, 709 | ]); 710 | 711 | let SQDMONE = fe25519([ 712 | 0x4d20, 0x44ed, 0x5aaa, 0x31ad, 0x1999, 0xb01e, 0x4a2c, 0xd29e, 713 | 0x4eeb, 0x529b, 0xd32f, 0x4cdc, 0x2241, 0xf66c, 0xb37a, 0x5968, 714 | ]); 715 | 716 | @inline function fe25519Copy(r: Fe25519, a: Fe25519): void { 717 | memory.copy(changetype(r), changetype(a), sizeof() * 16); 718 | } 719 | 720 | // @inline // -- commenting out this @inline attr causes exponential compilation time 721 | function fe25519Cmov(p: Fe25519, q: Fe25519, b: i64): void { 722 | let mask = ~(b - 1); 723 | unchecked(p[0] ^= (p[0] ^ q[0]) & mask); 724 | unchecked(p[1] ^= (p[1] ^ q[1]) & mask); 725 | unchecked(p[2] ^= (p[2] ^ q[2]) & mask); 726 | unchecked(p[3] ^= (p[3] ^ q[3]) & mask); 727 | unchecked(p[4] ^= (p[4] ^ q[4]) & mask); 728 | unchecked(p[5] ^= (p[5] ^ q[5]) & mask); 729 | unchecked(p[6] ^= (p[6] ^ q[6]) & mask); 730 | unchecked(p[7] ^= (p[7] ^ q[7]) & mask); 731 | unchecked(p[8] ^= (p[8] ^ q[8]) & mask); 732 | unchecked(p[9] ^= (p[9] ^ q[9]) & mask); 733 | unchecked(p[10] ^= (p[10] ^ q[10]) & mask); 734 | unchecked(p[11] ^= (p[11] ^ q[11]) & mask); 735 | unchecked(p[12] ^= (p[12] ^ q[12]) & mask); 736 | unchecked(p[13] ^= (p[13] ^ q[13]) & mask); 737 | unchecked(p[14] ^= (p[14] ^ q[14]) & mask); 738 | unchecked(p[15] ^= (p[15] ^ q[15]) & mask); 739 | } 740 | 741 | function fe25519Pack(o: Fe25519Packed, n: Fe25519): void { 742 | let b: i64; 743 | let m = newFe25519(); 744 | let t = newFe25519(); 745 | 746 | fe25519Copy(t, n); 747 | fe25519Carry(t); 748 | fe25519Carry(t); 749 | fe25519Carry(t); 750 | for (let j = 0; j < 2; ++j) { 751 | m[0] = t[0] - 0xffed; 752 | for (let i = 1; i < 15; ++i) { 753 | let mp = m[i - 1]; 754 | m[i] = t[i] - 0xffff - ((mp >> 16) & 1); 755 | m[i - 1] = mp & 0xffff; 756 | } 757 | m[15] = t[15] - 0x7fff - ((m[14] >> 16) & 1); 758 | b = (m[15] >> 16) & 1; 759 | m[14] &= 0xffff; 760 | fe25519Cmov(t, m, 1 - b); 761 | } 762 | for (let i = 0; i < 16; ++i) { 763 | let ti = t[i] as u32; 764 | o[2 * i + 0] = ti & 0xff; 765 | o[2 * i + 1] = ti >> 8; 766 | } 767 | } 768 | 769 | function fe25519Unpack(o: Fe25519, n: Fe25519Packed): void { 770 | let nb = changetype(n.buffer); 771 | for (let i = 0; i < 16; ++i) { 772 | o[i] = load(nb + 2 * i) as i64; 773 | } 774 | o[15] &= 0x7fff; 775 | } 776 | 777 | function fe25519Eq(a: Fe25519, b: Fe25519): bool { 778 | let c = newFe25519Packed(), d = newFe25519Packed(); 779 | 780 | fe25519Pack(c, a); 781 | fe25519Pack(d, b); 782 | 783 | return verify32(c, d); 784 | } 785 | 786 | function fe25519IsNegative(a: Fe25519): bool { 787 | let d = newFe25519Packed(); 788 | 789 | fe25519Pack(d, a); 790 | 791 | return (d[0] & 1) as bool; 792 | } 793 | 794 | function fe25519Neg(f: Fe25519): void { 795 | fe25519Sub(f, fe25519_0, f); 796 | } 797 | 798 | function fe25519Cneg(h: Fe25519, f: Fe25519, b: bool): void { 799 | let negf = newFe25519(); 800 | fe25519Sub(negf, fe25519_0, f); 801 | fe25519Copy(h, f); 802 | fe25519Cmov(h, negf, b as i64); 803 | } 804 | 805 | function fe25519Abs(h: Fe25519, f: Fe25519): void { 806 | fe25519Cneg(h, f, fe25519IsNegative(f)); 807 | } 808 | 809 | function fe25519IsZero(a: Fe25519): bool { 810 | let b = newFe25519Packed(); 811 | 812 | fe25519Pack(b, a); 813 | let c: i64 = 0; 814 | for (let i = 0; i < 16; i++) { 815 | c |= b[i]; 816 | } 817 | return c === 0; 818 | } 819 | 820 | @inline function fe25519Add(o: Fe25519, a: Fe25519, b: Fe25519): void { 821 | for (let i = 0; i < 16; ++i) { 822 | o[i] = a[i] + b[i]; 823 | } 824 | } 825 | 826 | @inline function fe25519Sub(o: Fe25519, a: Fe25519, b: Fe25519): void { 827 | for (let i = 0; i < 16; ++i) { 828 | o[i] = a[i] - b[i]; 829 | } 830 | } 831 | 832 | function fe25519Carry(o: Fe25519): void { 833 | let c: i64; 834 | 835 | for (let i = 0; i < 15; ++i) { 836 | o[i] += (1 << 16); 837 | c = o[i] >> 16; 838 | o[(i + 1)] += c - 1; 839 | o[i] -= c << 16; 840 | } 841 | o[15] += (1 << 16); 842 | c = o[15] >> 16; 843 | o[0] += c - 1 + 37 * (c - 1); 844 | o[15] -= c << 16; 845 | } 846 | 847 | @inline function fe25519Reduce(o: Fe25519, a: Fe25519): void { 848 | for (let i = 0; i < 15; ++i) { 849 | a[i] += 38 as i64 * a[i + 16]; 850 | } 851 | fe25519Copy(o, a); 852 | fe25519Carry(o); 853 | fe25519Carry(o); 854 | } 855 | 856 | function fe25519Mult(o: Fe25519, a: Fe25519, b: Fe25519): void { 857 | let t = new StaticArray(31 + 1); 858 | 859 | for (let i = 0; i < 16; ++i) { 860 | let ai = unchecked(a[i]); 861 | for (let j = 0; j < 16; ++j) { 862 | t[i + j] += ai * unchecked(b[j]); 863 | } 864 | } 865 | fe25519Reduce(o, t); 866 | } 867 | 868 | @inline function fe25519Sq(o: Fe25519, a: Fe25519): void { 869 | fe25519Mult(o, a, a); 870 | } 871 | 872 | function fe25519Sq2(o: Fe25519, a: Fe25519): void { 873 | let t = new StaticArray(31 + 1); 874 | 875 | for (let i = 0; i < 16; ++i) { 876 | let ai = 2 * unchecked(a[i]); 877 | for (let j = 0; j < 16; ++j) { 878 | t[i + j] += ai * unchecked(a[j]); 879 | } 880 | } 881 | fe25519Reduce(o, t); 882 | } 883 | 884 | function fe25519Inverse(o: Fe25519, i: Fe25519): void { 885 | let c = newFe25519(); 886 | 887 | fe25519Copy(c, i); 888 | for (let a = 253; a >= 5; --a) { 889 | fe25519Sq(c, c); 890 | fe25519Mult(c, c, i); 891 | } 892 | fe25519Sq(c, c); 893 | fe25519Sq(c, c); 894 | fe25519Mult(c, c, i); 895 | fe25519Sq(c, c); 896 | fe25519Sq(c, c); 897 | fe25519Mult(c, c, i); 898 | fe25519Sq(c, c); 899 | fe25519Mult(c, c, i); 900 | fe25519Copy(o, c); 901 | } 902 | 903 | function fe25519Pow252m3(o: Fe25519, i: Fe25519): void { 904 | let c = newFe25519(); 905 | 906 | fe25519Copy(c, i); 907 | for (let a = 250; a >= 2; --a) { 908 | fe25519Sq(c, c); 909 | fe25519Mult(c, c, i); 910 | } 911 | fe25519Sq(c, c); 912 | fe25519Sq(c, c); 913 | fe25519Mult(c, c, i); 914 | fe25519Copy(o, c); 915 | } 916 | 917 | // Ed25519 group arithmetic 918 | 919 | class Ge { 920 | x: Fe25519; 921 | y: Fe25519; 922 | z: Fe25519; 923 | t: Fe25519; 924 | 925 | @inline constructor() { 926 | this.x = newFe25519(); 927 | this.y = newFe25519(); 928 | this.z = newFe25519(); 929 | this.t = newFe25519(); 930 | } 931 | } 932 | 933 | type GePacked = Uint8Array(32); 934 | 935 | @inline function newGe(): Ge { 936 | return new Ge(); 937 | } 938 | 939 | @inline function newGePacked(): GePacked { 940 | return new Uint8Array(32); 941 | } 942 | 943 | @inline function geCopy(r: Ge, a: Ge): void { 944 | fe25519Copy(r.x, a.x); 945 | fe25519Copy(r.y, a.y); 946 | fe25519Copy(r.z, a.z); 947 | fe25519Copy(r.t, a.t); 948 | } 949 | 950 | let Aa = newFe25519(), 951 | Ab = newFe25519(), 952 | Ac = newFe25519(), 953 | Ad = newFe25519(), 954 | Ae = newFe25519(), 955 | Af = newFe25519(), 956 | Ag = newFe25519(), 957 | Ah = newFe25519(), 958 | At = newFe25519(); 959 | 960 | function add(p: Ge, q: Ge): void { 961 | fe25519Sub(Aa, p.x, p.y); 962 | fe25519Sub(At, q.x, q.y); 963 | fe25519Mult(Aa, Aa, At); 964 | fe25519Add(Ab, p.x, p.y); 965 | fe25519Add(At, q.x, q.y); 966 | fe25519Mult(Ab, Ab, At); 967 | fe25519Mult(Ac, p.t, q.t); 968 | fe25519Mult(Ac, Ac, D2); 969 | fe25519Mult(Ad, p.z, q.z); 970 | fe25519Add(Ad, Ad, Ad); 971 | fe25519Sub(Ae, Ab, Aa); 972 | fe25519Sub(Af, Ad, Ac); 973 | fe25519Add(Ag, Ad, Ac); 974 | fe25519Add(Ah, Ab, Aa); 975 | 976 | fe25519Mult(p.x, Ae, Af); 977 | fe25519Mult(p.y, Ah, Ag); 978 | fe25519Mult(p.z, Ag, Af); 979 | fe25519Mult(p.t, Ae, Ah); 980 | } 981 | 982 | function neg(p: Ge): void { 983 | fe25519Neg(p.x); 984 | fe25519Neg(p.t); 985 | } 986 | 987 | function sub(p: Ge, q: Ge): void { 988 | let negq = newGe(); 989 | geCopy(negq, q); 990 | neg(negq); 991 | add(p, negq); 992 | } 993 | 994 | function dbl(p: Ge): void { 995 | fe25519Add(At, p.x, p.y); 996 | fe25519Sq(At, At); 997 | fe25519Sq(Aa, p.x); 998 | fe25519Sq(Ac, p.y); 999 | fe25519Add(Ab, Ac, Aa); 1000 | fe25519Sub(Ac, Ac, Aa); 1001 | fe25519Sub(Aa, At, Ab); 1002 | fe25519Sq2(At, p.z); 1003 | fe25519Sub(At, At, Ac); 1004 | 1005 | fe25519Mult(p.x, Aa, At); 1006 | fe25519Mult(p.y, Ab, Ac); 1007 | fe25519Mult(p.z, Ac, At); 1008 | fe25519Mult(p.t, Aa, Ab); 1009 | } 1010 | 1011 | @inline function cmov(p: Ge, q: Ge, b: i64): void { 1012 | fe25519Cmov(p.x, q.x, b); 1013 | fe25519Cmov(p.y, q.y, b); 1014 | fe25519Cmov(p.z, q.z, b); 1015 | fe25519Cmov(p.t, q.t, b); 1016 | } 1017 | 1018 | function clearCofactor(p: Ge): void { 1019 | dbl(p); 1020 | dbl(p); 1021 | dbl(p); 1022 | } 1023 | 1024 | function pack(r: GePacked, p: Ge): void { 1025 | let tx = newFe25519(), 1026 | ty = newFe25519(), 1027 | zi = newFe25519(); 1028 | fe25519Inverse(zi, p.z); 1029 | fe25519Mult(tx, p.x, zi); 1030 | fe25519Mult(ty, p.y, zi); 1031 | fe25519Pack(r, ty); 1032 | r[31] ^= (fe25519IsNegative(tx) as u8) << 7; 1033 | } 1034 | 1035 | function scalarmult(p: Ge, s: ScalarPacked, q: Ge): void { 1036 | let pc: Array = [newGe(), newGe(), newGe(), newGe(), newGe(), newGe(), newGe(), newGe(), 1037 | newGe(), newGe(), newGe(), newGe(), newGe(), newGe(), newGe(), newGe()]; 1038 | let t = newGe(), 1039 | b: u32; 1040 | 1041 | fe25519Copy(pc[0].x, fe25519_0); 1042 | fe25519Copy(pc[0].y, fe25519_1); 1043 | fe25519Copy(pc[0].z, fe25519_1); 1044 | fe25519Copy(pc[0].t, fe25519_0); 1045 | geCopy(pc[1], q); 1046 | for (let i = 2; i < 16; ++i) { 1047 | geCopy(pc[i], pc[i - 1]); 1048 | add(pc[i], q); 1049 | } 1050 | 1051 | geCopy(p, pc[0]); 1052 | for (let i = 252; i >= 0; i -= 4) { 1053 | b = (s[(i >>> 3)] >>> (i as u8 & 7)) & 0xf; 1054 | dbl(p); 1055 | dbl(p); 1056 | dbl(p); 1057 | dbl(p); 1058 | geCopy(t, pc[0]); 1059 | cmov(t, unchecked(pc[15]), (((b ^ 15) - 1) >>> 8) as u8 & 1); 1060 | cmov(t, unchecked(pc[14]), (((b ^ 14) - 1) >>> 8) as u8 & 1); 1061 | cmov(t, unchecked(pc[13]), (((b ^ 13) - 1) >>> 8) as u8 & 1); 1062 | cmov(t, unchecked(pc[12]), (((b ^ 12) - 1) >>> 8) as u8 & 1); 1063 | cmov(t, unchecked(pc[11]), (((b ^ 11) - 1) >>> 8) as u8 & 1); 1064 | cmov(t, unchecked(pc[10]), (((b ^ 10) - 1) >>> 8) as u8 & 1); 1065 | cmov(t, unchecked(pc[9]), (((b ^ 9) - 1) >>> 8) as u8 & 1); 1066 | cmov(t, unchecked(pc[8]), (((b ^ 8) - 1) >>> 8) as u8 & 1); 1067 | cmov(t, unchecked(pc[7]), (((b ^ 7) - 1) >>> 8) as u8 & 1); 1068 | cmov(t, unchecked(pc[6]), (((b ^ 6) - 1) >>> 8) as u8 & 1); 1069 | cmov(t, unchecked(pc[5]), (((b ^ 5) - 1) >>> 8) as u8 & 1); 1070 | cmov(t, unchecked(pc[4]), (((b ^ 4) - 1) >>> 8) as u8 & 1); 1071 | cmov(t, unchecked(pc[3]), (((b ^ 3) - 1) >>> 8) as u8 & 1); 1072 | cmov(t, unchecked(pc[2]), (((b ^ 2) - 1) >>> 8) as u8 & 1); 1073 | cmov(t, unchecked(pc[1]), (((b ^ 1) - 1) >>> 8) as u8 & 1); 1074 | add(p, t); 1075 | } 1076 | } 1077 | 1078 | @inline function fe25519CopyPrecomp(r: Fe25519, a: i64[]): void { 1079 | memory.copy(changetype(r), a.dataStart, sizeof() * 16); 1080 | } 1081 | 1082 | function scalarmultBase(p: Ge, s: ScalarPacked): void { 1083 | let q = newGe(), 1084 | t = newGe(), 1085 | b: u8; 1086 | 1087 | fe25519Copy(p.x, fe25519_0); 1088 | fe25519Copy(p.y, fe25519_1); 1089 | fe25519Copy(p.z, fe25519_1); 1090 | fe25519Copy(p.t, fe25519_0); 1091 | 1092 | fe25519Copy(q.z, fe25519_1); 1093 | 1094 | let precomp_base = precompBase; 1095 | for (let i = 0; i <= 255; ++i) { 1096 | b = (s[(i >>> 3)] >>> (i as u8 & 7)) & 1; 1097 | let precomp = precomp_base[i]; 1098 | fe25519CopyPrecomp(q.x, precomp[0]); 1099 | fe25519CopyPrecomp(q.y, precomp[1]); 1100 | fe25519CopyPrecomp(q.t, precomp[2]); 1101 | geCopy(t, p); 1102 | add(t, q); 1103 | cmov(p, t, b); 1104 | } 1105 | } 1106 | 1107 | // Ed25519 encoding 1108 | 1109 | function unpack(r: Ge, p: GePacked, neg: bool = false): bool { 1110 | let t = newFe25519(), 1111 | chk = newFe25519(), 1112 | u = newFe25519(), 1113 | v = newFe25519(); 1114 | 1115 | fe25519Copy(r.z, fe25519_1); 1116 | fe25519Unpack(r.y, p); 1117 | fe25519Sq(u, r.y); 1118 | fe25519Mult(v, u, D); 1119 | fe25519Sub(u, u, r.z); 1120 | fe25519Add(v, r.z, v); 1121 | 1122 | fe25519Mult(t, u, v); 1123 | fe25519Pow252m3(t, t); 1124 | fe25519Mult(r.x, t, u); 1125 | fe25519Sq(chk, r.x); 1126 | fe25519Mult(chk, chk, v); 1127 | if (!fe25519Eq(chk, u)) { 1128 | fe25519Mult(r.x, r.x, SQRTM1); 1129 | } 1130 | fe25519Sq(chk, r.x); 1131 | fe25519Mult(chk, chk, v); 1132 | if (!fe25519Eq(chk, u)) { 1133 | return false; 1134 | } 1135 | if ((fe25519IsNegative(r.x) as u8 === (p[31] >> 7)) === neg) { 1136 | fe25519Neg(r.x); 1137 | } 1138 | fe25519Mult(r.t, r.x, r.y); 1139 | 1140 | return true; 1141 | } 1142 | 1143 | @inline function isIdentity(s: GePacked): bool { 1144 | let c: u8 = unchecked(s[0]) ^ 0x01; 1145 | for (let i = 1; i < 31; i++) { 1146 | c |= unchecked(s[i]); 1147 | } 1148 | c |= unchecked(s[31]) & 0x7f; 1149 | 1150 | return c === 0; 1151 | } 1152 | 1153 | // Check if a field element has canonical encoding, ignoring the top bit 1154 | function isCanonical(s: GePacked): bool { 1155 | let c: u32 = (s[31] & 0x7f) ^ 0x7f; 1156 | for (let i = 30; i > 0; --i) { 1157 | c |= s[i] ^ 0xff; 1158 | } 1159 | c = (c - 1) >> 8; 1160 | let d = ((0xed - 1) as u32 - (s[0] as u32)) >> 8; 1161 | 1162 | return !(c & d & 1); 1163 | } 1164 | 1165 | function hasLowOrder(q: Ge): bool { 1166 | let p = newGe(); 1167 | geCopy(p, q); 1168 | clearCofactor(p); 1169 | return fe25519IsZero(p.x); 1170 | } 1171 | 1172 | // Ristretto encoding 1173 | 1174 | function ristrettoSqrtRatioM1(x: Fe25519, u: Fe25519, v: Fe25519): bool { 1175 | let v3 = newFe25519(), vxx = newFe25519(), 1176 | m_root_check = newFe25519(), p_root_check = newFe25519(), f_root_check = newFe25519(), 1177 | x_sqrtm1 = newFe25519(); 1178 | fe25519Sq(v3, v); 1179 | fe25519Mult(v3, v3, v); 1180 | fe25519Sq(x, v3); 1181 | fe25519Mult(x, x, v); 1182 | fe25519Mult(x, x, u); 1183 | 1184 | fe25519Pow252m3(x, x); 1185 | fe25519Mult(x, x, v3); 1186 | fe25519Mult(x, x, u); 1187 | 1188 | fe25519Sq(vxx, x); 1189 | fe25519Mult(vxx, vxx, v); 1190 | fe25519Sub(m_root_check, vxx, u); 1191 | fe25519Add(p_root_check, vxx, u); 1192 | fe25519Mult(f_root_check, u, SQRTM1); 1193 | fe25519Add(f_root_check, vxx, f_root_check); 1194 | let has_m_root = fe25519IsZero(m_root_check); 1195 | let has_p_root = fe25519IsZero(p_root_check); 1196 | let has_f_root = fe25519IsZero(f_root_check); 1197 | fe25519Mult(x_sqrtm1, x, SQRTM1); 1198 | 1199 | fe25519Cmov(x, x_sqrtm1, (has_p_root | has_f_root) as i64); 1200 | fe25519Abs(x, x); 1201 | 1202 | return has_m_root | has_p_root; 1203 | } 1204 | 1205 | function ristrettoIsCanonical(s: GePacked): bool { 1206 | let c = ((s[31] & 0x7f) ^ 0x7f) as u64; 1207 | for (let i = 30; i > 0; i--) { 1208 | c |= s[i] ^ 0xff; 1209 | } 1210 | c = (c - 1) >> 8; 1211 | let d = (0xed as u64 - 1 as u64 - (s[0] as u64)) >> 8; 1212 | let e = s[31] >> 7; 1213 | 1214 | return (1 - (((c & d) | e | s[0]) & 1)) as bool; 1215 | } 1216 | 1217 | function ristrettoUnpack(h: Ge, s: GePacked, neg: bool = false): bool { 1218 | let inv_sqrt = newFe25519(), s_ = newFe25519(), ss = newFe25519(), 1219 | u1 = newFe25519(), u2 = newFe25519(), u1u1 = newFe25519(), u2u2 = newFe25519(), 1220 | v = newFe25519(), v_u2u2 = newFe25519(); 1221 | 1222 | if (!ristrettoIsCanonical(s)) { 1223 | return false; 1224 | } 1225 | fe25519Unpack(s_, s); 1226 | fe25519Sq(ss, s_); 1227 | 1228 | fe25519Copy(u1, fe25519_1); 1229 | fe25519Sub(u1, u1, ss); 1230 | fe25519Sq(u1u1, u1); 1231 | 1232 | fe25519Copy(u2, fe25519_1); 1233 | fe25519Add(u2, u2, ss); 1234 | fe25519Sq(u2u2, u2); 1235 | 1236 | fe25519Mult(v, D, u1u1); 1237 | fe25519Neg(v); 1238 | fe25519Sub(v, v, u2u2); 1239 | 1240 | fe25519Mult(v_u2u2, v, u2u2); 1241 | 1242 | let was_square = ristrettoSqrtRatioM1(inv_sqrt, fe25519_1, v_u2u2); 1243 | let x = h.x, y = h.y, z = h.z, t = h.t; 1244 | 1245 | fe25519Mult(x, inv_sqrt, u2); 1246 | fe25519Mult(y, inv_sqrt, x); 1247 | fe25519Mult(y, y, v); 1248 | 1249 | fe25519Mult(x, x, s_); 1250 | fe25519Add(x, x, x); 1251 | fe25519Abs(x, x); 1252 | fe25519Mult(y, u1, y); 1253 | 1254 | fe25519Copy(z, fe25519_1); 1255 | if (neg) { 1256 | fe25519Neg(y); 1257 | } 1258 | fe25519Mult(t, x, y); 1259 | 1260 | return !((!was_square) | (fe25519IsNegative(t) ^ neg) | fe25519IsZero(y)); 1261 | } 1262 | 1263 | function ristrettoPack(s: GePacked, h: Ge): void { 1264 | let den1 = newFe25519(), den2 = newFe25519(), den_inv = newFe25519(), eden = newFe25519(), 1265 | inv_sqrt = newFe25519(), ix = newFe25519(), iy = newFe25519(), s_ = newFe25519(), 1266 | t_z_inv = newFe25519(), u1 = newFe25519(), u2 = newFe25519(), u1_u2u2 = newFe25519(), 1267 | x_ = newFe25519(), y_ = newFe25519(), x_z_inv = newFe25519(), z_inv = newFe25519(), 1268 | zmy = newFe25519(); 1269 | let x = h.x, y = h.y, z = h.z, t = h.t; 1270 | 1271 | fe25519Add(u1, z, y); 1272 | fe25519Sub(zmy, z, y); 1273 | fe25519Mult(u1, u1, zmy); 1274 | fe25519Mult(u2, x, y); 1275 | 1276 | fe25519Sq(u1_u2u2, u2); 1277 | fe25519Mult(u1_u2u2, u1, u1_u2u2); 1278 | 1279 | ristrettoSqrtRatioM1(inv_sqrt, fe25519_1, u1_u2u2); 1280 | fe25519Mult(den1, inv_sqrt, u1); 1281 | fe25519Mult(den2, inv_sqrt, u2); 1282 | fe25519Mult(z_inv, den1, den2); 1283 | fe25519Mult(z_inv, z_inv, t); 1284 | 1285 | fe25519Mult(ix, x, SQRTM1); 1286 | fe25519Mult(iy, y, SQRTM1); 1287 | fe25519Mult(eden, den1, INVSQRTAMD); 1288 | 1289 | fe25519Mult(t_z_inv, t, z_inv); 1290 | let rotate = fe25519IsNegative(t_z_inv) as i64; 1291 | 1292 | fe25519Copy(x_, x); 1293 | fe25519Copy(y_, y); 1294 | fe25519Copy(den_inv, den2); 1295 | 1296 | fe25519Cmov(x_, iy, rotate); 1297 | fe25519Cmov(y_, ix, rotate); 1298 | fe25519Cmov(den_inv, eden, rotate); 1299 | 1300 | fe25519Mult(x_z_inv, x_, z_inv); 1301 | fe25519Cneg(y_, y_, fe25519IsNegative(x_z_inv)); 1302 | 1303 | fe25519Sub(s_, z, y_); 1304 | fe25519Mult(s_, den_inv, s_); 1305 | fe25519Abs(s_, s_); 1306 | fe25519Pack(s, s_); 1307 | } 1308 | 1309 | @inline function ristrettoIsIdentity(s: GePacked): bool { 1310 | return allZeros(s); 1311 | } 1312 | 1313 | function ristrettoElligator(p: Ge, t: Fe25519): void { 1314 | let c = newFe25519(), n = newFe25519(), r = newFe25519(), rpd = newFe25519(), 1315 | s = newFe25519(), s_prime = newFe25519(), ss = newFe25519(), 1316 | u = newFe25519(), v = newFe25519(), 1317 | w0 = newFe25519(), w1 = newFe25519(), w2 = newFe25519(), w3 = newFe25519(); 1318 | 1319 | fe25519Sq(r, t); 1320 | fe25519Mult(r, SQRTM1, r); 1321 | fe25519Add(u, r, fe25519_1); 1322 | fe25519Mult(u, u, ONEMSQD); 1323 | fe25519Sub(c, fe25519_0, fe25519_1); 1324 | fe25519Add(rpd, r, D); 1325 | fe25519Mult(v, r, D); 1326 | fe25519Sub(v, c, v); 1327 | fe25519Mult(v, v, rpd); 1328 | 1329 | let not_square = 1 - (ristrettoSqrtRatioM1(s, u, v) as i64); 1330 | fe25519Mult(s_prime, s, t); 1331 | fe25519Abs(s_prime, s_prime); 1332 | fe25519Neg(s_prime); 1333 | fe25519Cmov(s, s_prime, not_square); 1334 | fe25519Cmov(c, r, not_square); 1335 | 1336 | fe25519Sub(n, r, fe25519_1); 1337 | fe25519Mult(n, n, c); 1338 | fe25519Mult(n, n, SQDMONE); 1339 | fe25519Sub(n, n, v); 1340 | 1341 | fe25519Add(w0, s, s); 1342 | fe25519Mult(w0, w0, v); 1343 | fe25519Mult(w1, n, SQRTADM1); 1344 | fe25519Sq(ss, s); 1345 | fe25519Sub(w2, fe25519_1, ss); 1346 | fe25519Add(w3, fe25519_1, ss); 1347 | 1348 | fe25519Mult(p.x, w0, w3); 1349 | fe25519Mult(p.y, w2, w1); 1350 | fe25519Mult(p.z, w1, w3); 1351 | fe25519Mult(p.t, w0, w2); 1352 | } 1353 | 1354 | type Hash512 = Uint8Array(64); 1355 | 1356 | function ristrettoFromHash(s: GePacked, r: Hash512): void { 1357 | let r0 = newFe25519(), r1 = newFe25519(); 1358 | let p0 = newGe(), p1 = newGe(); 1359 | 1360 | fe25519Unpack(r0, r.subarray(0, 32)); 1361 | fe25519Unpack(r1, r.subarray(32, 64)); 1362 | ristrettoElligator(p0, r0); 1363 | ristrettoElligator(p1, r1); 1364 | add(p0, p1); 1365 | ristrettoPack(s, p0); 1366 | } 1367 | 1368 | // Common functions used for signatures 1369 | 1370 | function _signSyntheticRHv(hs: Uint8Array, r: isize, Z: Uint8Array, sk: Uint8Array): isize { 1371 | let zeros = new Uint8Array(128); 1372 | let empty_labelset = new Uint8Array(3); 1373 | let Zlen = Z.length; 1374 | 1375 | if (Zlen > 128 - (32 + 3)) { 1376 | Z = hash(Z); 1377 | Zlen = Z.length; 1378 | } 1379 | empty_labelset[0] = 0x02; 1380 | 1381 | r = Sha512._hashUpdate(hs, B, 32, r); 1382 | r = Sha512._hashUpdate(hs, empty_labelset, 3, r); 1383 | r = Sha512._hashUpdate(hs, Z, Zlen, r); 1384 | r = Sha512._hashUpdate(hs, zeros, 128 - ((32 + 3 + Zlen) & 127), r); 1385 | r = Sha512._hashUpdate(hs, sk, 32, r); 1386 | r = Sha512._hashUpdate(hs, zeros, 128 - (32 & 127), r); 1387 | r = Sha512._hashUpdate(hs, empty_labelset, 3, r); 1388 | r = Sha512._hashUpdate(hs, sk.subarray(32), 32, r); 1389 | 1390 | return r; 1391 | } 1392 | 1393 | let B = newFe25519Packed(); 1394 | for (let i = 0; i < 32; ++i) { 1395 | B[i] = 0x66; 1396 | } 1397 | 1398 | // Ed25519 1399 | 1400 | type KeyPair = Uint8Array(64); 1401 | type Signature = Uint8Array(64); 1402 | 1403 | function _signEdKeypairFromSeed(kp: KeyPair): void { 1404 | let d = new Uint8Array(64); 1405 | let p = newGe(); 1406 | 1407 | Sha512._hash(d, kp, 32); 1408 | scClamp(d); 1409 | scalarmultBase(p, d); 1410 | pack(kp.subarray(32), p); 1411 | } 1412 | 1413 | function _signEdDetached(sig: Signature, m: Uint8Array, kp: KeyPair, Z: Uint8Array | null): void { 1414 | let R = newGe(); 1415 | let az = new Uint8Array(64); 1416 | let nonce = newScalarDouble(); 1417 | let hram = newScalarDouble(); 1418 | let x = newScalar(); 1419 | let mlen = m.length; 1420 | let hs = Sha512._hashInit(); 1421 | let r: isize = 0; 1422 | 1423 | Sha512._hash(az, kp, 32); 1424 | if (Z !== null && Z.length > 0) { 1425 | r = _signSyntheticRHv(hs, r, Z, az); 1426 | } else { 1427 | r = Sha512._hashUpdate(hs, az.subarray(32), 32, r); 1428 | } 1429 | r = Sha512._hashUpdate(hs, m, mlen, r); 1430 | Sha512._hashFinal(hs, nonce, 32 + mlen, r); 1431 | scReduce(nonce); 1432 | scalarmultBase(R, nonce); 1433 | pack(sig, R); 1434 | setU8(sig, kp.subarray(32), 32); 1435 | 1436 | hs = Sha512._hashInit(); 1437 | r = Sha512._hashUpdate(hs, sig, 64, 0); 1438 | r = Sha512._hashUpdate(hs, m, mlen, r); 1439 | Sha512._hashFinal(hs, hram, 64 + mlen, r); 1440 | scReduce(hram); 1441 | scClamp(az); 1442 | for (let i = 0; i < 32; ++i) { 1443 | x[i] = nonce[i]; 1444 | } 1445 | for (let i = 0; i < 32; ++i) { 1446 | for (let j = 0; j < 32; ++j) { 1447 | x[i + j] += unchecked((hram[i] as i64) * (az[j] as i64)); 1448 | } 1449 | } 1450 | scModL(sig.subarray(32), x); 1451 | } 1452 | 1453 | function _signEdVerifyDetached(sig: Signature, m: Uint8Array, pk: GePacked): bool { 1454 | if (!isCanonical(pk) || !scIsLtL(sig.subarray(32))) { 1455 | return false; 1456 | } 1457 | let A = newGe(); 1458 | if (!unpack(A, pk, true) || hasLowOrder(A)) { 1459 | return false; 1460 | } 1461 | let expectedR_ = sig.subarray(0, 32); 1462 | if (!isCanonical(expectedR_)) { 1463 | return false; 1464 | } 1465 | let expectedR = newGe(); 1466 | if (!unpack(expectedR, expectedR_, false)) { 1467 | return false; 1468 | } 1469 | 1470 | let hram = newScalarDouble(); 1471 | let hs = Sha512._hashInit(); 1472 | let r = Sha512._hashUpdate(hs, sig, 32, 0); 1473 | r = Sha512._hashUpdate(hs, pk, 32, r); 1474 | r = Sha512._hashUpdate(hs, m, m.length, r); 1475 | Sha512._hashFinal(hs, hram, 32 + 32 + m.length, r); 1476 | scReduce(hram); 1477 | 1478 | let ah = newGe(); 1479 | scalarmult(ah, hram, A); 1480 | let sbAh = newGe(); 1481 | scalarmultBase(sbAh, sig.subarray(32)); 1482 | add(sbAh, ah); 1483 | sub(expectedR, sbAh); 1484 | 1485 | return hasLowOrder(expectedR); 1486 | } 1487 | 1488 | // Signatures over Ristretto 1489 | 1490 | function _signKeypairFromSeed(kp: KeyPair): void { 1491 | let d = newScalarDouble(); 1492 | let p = newGe(); 1493 | 1494 | Sha512._hash(d, kp, 32); 1495 | scalarmultBase(p, d); 1496 | ristrettoPack(kp.subarray(32), p); 1497 | } 1498 | 1499 | function _signDetached(sig: Signature, m: Uint8Array, kp: KeyPair, Z: Uint8Array | null): void { 1500 | let R = newGe(); 1501 | let az = new Uint8Array(64); 1502 | let nonce = newScalarDouble(); 1503 | let hram = newScalarDouble(); 1504 | let x = newScalar(); 1505 | let mlen = m.length; 1506 | let hs = Sha512._hashInit(); 1507 | let r: isize = 0; 1508 | 1509 | Sha512._hash(az, kp, 32); 1510 | if (Z !== null && Z.length > 0) { 1511 | r = _signSyntheticRHv(hs, r, Z, az); 1512 | } else { 1513 | r = Sha512._hashUpdate(hs, az.subarray(32), 32, r); 1514 | } 1515 | r = Sha512._hashUpdate(hs, m, mlen, r); 1516 | Sha512._hashFinal(hs, nonce, 32 + mlen, r); 1517 | setU8(sig, kp.subarray(32), 32); 1518 | 1519 | scReduce(nonce); 1520 | scalarmultBase(R, nonce); 1521 | ristrettoPack(sig, R); 1522 | 1523 | hs = Sha512._hashInit(); 1524 | r = Sha512._hashUpdate(hs, sig, 64, 0); 1525 | r = Sha512._hashUpdate(hs, m, mlen, r); 1526 | Sha512._hashFinal(hs, hram, 64 + mlen, r); 1527 | scReduce(hram); 1528 | for (let i = 0; i < 32; ++i) { 1529 | x[i] = nonce[i]; 1530 | } 1531 | for (let i = 0; i < 32; ++i) { 1532 | for (let j = 0; j < 32; ++j) { 1533 | x[i + j] += unchecked((hram[i] as i64) * (az[j] as i64)); 1534 | } 1535 | } 1536 | scModL(sig.subarray(32), x); 1537 | } 1538 | 1539 | function _signVerifyDetached(sig: Signature, m: Uint8Array, pk: GePacked): bool { 1540 | if (ristrettoIsIdentity(pk) || !scIsLtL(sig.subarray(32))) { 1541 | return false; 1542 | } 1543 | let A = newGe(); 1544 | if (!ristrettoUnpack(A, pk, true)) { 1545 | return false; 1546 | } 1547 | let h = newScalarDouble(); 1548 | let hs = Sha512._hashInit(); 1549 | let r = Sha512._hashUpdate(hs, sig, 32, 0); 1550 | r = Sha512._hashUpdate(hs, pk, 32, r); 1551 | r = Sha512._hashUpdate(hs, m, m.length, r); 1552 | Sha512._hashFinal(hs, h, 32 + 32 + m.length, r); 1553 | scReduce(h); 1554 | 1555 | let R = newGe(); 1556 | let rcheck = newFe25519Packed(); 1557 | scalarmult(R, h, A); 1558 | scalarmultBase(A, sig.subarray(32)); 1559 | add(R, A); 1560 | 1561 | ristrettoPack(rcheck, R); 1562 | 1563 | return verify32(rcheck, sig.subarray(0, 32)); 1564 | } 1565 | 1566 | // Exported API 1567 | 1568 | /** 1569 | * Signature size, in bytes 1570 | */ 1571 | @global export const SIGN_BYTES: isize = 64; 1572 | 1573 | /** 1574 | * Public key size, in bytes 1575 | */ 1576 | @global export const SIGN_PUBLICKEYBYTES: isize = 32; 1577 | 1578 | /** 1579 | * Secret key size, in bytes 1580 | */ 1581 | @global export const SIGN_SECRETKEYBYTES: isize = 32; 1582 | 1583 | /** 1584 | * Key pair size, in bytes 1585 | */ 1586 | @global export const SIGN_KEYPAIRBYTES: isize = 64; 1587 | 1588 | /** 1589 | * Seed size, in bytes 1590 | */ 1591 | @global export const SIGN_SEEDBYTES: isize = 32; 1592 | 1593 | /** 1594 | * Recommended random bytes size, in bytes 1595 | */ 1596 | @global export const SIGN_RANDBYTES: isize = 32; 1597 | 1598 | /** 1599 | * Ed25519 signature size, in bytes 1600 | */ 1601 | @global export const SIGN_ED_BYTES: isize = 64; 1602 | 1603 | /** 1604 | * Ed25519 public key size, in bytes 1605 | */ 1606 | @global export const SIGN_ED_PUBLICKEYBYTES: isize = 32; 1607 | 1608 | /** 1609 | * Ed25519 secret key size, in bytes 1610 | */ 1611 | @global export const SIGN_ED_SECRETKEYBYTES: isize = 32; 1612 | 1613 | /** 1614 | * Ed25519 key pair size, in bytes 1615 | */ 1616 | @global export const SIGN_ED_KEYPAIRBYTES: isize = 64; 1617 | 1618 | /** 1619 | * Ed25519 seed size, in bytes 1620 | */ 1621 | @global export const SIGN_ED_SEEDBYTES: isize = 32; 1622 | 1623 | /** 1624 | * Non-deterministic Ed25519 recommended random bytes size, in bytes 1625 | */ 1626 | @global export const SIGN_ED_RANDBYTES: isize = 32; 1627 | 1628 | /** 1629 | * Hash function output size, in bytes 1630 | */ 1631 | @global export const HASH_BYTES: isize = 64; 1632 | 1633 | /** 1634 | * HMAC output size, in bytes 1635 | */ 1636 | @global export const HMAC_BYTES: isize = 64; 1637 | 1638 | /** 1639 | * SHA-256 function output size, in bytes 1640 | */ 1641 | @global export const SHA256_HASH_BYTES: isize = 32; 1642 | 1643 | /** 1644 | * HMAC-SHA-256 output size, in bytes 1645 | */ 1646 | @global export const SHA256_HMAC_BYTES: isize = 32; 1647 | 1648 | /** 1649 | * Size of an encoded scalar, in bytes 1650 | */ 1651 | @global export const FA_SCALARBYTES: isize = 32; 1652 | 1653 | /** 1654 | * Size of an encoded point, in bytes 1655 | */ 1656 | @global export const FA_POINTBYTES: isize = 32; 1657 | 1658 | /** 1659 | * Fill an array with zeros 1660 | * @param x Array to clear 1661 | */ 1662 | @global export function memzero(x: Uint8Array): void { 1663 | for (let i = 0, j = x.length; i < j; ++i) { 1664 | x[i] = 0; 1665 | } 1666 | } 1667 | 1668 | /** 1669 | * Check two arrays for equality 1670 | * @param x First array 1671 | * @param y Second array 1672 | * @returns true if `x === y` 1673 | */ 1674 | @global export function equals(x: Uint8Array, y: Uint8Array): bool { 1675 | let len = x.length; 1676 | let d: u8 = 0; 1677 | 1678 | if (len === 0 || len !== y.length) { 1679 | return false; 1680 | } 1681 | for (let i = 0; i < len; ++i) { 1682 | d |= x[i] ^ y[i]; 1683 | } 1684 | return d === 0; 1685 | } 1686 | 1687 | /** 1688 | * Sign a message and returns its signature. 1689 | * @param m Message to sign 1690 | * @param kp Key pair (`SIGN_KEYPAIRBYTES` long) 1691 | * @param Z Random bytes. This can be an empty array to produce deterministic 1692 | * signatures 1693 | * @returns Signature 1694 | */ 1695 | @global export function sign(m: Uint8Array, kp: Uint8Array, Z: Uint8Array | null = null): Uint8Array { 1696 | let sig = new Uint8Array(SIGN_BYTES); 1697 | _signDetached(sig, m, kp, Z); 1698 | 1699 | return sig; 1700 | } 1701 | 1702 | /** 1703 | * Verify a signature 1704 | * @param m Message 1705 | * @param sig Signature 1706 | * @param pk Public key 1707 | * @returns `true` on success 1708 | */ 1709 | @global export function signVerify(sig: Uint8Array, m: Uint8Array, pk: Uint8Array): bool { 1710 | if (sig.length !== SIGN_BYTES) { 1711 | throw new Error('bad signature size'); 1712 | } 1713 | if (pk.length !== SIGN_PUBLICKEYBYTES) { 1714 | throw new Error('bad public key size'); 1715 | } 1716 | return _signVerifyDetached(sig, m, pk); 1717 | } 1718 | 1719 | /** 1720 | * Create a new key pair from a seed 1721 | * @param seed Seed (`SIGN_SEEDBYTES` long) 1722 | * @returns Key pair 1723 | */ 1724 | @global export function signKeypairFromSeed(seed: Uint8Array): Uint8Array { 1725 | if (seed.length !== SIGN_SEEDBYTES) { 1726 | throw new Error('bad seed size'); 1727 | } 1728 | let kp = new Uint8Array(SIGN_KEYPAIRBYTES); 1729 | for (let i = 0; i < 32; ++i) { 1730 | kp[i] = seed[i]; 1731 | } 1732 | _signKeypairFromSeed(kp); 1733 | 1734 | return kp; 1735 | } 1736 | 1737 | /** 1738 | * Return the public key from a key pair 1739 | * @param kp Key pair 1740 | * @returns Public key 1741 | */ 1742 | @global export function signPublicKey(kp: Uint8Array): Uint8Array { 1743 | const len = SIGN_PUBLICKEYBYTES; 1744 | let pk = new Uint8Array(len); 1745 | 1746 | for (let i = 0; i < len; ++i) { 1747 | pk[i] = kp[(i + 32)]; 1748 | } 1749 | return pk; 1750 | } 1751 | 1752 | /** 1753 | * Return the secret key from a key pair 1754 | * @param kp Key pair 1755 | * @returns Secret key 1756 | */ 1757 | @global export function signSecretKey(kp: Uint8Array): Uint8Array { 1758 | const len = SIGN_SECRETKEYBYTES; 1759 | let sk = new Uint8Array(len); 1760 | 1761 | for (let i = 0; i < len; ++i) { 1762 | sk[i] = kp[i]; 1763 | } 1764 | return sk; 1765 | } 1766 | 1767 | /** 1768 | * Sign a message using Ed25519 and returns its signature. 1769 | * @param m Message to sign 1770 | * @param kp Key pair (`SIGN_ED_KEYPAIRBYTES` long) 1771 | * @param Z Random bytes. This can be an empty array to produce deterministic 1772 | * signatures 1773 | * @returns Signature 1774 | */ 1775 | @global export function signEd(m: Uint8Array, kp: Uint8Array, Z: Uint8Array | null = null): Uint8Array { 1776 | let sig = new Uint8Array(SIGN_ED_BYTES); 1777 | _signEdDetached(sig, m, kp, Z); 1778 | 1779 | return sig; 1780 | } 1781 | 1782 | /** 1783 | * Verify a signature using Ed25519 1784 | * @param m Message 1785 | * @param sig Signature 1786 | * @param pk Public key 1787 | * @returns `true` on success 1788 | */ 1789 | @global export function signEdVerify(sig: Uint8Array, m: Uint8Array, pk: Uint8Array): bool { 1790 | if (sig.length !== SIGN_ED_BYTES) { 1791 | throw new Error('bad signature size'); 1792 | } 1793 | if (pk.length !== SIGN_ED_PUBLICKEYBYTES) { 1794 | throw new Error('bad public key size'); 1795 | } 1796 | return _signEdVerifyDetached(sig, m, pk); 1797 | } 1798 | 1799 | /** 1800 | * Create a new Ed25519 key pair from a seed 1801 | * @param seed Seed (`SIGN_ED_SEEDBYTES` long) 1802 | * @returns Key pair 1803 | */ 1804 | @global export function signEdKeypairFromSeed(seed: Uint8Array): Uint8Array { 1805 | if (seed.length !== SIGN_ED_SEEDBYTES) { 1806 | throw new Error('bad seed size'); 1807 | } 1808 | let kp = new Uint8Array(SIGN_ED_KEYPAIRBYTES); 1809 | for (let i = 0; i < 32; ++i) { 1810 | kp[i] = seed[i]; 1811 | } 1812 | _signEdKeypairFromSeed(kp); 1813 | 1814 | return kp; 1815 | } 1816 | 1817 | /** 1818 | * Return the public key from an Ed25519 key pair 1819 | * @param kp Key pair 1820 | * @returns Public key 1821 | */ 1822 | @global export function signEdPublicKey(kp: Uint8Array): Uint8Array { 1823 | const len = SIGN_ED_PUBLICKEYBYTES; 1824 | let pk = new Uint8Array(len); 1825 | 1826 | for (let i = 0; i < len; ++i) { 1827 | pk[i] = kp[(i + 32)]; 1828 | } 1829 | return pk; 1830 | } 1831 | 1832 | /** 1833 | * Return the secret key from an Ed25519ED_ key pair 1834 | * @param kp Key pair 1835 | * @returns Secret key 1836 | */ 1837 | @global export function signEdSecretKey(kp: Uint8Array): Uint8Array { 1838 | const len = SIGN_ED_SECRETKEYBYTES; 1839 | let sk = new Uint8Array(len); 1840 | 1841 | for (let i = 0; i < len; ++i) { 1842 | sk[i] = kp[i]; 1843 | } 1844 | return sk; 1845 | } 1846 | 1847 | /** 1848 | * Initialize a multipart hash computation 1849 | * @returns A hash function state 1850 | */ 1851 | @global export function hashInit(): Uint8Array { 1852 | return Sha512._hashInit(); 1853 | } 1854 | 1855 | /** 1856 | * Absorb data to be hashed 1857 | * @param st Hash function state 1858 | * @param m (partial) message 1859 | */ 1860 | @global export function hashUpdate(st: Uint8Array, m: Uint8Array): void { 1861 | let r = load64_be(st, 64 + 128); 1862 | let t = load64_be(st, 64 + 128 + 8); 1863 | let n = m.length; 1864 | 1865 | t += n; 1866 | r = Sha512._hashUpdate(st, m, n, r as isize); 1867 | store64_be(st, 64 + 128, r as u64); 1868 | store64_be(st, 64 + 128 + 8, t as u64); 1869 | } 1870 | 1871 | /** 1872 | * Finalize a hash computation 1873 | * @param st Hash function state 1874 | * @returns Hash 1875 | */ 1876 | @global export function hashFinal(st: Uint8Array): Uint8Array { 1877 | let h = new Uint8Array(HASH_BYTES); 1878 | let r = load64_be(st, 64 + 128); 1879 | let t = load64_be(st, 64 + 128 + 8); 1880 | 1881 | Sha512._hashFinal(st, h, t as isize, r as isize); 1882 | 1883 | return h; 1884 | } 1885 | 1886 | /** 1887 | * Compute a hash for a single-part message 1888 | * @param m Message 1889 | * @returns Hash 1890 | */ 1891 | @global export function hash(m: Uint8Array): Uint8Array { 1892 | let h = new Uint8Array(HASH_BYTES); 1893 | Sha512._hash(h, m, m.length); 1894 | return h; 1895 | } 1896 | 1897 | /** 1898 | * HMAC-SHA-512 1899 | * @param m Message 1900 | * @param k Key 1901 | * @returns `HMAC-SHA-512(m, k)` 1902 | */ 1903 | @global export function hmac(m: Uint8Array, k: Uint8Array): Uint8Array { 1904 | return Sha512._hmac(m, k); 1905 | } 1906 | 1907 | /** 1908 | * Initialize a multipart SHA-256 hash computation 1909 | * @returns A hash function state 1910 | */ 1911 | @global export function sha256HashInit(): Uint8Array { 1912 | return Sha256._hashInit(); 1913 | } 1914 | 1915 | /** 1916 | * Absorb data to be hashed using SHA-256 1917 | * @param st Hash function state 1918 | * @param m (partial) message 1919 | */ 1920 | @global export function sha256HashUpdate(st: Uint8Array, m: Uint8Array): void { 1921 | let r = load64_be(st, 32 + 64); 1922 | let t = load64_be(st, 32 + 64 + 8); 1923 | let n = m.length; 1924 | t += n; 1925 | r = Sha256._hashUpdate(st, m, n, r as isize); 1926 | store64_be(st, 32 + 64, r as u64); 1927 | store64_be(st, 32 + 64 + 8, t as u64); 1928 | } 1929 | 1930 | /** 1931 | * Finalize a SHA-256 hash computation 1932 | * @param st Hash function state 1933 | * @returns Hash 1934 | */ 1935 | @global export function sha256HashFinal(st: Uint8Array): Uint8Array { 1936 | let h = new Uint8Array(SHA256_HASH_BYTES); 1937 | let r = load64_be(st, 32 + 64); 1938 | let t = load64_be(st, 32 + 64 + 8); 1939 | 1940 | Sha256._hashFinal(st, h, t as isize, r as isize); 1941 | 1942 | return h; 1943 | } 1944 | 1945 | /** 1946 | * Compute a SHA-256 hash for a single-part message 1947 | * @param m Message 1948 | * @returns Hash 1949 | */ 1950 | @global export function sha256Hash(m: Uint8Array): Uint8Array { 1951 | let h = new Uint8Array(SHA256_HASH_BYTES); 1952 | Sha256._hash(h, m, m.length); 1953 | return h; 1954 | } 1955 | 1956 | /** 1957 | * HMAC-SHA-256 1958 | * @param m Message 1959 | * @param k Key 1960 | * @returns `HMAC-SHA-256(m, k)` 1961 | */ 1962 | @global export function sha256Hmac(m: Uint8Array, k: Uint8Array): Uint8Array { 1963 | return Sha256._hmac(m, k); 1964 | } 1965 | 1966 | /** 1967 | * Compute the multiplicative inverse of a scalar 1968 | * @param s Scalar 1969 | * @returns `s^-1` 1970 | */ 1971 | @global export function faScalarInverse(s: Uint8Array): Uint8Array { 1972 | return scInverse(s); 1973 | } 1974 | 1975 | /** 1976 | * Compute s mod the order of the prime order group 1977 | * 1978 | * @param s Scalar (between 32 and 64 bytes) 1979 | * @returns `s` reduced mod `L` 1980 | */ 1981 | @global export function faScalarReduce(s: Uint8Array): Uint8Array { 1982 | let s_ = newScalarDouble(); 1983 | if (s.length < 32 || s.length > 64) { 1984 | throw new Error('faScalarReduce() argument should be between 32 and 64 bytes long'); 1985 | } 1986 | setU8(s_, s); 1987 | scReduce(s_); 1988 | let r = newScalarPacked(); 1989 | for (let i = 0; i < 32; ++i) { 1990 | r[i] = s_[i]; 1991 | } 1992 | return r; 1993 | } 1994 | 1995 | /** 1996 | * Multiply `s` by the Ed25519 group cofactor 1997 | * 1998 | * @param s Scalar (32 bytes) 1999 | * @returns `s * 8` 2000 | */ 2001 | @global export function faScalarCofactorMult(s: Uint8Array): Uint8Array { 2002 | if (s.length !== 32) { 2003 | throw new Error('faScalarCofactorMult() argument should be 32 bytes long'); 2004 | } 2005 | if ((s[31] & 224) !== 0) { 2006 | throw new Error("faScalarCofactorMult() would overflow"); 2007 | } 2008 | let r = newScalarPacked(), t: u8 = 0; 2009 | for (let i = 0; i < 32; i++) { 2010 | let si = s[i]; 2011 | r[i] = (si << 3) | t; 2012 | t = (si >>> 5); 2013 | } 2014 | return r; 2015 | } 2016 | 2017 | /** 2018 | * Compute the additive inverse of a scalar (mod L) 2019 | * @param s Scalar 2020 | * @returns `-s` 2021 | */ 2022 | @global export function faScalarNegate(s: Uint8Array): Uint8Array { 2023 | let t = newScalarPacked(), t_ = newScalarDouble(), s_ = newScalarDouble(); 2024 | 2025 | for (let i = 0; i < 32; i++) { 2026 | t_[32 + i] = _L[i] as u8; 2027 | } 2028 | setU8(s_, s); 2029 | scSub(t_, s_); 2030 | scReduce(t_); 2031 | setU8(t, t_.subarray(0, 32)); 2032 | 2033 | return t; 2034 | } 2035 | 2036 | /** 2037 | * Compute the complement of a scalar (mod L) 2038 | * @param s Scalar 2039 | * @returns `1-s` 2040 | */ 2041 | @global export function faScalarComplement(s: Uint8Array): Uint8Array { 2042 | let t = newScalarPacked(), t_ = newScalarDouble(), s_ = newScalarDouble(); 2043 | t_[0] = 1; 2044 | for (let i = 0; i < 32; i++) { 2045 | t_[32 + i] = _L[i] as u8; 2046 | } 2047 | setU8(s_, s); 2048 | scSub(t_, s_); 2049 | scReduce(t_); 2050 | setU8(t, t_.subarray(0, 32)); 2051 | 2052 | return t; 2053 | } 2054 | 2055 | /** 2056 | * Compute `x + y (mod L)` 2057 | * @param x Scalar 2058 | * @param y Scalar 2059 | * @returns `x + y (mod L)` 2060 | */ 2061 | @global export function faScalarAdd(x: Uint8Array, y: Uint8Array): Uint8Array { 2062 | let x_ = newScalarDouble(), y_ = newScalarDouble(); 2063 | setU8(x_, x); 2064 | setU8(y_, y); 2065 | scAdd(x_, y_); 2066 | 2067 | return faScalarReduce(x_); 2068 | } 2069 | 2070 | /** 2071 | * Compute `x - y (mod L)` 2072 | * @param x Scalar 2073 | * @param y Scalar 2074 | * @returns `x - y (mod L)` 2075 | */ 2076 | @global export function faScalarSub(x: Uint8Array, y: Uint8Array): Uint8Array { 2077 | let yn = faScalarNegate(y); 2078 | 2079 | return faScalarAdd(x, yn); 2080 | } 2081 | 2082 | /** 2083 | * Check whether a scalar is in canonical form. 2084 | * @param x Scalar 2085 | * @returns true` is the scalar is in canonical form 2086 | */ 2087 | @global export function faScalarIsCanonical(x: Uint8Array): bool { 2088 | return scIsLtL(x); 2089 | } 2090 | 2091 | /** 2092 | * Compute `x * y (mod L)` 2093 | * @param x Scalar 2094 | * @param y Scalar 2095 | * @returns `x * y (mod L)` 2096 | */ 2097 | @global export function faScalarMult(x: Uint8Array, y: Uint8Array): Uint8Array { 2098 | let x_ = newScalar(), y_ = newScalar(); 2099 | let o = newScalar(), o_ = newScalarPacked(); 2100 | 2101 | for (let i = 0; i < 32; i++) { 2102 | x_[i] = x[i] as i64; 2103 | } 2104 | for (let i = 0; i < 32; i++) { 2105 | y_[i] = y[i] as i64; 2106 | } 2107 | scMult(o, x_, y_); 2108 | for (let i = 0; i < 32; i++) { 2109 | o_[i] = o[i] as u8; 2110 | } 2111 | return o_; 2112 | } 2113 | 2114 | /** 2115 | * Multiply a point by the cofactor 2116 | * @param q Compressed EC point 2117 | * @returns Compressed EC point `q * 8` 2118 | */ 2119 | @global export function faEdClearCofcator(q: Uint8Array): Uint8Array | null { 2120 | let p_ = newGe(); 2121 | let q_ = newGe(); 2122 | if (!unpack(q_, q, false)) { 2123 | return null; 2124 | } 2125 | clearCofactor(q_); 2126 | let p = newGePacked(); 2127 | pack(p, p_); 2128 | return p; 2129 | } 2130 | 2131 | /** 2132 | * Multiply a point `q` by a scalar `s` 2133 | * @param q Compressed EC point 2134 | * @param s Scalar 2135 | * @returns Compressed EC point `q * s` 2136 | */ 2137 | @global export function faEdPointMult(s: Uint8Array, q: Uint8Array): Uint8Array | null { 2138 | let p_ = newGe(); 2139 | let q_ = newGe(); 2140 | if (!unpack(q_, q, false) || !faEdPointValidate(q)) { 2141 | return null; 2142 | } 2143 | scalarmult(p_, s, q_); 2144 | let p = newGePacked(); 2145 | pack(p, p_); 2146 | if (isIdentity(p)) { 2147 | return null; 2148 | } 2149 | return p; 2150 | } 2151 | 2152 | /** 2153 | * Multiply the base point by a scalar `s` 2154 | * @param s Scalar 2155 | * @returns Compressed EC point `B * s` 2156 | */ 2157 | @global export function faEdBasePointMult(s: Uint8Array): Uint8Array | null { 2158 | if (allZeros(s)) { 2159 | return null; 2160 | } 2161 | let p = newGePacked(); 2162 | let p_ = newGe(); 2163 | scalarmultBase(p_, s); 2164 | pack(p, p_); 2165 | 2166 | return p; 2167 | } 2168 | 2169 | /** 2170 | * Multiply a point `q` by a scalar `s` after clamping `s` 2171 | * @param q Compressed EC point 2172 | * @param s Scalar 2173 | * @returns Compressed EC point `q * clamp(s)` 2174 | */ 2175 | @global export function faEdPointMultClamp(s: Uint8Array, q: Uint8Array): Uint8Array | null { 2176 | let s_ = newScalarPacked(); 2177 | setU8(s_, s); 2178 | scClamp(s_); 2179 | 2180 | return faEdPointMult(s_, q); 2181 | } 2182 | 2183 | /** 2184 | * Multiply the base point by a clamped scalar `s` 2185 | * @param s Scalar 2186 | * @returns Compressed EC point `B * clamp(s)` 2187 | */ 2188 | @global export function faEdBasePointMultClamp(s: Uint8Array): Uint8Array | null { 2189 | let s_ = newScalarPacked(); 2190 | setU8(s_, s); 2191 | scClamp(s_); 2192 | 2193 | return faEdBasePointMult(s_); 2194 | } 2195 | 2196 | /** 2197 | * Verify that the point is on the main subgroup 2198 | * @param q Compressed EC point 2199 | * @returns `true` if verification succeeds 2200 | */ 2201 | @global export function faEdPointValidate(q: Uint8Array): bool { 2202 | if (isIdentity(q)) { 2203 | return false; 2204 | } 2205 | let l = newGePacked(); 2206 | let p_ = newGe(); 2207 | let q_ = newGe(); 2208 | 2209 | for (let i = 0; i < 32; ++i) { 2210 | l[i] = _L[i] as u8; 2211 | } 2212 | if (!unpack(q_, q, false)) { 2213 | return false; 2214 | } 2215 | scalarmult(p_, l, q_); 2216 | 2217 | let c: i64 = 0; 2218 | let x = p_.x; 2219 | for (let i = 0; i < 16; ++i) { 2220 | c |= x[i]; 2221 | } 2222 | return c === 0; 2223 | } 2224 | 2225 | /** 2226 | * Point addition 2227 | * @param p Compressed EC point 2228 | * @param q Compressed EC point 2229 | * @returns `p` + `q` 2230 | */ 2231 | @global export function faEdPointAdd(p: Uint8Array, q: Uint8Array): Uint8Array | null { 2232 | let o = newGePacked(); 2233 | let p_ = newGe(); 2234 | let q_ = newGe(); 2235 | if (!unpack(p_, p, false) || !unpack(q_, q, false)) { 2236 | return null; 2237 | } 2238 | add(p_, q_); 2239 | pack(o, p_); 2240 | 2241 | return o; 2242 | } 2243 | 2244 | /** 2245 | * Point subtraction 2246 | * @param p Compressed EC point 2247 | * @param q Compressed EC point 2248 | * @returns `p` - `q` 2249 | */ 2250 | @global export function faEdPointSub(p: Uint8Array, q: Uint8Array): Uint8Array | null { 2251 | let o = newGePacked(); 2252 | let p_ = newGe(); 2253 | let q_ = newGe(); 2254 | if (!unpack(p_, p, false) || !unpack(q_, q, true)) { 2255 | return null; 2256 | } 2257 | add(p_, q_); 2258 | pack(o, p_); 2259 | 2260 | return o; 2261 | } 2262 | 2263 | /** 2264 | * Flip the X coordinate of a point 2265 | * @param p Compressed EC point 2266 | * @returns `-p` 2267 | */ 2268 | @global export function faEdPointNeg(p: Uint8Array): Uint8Array | null { 2269 | let negp = newGePacked(); 2270 | let negp_ = newGe(); 2271 | if (!unpack(negp_, p, true)) { 2272 | return null; 2273 | } 2274 | pack(negp, negp_); 2275 | 2276 | return negp; 2277 | } 2278 | 2279 | /** 2280 | * Multiply a point `q` by a scalar `s` 2281 | * @param q Ristretto-compressed EC point 2282 | * @param s Scalar 2283 | * @returns Compressed EC point `q * s` 2284 | */ 2285 | @global export function faPointMult(s: Uint8Array, q: Uint8Array): Uint8Array | null { 2286 | let p_ = newGe(); 2287 | let q_ = newGe(); 2288 | if (!ristrettoUnpack(q_, q)) { 2289 | return null; 2290 | } 2291 | scalarmult(p_, s, q_); 2292 | let p = newGePacked(); 2293 | ristrettoPack(p, p_); 2294 | if (ristrettoIsIdentity(p)) { 2295 | return null; 2296 | } 2297 | return p; 2298 | } 2299 | 2300 | /** 2301 | * Multiply the base point by a scalar `s` 2302 | * @param s Scalar 2303 | * @returns Ristretto-compressed EC point `B * s` 2304 | */ 2305 | @global export function faBasePointMult(s: Uint8Array): Uint8Array | null { 2306 | if (allZeros(s)) { 2307 | return null; 2308 | } 2309 | let p = newGePacked(); 2310 | let p_ = newGe(); 2311 | scalarmultBase(p_, s); 2312 | ristrettoPack(p, p_); 2313 | 2314 | return p; 2315 | } 2316 | 2317 | /** 2318 | * Verify that the point is on the main subgroup 2319 | * @param q Ristretto-compressed EC point 2320 | * @returns `true` if verification succeeds 2321 | */ 2322 | @global export function faPointValidate(q: Uint8Array): bool { 2323 | let q_ = newGe(); 2324 | 2325 | return (!ristrettoIsIdentity(q)) & ristrettoUnpack(q_, q); 2326 | } 2327 | 2328 | /** 2329 | * Point addition 2330 | * @param p Risterto-compressed EC point 2331 | * @param q Risterto-compressed EC point 2332 | * @returns `p` + `q` 2333 | */ 2334 | @global export function faPointAdd(p: Uint8Array, q: Uint8Array): Uint8Array | null { 2335 | let o = newGePacked(); 2336 | let p_ = newGe(); 2337 | let q_ = newGe(); 2338 | if (!ristrettoUnpack(p_, p) || !ristrettoUnpack(q_, q, false)) { 2339 | return null; 2340 | } 2341 | add(p_, q_); 2342 | ristrettoPack(o, p_); 2343 | 2344 | return o; 2345 | } 2346 | 2347 | /** 2348 | * Point subtraction 2349 | * @param p Ristretto-compressed EC point 2350 | * @param q Ristretto-compressed EC point 2351 | * @returns `p` - `q` 2352 | */ 2353 | @global export function faPointSub(p: Uint8Array, q: Uint8Array): Uint8Array | null { 2354 | let o = newGePacked(); 2355 | let p_ = newGe(); 2356 | let q_ = newGe(); 2357 | if (!ristrettoUnpack(p_, p) || !ristrettoUnpack(q_, q, true)) { 2358 | return null; 2359 | } 2360 | add(p_, q_); 2361 | ristrettoPack(o, p_); 2362 | 2363 | return o; 2364 | } 2365 | 2366 | /** 2367 | * Hash-to-point 2368 | * @param r 512 bit hash 2369 | * @returns Ristretto-compressed EC point 2370 | */ 2371 | @global export function faPointFromHash(r: Uint8Array): Uint8Array { 2372 | let p = newGePacked(); 2373 | 2374 | ristrettoFromHash(p, r); 2375 | 2376 | return p; 2377 | } 2378 | 2379 | /** 2380 | * (best-effort) Constant-time hexadecimal encoding 2381 | * @param bin Binary data 2382 | * @returns Hex-encoded representation 2383 | */ 2384 | @global export function bin2hex(bin: Uint8Array): string { 2385 | let bin_len = bin.length; 2386 | let hex = ""; 2387 | for (let i = 0; i < bin_len; i++) { 2388 | let bin_i = bin[i] as u32; 2389 | let c = bin_i & 0xf; 2390 | let b = bin_i >> 4; 2391 | let x: u32 = ((87 + c + (((c - 10) >> 8) & ~38)) << 8) | 2392 | (87 + b + (((b - 10) >> 8) & ~38)); 2393 | hex += String.fromCharCode(x as u8); 2394 | x >>= 8; 2395 | hex += String.fromCharCode(x as u8); 2396 | } 2397 | return hex; 2398 | } 2399 | 2400 | /** 2401 | * (best-effort) Constant-time hexadecimal decoding 2402 | * @param hex Hex-encoded data 2403 | * @returns Raw binary representation 2404 | */ 2405 | @global export function hex2bin(hex: string): Uint8Array | null { 2406 | let hex_len = hex.length; 2407 | if ((hex_len & 1) !== 0) { 2408 | return null; 2409 | } 2410 | let bin = new Uint8Array((hex_len / 2)); 2411 | let c_acc = 0; 2412 | let bin_pos = 0; 2413 | let state = false; 2414 | for (let hex_pos = 0; hex_pos < hex_len; hex_pos++) { 2415 | let c = hex.charCodeAt(hex_pos) as u32; 2416 | let c_num = c ^ 48; 2417 | let c_num0 = (c_num - 10) >> 8; 2418 | let c_alpha = (c & ~32) - 55; 2419 | let c_alpha0 = ((c_alpha - 10) ^ (c_alpha - 16)) >> 8; 2420 | if ((c_num0 | c_alpha0) === 0) { 2421 | return null; 2422 | } 2423 | let c_val = ((c_num0 & c_num) | (c_alpha0 & c_alpha)) as u8; 2424 | if (state === false) { 2425 | c_acc = c_val << 4; 2426 | } else { 2427 | bin[bin_pos++] = c_acc | c_val; 2428 | } 2429 | state = !state; 2430 | } 2431 | return bin; 2432 | } 2433 | -------------------------------------------------------------------------------- /assembly/precomp.ts: -------------------------------------------------------------------------------- 1 | 2 | export const precompBase: i64[][][] = [ 3 | [ 4 | [ 54554, 36645, 11616, 51542, 42930, 38181, 51040, 26924, 56412, 64982, 57905, 49316, 21502, 52590, 14035, 8553 ], 5 | [ 26200, 26214, 26214, 26214, 26214, 26214, 26214, 26214, 26214, 26214, 26214, 26214, 26214, 26214, 26214, 26214 ], 6 | [ 56720, 42423, 35507, 28126, 21237, 30545, 40832, 8432, 58237, 25771, 20110, 26346, 30309, 55179, 24335, 59271 ] 7 | ], 8 | [ 9 | [ 52750, 10307, 41294, 33733, 42079, 5591, 36421, 2061, 59308, 6195, 15229, 15620, 1132, 40794, 14412, 13995 ], 10 | [ 41910, 27384, 18094, 3679, 20822, 25656, 3921, 38713, 8022, 51618, 24296, 7586, 10690, 2339, 52723, 41568 ], 11 | [ 46062, 28009, 16213, 46874, 9218, 49655, 44233, 23929, 46099, 29443, 24328, 7653, 26844, 2863, 42885, 42136 ] 12 | ], 13 | [ 14 | [ 63600, 50377, 42583, 18746, 5447, 37838, 40641, 6771, 8441, 31285, 54456, 33573, 61766, 22223, 43227, 8253 ], 15 | [ 4380, 51762, 43873, 57144, 4080, 59951, 10290, 19698, 29036, 32981, 47237, 18190, 38369, 51989, 59431, 51152 ], 16 | [ 4952, 29322, 8950, 24463, 1994, 46813, 58142, 29077, 10592, 50812, 47722, 29204, 9740, 55411, 15576, 8824 ] 17 | ], 18 | [ 19 | [ 33992, 2213, 64956, 15239, 35737, 32873, 50811, 60218, 53139, 63566, 11612, 17030, 29110, 38871, 57695, 26434 ], 20 | [ 47540, 64567, 23465, 7727, 58515, 25118, 15612, 33144, 62351, 26250, 28425, 28333, 29561, 51685, 1536, 8659 ], 21 | [ 20908, 54298, 62490, 28606, 11253, 13388, 52845, 17904, 55699, 14515, 49819, 5640, 60129, 60919, 23020, 44111 ] 22 | ], 23 | [ 24 | [ 63992, 27688, 22893, 22962, 9076, 59327, 36147, 2391, 40081, 2084, 11029, 47330, 15086, 10213, 34310, 9124 ], 25 | [ 10200, 49511, 43831, 55418, 39975, 36359, 4607, 45162, 28280, 15021, 3886, 40856, 50034, 33407, 38642, 61590 ], 26 | [ 39894, 52991, 39453, 25679, 37738, 6417, 14828, 45000, 58457, 5428, 35435, 23071, 27457, 40810, 16704, 4598 ] 27 | ], 28 | [ 29 | [ 20262, 38782, 16630, 20445, 21244, 63864, 12688, 58883, 22141, 2873, 22045, 34178, 6905, 5954, 27753, 14799 ], 30 | [ 53846, 14854, 14671, 63789, 16440, 19596, 1511, 46098, 35704, 49400, 37868, 31454, 52843, 57644, 43278, 50228 ], 31 | [ 50828, 23010, 29823, 9153, 42677, 30392, 22209, 29006, 42389, 27975, 33876, 54179, 27757, 4724, 4473, 60920 ] 32 | ], 33 | [ 34 | [ 41976, 45116, 31247, 61777, 54904, 27353, 18173, 47336, 31144, 34589, 37113, 40178, 10515, 3064, 25632, 34298 ], 35 | [ 2342, 6106, 38319, 64470, 6506, 28173, 4702, 39409, 43596, 28584, 34425, 29428, 40, 63782, 40682, 15641 ], 36 | [ 3944, 47739, 43476, 15935, 21186, 56698, 22506, 24090, 55604, 42349, 48578, 53726, 36065, 29700, 9907, 12817 ] 37 | ], 38 | [ 39 | [ 56692, 61647, 18779, 23970, 31296, 9763, 31396, 35459, 35767, 6866, 60095, 9218, 24328, 43387, 48817, 47005 ], 40 | [ 34556, 2123, 59374, 64928, 17697, 13321, 25025, 9010, 39932, 18517, 39251, 25591, 39376, 462, 40928, 10475 ], 41 | [ 35526, 3568, 53256, 5218, 15536, 828, 61499, 29526, 61023, 38006, 59815, 49772, 25327, 29839, 19130, 15992 ] 42 | ], 43 | [ 44 | [ 42326, 3266, 48349, 8376, 22381, 46433, 30971, 54453, 21577, 9872, 52161, 59113, 60607, 19997, 2029, 24190 ], 45 | [ 63156, 22124, 8241, 3604, 55720, 49447, 15770, 32027, 9742, 33235, 60330, 27637, 633, 20977, 30044, 36693 ], 46 | [ 41598, 10327, 26108, 23283, 57311, 13298, 44422, 40525, 41389, 2382, 19542, 17076, 22138, 7853, 44588, 25576 ] 47 | ], 48 | [ 49 | [ 13322, 33485, 13116, 21513, 25042, 12345, 64923, 8687, 54310, 64112, 63982, 13105, 33907, 46032, 49025, 12012 ], 50 | [ 37864, 139, 63332, 47260, 57460, 18918, 19784, 18509, 6582, 16545, 55735, 16690, 33404, 41271, 56365, 21714 ], 51 | [ 1338, 9366, 8894, 14925, 32441, 11747, 6203, 43473, 7374, 29766, 22314, 61756, 33742, 31382, 16863, 29993 ] 52 | ], 53 | [ 54 | [ 11112, 23370, 51157, 37201, 57629, 19242, 18372, 48369, 45946, 51403, 31926, 37036, 64773, 63987, 14930, 27409 ], 55 | [ 49450, 62247, 17241, 37013, 38597, 62841, 38388, 10597, 39942, 1361, 55832, 11960, 32377, 22889, 369, 39659 ], 56 | [ 16300, 19258, 50153, 37387, 62746, 26256, 26326, 28857, 58231, 58289, 34904, 21952, 50906, 59079, 25510, 26315 ] 57 | ], 58 | [ 59 | [ 6116, 48403, 48379, 60626, 45893, 12565, 45033, 33922, 10301, 64710, 62737, 46401, 54155, 30226, 59218, 48154 ], 60 | [ 13902, 1809, 5538, 20768, 10948, 25283, 24203, 42623, 63759, 34117, 4460, 46982, 58750, 63959, 37315, 1308 ], 61 | [ 8580, 48846, 45158, 11079, 38433, 11260, 60501, 27105, 5712, 1194, 15647, 34914, 34108, 64978, 5176, 3498 ] 62 | ], 63 | [ 64 | [ 55018, 10718, 58, 697, 52057, 50214, 39354, 38833, 36399, 37376, 20262, 60242, 6983, 35721, 49188, 32019 ], 65 | [ 8386, 32859, 32934, 38176, 59843, 36511, 40583, 40478, 51066, 30156, 42348, 37361, 43034, 11265, 30379, 55721 ], 66 | [ 36772, 27382, 56296, 39731, 14492, 6461, 5927, 56892, 444, 13947, 48468, 13731, 26038, 37755, 62787, 26993 ] 67 | ], 68 | [ 69 | [ 51678, 12721, 5648, 13738, 27156, 46548, 33332, 53873, 23882, 8090, 9811, 58684, 36238, 32563, 43519, 6101 ], 70 | [ 44918, 42230, 54628, 57360, 44317, 17647, 55997, 44163, 43130, 7408, 63751, 17347, 16236, 54199, 8839, 62210 ], 71 | [ 7036, 46730, 65276, 64045, 47944, 50833, 52026, 26155, 21244, 44819, 47818, 34757, 27224, 63025, 3282, 12537 ] 72 | ], 73 | [ 74 | [ 19338, 14567, 55996, 45250, 57733, 65098, 17453, 52100, 27424, 48941, 39953, 48855, 16083, 48991, 48232, 1960 ], 75 | [ 35054, 8744, 30826, 10666, 51203, 38260, 15875, 48604, 4871, 41640, 11552, 6323, 17008, 31485, 55236, 62025 ], 76 | [ 23792, 37497, 2596, 49614, 48440, 45494, 51938, 11073, 51932, 18607, 55430, 39617, 29420, 5531, 11331, 39792 ] 77 | ], 78 | [ 79 | [ 65282, 11058, 37724, 12884, 22504, 6740, 13195, 25952, 26579, 49572, 50214, 13476, 39711, 43431, 55796, 23375 ], 80 | [ 36166, 13232, 9812, 26715, 48095, 60613, 63938, 23100, 49463, 10126, 43591, 23113, 64504, 1128, 53539, 16619 ], 81 | [ 14348, 21170, 29488, 49471, 3877, 967, 61979, 17214, 45646, 3836, 26838, 44986, 30187, 12903, 6055, 48933 ] 82 | ], 83 | [ 84 | [ 42322, 33809, 26506, 40605, 17617, 31336, 57652, 41887, 52564, 51719, 8057, 12116, 28691, 61006, 64162, 56807 ], 85 | [ 60470, 63572, 58574, 57221, 28662, 36893, 48136, 49384, 11666, 27459, 43410, 43918, 11786, 7708, 9060, 11423 ], 86 | [ 19086, 35389, 11287, 38707, 3413, 19045, 18212, 47017, 35947, 7162, 31858, 60560, 2180, 27492, 49457, 40501 ] 87 | ], 88 | [ 89 | [ 20244, 29392, 4529, 10004, 37909, 33096, 29822, 13016, 53717, 10257, 25440, 12854, 46391, 7187, 14240, 62691 ], 90 | [ 9694, 4430, 26518, 7398, 45762, 57939, 34266, 45806, 22943, 47859, 64189, 28367, 56057, 45988, 36610, 34916 ], 91 | [ 4540, 46259, 11399, 17877, 52698, 40707, 28491, 63784, 35142, 7036, 10421, 45115, 31510, 34381, 27199, 53255 ] 92 | ], 93 | [ 94 | [ 37940, 25842, 18260, 1847, 35392, 47648, 21834, 16343, 47687, 8997, 45076, 59436, 43093, 61350, 48465, 27247 ], 95 | [ 54878, 30230, 1714, 31210, 50421, 21187, 24958, 57809, 28845, 7544, 4374, 31992, 64555, 40789, 63570, 38645 ], 96 | [ 14786, 49352, 29224, 33626, 37739, 40310, 49011, 59304, 47468, 26283, 31186, 60773, 2882, 42697, 65070, 25918 ] 97 | ], 98 | [ 99 | [ 38452, 63130, 57541, 788, 3620, 44364, 39582, 9072, 45718, 12017, 50077, 39730, 42324, 56947, 45448, 9278 ], 100 | [ 58102, 8012, 45659, 33455, 53157, 4225, 61188, 41691, 9420, 32434, 31243, 491, 21208, 20980, 10633, 14201 ], 101 | [ 16280, 30555, 2206, 9953, 20655, 58819, 45285, 42692, 30757, 15343, 28862, 43812, 4174, 52634, 64115, 18424 ] 102 | ], 103 | [ 104 | [ 46554, 35994, 56730, 62503, 18303, 21209, 52647, 42341, 8753, 42733, 23395, 19072, 19885, 49133, 18926, 34483 ], 105 | [ 25848, 24715, 59792, 17630, 47479, 13831, 49714, 62800, 57189, 19528, 43575, 43880, 8090, 65342, 37513, 1952 ], 106 | [ 54982, 35440, 25892, 51635, 13371, 24036, 57195, 53756, 23671, 22909, 7812, 20524, 38678, 59173, 15865, 474 ] 107 | ], 108 | [ 109 | [ 20330, 6556, 19136, 60465, 43769, 45803, 39958, 26275, 53599, 60884, 37560, 43804, 60122, 22489, 19679, 51242 ], 110 | [ 45112, 28238, 15121, 48465, 64874, 9700, 24485, 16145, 37528, 5201, 24518, 2876, 63400, 33218, 56899, 62353 ], 111 | [ 30088, 57684, 26038, 63893, 60294, 944, 27501, 58790, 6562, 24172, 52717, 8699, 5806, 56991, 47735, 25567 ] 112 | ], 113 | [ 114 | [ 36668, 13215, 7978, 13123, 26767, 8191, 29501, 49003, 52328, 4989, 9324, 52299, 9293, 65037, 34526, 15277 ], 115 | [ 20838, 385, 29660, 57427, 39790, 26858, 23615, 33812, 36179, 49227, 40863, 11145, 47756, 64134, 52722, 44515 ], 116 | [ 22944, 16863, 44006, 29328, 55673, 2778, 5886, 56245, 5816, 14114, 31557, 64378, 12712, 41617, 30133, 58142 ] 117 | ], 118 | [ 119 | [ 48724, 52085, 45061, 46932, 9959, 19078, 6652, 10191, 54342, 38434, 4442, 54760, 60699, 50545, 51293, 17839 ], 120 | [ 31552, 22391, 40521, 14720, 60963, 2945, 53026, 31451, 5167, 22456, 41359, 7737, 64631, 42507, 35519, 27660 ], 121 | [ 14974, 9004, 10480, 60856, 58736, 30600, 24702, 2720, 5285, 62485, 2926, 2184, 6, 58638, 63484, 41871 ] 122 | ], 123 | [ 124 | [ 14948, 55508, 53031, 41448, 40306, 56778, 38413, 31194, 22253, 5442, 51040, 27420, 12326, 27382, 26517, 35571 ], 125 | [ 2226, 11172, 48431, 33073, 42538, 58550, 37120, 15834, 45234, 52886, 53898, 28813, 54195, 308, 36240, 41232 ], 126 | [ 51100, 50693, 37074, 52161, 28484, 15107, 58321, 43995, 59098, 56450, 24060, 358, 48086, 36221, 2491, 53089 ] 127 | ], 128 | [ 129 | [ 3360, 47847, 1871, 36319, 32234, 50592, 45526, 58800, 6999, 62811, 4933, 25620, 60250, 64604, 340, 43894 ], 130 | [ 3074, 44994, 13974, 19198, 21730, 27168, 45803, 25247, 52951, 16290, 4384, 14132, 17120, 28653, 6905, 32200 ], 131 | [ 8928, 62459, 3155, 8582, 53424, 9131, 51878, 41831, 44874, 35436, 62818, 57601, 2598, 35202, 10063, 2560 ] 132 | ], 133 | [ 134 | [ 56152, 40027, 37574, 9148, 50607, 30136, 17144, 55034, 33974, 25492, 37784, 30792, 52536, 6331, 49972, 59355 ], 135 | [ 62358, 2362, 45142, 31855, 7761, 14619, 59976, 3273, 41509, 51834, 37607, 23036, 41776, 34185, 28639, 14403 ], 136 | [ 18774, 61857, 32625, 55759, 49722, 65321, 53000, 33525, 15885, 26225, 4940, 2088, 33136, 10872, 22439, 7397 ] 137 | ], 138 | [ 139 | [ 33894, 6468, 59837, 50260, 28352, 43050, 39848, 54595, 8817, 56415, 64001, 46047, 18360, 2635, 17573, 43498 ], 140 | [ 36850, 44880, 24419, 40605, 40417, 38712, 27679, 12460, 45638, 6506, 19409, 48091, 55948, 43822, 23240, 60535 ], 141 | [ 21286, 55271, 10598, 47429, 51819, 24081, 31384, 21020, 22882, 26024, 51725, 61723, 64481, 25107, 60435, 27348 ] 142 | ], 143 | [ 144 | [ 48664, 41391, 12141, 45323, 58255, 14560, 3021, 6977, 5450, 62215, 56431, 59832, 45790, 16547, 42497, 40517 ], 145 | [ 2678, 36314, 1836, 35135, 1149, 17325, 28240, 18386, 35531, 34278, 9242, 54003, 64864, 29663, 3492, 3699 ], 146 | [ 21608, 48801, 21799, 37295, 31049, 27595, 32709, 36791, 48525, 51854, 54427, 14375, 34701, 16139, 36699, 41451 ] 147 | ], 148 | [ 149 | [ 37706, 48841, 37034, 39885, 29691, 45182, 39012, 17495, 16706, 44977, 49642, 8899, 24831, 52038, 33121, 57712 ], 150 | [ 33274, 65209, 52513, 62916, 3224, 29262, 34798, 63561, 38305, 36831, 48429, 1569, 5500, 4840, 37741, 47318 ], 151 | [ 27198, 57302, 64144, 21248, 39232, 38897, 61301, 14999, 20291, 16997, 29401, 16604, 51070, 45633, 14879, 31845 ] 152 | ], 153 | [ 154 | [ 63358, 55633, 32239, 322, 59667, 32696, 18854, 25623, 32801, 11395, 19555, 2400, 37209, 30610, 20793, 51444 ], 155 | [ 54624, 33570, 12040, 39423, 26942, 34925, 59354, 21083, 12582, 58666, 56969, 36968, 8886, 48474, 34259, 12627 ], 156 | [ 50610, 23377, 46002, 45722, 61363, 54639, 49578, 38129, 43365, 2758, 46434, 51884, 63386, 16361, 45206, 36703 ] 157 | ], 158 | [ 159 | [ 52952, 63964, 19260, 7586, 12076, 48694, 64634, 48333, 63964, 48432, 1535, 58567, 6030, 63586, 41037, 31062 ], 160 | [ 59266, 47862, 33875, 41738, 65332, 41788, 41322, 59959, 46813, 45973, 6520, 7798, 12117, 11895, 49535, 24298 ], 161 | [ 13670, 57005, 23463, 52101, 51122, 24426, 65048, 49130, 15192, 6153, 15855, 18180, 20213, 59743, 39905, 43124 ] 162 | ], 163 | [ 164 | [ 3240, 27324, 38820, 37655, 28461, 29406, 7184, 11272, 32783, 26674, 54311, 56747, 22725, 4961, 4461, 52510 ], 165 | [ 47386, 4297, 7931, 62542, 19332, 24202, 19323, 17384, 36748, 46336, 4948, 23749, 13750, 40270, 23524, 27969 ], 166 | [ 60766, 22146, 18651, 25970, 18432, 58333, 49166, 33259, 30853, 29742, 61173, 65513, 43202, 65407, 38777, 64151 ] 167 | ], 168 | [ 169 | [ 32002, 18450, 5250, 52546, 54322, 49483, 24946, 35882, 58092, 9464, 37957, 48867, 26589, 30632, 44634, 52059 ], 170 | [ 30648, 8346, 47326, 55587, 4000, 31628, 52133, 46766, 17132, 3687, 42072, 39029, 28961, 45956, 30432, 62356 ], 171 | [ 25592, 22764, 57418, 64115, 57372, 50231, 10660, 4345, 37165, 8649, 24416, 63357, 23437, 45998, 35162, 3648 ] 172 | ], 173 | [ 174 | [ 64716, 10345, 16163, 63579, 9275, 62263, 54557, 27426, 39120, 27816, 65487, 57606, 57107, 49593, 43276, 46015 ], 175 | [ 33222, 45786, 33359, 17309, 2433, 54001, 61185, 62636, 32045, 2305, 65521, 40869, 51941, 25383, 8411, 54193 ], 176 | [ 23704, 10713, 21952, 44689, 60872, 6883, 57605, 46522, 16908, 31639, 62094, 5522, 35452, 64966, 58979, 50906 ] 177 | ], 178 | [ 179 | [ 61382, 49337, 8747, 7688, 28785, 13747, 31388, 37377, 39492, 45302, 38232, 39873, 60674, 31789, 10548, 17481 ], 180 | [ 25138, 11805, 11007, 8476, 9636, 3451, 5516, 64569, 31887, 32165, 9502, 17827, 43990, 52157, 24261, 63352 ], 181 | [ 59542, 33412, 26891, 22100, 57927, 41475, 54989, 55445, 2717, 11448, 60081, 26052, 32237, 44031, 25297, 63137 ] 182 | ], 183 | [ 184 | [ 54224, 60738, 29, 5436, 39980, 33143, 29650, 1745, 50389, 38015, 37563, 11309, 17739, 59723, 35114, 11115 ], 185 | [ 3282, 50568, 19784, 3562, 51530, 27218, 31073, 30441, 34291, 23634, 11291, 55009, 4036, 3608, 63054, 32540 ], 186 | [ 65112, 5983, 53165, 64610, 8941, 5483, 29881, 58770, 60629, 61476, 13225, 47820, 57753, 6974, 2335, 1767 ] 187 | ], 188 | [ 189 | [ 1204, 16942, 8139, 4395, 31569, 44040, 16042, 21150, 46944, 25026, 35927, 54660, 42520, 64537, 30135, 7057 ], 190 | [ 26856, 17610, 14536, 52280, 2643, 13618, 21196, 3787, 50679, 60647, 34109, 22732, 6114, 65351, 42399, 5936 ], 191 | [ 28692, 63072, 43105, 436, 63169, 31168, 60093, 26778, 24359, 28546, 44078, 53368, 65350, 60020, 10326, 51680 ] 192 | ], 193 | [ 194 | [ 61044, 22182, 49822, 22170, 16932, 19845, 12696, 24606, 34637, 1157, 18094, 63762, 32654, 32740, 7414, 33079 ], 195 | [ 19552, 50614, 59844, 34156, 19016, 44122, 8153, 63555, 23394, 39150, 13098, 31118, 25038, 13574, 55256, 61898 ], 196 | [ 34888, 23844, 35470, 2014, 45005, 7905, 17593, 12508, 59903, 38372, 22942, 62417, 55118, 3776, 46838, 12951 ] 197 | ], 198 | [ 199 | [ 54130, 42670, 36810, 52429, 36472, 19737, 53927, 59687, 15524, 23318, 32900, 53497, 27340, 51742, 26398, 25533 ], 200 | [ 28264, 53802, 18567, 41471, 59850, 34069, 56284, 14636, 37138, 8361, 20394, 62505, 31253, 62930, 52274, 33888 ], 201 | [ 52154, 54765, 51328, 49933, 35173, 51811, 11511, 28949, 45771, 59512, 41715, 46316, 21947, 51282, 20476, 24062 ] 202 | ], 203 | [ 204 | [ 4306, 15175, 37114, 12540, 60085, 22127, 64399, 42766, 51259, 65458, 31234, 37939, 10899, 57347, 14998, 36716 ], 205 | [ 25434, 57703, 18331, 40824, 31032, 38828, 7526, 20830, 9454, 59458, 19288, 906, 34421, 34359, 38882, 15694 ], 206 | [ 65336, 57818, 58501, 17540, 12289, 15674, 23977, 7612, 9043, 48455, 8397, 8551, 20614, 29505, 60337, 10418 ] 207 | ], 208 | [ 209 | [ 46144, 59051, 40877, 26950, 45898, 43662, 40170, 8330, 23830, 5004, 63165, 50461, 48420, 10896, 50972, 15123 ], 210 | [ 56404, 3350, 48664, 25653, 21089, 32770, 1455, 42743, 54082, 11919, 9849, 48040, 6066, 45640, 2682, 5257 ], 211 | [ 8330, 25319, 47733, 30996, 62008, 51272, 12389, 52742, 635, 55566, 255, 48756, 11742, 974, 55487, 20772 ] 212 | ], 213 | [ 214 | [ 43040, 58248, 49297, 47982, 10122, 20866, 45699, 43304, 60291, 43430, 5965, 8793, 84, 17744, 18635, 6219 ], 215 | [ 31776, 9959, 19898, 65074, 62547, 33786, 42467, 26233, 61299, 9088, 49768, 56672, 13225, 988, 57466, 48864 ], 216 | [ 7284, 34299, 20029, 47592, 26261, 32359, 11840, 1669, 1638, 38011, 29830, 6166, 23935, 53690, 15488, 49615 ] 217 | ], 218 | [ 219 | [ 23604, 64275, 58304, 11128, 22612, 39714, 33142, 37759, 9628, 53820, 38633, 9761, 62728, 38381, 44561, 23044 ], 220 | [ 59558, 4805, 8087, 65155, 37950, 54425, 63789, 22866, 33372, 61606, 32373, 60648, 44236, 8472, 26377, 59238 ], 221 | [ 30366, 24751, 11576, 25332, 8443, 49509, 15752, 35277, 37483, 6762, 12026, 3449, 63652, 51572, 16695, 48241 ] 222 | ], 223 | [ 224 | [ 43070, 49720, 22103, 39490, 58033, 17912, 4522, 24392, 50199, 10068, 24028, 56746, 48193, 33247, 21433, 21230 ], 225 | [ 61872, 28071, 24499, 28562, 37324, 38328, 57093, 25660, 14679, 20833, 36013, 31544, 57032, 13312, 41406, 65200 ], 226 | [ 54692, 1424, 55112, 5304, 44054, 5507, 40414, 60078, 51020, 4530, 47327, 12694, 65155, 3430, 25132, 36935 ] 227 | ], 228 | [ 229 | [ 9234, 35357, 8295, 17134, 14571, 3053, 52619, 40262, 27486, 9246, 4765, 6661, 1484, 37454, 57656, 53279 ], 230 | [ 61006, 37148, 4582, 36541, 6741, 29976, 44902, 31565, 44559, 34157, 33482, 8536, 6300, 60896, 8940, 12160 ], 231 | [ 45296, 45741, 57017, 37992, 41, 37183, 13501, 17116, 11173, 44734, 39701, 58936, 22471, 8722, 18494, 62379 ] 232 | ], 233 | [ 234 | [ 15208, 14602, 27165, 22293, 61692, 21603, 14811, 59611, 25692, 41215, 20233, 46907, 24626, 38041, 38141, 11650 ], 235 | [ 63012, 17498, 22001, 56108, 31978, 31876, 44033, 64995, 10185, 23233, 57017, 23119, 56720, 26566, 28586, 14986 ], 236 | [ 46630, 54323, 41337, 17501, 65278, 9883, 37192, 6664, 13626, 27590, 62696, 42080, 50517, 27715, 59703, 29765 ] 237 | ], 238 | [ 239 | [ 55818, 25060, 20483, 35753, 6248, 45807, 33820, 41531, 38212, 1187, 54843, 153, 30383, 26434, 32002, 54917 ], 240 | [ 29390, 10510, 45700, 53885, 48709, 1623, 32749, 60879, 61389, 54809, 5564, 25721, 6354, 8419, 14951, 2900 ], 241 | [ 30896, 45036, 64583, 32428, 8385, 515, 47508, 2774, 59581, 22688, 54444, 11672, 45375, 41817, 50352, 42846 ] 242 | ], 243 | [ 244 | [ 64850, 50436, 39419, 59623, 36091, 17121, 61187, 55709, 19870, 33015, 11983, 39884, 51525, 31355, 14268, 21160 ], 245 | [ 4502, 35393, 37191, 46846, 31450, 25428, 5329, 1333, 35974, 13993, 62015, 21637, 37454, 34264, 17921, 20694 ], 246 | [ 45074, 19149, 1975, 36257, 18211, 54749, 37040, 20764, 39997, 64140, 44923, 14918, 65348, 30321, 26055, 32025 ] 247 | ], 248 | [ 249 | [ 52544, 34547, 58944, 16953, 54933, 17867, 8218, 17864, 12875, 1129, 44977, 17952, 27591, 23331, 61033, 48944 ], 250 | [ 33648, 49223, 21979, 43016, 6267, 62829, 23044, 3104, 35914, 44640, 4014, 21860, 11861, 7637, 12627, 16706 ], 251 | [ 1404, 29585, 25697, 999, 42103, 25249, 24322, 12485, 24028, 10037, 18644, 2955, 11854, 59281, 28815, 59555 ] 252 | ], 253 | [ 254 | [ 59108, 12397, 12413, 49717, 34680, 64761, 23147, 47043, 55397, 50990, 3237, 56518, 43538, 20438, 14533, 3772 ], 255 | [ 15586, 34422, 62008, 11387, 30742, 62861, 5540, 56282, 34086, 22176, 7645, 46051, 16637, 62191, 41433, 1203 ], 256 | [ 58680, 29215, 49150, 59554, 27182, 50440, 14525, 65475, 18311, 35050, 59870, 63956, 60478, 28576, 10885, 60138 ] 257 | ], 258 | [ 259 | [ 18888, 58894, 4184, 21114, 46554, 14205, 15978, 30881, 51150, 9244, 56099, 64381, 36236, 12508, 26983, 47989 ], 260 | [ 60054, 5741, 24598, 24820, 6535, 35908, 35658, 64318, 22, 21504, 40614, 61343, 55759, 19666, 12660, 46288 ], 261 | [ 6024, 18264, 17957, 47561, 46519, 39154, 38827, 14955, 54218, 48150, 18820, 9991, 17906, 64313, 15379, 36484 ] 262 | ], 263 | [ 264 | [ 60324, 41988, 36748, 10097, 34197, 21853, 45387, 9766, 44744, 32106, 8610, 52938, 43832, 53263, 11221, 107 ], 265 | [ 26578, 61708, 39482, 2538, 61241, 12497, 13244, 45498, 50538, 2087, 21631, 15744, 63147, 31253, 16578, 62067 ], 266 | [ 49602, 47022, 48223, 61728, 48653, 41706, 19854, 38939, 14616, 23549, 9684, 19194, 35120, 1415, 34185, 21353 ] 267 | ], 268 | [ 269 | [ 11224, 5723, 8426, 54257, 36712, 23470, 43472, 6426, 13992, 11259, 34903, 36989, 42709, 56563, 35128, 8014 ], 270 | [ 6604, 39898, 17211, 8520, 9006, 15693, 63662, 64652, 42717, 14196, 51813, 6894, 36377, 25759, 3183, 23179 ], 271 | [ 42580, 11948, 57697, 44644, 25765, 10896, 39454, 43907, 58868, 15942, 36386, 50172, 39449, 34494, 55884, 52924 ] 272 | ], 273 | [ 274 | [ 47378, 61634, 47218, 5653, 36300, 28476, 60709, 18164, 3118, 3936, 34018, 21812, 22921, 6964, 36341, 35070 ], 275 | [ 44024, 48275, 47684, 29979, 18763, 53359, 11860, 47715, 60085, 13037, 51476, 55444, 52933, 4340, 57448, 10040 ], 276 | [ 60722, 14122, 45629, 48429, 3460, 44603, 36370, 8476, 58777, 23247, 13767, 48099, 55965, 51750, 599, 59337 ] 277 | ], 278 | [ 279 | [ 7284, 39700, 25812, 29025, 46682, 13089, 63311, 47758, 18597, 51098, 39674, 46320, 44386, 24306, 972, 6692 ], 280 | [ 30434, 58621, 47535, 22787, 25550, 15314, 52511, 3105, 17581, 38821, 32940, 529, 3227, 35813, 64461, 63353 ], 281 | [ 8690, 31559, 3605, 50420, 25984, 39031, 26853, 59341, 51295, 11004, 46319, 30252, 38322, 54987, 25282, 36859 ] 282 | ], 283 | [ 284 | [ 3556, 48628, 12782, 60688, 4811, 44422, 12244, 14224, 49970, 29451, 38892, 42117, 7169, 13686, 30206, 29149 ], 285 | [ 41982, 40840, 21310, 15209, 57371, 47863, 44443, 33102, 46431, 44636, 26558, 14214, 36404, 12807, 19013, 47463 ], 286 | [ 828, 25223, 20227, 42054, 47620, 53747, 25821, 21684, 26353, 17834, 6623, 10809, 10508, 29028, 1113, 54455 ] 287 | ], 288 | [ 289 | [ 28816, 8280, 7683, 45671, 39880, 50520, 60337, 18989, 33502, 62092, 5330, 28856, 20065, 54899, 27403, 12301 ], 290 | [ 64622, 23637, 42943, 48580, 61666, 36683, 32233, 64153, 43987, 51132, 11139, 32516, 6412, 835, 1853, 49354 ], 291 | [ 10742, 62122, 23572, 50596, 45800, 41495, 59725, 21836, 570, 25176, 49615, 52631, 41487, 48606, 43459, 6597 ] 292 | ], 293 | [ 294 | [ 51430, 36030, 33046, 38457, 6134, 51288, 22576, 49915, 17667, 21202, 57462, 9834, 23592, 22920, 23146, 49748 ], 295 | [ 46324, 11310, 5479, 64411, 27011, 3870, 55002, 45353, 57440, 47794, 41577, 48542, 57533, 48412, 1741, 61540 ], 296 | [ 49210, 54761, 63356, 39886, 38407, 48990, 64599, 35275, 9571, 50943, 1984, 47049, 54182, 24040, 21306, 2605 ] 297 | ], 298 | [ 299 | [ 14850, 16752, 4580, 9047, 59052, 21756, 52606, 8919, 30411, 8351, 41166, 30323, 15185, 63652, 25315, 27666 ], 300 | [ 108, 9884, 28429, 32584, 314, 50669, 45206, 20255, 680, 10082, 20618, 39565, 21131, 7695, 16847, 39224 ], 301 | [ 6390, 39868, 10653, 64313, 9109, 45390, 23352, 51722, 8153, 52427, 42832, 51525, 32930, 63607, 422, 59252 ] 302 | ], 303 | [ 304 | [ 27874, 12244, 26895, 34575, 24895, 7781, 13365, 47749, 12290, 9644, 57917, 61794, 59852, 49691, 27375, 55106 ], 305 | [ 7988, 44078, 51153, 20996, 26162, 13234, 8563, 21556, 29175, 1773, 65456, 22950, 35439, 64334, 45058, 27461 ], 306 | [ 9112, 8122, 40047, 64254, 57636, 40591, 20798, 59382, 5743, 17158, 41079, 4310, 5765, 26581, 26331, 5587 ] 307 | ], 308 | [ 309 | [ 18658, 779, 8901, 32893, 21256, 13054, 41393, 29834, 48495, 34111, 53236, 24821, 16815, 15998, 41798, 41050 ], 310 | [ 13738, 17543, 26211, 63639, 21870, 1036, 13630, 48976, 27027, 35794, 21765, 48793, 21474, 60513, 2280, 12811 ], 311 | [ 17820, 4075, 22309, 57384, 44423, 46058, 24195, 39865, 18722, 18118, 863, 21363, 39512, 63733, 52918, 41773 ] 312 | ], 313 | [ 314 | [ 59940, 26110, 9531, 57832, 50626, 41986, 39102, 11018, 49505, 58011, 37589, 40678, 8061, 17354, 35720, 55596 ], 315 | [ 46560, 7424, 28458, 31151, 12166, 23206, 53651, 44798, 60986, 31963, 48737, 380, 65273, 56402, 21208, 17059 ], 316 | [ 51972, 42886, 54625, 52885, 33910, 48973, 38764, 34854, 15333, 54142, 6118, 2308, 10177, 55277, 30898, 39102 ] 317 | ], 318 | [ 319 | [ 44834, 14099, 14269, 44145, 17924, 44131, 30628, 9709, 57400, 43029, 100, 52749, 337, 48297, 783, 1052 ], 320 | [ 63862, 1920, 16335, 59827, 17895, 15684, 31786, 58601, 23574, 25950, 50972, 50813, 64378, 60995, 30245, 62022 ], 321 | [ 11502, 18700, 40469, 37396, 61592, 57845, 22955, 13816, 13604, 48608, 2071, 43311, 32953, 40098, 7048, 3110 ] 322 | ], 323 | [ 324 | [ 41474, 62701, 27535, 15883, 13803, 54554, 56190, 120, 35478, 46240, 24783, 54347, 63957, 48941, 48520, 25122 ], 325 | [ 21248, 33508, 64087, 36638, 11014, 47760, 46600, 21520, 31823, 9755, 56045, 56683, 53285, 59982, 47938, 33573 ], 326 | [ 2118, 46708, 37609, 11773, 49030, 40132, 48654, 15114, 17760, 16393, 32998, 51097, 44554, 51155, 2530, 57995 ] 327 | ], 328 | [ 329 | [ 42372, 35803, 43565, 4418, 61961, 48019, 1753, 20100, 43025, 9632, 42539, 44639, 46276, 51276, 51115, 33339 ], 330 | [ 51694, 3881, 4575, 60805, 3534, 11362, 19343, 1273, 1769, 7538, 8247, 51536, 60180, 14828, 38823, 19755 ], 331 | [ 21402, 11284, 8363, 12539, 30731, 48512, 46217, 52578, 47987, 36205, 6664, 31077, 26696, 55204, 19901, 11234 ] 332 | ], 333 | [ 334 | [ 53590, 48441, 13307, 50366, 23792, 61679, 26710, 38908, 51271, 46706, 42067, 38922, 46245, 28983, 26319, 60752 ], 335 | [ 41988, 21017, 18193, 23731, 43355, 8750, 180, 63826, 6231, 48824, 58202, 33707, 34760, 10762, 36056, 54459 ], 336 | [ 31856, 26795, 60120, 14536, 38050, 43215, 731, 2709, 28447, 10894, 16510, 7326, 65126, 12519, 17121, 24721 ] 337 | ], 338 | [ 339 | [ 25238, 34195, 59582, 19059, 45070, 11701, 20628, 54186, 60082, 25245, 15222, 13319, 11598, 51312, 5530, 60262 ], 340 | [ 38578, 51402, 6690, 24558, 12775, 8800, 2179, 52835, 12985, 22596, 14941, 58523, 54532, 14575, 19439, 39389 ], 341 | [ 64944, 59332, 854, 41808, 64691, 26446, 39926, 48956, 18586, 4236, 19104, 19987, 12749, 57564, 47820, 59007 ] 342 | ], 343 | [ 344 | [ 41510, 592, 29220, 61681, 11598, 54675, 59144, 14510, 6391, 12965, 49716, 42736, 47596, 31585, 39268, 29100 ], 345 | [ 53010, 21876, 43547, 14505, 16449, 38357, 43925, 24092, 16828, 5246, 48688, 35091, 58868, 10475, 49856, 47766 ], 346 | [ 42098, 27556, 695, 52167, 39518, 10369, 22897, 49185, 4104, 30434, 60057, 60172, 11063, 1957, 49769, 49979 ] 347 | ], 348 | [ 349 | [ 30488, 60485, 30311, 19506, 57273, 12837, 52075, 5351, 17249, 47854, 29083, 53999, 25928, 7099, 5002, 41499 ], 350 | [ 44420, 6156, 23096, 53434, 22936, 14271, 20400, 24727, 45856, 38811, 2294, 42092, 64511, 64183, 45717, 31057 ], 351 | [ 48368, 64145, 14396, 58377, 1956, 45060, 33844, 23810, 15649, 53391, 61218, 39526, 55066, 38680, 46148, 42337 ] 352 | ], 353 | [ 354 | [ 23592, 56127, 6251, 23611, 1233, 56872, 21125, 46385, 63163, 60841, 10430, 45903, 1406, 56170, 3477, 7195 ], 355 | [ 50626, 39619, 53258, 15921, 13831, 49294, 25226, 51889, 3798, 40222, 44015, 19864, 27835, 57349, 24036, 55229 ], 356 | [ 4122, 39269, 35840, 32233, 37298, 35543, 40214, 16841, 41624, 4570, 54921, 710, 40306, 60038, 49613, 54613 ] 357 | ], 358 | [ 359 | [ 40756, 22140, 17276, 7313, 20155, 15986, 43876, 41120, 46303, 34776, 48442, 18600, 47305, 12015, 28589, 53124 ], 360 | [ 11546, 7152, 10878, 63596, 27305, 61665, 41369, 39527, 5076, 51914, 10170, 43666, 23969, 56912, 16588, 35366 ], 361 | [ 23760, 27347, 49605, 20786, 6053, 9277, 23751, 33308, 25273, 45543, 10432, 57948, 33300, 23630, 64153, 47952 ] 362 | ], 363 | [ 364 | [ 16012, 45810, 52880, 25819, 830, 14301, 21558, 30320, 46372, 873, 41212, 29739, 1458, 52238, 8152, 40810 ], 365 | [ 24070, 26976, 34392, 12704, 12989, 11497, 53852, 47749, 25664, 29864, 3832, 45852, 27049, 7912, 25664, 63385 ], 366 | [ 818, 56088, 14957, 27462, 32861, 15469, 59307, 11519, 11089, 15675, 43182, 10310, 59323, 21454, 2526, 35584 ] 367 | ], 368 | [ 369 | [ 12908, 64847, 23739, 36283, 26212, 29002, 31007, 44451, 63885, 60628, 26575, 64112, 18949, 28175, 34735, 28426 ], 370 | [ 14022, 27758, 9356, 24585, 9918, 19666, 5982, 24522, 52253, 59527, 27202, 52171, 37501, 13573, 4993, 27488 ], 371 | [ 41160, 6384, 52136, 50463, 40878, 53034, 9544, 17525, 26338, 11197, 31303, 36652, 63005, 19031, 30144, 10110 ] 372 | ], 373 | [ 374 | [ 1380, 33914, 4938, 63171, 28336, 27546, 27475, 55858, 29913, 50293, 25786, 15165, 56584, 17936, 51183, 8080 ], 375 | [ 12136, 52794, 41416, 15481, 4656, 10308, 48374, 65023, 49396, 45207, 50124, 31251, 39609, 58390, 19659, 58164 ], 376 | [ 8068, 43361, 49485, 53687, 49576, 44346, 58345, 31847, 7642, 48040, 3493, 12637, 50994, 14908, 59809, 23384 ] 377 | ], 378 | [ 379 | [ 19956, 11731, 13065, 53774, 48653, 59198, 43748, 183, 59531, 43693, 36218, 10292, 33193, 50580, 17127, 51116 ], 380 | [ 35108, 36730, 39861, 49904, 25603, 7888, 42229, 62386, 59764, 5658, 52221, 59925, 4331, 13676, 49617, 10406 ], 381 | [ 46100, 3213, 25469, 17876, 31068, 34913, 5699, 25770, 31470, 716, 3005, 20793, 45235, 62845, 18983, 62817 ] 382 | ], 383 | [ 384 | [ 54732, 64569, 42149, 12973, 52757, 59417, 11060, 24604, 64657, 43269, 56499, 10624, 8388, 1657, 49209, 8930 ], 385 | [ 43176, 35297, 22384, 21528, 63036, 33293, 1298, 38535, 14598, 63715, 38323, 55269, 48934, 23049, 63892, 58140 ], 386 | [ 7610, 3122, 27127, 39149, 32246, 53656, 15271, 15223, 8505, 55709, 38732, 49338, 564, 15631, 14496, 44210 ] 387 | ], 388 | [ 389 | [ 54570, 25754, 13939, 54961, 39046, 16194, 61834, 62919, 43074, 21148, 56488, 9465, 19007, 42145, 59483, 39522 ], 390 | [ 48562, 5320, 3541, 57835, 59045, 4483, 9, 21789, 20867, 30078, 33024, 52153, 50648, 41445, 6105, 40813 ], 391 | [ 37162, 54553, 26415, 11392, 62156, 48013, 52981, 41989, 44786, 18094, 53579, 53097, 272, 52516, 51080, 26055 ] 392 | ], 393 | [ 394 | [ 63978, 59876, 21217, 20799, 3353, 55773, 37789, 34609, 2339, 33749, 37611, 30217, 58222, 49400, 26274, 14005 ], 395 | [ 47930, 60729, 562, 17383, 14458, 33812, 17635, 24274, 56724, 35192, 19541, 40563, 58593, 17214, 19152, 7134 ], 396 | [ 34288, 26936, 26924, 64203, 29687, 36186, 45278, 948, 6757, 6014, 396, 12010, 591, 52580, 10411, 6786 ] 397 | ], 398 | [ 399 | [ 59314, 58255, 50595, 29387, 31214, 63553, 61151, 50533, 30533, 15399, 22717, 30163, 1250, 47947, 62309, 4040 ], 400 | [ 31524, 13459, 58037, 18548, 41165, 37387, 26263, 62521, 58032, 14685, 23402, 5957, 7800, 37339, 7297, 5881 ], 401 | [ 63670, 584, 62782, 48075, 63819, 57151, 60388, 65067, 59350, 27594, 39744, 39672, 39352, 36806, 10761, 50335 ] 402 | ], 403 | [ 404 | [ 4340, 48710, 53943, 52945, 30302, 55202, 56323, 33252, 63066, 56892, 31406, 8605, 42292, 43510, 57971, 24717 ], 405 | [ 17658, 63089, 55361, 22726, 14099, 34027, 38415, 56519, 43464, 33658, 12210, 45361, 55322, 16280, 53265, 15153 ], 406 | [ 17576, 60955, 52972, 37572, 31281, 7613, 57259, 47926, 5101, 41656, 5242, 94, 15936, 13063, 29174, 16805 ] 407 | ], 408 | [ 409 | [ 54638, 5684, 41729, 60051, 37970, 37868, 33207, 11537, 63832, 2741, 20394, 12022, 13887, 13247, 59226, 35025 ], 410 | [ 53018, 44610, 46540, 14711, 23492, 53339, 22822, 53287, 29013, 40210, 15752, 60060, 27201, 20720, 37779, 18397 ], 411 | [ 46822, 20414, 13489, 20076, 39570, 56458, 6230, 64980, 11314, 23287, 26408, 32800, 23288, 11450, 21471, 45096 ] 412 | ], 413 | [ 414 | [ 51548, 27985, 43548, 42485, 16272, 57876, 36462, 64868, 57516, 8782, 49637, 10684, 27146, 41374, 52064, 35631 ], 415 | [ 14812, 62258, 17569, 50665, 30915, 38395, 13383, 13365, 9704, 37854, 46278, 28022, 4998, 59846, 46440, 25345 ], 416 | [ 38150, 43285, 30331, 2121, 54230, 61359, 24491, 28928, 11481, 22149, 56518, 47909, 16075, 49006, 15920, 11126 ] 417 | ], 418 | [ 419 | [ 44564, 3539, 36684, 59956, 15485, 35557, 23503, 55442, 5680, 41908, 65397, 10219, 23752, 49772, 27886, 35617 ], 420 | [ 47792, 21266, 43562, 44407, 30745, 35413, 24622, 49799, 37230, 37176, 31295, 9413, 20879, 57029, 21424, 54832 ], 421 | [ 12834, 65150, 47079, 21134, 22856, 19695, 36008, 37303, 63179, 25084, 7717, 63173, 51017, 46725, 23119, 26997 ] 422 | ], 423 | [ 424 | [ 65026, 4692, 51736, 42365, 17256, 28067, 10772, 42346, 12942, 25575, 58191, 17606, 43838, 51811, 34327, 16244 ], 425 | [ 25630, 32193, 56402, 23059, 40097, 61006, 10393, 19643, 44270, 7081, 41609, 14648, 50299, 16911, 35302, 4077 ], 426 | [ 56494, 13607, 11071, 64046, 56225, 9721, 39692, 64924, 58387, 48355, 25501, 11718, 706, 53409, 53273, 8958 ] 427 | ], 428 | [ 429 | [ 15584, 32908, 4227, 14218, 40016, 57268, 35903, 9207, 54791, 41215, 27778, 15221, 46564, 58555, 20710, 35056 ], 430 | [ 61026, 18549, 13202, 62706, 5549, 41338, 17921, 12969, 34822, 14006, 13639, 46265, 34114, 61558, 72, 14480 ], 431 | [ 23732, 22042, 58434, 61361, 43649, 43233, 41018, 63263, 41203, 15990, 62733, 54617, 52614, 54850, 33380, 12457 ] 432 | ], 433 | [ 434 | [ 170, 1209, 13693, 60412, 3024, 12805, 31314, 9353, 20597, 25569, 33282, 59278, 3205, 22258, 14148, 42371 ], 435 | [ 41340, 52174, 55904, 530, 10526, 10809, 46851, 30699, 59968, 11209, 54572, 32381, 50988, 64858, 50431, 58065 ], 436 | [ 33596, 14700, 14973, 62820, 9830, 44952, 2083, 11787, 42939, 41876, 63267, 19391, 31872, 27074, 1281, 39087 ] 437 | ], 438 | [ 439 | [ 34826, 23448, 64590, 9281, 58885, 11088, 38574, 55633, 29291, 13234, 38978, 47976, 23056, 35962, 1949, 34228 ], 440 | [ 24860, 55199, 16296, 35971, 26896, 59024, 53967, 41827, 21732, 58750, 4969, 36892, 43607, 21481, 17186, 41769 ], 441 | [ 30762, 48897, 11200, 38671, 24567, 11776, 4656, 44478, 12561, 12524, 21406, 9747, 4407, 61736, 54354, 28735 ] 442 | ], 443 | [ 444 | [ 7378, 2808, 11773, 62846, 28917, 16765, 4459, 48894, 53657, 10581, 48945, 38848, 54636, 52277, 35678, 59865 ], 445 | [ 20110, 9631, 33272, 11604, 54542, 33108, 42651, 52882, 59723, 9359, 51771, 17632, 13995, 64510, 54407, 15910 ], 446 | [ 64428, 28042, 7507, 57541, 22517, 31303, 14531, 13991, 39188, 56263, 46488, 8721, 43819, 32852, 51701, 55380 ] 447 | ], 448 | [ 449 | [ 46790, 40404, 27348, 28847, 11271, 40464, 4541, 58541, 13094, 37488, 7288, 40820, 24693, 62550, 43065, 58024 ], 450 | [ 48936, 13653, 35681, 38724, 15080, 49493, 15304, 38397, 4393, 38496, 51998, 40209, 962, 7050, 54982, 48453 ], 451 | [ 47624, 5221, 2227, 62264, 45831, 22453, 10817, 21518, 31746, 63461, 63786, 18926, 54698, 15856, 16802, 37978 ] 452 | ], 453 | [ 454 | [ 3710, 45648, 3532, 42603, 23409, 60738, 44989, 61612, 4860, 16290, 55886, 4584, 9203, 1249, 866, 19996 ], 455 | [ 45512, 28443, 24947, 10045, 32013, 9594, 29535, 12046, 63123, 55332, 36943, 41644, 2658, 25072, 2265, 27225 ], 456 | [ 37666, 46012, 34066, 46486, 55088, 15235, 11526, 41786, 31823, 24601, 61469, 7536, 59257, 46351, 44078, 17239 ] 457 | ], 458 | [ 459 | [ 11612, 63573, 36399, 6384, 59963, 9949, 53618, 65269, 47333, 54246, 18448, 18758, 40762, 17758, 36971, 65512 ], 460 | [ 30400, 13161, 47483, 28736, 42734, 27433, 53469, 36189, 16065, 59978, 45367, 515, 13571, 10481, 65437, 37632 ], 461 | [ 60638, 33261, 33349, 11385, 35478, 57407, 51459, 35502, 44933, 49497, 52254, 37256, 36788, 48465, 14604, 7568 ] 462 | ], 463 | [ 464 | [ 54818, 6069, 49028, 52242, 5155, 57162, 12564, 41404, 28332, 64171, 4439, 45907, 58919, 18425, 17459, 7732 ], 465 | [ 64614, 46246, 13579, 51488, 8781, 50308, 8361, 35308, 47764, 22118, 47432, 32647, 7882, 60678, 21925, 43353 ], 466 | [ 41428, 64340, 63562, 4099, 29648, 36666, 7318, 32314, 51028, 52454, 51563, 14873, 11836, 54590, 62875, 10547 ] 467 | ], 468 | [ 469 | [ 57686, 61941, 43989, 11176, 35246, 53235, 40790, 19442, 48177, 43288, 23302, 46270, 63585, 1714, 33180, 19627 ], 470 | [ 26636, 374, 14358, 3883, 38775, 26514, 34382, 35690, 59621, 63244, 14646, 13237, 53222, 48478, 64280, 40720 ], 471 | [ 40814, 63200, 13339, 36643, 2158, 20907, 7573, 45913, 55564, 14841, 58413, 45439, 29935, 44646, 60930, 356 ] 472 | ], 473 | [ 474 | [ 61552, 25357, 21487, 46443, 63851, 53123, 1246, 39714, 2604, 42464, 51160, 42396, 63139, 53103, 27536, 64616 ], 475 | [ 5408, 32727, 54554, 22561, 6340, 61605, 29644, 64936, 6394, 977, 36241, 53842, 42147, 45523, 7658, 32783 ], 476 | [ 11086, 40333, 2080, 62195, 19761, 22811, 50077, 60227, 43854, 51186, 3719, 59207, 50862, 60181, 41867, 14715 ] 477 | ], 478 | [ 479 | [ 14892, 44517, 56820, 63277, 17500, 23477, 41761, 24457, 17814, 19914, 8612, 28825, 50394, 41156, 62693, 2796 ], 480 | [ 26612, 25889, 2281, 2976, 19050, 46522, 44928, 7120, 62917, 29515, 24656, 28973, 24937, 49166, 16416, 39216 ], 481 | [ 24376, 47766, 29505, 34548, 28027, 27133, 19961, 39300, 64497, 14476, 18097, 24816, 7070, 40039, 44384, 13521 ] 482 | ], 483 | [ 484 | [ 30160, 15191, 23787, 22036, 51536, 47183, 7864, 62627, 62891, 8361, 37909, 55938, 7318, 22939, 65420, 20980 ], 485 | [ 15022, 55174, 1712, 32644, 48411, 2004, 32888, 45358, 61108, 14418, 39662, 63225, 16883, 54382, 38280, 46508 ], 486 | [ 51454, 2262, 29191, 36827, 29872, 36887, 12629, 3200, 26367, 45605, 18033, 64393, 62186, 55896, 12116, 52640 ] 487 | ], 488 | [ 489 | [ 38702, 29119, 39786, 60530, 63731, 58987, 27662, 42345, 26671, 55378, 33121, 25536, 42559, 4924, 59024, 54925 ], 490 | [ 14824, 30512, 45347, 7165, 15933, 19828, 44671, 14939, 26036, 14862, 56387, 16860, 58951, 37608, 8713, 19528 ], 491 | [ 39132, 5898, 56260, 111, 6633, 18529, 3586, 46118, 12903, 3230, 46009, 34683, 29687, 63326, 63211, 49296 ] 492 | ], 493 | [ 494 | [ 986, 26164, 3268, 28275, 9404, 63925, 33136, 59730, 31988, 56611, 47263, 61254, 8733, 32085, 50289, 13122 ], 495 | [ 14258, 23401, 50856, 42141, 25084, 26734, 59974, 7383, 53863, 64125, 52465, 36180, 13622, 201, 27871, 53351 ], 496 | [ 47272, 64848, 46202, 37434, 3539, 17306, 10295, 11614, 18013, 16, 1324, 39875, 20444, 2890, 16545, 44348 ] 497 | ], 498 | [ 499 | [ 19866, 10562, 42077, 28523, 35496, 37197, 53883, 14047, 495, 50466, 36300, 22763, 45885, 64592, 38795, 13206 ], 500 | [ 13184, 51207, 51786, 45520, 48555, 42973, 44156, 17726, 52427, 37127, 13759, 52125, 4733, 4412, 4953, 56527 ], 501 | [ 1590, 45291, 12525, 30863, 47551, 5952, 31544, 41624, 1305, 19600, 22328, 41628, 42169, 24277, 34012, 56427 ] 502 | ], 503 | [ 504 | [ 47154, 55105, 1963, 21, 52878, 45791, 23619, 56321, 500, 38225, 23056, 9462, 40996, 14873, 10761, 49066 ], 505 | [ 36572, 50923, 56767, 31505, 18407, 52966, 46823, 59589, 56458, 22347, 15125, 51814, 41865, 44285, 57613, 31261 ], 506 | [ 45080, 37114, 34084, 4403, 11218, 44421, 50399, 57771, 34429, 58981, 10928, 20984, 41078, 12023, 32950, 52502 ] 507 | ], 508 | [ 509 | [ 58290, 44776, 10007, 25827, 29024, 10567, 3842, 23954, 37648, 3784, 60833, 43450, 7318, 30405, 52528, 45305 ], 510 | [ 45186, 36029, 42940, 32335, 20221, 48954, 1119, 32889, 23083, 20383, 8552, 28953, 8390, 16897, 57258, 44206 ], 511 | [ 55832, 147, 37349, 17470, 11682, 46270, 54584, 41614, 5477, 24140, 62164, 31600, 50118, 22369, 3705, 54163 ] 512 | ], 513 | [ 514 | [ 28304, 19326, 37745, 29376, 60397, 9329, 9879, 65180, 16075, 6489, 4008, 32117, 6334, 38630, 38174, 24688 ], 515 | [ 26230, 7486, 24396, 49406, 17156, 17622, 46361, 51117, 56354, 10353, 56932, 14401, 36647, 27436, 47112, 64440 ], 516 | [ 11742, 41547, 15790, 50057, 16698, 1429, 29621, 27344, 62344, 61544, 18444, 38136, 34489, 43200, 27607, 43103 ] 517 | ], 518 | [ 519 | [ 28714, 40231, 45017, 10161, 58287, 7773, 12346, 24916, 59488, 9923, 48186, 62846, 56705, 356, 60164, 40640 ], 520 | [ 11482, 53668, 50081, 28252, 1842, 47135, 6414, 39326, 13097, 44698, 60794, 17000, 31849, 45831, 11320, 15862 ], 521 | [ 63140, 7803, 19175, 38025, 55094, 34247, 44066, 57026, 48589, 50622, 10423, 11999, 55092, 8942, 27131, 32125 ] 522 | ], 523 | [ 524 | [ 43260, 469, 18602, 10319, 12902, 47642, 60028, 32785, 6167, 22171, 9608, 26886, 11282, 22250, 16745, 39204 ], 525 | [ 8670, 56048, 64394, 47281, 51405, 33386, 29465, 51163, 35023, 38635, 28654, 1787, 52690, 31613, 10258, 3214 ], 526 | [ 8050, 5348, 31788, 49488, 2187, 7106, 27858, 1711, 25837, 56064, 60976, 50925, 56298, 17118, 54899, 54335 ] 527 | ], 528 | [ 529 | [ 17536, 52887, 65320, 16442, 62916, 39926, 27636, 33799, 39163, 60632, 908, 60503, 60745, 46691, 65450, 43160 ], 530 | [ 5674, 62261, 48198, 62643, 46790, 64079, 41204, 58899, 17751, 47507, 54972, 59225, 38007, 43884, 15254, 35151 ], 531 | [ 18642, 7612, 28171, 32004, 6223, 22171, 24140, 7174, 21251, 54536, 44281, 29012, 47056, 7918, 43209, 13623 ] 532 | ], 533 | [ 534 | [ 63322, 363, 20242, 49489, 33904, 18324, 434, 29036, 52439, 26135, 22799, 23901, 272, 4439, 56821, 13538 ], 535 | [ 55590, 23583, 44120, 907, 50130, 3973, 49978, 28031, 34446, 21197, 36724, 30549, 46871, 46990, 60040, 7130 ], 536 | [ 57316, 46758, 64156, 59883, 32897, 30969, 8926, 46030, 50626, 48055, 3741, 3362, 9530, 23756, 47883, 7163 ] 537 | ], 538 | [ 539 | [ 23752, 65046, 40941, 22054, 19446, 42911, 34058, 42494, 34700, 39133, 20174, 22723, 45653, 15739, 27608, 19637 ], 540 | [ 14418, 5536, 43002, 36788, 50411, 39814, 42288, 19806, 35562, 40858, 55322, 21339, 6420, 25381, 28596, 56607 ], 541 | [ 2758, 55398, 40494, 50399, 8816, 46317, 16301, 12045, 52060, 28427, 53610, 30914, 42195, 27664, 20195, 44885 ] 542 | ], 543 | [ 544 | [ 36780, 7868, 35709, 2906, 44941, 11894, 58225, 28475, 12115, 36926, 54421, 5173, 35919, 52796, 7255, 18806 ], 545 | [ 20648, 25057, 22379, 60213, 2884, 28172, 9721, 29824, 36850, 31343, 32574, 62253, 2382, 4197, 862, 12837 ], 546 | [ 52622, 54759, 7165, 32039, 29484, 18181, 17736, 535, 63279, 40334, 11549, 3906, 3183, 6320, 48320, 59162 ] 547 | ], 548 | [ 549 | [ 24726, 4060, 58724, 57885, 20365, 12153, 9230, 2, 30469, 9539, 27197, 47047, 1215, 25864, 14836, 58699 ], 550 | [ 6550, 27410, 46954, 56547, 39749, 46299, 44712, 43228, 17428, 25189, 13518, 33946, 4632, 61697, 31714, 20686 ], 551 | [ 53290, 43355, 55544, 14805, 15504, 16967, 39691, 58383, 56900, 14443, 64587, 48259, 32627, 37783, 7142, 12114 ] 552 | ], 553 | [ 554 | [ 31996, 35939, 23662, 12510, 26079, 12026, 41904, 1317, 48468, 47653, 44550, 35807, 7129, 14570, 1459, 35094 ], 555 | [ 36020, 25791, 44328, 42488, 28506, 47817, 32725, 54997, 26301, 15663, 21674, 47862, 8754, 7834, 1362, 40436 ], 556 | [ 64198, 37630, 9627, 27010, 53612, 51231, 48673, 13813, 19262, 33525, 44917, 35072, 63273, 29896, 56891, 3722 ] 557 | ], 558 | [ 559 | [ 8106, 60347, 58622, 64647, 11441, 34999, 50932, 62905, 17956, 42482, 36767, 37770, 26992, 22228, 65004, 17926 ], 560 | [ 26190, 20175, 52788, 55564, 20646, 24278, 44949, 22761, 61178, 47259, 4005, 57397, 33347, 25965, 55782, 3840 ], 561 | [ 34352, 42166, 56827, 6601, 29978, 63273, 34804, 59382, 1191, 17054, 42650, 37483, 37020, 29198, 11674, 44774 ] 562 | ], 563 | [ 564 | [ 30056, 64570, 54116, 32297, 18909, 22938, 48979, 42932, 45906, 43781, 44995, 6678, 17029, 41522, 64134, 49977 ], 565 | [ 19214, 25507, 65162, 22693, 5105, 40381, 32682, 16502, 33136, 29968, 48025, 3006, 59670, 25274, 52276, 27911 ], 566 | [ 33930, 24196, 3057, 10520, 43642, 23602, 56889, 37205, 30440, 22627, 24315, 21984, 45268, 31184, 25438, 52683 ] 567 | ], 568 | [ 569 | [ 472, 14023, 20119, 43958, 3423, 47660, 25703, 56917, 65468, 60582, 54020, 14733, 24150, 63726, 12004, 57907 ], 570 | [ 61266, 40888, 19400, 64935, 18721, 37531, 33333, 2774, 62107, 61817, 12103, 32362, 53151, 536, 64316, 48667 ], 571 | [ 4840, 3498, 54236, 48928, 24325, 51571, 49052, 29004, 17407, 26083, 43622, 17101, 31876, 56565, 3473, 27468 ] 572 | ], 573 | [ 574 | [ 35612, 16584, 53585, 6828, 58379, 41641, 8514, 12057, 38779, 63423, 27991, 15679, 3919, 45794, 129, 64414 ], 575 | [ 34188, 50219, 61948, 59563, 8825, 33988, 14871, 34554, 32166, 62457, 879, 8279, 31053, 28409, 21617, 2360 ], 576 | [ 3842, 32320, 63157, 61862, 63647, 31005, 14581, 10227, 39974, 63746, 62522, 7840, 11462, 7486, 46651, 48000 ] 577 | ], 578 | [ 579 | [ 10560, 43124, 24111, 31225, 62372, 47422, 13309, 44081, 27034, 7816, 8567, 62253, 21137, 5414, 42674, 32463 ], 580 | [ 8390, 27719, 32164, 25547, 23530, 57091, 34878, 28033, 1998, 6210, 32352, 21883, 27390, 56051, 35676, 4245 ], 581 | [ 42686, 47185, 20244, 44037, 51071, 4064, 35360, 21987, 10083, 33452, 44364, 15841, 11963, 1861, 7012, 20339 ] 582 | ], 583 | [ 584 | [ 38376, 25490, 64592, 61538, 24228, 6284, 6082, 46884, 49784, 59305, 12906, 10710, 44933, 36299, 5009, 60378 ], 585 | [ 2614, 46786, 42315, 1885, 16663, 24369, 18018, 37624, 26361, 29512, 38822, 32013, 61064, 45410, 43011, 11327 ], 586 | [ 64616, 2472, 36083, 41761, 39307, 746, 46630, 36957, 34356, 39450, 19238, 48147, 2309, 49370, 37876, 9239 ] 587 | ], 588 | [ 589 | [ 45386, 35440, 59561, 31075, 57856, 5669, 19402, 41999, 44390, 40729, 26504, 35596, 19138, 11099, 38253, 6575 ], 590 | [ 40312, 52406, 46176, 20338, 26903, 19034, 13416, 41387, 12869, 33596, 29319, 21552, 26743, 64430, 35765, 56866 ], 591 | [ 40354, 33734, 6457, 13004, 42796, 16069, 6595, 55878, 28867, 51342, 36808, 5287, 21067, 21560, 41323, 23871 ] 592 | ], 593 | [ 594 | [ 47582, 13703, 48069, 53177, 55029, 54733, 31756, 58894, 13456, 20987, 7746, 44141, 18074, 38852, 12841, 50623 ], 595 | [ 40550, 9414, 60864, 23973, 54408, 29680, 31639, 32746, 65346, 40993, 12187, 64922, 22355, 33799, 34888, 21149 ], 596 | [ 59874, 43797, 52175, 17416, 16260, 39519, 22855, 42421, 3181, 31337, 24816, 39494, 63253, 8873, 63019, 2438 ] 597 | ], 598 | [ 599 | [ 50676, 5410, 40162, 41568, 55577, 44583, 20023, 51622, 42624, 36753, 18706, 229, 18200, 55249, 8744, 47459 ], 600 | [ 58088, 32256, 40690, 39198, 38201, 48388, 26398, 45691, 44070, 43750, 18146, 58581, 34536, 43965, 21884, 28505 ], 601 | [ 40378, 56424, 12107, 22584, 40535, 14510, 56053, 59877, 30866, 6429, 36252, 44357, 28818, 1778, 38936, 59633 ] 602 | ], 603 | [ 604 | [ 25636, 39790, 28981, 52856, 819, 13089, 61750, 39795, 5561, 11403, 53097, 60749, 19791, 5207, 33299, 19876 ], 605 | [ 28242, 41994, 1881, 61975, 19051, 28191, 46582, 25276, 46820, 41690, 48275, 1321, 53970, 18035, 5635, 45376 ], 606 | [ 61280, 28698, 31734, 37481, 26262, 1744, 12783, 44370, 3377, 58592, 6826, 60980, 39027, 61326, 28012, 36961 ] 607 | ], 608 | [ 609 | [ 29516, 5485, 41405, 23629, 2835, 1572, 30872, 23324, 8171, 21528, 55619, 26197, 10714, 59425, 15544, 8770 ], 610 | [ 52660, 28424, 8981, 2842, 60706, 61905, 51111, 17779, 40691, 30414, 63159, 46649, 31118, 59838, 53147, 25213 ], 611 | [ 29804, 9221, 22712, 50929, 40966, 36843, 45935, 36511, 4297, 15481, 447, 3438, 60098, 39746, 1157, 59116 ] 612 | ], 613 | [ 614 | [ 2996, 43826, 1244, 21841, 7713, 29963, 35225, 13683, 37178, 65067, 18919, 30442, 63937, 47430, 595, 1059 ], 615 | [ 23292, 7454, 22644, 42645, 31631, 16023, 15127, 11641, 22438, 17903, 2818, 28237, 37790, 12173, 40409, 1243 ], 616 | [ 37738, 62557, 13130, 3528, 58803, 19254, 20607, 58433, 9849, 3558, 5106, 51521, 14004, 13233, 31040, 24005 ] 617 | ], 618 | [ 619 | [ 55232, 38742, 37208, 2526, 40783, 25534, 33712, 17286, 48221, 62432, 30144, 35775, 43662, 35831, 28260, 25520 ], 620 | [ 44566, 57483, 9371, 23656, 49732, 2256, 31671, 64866, 55423, 47060, 64848, 6956, 16831, 55701, 55438, 6935 ], 621 | [ 9602, 24997, 35929, 58397, 23128, 19209, 55578, 812, 35634, 8573, 52215, 35407, 5661, 1717, 46608, 26481 ] 622 | ], 623 | [ 624 | [ 21894, 36407, 14531, 5192, 38837, 42962, 17748, 13809, 14404, 61854, 46619, 52, 38460, 10734, 59904, 2860 ], 625 | [ 56042, 40601, 33561, 28006, 30441, 20615, 64977, 24636, 50823, 55617, 56206, 56926, 39594, 10451, 38362, 18410 ], 626 | [ 50188, 55875, 51480, 25920, 43417, 62641, 16222, 60507, 15610, 26281, 29699, 11335, 4471, 61825, 352, 27159 ] 627 | ], 628 | [ 629 | [ 43690, 58899, 17869, 42058, 2649, 45412, 54936, 4916, 58884, 38039, 51974, 20180, 38587, 53709, 53591, 34531 ], 630 | [ 27770, 10053, 37828, 32127, 25212, 14416, 27450, 34997, 55750, 30961, 47385, 37689, 51517, 40160, 52796, 29429 ], 631 | [ 28230, 34123, 19213, 65289, 40438, 61826, 47405, 1487, 15232, 50105, 23559, 19299, 56289, 9073, 10143, 1131 ] 632 | ], 633 | [ 634 | [ 59940, 32035, 11350, 23010, 34062, 1120, 23176, 7796, 61259, 55827, 65356, 17795, 16261, 38152, 8236, 7955 ], 635 | [ 24392, 36903, 604, 44354, 18296, 46428, 2174, 133, 32762, 65021, 2535, 61969, 7038, 27704, 27957, 26163 ], 636 | [ 23354, 45507, 34148, 16809, 57196, 8629, 37119, 17741, 20177, 52233, 16948, 12301, 14213, 47687, 21633, 55538 ] 637 | ], 638 | [ 639 | [ 896, 33078, 58540, 2336, 19509, 45637, 19486, 8468, 59878, 31626, 65165, 50718, 49470, 64053, 28903, 40270 ], 640 | [ 11854, 56770, 22421, 43985, 59520, 5987, 18613, 35556, 40465, 48754, 36229, 2641, 40946, 7392, 1961, 64296 ], 641 | [ 58624, 51107, 13193, 9015, 3366, 62034, 65393, 22632, 37297, 58511, 17298, 50098, 25460, 13779, 48664, 42812 ] 642 | ], 643 | [ 644 | [ 59428, 24759, 18350, 64640, 9189, 49895, 34249, 39142, 10656, 57678, 14724, 38189, 62252, 15429, 45055, 19495 ], 645 | [ 42584, 19445, 48401, 23482, 50334, 20900, 48670, 37072, 39994, 9922, 7862, 38385, 51325, 21101, 39398, 57132 ], 646 | [ 13194, 18161, 12745, 59879, 44457, 26211, 25730, 5240, 19306, 1938, 22016, 54497, 24623, 3060, 25853, 1441 ] 647 | ], 648 | [ 649 | [ 57458, 12836, 53684, 64751, 41577, 36799, 11378, 63125, 28388, 36989, 22519, 41089, 56055, 13295, 58119, 63595 ], 650 | [ 10038, 50750, 1810, 20139, 27070, 45981, 2238, 10876, 2119, 54525, 3789, 13351, 39003, 12084, 24439, 25914 ], 651 | [ 25800, 29087, 59415, 196, 48494, 22458, 61013, 38596, 55532, 23507, 26266, 3472, 16011, 19761, 16083, 4807 ] 652 | ], 653 | [ 654 | [ 43520, 19502, 8944, 27832, 6579, 60237, 53355, 50852, 56732, 23496, 22401, 57225, 43315, 18792, 58496, 41470 ], 655 | [ 5888, 12432, 54249, 12384, 49713, 35186, 13946, 48549, 33593, 20613, 23969, 16748, 46365, 1836, 30528, 20491 ], 656 | [ 33272, 57779, 42372, 56704, 38896, 57863, 28950, 59974, 38059, 1512, 10223, 26766, 36848, 35864, 35062, 6533 ] 657 | ], 658 | [ 659 | [ 46028, 4422, 4974, 10423, 22094, 61917, 44460, 50008, 35064, 24212, 38918, 58529, 64362, 18698, 35421, 63486 ], 660 | [ 582, 42485, 50607, 28021, 17850, 2613, 51710, 8876, 36241, 38177, 819, 35520, 62230, 57401, 3841, 15443 ], 661 | [ 44332, 6994, 26246, 65069, 2310, 38272, 56570, 15064, 60248, 65486, 62051, 34084, 2079, 30502, 50572, 9634 ] 662 | ], 663 | [ 664 | [ 30004, 7991, 20020, 7593, 26472, 18936, 38552, 19708, 38757, 759, 21066, 364, 18621, 7099, 42221, 21474 ], 665 | [ 54598, 23195, 37026, 47315, 19511, 33365, 2088, 32527, 33194, 57445, 21004, 41929, 10034, 55908, 13565, 55843 ], 666 | [ 23314, 23270, 59239, 63358, 23501, 58990, 23901, 42056, 33330, 40915, 46958, 18781, 347, 48981, 28759, 17084 ] 667 | ], 668 | [ 669 | [ 45218, 19724, 31667, 51235, 35359, 26169, 47846, 4172, 51767, 31900, 40453, 49407, 36600, 36785, 26479, 42520 ], 670 | [ 16696, 21523, 6691, 20132, 35753, 19230, 5628, 47908, 52094, 7862, 62747, 51442, 60502, 41522, 23392, 43680 ], 671 | [ 47246, 63930, 31753, 34746, 30374, 60139, 13814, 49748, 30603, 46863, 33157, 58403, 47057, 38874, 6852, 49654 ] 672 | ], 673 | [ 674 | [ 27658, 48207, 12862, 19175, 4890, 18881, 48952, 49911, 36819, 44395, 63314, 48335, 52007, 26432, 52598, 22125 ], 675 | [ 45266, 44327, 39870, 46578, 56931, 9018, 46997, 32266, 40691, 28485, 14617, 36725, 15673, 49167, 61855, 53737 ], 676 | [ 3318, 36896, 31330, 19110, 58575, 9748, 59155, 31016, 63252, 10557, 12919, 64554, 12855, 5094, 51707, 7457 ] 677 | ], 678 | [ 679 | [ 43656, 9236, 38022, 4625, 6718, 52405, 57531, 54684, 28060, 22714, 36210, 8955, 40827, 38012, 45872, 8529 ], 680 | [ 29942, 62013, 53423, 798, 9084, 51563, 9724, 36976, 39644, 64420, 64585, 2621, 14389, 58479, 20606, 10753 ], 681 | [ 2870, 14949, 51432, 9154, 41467, 12609, 12184, 44975, 12220, 46737, 38336, 24659, 6319, 1337, 12683, 5426 ] 682 | ], 683 | [ 684 | [ 58326, 24982, 64826, 39919, 36895, 9380, 23316, 57032, 45392, 44829, 21992, 34698, 65037, 15274, 11394, 31629 ], 685 | [ 3186, 63663, 17539, 55625, 53061, 18679, 21465, 61876, 41061, 50145, 5555, 35309, 20379, 45922, 42327, 40005 ], 686 | [ 38838, 32550, 17377, 53186, 13872, 51608, 50728, 58840, 10263, 59211, 60261, 52, 52276, 41405, 26686, 21063 ] 687 | ], 688 | [ 689 | [ 49544, 53401, 7228, 46173, 5103, 36879, 14009, 38191, 50837, 57052, 20746, 36322, 48371, 60497, 45535, 24482 ], 690 | [ 26670, 9121, 39805, 26944, 31621, 48962, 19344, 16598, 55087, 21074, 8626, 25822, 35005, 28099, 64165, 16257 ], 691 | [ 24454, 45495, 38472, 49167, 63443, 50502, 43548, 18625, 11937, 33637, 33787, 29411, 35243, 18564, 25266, 55802 ] 692 | ], 693 | [ 694 | [ 65000, 31559, 26250, 31134, 25646, 61314, 8695, 63212, 34520, 12553, 56700, 27139, 41048, 46967, 35995, 40839 ], 695 | [ 18242, 43236, 21821, 13345, 7595, 57518, 60148, 50651, 22713, 50367, 35114, 6705, 11764, 51937, 39223, 55623 ], 696 | [ 52676, 31195, 13433, 13073, 26987, 50172, 38375, 41651, 45574, 21726, 55018, 21606, 21999, 20533, 57636, 1625 ] 697 | ], 698 | [ 699 | [ 51892, 49507, 43337, 17717, 32341, 25818, 1842, 63312, 44082, 30174, 39768, 45585, 7994, 63477, 1145, 35046 ], 700 | [ 64070, 19234, 57850, 38654, 26620, 26554, 50327, 7143, 36998, 61023, 23540, 45585, 44493, 49902, 27720, 6955 ], 701 | [ 13256, 31016, 36623, 53786, 1340, 2495, 47034, 25714, 25577, 47980, 22291, 31029, 59783, 4291, 27533, 3343 ] 702 | ], 703 | [ 704 | [ 32766, 13819, 50813, 8961, 50216, 44034, 16927, 40372, 252, 42388, 51950, 38874, 16649, 34679, 31581, 30855 ], 705 | [ 64482, 11664, 6529, 12190, 34157, 35976, 23616, 16759, 333, 30233, 59488, 18508, 13284, 12931, 46188, 33601 ], 706 | [ 44600, 8337, 30770, 46753, 57558, 58360, 7487, 2644, 43912, 62137, 8386, 23443, 27025, 905, 49721, 16650 ] 707 | ], 708 | [ 709 | [ 4332, 2498, 28239, 54004, 32479, 31690, 7452, 41914, 55990, 13159, 34772, 19254, 8209, 42501, 49449, 38791 ], 710 | [ 38646, 12234, 14554, 7079, 51964, 65149, 35080, 18402, 27179, 19293, 41466, 57012, 49846, 20785, 57589, 2980 ], 711 | [ 11716, 8108, 36739, 22422, 24876, 62155, 21204, 36782, 37200, 12335, 39593, 57072, 12547, 60194, 23494, 54010 ] 712 | ], 713 | [ 714 | [ 58716, 1222, 11150, 48727, 34104, 52003, 48823, 43343, 28371, 43538, 45781, 37678, 39465, 34890, 17176, 501 ], 715 | [ 64592, 41691, 8537, 48525, 13182, 12206, 6791, 38864, 3527, 25421, 61185, 33797, 16620, 43229, 20234, 2928 ], 716 | [ 27842, 46560, 43622, 47535, 54034, 26069, 41291, 11199, 52952, 61535, 28190, 37594, 62091, 7096, 57297, 26255 ] 717 | ], 718 | [ 719 | [ 9772, 16617, 1001, 1709, 37225, 53728, 24713, 31108, 10206, 58989, 48502, 59114, 18606, 26563, 22464, 45005 ], 720 | [ 49516, 47580, 48327, 15750, 19285, 31272, 19963, 63687, 26556, 24618, 36685, 2823, 5914, 64191, 42924, 39485 ], 721 | [ 9780, 43458, 35113, 44502, 34737, 33930, 40237, 42986, 16113, 23488, 7720, 38446, 36231, 6124, 23262, 13330 ] 722 | ], 723 | [ 724 | [ 16254, 24301, 30744, 9023, 3372, 17548, 59392, 59899, 54926, 14033, 22360, 44702, 23627, 1803, 27580, 43861 ], 725 | [ 19804, 55063, 34017, 30937, 37041, 12029, 46515, 16153, 64027, 26816, 56755, 11776, 48521, 32894, 4914, 64416 ], 726 | [ 35884, 56321, 62410, 15168, 23138, 42068, 41903, 20292, 50217, 305, 54892, 52499, 40279, 47100, 27690, 22582 ] 727 | ], 728 | [ 729 | [ 28442, 44864, 17476, 17328, 3471, 7888, 3012, 23833, 65166, 62401, 23749, 63633, 19972, 37054, 18356, 16220 ], 730 | [ 15280, 62252, 13054, 1905, 43583, 17850, 43104, 60045, 52052, 4153, 62132, 53899, 33300, 1858, 59790, 21372 ], 731 | [ 4056, 34619, 8427, 27480, 42853, 15317, 47739, 16166, 1365, 53824, 39435, 45885, 35000, 26016, 63232, 24273 ] 732 | ], 733 | [ 734 | [ 63562, 43188, 56624, 14540, 54181, 55498, 63697, 12722, 54417, 1394, 19031, 33339, 50762, 8296, 6370, 57665 ], 735 | [ 54278, 18317, 4649, 45157, 30737, 46407, 41931, 64165, 34053, 43348, 38707, 11149, 65218, 13721, 58664, 58347 ], 736 | [ 10624, 6514, 65504, 8127, 26392, 42254, 29813, 41297, 12945, 34945, 16883, 19585, 48525, 6637, 29742, 55292 ] 737 | ], 738 | [ 739 | [ 16286, 61247, 62680, 46076, 24736, 1616, 10539, 28754, 2837, 9252, 24568, 6265, 65484, 39305, 41348, 37806 ], 740 | [ 8004, 49848, 49409, 6448, 1365, 4192, 27812, 26413, 58736, 6949, 49138, 64477, 11120, 36001, 38044, 2180 ], 741 | [ 638, 30298, 56655, 9399, 30117, 59304, 4810, 26219, 18520, 24727, 31943, 19160, 57857, 57269, 43467, 8800 ] 742 | ], 743 | [ 744 | [ 50388, 19779, 11209, 23913, 15389, 48047, 14403, 38990, 60733, 8461, 64771, 39408, 1095, 39088, 21865, 36722 ], 745 | [ 57182, 21269, 34363, 45184, 28913, 36712, 31846, 18702, 55322, 65131, 61262, 18378, 980, 14273, 40016, 5825 ], 746 | [ 39162, 887, 41162, 38817, 41457, 598, 38782, 57112, 59910, 53118, 37892, 23886, 44942, 32377, 40386, 57741 ] 747 | ], 748 | [ 749 | [ 14088, 58183, 40693, 11498, 59178, 13954, 8180, 18305, 19346, 3689, 35857, 21341, 33115, 2087, 41148, 42414 ], 750 | [ 12886, 1441, 16913, 53760, 44121, 25165, 5003, 20706, 41053, 39837, 48125, 16658, 16757, 52382, 51164, 56796 ], 751 | [ 49594, 64893, 48594, 20848, 64624, 20156, 32909, 27928, 46014, 50100, 43407, 34407, 2435, 8182, 37248, 43340 ] 752 | ], 753 | [ 754 | [ 58310, 1592, 28742, 24194, 18728, 65401, 53797, 10574, 1677, 9136, 39854, 58470, 49277, 37232, 64675, 52972 ], 755 | [ 4706, 27191, 63024, 64286, 23572, 3597, 33207, 59242, 1288, 43692, 17976, 29666, 19434, 33031, 31811, 24222 ], 756 | [ 29992, 59478, 50840, 38693, 63335, 29799, 47633, 426, 64291, 47237, 19989, 34117, 23751, 42351, 35771, 48515 ] 757 | ], 758 | [ 759 | [ 63996, 20257, 30254, 8091, 24616, 17271, 40242, 6078, 10800, 6342, 26258, 12386, 16536, 42513, 6271, 10372 ], 760 | [ 43820, 62675, 30346, 15521, 11722, 49993, 2282, 34059, 10775, 27843, 64776, 40791, 24381, 26591, 17000, 45568 ], 761 | [ 58472, 40357, 40041, 10399, 16041, 21611, 58355, 19218, 23469, 45222, 44902, 14629, 64540, 56237, 21298, 40009 ] 762 | ], 763 | [ 764 | [ 55834, 42483, 17217, 64552, 59262, 60017, 15302, 52313, 54062, 60480, 5043, 17519, 5069, 14258, 28402, 7385 ], 765 | [ 56272, 52576, 19036, 3864, 29679, 28982, 63116, 46097, 52952, 24087, 9807, 38775, 52063, 37359, 27371, 64098 ], 766 | [ 42832, 23116, 56743, 48105, 59536, 61997, 50875, 53022, 53095, 35208, 48043, 2516, 4268, 6665, 40152, 28278 ] 767 | ], 768 | [ 769 | [ 18968, 38818, 33032, 33581, 52420, 33776, 60542, 38157, 23372, 64251, 32920, 26186, 3158, 45905, 1266, 10077 ], 770 | [ 47400, 1720, 11866, 50174, 14210, 41884, 7953, 42652, 25562, 39752, 57005, 42541, 28348, 55858, 25895, 55261 ], 771 | [ 20184, 426, 14275, 55361, 9014, 36892, 54317, 21931, 3632, 19042, 44851, 62146, 62605, 16010, 15513, 52732 ] 772 | ], 773 | [ 774 | [ 20356, 12599, 11901, 44476, 1927, 27434, 64567, 60255, 30030, 42549, 43998, 6410, 46906, 61361, 27282, 15419 ], 775 | [ 45608, 28052, 24633, 61100, 33255, 15130, 34678, 1372, 10900, 47429, 59776, 45346, 51975, 40512, 18800, 37485 ], 776 | [ 42312, 29149, 20322, 64207, 54182, 41762, 47810, 7881, 55922, 16555, 8873, 57904, 17885, 24584, 52454, 12487 ] 777 | ], 778 | [ 779 | [ 24642, 23381, 7652, 19569, 23453, 28831, 34214, 11418, 58016, 18482, 40654, 42282, 15111, 27847, 30598, 48350 ], 780 | [ 6372, 38522, 17278, 43351, 64597, 46670, 114, 58610, 21207, 54227, 34230, 29174, 17607, 32575, 46039, 63986 ], 781 | [ 53194, 19356, 43083, 41674, 6500, 11908, 18863, 16446, 26309, 57022, 44735, 24560, 58971, 18622, 7319, 10047 ] 782 | ], 783 | [ 784 | [ 51782, 21927, 31099, 51955, 25946, 60918, 5200, 58491, 10948, 40549, 63970, 42954, 9762, 52051, 23329, 12711 ], 785 | [ 55184, 9925, 48392, 21424, 22627, 12739, 30046, 5446, 42641, 12280, 2074, 34917, 38959, 61700, 28284, 30464 ], 786 | [ 55314, 24572, 30584, 20886, 47283, 59790, 11104, 50050, 33766, 53599, 58295, 10698, 18752, 40595, 49531, 44526 ] 787 | ], 788 | [ 789 | [ 8558, 2401, 20214, 37617, 25582, 29537, 51079, 3668, 19266, 18377, 47313, 37246, 14197, 10393, 56760, 53375 ], 790 | [ 36726, 48832, 54877, 41119, 40432, 52865, 31546, 22680, 55227, 51320, 4927, 29937, 57113, 39160, 23945, 57338 ], 791 | [ 15050, 56256, 11488, 5386, 23917, 5512, 39822, 21825, 14586, 40417, 37016, 32519, 52869, 17473, 58245, 5307 ] 792 | ], 793 | [ 794 | [ 10896, 14177, 23010, 3602, 47655, 17252, 49326, 26946, 42105, 10526, 5515, 63723, 54447, 26786, 46387, 42106 ], 795 | [ 6444, 56627, 43803, 492, 9136, 17144, 1579, 60040, 11581, 10752, 17784, 14413, 12013, 17454, 60745, 13259 ], 796 | [ 25008, 22624, 38598, 62937, 25506, 61215, 30483, 43651, 12358, 54985, 24565, 32918, 3951, 38687, 58254, 43249 ] 797 | ], 798 | [ 799 | [ 26784, 16872, 37263, 4600, 36883, 42798, 12459, 44527, 24992, 34816, 56303, 23502, 47964, 51298, 63830, 29440 ], 800 | [ 24620, 33473, 41773, 22568, 40484, 58271, 52336, 19977, 16154, 4369, 1813, 42044, 57409, 41829, 16650, 37229 ], 801 | [ 55136, 16549, 18430, 26236, 18861, 49554, 11007, 15169, 63910, 62016, 17602, 14770, 61440, 8427, 20974, 23067 ] 802 | ], 803 | [ 804 | [ 16414, 20993, 37974, 10331, 43658, 61010, 2776, 36101, 46541, 11946, 43576, 34743, 11255, 1275, 33995, 54333 ], 805 | [ 61216, 56921, 11172, 28307, 60462, 39490, 11732, 18164, 10072, 6187, 33679, 26941, 54430, 46654, 64965, 856 ], 806 | [ 8736, 920, 9802, 58823, 54695, 57112, 58013, 27221, 3214, 15584, 1703, 15514, 29292, 16203, 22220, 1114 ] 807 | ], 808 | [ 809 | [ 24206, 20320, 57851, 27248, 21791, 2383, 38324, 13875, 33222, 6145, 9478, 42023, 9396, 34468, 19459, 33452 ], 810 | [ 14436, 55262, 18528, 61447, 43124, 21759, 12517, 65347, 64375, 1825, 45823, 27399, 58852, 64560, 27673, 33187 ], 811 | [ 58496, 20491, 21786, 33413, 59395, 46274, 59249, 18265, 2809, 26471, 3226, 15789, 13417, 7732, 5267, 9038 ] 812 | ], 813 | [ 814 | [ 50432, 44076, 33747, 31874, 63273, 42245, 46592, 34335, 62549, 12246, 39180, 26064, 27547, 3398, 63555, 43030 ], 815 | [ 32542, 29876, 45438, 20361, 23064, 25771, 57094, 34629, 27360, 61638, 51470, 13604, 59960, 21552, 50356, 21586 ], 816 | [ 22354, 19379, 926, 9196, 27220, 59527, 225, 22840, 59906, 35900, 23413, 45646, 34923, 64781, 15477, 17994 ] 817 | ], 818 | [ 819 | [ 40918, 16348, 35265, 29764, 58407, 37057, 19199, 15527, 52718, 7668, 37925, 25471, 18454, 25788, 38398, 36036 ], 820 | [ 6520, 28277, 1539, 27230, 6767, 58252, 10451, 57586, 31417, 26947, 54246, 65216, 38782, 27819, 36475, 49683 ], 821 | [ 57718, 56247, 25828, 12748, 55356, 40486, 55050, 23382, 4223, 39537, 19733, 33288, 8455, 26163, 51418, 48394 ] 822 | ], 823 | [ 824 | [ 8282, 41307, 17573, 9361, 25346, 25618, 21944, 57078, 56108, 47175, 2758, 195, 37752, 62936, 6389, 2600 ], 825 | [ 7126, 27802, 18149, 28906, 36246, 10830, 8530, 19238, 48049, 31759, 39849, 47876, 2129, 39665, 30372, 6268 ], 826 | [ 29936, 64363, 29959, 15514, 1050, 63721, 46634, 22698, 51514, 24653, 42046, 27366, 11888, 25298, 10994, 26137 ] 827 | ], 828 | [ 829 | [ 38138, 16631, 55248, 43499, 13954, 5589, 13241, 49018, 62090, 43619, 62775, 44121, 48061, 13874, 29630, 14489 ], 830 | [ 45868, 31450, 15832, 51865, 62674, 39386, 20366, 47000, 44788, 40766, 13710, 42080, 30003, 1188, 45459, 19819 ], 831 | [ 24362, 29778, 19061, 13844, 33631, 52635, 24560, 16177, 32517, 36303, 1358, 48314, 36303, 2773, 59942, 49889 ] 832 | ], 833 | [ 834 | [ 40324, 52648, 31639, 47517, 42471, 65007, 17064, 50027, 25698, 42365, 51483, 53918, 47429, 1006, 49072, 59584 ], 835 | [ 47066, 11396, 54262, 27553, 27940, 22151, 22935, 25209, 44191, 62445, 35273, 11809, 45828, 12236, 54974, 51978 ], 836 | [ 31716, 62923, 5818, 2872, 96, 27769, 31003, 12376, 6956, 18064, 46854, 10656, 46401, 46378, 43105, 49596 ] 837 | ], 838 | [ 839 | [ 35874, 48747, 19964, 25200, 21102, 39287, 32392, 22395, 3450, 56574, 37490, 26865, 38685, 31959, 21389, 14096 ], 840 | [ 34880, 631, 10186, 58792, 57925, 18600, 43818, 51736, 11754, 21546, 14103, 2354, 57564, 46922, 33405, 64784 ], 841 | [ 16096, 5989, 19990, 59394, 62487, 3242, 40735, 20949, 45866, 50603, 24117, 24986, 61920, 30762, 35415, 45603 ] 842 | ], 843 | [ 844 | [ 25738, 5150, 22282, 56020, 38492, 411, 26444, 35775, 65072, 56072, 54541, 55208, 4361, 41605, 17875, 32507 ], 845 | [ 36058, 53442, 6316, 21224, 54326, 41761, 22493, 31010, 63671, 40305, 37318, 34416, 48982, 4513, 6539, 4065 ], 846 | [ 25088, 59564, 27489, 25633, 10165, 42474, 392, 7767, 53270, 40321, 38051, 54763, 39843, 61410, 60158, 17278 ] 847 | ], 848 | [ 849 | [ 12824, 11416, 37263, 4782, 36080, 62442, 47420, 58461, 60777, 18354, 48408, 5838, 23634, 57891, 9637, 23890 ], 850 | [ 45478, 24039, 48206, 48110, 33088, 33399, 43801, 50869, 44014, 27483, 37475, 13450, 52621, 20462, 58697, 65225 ], 851 | [ 13444, 51726, 41256, 20937, 56834, 60695, 39950, 50598, 55307, 53152, 20991, 4837, 10482, 57090, 49086, 2745 ] 852 | ], 853 | [ 854 | [ 22368, 39470, 7538, 28267, 13144, 35876, 14664, 36422, 27273, 20872, 25123, 12981, 13833, 22499, 39157, 28638 ], 855 | [ 11384, 18432, 63818, 34651, 21097, 23525, 45521, 9701, 57381, 49820, 17427, 47592, 28682, 48557, 20751, 59796 ], 856 | [ 7154, 12385, 2132, 30639, 17142, 31186, 14804, 59858, 33141, 25036, 34419, 57928, 3997, 20211, 45559, 15494 ] 857 | ], 858 | [ 859 | [ 56482, 43435, 11557, 24492, 13059, 59144, 65150, 13973, 23356, 54074, 33285, 38172, 55341, 32375, 55554, 28763 ], 860 | [ 65218, 3099, 52583, 57558, 36433, 57388, 34937, 53232, 19009, 9133, 18132, 38090, 50081, 10475, 64006, 5143 ], 861 | [ 22560, 19366, 5134, 54818, 49736, 39678, 39401, 21381, 18771, 3990, 63132, 52455, 40270, 8086, 41575, 52033 ] 862 | ], 863 | [ 864 | [ 43624, 2672, 64331, 49141, 50560, 2255, 56698, 62625, 21661, 21328, 30499, 62755, 42292, 53538, 38413, 50990 ], 865 | [ 47052, 35122, 53335, 30104, 14308, 43417, 47848, 47853, 51179, 5455, 1910, 19468, 40943, 64594, 23812, 4184 ], 866 | [ 5216, 36504, 1045, 4905, 51365, 8696, 40370, 43309, 56521, 29925, 15718, 50707, 22476, 53291, 29005, 4116 ] 867 | ], 868 | [ 869 | [ 50552, 15820, 42601, 6305, 48196, 30541, 50999, 60550, 51468, 17622, 9129, 47399, 13315, 2727, 51157, 46900 ], 870 | [ 32486, 26174, 63982, 10393, 44543, 55313, 26338, 52677, 3343, 27147, 31996, 43044, 43087, 32862, 35653, 49516 ], 871 | [ 39002, 29476, 36022, 18380, 57538, 11840, 13884, 34911, 33918, 32066, 57408, 9925, 16128, 17064, 4498, 39504 ] 872 | ], 873 | [ 874 | [ 7900, 63468, 30605, 60146, 24795, 8451, 65472, 26462, 29123, 8459, 16820, 26784, 50744, 41729, 20947, 48188 ], 875 | [ 63634, 19414, 17135, 45587, 50250, 29230, 51519, 48401, 628, 62734, 40211, 6787, 54555, 56916, 7876, 27670 ], 876 | [ 20716, 1136, 43322, 7805, 2530, 12528, 1233, 20151, 35769, 41678, 21415, 22262, 41348, 1929, 18198, 8798 ] 877 | ], 878 | [ 879 | [ 21012, 25572, 38058, 50150, 39976, 22214, 64172, 48566, 52450, 50806, 10023, 36514, 11128, 29316, 48400, 43598 ], 880 | [ 42986, 61219, 24836, 20608, 28361, 38565, 53713, 50120, 55064, 64813, 48422, 31691, 20882, 18958, 22373, 18872 ], 881 | [ 46612, 15584, 38674, 36657, 18371, 16457, 15715, 13043, 19871, 56380, 9638, 38287, 19170, 60592, 10589, 22147 ] 882 | ], 883 | [ 884 | [ 60266, 39676, 4250, 56270, 7226, 27196, 60061, 48198, 18757, 58284, 4673, 61564, 20471, 63481, 11519, 1161 ], 885 | [ 12592, 6740, 51782, 50918, 58059, 49603, 30091, 48769, 63726, 4515, 9500, 42915, 20789, 57941, 43557, 15074 ], 886 | [ 24280, 56801, 49544, 17589, 37611, 17655, 31192, 46392, 37532, 22386, 3527, 54442, 37680, 49081, 7076, 11260 ] 887 | ], 888 | [ 889 | [ 18612, 40720, 2442, 64118, 31472, 28848, 33783, 21120, 11140, 41510, 24004, 47695, 51377, 3392, 38776, 24772 ], 890 | [ 45524, 2156, 16583, 29496, 2911, 30451, 45661, 12197, 22359, 60679, 41480, 20332, 520, 3765, 17646, 8954 ], 891 | [ 18162, 44514, 453, 46371, 3288, 40270, 54028, 36887, 27826, 46531, 34930, 52848, 3711, 28321, 16198, 59424 ] 892 | ], 893 | [ 894 | [ 65532, 42558, 6404, 25942, 32561, 60299, 57613, 35143, 5783, 64083, 42881, 45738, 26559, 29419, 33120, 51213 ], 895 | [ 4990, 52531, 33960, 7766, 44903, 17259, 6060, 5807, 21184, 18841, 34651, 32371, 17333, 27610, 3869, 21805 ], 896 | [ 26444, 23452, 40782, 18762, 56756, 24819, 6568, 57524, 31984, 21964, 12080, 38680, 23338, 59483, 39288, 64485 ] 897 | ], 898 | [ 899 | [ 1592, 3064, 33452, 38852, 36907, 63456, 43944, 2156, 26240, 18064, 9975, 63533, 50417, 19051, 39042, 14222 ], 900 | [ 46222, 47342, 16340, 7090, 2784, 30013, 10292, 36514, 37572, 65147, 28256, 47213, 7473, 3426, 5240, 4418 ], 901 | [ 150, 22462, 40913, 26757, 38240, 12119, 52098, 55362, 36218, 29872, 7630, 54709, 44860, 9041, 59969, 50110 ] 902 | ], 903 | [ 904 | [ 43102, 1240, 29595, 51657, 3548, 49011, 2570, 65395, 7960, 20892, 50858, 33777, 64805, 41899, 54033, 9217 ], 905 | [ 58170, 14462, 24162, 47972, 21291, 949, 50280, 11250, 858, 39218, 16714, 57754, 44570, 18572, 9459, 58674 ], 906 | [ 19754, 32565, 48473, 58120, 27034, 12393, 48943, 64566, 9079, 16617, 10806, 1779, 16714, 31579, 16375, 29685 ] 907 | ], 908 | [ 909 | [ 56808, 15021, 60044, 46068, 58802, 62067, 35821, 60863, 3249, 64268, 61739, 18433, 9960, 36355, 19751, 29334 ], 910 | [ 2504, 24635, 9929, 31821, 40178, 41428, 9787, 1218, 17459, 15478, 47874, 16913, 8716, 50871, 44257, 3764 ], 911 | [ 56142, 33016, 57371, 31673, 3865, 16092, 60208, 11705, 25033, 1466, 55684, 18500, 53680, 61426, 52077, 55302 ] 912 | ], 913 | [ 914 | [ 36562, 64155, 36418, 36831, 34503, 42233, 28874, 40192, 48929, 22508, 12386, 35928, 13581, 24027, 27275, 23200 ], 915 | [ 22702, 3452, 56608, 9745, 35167, 38715, 63576, 58251, 13023, 64738, 26584, 42482, 7735, 60525, 10108, 63776 ], 916 | [ 21274, 7470, 48129, 36445, 7164, 19080, 22894, 5070, 52043, 52704, 46164, 65283, 36979, 17725, 41480, 49870 ] 917 | ], 918 | [ 919 | [ 59856, 64192, 17813, 38435, 11505, 9593, 52756, 5184, 11332, 20534, 25561, 46934, 15190, 42910, 35311, 3771 ], 920 | [ 32718, 2780, 33484, 2588, 29048, 29928, 397, 3888, 4519, 57164, 55096, 3495, 18680, 82, 31616, 3679 ], 921 | [ 35540, 29875, 39635, 38116, 13963, 2439, 28695, 35206, 47607, 52947, 36139, 16322, 50162, 51174, 17981, 5576 ] 922 | ], 923 | [ 924 | [ 33554, 38118, 33147, 37298, 3758, 51461, 26787, 55597, 9608, 10777, 24929, 38689, 41237, 42293, 51270, 36514 ], 925 | [ 776, 35597, 7002, 19351, 5874, 15665, 13087, 20640, 6202, 5054, 30369, 47809, 61723, 31493, 43059, 48002 ], 926 | [ 36758, 24317, 39085, 15562, 22269, 41029, 4657, 61090, 4400, 3500, 14250, 19282, 18055, 3478, 57995, 15581 ] 927 | ], 928 | [ 929 | [ 24362, 53852, 32188, 3703, 27946, 17698, 1668, 56772, 42694, 55238, 44361, 34669, 3729, 26426, 11293, 54813 ], 930 | [ 31486, 53108, 53972, 6629, 53470, 28891, 26915, 28134, 60652, 2508, 27187, 56439, 8811, 23926, 2450, 11692 ], 931 | [ 21292, 16187, 55084, 35224, 63715, 32450, 12503, 48893, 20878, 5927, 55873, 11108, 53077, 43777, 1013, 42199 ] 932 | ], 933 | [ 934 | [ 5392, 60183, 56275, 24082, 61441, 43921, 16684, 44238, 7149, 11595, 56252, 26135, 18057, 19373, 28446, 37899 ], 935 | [ 52734, 46783, 11639, 8776, 20248, 23971, 45130, 4720, 21566, 55511, 11022, 56359, 65363, 36042, 45913, 50254 ], 936 | [ 19626, 60178, 47355, 57636, 49334, 58293, 30255, 59815, 53920, 63097, 51233, 27398, 21832, 56809, 3390, 45216 ] 937 | ], 938 | [ 939 | [ 30196, 3937, 45670, 14625, 49278, 17900, 33320, 10657, 17458, 4917, 24926, 21598, 31947, 63215, 53057, 35487 ], 940 | [ 63946, 34010, 59075, 40842, 53796, 23958, 28473, 35928, 22209, 43923, 31157, 53819, 29608, 60694, 46330, 62255 ], 941 | [ 7204, 53984, 1994, 38097, 22523, 46236, 34374, 53531, 26102, 60060, 28002, 42329, 15798, 13913, 8633, 15949 ] 942 | ], 943 | [ 944 | [ 49448, 21729, 62067, 30399, 6516, 6937, 47588, 18088, 29541, 30707, 10651, 23412, 35270, 11372, 63612, 4019 ], 945 | [ 54756, 29929, 47197, 5669, 12469, 33980, 61637, 51885, 10258, 40380, 64212, 59010, 49123, 5538, 54316, 36916 ], 946 | [ 58932, 18819, 13721, 2738, 11689, 11592, 57770, 63962, 40437, 15674, 38, 34951, 22899, 60425, 3527, 6250 ] 947 | ], 948 | [ 949 | [ 45390, 47686, 12558, 26533, 32620, 55766, 34087, 30991, 51220, 12140, 23391, 13724, 14397, 30598, 21861, 64362 ], 950 | [ 45248, 26170, 7008, 61763, 22566, 2457, 11663, 5283, 34161, 60891, 9974, 25045, 29594, 3756, 44266, 36023 ], 951 | [ 64384, 265, 44330, 36446, 19188, 53374, 4863, 63681, 1356, 9717, 10853, 5230, 54315, 57014, 3615, 39223 ] 952 | ], 953 | [ 954 | [ 62558, 6117, 4110, 59295, 24387, 23655, 19372, 5349, 53825, 18623, 5365, 29104, 25030, 45761, 22640, 23250 ], 955 | [ 47642, 1814, 38034, 48604, 11088, 32713, 66, 25018, 63725, 60739, 63989, 24640, 45234, 52098, 30189, 58823 ], 956 | [ 31966, 60938, 33091, 20868, 27053, 55718, 63740, 34823, 63284, 50743, 54516, 55854, 22695, 61399, 20701, 42020 ] 957 | ], 958 | [ 959 | [ 46800, 12374, 44636, 30131, 42052, 20867, 366, 61285, 30277, 62950, 3490, 5844, 22587, 61999, 13871, 16152 ], 960 | [ 12266, 39904, 35870, 6341, 51881, 11220, 46645, 2709, 32415, 50427, 35055, 9083, 60483, 3375, 31247, 56572 ], 961 | [ 42820, 18058, 33837, 21708, 33906, 37356, 33052, 12435, 51500, 34165, 58234, 47393, 8400, 18244, 11109, 21469 ] 962 | ], 963 | [ 964 | [ 53882, 51162, 54852, 56186, 32038, 47133, 57057, 31389, 6013, 7294, 1079, 11661, 24188, 14360, 44830, 39879 ], 965 | [ 18464, 49, 63065, 51954, 9999, 25371, 32274, 7426, 49225, 31069, 61319, 31326, 7983, 21862, 2520, 57817 ], 966 | [ 49844, 26166, 17697, 20920, 32504, 22238, 62006, 39864, 4029, 19231, 25822, 52406, 64068, 21688, 2944, 39476 ] 967 | ], 968 | [ 969 | [ 33620, 6146, 37762, 1945, 42960, 55514, 35189, 62202, 41945, 27576, 13658, 53800, 22891, 63682, 57925, 1724 ], 970 | [ 49234, 34979, 38225, 38652, 30868, 3560, 16779, 49865, 18520, 4213, 52527, 51498, 28064, 56591, 39068, 48422 ], 971 | [ 19204, 36537, 26091, 57163, 26310, 49705, 39936, 6908, 58413, 33845, 26259, 9746, 44816, 58963, 25184, 64159 ] 972 | ], 973 | [ 974 | [ 54500, 27670, 38222, 23965, 37135, 21035, 23806, 58676, 58928, 15268, 62451, 2100, 19113, 46496, 45934, 35337 ], 975 | [ 55590, 41822, 60175, 62370, 15136, 54327, 40676, 1742, 21309, 44781, 60203, 9398, 4362, 4003, 32726, 15012 ], 976 | [ 49216, 27396, 45516, 65059, 11138, 62254, 39241, 12070, 1424, 12286, 32900, 42655, 36184, 46180, 57268, 48085 ] 977 | ], 978 | [ 979 | [ 40904, 64556, 45782, 11806, 31314, 34566, 34349, 11122, 36973, 18039, 46403, 63610, 32096, 24721, 40283, 34718 ], 980 | [ 34692, 1223, 14364, 14593, 51032, 41861, 25852, 25600, 41509, 20671, 51860, 12582, 2629, 53796, 10577, 38481 ], 981 | [ 20010, 13241, 47547, 50241, 57749, 35712, 58467, 53137, 2023, 20936, 59582, 11467, 45369, 38272, 52600, 6306 ] 982 | ], 983 | [ 984 | [ 19002, 39127, 22385, 32172, 14219, 25533, 34815, 18865, 8341, 53116, 22908, 37316, 61340, 56272, 2400, 50845 ], 985 | [ 30904, 37012, 17892, 63155, 63193, 29783, 63701, 20355, 51513, 35005, 22466, 7969, 12836, 63592, 8647, 35679 ], 986 | [ 53892, 12022, 7480, 19644, 62853, 38634, 36549, 54803, 57819, 11235, 5670, 38838, 11375, 24298, 21646, 36392 ] 987 | ], 988 | [ 989 | [ 26514, 22135, 65441, 50628, 61589, 15075, 51722, 19860, 32414, 47421, 46702, 52912, 12452, 39305, 44521, 22801 ], 990 | [ 18678, 41365, 24431, 42423, 12475, 7168, 35538, 9686, 6950, 3506, 27191, 62469, 16029, 10775, 53827, 1594 ], 991 | [ 15246, 33481, 39828, 62945, 35337, 30500, 30635, 1360, 55879, 13360, 20824, 55736, 45662, 36199, 6583, 9563 ] 992 | ], 993 | [ 994 | [ 39218, 53651, 29338, 43507, 48406, 19636, 63965, 45780, 39524, 1491, 41956, 7283, 32459, 26455, 1279, 4275 ], 995 | [ 19366, 44452, 28112, 9057, 44980, 43316, 26026, 55788, 58217, 52613, 59340, 39856, 49473, 63772, 64160, 37815 ], 996 | [ 37928, 15723, 4481, 65144, 52430, 48928, 28581, 6708, 61210, 3857, 47495, 50135, 55537, 48719, 63990, 50298 ] 997 | ], 998 | [ 999 | [ 64772, 15496, 53260, 21001, 20305, 6406, 50124, 57019, 50560, 48179, 62457, 13847, 50909, 59614, 23963, 7033 ], 1000 | [ 2642, 20926, 44375, 31056, 28936, 1947, 36757, 44795, 14411, 53178, 10835, 7814, 20672, 26460, 63003, 60551 ], 1001 | [ 40058, 56575, 52932, 32250, 32063, 22583, 14214, 33720, 23678, 55139, 43582, 35795, 42757, 14578, 41447, 16320 ] 1002 | ], 1003 | [ 1004 | [ 52184, 28869, 12689, 37648, 51213, 61392, 59490, 33391, 27107, 37181, 12671, 9953, 15413, 12106, 50347, 56986 ], 1005 | [ 7064, 58805, 49963, 10510, 53424, 58995, 25679, 48370, 58596, 39649, 13138, 48431, 972, 35566, 250, 53343 ], 1006 | [ 10824, 48855, 28126, 16856, 48365, 59965, 24610, 20018, 3481, 33183, 3194, 24247, 44732, 1676, 12658, 19476 ] 1007 | ], 1008 | [ 1009 | [ 56310, 8717, 46397, 29972, 61489, 57985, 14265, 43426, 4484, 1946, 21429, 30857, 12457, 41255, 20209, 11868 ], 1010 | [ 120, 64340, 56397, 6091, 16437, 47103, 65164, 58442, 39246, 43086, 21620, 23645, 41878, 21778, 12598, 56343 ], 1011 | [ 16524, 11918, 15444, 4725, 63923, 29368, 36484, 57543, 39736, 47890, 48063, 62680, 46120, 49597, 36733, 31272 ] 1012 | ], 1013 | [ 1014 | [ 9422, 31727, 62086, 30479, 23784, 34685, 11576, 45039, 36082, 11890, 46827, 19285, 61806, 35406, 39438, 19564 ], 1015 | [ 59922, 49798, 20433, 16055, 23720, 26253, 9601, 50669, 1356, 55481, 28886, 29630, 59522, 58785, 28958, 42709 ], 1016 | [ 56866, 39951, 43959, 20789, 15838, 33745, 22636, 5604, 52921, 868, 41198, 64540, 11645, 18242, 33665, 62775 ] 1017 | ], 1018 | [ 1019 | [ 32402, 10064, 55154, 54796, 38505, 13697, 38020, 35637, 43628, 34402, 7278, 62229, 45932, 26111, 41499, 22939 ], 1020 | [ 43490, 34917, 20676, 48122, 28219, 17503, 51713, 54423, 63197, 16333, 58687, 26519, 35883, 3942, 39733, 2037 ], 1021 | [ 50312, 60425, 5575, 41043, 48164, 56341, 62651, 45348, 50756, 41110, 3241, 56109, 59548, 29825, 45510, 26067 ] 1022 | ], 1023 | [ 1024 | [ 23006, 55335, 23259, 24081, 62338, 65336, 60700, 16382, 21604, 32575, 33233, 61421, 50533, 64971, 32993, 37325 ], 1025 | [ 56288, 10274, 65510, 40289, 5185, 15149, 8742, 61919, 33076, 17897, 4078, 35736, 16294, 63471, 6467, 17393 ], 1026 | [ 3192, 1405, 12736, 58011, 11229, 7264, 35686, 58730, 9040, 17195, 61786, 48853, 40942, 35412, 31256, 1037 ] 1027 | ], 1028 | [ 1029 | [ 62446, 41216, 56912, 46784, 58113, 15500, 12621, 45266, 52568, 4333, 31306, 33007, 6569, 62258, 13272, 1676 ], 1030 | [ 32184, 65359, 55344, 15122, 7225, 63750, 13388, 28981, 5813, 26516, 61151, 56849, 7588, 37768, 43317, 36914 ], 1031 | [ 56146, 11026, 50398, 22932, 48592, 5425, 32408, 9520, 61575, 60659, 28226, 20690, 64910, 6547, 56592, 7090 ] 1032 | ], 1033 | [ 1034 | [ 49268, 61617, 28579, 37644, 2729, 61298, 48732, 13669, 27303, 11342, 8639, 59427, 38703, 16071, 6088, 40620 ], 1035 | [ 61288, 58657, 52288, 56350, 48598, 31383, 30076, 31366, 23077, 31854, 20965, 6972, 33371, 1946, 41312, 33817 ], 1036 | [ 44866, 48304, 28300, 32283, 7762, 31944, 5571, 16543, 6702, 44953, 5323, 36863, 31834, 48345, 38482, 49481 ] 1037 | ], 1038 | [ 1039 | [ 34966, 43942, 58255, 18746, 65272, 59188, 45674, 16638, 29734, 19543, 54518, 52889, 31581, 26415, 23254, 20196 ], 1040 | [ 33372, 48563, 9557, 27382, 42131, 50690, 23677, 11185, 65371, 22267, 504, 36929, 46790, 20396, 43006, 28737 ], 1041 | [ 17030, 16888, 41629, 2330, 44604, 20033, 355, 30500, 60158, 40376, 54020, 14913, 1663, 11398, 36387, 50497 ] 1042 | ], 1043 | [ 1044 | [ 64200, 11419, 9172, 11367, 25482, 1900, 18470, 49743, 53763, 8275, 60712, 29029, 43335, 5654, 48146, 45864 ], 1045 | [ 49190, 64250, 13261, 51011, 30359, 37787, 29329, 50667, 26392, 4428, 62704, 29669, 23730, 49691, 16166, 43967 ], 1046 | [ 23966, 24384, 62251, 911, 56187, 62573, 52348, 18175, 26352, 29510, 17364, 21015, 27988, 56485, 64457, 53987 ] 1047 | ], 1048 | [ 1049 | [ 42784, 31888, 28611, 42263, 26528, 6002, 32490, 5219, 56963, 29121, 16685, 31282, 53747, 55339, 42538, 46662 ], 1050 | [ 52396, 31851, 47353, 2187, 53340, 36733, 60019, 55840, 51846, 50944, 29613, 59725, 43496, 8154, 1539, 9437 ], 1051 | [ 35626, 58547, 41751, 46368, 45467, 7928, 13945, 55261, 26420, 58412, 31064, 35723, 8429, 20812, 19275, 16926 ] 1052 | ], 1053 | [ 1054 | [ 45724, 2657, 10904, 55205, 43502, 26028, 2763, 57886, 56510, 22917, 39951, 22438, 42292, 60295, 7803, 15372 ], 1055 | [ 48412, 25476, 46349, 61600, 40523, 50835, 39476, 65332, 6515, 28207, 17748, 37420, 30257, 61748, 9906, 62696 ], 1056 | [ 55630, 41533, 57922, 27899, 28871, 28138, 37046, 64311, 15854, 21323, 50617, 41877, 41353, 46961, 35904, 14920 ] 1057 | ], 1058 | [ 1059 | [ 26378, 28048, 19468, 49356, 48614, 24231, 35925, 22733, 4507, 48034, 45387, 1091, 21820, 9197, 52734, 21425 ], 1060 | [ 64242, 62837, 44801, 29240, 64600, 10500, 31284, 41575, 20488, 53358, 29483, 47317, 12516, 44438, 57157, 56486 ], 1061 | [ 62304, 42453, 60550, 31698, 19119, 12998, 21626, 12565, 58221, 14638, 24260, 48034, 59464, 34238, 27108, 52454 ] 1062 | ], 1063 | [ 1064 | [ 33688, 14274, 16800, 18600, 24412, 51391, 9466, 23008, 48428, 33270, 34942, 51942, 55300, 24669, 29883, 2983 ], 1065 | [ 4878, 49041, 31351, 48179, 2025, 2617, 32221, 4102, 61082, 29511, 5403, 64346, 19917, 53968, 314, 54458 ], 1066 | [ 11872, 60232, 8640, 53242, 50458, 56536, 2586, 41573, 10676, 62267, 23048, 8155, 21596, 58316, 16782, 22338 ] 1067 | ], 1068 | [ 1069 | [ 54600, 19001, 8203, 17258, 1952, 24194, 31817, 18377, 31985, 47415, 61219, 18027, 35909, 30277, 5343, 28267 ], 1070 | [ 51522, 10698, 30284, 55863, 11658, 14972, 62040, 46083, 47541, 4890, 56877, 27487, 47773, 51538, 45917, 12531 ], 1071 | [ 10132, 51292, 12475, 7418, 41523, 20551, 34414, 31238, 46322, 56930, 15886, 56008, 62024, 4148, 58779, 57683 ] 1072 | ], 1073 | [ 1074 | [ 28492, 27646, 25100, 18647, 61297, 34225, 49273, 9453, 2225, 30355, 63374, 36408, 65259, 16512, 37039, 18788 ], 1075 | [ 34890, 49626, 17560, 21308, 56142, 47435, 24338, 2253, 61188, 59253, 15025, 2021, 51962, 31589, 4210, 32612 ], 1076 | [ 12728, 554, 15557, 42320, 38206, 63810, 38143, 14973, 59400, 5528, 48817, 56282, 5376, 3274, 34245, 8194 ] 1077 | ], 1078 | [ 1079 | [ 26592, 31721, 38619, 45148, 53298, 12633, 56464, 38802, 2476, 12600, 32271, 24022, 1744, 8118, 61674, 1883 ], 1080 | [ 40814, 57031, 16747, 13602, 26388, 15991, 33168, 55728, 19589, 39882, 1087, 54873, 6058, 35011, 14132, 50106 ], 1081 | [ 2994, 23561, 34625, 42515, 28372, 33122, 8183, 41413, 29854, 40901, 61435, 639, 48837, 50335, 14191, 3255 ] 1082 | ], 1083 | [ 1084 | [ 46668, 51305, 38273, 13204, 13458, 15593, 3460, 23101, 39991, 40994, 26026, 46286, 11714, 26470, 65282, 4212 ], 1085 | [ 45090, 59093, 61383, 42929, 55827, 46176, 49536, 32066, 28688, 1175, 55885, 35107, 3778, 52072, 57566, 10651 ], 1086 | [ 18924, 26298, 27893, 51058, 57660, 26826, 45243, 57459, 5401, 60745, 15683, 5142, 30042, 9247, 45301, 62157 ] 1087 | ], 1088 | [ 1089 | [ 65056, 10818, 11062, 13870, 23652, 52363, 27265, 2069, 10145, 22504, 30949, 62094, 6488, 16914, 50350, 48739 ], 1090 | [ 38520, 42908, 32970, 686, 45445, 1148, 49500, 9819, 47809, 42477, 28761, 35973, 59532, 44167, 10346, 13721 ], 1091 | [ 33768, 21140, 49714, 19739, 9014, 6966, 44675, 39896, 63671, 59879, 37833, 30298, 5491, 35731, 50790, 29233 ] 1092 | ], 1093 | [ 1094 | [ 19070, 44295, 29960, 20417, 45732, 28611, 15942, 52913, 43858, 2407, 18516, 27755, 7639, 30321, 65483, 45533 ], 1095 | [ 34870, 65018, 14064, 1903, 34932, 53328, 14485, 18506, 1838, 38756, 30225, 6657, 19751, 9614, 39834, 8732 ], 1096 | [ 9174, 459, 61827, 7698, 63763, 58894, 7839, 9401, 23109, 15082, 22041, 38550, 41152, 41531, 60582, 20597 ] 1097 | ], 1098 | [ 1099 | [ 22462, 3773, 44047, 30302, 29091, 11181, 17680, 60418, 54617, 43357, 52292, 19493, 15539, 26971, 21767, 27430 ], 1100 | [ 27440, 42964, 10577, 63971, 30074, 33322, 54831, 39197, 32811, 26581, 5406, 51869, 60413, 38828, 2357, 16255 ], 1101 | [ 17208, 26270, 32814, 48765, 2371, 6224, 2086, 11305, 27046, 7814, 6546, 53175, 40740, 53337, 46884, 65202 ] 1102 | ], 1103 | [ 1104 | [ 3362, 2612, 26552, 10582, 62240, 24345, 33762, 29506, 43091, 709, 13081, 25780, 50109, 35975, 30423, 42477 ], 1105 | [ 14644, 30263, 7437, 62732, 27994, 34883, 5529, 21172, 10767, 45235, 42559, 9907, 51123, 62789, 24466, 38811 ], 1106 | [ 29816, 64506, 44358, 26708, 20466, 1482, 2857, 12475, 13741, 825, 49419, 4416, 20562, 35486, 56024, 36413 ] 1107 | ], 1108 | [ 1109 | [ 47404, 42050, 15279, 3650, 4034, 60146, 44931, 5018, 45079, 35261, 58135, 52082, 30222, 16766, 1123, 29064 ], 1110 | [ 30818, 34360, 56663, 61087, 28756, 48997, 11505, 14816, 58125, 64905, 37774, 17231, 54748, 56923, 39161, 64485 ], 1111 | [ 3382, 56176, 43370, 21057, 31148, 28486, 64799, 44197, 30498, 3280, 27394, 31308, 52096, 49639, 27585, 24771 ] 1112 | ], 1113 | [ 1114 | [ 15316, 4453, 45791, 25586, 4756, 23663, 30622, 46785, 43992, 31320, 38173, 56691, 58343, 62063, 7427, 63195 ], 1115 | [ 1710, 11342, 6994, 23228, 42330, 10174, 60349, 5345, 26647, 1830, 53507, 2840, 61919, 23558, 7078, 9401 ], 1116 | [ 25304, 53432, 49780, 29573, 23422, 41435, 8477, 19426, 44134, 14118, 33147, 18669, 44064, 19425, 26820, 8312 ] 1117 | ], 1118 | [ 1119 | [ 26290, 4992, 18446, 34700, 33841, 24756, 50669, 46828, 1477, 24371, 32047, 46656, 7474, 29752, 61723, 48393 ], 1120 | [ 27092, 48258, 63629, 13876, 21877, 21784, 15448, 44921, 32806, 39851, 149, 52209, 49626, 63135, 41519, 17908 ], 1121 | [ 22584, 41832, 44500, 51065, 57235, 12321, 43427, 38834, 64816, 13310, 45964, 33133, 33275, 13353, 32762, 17842 ] 1122 | ], 1123 | [ 1124 | [ 56364, 51973, 15425, 9160, 11268, 39224, 26851, 63829, 13011, 49095, 54522, 23835, 56542, 16912, 17088, 62937 ], 1125 | [ 43802, 20021, 50311, 38757, 9319, 18340, 16301, 62350, 12747, 30487, 58053, 36823, 49468, 22221, 49480, 59756 ], 1126 | [ 49668, 39315, 22668, 5505, 54755, 34179, 35352, 26700, 17208, 50679, 54143, 41238, 51638, 34438, 14651, 26741 ] 1127 | ], 1128 | [ 1129 | [ 44564, 34911, 42363, 57232, 45584, 24203, 5924, 41923, 4052, 24978, 6426, 44378, 48502, 7384, 57565, 27922 ], 1130 | [ 48526, 36720, 41730, 19748, 26458, 56004, 8439, 33039, 31323, 9221, 33639, 10763, 59264, 29949, 40523, 3420 ], 1131 | [ 43076, 55885, 28633, 50646, 49021, 24160, 11995, 47496, 9817, 32671, 26020, 27169, 46545, 42837, 51901, 12817 ] 1132 | ], 1133 | [ 1134 | [ 54676, 8031, 64418, 57835, 13319, 8440, 33197, 1584, 41261, 38273, 53046, 2833, 49583, 39467, 21868, 5825 ], 1135 | [ 20278, 24305, 13684, 10259, 4567, 47311, 37854, 1459, 46520, 59763, 44523, 7705, 3977, 5515, 36053, 9187 ], 1136 | [ 43048, 38310, 50723, 3612, 6111, 25195, 35939, 12040, 41597, 16359, 50512, 37397, 47101, 8341, 53724, 10680 ] 1137 | ], 1138 | [ 1139 | [ 48674, 46723, 32843, 17259, 24100, 39407, 43163, 9724, 15245, 37891, 15915, 38375, 39798, 5580, 13019, 26342 ], 1140 | [ 61572, 4938, 54950, 37882, 1862, 32502, 27996, 63070, 59302, 61512, 59910, 37119, 52417, 6476, 15516, 21326 ], 1141 | [ 56194, 34816, 19935, 9528, 56486, 15275, 20548, 41449, 38482, 36475, 25336, 50389, 52675, 20236, 61311, 64077 ] 1142 | ], 1143 | [ 1144 | [ 20522, 2019, 22805, 35826, 62081, 54259, 39276, 28812, 60519, 61132, 22942, 22853, 18301, 26997, 9461, 23955 ], 1145 | [ 20330, 48667, 12395, 30159, 58182, 40315, 52732, 23768, 46111, 58056, 60452, 10266, 12805, 64855, 23100, 4248 ], 1146 | [ 59508, 21446, 58581, 43618, 7433, 60014, 61575, 16974, 16498, 32487, 48863, 29615, 1013, 13222, 24618, 39416 ] 1147 | ], 1148 | [ 1149 | [ 56208, 12535, 49880, 57754, 52947, 58658, 7808, 58585, 43807, 29120, 34330, 9998, 23449, 30458, 45209, 48136 ], 1150 | [ 37674, 34258, 27163, 42589, 53742, 13265, 27325, 29494, 14903, 46148, 43500, 56954, 16515, 57303, 47656, 12450 ], 1151 | [ 41898, 33230, 47001, 30887, 43137, 16625, 13801, 33175, 49844, 27096, 52473, 20388, 14460, 35168, 15079, 1494 ] 1152 | ], 1153 | [ 1154 | [ 60338, 17991, 15896, 39199, 52236, 11505, 59360, 57487, 32257, 47205, 53260, 51451, 37049, 13208, 15201, 10200 ], 1155 | [ 48800, 14962, 19280, 43892, 51201, 50579, 51172, 27656, 51892, 60398, 55182, 9806, 7622, 29154, 35247, 10912 ], 1156 | [ 42840, 43365, 65340, 27838, 57975, 5790, 63347, 38780, 48029, 25164, 39066, 54556, 43818, 37389, 7217, 22978 ] 1157 | ], 1158 | [ 1159 | [ 2968, 57060, 43227, 33530, 1652, 27986, 21000, 65418, 50530, 17514, 20751, 8076, 46702, 11462, 54145, 18038 ], 1160 | [ 10740, 11892, 42880, 36634, 48630, 36566, 49599, 10901, 41195, 17791, 20640, 1300, 22449, 29772, 58039, 32137 ], 1161 | [ 42096, 1948, 19810, 46779, 29628, 43763, 51782, 20463, 40381, 1213, 64615, 53652, 53853, 28948, 49762, 36033 ] 1162 | ], 1163 | [ 1164 | [ 60916, 44455, 2487, 18699, 48974, 58826, 58913, 45030, 26581, 52979, 31870, 31635, 4186, 3602, 1644, 62737 ], 1165 | [ 64706, 41862, 41787, 2622, 3067, 14071, 23473, 28890, 183, 55975, 36744, 43140, 7356, 47161, 62309, 57421 ], 1166 | [ 48156, 54716, 43339, 26443, 18101, 53206, 36400, 11420, 17663, 16165, 30992, 39784, 45835, 21308, 24809, 48077 ] 1167 | ], 1168 | [ 1169 | [ 38900, 59489, 53866, 18817, 54565, 6235, 13767, 20818, 18084, 6317, 51469, 6239, 15249, 49332, 22880, 59021 ], 1170 | [ 6896, 21369, 9326, 22446, 22745, 34057, 41544, 46547, 19938, 33297, 34534, 59708, 177, 49689, 63319, 64102 ], 1171 | [ 1368, 37565, 15740, 5497, 34253, 27136, 52579, 20503, 59422, 63811, 12109, 20891, 18433, 12391, 27971, 24382 ] 1172 | ], 1173 | [ 1174 | [ 58108, 905, 8919, 40853, 46282, 40589, 38765, 36351, 22817, 61191, 11523, 63582, 17988, 34279, 50560, 53385 ], 1175 | [ 55416, 34387, 34340, 21033, 64001, 49952, 38222, 44491, 13435, 12436, 31415, 38650, 24641, 52011, 47449, 53450 ], 1176 | [ 32256, 57142, 2905, 13971, 17574, 25853, 41890, 51930, 23790, 42503, 54365, 3763, 17338, 44515, 41481, 47554 ] 1177 | ], 1178 | [ 1179 | [ 23490, 30875, 6947, 34874, 24468, 39690, 11160, 21358, 62993, 50943, 17021, 716, 16512, 7693, 45051, 1889 ], 1180 | [ 59056, 33071, 41328, 14638, 31748, 11460, 17799, 23370, 38761, 28076, 4140, 31810, 5435, 24688, 4366, 14957 ], 1181 | [ 38658, 6985, 27547, 4009, 23822, 64189, 48871, 46012, 28058, 34017, 49733, 20538, 22634, 60490, 39857, 56684 ] 1182 | ], 1183 | [ 1184 | [ 56358, 15222, 63996, 16284, 2953, 21346, 33711, 11777, 27324, 966, 29965, 3370, 38118, 53076, 58803, 9622 ], 1185 | [ 33534, 29873, 35377, 28583, 48470, 62605, 38112, 22865, 11486, 62554, 27524, 34890, 49299, 39436, 42924, 26784 ], 1186 | [ 18206, 53203, 28989, 3594, 30717, 41499, 31337, 54582, 53366, 12795, 13291, 19413, 58135, 65315, 37801, 34126 ] 1187 | ], 1188 | [ 1189 | [ 3346, 51158, 18211, 44304, 2247, 34652, 37767, 6296, 54200, 44188, 15706, 30149, 18936, 5170, 20940, 42134 ], 1190 | [ 40018, 61533, 1079, 13552, 10857, 42480, 51812, 11230, 5467, 53776, 1707, 50397, 46768, 49499, 57111, 33423 ], 1191 | [ 64986, 34791, 58199, 19309, 40719, 59185, 20120, 50841, 37132, 37892, 13338, 36662, 59652, 47500, 20036, 28716 ] 1192 | ], 1193 | [ 1194 | [ 22954, 48957, 12636, 11332, 37938, 24580, 3972, 173, 36790, 7625, 23756, 18850, 20494, 2193, 17306, 34133 ], 1195 | [ 37706, 57173, 4763, 60441, 34195, 40514, 3942, 44957, 44953, 35110, 25020, 65533, 19406, 13300, 51605, 55349 ], 1196 | [ 47718, 36816, 61481, 40699, 38690, 63253, 47976, 64598, 34874, 17964, 52183, 6979, 50776, 19666, 11286, 9158 ] 1197 | ], 1198 | [ 1199 | [ 46084, 29358, 53337, 43178, 35606, 4451, 17331, 55812, 43020, 26807, 20189, 59220, 23983, 1373, 13942, 36332 ], 1200 | [ 31834, 12930, 21816, 29783, 32091, 50371, 1787, 61481, 21779, 50772, 56487, 40780, 18840, 43040, 36291, 51450 ], 1201 | [ 42646, 16294, 47289, 18198, 52209, 42766, 28915, 24998, 42175, 58237, 20664, 62750, 33075, 20741, 30138, 56473 ] 1202 | ], 1203 | [ 1204 | [ 18292, 59805, 54565, 18403, 57208, 42885, 24197, 19578, 31071, 62234, 45730, 41000, 56732, 16432, 14548, 43197 ], 1205 | [ 48124, 30933, 7533, 39380, 43700, 17476, 7034, 65240, 39348, 52409, 50407, 15059, 33651, 23617, 55104, 21805 ], 1206 | [ 56292, 35238, 24411, 18371, 52398, 10490, 31028, 46526, 48921, 63236, 10300, 34795, 53084, 4221, 13473, 27842 ] 1207 | ], 1208 | [ 1209 | [ 57638, 24443, 56549, 32063, 42913, 17446, 8994, 36800, 61821, 4533, 31559, 54297, 28533, 42270, 65063, 3784 ], 1210 | [ 4544, 43837, 11503, 45549, 31805, 33074, 65131, 7416, 31548, 25024, 47327, 30325, 43647, 37848, 15791, 48616 ], 1211 | [ 16662, 3669, 37290, 32879, 15831, 4552, 42805, 8390, 22308, 35530, 18577, 54116, 3271, 38669, 14279, 38062 ] 1212 | ], 1213 | [ 1214 | [ 35282, 30346, 56172, 2637, 29275, 22941, 25454, 6243, 58236, 58106, 41435, 62605, 55205, 45590, 46032, 47423 ], 1215 | [ 24782, 27657, 30453, 9239, 14976, 51094, 11924, 27639, 46575, 38405, 54255, 20859, 1498, 26436, 1980, 20001 ], 1216 | [ 8142, 5832, 53662, 49060, 47205, 23460, 14581, 54466, 16159, 7557, 29261, 3044, 37361, 13977, 31472, 53603 ] 1217 | ], 1218 | [ 1219 | [ 29654, 8559, 57017, 32034, 38891, 4145, 60067, 50913, 60215, 17295, 56920, 25665, 15886, 39175, 61757, 40671 ], 1220 | [ 44536, 49731, 1559, 58594, 34473, 6349, 30935, 29896, 53862, 6153, 61861, 42698, 37474, 52161, 60160, 11842 ], 1221 | [ 12672, 920, 51599, 3932, 52712, 42451, 31752, 9967, 59339, 43745, 22828, 41506, 1176, 6877, 32884, 380 ] 1222 | ], 1223 | [ 1224 | [ 13416, 19492, 14543, 27877, 266, 8748, 9227, 44344, 32292, 61465, 63852, 62513, 4405, 18166, 14899, 55587 ], 1225 | [ 2848, 2209, 44313, 21561, 16106, 2339, 58038, 48338, 64589, 61596, 5651, 16162, 53945, 34321, 21904, 15566 ], 1226 | [ 21938, 46122, 4544, 50970, 16139, 26657, 43367, 50501, 19802, 9010, 31953, 15260, 44346, 31204, 13440, 20808 ] 1227 | ], 1228 | [ 1229 | [ 59930, 64959, 15434, 60558, 32297, 30583, 39186, 34007, 22009, 61823, 46219, 38354, 36259, 35568, 60327, 19330 ], 1230 | [ 10284, 15092, 57078, 57354, 17473, 63523, 831, 40804, 21955, 50764, 38081, 9244, 24413, 17810, 22422, 5175 ], 1231 | [ 62124, 34030, 9317, 60032, 6930, 30364, 38783, 37742, 1868, 48106, 35144, 49337, 14232, 24194, 4708, 20231 ] 1232 | ], 1233 | [ 1234 | [ 52654, 26256, 30393, 23456, 34213, 9077, 35321, 33445, 28594, 60337, 27076, 6255, 60762, 15764, 55709, 39468 ], 1235 | [ 45090, 29670, 46854, 57399, 45304, 59426, 60882, 61195, 50918, 39258, 6814, 1183, 58519, 2893, 47806, 49220 ], 1236 | [ 49850, 58802, 41633, 52431, 49719, 42218, 15379, 29292, 35311, 41157, 28745, 59096, 64905, 43884, 27024, 35759 ] 1237 | ], 1238 | [ 1239 | [ 22190, 37270, 8031, 21691, 34927, 2697, 54962, 16961, 33386, 5358, 30378, 25904, 26383, 42553, 31825, 42057 ], 1240 | [ 41762, 53624, 3857, 54133, 18032, 8411, 52049, 32914, 4180, 13940, 43398, 41943, 30728, 497, 63529, 48000 ], 1241 | [ 23596, 13344, 48207, 62529, 1687, 52500, 6989, 7582, 19675, 37709, 20907, 23527, 10583, 50048, 60779, 19369 ] 1242 | ], 1243 | [ 1244 | [ 38412, 13567, 4908, 52001, 35082, 48773, 28851, 7838, 38878, 38575, 63280, 35144, 36160, 61703, 61477, 55344 ], 1245 | [ 54302, 22419, 6114, 40423, 15531, 853, 12162, 56107, 7766, 11824, 18212, 58990, 13311, 11300, 20853, 26580 ], 1246 | [ 18424, 32658, 13284, 64273, 27151, 2919, 61935, 46954, 45308, 52807, 29784, 4411, 4360, 64745, 6044, 64717 ] 1247 | ], 1248 | [ 1249 | [ 1560, 41433, 57693, 53748, 15390, 50842, 11049, 4883, 49272, 5848, 11543, 43422, 31177, 43863, 37156, 39314 ], 1250 | [ 64342, 40097, 30118, 32073, 29536, 16960, 5060, 38154, 7801, 33540, 39316, 7835, 59404, 21535, 52207, 53952 ], 1251 | [ 63472, 53303, 37277, 32113, 43469, 25775, 43363, 65509, 35819, 30694, 20673, 38215, 43809, 50726, 37695, 25771 ] 1252 | ], 1253 | [ 1254 | [ 35092, 41331, 34615, 31338, 7631, 11993, 26394, 29933, 61632, 13212, 57309, 48904, 53627, 55910, 51686, 2121 ], 1255 | [ 56790, 21854, 2736, 8670, 23116, 54318, 14976, 37463, 61818, 11460, 44864, 51503, 914, 23269, 56508, 35316 ], 1256 | [ 40676, 28131, 41158, 22989, 56374, 49772, 19103, 54847, 13683, 10108, 23091, 20820, 31928, 57630, 31623, 64886 ] 1257 | ], 1258 | [ 1259 | [ 8404, 31858, 37997, 21087, 21572, 61923, 45234, 17974, 44559, 59538, 40304, 31086, 44465, 43319, 49247, 33758 ], 1260 | [ 21762, 50743, 10012, 27932, 20244, 42186, 35012, 17957, 64569, 58714, 10750, 26897, 29429, 19844, 40824, 38292 ], 1261 | [ 54, 44973, 58640, 48521, 34318, 29625, 2240, 19743, 44957, 11520, 28299, 1905, 38676, 36741, 34294, 61654 ] 1262 | ], 1263 | [ 1264 | [ 54252, 22527, 45067, 56498, 20472, 4834, 14037, 27582, 17161, 41837, 36941, 47149, 59508, 17777, 35609, 27148 ], 1265 | [ 17080, 796, 11437, 36355, 55212, 10648, 50707, 10498, 54453, 53223, 35788, 60547, 50997, 29852, 44471, 24453 ], 1266 | [ 62506, 15199, 43592, 64453, 32714, 36427, 1766, 33498, 65074, 53121, 32712, 2000, 28650, 59118, 1492, 54088 ] 1267 | ], 1268 | [ 1269 | [ 33912, 22241, 26949, 23144, 47183, 10673, 13311, 12547, 52151, 9622, 59110, 38977, 47898, 22019, 45810, 13457 ], 1270 | [ 27692, 26359, 25252, 14699, 47795, 54117, 63516, 43537, 56510, 22912, 62855, 58747, 46051, 14654, 48858, 2440 ], 1271 | [ 27688, 44348, 32458, 51073, 17391, 39258, 8677, 9200, 17303, 48694, 20745, 40981, 59634, 63179, 57156, 44010 ] 1272 | ], 1273 | [ 1274 | [ 34314, 53070, 14327, 9488, 4751, 6651, 57595, 4333, 58056, 30197, 13233, 38592, 64269, 27669, 1805, 34143 ], 1275 | [ 15958, 38727, 44844, 31826, 33656, 7085, 33337, 559, 18287, 10971, 57776, 39313, 47189, 15001, 17568, 53521 ], 1276 | [ 58542, 36850, 50104, 24495, 12543, 56850, 20464, 34142, 10352, 18505, 675, 29411, 57788, 21467, 49566, 4691 ] 1277 | ], 1278 | [ 1279 | [ 57196, 31994, 45955, 61163, 20795, 10593, 14615, 57760, 22116, 27515, 57451, 56749, 55249, 5273, 16407, 4597 ], 1280 | [ 19310, 42132, 43036, 36029, 26766, 2478, 59760, 61011, 33442, 60235, 26881, 64812, 5762, 57381, 33407, 16779 ], 1281 | [ 22462, 14292, 36457, 27576, 13510, 11771, 8181, 61157, 63411, 17637, 44111, 5076, 56109, 41280, 14207, 33235 ] 1282 | ] 1283 | ]; 1284 | -------------------------------------------------------------------------------- /assembly/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../node_modules/assemblyscript/std/assembly.json", 3 | "include": [ 4 | "./**/*.ts" 5 | ] 6 | } -------------------------------------------------------------------------------- /logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jedisct1/wasm-crypto/97e711337811b9f50668f62c482650f02b7bddd7/logo.png -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "wasm-crypto", 3 | "version": "0.0.13", 4 | "scripts": { 5 | "asbuild:untouched": "asc assembly/crypto.ts assembly/precomp.ts -b build/untouched.wasm", 6 | "asbuild:small": "asc assembly/crypto.ts assembly/precomp.ts -b build/small.wasm -t build/small.wat --sourceMap -O3z", 7 | "asbuild:optimized": "asc assembly/crypto.ts assembly/precomp.ts -b build/optimized.wasm -t build/optimized.wat --sourceMap -O3", 8 | "asbuild": "npm run asbuild:optimized", 9 | "test": "asp --verbose" 10 | }, 11 | "types": "assembly/crypto.ts", 12 | "ascMain": "assembly/crypto.ts", 13 | "devDependencies": { 14 | "@as-pect/cli": "^6.2.4", 15 | "assemblyscript": "^0.19.22" 16 | }, 17 | "author": "Frank Denis ", 18 | "bugs": { 19 | "url": "https://github.com/jedisct1/wasm-crypto/issues" 20 | }, 21 | "description": "A WebAssembly (via AssemblyScript) set of cryptographic primitives for building authentication and key exchange protocols.", 22 | "homepage": "https://github.com/jedisct1/wasm-crypto", 23 | "keywords": [ 24 | "webassembly", 25 | "assemblyscript", 26 | "crypto", 27 | "cryptography" 28 | ], 29 | "license": "MIT", 30 | "repository": { 31 | "type": "git", 32 | "url": "https://github.com/jedisct1/wasm-crypto.git" 33 | } 34 | } -------------------------------------------------------------------------------- /tsfmt.json: -------------------------------------------------------------------------------- 1 | { 2 | "baseIndentSize": 0, 3 | "indentSize": 4, 4 | "tabSize": 4, 5 | "indentStyle": 2, 6 | "newLineCharacter": "\n", 7 | "convertTabsToSpaces": true, 8 | "insertSpaceAfterCommaDelimiter": true, 9 | "insertSpaceAfterSemicolonInForStatements": true, 10 | "insertSpaceBeforeAndAfterBinaryOperators": true, 11 | "insertSpaceAfterConstructor": false, 12 | "insertSpaceAfterKeywordsInControlFlowStatements": true, 13 | "insertSpaceAfterFunctionKeywordForAnonymousFunctions": false, 14 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis": false, 15 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": false, 16 | "insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces": true, 17 | "insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces": false, 18 | "insertSpaceAfterOpeningAndBeforeClosingJsxExpressionBraces": false, 19 | "insertSpaceAfterTypeAssertion": false, 20 | "insertSpaceBeforeFunctionParenthesis": false, 21 | "insertSpaceBeforeTypeAnnotation": false, 22 | "placeOpenBraceOnNewLineForFunctions": false, 23 | "placeOpenBraceOnNewLineForControlBlocks": false 24 | } 25 | -------------------------------------------------------------------------------- /tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "defaultSeverity": "error", 3 | "extends": [ 4 | "tslint:recommended" 5 | ], 6 | "jsRules": {}, 7 | "rules": { 8 | "no-bitwise": false, 9 | "variable-name": false, 10 | "one-variable-per-declaration": false, 11 | "prefer-const": false, 12 | "max-classes-per-file": false, 13 | "indent": [true, 4], 14 | "whitespace": [true, 15 | "check-branch", 16 | "check-operator", 17 | "check-separator", 18 | "check-typecast" 19 | ] 20 | }, 21 | "rulesDirectory": [] 22 | } --------------------------------------------------------------------------------