Socket
Socket
Sign inDemoInstall

bcrypto

Package Overview
Dependencies
Maintainers
1
Versions
59
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

bcrypto - npm Package Compare versions

Comparing version 5.3.0 to 5.4.0

cmake/CheckCThreadLocalStorage.cmake

26

deps/secp256k1/CMakeLists.txt

@@ -94,6 +94,8 @@ # CMakeLists.txt - cmake build for secp256k1

ENABLE_MODULE_ECDH=1
ENABLE_MODULE_RECOVERY=1
ENABLE_MODULE_EXTRAKEYS=1
ENABLE_MODULE_SCHNORRSIG=1
ENABLE_MODULE_SCHNORRLEG=1
ENABLE_MODULE_ELLIGATOR=1
ENABLE_MODULE_EXTRA=1
ENABLE_MODULE_RECOVERY=1
ENABLE_MODULE_SCHNORRLEG=1)
ENABLE_MODULE_EXTRA=1)

@@ -105,21 +107,13 @@ if(SECP256K1_HAS_ASM_X64)

if(SECP256K1_HAS_INT128)
list(APPEND secp256k1_defines HAVE___INT128=1)
list(APPEND secp256k1_defines USE_FORCE_WIDEMUL_INT128=1)
else()
list(APPEND secp256k1_defines USE_FORCE_WIDEMUL_INT64=1)
endif()
if(SECP256K1_BIGENDIAN)
list(APPEND secp256k1_defines WORDS_BIGENDIAN=1)
endif()
if(SECP256K1_HAS_ASM_X64 OR SECP256K1_HAS_ASM_X64)
list(APPEND secp256k1_defines USE_FIELD_5X52=1)
list(APPEND secp256k1_defines SECP256K1_BIG_ENDIAN)
else()
list(APPEND secp256k1_defines USE_FIELD_10X26=1)
list(APPEND secp256k1_defines SECP256K1_LITTLE_ENDIAN)
endif()
if(SECP256K1_HAS_ASM_X64)
list(APPEND secp256k1_defines USE_SCALAR_4X64=1)
else()
list(APPEND secp256k1_defines USE_SCALAR_8X32=1)
endif()
#

@@ -126,0 +120,0 @@ # Targets

@@ -17,2 +17,3 @@ # CMakeLists.txt - cmake build for libtorsion

include(../../cmake/AppendCCompilerFlag.cmake)
include(../../cmake/CheckCThreadLocalStorage.cmake)
include(CheckCSourceCompiles)

@@ -79,3 +80,3 @@ include(NodeJS)

__asm__ ("" : "+r" (x) ::);
__asm__ __volatile__("" :: "r" (ptr) : "memory");
__asm__ __volatile__ ("" :: "r" (ptr) : "memory");
return x;

@@ -90,9 +91,33 @@ }

