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