From 33b8a7477d18a2ee207c3ec9369a5b5bc411eecf Mon Sep 17 00:00:00 2001 From: Brandon Berhent Date: Thu, 2 May 2019 14:33:14 -0400 Subject: [PATCH] Don't use nanocurrency-js due to potential licensing issues --- package-lock.json | 19 +- package.json | 3 +- src/types/blakejs/index.d.ts | 1 + src/util/nacl.d.ts | 98 +++ src/util/nacl.js | 1546 ++++++++++++++++++++++++++++++++++ src/util/wallet_gen.ts | 114 ++- 6 files changed, 1758 insertions(+), 23 deletions(-) create mode 100644 src/types/blakejs/index.d.ts create mode 100644 src/util/nacl.d.ts create mode 100644 src/util/nacl.js diff --git a/package-lock.json b/package-lock.json index addbff4..ca8c4aa 100755 --- a/package-lock.json +++ b/package-lock.json @@ -283,6 +283,11 @@ "@fortawesome/fontawesome-common-types": "^0.2.15" } }, + "@types/node": { + "version": "11.13.8", + "resolved": "https://registry.npmjs.org/@types/node/-/node-11.13.8.tgz", + "integrity": "sha512-szA3x/3miL90ZJxUCzx9haNbK5/zmPieGraZEe4WI+3srN0eGLiT22NXeMHmyhNEopn+IrxqMc7wdVwvPl8meg==" + }, "@types/q": { "version": "1.5.2", "resolved": "https://registry.npmjs.org/@types/q/-/q-1.5.2.tgz", @@ -1690,11 +1695,6 @@ "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==" }, - "bignumber.js": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-8.1.1.tgz", - "integrity": "sha512-QD46ppGintwPGuL1KqmwhR0O+N2cZUg8JG/VzwI2e28sM9TqHjQB10lI4QAaMHVbLzwVLLAwEglpKPViWX+5NQ==" - }, "binary-extensions": { "version": "1.13.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.0.tgz", @@ -6936,15 +6936,6 @@ "resolved": "https://registry.npmjs.org/nan/-/nan-2.13.1.tgz", "integrity": "sha512-I6YB/YEuDeUZMmhscXKxGgZlFnhsn5y0hgOZBadkzfTRrZBtJDZeg6eQf7PYMIEclwmorTKK8GztsyOUSVBREA==" }, - "nanocurrency": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/nanocurrency/-/nanocurrency-2.3.0.tgz", - "integrity": "sha512-1zllVr8nurIZtaA5pETMf4WpXyFcKHhIJEM1h0DC6o1xFLkrAkiV0rG5i8nTV3s3qX9ktD2ae4vpY7cYE3ul1w==", - "requires": { - "bignumber.js": "^8.0.0", - "blakejs": "^1.1.0" - } - }, "nanomatch": { "version": "1.2.13", "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", diff --git a/package.json b/package.json index 4c65e77..073228d 100644 --- a/package.json +++ b/package.json @@ -28,15 +28,16 @@ "@fortawesome/free-brands-svg-icons": "^5.2.0", "@fortawesome/free-regular-svg-icons": "^5.2.0", "@fortawesome/free-solid-svg-icons": "^5.2.0", + "@types/node": "^11.13.8", "affix": "^1.0.15", "babel-cli": "^6.26.0", "babel-preset-env": "^1.7.0", + "blakejs": "^1.1.0", "bootstrap": "^4.3.1", "bufferutil": "^3.0.5", "fs": "0.0.1-security", "ignore-loader": "^0.1.2", "mini-css-extract-plugin": "^0.5.0", - "nanocurrency": "^2.3.0", "node-sass": "^4.11.0", "popper.js": "^1.14.3", "precss": "^3.1.2", diff --git a/src/types/blakejs/index.d.ts b/src/types/blakejs/index.d.ts new file mode 100644 index 0000000..b69fbc2 --- /dev/null +++ b/src/types/blakejs/index.d.ts @@ -0,0 +1 @@ +declare module "blakejs"; \ No newline at end of file diff --git a/src/util/nacl.d.ts b/src/util/nacl.d.ts new file mode 100644 index 0000000..e4dd3de --- /dev/null +++ b/src/util/nacl.d.ts @@ -0,0 +1,98 @@ +// Type definitions for TweetNaCl.js + +export as namespace nacl; + +declare var nacl: nacl; +export = nacl; + +declare namespace nacl { + export interface BoxKeyPair { + publicKey: Uint8Array; + secretKey: Uint8Array; + } + + export interface SignKeyPair { + publicKey: Uint8Array; + secretKey: Uint8Array; + } + + export interface secretbox { + (msg: Uint8Array, nonce: Uint8Array, key: Uint8Array): Uint8Array; + open(box: Uint8Array, nonce: Uint8Array, key: Uint8Array): Uint8Array | null; + readonly keyLength: number; + readonly nonceLength: number; + readonly overheadLength: number; + } + + export interface scalarMult { + (n: Uint8Array, p: Uint8Array): Uint8Array; + base(n: Uint8Array): Uint8Array; + readonly scalarLength: number; + readonly groupElementLength: number; + } + + namespace boxProps { + export interface open { + (msg: Uint8Array, nonce: Uint8Array, publicKey: Uint8Array, secretKey: Uint8Array): Uint8Array | null; + after(box: Uint8Array, nonce: Uint8Array, key: Uint8Array): Uint8Array | null; + } + + export interface keyPair { + (): BoxKeyPair; + fromSecretKey(secretKey: Uint8Array): BoxKeyPair; + } + } + + export interface box { + (msg: Uint8Array, nonce: Uint8Array, publicKey: Uint8Array, secretKey: Uint8Array): Uint8Array; + before(publicKey: Uint8Array, secretKey: Uint8Array): Uint8Array; + after(msg: Uint8Array, nonce: Uint8Array, key: Uint8Array): Uint8Array; + open: boxProps.open; + keyPair: boxProps.keyPair; + readonly publicKeyLength: number; + readonly secretKeyLength: number; + readonly sharedKeyLength: number; + readonly nonceLength: number; + readonly overheadLength: number; + } + + namespace signProps { + export interface detached { + (msg: Uint8Array, secretKey: Uint8Array): Uint8Array; + verify(msg: Uint8Array, sig: Uint8Array, publicKey: Uint8Array): boolean; + } + + export interface keyPair { + (): SignKeyPair; + fromSecretKey(secretKey: Uint8Array): SignKeyPair; + fromSeed(secretKey: Uint8Array): SignKeyPair; + } + } + + export interface sign { + (msg: Uint8Array, secretKey: Uint8Array): Uint8Array; + open(signedMsg: Uint8Array, publicKey: Uint8Array): Uint8Array | null; + detached: signProps.detached; + keyPair: signProps.keyPair; + readonly publicKeyLength: number; + readonly secretKeyLength: number; + readonly seedLength: number; + readonly signatureLength: number; + } + + export interface hash { + (msg: Uint8Array): Uint8Array; + readonly hashLength: number; + } +} + +declare interface nacl { + randomBytes(n: number): Uint8Array; + secretbox: nacl.secretbox; + scalarMult: nacl.scalarMult; + box: nacl.box; + sign: nacl.sign; + hash: nacl.hash; + verify(x: Uint8Array, y: Uint8Array): boolean; + setPRNG(fn: (x: Uint8Array, n: number) => void): void; +} \ No newline at end of file diff --git a/src/util/nacl.js b/src/util/nacl.js new file mode 100644 index 0000000..d6abd44 --- /dev/null +++ b/src/util/nacl.js @@ -0,0 +1,1546 @@ +import * as blake from "blakejs" + +(function(nacl) { +"use strict" + +// Ported in 2014 by Dmitry Chestnykh and Devi Mandiri. +// Public domain. +// +// Implementation derived from TweetNaCl version 20140427. +// See for details: http://tweetnacl.cr.yp.to/ + +var u64 = function(h, l) { + this.hi = h | (0 >>> 0) + this.lo = l | (0 >>> 0) +} +var gf = function(init) { + var i, + r = new Float64Array(16) + if (init) for (i = 0; i < init.length; i++) r[i] = init[i] + return r +} + +// Pluggable, initialized in high-level API below. +var randombytes = function(/* x, n */) { + throw new Error("no PRNG") +} + +var _0 = new Uint8Array(16) +var _9 = new Uint8Array(32) +_9[0] = 9 + +var gf0 = gf(), + gf1 = gf([1]), + _121665 = gf([0xdb41, 1]), + D = gf([ + 0x78a3, + 0x1359, + 0x4dca, + 0x75eb, + 0xd8ab, + 0x4141, + 0x0a4d, + 0x0070, + 0xe898, + 0x7779, + 0x4079, + 0x8cc7, + 0xfe73, + 0x2b6f, + 0x6cee, + 0x5203 + ]), + D2 = gf([ + 0xf159, + 0x26b2, + 0x9b94, + 0xebd6, + 0xb156, + 0x8283, + 0x149a, + 0x00e0, + 0xd130, + 0xeef3, + 0x80f2, + 0x198e, + 0xfce7, + 0x56df, + 0xd9dc, + 0x2406 + ]), + X = gf([ + 0xd51a, + 0x8f25, + 0x2d60, + 0xc956, + 0xa7b2, + 0x9525, + 0xc760, + 0x692c, + 0xdc5c, + 0xfdd6, + 0xe231, + 0xc0a4, + 0x53fe, + 0xcd6e, + 0x36d3, + 0x2169 + ]), + Y = gf([ + 0x6658, + 0x6666, + 0x6666, + 0x6666, + 0x6666, + 0x6666, + 0x6666, + 0x6666, + 0x6666, + 0x6666, + 0x6666, + 0x6666, + 0x6666, + 0x6666, + 0x6666, + 0x6666 + ]), + I = gf([ + 0xa0b0, + 0x4a0e, + 0x1b27, + 0xc4ee, + 0xe478, + 0xad2f, + 0x1806, + 0x2f43, + 0xd7a7, + 0x3dfb, + 0x0099, + 0x2b4d, + 0xdf0b, + 0x4fc1, + 0x2480, + 0x2b83 + ]) + +function L32(x, c) { + return (x << c) | (x >>> (32 - c)) +} + +function ld32(x, i) { + var u = x[i + 3] & 0xff + u = (u << 8) | (x[i + 2] & 0xff) + u = (u << 8) | (x[i + 1] & 0xff) + return (u << 8) | (x[i + 0] & 0xff) +} + +function dl64(x, i) { + var h = (x[i] << 24) | (x[i + 1] << 16) | (x[i + 2] << 8) | x[i + 3] + var l = (x[i + 4] << 24) | (x[i + 5] << 16) | (x[i + 6] << 8) | x[i + 7] + return new u64(h, l) +} + +function st32(x, j, u) { + var i + for (i = 0; i < 4; i++) { + x[j + i] = u & 255 + u >>>= 8 + } +} + +function ts64(x, i, u) { + x[i] = (u.hi >> 24) & 0xff + x[i + 1] = (u.hi >> 16) & 0xff + x[i + 2] = (u.hi >> 8) & 0xff + x[i + 3] = u.hi & 0xff + x[i + 4] = (u.lo >> 24) & 0xff + x[i + 5] = (u.lo >> 16) & 0xff + x[i + 6] = (u.lo >> 8) & 0xff + x[i + 7] = u.lo & 0xff +} + +function vn(x, xi, y, yi, n) { + 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, xi, y, yi) { + return vn(x, xi, y, yi, 16) +} + +function crypto_verify_32(x, xi, y, yi) { + return vn(x, xi, y, yi, 32) +} + +function core(out, inp, k, c, h) { + var w = new Uint32Array(16), + x = new Uint32Array(16), + y = new Uint32Array(16), + t = new Uint32Array(4) + var i, j, m + + for (i = 0; i < 4; i++) { + x[5 * i] = ld32(c, 4 * i) + x[1 + i] = ld32(k, 4 * i) + x[6 + i] = ld32(inp, 4 * i) + x[11 + i] = ld32(k, 16 + 4 * i) + } + + for (i = 0; i < 16; i++) y[i] = x[i] + + for (i = 0; i < 20; i++) { + for (j = 0; j < 4; j++) { + for (m = 0; m < 4; m++) t[m] = x[(5 * j + 4 * m) % 16] + t[1] ^= L32((t[0] + t[3]) | 0, 7) + t[2] ^= L32((t[1] + t[0]) | 0, 9) + t[3] ^= L32((t[2] + t[1]) | 0, 13) + t[0] ^= L32((t[3] + t[2]) | 0, 18) + for (m = 0; m < 4; m++) w[4 * j + ((j + m) % 4)] = t[m] + } + for (m = 0; m < 16; m++) x[m] = w[m] + } + + if (h) { + for (i = 0; i < 16; i++) x[i] = (x[i] + y[i]) | 0 + for (i = 0; i < 4; i++) { + x[5 * i] = (x[5 * i] - ld32(c, 4 * i)) | 0 + x[6 + i] = (x[6 + i] - ld32(inp, 4 * i)) | 0 + } + for (i = 0; i < 4; i++) { + st32(out, 4 * i, x[5 * i]) + st32(out, 16 + 4 * i, x[6 + i]) + } + } else { + for (i = 0; i < 16; i++) st32(out, 4 * i, (x[i] + y[i]) | 0) + } +} + +function crypto_core_salsa20(out, inp, k, c) { + core(out, inp, k, c, false) + return 0 +} + +function crypto_core_hsalsa20(out, inp, k, c) { + core(out, inp, k, c, true) + return 0 +} + +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, cpos, m, mpos, b, n, k) { + var z = new Uint8Array(16), + x = new Uint8Array(64) + var u, i + if (!b) return 0 + 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 ? m[mpos + i] : 0) ^ x[i] + u = 1 + for (i = 8; i < 16; i++) { + u = (u + (z[i] & 0xff)) | 0 + z[i] = u & 0xff + u >>>= 8 + } + b -= 64 + cpos += 64 + if (m) mpos += 64 + } + if (b > 0) { + crypto_core_salsa20(x, z, k, sigma) + for (i = 0; i < b; i++) c[cpos + i] = (m ? m[mpos + i] : 0) ^ x[i] + } + return 0 +} + +function crypto_stream_salsa20(c, cpos, d, n, k) { + return crypto_stream_salsa20_xor(c, cpos, null, 0, d, n, k) +} + +function crypto_stream(c, cpos, d, n, k) { + var s = new Uint8Array(32) + crypto_core_hsalsa20(s, n, k, sigma) + return crypto_stream_salsa20(c, cpos, d, n.subarray(16), s) +} + +function crypto_stream_xor(c, cpos, m, mpos, d, n, k) { + var s = new Uint8Array(32) + crypto_core_hsalsa20(s, n, k, sigma) + return crypto_stream_salsa20_xor(c, cpos, m, mpos, d, n.subarray(16), s) +} + +function add1305(h, c) { + var j, + u = 0 + for (j = 0; j < 17; j++) { + u = (u + ((h[j] + c[j]) | 0)) | 0 + h[j] = u & 255 + u >>>= 8 + } +} + +var minusp = new Uint32Array([ + 5, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 252 +]) + +function crypto_onetimeauth(out, outpos, m, mpos, n, k) { + var s, i, j, u + var x = new Uint32Array(17), + r = new Uint32Array(17), + h = new Uint32Array(17), + c = new Uint32Array(17), + g = new Uint32Array(17) + for (j = 0; j < 17; j++) r[j] = h[j] = 0 + for (j = 0; j < 16; j++) r[j] = k[j] + r[3] &= 15 + r[4] &= 252 + r[7] &= 15 + r[8] &= 252 + r[11] &= 15 + r[12] &= 252 + r[15] &= 15 + + while (n > 0) { + for (j = 0; j < 17; j++) c[j] = 0 + for (j = 0; j < 16 && j < n; ++j) c[j] = m[mpos + j] + c[j] = 1 + mpos += j + n -= j + add1305(h, c) + for (i = 0; i < 17; i++) { + x[i] = 0 + for (j = 0; j < 17; j++) + x[i] = + (x[i] + h[j] * (j <= i ? r[i - j] : (320 * r[i + 17 - j]) | 0)) | + 0 | + 0 + } + for (i = 0; i < 17; i++) h[i] = x[i] + u = 0 + for (j = 0; j < 16; j++) { + u = (u + h[j]) | 0 + h[j] = u & 255 + u >>>= 8 + } + u = (u + h[16]) | 0 + h[16] = u & 3 + u = (5 * (u >>> 2)) | 0 + for (j = 0; j < 16; j++) { + u = (u + h[j]) | 0 + h[j] = u & 255 + u >>>= 8 + } + u = (u + h[16]) | 0 + h[16] = u + } + + for (j = 0; j < 17; j++) g[j] = h[j] + add1305(h, minusp) + s = -(h[16] >>> 7) | 0 + for (j = 0; j < 17; j++) h[j] ^= s & (g[j] ^ h[j]) + + for (j = 0; j < 16; j++) c[j] = k[j + 16] + c[16] = 0 + add1305(h, c) + for (j = 0; j < 16; j++) out[outpos + j] = h[j] + return 0 +} + +function crypto_onetimeauth_verify(h, hpos, m, mpos, n, k) { + var x = new Uint8Array(16) + crypto_onetimeauth(x, 0, m, mpos, n, k) + return crypto_verify_16(h, hpos, x, 0) +} + +function crypto_secretbox(c, m, d, n, k) { + var i + if (d < 32) return -1 + 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, c, d, n, k) { + 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) + for (i = 0; i < 32; i++) m[i] = 0 + return 0 +} + +function set25519(r, a) { + var i + for (i = 0; i < 16; i++) r[i] = a[i] | 0 +} + +function car25519(o) { + var c + var i + for (i = 0; i < 16; i++) { + o[i] += 65536 + c = Math.floor(o[i] / 65536) + o[(i + 1) * (i < 15 ? 1 : 0)] += c - 1 + 37 * (c - 1) * (i === 15 ? 1 : 0) + o[i] -= c * 65536 + } +} + +function sel25519(p, q, b) { + var t, + c = ~(b - 1) + for (var i = 0; i < 16; i++) { + t = c & (p[i] ^ q[i]) + p[i] ^= t + q[i] ^= t + } +} + +function pack25519(o, n) { + var i, j, b + var m = gf(), + t = gf() + for (i = 0; i < 16; i++) t[i] = n[i] + car25519(t) + car25519(t) + car25519(t) + 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[15] = t[15] - 0x7fff - ((m[14] >> 16) & 1) + b = (m[15] >> 16) & 1 + m[14] &= 0xffff + sel25519(t, m, 1 - b) + } + for (i = 0; i < 16; i++) { + o[2 * i] = t[i] & 0xff + o[2 * i + 1] = t[i] >> 8 + } +} + +function neq25519(a, b) { + var c = new Uint8Array(32), + d = new Uint8Array(32) + pack25519(c, a) + pack25519(d, b) + return crypto_verify_32(c, 0, d, 0) +} + +function par25519(a) { + var d = new Uint8Array(32) + pack25519(d, a) + return d[0] & 1 +} + +function unpack25519(o, n) { + var i + for (i = 0; i < 16; i++) o[i] = n[2 * i] + (n[2 * i + 1] << 8) + o[15] &= 0x7fff +} + +function A(o, a, b) { + var i + for (i = 0; i < 16; i++) o[i] = (a[i] + b[i]) | 0 +} + +function Z(o, a, b) { + var i + for (i = 0; i < 16; i++) o[i] = (a[i] - b[i]) | 0 +} + +function M(o, a, b) { + var i, + j, + t = new Float64Array(31) + for (i = 0; i < 31; i++) t[i] = 0 + for (i = 0; i < 16; i++) { + for (j = 0; j < 16; j++) { + t[i + j] += a[i] * b[j] + } + } + for (i = 0; i < 15; i++) { + t[i] += 38 * t[i + 16] + } + for (i = 0; i < 16; i++) o[i] = t[i] + car25519(o) + car25519(o) +} + +function S(o, a) { + M(o, a, a) +} + +function inv25519(o, i) { + var c = gf() + var a + 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) + } + for (a = 0; a < 16; a++) o[a] = c[a] +} + +function pow2523(o, i) { + var c = gf() + 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) + } + for (a = 0; a < 16; a++) o[a] = c[a] +} + +function crypto_scalarmult(q, n, p) { + 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() + for (i = 0; i < 31; i++) z[i] = n[i] + 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 + } + 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] + } + var x32 = x.subarray(32) + var x16 = x.subarray(16) + inv25519(x32, x32) + M(x16, x16, x32) + pack25519(q, x16) + return 0 +} + +function crypto_scalarmult_base(q, n) { + return crypto_scalarmult(q, n, _9) +} + +function crypto_box_keypair(y, x) { + randombytes(x, 32) + return crypto_scalarmult_base(y, x) +} + +function crypto_box_beforenm(k, y, x) { + var s = new Uint8Array(32) + crypto_scalarmult(s, x, y) + return crypto_core_hsalsa20(k, _0, s, sigma) +} + +var crypto_box_afternm = crypto_secretbox +var crypto_box_open_afternm = crypto_secretbox_open + +function crypto_box(c, m, d, n, y, x) { + 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, c, d, n, y, x) { + var k = new Uint8Array(32) + crypto_box_beforenm(k, y, x) + return crypto_box_open_afternm(m, c, d, n, k) +} + +function add64() { + var a = 0, + b = 0, + c = 0, + d = 0, + m16 = 65535, + l, + h, + i + for (i = 0; i < arguments.length; i++) { + l = arguments[i].lo + h = arguments[i].hi + a += l & m16 + b += l >>> 16 + c += h & m16 + d += h >>> 16 + } + + b += a >>> 16 + c += b >>> 16 + d += c >>> 16 + + return new u64((c & m16) | (d << 16), (a & m16) | (b << 16)) +} + +function shr64(x, c) { + return new u64(x.hi >>> c, (x.lo >>> c) | (x.hi << (32 - c))) +} + +function xor64() { + var l = 0, + h = 0, + i + for (i = 0; i < arguments.length; i++) { + l ^= arguments[i].lo + h ^= arguments[i].hi + } + return new u64(h, l) +} + +function R(x, c) { + var h, + l, + c1 = 32 - c + if (c < 32) { + h = (x.hi >>> c) | (x.lo << c1) + l = (x.lo >>> c) | (x.hi << c1) + } else if (c < 64) { + h = (x.lo >>> c) | (x.hi << c1) + l = (x.hi >>> c) | (x.lo << c1) + } + return new u64(h, l) +} + +function Ch(x, y, z) { + var h = (x.hi & y.hi) ^ (~x.hi & z.hi), + l = (x.lo & y.lo) ^ (~x.lo & z.lo) + return new u64(h, l) +} + +function Maj(x, y, z) { + var h = (x.hi & y.hi) ^ (x.hi & z.hi) ^ (y.hi & z.hi), + l = (x.lo & y.lo) ^ (x.lo & z.lo) ^ (y.lo & z.lo) + return new u64(h, l) +} + +function Sigma0(x) { + return xor64(R(x, 28), R(x, 34), R(x, 39)) +} +function Sigma1(x) { + return xor64(R(x, 14), R(x, 18), R(x, 41)) +} +function sigma0(x) { + return xor64(R(x, 1), R(x, 8), shr64(x, 7)) +} +function sigma1(x) { + return xor64(R(x, 19), R(x, 61), shr64(x, 6)) +} + +var K = [ + new u64(0x428a2f98, 0xd728ae22), + new u64(0x71374491, 0x23ef65cd), + new u64(0xb5c0fbcf, 0xec4d3b2f), + new u64(0xe9b5dba5, 0x8189dbbc), + new u64(0x3956c25b, 0xf348b538), + new u64(0x59f111f1, 0xb605d019), + new u64(0x923f82a4, 0xaf194f9b), + new u64(0xab1c5ed5, 0xda6d8118), + new u64(0xd807aa98, 0xa3030242), + new u64(0x12835b01, 0x45706fbe), + new u64(0x243185be, 0x4ee4b28c), + new u64(0x550c7dc3, 0xd5ffb4e2), + new u64(0x72be5d74, 0xf27b896f), + new u64(0x80deb1fe, 0x3b1696b1), + new u64(0x9bdc06a7, 0x25c71235), + new u64(0xc19bf174, 0xcf692694), + new u64(0xe49b69c1, 0x9ef14ad2), + new u64(0xefbe4786, 0x384f25e3), + new u64(0x0fc19dc6, 0x8b8cd5b5), + new u64(0x240ca1cc, 0x77ac9c65), + new u64(0x2de92c6f, 0x592b0275), + new u64(0x4a7484aa, 0x6ea6e483), + new u64(0x5cb0a9dc, 0xbd41fbd4), + new u64(0x76f988da, 0x831153b5), + new u64(0x983e5152, 0xee66dfab), + new u64(0xa831c66d, 0x2db43210), + new u64(0xb00327c8, 0x98fb213f), + new u64(0xbf597fc7, 0xbeef0ee4), + new u64(0xc6e00bf3, 0x3da88fc2), + new u64(0xd5a79147, 0x930aa725), + new u64(0x06ca6351, 0xe003826f), + new u64(0x14292967, 0x0a0e6e70), + new u64(0x27b70a85, 0x46d22ffc), + new u64(0x2e1b2138, 0x5c26c926), + new u64(0x4d2c6dfc, 0x5ac42aed), + new u64(0x53380d13, 0x9d95b3df), + new u64(0x650a7354, 0x8baf63de), + new u64(0x766a0abb, 0x3c77b2a8), + new u64(0x81c2c92e, 0x47edaee6), + new u64(0x92722c85, 0x1482353b), + new u64(0xa2bfe8a1, 0x4cf10364), + new u64(0xa81a664b, 0xbc423001), + new u64(0xc24b8b70, 0xd0f89791), + new u64(0xc76c51a3, 0x0654be30), + new u64(0xd192e819, 0xd6ef5218), + new u64(0xd6990624, 0x5565a910), + new u64(0xf40e3585, 0x5771202a), + new u64(0x106aa070, 0x32bbd1b8), + new u64(0x19a4c116, 0xb8d2d0c8), + new u64(0x1e376c08, 0x5141ab53), + new u64(0x2748774c, 0xdf8eeb99), + new u64(0x34b0bcb5, 0xe19b48a8), + new u64(0x391c0cb3, 0xc5c95a63), + new u64(0x4ed8aa4a, 0xe3418acb), + new u64(0x5b9cca4f, 0x7763e373), + new u64(0x682e6ff3, 0xd6b2b8a3), + new u64(0x748f82ee, 0x5defb2fc), + new u64(0x78a5636f, 0x43172f60), + new u64(0x84c87814, 0xa1f0ab72), + new u64(0x8cc70208, 0x1a6439ec), + new u64(0x90befffa, 0x23631e28), + new u64(0xa4506ceb, 0xde82bde9), + new u64(0xbef9a3f7, 0xb2c67915), + new u64(0xc67178f2, 0xe372532b), + new u64(0xca273ece, 0xea26619c), + new u64(0xd186b8c7, 0x21c0c207), + new u64(0xeada7dd6, 0xcde0eb1e), + new u64(0xf57d4f7f, 0xee6ed178), + new u64(0x06f067aa, 0x72176fba), + new u64(0x0a637dc5, 0xa2c898a6), + new u64(0x113f9804, 0xbef90dae), + new u64(0x1b710b35, 0x131c471b), + new u64(0x28db77f5, 0x23047d84), + new u64(0x32caab7b, 0x40c72493), + new u64(0x3c9ebe0a, 0x15c9bebc), + new u64(0x431d67c4, 0x9c100d4c), + new u64(0x4cc5d4be, 0xcb3e42b6), + new u64(0x597f299c, 0xfc657e2a), + new u64(0x5fcb6fab, 0x3ad6faec), + new u64(0x6c44198c, 0x4a475817) +] + +function crypto_hashblocks(x, m, n) { + var z = [], + b = [], + a = [], + w = [], + t, + i, + j + + for (i = 0; i < 8; i++) z[i] = a[i] = dl64(x, 8 * i) + + var pos = 0 + while (n >= 128) { + for (i = 0; i < 16; i++) w[i] = dl64(m, 8 * i + pos) + for (i = 0; i < 80; i++) { + for (j = 0; j < 8; j++) b[j] = a[j] + t = add64(a[7], Sigma1(a[4]), Ch(a[4], a[5], a[6]), K[i], w[i % 16]) + b[7] = add64(t, Sigma0(a[0]), Maj(a[0], a[1], a[2])) + b[3] = add64(b[3], t) + for (j = 0; j < 8; j++) a[(j + 1) % 8] = b[j] + if (i % 16 === 15) { + for (j = 0; j < 16; j++) { + w[j] = add64( + w[j], + w[(j + 9) % 16], + sigma0(w[(j + 1) % 16]), + sigma1(w[(j + 14) % 16]) + ) + } + } + } + + for (i = 0; i < 8; i++) { + a[i] = add64(a[i], z[i]) + z[i] = a[i] + } + + pos += 128 + n -= 128 + } + + for (i = 0; i < 8; i++) ts64(x, 8 * i, z[i]) + return n +} + +var iv = new Uint8Array([ + 0x6a, + 0x09, + 0xe6, + 0x67, + 0xf3, + 0xbc, + 0xc9, + 0x08, + 0xbb, + 0x67, + 0xae, + 0x85, + 0x84, + 0xca, + 0xa7, + 0x3b, + 0x3c, + 0x6e, + 0xf3, + 0x72, + 0xfe, + 0x94, + 0xf8, + 0x2b, + 0xa5, + 0x4f, + 0xf5, + 0x3a, + 0x5f, + 0x1d, + 0x36, + 0xf1, + 0x51, + 0x0e, + 0x52, + 0x7f, + 0xad, + 0xe6, + 0x82, + 0xd1, + 0x9b, + 0x05, + 0x68, + 0x8c, + 0x2b, + 0x3e, + 0x6c, + 0x1f, + 0x1f, + 0x83, + 0xd9, + 0xab, + 0xfb, + 0x41, + 0xbd, + 0x6b, + 0x5b, + 0xe0, + 0xcd, + 0x19, + 0x13, + 0x7e, + 0x21, + 0x79 +]) + +function crypto_hash(out, m, n) { + var h = new Uint8Array(64), + x = new Uint8Array(256) + var i, + b = n + + for (i = 0; i < 64; i++) h[i] = iv[i] + + crypto_hashblocks(h, m, n) + n %= 128 + + for (i = 0; i < 256; i++) x[i] = 0 + 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, new u64((b / 0x20000000) | 0, b << 3)) + crypto_hashblocks(h, x, n) + + for (i = 0; i < 64; i++) out[i] = h[i] + + return 0 +} + +function add(p, q) { + 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]) + M(a, a, t) + A(b, p[0], p[1]) + A(t, q[0], q[1]) + M(b, b, t) + M(c, p[3], q[3]) + M(c, c, D2) + M(d, p[2], q[2]) + A(d, d, d) + Z(e, b, a) + Z(f, d, c) + A(g, d, c) + A(h, b, a) + + M(p[0], e, f) + M(p[1], h, g) + M(p[2], g, f) + M(p[3], e, h) +} + +function cswap(p, q, b) { + var i + for (i = 0; i < 4; i++) { + sel25519(p[i], q[i], b) + } +} + +function pack(r, p) { + var tx = gf(), + ty = gf(), + zi = gf() + inv25519(zi, p[2]) + M(tx, p[0], zi) + M(ty, p[1], zi) + pack25519(r, ty) + r[31] ^= par25519(tx) << 7 +} + +function scalarmult(p, q, s) { + var b, i + set25519(p[0], gf0) + set25519(p[1], gf1) + set25519(p[2], gf1) + set25519(p[3], gf0) + for (i = 255; i >= 0; --i) { + b = (s[(i / 8) | 0] >> (i & 7)) & 1 + cswap(p, q, b) + add(q, p) + add(p, p) + cswap(p, q, b) + } +} + +function scalarbase(p, s) { + var q = [gf(), gf(), gf(), gf()] + set25519(q[0], X) + set25519(q[1], Y) + set25519(q[2], gf1) + M(q[3], X, Y) + scalarmult(p, q, s) +} + +function crypto_sign_keypair(pk, sk, seeded) { + var d = new Uint8Array(64) + var p = [gf(), gf(), gf(), gf()] + var i + + if (!seeded) randombytes(sk, 32) + + var context = blake.blake2bInit(64) + blake.blake2bUpdate(context, sk) + d = blake.blake2bFinal(context) + + d[0] &= 248 + d[31] &= 127 + d[31] |= 64 + + scalarbase(p, d) + pack(pk, p) + + return 0 +} + +function derivePublicFromSecret(sk) { + var d = new Uint8Array(64) + var p = [gf(), gf(), gf(), gf()] + var i + var pk = new Uint8Array(32) + var context = blake.blake2bInit(64) + blake.blake2bUpdate(context, sk) + d = blake.blake2bFinal(context) + + d[0] &= 248 + d[31] &= 127 + d[31] |= 64 + + scalarbase(p, d) + pack(pk, p) + return pk +} + +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, x) { + var carry, i, j, k + for (i = 63; i >= 32; --i) { + carry = 0 + for (j = i - 32, k = i - 12; j < k; ++j) { + x[j] += carry - 16 * x[i] * L[j - (i - 32)] + carry = (x[j] + 128) >> 8 + x[j] -= carry * 256 + } + x[j] += carry + x[i] = 0 + } + carry = 0 + for (j = 0; j < 32; j++) { + x[j] += carry - (x[31] >> 4) * L[j] + carry = x[j] >> 8 + x[j] &= 255 + } + for (j = 0; j < 32; j++) x[j] -= carry * L[j] + for (i = 0; i < 32; i++) { + x[i + 1] += x[i] >> 8 + r[i] = x[i] & 255 + } +} + +function reduce(r) { + 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 + modL(r, x) +} + +// Note: difference from C - smlen returned, not passed as argument. +function crypto_sign(sm, m, n, sk) { + 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()] + + var pk = derivePublicFromSecret(sk) + + var context = blake.blake2bInit(64, null) + blake.blake2bUpdate(context, sk) + d = blake.blake2bFinal(context) + d[0] &= 248 + d[31] &= 127 + d[31] |= 64 + + var smlen = n + 64 + for (i = 0; i < n; i++) sm[64 + i] = m[i] + for (i = 0; i < 32; i++) sm[32 + i] = d[32 + i] + + context = blake.blake2bInit(64, null) + blake.blake2bUpdate(context, sm.subarray(32)) + r = blake.blake2bFinal(context) + + reduce(r) + scalarbase(p, r) + pack(sm, p) + + for (i = 32; i < 64; i++) sm[i] = pk[i - 32] + + context = blake.blake2bInit(64, null) + blake.blake2bUpdate(context, sm) + h = blake.blake2bFinal(context) + + reduce(h) + + for (i = 0; i < 64; i++) x[i] = 0 + 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] + } + } + + modL(sm.subarray(32), x) + return smlen +} + +function unpackneg(r, p) { + var t = gf(), + chk = gf(), + num = gf(), + den = gf(), + den2 = gf(), + den4 = gf(), + den6 = gf() + + set25519(r[2], gf1) + unpack25519(r[1], p) + S(num, r[1]) + M(den, num, D) + Z(num, num, r[2]) + A(den, r[2], den) + + S(den2, den) + S(den4, den2) + M(den6, den4, den2) + M(t, den6, num) + M(t, t, den) + + pow2523(t, t) + M(t, t, num) + M(t, t, den) + M(t, t, den) + M(r[0], t, den) + + S(chk, r[0]) + M(chk, chk, den) + if (neq25519(chk, num)) M(r[0], r[0], I) + + S(chk, r[0]) + M(chk, chk, den) + if (neq25519(chk, num)) return -1 + + 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, sm, n, pk) { + var i, mlen + var t = new Uint8Array(32), + h = new Uint8Array(64) + var p = [gf(), gf(), gf(), gf()], + q = [gf(), gf(), gf(), gf()] + + mlen = -1 + if (n < 64) return -1 + + 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] + //crypto_hash(h, m, n); + + context = blake.blake2bInit(64, null) + blake.blake2bUpdate(context, m) + h = blake.blake2bFinal(context) + + reduce(h) + scalarmult(p, q, h) + + scalarbase(q, sm.subarray(32)) + add(p, q) + pack(t, p) + + n -= 64 + if (crypto_verify_32(sm, 0, t, 0)) { + for (i = 0; i < n; i++) m[i] = 0 + return -1 + } + + for (i = 0; i < n; i++) m[i] = sm[i + 64] + mlen = n + return mlen +} + +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 = 32, + crypto_sign_SEEDBYTES = 32, + crypto_hash_BYTES = 64 + +nacl.lowlevel = { + crypto_core_hsalsa20: crypto_core_hsalsa20, + crypto_stream_xor: crypto_stream_xor, + crypto_stream: crypto_stream, + crypto_stream_salsa20_xor: crypto_stream_salsa20_xor, + crypto_stream_salsa20: crypto_stream_salsa20, + crypto_onetimeauth: crypto_onetimeauth, + crypto_onetimeauth_verify: crypto_onetimeauth_verify, + crypto_verify_16: crypto_verify_16, + crypto_verify_32: crypto_verify_32, + crypto_secretbox: crypto_secretbox, + crypto_secretbox_open: crypto_secretbox_open, + crypto_scalarmult: crypto_scalarmult, + crypto_scalarmult_base: crypto_scalarmult_base, + crypto_box_beforenm: crypto_box_beforenm, + crypto_box_afternm: crypto_box_afternm, + crypto_box: crypto_box, + crypto_box_open: crypto_box_open, + crypto_box_keypair: crypto_box_keypair, + crypto_hash: crypto_hash, + crypto_sign: crypto_sign, + crypto_sign_keypair: crypto_sign_keypair, + crypto_sign_open: crypto_sign_open, + + crypto_secretbox_KEYBYTES: crypto_secretbox_KEYBYTES, + crypto_secretbox_NONCEBYTES: crypto_secretbox_NONCEBYTES, + crypto_secretbox_ZEROBYTES: crypto_secretbox_ZEROBYTES, + crypto_secretbox_BOXZEROBYTES: crypto_secretbox_BOXZEROBYTES, + crypto_scalarmult_BYTES: crypto_scalarmult_BYTES, + crypto_scalarmult_SCALARBYTES: crypto_scalarmult_SCALARBYTES, + crypto_box_PUBLICKEYBYTES: crypto_box_PUBLICKEYBYTES, + crypto_box_SECRETKEYBYTES: crypto_box_SECRETKEYBYTES, + crypto_box_BEFORENMBYTES: crypto_box_BEFORENMBYTES, + crypto_box_NONCEBYTES: crypto_box_NONCEBYTES, + crypto_box_ZEROBYTES: crypto_box_ZEROBYTES, + crypto_box_BOXZEROBYTES: crypto_box_BOXZEROBYTES, + crypto_sign_BYTES: crypto_sign_BYTES, + crypto_sign_PUBLICKEYBYTES: crypto_sign_PUBLICKEYBYTES, + crypto_sign_SECRETKEYBYTES: crypto_sign_SECRETKEYBYTES, + crypto_sign_SEEDBYTES: crypto_sign_SEEDBYTES, + crypto_hash_BYTES: crypto_hash_BYTES +} + +/* High-level API */ + +function checkLengths(k, n) { + 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, sk) { + 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() { + for (var i = 0; i < arguments.length; i++) { + if (!(arguments[i] instanceof Uint8Array)) + throw new TypeError("unexpected type, use Uint8Array") + } +} + +function cleanup(arr) { + for (var i = 0; i < arr.length; i++) arr[i] = 0 +} + +nacl.randomBytes = function(n) { + var b = new Uint8Array(n) + randombytes(b, n) + return b +} + +nacl.secretbox = function(msg, nonce, key) { + 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] + crypto_secretbox(c, m, m.length, nonce, key) + return c.subarray(crypto_secretbox_BOXZEROBYTES) +} + +nacl.secretbox.open = function(box, nonce, key) { + 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] + 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) +} + +nacl.secretbox.keyLength = crypto_secretbox_KEYBYTES +nacl.secretbox.nonceLength = crypto_secretbox_NONCEBYTES +nacl.secretbox.overheadLength = crypto_secretbox_BOXZEROBYTES + +nacl.scalarMult = function(n, p) { + 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") + var q = new Uint8Array(crypto_scalarmult_BYTES) + crypto_scalarmult(q, n, p) + return q +} + +nacl.scalarMult.base = function(n) { + checkArrayTypes(n) + 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 +} + +nacl.scalarMult.scalarLength = crypto_scalarmult_SCALARBYTES +nacl.scalarMult.groupElementLength = crypto_scalarmult_BYTES + +nacl.box = function(msg, nonce, publicKey, secretKey) { + var k = nacl.box.before(publicKey, secretKey) + return nacl.secretbox(msg, nonce, k) +} + +nacl.box.before = function(publicKey, secretKey) { + checkArrayTypes(publicKey, secretKey) + checkBoxLengths(publicKey, secretKey) + var k = new Uint8Array(crypto_box_BEFORENMBYTES) + crypto_box_beforenm(k, publicKey, secretKey) + return k +} + +nacl.box.after = nacl.secretbox + +nacl.box.open = function(msg, nonce, publicKey, secretKey) { + var k = nacl.box.before(publicKey, secretKey) + return nacl.secretbox.open(msg, nonce, k) +} + +nacl.box.open.after = nacl.secretbox.open + +nacl.box.keyPair = function() { + var pk = new Uint8Array(crypto_box_PUBLICKEYBYTES) + var sk = new Uint8Array(crypto_box_SECRETKEYBYTES) + crypto_box_keypair(pk, sk) + return { publicKey: pk, secretKey: sk } +} + +nacl.box.keyPair.fromSecretKey = function(secretKey) { + checkArrayTypes(secretKey) + if (secretKey.length !== crypto_box_SECRETKEYBYTES) + 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) } +} + +nacl.box.publicKeyLength = crypto_box_PUBLICKEYBYTES +nacl.box.secretKeyLength = crypto_box_SECRETKEYBYTES +nacl.box.sharedKeyLength = crypto_box_BEFORENMBYTES +nacl.box.nonceLength = crypto_box_NONCEBYTES +nacl.box.overheadLength = nacl.secretbox.overheadLength + +nacl.sign = function(msg, secretKey) { + 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) + crypto_sign(signedMsg, msg, msg.length, secretKey) + return signedMsg +} + +nacl.sign.open = function(signedMsg, publicKey) { + checkArrayTypes(signedMsg, publicKey) + if (publicKey.length !== crypto_sign_PUBLICKEYBYTES) + 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 +} + +nacl.sign.detached = function(msg, secretKey) { + var signedMsg = nacl.sign(msg, secretKey) + var sig = new Uint8Array(crypto_sign_BYTES) + for (var i = 0; i < sig.length; i++) sig[i] = signedMsg[i] + return sig +} + +nacl.sign.detached.verify = function(msg, sig, publicKey) { + checkArrayTypes(msg, sig, publicKey) + 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") + 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 +} + +nacl.sign.keyPair = function() { + var pk = new Uint8Array(crypto_sign_PUBLICKEYBYTES) + var sk = new Uint8Array(crypto_sign_SECRETKEYBYTES) + crypto_sign_keypair(pk, sk) + return { publicKey: pk, secretKey: sk } +} + +nacl.sign.keyPair.fromSecretKey = function(secretKey) { + checkArrayTypes(secretKey) + if (secretKey.length !== crypto_sign_SECRETKEYBYTES) + throw new Error("bad secret key size") + var pk = new Uint8Array(crypto_sign_PUBLICKEYBYTES) + pk = derivePublicFromSecret(secretKey) + return { publicKey: pk, secretKey: new Uint8Array(secretKey) } +} + +nacl.sign.keyPair.fromSeed = function(seed) { + checkArrayTypes(seed) + 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 } +} + +nacl.sign.publicKeyLength = crypto_sign_PUBLICKEYBYTES +nacl.sign.secretKeyLength = crypto_sign_SECRETKEYBYTES +nacl.sign.seedLength = crypto_sign_SEEDBYTES +nacl.sign.signatureLength = crypto_sign_BYTES + +nacl.hash = function(msg) { + checkArrayTypes(msg) + var h = new Uint8Array(crypto_hash_BYTES) + crypto_hash(h, msg, msg.length) + return h +} + +nacl.hash.hashLength = crypto_hash_BYTES + +nacl.verify = function(x, y) { + checkArrayTypes(x, y) + // 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 +} + +nacl.setPRNG = function(fn) { + randombytes = fn +} +;(function() { + // Initialize PRNG if environment provides CSPRNG. + // If not, methods calling randombytes will throw. + var crypto = + typeof self !== "undefined" ? self.crypto || self.msCrypto : null + if (crypto && crypto.getRandomValues) { + // Browsers. + var QUOTA = 65536 + nacl.setPRNG(function(x, 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") { + // Node.js. + crypto = require("crypto") + if (crypto && crypto.randomBytes) { + nacl.setPRNG(function(x, n) { + var i, + v = crypto.randomBytes(n) + for (i = 0; i < n; i++) x[i] = v[i] + cleanup(v) + }) + } + } +})() + +})(typeof module !== 'undefined' && module.exports ? module.exports : (self.nacl = self.nacl || {})); \ No newline at end of file diff --git a/src/util/wallet_gen.ts b/src/util/wallet_gen.ts index 5c82d0b..7e917e1 100644 --- a/src/util/wallet_gen.ts +++ b/src/util/wallet_gen.ts @@ -1,15 +1,113 @@ -import * as nanocurrency from 'nanocurrency' +import { blake2b, blake2bFinal, blake2bInit, blake2bUpdate } from 'blakejs' + +var nacl = require("./nacl.js") export default class WalletGen { // Generate seed and index 0 account static async genWallet() : Promise { - const seed = await nanocurrency.generateSeed() - const address = nanocurrency.deriveAddress( - nanocurrency.derivePublicKey(nanocurrency.deriveSecretKey(seed, 0)), - { - useNanoPrefix: true - } + const seed = WalletGen.generateSeedBytes(); + const privateKey = WalletGen.deriveSecretKey(seed, 0) + const publicKey = WalletGen.generatePublicFromPrivate(privateKey); + const address = WalletGen.getAddressFromPublic(publicKey) + return {seed: WalletGen.uint8ToHex(seed), address:address} + } + + static generateSeedBytes() { + return nacl.randomBytes(32) + } + + static generatePublicFromPrivate(accountSecretKeyBytes : Uint8Array) : Uint8Array { + return nacl.sign.keyPair.fromSecretKey(accountSecretKeyBytes).publicKey + } + + static deriveSecretKey(seedBytes: Uint8Array, index: number): Uint8Array { + const indexBuffer = new ArrayBuffer(4) + const indexView = new DataView(indexBuffer) + indexView.setUint32(0, index) + const indexBytes = new Uint8Array(indexBuffer) + + const context = blake2bInit(32) + blake2bUpdate(context, seedBytes) + blake2bUpdate(context, indexBytes) + const secretKeyBytes = blake2bFinal(context) + + return secretKeyBytes + } + + static getAddressFromPublic(accountPublicKeyBytes : Uint8Array, prefix = "nano") : string { + const accountHex = WalletGen.uint8ToHex(accountPublicKeyBytes) + const keyBytes = WalletGen.uint4ToUint8(WalletGen.hexToUint4(accountHex)) // For some reason here we go from u, to hex, to 4, to 8?? + const checksum = WalletGen.uint5ToString( + WalletGen.uint4ToUint5(WalletGen.uint8ToUint4(blake2b(keyBytes, null, 5).reverse())) ) - return {seed:seed, address:address} + const account = WalletGen.uint5ToString(WalletGen.uint4ToUint5(WalletGen.hexToUint4(`0${accountHex}`))) + + return `${prefix}_${account}${checksum}` + } + + /** Byte Helpers */ + + static hexToUint4(hexValue : string) : Uint8Array { + const uint4 = new Uint8Array(hexValue.length) + for (let i = 0; i < hexValue.length; i++) + uint4[i] = parseInt(hexValue.substr(i, 1), 16) + + return uint4 + } + + static uint8ToUint4(uintValue : Uint8Array) : Uint8Array { + const uint4 = new Uint8Array(uintValue.length * 2) + for (let i = 0; i < uintValue.length; i++) { + uint4[i * 2] = (uintValue[i] / 16) | 0 + uint4[i * 2 + 1] = uintValue[i] % 16 + } + + return uint4 + } + + static uint8ToHex(uintValue : Uint8Array) : string { + let hex = "" + let aux + for (let i = 0; i < uintValue.length; i++) { + aux = uintValue[i].toString(16).toUpperCase() + if (aux.length == 1) aux = "0" + aux + hex += aux + aux = "" + } + + return hex + } + + static uint4ToUint8(uintValue : Uint8Array) { + const length = uintValue.length / 2 + const uint8 = new Uint8Array(length) + for (let i = 0; i < length; i++) + uint8[i] = uintValue[i * 2] * 16 + uintValue[i * 2 + 1] + + return uint8 + } + + static uint4ToUint5(uintValue : Uint8Array) { + var length = (uintValue.length / 5) * 4 + var uint5 = new Uint8Array(length) + for (let i = 1; i <= length; i++) { + let n = i - 1 + let m = i % 4 + let z = n + (i - m) / 4 + let right = uintValue[z] << m + let left + if ((length - i) % 4 == 0) left = uintValue[z - 1] << 4 + else left = uintValue[z + 1] >> (4 - m) + uint5[n] = (left + right) % 32 + } + return uint5 + } + + static uint5ToString(uint5 : Uint8Array) : string { + const letter_list = "13456789abcdefghijkmnopqrstuwxyz".split("") + let string = "" + for (let i = 0; i < uint5.length; i++) string += letter_list[uint5[i]] + + return string } } \ No newline at end of file