diff options
author | Florian Dold <florian.dold@gmail.com> | 2019-11-27 17:59:51 +0100 |
---|---|---|
committer | Florian Dold <florian.dold@gmail.com> | 2019-11-27 17:59:57 +0100 |
commit | c3ca556affe2f514aeb7fd052fe6d626d9319e99 (patch) | |
tree | ffd85c479b3201c6372d380bb0a2819af503539c /src/crypto | |
parent | d42b9e3df8d1bf0e2d0805a04663a79b22a2545d (diff) |
JS-only crypto (only primitives so far)
Diffstat (limited to 'src/crypto')
-rw-r--r-- | src/crypto/cryptoImplementation.ts | 2 | ||||
-rw-r--r-- | src/crypto/emscInterface-test.ts | 31 | ||||
-rw-r--r-- | src/crypto/kdf.ts | 58 | ||||
-rw-r--r-- | src/crypto/nacl-fast.ts | 1956 | ||||
-rw-r--r-- | src/crypto/nativeCrypto-test.ts | 85 | ||||
-rw-r--r-- | src/crypto/nativeCrypto.ts | 140 | ||||
-rw-r--r-- | src/crypto/talerCrypto-test.ts | 161 | ||||
-rw-r--r-- | src/crypto/talerCrypto.ts | 277 |
8 files changed, 1760 insertions, 950 deletions
diff --git a/src/crypto/cryptoImplementation.ts b/src/crypto/cryptoImplementation.ts index 7dd019c18..38c63ceee 100644 --- a/src/crypto/cryptoImplementation.ts +++ b/src/crypto/cryptoImplementation.ts @@ -45,7 +45,7 @@ import * as native from "./emscInterface"; import { AmountJson } from "../amounts"; import * as Amounts from "../amounts"; import * as timer from "../timer"; -import { getRandomBytes, encodeCrock } from "./nativeCrypto"; +import { getRandomBytes, encodeCrock } from "./talerCrypto"; export class CryptoImplementation { static enableTracing: boolean = false; diff --git a/src/crypto/emscInterface-test.ts b/src/crypto/emscInterface-test.ts index 422ee45e2..30b9c2b51 100644 --- a/src/crypto/emscInterface-test.ts +++ b/src/crypto/emscInterface-test.ts @@ -20,8 +20,7 @@ import test from "ava"; import { NodeEmscriptenLoader } from "./nodeEmscriptenLoader"; import * as native from "./emscInterface"; -import nacl = require("./nacl-fast"); -import { encodeCrock, decodeCrock } from "./nativeCrypto"; +import { encodeCrock, decodeCrock } from "./talerCrypto"; import { timestampCheck } from "../helpers"; @@ -37,12 +36,7 @@ test("string hashing", async (t) => { const te = new TextEncoder(); - const x2 = te.encode("hello taler\0") - - const hc2 = encodeCrock(nacl.hash(x2)); - - console.log(`# hc2 ${hc}`); - t.true(h === hc2); + const x2 = te.encode("hello taler\0"); t.pass(); }); @@ -68,29 +62,8 @@ test("signing", async (t) => { console.timeEnd("a"); t.true(native.eddsaVerify(native.SignaturePurpose.TEST, purpose, sig, pub)); - console.log("priv size", decodeCrock(privCrock).byteLength); - - const pair = nacl.sign_keyPair_fromSeed(new Uint8Array(decodeCrock(privCrock))); - - console.log("emsc priv", privCrock); - console.log("emsc pub", pubCrock); - - console.log("nacl priv", encodeCrock(pair.secretKey)); - console.log("nacl pub", encodeCrock(pair.publicKey)); - const d2 = new Uint8Array(decodeCrock(purposeDataCrock)); - const d3 = nacl.hash(d2); - - console.time("b"); - for (let i = 0; i < 5000; i++) { - const s2 = nacl.sign_detached(d3, pair.secretKey); - } - console.timeEnd("b"); - - const s2 = nacl.sign_detached(d3, pair.secretKey); - console.log("sig1:", sig.toCrock()); - console.log("sig2:", encodeCrock(s2)); t.pass(); }); diff --git a/src/crypto/kdf.ts b/src/crypto/kdf.ts index 3c44be3bc..082963074 100644 --- a/src/crypto/kdf.ts +++ b/src/crypto/kdf.ts @@ -17,8 +17,6 @@ import nacl = require("./nacl-fast"); import { sha256 } from "./sha256"; -let createHmac: any; - export function sha512(data: Uint8Array): Uint8Array { return nacl.hash(data); } @@ -32,7 +30,6 @@ export function hmac( if (key.byteLength > blockSize) { key = digest(key); } - console.log("message", message); if (key.byteLength < blockSize) { const k = key; key = new Uint8Array(blockSize); @@ -62,39 +59,34 @@ export function hmacSha256(key: Uint8Array, message: Uint8Array) { return hmac(sha256, 64, key, message); } -/* -function expand(prfAlgo: string, prk: Uint8Array, length: number, info: Uint8Array) { - let hashLength; - if (prfAlgo == "sha512") { - hashLength = 64; - } else if (prfAlgo == "sha256") { - hashLength = 32; - } else { - throw Error("unsupported hash"); - } - info = info || Buffer.alloc(0); - var N = Math.ceil(length / hashLength); - var memo: Buffer[] = []; - - for (var i = 0; i < N; i++) { - memo[i] = createHmac(prfAlgo, prk) - .update(memo[i - 1] || Buffer.alloc(0)) - .update(info) - .update(Buffer.alloc(1, i + 1)) - .digest(); - } - return Buffer.concat(memo, length); -} -*/ - -export function kdf(ikm: Uint8Array, salt: Uint8Array, info: Uint8Array) { +export function kdf( + outputLength: number, + ikm: Uint8Array, + salt: Uint8Array, + info: Uint8Array, +): Uint8Array { // extract const prk = hmacSha512(salt, ikm); // expand + const N = Math.ceil(outputLength / 32); + const output = new Uint8Array(N * 32); + for (let i = 0; i < N; i++) { + let buf; + if (i == 0) { + buf = new Uint8Array(info.byteLength + 1); + buf.set(info, 0); + } else { + buf = new Uint8Array(info.byteLength + 1 + 32); + for (let j = 0; j < 32; j++) { + buf[j] = output[(i - 1) * 32 + j]; + } + buf.set(info, 32); + } + buf[buf.length - 1] = i + 1; + const chunk = hmacSha256(prk, buf); + output.set(chunk, i * 32); + } - var N = Math.ceil(length / 256); - - //return expand(prfAlgo, prk, length, info); - return prk; + return output; } diff --git a/src/crypto/nacl-fast.ts b/src/crypto/nacl-fast.ts index 6757e7c51..418662e8d 100644 --- a/src/crypto/nacl-fast.ts +++ b/src/crypto/nacl-fast.ts @@ -13,45 +13,142 @@ const gf = function(init: number[] = []) { // Pluggable, initialized in high-level API below. let randombytes = function(x: Uint8Array, n: number): void { - throw new Error('no PRNG'); + throw new Error("no PRNG"); }; const _0 = new Uint8Array(16); -const _9 = new Uint8Array(32); _9[0] = 9; +const _9 = new Uint8Array(32); +_9[0] = 9; // prettier-ignore const gf0 = gf(); const gf1 = gf([1]); const _121665 = gf([0xdb41, 1]); -const D = gf([0x78a3, 0x1359, 0x4dca, 0x75eb, 0xd8ab, 0x4141, 0x0a4d, 0x0070, 0xe898, 0x7779, 0x4079, 0x8cc7, 0xfe73, 0x2b6f, 0x6cee, 0x5203]); -const D2 = gf([0xf159, 0x26b2, 0x9b94, 0xebd6, 0xb156, 0x8283, 0x149a, 0x00e0, 0xd130, 0xeef3, 0x80f2, 0x198e, 0xfce7, 0x56df, 0xd9dc, 0x2406]); -const X = gf([0xd51a, 0x8f25, 0x2d60, 0xc956, 0xa7b2, 0x9525, 0xc760, 0x692c, 0xdc5c, 0xfdd6, 0xe231, 0xc0a4, 0x53fe, 0xcd6e, 0x36d3, 0x2169]); -const Y = gf([0x6658, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666]); -const I = gf([0xa0b0, 0x4a0e, 0x1b27, 0xc4ee, 0xe478, 0xad2f, 0x1806, 0x2f43, 0xd7a7, 0x3dfb, 0x0099, 0x2b4d, 0xdf0b, 0x4fc1, 0x2480, 0x2b83]); +const D = gf([ + 0x78a3, + 0x1359, + 0x4dca, + 0x75eb, + 0xd8ab, + 0x4141, + 0x0a4d, + 0x0070, + 0xe898, + 0x7779, + 0x4079, + 0x8cc7, + 0xfe73, + 0x2b6f, + 0x6cee, + 0x5203, +]); +const D2 = gf([ + 0xf159, + 0x26b2, + 0x9b94, + 0xebd6, + 0xb156, + 0x8283, + 0x149a, + 0x00e0, + 0xd130, + 0xeef3, + 0x80f2, + 0x198e, + 0xfce7, + 0x56df, + 0xd9dc, + 0x2406, +]); +const X = gf([ + 0xd51a, + 0x8f25, + 0x2d60, + 0xc956, + 0xa7b2, + 0x9525, + 0xc760, + 0x692c, + 0xdc5c, + 0xfdd6, + 0xe231, + 0xc0a4, + 0x53fe, + 0xcd6e, + 0x36d3, + 0x2169, +]); +const Y = gf([ + 0x6658, + 0x6666, + 0x6666, + 0x6666, + 0x6666, + 0x6666, + 0x6666, + 0x6666, + 0x6666, + 0x6666, + 0x6666, + 0x6666, + 0x6666, + 0x6666, + 0x6666, + 0x6666, +]); +const I = gf([ + 0xa0b0, + 0x4a0e, + 0x1b27, + 0xc4ee, + 0xe478, + 0xad2f, + 0x1806, + 0x2f43, + 0xd7a7, + 0x3dfb, + 0x0099, + 0x2b4d, + 0xdf0b, + 0x4fc1, + 0x2480, + 0x2b83, +]); function ts64(x: Uint8Array, i: number, h: number, l: number) { - x[i] = (h >> 24) & 0xff; - x[i+1] = (h >> 16) & 0xff; - x[i+2] = (h >> 8) & 0xff; - x[i+3] = h & 0xff; - x[i+4] = (l >> 24) & 0xff; - x[i+5] = (l >> 16) & 0xff; - x[i+6] = (l >> 8) & 0xff; - x[i+7] = l & 0xff; + x[i] = (h >> 24) & 0xff; + x[i + 1] = (h >> 16) & 0xff; + x[i + 2] = (h >> 8) & 0xff; + x[i + 3] = h & 0xff; + x[i + 4] = (l >> 24) & 0xff; + x[i + 5] = (l >> 16) & 0xff; + x[i + 6] = (l >> 8) & 0xff; + x[i + 7] = l & 0xff; } function vn(x: Uint8Array, xi: number, y: Uint8Array, yi: number, n: number) { - var i,d = 0; - for (i = 0; i < n; i++) d |= x[xi+i]^y[yi+i]; + var i, + d = 0; + for (i = 0; i < n; i++) d |= x[xi + i] ^ y[yi + i]; return (1 & ((d - 1) >>> 8)) - 1; } -function crypto_verify_16(x: Uint8Array, xi: number, y: Uint8Array, yi: number) { - return vn(x,xi,y,yi,16); +function crypto_verify_16( + x: Uint8Array, + xi: number, + y: Uint8Array, + yi: number, +) { + return vn(x, xi, y, yi, 16); } -function crypto_verify_32(x: Uint8Array, xi: number, y: Uint8Array, yi: number) { - return vn(x,xi,y,yi,32); +function crypto_verify_32( + x: Uint8Array, + xi: number, + y: Uint8Array, + yi: number, +) { + return vn(x, xi, y, yi, 32); } // prettier-ignore @@ -248,165 +345,284 @@ function core_salsa20(o: Uint8Array, p: Uint8Array, k: Uint8Array, c: Uint8Array o[63] = x15 >>> 24 & 0xff; } -function core_hsalsa20(o: Uint8Array,p: Uint8Array,k: Uint8Array,c: Uint8Array) { - var j0 = c[ 0] & 0xff | (c[ 1] & 0xff)<<8 | (c[ 2] & 0xff)<<16 | (c[ 3] & 0xff)<<24, - j1 = k[ 0] & 0xff | (k[ 1] & 0xff)<<8 | (k[ 2] & 0xff)<<16 | (k[ 3] & 0xff)<<24, - j2 = k[ 4] & 0xff | (k[ 5] & 0xff)<<8 | (k[ 6] & 0xff)<<16 | (k[ 7] & 0xff)<<24, - j3 = k[ 8] & 0xff | (k[ 9] & 0xff)<<8 | (k[10] & 0xff)<<16 | (k[11] & 0xff)<<24, - j4 = k[12] & 0xff | (k[13] & 0xff)<<8 | (k[14] & 0xff)<<16 | (k[15] & 0xff)<<24, - j5 = c[ 4] & 0xff | (c[ 5] & 0xff)<<8 | (c[ 6] & 0xff)<<16 | (c[ 7] & 0xff)<<24, - j6 = p[ 0] & 0xff | (p[ 1] & 0xff)<<8 | (p[ 2] & 0xff)<<16 | (p[ 3] & 0xff)<<24, - j7 = p[ 4] & 0xff | (p[ 5] & 0xff)<<8 | (p[ 6] & 0xff)<<16 | (p[ 7] & 0xff)<<24, - j8 = p[ 8] & 0xff | (p[ 9] & 0xff)<<8 | (p[10] & 0xff)<<16 | (p[11] & 0xff)<<24, - j9 = p[12] & 0xff | (p[13] & 0xff)<<8 | (p[14] & 0xff)<<16 | (p[15] & 0xff)<<24, - j10 = c[ 8] & 0xff | (c[ 9] & 0xff)<<8 | (c[10] & 0xff)<<16 | (c[11] & 0xff)<<24, - j11 = k[16] & 0xff | (k[17] & 0xff)<<8 | (k[18] & 0xff)<<16 | (k[19] & 0xff)<<24, - j12 = k[20] & 0xff | (k[21] & 0xff)<<8 | (k[22] & 0xff)<<16 | (k[23] & 0xff)<<24, - j13 = k[24] & 0xff | (k[25] & 0xff)<<8 | (k[26] & 0xff)<<16 | (k[27] & 0xff)<<24, - j14 = k[28] & 0xff | (k[29] & 0xff)<<8 | (k[30] & 0xff)<<16 | (k[31] & 0xff)<<24, - j15 = c[12] & 0xff | (c[13] & 0xff)<<8 | (c[14] & 0xff)<<16 | (c[15] & 0xff)<<24; - - var x0 = j0, x1 = j1, x2 = j2, x3 = j3, x4 = j4, x5 = j5, x6 = j6, x7 = j7, - x8 = j8, x9 = j9, x10 = j10, x11 = j11, x12 = j12, x13 = j13, x14 = j14, - x15 = j15, u; +function core_hsalsa20( + o: Uint8Array, + p: Uint8Array, + k: Uint8Array, + c: Uint8Array, +) { + var j0 = + (c[0] & 0xff) | + ((c[1] & 0xff) << 8) | + ((c[2] & 0xff) << 16) | + ((c[3] & 0xff) << 24), + j1 = + (k[0] & 0xff) | + ((k[1] & 0xff) << 8) | + ((k[2] & 0xff) << 16) | + ((k[3] & 0xff) << 24), + j2 = + (k[4] & 0xff) | + ((k[5] & 0xff) << 8) | + ((k[6] & 0xff) << 16) | + ((k[7] & 0xff) << 24), + j3 = + (k[8] & 0xff) | + ((k[9] & 0xff) << 8) | + ((k[10] & 0xff) << 16) | + ((k[11] & 0xff) << 24), + j4 = + (k[12] & 0xff) | + ((k[13] & 0xff) << 8) | + ((k[14] & 0xff) << 16) | + ((k[15] & 0xff) << 24), + j5 = + (c[4] & 0xff) | + ((c[5] & 0xff) << 8) | + ((c[6] & 0xff) << 16) | + ((c[7] & 0xff) << 24), + j6 = + (p[0] & 0xff) | + ((p[1] & 0xff) << 8) | + ((p[2] & 0xff) << 16) | + ((p[3] & 0xff) << 24), + j7 = + (p[4] & 0xff) | + ((p[5] & 0xff) << 8) | + ((p[6] & 0xff) << 16) | + ((p[7] & 0xff) << 24), + j8 = + (p[8] & 0xff) | + ((p[9] & 0xff) << 8) | + ((p[10] & 0xff) << 16) | + ((p[11] & 0xff) << 24), + j9 = + (p[12] & 0xff) | + ((p[13] & 0xff) << 8) | + ((p[14] & 0xff) << 16) | + ((p[15] & 0xff) << 24), + j10 = + (c[8] & 0xff) | + ((c[9] & 0xff) << 8) | + ((c[10] & 0xff) << 16) | + ((c[11] & 0xff) << 24), + j11 = + (k[16] & 0xff) | + ((k[17] & 0xff) << 8) | + ((k[18] & 0xff) << 16) | + ((k[19] & 0xff) << 24), + j12 = + (k[20] & 0xff) | + ((k[21] & 0xff) << 8) | + ((k[22] & 0xff) << 16) | + ((k[23] & 0xff) << 24), + j13 = + (k[24] & 0xff) | + ((k[25] & 0xff) << 8) | + ((k[26] & 0xff) << 16) | + ((k[27] & 0xff) << 24), + j14 = + (k[28] & 0xff) | + ((k[29] & 0xff) << 8) | + ((k[30] & 0xff) << 16) | + ((k[31] & 0xff) << 24), + j15 = + (c[12] & 0xff) | + ((c[13] & 0xff) << 8) | + ((c[14] & 0xff) << 16) | + ((c[15] & 0xff) << 24); + + var x0 = j0, + x1 = j1, + x2 = j2, + x3 = j3, + x4 = j4, + x5 = j5, + x6 = j6, + x7 = j7, + x8 = j8, + x9 = j9, + x10 = j10, + x11 = j11, + x12 = j12, + x13 = j13, + x14 = j14, + x15 = j15, + u; for (var i = 0; i < 20; i += 2) { - u = x0 + x12 | 0; - x4 ^= u<<7 | u>>>(32-7); - u = x4 + x0 | 0; - x8 ^= u<<9 | u>>>(32-9); - u = x8 + x4 | 0; - x12 ^= u<<13 | u>>>(32-13); - u = x12 + x8 | 0; - x0 ^= u<<18 | u>>>(32-18); - - u = x5 + x1 | 0; - x9 ^= u<<7 | u>>>(32-7); - u = x9 + x5 | 0; - x13 ^= u<<9 | u>>>(32-9); - u = x13 + x9 | 0; - x1 ^= u<<13 | u>>>(32-13); - u = x1 + x13 | 0; - x5 ^= u<<18 | u>>>(32-18); - - u = x10 + x6 | 0; - x14 ^= u<<7 | u>>>(32-7); - u = x14 + x10 | 0; - x2 ^= u<<9 | u>>>(32-9); - u = x2 + x14 | 0; - x6 ^= u<<13 | u>>>(32-13); - u = x6 + x2 | 0; - x10 ^= u<<18 | u>>>(32-18); - - u = x15 + x11 | 0; - x3 ^= u<<7 | u>>>(32-7); - u = x3 + x15 | 0; - x7 ^= u<<9 | u>>>(32-9); - u = x7 + x3 | 0; - x11 ^= u<<13 | u>>>(32-13); - u = x11 + x7 | 0; - x15 ^= u<<18 | u>>>(32-18); - - u = x0 + x3 | 0; - x1 ^= u<<7 | u>>>(32-7); - u = x1 + x0 | 0; - x2 ^= u<<9 | u>>>(32-9); - u = x2 + x1 | 0; - x3 ^= u<<13 | u>>>(32-13); - u = x3 + x2 | 0; - x0 ^= u<<18 | u>>>(32-18); - - u = x5 + x4 | 0; - x6 ^= u<<7 | u>>>(32-7); - u = x6 + x5 | 0; - x7 ^= u<<9 | u>>>(32-9); - u = x7 + x6 | 0; - x4 ^= u<<13 | u>>>(32-13); - u = x4 + x7 | 0; - x5 ^= u<<18 | u>>>(32-18); - - u = x10 + x9 | 0; - x11 ^= u<<7 | u>>>(32-7); - u = x11 + x10 | 0; - x8 ^= u<<9 | u>>>(32-9); - u = x8 + x11 | 0; - x9 ^= u<<13 | u>>>(32-13); - u = x9 + x8 | 0; - x10 ^= u<<18 | u>>>(32-18); - - u = x15 + x14 | 0; - x12 ^= u<<7 | u>>>(32-7); - u = x12 + x15 | 0; - x13 ^= u<<9 | u>>>(32-9); - u = x13 + x12 | 0; - x14 ^= u<<13 | u>>>(32-13); - u = x14 + x13 | 0; - x15 ^= u<<18 | u>>>(32-18); + u = (x0 + x12) | 0; + x4 ^= (u << 7) | (u >>> (32 - 7)); + u = (x4 + x0) | 0; + x8 ^= (u << 9) | (u >>> (32 - 9)); + u = (x8 + x4) | 0; + x12 ^= (u << 13) | (u >>> (32 - 13)); + u = (x12 + x8) | 0; + x0 ^= (u << 18) | (u >>> (32 - 18)); + + u = (x5 + x1) | 0; + x9 ^= (u << 7) | (u >>> (32 - 7)); + u = (x9 + x5) | 0; + x13 ^= (u << 9) | (u >>> (32 - 9)); + u = (x13 + x9) | 0; + x1 ^= (u << 13) | (u >>> (32 - 13)); + u = (x1 + x13) | 0; + x5 ^= (u << 18) | (u >>> (32 - 18)); + + u = (x10 + x6) | 0; + x14 ^= (u << 7) | (u >>> (32 - 7)); + u = (x14 + x10) | 0; + x2 ^= (u << 9) | (u >>> (32 - 9)); + u = (x2 + x14) | 0; + x6 ^= (u << 13) | (u >>> (32 - 13)); + u = (x6 + x2) | 0; + x10 ^= (u << 18) | (u >>> (32 - 18)); + + u = (x15 + x11) | 0; + x3 ^= (u << 7) | (u >>> (32 - 7)); + u = (x3 + x15) | 0; + x7 ^= (u << 9) | (u >>> (32 - 9)); + u = (x7 + x3) | 0; + x11 ^= (u << 13) | (u >>> (32 - 13)); + u = (x11 + x7) | 0; + x15 ^= (u << 18) | (u >>> (32 - 18)); + + u = (x0 + x3) | 0; + x1 ^= (u << 7) | (u >>> (32 - 7)); + u = (x1 + x0) | 0; + x2 ^= (u << 9) | (u >>> (32 - 9)); + u = (x2 + x1) | 0; + x3 ^= (u << 13) | (u >>> (32 - 13)); + u = (x3 + x2) | 0; + x0 ^= (u << 18) | (u >>> (32 - 18)); + + u = (x5 + x4) | 0; + x6 ^= (u << 7) | (u >>> (32 - 7)); + u = (x6 + x5) | 0; + x7 ^= (u << 9) | (u >>> (32 - 9)); + u = (x7 + x6) | 0; + x4 ^= (u << 13) | (u >>> (32 - 13)); + u = (x4 + x7) | 0; + x5 ^= (u << 18) | (u >>> (32 - 18)); + + u = (x10 + x9) | 0; + x11 ^= (u << 7) | (u >>> (32 - 7)); + u = (x11 + x10) | 0; + x8 ^= (u << 9) | (u >>> (32 - 9)); + u = (x8 + x11) | 0; + x9 ^= (u << 13) | (u >>> (32 - 13)); + u = (x9 + x8) | 0; + x10 ^= (u << 18) | (u >>> (32 - 18)); + + u = (x15 + x14) | 0; + x12 ^= (u << 7) | (u >>> (32 - 7)); + u = (x12 + x15) | 0; + x13 ^= (u << 9) | (u >>> (32 - 9)); + u = (x13 + x12) | 0; + x14 ^= (u << 13) | (u >>> (32 - 13)); + u = (x14 + x13) | 0; + x15 ^= (u << 18) | (u >>> (32 - 18)); } - o[ 0] = x0 >>> 0 & 0xff; - o[ 1] = x0 >>> 8 & 0xff; - o[ 2] = x0 >>> 16 & 0xff; - o[ 3] = x0 >>> 24 & 0xff; - - o[ 4] = x5 >>> 0 & 0xff; - o[ 5] = x5 >>> 8 & 0xff; - o[ 6] = x5 >>> 16 & 0xff; - o[ 7] = x5 >>> 24 & 0xff; - - o[ 8] = x10 >>> 0 & 0xff; - o[ 9] = x10 >>> 8 & 0xff; - o[10] = x10 >>> 16 & 0xff; - o[11] = x10 >>> 24 & 0xff; - - o[12] = x15 >>> 0 & 0xff; - o[13] = x15 >>> 8 & 0xff; - o[14] = x15 >>> 16 & 0xff; - o[15] = x15 >>> 24 & 0xff; - - o[16] = x6 >>> 0 & 0xff; - o[17] = x6 >>> 8 & 0xff; - o[18] = x6 >>> 16 & 0xff; - o[19] = x6 >>> 24 & 0xff; - - o[20] = x7 >>> 0 & 0xff; - o[21] = x7 >>> 8 & 0xff; - o[22] = x7 >>> 16 & 0xff; - o[23] = x7 >>> 24 & 0xff; - - o[24] = x8 >>> 0 & 0xff; - o[25] = x8 >>> 8 & 0xff; - o[26] = x8 >>> 16 & 0xff; - o[27] = x8 >>> 24 & 0xff; - - o[28] = x9 >>> 0 & 0xff; - o[29] = x9 >>> 8 & 0xff; - o[30] = x9 >>> 16 & 0xff; - o[31] = x9 >>> 24 & 0xff; + o[0] = (x0 >>> 0) & 0xff; + o[1] = (x0 >>> 8) & 0xff; + o[2] = (x0 >>> 16) & 0xff; + o[3] = (x0 >>> 24) & 0xff; + + o[4] = (x5 >>> 0) & 0xff; + o[5] = (x5 >>> 8) & 0xff; + o[6] = (x5 >>> 16) & 0xff; + o[7] = (x5 >>> 24) & 0xff; + + o[8] = (x10 >>> 0) & 0xff; + o[9] = (x10 >>> 8) & 0xff; + o[10] = (x10 >>> 16) & 0xff; + o[11] = (x10 >>> 24) & 0xff; + + o[12] = (x15 >>> 0) & 0xff; + o[13] = (x15 >>> 8) & 0xff; + o[14] = (x15 >>> 16) & 0xff; + o[15] = (x15 >>> 24) & 0xff; + + o[16] = (x6 >>> 0) & 0xff; + o[17] = (x6 >>> 8) & 0xff; + o[18] = (x6 >>> 16) & 0xff; + o[19] = (x6 >>> 24) & 0xff; + + o[20] = (x7 >>> 0) & 0xff; + o[21] = (x7 >>> 8) & 0xff; + o[22] = (x7 >>> 16) & 0xff; + o[23] = (x7 >>> 24) & 0xff; + + o[24] = (x8 >>> 0) & 0xff; + o[25] = (x8 >>> 8) & 0xff; + o[26] = (x8 >>> 16) & 0xff; + o[27] = (x8 >>> 24) & 0xff; + + o[28] = (x9 >>> 0) & 0xff; + o[29] = (x9 >>> 8) & 0xff; + o[30] = (x9 >>> 16) & 0xff; + o[31] = (x9 >>> 24) & 0xff; } -function crypto_core_salsa20(out: Uint8Array, inp: Uint8Array, k: Uint8Array, c: Uint8Array) { - core_salsa20(out,inp,k,c); +function crypto_core_salsa20( + out: Uint8Array, + inp: Uint8Array, + k: Uint8Array, + c: Uint8Array, +) { + core_salsa20(out, inp, k, c); } -function crypto_core_hsalsa20(out: Uint8Array,inp: Uint8Array,k: Uint8Array,c: Uint8Array) { - core_hsalsa20(out,inp,k,c); +function crypto_core_hsalsa20( + out: Uint8Array, + inp: Uint8Array, + k: Uint8Array, + c: Uint8Array, +) { + core_hsalsa20(out, inp, k, c); } -var sigma = new Uint8Array([101, 120, 112, 97, 110, 100, 32, 51, 50, 45, 98, 121, 116, 101, 32, 107]); - // "expand 32-byte k" - -function crypto_stream_salsa20_xor(c: Uint8Array, cpos: number,m: Uint8Array, mpos: number,b: number,n: Uint8Array,k: Uint8Array) { - var z = new Uint8Array(16), x = new Uint8Array(64); +var sigma = new Uint8Array([ + 101, + 120, + 112, + 97, + 110, + 100, + 32, + 51, + 50, + 45, + 98, + 121, + 116, + 101, + 32, + 107, +]); +// "expand 32-byte k" + +function crypto_stream_salsa20_xor( + c: Uint8Array, + cpos: number, + m: Uint8Array, + mpos: number, + b: number, + n: Uint8Array, + k: Uint8Array, +) { + var z = new Uint8Array(16), + x = new Uint8Array(64); var u, i; for (i = 0; i < 16; i++) z[i] = 0; for (i = 0; i < 8; i++) z[i] = n[i]; while (b >= 64) { - crypto_core_salsa20(x,z,k,sigma); - for (i = 0; i < 64; i++) c[cpos+i] = m[mpos+i] ^ x[i]; + crypto_core_salsa20(x, z, k, sigma); + for (i = 0; i < 64; i++) c[cpos + i] = m[mpos + i] ^ x[i]; u = 1; for (i = 8; i < 16; i++) { - u = u + (z[i] & 0xff) | 0; + u = (u + (z[i] & 0xff)) | 0; z[i] = u & 0xff; u >>>= 8; } @@ -415,23 +631,30 @@ function crypto_stream_salsa20_xor(c: Uint8Array, cpos: number,m: Uint8Array, mp mpos += 64; } if (b > 0) { - crypto_core_salsa20(x,z,k,sigma); - for (i = 0; i < b; i++) c[cpos+i] = m[mpos+i] ^ x[i]; + crypto_core_salsa20(x, z, k, sigma); + for (i = 0; i < b; i++) c[cpos + i] = m[mpos + i] ^ x[i]; } return 0; } -function crypto_stream_salsa20(c: Uint8Array ,cpos: number,b: number,n: Uint8Array,k: Uint8Array) { - var z = new Uint8Array(16), x = new Uint8Array(64); +function crypto_stream_salsa20( + c: Uint8Array, + cpos: number, + b: number, + n: Uint8Array, + k: Uint8Array, +) { + var z = new Uint8Array(16), + x = new Uint8Array(64); var u, i; for (i = 0; i < 16; i++) z[i] = 0; for (i = 0; i < 8; i++) z[i] = n[i]; while (b >= 64) { - crypto_core_salsa20(x,z,k,sigma); - for (i = 0; i < 64; i++) c[cpos+i] = x[i]; + crypto_core_salsa20(x, z, k, sigma); + for (i = 0; i < 64; i++) c[cpos + i] = x[i]; u = 1; for (i = 8; i < 16; i++) { - u = u + (z[i] & 0xff) | 0; + u = (u + (z[i] & 0xff)) | 0; z[i] = u & 0xff; u >>>= 8; } @@ -439,32 +662,46 @@ function crypto_stream_salsa20(c: Uint8Array ,cpos: number,b: number,n: Uint8Arr cpos += 64; } if (b > 0) { - crypto_core_salsa20(x,z,k,sigma); - for (i = 0; i < b; i++) c[cpos+i] = x[i]; + crypto_core_salsa20(x, z, k, sigma); + for (i = 0; i < b; i++) c[cpos + i] = x[i]; } return 0; } -function crypto_stream(c: Uint8Array,cpos: number,d: number,n: Uint8Array,k: Uint8Array) { +function crypto_stream( + c: Uint8Array, + cpos: number, + d: number, + n: Uint8Array, + k: Uint8Array, +) { var s = new Uint8Array(32); - crypto_core_hsalsa20(s,n,k,sigma); + crypto_core_hsalsa20(s, n, k, sigma); var sn = new Uint8Array(8); - for (var i = 0; i < 8; i++) sn[i] = n[i+16]; - return crypto_stream_salsa20(c,cpos,d,sn,s); + for (var i = 0; i < 8; i++) sn[i] = n[i + 16]; + return crypto_stream_salsa20(c, cpos, d, sn, s); } -function crypto_stream_xor(c: Uint8Array, cpos: number,m: Uint8Array,mpos: number,d: number,n: Uint8Array,k: Uint8Array) { +function crypto_stream_xor( + c: Uint8Array, + cpos: number, + m: Uint8Array, + mpos: number, + d: number, + n: Uint8Array, + k: Uint8Array, +) { var s = new Uint8Array(32); - crypto_core_hsalsa20(s,n,k,sigma); + crypto_core_hsalsa20(s, n, k, sigma); var sn = new Uint8Array(8); - for (var i = 0; i < 8; i++) sn[i] = n[i+16]; - return crypto_stream_salsa20_xor(c,cpos,m,mpos,d,sn,s); + for (var i = 0; i < 8; i++) sn[i] = n[i + 16]; + return crypto_stream_salsa20_xor(c, cpos, m, mpos, d, sn, s); } /* -* Port of Andrew Moon's Poly1305-donna-16. Public domain. -* https://github.com/floodyberry/poly1305-donna -*/ + * Port of Andrew Moon's Poly1305-donna-16. Public domain. + * https://github.com/floodyberry/poly1305-donna + */ class poly1305 { buffer = new Uint8Array(16); @@ -477,214 +714,250 @@ class poly1305 { constructor(key: Uint8Array) { var t0, t1, t2, t3, t4, t5, t6, t7; - t0 = key[ 0] & 0xff | (key[ 1] & 0xff) << 8; this.r[0] = ( t0 ) & 0x1fff; - t1 = key[ 2] & 0xff | (key[ 3] & 0xff) << 8; this.r[1] = ((t0 >>> 13) | (t1 << 3)) & 0x1fff; - t2 = key[ 4] & 0xff | (key[ 5] & 0xff) << 8; this.r[2] = ((t1 >>> 10) | (t2 << 6)) & 0x1f03; - t3 = key[ 6] & 0xff | (key[ 7] & 0xff) << 8; this.r[3] = ((t2 >>> 7) | (t3 << 9)) & 0x1fff; - t4 = key[ 8] & 0xff | (key[ 9] & 0xff) << 8; this.r[4] = ((t3 >>> 4) | (t4 << 12)) & 0x00ff; - this.r[5] = ((t4 >>> 1)) & 0x1ffe; - t5 = key[10] & 0xff | (key[11] & 0xff) << 8; this.r[6] = ((t4 >>> 14) | (t5 << 2)) & 0x1fff; - t6 = key[12] & 0xff | (key[13] & 0xff) << 8; this.r[7] = ((t5 >>> 11) | (t6 << 5)) & 0x1f81; - t7 = key[14] & 0xff | (key[15] & 0xff) << 8; this.r[8] = ((t6 >>> 8) | (t7 << 8)) & 0x1fff; - this.r[9] = ((t7 >>> 5)) & 0x007f; - - this.pad[0] = key[16] & 0xff | (key[17] & 0xff) << 8; - this.pad[1] = key[18] & 0xff | (key[19] & 0xff) << 8; - this.pad[2] = key[20] & 0xff | (key[21] & 0xff) << 8; - this.pad[3] = key[22] & 0xff | (key[23] & 0xff) << 8; - this.pad[4] = key[24] & 0xff | (key[25] & 0xff) << 8; - this.pad[5] = key[26] & 0xff | (key[27] & 0xff) << 8; - this.pad[6] = key[28] & 0xff | (key[29] & 0xff) << 8; - this.pad[7] = key[30] & 0xff | (key[31] & 0xff) << 8; + t0 = (key[0] & 0xff) | ((key[1] & 0xff) << 8); + this.r[0] = t0 & 0x1fff; + t1 = (key[2] & 0xff) | ((key[3] & 0xff) << 8); + this.r[1] = ((t0 >>> 13) | (t1 << 3)) & 0x1fff; + t2 = (key[4] & 0xff) | ((key[5] & 0xff) << 8); + this.r[2] = ((t1 >>> 10) | (t2 << 6)) & 0x1f03; + t3 = (key[6] & 0xff) | ((key[7] & 0xff) << 8); + this.r[3] = ((t2 >>> 7) | (t3 << 9)) & 0x1fff; + t4 = (key[8] & 0xff) | ((key[9] & 0xff) << 8); + this.r[4] = ((t3 >>> 4) | (t4 << 12)) & 0x00ff; + this.r[5] = (t4 >>> 1) & 0x1ffe; + t5 = (key[10] & 0xff) | ((key[11] & 0xff) << 8); + this.r[6] = ((t4 >>> 14) | (t5 << 2)) & 0x1fff; + t6 = (key[12] & 0xff) | ((key[13] & 0xff) << 8); + this.r[7] = ((t5 >>> 11) | (t6 << 5)) & 0x1f81; + t7 = (key[14] & 0xff) | ((key[15] & 0xff) << 8); + this.r[8] = ((t6 >>> 8) | (t7 << 8)) & 0x1fff; + this.r[9] = (t7 >>> 5) & 0x007f; + + this.pad[0] = (key[16] & 0xff) | ((key[17] & 0xff) << 8); + this.pad[1] = (key[18] & 0xff) | ((key[19] & 0xff) << 8); + this.pad[2] = (key[20] & 0xff) | ((key[21] & 0xff) << 8); + this.pad[3] = (key[22] & 0xff) | ((key[23] & 0xff) << 8); + this.pad[4] = (key[24] & 0xff) | ((key[25] & 0xff) << 8); + this.pad[5] = (key[26] & 0xff) | ((key[27] & 0xff) << 8); + this.pad[6] = (key[28] & 0xff) | ((key[29] & 0xff) << 8); + this.pad[7] = (key[30] & 0xff) | ((key[31] & 0xff) << 8); } blocks(m: Uint8Array, mpos: number, bytes: number) { - var hibit = this.fin ? 0 : (1 << 11); + var hibit = this.fin ? 0 : 1 << 11; var t0, t1, t2, t3, t4, t5, t6, t7, c; var d0, d1, d2, d3, d4, d5, d6, d7, d8, d9; - + var h0 = this.h[0], - h1 = this.h[1], - h2 = this.h[2], - h3 = this.h[3], - h4 = this.h[4], - h5 = this.h[5], - h6 = this.h[6], - h7 = this.h[7], - h8 = this.h[8], - h9 = this.h[9]; - + h1 = this.h[1], + h2 = this.h[2], + h3 = this.h[3], + h4 = this.h[4], + h5 = this.h[5], + h6 = this.h[6], + h7 = this.h[7], + h8 = this.h[8], + h9 = this.h[9]; + var r0 = this.r[0], - r1 = this.r[1], - r2 = this.r[2], - r3 = this.r[3], - r4 = this.r[4], - r5 = this.r[5], - r6 = this.r[6], - r7 = this.r[7], - r8 = this.r[8], - r9 = this.r[9]; - + r1 = this.r[1], + r2 = this.r[2], + r3 = this.r[3], + r4 = this.r[4], + r5 = this.r[5], + r6 = this.r[6], + r7 = this.r[7], + r8 = this.r[8], + r9 = this.r[9]; + while (bytes >= 16) { - t0 = m[mpos+ 0] & 0xff | (m[mpos+ 1] & 0xff) << 8; h0 += ( t0 ) & 0x1fff; - t1 = m[mpos+ 2] & 0xff | (m[mpos+ 3] & 0xff) << 8; h1 += ((t0 >>> 13) | (t1 << 3)) & 0x1fff; - t2 = m[mpos+ 4] & 0xff | (m[mpos+ 5] & 0xff) << 8; h2 += ((t1 >>> 10) | (t2 << 6)) & 0x1fff; - t3 = m[mpos+ 6] & 0xff | (m[mpos+ 7] & 0xff) << 8; h3 += ((t2 >>> 7) | (t3 << 9)) & 0x1fff; - t4 = m[mpos+ 8] & 0xff | (m[mpos+ 9] & 0xff) << 8; h4 += ((t3 >>> 4) | (t4 << 12)) & 0x1fff; - h5 += ((t4 >>> 1)) & 0x1fff; - t5 = m[mpos+10] & 0xff | (m[mpos+11] & 0xff) << 8; h6 += ((t4 >>> 14) | (t5 << 2)) & 0x1fff; - t6 = m[mpos+12] & 0xff | (m[mpos+13] & 0xff) << 8; h7 += ((t5 >>> 11) | (t6 << 5)) & 0x1fff; - t7 = m[mpos+14] & 0xff | (m[mpos+15] & 0xff) << 8; h8 += ((t6 >>> 8) | (t7 << 8)) & 0x1fff; - h9 += ((t7 >>> 5)) | hibit; - + t0 = (m[mpos + 0] & 0xff) | ((m[mpos + 1] & 0xff) << 8); + h0 += t0 & 0x1fff; + t1 = (m[mpos + 2] & 0xff) | ((m[mpos + 3] & 0xff) << 8); + h1 += ((t0 >>> 13) | (t1 << 3)) & 0x1fff; + t2 = (m[mpos + 4] & 0xff) | ((m[mpos + 5] & 0xff) << 8); + h2 += ((t1 >>> 10) | (t2 << 6)) & 0x1fff; + t3 = (m[mpos + 6] & 0xff) | ((m[mpos + 7] & 0xff) << 8); + h3 += ((t2 >>> 7) | (t3 << 9)) & 0x1fff; + t4 = (m[mpos + 8] & 0xff) | ((m[mpos + 9] & 0xff) << 8); + h4 += ((t3 >>> 4) | (t4 << 12)) & 0x1fff; + h5 += (t4 >>> 1) & 0x1fff; + t5 = (m[mpos + 10] & 0xff) | ((m[mpos + 11] & 0xff) << 8); + h6 += ((t4 >>> 14) | (t5 << 2)) & 0x1fff; + t6 = (m[mpos + 12] & 0xff) | ((m[mpos + 13] & 0xff) << 8); + h7 += ((t5 >>> 11) | (t6 << 5)) & 0x1fff; + t7 = (m[mpos + 14] & 0xff) | ((m[mpos + 15] & 0xff) << 8); + h8 += ((t6 >>> 8) | (t7 << 8)) & 0x1fff; + h9 += (t7 >>> 5) | hibit; + c = 0; - + d0 = c; d0 += h0 * r0; d0 += h1 * (5 * r9); d0 += h2 * (5 * r8); d0 += h3 * (5 * r7); d0 += h4 * (5 * r6); - c = (d0 >>> 13); d0 &= 0x1fff; + c = d0 >>> 13; + d0 &= 0x1fff; d0 += h5 * (5 * r5); d0 += h6 * (5 * r4); d0 += h7 * (5 * r3); d0 += h8 * (5 * r2); d0 += h9 * (5 * r1); - c += (d0 >>> 13); d0 &= 0x1fff; - + c += d0 >>> 13; + d0 &= 0x1fff; + d1 = c; d1 += h0 * r1; d1 += h1 * r0; d1 += h2 * (5 * r9); d1 += h3 * (5 * r8); d1 += h4 * (5 * r7); - c = (d1 >>> 13); d1 &= 0x1fff; + c = d1 >>> 13; + d1 &= 0x1fff; d1 += h5 * (5 * r6); d1 += h6 * (5 * r5); d1 += h7 * (5 * r4); d1 += h8 * (5 * r3); d1 += h9 * (5 * r2); - c += (d1 >>> 13); d1 &= 0x1fff; - + c += d1 >>> 13; + d1 &= 0x1fff; + d2 = c; d2 += h0 * r2; d2 += h1 * r1; d2 += h2 * r0; d2 += h3 * (5 * r9); d2 += h4 * (5 * r8); - c = (d2 >>> 13); d2 &= 0x1fff; + c = d2 >>> 13; + d2 &= 0x1fff; d2 += h5 * (5 * r7); d2 += h6 * (5 * r6); d2 += h7 * (5 * r5); d2 += h8 * (5 * r4); d2 += h9 * (5 * r3); - c += (d2 >>> 13); d2 &= 0x1fff; - + c += d2 >>> 13; + d2 &= 0x1fff; + d3 = c; d3 += h0 * r3; d3 += h1 * r2; d3 += h2 * r1; d3 += h3 * r0; d3 += h4 * (5 * r9); - c = (d3 >>> 13); d3 &= 0x1fff; + c = d3 >>> 13; + d3 &= 0x1fff; d3 += h5 * (5 * r8); d3 += h6 * (5 * r7); d3 += h7 * (5 * r6); d3 += h8 * (5 * r5); d3 += h9 * (5 * r4); - c += (d3 >>> 13); d3 &= 0x1fff; - + c += d3 >>> 13; + d3 &= 0x1fff; + d4 = c; d4 += h0 * r4; d4 += h1 * r3; d4 += h2 * r2; d4 += h3 * r1; d4 += h4 * r0; - c = (d4 >>> 13); d4 &= 0x1fff; + c = d4 >>> 13; + d4 &= 0x1fff; d4 += h5 * (5 * r9); d4 += h6 * (5 * r8); d4 += h7 * (5 * r7); d4 += h8 * (5 * r6); d4 += h9 * (5 * r5); - c += (d4 >>> 13); d4 &= 0x1fff; - + c += d4 >>> 13; + d4 &= 0x1fff; + d5 = c; d5 += h0 * r5; d5 += h1 * r4; d5 += h2 * r3; d5 += h3 * r2; d5 += h4 * r1; - c = (d5 >>> 13); d5 &= 0x1fff; + c = d5 >>> 13; + d5 &= 0x1fff; d5 += h5 * r0; d5 += h6 * (5 * r9); d5 += h7 * (5 * r8); d5 += h8 * (5 * r7); d5 += h9 * (5 * r6); - c += (d5 >>> 13); d5 &= 0x1fff; - + c += d5 >>> 13; + d5 &= 0x1fff; + d6 = c; d6 += h0 * r6; d6 += h1 * r5; d6 += h2 * r4; d6 += h3 * r3; d6 += h4 * r2; - c = (d6 >>> 13); d6 &= 0x1fff; + c = d6 >>> 13; + d6 &= 0x1fff; d6 += h5 * r1; d6 += h6 * r0; d6 += h7 * (5 * r9); d6 += h8 * (5 * r8); d6 += h9 * (5 * r7); - c += (d6 >>> 13); d6 &= 0x1fff; - + c += d6 >>> 13; + d6 &= 0x1fff; + d7 = c; d7 += h0 * r7; d7 += h1 * r6; d7 += h2 * r5; d7 += h3 * r4; d7 += h4 * r3; - c = (d7 >>> 13); d7 &= 0x1fff; + c = d7 >>> 13; + d7 &= 0x1fff; d7 += h5 * r2; d7 += h6 * r1; d7 += h7 * r0; d7 += h8 * (5 * r9); d7 += h9 * (5 * r8); - c += (d7 >>> 13); d7 &= 0x1fff; - + c += d7 >>> 13; + d7 &= 0x1fff; + d8 = c; d8 += h0 * r8; d8 += h1 * r7; d8 += h2 * r6; d8 += h3 * r5; d8 += h4 * r4; - c = (d8 >>> 13); d8 &= 0x1fff; + c = d8 >>> 13; + d8 &= 0x1fff; d8 += h5 * r3; d8 += h6 * r2; d8 += h7 * r1; d8 += h8 * r0; d8 += h9 * (5 * r9); - c += (d8 >>> 13); d8 &= 0x1fff; - + c += d8 >>> 13; + d8 &= 0x1fff; + d9 = c; d9 += h0 * r9; d9 += h1 * r8; d9 += h2 * r7; d9 += h3 * r6; d9 += h4 * r5; - c = (d9 >>> 13); d9 &= 0x1fff; + c = d9 >>> 13; + d9 &= 0x1fff; d9 += h5 * r4; d9 += h6 * r3; d9 += h7 * r2; d9 += h8 * r1; d9 += h9 * r0; - c += (d9 >>> 13); d9 &= 0x1fff; - - c = (((c << 2) + c)) | 0; + c += d9 >>> 13; + d9 &= 0x1fff; + + c = ((c << 2) + c) | 0; c = (c + d0) | 0; d0 = c & 0x1fff; - c = (c >>> 13); + c = c >>> 13; d1 += c; - + h0 = d0; h1 = d1; h2 = d2; @@ -695,7 +968,7 @@ class poly1305 { h7 = d7; h8 = d8; h9 = d9; - + mpos += 16; bytes -= 16; } @@ -714,7 +987,7 @@ class poly1305 { finish(mac: Uint8Array, macpos: number) { var g = new Uint16Array(10); var c, mask, f, i; - + if (this.leftover) { i = this.leftover; this.buffer[i++] = 1; @@ -722,7 +995,7 @@ class poly1305 { this.fin = 1; this.blocks(this.buffer, 0, 16); } - + c = this.h[1] >>> 13; this.h[1] &= 0x1fff; for (i = 2; i < 10; i++) { @@ -730,14 +1003,14 @@ class poly1305 { c = this.h[i] >>> 13; this.h[i] &= 0x1fff; } - this.h[0] += (c * 5); + this.h[0] += c * 5; c = this.h[0] >>> 13; this.h[0] &= 0x1fff; this.h[1] += c; c = this.h[1] >>> 13; this.h[1] &= 0x1fff; this.h[2] += c; - + g[0] = this.h[0] + 5; c = g[0] >>> 13; g[0] &= 0x1fff; @@ -746,131 +1019,156 @@ class poly1305 { c = g[i] >>> 13; g[i] &= 0x1fff; } - g[9] -= (1 << 13); - + g[9] -= 1 << 13; + mask = (c ^ 1) - 1; for (i = 0; i < 10; i++) g[i] &= mask; mask = ~mask; for (i = 0; i < 10; i++) this.h[i] = (this.h[i] & mask) | g[i]; - - this.h[0] = ((this.h[0] ) | (this.h[1] << 13) ) & 0xffff; - this.h[1] = ((this.h[1] >>> 3) | (this.h[2] << 10) ) & 0xffff; - this.h[2] = ((this.h[2] >>> 6) | (this.h[3] << 7) ) & 0xffff; - this.h[3] = ((this.h[3] >>> 9) | (this.h[4] << 4) ) & 0xffff; - this.h[4] = ((this.h[4] >>> 12) | (this.h[5] << 1) | (this.h[6] << 14)) & 0xffff; - this.h[5] = ((this.h[6] >>> 2) | (this.h[7] << 11) ) & 0xffff; - this.h[6] = ((this.h[7] >>> 5) | (this.h[8] << 8) ) & 0xffff; - this.h[7] = ((this.h[8] >>> 8) | (this.h[9] << 5) ) & 0xffff; - + + this.h[0] = (this.h[0] | (this.h[1] << 13)) & 0xffff; + this.h[1] = ((this.h[1] >>> 3) | (this.h[2] << 10)) & 0xffff; + this.h[2] = ((this.h[2] >>> 6) | (this.h[3] << 7)) & 0xffff; + this.h[3] = ((this.h[3] >>> 9) | (this.h[4] << 4)) & 0xffff; + this.h[4] = + ((this.h[4] >>> 12) | (this.h[5] << 1) | (this.h[6] << 14)) & 0xffff; + this.h[5] = ((this.h[6] >>> 2) | (this.h[7] << 11)) & 0xffff; + this.h[6] = ((this.h[7] >>> 5) | (this.h[8] << 8)) & 0xffff; + this.h[7] = ((this.h[8] >>> 8) | (this.h[9] << 5)) & 0xffff; + f = this.h[0] + this.pad[0]; this.h[0] = f & 0xffff; for (i = 1; i < 8; i++) { f = (((this.h[i] + this.pad[i]) | 0) + (f >>> 16)) | 0; this.h[i] = f & 0xffff; } - - mac[macpos+ 0] = (this.h[0] >>> 0) & 0xff; - mac[macpos+ 1] = (this.h[0] >>> 8) & 0xff; - mac[macpos+ 2] = (this.h[1] >>> 0) & 0xff; - mac[macpos+ 3] = (this.h[1] >>> 8) & 0xff; - mac[macpos+ 4] = (this.h[2] >>> 0) & 0xff; - mac[macpos+ 5] = (this.h[2] >>> 8) & 0xff; - mac[macpos+ 6] = (this.h[3] >>> 0) & 0xff; - mac[macpos+ 7] = (this.h[3] >>> 8) & 0xff; - mac[macpos+ 8] = (this.h[4] >>> 0) & 0xff; - mac[macpos+ 9] = (this.h[4] >>> 8) & 0xff; - mac[macpos+10] = (this.h[5] >>> 0) & 0xff; - mac[macpos+11] = (this.h[5] >>> 8) & 0xff; - mac[macpos+12] = (this.h[6] >>> 0) & 0xff; - mac[macpos+13] = (this.h[6] >>> 8) & 0xff; - mac[macpos+14] = (this.h[7] >>> 0) & 0xff; - mac[macpos+15] = (this.h[7] >>> 8) & 0xff; + + mac[macpos + 0] = (this.h[0] >>> 0) & 0xff; + mac[macpos + 1] = (this.h[0] >>> 8) & 0xff; + mac[macpos + 2] = (this.h[1] >>> 0) & 0xff; + mac[macpos + 3] = (this.h[1] >>> 8) & 0xff; + mac[macpos + 4] = (this.h[2] >>> 0) & 0xff; + mac[macpos + 5] = (this.h[2] >>> 8) & 0xff; + mac[macpos + 6] = (this.h[3] >>> 0) & 0xff; + mac[macpos + 7] = (this.h[3] >>> 8) & 0xff; + mac[macpos + 8] = (this.h[4] >>> 0) & 0xff; + mac[macpos + 9] = (this.h[4] >>> 8) & 0xff; + mac[macpos + 10] = (this.h[5] >>> 0) & 0xff; + mac[macpos + 11] = (this.h[5] >>> 8) & 0xff; + mac[macpos + 12] = (this.h[6] >>> 0) & 0xff; + mac[macpos + 13] = (this.h[6] >>> 8) & 0xff; + mac[macpos + 14] = (this.h[7] >>> 0) & 0xff; + mac[macpos + 15] = (this.h[7] >>> 8) & 0xff; } update(m: Uint8Array, mpos: number, bytes: number) { var i, want; - + if (this.leftover) { - want = (16 - this.leftover); - if (want > bytes) - want = bytes; - for (i = 0; i < want; i++) - this.buffer[this.leftover + i] = m[mpos+i]; + want = 16 - this.leftover; + if (want > bytes) want = bytes; + for (i = 0; i < want; i++) this.buffer[this.leftover + i] = m[mpos + i]; bytes -= want; mpos += want; this.leftover += want; - if (this.leftover < 16) - return; + if (this.leftover < 16) return; this.blocks(this.buffer, 0, 16); this.leftover = 0; } - + if (bytes >= 16) { want = bytes - (bytes % 16); this.blocks(m, mpos, want); mpos += want; bytes -= want; } - + if (bytes) { - for (i = 0; i < bytes; i++) - this.buffer[this.leftover + i] = m[mpos+i]; + for (i = 0; i < bytes; i++) this.buffer[this.leftover + i] = m[mpos + i]; this.leftover += bytes; } } } - -function crypto_onetimeauth(out: Uint8Array, outpos: number, m: Uint8Array, mpos: number, n: number, k: Uint8Array) { +function crypto_onetimeauth( + out: Uint8Array, + outpos: number, + m: Uint8Array, + mpos: number, + n: number, + k: Uint8Array, +) { var s = new poly1305(k); s.update(m, mpos, n); s.finish(out, outpos); return 0; } -function crypto_onetimeauth_verify(h: Uint8Array, hpos: number, m: Uint8Array, mpos: number, n: number, k: Uint8Array) { +function crypto_onetimeauth_verify( + h: Uint8Array, + hpos: number, + m: Uint8Array, + mpos: number, + n: number, + k: Uint8Array, +) { var x = new Uint8Array(16); - crypto_onetimeauth(x,0,m,mpos,n,k); - return crypto_verify_16(h,hpos,x,0); + crypto_onetimeauth(x, 0, m, mpos, n, k); + return crypto_verify_16(h, hpos, x, 0); } -function crypto_secretbox(c: Uint8Array,m: Uint8Array,d: number,n: Uint8Array,k: Uint8Array) { +function crypto_secretbox( + c: Uint8Array, + m: Uint8Array, + d: number, + n: Uint8Array, + k: Uint8Array, +) { var i; if (d < 32) return -1; - crypto_stream_xor(c,0,m,0,d,n,k); + crypto_stream_xor(c, 0, m, 0, d, n, k); crypto_onetimeauth(c, 16, c, 32, d - 32, c); for (i = 0; i < 16; i++) c[i] = 0; return 0; } -function crypto_secretbox_open(m: Uint8Array,c: Uint8Array,d: number,n: Uint8Array,k: Uint8Array) { +function crypto_secretbox_open( + m: Uint8Array, + c: Uint8Array, + d: number, + n: Uint8Array, + k: Uint8Array, +) { var i; var x = new Uint8Array(32); if (d < 32) return -1; - crypto_stream(x,0,32,n,k); - if (crypto_onetimeauth_verify(c, 16,c, 32,d - 32,x) !== 0) return -1; - crypto_stream_xor(m,0,c,0,d,n,k); + crypto_stream(x, 0, 32, n, k); + if (crypto_onetimeauth_verify(c, 16, c, 32, d - 32, x) !== 0) return -1; + crypto_stream_xor(m, 0, c, 0, d, n, k); for (i = 0; i < 32; i++) m[i] = 0; return 0; } function set25519(r: Float64Array, a: Float64Array) { var i; - for (i = 0; i < 16; i++) r[i] = a[i]|0; + for (i = 0; i < 16; i++) r[i] = a[i] | 0; } function car25519(o: Float64Array) { - var i, v, c = 1; + var i, + v, + c = 1; for (i = 0; i < 16; i++) { v = o[i] + c + 65535; c = Math.floor(v / 65536); o[i] = v - c * 65536; } - o[0] += c-1 + 37 * (c-1); + o[0] += c - 1 + 37 * (c - 1); } function sel25519(p: Float64Array, q: Float64Array, b: number) { - var t, c = ~(b-1); + var t, + c = ~(b - 1); for (var i = 0; i < 16; i++) { t = c & (p[i] ^ q[i]); p[i] ^= t; @@ -880,7 +1178,8 @@ function sel25519(p: Float64Array, q: Float64Array, b: number) { function pack25519(o: Uint8Array, n: Float64Array) { var i, j, b; - var m = gf(), t = gf(); + var m = gf(), + t = gf(); for (i = 0; i < 16; i++) t[i] = n[i]; car25519(t); car25519(t); @@ -888,22 +1187,23 @@ function pack25519(o: Uint8Array, n: Float64Array) { for (j = 0; j < 2; j++) { m[0] = t[0] - 0xffed; for (i = 1; i < 15; i++) { - m[i] = t[i] - 0xffff - ((m[i-1]>>16) & 1); - m[i-1] &= 0xffff; + m[i] = t[i] - 0xffff - ((m[i - 1] >> 16) & 1); + m[i - 1] &= 0xffff; } - m[15] = t[15] - 0x7fff - ((m[14]>>16) & 1); - b = (m[15]>>16) & 1; + m[15] = t[15] - 0x7fff - ((m[14] >> 16) & 1); + b = (m[15] >> 16) & 1; m[14] &= 0xffff; - sel25519(t, m, 1-b); + sel25519(t, m, 1 - b); } for (i = 0; i < 16; i++) { - o[2*i] = t[i] & 0xff; - o[2*i+1] = t[i]>>8; + o[2 * i] = t[i] & 0xff; + o[2 * i + 1] = t[i] >> 8; } } function neq25519(a: Float64Array, b: Float64Array) { - var c = new Uint8Array(32), d = new Uint8Array(32); + var c = new Uint8Array(32), + d = new Uint8Array(32); pack25519(c, a); pack25519(d, b); return crypto_verify_32(c, 0, d, 0); @@ -917,7 +1217,7 @@ function par25519(a: Float64Array) { function unpack25519(o: Float64Array, n: Uint8Array) { var i; - for (i = 0; i < 16; i++) o[i] = n[2*i] + (n[2*i+1] << 8); + for (i = 0; i < 16; i++) o[i] = n[2 * i] + (n[2 * i + 1] << 8); o[15] &= 0x7fff; } @@ -930,11 +1230,39 @@ function Z(o: Float64Array, a: Float64Array, b: Float64Array) { } function M(o: Float64Array, a: Float64Array, b: Float64Array) { - var v, c, - t0 = 0, t1 = 0, t2 = 0, t3 = 0, t4 = 0, t5 = 0, t6 = 0, t7 = 0, - t8 = 0, t9 = 0, t10 = 0, t11 = 0, t12 = 0, t13 = 0, t14 = 0, t15 = 0, - t16 = 0, t17 = 0, t18 = 0, t19 = 0, t20 = 0, t21 = 0, t22 = 0, t23 = 0, - t24 = 0, t25 = 0, t26 = 0, t27 = 0, t28 = 0, t29 = 0, t30 = 0, + var v, + c, + t0 = 0, + t1 = 0, + t2 = 0, + t3 = 0, + t4 = 0, + t5 = 0, + t6 = 0, + t7 = 0, + t8 = 0, + t9 = 0, + t10 = 0, + t11 = 0, + t12 = 0, + t13 = 0, + t14 = 0, + t15 = 0, + t16 = 0, + t17 = 0, + t18 = 0, + t19 = 0, + t20 = 0, + t21 = 0, + t22 = 0, + t23 = 0, + t24 = 0, + t25 = 0, + t26 = 0, + t27 = 0, + t28 = 0, + t29 = 0, + t30 = 0, b0 = b[0], b1 = b[1], b2 = b[2], @@ -1225,16 +1553,16 @@ function M(o: Float64Array, a: Float64Array, b: Float64Array) { t29 += v * b14; t30 += v * b15; - t0 += 38 * t16; - t1 += 38 * t17; - t2 += 38 * t18; - t3 += 38 * t19; - t4 += 38 * t20; - t5 += 38 * t21; - t6 += 38 * t22; - t7 += 38 * t23; - t8 += 38 * t24; - t9 += 38 * t25; + t0 += 38 * t16; + t1 += 38 * t17; + t2 += 38 * t18; + t3 += 38 * t19; + t4 += 38 * t20; + t5 += 38 * t21; + t6 += 38 * t22; + t7 += 38 * t23; + t8 += 38 * t24; + t9 += 38 * t25; t10 += 38 * t26; t11 += 38 * t27; t12 += 38 * t28; @@ -1244,54 +1572,118 @@ function M(o: Float64Array, a: Float64Array, b: Float64Array) { // first car c = 1; - v = t0 + c + 65535; c = Math.floor(v / 65536); t0 = v - c * 65536; - v = t1 + c + 65535; c = Math.floor(v / 65536); t1 = v - c * 65536; - v = t2 + c + 65535; c = Math.floor(v / 65536); t2 = v - c * 65536; - v = t3 + c + 65535; c = Math.floor(v / 65536); t3 = v - c * 65536; - v = t4 + c + 65535; c = Math.floor(v / 65536); t4 = v - c * 65536; - v = t5 + c + 65535; c = Math.floor(v / 65536); t5 = v - c * 65536; - v = t6 + c + 65535; c = Math.floor(v / 65536); t6 = v - c * 65536; - v = t7 + c + 65535; c = Math.floor(v / 65536); t7 = v - c * 65536; - v = t8 + c + 65535; c = Math.floor(v / 65536); t8 = v - c * 65536; - v = t9 + c + 65535; c = Math.floor(v / 65536); t9 = v - c * 65536; - v = t10 + c + 65535; c = Math.floor(v / 65536); t10 = v - c * 65536; - v = t11 + c + 65535; c = Math.floor(v / 65536); t11 = v - c * 65536; - v = t12 + c + 65535; c = Math.floor(v / 65536); t12 = v - c * 65536; - v = t13 + c + 65535; c = Math.floor(v / 65536); t13 = v - c * 65536; - v = t14 + c + 65535; c = Math.floor(v / 65536); t14 = v - c * 65536; - v = t15 + c + 65535; c = Math.floor(v / 65536); t15 = v - c * 65536; - t0 += c-1 + 37 * (c-1); + v = t0 + c + 65535; + c = Math.floor(v / 65536); + t0 = v - c * 65536; + v = t1 + c + 65535; + c = Math.floor(v / 65536); + t1 = v - c * 65536; + v = t2 + c + 65535; + c = Math.floor(v / 65536); + t2 = v - c * 65536; + v = t3 + c + 65535; + c = Math.floor(v / 65536); + t3 = v - c * 65536; + v = t4 + c + 65535; + c = Math.floor(v / 65536); + t4 = v - c * 65536; + v = t5 + c + 65535; + c = Math.floor(v / 65536); + t5 = v - c * 65536; + v = t6 + c + 65535; + c = Math.floor(v / 65536); + t6 = v - c * 65536; + v = t7 + c + 65535; + c = Math.floor(v / 65536); + t7 = v - c * 65536; + v = t8 + c + 65535; + c = Math.floor(v / 65536); + t8 = v - c * 65536; + v = t9 + c + 65535; + c = Math.floor(v / 65536); + t9 = v - c * 65536; + v = t10 + c + 65535; + c = Math.floor(v / 65536); + t10 = v - c * 65536; + v = t11 + c + 65535; + c = Math.floor(v / 65536); + t11 = v - c * 65536; + v = t12 + c + 65535; + c = Math.floor(v / 65536); + t12 = v - c * 65536; + v = t13 + c + 65535; + c = Math.floor(v / 65536); + t13 = v - c * 65536; + v = t14 + c + 65535; + c = Math.floor(v / 65536); + t14 = v - c * 65536; + v = t15 + c + 65535; + c = Math.floor(v / 65536); + t15 = v - c * 65536; + t0 += c - 1 + 37 * (c - 1); // second car c = 1; - v = t0 + c + 65535; c = Math.floor(v / 65536); t0 = v - c * 65536; - v = t1 + c + 65535; c = Math.floor(v / 65536); t1 = v - c * 65536; - v = t2 + c + 65535; c = Math.floor(v / 65536); t2 = v - c * 65536; - v = t3 + c + 65535; c = Math.floor(v / 65536); t3 = v - c * 65536; - v = t4 + c + 65535; c = Math.floor(v / 65536); t4 = v - c * 65536; - v = t5 + c + 65535; c = Math.floor(v / 65536); t5 = v - c * 65536; - v = t6 + c + 65535; c = Math.floor(v / 65536); t6 = v - c * 65536; - v = t7 + c + 65535; c = Math.floor(v / 65536); t7 = v - c * 65536; - v = t8 + c + 65535; c = Math.floor(v / 65536); t8 = v - c * 65536; - v = t9 + c + 65535; c = Math.floor(v / 65536); t9 = v - c * 65536; - v = t10 + c + 65535; c = Math.floor(v / 65536); t10 = v - c * 65536; - v = t11 + c + 65535; c = Math.floor(v / 65536); t11 = v - c * 65536; - v = t12 + c + 65535; c = Math.floor(v / 65536); t12 = v - c * 65536; - v = t13 + c + 65535; c = Math.floor(v / 65536); t13 = v - c * 65536; - v = t14 + c + 65535; c = Math.floor(v / 65536); t14 = v - c * 65536; - v = t15 + c + 65535; c = Math.floor(v / 65536); t15 = v - c * 65536; - t0 += c-1 + 37 * (c-1); - - o[ 0] = t0; - o[ 1] = t1; - o[ 2] = t2; - o[ 3] = t3; - o[ 4] = t4; - o[ 5] = t5; - o[ 6] = t6; - o[ 7] = t7; - o[ 8] = t8; - o[ 9] = t9; + v = t0 + c + 65535; + c = Math.floor(v / 65536); + t0 = v - c * 65536; + v = t1 + c + 65535; + c = Math.floor(v / 65536); + t1 = v - c * 65536; + v = t2 + c + 65535; + c = Math.floor(v / 65536); + t2 = v - c * 65536; + v = t3 + c + 65535; + c = Math.floor(v / 65536); + t3 = v - c * 65536; + v = t4 + c + 65535; + c = Math.floor(v / 65536); + t4 = v - c * 65536; + v = t5 + c + 65535; + c = Math.floor(v / 65536); + t5 = v - c * 65536; + v = t6 + c + 65535; + c = Math.floor(v / 65536); + t6 = v - c * 65536; + v = t7 + c + 65535; + c = Math.floor(v / 65536); + t7 = v - c * 65536; + v = t8 + c + 65535; + c = Math.floor(v / 65536); + t8 = v - c * 65536; + v = t9 + c + 65535; + c = Math.floor(v / 65536); + t9 = v - c * 65536; + v = t10 + c + 65535; + c = Math.floor(v / 65536); + t10 = v - c * 65536; + v = t11 + c + 65535; + c = Math.floor(v / 65536); + t11 = v - c * 65536; + v = t12 + c + 65535; + c = Math.floor(v / 65536); + t12 = v - c * 65536; + v = t13 + c + 65535; + c = Math.floor(v / 65536); + t13 = v - c * 65536; + v = t14 + c + 65535; + c = Math.floor(v / 65536); + t14 = v - c * 65536; + v = t15 + c + 65535; + c = Math.floor(v / 65536); + t15 = v - c * 65536; + t0 += c - 1 + 37 * (c - 1); + + o[0] = t0; + o[1] = t1; + o[2] = t2; + o[3] = t3; + o[4] = t4; + o[5] = t5; + o[6] = t6; + o[7] = t7; + o[8] = t8; + o[9] = t9; o[10] = t10; o[11] = t11; o[12] = t12; @@ -1310,7 +1702,7 @@ function inv25519(o: Float64Array, i: Float64Array) { for (a = 0; a < 16; a++) c[a] = i[a]; for (a = 253; a >= 0; a--) { S(c, c); - if(a !== 2 && a !== 4) M(c, c, i); + if (a !== 2 && a !== 4) M(c, c, i); } for (a = 0; a < 16; a++) o[a] = c[a]; } @@ -1320,62 +1712,68 @@ function pow2523(o: Float64Array, i: Float64Array) { var a; for (a = 0; a < 16; a++) c[a] = i[a]; for (a = 250; a >= 0; a--) { - S(c, c); - if(a !== 1) M(c, c, i); + S(c, c); + if (a !== 1) M(c, c, i); } for (a = 0; a < 16; a++) o[a] = c[a]; } function crypto_scalarmult(q: Uint8Array, n: Uint8Array, p: Uint8Array) { var z = new Uint8Array(32); - var x = new Float64Array(80), r, i; - var a = gf(), b = gf(), c = gf(), - d = gf(), e = gf(), f = gf(); + var x = new Float64Array(80), + r, + i; + var a = gf(), + b = gf(), + c = gf(), + d = gf(), + e = gf(), + f = gf(); for (i = 0; i < 31; i++) z[i] = n[i]; - z[31]=(n[31]&127)|64; - z[0]&=248; - unpack25519(x,p); + z[31] = (n[31] & 127) | 64; + z[0] &= 248; + unpack25519(x, p); for (i = 0; i < 16; i++) { - b[i]=x[i]; - d[i]=a[i]=c[i]=0; + b[i] = x[i]; + d[i] = a[i] = c[i] = 0; } - a[0]=d[0]=1; - for (i=254; i>=0; --i) { - r=(z[i>>>3]>>>(i&7))&1; - sel25519(a,b,r); - sel25519(c,d,r); - A(e,a,c); - Z(a,a,c); - A(c,b,d); - Z(b,b,d); - S(d,e); - S(f,a); - M(a,c,a); - M(c,b,e); - A(e,a,c); - Z(a,a,c); - S(b,a); - Z(c,d,f); - M(a,c,_121665); - A(a,a,d); - M(c,c,a); - M(a,d,f); - M(d,b,x); - S(b,e); - sel25519(a,b,r); - sel25519(c,d,r); + a[0] = d[0] = 1; + for (i = 254; i >= 0; --i) { + r = (z[i >>> 3] >>> (i & 7)) & 1; + sel25519(a, b, r); + sel25519(c, d, r); + A(e, a, c); + Z(a, a, c); + A(c, b, d); + Z(b, b, d); + S(d, e); + S(f, a); + M(a, c, a); + M(c, b, e); + A(e, a, c); + Z(a, a, c); + S(b, a); + Z(c, d, f); + M(a, c, _121665); + A(a, a, d); + M(c, c, a); + M(a, d, f); + M(d, b, x); + S(b, e); + sel25519(a, b, r); + sel25519(c, d, r); } for (i = 0; i < 16; i++) { - x[i+16]=a[i]; - x[i+32]=c[i]; - x[i+48]=b[i]; - x[i+64]=d[i]; + x[i + 16] = a[i]; + x[i + 32] = c[i]; + x[i + 48] = b[i]; + x[i + 64] = d[i]; } var x32 = x.subarray(32); var x16 = x.subarray(16); - inv25519(x32,x32); - M(x16,x16,x32); - pack25519(q,x16); + inv25519(x32, x32); + M(x16, x16, x32); + pack25519(q, x16); return 0; } @@ -1397,13 +1795,27 @@ function crypto_box_beforenm(k: Uint8Array, y: Uint8Array, x: Uint8Array) { var crypto_box_afternm = crypto_secretbox; var crypto_box_open_afternm = crypto_secretbox_open; -function crypto_box(c: Uint8Array, m: Uint8Array, d: number, n: Uint8Array, y: Uint8Array, x: Uint8Array) { +function crypto_box( + c: Uint8Array, + m: Uint8Array, + d: number, + n: Uint8Array, + y: Uint8Array, + x: Uint8Array, +) { var k = new Uint8Array(32); crypto_box_beforenm(k, y, x); return crypto_box_afternm(c, m, d, n, k); } -function crypto_box_open(m: Uint8Array, c: Uint8Array, d: number, n: Uint8Array, y: Uint8Array, x: Uint8Array) { +function crypto_box_open( + m: Uint8Array, + c: Uint8Array, + d: number, + n: Uint8Array, + y: Uint8Array, + x: Uint8Array, +) { var k = new Uint8Array(32); crypto_box_beforenm(k, y, x); return crypto_box_open_afternm(m, c, d, n, k); @@ -1453,36 +1865,64 @@ var K = [ 0x5fcb6fab, 0x3ad6faec, 0x6c44198c, 0x4a475817 ]; -function crypto_hashblocks_hl(hh: Int32Array, hl: Int32Array, m: Uint8Array, n: number) { - var wh = new Int32Array(16), wl = new Int32Array(16), - bh0, bh1, bh2, bh3, bh4, bh5, bh6, bh7, - bl0, bl1, bl2, bl3, bl4, bl5, bl6, bl7, - th, tl, i, j, h, l, a, b, c, d; +function crypto_hashblocks_hl( + hh: Int32Array, + hl: Int32Array, + m: Uint8Array, + n: number, +) { + var wh = new Int32Array(16), + wl = new Int32Array(16), + bh0, + bh1, + bh2, + bh3, + bh4, + bh5, + bh6, + bh7, + bl0, + bl1, + bl2, + bl3, + bl4, + bl5, + bl6, + bl7, + th, + tl, + i, + j, + h, + l, + a, + b, + c, + d; var ah0 = hh[0], - ah1 = hh[1], - ah2 = hh[2], - ah3 = hh[3], - ah4 = hh[4], - ah5 = hh[5], - ah6 = hh[6], - ah7 = hh[7], - - al0 = hl[0], - al1 = hl[1], - al2 = hl[2], - al3 = hl[3], - al4 = hl[4], - al5 = hl[5], - al6 = hl[6], - al7 = hl[7]; + ah1 = hh[1], + ah2 = hh[2], + ah3 = hh[3], + ah4 = hh[4], + ah5 = hh[5], + ah6 = hh[6], + ah7 = hh[7], + al0 = hl[0], + al1 = hl[1], + al2 = hl[2], + al3 = hl[3], + al4 = hl[4], + al5 = hl[5], + al6 = hl[6], + al7 = hl[7]; var pos = 0; while (n >= 128) { for (i = 0; i < 16; i++) { j = 8 * i + pos; - wh[i] = (m[j+0] << 24) | (m[j+1] << 16) | (m[j+2] << 8) | m[j+3]; - wl[i] = (m[j+4] << 24) | (m[j+5] << 16) | (m[j+6] << 8) | m[j+7]; + wh[i] = (m[j + 0] << 24) | (m[j + 1] << 16) | (m[j + 2] << 8) | m[j + 3]; + wl[i] = (m[j + 4] << 24) | (m[j + 5] << 16) | (m[j + 6] << 8) | m[j + 7]; } for (i = 0; i < 80; i++) { bh0 = ah0; @@ -1507,64 +1947,92 @@ function crypto_hashblocks_hl(hh: Int32Array, hl: Int32Array, m: Uint8Array, n: h = ah7; l = al7; - a = l & 0xffff; b = l >>> 16; - c = h & 0xffff; d = h >>> 16; + a = l & 0xffff; + b = l >>> 16; + c = h & 0xffff; + d = h >>> 16; // Sigma1 - h = ((ah4 >>> 14) | (al4 << (32-14))) ^ ((ah4 >>> 18) | (al4 << (32-18))) ^ ((al4 >>> (41-32)) | (ah4 << (32-(41-32)))); - l = ((al4 >>> 14) | (ah4 << (32-14))) ^ ((al4 >>> 18) | (ah4 << (32-18))) ^ ((ah4 >>> (41-32)) | (al4 << (32-(41-32)))); - - a += l & 0xffff; b += l >>> 16; - c += h & 0xffff; d += h >>> 16; + h = + ((ah4 >>> 14) | (al4 << (32 - 14))) ^ + ((ah4 >>> 18) | (al4 << (32 - 18))) ^ + ((al4 >>> (41 - 32)) | (ah4 << (32 - (41 - 32)))); + l = + ((al4 >>> 14) | (ah4 << (32 - 14))) ^ + ((al4 >>> 18) | (ah4 << (32 - 18))) ^ + ((ah4 >>> (41 - 32)) | (al4 << (32 - (41 - 32)))); + + a += l & 0xffff; + b += l >>> 16; + c += h & 0xffff; + d += h >>> 16; // Ch h = (ah4 & ah5) ^ (~ah4 & ah6); l = (al4 & al5) ^ (~al4 & al6); - a += l & 0xffff; b += l >>> 16; - c += h & 0xffff; d += h >>> 16; + a += l & 0xffff; + b += l >>> 16; + c += h & 0xffff; + d += h >>> 16; // K - h = K[i*2]; - l = K[i*2+1]; + h = K[i * 2]; + l = K[i * 2 + 1]; - a += l & 0xffff; b += l >>> 16; - c += h & 0xffff; d += h >>> 16; + a += l & 0xffff; + b += l >>> 16; + c += h & 0xffff; + d += h >>> 16; // w - h = wh[i%16]; - l = wl[i%16]; + h = wh[i % 16]; + l = wl[i % 16]; - a += l & 0xffff; b += l >>> 16; - c += h & 0xffff; d += h >>> 16; + a += l & 0xffff; + b += l >>> 16; + c += h & 0xffff; + d += h >>> 16; b += a >>> 16; c += b >>> 16; d += c >>> 16; - th = c & 0xffff | d << 16; - tl = a & 0xffff | b << 16; + th = (c & 0xffff) | (d << 16); + tl = (a & 0xffff) | (b << 16); // add h = th; l = tl; - a = l & 0xffff; b = l >>> 16; - c = h & 0xffff; d = h >>> 16; + a = l & 0xffff; + b = l >>> 16; + c = h & 0xffff; + d = h >>> 16; // Sigma0 - h = ((ah0 >>> 28) | (al0 << (32-28))) ^ ((al0 >>> (34-32)) | (ah0 << (32-(34-32)))) ^ ((al0 >>> (39-32)) | (ah0 << (32-(39-32)))); - l = ((al0 >>> 28) | (ah0 << (32-28))) ^ ((ah0 >>> (34-32)) | (al0 << (32-(34-32)))) ^ ((ah0 >>> (39-32)) | (al0 << (32-(39-32)))); - - a += l & 0xffff; b += l >>> 16; - c += h & 0xffff; d += h >>> 16; + h = + ((ah0 >>> 28) | (al0 << (32 - 28))) ^ + ((al0 >>> (34 - 32)) | (ah0 << (32 - (34 - 32)))) ^ + ((al0 >>> (39 - 32)) | (ah0 << (32 - (39 - 32)))); + l = + ((al0 >>> 28) | (ah0 << (32 - 28))) ^ + ((ah0 >>> (34 - 32)) | (al0 << (32 - (34 - 32)))) ^ + ((ah0 >>> (39 - 32)) | (al0 << (32 - (39 - 32)))); + + a += l & 0xffff; + b += l >>> 16; + c += h & 0xffff; + d += h >>> 16; // Maj h = (ah0 & ah1) ^ (ah0 & ah2) ^ (ah1 & ah2); l = (al0 & al1) ^ (al0 & al2) ^ (al1 & al2); - a += l & 0xffff; b += l >>> 16; - c += h & 0xffff; d += h >>> 16; + a += l & 0xffff; + b += l >>> 16; + c += h & 0xffff; + d += h >>> 16; b += a >>> 16; c += b >>> 16; @@ -1577,14 +2045,18 @@ function crypto_hashblocks_hl(hh: Int32Array, hl: Int32Array, m: Uint8Array, n: h = bh3; l = bl3; - a = l & 0xffff; b = l >>> 16; - c = h & 0xffff; d = h >>> 16; + a = l & 0xffff; + b = l >>> 16; + c = h & 0xffff; + d = h >>> 16; h = th; l = tl; - a += l & 0xffff; b += l >>> 16; - c += h & 0xffff; d += h >>> 16; + a += l & 0xffff; + b += l >>> 16; + c += h & 0xffff; + d += h >>> 16; b += a >>> 16; c += b >>> 16; @@ -1611,38 +2083,58 @@ function crypto_hashblocks_hl(hh: Int32Array, hl: Int32Array, m: Uint8Array, n: al7 = bl6; al0 = bl7; - if (i%16 === 15) { + if (i % 16 === 15) { for (j = 0; j < 16; j++) { // add h = wh[j]; l = wl[j]; - a = l & 0xffff; b = l >>> 16; - c = h & 0xffff; d = h >>> 16; + a = l & 0xffff; + b = l >>> 16; + c = h & 0xffff; + d = h >>> 16; - h = wh[(j+9)%16]; - l = wl[(j+9)%16]; + h = wh[(j + 9) % 16]; + l = wl[(j + 9) % 16]; - a += l & 0xffff; b += l >>> 16; - c += h & 0xffff; d += h >>> 16; + a += l & 0xffff; + b += l >>> 16; + c += h & 0xffff; + d += h >>> 16; // sigma0 - th = wh[(j+1)%16]; - tl = wl[(j+1)%16]; - h = ((th >>> 1) | (tl << (32-1))) ^ ((th >>> 8) | (tl << (32-8))) ^ (th >>> 7); - l = ((tl >>> 1) | (th << (32-1))) ^ ((tl >>> 8) | (th << (32-8))) ^ ((tl >>> 7) | (th << (32-7))); - - a += l & 0xffff; b += l >>> 16; - c += h & 0xffff; d += h >>> 16; + th = wh[(j + 1) % 16]; + tl = wl[(j + 1) % 16]; + h = + ((th >>> 1) | (tl << (32 - 1))) ^ + ((th >>> 8) | (tl << (32 - 8))) ^ + (th >>> 7); + l = + ((tl >>> 1) | (th << (32 - 1))) ^ + ((tl >>> 8) | (th << (32 - 8))) ^ + ((tl >>> 7) | (th << (32 - 7))); + + a += l & 0xffff; + b += l >>> 16; + c += h & 0xffff; + d += h >>> 16; // sigma1 - th = wh[(j+14)%16]; - tl = wl[(j+14)%16]; - h = ((th >>> 19) | (tl << (32-19))) ^ ((tl >>> (61-32)) | (th << (32-(61-32)))) ^ (th >>> 6); - l = ((tl >>> 19) | (th << (32-19))) ^ ((th >>> (61-32)) | (tl << (32-(61-32)))) ^ ((tl >>> 6) | (th << (32-6))); - - a += l & 0xffff; b += l >>> 16; - c += h & 0xffff; d += h >>> 16; + th = wh[(j + 14) % 16]; + tl = wl[(j + 14) % 16]; + h = + ((th >>> 19) | (tl << (32 - 19))) ^ + ((tl >>> (61 - 32)) | (th << (32 - (61 - 32)))) ^ + (th >>> 6); + l = + ((tl >>> 19) | (th << (32 - 19))) ^ + ((th >>> (61 - 32)) | (tl << (32 - (61 - 32)))) ^ + ((tl >>> 6) | (th << (32 - 6))); + + a += l & 0xffff; + b += l >>> 16; + c += h & 0xffff; + d += h >>> 16; b += a >>> 16; c += b >>> 16; @@ -1658,14 +2150,18 @@ function crypto_hashblocks_hl(hh: Int32Array, hl: Int32Array, m: Uint8Array, n: h = ah0; l = al0; - a = l & 0xffff; b = l >>> 16; - c = h & 0xffff; d = h >>> 16; + a = l & 0xffff; + b = l >>> 16; + c = h & 0xffff; + d = h >>> 16; h = hh[0]; l = hl[0]; - a += l & 0xffff; b += l >>> 16; - c += h & 0xffff; d += h >>> 16; + a += l & 0xffff; + b += l >>> 16; + c += h & 0xffff; + d += h >>> 16; b += a >>> 16; c += b >>> 16; @@ -1677,14 +2173,18 @@ function crypto_hashblocks_hl(hh: Int32Array, hl: Int32Array, m: Uint8Array, n: h = ah1; l = al1; - a = l & 0xffff; b = l >>> 16; - c = h & 0xffff; d = h >>> 16; + a = l & 0xffff; + b = l >>> 16; + c = h & 0xffff; + d = h >>> 16; h = hh[1]; l = hl[1]; - a += l & 0xffff; b += l >>> 16; - c += h & 0xffff; d += h >>> 16; + a += l & 0xffff; + b += l >>> 16; + c += h & 0xffff; + d += h >>> 16; b += a >>> 16; c += b >>> 16; @@ -1696,14 +2196,18 @@ function crypto_hashblocks_hl(hh: Int32Array, hl: Int32Array, m: Uint8Array, n: h = ah2; l = al2; - a = l & 0xffff; b = l >>> 16; - c = h & 0xffff; d = h >>> 16; + a = l & 0xffff; + b = l >>> 16; + c = h & 0xffff; + d = h >>> 16; h = hh[2]; l = hl[2]; - a += l & 0xffff; b += l >>> 16; - c += h & 0xffff; d += h >>> 16; + a += l & 0xffff; + b += l >>> 16; + c += h & 0xffff; + d += h >>> 16; b += a >>> 16; c += b >>> 16; @@ -1715,14 +2219,18 @@ function crypto_hashblocks_hl(hh: Int32Array, hl: Int32Array, m: Uint8Array, n: h = ah3; l = al3; - a = l & 0xffff; b = l >>> 16; - c = h & 0xffff; d = h >>> 16; + a = l & 0xffff; + b = l >>> 16; + c = h & 0xffff; + d = h >>> 16; h = hh[3]; l = hl[3]; - a += l & 0xffff; b += l >>> 16; - c += h & 0xffff; d += h >>> 16; + a += l & 0xffff; + b += l >>> 16; + c += h & 0xffff; + d += h >>> 16; b += a >>> 16; c += b >>> 16; @@ -1734,14 +2242,18 @@ function crypto_hashblocks_hl(hh: Int32Array, hl: Int32Array, m: Uint8Array, n: h = ah4; l = al4; - a = l & 0xffff; b = l >>> 16; - c = h & 0xffff; d = h >>> 16; + a = l & 0xffff; + b = l >>> 16; + c = h & 0xffff; + d = h >>> 16; h = hh[4]; l = hl[4]; - a += l & 0xffff; b += l >>> 16; - c += h & 0xffff; d += h >>> 16; + a += l & 0xffff; + b += l >>> 16; + c += h & 0xffff; + d += h >>> 16; b += a >>> 16; c += b >>> 16; @@ -1753,14 +2265,18 @@ function crypto_hashblocks_hl(hh: Int32Array, hl: Int32Array, m: Uint8Array, n: h = ah5; l = al5; - a = l & 0xffff; b = l >>> 16; - c = h & 0xffff; d = h >>> 16; + a = l & 0xffff; + b = l >>> 16; + c = h & 0xffff; + d = h >>> 16; h = hh[5]; l = hl[5]; - a += l & 0xffff; b += l >>> 16; - c += h & 0xffff; d += h >>> 16; + a += l & 0xffff; + b += l >>> 16; + c += h & 0xffff; + d += h >>> 16; b += a >>> 16; c += b >>> 16; @@ -1772,14 +2288,18 @@ function crypto_hashblocks_hl(hh: Int32Array, hl: Int32Array, m: Uint8Array, n: h = ah6; l = al6; - a = l & 0xffff; b = l >>> 16; - c = h & 0xffff; d = h >>> 16; + a = l & 0xffff; + b = l >>> 16; + c = h & 0xffff; + d = h >>> 16; h = hh[6]; l = hl[6]; - a += l & 0xffff; b += l >>> 16; - c += h & 0xffff; d += h >>> 16; + a += l & 0xffff; + b += l >>> 16; + c += h & 0xffff; + d += h >>> 16; b += a >>> 16; c += b >>> 16; @@ -1791,14 +2311,18 @@ function crypto_hashblocks_hl(hh: Int32Array, hl: Int32Array, m: Uint8Array, n: h = ah7; l = al7; - a = l & 0xffff; b = l >>> 16; - c = h & 0xffff; d = h >>> 16; + a = l & 0xffff; + b = l >>> 16; + c = h & 0xffff; + d = h >>> 16; h = hh[7]; l = hl[7]; - a += l & 0xffff; b += l >>> 16; - c += h & 0xffff; d += h >>> 16; + a += l & 0xffff; + b += l >>> 16; + c += h & 0xffff; + d += h >>> 16; b += a >>> 16; c += b >>> 16; @@ -1842,23 +2366,29 @@ function crypto_hash(out: Uint8Array, m: Uint8Array, n: number) { crypto_hashblocks_hl(hh, hl, m, n); n %= 128; - for (i = 0; i < n; i++) x[i] = m[b-n+i]; + for (i = 0; i < n; i++) x[i] = m[b - n + i]; x[n] = 128; - n = 256-128*(n<112?1:0); - x[n-9] = 0; - ts64(x, n-8, (b / 0x20000000) | 0, b << 3); + n = 256 - 128 * (n < 112 ? 1 : 0); + x[n - 9] = 0; + ts64(x, n - 8, (b / 0x20000000) | 0, b << 3); crypto_hashblocks_hl(hh, hl, x, n); - for (i = 0; i < 8; i++) ts64(out, 8*i, hh[i], hl[i]); + for (i = 0; i < 8; i++) ts64(out, 8 * i, hh[i], hl[i]); return 0; } function add(p: Float64Array[], q: Float64Array[]) { - var a = gf(), b = gf(), c = gf(), - d = gf(), e = gf(), f = gf(), - g = gf(), h = gf(), t = gf(); + var a = gf(), + b = gf(), + c = gf(), + d = gf(), + e = gf(), + f = gf(), + g = gf(), + h = gf(), + t = gf(); Z(a, p[1], p[0]); Z(t, q[1], q[0]); @@ -1889,7 +2419,9 @@ function cswap(p: Float64Array[], q: Float64Array[], b: number) { } function pack(r: Uint8Array, p: Float64Array[]) { - var tx = gf(), ty = gf(), zi = gf(); + var tx = gf(), + ty = gf(), + zi = gf(); inv25519(zi, p[2]); M(tx, p[0], zi); M(ty, p[1], zi); @@ -1904,7 +2436,7 @@ function scalarmult(p: Float64Array[], q: Float64Array[], s: Uint8Array) { set25519(p[2], gf1); set25519(p[3], gf0); for (i = 255; i >= 0; --i) { - b = (s[(i/8)|0] >> (i&7)) & 1; + b = (s[(i / 8) | 0] >> (i & 7)) & 1; cswap(p, q, b); add(q, p); add(p, p); @@ -1921,7 +2453,11 @@ function scalarbase(p: Float64Array[], s: Uint8Array) { scalarmult(p, q, s); } -function crypto_sign_keypair(pk: Uint8Array, sk: Uint8Array, seeded: boolean): number { +function crypto_sign_keypair( + pk: Uint8Array, + sk: Uint8Array, + seeded: boolean, +): number { const d = new Uint8Array(64); const p = [gf(), gf(), gf(), gf()]; @@ -1934,11 +2470,44 @@ function crypto_sign_keypair(pk: Uint8Array, sk: Uint8Array, seeded: boolean): n scalarbase(p, d); pack(pk, p); - for (let i = 0; i < 32; i++) sk[i+32] = pk[i]; + for (let i = 0; i < 32; i++) sk[i + 32] = pk[i]; return 0; } -var L = new Float64Array([0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10]); +var L = new Float64Array([ + 0xed, + 0xd3, + 0xf5, + 0x5c, + 0x1a, + 0x63, + 0x12, + 0x58, + 0xd6, + 0x9c, + 0xf7, + 0xa2, + 0xde, + 0xf9, + 0xde, + 0x14, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0x10, +]); function modL(r: Uint8Array, x: Float64Array) { var carry, i, j, k; @@ -1960,22 +2529,26 @@ function modL(r: Uint8Array, x: Float64Array) { } for (j = 0; j < 32; j++) x[j] -= carry * L[j]; for (i = 0; i < 32; i++) { - x[i+1] += x[i] >> 8; + x[i + 1] += x[i] >> 8; r[i] = x[i] & 255; } } function reduce(r: Uint8Array) { - var x = new Float64Array(64), i; - for (i = 0; i < 64; i++) x[i] = r[i]; - for (i = 0; i < 64; i++) r[i] = 0; + const x = new Float64Array(64); + for (let i = 0; i < 64; i++) x[i] = r[i]; + for (let i = 0; i < 64; i++) r[i] = 0; modL(r, x); } // Note: difference from C - smlen returned, not passed as argument. function crypto_sign(sm: Uint8Array, m: Uint8Array, n: number, sk: Uint8Array) { - var d = new Uint8Array(64), h = new Uint8Array(64), r = new Uint8Array(64); - var i, j, x = new Float64Array(64); + var d = new Uint8Array(64), + h = new Uint8Array(64), + r = new Uint8Array(64); + var i, + j, + x = new Float64Array(64); var p = [gf(), gf(), gf(), gf()]; crypto_hash(d, sk, 32); @@ -1987,7 +2560,7 @@ function crypto_sign(sm: Uint8Array, m: Uint8Array, n: number, sk: Uint8Array) { for (i = 0; i < n; i++) sm[64 + i] = m[i]; for (i = 0; i < 32; i++) sm[32 + i] = d[32 + i]; - crypto_hash(r, sm.subarray(32), n+32); + crypto_hash(r, sm.subarray(32), n + 32); reduce(r); scalarbase(p, r); pack(sm, p); @@ -2000,7 +2573,7 @@ function crypto_sign(sm: Uint8Array, m: Uint8Array, n: number, sk: Uint8Array) { for (i = 0; i < 32; i++) x[i] = r[i]; for (i = 0; i < 32; i++) { for (j = 0; j < 32; j++) { - x[i+j] += h[i] * d[j]; + x[i + j] += h[i] * d[j]; } } @@ -2009,9 +2582,13 @@ function crypto_sign(sm: Uint8Array, m: Uint8Array, n: number, sk: Uint8Array) { } function unpackneg(r: Float64Array[], p: Uint8Array) { - var t = gf(), chk = gf(), num = gf(), - den = gf(), den2 = gf(), den4 = gf(), - den6 = gf(); + const t = gf(); + const chk = gf(); + const num = gf(); + const den = gf(); + const den2 = gf(); + const den4 = gf(); + const den6 = gf(); set25519(r[2], gf1); unpack25519(r[1], p); @@ -2040,17 +2617,23 @@ function unpackneg(r: Float64Array[], p: Uint8Array) { M(chk, chk, den); if (neq25519(chk, num)) return -1; - if (par25519(r[0]) === (p[31]>>7)) Z(r[0], gf0, r[0]); + if (par25519(r[0]) === p[31] >> 7) Z(r[0], gf0, r[0]); M(r[3], r[0], r[1]); return 0; } -function crypto_sign_open(m: Uint8Array, sm: Uint8Array, n: number, pk: Uint8Array) { +function crypto_sign_open( + m: Uint8Array, + sm: Uint8Array, + n: number, + pk: Uint8Array, +) { var i, mlen; - var t = new Uint8Array(32), h = new Uint8Array(64); + var t = new Uint8Array(32), + h = new Uint8Array(64); var p = [gf(), gf(), gf(), gf()], - q = [gf(), gf(), gf(), gf()]; + q = [gf(), gf(), gf(), gf()]; mlen = -1; if (n < 64) return -1; @@ -2058,7 +2641,7 @@ function crypto_sign_open(m: Uint8Array, sm: Uint8Array, n: number, pk: Uint8Arr if (unpackneg(q, pk)) return -1; for (i = 0; i < n; i++) m[i] = sm[i]; - for (i = 0; i < 32; i++) m[i+32] = pk[i]; + for (i = 0; i < 32; i++) m[i + 32] = pk[i]; crypto_hash(h, m, n); reduce(h); scalarmult(p, q, h); @@ -2079,23 +2662,22 @@ function crypto_sign_open(m: Uint8Array, sm: Uint8Array, n: number, pk: Uint8Arr } var crypto_secretbox_KEYBYTES = 32, - crypto_secretbox_NONCEBYTES = 24, - crypto_secretbox_ZEROBYTES = 32, - crypto_secretbox_BOXZEROBYTES = 16, - crypto_scalarmult_BYTES = 32, - crypto_scalarmult_SCALARBYTES = 32, - crypto_box_PUBLICKEYBYTES = 32, - crypto_box_SECRETKEYBYTES = 32, - crypto_box_BEFORENMBYTES = 32, - crypto_box_NONCEBYTES = crypto_secretbox_NONCEBYTES, - crypto_box_ZEROBYTES = crypto_secretbox_ZEROBYTES, - crypto_box_BOXZEROBYTES = crypto_secretbox_BOXZEROBYTES, - crypto_sign_BYTES = 64, - crypto_sign_PUBLICKEYBYTES = 32, - crypto_sign_SECRETKEYBYTES = 64, - crypto_sign_SEEDBYTES = 32, - crypto_hash_BYTES = 64; - + crypto_secretbox_NONCEBYTES = 24, + crypto_secretbox_ZEROBYTES = 32, + crypto_secretbox_BOXZEROBYTES = 16, + crypto_scalarmult_BYTES = 32, + crypto_scalarmult_SCALARBYTES = 32, + crypto_box_PUBLICKEYBYTES = 32, + crypto_box_SECRETKEYBYTES = 32, + crypto_box_BEFORENMBYTES = 32, + crypto_box_NONCEBYTES = crypto_secretbox_NONCEBYTES, + crypto_box_ZEROBYTES = crypto_secretbox_ZEROBYTES, + crypto_box_BOXZEROBYTES = crypto_secretbox_BOXZEROBYTES, + crypto_sign_BYTES = 64, + crypto_sign_PUBLICKEYBYTES = 32, + crypto_sign_SECRETKEYBYTES = 64, + crypto_sign_SEEDBYTES = 32, + crypto_hash_BYTES = 64; const lowlevel = { crypto_core_hsalsa20: crypto_core_hsalsa20, @@ -2137,25 +2719,28 @@ const lowlevel = { crypto_sign_PUBLICKEYBYTES: crypto_sign_PUBLICKEYBYTES, crypto_sign_SECRETKEYBYTES: crypto_sign_SECRETKEYBYTES, crypto_sign_SEEDBYTES: crypto_sign_SEEDBYTES, - crypto_hash_BYTES: crypto_hash_BYTES + crypto_hash_BYTES: crypto_hash_BYTES, }; /* High-level API */ function checkLengths(k: Uint8Array, n: Uint8Array) { - if (k.length !== crypto_secretbox_KEYBYTES) throw new Error('bad key size'); - if (n.length !== crypto_secretbox_NONCEBYTES) throw new Error('bad nonce size'); + if (k.length !== crypto_secretbox_KEYBYTES) throw new Error("bad key size"); + if (n.length !== crypto_secretbox_NONCEBYTES) + throw new Error("bad nonce size"); } function checkBoxLengths(pk: Uint8Array, sk: Uint8Array) { - if (pk.length !== crypto_box_PUBLICKEYBYTES) throw new Error('bad public key size'); - if (sk.length !== crypto_box_SECRETKEYBYTES) throw new Error('bad secret key size'); + if (pk.length !== crypto_box_PUBLICKEYBYTES) + throw new Error("bad public key size"); + if (sk.length !== crypto_box_SECRETKEYBYTES) + throw new Error("bad secret key size"); } function checkArrayTypes(...args: Uint8Array[]) { for (var i = 0; i < args.length; i++) { if (!(args[i] instanceof Uint8Array)) - throw new TypeError('unexpected type, use Uint8Array'); + throw new TypeError("unexpected type, use Uint8Array"); } } @@ -2167,29 +2752,34 @@ export function randomBytes(n: number) { var b = new Uint8Array(n); randombytes(b, n); return b; -}; +} export function secretbox(msg: Uint8Array, nonce: Uint8Array, key: Uint8Array) { checkArrayTypes(msg, nonce, key); checkLengths(key, nonce); var m = new Uint8Array(crypto_secretbox_ZEROBYTES + msg.length); var c = new Uint8Array(m.length); - for (var i = 0; i < msg.length; i++) m[i+crypto_secretbox_ZEROBYTES] = msg[i]; + for (var i = 0; i < msg.length; i++) + m[i + crypto_secretbox_ZEROBYTES] = msg[i]; crypto_secretbox(c, m, m.length, nonce, key); return c.subarray(crypto_secretbox_BOXZEROBYTES); -}; - +} -export function secretbox_open(box: Uint8Array, nonce: Uint8Array, key: Uint8Array) { +export function secretbox_open( + box: Uint8Array, + nonce: Uint8Array, + key: Uint8Array, +) { checkArrayTypes(box, nonce, key); checkLengths(key, nonce); var c = new Uint8Array(crypto_secretbox_BOXZEROBYTES + box.length); var m = new Uint8Array(c.length); - for (var i = 0; i < box.length; i++) c[i+crypto_secretbox_BOXZEROBYTES] = box[i]; + for (var i = 0; i < box.length; i++) + c[i + crypto_secretbox_BOXZEROBYTES] = box[i]; if (c.length < 32) return null; if (crypto_secretbox_open(m, c, c.length, nonce, key) !== 0) return null; return m.subarray(crypto_secretbox_ZEROBYTES); -}; +} export const secretbox_keyLength = crypto_secretbox_KEYBYTES; export const secretbox_nonceLength = crypto_secretbox_NONCEBYTES; @@ -2197,28 +2787,33 @@ export const secretbox_overheadLength = crypto_secretbox_BOXZEROBYTES; export function scalarMult(n: Uint8Array, p: Uint8Array) { checkArrayTypes(n, p); - if (n.length !== crypto_scalarmult_SCALARBYTES) throw new Error('bad n size'); - if (p.length !== crypto_scalarmult_BYTES) throw new Error('bad p size'); + if (n.length !== crypto_scalarmult_SCALARBYTES) throw new Error("bad n size"); + if (p.length !== crypto_scalarmult_BYTES) throw new Error("bad p size"); var q = new Uint8Array(crypto_scalarmult_BYTES); crypto_scalarmult(q, n, p); return q; -}; +} export function scalarMult_base(n: Uint8Array) { checkArrayTypes(n); - if (n.length !== crypto_scalarmult_SCALARBYTES) throw new Error('bad n size'); + if (n.length !== crypto_scalarmult_SCALARBYTES) throw new Error("bad n size"); var q = new Uint8Array(crypto_scalarmult_BYTES); crypto_scalarmult_base(q, n); return q; -}; +} export const scalarMult_scalarLength = crypto_scalarmult_SCALARBYTES; export const scalarMult_groupElementLength = crypto_scalarmult_BYTES; -export function box(msg: Uint8Array, nonce: Uint8Array, publicKey: Uint8Array, secretKey: Uint8Array) { +export function box( + msg: Uint8Array, + nonce: Uint8Array, + publicKey: Uint8Array, + secretKey: Uint8Array, +) { var k = box_before(publicKey, secretKey); return secretbox(msg, nonce, k); -}; +} export function box_before(publicKey: Uint8Array, secretKey: Uint8Array) { checkArrayTypes(publicKey, secretKey); @@ -2226,14 +2821,19 @@ export function box_before(publicKey: Uint8Array, secretKey: Uint8Array) { var k = new Uint8Array(crypto_box_BEFORENMBYTES); crypto_box_beforenm(k, publicKey, secretKey); return k; -}; +} export const box_after = secretbox; -export function box_open(msg: Uint8Array, nonce: Uint8Array, publicKey: Uint8Array, secretKey: Uint8Array) { +export function box_open( + msg: Uint8Array, + nonce: Uint8Array, + publicKey: Uint8Array, + secretKey: Uint8Array, +) { var k = box_before(publicKey, secretKey); return secretbox_open(msg, nonce, k); -}; +} export const box_open_after = secretbox_open; @@ -2241,17 +2841,17 @@ export function box_keyPair() { var pk = new Uint8Array(crypto_box_PUBLICKEYBYTES); var sk = new Uint8Array(crypto_box_SECRETKEYBYTES); crypto_box_keypair(pk, sk); - return {publicKey: pk, secretKey: sk}; -}; + return { publicKey: pk, secretKey: sk }; +} export function box_keyPair_fromSecretKey(secretKey: Uint8Array) { checkArrayTypes(secretKey); if (secretKey.length !== crypto_box_SECRETKEYBYTES) - throw new Error('bad secret key size'); + throw new Error("bad secret key size"); var pk = new Uint8Array(crypto_box_PUBLICKEYBYTES); crypto_scalarmult_base(pk, secretKey); - return {publicKey: pk, secretKey: new Uint8Array(secretKey)}; -}; + return { publicKey: pk, secretKey: new Uint8Array(secretKey) }; +} export const box_publicKeyLength = crypto_box_PUBLICKEYBYTES; export const box_secretKeyLength = crypto_box_SECRETKEYBYTES; @@ -2262,57 +2862,62 @@ export const box_overheadLength = secretbox_overheadLength; export function sign(msg: Uint8Array, secretKey: Uint8Array) { checkArrayTypes(msg, secretKey); if (secretKey.length !== crypto_sign_SECRETKEYBYTES) - throw new Error('bad secret key size'); - var signedMsg = new Uint8Array(crypto_sign_BYTES+msg.length); + throw new Error("bad secret key size"); + var signedMsg = new Uint8Array(crypto_sign_BYTES + msg.length); crypto_sign(signedMsg, msg, msg.length, secretKey); return signedMsg; -}; +} export function sign_open(signedMsg: Uint8Array, publicKey: Uint8Array) { checkArrayTypes(signedMsg, publicKey); if (publicKey.length !== crypto_sign_PUBLICKEYBYTES) - throw new Error('bad public key size'); + throw new Error("bad public key size"); var tmp = new Uint8Array(signedMsg.length); var mlen = crypto_sign_open(tmp, signedMsg, signedMsg.length, publicKey); if (mlen < 0) return null; var m = new Uint8Array(mlen); for (var i = 0; i < m.length; i++) m[i] = tmp[i]; return m; -}; +} export function sign_detached(msg: Uint8Array, secretKey: Uint8Array) { var signedMsg = sign(msg, secretKey); var sig = new Uint8Array(crypto_sign_BYTES); for (var i = 0; i < sig.length; i++) sig[i] = signedMsg[i]; return sig; -}; +} -export function sign_detached_verify(msg: Uint8Array, sig: Uint8Array, publicKey: Uint8Array) { +export function sign_detached_verify( + msg: Uint8Array, + sig: Uint8Array, + publicKey: Uint8Array, +) { checkArrayTypes(msg, sig, publicKey); - if (sig.length !== crypto_sign_BYTES) - throw new Error('bad signature size'); + if (sig.length !== crypto_sign_BYTES) throw new Error("bad signature size"); if (publicKey.length !== crypto_sign_PUBLICKEYBYTES) - throw new Error('bad public key size'); + throw new Error("bad public key size"); var sm = new Uint8Array(crypto_sign_BYTES + msg.length); var m = new Uint8Array(crypto_sign_BYTES + msg.length); var i; for (i = 0; i < crypto_sign_BYTES; i++) sm[i] = sig[i]; - for (i = 0; i < msg.length; i++) sm[i+crypto_sign_BYTES] = msg[i]; - return (crypto_sign_open(m, sm, sm.length, publicKey) >= 0); -}; + for (i = 0; i < msg.length; i++) sm[i + crypto_sign_BYTES] = msg[i]; + return crypto_sign_open(m, sm, sm.length, publicKey) >= 0; +} export function sign_keyPair() { var pk = new Uint8Array(crypto_sign_PUBLICKEYBYTES); var sk = new Uint8Array(crypto_sign_SECRETKEYBYTES); crypto_sign_keypair(pk, sk, false); - return {publicKey: pk, secretKey: sk}; -}; + return { publicKey: pk, secretKey: sk }; +} -export function x25519_edwards_keyPair_fromSecretKey(secretKey: Uint8Array): Uint8Array { +export function x25519_edwards_keyPair_fromSecretKey( + secretKey: Uint8Array, +): Uint8Array { const p = [gf(), gf(), gf(), gf()]; const pk = new Uint8Array(32); - const d = new Uint8Array(64) + const d = new Uint8Array(64); if (secretKey.length != 32) { throw new Error("bad secret key size"); } @@ -2326,28 +2931,27 @@ export function x25519_edwards_keyPair_fromSecretKey(secretKey: Uint8Array): Uin scalarbase(p, d); pack(pk, p); - return pk + return pk; } export function sign_keyPair_fromSecretKey(secretKey: Uint8Array) { checkArrayTypes(secretKey); if (secretKey.length !== crypto_sign_SECRETKEYBYTES) - throw new Error('bad secret key size'); + throw new Error("bad secret key size"); var pk = new Uint8Array(crypto_sign_PUBLICKEYBYTES); - for (var i = 0; i < pk.length; i++) pk[i] = secretKey[32+i]; - return {publicKey: pk, secretKey: new Uint8Array(secretKey)}; -}; + for (var i = 0; i < pk.length; i++) pk[i] = secretKey[32 + i]; + return { publicKey: pk, secretKey: new Uint8Array(secretKey) }; +} export function sign_keyPair_fromSeed(seed: Uint8Array) { checkArrayTypes(seed); - if (seed.length !== crypto_sign_SEEDBYTES) - throw new Error('bad seed size'); + if (seed.length !== crypto_sign_SEEDBYTES) throw new Error("bad seed size"); var pk = new Uint8Array(crypto_sign_PUBLICKEYBYTES); var sk = new Uint8Array(crypto_sign_SECRETKEYBYTES); for (var i = 0; i < 32; i++) sk[i] = seed[i]; crypto_sign_keypair(pk, sk, true); - return {publicKey: pk, secretKey: sk}; -}; + return { publicKey: pk, secretKey: sk }; +} export const sign_publicKeyLength = crypto_sign_PUBLICKEYBYTES; export const sign_secretKeyLength = crypto_sign_SECRETKEYBYTES; @@ -2359,7 +2963,7 @@ export function hash(msg: Uint8Array) { var h = new Uint8Array(crypto_hash_BYTES); crypto_hash(h, msg, msg.length); return h; -}; +} export const hash_hashLength = crypto_hash_BYTES; @@ -2368,37 +2972,65 @@ export function verify(x: Uint8Array, y: Uint8Array) { // Zero length arguments are considered not equal. if (x.length === 0 || y.length === 0) return false; if (x.length !== y.length) return false; - return (vn(x, 0, y, 0, x.length) === 0) ? true : false; + return vn(x, 0, y, 0, x.length) === 0 ? true : false; } export function setPRNG(fn: (x: Uint8Array, n: number) => void) { randombytes = fn; } +export function sign_ed25519_pk_to_curve25519( + ed25519_pk: Uint8Array, +): Uint8Array { + const ge_a = [gf(), gf(), gf(), gf()]; + const x = gf(); + const one_minus_y = gf(); + const x25519_pk = new Uint8Array(32); + + if (unpackneg(ge_a, ed25519_pk)) { + throw Error("invalid public key"); + } + + set25519(one_minus_y, gf1); + Z(one_minus_y, one_minus_y, ge_a[1]); + + set25519(x, gf1); + A(x, x, ge_a[1]); + + inv25519(one_minus_y, one_minus_y); + M(x, x, one_minus_y); + pack25519(x25519_pk, x); + + return x25519_pk; +} + (function() { // Initialize PRNG if environment provides CSPRNG. // If not, methods calling randombytes will throw. - const crypto = typeof self !== 'undefined' ? (self.crypto || (self as any).msCrypto) : null; + const crypto = + typeof self !== "undefined" ? self.crypto || (self as any).msCrypto : null; if (crypto && crypto.getRandomValues) { // Browsers. var QUOTA = 65536; setPRNG(function(x: Uint8Array, n: number) { - var i, v = new Uint8Array(n); + var i, + v = new Uint8Array(n); for (i = 0; i < n; i += QUOTA) { crypto.getRandomValues(v.subarray(i, i + Math.min(n - i, QUOTA))); } for (i = 0; i < n; i++) x[i] = v[i]; cleanup(v); }); - } else if (typeof require !== 'undefined') { + } else if (typeof require !== "undefined") { // Node.js. - const cr = require('crypto'); + const cr = require("crypto"); if (cr && cr.randomBytes) { setPRNG(function(x: Uint8Array, n: number) { - var i, v = cr.randomBytes(n); + var i, + v = cr.randomBytes(n); for (i = 0; i < n; i++) x[i] = v[i]; cleanup(v); }); } } -})();
\ No newline at end of file +})(); diff --git a/src/crypto/nativeCrypto-test.ts b/src/crypto/nativeCrypto-test.ts deleted file mode 100644 index c38110577..000000000 --- a/src/crypto/nativeCrypto-test.ts +++ /dev/null @@ -1,85 +0,0 @@ -/* - This file is part of GNU Taler - (C) 2019 GNUnet e.V. - - GNU Taler is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/> - */ - -/** - * Imports - */ -import test from "ava"; -import { encodeCrock, decodeCrock } from "./nativeCrypto"; -import { hmacSha512, sha512 } from "./kdf"; -import nacl = require("./nacl-fast"); - -function hexToBytes(hex: string) { - for (var bytes = [], c = 0; c < hex.length; c += 2) - bytes.push(parseInt(hex.substr(c, 2), 16)); - return bytes; -} - -function bytesToHex(bytes: Uint8Array): string { - for (var hex = [], i = 0; i < bytes.length; i++) { - var current = bytes[i] < 0 ? bytes[i] + 256 : bytes[i]; - hex.push((current >>> 4).toString(16)); - hex.push((current & 0xf).toString(16)); - } - return hex.join(""); -} - -test("encoding", t => { - const utf8decoder = new TextDecoder("utf-8"); - const utf8encoder = new TextEncoder(); - const s = "Hello, World"; - const encStr = encodeCrock(utf8encoder.encode(s)); - const outBuf = decodeCrock(encStr); - const sOut = utf8decoder.decode(outBuf); - t.deepEqual(s, sOut); -}); - -test("taler-exchange-tvg hash code", t => { - const input = "91JPRV3F5GG4EKJN41A62V35E8"; - const output = - "CW96WR74JS8T53EC8GKSGD49QKH4ZNFTZXDAWMMV5GJ1E4BM6B8GPN5NVHDJ8ZVXNCW7Q4WBYCV61HCA3PZC2YJD850DT29RHHN7ESR"; - - const myOutput = encodeCrock(sha512(decodeCrock(input))); - - t.deepEqual(myOutput, output); -}); - -test("taler-exchange-tvg ecdhe key", t => { - const priv1 = "YSYA38XH1PH40ZPSEZCXEFX9PH9Q3A2PE19FHM54DMTZ4MAPH9S0"; - const pub1 = "GNQRNSYF4BT4V0EV0DBXZCHFVQ79ATP0KBJ9EAY18FGSY513A5VG"; - - const myPub = nacl.x25519_edwards_keyPair_fromSecretKey(decodeCrock(priv1)) - t.deepEqual(encodeCrock(myPub), pub1); - - //const myPub1 = nacl.scalarMult.base(decodeCrock(priv1)); - //t.deepEqual(encodeCrock(myPub1), pub1); - - //const p = nacl.box.keyPair.fromSecretKey(decodeCrock(priv1)) - //t.deepEqual(encodeCrock(p.publicKey), pub1); - - //const r = nacl.scalarMult(decodeCrock(priv2), decodeCrock(pub1)); - //t.deepEqual(encodeCrock(nacl.hash(r)), skm); - - //const mySkm = nacl. -}); - -test("taler-exchange-tvg eddsa key", t => { - const priv = "H2JGQ2T3A5WBC5QV3YRFE31AMRGF2F9WPXZ03EM3NS3PYHM80WA0"; - const pub = "QFGMB2WTPYXMXZRPFYFEM2VMQ028M71JMECF31P3J8VC3SCJ777G"; - - const pair = nacl.sign_keyPair_fromSeed(decodeCrock(priv)); - t.deepEqual(encodeCrock(pair.publicKey), pub); -}); diff --git a/src/crypto/nativeCrypto.ts b/src/crypto/nativeCrypto.ts deleted file mode 100644 index 306d22009..000000000 --- a/src/crypto/nativeCrypto.ts +++ /dev/null @@ -1,140 +0,0 @@ -/* - This file is part of GNU Taler - (C) 2019 GNUnet e.V. - - GNU Taler is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/> - */ - -/** - * Native implementation of GNU Taler crypto. - */ - -let isNode; - -let myGetRandom: (n: number) => ArrayBuffer; - -if (require) { - // node.js - const cr = require("crypto"); - myGetRandom = (n: number) => { - const buf = cr.randomBytes(n); - return Uint8Array.from(buf); - } -} else { - // Browser - myGetRandom = (n: number) => { - const ret = new Uint8Array(n); - window.crypto.getRandomValues(ret); - return ret; - } -} - -export function getRandomBytes(n: number): ArrayBuffer { - return myGetRandom(n); -} - -const encTable = "0123456789ABCDEFGHJKMNPQRSTVWXYZ"; - -class EncodingError extends Error { - constructor() { - super("Encoding error"); - Object.setPrototypeOf(this, EncodingError.prototype); - } -} - -function getValue(chr: string): number { - let a = chr; - switch (chr) { - case "O": - case "o": - a = "0;"; - break; - case "i": - case "I": - case "l": - case "L": - a = "1"; - break; - case "u": - case "U": - a = "V"; - } - - if (a >= "0" && a <= "9") { - return a.charCodeAt(0) - "0".charCodeAt(0); - } - - if (a >= "a" && a <= "z") a = a.toUpperCase(); - let dec = 0; - if (a >= "A" && a <= "Z") { - if ("I" < a) dec++; - if ("L" < a) dec++; - if ("O" < a) dec++; - if ("U" < a) dec++; - return a.charCodeAt(0) - "A".charCodeAt(0) + 10 - dec; - } - throw new EncodingError(); -} - -export function encodeCrock(data: ArrayBuffer): string { - const dataBytes = new Uint8Array(data); - let sb = ""; - const size = data.byteLength; - let bitBuf = 0; - let numBits = 0; - let pos = 0; - while (pos < size || numBits > 0) { - if (pos < size && numBits < 5) { - const d = dataBytes[pos++]; - bitBuf = (bitBuf << 8) | d; - numBits += 8; - } - if (numBits < 5) { - // zero-padding - bitBuf = bitBuf << (5 - numBits); - numBits = 5; - } - const v = (bitBuf >>> (numBits - 5)) & 31; - sb += encTable[v]; - numBits -= 5; - } - return sb; -} - -export function decodeCrock(encoded: string): Uint8Array { - const size = encoded.length; - let bitpos = 0; - let bitbuf = 0; - let readPosition = 0; - const outLen = Math.floor((size * 5) / 8); - const out = new Uint8Array(outLen); - let outPos = 0; - - while (readPosition < size || bitpos > 0) { - //println("at position $readPosition with bitpos $bitpos") - if (readPosition < size) { - const v = getValue(encoded[readPosition++]); - bitbuf = (bitbuf << 5) | v; - bitpos += 5; - } - while (bitpos >= 8) { - const d = (bitbuf >>> (bitpos - 8)) & 0xff; - out[outPos++] = d; - bitpos -= 8; - } - if (readPosition == size && bitpos > 0) { - bitbuf = (bitbuf << (8 - bitpos)) & 0xff; - bitpos = bitbuf == 0 ? 0 : 8; - } - } - return out; -} diff --git a/src/crypto/talerCrypto-test.ts b/src/crypto/talerCrypto-test.ts new file mode 100644 index 000000000..3f9d6f398 --- /dev/null +++ b/src/crypto/talerCrypto-test.ts @@ -0,0 +1,161 @@ +/* + This file is part of GNU Taler + (C) 2019 GNUnet e.V. + + GNU Taler is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + */ + +/** + * Imports + */ +import test from "ava"; +import { + encodeCrock, + decodeCrock, + ecdheGetPublic, + eddsaGetPublic, + keyExchangeEddsaEcdhe, + keyExchangeEcdheEddsa, + rsaBlind, + rsaUnblind, + rsaVerify, +} from "./talerCrypto"; +import { hmacSha512, sha512, kdf } from "./kdf"; +import nacl = require("./nacl-fast"); + +function hexToBytes(hex: string) { + for (var bytes = [], c = 0; c < hex.length; c += 2) + bytes.push(parseInt(hex.substr(c, 2), 16)); + return bytes; +} + +function bytesToHex(bytes: Uint8Array): string { + for (var hex = [], i = 0; i < bytes.length; i++) { + var current = bytes[i] < 0 ? bytes[i] + 256 : bytes[i]; + hex.push((current >>> 4).toString(16)); + hex.push((current & 0xf).toString(16)); + } + return hex.join(""); +} + +test("encoding", t => { + const utf8decoder = new TextDecoder("utf-8"); + const utf8encoder = new TextEncoder(); + const s = "Hello, World"; + const encStr = encodeCrock(utf8encoder.encode(s)); + const outBuf = decodeCrock(encStr); + const sOut = utf8decoder.decode(outBuf); + t.deepEqual(s, sOut); +}); + +test("taler-exchange-tvg hash code", t => { + const input = "91JPRV3F5GG4EKJN41A62V35E8"; + const output = + "CW96WR74JS8T53EC8GKSGD49QKH4ZNFTZXDAWMMV5GJ1E4BM6B8GPN5NVHDJ8ZVXNCW7Q4WBYCV61HCA3PZC2YJD850DT29RHHN7ESR"; + + const myOutput = encodeCrock(sha512(decodeCrock(input))); + + t.deepEqual(myOutput, output); +}); + +test("taler-exchange-tvg ecdhe key", t => { + const priv1 = "X4T4N0M8PVQXQEBW2BA7049KFSM7J437NSDFC6GDNM3N5J9367A0"; + const pub1 = "M997P494MS6A95G1P0QYWW2VNPSHSX5Q6JBY5B9YMNYWP0B50X3G"; + const priv2 = "14A0MMQ64DCV8HE0CS3WBC9DHFJAHXRGV7NEARFJPC5R5E1697E0"; + const skm = + "NXRY2YCY7H9B6KM928ZD55WG964G59YR0CPX041DYXKBZZ85SAWNPQ8B30QRM5FMHYCXJAN0EAADJYWEF1X3PAC2AJN28626TR5A6AR"; + + const myPub1 = nacl.scalarMult_base(decodeCrock(priv1)); + t.deepEqual(encodeCrock(myPub1), pub1); + + const mySkm = nacl.hash( + nacl.scalarMult(decodeCrock(priv2), decodeCrock(pub1)), + ); + t.deepEqual(encodeCrock(mySkm), skm); +}); + +test("taler-exchange-tvg eddsa key", t => { + const priv = "9TM70AKDTS57AWY9JK2J4TMBTMW6K62WHHGZWYDG0VM5ABPZKD40"; + const pub = "8GSJZ649T2PXMKZC01Y4ANNBE7MF14QVK9SQEC4E46ZHKCVG8AS0"; + + const pair = nacl.sign_keyPair_fromSeed(decodeCrock(priv)); + t.deepEqual(encodeCrock(pair.publicKey), pub); +}); + +test("taler-exchange-tvg kdf", t => { + const salt = "94KPT83PCNS7J83KC5P78Y8"; + const ikm = "94KPT83MD1JJ0WV5CDS6AX10D5Q70XBM41NPAY90DNGQ8SBJD5GPR"; + const ctx = + "94KPT83141HPYVKMCNW78833D1TPWTSC41GPRWVF41NPWVVQDRG62WS04XMPWSKF4WG6JVH0EHM6A82J8S1G"; + const outLen = 64; + const out = + "GTMR4QT05Z9WF5HKVG0WK9RPXGHSMHJNW377G9GJXCA8B0FEKPF4D27RJMSJZYWSQNTBJ5EYVV7ZW18B48Z0JVJJ80RHB706Y96Q358"; + + const myOut = kdf( + outLen, + decodeCrock(ikm), + decodeCrock(salt), + decodeCrock(ctx), + ); + + t.deepEqual(encodeCrock(myOut), out); +}); + +test("taler-exchange-tvg eddsa_ecdh", t => { + const priv_ecdhe = "4AFZWMSGTVCHZPQ0R81NWXDCK4N58G7SDBBE5KXE080Y50370JJG"; + const pub_ecdhe = "FXFN5GPAFTKVPWJDPVXQ87167S8T82T5ZV8CDYC0NH2AE14X0M30"; + const priv_eddsa = "1KG54M8T3X8BSFSZXCR3SQBSR7Y9P53NX61M864S7TEVMJ2XVPF0"; + const pub_eddsa = "7BXWKG6N224C57RTDV8XEAHR108HG78NMA995BE8QAT5GC1S7E80"; + const key_material = + "PKZ42Z56SVK2796HG1QYBRJ6ZQM2T9QGA3JA4AAZ8G7CWK9FPX175Q9JE5P0ZAX3HWWPHAQV4DPCK10R9X3SAXHRV0WF06BHEC2ZTKR"; + + const myEcdhePub = ecdheGetPublic(decodeCrock(priv_ecdhe)); + t.deepEqual(encodeCrock(myEcdhePub), pub_ecdhe); + + const myEddsaPub = eddsaGetPublic(decodeCrock(priv_eddsa)); + t.deepEqual(encodeCrock(myEddsaPub), pub_eddsa); + + const myKm1 = keyExchangeEddsaEcdhe( + decodeCrock(priv_eddsa), + decodeCrock(pub_ecdhe), + ); + t.deepEqual(encodeCrock(myKm1), key_material); + + const myKm2 = keyExchangeEcdheEddsa( + decodeCrock(priv_ecdhe), + decodeCrock(pub_eddsa), + ); + t.deepEqual(encodeCrock(myKm2), key_material); +}); + +test("taler-exchange-tvg blind signing", t => { + const messageHash = + "TT1R28D79EJEJ9PC35AQS35CCG85DSXSZ508MV2HS2FN4ME6AHESZX5WP485R8A75KG53FN6F1YNW95008663TKAPWB81420VG17BY8"; + const rsaPublicKey = + "040000Y62RSDDKZXTE7GDVA302ZZR0DY224RSDT6WDWR1XGT8E3YG80XV6TMT3ZCNP8XC84W0N6MSZ0EF8S3YB1JJ2AXY9JQZW3MCA0CG38ER4YE2RY4Q2666DEZSNKT29V6CKZVCDHXSAKY8W6RPEKEQ5YSBYQK23MRK3CQTNNJXQFDKEMRHEC5Y6RDHAC5RJCV8JJ8BF18VPKZ2Q7BB14YN1HJ22H8EZGW0RDGG9YPEWA9183BHEQ651PP81J514TJ9K8DH23AJ50SZFNS429HQ390VRP5E4MQ7RK7ZJXXTSZAQSRTC0QF28P23PD37C17QFQB0BBC54MB8MDH7RW104STG6VN0J22P39JP4EXPVGK5D9AX5W869MDQ6SRD42ZYK5H20227Q8CCWSQ6C3132WP0F0H04002"; + const bks = "7QD31RPJH0W306RJWBRG646Z2FTA1F89BKSXPDAG7YM0N5Z0B610"; + const bm = + "GA8PC6YH9VF5MW6P2DKTV0W0ZTQ24DZ9EAN5QH3SQXRH7SCZHFMM21ZY05F0BS7MFW8TSEP4SEB280BYP5ACHNQWGE10PCXDDMK7ECXJDPHJ224JBCV4KYNWG6NBR3SC9HK8FXVFX55GFBJFNQHNZGEB8DB0KN9MSVYFDXN45KPMSNY03FVX0JZ0R3YG9XQ8XVGB5SYZCF0QSHWH61MT0Q10CZD2V114BT64D3GD86EJ5S9WBMYG51SDN5CSKEJ734YAJ4HCEWW0RDN8GXA9ZMA18SKVW8T3TTBCPJRF2Y77JGQ08GF35SYGA2HWFV1HGVS8RCTER6GB9SZHRG4T7919H9C1KFAP50G2KSV6X42D6KNJANNSGKQH649TJ00YJQXPHPNFBSS198RY2C243D4B4W"; + const bs = + "5VW0MS5PRBA3W8TPATSTDA2YRFQM1Z7F2DWKQ8ATMZYYY768Q3STZ3HGNVYQ6JB5NKP80G5HGE58616FPA70SX9PTW7EN8EJ23E26FASBWZBP8E2RWQQ5E0F72B2PWRP5ZCA2J3AB3F6P86XK4PZYT64RF94MDGHY0GSDSSBH5YSFB3VM0KVXA52H2Y2G9S85AVCSD3BTMHQRF5BJJ8JE00T4GK70PSTVCGMRKRNA7DGW7GD2F35W55AXF7R2YJC8PAGNSJYWKC3PC75A5N8H69K299AK5PM3CDDHNS4BMRNGF7K49CR4ZBFRXDAWMB3X6T05Q4NKSG0F1KP5JA0XBMF2YJK7KEPRD1EWCHJE44T9YXBTK4W9CV77X7Z9P407ZC6YB3M2ARANZXHJKSM3XC33M"; + const sig = + "PFT6WQJGCM9DE6264DJS6RMG4XDMCDBJKZGSXAF3BEXWZ979Q13NETKK05S1YV91CX3Y034FSS86SSHZTTE8097RRESQP52EKFGTWJXKHZJEQJ49YHMBNQDHW4CFBJECNJSV2PMHWVGXV7HB84R6P0S3ES559HWQX01Q9MYDEGRNHKW87QR2BNSG951D5NQGAKEJ2SSJBE18S6WYAC24FAP8TT8ANECH5371J0DJY0YR0VWAFWVJDV8XQSFXWMJ80N3A80SPSHPYJY3WZZXW63WQ46WHYY56ZSNE5G1RZ5CR0XYV2ECKPM8R0FS58EV16WTRAM1ABBFVNAT3CAEFAZCWP3XHPVBQY5NZVTD5QS2Q8SKJQ2XB30E11CWDN9KTV5CBK4DN72EVG73F3W3BATAKHG"; + + const myBm = rsaBlind(decodeCrock(messageHash), decodeCrock(bks), decodeCrock(rsaPublicKey)); + t.deepEqual(encodeCrock(myBm), bm); + + const mySig = rsaUnblind(decodeCrock(bs), decodeCrock(rsaPublicKey), decodeCrock(bks)); + t.deepEqual(encodeCrock(mySig), sig); + + const v = rsaVerify(decodeCrock(messageHash), decodeCrock(sig), decodeCrock(rsaPublicKey)); + t.true(v); +}); diff --git a/src/crypto/talerCrypto.ts b/src/crypto/talerCrypto.ts new file mode 100644 index 000000000..0a36f0fe4 --- /dev/null +++ b/src/crypto/talerCrypto.ts @@ -0,0 +1,277 @@ +/* + This file is part of GNU Taler + (C) 2019 GNUnet e.V. + + GNU Taler is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + */ + +/** + * Native implementation of GNU Taler crypto. + */ + +import nacl = require("./nacl-fast"); +import bigint from "big-integer"; +import { kdf } from "./kdf"; + +export function getRandomBytes(n: number): Uint8Array { + return nacl.randomBytes(n); +} + +const encTable = "0123456789ABCDEFGHJKMNPQRSTVWXYZ"; + +class EncodingError extends Error { + constructor() { + super("Encoding error"); + Object.setPrototypeOf(this, EncodingError.prototype); + } +} + +function getValue(chr: string): number { + let a = chr; + switch (chr) { + case "O": + case "o": + a = "0;"; + break; + case "i": + case "I": + case "l": + case "L": + a = "1"; + break; + case "u": + case "U": + a = "V"; + } + + if (a >= "0" && a <= "9") { + return a.charCodeAt(0) - "0".charCodeAt(0); + } + + if (a >= "a" && a <= "z") a = a.toUpperCase(); + let dec = 0; + if (a >= "A" && a <= "Z") { + if ("I" < a) dec++; + if ("L" < a) dec++; + if ("O" < a) dec++; + if ("U" < a) dec++; + return a.charCodeAt(0) - "A".charCodeAt(0) + 10 - dec; + } + throw new EncodingError(); +} + +export function encodeCrock(data: ArrayBuffer): string { + const dataBytes = new Uint8Array(data); + let sb = ""; + const size = data.byteLength; + let bitBuf = 0; + let numBits = 0; + let pos = 0; + while (pos < size || numBits > 0) { + if (pos < size && numBits < 5) { + const d = dataBytes[pos++]; + bitBuf = (bitBuf << 8) | d; + numBits += 8; + } + if (numBits < 5) { + // zero-padding + bitBuf = bitBuf << (5 - numBits); + numBits = 5; + } + const v = (bitBuf >>> (numBits - 5)) & 31; + sb += encTable[v]; + numBits -= 5; + } + return sb; +} + +export function decodeCrock(encoded: string): Uint8Array { + const size = encoded.length; + let bitpos = 0; + let bitbuf = 0; + let readPosition = 0; + const outLen = Math.floor((size * 5) / 8); + const out = new Uint8Array(outLen); + let outPos = 0; + + while (readPosition < size || bitpos > 0) { + if (readPosition < size) { + const v = getValue(encoded[readPosition++]); + bitbuf = (bitbuf << 5) | v; + bitpos += 5; + } + while (bitpos >= 8) { + const d = (bitbuf >>> (bitpos - 8)) & 0xff; + out[outPos++] = d; + bitpos -= 8; + } + if (readPosition == size && bitpos > 0) { + bitbuf = (bitbuf << (8 - bitpos)) & 0xff; + bitpos = bitbuf == 0 ? 0 : 8; + } + } + return out; +} + +export function eddsaGetPublic(eddsaPriv: Uint8Array): Uint8Array { + const pair = nacl.sign_keyPair_fromSeed(eddsaPriv); + return pair.publicKey; +} + +export function ecdheGetPublic(ecdhePriv: Uint8Array): Uint8Array { + return nacl.scalarMult_base(ecdhePriv); +} + +export function keyExchangeEddsaEcdhe(eddsaPriv: Uint8Array, ecdhePub: Uint8Array): Uint8Array { + const ph = nacl.hash(eddsaPriv); + const a = new Uint8Array(32); + for (let i = 0; i < 32; i++) { + a[i] = ph[i]; + } + const x = nacl.scalarMult(a, ecdhePub); + return nacl.hash(x); +} + +export function keyExchangeEcdheEddsa(ecdhePriv: Uint8Array, eddsaPub: Uint8Array): Uint8Array { + const curve25519Pub = nacl.sign_ed25519_pk_to_curve25519(eddsaPub); + const x = nacl.scalarMult(ecdhePriv, curve25519Pub); + return nacl.hash(x); +} + +interface RsaPub { + N: bigint.BigInteger; + e: bigint.BigInteger; +} + +interface RsaBlindingKey { + r: bigint.BigInteger; +} + +/** + * KDF modulo a big integer. + */ +function kdfMod( + n: bigint.BigInteger, + ikm: Uint8Array, + salt: Uint8Array, + info: Uint8Array, +): bigint.BigInteger { + const nbits = n.bitLength().toJSNumber(); + const buflen = Math.floor((nbits - 1) / 8 + 1); + const mask = (1 << (8 - (buflen * 8 - nbits))) - 1; + let counter = 0; + while (true) { + const ctx = new Uint8Array(info.byteLength + 2); + ctx.set(info, 0); + ctx[ctx.length - 2] = (counter >>> 8) & 0xFF; + ctx[ctx.length - 1] = counter & 0xFF; + const buf = kdf(buflen, ikm, salt, ctx); + const arr = Array.from(buf); + arr[0] = arr[0] & mask; + const r = bigint.fromArray(arr, 256, false); + if (r.lt(n)) { + return r; + } + counter++; + } +} + +function stringToBuf(s: string) { + const te = new TextEncoder(); + return te.encode(s); +} + +function loadBigInt(arr: Uint8Array) { + return bigint.fromArray(Array.from(arr), 256, false); +} + +function rsaBlindingKeyDerive(rsaPub: RsaPub, bks: Uint8Array): bigint.BigInteger { + const salt = stringToBuf("Blinding KDF extrator HMAC key"); + const info = stringToBuf("Blinding KDF"); + return kdfMod(rsaPub.N, bks, salt, info); +} + +/* + * Test for malicious RSA key. + * + * Assuming n is an RSA modulous and r is generated using a call to + * GNUNET_CRYPTO_kdf_mod_mpi, if gcd(r,n) != 1 then n must be a + * malicious RSA key designed to deanomize the user. + * + * @param r KDF result + * @param n RSA modulus of the public key + */ +function rsaGcdValidate(r: bigint.BigInteger, n: bigint.BigInteger) { + const t = bigint.gcd(r, n); + if (!t.equals(bigint.one)) { + throw Error("malicious RSA public key"); + } +} + +function rsaFullDomainHash(hm: Uint8Array, rsaPub: RsaPub): bigint.BigInteger { + const info = stringToBuf("RSA-FDA FTpsW!"); + const salt = rsaPubEncode(rsaPub); + const r = kdfMod(rsaPub.N, hm, salt, info); + rsaGcdValidate(r, rsaPub.N); + return r; +} + +function rsaPubDecode(rsaPub: Uint8Array): RsaPub { + const modulusLength = (rsaPub[0] << 8) | rsaPub[1]; + const exponentLength = (rsaPub[2] << 8) | rsaPub[3]; + const modulus = rsaPub.slice(4, 4 + modulusLength) + const exponent = rsaPub.slice(4 + modulusLength, 4 + modulusLength + exponentLength); + const res = { + N: loadBigInt(modulus), + e: loadBigInt(exponent), + } + return res; +} + +function rsaPubEncode(rsaPub: RsaPub): Uint8Array { + const mb = rsaPub.N.toArray(256).value; + const eb = rsaPub.e.toArray(256).value; + const out = new Uint8Array(4 + mb.length + eb.length); + out[0] = (mb.length >>> 8) & 0xFF; + out[1] = mb.length & 0xFF; + out[2] = (eb.length >>> 8) & 0xFF; + out[3] = eb.length & 0xFF; + out.set(mb, 4); + out.set(eb, 4 + mb.length); + return out; +} + +export function rsaBlind(hm: Uint8Array, bks: Uint8Array, rsaPubEnc: Uint8Array): Uint8Array { + const rsaPub = rsaPubDecode(rsaPubEnc); + const data = rsaFullDomainHash(hm, rsaPub); + const r = rsaBlindingKeyDerive(rsaPub, bks); + const r_e = r.modPow(rsaPub.e, rsaPub.N); + const bm = r_e.multiply(data).mod(rsaPub.N); + return new Uint8Array(bm.toArray(256).value); +} + +export function rsaUnblind(sig: Uint8Array, rsaPubEnc: Uint8Array, bks: Uint8Array): Uint8Array { + const rsaPub = rsaPubDecode(rsaPubEnc); + const blinded_s = loadBigInt(sig); + const r = rsaBlindingKeyDerive(rsaPub, bks); + const r_inv = r.modInv(rsaPub.N); + const s = blinded_s.multiply(r_inv).mod(rsaPub.N); + return new Uint8Array(s.toArray(256).value); +} + +export function rsaVerify(hm: Uint8Array, rsaSig: Uint8Array, rsaPubEnc: Uint8Array): boolean { + const rsaPub = rsaPubDecode(rsaPubEnc); + const d = rsaFullDomainHash(hm, rsaPub); + const sig = loadBigInt(rsaSig); + const sig_e = sig.modPow(rsaPub.e, rsaPub.N); + return sig_e.equals(d); +}
\ No newline at end of file |