1 |
|
2 | const { crypto_verify_32 } = require('./crypto_verify')
|
3 | const { crypto_hash } = require('./crypto_hash')
|
4 | const {
|
5 | gf, gf0, gf1, D, D2,
|
6 | X, Y, I, A, Z, M, S,
|
7 | sel25519, pack25519,
|
8 | inv25519, unpack25519
|
9 | } = require('./internal/ed25519')
|
10 | const { randombytes } = require('./randombytes')
|
11 |
|
12 | const crypto_sign_BYTES = 64
|
13 | const crypto_sign_PUBLICKEYBYTES = 32
|
14 | const crypto_sign_SECRETKEYBYTES = 64
|
15 | const crypto_sign_SEEDBYTES = 32
|
16 |
|
17 | module.exports = {
|
18 | crypto_sign_keypair,
|
19 | crypto_sign_seed_keypair,
|
20 | crypto_sign,
|
21 | crypto_sign_detached,
|
22 | crypto_sign_open,
|
23 | crypto_sign_verify_detached,
|
24 | crypto_sign_BYTES,
|
25 | crypto_sign_PUBLICKEYBYTES,
|
26 | crypto_sign_SECRETKEYBYTES,
|
27 | crypto_sign_SEEDBYTES
|
28 | }
|
29 |
|
30 | function set25519 (r, a) {
|
31 | for (let i = 0; i < 16; i++) r[i] = a[i] | 0
|
32 | }
|
33 |
|
34 | function pow2523 (o, i) {
|
35 | var c = gf()
|
36 | var a
|
37 | for (a = 0; a < 16; a++) c[a] = i[a]
|
38 | for (a = 250; a >= 0; a--) {
|
39 | S(c, c)
|
40 | if (a !== 1) M(c, c, i)
|
41 | }
|
42 | for (a = 0; a < 16; a++) o[a] = c[a]
|
43 | }
|
44 |
|
45 | function add (p, q) {
|
46 | var a = gf(), b = gf(), c = gf(),
|
47 | d = gf(), e = gf(), f = gf(),
|
48 | g = gf(), h = gf(), t = gf()
|
49 |
|
50 | Z(a, p[1], p[0])
|
51 | Z(t, q[1], q[0])
|
52 | M(a, a, t)
|
53 | A(b, p[0], p[1])
|
54 | A(t, q[0], q[1])
|
55 | M(b, b, t)
|
56 | M(c, p[3], q[3])
|
57 | M(c, c, D2)
|
58 | M(d, p[2], q[2])
|
59 | A(d, d, d)
|
60 | Z(e, b, a)
|
61 | Z(f, d, c)
|
62 | A(g, d, c)
|
63 | A(h, b, a)
|
64 |
|
65 | M(p[0], e, f)
|
66 | M(p[1], h, g)
|
67 | M(p[2], g, f)
|
68 | M(p[3], e, h)
|
69 | }
|
70 |
|
71 | function cswap (p, q, b) {
|
72 | var i
|
73 | for (i = 0; i < 4; i++) {
|
74 | sel25519(p[i], q[i], b)
|
75 | }
|
76 | }
|
77 |
|
78 | function pack (r, p) {
|
79 | var tx = gf(), ty = gf(), zi = gf()
|
80 | inv25519(zi, p[2])
|
81 | M(tx, p[0], zi)
|
82 | M(ty, p[1], zi)
|
83 | pack25519(r, ty)
|
84 | r[31] ^= par25519(tx) << 7
|
85 | }
|
86 |
|
87 | function scalarmult (p, q, s) {
|
88 | var b, i
|
89 | set25519(p[0], gf0)
|
90 | set25519(p[1], gf1)
|
91 | set25519(p[2], gf1)
|
92 | set25519(p[3], gf0)
|
93 | for (i = 255; i >= 0; --i) {
|
94 | b = (s[(i / 8) | 0] >> (i & 7)) & 1
|
95 | cswap(p, q, b)
|
96 | add(q, p)
|
97 | add(p, p)
|
98 | cswap(p, q, b)
|
99 | }
|
100 | }
|
101 |
|
102 | function scalarbase (p, s) {
|
103 | var q = [gf(), gf(), gf(), gf()]
|
104 | set25519(q[0], X)
|
105 | set25519(q[1], Y)
|
106 | set25519(q[2], gf1)
|
107 | M(q[3], X, Y)
|
108 | scalarmult(p, q, s)
|
109 | }
|
110 |
|
111 | function crypto_sign_keypair (pk, sk, seeded) {
|
112 | check(pk, crypto_sign_PUBLICKEYBYTES)
|
113 | check(sk, crypto_sign_SECRETKEYBYTES)
|
114 |
|
115 | var d = new Uint8Array(64)
|
116 | var p = [gf(), gf(), gf(), gf()]
|
117 | var i
|
118 |
|
119 | if (!seeded) randombytes(sk, 32)
|
120 | crypto_hash(d, sk, 32)
|
121 | d[0] &= 248
|
122 | d[31] &= 127
|
123 | d[31] |= 64
|
124 |
|
125 | scalarbase(p, d)
|
126 | pack(pk, p)
|
127 |
|
128 | for (i = 0; i < 32; i++) sk[i + 32] = pk[i]
|
129 | return 0
|
130 | }
|
131 |
|
132 | function crypto_sign_seed_keypair (pk, sk, seed) {
|
133 | check(seed, crypto_sign_SEEDBYTES)
|
134 | sk.set(seed)
|
135 | return crypto_sign_keypair(pk, sk, true)
|
136 | }
|
137 |
|
138 | var L = new Float64Array([0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10])
|
139 |
|
140 | function modL (r, x) {
|
141 | var carry, i, j, k
|
142 | for (i = 63; i >= 32; --i) {
|
143 | carry = 0
|
144 | for (j = i - 32, k = i - 12; j < k; ++j) {
|
145 | x[j] += carry - 16 * x[i] * L[j - (i - 32)]
|
146 | carry = (x[j] + 128) >> 8
|
147 | x[j] -= carry * 256
|
148 | }
|
149 | x[j] += carry
|
150 | x[i] = 0
|
151 | }
|
152 | carry = 0
|
153 | for (j = 0; j < 32; j++) {
|
154 | x[j] += carry - (x[31] >> 4) * L[j]
|
155 | carry = x[j] >> 8
|
156 | x[j] &= 255
|
157 | }
|
158 | for (j = 0; j < 32; j++) x[j] -= carry * L[j]
|
159 | for (i = 0; i < 32; i++) {
|
160 | x[i + 1] += x[i] >> 8
|
161 | r[i] = x[i] & 255
|
162 | }
|
163 | }
|
164 |
|
165 | function reduce (r) {
|
166 | var x = new Float64Array(64)
|
167 | for (let i = 0; i < 64; i++) x[i] = r[i]
|
168 | for (let i = 0; i < 64; i++) r[i] = 0
|
169 | modL(r, x)
|
170 | }
|
171 |
|
172 |
|
173 | function crypto_sign (sm, m, sk) {
|
174 | check(sm, crypto_sign_BYTES + m.length)
|
175 | check(m, 0)
|
176 | check(sk, crypto_sign_SECRETKEYBYTES)
|
177 | var n = m.length
|
178 |
|
179 | var d = new Uint8Array(64), h = new Uint8Array(64), r = new Uint8Array(64)
|
180 | var i, j, x = new Float64Array(64)
|
181 | var p = [gf(), gf(), gf(), gf()]
|
182 |
|
183 | crypto_hash(d, sk, 32)
|
184 | d[0] &= 248
|
185 | d[31] &= 127
|
186 | d[31] |= 64
|
187 |
|
188 | var smlen = n + 64
|
189 | for (i = 0; i < n; i++) sm[64 + i] = m[i]
|
190 | for (i = 0; i < 32; i++) sm[32 + i] = d[32 + i]
|
191 |
|
192 | crypto_hash(r, sm.subarray(32), n + 32)
|
193 | reduce(r)
|
194 | scalarbase(p, r)
|
195 | pack(sm, p)
|
196 |
|
197 | for (i = 32; i < 64; i++) sm[i] = sk[i]
|
198 | crypto_hash(h, sm, n + 64)
|
199 | reduce(h)
|
200 |
|
201 | for (i = 0; i < 64; i++) x[i] = 0
|
202 | for (i = 0; i < 32; i++) x[i] = r[i]
|
203 | for (i = 0; i < 32; i++) {
|
204 | for (j = 0; j < 32; j++) {
|
205 | x[i + j] += h[i] * d[j]
|
206 | }
|
207 | }
|
208 |
|
209 | modL(sm.subarray(32), x)
|
210 | return smlen
|
211 | }
|
212 |
|
213 | function crypto_sign_detached (sig, m, sk) {
|
214 | var sm = new Uint8Array(m.length + crypto_sign_BYTES)
|
215 | crypto_sign(sm, m, sk)
|
216 | for (let i = 0; i < crypto_sign_BYTES; i++) sig[i] = sm[i]
|
217 | }
|
218 |
|
219 | function unpackneg (r, p) {
|
220 | var t = gf(), chk = gf(), num = gf(),
|
221 | den = gf(), den2 = gf(), den4 = gf(),
|
222 | den6 = gf()
|
223 |
|
224 | set25519(r[2], gf1)
|
225 | unpack25519(r[1], p)
|
226 | S(num, r[1])
|
227 | M(den, num, D)
|
228 | Z(num, num, r[2])
|
229 | A(den, r[2], den)
|
230 |
|
231 | S(den2, den)
|
232 | S(den4, den2)
|
233 | M(den6, den4, den2)
|
234 | M(t, den6, num)
|
235 | M(t, t, den)
|
236 |
|
237 | pow2523(t, t)
|
238 | M(t, t, num)
|
239 | M(t, t, den)
|
240 | M(t, t, den)
|
241 | M(r[0], t, den)
|
242 |
|
243 | S(chk, r[0])
|
244 | M(chk, chk, den)
|
245 | if (neq25519(chk, num)) M(r[0], r[0], I)
|
246 |
|
247 | S(chk, r[0])
|
248 | M(chk, chk, den)
|
249 | if (neq25519(chk, num)) return -1
|
250 |
|
251 | if (par25519(r[0]) === (p[31] >> 7)) Z(r[0], gf0, r[0])
|
252 |
|
253 | M(r[3], r[0], r[1])
|
254 | return 0
|
255 | }
|
256 |
|
257 |
|
258 | function crypto_sign_open (msg, sm, pk) {
|
259 | check(msg, sm.length - crypto_sign_BYTES)
|
260 | check(sm, crypto_sign_BYTES)
|
261 | check(pk, crypto_sign_PUBLICKEYBYTES)
|
262 | var n = sm.length
|
263 | var m = new Uint8Array(sm.length)
|
264 |
|
265 | var i, mlen
|
266 | var t = new Uint8Array(32), h = new Uint8Array(64)
|
267 | var p = [gf(), gf(), gf(), gf()],
|
268 | q = [gf(), gf(), gf(), gf()]
|
269 |
|
270 | mlen = -1
|
271 | if (n < 64) return false
|
272 |
|
273 | if (unpackneg(q, pk)) return false
|
274 |
|
275 | for (i = 0; i < n; i++) m[i] = sm[i]
|
276 | for (i = 0; i < 32; i++) m[i + 32] = pk[i]
|
277 | crypto_hash(h, m, n)
|
278 | reduce(h)
|
279 | scalarmult(p, q, h)
|
280 |
|
281 | scalarbase(q, sm.subarray(32))
|
282 | add(p, q)
|
283 | pack(t, p)
|
284 |
|
285 | n -= 64
|
286 | if (crypto_verify_32(sm, 0, t, 0)) {
|
287 | for (i = 0; i < n; i++) m[i] = 0
|
288 | return false
|
289 |
|
290 | }
|
291 |
|
292 | for (i = 0; i < n; i++) msg[i] = sm[i + 64]
|
293 | mlen = n
|
294 | return true
|
295 | }
|
296 |
|
297 |
|
298 | function crypto_sign_verify_detached (sig, m, pk) {
|
299 | check(sig, crypto_sign_BYTES)
|
300 | var sm = new Uint8Array(m.length + crypto_sign_BYTES)
|
301 | var i = 0
|
302 | for (i = 0; i < crypto_sign_BYTES; i++) sm[i] = sig[i]
|
303 | for (i = 0; i < m.length; i++) sm[i + crypto_sign_BYTES] = m[i]
|
304 | return crypto_sign_open(m, sm, pk)
|
305 | }
|
306 |
|
307 | function par25519 (a) {
|
308 | var d = new Uint8Array(32)
|
309 | pack25519(d, a)
|
310 | return d[0] & 1
|
311 | }
|
312 |
|
313 | function neq25519 (a, b) {
|
314 | var c = new Uint8Array(32), d = new Uint8Array(32)
|
315 | pack25519(c, a)
|
316 | pack25519(d, b)
|
317 | return crypto_verify_32(c, 0, d, 0)
|
318 | }
|
319 |
|
320 | function check (buf, len) {
|
321 | if (!buf || (len && buf.length < len)) throw new Error('Argument must be a buffer' + (len ? ' of length ' + len : ''))
|
322 | }
|