From 4e42b942a59acaa65a44421ae2ce3a8633798125 Mon Sep 17 00:00:00 2001 From: Fedor Indutny Date: Tue, 13 Aug 2019 08:00:27 -0700 Subject: [PATCH] crypto_box: fix keypair, implement seal/seal_open Secret Key is a random nonce, and public key is a point on elliptic curve. `crypto_box_seal`/`crypto_box_seal_open` are implemented using existing primitives and newly exported `core_hsalsa20` in `xsalsa20` --- index.js | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 54 insertions(+), 2 deletions(-) diff --git a/index.js b/index.js index 7d8612c..c7af053 100644 --- a/index.js +++ b/index.js @@ -1,5 +1,7 @@ 'use strict'; +var xsalsa20 = require('xsalsa20') + // Based on https://github.com/dchest/tweetnacl-js/blob/6dcbcaf5f5cbfd313f2dcfe763db35c828c8ff5b/nacl-fast.js. var sodium = module.exports @@ -1739,8 +1741,52 @@ function crypto_secretbox_open_easy(msg, box, n, k) { function crypto_box_keypair(pk, sk) { check(pk, crypto_box_PUBLICKEYBYTES) check(sk, crypto_box_SECRETKEYBYTES) - randombytes(pk, 32); - return crypto_scalarmult_base(sk, pk); + randombytes(sk, 32) + return crypto_scalarmult_base(pk, sk) +} + +function crypto_box_seal(c, m, pk) { + check(c, crypto_box_SEALBYTES + m.length) + check(pk, crypto_box_PUBLICKEYBYTES) + + var epk = c.subarray(0, crypto_box_PUBLICKEYBYTES) + var esk = new Uint8Array(crypto_box_SECRETKEYBYTES) + crypto_box_keypair(epk, esk) + + var n = new Uint8Array(crypto_box_NONCEBYTES) + sodium.crypto_generichash_batch(n, [ epk, pk ]) + + var s = new Uint8Array(crypto_box_PUBLICKEYBYTES) + crypto_scalarmult(s, esk, pk) + + var k = new Uint8Array(crypto_box_BEFORENMBYTES) + var zero = new Uint8Array(16) + xsalsa20.core_hsalsa20(k, zero, s, xsalsa20.SIGMA) + + crypto_secretbox_easy(c.subarray(epk.length), m, n, k) + + cleanup(esk) +} + +function crypto_box_seal_open(m, c, pk, sk) { + check(c, crypto_box_SEALBYTES) + check(m, c.length - crypto_box_SEALBYTES) + check(pk, crypto_box_PUBLICKEYBYTES) + check(sk, crypto_box_SECRETKEYBYTES) + + var epk = c.subarray(0, crypto_box_PUBLICKEYBYTES) + + var n = new Uint8Array(crypto_box_NONCEBYTES) + sodium.crypto_generichash_batch(n, [ epk, pk ]) + + var s = new Uint8Array(crypto_box_PUBLICKEYBYTES) + crypto_scalarmult(s, sk, epk) + + var k = new Uint8Array(crypto_box_BEFORENMBYTES) + var zero = new Uint8Array(16) + xsalsa20.core_hsalsa20(k, zero, s, xsalsa20.SIGMA) + + return crypto_secretbox_open_easy(m, c.subarray(epk.length), n, k) } var crypto_secretbox_KEYBYTES = 32, @@ -1755,6 +1801,8 @@ var crypto_secretbox_KEYBYTES = 32, crypto_box_NONCEBYTES = crypto_secretbox_NONCEBYTES, crypto_box_ZEROBYTES = crypto_secretbox_ZEROBYTES, crypto_box_BOXZEROBYTES = crypto_secretbox_BOXZEROBYTES, + crypto_box_SEALBYTES = 48, + crypto_box_BEFORENMBYTES = 32, crypto_sign_BYTES = 64, crypto_sign_PUBLICKEYBYTES = 32, crypto_sign_SECRETKEYBYTES = 64, @@ -1797,7 +1845,11 @@ sodium.crypto_secretbox_open_detached = crypto_secretbox_open_detached sodium.crypto_box_PUBLICKEYBYTES = crypto_box_PUBLICKEYBYTES sodium.crypto_box_SECRETKEYBYTES = crypto_box_SECRETKEYBYTES +sodium.crypto_box_SEALBYTES = crypto_box_SEALBYTES +sodium.crypto_box_BEFORENMBYTES = crypto_box_BEFORENMBYTES sodium.crypto_box_keypair = crypto_box_keypair +sodium.crypto_box_seal = crypto_box_seal +sodium.crypto_box_seal_open = crypto_box_seal_open function cleanup(arr) { for (var i = 0; i < arr.length; i++) arr[i] = 0;