check_c_source_compiles([=[
#if defined(__amd64__) || defined(__x86_64__)
# error "not an x86 platform"
#endif
#ifndef __i386__
# error "not an x86 platform"
#endif
int main(void) {
unsigned int n1 = 0;
unsigned int n0 = 100;
unsigned int d = 3;
unsigned int q0, r0;
__asm__ __volatile__ (
"divl %k4\\n"
: "=a" (q0), "=d" (r0)
: "0" (n0), "1" (n1), "rm" (d)
);
return 0;
}
]=] TORSION_HAS_ASM_X86)
else()
set(TORSION_HAS_ASM_X86)
endif()
if(TORSION_ENABLE_ASM)
check_c_source_compiles([=[
#if !defined(__amd64__) && !defined(__x86_64__)
# error "not an x64 platform"
#endif
#include <stdint.h>
int main(void) {
uint32_t stream[8], state[8];
__asm__ __volatile__(
unsigned int dst[8], src[8];
__asm__ __volatile__ (
"movups (%%rsi), %%xmm0\\n"

@@ -104,3 +129,3 @@ "movups 16(%%rsi), %%xmm1\\n"

:
: "D" (stream), "S" (state)
: "D" (dst), "S" (src)
: "xmm0", "xmm1", "cc", "memory"

@@ -117,3 +142,3 @@ );

check_c_source_compiles([=[
typedef char check_64bit_t[sizeof(void *) == 8 ? 1 : -1];
typedef char check_64bit_t[sizeof(void *) >= 8 ? 1 : -1];
typedef signed __int128 int128_t;

@@ -144,19 +169,8 @@ typedef unsigned __int128 uint128_t;

if(TORSION_ENABLE_TLS)
check_c_source_compiles([=[
#if defined(_WIN32) && !defined(__MINGW32__)
# define TLS __declspec(thread)
#else
# define TLS __thread
#endif
static TLS int value;
int main(void) {
value = 1;
return 0;
}
]=] TORSION_HAS_TLS)
check_c_thread_local_storage(TORSION_TLS)
else()
set(TORSION_HAS_TLS)
set(TORSION_TLS)
endif()
if(NOT TORSION_HAS_TLS)
if(NOT TORSION_TLS)
set(TORSION_HAS_TLS_FALLBACK ${TORSION_HAS_PTHREAD})

@@ -187,2 +201,6 @@ else()

if(TORSION_HAS_ASM_X86)
list(APPEND torsion_defines TORSION_HAVE_ASM_X86)
endif()
if(TORSION_HAS_ASM_X64)

@@ -210,4 +228,7 @@ list(APPEND torsion_defines TORSION_HAVE_ASM_X64)

if(TORSION_HAS_TLS)
if(TORSION_TLS)
list(APPEND torsion_defines TORSION_HAVE_TLS)
list(APPEND torsion_defines TORSION_TLS=${TORSION_TLS})
else()
list(APPEND torsion_defines TORSION_TLS=)
endif()

@@ -214,0 +235,0 @@

@@ -97,3 +97,3 @@ /*!

exports.version = '5.3.0';
exports.version = '5.4.0';
exports.native = exports.SHA256.native;

@@ -1219,4 +1219,4 @@ /*!

// We replicate OpenSSL which takes
// the left-most ceil(log2(n+1)) bits
// modulo `q`.
// the left-most ceil(log2(q+1)) bits
// modulo the order.
assert(Buffer.isBuffer(msg));

@@ -1226,11 +1226,14 @@ assert(q instanceof BN);

const bits = q.bitLength();
const bytes = (bits + 7) >>> 3;
assert((bits & 7) === 0);
const bytes = bits >>> 3;
if (msg.length > bytes)
msg = msg.slice(0, bytes);
return BN.decode(msg);
const m = BN.decode(msg);
const d = msg.length * 8 - bits;
if (d > 0)
m.iushrn(d);
return m;
}

@@ -1237,0 +1240,0 @@

@@ -15,5 +15,5 @@ /*!

const assert = require('../internal/assert');
const BN = require('../bn');
const elliptic = require('./elliptic');
const rng = require('../random');
const {padRight} = require('../encoding/util');

@@ -85,3 +85,8 @@ /**

return padRight(json.d, this.curve.scalarSize);
const a = BN.decode(json.d, this.curve.endian);
if (a.byteLength() > this.curve.scalarSize)
throw new Error('Invalid private key.');
return this.curve.encodeScalar(a);
}

@@ -204,8 +209,23 @@

const x = padRight(json.x, this.curve.fieldSize);
const A = this.curve.decodeX(x);
const x = BN.decode(json.x, this.curve.endian);
if (!A.validate())
if (x.cmp(this.curve.p) >= 0)
throw new Error('Invalid point.');
if (json.y != null) {
const y = BN.decode(json.y, this.curve.endian);
if (y.cmp(this.curve.p) >= 0)
throw new Error('Invalid point.');
const A = this.curve.point(x, y);
if (!A.validate())
throw new Error('Invalid point.');
return A.encode();
}
const A = this.curve.pointFromX(x);
return A.encode();

@@ -217,3 +237,3 @@ }

const a = this.curve.decodeClamped(priv);
const P = A.mulConst(a, rng);
const P = A.mulBlind(a, rng);

@@ -220,0 +240,0 @@ return P.encode();

@@ -45,5 +45,6 @@ /*!

class ECDSA {
constructor(name, hash, pre) {
constructor(name, hash, xof, pre) {
assert(typeof name === 'string');
assert(hash);
assert(xof);

@@ -53,2 +54,3 @@ this.id = name;

this.hash = hash;
this.xof = xof;
this.native = 0;

@@ -72,3 +74,3 @@

if (!this._schnorr)
this._schnorr = new Schnorr(this.curve, this.hash);
this._schnorr = new Schnorr(this.curve, this.xof);
return this._schnorr;

@@ -163,16 +165,2 @@ }

privateKeyReduce(key) {
assert(Buffer.isBuffer(key));
if (key.length > this.curve.scalarSize)
key = key.slice(0, this.curve.scalarSize);
const a = BN.decode(key, this.curve.endian).imod(this.curve.n);
if (a.isZero())
throw new Error('Invalid private key.');
return this.curve.encodeScalar(a);
}
privateKeyNegate(key) {

@@ -720,3 +708,3 @@ const a = this.curve.decodeScalar(key);

const P = A.mulConst(a, rng);
const P = A.mulBlind(a, rng);

@@ -723,0 +711,0 @@ return P.encode(compress);

@@ -266,9 +266,5 @@ /*!

scalarReduce(scalar) {
assert(Buffer.isBuffer(scalar));
const a = this.curve.decodeScalar(scalar);
const k = a.imod(this.curve.n);
if (scalar.length > this.curve.scalarSize)
scalar = scalar.slice(0, this.curve.scalarSize);
const k = BN.decode(scalar, this.curve.endian).imod(this.curve.n);
return this.curve.encodeScalar(k);

@@ -779,3 +775,3 @@ }

const a = this.curve.decodeClamped(scalar);
const P = A.mulConst(a, rng);
const P = A.mulBlind(a, rng);

@@ -782,0 +778,0 @@ if (P.isInfinity())

@@ -16,2 +16,2 @@ /*!

module.exports = new ECDSA('P192', SHA256);
module.exports = new ECDSA('P192', SHA256, SHA256);

@@ -16,2 +16,2 @@ /*!

module.exports = new ECDSA('P224', SHA256);
module.exports = new ECDSA('P224', SHA256, SHA256);

@@ -16,2 +16,2 @@ /*!

module.exports = new ECDSA('P256', SHA256);
module.exports = new ECDSA('P256', SHA256, SHA256);

@@ -16,2 +16,2 @@ /*!

module.exports = new ECDSA('P384', SHA384);
module.exports = new ECDSA('P384', SHA384, SHA384);

@@ -11,2 +11,3 @@ /*!

const SHA512 = require('../sha512');
const SHAKE256 = require('../shake256');

@@ -17,2 +18,2 @@ /*

module.exports = new ECDSA('P521', SHA512);
module.exports = new ECDSA('P521', SHA512, SHAKE256);

@@ -6,7 +6,22 @@ /*!

*
* References:
*
* [DECAF] Decaf: Eliminating cofactors through point compression
* Mike Hamburg
* https://www.shiftleft.org/papers/decaf/decaf.pdf
*
* [RIST] The Ristretto Group
* Henry de Valence, Isis Lovecruft, Tony Arcieri
* https://ristretto.group
*
* [RIST255] The ristretto255 Group
* H. de Valence, J. Grigg, G. Tankersley, F. Valsorda, I. Lovecruft
* https://tools.ietf.org/html/draft-hdevalence-cfrg-ristretto-01
*
* Resources:
* https://ristretto.group
* https://datatracker.ietf.org/doc/draft-hdevalence-cfrg-ristretto
* https://git.zx2c4.com/goldilocks
* https://github.com/dalek-cryptography/curve25519-dalek
* https://git.zx2c4.com/goldilocks/tree/_aux/ristretto/ristretto.sage
* https://git.zx2c4.com/goldilocks/tree/src/per_curve/decaf.tmpl.c
* https://git.zx2c4.com/goldilocks/tree/src/per_curve/elligator.tmpl.c
* https://github.com/dalek-cryptography/curve25519-dalek/blob/9a62386/src/ristretto.rs
* https://github.com/bwesterb/go-ristretto/blob/9343fcb/edwards25519/elligator.go
*/

@@ -25,4 +40,24 @@

constructor(curve) {
// [RIST] "The Ristretto Group".
//
// Assumptions (h = 4):
//
// - p = 3 (mod 4).
// - a = 1 mod p.
// - d is non-square in F(p).
//
// Assumptions (h = 8):
//
// - p = 5 (mod 8).
// - a = -1 mod p.
// - d is non-square in F(p).
//
// No other parameters are acceptable.
assert(curve != null);
assert(curve.type === 'edwards');
assert(curve.h.cmpn(4) === 0 || curve.h.cmpn(8) === 0);
assert((curve.p.andln(3) === 3) === (curve.h.cmpn(4) === 0));
assert((curve.p.andln(7) === 5) === (curve.h.cmpn(8) === 0));
assert((curve.a.cmp(curve.one) === 0) === (curve.h.cmpn(4) === 0));
assert((curve.a.cmp(curve.one.redNeg()) === 0) === (curve.h.cmpn(8) === 0));

@@ -35,54 +70,45 @@ // Curve.

// AD = a * d
// ad = a * d
this.ad = this.curve._mulA(this.curve.d);
// MA = -a
this.ma = this.curve.a.redNeg();
// AMD = a - d
// amd = a - d
this.amd = this.curve.a.redSub(this.curve.d);
// ADM1S = sqrt(a * d - 1)
// adm1s = sqrt(a * d - 1)
this.adm1s = this.ad.redSub(this.curve.one).redSqrt();
// ADM1SI = 1 / sqrt(a * d - 1)
// adm1si = 1 / sqrt(a * d - 1)
this.adm1si = this.adm1s.redInvert();
// DPA = d + a
// dpa = d + a
this.dpa = this.curve.d.redAdd(this.curve.a);
// DMA = d - a
// dma = d - a
this.dma = this.curve.d.redSub(this.curve.a);
// DMADDPA = DMA / DPA
// dmaddpa = (d - a) / (d + a)
this.dmaddpa = this.dma.redDiv(this.dpa);
// if H = 8
// h = 8
if (this.curve.h.cmpn(8) === 0) {
// QNR = sqrt(a)
// qnr = sqrt(a)
this.qnr = this.curve.a.redSqrt();
// MAS = sqrt(-a)
this.mas = this.ma.redSqrt();
// amdsi = 1 / sqrt(a - d) = 1 / sqrt(a * d - 1)
this.amdsi = this.adm1si.clone();
// AMDSI = 1 / sqrt(a - d)
this.amdsi = this.amd.redSqrt().redInvert();
// DMASI = 1 / sqrt(d - a)
// dmasi = 1 / sqrt(d - a)
this.dmasi = this.dma.redSqrt().redInvert();
} else {
// QNR = non-square in F(p).
// qnr = non-square in F(p).
this.qnr = this.curve.z;
// MAS = 0 (unused)
this.mas = this.curve.zero;
// AMDSI = 0 (unused)
// amdsi = 0 (unused)
this.amdsi = this.curve.zero;
// DMASI = 0 (unused)
// dmasi = 0 (unused)
this.dmasi = this.curve.zero;
}
// QNRDS = sqrt(QNR * D)
// qnrds = sqrt(qnr * d)
this.qnrds = this.curve._mulD(this.qnr).redSqrt();

@@ -104,3 +130,8 @@

if (this.curve.id === 'ED25519'
|| this.curve.id === 'ED448') {
|| this.curve.id === 'ED448'
|| this.curve.id === 'ED1174'
|| this.curve.id === 'E222'
|| this.curve.id === 'E382'
|| this.curve.id === 'E521'
|| this.curve.id === 'MDC') {
this.adm1si = this.adm1si.redNeg();

@@ -111,3 +142,2 @@ }

_invsqrt(v) {
// https://github.com/dalek-cryptography/curve25519-dalek/blob/9a62386/src/field.rs#L270
return this._isqrt(this.curve.one, v);

@@ -117,180 +147,55 @@ }

_isqrt(u, v) {
// p mod 4 == 3 (p448)
if (this.curve.p.andln(3) === 3)
return this._isqrt3mod4(u, v);
// [RIST] "Extracting an Inverse Square Root".
// [RIST255] Page 6, Section 3.1.3.
let ok = true;
let r;
// p mod 8 == 5 (p25519)
if (this.curve.p.andln(7) === 5)
return this._isqrt5mod8(u, v);
// R = sqrt(u / v)
try {
r = u.redDivSqrt(v);
} catch ({result}) {
r = result.toRed(this.curve.red);
ok = false;
}
// Compute `r = sqrt(u / v)` slowly.
return this._isqrt0(u, v);
}
_isqrt3mod4(u, v) {
// https://git.zx2c4.com/goldilocks/tree/_aux/ristretto/ristretto.sage#n48
// https://git.zx2c4.com/goldilocks/tree/src/p448/f_arithmetic.c
// Compute sqrt(u / v).
assert(u instanceof BN);
assert(v instanceof BN);
// U2 = U^2
const u2 = u.redSqr();
// U3 = U2 * U
const u3 = u2.redMul(u);
// U5 = U3 * U2
const u5 = u3.redMul(u2);
// V3 = V^2 * V
const v3 = v.redSqr().redMul(v);
// E = (p - 3) / 4
const e = this.curve.p.subn(3).iushrn(2);
// P = (U5 * V3)^E
const p = u5.redMul(v3).redPow(e);
// R = U3 * V * P
const r = u3.redMul(v).redMul(p);
// C = V * R^2
const c = v.redMul(r.redSqr());
// CSS = C = U
const css = c.ceq(u);
// R = -R if R < 0
r.cinject(r.redNeg(), r.redIsOdd() | 0);
if (r.redIsOdd())
r.redINeg();
// Return (CSS, R).
return [css, r];
return [ok, r];
}
_isqrt5mod8(u, v) {
// https://ristretto.group/formulas/invsqrt.html
// https://github.com/dalek-cryptography/curve25519-dalek/blob/9a62386/src/field.rs#L210
// https://git.zx2c4.com/goldilocks/tree/src/p25519/f_arithmetic.c
// Compute sqrt(u / v).
assert(u instanceof BN);
assert(v instanceof BN);
// V3 = V^2 * V
const v3 = v.redSqr().redMul(v);
// V7 = V3^2 * V
const v7 = v3.redSqr().redMul(v);
// E = (p - 5) / 8
const e = this.curve.p.subn(5).iushrn(3);
// P = (U * V7)^E
const p = u.redMul(v7).redPow(e);
// R = U * V3 * P
const r = u.redMul(v3).redMul(p);
// C = V * R^2
const c = v.redMul(r.redSqr());
// CSS = C = U
const css = c.ceq(u);
// MC = -C
const mc = c.redINeg();
// FSS = MC = U
const fss = mc.ceq(u);
// FSSI = MC = U * sqrt(-1)
const fssi = mc.ceq(u.redMul(this.qnr));
// R = sqrt(-1) * R if FSS = 1 or FSSI = 1
r.cinject(this.qnr.redMul(r), fss | fssi);
// R = -R if R < 0
r.cinject(r.redNeg(), r.redIsOdd() | 0);
// Return (CSS | FSS, R).
return [css | fss, r];
}
_isqrt0(u, v) {
// https://git.zx2c4.com/goldilocks/tree/_aux/ristretto/ristretto.sage#n58
// Compute sqrt(u / v).
assert(u instanceof BN);
assert(v instanceof BN);
// E = p - 2
const e = this.curve.p.subn(2);
// X = U / V
const x = u.redMul(v.redPow(e));
// CSS = X is square
const css = x.redIsSquare() | 0;
// X = X * qnr if CSS != 1
x.cinject(x.redMul(this.qnr), css ^ 1);
// R = sqrt(X)
const r = x.redSqrt();
// R = -R if R < 0
r.cinject(r.redNeg(), r.redIsOdd() | 0);
// Return (CSS, R).
return [css, r];
}
encode(p) {
// [DECAF] Page 8, Section 4.2.
// Page 15, Appendix A.1.
// [RIST] "Encoding from Extended Coordinates".
// [RIST255] Page 8, Section 3.2.2.
//
// Affine Formula:
//
// If h = 8 and x * y < 0 or x = 0 then (x, y) = (x, y) + Q
// If x < 0 or y = -1 then (x, y) = (-x, -y)
// s = +sqrt(-a * (1 - y) / (1 + y))
//
// Where Q is a 4-torsion point.
//
// Note that the U1 calculation stated in the
// formula is actually:
//
// U1 = (Z0 + Y0) * (Z0 - Y0)
//
// The calculation of S stated in the formula is:
//
// S = sqrt(-a) * (Z0 - Y) * D
//
// We move the `sqrt(-a)` in S to U1 with the
// following modifications:
//
// U1 = -a * (Z0 + Y0) * (Z0 - Y0)
// S = (Z0 - Y) * D
assert(p instanceof this.Point);
// H = 4
if (this.curve.h.cmpn(4) === 0)
return this._encode4(p);
// U1 = -a * (Z0 + Y0) * (Z0 - Y0)
const u1 = this.curve._mulA(p.y.redAdd(p.z).redMul(p.y.redSub(p.z)));
// H = 8
return this._encode8(p);
}
_encode4(p) {
// https://git.zx2c4.com/goldilocks/tree/_aux/ristretto/ristretto.sage#n176
// https://git.zx2c4.com/goldilocks/tree/src/per_curve/decaf.tmpl.c#n233
// U = -((Z0 + Y0) * (Z0 - Y0))
const u = p.z.redAdd(p.y).redMul(p.z.redSub(p.y)).redINeg();
// I = 1 / sqrt(U * Y0^2)
const [, i] = this._invsqrt(u.redMul(p.y.redSqr()));
// N = I^2 * U * Y0 * T0
const n = i.redSqr().redMul(u).redMul(p.y).redMul(p.t);
// Y = Y0
const y = p.y.clone();
// Y = -Y if N < 0
y.cinject(y.redNeg(), n.redIsOdd() | 0);
// S = I * Y * (Z0 - Y)
const s = i.redMul(y).redMul(p.z.redSub(y));
// S = -S if S < 0
s.cinject(s.redNeg(), s.redIsOdd() | 0);
// Return the byte encoding of S.
return this.curve.encodeField(s.fromRed());
}
_encode8(p) {
// https://ristretto.group/formulas/encoding.html
// https://github.com/dalek-cryptography/curve25519-dalek/blob/9a62386/src/ristretto.rs#L434
// https://git.zx2c4.com/goldilocks/tree/_aux/ristretto/ristretto.sage#n176
// https://git.zx2c4.com/goldilocks/tree/src/per_curve/decaf.tmpl.c#n233
// U1 = (Z0 + Y0) * (Z0 - Y0)
const u1 = p.z.redAdd(p.y).redMul(p.z.redSub(p.y));
// U2 = X0 * Y0

@@ -320,22 +225,27 @@ const u2 = p.x.redMul(p.y);

// rotate = T0 * Zinv < 0
const rotate = p.t.redMul(zinv).redIsOdd() | 0;
// h = 8
if (this.curve.h.cmpn(8) === 0) {
// rotate = T0 * Zinv < 0
if (p.t.redMul(zinv).redIsOdd()) {
// X = Y0 * sqrt(a) if rotate
x.inject(p.y.redMul(this.qnr));
// X = Y0 * sqrt(a) if rotate = 1
x.cinject(p.y.redMul(this.qnr), rotate);
// Y = X0 * sqrt(a) if rotate
y.inject(p.x.redMul(this.qnr));
// Y = X0 * sqrt(a) if rotate = 1
y.cinject(p.x.redMul(this.qnr), rotate);
// D = D1 / sqrt(a - d) if rotate
d.inject(d1.redMul(this.amdsi));
}
}
// D = D1 / sqrt(a - d) if rotate = 1
d.cinject(d1.redMul(this.amdsi), rotate);
// Y = -Y if X * Zinv < 0
y.cinject(y.redNeg(), x.redMul(zinv).redIsOdd() | 0);
if (x.redMul(zinv).redIsOdd())
y.redINeg();
// S = sqrt(-a) * (Z - Y) * D
const s = this.mas.redMul(d.redMul(p.z.redSub(y)));
// S = (Z0 - Y) * D
const s = d.redMul(p.z.redSub(y));
// S = -S if S < 0
s.cinject(s.redNeg(), s.redIsOdd() | 0);
if (s.redIsOdd())
s.redINeg();

@@ -347,6 +257,19 @@ // Return the byte encoding of S.

decode(bytes) {
// https://ristretto.group/formulas/decoding.html
// https://github.com/dalek-cryptography/curve25519-dalek/blob/9a62386/src/ristretto.rs#L251
// https://git.zx2c4.com/goldilocks/tree/_aux/ristretto/ristretto.sage#n248
// https://git.zx2c4.com/goldilocks/tree/src/per_curve/decaf.tmpl.c#n239
// [DECAF] Page 8, Section 4.3.
// Page 16, Appendix A.2.
// [RIST] "Decoding to Extended Coordinates".
// [RIST255] Page 7, Section 3.2.1.
//
// Assumptions:
//
// - Let s be a canonically encoded field element.
// - s >= 0.
// - (4 * s^2 / (a * d * (1 + w)^2 - (1 - w)^2)) is square in F(p).
// - if h = 8 then t >= 0 and y != 0.
//
// Affine Formula:
//
// y = (1 + a * s^2) / (1 - a * s^2)
// w = a * s^2
// x = +sqrt(4 * s^2 / (a * d * (1 + w)^2 - (1 - w)^2))
const e = this.curve.decodeField(bytes);

@@ -361,3 +284,3 @@

// S < 0
// Reject if S < 0.
if (s.redIsOdd())

@@ -394,3 +317,4 @@ throw new Error('Invalid point.');

// X = -X if X < 0
x.cinject(x.redNeg(), x.redIsOdd() | 0);
if (x.redIsOdd())
x.redINeg();

@@ -406,14 +330,14 @@ // Y = U1 * DY

// if H = 4
// h = 4
if (this.curve.h.cmpn(4) === 0) {
// SQR = 0
if (sqr ^ 1)
// Reject if V * U2^2 is not square.
if (!sqr)
throw new Error('Invalid point.');
// P = (X : Y : Z)
// P = (X : Y : Z: T)
return this.curve.point(x, y, z, t);
}
// SQR = 0 or T < 0 or Y = 0
if ((sqr ^ 1) | t.redIsOdd() | y.czero())
// Reject if V * U2^2 is not square or T < 0 or Y = 0.
if (!sqr || t.redIsOdd() || y.isZero())
throw new Error('Invalid point.');

@@ -425,5 +349,154 @@

encodeBatch(points) {
// [DECAF] Page 9, Section 4.7.
// [RIST] "Batched Double-and-Encode".
//
// Affine Formula:
//
// e = 2 * x * y
// f = 1 + ((x * y)^2 * d)
// g = y^2 - a * x^2
// h = 1 - ((x * y)^2 * d)
//
// if h = 8 and e * g / (f * h) < 0
// e = g, g = -e
// h = f * sqrt(a)
// magic = sqrt(a)
// else
// magic = 1 / sqrt(a - d) if h = 8
// = 1 / sqrt(a * d - 1) otherwise
//
// g = -g if h * e / (f * h) < 0
// s = +((h - g) * magic * g / (e * g))
//
// The trick here is that the inverses can be
// batched. Every product of (e * g * f * h)
// can be inverted with montgomery's trick.
// The necessary inverses can then be retrieved
// from each value with:
//
// (e * g) / (e * g * f * h) = 1 / (f * h)
// (f * h) / (e * g * f * h) = 1 / (e * g)
assert(Array.isArray(points));
for (const p of points)
assert(p instanceof this.Point);
const states = [];
const products = [];
// Set up state.
for (const p of points) {
// XX = X0^2
const xx = p.x.redSqr();
// YY = Y0^2
const yy = p.y.redSqr();
// ZZ = Z0^2
const zz = p.z.redSqr();
// DTT = T0^2 * d
const dtt = p.t.redSqr().redMul(this.curve.d);
// E = 2 * X0 * Y0
const e = p.x.redMul(p.y.redAdd(p.y));
// F = ZZ + DTT
const f = zz.redAdd(dtt);
// G = YY - a * XX
const g = yy.redSub(this.curve._mulA(xx));
// H = ZZ - DTT
const h = zz.redSub(dtt);
// EG = E * G
const eg = e.redMul(g);
// FH = F * H
const fh = f.redMul(h);
// EFGH = EG * FH
const efgh = eg.redMul(fh);
states.push([e, f, g, h, eg, fh]);
products.push(efgh);
}
// Montgomery's trick.
const invs = this.curve.red.invertAll(products);
const out = [];
// Output encoded points.
for (let i = 0; i < states.length; i++) {
const [e, f, g, h, eg, fh] = states[i];
// Zinv = EG / EFGH
const zinv = eg.redMul(invs[i]);
// Tinv = FH / EFGH
const tinv = fh.redMul(invs[i]);
// magic = 1 / sqrt(a - d)
const magic = this.amdsi.clone();
// h = 8
if (this.curve.h.cmpn(8) === 0) {
// rotate = EG * Zinv < 0
if (eg.redMul(zinv).redIsOdd()) {
// ME = -E
const me = e.redNeg();
// FQNR = F * sqrt(a)
const fqnr = f.redMul(this.qnr);
// E = G if rotate
e.inject(g);
// G = ME if rotate
g.inject(me);
// H = FQNR if rotate
h.inject(fqnr);
// magic = sqrt(a) if rotate
magic.inject(this.qnr);
}
} else {
// magic = 1 / sqrt(a * d - 1)
magic.inject(this.adm1si);
}
// G = -G if H * E * Zinv < 0
if (h.redMul(e).redMul(zinv).redIsOdd())
g.redINeg();
// S = (H - G) * magic * G * Tinv
const s = h.redSub(g).redMul(magic).redMul(g).redMul(tinv);
// S = -S if S < 0
if (s.redIsOdd())
s.redINeg();
// Output the byte encoding of S.
out.push(this.curve.encodeField(s.fromRed()));
}
return out;
}
eq(p, q) {
// https://ristretto.group/formulas/equality.html
// https://github.com/dalek-cryptography/curve25519-dalek/blob/9a62386/src/ristretto.rs#L752
// [DECAF] Page 9, Section 4.5.
// [RIST] "Testing Equality".
// [RIST255] Page 9, Section 3.2.3.
//
// Affine Formula (h = 4):
//
// x1 * y2 = y1 * x2
//
// Affine Formula (h = 8):
//
// x1 * y2 = y1 * x2 or
// y1 * y2 = -a * x1 * x2
assert(p instanceof this.Point);

@@ -438,32 +511,68 @@ assert(q instanceof this.Point);

// EQ1 = X1 * Y2 = Y1 * X2
const eq1 = xy.ceq(yx);
// X1 * Y2 = Y1 * X2
if (xy.eq(yx))
return true;
// if H = 4
if (this.curve.h.cmpn(4) === 0) {
// Return (EQ1).
return Boolean(eq1);
// h = 8
if (this.curve.h.cmpn(8) === 0) {
// YY = Y1 * Y2
const yy = p.y.redMul(q.y);
// XX = -a * X1 * X2
const xx = p.x.redMul(q.x);
// Y1 * Y2 = -a * X1 * X2
if (yy.eq(xx))
return true;
}
// YY = Y1 * Y2
const yy = p.y.redMul(q.y);
return false;
}
// XX = -a * X1 * X2
const xx = this.ma.redMul(p.x).redMul(q.x);
isInfinity(p) {
// See above for references.
//
// Affine Formula (h = 4):
//
// x = 0
//
// Affine Formula (h = 8):
//
// x = 0 or y = 0
assert(p instanceof this.Point);
// EQ2 = Y1 * Y2 = -a * X1 * X2
const eq2 = yy.ceq(xx);
// X1 = 0
if (p.x.isZero())
return true;
// Return (EQ1 | EQ2).
return Boolean(eq1 | eq2);
// h = 8
if (this.curve.h.cmpn(8) === 0) {
// Y1 = 0
if (p.y.isZero())
return true;
}
return false;
}
pointFromUniform(r0) {
// Distribution: 2/h (1).
// https://ristretto.group/details/elligator.html
// https://ristretto.group/details/elligator_in_extended.html
// https://ristretto.group/formulas/elligator.html
// https://github.com/dalek-cryptography/curve25519-dalek/blob/9a62386/src/ristretto.rs#L592
// https://git.zx2c4.com/goldilocks/tree/_aux/ristretto/ristretto.sage#n298
// https://git.zx2c4.com/goldilocks/tree/src/per_curve/elligator.tmpl.c#n28
// [DECAF] Page 12, Section 6.
// Page 19, Appendix C.
// [RIST] "Elligator in Extended Coordinates".
// [RIST255] Page 10, Section 3.2.4.
//
// Affine Formula:
//
// w = (d * r - a) * (a * r - d)
// s = +sqrt((a * (r + 1) * (d + a) * (d - a)) / w
// t = +(a * (r - 1) * (d + a)^2) / w - 1
//
// Or:
//
// w = (d * r - a) * (a * r - d)
// s = -sqrt((a * r * (r + 1) * (d + a) * (d - a)) / w
// t = -(a * r * (r - 1) * (d + a)^2) / w - 1
//
// Depending on which square root exists, preferring
// the second when r = 0 or both are square.
assert(r0 instanceof BN);

@@ -499,9 +608,12 @@

// S' = -S' if S' >= 0
sp.cinject(sp.redNeg(), sp.redIsOdd() ^ 1);
if (!sp.redIsOdd())
sp.redINeg();
// S = S' if S^2 != NS / D
s.cinject(sp, sqr ^ 1);
if (!sqr) {
// S = S' if NS / D is not square
s.inject(sp);
// C = R if S^2 != NS / D
c.cinject(r, sqr ^ 1);
// C = R if NS / D is not square
c.inject(r);
}

@@ -514,3 +626,3 @@ // DS = (d + a)^2

// AS2 = A * S^2
// AS2 = a * S^2
const as2 = this.curve._mulA(s.redSqr());

@@ -524,6 +636,6 @@

// W2 = 1 + a * s^2
// W2 = 1 + a * S^2
const w2 = this.curve.one.redAdd(as2);
// W3 = 1 - a * s^2
// W3 = 1 - a * S^2
const w3 = this.curve.one.redSub(as2);

@@ -548,36 +660,80 @@

pointToUniform(p, hint) {
// https://git.zx2c4.com/goldilocks/tree/src/per_curve/elligator.tmpl.c#n106
// https://github.com/bwesterb/go-ristretto/blob/9343fcb/edwards25519/elligator.go#L17
// [RIST] "Isogenies".
//
// Notes:
// - Each point has a 99%+ chance of mapping to at least one preimage.
// - The preimage distribution is even, meaning we can simply randomly
// select a preimage without rejection sampling (each preimage has a
// ~50% chance of existing).
// Convert a ristretto group element to a field
// element by inverting the ristretto-flavored
// elligator.
//
// Hint Layout:
//
// [00000000] 000[0] [0000]
// | | |
// | | +-- index for jacobi quartic point
// | +-- sign bit
// +-- bits to OR with uniform bytes
//
// In order to invert the ristretto elligator, we
// must first first map the edwards point to an
// isogenous jacobi quartic curve.
//
// Isogeny: E(a,d) -> J(a^2,a-2d)
//
// This gives us a maximum of `h` possible points
// to work with in the jacobi quartic space.
//
// After a jacobi quartic point is chosen, it is
// run through the inverse elligator 2 map, and
// oddness is set according to the sign in the
// hint.
//
// Note that the upper half of all jacobi quartic
// points will be the negations of the lower half.
assert(p instanceof this.Point);
assert((hint >>> 0) === hint);
const R = [];
const sign = (hint >>> 4) & 15;
const index = hint & 15;
const Q = this._quartic(p);
const len = Q.length;
for (const [s, t] of this._quartic(p)) {
const [v0, r0] = this._invert(s, t);
const [v1, r1] = this._invert(s.redNeg(), t.redNeg());
for (let i = 0; i < len; i++) {
const [s, t] = Q[i];
if (v0)
R.push(r0);
if (v1)
R.push(r1);
Q.push([s.redNeg(), t.redNeg()]);
}
if (R.length === 0)
throw new Error('Invalid point.');
const [s, t] = Q[index % Q.length];
return R[hint % R.length];
return this._invert(s, t, sign);
}
_quartic(p) {
// https://git.zx2c4.com/goldilocks/tree/_aux/ristretto/ristretto.sage#n351
// https://git.zx2c4.com/goldilocks/tree/src/per_curve/decaf.tmpl.c#n145
// https://github.com/bwesterb/go-ristretto/blob/9343fcb/edwards25519/elligator.go#L57
// [DECAF] Page 7, Section 4.1.
// [RIST] "Isogenies".
//
// Affine Formula:
//
// g = sqrt(y^4 * x^2 * (1 - y^2))
//
// d1 = y^2 / g
// s1 = d1 * (1 - y) * x
// t1 = 2 * d1 * (1 - y) / sqrt(a * d - 1)
// s2 = -d1 * (1 + y) * x
// t2 = 2 * d1 * (1 + y) / sqrt(a * d - 1)
//
// if h = 8
// d2 = -(1 - y^2) / (g * sqrt(d - a))
// s3 = d2 * (sqrt(a) - x) * y
// t3 = 2 * d2 * (sqrt(a) - x) * sqrt(a) / sqrt(a * d - 1)
// s4 = -d2 * (sqrt(a) + x) * y
// t4 = 2 * d2 * (sqrt(a) + x) * sqrt(a) / sqrt(a * d - 1)
//
// Undefined for x = 0 or y = 0.
//
// The exceptional cases must be handled as:
//
// (s1, t1) = (0, 1)
// (s2, t2) = (0, 1)
// (s3, t3) = (+1, 2 * sqrt(a) / sqrt(a * d - 1))
// (s4, t4) = (-1, 2 * sqrt(a) / sqrt(a * d - 1))
assert(p instanceof this.Point);

@@ -588,5 +744,2 @@

// XYZ = X0 = 0 or Y0 = 0
const xyz = x.czero() | y.czero();
// X2 = X0^2

@@ -601,3 +754,3 @@ const x2 = x.redSqr();

// Z2 = Z^2
// Z2 = Z0^2
const z2 = z.redSqr();

@@ -614,6 +767,6 @@

// SX = D0 * (Z - Y0)
// SX = D0 * (Z0 - Y0)
const sx = d0.redMul(z.redSub(y));
// SPXP = D0 * (Z + Y0)
// SPXP = D0 * (Z0 + Y0)
const spxp = d0.redMul(z.redAdd(y));

@@ -627,3 +780,3 @@

// H0 = 2 / sqrt(a * d - 1) * Z
// H0 = 2 * Z0 / sqrt(a * d - 1)
const h0 = this.adm1si.redMuln(2).redMul(z);

@@ -637,78 +790,94 @@

// S0 = 0, T0 = 1 if XYZ = 1
s0.cinject(zero, xyz);
t0.cinject(one, xyz);
// X0 = 0 or Y0 = 0
if (x.isZero() || y.isZero()) {
// S0 = 0, T0 = 1 if X0 = 0 or Y0 = 0
s0.inject(zero);
t0.inject(one);
// S0 = 0, T0 = 1 if XYZ = 1
s1.cinject(zero, xyz);
t1.cinject(one, xyz);
// H = 4
if (this.curve.h.cmpn(4) === 0) {
// Return ((S0, T0), ...).
return [[s0, t0], [s1, t1]];
// S1 = 0, T1 = 1 if X0 = 0 or Y0 = 0
s1.inject(zero);
t1.inject(one);
}
// D1 = (1 / sqrt(d - a)) * -Z2MY2 * G
const d1 = z2my2.redNeg().redMul(this.dmasi).redMul(g);
// h = 8
if (this.curve.h.cmpn(8) === 0) {
// D1 = -Z2MY2 * G / sqrt(d - a)
const d1 = z2my2.redNeg().redMul(this.dmasi).redMul(g);
// IZ = qnr * Z
const iz = this.qnr.redMul(z);
// IZ = sqrt(a) * Z0
const iz = this.qnr.redMul(z);
// SY = D1 * (IZ - X0)
const sy = d1.redMul(iz.redSub(x));
// SY = D1 * (IZ - X0)
const sy = d1.redMul(iz.redSub(x));
// SPYP = D1 * (IZ + X0)
const spyp = d1.redMul(iz.redAdd(x));
// SPYP = D1 * (IZ + X0)
const spyp = d1.redMul(iz.redAdd(x));
// S2 = SY * Y0
const s2 = sy.redMul(y);
// S2 = SY * Y0
const s2 = sy.redMul(y);
// S3 = -SPYP * Y0
const s3 = spyp.redNeg().redMul(y);
// S3 = -SPYP * Y0
const s3 = spyp.redNeg().redMul(y);
// H1 = (2 / sqrt(a * d - 1)) * IZ
const h1 = this.adm1si.redMuln(2).redMul(iz);
// H1 = 2 * IZ / sqrt(a * d - 1)
const h1 = this.adm1si.redMuln(2).redMul(iz);
// T2 = H1 * SY
const t2 = h1.redMul(sy);
// T2 = H1 * SY
const t2 = h1.redMul(sy);
// T3 = H1 * SPYP
const t3 = h1.redMul(spyp);
// T3 = H1 * SPYP
const t3 = h1.redMul(spyp);
// H2 = qnr / sqrt(a * d - 1)
const h2 = this.qnr.redMul(this.adm1si);
// H2 = 2 * sqrt(a) / sqrt(a * d - 1)
const h2 = this.qnr.redMul(this.adm1si).redIMuln(2);
// S0 = 1, T0 = H2 if XYZ = 1
s2.cinject(one, xyz);
t2.cinject(h2, xyz);
// X0 = 0 or Y0 = 0
if (x.isZero() || y.isZero()) {
// S2 = 1, T2 = H2 if X0 = 0 or Y0 = 0
s2.inject(one);
t2.inject(h2);
// S0 = -1, T0 = H2 if XYZ = 1
s3.cinject(one.redNeg(), xyz);
t3.cinject(h2, xyz);
// S3 = -1, T3 = H2 if X0 = 0 or Y0 = 0
s3.inject(one.redNeg());
t3.inject(h2);
}
// Return ((S0, T0), ...).
return [[s0, t0],
[s1, t1],
[s2, t2],
[s3, t3]];
}
// Return ((S0, T0), ...).
return [[s0, t0],
[s1, t1],
[s2, t2],
[s3, t3]];
return [[s0, t0], [s1, t1]];
}
_invert(s, t) {
// https://github.com/bwesterb/go-ristretto/blob/9343fcb/edwards25519/elligator.go#L151
_invert(s, t, hint) {
// [DECAF] Page 13, Section 6.
//
// Assumptions:
//
// - qnr * (s^4 - w^2) is square in F(p).
// - s != 0, t != +-1.
//
// Affine Formula:
//
// w = (t + 1) * (d - a) / (d + a)
// r = (w + s^2) / sqrt(qnr * (s^4 - w^2))
//
// Undefined for s = 0 and t = +-1.
//
// The exceptional cases must be handled as:
//
// (0, +1) -> sqrt(qnr * d)
// (0, -1) -> 0
assert(s instanceof BN);
assert(t instanceof BN);
assert((hint >>> 0) === hint);
const {zero, one} = this.curve;
// A = (T + 1) * (d - a) / (d + a)
const a = t.redAdd(this.curve.one).redMul(this.dmaddpa);
// TZ = T = 0
const tz = t.czero();
// TO = T = 1
const to = tz & t.ceq(one);
// A = (T + 1) * ((d - a) / (d + a))
const a = t.redAdd(one).redMul(this.dmaddpa);
// A = A^2
// A2 = A^2
const a2 = a.redSqr();

@@ -723,7 +892,7 @@

// Y = 1 / sqrt(qnr * (S4 - A2))
// SQR = Y^2 = 1 / (qnr * (S4 - A2))
const [sqr, y] = this._invsqrt(this.qnr.redMul(s4.redSub(a2)));
// S2 = -S2 if S < 0
s2.cinject(s2.redNeg(), s.redIsOdd() | 0);
if (s.redIsOdd())
s2.redINeg();

@@ -733,18 +902,24 @@ // R = (A + S2) * Y

// R = -R if R < 0
r.cinject(r.redNeg(), r.redIsOdd() | 0);
// R = sqrt(qnr * d) if S = 0, T = 1
if (s.isZero() && t.eq(this.curve.one))
r.inject(this.qnrds);
// R = 0 if TZ = 1
r.cinject(zero, tz);
// R = 0 if S = 0, T = -1
if (s.isZero() && !t.eq(this.curve.one))
r.inject(this.curve.zero);
// R = sqrt(qnr * d) if TO = 1
r.cinject(this.qnrds, to);
// R = -R if R < 0 (or random)
if (r.redIsOdd() !== Boolean(hint & 1))
r.redINeg();
// Return (SQR | TZ, R).
return [sqr | tz, r];
// Fail if (qnr * (S4 - A2)) is not square.
if (!sqr && !s.isZero())
throw new Error('Invalid point.');
return r;
}
pointFromHash(bytes) {
// https://github.com/dalek-cryptography/curve25519-dalek/blob/9a62386/src/ristretto.rs#L713
// https://git.zx2c4.com/goldilocks/tree/src/per_curve/elligator.tmpl.c#n87
// [RIST] "Hash-to-Group with Elligator".
// [RIST255] Page 10, Section 3.2.4.
assert(Buffer.isBuffer(bytes));

@@ -764,6 +939,7 @@

return p1.uadd(p2);
return p1.add(p2);
}
pointToHash(p, rng) {
// [SQUARED] Algorithm 1, Page 8, Section 3.3.
assert(p instanceof this.Point);

@@ -776,8 +952,3 @@

const p1 = this.pointFromUniform(r1);
// Avoid 2-torsion points.
if (p1.x.isZero())
continue;
const p2 = p0.usub(p1);
const p2 = p0.sub(p1);
const hint = randomInt(rng);

@@ -784,0 +955,0 @@

@@ -86,3 +86,3 @@ /*!

let hash = h.final();
let hash = h.final(this.curve.scalarSize);

@@ -94,2 +94,4 @@ if (hash.length > this.curve.scalarSize)

num.iumaskn(this.curve.scalarBits);
return num.imod(this.curve.n);

@@ -198,2 +200,3 @@ }

// - r^3 + a * r + b is square in F(p).
// - sqrt(r^3 + a * r + b) is square in F(p).
// - r < p, s < n.

@@ -284,2 +287,3 @@ // - R != O.

// - r^3 + a * r + b is square in F(p).
// - sqrt(r^3 + a * r + b) is square in F(p).
// - r < p, s < n.

@@ -286,0 +290,0 @@ // - a1 = 1 mod n.

@@ -33,2 +33,3 @@ /*!

const SHA256 = require('../sha256');
const SHAKE256 = require('../shake256');
const elliptic = require('./elliptic');

@@ -64,3 +65,2 @@ const pre = require('./precomputed/secp256k1.json');

this._pre = null;
this.check();
}

@@ -86,9 +86,2 @@

check() {
// [BIP340] "Footnotes".
// Must be congruent to 3 mod 4.
if (this.curve.p.andln(3) !== 3)
throw new Error(`Schnorr is not supported for ${this.curve.id}.`);
}
hashInt(...items) {

@@ -104,3 +97,3 @@ // [BIP340] "Specification".

let hash = h.final();
let hash = h.final(this.curve.scalarSize);

@@ -112,2 +105,4 @@ if (hash.length > this.curve.scalarSize)

num.iumaskn(this.curve.scalarBits);
return num.imod(this.curve.n);

@@ -119,5 +114,7 @@ }

assert(Buffer.isBuffer(d));
assert(a.length === this.curve.scalarSize);
assert(d.length === 32);
if (!this._auxTag)
this._auxTag = createTag(this.hash, 'BIP340/aux');
this._auxTag = createTag(this.hash, 'BIP0340/aux');

@@ -131,7 +128,7 @@ // eslint-disable-next-line

const hash = h.final();
const t = Buffer.alloc(a.length);
const hash = h.final(this.curve.scalarSize);
const t = Buffer.alloc(this.curve.scalarSize);
for (let i = 0; i < t.length; i++)
t[i] = a[i] ^ hash[i % hash.length];
for (let i = 0; i < this.curve.scalarSize; i++)
t[i] = a[i] ^ hash[i];

@@ -143,4 +140,7 @@ return t;

if (!this._nonceTag)
this._nonceTag = createTag(this.hash, 'BIP340/nonce');
this._nonceTag = createTag(this.hash, 'BIP0340/nonce');
if (d == null)
return this.hashInt(this._nonceTag, a, A, m);
return this.hashInt(this._nonceTag, this.hashAux(a, d), A, m);

@@ -151,3 +151,3 @@ }

if (!this._challengeTag)
this._challengeTag = createTag(this.hash, 'BIP340/challenge');
this._challengeTag = createTag(this.hash, 'BIP0340/challenge');

@@ -249,16 +249,2 @@ return this.hashInt(this._challengeTag, R, A, m);

privateKeyReduce(key) {
assert(Buffer.isBuffer(key));
if (key.length > this.curve.scalarSize)
key = key.slice(0, this.curve.scalarSize);
const a = BN.decode(key, this.curve.endian).imod(this.curve.n);
if (a.isZero())
throw new Error('Invalid private key.');
return this.curve.encodeScalar(a);
}
privateKeyInvert(key) {

@@ -340,2 +326,16 @@ const a = this.curve.decodeScalar(key);

if (json.y != null) {
const y = BN.decode(json.y, this.curve.endian);
if (y.cmp(this.curve.p) >= 0)
throw new Error('Invalid point.');
const A = this.curve.point(x, y);
if (!A.validate())
throw new Error('Invalid point.');
return A.encodeX();
}
const A = this.curve.pointFromX(x);

@@ -384,3 +384,3 @@

publicKeyTweakTest(key, tweak, expect, negated) {
publicKeyTweakCheck(key, tweak, expect, negated) {
assert(Buffer.isBuffer(key));

@@ -391,25 +391,11 @@ assert(Buffer.isBuffer(tweak));

let point, sign;
try {
return this._publicKeyTweakTest(key, tweak, expect, negated);
[point, sign] = this.publicKeyTweakSum(key, tweak);
} catch (e) {
return false;
}
}
_publicKeyTweakTest(key, tweak, expect, negated) {
const t = this.curve.decodeScalar(tweak);
if (t.cmp(this.curve.n) >= 0)
throw new Error('Invalid scalar.');
const A = this.curve.decodeEven(key);
const T = this.curve.g.jmul(t);
const Q = this.curve.decodeEven(expect);
let P = T.add(A);
if (negated)
P = P.neg();
return P.eq(Q.toJ());
return point.equals(expect) && sign === negated;
}

@@ -433,5 +419,8 @@

assert(Buffer.isBuffer(msg));
assert(Buffer.isBuffer(aux));
assert(aux.length === 32);
if (aux != null) {
assert(Buffer.isBuffer(aux));
assert(aux.length === 32);
}
return this._sign(msg, key, aux);

@@ -458,8 +447,8 @@ }

// x = x(A)
// t = a xor H("BIP340/aux", d)
// k = H("BIP340/nonce", t, x, m) mod n
// t = a xor H("BIP0340/aux", d)
// k = H("BIP0340/nonce", t, x, m) mod n
// R = G * k
// k = -k mod n, if y(R) is not square
// k = -k mod n, if y(R) is not even
// r = x(R)
// e = H("BIP340/challenge", r, x, m) mod n
// e = H("BIP0340/challenge", r, x, m) mod n
// s = (k + e * a) mod n

@@ -493,3 +482,3 @@ // S = (r, s)

if (!R.isSquare())
if (!R.isEven())
k.ineg().imod(n);

@@ -534,3 +523,5 @@

// - r^3 + a * r + b is square in F(p).
// - x^3 + a * x + b is even in F(p).
// - x^3 + a * x + b is square in F(p).
// - sqrt(r^3 + a * r + b) is even in F(p).
// - sqrt(x^3 + a * x + b) is even in F(p).
// - r < p, s < n, x < p.

@@ -543,3 +534,3 @@ // - R != O.

// A = (x, sqrt(x^3 + a * x + b))
// e = H("BIP340/challenge", r, x, m) mod n
// e = H("BIP0340/challenge", r, x, m) mod n
// R == G * s - A * e

@@ -550,15 +541,6 @@ //

// A = (x, sqrt(x^3 + a * x + b))
// e = H("BIP340/challenge", r, x, m) mod n
// e = H("BIP0340/challenge", r, x, m) mod n
// R = G * s - A * e
// y(R) is square
// y(R) is even
// x(R) == r
//
// We can also avoid affinization by
// replacing the two assertions with:
//
// (y(R) * z(R) mod p) is square
// x(R) == r * z(R)^2 mod p
//
// Furthermore, squareness can be calculated
// with a variable time Jacobi symbol algorithm.
const {p, n} = this.curve;

@@ -576,5 +558,5 @@ const G = this.curve.g;

const e = this.hashChallenge(Rraw, key, msg);
const R = G.jmulAdd(s, A, e.ineg().imod(n));
const R = G.mulAdd(s, A, e.ineg().imod(n));
if (!R.isSquare())
if (!R.isEven())
return false;

@@ -627,3 +609,5 @@

// - r^3 + a * r + b is square in F(p).
// - x^3 + a * x + b is even in F(p).
// - x^3 + a * x + b is square in F(p).
// - sqrt(r^3 + a * r + b) is even in F(p).
// - sqrt(x^3 + a * x + b) is even in F(p).
// - r < p, s < n, x < p.

@@ -636,3 +620,3 @@ // - a1 = 1 mod n.

// Ai = (xi, sqrt(xi^3 + a * xi + b))
// ei = H("BIP340/challenge", ri, xi, mi) mod n
// ei = H("BIP0340/challenge", ri, xi, mi) mod n
// ai = random integer in [1,n-1]

@@ -657,3 +641,3 @@ // lhs = si * ai + ... mod n

const sraw = sig.slice(this.curve.fieldSize);
const R = this.curve.decodeSquare(Rraw);
const R = this.curve.decodeEven(Rraw);
const s = this.curve.decodeScalar(sraw);

@@ -702,4 +686,10 @@ const A = this.curve.decodeEven(key);

const raw = Buffer.from(tag, 'binary');
const hash = alg.digest(raw);
let hash;
if (alg.size !== alg.blockSize / 2)
hash = SHAKE256.digest(raw, alg.blockSize / 2);
else
hash = alg.digest(raw);
return Buffer.concat([hash, hash]);

@@ -706,0 +696,0 @@ }

@@ -18,2 +18,2 @@ /*!

module.exports = new ECDSA('SECP256K1', SHA256, pre);
module.exports = new ECDSA('SECP256K1', SHA256, SHA256, pre);

@@ -169,5 +169,15 @@ /*!

assert(json && typeof json === 'object');
assert(Buffer.isBuffer(json.x));
return binding.ecdh_pubkey_import(this._handle, json.x);
let {x, y} = json;
if (x == null)
x = binding.NULL;
if (y == null)
y = binding.NULL;
assert(Buffer.isBuffer(x));
assert(Buffer.isBuffer(y));
return binding.ecdh_pubkey_import(this._handle, x, y);
}

@@ -174,0 +184,0 @@

@@ -93,9 +93,2 @@ /*!

privateKeyReduce(key) {
assert(this instanceof ECDSA);
assert(Buffer.isBuffer(key));
return binding.ecdsa_privkey_reduce(this._handle, key);
}
privateKeyNegate(key) {

@@ -102,0 +95,0 @@ assert(this instanceof ECDSA);

@@ -90,13 +90,2 @@ /*!

/**
* Compute (key mod n).
* @param {Buffer} key
* @returns {Buffer}
*/
function privateKeyReduce(key) {
assert(Buffer.isBuffer(key));
return binding.secp256k1_seckey_reduce(handle(), key);
}
/**
* Compute (-key mod n).

@@ -283,3 +272,3 @@ * @param {Buffer} key

function publicKeyTweakTest(key, tweak, expect, negated) {
function publicKeyTweakCheck(key, tweak, expect, negated) {
assert(Buffer.isBuffer(key));

@@ -290,7 +279,7 @@ assert(Buffer.isBuffer(tweak));

return binding.secp256k1_xonly_tweak_test(handle(),
key,
tweak,
expect,
negated);
return binding.secp256k1_xonly_tweak_check(handle(),
key,
tweak,
expect,
negated);
}

@@ -322,2 +311,5 @@

function sign(msg, key, aux = binding.entropy(32)) {
if (aux == null)
aux = binding.NULL;
assert(Buffer.isBuffer(msg));

@@ -395,3 +387,2 @@ assert(Buffer.isBuffer(key));

exports.privateKeyTweakMul = privateKeyTweakMul;
exports.privateKeyReduce = privateKeyReduce;
exports.privateKeyNegate = privateKeyNegate;

@@ -410,3 +401,3 @@ exports.privateKeyInvert = privateKeyInvert;

exports.publicKeyTweakSum = publicKeyTweakSum;
exports.publicKeyTweakTest = publicKeyTweakTest;
exports.publicKeyTweakCheck = publicKeyTweakCheck;
exports.publicKeyCombine = publicKeyCombine;

@@ -413,0 +404,0 @@ exports.sign = sign;

@@ -88,9 +88,2 @@ /*!

privateKeyReduce(key) {
assert(this instanceof Schnorr);
assert(Buffer.isBuffer(key));
return binding.schnorr_privkey_reduce(this._handle, key);
}
privateKeyInvert(key) {

@@ -158,5 +151,15 @@ assert(this instanceof Schnorr);

assert(json && typeof json === 'object');
assert(Buffer.isBuffer(json.x));
return binding.schnorr_pubkey_import(this._handle, json.x);
let {x, y} = json;
if (x == null)
x = binding.NULL;
if (y == null)
y = binding.NULL;
assert(Buffer.isBuffer(x));
assert(Buffer.isBuffer(y));
return binding.schnorr_pubkey_import(this._handle, x, y);
}

@@ -188,3 +191,3 @@

publicKeyTweakTest(key, tweak, expect, negated) {
publicKeyTweakCheck(key, tweak, expect, negated) {
assert(this instanceof Schnorr);

@@ -196,4 +199,4 @@ assert(Buffer.isBuffer(key));

return binding.schnorr_pubkey_tweak_test(this._handle, key,
tweak, expect, negated);
return binding.schnorr_pubkey_tweak_check(this._handle, key,
tweak, expect, negated);
}

@@ -212,2 +215,5 @@

sign(msg, key, aux = binding.entropy(32)) {
if (aux == null)
aux = binding.NULL;
assert(this instanceof Schnorr);

@@ -214,0 +220,0 @@ assert(Buffer.isBuffer(msg));

@@ -11,5 +11,5 @@ /*!

if (binding.USE_SECP256K1_LATEST && process.env.BCRYPTO_FORCE_TORSION !== '1')
if (binding.USE_SECP256K1 && process.env.BCRYPTO_FORCE_TORSION !== '1')
module.exports = require('./schnorr-libsecp256k1');
else
module.exports = require('./schnorr-torsion');

@@ -95,13 +95,2 @@ /*!

/**
* Compute (key mod n).
* @param {Buffer} key
* @returns {Buffer}
*/
function privateKeyReduce(key) {
assert(Buffer.isBuffer(key));
return binding.secp256k1_seckey_reduce(handle(), key);
}
/**
* Compute (-key mod n).

@@ -595,3 +584,2 @@ * @param {Buffer} key

exports.privateKeyTweakMul = privateKeyTweakMul;
exports.privateKeyReduce = privateKeyReduce;
exports.privateKeyNegate = privateKeyNegate;

@@ -598,0 +586,0 @@ exports.privateKeyInvert = privateKeyInvert;

{
"name": "bcrypto",
"version": "5.3.0",
"version": "5.4.0",
"description": "JS crypto library",

@@ -5,0 +5,0 @@ "keywords": [

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc