}\r
}\r
\r
-const crypto_sign_BYTES: u8 = 64\r
-const crypto_sign_PUBLICKEYBYTES: u8 = 32\r
-const crypto_sign_PRIVATEKEYBYTES: u8 = 32\r
-const crypto_sign_SEEDBYTES: u8 = 32\r
+const BLOCKHASH_BYTES: u8 = 32\r
+const PRIVATEKEY_BYTES: u8 = 32\r
+const PUBLICKEY_BYTES: u8 = 32\r
+const SIGNATURE_BYTES: u8 = 64\r
const D: Int64Array = new Int64Array(16); D.set([0x78a3, 0x1359, 0x4dca, 0x75eb, 0xd8ab, 0x4141, 0x0a4d, 0x0070, 0xe898, 0x7779, 0x4079, 0x8cc7, 0xfe73, 0x2b6f, 0x6cee, 0x5203])\r
const D2: Int64Array = new Int64Array(16); D2.set([0xf159, 0x26b2, 0x9b94, 0xebd6, 0xb156, 0x8283, 0x149a, 0x00e0, 0xd130, 0xeef3, 0x80f2, 0x198e, 0xfce7, 0x56df, 0xd9dc, 0x2406])\r
const X: Int64Array = new Int64Array(16); X.set([0xd51a, 0x8f25, 0x2d60, 0xc956, 0xa7b2, 0x9525, 0xc760, 0x692c, 0xdc5c, 0xfdd6, 0xe231, 0xc0a4, 0x53fe, 0xcd6e, 0x36d3, 0x2169])\r
}\r
\r
/**\r
-* Derives a public key from a private key "seed".\r
+* Derives a Nano public key from a private key. This mirrors the functionality\r
+* of `nacl.sign.keyPair.fromSeed()`, returning just the `publicKey` property.\r
*\r
-* @param {Uint8Array} seed - 32-byte private key\r
+* @param {Uint8Array} privateKey - 32-byte private key\r
* @returns {Uint8Array} 32-byte public key\r
*/\r
-export function derive (seed: Uint8Array): Uint8Array {\r
- if (seed.length !== crypto_sign_SEEDBYTES) {\r
- const err = `Invalid private key byte length to convert to public key, expected ${crypto_sign_SEEDBYTES}, actual ${seed.byteLength}`\r
- trace(err, 1, seed.byteLength)\r
+export function derive (k0: u64, k1: u64, k2: u64, k3: u64): Uint8Array {\r
+ const k = new Uint64Array(4); k.set([k0, k1, k2, k3])\r
+ const privateKey = Uint8Array.wrap(k.buffer)\r
+ if (privateKey.byteLength !== PRIVATEKEY_BYTES) {\r
+ const err = `Invalid private key byte length to convert to public key, expected ${PRIVATEKEY_BYTES}, actual ${privateKey.byteLength}`\r
+ trace(err, 1, privateKey.byteLength)\r
throw new Error(err)\r
}\r
- const pk = new Uint8Array(crypto_sign_PUBLICKEYBYTES)\r
+ const publicKey = new Uint8Array(PUBLICKEY_BYTES)\r
const p: Int64Array[] = [new Int64Array(16), new Int64Array(16), new Int64Array(16), new Int64Array(16)]\r
\r
- const h: Uint8Array = new Blake2b(64).update(seed).digest()\r
+ const h: Uint8Array = new Blake2b(64).update(privateKey).digest()\r
h[0] &= 248\r
h[31] &= 127\r
h[31] |= 64\r
\r
scalarbase(p, h)\r
- pack(pk, p)\r
+ pack(publicKey, p)\r
\r
- return pk\r
+ return publicKey\r
}\r
\r
/**\r
-* Signs the message using the secret key and returns a signature.\r
+* Signs the message using the private key and returns a signature.\r
*\r
* @param {Uint8Array} message - Message to sign\r
* @param {Uint8Array} privateKey - 32-byte key to use for signing\r
const k = new Uint64Array(4); k.set([k0, k1, k2, k3])\r
const message = Uint8Array.wrap(h.buffer)\r
const privateKey = Uint8Array.wrap(k.buffer)\r
- if (privateKey.byteLength !== crypto_sign_PRIVATEKEYBYTES) {\r
- const err = `Invalid key byte length to sign message, expected ${crypto_sign_PRIVATEKEYBYTES}, actual ${privateKey.byteLength}`\r
+ if (privateKey.byteLength !== PRIVATEKEY_BYTES) {\r
+ const err = `Invalid key byte length to sign message, expected ${PRIVATEKEY_BYTES}, actual ${privateKey.byteLength}`\r
trace(err, 1, privateKey.byteLength)\r
throw new Error(err)\r
}\r
- const signed = new Uint8Array(crypto_sign_BYTES + message.length)\r
- const publicKey = derive(privateKey)\r
+ const signed = new Uint8Array(SIGNATURE_BYTES + message.length)\r
+ const publicKey = derive(k0, k1, k2, k3)\r
crypto_sign(signed, message, message.length, privateKey, publicKey)\r
- const sig = new Uint8Array(crypto_sign_BYTES)\r
+ const sig = new Uint8Array(SIGNATURE_BYTES)\r
for (let i = 0; i < sig.length; i++) {\r
sig[i] = signed[i]\r
}\r
}\r
\r
/**\r
-* Verifies a detached signature for a message.\r
+* Verifies a signature on a blockhash against a public key.\r
*\r
-* @param {Uint8Array} message - Signed message\r
+* @param {Uint8Array} blockhash - 32-byte hash of signed Nano block\r
* @param {Uint8Array} signature - 64-byte signature\r
* @param {Uint8Array} publicKey - 32-byte key used for signing\r
-* @returns {boolean} - True if `publicKey` was used to sign `msg` and generate `sig`, else false\r
+* @returns {boolean} - True if `publicKey` was used to sign `blockhash` and generate `signature`, else false\r
*/\r
-export function verify (message: Uint8Array, signature: Uint8Array, publicKey: Uint8Array): boolean {\r
- if (signature.byteLength !== crypto_sign_BYTES) {\r
- const err = `Invalid signature size to verify signature, expected ${crypto_sign_BYTES}, actual ${signature.byteLength}`\r
+export function verify (h0: u64, h1: u64, h2: u64, h3: u64, s0: u64, s1: u64, s2: u64, s3: u64, s4: u64, s5: u64, s6: u64, s7: u64, k0: u64, k1: u64, k2: u64, k3: u64): boolean {\r
+ const h = new Uint64Array(4); h.set([h0, h1, h2, h3])\r
+ const s = new Uint64Array(8); s.set([s0, s1, s2, s3, s4, s5, s6, s7])\r
+ const k = new Uint64Array(4); k.set([k0, k1, k2, k3])\r
+ const blockhash = Uint8Array.wrap(h.buffer)\r
+ const signature = Uint8Array.wrap(s.buffer)\r
+ const publicKey = Uint8Array.wrap(k.buffer)\r
+ if (blockhash.byteLength !== BLOCKHASH_BYTES) {\r
+ const err = `Invalid blockhash size to verify signature, expected ${BLOCKHASH_BYTES}, actual ${blockhash.byteLength}`\r
+ trace(err, 1, blockhash.byteLength)\r
+ throw new Error(err)\r
+ }\r
+ if (signature.byteLength !== SIGNATURE_BYTES) {\r
+ const err = `Invalid signature size to verify signature, expected ${SIGNATURE_BYTES}, actual ${signature.byteLength}`\r
trace(err, 1, signature.byteLength)\r
throw new Error(err)\r
}\r
- if (publicKey.byteLength !== crypto_sign_PUBLICKEYBYTES) {\r
- const err = `Invalid public key size to verify signature, expected ${crypto_sign_PUBLICKEYBYTES}, actual ${publicKey.byteLength}`\r
+ if (publicKey.byteLength !== PUBLICKEY_BYTES) {\r
+ const err = `Invalid public key size to verify signature, expected ${PUBLICKEY_BYTES}, actual ${publicKey.byteLength}`\r
trace(err, 1, signature.byteLength)\r
throw new Error(err)\r
}\r
- const sm = new Uint8Array(crypto_sign_BYTES + message.length)\r
- const m = new Uint8Array(crypto_sign_BYTES + message.length)\r
+ const sm = new Uint8Array(SIGNATURE_BYTES + blockhash.length)\r
+ const m = new Uint8Array(SIGNATURE_BYTES + blockhash.length)\r
sm.set(signature, 0)\r
- sm.set(message, crypto_sign_BYTES)\r
+ sm.set(blockhash, SIGNATURE_BYTES)\r
return (crypto_sign_open(m, sm, sm.length, publicKey) >= 0)\r
}\r