From d97952035ea29879b924dc306ee017e9e7ca832a Mon Sep 17 00:00:00 2001 From: Luke Burns Date: Sun, 27 Dec 2020 01:51:00 -0800 Subject: [PATCH 1/6] add ristretto bindings --- binding.c | 213 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 213 insertions(+) diff --git a/binding.c b/binding.c index 0d1e12c5..e803672f 100644 --- a/binding.c +++ b/binding.c @@ -1428,6 +1428,199 @@ napi_value sn_crypto_core_ed25519_scalar_sub (napi_env env, napi_callback_info i return NULL; } +napi_value sn_crypto_scalarmult_ristretto255_base (napi_env env, napi_callback_info info) { + SN_ARGV(2, crypto_scalarmult_ristretto255_base) + + SN_ARGV_TYPEDARRAY(q, 0) + SN_ARGV_TYPEDARRAY(n, 1) + + SN_ASSERT_LENGTH(q_size, crypto_scalarmult_ristretto255_BYTES, "q") + SN_ASSERT_LENGTH(n_size, crypto_scalarmult_ristretto255_SCALARBYTES, "n") + + SN_RETURN(crypto_scalarmult_ristretto255_base(q_data, n_data), "failed to derive public key") +} + +napi_value sn_crypto_scalarmult_ristretto255 (napi_env env, napi_callback_info info) { + SN_ARGV(3, crypto_scalarmult_ristretto255) + + SN_ARGV_TYPEDARRAY(q, 0) + SN_ARGV_TYPEDARRAY(n, 1) + SN_ARGV_TYPEDARRAY(p, 2) + + SN_ASSERT_LENGTH(q_size, crypto_scalarmult_ristretto255_BYTES, "q") + SN_ASSERT_LENGTH(n_size, crypto_scalarmult_ristretto255_SCALARBYTES, "n") + SN_ASSERT_LENGTH(p_size, crypto_scalarmult_ristretto255_BYTES, "p") + + SN_RETURN(crypto_scalarmult_ristretto255(q_data, n_data, p_data), "failed to derive shared secret") +} + +napi_value sn_crypto_core_ristretto255_add (napi_env env, napi_callback_info info) { + SN_ARGV(3, crypto_core_ristretto255_add) + + SN_ARGV_TYPEDARRAY(r, 0) + SN_ARGV_TYPEDARRAY(p, 1) + SN_ARGV_TYPEDARRAY(q, 2) + + SN_ASSERT_LENGTH(r_size, crypto_core_ristretto255_BYTES, "r") + SN_ASSERT_LENGTH(p_size, crypto_core_ristretto255_BYTES, "p") + SN_ASSERT_LENGTH(q_size, crypto_core_ristretto255_BYTES, "q") + + SN_RETURN(crypto_core_ristretto255_add(r_data, p_data, q_data), "could not add curve points") +} + +napi_value sn_crypto_core_ristretto255_sub (napi_env env, napi_callback_info info) { + SN_ARGV(3, crypto_core_ristretto255_sub) + + SN_ARGV_TYPEDARRAY(r, 0) + SN_ARGV_TYPEDARRAY(p, 1) + SN_ARGV_TYPEDARRAY(q, 2) + + SN_ASSERT_LENGTH(r_size, crypto_core_ristretto255_BYTES, "r") + SN_ASSERT_LENGTH(p_size, crypto_core_ristretto255_BYTES, "p") + SN_ASSERT_LENGTH(q_size, crypto_core_ristretto255_BYTES, "q") + + SN_RETURN(crypto_core_ristretto255_sub(r_data, p_data, q_data), "could not add curve points") +} + +napi_value sn_crypto_core_ristretto255_scalar_random (napi_env env, napi_callback_info info) { + SN_ARGV(1, crypto_core_ristretto255_scalar_random) + + SN_ARGV_TYPEDARRAY(r, 0) + + SN_ASSERT_LENGTH(r_size, crypto_core_ristretto255_SCALARBYTES, "r") + + crypto_core_ristretto255_scalar_random(r_data); + + return NULL; +} + +napi_value sn_crypto_core_ristretto255_scalar_reduce (napi_env env, napi_callback_info info) { + SN_ARGV(2, crypto_core_ristretto255_scalar_reduce) + + SN_ARGV_TYPEDARRAY(r, 0) + SN_ARGV_TYPEDARRAY(s, 1) + + SN_ASSERT_LENGTH(r_size, crypto_core_ristretto255_SCALARBYTES, "r") + SN_ASSERT_LENGTH(s_size, crypto_core_ristretto255_NONREDUCEDSCALARBYTES, "s") + + crypto_core_ristretto255_scalar_reduce(r_data, s_data); + + return NULL; +} + +napi_value sn_crypto_core_ristretto255_scalar_invert (napi_env env, napi_callback_info info) { + SN_ARGV(2, crypto_core_ristretto255_scalar_invert) + + SN_ARGV_TYPEDARRAY(recip, 0) + SN_ARGV_TYPEDARRAY(s, 1) + + SN_ASSERT_LENGTH(recip_size, crypto_core_ristretto255_SCALARBYTES, "recip") + SN_ASSERT_LENGTH(s_size, crypto_core_ristretto255_SCALARBYTES, "s") + + crypto_core_ristretto255_scalar_invert(recip_data, s_data); + + return NULL; +} + +napi_value sn_crypto_core_ristretto255_scalar_negate (napi_env env, napi_callback_info info) { + SN_ARGV(2, crypto_core_ristretto255_scalar_negate) + + SN_ARGV_TYPEDARRAY(neg, 0) + SN_ARGV_TYPEDARRAY(s, 1) + + SN_ASSERT_LENGTH(neg_size, crypto_core_ristretto255_SCALARBYTES, "neg") + SN_ASSERT_LENGTH(s_size, crypto_core_ristretto255_SCALARBYTES, "s") + + crypto_core_ristretto255_scalar_negate(neg_data, s_data); + + return NULL; +} + +napi_value sn_crypto_core_ristretto255_scalar_complement (napi_env env, napi_callback_info info) { + SN_ARGV(2, crypto_core_ristretto255_scalar_complement) + + SN_ARGV_TYPEDARRAY(comp, 0) + SN_ARGV_TYPEDARRAY(s, 1) + + SN_ASSERT_LENGTH(comp_size, crypto_core_ristretto255_SCALARBYTES, "comp") + SN_ASSERT_LENGTH(s_size, crypto_core_ristretto255_SCALARBYTES, "s") + + crypto_core_ristretto255_scalar_complement(comp_data, s_data); + + return NULL; +} + +napi_value sn_crypto_core_ristretto255_scalar_add (napi_env env, napi_callback_info info) { + SN_ARGV(3, crypto_core_ristretto255_scalar_add) + + SN_ARGV_TYPEDARRAY(z, 0) + SN_ARGV_TYPEDARRAY(x, 1) + SN_ARGV_TYPEDARRAY(y, 2) + + SN_ASSERT_LENGTH(z_size, crypto_core_ristretto255_SCALARBYTES, "z") + SN_ASSERT_LENGTH(x_size, crypto_core_ristretto255_SCALARBYTES, "x") + SN_ASSERT_LENGTH(y_size, crypto_core_ristretto255_SCALARBYTES, "y") + + crypto_core_ristretto255_scalar_add(z_data, x_data, y_data); + + return NULL; +} + + +napi_value sn_crypto_core_ristretto255_scalar_sub (napi_env env, napi_callback_info info) { + SN_ARGV(3, crypto_core_ristretto255_scalar_sub) + + SN_ARGV_TYPEDARRAY(z, 0) + SN_ARGV_TYPEDARRAY(x, 1) + SN_ARGV_TYPEDARRAY(y, 2) + + SN_ASSERT_LENGTH(z_size, crypto_core_ristretto255_SCALARBYTES, "z") + SN_ASSERT_LENGTH(x_size, crypto_core_ristretto255_SCALARBYTES, "x") + SN_ASSERT_LENGTH(y_size, crypto_core_ristretto255_SCALARBYTES, "y") + + crypto_core_ristretto255_scalar_sub(z_data, x_data, y_data); + + return NULL; +} + +napi_value sn_crypto_core_ristretto255_scalar_mul (napi_env env, napi_callback_info info) { + SN_ARGV(3, crypto_core_ristretto255_scalar_mul) + + SN_ARGV_TYPEDARRAY(z, 0) + SN_ARGV_TYPEDARRAY(x, 1) + SN_ARGV_TYPEDARRAY(y, 2) + + SN_ASSERT_LENGTH(z_size, crypto_core_ristretto255_SCALARBYTES, "z") + SN_ASSERT_LENGTH(x_size, crypto_core_ristretto255_SCALARBYTES, "x") + SN_ASSERT_LENGTH(y_size, crypto_core_ristretto255_SCALARBYTES, "y") + + crypto_core_ristretto255_scalar_mul(z_data, x_data, y_data); + + return NULL; +} + +napi_value sn_crypto_core_ristretto255_is_valid_point (napi_env env, napi_callback_info info) { + SN_ARGV(1, crypto_core_ristretto255_is_valid_point) + + SN_ARGV_TYPEDARRAY(p, 0) + + SN_ASSERT_LENGTH(p_size, crypto_core_ristretto255_BYTES, "p") + + SN_RETURN_BOOLEAN_FROM_1(crypto_core_ristretto255_is_valid_point(p_data)) +} + +napi_value sn_crypto_core_ristretto255_from_hash (napi_env env, napi_callback_info info) { + SN_ARGV(2, crypto_core_ristretto255_from_hash) + + SN_ARGV_TYPEDARRAY(p, 0) + SN_ARGV_TYPEDARRAY(r, 1) + + SN_ASSERT_LENGTH(p_size, crypto_core_ristretto255_BYTES, "p") + SN_ASSERT_LENGTH(r_size, crypto_core_ristretto255_HASHBYTES, "r") + + SN_RETURN(crypto_core_ristretto255_from_hash(p_data, r_data), "could not generate curve point from input") +} + napi_value sn_crypto_shorthash (napi_env env, napi_callback_info info) { SN_ARGV(3, crypto_shorthash) @@ -2953,6 +3146,20 @@ static napi_value create_sodium_native(napi_env env) { SN_EXPORT_FUNCTION(crypto_core_ed25519_scalar_complement, sn_crypto_core_ed25519_scalar_complement) SN_EXPORT_FUNCTION(crypto_core_ed25519_scalar_add, sn_crypto_core_ed25519_scalar_add) SN_EXPORT_FUNCTION(crypto_core_ed25519_scalar_sub, sn_crypto_core_ed25519_scalar_sub) + SN_EXPORT_FUNCTION(crypto_scalarmult_ristretto255_base, sn_crypto_scalarmult_ristretto255_base) + SN_EXPORT_FUNCTION(crypto_scalarmult_ristretto255, sn_crypto_scalarmult_ristretto255) + SN_EXPORT_FUNCTION(crypto_core_ristretto255_add, sn_crypto_core_ristretto255_add) + SN_EXPORT_FUNCTION(crypto_core_ristretto255_sub, sn_crypto_core_ristretto255_sub) + SN_EXPORT_FUNCTION(crypto_core_ristretto255_scalar_random, sn_crypto_core_ristretto255_scalar_random) + SN_EXPORT_FUNCTION(crypto_core_ristretto255_scalar_reduce, sn_crypto_core_ristretto255_scalar_reduce) + SN_EXPORT_FUNCTION(crypto_core_ristretto255_scalar_invert, sn_crypto_core_ristretto255_scalar_invert) + SN_EXPORT_FUNCTION(crypto_core_ristretto255_scalar_negate, sn_crypto_core_ristretto255_scalar_negate) + SN_EXPORT_FUNCTION(crypto_core_ristretto255_scalar_complement, sn_crypto_core_ristretto255_scalar_complement) + SN_EXPORT_FUNCTION(crypto_core_ristretto255_scalar_add, sn_crypto_core_ristretto255_scalar_add) + SN_EXPORT_FUNCTION(crypto_core_ristretto255_scalar_sub, sn_crypto_core_ristretto255_scalar_sub) + SN_EXPORT_FUNCTION(crypto_core_ristretto255_scalar_mul, sn_crypto_core_ristretto255_scalar_mul) + SN_EXPORT_FUNCTION(crypto_core_ristretto255_from_hash, sn_crypto_core_ristretto255_from_hash) + SN_EXPORT_FUNCTION(crypto_core_ristretto255_is_valid_point, sn_crypto_core_ristretto255_is_valid_point) SN_EXPORT_FUNCTION(crypto_shorthash, sn_crypto_shorthash) SN_EXPORT_FUNCTION(crypto_kdf_keygen, sn_crypto_kdf_keygen) SN_EXPORT_FUNCTION(crypto_kdf_derive_from_key, sn_crypto_kdf_derive_from_key) @@ -3096,6 +3303,12 @@ static napi_value create_sodium_native(napi_env env) { SN_EXPORT_UINT32(crypto_core_ed25519_NONREDUCEDSCALARBYTES, crypto_core_ed25519_NONREDUCEDSCALARBYTES) SN_EXPORT_UINT32(crypto_scalarmult_ed25519_BYTES, crypto_scalarmult_ed25519_BYTES) SN_EXPORT_UINT32(crypto_scalarmult_ed25519_SCALARBYTES, crypto_scalarmult_ed25519_SCALARBYTES) + SN_EXPORT_UINT32(crypto_core_ristretto255_BYTES, crypto_core_ristretto255_BYTES) + SN_EXPORT_UINT32(crypto_core_ristretto255_HASHBYTES, crypto_core_ristretto255_HASHBYTES) + SN_EXPORT_UINT32(crypto_core_ristretto255_SCALARBYTES, crypto_core_ristretto255_SCALARBYTES) + SN_EXPORT_UINT32(crypto_core_ristretto255_NONREDUCEDSCALARBYTES, crypto_core_ristretto255_NONREDUCEDSCALARBYTES) + SN_EXPORT_UINT32(crypto_scalarmult_ristretto255_BYTES, crypto_scalarmult_ristretto255_BYTES) + SN_EXPORT_UINT32(crypto_scalarmult_ristretto255_SCALARBYTES, crypto_scalarmult_ristretto255_SCALARBYTES) SN_EXPORT_UINT32(crypto_aead_xchacha20poly1305_ietf_ABYTES, crypto_aead_xchacha20poly1305_ietf_ABYTES) SN_EXPORT_UINT32(crypto_aead_xchacha20poly1305_ietf_KEYBYTES, crypto_aead_xchacha20poly1305_ietf_KEYBYTES) SN_EXPORT_UINT32(crypto_aead_xchacha20poly1305_ietf_NPUBBYTES, crypto_aead_xchacha20poly1305_ietf_NPUBBYTES) From a34a4df21c49b22ac7c73026f5f86ecfc654ca88 Mon Sep 17 00:00:00 2001 From: Luke Burns Date: Mon, 28 Dec 2020 21:55:36 -0800 Subject: [PATCH 2/6] add tests and example --- binding.c | 13 ++ example-ristretto255.js | 48 ++++++++ test/core_ristretto255.js | 247 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 308 insertions(+) create mode 100644 example-ristretto255.js create mode 100644 test/core_ristretto255.js diff --git a/binding.c b/binding.c index e803672f..81605347 100644 --- a/binding.c +++ b/binding.c @@ -1454,6 +1454,18 @@ napi_value sn_crypto_scalarmult_ristretto255 (napi_env env, napi_callback_info i SN_RETURN(crypto_scalarmult_ristretto255(q_data, n_data, p_data), "failed to derive shared secret") } +napi_value sn_crypto_core_ristretto255_random (napi_env env, napi_callback_info info) { + SN_ARGV(1, crypto_core_ristretto255_random) + + SN_ARGV_TYPEDARRAY(p, 0) + + SN_ASSERT_LENGTH(p_size, crypto_core_ristretto255_BYTES, "p") + + crypto_core_ristretto255_random(p_data); + + return NULL; +} + napi_value sn_crypto_core_ristretto255_add (napi_env env, napi_callback_info info) { SN_ARGV(3, crypto_core_ristretto255_add) @@ -3148,6 +3160,7 @@ static napi_value create_sodium_native(napi_env env) { SN_EXPORT_FUNCTION(crypto_core_ed25519_scalar_sub, sn_crypto_core_ed25519_scalar_sub) SN_EXPORT_FUNCTION(crypto_scalarmult_ristretto255_base, sn_crypto_scalarmult_ristretto255_base) SN_EXPORT_FUNCTION(crypto_scalarmult_ristretto255, sn_crypto_scalarmult_ristretto255) + SN_EXPORT_FUNCTION(crypto_core_ristretto255_random, sn_crypto_core_ristretto255_random) SN_EXPORT_FUNCTION(crypto_core_ristretto255_add, sn_crypto_core_ristretto255_add) SN_EXPORT_FUNCTION(crypto_core_ristretto255_sub, sn_crypto_core_ristretto255_sub) SN_EXPORT_FUNCTION(crypto_core_ristretto255_scalar_random, sn_crypto_core_ristretto255_scalar_random) diff --git a/example-ristretto255.js b/example-ristretto255.js new file mode 100644 index 00000000..cb8b9ebf --- /dev/null +++ b/example-ristretto255.js @@ -0,0 +1,48 @@ +var sodium = require('.') + +// Perform a secure two-party computation of f(x) = k*p(x). +// +// x is the input sent to the second party by the first party after blinding it using a random invertible scalar r, +// and k is a secret key only known by the second party. p(x) is a hash-to-group function. + +// -------- First party -------- Send `a` to second party +var x = Buffer.alloc(sodium.crypto_core_ristretto255_HASHBYTES) +sodium.randombytes_buf(x) + +// Compute p = p(x), a group element derived from x +var p = Buffer.alloc(sodium.crypto_core_ristretto255_BYTES) +sodium.crypto_core_ristretto255_from_hash(p, x) + +// Compute a = p + rg +var r = Buffer.alloc(sodium.crypto_core_ristretto255_SCALARBYTES) +var rg = Buffer.alloc(sodium.crypto_core_ristretto255_BYTES) +var a = Buffer.alloc(sodium.crypto_core_ristretto255_BYTES) +sodium.crypto_core_ristretto255_scalar_random(r) +sodium.crypto_scalarmult_ristretto255_base(rg, r) +sodium.crypto_core_ristretto255_add(a, p, rg) + +// -------- Second party -------- Send v=kg and b=ka to first party +var k = Buffer.alloc(sodium.crypto_core_ristretto255_SCALARBYTES) +sodium.randombytes_buf(k) + +// Compute v = kg +var v = Buffer.alloc(sodium.crypto_core_ristretto255_BYTES) +sodium.crypto_scalarmult_ristretto255_base(v, k) + +// Compute b = ka +var b = Buffer.alloc(sodium.crypto_core_ristretto255_BYTES) +sodium.crypto_scalarmult_ristretto255(b, k, a) + +// -------- First party -------- Unblind f(x) +// Compute irv = -rv +var ir = Buffer.alloc(sodium.crypto_core_ristretto255_SCALARBYTES) +var irv = Buffer.alloc(sodium.crypto_core_ristretto255_BYTES) +sodium.crypto_core_ristretto255_scalar_negate(ir, r) +sodium.crypto_scalarmult_ristretto255(irv, ir, v) + +// Compute f(x) = b + (-rv) = k(p + rg) - r(kg) +// = k(p + g) - kg = kp +var fx = Buffer.alloc(sodium.crypto_core_ristretto255_BYTES) +sodium.crypto_core_ristretto255_add(fx, b, irv) + +console.log('f(x) =', fx) diff --git a/test/core_ristretto255.js b/test/core_ristretto255.js new file mode 100644 index 00000000..b639b98f --- /dev/null +++ b/test/core_ristretto255.js @@ -0,0 +1,247 @@ +var test = require('tape') +var sodium = require('..') + +test('bad encodings', function (assert) { + const badEncodingsHex = [ + /* Non-canonical field encodings */ + '00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff', + 'ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f', + 'f3ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f', + 'edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f', + '0100000000000000000000000000000000000000000000000000000000000080', + + /* Negative field elements */ + '0100000000000000000000000000000000000000000000000000000000000000', + '01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f', + 'ed57ffd8c914fb201471d1c3d245ce3c746fcbe63a3679d51b6a516ebebe0e20', + 'c34c4e1826e5d403b78e246e88aa051c36ccf0aafebffe137d148a2bf9104562', + 'c940e5a4404157cfb1628b108db051a8d439e1a421394ec4ebccb9ec92a8ac78', + '47cfc5497c53dc8e61c91d17fd626ffb1c49e2bca94eed052281b510b1117a24', + 'f1c6165d33367351b0da8f6e4511010c68174a03b6581212c71c0e1d026c3c72', + '87260f7a2f12495118360f02c26a470f450dadf34a413d21042b43b9d93e1309', + + /* Non-square x^2 */ + '26948d35ca62e643e26a83177332e6b6afeb9d08e4268b650f1f5bbd8d81d371', + '4eac077a713c57b4f4397629a4145982c661f48044dd3f96427d40b147d9742f', + 'de6a7b00deadc788eb6b6c8d20c0ae96c2f2019078fa604fee5b87d6e989ad7b', + 'bcab477be20861e01e4a0e295284146a510150d9817763caf1a6f4b422d67042', + '2a292df7e32cababbd9de088d1d1abec9fc0440f637ed2fba145094dc14bea08', + 'f4a9e534fc0d216c44b218fa0c42d99635a0127ee2e53c712f70609649fdff22', + '8268436f8c4126196cf64b3c7ddbda90746a378625f9813dd9b8457077256731', + '2810e5cbc2cc4d4eece54f61c6f69758e289aa7ab440b3cbeaa21995c2f4232b', + + /* Negative xy value */ + '3eb858e78f5a7254d8c9731174a94f76755fd3941c0ac93735c07ba14579630e', + 'a45fdc55c76448c049a1ab33f17023edfb2be3581e9c7aade8a6125215e04220', + 'd483fe813c6ba647ebbfd3ec41adca1c6130c2beeee9d9bf065c8d151c5f396e', + '8a2e1d30050198c65a54483123960ccc38aef6848e1ec8f5f780e8523769ba32', + '32888462f8b486c68ad7dd9610be5192bbeaf3b443951ac1a8118419d9fa097b', + '227142501b9d4355ccba290404bde41575b037693cef1f438c47f8fbf35d1165', + '5c37cc491da847cfeb9281d407efc41e15144c876e0170b499a96a22ed31e01e', + '445425117cb8c90edcbc7c1cc0e74f747f2c1efa5630a967c64f287792a48a4b', + + /* s = -1, which causes y = 0 */ + 'ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f' + ] + + badEncodingsHex.forEach(hex => { + const s = Buffer.from(hex, 'hex', sodium.crypto_core_ristretto255_BYTES) + assert.notOk(sodium.crypto_core_ristretto255_is_valid_point(s), `${hex} was rejected`) + }) + + assert.end() +}) + +test('hash to point', function (assert) { + const hashHex = [ + '5d1be09e3d0c82fc538112490e35701979d99e06ca3e2b5b54bffe8b4dc772c1' + + '4d98b696a1bbfb5ca32c436cc61c16563790306c79eaca7705668b47dffe5bb6', + + 'f116b34b8f17ceb56e8732a60d913dd10cce47a6d53bee9204be8b44f6678b27' + + '0102a56902e2488c46120e9276cfe54638286b9e4b3cdb470b542d46c2068d38', + + '8422e1bbdaab52938b81fd602effb6f89110e1e57208ad12d9ad767e2e25510c' + + '27140775f9337088b982d83d7fcf0b2fa1edffe51952cbe7365e95c86eaf325c', + + 'ac22415129b61427bf464e17baee8db65940c233b98afce8d17c57beeb7876c2' + + '150d15af1cb1fb824bbd14955f2b57d08d388aab431a391cfc33d5bafb5dbbaf', + + '165d697a1ef3d5cf3c38565beefcf88c0f282b8e7dbd28544c483432f1cec767' + + '5debea8ebb4e5fe7d6f6e5db15f15587ac4d4d4a1de7191e0c1ca6664abcc413', + + 'a836e6c9a9ca9f1e8d486273ad56a78c70cf18f0ce10abb1c7172ddd605d7fd2' + + '979854f47ae1ccf204a33102095b4200e5befc0465accc263175485f0e17ea5c', + + '2cdc11eaeb95daf01189417cdddbf95952993aa9cb9c640eb5058d09702c7462' + + '2c9965a697a3b345ec24ee56335b556e677b30e6f90ac77d781064f866a3c982' + ] + + hashHex.forEach(hash => { + const s = sodium.sodium_malloc(sodium.crypto_core_ristretto255_BYTES) + const u = Buffer.from(hash, 'hex', sodium.crypto_core_ristretto255_HASHBYTES) + sodium.crypto_core_ristretto255_from_hash(s, u) + const hex = s.toString('hex') + assert.ok(hex, `hashed to point ${hex}`) + }) + assert.end() +}) + +test('1000 iteration check', function (assert) { + var l = Buffer.from('edd3f55c1a631258d69cf7a2def9de1400000000000000000000000000000010', 'hex') + var r = sodium.sodium_malloc(sodium.crypto_core_ristretto255_SCALARBYTES) + var rInv = sodium.sodium_malloc(sodium.crypto_core_ristretto255_SCALARBYTES) + var ru = sodium.sodium_malloc(sodium.crypto_core_ristretto255_HASHBYTES) + var s = sodium.sodium_malloc(sodium.crypto_core_ristretto255_BYTES) + var s_ = sodium.sodium_malloc(sodium.crypto_core_ristretto255_BYTES) + var s2 = sodium.sodium_malloc(sodium.crypto_core_ristretto255_BYTES) + + var n = 1000 + for (var i = 0; i < n; i++) { + sodium.crypto_core_ristretto255_scalar_random(r) + sodium.crypto_scalarmult_ristretto255_base(s, r) + assert.ok(sodium.crypto_core_ristretto255_is_valid_point(s), 'sodium.crypto_scalarmult_ristretto255_base() succeeded') + + sodium.crypto_core_ristretto255_random(s) + assert.ok(sodium.crypto_core_ristretto255_is_valid_point(s), 'sodium.crypto_core_ristretto255_random() succeeded') + + try { + sodium.crypto_scalarmult_ristretto255(s, l, s) + assert.notOk(true, 'scalarmult succeeds when multiplying point') + } catch { + assert.ok(true, 'scalarmult fails when multiplying point (1)') + } + + sodium.randombytes_buf(ru) + sodium.crypto_core_ristretto255_from_hash(s, ru) + assert.ok(sodium.crypto_core_ristretto255_is_valid_point(s), 'sodium.crypto_core_ristretto255_from_hash() succeeded') + + try { + sodium.crypto_scalarmult_ristretto255(s2, l, s) + assert.notOk(true, 'scalarmult succeeds when multiplying point') + } catch { + assert.ok(true, 'scalarmult fails when multiplying point (2)') + } + + sodium.crypto_scalarmult_ristretto255(s2, r, s) + assert.ok(sodium.crypto_core_ristretto255_is_valid_point(s2), 'sodium.crypto_scalarmult_ristretto255() succeeded') + + try { + sodium.crypto_core_ristretto255_scalar_invert(rInv, r) + assert.ok(true, 'sodium.crypto_core_ristretto255_scalar_invert() succeeded') + } catch { + assert.notOk(true, 'sodium.crypto_core_ristretto255_scalar_invert() failed') + } + + sodium.crypto_scalarmult_ristretto255(s_, rInv, s2) + assert.ok(sodium.crypto_core_ristretto255_is_valid_point(s_), 'sodium.crypto_scalarmult_ristretto255() succeeded') + + assert.ok(s.equals(s_), 'inversion succeeded') + + try { + sodium.crypto_scalarmult_ristretto255(s2, l, s2) + assert.notOk(true, 'scalarmult succeeds when multiplying point') + } catch { + assert.ok(true, 'scalarmult fails when multiplying point (3)') + } + + sodium.crypto_core_ristretto255_add(s2, s, s_) + assert.ok(sodium.crypto_core_ristretto255_is_valid_point(s2), 'addition succeeded') + + sodium.crypto_core_ristretto255_sub(s2, s2, s_) + assert.ok(sodium.crypto_core_ristretto255_is_valid_point(s2), 'subtraction succeeded') + + assert.ok(s.equals(s2), 's2 + s - s_ == s') + sodium.crypto_core_ristretto255_sub(s2, s2, s) + assert.ok(sodium.crypto_core_ristretto255_is_valid_point(s2), 'subtraction succeeded') + } + + sodium.crypto_core_ristretto255_random(s) + s_ = Buffer.alloc(sodium.crypto_core_ristretto255_BYTES) + s_.fill('fe', 'hex') + try { + sodium.crypto_core_ristretto255_add(s2, s_, s) + assert.ok(true, 'successfully added bad point') + } catch { + assert.ok(true, 'failed to add bad point') + } + try { + sodium.crypto_core_ristretto255_add(s2, s, s_) + assert.ok(true, 'successfully added bad point') + } catch { + assert.ok(true, 'failed to add bad point') + } + try { + sodium.crypto_core_ristretto255_add(s2, s_, s_) + assert.ok(true, 'successfully added bad point') + } catch { + assert.ok(true, 'failed to add bad point') + } + try { + sodium.crypto_core_ristretto255_add(s2, s, s) + assert.ok(true, 'successfully added good points') + } catch { + assert.ok(true, 'failed to add good points') + } + try { + sodium.crypto_core_ristretto255_sub(s2, s_, s) + assert.ok(true, 'successfully added bad point') + } catch { + assert.ok(true, 'failed to add bad point') + } + try { + sodium.crypto_core_ristretto255_sub(s2, s, s_) + assert.ok(true, 'successfully added bad point') + } catch { + assert.ok(true, 'failed to add bad point') + } + try { + sodium.crypto_core_ristretto255_sub(s2, s_, s_) + assert.ok(true, 'successfully added bad point') + } catch { + assert.ok(true, 'failed to add bad point') + } + try { + sodium.crypto_core_ristretto255_sub(s2, s, s) + assert.ok(true, 'successfully added good points') + } catch { + assert.ok(true, 'failed to add good points') + } + + assert.end() +}) + +test('tv4', function (assert) { + var r = sodium.sodium_malloc(sodium.crypto_core_ristretto255_NONREDUCEDSCALARBYTES) + var s1 = sodium.sodium_malloc(sodium.crypto_core_ristretto255_SCALARBYTES) + var s2 = sodium.sodium_malloc(sodium.crypto_core_ristretto255_SCALARBYTES) + var s3 = sodium.sodium_malloc(sodium.crypto_core_ristretto255_SCALARBYTES) + var s4 = sodium.sodium_malloc(sodium.crypto_core_ristretto255_SCALARBYTES) + + sodium.crypto_core_ristretto255_scalar_random(s1) + sodium.randombytes_buf(r) + sodium.crypto_core_ristretto255_scalar_reduce(s2, r) + s1.copy(s4) + sodium.crypto_core_ristretto255_scalar_add(s3, s1, s2) + sodium.crypto_core_ristretto255_scalar_sub(s4, s1, s2) + sodium.crypto_core_ristretto255_scalar_add(s2, s3, s4) + sodium.crypto_core_ristretto255_scalar_sub(s2, s2, s1) + sodium.crypto_core_ristretto255_scalar_mul(s2, s3, s2) + sodium.crypto_core_ristretto255_scalar_invert(s4, s3) + sodium.crypto_core_ristretto255_scalar_mul(s2, s2, s4) + sodium.crypto_core_ristretto255_scalar_negate(s1, s1) + sodium.crypto_core_ristretto255_scalar_add(s2, s2, s1) + sodium.crypto_core_ristretto255_scalar_complement(s1, s2) + s1[0]-- + assert.ok(sodium.sodium_is_zero(s1, sodium.crypto_core_ristretto255_SCALARBYTES)) + assert.end() +}) + +test('main', function (assert) { + assert.ok(sodium.crypto_core_ristretto255_NONREDUCEDSCALARBYTES >= sodium.crypto_core_ristretto255_SCALARBYTES) + assert.ok(sodium.crypto_core_ristretto255_HASHBYTES >= sodium.crypto_core_ristretto255_BYTES) + assert.ok(sodium.crypto_core_ristretto255_BYTES === sodium.crypto_core_ed25519_BYTES) + assert.ok(sodium.crypto_core_ristretto255_SCALARBYTES === sodium.crypto_core_ed25519_SCALARBYTES) + assert.ok(sodium.crypto_core_ristretto255_NONREDUCEDSCALARBYTES === sodium.crypto_core_ed25519_NONREDUCEDSCALARBYTES) + assert.ok(sodium.crypto_core_ristretto255_HASHBYTES >= 2 * sodium.crypto_core_ed25519_UNIFORMBYTES) + assert.end() +}) From 6300495af03a3c6cdaedb57583398ba24812e541 Mon Sep 17 00:00:00 2001 From: Christophe Diederichs Date: Thu, 7 Oct 2021 13:35:47 +0100 Subject: [PATCH 3/6] add expected outputs and tests only log on failure --- test/core_ristretto255.js | 149 +++++++++++++++----------------------- 1 file changed, 57 insertions(+), 92 deletions(-) diff --git a/test/core_ristretto255.js b/test/core_ristretto255.js index b639b98f..bba19228 100644 --- a/test/core_ristretto255.js +++ b/test/core_ristretto255.js @@ -1,6 +1,16 @@ var test = require('tape') var sodium = require('..') +const expected = [ + '3066f82a1a747d45120d1740f14358531a8f04bbffe6a819f86dfe50f44a0a46', + 'f26e5b6f7d362d2d2a94c5d0e7602cb4773c95a2e5c31a64f133189fa76ed61b', + '006ccd2a9e6867e6a2c5cea83d3302cc9de128dd2a9a57dd8ee7b9d7ffe02826', + 'f8f0c87cf237953c5890aec3998169005dae3eca1fbb04548c635953c817f92a', + 'ae81e7dedf20a497e10c304a765c1767a42d6e06029758d2d7e8ef7cc4c41179', + 'e2705652ff9f5e44d3e841bf1c251cf7dddb77d140870d1ab2ed64f1a9ce8628', + '80bd07262511cdde4863f8a7434cef696750681cb9510eea557088f76d9e5065', +].map(b => Buffer.from(b, 'hex')) + test('bad encodings', function (assert) { const badEncodingsHex = [ /* Non-canonical field encodings */ @@ -44,9 +54,9 @@ test('bad encodings', function (assert) { 'ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f' ] - badEncodingsHex.forEach(hex => { + badEncodingsHex.forEach((hex, i) => { const s = Buffer.from(hex, 'hex', sodium.crypto_core_ristretto255_BYTES) - assert.notOk(sodium.crypto_core_ristretto255_is_valid_point(s), `${hex} was rejected`) + assert.notOk(sodium.crypto_core_ristretto255_is_valid_point(s), `bad encoding ${i + 1} was rejected`) }) assert.end() @@ -76,12 +86,11 @@ test('hash to point', function (assert) { '2c9965a697a3b345ec24ee56335b556e677b30e6f90ac77d781064f866a3c982' ] - hashHex.forEach(hash => { + hashHex.forEach((hash, i) => { const s = sodium.sodium_malloc(sodium.crypto_core_ristretto255_BYTES) const u = Buffer.from(hash, 'hex', sodium.crypto_core_ristretto255_HASHBYTES) sodium.crypto_core_ristretto255_from_hash(s, u) - const hex = s.toString('hex') - assert.ok(hex, `hashed to point ${hex}`) + assert.same(s, expected[i], `hashed to point correctly`) }) assert.end() }) @@ -99,115 +108,71 @@ test('1000 iteration check', function (assert) { for (var i = 0; i < n; i++) { sodium.crypto_core_ristretto255_scalar_random(r) sodium.crypto_scalarmult_ristretto255_base(s, r) - assert.ok(sodium.crypto_core_ristretto255_is_valid_point(s), 'sodium.crypto_scalarmult_ristretto255_base() succeeded') + validPoint(s, 'sodium.crypto_scalarmult_ristretto255_base() failed') sodium.crypto_core_ristretto255_random(s) - assert.ok(sodium.crypto_core_ristretto255_is_valid_point(s), 'sodium.crypto_core_ristretto255_random() succeeded') + validPoint(s, 'sodium.crypto_core_ristretto255_random() failed') - try { - sodium.crypto_scalarmult_ristretto255(s, l, s) - assert.notOk(true, 'scalarmult succeeds when multiplying point') - } catch { - assert.ok(true, 'scalarmult fails when multiplying point (1)') - } + call(() => sodium.crypto_scalarmult_ristretto255(s, l, s), 's*l != inf (1)', true) sodium.randombytes_buf(ru) sodium.crypto_core_ristretto255_from_hash(s, ru) - assert.ok(sodium.crypto_core_ristretto255_is_valid_point(s), 'sodium.crypto_core_ristretto255_from_hash() succeeded') + validPoint(s, 'sodium.crypto_core_ristretto255_from_hash() failed') - try { - sodium.crypto_scalarmult_ristretto255(s2, l, s) - assert.notOk(true, 'scalarmult succeeds when multiplying point') - } catch { - assert.ok(true, 'scalarmult fails when multiplying point (2)') - } + call(() => sodium.crypto_scalarmult_ristretto255(s2, l, s), 's*l != inf (2)', true) sodium.crypto_scalarmult_ristretto255(s2, r, s) - assert.ok(sodium.crypto_core_ristretto255_is_valid_point(s2), 'sodium.crypto_scalarmult_ristretto255() succeeded') + validPoint(s2, 'sodium.crypto_scalarmult_ristretto255() failed') - try { - sodium.crypto_core_ristretto255_scalar_invert(rInv, r) - assert.ok(true, 'sodium.crypto_core_ristretto255_scalar_invert() succeeded') - } catch { - assert.notOk(true, 'sodium.crypto_core_ristretto255_scalar_invert() failed') - } + call(() => sodium.crypto_core_ristretto255_scalar_invert(rInv, r), + 'sodium.crypto_core_ristretto255_scalar_invert() failed') sodium.crypto_scalarmult_ristretto255(s_, rInv, s2) - assert.ok(sodium.crypto_core_ristretto255_is_valid_point(s_), 'sodium.crypto_scalarmult_ristretto255() succeeded') + validPoint(s_, 'sodium.crypto_scalarmult_ristretto255() failed') + if (Buffer.compare(s, s_)) assert.fail('inversion failed') - assert.ok(s.equals(s_), 'inversion succeeded') - - try { - sodium.crypto_scalarmult_ristretto255(s2, l, s2) - assert.notOk(true, 'scalarmult succeeds when multiplying point') - } catch { - assert.ok(true, 'scalarmult fails when multiplying point (3)') - } + call(() => sodium.crypto_scalarmult_ristretto255(s2, l, s2), 's*l != inf (3)', true) sodium.crypto_core_ristretto255_add(s2, s, s_) - assert.ok(sodium.crypto_core_ristretto255_is_valid_point(s2), 'addition succeeded') - sodium.crypto_core_ristretto255_sub(s2, s2, s_) - assert.ok(sodium.crypto_core_ristretto255_is_valid_point(s2), 'subtraction succeeded') + validPoint(s2, 'addition failed') + call(() => sodium.crypto_core_ristretto255_sub(s2, s2, s_), 'subtraction failed') + validPoint(s2, 'subtraction failed') + + if (Buffer.compare(s, s2)) assert.fail('s2 + s - s_ == s') + + call(() => sodium.crypto_core_ristretto255_sub(s2, s2, s), 'subtraction failed') - assert.ok(s.equals(s2), 's2 + s - s_ == s') - sodium.crypto_core_ristretto255_sub(s2, s2, s) - assert.ok(sodium.crypto_core_ristretto255_is_valid_point(s2), 'subtraction succeeded') + validPoint(s2, 's + s\' - s - s\' != 0') } sodium.crypto_core_ristretto255_random(s) - s_ = Buffer.alloc(sodium.crypto_core_ristretto255_BYTES) - s_.fill('fe', 'hex') - try { - sodium.crypto_core_ristretto255_add(s2, s_, s) - assert.ok(true, 'successfully added bad point') - } catch { - assert.ok(true, 'failed to add bad point') - } - try { - sodium.crypto_core_ristretto255_add(s2, s, s_) - assert.ok(true, 'successfully added bad point') - } catch { - assert.ok(true, 'failed to add bad point') - } - try { - sodium.crypto_core_ristretto255_add(s2, s_, s_) - assert.ok(true, 'successfully added bad point') - } catch { - assert.ok(true, 'failed to add bad point') - } - try { - sodium.crypto_core_ristretto255_add(s2, s, s) - assert.ok(true, 'successfully added good points') - } catch { - assert.ok(true, 'failed to add good points') - } - try { - sodium.crypto_core_ristretto255_sub(s2, s_, s) - assert.ok(true, 'successfully added bad point') - } catch { - assert.ok(true, 'failed to add bad point') - } - try { - sodium.crypto_core_ristretto255_sub(s2, s, s_) - assert.ok(true, 'successfully added bad point') - } catch { - assert.ok(true, 'failed to add bad point') - } - try { - sodium.crypto_core_ristretto255_sub(s2, s_, s_) - assert.ok(true, 'successfully added bad point') - } catch { - assert.ok(true, 'failed to add bad point') - } - try { - sodium.crypto_core_ristretto255_sub(s2, s, s) - assert.ok(true, 'successfully added good points') - } catch { - assert.ok(true, 'failed to add good points') + s_.fill(0xfe) + + call(() => sodium.crypto_core_ristretto255_add(s2, s_, s), 'successfully added bad point', true) + call(() => sodium.crypto_core_ristretto255_add(s2, s, s_), 'successfully added bad point', true) + call(() => sodium.crypto_core_ristretto255_add(s2, s_, s_), 'successfully added bad point', true) + call(() => sodium.crypto_core_ristretto255_add(s2, s, s), 'failed to add good points') + call(() => sodium.crypto_core_ristretto255_add(s2, s_, s), 'successfully added bad point', true) + call(() => sodium.crypto_core_ristretto255_add(s2, s, s_), 'successfully added bad point', true) + call(() => sodium.crypto_core_ristretto255_add(s2, s_, s_), 'successfully added bad point', true) + call(() => sodium.crypto_core_ristretto255_add(s2, s, s), 'failed to add good points') + + assert.ok(true, 'passed all iterations') + assert.end() + + function call (fn, msg, shouldFail = false) { + try { + fn() + if (shouldFail) assert.fail(msg) + } catch { + if (!shouldFail) assert.fail(msg) + } } - assert.end() + function validPoint (p, msg) { + if (!sodium.crypto_core_ristretto255_is_valid_point(p)) assert.fail(msg) + } }) test('tv4', function (assert) { From 7e2db871b6e11770164e793cf15587b819e51a2d Mon Sep 17 00:00:00 2001 From: Christophe Diederichs Date: Thu, 7 Oct 2021 13:37:05 +0100 Subject: [PATCH 4/6] check ristretto255_scalar_invert for failure --- binding.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/binding.c b/binding.c index 81605347..ef0093e0 100644 --- a/binding.c +++ b/binding.c @@ -1529,9 +1529,7 @@ napi_value sn_crypto_core_ristretto255_scalar_invert (napi_env env, napi_callbac SN_ASSERT_LENGTH(recip_size, crypto_core_ristretto255_SCALARBYTES, "recip") SN_ASSERT_LENGTH(s_size, crypto_core_ristretto255_SCALARBYTES, "s") - crypto_core_ristretto255_scalar_invert(recip_data, s_data); - - return NULL; + SN_RETURN(crypto_core_ristretto255_scalar_invert(recip_data, s_data), "point inversion failed") } napi_value sn_crypto_core_ristretto255_scalar_negate (napi_env env, napi_callback_info info) { From 7bfec9f231e6fe3f12d2050f54409a5d0275b4c0 Mon Sep 17 00:00:00 2001 From: Christophe Diederichs Date: Thu, 7 Oct 2021 13:57:38 +0100 Subject: [PATCH 5/6] move examples to folder --- examples/ristretto255.js | 48 ++++++++++++++++++++++++++++++++++++++++ examples/sodium.js | 22 ++++++++++++++++++ 2 files changed, 70 insertions(+) create mode 100644 examples/ristretto255.js create mode 100644 examples/sodium.js diff --git a/examples/ristretto255.js b/examples/ristretto255.js new file mode 100644 index 00000000..cb8b9ebf --- /dev/null +++ b/examples/ristretto255.js @@ -0,0 +1,48 @@ +var sodium = require('.') + +// Perform a secure two-party computation of f(x) = k*p(x). +// +// x is the input sent to the second party by the first party after blinding it using a random invertible scalar r, +// and k is a secret key only known by the second party. p(x) is a hash-to-group function. + +// -------- First party -------- Send `a` to second party +var x = Buffer.alloc(sodium.crypto_core_ristretto255_HASHBYTES) +sodium.randombytes_buf(x) + +// Compute p = p(x), a group element derived from x +var p = Buffer.alloc(sodium.crypto_core_ristretto255_BYTES) +sodium.crypto_core_ristretto255_from_hash(p, x) + +// Compute a = p + rg +var r = Buffer.alloc(sodium.crypto_core_ristretto255_SCALARBYTES) +var rg = Buffer.alloc(sodium.crypto_core_ristretto255_BYTES) +var a = Buffer.alloc(sodium.crypto_core_ristretto255_BYTES) +sodium.crypto_core_ristretto255_scalar_random(r) +sodium.crypto_scalarmult_ristretto255_base(rg, r) +sodium.crypto_core_ristretto255_add(a, p, rg) + +// -------- Second party -------- Send v=kg and b=ka to first party +var k = Buffer.alloc(sodium.crypto_core_ristretto255_SCALARBYTES) +sodium.randombytes_buf(k) + +// Compute v = kg +var v = Buffer.alloc(sodium.crypto_core_ristretto255_BYTES) +sodium.crypto_scalarmult_ristretto255_base(v, k) + +// Compute b = ka +var b = Buffer.alloc(sodium.crypto_core_ristretto255_BYTES) +sodium.crypto_scalarmult_ristretto255(b, k, a) + +// -------- First party -------- Unblind f(x) +// Compute irv = -rv +var ir = Buffer.alloc(sodium.crypto_core_ristretto255_SCALARBYTES) +var irv = Buffer.alloc(sodium.crypto_core_ristretto255_BYTES) +sodium.crypto_core_ristretto255_scalar_negate(ir, r) +sodium.crypto_scalarmult_ristretto255(irv, ir, v) + +// Compute f(x) = b + (-rv) = k(p + rg) - r(kg) +// = k(p + g) - kg = kp +var fx = Buffer.alloc(sodium.crypto_core_ristretto255_BYTES) +sodium.crypto_core_ristretto255_add(fx, b, irv) + +console.log('f(x) =', fx) diff --git a/examples/sodium.js b/examples/sodium.js new file mode 100644 index 00000000..f143f302 --- /dev/null +++ b/examples/sodium.js @@ -0,0 +1,22 @@ +var sodium = require('./') + +var nonce = Buffer.alloc(sodium.crypto_secretbox_NONCEBYTES) +var key = sodium.sodium_malloc(sodium.crypto_secretbox_KEYBYTES) +var message = Buffer.from('Hello, World!') +var cipher = Buffer.alloc(message.length + sodium.crypto_secretbox_MACBYTES) + +sodium.randombytes_buf(nonce) // insert random data into nonce +sodium.randombytes_buf(key) // insert random data into key + +// encrypted message is stored in cipher. +sodium.crypto_secretbox_easy(cipher, message, nonce, key) + +console.log('Encrypted message:', cipher) + +var plainText = Buffer.alloc(cipher.length - sodium.crypto_secretbox_MACBYTES) + +if (!sodium.crypto_secretbox_open_easy(plainText, cipher, nonce, key)) { + console.log('Decryption failed!') +} else { + console.log('Decrypted message:', plainText, '(' + plainText.toString() + ')') +} From 7bedb080ab22905beac5b345f5636845315062bf Mon Sep 17 00:00:00 2001 From: Luke Burns Date: Thu, 18 Nov 2021 15:55:59 -0800 Subject: [PATCH 6/6] fix examples and audit --- example-ristretto255.js | 48 ---------------------------------------- example.js | 22 ------------------ examples/ristretto255.js | 2 +- examples/sodium.js | 2 +- package.json | 2 +- 5 files changed, 3 insertions(+), 73 deletions(-) delete mode 100644 example-ristretto255.js delete mode 100644 example.js diff --git a/example-ristretto255.js b/example-ristretto255.js deleted file mode 100644 index cb8b9ebf..00000000 --- a/example-ristretto255.js +++ /dev/null @@ -1,48 +0,0 @@ -var sodium = require('.') - -// Perform a secure two-party computation of f(x) = k*p(x). -// -// x is the input sent to the second party by the first party after blinding it using a random invertible scalar r, -// and k is a secret key only known by the second party. p(x) is a hash-to-group function. - -// -------- First party -------- Send `a` to second party -var x = Buffer.alloc(sodium.crypto_core_ristretto255_HASHBYTES) -sodium.randombytes_buf(x) - -// Compute p = p(x), a group element derived from x -var p = Buffer.alloc(sodium.crypto_core_ristretto255_BYTES) -sodium.crypto_core_ristretto255_from_hash(p, x) - -// Compute a = p + rg -var r = Buffer.alloc(sodium.crypto_core_ristretto255_SCALARBYTES) -var rg = Buffer.alloc(sodium.crypto_core_ristretto255_BYTES) -var a = Buffer.alloc(sodium.crypto_core_ristretto255_BYTES) -sodium.crypto_core_ristretto255_scalar_random(r) -sodium.crypto_scalarmult_ristretto255_base(rg, r) -sodium.crypto_core_ristretto255_add(a, p, rg) - -// -------- Second party -------- Send v=kg and b=ka to first party -var k = Buffer.alloc(sodium.crypto_core_ristretto255_SCALARBYTES) -sodium.randombytes_buf(k) - -// Compute v = kg -var v = Buffer.alloc(sodium.crypto_core_ristretto255_BYTES) -sodium.crypto_scalarmult_ristretto255_base(v, k) - -// Compute b = ka -var b = Buffer.alloc(sodium.crypto_core_ristretto255_BYTES) -sodium.crypto_scalarmult_ristretto255(b, k, a) - -// -------- First party -------- Unblind f(x) -// Compute irv = -rv -var ir = Buffer.alloc(sodium.crypto_core_ristretto255_SCALARBYTES) -var irv = Buffer.alloc(sodium.crypto_core_ristretto255_BYTES) -sodium.crypto_core_ristretto255_scalar_negate(ir, r) -sodium.crypto_scalarmult_ristretto255(irv, ir, v) - -// Compute f(x) = b + (-rv) = k(p + rg) - r(kg) -// = k(p + g) - kg = kp -var fx = Buffer.alloc(sodium.crypto_core_ristretto255_BYTES) -sodium.crypto_core_ristretto255_add(fx, b, irv) - -console.log('f(x) =', fx) diff --git a/example.js b/example.js deleted file mode 100644 index f143f302..00000000 --- a/example.js +++ /dev/null @@ -1,22 +0,0 @@ -var sodium = require('./') - -var nonce = Buffer.alloc(sodium.crypto_secretbox_NONCEBYTES) -var key = sodium.sodium_malloc(sodium.crypto_secretbox_KEYBYTES) -var message = Buffer.from('Hello, World!') -var cipher = Buffer.alloc(message.length + sodium.crypto_secretbox_MACBYTES) - -sodium.randombytes_buf(nonce) // insert random data into nonce -sodium.randombytes_buf(key) // insert random data into key - -// encrypted message is stored in cipher. -sodium.crypto_secretbox_easy(cipher, message, nonce, key) - -console.log('Encrypted message:', cipher) - -var plainText = Buffer.alloc(cipher.length - sodium.crypto_secretbox_MACBYTES) - -if (!sodium.crypto_secretbox_open_easy(plainText, cipher, nonce, key)) { - console.log('Decryption failed!') -} else { - console.log('Decrypted message:', plainText, '(' + plainText.toString() + ')') -} diff --git a/examples/ristretto255.js b/examples/ristretto255.js index cb8b9ebf..124ac08e 100644 --- a/examples/ristretto255.js +++ b/examples/ristretto255.js @@ -1,4 +1,4 @@ -var sodium = require('.') +var sodium = require('..') // Perform a secure two-party computation of f(x) = k*p(x). // diff --git a/examples/sodium.js b/examples/sodium.js index f143f302..e59cf0d3 100644 --- a/examples/sodium.js +++ b/examples/sodium.js @@ -1,4 +1,4 @@ -var sodium = require('./') +var sodium = require('..') var nonce = Buffer.alloc(sodium.crypto_secretbox_NONCEBYTES) var key = sodium.sodium_malloc(sodium.crypto_secretbox_KEYBYTES) diff --git a/package.json b/package.json index 45d466e3..a3b19c11 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,7 @@ "prebuildify": "^4.2.1", "sodium-test": "^0.8.0", "sodium-vectors": "^1.0.0", - "standard": "^14.3.1", + "standard": "^16.0.4", "tape": "^5.3.1" }, "scripts": {