@noble/curves 0.3.0 → 0.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/crypto.js +2 -5
- package/lib/cryptoBrowser.js +1 -4
- package/lib/definitions/_shortw_utils.d.ts +17 -17
- package/lib/definitions/_shortw_utils.js +7 -12
- package/lib/definitions/bn.d.ts +1 -1
- package/lib/definitions/bn.js +5 -8
- package/lib/definitions/ed25519.d.ts +6 -6
- package/lib/definitions/ed25519.js +58 -62
- package/lib/definitions/ed448.d.ts +3 -3
- package/lib/definitions/ed448.js +30 -33
- package/lib/definitions/jubjub.d.ts +3 -3
- package/lib/definitions/jubjub.js +14 -19
- package/lib/definitions/p192.js +5 -8
- package/lib/definitions/p224.js +5 -8
- package/lib/definitions/p256.js +5 -8
- package/lib/definitions/p384.js +5 -8
- package/lib/definitions/p521.d.ts +11 -11
- package/lib/definitions/p521.js +7 -10
- package/lib/definitions/pasta.d.ts +2 -2
- package/lib/definitions/pasta.js +8 -11
- package/lib/definitions/secp256k1.d.ts +11 -11
- package/lib/definitions/secp256k1.js +53 -57
- package/lib/definitions/stark.d.ts +6 -6
- package/lib/definitions/stark.js +40 -61
- package/lib/edwards.js +25 -29
- package/lib/group.js +1 -5
- package/lib/modular.js +9 -21
- package/lib/montgomery.js +10 -12
- package/lib/utils.js +21 -39
- package/lib/weierstrass.js +38 -43
- package/package.json +5 -39
- package/lib/esm/crypto.js +0 -5
- package/lib/esm/cryptoBrowser.js +0 -4
- package/lib/esm/definitions/_shortw_utils.js +0 -13
- package/lib/esm/definitions/bn.js +0 -20
- package/lib/esm/definitions/ed25519.js +0 -304
- package/lib/esm/definitions/ed448.js +0 -124
- package/lib/esm/definitions/index.js +0 -2
- package/lib/esm/definitions/jubjub.js +0 -50
- package/lib/esm/definitions/p192.js +0 -20
- package/lib/esm/definitions/p224.js +0 -21
- package/lib/esm/definitions/p256.js +0 -20
- package/lib/esm/definitions/p384.js +0 -21
- package/lib/esm/definitions/p521.js +0 -33
- package/lib/esm/definitions/pasta.js +0 -29
- package/lib/esm/definitions/secp256k1.js +0 -241
- package/lib/esm/definitions/stark.js +0 -227
- package/lib/esm/edwards.js +0 -546
- package/lib/esm/group.js +0 -107
- package/lib/esm/modular.js +0 -171
- package/lib/esm/montgomery.js +0 -189
- package/lib/esm/package.json +0 -7
- package/lib/esm/utils.js +0 -141
- package/lib/esm/weierstrass.js +0 -989
package/lib/crypto.js
CHANGED
|
@@ -1,8 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
exports.crypto = void 0;
|
|
4
|
-
const nodeCrypto = require("crypto");
|
|
5
|
-
exports.crypto = {
|
|
1
|
+
import * as nodeCrypto from 'crypto';
|
|
2
|
+
export const crypto = {
|
|
6
3
|
node: nodeCrypto,
|
|
7
4
|
web: undefined,
|
|
8
5
|
};
|
package/lib/cryptoBrowser.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { CurveType, CHash } from '../weierstrass';
|
|
1
|
+
import { CurveType, CHash } from '../weierstrass.js';
|
|
2
2
|
export declare function getHash(hash: CHash): {
|
|
3
3
|
hash: CHash;
|
|
4
4
|
hmac: (key: Uint8Array, ...msgs: Uint8Array[]) => Uint8Array;
|
|
5
5
|
};
|
|
6
6
|
declare type CurveDef = Readonly<Omit<CurveType, 'hash' | 'hmac'>>;
|
|
7
7
|
export declare function createCurve(curveDef: CurveDef, defHash: CHash): Readonly<{
|
|
8
|
-
create: (hash: CHash) => import("../weierstrass").CurveFn;
|
|
8
|
+
create: (hash: CHash) => import("../weierstrass.js").CurveFn;
|
|
9
9
|
CURVE: Readonly<{
|
|
10
10
|
readonly nBitLength: number;
|
|
11
11
|
readonly nByteLength: number;
|
|
@@ -19,10 +19,10 @@ export declare function createCurve(curveDef: CurveDef, defHash: CHash): Readonl
|
|
|
19
19
|
lowS: boolean;
|
|
20
20
|
readonly hash: CHash;
|
|
21
21
|
readonly hmac: (key: Uint8Array, ...messages: Uint8Array[]) => Uint8Array;
|
|
22
|
-
randomBytes: typeof import("../utils").randomBytes;
|
|
22
|
+
randomBytes: typeof import("../utils.js").randomBytes;
|
|
23
23
|
readonly truncateHash?: ((hash: Uint8Array, truncateOnly?: boolean | undefined) => bigint) | undefined;
|
|
24
24
|
readonly sqrtMod?: ((n: bigint) => bigint) | undefined;
|
|
25
|
-
readonly normalizePrivateKey?: ((key: import("../utils").PrivKey) => import("../utils").PrivKey) | undefined;
|
|
25
|
+
readonly normalizePrivateKey?: ((key: import("../utils.js").PrivKey) => import("../utils.js").PrivKey) | undefined;
|
|
26
26
|
readonly endo?: {
|
|
27
27
|
beta: bigint;
|
|
28
28
|
splitScalar: (k: bigint) => {
|
|
@@ -33,30 +33,30 @@ export declare function createCurve(curveDef: CurveDef, defHash: CHash): Readonl
|
|
|
33
33
|
};
|
|
34
34
|
} | undefined;
|
|
35
35
|
}>;
|
|
36
|
-
getPublicKey: (privateKey: import("../utils").PrivKey, isCompressed?: boolean | undefined) => Uint8Array;
|
|
37
|
-
getSharedSecret: (privateA: import("../utils").PrivKey, publicB: import("../weierstrass").PubKey, isCompressed?: boolean | undefined) => Uint8Array;
|
|
38
|
-
sign: (msgHash: import("../utils").Hex, privKey: import("../utils").PrivKey, opts?: {
|
|
36
|
+
getPublicKey: (privateKey: import("../utils.js").PrivKey, isCompressed?: boolean | undefined) => Uint8Array;
|
|
37
|
+
getSharedSecret: (privateA: import("../utils.js").PrivKey, publicB: import("../weierstrass.js").PubKey, isCompressed?: boolean | undefined) => Uint8Array;
|
|
38
|
+
sign: (msgHash: import("../utils.js").Hex, privKey: import("../utils.js").PrivKey, opts?: {
|
|
39
39
|
lowS?: boolean | undefined;
|
|
40
|
-
extraEntropy?: (true | import("../utils").Hex) | undefined;
|
|
41
|
-
} | undefined) => import("../weierstrass").SignatureType;
|
|
42
|
-
verify: (signature: import("../utils").Hex | import("../weierstrass").SignatureType, msgHash: import("../utils").Hex, publicKey: import("../weierstrass").PubKey, opts?: {
|
|
40
|
+
extraEntropy?: (true | import("../utils.js").Hex) | undefined;
|
|
41
|
+
} | undefined) => import("../weierstrass.js").SignatureType;
|
|
42
|
+
verify: (signature: import("../utils.js").Hex | import("../weierstrass.js").SignatureType, msgHash: import("../utils.js").Hex, publicKey: import("../weierstrass.js").PubKey, opts?: {
|
|
43
43
|
lowS?: boolean | undefined;
|
|
44
44
|
} | undefined) => boolean;
|
|
45
|
-
Point: import("../weierstrass").PointConstructor;
|
|
46
|
-
JacobianPoint: import("../weierstrass").JacobianPointConstructor;
|
|
47
|
-
Signature: import("../weierstrass").SignatureConstructor;
|
|
45
|
+
Point: import("../weierstrass.js").PointConstructor;
|
|
46
|
+
JacobianPoint: import("../weierstrass.js").JacobianPointConstructor;
|
|
47
|
+
Signature: import("../weierstrass.js").SignatureConstructor;
|
|
48
48
|
utils: {
|
|
49
49
|
mod: (a: bigint, b?: bigint | undefined) => bigint;
|
|
50
50
|
invert: (number: bigint, modulo?: bigint | undefined) => bigint;
|
|
51
51
|
_bigintToBytes: (num: bigint) => Uint8Array;
|
|
52
52
|
_bigintToString: (num: bigint) => string;
|
|
53
|
-
_normalizePrivateKey: (key: import("../utils").PrivKey) => bigint;
|
|
54
|
-
_normalizePublicKey: (publicKey: import("../weierstrass").PubKey) => import("../weierstrass").PointType;
|
|
53
|
+
_normalizePrivateKey: (key: import("../utils.js").PrivKey) => bigint;
|
|
54
|
+
_normalizePublicKey: (publicKey: import("../weierstrass.js").PubKey) => import("../weierstrass.js").PointType;
|
|
55
55
|
_isWithinCurveOrder: (num: bigint) => boolean;
|
|
56
56
|
_isValidFieldElement: (num: bigint) => boolean;
|
|
57
57
|
_weierstrassEquation: (x: bigint) => bigint;
|
|
58
|
-
isValidPrivateKey(privateKey: import("../utils").PrivKey): boolean;
|
|
59
|
-
hashToPrivateKey: (hash: import("../utils").Hex) => Uint8Array;
|
|
58
|
+
isValidPrivateKey(privateKey: import("../utils.js").PrivKey): boolean;
|
|
59
|
+
hashToPrivateKey: (hash: import("../utils.js").Hex) => Uint8Array;
|
|
60
60
|
randomPrivateKey: () => Uint8Array;
|
|
61
61
|
};
|
|
62
62
|
}>;
|
|
@@ -1,18 +1,13 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
const utils_1 = require("@noble/hashes/utils");
|
|
6
|
-
const weierstrass_1 = require("../weierstrass");
|
|
7
|
-
function getHash(hash) {
|
|
1
|
+
import { hmac } from '@noble/hashes/hmac';
|
|
2
|
+
import { concatBytes } from '@noble/hashes/utils';
|
|
3
|
+
import { weierstrass } from '../weierstrass.js';
|
|
4
|
+
export function getHash(hash) {
|
|
8
5
|
return {
|
|
9
6
|
hash,
|
|
10
|
-
hmac: (key, ...msgs) =>
|
|
7
|
+
hmac: (key, ...msgs) => hmac(hash, key, concatBytes(...msgs)),
|
|
11
8
|
};
|
|
12
9
|
}
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
const create = (hash) => (0, weierstrass_1.weierstrass)({ ...curveDef, ...getHash(hash) });
|
|
10
|
+
export function createCurve(curveDef, defHash) {
|
|
11
|
+
const create = (hash) => weierstrass({ ...curveDef, ...getHash(hash) });
|
|
16
12
|
return Object.freeze({ ...create(defHash), create });
|
|
17
13
|
}
|
|
18
|
-
exports.createCurve = createCurve;
|
package/lib/definitions/bn.d.ts
CHANGED
|
@@ -4,4 +4,4 @@
|
|
|
4
4
|
* Recent research shown it's weaker, the naming has been adjusted to its prime bit count.
|
|
5
5
|
* https://github.com/zcash/zcash/issues/2502
|
|
6
6
|
*/
|
|
7
|
-
export declare const bn254: import("../weierstrass").CurveFn;
|
|
7
|
+
export declare const bn254: import("../weierstrass.js").CurveFn;
|
package/lib/definitions/bn.js
CHANGED
|
@@ -1,17 +1,14 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.bn254 = void 0;
|
|
4
1
|
/*! @noble/curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
2
|
+
import { weierstrass } from '../weierstrass.js';
|
|
3
|
+
import { sha256 } from '@noble/hashes/sha256';
|
|
4
|
+
import { getHash } from './_shortw_utils.js';
|
|
8
5
|
/**
|
|
9
6
|
* bn254 pairing-friendly curve.
|
|
10
7
|
* Previously known as alt_bn_128, when it had 128-bit security.
|
|
11
8
|
* Recent research shown it's weaker, the naming has been adjusted to its prime bit count.
|
|
12
9
|
* https://github.com/zcash/zcash/issues/2502
|
|
13
10
|
*/
|
|
14
|
-
|
|
11
|
+
export const bn254 = weierstrass({
|
|
15
12
|
a: BigInt(0),
|
|
16
13
|
b: BigInt(3),
|
|
17
14
|
P: BigInt('0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47'),
|
|
@@ -19,5 +16,5 @@ exports.bn254 = (0, weierstrass_1.weierstrass)({
|
|
|
19
16
|
Gx: BigInt(1),
|
|
20
17
|
Gy: BigInt(2),
|
|
21
18
|
h: BigInt(1),
|
|
22
|
-
...
|
|
19
|
+
...getHash(sha256),
|
|
23
20
|
});
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { ExtendedPointType } from '../edwards';
|
|
2
|
-
import { Hex } from '../utils';
|
|
1
|
+
import { ExtendedPointType } from '../edwards.js';
|
|
2
|
+
import { Hex } from '../utils.js';
|
|
3
3
|
export declare const ED25519_TORSION_SUBGROUP: string[];
|
|
4
|
-
export declare const ed25519: import("../edwards").CurveFn;
|
|
5
|
-
export declare const ed25519ctx: import("../edwards").CurveFn;
|
|
6
|
-
export declare const ed25519ph: import("../edwards").CurveFn;
|
|
7
|
-
export declare const x25519: import("../montgomery").CurveFn;
|
|
4
|
+
export declare const ed25519: import("../edwards.js").CurveFn;
|
|
5
|
+
export declare const ed25519ctx: import("../edwards.js").CurveFn;
|
|
6
|
+
export declare const ed25519ph: import("../edwards.js").CurveFn;
|
|
7
|
+
export declare const x25519: import("../montgomery.js").CurveFn;
|
|
8
8
|
declare type ExtendedPoint = ExtendedPointType;
|
|
9
9
|
/**
|
|
10
10
|
* Each ed25519/ExtendedPoint has 8 different equivalent points. This can be
|
|
@@ -1,13 +1,10 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.RistrettoPoint = exports.x25519 = exports.ed25519ph = exports.ed25519ctx = exports.ed25519 = exports.ED25519_TORSION_SUBGROUP = void 0;
|
|
4
1
|
/*! @noble/curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
2
|
+
import { sha512 } from '@noble/hashes/sha512';
|
|
3
|
+
import { concatBytes, utf8ToBytes } from '@noble/hashes/utils';
|
|
4
|
+
import { twistedEdwards } from '../edwards.js';
|
|
5
|
+
import { montgomery } from '../montgomery.js';
|
|
6
|
+
import { mod, pow2, isNegativeLE } from '../modular.js';
|
|
7
|
+
import { ensureBytes, equalBytes, bytesToHex, bytesToNumberLE, numberToBytesLE, } from '../utils.js';
|
|
11
8
|
/**
|
|
12
9
|
* ed25519 Twisted Edwards curve with following addons:
|
|
13
10
|
* - X25519 ECDH
|
|
@@ -25,16 +22,16 @@ function ed25519_pow_2_252_3(x) {
|
|
|
25
22
|
const P = ED25519_P;
|
|
26
23
|
const x2 = (x * x) % P;
|
|
27
24
|
const b2 = (x2 * x) % P; // x^3, 11
|
|
28
|
-
const b4 = (
|
|
29
|
-
const b5 = (
|
|
30
|
-
const b10 = (
|
|
31
|
-
const b20 = (
|
|
32
|
-
const b40 = (
|
|
33
|
-
const b80 = (
|
|
34
|
-
const b160 = (
|
|
35
|
-
const b240 = (
|
|
36
|
-
const b250 = (
|
|
37
|
-
const pow_p_5_8 = (
|
|
25
|
+
const b4 = (pow2(b2, _2n, P) * b2) % P; // x^15, 1111
|
|
26
|
+
const b5 = (pow2(b4, _1n, P) * x) % P; // x^31
|
|
27
|
+
const b10 = (pow2(b5, _5n, P) * b5) % P;
|
|
28
|
+
const b20 = (pow2(b10, _10n, P) * b10) % P;
|
|
29
|
+
const b40 = (pow2(b20, _20n, P) * b20) % P;
|
|
30
|
+
const b80 = (pow2(b40, _40n, P) * b40) % P;
|
|
31
|
+
const b160 = (pow2(b80, _80n, P) * b80) % P;
|
|
32
|
+
const b240 = (pow2(b160, _80n, P) * b80) % P;
|
|
33
|
+
const b250 = (pow2(b240, _10n, P) * b10) % P;
|
|
34
|
+
const pow_p_5_8 = (pow2(b250, _2n, P) * x) % P;
|
|
38
35
|
// ^ To pow to (p+3)/8, multiply it by x.
|
|
39
36
|
return { pow_p_5_8, b2 };
|
|
40
37
|
}
|
|
@@ -54,27 +51,27 @@ function adjustScalarBytes(bytes) {
|
|
|
54
51
|
// sqrt(u/v)
|
|
55
52
|
function uvRatio(u, v) {
|
|
56
53
|
const P = ED25519_P;
|
|
57
|
-
const v3 =
|
|
58
|
-
const v7 =
|
|
54
|
+
const v3 = mod(v * v * v, P); // v³
|
|
55
|
+
const v7 = mod(v3 * v3 * v, P); // v⁷
|
|
59
56
|
// (p+3)/8 and (p-5)/8
|
|
60
57
|
const pow = ed25519_pow_2_252_3(u * v7).pow_p_5_8;
|
|
61
|
-
let x =
|
|
62
|
-
const vx2 =
|
|
58
|
+
let x = mod(u * v3 * pow, P); // (uv³)(uv⁷)^(p-5)/8
|
|
59
|
+
const vx2 = mod(v * x * x, P); // vx²
|
|
63
60
|
const root1 = x; // First root candidate
|
|
64
|
-
const root2 =
|
|
61
|
+
const root2 = mod(x * ED25519_SQRT_M1, P); // Second root candidate
|
|
65
62
|
const useRoot1 = vx2 === u; // If vx² = u (mod p), x is a square root
|
|
66
|
-
const useRoot2 = vx2 ===
|
|
67
|
-
const noRoot = vx2 ===
|
|
63
|
+
const useRoot2 = vx2 === mod(-u, P); // If vx² = -u, set x <-- x * 2^((p-1)/4)
|
|
64
|
+
const noRoot = vx2 === mod(-u * ED25519_SQRT_M1, P); // There is no valid root, vx² = -u√(-1)
|
|
68
65
|
if (useRoot1)
|
|
69
66
|
x = root1;
|
|
70
67
|
if (useRoot2 || noRoot)
|
|
71
68
|
x = root2; // We return root2 anyway, for const-time
|
|
72
|
-
if (
|
|
73
|
-
x =
|
|
69
|
+
if (isNegativeLE(x, P))
|
|
70
|
+
x = mod(-x, P);
|
|
74
71
|
return { isValid: useRoot1 || useRoot2, value: x };
|
|
75
72
|
}
|
|
76
73
|
// Just in case
|
|
77
|
-
|
|
74
|
+
export const ED25519_TORSION_SUBGROUP = [
|
|
78
75
|
'0100000000000000000000000000000000000000000000000000000000000000',
|
|
79
76
|
'c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a',
|
|
80
77
|
'0000000000000000000000000000000000000000000000000000000000000080',
|
|
@@ -100,26 +97,26 @@ const ED25519_DEF = {
|
|
|
100
97
|
// Base point (x, y) aka generator point
|
|
101
98
|
Gx: BigInt('15112221349535400772501151409588531511454012693041857206046113283949847762202'),
|
|
102
99
|
Gy: BigInt('46316835694926478169428394003475163141307993866256225615783033603165251855960'),
|
|
103
|
-
hash:
|
|
100
|
+
hash: sha512,
|
|
104
101
|
adjustScalarBytes,
|
|
105
102
|
// dom2
|
|
106
103
|
// Ratio of u to v. Allows us to combine inversion and square root. Uses algo from RFC8032 5.1.3.
|
|
107
104
|
// Constant-time, u/√v
|
|
108
105
|
uvRatio,
|
|
109
106
|
};
|
|
110
|
-
|
|
107
|
+
export const ed25519 = twistedEdwards(ED25519_DEF);
|
|
111
108
|
function ed25519_domain(data, ctx, phflag) {
|
|
112
109
|
if (ctx.length > 255)
|
|
113
110
|
throw new Error('Context is too big');
|
|
114
|
-
return
|
|
111
|
+
return concatBytes(utf8ToBytes('SigEd25519 no Ed25519 collisions'), new Uint8Array([phflag ? 1 : 0, ctx.length]), ctx, data);
|
|
115
112
|
}
|
|
116
|
-
|
|
117
|
-
|
|
113
|
+
export const ed25519ctx = twistedEdwards({ ...ED25519_DEF, domain: ed25519_domain });
|
|
114
|
+
export const ed25519ph = twistedEdwards({
|
|
118
115
|
...ED25519_DEF,
|
|
119
116
|
domain: ed25519_domain,
|
|
120
|
-
preHash:
|
|
117
|
+
preHash: sha512,
|
|
121
118
|
});
|
|
122
|
-
|
|
119
|
+
export const x25519 = montgomery({
|
|
123
120
|
P: ED25519_P,
|
|
124
121
|
a24: BigInt('121665'),
|
|
125
122
|
montgomeryBits: 255,
|
|
@@ -129,7 +126,7 @@ exports.x25519 = (0, montgomery_1.montgomery)({
|
|
|
129
126
|
const P = ED25519_P;
|
|
130
127
|
// x^(p-2) aka x^(2^255-21)
|
|
131
128
|
const { pow_p_5_8, b2 } = ed25519_pow_2_252_3(x);
|
|
132
|
-
return
|
|
129
|
+
return mod(pow2(pow_p_5_8, BigInt(3), P) * b2, P);
|
|
133
130
|
},
|
|
134
131
|
adjustScalarBytes,
|
|
135
132
|
});
|
|
@@ -150,7 +147,7 @@ const D_MINUS_ONE_SQ = BigInt('4044083434630853685810104246932319082624839914623
|
|
|
150
147
|
// Calculates 1/√(number)
|
|
151
148
|
const invertSqrt = (number) => uvRatio(_1n, number);
|
|
152
149
|
const MAX_255B = BigInt('0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff');
|
|
153
|
-
const bytes255ToNumberLE = (bytes) =>
|
|
150
|
+
const bytes255ToNumberLE = (bytes) => ed25519.utils.mod(bytesToNumberLE(bytes) & MAX_255B);
|
|
154
151
|
/**
|
|
155
152
|
* Each ed25519/ExtendedPoint has 8 different equivalent points. This can be
|
|
156
153
|
* a source of bugs for protocols like ring signatures. Ristretto was created to solve this.
|
|
@@ -158,7 +155,7 @@ const bytes255ToNumberLE = (bytes) => exports.ed25519.utils.mod((0, utils_2.byte
|
|
|
158
155
|
* but it should work in its own namespace: do not combine those two.
|
|
159
156
|
* https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-ristretto255-decaf448
|
|
160
157
|
*/
|
|
161
|
-
class RistrettoPoint {
|
|
158
|
+
export class RistrettoPoint {
|
|
162
159
|
// Private property to discourage combining ExtendedPoint + RistrettoPoint
|
|
163
160
|
// Always use Ristretto encoding/decoding instead.
|
|
164
161
|
constructor(ep) {
|
|
@@ -167,15 +164,15 @@ class RistrettoPoint {
|
|
|
167
164
|
// Computes Elligator map for Ristretto
|
|
168
165
|
// https://ristretto.group/formulas/elligator.html
|
|
169
166
|
static calcElligatorRistrettoMap(r0) {
|
|
170
|
-
const { d, P } =
|
|
171
|
-
const { mod } =
|
|
167
|
+
const { d, P } = ed25519.CURVE;
|
|
168
|
+
const { mod } = ed25519.utils;
|
|
172
169
|
const r = mod(SQRT_M1 * r0 * r0); // 1
|
|
173
170
|
const Ns = mod((r + _1n) * ONE_MINUS_D_SQ); // 2
|
|
174
171
|
let c = BigInt(-1); // 3
|
|
175
172
|
const D = mod((c - d * r) * mod(r + d)); // 4
|
|
176
173
|
let { isValid: Ns_D_is_sq, value: s } = uvRatio(Ns, D); // 5
|
|
177
174
|
let s_ = mod(s * r0); // 6
|
|
178
|
-
if (!
|
|
175
|
+
if (!isNegativeLE(s_, P))
|
|
179
176
|
s_ = mod(-s_);
|
|
180
177
|
if (!Ns_D_is_sq)
|
|
181
178
|
s = s_; // 7
|
|
@@ -187,7 +184,7 @@ class RistrettoPoint {
|
|
|
187
184
|
const W1 = mod(Nt * SQRT_AD_MINUS_ONE); // 11
|
|
188
185
|
const W2 = mod(_1n - s2); // 12
|
|
189
186
|
const W3 = mod(_1n + s2); // 13
|
|
190
|
-
return new
|
|
187
|
+
return new ed25519.ExtendedPoint(mod(W0 * W3), mod(W2 * W1), mod(W1 * W3), mod(W0 * W2));
|
|
191
188
|
}
|
|
192
189
|
/**
|
|
193
190
|
* Takes uniform output of 64-bit hash function like sha512 and converts it to `RistrettoPoint`.
|
|
@@ -197,7 +194,7 @@ class RistrettoPoint {
|
|
|
197
194
|
* @param hex 64-bit output of a hash function
|
|
198
195
|
*/
|
|
199
196
|
static hashToCurve(hex) {
|
|
200
|
-
hex =
|
|
197
|
+
hex = ensureBytes(hex, 64);
|
|
201
198
|
const r1 = bytes255ToNumberLE(hex.slice(0, 32));
|
|
202
199
|
const R1 = this.calcElligatorRistrettoMap(r1);
|
|
203
200
|
const r2 = bytes255ToNumberLE(hex.slice(32, 64));
|
|
@@ -210,14 +207,14 @@ class RistrettoPoint {
|
|
|
210
207
|
* @param hex Ristretto-encoded 32 bytes. Not every 32-byte string is valid ristretto encoding
|
|
211
208
|
*/
|
|
212
209
|
static fromHex(hex) {
|
|
213
|
-
hex =
|
|
214
|
-
const { a, d, P } =
|
|
215
|
-
const { mod } =
|
|
210
|
+
hex = ensureBytes(hex, 32);
|
|
211
|
+
const { a, d, P } = ed25519.CURVE;
|
|
212
|
+
const { mod } = ed25519.utils;
|
|
216
213
|
const emsg = 'RistrettoPoint.fromHex: the hex is not valid encoding of RistrettoPoint';
|
|
217
214
|
const s = bytes255ToNumberLE(hex);
|
|
218
215
|
// 1. Check that s_bytes is the canonical encoding of a field element, or else abort.
|
|
219
216
|
// 3. Check that s is non-negative, or else abort
|
|
220
|
-
if (!
|
|
217
|
+
if (!equalBytes(numberToBytesLE(s, 32), hex) || isNegativeLE(s, P))
|
|
221
218
|
throw new Error(emsg);
|
|
222
219
|
const s2 = mod(s * s);
|
|
223
220
|
const u1 = mod(_1n + a * s2); // 4 (a is -1)
|
|
@@ -229,13 +226,13 @@ class RistrettoPoint {
|
|
|
229
226
|
const Dx = mod(I * u2); // 8
|
|
230
227
|
const Dy = mod(I * Dx * v); // 9
|
|
231
228
|
let x = mod((s + s) * Dx); // 10
|
|
232
|
-
if (
|
|
229
|
+
if (isNegativeLE(x, P))
|
|
233
230
|
x = mod(-x); // 10
|
|
234
231
|
const y = mod(u1 * Dy); // 11
|
|
235
232
|
const t = mod(x * y); // 12
|
|
236
|
-
if (!isValid ||
|
|
233
|
+
if (!isValid || isNegativeLE(t, P) || y === _0n)
|
|
237
234
|
throw new Error(emsg);
|
|
238
|
-
return new RistrettoPoint(new
|
|
235
|
+
return new RistrettoPoint(new ed25519.ExtendedPoint(x, y, _1n, t));
|
|
239
236
|
}
|
|
240
237
|
/**
|
|
241
238
|
* Encodes ristretto point to Uint8Array.
|
|
@@ -243,8 +240,8 @@ class RistrettoPoint {
|
|
|
243
240
|
*/
|
|
244
241
|
toRawBytes() {
|
|
245
242
|
let { x, y, z, t } = this.ep;
|
|
246
|
-
const { P } =
|
|
247
|
-
const { mod } =
|
|
243
|
+
const { P } = ed25519.CURVE;
|
|
244
|
+
const { mod } = ed25519.utils;
|
|
248
245
|
const u1 = mod(mod(z + y) * mod(z - y)); // 1
|
|
249
246
|
const u2 = mod(x * y); // 2
|
|
250
247
|
// Square root always exists
|
|
@@ -254,7 +251,7 @@ class RistrettoPoint {
|
|
|
254
251
|
const D2 = mod(invsqrt * u2); // 5
|
|
255
252
|
const zInv = mod(D1 * D2 * t); // 6
|
|
256
253
|
let D; // 7
|
|
257
|
-
if (
|
|
254
|
+
if (isNegativeLE(t * zInv, P)) {
|
|
258
255
|
let _x = mod(y * SQRT_M1);
|
|
259
256
|
let _y = mod(x * SQRT_M1);
|
|
260
257
|
x = _x;
|
|
@@ -264,15 +261,15 @@ class RistrettoPoint {
|
|
|
264
261
|
else {
|
|
265
262
|
D = D2; // 8
|
|
266
263
|
}
|
|
267
|
-
if (
|
|
264
|
+
if (isNegativeLE(x * zInv, P))
|
|
268
265
|
y = mod(-y); // 9
|
|
269
266
|
let s = mod((z - y) * D); // 10 (check footer's note, no sqrt(-a))
|
|
270
|
-
if (
|
|
267
|
+
if (isNegativeLE(s, P))
|
|
271
268
|
s = mod(-s);
|
|
272
|
-
return
|
|
269
|
+
return numberToBytesLE(s, 32); // 11
|
|
273
270
|
}
|
|
274
271
|
toHex() {
|
|
275
|
-
return
|
|
272
|
+
return bytesToHex(this.toRawBytes());
|
|
276
273
|
}
|
|
277
274
|
toString() {
|
|
278
275
|
return this.toHex();
|
|
@@ -282,7 +279,7 @@ class RistrettoPoint {
|
|
|
282
279
|
assertRstPoint(other);
|
|
283
280
|
const a = this.ep;
|
|
284
281
|
const b = other.ep;
|
|
285
|
-
const { mod } =
|
|
282
|
+
const { mod } = ed25519.utils;
|
|
286
283
|
// (x1 * y2 == y1 * x2) | (y1 * y2 == x1 * x2)
|
|
287
284
|
const one = mod(a.x * b.y) === mod(a.y * b.x);
|
|
288
285
|
const two = mod(a.y * b.y) === mod(a.x * b.x);
|
|
@@ -303,6 +300,5 @@ class RistrettoPoint {
|
|
|
303
300
|
return new RistrettoPoint(this.ep.multiplyUnsafe(scalar));
|
|
304
301
|
}
|
|
305
302
|
}
|
|
306
|
-
|
|
307
|
-
RistrettoPoint.
|
|
308
|
-
RistrettoPoint.ZERO = new RistrettoPoint(exports.ed25519.ExtendedPoint.ZERO);
|
|
303
|
+
RistrettoPoint.BASE = new RistrettoPoint(ed25519.ExtendedPoint.BASE);
|
|
304
|
+
RistrettoPoint.ZERO = new RistrettoPoint(ed25519.ExtendedPoint.ZERO);
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export declare const ed448: import("../edwards").CurveFn;
|
|
2
|
-
export declare const ed448ph: import("../edwards").CurveFn;
|
|
3
|
-
export declare const x448: import("../montgomery").CurveFn;
|
|
1
|
+
export declare const ed448: import("../edwards.js").CurveFn;
|
|
2
|
+
export declare const ed448ph: import("../edwards.js").CurveFn;
|
|
3
|
+
export declare const x448: import("../montgomery.js").CurveFn;
|
package/lib/definitions/ed448.js
CHANGED
|
@@ -1,19 +1,16 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.x448 = exports.ed448ph = exports.ed448 = void 0;
|
|
4
1
|
/*! @noble/curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
2
|
+
import { shake256 } from '@noble/hashes/sha3';
|
|
3
|
+
import { concatBytes, utf8ToBytes, wrapConstructor } from '@noble/hashes/utils';
|
|
4
|
+
import { twistedEdwards } from '../edwards.js';
|
|
5
|
+
import { mod, pow2 } from '../modular.js';
|
|
6
|
+
import { montgomery } from '../montgomery.js';
|
|
10
7
|
/**
|
|
11
8
|
* Edwards448 (not Ed448-Goldilocks) curve with following addons:
|
|
12
9
|
* * X448 ECDH
|
|
13
10
|
* Conforms to RFC 8032 https://www.rfc-editor.org/rfc/rfc8032.html#section-5.2
|
|
14
11
|
*/
|
|
15
|
-
const shake256_114 =
|
|
16
|
-
const shake256_64 =
|
|
12
|
+
const shake256_114 = wrapConstructor(() => shake256.create({ dkLen: 114 }));
|
|
13
|
+
const shake256_64 = wrapConstructor(() => shake256.create({ dkLen: 64 }));
|
|
17
14
|
const ed448P = BigInt('726838724295606890549323807888004534353641360687318060281490199180612328166730772686396383698676545930088884461843637361053498018365439');
|
|
18
15
|
// powPminus3div4 calculates z = x^k mod p, where k = (p-3)/4.
|
|
19
16
|
function ed448_pow_Pminus3div4(x) {
|
|
@@ -25,17 +22,17 @@ function ed448_pow_Pminus3div4(x) {
|
|
|
25
22
|
// [223 of 1, 0, 222 of 1], almost same as secp!
|
|
26
23
|
const b2 = (x * x * x) % P;
|
|
27
24
|
const b3 = (b2 * b2 * x) % P;
|
|
28
|
-
const b6 = (
|
|
29
|
-
const b9 = (
|
|
30
|
-
const b11 = (
|
|
31
|
-
const b22 = (
|
|
32
|
-
const b44 = (
|
|
33
|
-
const b88 = (
|
|
34
|
-
const b176 = (
|
|
35
|
-
const b220 = (
|
|
36
|
-
const b222 = (
|
|
37
|
-
const b223 = (
|
|
38
|
-
return (
|
|
25
|
+
const b6 = (pow2(b3, _3n, P) * b3) % P;
|
|
26
|
+
const b9 = (pow2(b6, _3n, P) * b3) % P;
|
|
27
|
+
const b11 = (pow2(b9, _2n, P) * b2) % P;
|
|
28
|
+
const b22 = (pow2(b11, _11n, P) * b11) % P;
|
|
29
|
+
const b44 = (pow2(b22, _22n, P) * b22) % P;
|
|
30
|
+
const b88 = (pow2(b44, _44n, P) * b44) % P;
|
|
31
|
+
const b176 = (pow2(b88, _88n, P) * b88) % P;
|
|
32
|
+
const b220 = (pow2(b176, _44n, P) * b44) % P;
|
|
33
|
+
const b222 = (pow2(b220, _2n, P) * b2) % P;
|
|
34
|
+
const b223 = (pow2(b222, _1n, P) * x) % P;
|
|
35
|
+
return (pow2(b223, _223n, P) * b222) % P;
|
|
39
36
|
}
|
|
40
37
|
function adjustScalarBytes(bytes) {
|
|
41
38
|
// Section 5: Likewise, for X448, set the two least significant bits of the first byte to 0, and the most
|
|
@@ -69,7 +66,7 @@ const ED448_DEF = {
|
|
|
69
66
|
domain: (data, ctx, phflag) => {
|
|
70
67
|
if (ctx.length > 255)
|
|
71
68
|
throw new Error(`Context is too big: ${ctx.length}`);
|
|
72
|
-
return
|
|
69
|
+
return concatBytes(utf8ToBytes('SigEd448'), new Uint8Array([phflag ? 1 : 0, ctx.length]), ctx, data);
|
|
73
70
|
},
|
|
74
71
|
// Constant-time ratio of u to v. Allows to combine inversion and square root u/√v.
|
|
75
72
|
// Uses algo from RFC8032 5.1.3.
|
|
@@ -82,22 +79,22 @@ const ED448_DEF = {
|
|
|
82
79
|
// inversion of v and the square root:
|
|
83
80
|
// (p+1)/4 3 (p-3)/4
|
|
84
81
|
// x = (u/v) = u v (u^5 v^3) (mod p)
|
|
85
|
-
const u2v =
|
|
86
|
-
const u3v =
|
|
87
|
-
const u5v3 =
|
|
82
|
+
const u2v = mod(u * u * v, P);
|
|
83
|
+
const u3v = mod(u2v * u, P); // u^2v
|
|
84
|
+
const u5v3 = mod(u3v * u2v * v, P); // u^5v^3
|
|
88
85
|
const root = ed448_pow_Pminus3div4(u5v3);
|
|
89
|
-
const x =
|
|
86
|
+
const x = mod(u3v * root, P);
|
|
90
87
|
// Verify that root is exists
|
|
91
|
-
const x2 =
|
|
88
|
+
const x2 = mod(x * x, P); // x^2
|
|
92
89
|
// If v * x^2 = u, the recovered x-coordinate is x. Otherwise, no
|
|
93
90
|
// square root exists, and the decoding fails.
|
|
94
|
-
return { isValid:
|
|
91
|
+
return { isValid: mod(x2 * v, P) === u, value: x };
|
|
95
92
|
},
|
|
96
93
|
};
|
|
97
|
-
|
|
94
|
+
export const ed448 = twistedEdwards(ED448_DEF);
|
|
98
95
|
// NOTE: there is no ed448ctx, since ed448 supports ctx by default
|
|
99
|
-
|
|
100
|
-
|
|
96
|
+
export const ed448ph = twistedEdwards({ ...ED448_DEF, preHash: shake256_64 });
|
|
97
|
+
export const x448 = montgomery({
|
|
101
98
|
a24: BigInt(39081),
|
|
102
99
|
montgomeryBits: 448,
|
|
103
100
|
nByteLength: 57,
|
|
@@ -106,8 +103,8 @@ exports.x448 = (0, montgomery_1.montgomery)({
|
|
|
106
103
|
powPminus2: (x) => {
|
|
107
104
|
const P = ed448P;
|
|
108
105
|
const Pminus3div4 = ed448_pow_Pminus3div4(x);
|
|
109
|
-
const Pminus3 =
|
|
110
|
-
return
|
|
106
|
+
const Pminus3 = pow2(Pminus3div4, BigInt(2), P);
|
|
107
|
+
return mod(Pminus3 * x, P); // Pminus3 * x = Pminus2
|
|
111
108
|
},
|
|
112
109
|
adjustScalarBytes,
|
|
113
110
|
// The 4-isogeny maps between the Montgomery curve and this Edwards
|
|
@@ -2,6 +2,6 @@
|
|
|
2
2
|
* jubjub Twisted Edwards curve.
|
|
3
3
|
* https://neuromancer.sk/std/other/JubJub
|
|
4
4
|
*/
|
|
5
|
-
export declare const jubjub: import("../edwards").CurveFn;
|
|
6
|
-
export declare function groupHash(tag: Uint8Array, personalization: Uint8Array): import("../edwards").ExtendedPointType;
|
|
7
|
-
export declare function findGroupHash(m: Uint8Array, personalization: Uint8Array): import("../edwards").ExtendedPointType;
|
|
5
|
+
export declare const jubjub: import("../edwards.js").CurveFn;
|
|
6
|
+
export declare function groupHash(tag: Uint8Array, personalization: Uint8Array): import("../edwards.js").ExtendedPointType;
|
|
7
|
+
export declare function findGroupHash(m: Uint8Array, personalization: Uint8Array): import("../edwards.js").ExtendedPointType;
|
|
@@ -1,16 +1,13 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.findGroupHash = exports.groupHash = exports.jubjub = void 0;
|
|
4
1
|
/*! @noble/curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
2
|
+
import { sha256 } from '@noble/hashes/sha256';
|
|
3
|
+
import { concatBytes, utf8ToBytes } from '@noble/hashes/utils';
|
|
4
|
+
import { twistedEdwards } from '../edwards.js';
|
|
5
|
+
import { blake2s } from '@noble/hashes/blake2s';
|
|
9
6
|
/**
|
|
10
7
|
* jubjub Twisted Edwards curve.
|
|
11
8
|
* https://neuromancer.sk/std/other/JubJub
|
|
12
9
|
*/
|
|
13
|
-
|
|
10
|
+
export const jubjub = twistedEdwards({
|
|
14
11
|
// Params: a, d
|
|
15
12
|
a: BigInt('0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000000'),
|
|
16
13
|
d: BigInt('0x2a9318e74bfa2b48f5fd9207e6bd7fd4292d7f6d37579d2601065fd6d6343eb1'),
|
|
@@ -24,25 +21,24 @@ exports.jubjub = (0, edwards_1.twistedEdwards)({
|
|
|
24
21
|
// Base point (x, y) aka generator point
|
|
25
22
|
Gx: BigInt('0x11dafe5d23e1218086a365b99fbf3d3be72f6afd7d1f72623e6b071492d1122b'),
|
|
26
23
|
Gy: BigInt('0x1d523cf1ddab1a1793132e78c866c0c33e26ba5cc220fed7cc3f870e59d292aa'),
|
|
27
|
-
hash:
|
|
24
|
+
hash: sha256,
|
|
28
25
|
});
|
|
29
|
-
const GH_FIRST_BLOCK =
|
|
26
|
+
const GH_FIRST_BLOCK = utf8ToBytes('096b36a5804bfacef1691e173c366a47ff5ba84a44f26ddd7e8d9f79d5b42df0');
|
|
30
27
|
// Returns point at JubJub curve which is prime order and not zero
|
|
31
|
-
function groupHash(tag, personalization) {
|
|
32
|
-
const h =
|
|
28
|
+
export function groupHash(tag, personalization) {
|
|
29
|
+
const h = blake2s.create({ personalization, dkLen: 32 });
|
|
33
30
|
h.update(GH_FIRST_BLOCK);
|
|
34
31
|
h.update(tag);
|
|
35
32
|
// NOTE: returns ExtendedPoint, in case it will be multiplied later
|
|
36
|
-
let p =
|
|
33
|
+
let p = jubjub.ExtendedPoint.fromAffine(jubjub.Point.fromHex(h.digest()));
|
|
37
34
|
// NOTE: cannot replace with isSmallOrder, returns Point*8
|
|
38
|
-
p = p.multiply(
|
|
39
|
-
if (p.equals(
|
|
35
|
+
p = p.multiply(jubjub.CURVE.h);
|
|
36
|
+
if (p.equals(jubjub.ExtendedPoint.ZERO))
|
|
40
37
|
throw new Error('Point has small order');
|
|
41
38
|
return p;
|
|
42
39
|
}
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
const tag = (0, utils_1.concatBytes)(m, new Uint8Array([0]));
|
|
40
|
+
export function findGroupHash(m, personalization) {
|
|
41
|
+
const tag = concatBytes(m, new Uint8Array([0]));
|
|
46
42
|
for (let i = 0; i < 256; i++) {
|
|
47
43
|
tag[tag.length - 1] = i;
|
|
48
44
|
try {
|
|
@@ -52,4 +48,3 @@ function findGroupHash(m, personalization) {
|
|
|
52
48
|
}
|
|
53
49
|
throw new Error('findGroupHash tag overflow');
|
|
54
50
|
}
|
|
55
|
-
exports.findGroupHash = findGroupHash;
|