@noble/curves 1.9.2 → 1.9.4
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/README.md +186 -206
- package/_shortw_utils.d.ts +1 -0
- package/_shortw_utils.d.ts.map +1 -1
- package/_shortw_utils.js +1 -0
- package/_shortw_utils.js.map +1 -1
- package/abstract/bls.d.ts +87 -62
- package/abstract/bls.d.ts.map +1 -1
- package/abstract/bls.js +170 -163
- package/abstract/bls.js.map +1 -1
- package/abstract/curve.d.ts +109 -23
- package/abstract/curve.d.ts.map +1 -1
- package/abstract/curve.js +158 -156
- package/abstract/curve.js.map +1 -1
- package/abstract/edwards.d.ts +126 -70
- package/abstract/edwards.d.ts.map +1 -1
- package/abstract/edwards.js +212 -62
- package/abstract/edwards.js.map +1 -1
- package/abstract/hash-to-curve.d.ts +8 -4
- package/abstract/hash-to-curve.d.ts.map +1 -1
- package/abstract/hash-to-curve.js +23 -11
- package/abstract/hash-to-curve.js.map +1 -1
- package/abstract/modular.d.ts +8 -3
- package/abstract/modular.d.ts.map +1 -1
- package/abstract/modular.js +79 -35
- package/abstract/modular.js.map +1 -1
- package/abstract/montgomery.d.ts +17 -4
- package/abstract/montgomery.d.ts.map +1 -1
- package/abstract/montgomery.js +19 -3
- package/abstract/montgomery.js.map +1 -1
- package/abstract/tower.d.ts +3 -3
- package/abstract/tower.d.ts.map +1 -1
- package/abstract/tower.js.map +1 -1
- package/abstract/weierstrass.d.ts +145 -118
- package/abstract/weierstrass.d.ts.map +1 -1
- package/abstract/weierstrass.js +415 -336
- package/abstract/weierstrass.js.map +1 -1
- package/bls12-381.d.ts.map +1 -1
- package/bls12-381.js +4 -4
- package/bls12-381.js.map +1 -1
- package/ed25519.d.ts +52 -66
- package/ed25519.d.ts.map +1 -1
- package/ed25519.js +128 -155
- package/ed25519.js.map +1 -1
- package/ed448.d.ts +57 -58
- package/ed448.d.ts.map +1 -1
- package/ed448.js +114 -131
- package/ed448.js.map +1 -1
- package/esm/_shortw_utils.d.ts +1 -0
- package/esm/_shortw_utils.d.ts.map +1 -1
- package/esm/_shortw_utils.js +1 -0
- package/esm/_shortw_utils.js.map +1 -1
- package/esm/abstract/bls.d.ts +87 -62
- package/esm/abstract/bls.d.ts.map +1 -1
- package/esm/abstract/bls.js +171 -164
- package/esm/abstract/bls.js.map +1 -1
- package/esm/abstract/curve.d.ts +109 -23
- package/esm/abstract/curve.d.ts.map +1 -1
- package/esm/abstract/curve.js +156 -155
- package/esm/abstract/curve.js.map +1 -1
- package/esm/abstract/edwards.d.ts +126 -70
- package/esm/abstract/edwards.d.ts.map +1 -1
- package/esm/abstract/edwards.js +210 -62
- package/esm/abstract/edwards.js.map +1 -1
- package/esm/abstract/hash-to-curve.d.ts +8 -4
- package/esm/abstract/hash-to-curve.d.ts.map +1 -1
- package/esm/abstract/hash-to-curve.js +22 -11
- package/esm/abstract/hash-to-curve.js.map +1 -1
- package/esm/abstract/modular.d.ts +8 -3
- package/esm/abstract/modular.d.ts.map +1 -1
- package/esm/abstract/modular.js +79 -35
- package/esm/abstract/modular.js.map +1 -1
- package/esm/abstract/montgomery.d.ts +17 -4
- package/esm/abstract/montgomery.d.ts.map +1 -1
- package/esm/abstract/montgomery.js +19 -3
- package/esm/abstract/montgomery.js.map +1 -1
- package/esm/abstract/tower.d.ts +3 -3
- package/esm/abstract/tower.d.ts.map +1 -1
- package/esm/abstract/tower.js.map +1 -1
- package/esm/abstract/weierstrass.d.ts +145 -118
- package/esm/abstract/weierstrass.d.ts.map +1 -1
- package/esm/abstract/weierstrass.js +412 -334
- package/esm/abstract/weierstrass.js.map +1 -1
- package/esm/bls12-381.d.ts.map +1 -1
- package/esm/bls12-381.js +4 -4
- package/esm/bls12-381.js.map +1 -1
- package/esm/ed25519.d.ts +52 -66
- package/esm/ed25519.d.ts.map +1 -1
- package/esm/ed25519.js +131 -157
- package/esm/ed25519.js.map +1 -1
- package/esm/ed448.d.ts +57 -58
- package/esm/ed448.d.ts.map +1 -1
- package/esm/ed448.js +116 -132
- package/esm/ed448.js.map +1 -1
- package/esm/index.js +7 -9
- package/esm/index.js.map +1 -1
- package/esm/jubjub.d.ts +3 -3
- package/esm/jubjub.d.ts.map +1 -1
- package/esm/jubjub.js +3 -3
- package/esm/jubjub.js.map +1 -1
- package/esm/misc.d.ts +3 -5
- package/esm/misc.d.ts.map +1 -1
- package/esm/misc.js +0 -3
- package/esm/misc.js.map +1 -1
- package/esm/nist.d.ts +0 -6
- package/esm/nist.d.ts.map +1 -1
- package/esm/nist.js +31 -15
- package/esm/nist.js.map +1 -1
- package/esm/p256.d.ts +4 -0
- package/esm/p256.d.ts.map +1 -1
- package/esm/p256.js +4 -0
- package/esm/p256.js.map +1 -1
- package/esm/p384.d.ts +4 -1
- package/esm/p384.d.ts.map +1 -1
- package/esm/p384.js +4 -1
- package/esm/p384.js.map +1 -1
- package/esm/p521.d.ts +4 -0
- package/esm/p521.d.ts.map +1 -1
- package/esm/p521.js +4 -0
- package/esm/p521.js.map +1 -1
- package/esm/secp256k1.d.ts +32 -15
- package/esm/secp256k1.d.ts.map +1 -1
- package/esm/secp256k1.js +72 -67
- package/esm/secp256k1.js.map +1 -1
- package/esm/utils.d.ts +1 -1
- package/esm/utils.js +1 -1
- package/index.js +7 -9
- package/index.js.map +1 -1
- package/jubjub.d.ts +3 -3
- package/jubjub.d.ts.map +1 -1
- package/jubjub.js +3 -3
- package/jubjub.js.map +1 -1
- package/misc.d.ts +3 -5
- package/misc.d.ts.map +1 -1
- package/misc.js +0 -3
- package/misc.js.map +1 -1
- package/nist.d.ts +0 -6
- package/nist.d.ts.map +1 -1
- package/nist.js +31 -15
- package/nist.js.map +1 -1
- package/p256.d.ts +4 -0
- package/p256.d.ts.map +1 -1
- package/p256.js +4 -0
- package/p256.js.map +1 -1
- package/p384.d.ts +4 -1
- package/p384.d.ts.map +1 -1
- package/p384.js +4 -1
- package/p384.js.map +1 -1
- package/p521.d.ts +4 -0
- package/p521.d.ts.map +1 -1
- package/p521.js +4 -0
- package/p521.js.map +1 -1
- package/package.json +4 -2
- package/secp256k1.d.ts +32 -15
- package/secp256k1.d.ts.map +1 -1
- package/secp256k1.js +70 -65
- package/secp256k1.js.map +1 -1
- package/src/_shortw_utils.ts +1 -0
- package/src/abstract/bls.ts +319 -257
- package/src/abstract/curve.ts +226 -170
- package/src/abstract/edwards.ts +352 -139
- package/src/abstract/hash-to-curve.ts +33 -16
- package/src/abstract/modular.ts +86 -35
- package/src/abstract/montgomery.ts +36 -9
- package/src/abstract/tower.ts +4 -4
- package/src/abstract/weierstrass.ts +570 -476
- package/src/bls12-381.ts +28 -20
- package/src/ed25519.ts +161 -179
- package/src/ed448.ts +150 -156
- package/src/index.ts +7 -9
- package/src/jubjub.ts +3 -3
- package/src/misc.ts +3 -7
- package/src/nist.ts +40 -16
- package/src/p256.ts +4 -0
- package/src/p384.ts +4 -2
- package/src/p521.ts +4 -0
- package/src/secp256k1.ts +91 -73
- package/src/utils.ts +1 -1
- package/utils.d.ts +1 -1
- package/utils.js +1 -1
package/src/abstract/edwards.ts
CHANGED
|
@@ -27,8 +27,9 @@ import {
|
|
|
27
27
|
wNAF,
|
|
28
28
|
type AffinePoint,
|
|
29
29
|
type BasicCurve,
|
|
30
|
-
type
|
|
31
|
-
type
|
|
30
|
+
type CurveInfo,
|
|
31
|
+
type CurvePoint,
|
|
32
|
+
type CurvePointCons,
|
|
32
33
|
} from './curve.ts';
|
|
33
34
|
import { Field, type IField, type NLength } from './modular.ts';
|
|
34
35
|
|
|
@@ -38,10 +39,11 @@ const _0n = BigInt(0), _1n = BigInt(1), _2n = BigInt(2), _8n = BigInt(8);
|
|
|
38
39
|
|
|
39
40
|
export type UVRatio = (u: bigint, v: bigint) => { isValid: boolean; value: bigint };
|
|
40
41
|
|
|
41
|
-
|
|
42
|
+
// TODO: remove
|
|
42
43
|
export type CurveType = BasicCurve<bigint> & {
|
|
43
44
|
a: bigint; // curve param a
|
|
44
45
|
d: bigint; // curve param d
|
|
46
|
+
/** @deprecated the property will be removed in next release */
|
|
45
47
|
hash: FHash; // Hashing
|
|
46
48
|
randomBytes?: (bytesLength?: number) => Uint8Array; // CSPRNG
|
|
47
49
|
adjustScalarBytes?: (bytes: Uint8Array) => Uint8Array; // clears bits to get valid field elemtn
|
|
@@ -51,45 +53,45 @@ export type CurveType = BasicCurve<bigint> & {
|
|
|
51
53
|
mapToCurve?: (scalar: bigint[]) => AffinePoint<bigint>; // for hash-to-curve standard
|
|
52
54
|
};
|
|
53
55
|
|
|
56
|
+
// TODO: remove
|
|
54
57
|
export type CurveTypeWithLength = Readonly<CurveType & Partial<NLength>>;
|
|
55
58
|
|
|
56
|
-
// verification rule is either zip215 or rfc8032 / nist186-5. Consult fromHex:
|
|
57
|
-
const VERIFY_DEFAULT = { zip215: true };
|
|
58
|
-
|
|
59
59
|
/** Instance of Extended Point with coordinates in X, Y, Z, T. */
|
|
60
|
-
export interface
|
|
61
|
-
|
|
62
|
-
readonly
|
|
63
|
-
|
|
64
|
-
readonly
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
is0(): boolean;
|
|
71
|
-
isSmallOrder(): boolean;
|
|
72
|
-
isTorsionFree(): boolean;
|
|
73
|
-
clearCofactor(): ExtPointType;
|
|
74
|
-
toAffine(iz?: bigint): AffinePoint<bigint>;
|
|
75
|
-
toBytes(): Uint8Array;
|
|
60
|
+
export interface EdwardsPoint extends CurvePoint<bigint, EdwardsPoint> {
|
|
61
|
+
/** extended X coordinate. Different from affine x. */
|
|
62
|
+
readonly X: bigint;
|
|
63
|
+
/** extended Y coordinate. Different from affine y. */
|
|
64
|
+
readonly Y: bigint;
|
|
65
|
+
/** extended Z coordinate */
|
|
66
|
+
readonly Z: bigint;
|
|
67
|
+
/** extended T coordinate */
|
|
68
|
+
readonly T: bigint;
|
|
69
|
+
|
|
76
70
|
/** @deprecated use `toBytes` */
|
|
77
71
|
toRawBytes(): Uint8Array;
|
|
78
|
-
toHex(): string;
|
|
79
|
-
precompute(windowSize?: number, isLazy?: boolean): ExtPointType;
|
|
80
72
|
/** @deprecated use `p.precompute(windowSize)` */
|
|
81
73
|
_setWindowSize(windowSize: number): void;
|
|
74
|
+
/** @deprecated use .X */
|
|
75
|
+
readonly ex: bigint;
|
|
76
|
+
/** @deprecated use .Y */
|
|
77
|
+
readonly ey: bigint;
|
|
78
|
+
/** @deprecated use .Z */
|
|
79
|
+
readonly ez: bigint;
|
|
80
|
+
/** @deprecated use .T */
|
|
81
|
+
readonly et: bigint;
|
|
82
82
|
}
|
|
83
83
|
/** Static methods of Extended Point with coordinates in X, Y, Z, T. */
|
|
84
|
-
export interface
|
|
85
|
-
new (
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
fromHex(hex: Hex, zip215?: boolean): ExtPointType;
|
|
91
|
-
msm(points: ExtPointType[], scalars: bigint[]): ExtPointType;
|
|
84
|
+
export interface EdwardsPointCons extends CurvePointCons<bigint, EdwardsPoint> {
|
|
85
|
+
new (X: bigint, Y: bigint, Z: bigint, T: bigint): EdwardsPoint;
|
|
86
|
+
fromBytes(bytes: Uint8Array, zip215?: boolean): EdwardsPoint;
|
|
87
|
+
fromHex(hex: Hex, zip215?: boolean): EdwardsPoint;
|
|
88
|
+
/** @deprecated use `import { pippenger } from '@noble/curves/abstract/curve.js';` */
|
|
89
|
+
msm(points: EdwardsPoint[], scalars: bigint[]): EdwardsPoint;
|
|
92
90
|
}
|
|
91
|
+
/** @deprecated use EdwardsPoint */
|
|
92
|
+
export type ExtPointType = EdwardsPoint;
|
|
93
|
+
/** @deprecated use EdwardsPointCons */
|
|
94
|
+
export type ExtPointConstructor = EdwardsPointCons;
|
|
93
95
|
|
|
94
96
|
/**
|
|
95
97
|
* Twisted Edwards curve options.
|
|
@@ -103,11 +105,11 @@ export interface ExtPointConstructor extends GroupConstructor<ExtPointType> {
|
|
|
103
105
|
* * Gy: y coordinate of generator point
|
|
104
106
|
*/
|
|
105
107
|
export type EdwardsOpts = Readonly<{
|
|
106
|
-
a: bigint;
|
|
107
|
-
d: bigint;
|
|
108
108
|
p: bigint;
|
|
109
109
|
n: bigint;
|
|
110
110
|
h: bigint;
|
|
111
|
+
a: bigint;
|
|
112
|
+
d: bigint;
|
|
111
113
|
Gx: bigint;
|
|
112
114
|
Gy: bigint;
|
|
113
115
|
}>;
|
|
@@ -128,76 +130,91 @@ export type EdwardsExtraOpts = Partial<{
|
|
|
128
130
|
/**
|
|
129
131
|
* EdDSA (Edwards Digital Signature algorithm) options.
|
|
130
132
|
*
|
|
131
|
-
* * hash: hash function used to hash
|
|
133
|
+
* * hash: hash function used to hash secret keys and messages
|
|
132
134
|
* * adjustScalarBytes: clears bits to get valid field element
|
|
133
135
|
* * domain: Used for hashing
|
|
134
136
|
* * mapToCurve: for hash-to-curve standard
|
|
135
137
|
* * prehash: RFC 8032 pre-hashing of messages to sign() / verify()
|
|
136
|
-
* * randomBytes: function generating random bytes, used for
|
|
138
|
+
* * randomBytes: function generating random bytes, used for randomSecretKey
|
|
137
139
|
*/
|
|
138
|
-
export type EdDSAOpts = {
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
};
|
|
140
|
+
export type EdDSAOpts = Partial<{
|
|
141
|
+
adjustScalarBytes: (bytes: Uint8Array) => Uint8Array;
|
|
142
|
+
domain: (data: Uint8Array, ctx: Uint8Array, phflag: boolean) => Uint8Array;
|
|
143
|
+
mapToCurve: (scalar: bigint[]) => AffinePoint<bigint>;
|
|
144
|
+
prehash: FHash;
|
|
145
|
+
randomBytes: (bytesLength?: number) => Uint8Array;
|
|
146
|
+
}>;
|
|
146
147
|
|
|
147
148
|
/**
|
|
148
149
|
* EdDSA (Edwards Digital Signature algorithm) interface.
|
|
149
150
|
*
|
|
150
|
-
* Allows to create and verify signatures, create public and
|
|
151
|
+
* Allows to create and verify signatures, create public and secret keys.
|
|
151
152
|
*/
|
|
152
153
|
export interface EdDSA {
|
|
153
|
-
|
|
154
|
-
|
|
154
|
+
keygen: (seed?: Uint8Array) => { secretKey: Uint8Array; publicKey: Uint8Array };
|
|
155
|
+
getPublicKey: (secretKey: Hex) => Uint8Array;
|
|
156
|
+
sign: (message: Hex, secretKey: Hex, options?: { context?: Hex }) => Uint8Array;
|
|
155
157
|
verify: (
|
|
156
158
|
sig: Hex,
|
|
157
159
|
message: Hex,
|
|
158
160
|
publicKey: Hex,
|
|
159
161
|
options?: { context?: Hex; zip215: boolean }
|
|
160
162
|
) => boolean;
|
|
161
|
-
Point:
|
|
163
|
+
Point: EdwardsPointCons;
|
|
162
164
|
utils: {
|
|
163
|
-
|
|
165
|
+
randomSecretKey: (seed?: Uint8Array) => Uint8Array;
|
|
166
|
+
isValidSecretKey: (secretKey: Uint8Array) => boolean;
|
|
167
|
+
isValidPublicKey: (publicKey: Uint8Array, zip215?: boolean) => boolean;
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Converts ed public key to x public key.
|
|
171
|
+
* @example
|
|
172
|
+
* ```js
|
|
173
|
+
* const someonesPub = ed25519.getPublicKey(ed25519.utils.randomSecretKey());
|
|
174
|
+
* const aPriv = x25519.utils.randomSecretKey();
|
|
175
|
+
* x25519.getSharedSecret(aPriv, ed25519.utils.toMontgomery(someonesPub))
|
|
176
|
+
* ```
|
|
177
|
+
*/
|
|
178
|
+
toMontgomery: (publicKey: Uint8Array) => Uint8Array;
|
|
179
|
+
/**
|
|
180
|
+
* Converts ed secret key to x secret key.
|
|
181
|
+
* @example
|
|
182
|
+
* ```js
|
|
183
|
+
* const someonesPub = x25519.getPublicKey(x25519.utils.randomSecretKey());
|
|
184
|
+
* const aPriv = ed25519.utils.randomSecretKey();
|
|
185
|
+
* x25519.getSharedSecret(ed25519.utils.toMontgomeryPriv(aPriv), someonesPub)
|
|
186
|
+
* ```
|
|
187
|
+
*/
|
|
188
|
+
toMontgomeryPriv: (privateKey: Uint8Array) => Uint8Array;
|
|
164
189
|
getExtendedPublicKey: (key: Hex) => {
|
|
165
190
|
head: Uint8Array;
|
|
166
191
|
prefix: Uint8Array;
|
|
167
192
|
scalar: bigint;
|
|
168
|
-
point:
|
|
193
|
+
point: EdwardsPoint;
|
|
169
194
|
pointBytes: Uint8Array;
|
|
170
195
|
};
|
|
196
|
+
|
|
197
|
+
/** @deprecated use `randomSecretKey` */
|
|
198
|
+
randomPrivateKey: (seed?: Uint8Array) => Uint8Array;
|
|
171
199
|
/** @deprecated use `point.precompute()` */
|
|
172
|
-
precompute: (windowSize?: number, point?:
|
|
200
|
+
precompute: (windowSize?: number, point?: EdwardsPoint) => EdwardsPoint;
|
|
173
201
|
};
|
|
202
|
+
info: CurveInfo;
|
|
174
203
|
}
|
|
175
204
|
|
|
176
205
|
// Legacy params. TODO: remove
|
|
177
206
|
export type CurveFn = {
|
|
207
|
+
/** @deprecated the property will be removed in next release */
|
|
178
208
|
CURVE: CurveType;
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
publicKey: Hex,
|
|
185
|
-
options?: { context?: Hex; zip215: boolean }
|
|
186
|
-
) => boolean;
|
|
187
|
-
Point: ExtPointConstructor;
|
|
209
|
+
keygen: EdDSA['keygen'];
|
|
210
|
+
getPublicKey: EdDSA['getPublicKey'];
|
|
211
|
+
sign: EdDSA['sign'];
|
|
212
|
+
verify: EdDSA['verify'];
|
|
213
|
+
Point: EdwardsPointCons;
|
|
188
214
|
/** @deprecated use `Point` */
|
|
189
|
-
ExtendedPoint:
|
|
190
|
-
utils:
|
|
191
|
-
|
|
192
|
-
getExtendedPublicKey: (key: Hex) => {
|
|
193
|
-
head: Uint8Array;
|
|
194
|
-
prefix: Uint8Array;
|
|
195
|
-
scalar: bigint;
|
|
196
|
-
point: ExtPointType;
|
|
197
|
-
pointBytes: Uint8Array;
|
|
198
|
-
};
|
|
199
|
-
precompute: (windowSize?: number, point?: ExtPointType) => ExtPointType;
|
|
200
|
-
};
|
|
215
|
+
ExtendedPoint: EdwardsPointCons;
|
|
216
|
+
utils: EdDSA['utils'];
|
|
217
|
+
info: CurveInfo;
|
|
201
218
|
};
|
|
202
219
|
|
|
203
220
|
function isEdValidXY(Fp: IField<bigint>, CURVE: EdwardsOpts, x: bigint, y: bigint): boolean {
|
|
@@ -208,7 +225,7 @@ function isEdValidXY(Fp: IField<bigint>, CURVE: EdwardsOpts, x: bigint, y: bigin
|
|
|
208
225
|
return Fp.eql(left, right);
|
|
209
226
|
}
|
|
210
227
|
|
|
211
|
-
export function edwards(CURVE: EdwardsOpts, curveOpts: EdwardsExtraOpts = {}):
|
|
228
|
+
export function edwards(CURVE: EdwardsOpts, curveOpts: EdwardsExtraOpts = {}): EdwardsPointCons {
|
|
212
229
|
const { Fp, Fn } = _createCurveFields('edwards', CURVE, curveOpts);
|
|
213
230
|
const { h: cofactor, n: CURVE_ORDER } = CURVE;
|
|
214
231
|
_validateObject(curveOpts, {}, { uvRatio: 'function' });
|
|
@@ -252,22 +269,22 @@ export function edwards(CURVE: EdwardsOpts, curveOpts: EdwardsExtraOpts = {}): E
|
|
|
252
269
|
// Converts Extended point to default (x, y) coordinates.
|
|
253
270
|
// Can accept precomputed Z^-1 - for example, from invertBatch.
|
|
254
271
|
const toAffineMemo = memoized((p: Point, iz?: bigint): AffinePoint<bigint> => {
|
|
255
|
-
const {
|
|
272
|
+
const { X, Y, Z } = p;
|
|
256
273
|
const is0 = p.is0();
|
|
257
|
-
if (iz == null) iz = is0 ? _8n : (Fp.inv(
|
|
258
|
-
const
|
|
259
|
-
const
|
|
260
|
-
const zz =
|
|
274
|
+
if (iz == null) iz = is0 ? _8n : (Fp.inv(Z) as bigint); // 8 was chosen arbitrarily
|
|
275
|
+
const x = modP(X * iz);
|
|
276
|
+
const y = modP(Y * iz);
|
|
277
|
+
const zz = Fp.mul(Z, iz);
|
|
261
278
|
if (is0) return { x: _0n, y: _1n };
|
|
262
279
|
if (zz !== _1n) throw new Error('invZ was invalid');
|
|
263
|
-
return { x
|
|
280
|
+
return { x, y };
|
|
264
281
|
});
|
|
265
282
|
const assertValidMemo = memoized((p: Point) => {
|
|
266
283
|
const { a, d } = CURVE;
|
|
267
284
|
if (p.is0()) throw new Error('bad point: ZERO'); // TODO: optimize, with vars below?
|
|
268
285
|
// Equation in affine coordinates: ax² + y² = 1 + dx²y²
|
|
269
286
|
// Equation in projective coordinates (X/Z, Y/Z, Z): (aX² + Y²)Z² = Z⁴ + dX²Y²
|
|
270
|
-
const {
|
|
287
|
+
const { X, Y, Z, T } = p;
|
|
271
288
|
const X2 = modP(X * X); // X²
|
|
272
289
|
const Y2 = modP(Y * Y); // Y²
|
|
273
290
|
const Z2 = modP(Z * Z); // Z²
|
|
@@ -285,7 +302,7 @@ export function edwards(CURVE: EdwardsOpts, curveOpts: EdwardsExtraOpts = {}): E
|
|
|
285
302
|
|
|
286
303
|
// Extended Point works in extended coordinates: (X, Y, Z, T) ∋ (x=X/Z, y=Y/Z, T=xy).
|
|
287
304
|
// https://en.wikipedia.org/wiki/Twisted_Edwards_curve#Extended_coordinates
|
|
288
|
-
class Point implements
|
|
305
|
+
class Point implements EdwardsPoint {
|
|
289
306
|
// base / generator point
|
|
290
307
|
static readonly BASE = new Point(CURVE.Gx, CURVE.Gy, _1n, modP(CURVE.Gx * CURVE.Gy));
|
|
291
308
|
// zero / infinity / identity point
|
|
@@ -294,16 +311,16 @@ export function edwards(CURVE: EdwardsOpts, curveOpts: EdwardsExtraOpts = {}): E
|
|
|
294
311
|
static readonly Fp = Fp;
|
|
295
312
|
static readonly Fn = Fn;
|
|
296
313
|
|
|
297
|
-
readonly
|
|
298
|
-
readonly
|
|
299
|
-
readonly
|
|
300
|
-
readonly
|
|
314
|
+
readonly X: bigint;
|
|
315
|
+
readonly Y: bigint;
|
|
316
|
+
readonly Z: bigint;
|
|
317
|
+
readonly T: bigint;
|
|
301
318
|
|
|
302
|
-
constructor(
|
|
303
|
-
this.
|
|
304
|
-
this.
|
|
305
|
-
this.
|
|
306
|
-
this.
|
|
319
|
+
constructor(X: bigint, Y: bigint, Z: bigint, T: bigint) {
|
|
320
|
+
this.X = acoord('x', X);
|
|
321
|
+
this.Y = acoord('y', Y);
|
|
322
|
+
this.Z = acoord('z', Z, true);
|
|
323
|
+
this.T = acoord('t', T);
|
|
307
324
|
Object.freeze(this);
|
|
308
325
|
}
|
|
309
326
|
|
|
@@ -314,32 +331,44 @@ export function edwards(CURVE: EdwardsOpts, curveOpts: EdwardsExtraOpts = {}): E
|
|
|
314
331
|
return this.toAffine().y;
|
|
315
332
|
}
|
|
316
333
|
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
return
|
|
334
|
+
// TODO: remove
|
|
335
|
+
get ex(): bigint {
|
|
336
|
+
return this.X;
|
|
337
|
+
}
|
|
338
|
+
get ey(): bigint {
|
|
339
|
+
return this.Y;
|
|
340
|
+
}
|
|
341
|
+
get ez(): bigint {
|
|
342
|
+
return this.Z;
|
|
343
|
+
}
|
|
344
|
+
get et(): bigint {
|
|
345
|
+
return this.T;
|
|
323
346
|
}
|
|
324
347
|
static normalizeZ(points: Point[]): Point[] {
|
|
325
|
-
return normalizeZ(Point,
|
|
348
|
+
return normalizeZ(Point, points);
|
|
326
349
|
}
|
|
327
|
-
// Multiscalar Multiplication
|
|
328
350
|
static msm(points: Point[], scalars: bigint[]): Point {
|
|
329
351
|
return pippenger(Point, Fn, points, scalars);
|
|
330
352
|
}
|
|
331
|
-
|
|
332
|
-
// "Private method", don't use it directly
|
|
333
353
|
_setWindowSize(windowSize: number) {
|
|
334
354
|
this.precompute(windowSize);
|
|
335
355
|
}
|
|
356
|
+
|
|
357
|
+
static fromAffine(p: AffinePoint<bigint>): Point {
|
|
358
|
+
if (p instanceof Point) throw new Error('extended point not allowed');
|
|
359
|
+
const { x, y } = p || {};
|
|
360
|
+
acoord('x', x);
|
|
361
|
+
acoord('y', y);
|
|
362
|
+
return new Point(x, y, _1n, modP(x * y));
|
|
363
|
+
}
|
|
364
|
+
|
|
336
365
|
precompute(windowSize: number = 8, isLazy = true) {
|
|
337
|
-
wnaf.
|
|
366
|
+
wnaf.createCache(this, windowSize);
|
|
338
367
|
if (!isLazy) this.multiply(_2n); // random number
|
|
339
368
|
return this;
|
|
340
369
|
}
|
|
341
|
-
|
|
342
|
-
//
|
|
370
|
+
|
|
371
|
+
// Useful in fromAffine() - not for fromBytes(), which always created valid points.
|
|
343
372
|
assertValidity(): void {
|
|
344
373
|
assertValidMemo(this);
|
|
345
374
|
}
|
|
@@ -347,8 +376,8 @@ export function edwards(CURVE: EdwardsOpts, curveOpts: EdwardsExtraOpts = {}): E
|
|
|
347
376
|
// Compare one point to another.
|
|
348
377
|
equals(other: Point): boolean {
|
|
349
378
|
aextpoint(other);
|
|
350
|
-
const {
|
|
351
|
-
const {
|
|
379
|
+
const { X: X1, Y: Y1, Z: Z1 } = this;
|
|
380
|
+
const { X: X2, Y: Y2, Z: Z2 } = other;
|
|
352
381
|
const X1Z2 = modP(X1 * Z2);
|
|
353
382
|
const X2Z1 = modP(X2 * Z1);
|
|
354
383
|
const Y1Z2 = modP(Y1 * Z2);
|
|
@@ -362,7 +391,7 @@ export function edwards(CURVE: EdwardsOpts, curveOpts: EdwardsExtraOpts = {}): E
|
|
|
362
391
|
|
|
363
392
|
negate(): Point {
|
|
364
393
|
// Flips point sign to a negative one (-x, y in affine coords)
|
|
365
|
-
return new Point(modP(-this.
|
|
394
|
+
return new Point(modP(-this.X), this.Y, this.Z, modP(-this.T));
|
|
366
395
|
}
|
|
367
396
|
|
|
368
397
|
// Fast algo for doubling Extended Point.
|
|
@@ -370,7 +399,7 @@ export function edwards(CURVE: EdwardsOpts, curveOpts: EdwardsExtraOpts = {}): E
|
|
|
370
399
|
// Cost: 4M + 4S + 1*a + 6add + 1*2.
|
|
371
400
|
double(): Point {
|
|
372
401
|
const { a } = CURVE;
|
|
373
|
-
const {
|
|
402
|
+
const { X: X1, Y: Y1, Z: Z1 } = this;
|
|
374
403
|
const A = modP(X1 * X1); // A = X12
|
|
375
404
|
const B = modP(Y1 * Y1); // B = Y12
|
|
376
405
|
const C = modP(_2n * modP(Z1 * Z1)); // C = 2*Z12
|
|
@@ -393,8 +422,8 @@ export function edwards(CURVE: EdwardsOpts, curveOpts: EdwardsExtraOpts = {}): E
|
|
|
393
422
|
add(other: Point) {
|
|
394
423
|
aextpoint(other);
|
|
395
424
|
const { a, d } = CURVE;
|
|
396
|
-
const {
|
|
397
|
-
const {
|
|
425
|
+
const { X: X1, Y: Y1, Z: Z1, T: T1 } = this;
|
|
426
|
+
const { X: X2, Y: Y2, Z: Z2, T: T2 } = other;
|
|
398
427
|
const A = modP(X1 * X2); // A = X1*X2
|
|
399
428
|
const B = modP(Y1 * Y2); // B = Y1*Y2
|
|
400
429
|
const C = modP(T1 * d * T2); // C = T1*d*T2
|
|
@@ -418,8 +447,8 @@ export function edwards(CURVE: EdwardsOpts, curveOpts: EdwardsExtraOpts = {}): E
|
|
|
418
447
|
multiply(scalar: bigint): Point {
|
|
419
448
|
const n = scalar;
|
|
420
449
|
aInRange('scalar', n, _1n, CURVE_ORDER); // 1 <= scalar < L
|
|
421
|
-
const { p, f } = wnaf.
|
|
422
|
-
return
|
|
450
|
+
const { p, f } = wnaf.cached(this, n, (p) => normalizeZ(Point, p));
|
|
451
|
+
return normalizeZ(Point, [p, f])[0];
|
|
423
452
|
}
|
|
424
453
|
|
|
425
454
|
// Non-constant-time multiplication. Uses double-and-add algorithm.
|
|
@@ -432,7 +461,7 @@ export function edwards(CURVE: EdwardsOpts, curveOpts: EdwardsExtraOpts = {}): E
|
|
|
432
461
|
aInRange('scalar', n, _0n, CURVE_ORDER); // 0 <= scalar < L
|
|
433
462
|
if (n === _0n) return Point.ZERO;
|
|
434
463
|
if (this.is0() || n === _1n) return this;
|
|
435
|
-
return wnaf.
|
|
464
|
+
return wnaf.unsafe(this, n, (p) => normalizeZ(Point, p), acc);
|
|
436
465
|
}
|
|
437
466
|
|
|
438
467
|
// Checks if point is of small order.
|
|
@@ -446,7 +475,7 @@ export function edwards(CURVE: EdwardsOpts, curveOpts: EdwardsExtraOpts = {}): E
|
|
|
446
475
|
// Multiplies point by curve order and checks if the result is 0.
|
|
447
476
|
// Returns `false` is the point is dirty.
|
|
448
477
|
isTorsionFree(): boolean {
|
|
449
|
-
return wnaf.
|
|
478
|
+
return wnaf.unsafe(this, CURVE_ORDER).is0();
|
|
450
479
|
}
|
|
451
480
|
|
|
452
481
|
// Converts Extended point to default (x, y) coordinates.
|
|
@@ -462,7 +491,7 @@ export function edwards(CURVE: EdwardsOpts, curveOpts: EdwardsExtraOpts = {}): E
|
|
|
462
491
|
|
|
463
492
|
static fromBytes(bytes: Uint8Array, zip215 = false): Point {
|
|
464
493
|
abytes(bytes);
|
|
465
|
-
return
|
|
494
|
+
return Point.fromHex(bytes, zip215);
|
|
466
495
|
}
|
|
467
496
|
|
|
468
497
|
// Converts hash string or Uint8Array to Point.
|
|
@@ -499,9 +528,6 @@ export function edwards(CURVE: EdwardsOpts, curveOpts: EdwardsExtraOpts = {}): E
|
|
|
499
528
|
if (isLastByteOdd !== isXOdd) x = modP(-x); // if x_0 != x mod 2, set x = p-x
|
|
500
529
|
return Point.fromAffine({ x, y });
|
|
501
530
|
}
|
|
502
|
-
static fromPrivateScalar(scalar: bigint): Point {
|
|
503
|
-
return Point.BASE.multiply(scalar);
|
|
504
|
-
}
|
|
505
531
|
toBytes(): Uint8Array {
|
|
506
532
|
const { x, y } = this.toAffine();
|
|
507
533
|
const bytes = numberToBytesLE(y, Fp.BYTES); // each y has 2 x values (x, -y)
|
|
@@ -520,19 +546,128 @@ export function edwards(CURVE: EdwardsOpts, curveOpts: EdwardsExtraOpts = {}): E
|
|
|
520
546
|
return `<Point ${this.is0() ? 'ZERO' : this.toHex()}>`;
|
|
521
547
|
}
|
|
522
548
|
}
|
|
523
|
-
const wnaf = wNAF(Point, Fn.BYTES * 8); // Fn.BITS?
|
|
549
|
+
const wnaf = new wNAF(Point, Fn.BYTES * 8); // Fn.BITS?
|
|
524
550
|
return Point;
|
|
525
551
|
}
|
|
526
552
|
|
|
553
|
+
/**
|
|
554
|
+
* Base class for prime-order points like Ristretto255 and Decaf448.
|
|
555
|
+
* These points eliminate cofactor issues by representing equivalence classes
|
|
556
|
+
* of Edwards curve points.
|
|
557
|
+
*/
|
|
558
|
+
export abstract class PrimeEdwardsPoint<T extends PrimeEdwardsPoint<T>>
|
|
559
|
+
implements CurvePoint<bigint, T>
|
|
560
|
+
{
|
|
561
|
+
static BASE: PrimeEdwardsPoint<any>;
|
|
562
|
+
static ZERO: PrimeEdwardsPoint<any>;
|
|
563
|
+
static Fp: IField<bigint>;
|
|
564
|
+
static Fn: IField<bigint>;
|
|
565
|
+
|
|
566
|
+
protected readonly ep: EdwardsPoint;
|
|
567
|
+
|
|
568
|
+
constructor(ep: EdwardsPoint) {
|
|
569
|
+
this.ep = ep;
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
// Abstract methods that must be implemented by subclasses
|
|
573
|
+
abstract toBytes(): Uint8Array;
|
|
574
|
+
abstract equals(other: T): boolean;
|
|
575
|
+
|
|
576
|
+
// Static methods that must be implemented by subclasses
|
|
577
|
+
static fromBytes(_bytes: Uint8Array): any {
|
|
578
|
+
throw new Error('fromBytes must be implemented by subclass');
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
static fromHex(_hex: Hex): any {
|
|
582
|
+
throw new Error('fromHex must be implemented by subclass');
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
get x(): bigint {
|
|
586
|
+
return this.toAffine().x;
|
|
587
|
+
}
|
|
588
|
+
get y(): bigint {
|
|
589
|
+
return this.toAffine().y;
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
// Common implementations
|
|
593
|
+
clearCofactor(): T {
|
|
594
|
+
// no-op for prime-order groups
|
|
595
|
+
return this as any;
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
assertValidity(): void {
|
|
599
|
+
this.ep.assertValidity();
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
toAffine(invertedZ?: bigint): AffinePoint<bigint> {
|
|
603
|
+
return this.ep.toAffine(invertedZ);
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
/** @deprecated use `toBytes` */
|
|
607
|
+
toRawBytes(): Uint8Array {
|
|
608
|
+
return this.toBytes();
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
toHex(): string {
|
|
612
|
+
return bytesToHex(this.toBytes());
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
toString(): string {
|
|
616
|
+
return this.toHex();
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
isTorsionFree(): boolean {
|
|
620
|
+
return true;
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
isSmallOrder(): boolean {
|
|
624
|
+
return false;
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
add(other: T): T {
|
|
628
|
+
this.assertSame(other);
|
|
629
|
+
return this.init(this.ep.add(other.ep));
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
subtract(other: T): T {
|
|
633
|
+
this.assertSame(other);
|
|
634
|
+
return this.init(this.ep.subtract(other.ep));
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
multiply(scalar: bigint): T {
|
|
638
|
+
return this.init(this.ep.multiply(scalar));
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
multiplyUnsafe(scalar: bigint): T {
|
|
642
|
+
return this.init(this.ep.multiplyUnsafe(scalar));
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
double(): T {
|
|
646
|
+
return this.init(this.ep.double());
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
negate(): T {
|
|
650
|
+
return this.init(this.ep.negate());
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
precompute(windowSize?: number, isLazy?: boolean): T {
|
|
654
|
+
return this.init(this.ep.precompute(windowSize, isLazy));
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
// Helper methods
|
|
658
|
+
abstract is0(): boolean;
|
|
659
|
+
protected abstract assertSame(other: T): void;
|
|
660
|
+
protected abstract init(ep: EdwardsPoint): T;
|
|
661
|
+
}
|
|
662
|
+
|
|
527
663
|
/**
|
|
528
664
|
* Initializes EdDSA signatures over given Edwards curve.
|
|
529
665
|
*/
|
|
530
|
-
export function eddsa(Point:
|
|
666
|
+
export function eddsa(Point: EdwardsPointCons, cHash: FHash, eddsaOpts: EdDSAOpts): EdDSA {
|
|
667
|
+
if (typeof cHash !== 'function') throw new Error('"hash" function param is required');
|
|
531
668
|
_validateObject(
|
|
532
669
|
eddsaOpts,
|
|
533
|
-
{
|
|
534
|
-
hash: 'function',
|
|
535
|
-
},
|
|
670
|
+
{},
|
|
536
671
|
{
|
|
537
672
|
adjustScalarBytes: 'function',
|
|
538
673
|
randomBytes: 'function',
|
|
@@ -542,7 +677,7 @@ export function eddsa(Point: ExtPointConstructor, eddsaOpts: EdDSAOpts): EdDSA {
|
|
|
542
677
|
}
|
|
543
678
|
);
|
|
544
679
|
|
|
545
|
-
const { prehash
|
|
680
|
+
const { prehash } = eddsaOpts;
|
|
546
681
|
const { BASE: G, Fp, Fn } = Point;
|
|
547
682
|
const CURVE_ORDER = Fn.ORDER;
|
|
548
683
|
|
|
@@ -559,6 +694,7 @@ export function eddsa(Point: ExtPointConstructor, eddsaOpts: EdDSAOpts): EdDSA {
|
|
|
559
694
|
function modN(a: bigint) {
|
|
560
695
|
return Fn.create(a);
|
|
561
696
|
}
|
|
697
|
+
|
|
562
698
|
// Little-endian SHA512 with modulo n
|
|
563
699
|
function modN_LE(hash: Uint8Array): bigint {
|
|
564
700
|
// Not using Fn.fromBytes: hash can be 2*Fn.BYTES
|
|
@@ -578,17 +714,17 @@ export function eddsa(Point: ExtPointConstructor, eddsaOpts: EdDSAOpts): EdDSA {
|
|
|
578
714
|
return { head, prefix, scalar };
|
|
579
715
|
}
|
|
580
716
|
|
|
581
|
-
|
|
582
|
-
function getExtendedPublicKey(
|
|
583
|
-
const { head, prefix, scalar } = getPrivateScalar(
|
|
717
|
+
/** Convenience method that creates public key from scalar. RFC8032 5.1.5 */
|
|
718
|
+
function getExtendedPublicKey(secretKey: Hex) {
|
|
719
|
+
const { head, prefix, scalar } = getPrivateScalar(secretKey);
|
|
584
720
|
const point = G.multiply(scalar); // Point on Edwards curve aka public key
|
|
585
721
|
const pointBytes = point.toBytes();
|
|
586
722
|
return { head, prefix, scalar, point, pointBytes };
|
|
587
723
|
}
|
|
588
724
|
|
|
589
|
-
|
|
590
|
-
function getPublicKey(
|
|
591
|
-
return getExtendedPublicKey(
|
|
725
|
+
/** Calculates EdDSA pub key. RFC8032 5.1.5. */
|
|
726
|
+
function getPublicKey(secretKey: Hex): Uint8Array {
|
|
727
|
+
return getExtendedPublicKey(secretKey).pointBytes;
|
|
592
728
|
}
|
|
593
729
|
|
|
594
730
|
// int('LE', SHA512(dom2(F, C) || msgs)) mod N
|
|
@@ -598,10 +734,10 @@ export function eddsa(Point: ExtPointConstructor, eddsaOpts: EdDSAOpts): EdDSA {
|
|
|
598
734
|
}
|
|
599
735
|
|
|
600
736
|
/** Signs message with privateKey. RFC8032 5.1.6 */
|
|
601
|
-
function sign(msg: Hex,
|
|
737
|
+
function sign(msg: Hex, secretKey: Hex, options: { context?: Hex } = {}): Uint8Array {
|
|
602
738
|
msg = ensureBytes('message', msg);
|
|
603
739
|
if (prehash) msg = prehash(msg); // for ed25519ph etc.
|
|
604
|
-
const { prefix, scalar, pointBytes } = getExtendedPublicKey(
|
|
740
|
+
const { prefix, scalar, pointBytes } = getExtendedPublicKey(secretKey);
|
|
605
741
|
const r = hashDomainToScalar(options.context, prefix, msg); // r = dom2(F, C) || prefix || PH(M)
|
|
606
742
|
const R = G.multiply(r).toBytes(); // R = rG
|
|
607
743
|
const k = hashDomainToScalar(options.context, R, pointBytes, msg); // R || A || PH(M)
|
|
@@ -612,7 +748,8 @@ export function eddsa(Point: ExtPointConstructor, eddsaOpts: EdDSAOpts): EdDSA {
|
|
|
612
748
|
return ensureBytes('result', res, L * 2); // 64-byte signature
|
|
613
749
|
}
|
|
614
750
|
|
|
615
|
-
|
|
751
|
+
// verification rule is either zip215 or rfc8032 / nist186-5. Consult fromHex:
|
|
752
|
+
const verifyOpts: { context?: Hex; zip215?: boolean } = { zip215: true };
|
|
616
753
|
|
|
617
754
|
/**
|
|
618
755
|
* Verifies EdDSA signature against message and public key. RFC8032 5.1.7.
|
|
@@ -650,10 +787,54 @@ export function eddsa(Point: ExtPointConstructor, eddsaOpts: EdDSAOpts): EdDSA {
|
|
|
650
787
|
|
|
651
788
|
G.precompute(8); // Enable precomputes. Slows down first publicKey computation by 20ms.
|
|
652
789
|
|
|
790
|
+
const size = Fp.BYTES;
|
|
791
|
+
const lengths = {
|
|
792
|
+
secret: size,
|
|
793
|
+
public: size,
|
|
794
|
+
signature: 2 * size,
|
|
795
|
+
seed: size,
|
|
796
|
+
};
|
|
797
|
+
function randomSecretKey(seed = randomBytes_!(lengths.seed)): Uint8Array {
|
|
798
|
+
return seed;
|
|
799
|
+
}
|
|
800
|
+
|
|
653
801
|
const utils = {
|
|
654
802
|
getExtendedPublicKey,
|
|
655
803
|
/** ed25519 priv keys are uniform 32b. No need to check for modulo bias, like in secp256k1. */
|
|
656
|
-
|
|
804
|
+
randomSecretKey,
|
|
805
|
+
|
|
806
|
+
isValidSecretKey,
|
|
807
|
+
isValidPublicKey,
|
|
808
|
+
|
|
809
|
+
randomPrivateKey: randomSecretKey,
|
|
810
|
+
|
|
811
|
+
/**
|
|
812
|
+
* Converts ed public key to x public key. Uses formula:
|
|
813
|
+
* - ed25519:
|
|
814
|
+
* - `(u, v) = ((1+y)/(1-y), sqrt(-486664)*u/x)`
|
|
815
|
+
* - `(x, y) = (sqrt(-486664)*u/v, (u-1)/(u+1))`
|
|
816
|
+
* - ed448:
|
|
817
|
+
* - `(u, v) = ((y-1)/(y+1), sqrt(156324)*u/x)`
|
|
818
|
+
* - `(x, y) = (sqrt(156324)*u/v, (1+u)/(1-u))`
|
|
819
|
+
*
|
|
820
|
+
* There is NO `fromMontgomery`:
|
|
821
|
+
* - There are 2 valid ed25519 points for every x25519, with flipped coordinate
|
|
822
|
+
* - Sometimes there are 0 valid ed25519 points, because x25519 *additionally*
|
|
823
|
+
* accepts inputs on the quadratic twist, which can't be moved to ed25519
|
|
824
|
+
*/
|
|
825
|
+
toMontgomery(publicKey: Uint8Array): Uint8Array {
|
|
826
|
+
const { y } = Point.fromBytes(publicKey);
|
|
827
|
+
const is25519 = size === 32;
|
|
828
|
+
if (!is25519 && size !== 57) throw new Error('only defined for 25519 and 448');
|
|
829
|
+
const u = is25519 ? Fp.div(_1n + y, _1n - y) : Fp.div(y - _1n, y + _1n);
|
|
830
|
+
return Fp.toBytes(u);
|
|
831
|
+
},
|
|
832
|
+
|
|
833
|
+
toMontgomeryPriv(privateKey: Uint8Array): Uint8Array {
|
|
834
|
+
abytes(privateKey, size);
|
|
835
|
+
const hashed = cHash(privateKey.subarray(0, size));
|
|
836
|
+
return adjustScalarBytes(hashed).subarray(0, size);
|
|
837
|
+
},
|
|
657
838
|
|
|
658
839
|
/**
|
|
659
840
|
* We're doing scalar multiplication (used in getPublicKey etc) with precomputed BASE_POINT
|
|
@@ -661,19 +842,51 @@ export function eddsa(Point: ExtPointConstructor, eddsaOpts: EdDSAOpts): EdDSA {
|
|
|
661
842
|
* but allows to speed-up subsequent getPublicKey() calls up to 20x.
|
|
662
843
|
* @param windowSize 2, 4, 8, 16
|
|
663
844
|
*/
|
|
664
|
-
precompute(windowSize = 8, point:
|
|
845
|
+
precompute(windowSize = 8, point: EdwardsPoint = Point.BASE): EdwardsPoint {
|
|
665
846
|
return point.precompute(windowSize, false);
|
|
666
847
|
},
|
|
667
848
|
};
|
|
668
849
|
|
|
669
|
-
|
|
850
|
+
function keygen(seed?: Uint8Array) {
|
|
851
|
+
const secretKey = utils.randomSecretKey(seed);
|
|
852
|
+
return { secretKey, publicKey: getPublicKey(secretKey) };
|
|
853
|
+
}
|
|
854
|
+
|
|
855
|
+
function isValidSecretKey(key: Uint8Array): boolean {
|
|
856
|
+
try {
|
|
857
|
+
return !!Fn.fromBytes(key, false);
|
|
858
|
+
} catch (error) {
|
|
859
|
+
return false;
|
|
860
|
+
}
|
|
861
|
+
}
|
|
862
|
+
|
|
863
|
+
function isValidPublicKey(key: Uint8Array, zip215?: boolean): boolean {
|
|
864
|
+
try {
|
|
865
|
+
return !!Point.fromBytes(key, zip215);
|
|
866
|
+
} catch (error) {
|
|
867
|
+
return false;
|
|
868
|
+
}
|
|
869
|
+
}
|
|
870
|
+
|
|
871
|
+
return Object.freeze({
|
|
872
|
+
keygen,
|
|
873
|
+
getPublicKey,
|
|
874
|
+
sign,
|
|
875
|
+
verify,
|
|
876
|
+
utils,
|
|
877
|
+
Point,
|
|
878
|
+
info: { type: 'edwards' as const, lengths },
|
|
879
|
+
});
|
|
670
880
|
}
|
|
671
881
|
|
|
882
|
+
// TODO: remove
|
|
672
883
|
export type EdComposed = {
|
|
673
884
|
CURVE: EdwardsOpts;
|
|
674
885
|
curveOpts: EdwardsExtraOpts;
|
|
886
|
+
hash: FHash;
|
|
675
887
|
eddsaOpts: EdDSAOpts;
|
|
676
888
|
};
|
|
889
|
+
// TODO: remove
|
|
677
890
|
function _eddsa_legacy_opts_to_new(c: CurveTypeWithLength): EdComposed {
|
|
678
891
|
const CURVE: EdwardsOpts = {
|
|
679
892
|
a: c.a,
|
|
@@ -688,23 +901,23 @@ function _eddsa_legacy_opts_to_new(c: CurveTypeWithLength): EdComposed {
|
|
|
688
901
|
const Fn = Field(CURVE.n, c.nBitLength, true);
|
|
689
902
|
const curveOpts: EdwardsExtraOpts = { Fp, Fn, uvRatio: c.uvRatio };
|
|
690
903
|
const eddsaOpts: EdDSAOpts = {
|
|
691
|
-
hash: c.hash,
|
|
692
904
|
randomBytes: c.randomBytes,
|
|
693
905
|
adjustScalarBytes: c.adjustScalarBytes,
|
|
694
906
|
domain: c.domain,
|
|
695
907
|
prehash: c.prehash,
|
|
696
908
|
mapToCurve: c.mapToCurve,
|
|
697
909
|
};
|
|
698
|
-
return { CURVE, curveOpts, eddsaOpts };
|
|
910
|
+
return { CURVE, curveOpts, hash: c.hash, eddsaOpts };
|
|
699
911
|
}
|
|
912
|
+
// TODO: remove
|
|
700
913
|
function _eddsa_new_output_to_legacy(c: CurveTypeWithLength, eddsa: EdDSA): CurveFn {
|
|
701
914
|
const legacy = Object.assign({}, eddsa, { ExtendedPoint: eddsa.Point, CURVE: c });
|
|
702
915
|
return legacy;
|
|
703
916
|
}
|
|
704
917
|
// TODO: remove. Use eddsa
|
|
705
918
|
export function twistedEdwards(c: CurveTypeWithLength): CurveFn {
|
|
706
|
-
const { CURVE, curveOpts, eddsaOpts } = _eddsa_legacy_opts_to_new(c);
|
|
919
|
+
const { CURVE, curveOpts, hash, eddsaOpts } = _eddsa_legacy_opts_to_new(c);
|
|
707
920
|
const Point = edwards(CURVE, curveOpts);
|
|
708
|
-
const EDDSA = eddsa(Point, eddsaOpts);
|
|
921
|
+
const EDDSA = eddsa(Point, hash, eddsaOpts);
|
|
709
922
|
return _eddsa_new_output_to_legacy(c, EDDSA);
|
|
710
923
|
}
|