├── .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 | [](https://www.npmjs.com/package/wasm-crypto)
2 | [](https://github.com/jedisct1/wasm-crypto/actions)
3 |
4 | # 
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 | }
--------------------------------------------------------------------------------