UNPKG

7 kBJavaScriptView Raw
1/* eslint-disable camelcase, one-var */
2const { crypto_verify_32 } = require('./crypto_verify')
3const { crypto_hash } = require('./crypto_hash')
4const {
5 gf, gf0, gf1, D, D2,
6 X, Y, I, A, Z, M, S,
7 sel25519, pack25519,
8 inv25519, unpack25519
9} = require('./internal/ed25519')
10const { randombytes } = require('./randombytes')
11
12const crypto_sign_BYTES = 64
13const crypto_sign_PUBLICKEYBYTES = 32
14const crypto_sign_SECRETKEYBYTES = 64
15const crypto_sign_SEEDBYTES = 32
16
17module.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
30function set25519 (r, a) {
31 for (let i = 0; i < 16; i++) r[i] = a[i] | 0
32}
33
34function 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
45function 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
71function cswap (p, q, b) {
72 var i
73 for (i = 0; i < 4; i++) {
74 sel25519(p[i], q[i], b)
75 }
76}
77
78function 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
87function 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
102function 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
111function 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
132function 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
138var 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
140function 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
165function 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// Note: difference from C - smlen returned, not passed as argument.
173function 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
213function 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
219function 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/* eslint-disable no-unused-vars */
258function 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 // throw new Error('crypto_sign_open failed')
290 }
291
292 for (i = 0; i < n; i++) msg[i] = sm[i + 64]
293 mlen = n
294 return true
295}
296/* eslint-enable no-unused-vars */
297
298function 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
307function par25519 (a) {
308 var d = new Uint8Array(32)
309 pack25519(d, a)
310 return d[0] & 1
311}
312
313function 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
320function check (buf, len) {
321 if (!buf || (len && buf.length < len)) throw new Error('Argument must be a buffer' + (len ? ' of length ' + len : ''))
322}