@noble/curves 0.5.0 → 0.5.1
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 +61 -10
- package/lib/abstract/hash-to-curve.d.ts +10 -1
- package/lib/abstract/hash-to-curve.js +32 -10
- package/lib/abstract/modular.d.ts +8 -17
- package/lib/abstract/modular.js +131 -152
- package/lib/abstract/utils.d.ts +3 -1
- package/lib/bls12-381.d.ts +1 -1
- package/lib/bls12-381.js +1 -1
- package/lib/ed25519.js +70 -7
- package/lib/ed448.js +84 -1
- package/lib/esm/abstract/hash-to-curve.js +30 -9
- package/lib/esm/abstract/modular.js +125 -148
- package/lib/esm/bls12-381.js +1 -1
- package/lib/esm/ed25519.js +71 -8
- package/lib/esm/ed448.js +85 -2
- package/lib/esm/p256.js +1 -1
- package/lib/esm/p384.js +1 -1
- package/lib/esm/p521.js +1 -1
- package/lib/esm/secp256k1.js +5 -2
- package/lib/esm/stark.js +2 -0
- package/lib/p256.js +1 -1
- package/lib/p384.js +1 -1
- package/lib/p521.js +1 -1
- package/lib/secp256k1.js +5 -2
- package/lib/stark.d.ts +1 -1
- package/lib/stark.js +2 -0
- package/package.json +1 -1
package/lib/ed25519.js
CHANGED
|
@@ -81,7 +81,74 @@ exports.ED25519_TORSION_SUBGROUP = [
|
|
|
81
81
|
'0000000000000000000000000000000000000000000000000000000000000000',
|
|
82
82
|
'c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa',
|
|
83
83
|
];
|
|
84
|
-
const Fp = (0, modular_js_1.Fp)(ED25519_P);
|
|
84
|
+
const Fp = (0, modular_js_1.Fp)(ED25519_P, undefined, true);
|
|
85
|
+
// Hash To Curve Elligator2 Map (NOTE: different from ristretto255 elligator)
|
|
86
|
+
// NOTE: very important part is usage of FpSqrtEven for ELL2_C1_EDWARDS, since
|
|
87
|
+
// SageMath returns different root first and everything falls apart
|
|
88
|
+
const ELL2_C1 = (Fp.ORDER + BigInt(3)) / BigInt(8); // 1. c1 = (q + 3) / 8 # Integer arithmetic
|
|
89
|
+
const ELL2_C2 = Fp.pow(_2n, ELL2_C1); // 2. c2 = 2^c1
|
|
90
|
+
const ELL2_C3 = Fp.sqrt(Fp.negate(Fp.ONE)); // 3. c3 = sqrt(-1)
|
|
91
|
+
const ELL2_C4 = (Fp.ORDER - BigInt(5)) / BigInt(8); // 4. c4 = (q - 5) / 8 # Integer arithmetic
|
|
92
|
+
const ELL2_J = BigInt(486662);
|
|
93
|
+
// prettier-ignore
|
|
94
|
+
function map_to_curve_elligator2_curve25519(u) {
|
|
95
|
+
let tv1 = Fp.square(u); // 1. tv1 = u^2
|
|
96
|
+
tv1 = Fp.mul(tv1, _2n); // 2. tv1 = 2 * tv1
|
|
97
|
+
let xd = Fp.add(tv1, Fp.ONE); // 3. xd = tv1 + 1 # Nonzero: -1 is square (mod p), tv1 is not
|
|
98
|
+
let x1n = Fp.negate(ELL2_J); // 4. x1n = -J # x1 = x1n / xd = -J / (1 + 2 * u^2)
|
|
99
|
+
let tv2 = Fp.square(xd); // 5. tv2 = xd^2
|
|
100
|
+
let gxd = Fp.mul(tv2, xd); // 6. gxd = tv2 * xd # gxd = xd^3
|
|
101
|
+
let gx1 = Fp.mul(tv1, ELL2_J); // 7. gx1 = J * tv1 # x1n + J * xd
|
|
102
|
+
gx1 = Fp.mul(gx1, x1n); // 8. gx1 = gx1 * x1n # x1n^2 + J * x1n * xd
|
|
103
|
+
gx1 = Fp.add(gx1, tv2); // 9. gx1 = gx1 + tv2 # x1n^2 + J * x1n * xd + xd^2
|
|
104
|
+
gx1 = Fp.mul(gx1, x1n); // 10. gx1 = gx1 * x1n # x1n^3 + J * x1n^2 * xd + x1n * xd^2
|
|
105
|
+
let tv3 = Fp.square(gxd); // 11. tv3 = gxd^2
|
|
106
|
+
tv2 = Fp.square(tv3); // 12. tv2 = tv3^2 # gxd^4
|
|
107
|
+
tv3 = Fp.mul(tv3, gxd); // 13. tv3 = tv3 * gxd # gxd^3
|
|
108
|
+
tv3 = Fp.mul(tv3, gx1); // 14. tv3 = tv3 * gx1 # gx1 * gxd^3
|
|
109
|
+
tv2 = Fp.mul(tv2, tv3); // 15. tv2 = tv2 * tv3 # gx1 * gxd^7
|
|
110
|
+
let y11 = Fp.pow(tv2, ELL2_C4); // 16. y11 = tv2^c4 # (gx1 * gxd^7)^((p - 5) / 8)
|
|
111
|
+
y11 = Fp.mul(y11, tv3); // 17. y11 = y11 * tv3 # gx1*gxd^3*(gx1*gxd^7)^((p-5)/8)
|
|
112
|
+
let y12 = Fp.mul(y11, ELL2_C3); // 18. y12 = y11 * c3
|
|
113
|
+
tv2 = Fp.square(y11); // 19. tv2 = y11^2
|
|
114
|
+
tv2 = Fp.mul(tv2, gxd); // 20. tv2 = tv2 * gxd
|
|
115
|
+
let e1 = Fp.equals(tv2, gx1); // 21. e1 = tv2 == gx1
|
|
116
|
+
let y1 = Fp.cmov(y12, y11, e1); // 22. y1 = CMOV(y12, y11, e1) # If g(x1) is square, this is its sqrt
|
|
117
|
+
let x2n = Fp.mul(x1n, tv1); // 23. x2n = x1n * tv1 # x2 = x2n / xd = 2 * u^2 * x1n / xd
|
|
118
|
+
let y21 = Fp.mul(y11, u); // 24. y21 = y11 * u
|
|
119
|
+
y21 = Fp.mul(y21, ELL2_C2); // 25. y21 = y21 * c2
|
|
120
|
+
let y22 = Fp.mul(y21, ELL2_C3); // 26. y22 = y21 * c3
|
|
121
|
+
let gx2 = Fp.mul(gx1, tv1); // 27. gx2 = gx1 * tv1 # g(x2) = gx2 / gxd = 2 * u^2 * g(x1)
|
|
122
|
+
tv2 = Fp.square(y21); // 28. tv2 = y21^2
|
|
123
|
+
tv2 = Fp.mul(tv2, gxd); // 29. tv2 = tv2 * gxd
|
|
124
|
+
let e2 = Fp.equals(tv2, gx2); // 30. e2 = tv2 == gx2
|
|
125
|
+
let y2 = Fp.cmov(y22, y21, e2); // 31. y2 = CMOV(y22, y21, e2) # If g(x2) is square, this is its sqrt
|
|
126
|
+
tv2 = Fp.square(y1); // 32. tv2 = y1^2
|
|
127
|
+
tv2 = Fp.mul(tv2, gxd); // 33. tv2 = tv2 * gxd
|
|
128
|
+
let e3 = Fp.equals(tv2, gx1); // 34. e3 = tv2 == gx1
|
|
129
|
+
let xn = Fp.cmov(x2n, x1n, e3); // 35. xn = CMOV(x2n, x1n, e3) # If e3, x = x1, else x = x2
|
|
130
|
+
let y = Fp.cmov(y2, y1, e3); // 36. y = CMOV(y2, y1, e3) # If e3, y = y1, else y = y2
|
|
131
|
+
let e4 = Fp.isOdd(y); // 37. e4 = sgn0(y) == 1 # Fix sign of y
|
|
132
|
+
y = Fp.cmov(y, Fp.negate(y), e3 !== e4); // 38. y = CMOV(y, -y, e3 XOR e4)
|
|
133
|
+
return { xMn: xn, xMd: xd, yMn: y, yMd: 1n }; // 39. return (xn, xd, y, 1)
|
|
134
|
+
}
|
|
135
|
+
const ELL2_C1_EDWARDS = (0, modular_js_1.FpSqrtEven)(Fp, Fp.negate(BigInt(486664))); // sgn0(c1) MUST equal 0
|
|
136
|
+
function map_to_curve_elligator2_edwards25519(u) {
|
|
137
|
+
const { xMn, xMd, yMn, yMd } = map_to_curve_elligator2_curve25519(u); // 1. (xMn, xMd, yMn, yMd) = map_to_curve_elligator2_curve25519(u)
|
|
138
|
+
let xn = Fp.mul(xMn, yMd); // 2. xn = xMn * yMd
|
|
139
|
+
xn = Fp.mul(xn, ELL2_C1_EDWARDS); // 3. xn = xn * c1
|
|
140
|
+
let xd = Fp.mul(xMd, yMn); // 4. xd = xMd * yMn # xn / xd = c1 * xM / yM
|
|
141
|
+
let yn = Fp.sub(xMn, xMd); // 5. yn = xMn - xMd
|
|
142
|
+
let yd = Fp.add(xMn, xMd); // 6. yd = xMn + xMd # (n / d - 1) / (n / d + 1) = (n - d) / (n + d)
|
|
143
|
+
let tv1 = Fp.mul(xd, yd); // 7. tv1 = xd * yd
|
|
144
|
+
let e = Fp.equals(tv1, Fp.ZERO); // 8. e = tv1 == 0
|
|
145
|
+
xn = Fp.cmov(xn, Fp.ZERO, e); // 9. xn = CMOV(xn, 0, e)
|
|
146
|
+
xd = Fp.cmov(xd, Fp.ONE, e); // 10. xd = CMOV(xd, 1, e)
|
|
147
|
+
yn = Fp.cmov(yn, Fp.ONE, e); // 11. yn = CMOV(yn, 1, e)
|
|
148
|
+
yd = Fp.cmov(yd, Fp.ONE, e); // 12. yd = CMOV(yd, 1, e)
|
|
149
|
+
const inv = Fp.invertBatch([xd, yd]); // batch division
|
|
150
|
+
return { x: Fp.mul(xn, inv[0]), y: Fp.mul(yn, inv[1]) }; // 13. return (xn, xd, yn, yd)
|
|
151
|
+
}
|
|
85
152
|
const ED25519_DEF = {
|
|
86
153
|
// Param: a
|
|
87
154
|
a: BigInt(-1),
|
|
@@ -110,14 +177,10 @@ const ED25519_DEF = {
|
|
|
110
177
|
p: Fp.ORDER,
|
|
111
178
|
m: 1,
|
|
112
179
|
k: 128,
|
|
113
|
-
expand:
|
|
180
|
+
expand: 'xmd',
|
|
114
181
|
hash: sha512_1.sha512,
|
|
115
182
|
},
|
|
116
|
-
mapToCurve: (scalars) =>
|
|
117
|
-
throw new Error('Not supported yet');
|
|
118
|
-
// const { x, y } = calcElligatorRistrettoMap(scalars[0]).toAffine();
|
|
119
|
-
// return { x, y };
|
|
120
|
-
},
|
|
183
|
+
mapToCurve: (scalars) => map_to_curve_elligator2_edwards25519(scalars[0]),
|
|
121
184
|
};
|
|
122
185
|
exports.ed25519 = (0, edwards_js_1.twistedEdwards)(ED25519_DEF);
|
|
123
186
|
function ed25519_domain(data, ctx, phflag) {
|
package/lib/ed448.js
CHANGED
|
@@ -48,13 +48,87 @@ function adjustScalarBytes(bytes) {
|
|
|
48
48
|
bytes[56] = 0; // Byte outside of group (456 buts vs 448 bits)
|
|
49
49
|
return bytes;
|
|
50
50
|
}
|
|
51
|
+
const Fp = (0, modular_js_1.Fp)(ed448P, 456, true);
|
|
52
|
+
// Hash To Curve Elligator2 Map
|
|
53
|
+
const ELL2_C1 = (Fp.ORDER - BigInt(3)) / BigInt(4); // 1. c1 = (q - 3) / 4 # Integer arithmetic
|
|
54
|
+
const ELL2_J = BigInt(156326);
|
|
55
|
+
function map_to_curve_elligator2_curve448(u) {
|
|
56
|
+
let tv1 = Fp.square(u); // 1. tv1 = u^2
|
|
57
|
+
let e1 = Fp.equals(tv1, Fp.ONE); // 2. e1 = tv1 == 1
|
|
58
|
+
tv1 = Fp.cmov(tv1, Fp.ZERO, e1); // 3. tv1 = CMOV(tv1, 0, e1) # If Z * u^2 == -1, set tv1 = 0
|
|
59
|
+
let xd = Fp.sub(Fp.ONE, tv1); // 4. xd = 1 - tv1
|
|
60
|
+
let x1n = Fp.negate(ELL2_J); // 5. x1n = -J
|
|
61
|
+
let tv2 = Fp.square(xd); // 6. tv2 = xd^2
|
|
62
|
+
let gxd = Fp.mul(tv2, xd); // 7. gxd = tv2 * xd # gxd = xd^3
|
|
63
|
+
let gx1 = Fp.mul(tv1, Fp.negate(ELL2_J)); // 8. gx1 = -J * tv1 # x1n + J * xd
|
|
64
|
+
gx1 = Fp.mul(gx1, x1n); // 9. gx1 = gx1 * x1n # x1n^2 + J * x1n * xd
|
|
65
|
+
gx1 = Fp.add(gx1, tv2); // 10. gx1 = gx1 + tv2 # x1n^2 + J * x1n * xd + xd^2
|
|
66
|
+
gx1 = Fp.mul(gx1, x1n); // 11. gx1 = gx1 * x1n # x1n^3 + J * x1n^2 * xd + x1n * xd^2
|
|
67
|
+
let tv3 = Fp.square(gxd); // 12. tv3 = gxd^2
|
|
68
|
+
tv2 = Fp.mul(gx1, gxd); // 13. tv2 = gx1 * gxd # gx1 * gxd
|
|
69
|
+
tv3 = Fp.mul(tv3, tv2); // 14. tv3 = tv3 * tv2 # gx1 * gxd^3
|
|
70
|
+
let y1 = Fp.pow(tv3, ELL2_C1); // 15. y1 = tv3^c1 # (gx1 * gxd^3)^((p - 3) / 4)
|
|
71
|
+
y1 = Fp.mul(y1, tv2); // 16. y1 = y1 * tv2 # gx1 * gxd * (gx1 * gxd^3)^((p - 3) / 4)
|
|
72
|
+
let x2n = Fp.mul(x1n, Fp.negate(tv1)); // 17. x2n = -tv1 * x1n # x2 = x2n / xd = -1 * u^2 * x1n / xd
|
|
73
|
+
let y2 = Fp.mul(y1, u); // 18. y2 = y1 * u
|
|
74
|
+
y2 = Fp.cmov(y2, Fp.ZERO, e1); // 19. y2 = CMOV(y2, 0, e1)
|
|
75
|
+
tv2 = Fp.square(y1); // 20. tv2 = y1^2
|
|
76
|
+
tv2 = Fp.mul(tv2, gxd); // 21. tv2 = tv2 * gxd
|
|
77
|
+
let e2 = Fp.equals(tv2, gx1); // 22. e2 = tv2 == gx1
|
|
78
|
+
let xn = Fp.cmov(x2n, x1n, e2); // 23. xn = CMOV(x2n, x1n, e2) # If e2, x = x1, else x = x2
|
|
79
|
+
let y = Fp.cmov(y2, y1, e2); // 24. y = CMOV(y2, y1, e2) # If e2, y = y1, else y = y2
|
|
80
|
+
let e3 = Fp.isOdd(y); // 25. e3 = sgn0(y) == 1 # Fix sign of y
|
|
81
|
+
y = Fp.cmov(y, Fp.negate(y), e2 !== e3); // 26. y = CMOV(y, -y, e2 XOR e3)
|
|
82
|
+
return { xn, xd, yn: y, yd: Fp.ONE }; // 27. return (xn, xd, y, 1)
|
|
83
|
+
}
|
|
84
|
+
function map_to_curve_elligator2_edwards448(u) {
|
|
85
|
+
let { xn, xd, yn, yd } = map_to_curve_elligator2_curve448(u); // 1. (xn, xd, yn, yd) = map_to_curve_elligator2_curve448(u)
|
|
86
|
+
let xn2 = Fp.square(xn); // 2. xn2 = xn^2
|
|
87
|
+
let xd2 = Fp.square(xd); // 3. xd2 = xd^2
|
|
88
|
+
let xd4 = Fp.square(xd2); // 4. xd4 = xd2^2
|
|
89
|
+
let yn2 = Fp.square(yn); // 5. yn2 = yn^2
|
|
90
|
+
let yd2 = Fp.square(yd); // 6. yd2 = yd^2
|
|
91
|
+
let xEn = Fp.sub(xn2, xd2); // 7. xEn = xn2 - xd2
|
|
92
|
+
let tv2 = Fp.sub(xEn, xd2); // 8. tv2 = xEn - xd2
|
|
93
|
+
xEn = Fp.mul(xEn, xd2); // 9. xEn = xEn * xd2
|
|
94
|
+
xEn = Fp.mul(xEn, yd); // 10. xEn = xEn * yd
|
|
95
|
+
xEn = Fp.mul(xEn, yn); // 11. xEn = xEn * yn
|
|
96
|
+
xEn = Fp.mul(xEn, 4n); // 12. xEn = xEn * 4
|
|
97
|
+
tv2 = Fp.mul(tv2, xn2); // 13. tv2 = tv2 * xn2
|
|
98
|
+
tv2 = Fp.mul(tv2, yd2); // 14. tv2 = tv2 * yd2
|
|
99
|
+
let tv3 = Fp.mul(yn2, 4n); // 15. tv3 = 4 * yn2
|
|
100
|
+
let tv1 = Fp.add(tv3, yd2); // 16. tv1 = tv3 + yd2
|
|
101
|
+
tv1 = Fp.mul(tv1, xd4); // 17. tv1 = tv1 * xd4
|
|
102
|
+
let xEd = Fp.add(tv1, tv2); // 18. xEd = tv1 + tv2
|
|
103
|
+
tv2 = Fp.mul(tv2, xn); // 19. tv2 = tv2 * xn
|
|
104
|
+
let tv4 = Fp.mul(xn, xd4); // 20. tv4 = xn * xd4
|
|
105
|
+
let yEn = Fp.sub(tv3, yd2); // 21. yEn = tv3 - yd2
|
|
106
|
+
yEn = Fp.mul(yEn, tv4); // 22. yEn = yEn * tv4
|
|
107
|
+
yEn = Fp.sub(yEn, tv2); // 23. yEn = yEn - tv2
|
|
108
|
+
tv1 = Fp.add(xn2, xd2); // 24. tv1 = xn2 + xd2
|
|
109
|
+
tv1 = Fp.mul(tv1, xd2); // 25. tv1 = tv1 * xd2
|
|
110
|
+
tv1 = Fp.mul(tv1, xd); // 26. tv1 = tv1 * xd
|
|
111
|
+
tv1 = Fp.mul(tv1, yn2); // 27. tv1 = tv1 * yn2
|
|
112
|
+
tv1 = Fp.mul(tv1, BigInt(-2)); // 28. tv1 = -2 * tv1
|
|
113
|
+
let yEd = Fp.add(tv2, tv1); // 29. yEd = tv2 + tv1
|
|
114
|
+
tv4 = Fp.mul(tv4, yd2); // 30. tv4 = tv4 * yd2
|
|
115
|
+
yEd = Fp.add(yEd, tv4); // 31. yEd = yEd + tv4
|
|
116
|
+
tv1 = Fp.mul(xEd, yEd); // 32. tv1 = xEd * yEd
|
|
117
|
+
let e = Fp.equals(tv1, Fp.ZERO); // 33. e = tv1 == 0
|
|
118
|
+
xEn = Fp.cmov(xEn, Fp.ZERO, e); // 34. xEn = CMOV(xEn, 0, e)
|
|
119
|
+
xEd = Fp.cmov(xEd, Fp.ONE, e); // 35. xEd = CMOV(xEd, 1, e)
|
|
120
|
+
yEn = Fp.cmov(yEn, Fp.ONE, e); // 36. yEn = CMOV(yEn, 1, e)
|
|
121
|
+
yEd = Fp.cmov(yEd, Fp.ONE, e); // 37. yEd = CMOV(yEd, 1, e)
|
|
122
|
+
const inv = Fp.invertBatch([xEd, yEd]); // batch division
|
|
123
|
+
return { x: Fp.mul(xEn, inv[0]), y: Fp.mul(yEn, inv[1]) }; // 38. return (xEn, xEd, yEn, yEd)
|
|
124
|
+
}
|
|
51
125
|
const ED448_DEF = {
|
|
52
126
|
// Param: a
|
|
53
127
|
a: BigInt(1),
|
|
54
128
|
// -39081. Negative number is P - number
|
|
55
129
|
d: BigInt('726838724295606890549323807888004534353641360687318060281490199180612328166730772686396383698676545930088884461843637361053498018326358'),
|
|
56
130
|
// Finite field 𝔽p over which we'll do calculations; 2n ** 448n - 2n ** 224n - 1n
|
|
57
|
-
Fp
|
|
131
|
+
Fp,
|
|
58
132
|
// Subgroup order: how many points ed448 has; 2n**446n - 13818066809895115352007386748515426880336692474882178609894547503885n
|
|
59
133
|
n: BigInt('181709681073901722637330951972001133588410340171829515070372549795146003961539585716195755291692375963310293709091662304773755859649779'),
|
|
60
134
|
nBitLength: 456,
|
|
@@ -94,6 +168,15 @@ const ED448_DEF = {
|
|
|
94
168
|
// square root exists, and the decoding fails.
|
|
95
169
|
return { isValid: (0, modular_js_1.mod)(x2 * v, P) === u, value: x };
|
|
96
170
|
},
|
|
171
|
+
htfDefaults: {
|
|
172
|
+
DST: 'edwards448_XOF:SHAKE256_ELL2_RO_',
|
|
173
|
+
p: Fp.ORDER,
|
|
174
|
+
m: 1,
|
|
175
|
+
k: 224,
|
|
176
|
+
expand: 'xof',
|
|
177
|
+
hash: sha3_1.shake256,
|
|
178
|
+
},
|
|
179
|
+
mapToCurve: (scalars) => map_to_curve_elligator2_edwards448(scalars[0]),
|
|
97
180
|
};
|
|
98
181
|
exports.ed448 = (0, edwards_js_1.twistedEdwards)(ED448_DEF);
|
|
99
182
|
// NOTE: there is no ed448ctx, since ed448 supports ctx by default
|
|
@@ -10,7 +10,7 @@ export function validateHTFOpts(opts) {
|
|
|
10
10
|
throw new Error('Invalid htf/m');
|
|
11
11
|
if (typeof opts.k !== 'number')
|
|
12
12
|
throw new Error('Invalid htf/k');
|
|
13
|
-
if (
|
|
13
|
+
if (opts.expand !== 'xmd' && opts.expand !== 'xof' && opts.expand !== undefined)
|
|
14
14
|
throw new Error('Invalid htf/expand');
|
|
15
15
|
if (typeof opts.hash !== 'function' || !Number.isSafeInteger(opts.hash.outputLen))
|
|
16
16
|
throw new Error('Invalid htf/hash function');
|
|
@@ -75,13 +75,31 @@ export function expand_message_xmd(msg, DST, lenInBytes, H) {
|
|
|
75
75
|
const pseudo_random_bytes = concatBytes(...b);
|
|
76
76
|
return pseudo_random_bytes.slice(0, lenInBytes);
|
|
77
77
|
}
|
|
78
|
-
|
|
79
|
-
// https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-
|
|
80
|
-
//
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
78
|
+
export function expand_message_xof(msg, DST, lenInBytes, k, H) {
|
|
79
|
+
// https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-16#section-5.3.3
|
|
80
|
+
// DST = H('H2C-OVERSIZE-DST-' || a_very_long_DST, Math.ceil((lenInBytes * k) / 8));
|
|
81
|
+
if (DST.length > 255) {
|
|
82
|
+
const dkLen = Math.ceil((2 * k) / 8);
|
|
83
|
+
DST = H.create({ dkLen }).update(stringToBytes('H2C-OVERSIZE-DST-')).update(DST).digest();
|
|
84
|
+
}
|
|
85
|
+
if (lenInBytes > 65535 || DST.length > 255)
|
|
86
|
+
throw new Error('expand_message_xof: invalid lenInBytes');
|
|
87
|
+
return (H.create({ dkLen: lenInBytes })
|
|
88
|
+
.update(msg)
|
|
89
|
+
.update(i2osp(lenInBytes, 2))
|
|
90
|
+
// 2. DST_prime = DST || I2OSP(len(DST), 1)
|
|
91
|
+
.update(DST)
|
|
92
|
+
.update(i2osp(DST.length, 1))
|
|
93
|
+
.digest());
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Hashes arbitrary-length byte strings to a list of one or more elements of a finite field F
|
|
97
|
+
* https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-11#section-5.3
|
|
98
|
+
* @param msg a byte string containing the message to hash
|
|
99
|
+
* @param count the number of elements of F to output
|
|
100
|
+
* @param options `{DST: string, p: bigint, m: number, k: number, expand: 'xmd' | 'xof', hash: H}`
|
|
101
|
+
* @returns [u_0, ..., u_(count - 1)], a list of field elements.
|
|
102
|
+
*/
|
|
85
103
|
export function hash_to_field(msg, count, options) {
|
|
86
104
|
// if options is provided but incomplete, fill any missing fields with the
|
|
87
105
|
// value in hftDefaults (ie hash to G2).
|
|
@@ -90,9 +108,12 @@ export function hash_to_field(msg, count, options) {
|
|
|
90
108
|
const len_in_bytes = count * options.m * L;
|
|
91
109
|
const DST = stringToBytes(options.DST);
|
|
92
110
|
let pseudo_random_bytes = msg;
|
|
93
|
-
if (options.expand) {
|
|
111
|
+
if (options.expand === 'xmd') {
|
|
94
112
|
pseudo_random_bytes = expand_message_xmd(msg, DST, len_in_bytes, options.hash);
|
|
95
113
|
}
|
|
114
|
+
else if (options.expand === 'xof') {
|
|
115
|
+
pseudo_random_bytes = expand_message_xof(msg, DST, len_in_bytes, options.k, options.hash);
|
|
116
|
+
}
|
|
96
117
|
const u = new Array(count);
|
|
97
118
|
for (let i = 0; i < count; i++) {
|
|
98
119
|
const e = new Array(options.m);
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
|
|
2
|
+
// TODO: remove circular imports
|
|
2
3
|
import * as utils from './utils.js';
|
|
3
4
|
// Utilities for modular arithmetics and finite fields
|
|
4
5
|
// prettier-ignore
|
|
5
6
|
const _0n = BigInt(0), _1n = BigInt(1), _2n = BigInt(2), _3n = BigInt(3);
|
|
6
7
|
// prettier-ignore
|
|
7
|
-
const _4n = BigInt(4), _5n = BigInt(5),
|
|
8
|
+
const _4n = BigInt(4), _5n = BigInt(5), _8n = BigInt(8);
|
|
8
9
|
// prettier-ignore
|
|
9
10
|
const _9n = BigInt(9), _16n = BigInt(16);
|
|
10
11
|
// Calculates a modulo b
|
|
@@ -66,25 +67,66 @@ export function invert(number, modulo) {
|
|
|
66
67
|
throw new Error('invert: does not exist');
|
|
67
68
|
return mod(x, modulo);
|
|
68
69
|
}
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
70
|
+
// Tonelli-Shanks algorithm
|
|
71
|
+
// https://eprint.iacr.org/2012/685.pdf (page 12)
|
|
72
|
+
export function tonelliShanks(P) {
|
|
73
|
+
// Legendre constant: used to calculate Legendre symbol (a | p),
|
|
74
|
+
// which denotes the value of a^((p-1)/2) (mod p).
|
|
75
|
+
// (a | p) ≡ 1 if a is a square (mod p)
|
|
76
|
+
// (a | p) ≡ -1 if a is not a square (mod p)
|
|
77
|
+
// (a | p) ≡ 0 if a ≡ 0 (mod p)
|
|
78
|
+
const legendreC = (P - _1n) / _2n;
|
|
79
|
+
let Q, S, Z;
|
|
80
|
+
// Step 1: By factoring out powers of 2 from p - 1,
|
|
81
|
+
// find q and s such that p - 1 = q2s with q odd
|
|
82
|
+
for (Q = P - _1n, S = 0; Q % _2n === _0n; Q /= _2n, S++)
|
|
83
|
+
;
|
|
84
|
+
// Step 2: Select a non-square z such that (z | p) ≡ -1 and set c ≡ zq
|
|
85
|
+
for (Z = _2n; Z < P && pow(Z, legendreC, P) !== P - _1n; Z++)
|
|
86
|
+
;
|
|
87
|
+
// Fast-path
|
|
88
|
+
if (S === 1) {
|
|
89
|
+
const p1div4 = (P + _1n) / _4n;
|
|
90
|
+
return function tonelliFast(Fp, n) {
|
|
91
|
+
const root = Fp.pow(n, p1div4);
|
|
92
|
+
if (!Fp.equals(Fp.square(root), n))
|
|
93
|
+
throw new Error('Cannot find square root');
|
|
94
|
+
return root;
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
// Slow-path
|
|
98
|
+
const Q1div2 = (Q + _1n) / _2n;
|
|
99
|
+
return function tonelliSlow(Fp, n) {
|
|
100
|
+
// Step 0: Check that n is indeed a square: (n | p) must be ≡ 1
|
|
101
|
+
if (Fp.pow(n, legendreC) !== Fp.ONE)
|
|
102
|
+
throw new Error('Cannot find square root');
|
|
103
|
+
let s = S;
|
|
104
|
+
let c = pow(Z, Q, P);
|
|
105
|
+
let r = Fp.pow(n, Q1div2);
|
|
106
|
+
let t = Fp.pow(n, Q);
|
|
107
|
+
let t2 = Fp.ZERO;
|
|
108
|
+
while (!Fp.equals(Fp.sub(t, Fp.ONE), Fp.ZERO)) {
|
|
109
|
+
t2 = Fp.square(t);
|
|
110
|
+
let i;
|
|
111
|
+
for (i = 1; i < s; i++) {
|
|
112
|
+
// stop if t2-1 == 0
|
|
113
|
+
if (Fp.equals(Fp.sub(t2, Fp.ONE), Fp.ZERO))
|
|
114
|
+
break;
|
|
115
|
+
// t2 *= t2
|
|
116
|
+
t2 = Fp.square(t2);
|
|
117
|
+
}
|
|
118
|
+
let b = pow(c, BigInt(1 << (s - i - 1)), P);
|
|
119
|
+
r = Fp.mul(r, b);
|
|
120
|
+
c = mod(b * b, P);
|
|
121
|
+
t = Fp.mul(t, c);
|
|
122
|
+
s = i;
|
|
123
|
+
}
|
|
124
|
+
return r;
|
|
125
|
+
};
|
|
77
126
|
}
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
*/
|
|
82
|
-
// TODO: rewrite as generic Fp function && remove bls versions
|
|
83
|
-
export function sqrt(number, modulo) {
|
|
84
|
-
// prettier-ignore
|
|
85
|
-
const n = number;
|
|
86
|
-
const P = modulo;
|
|
87
|
-
const p1div4 = (P + _1n) / _4n;
|
|
127
|
+
export function FpSqrt(P) {
|
|
128
|
+
// NOTE: different algorithms can give different roots, it is up to user to decide which one they want.
|
|
129
|
+
// For example there is FpSqrtOdd/FpSqrtEven to choice root based on oddness (used for hash-to-curve).
|
|
88
130
|
// P ≡ 3 (mod 4)
|
|
89
131
|
// √n = n^((P+1)/4)
|
|
90
132
|
if (P % _4n === _3n) {
|
|
@@ -92,50 +134,53 @@ export function sqrt(number, modulo) {
|
|
|
92
134
|
// const ORDER =
|
|
93
135
|
// 0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaabn;
|
|
94
136
|
// const NUM = 72057594037927816n;
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
137
|
+
const p1div4 = (P + _1n) / _4n;
|
|
138
|
+
return function sqrt3mod4(Fp, n) {
|
|
139
|
+
const root = Fp.pow(n, p1div4);
|
|
140
|
+
// Throw if root**2 != n
|
|
141
|
+
if (!Fp.equals(Fp.square(root), n))
|
|
142
|
+
throw new Error('Cannot find square root');
|
|
143
|
+
return root;
|
|
144
|
+
};
|
|
100
145
|
}
|
|
101
|
-
//
|
|
146
|
+
// Atkin algorithm for q ≡ 5 (mod 8), https://eprint.iacr.org/2012/685.pdf (page 10)
|
|
102
147
|
if (P % _8n === _5n) {
|
|
103
|
-
const
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
148
|
+
const c1 = (P - _5n) / _8n;
|
|
149
|
+
return function sqrt5mod8(Fp, n) {
|
|
150
|
+
const n2 = Fp.mul(n, _2n);
|
|
151
|
+
const v = Fp.pow(n2, c1);
|
|
152
|
+
const nv = Fp.mul(n, v);
|
|
153
|
+
const i = Fp.mul(Fp.mul(nv, _2n), v);
|
|
154
|
+
const root = Fp.mul(nv, Fp.sub(i, Fp.ONE));
|
|
155
|
+
if (!Fp.equals(Fp.square(root), n))
|
|
156
|
+
throw new Error('Cannot find square root');
|
|
157
|
+
return root;
|
|
158
|
+
};
|
|
109
159
|
}
|
|
110
|
-
//
|
|
111
|
-
if (
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
;
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
}
|
|
132
|
-
let b = pow(c, BigInt(1 << (s - i - 1)), P);
|
|
133
|
-
r = mod(r * b, P);
|
|
134
|
-
c = mod(b * b, P);
|
|
135
|
-
t = mod(t * c, P);
|
|
136
|
-
s = i;
|
|
160
|
+
// P ≡ 9 (mod 16)
|
|
161
|
+
if (P % _16n === _9n) {
|
|
162
|
+
// NOTE: tonelli is too slow for bls-Fp2 calculations even on start
|
|
163
|
+
// Means we cannot use sqrt for constants at all!
|
|
164
|
+
//
|
|
165
|
+
// const c1 = Fp.sqrt(Fp.negate(Fp.ONE)); // 1. c1 = sqrt(-1) in F, i.e., (c1^2) == -1 in F
|
|
166
|
+
// const c2 = Fp.sqrt(c1); // 2. c2 = sqrt(c1) in F, i.e., (c2^2) == c1 in F
|
|
167
|
+
// const c3 = Fp.sqrt(Fp.negate(c1)); // 3. c3 = sqrt(-c1) in F, i.e., (c3^2) == -c1 in F
|
|
168
|
+
// const c4 = (P + _7n) / _16n; // 4. c4 = (q + 7) / 16 # Integer arithmetic
|
|
169
|
+
// sqrt = (x) => {
|
|
170
|
+
// let tv1 = Fp.pow(x, c4); // 1. tv1 = x^c4
|
|
171
|
+
// let tv2 = Fp.mul(c1, tv1); // 2. tv2 = c1 * tv1
|
|
172
|
+
// const tv3 = Fp.mul(c2, tv1); // 3. tv3 = c2 * tv1
|
|
173
|
+
// let tv4 = Fp.mul(c3, tv1); // 4. tv4 = c3 * tv1
|
|
174
|
+
// const e1 = Fp.equals(Fp.square(tv2), x); // 5. e1 = (tv2^2) == x
|
|
175
|
+
// const e2 = Fp.equals(Fp.square(tv3), x); // 6. e2 = (tv3^2) == x
|
|
176
|
+
// tv1 = Fp.cmov(tv1, tv2, e1); // 7. tv1 = CMOV(tv1, tv2, e1) # Select tv2 if (tv2^2) == x
|
|
177
|
+
// tv2 = Fp.cmov(tv4, tv3, e2); // 8. tv2 = CMOV(tv4, tv3, e2) # Select tv3 if (tv3^2) == x
|
|
178
|
+
// const e3 = Fp.equals(Fp.square(tv2), x); // 9. e3 = (tv2^2) == x
|
|
179
|
+
// return Fp.cmov(tv1, tv2, e3); // 10. z = CMOV(tv1, tv2, e3) # Select the sqrt from tv1 and tv2
|
|
180
|
+
// }
|
|
137
181
|
}
|
|
138
|
-
|
|
182
|
+
// Other cases: Tonelli-Shanks algorithm
|
|
183
|
+
return tonelliShanks(P);
|
|
139
184
|
}
|
|
140
185
|
// Little-endian check for first LE bit (last BE bit);
|
|
141
186
|
export const isNegativeLE = (num, modulo) => (mod(num, modulo) & _1n) === _1n;
|
|
@@ -202,17 +247,21 @@ export function FpInvertBatch(f, nums) {
|
|
|
202
247
|
export function FpDiv(f, lhs, rhs) {
|
|
203
248
|
return f.mul(lhs, typeof rhs === 'bigint' ? invert(rhs, f.ORDER) : f.invert(rhs));
|
|
204
249
|
}
|
|
205
|
-
//
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
250
|
+
// This function returns True whenever the value x is a square in the field F.
|
|
251
|
+
export function FpIsSquare(f) {
|
|
252
|
+
const legendreConst = (f.ORDER - _1n) / _2n; // Integer arithmetic
|
|
253
|
+
return (x) => {
|
|
254
|
+
const p = f.pow(x, legendreConst);
|
|
255
|
+
return f.equals(p, f.ZERO) || f.equals(p, f.ONE);
|
|
256
|
+
};
|
|
257
|
+
}
|
|
209
258
|
export function Fp(ORDER, bitLen, isLE = false, redef = {}) {
|
|
210
259
|
if (ORDER <= _0n)
|
|
211
260
|
throw new Error(`Expected Fp ORDER > 0, got ${ORDER}`);
|
|
212
261
|
const { nBitLength: BITS, nByteLength: BYTES } = utils.nLength(ORDER, bitLen);
|
|
213
262
|
if (BYTES > 2048)
|
|
214
263
|
throw new Error('Field lengths over 2048 bytes are not supported');
|
|
215
|
-
const sqrtP = (
|
|
264
|
+
const sqrtP = FpSqrt(ORDER);
|
|
216
265
|
const f = Object.freeze({
|
|
217
266
|
ORDER,
|
|
218
267
|
BITS,
|
|
@@ -242,7 +291,7 @@ export function Fp(ORDER, bitLen, isLE = false, redef = {}) {
|
|
|
242
291
|
subN: (lhs, rhs) => lhs - rhs,
|
|
243
292
|
mulN: (lhs, rhs) => lhs * rhs,
|
|
244
293
|
invert: (num) => invert(num, ORDER),
|
|
245
|
-
sqrt: redef.sqrt || sqrtP,
|
|
294
|
+
sqrt: redef.sqrt || ((n) => sqrtP(f, n)),
|
|
246
295
|
invertBatch: (lst) => FpInvertBatch(f, lst),
|
|
247
296
|
// TODO: do we really need constant cmov?
|
|
248
297
|
// We don't have const-time bigints anyway, so probably will be not very useful
|
|
@@ -256,87 +305,15 @@ export function Fp(ORDER, bitLen, isLE = false, redef = {}) {
|
|
|
256
305
|
});
|
|
257
306
|
return Object.freeze(f);
|
|
258
307
|
}
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
const p = Fp.pow(x, squareConst);
|
|
271
|
-
return Fp.equals(p, Fp.ZERO) || Fp.equals(p, Fp.ONE);
|
|
272
|
-
};
|
|
273
|
-
// Constant-time Tonelli-Shanks algorithm
|
|
274
|
-
let l = _0n;
|
|
275
|
-
for (let o = q - _1n; o % _2n === _0n; o /= _2n)
|
|
276
|
-
l += _1n;
|
|
277
|
-
const c1 = l; // 1. c1, the largest integer such that 2^c1 divides q - 1.
|
|
278
|
-
const c2 = (q - _1n) / _2n ** c1; // 2. c2 = (q - 1) / (2^c1) # Integer arithmetic
|
|
279
|
-
const c3 = (c2 - _1n) / _2n; // 3. c3 = (c2 - 1) / 2 # Integer arithmetic
|
|
280
|
-
// 4. c4, a non-square value in F
|
|
281
|
-
// 5. c5 = c4^c2 in F
|
|
282
|
-
let c4 = Fp.ONE;
|
|
283
|
-
while (isSquare(c4))
|
|
284
|
-
c4 = Fp.add(c4, Fp.ONE);
|
|
285
|
-
const c5 = Fp.pow(c4, c2);
|
|
286
|
-
let sqrt = (x) => {
|
|
287
|
-
let z = Fp.pow(x, c3); // 1. z = x^c3
|
|
288
|
-
let t = Fp.square(z); // 2. t = z * z
|
|
289
|
-
t = Fp.mul(t, x); // 3. t = t * x
|
|
290
|
-
z = Fp.mul(z, x); // 4. z = z * x
|
|
291
|
-
let b = t; // 5. b = t
|
|
292
|
-
let c = c5; // 6. c = c5
|
|
293
|
-
// 7. for i in (c1, c1 - 1, ..., 2):
|
|
294
|
-
for (let i = c1; i > 1; i--) {
|
|
295
|
-
// 8. for j in (1, 2, ..., i - 2):
|
|
296
|
-
// 9. b = b * b
|
|
297
|
-
for (let j = _1n; j < i - _1n; i++)
|
|
298
|
-
b = Fp.square(b);
|
|
299
|
-
const e = Fp.equals(b, Fp.ONE); // 10. e = b == 1
|
|
300
|
-
const zt = Fp.mul(z, c); // 11. zt = z * c
|
|
301
|
-
z = Fp.cmov(zt, z, e); // 12. z = CMOV(zt, z, e)
|
|
302
|
-
c = Fp.square(c); // 13. c = c * c
|
|
303
|
-
let tt = Fp.mul(t, c); // 14. tt = t * c
|
|
304
|
-
t = Fp.cmov(tt, t, e); // 15. t = CMOV(tt, t, e)
|
|
305
|
-
b = t; // 16. b = t
|
|
306
|
-
}
|
|
307
|
-
return z; // 17. return z
|
|
308
|
-
};
|
|
309
|
-
if (q % _4n === _3n) {
|
|
310
|
-
const c1 = (q + _1n) / _4n; // 1. c1 = (q + 1) / 4 # Integer arithmetic
|
|
311
|
-
sqrt = (x) => Fp.pow(x, c1);
|
|
312
|
-
}
|
|
313
|
-
else if (q % _8n === _5n) {
|
|
314
|
-
const c1 = Fp.sqrt(Fp.negate(Fp.ONE)); // 1. c1 = sqrt(-1) in F, i.e., (c1^2) == -1 in F
|
|
315
|
-
const c2 = (q + _3n) / _8n; // 2. c2 = (q + 3) / 8 # Integer arithmetic
|
|
316
|
-
sqrt = (x) => {
|
|
317
|
-
let tv1 = Fp.pow(x, c2); // 1. tv1 = x^c2
|
|
318
|
-
let tv2 = Fp.mul(tv1, c1); // 2. tv2 = tv1 * c1
|
|
319
|
-
let e = Fp.equals(Fp.square(tv1), x); // 3. e = (tv1^2) == x
|
|
320
|
-
return Fp.cmov(tv2, tv1, e); // 4. z = CMOV(tv2, tv1, e)
|
|
321
|
-
};
|
|
322
|
-
}
|
|
323
|
-
else if (Fp.ORDER % _16n === _9n) {
|
|
324
|
-
const c1 = Fp.sqrt(Fp.negate(Fp.ONE)); // 1. c1 = sqrt(-1) in F, i.e., (c1^2) == -1 in F
|
|
325
|
-
const c2 = Fp.sqrt(c1); // 2. c2 = sqrt(c1) in F, i.e., (c2^2) == c1 in F
|
|
326
|
-
const c3 = Fp.sqrt(Fp.negate(c1)); // 3. c3 = sqrt(-c1) in F, i.e., (c3^2) == -c1 in F
|
|
327
|
-
const c4 = (Fp.ORDER + _7n) / _16n; // 4. c4 = (q + 7) / 16 # Integer arithmetic
|
|
328
|
-
sqrt = (x) => {
|
|
329
|
-
let tv1 = Fp.pow(x, c4); // 1. tv1 = x^c4
|
|
330
|
-
let tv2 = Fp.mul(c1, tv1); // 2. tv2 = c1 * tv1
|
|
331
|
-
const tv3 = Fp.mul(c2, tv1); // 3. tv3 = c2 * tv1
|
|
332
|
-
let tv4 = Fp.mul(c3, tv1); // 4. tv4 = c3 * tv1
|
|
333
|
-
const e1 = Fp.equals(Fp.square(tv2), x); // 5. e1 = (tv2^2) == x
|
|
334
|
-
const e2 = Fp.equals(Fp.square(tv3), x); // 6. e2 = (tv3^2) == x
|
|
335
|
-
tv1 = Fp.cmov(tv1, tv2, e1); // 7. tv1 = CMOV(tv1, tv2, e1) # Select tv2 if (tv2^2) == x
|
|
336
|
-
tv2 = Fp.cmov(tv4, tv3, e2); // 8. tv2 = CMOV(tv4, tv3, e2) # Select tv3 if (tv3^2) == x
|
|
337
|
-
const e3 = Fp.equals(Fp.square(tv2), x); // 9. e3 = (tv2^2) == x
|
|
338
|
-
return Fp.cmov(tv1, tv2, e3); // 10. z = CMOV(tv1, tv2, e3) # Select the sqrt from tv1 and tv2
|
|
339
|
-
};
|
|
340
|
-
}
|
|
341
|
-
return { sqrt, isSquare };
|
|
308
|
+
export function FpSqrtOdd(Fp, elm) {
|
|
309
|
+
if (!Fp.isOdd)
|
|
310
|
+
throw new Error(`Field doesn't have isOdd`);
|
|
311
|
+
const root = Fp.sqrt(elm);
|
|
312
|
+
return Fp.isOdd(root) ? root : Fp.negate(root);
|
|
313
|
+
}
|
|
314
|
+
export function FpSqrtEven(Fp, elm) {
|
|
315
|
+
if (!Fp.isOdd)
|
|
316
|
+
throw new Error(`Field doesn't have isOdd`);
|
|
317
|
+
const root = Fp.sqrt(elm);
|
|
318
|
+
return Fp.isOdd(root) ? Fp.negate(root) : root;
|
|
342
319
|
}
|
package/lib/esm/bls12-381.js
CHANGED
|
@@ -815,7 +815,7 @@ const htfDefaults = {
|
|
|
815
815
|
k: 128,
|
|
816
816
|
// option to use a message that has already been processed by
|
|
817
817
|
// expand_message_xmd
|
|
818
|
-
expand:
|
|
818
|
+
expand: 'xmd',
|
|
819
819
|
// Hash functions for: expand_message_xmd is appropriate for use with a
|
|
820
820
|
// wide range of hash functions, including SHA-2, SHA-3, BLAKE2, and others.
|
|
821
821
|
// BBS+ uses blake2: https://github.com/hyperledger/aries-framework-go/issues/2247
|