Initial commit
[yaffs-website] / node_modules / jodid25519 / lib / core.js
1 "use strict";
2 /**
3  * @fileOverview
4  * Core operations on curve 25519 required for the higher level modules.
5  */
6
7 /*
8  * Copyright (c) 2007, 2013, 2014 Michele Bini
9  * Copyright (c) 2014 Mega Limited
10  * under the MIT License.
11  *
12  * Authors: Guy K. Kloss, Michele Bini
13  *
14  * You should have received a copy of the license along with this program.
15  */
16
17 var crypto = require('crypto');
18
19     /**
20      * @exports jodid25519/core
21      * Core operations on curve 25519 required for the higher level modules.
22      *
23      * @description
24      * Core operations on curve 25519 required for the higher level modules.
25      *
26      * <p>
27      * This core code is extracted from Michele Bini's curve255.js implementation,
28      * which is used as a base for Curve25519 ECDH and Ed25519 EdDSA operations.
29      * </p>
30      */
31     var ns = {};
32
33     function _setbit(n, c, v) {
34         var i = c >> 4;
35         var a = n[i];
36         a = a + (1 << (c & 0xf)) * v;
37         n[i] = a;
38     }
39
40     function _getbit(n, c) {
41         return (n[c >> 4] >> (c & 0xf)) & 1;
42     }
43
44     function _ZERO() {
45         return [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
46     }
47
48     function _ONE() {
49         return [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
50     }
51
52     // Basepoint.
53     function _BASE() {
54         return [9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
55     }
56
57     // return -1, 0, +1 when a is less than, equal, or greater than b
58     function _bigintcmp(a, b) {
59         // The following code is a bit tricky to avoid code branching
60         var c, abs_r, mask;
61         var r = 0;
62         for (c = 15; c >= 0; c--) {
63             var x = a[c];
64             var y = b[c];
65             r = r + (x - y) * (1 - r * r);
66             // http://graphics.stanford.edu/~seander/bithacks.html#IntegerAbs
67             // correct for [-294967295, 294967295]
68             mask = r >> 31;
69             abs_r = (r + mask) ^ mask;
70             // http://stackoverflow.com/questions/596467/how-do-i-convert-a-number-to-an-integer-in-javascript
71             // this rounds towards zero
72             r = ~~((r << 1) / (abs_r + 1));
73         }
74         return r;
75     }
76
77     function _bigintadd(a, b) {
78         var r = [];
79         var v;
80         r[0] = (v = a[0] + b[0]) & 0xffff;
81         r[1] = (v = (v >>> 16) + a[1] + b[1]) & 0xffff;
82         r[2] = (v = (v >>> 16) + a[2] + b[2]) & 0xffff;
83         r[3] = (v = (v >>> 16) + a[3] + b[3]) & 0xffff;
84         r[4] = (v = (v >>> 16) + a[4] + b[4]) & 0xffff;
85         r[5] = (v = (v >>> 16) + a[5] + b[5]) & 0xffff;
86         r[6] = (v = (v >>> 16) + a[6] + b[6]) & 0xffff;
87         r[7] = (v = (v >>> 16) + a[7] + b[7]) & 0xffff;
88         r[8] = (v = (v >>> 16) + a[8] + b[8]) & 0xffff;
89         r[9] = (v = (v >>> 16) + a[9] + b[9]) & 0xffff;
90         r[10] = (v = (v >>> 16) + a[10] + b[10]) & 0xffff;
91         r[11] = (v = (v >>> 16) + a[11] + b[11]) & 0xffff;
92         r[12] = (v = (v >>> 16) + a[12] + b[12]) & 0xffff;
93         r[13] = (v = (v >>> 16) + a[13] + b[13]) & 0xffff;
94         r[14] = (v = (v >>> 16) + a[14] + b[14]) & 0xffff;
95         r[15] = (v >>> 16) + a[15] + b[15];
96         return r;
97     }
98
99     function _bigintsub(a, b) {
100         var r = [];
101         var v;
102         r[0] = (v = 0x80000 + a[0] - b[0]) & 0xffff;
103         r[1] = (v = (v >>> 16) + 0x7fff8 + a[1] - b[1]) & 0xffff;
104         r[2] = (v = (v >>> 16) + 0x7fff8 + a[2] - b[2]) & 0xffff;
105         r[3] = (v = (v >>> 16) + 0x7fff8 + a[3] - b[3]) & 0xffff;
106         r[4] = (v = (v >>> 16) + 0x7fff8 + a[4] - b[4]) & 0xffff;
107         r[5] = (v = (v >>> 16) + 0x7fff8 + a[5] - b[5]) & 0xffff;
108         r[6] = (v = (v >>> 16) + 0x7fff8 + a[6] - b[6]) & 0xffff;
109         r[7] = (v = (v >>> 16) + 0x7fff8 + a[7] - b[7]) & 0xffff;
110         r[8] = (v = (v >>> 16) + 0x7fff8 + a[8] - b[8]) & 0xffff;
111         r[9] = (v = (v >>> 16) + 0x7fff8 + a[9] - b[9]) & 0xffff;
112         r[10] = (v = (v >>> 16) + 0x7fff8 + a[10] - b[10]) & 0xffff;
113         r[11] = (v = (v >>> 16) + 0x7fff8 + a[11] - b[11]) & 0xffff;
114         r[12] = (v = (v >>> 16) + 0x7fff8 + a[12] - b[12]) & 0xffff;
115         r[13] = (v = (v >>> 16) + 0x7fff8 + a[13] - b[13]) & 0xffff;
116         r[14] = (v = (v >>> 16) + 0x7fff8 + a[14] - b[14]) & 0xffff;
117         r[15] = (v >>> 16) - 8 + a[15] - b[15];
118         return r;
119     }
120
121     function _sqr8h(a7, a6, a5, a4, a3, a2, a1, a0) {
122         // 'division by 0x10000' can not be replaced by '>> 16' because
123         // more than 32 bits of precision are needed similarly
124         // 'multiplication by 2' cannot be replaced by '<< 1'
125         var r = [];
126         var v;
127         r[0] = (v = a0 * a0) & 0xffff;
128         r[1] = (v = (0 | (v / 0x10000)) + 2 * a0 * a1) & 0xffff;
129         r[2] = (v = (0 | (v / 0x10000)) + 2 * a0 * a2 + a1 * a1) & 0xffff;
130         r[3] = (v = (0 | (v / 0x10000)) + 2 * a0 * a3 + 2 * a1 * a2) & 0xffff;
131         r[4] = (v = (0 | (v / 0x10000)) + 2 * a0 * a4 + 2 * a1 * a3 + a2
132                     * a2) & 0xffff;
133         r[5] = (v = (0 | (v / 0x10000)) + 2 * a0 * a5 + 2 * a1 * a4 + 2
134                     * a2 * a3) & 0xffff;
135         r[6] = (v = (0 | (v / 0x10000)) + 2 * a0 * a6 + 2 * a1 * a5 + 2
136                     * a2 * a4 + a3 * a3) & 0xffff;
137         r[7] = (v = (0 | (v / 0x10000)) + 2 * a0 * a7 + 2 * a1 * a6 + 2
138                     * a2 * a5 + 2 * a3 * a4) & 0xffff;
139         r[8] = (v = (0 | (v / 0x10000)) + 2 * a1 * a7 + 2 * a2 * a6 + 2
140                     * a3 * a5 + a4 * a4) & 0xffff;
141         r[9] = (v = (0 | (v / 0x10000)) + 2 * a2 * a7 + 2 * a3 * a6 + 2
142                     * a4 * a5) & 0xffff;
143         r[10] = (v = (0 | (v / 0x10000)) + 2 * a3 * a7 + 2 * a4 * a6
144                      + a5 * a5) & 0xffff;
145         r[11] = (v = (0 | (v / 0x10000)) + 2 * a4 * a7 + 2 * a5 * a6) & 0xffff;
146         r[12] = (v = (0 | (v / 0x10000)) + 2 * a5 * a7 + a6 * a6) & 0xffff;
147         r[13] = (v = (0 | (v / 0x10000)) + 2 * a6 * a7) & 0xffff;
148         r[14] = (v = (0 | (v / 0x10000)) + a7 * a7) & 0xffff;
149         r[15] = 0 | (v / 0x10000);
150         return r;
151     }
152
153     function _sqrmodp(a) {
154         var x = _sqr8h(a[15], a[14], a[13], a[12], a[11], a[10], a[9],
155                        a[8]);
156         var z = _sqr8h(a[7], a[6], a[5], a[4], a[3], a[2], a[1], a[0]);
157         var y = _sqr8h(a[15] + a[7], a[14] + a[6], a[13] + a[5], a[12]
158                                                                  + a[4],
159                        a[11] + a[3], a[10] + a[2], a[9] + a[1], a[8]
160                                                                 + a[0]);
161         var r = [];
162         var v;
163         r[0] = (v = 0x800000 + z[0] + (y[8] - x[8] - z[8] + x[0] - 0x80)
164                     * 38) & 0xffff;
165         r[1] = (v = 0x7fff80 + (v >>> 16) + z[1]
166                     + (y[9] - x[9] - z[9] + x[1]) * 38) & 0xffff;
167         r[2] = (v = 0x7fff80 + (v >>> 16) + z[2]
168                     + (y[10] - x[10] - z[10] + x[2]) * 38) & 0xffff;
169         r[3] = (v = 0x7fff80 + (v >>> 16) + z[3]
170                     + (y[11] - x[11] - z[11] + x[3]) * 38) & 0xffff;
171         r[4] = (v = 0x7fff80 + (v >>> 16) + z[4]
172                     + (y[12] - x[12] - z[12] + x[4]) * 38) & 0xffff;
173         r[5] = (v = 0x7fff80 + (v >>> 16) + z[5]
174                     + (y[13] - x[13] - z[13] + x[5]) * 38) & 0xffff;
175         r[6] = (v = 0x7fff80 + (v >>> 16) + z[6]
176                     + (y[14] - x[14] - z[14] + x[6]) * 38) & 0xffff;
177         r[7] = (v = 0x7fff80 + (v >>> 16) + z[7]
178                     + (y[15] - x[15] - z[15] + x[7]) * 38) & 0xffff;
179         r[8] = (v = 0x7fff80 + (v >>> 16) + z[8] + y[0] - x[0] - z[0]
180                     + x[8] * 38) & 0xffff;
181         r[9] = (v = 0x7fff80 + (v >>> 16) + z[9] + y[1] - x[1] - z[1]
182                     + x[9] * 38) & 0xffff;
183         r[10] = (v = 0x7fff80 + (v >>> 16) + z[10] + y[2] - x[2] - z[2]
184                      + x[10] * 38) & 0xffff;
185         r[11] = (v = 0x7fff80 + (v >>> 16) + z[11] + y[3] - x[3] - z[3]
186                      + x[11] * 38) & 0xffff;
187         r[12] = (v = 0x7fff80 + (v >>> 16) + z[12] + y[4] - x[4] - z[4]
188                      + x[12] * 38) & 0xffff;
189         r[13] = (v = 0x7fff80 + (v >>> 16) + z[13] + y[5] - x[5] - z[5]
190                      + x[13] * 38) & 0xffff;
191         r[14] = (v = 0x7fff80 + (v >>> 16) + z[14] + y[6] - x[6] - z[6]
192                      + x[14] * 38) & 0xffff;
193         r[15] = 0x7fff80 + (v >>> 16) + z[15] + y[7] - x[7] - z[7]
194                 + x[15] * 38;
195         _reduce(r);
196         return r;
197     }
198
199     function _mul8h(a7, a6, a5, a4, a3, a2, a1, a0, b7, b6, b5, b4, b3,
200                     b2, b1, b0) {
201         // 'division by 0x10000' can not be replaced by '>> 16' because
202         // more than 32 bits of precision are needed
203         var r = [];
204         var v;
205         r[0] = (v = a0 * b0) & 0xffff;
206         r[1] = (v = (0 | (v / 0x10000)) + a0 * b1 + a1 * b0) & 0xffff;
207         r[2] = (v = (0 | (v / 0x10000)) + a0 * b2 + a1 * b1 + a2 * b0) & 0xffff;
208         r[3] = (v = (0 | (v / 0x10000)) + a0 * b3 + a1 * b2 + a2 * b1
209                     + a3 * b0) & 0xffff;
210         r[4] = (v = (0 | (v / 0x10000)) + a0 * b4 + a1 * b3 + a2 * b2
211                     + a3 * b1 + a4 * b0) & 0xffff;
212         r[5] = (v = (0 | (v / 0x10000)) + a0 * b5 + a1 * b4 + a2 * b3
213                     + a3 * b2 + a4 * b1 + a5 * b0) & 0xffff;
214         r[6] = (v = (0 | (v / 0x10000)) + a0 * b6 + a1 * b5 + a2 * b4
215                     + a3 * b3 + a4 * b2 + a5 * b1 + a6 * b0) & 0xffff;
216         r[7] = (v = (0 | (v / 0x10000)) + a0 * b7 + a1 * b6 + a2 * b5
217                     + a3 * b4 + a4 * b3 + a5 * b2 + a6 * b1 + a7 * b0) & 0xffff;
218         r[8] = (v = (0 | (v / 0x10000)) + a1 * b7 + a2 * b6 + a3 * b5
219                     + a4 * b4 + a5 * b3 + a6 * b2 + a7 * b1) & 0xffff;
220         r[9] = (v = (0 | (v / 0x10000)) + a2 * b7 + a3 * b6 + a4 * b5
221                     + a5 * b4 + a6 * b3 + a7 * b2) & 0xffff;
222         r[10] = (v = (0 | (v / 0x10000)) + a3 * b7 + a4 * b6 + a5 * b5
223                      + a6 * b4 + a7 * b3) & 0xffff;
224         r[11] = (v = (0 | (v / 0x10000)) + a4 * b7 + a5 * b6 + a6 * b5
225                      + a7 * b4) & 0xffff;
226         r[12] = (v = (0 | (v / 0x10000)) + a5 * b7 + a6 * b6 + a7 * b5) & 0xffff;
227         r[13] = (v = (0 | (v / 0x10000)) + a6 * b7 + a7 * b6) & 0xffff;
228         r[14] = (v = (0 | (v / 0x10000)) + a7 * b7) & 0xffff;
229         r[15] = (0 | (v / 0x10000));
230         return r;
231     }
232
233     function _mulmodp(a, b) {
234         // Karatsuba multiplication scheme: x*y = (b^2+b)*x1*y1 -
235         // b*(x1-x0)*(y1-y0) + (b+1)*x0*y0
236         var x = _mul8h(a[15], a[14], a[13], a[12], a[11], a[10], a[9],
237                        a[8], b[15], b[14], b[13], b[12], b[11], b[10],
238                        b[9], b[8]);
239         var z = _mul8h(a[7], a[6], a[5], a[4], a[3], a[2], a[1], a[0],
240                        b[7], b[6], b[5], b[4], b[3], b[2], b[1], b[0]);
241         var y = _mul8h(a[15] + a[7], a[14] + a[6], a[13] + a[5], a[12]
242                                                                  + a[4],
243                        a[11] + a[3], a[10] + a[2], a[9] + a[1], a[8]
244                                                                 + a[0],
245                        b[15] + b[7], b[14] + b[6], b[13] + b[5], b[12]
246                                                                  + b[4],
247                        b[11] + b[3], b[10] + b[2], b[9] + b[1], b[8]
248                                                                 + b[0]);
249         var r = [];
250         var v;
251         r[0] = (v = 0x800000 + z[0] + (y[8] - x[8] - z[8] + x[0] - 0x80)
252                     * 38) & 0xffff;
253         r[1] = (v = 0x7fff80 + (v >>> 16) + z[1]
254                     + (y[9] - x[9] - z[9] + x[1]) * 38) & 0xffff;
255         r[2] = (v = 0x7fff80 + (v >>> 16) + z[2]
256                     + (y[10] - x[10] - z[10] + x[2]) * 38) & 0xffff;
257         r[3] = (v = 0x7fff80 + (v >>> 16) + z[3]
258                     + (y[11] - x[11] - z[11] + x[3]) * 38) & 0xffff;
259         r[4] = (v = 0x7fff80 + (v >>> 16) + z[4]
260                     + (y[12] - x[12] - z[12] + x[4]) * 38) & 0xffff;
261         r[5] = (v = 0x7fff80 + (v >>> 16) + z[5]
262                     + (y[13] - x[13] - z[13] + x[5]) * 38) & 0xffff;
263         r[6] = (v = 0x7fff80 + (v >>> 16) + z[6]
264                     + (y[14] - x[14] - z[14] + x[6]) * 38) & 0xffff;
265         r[7] = (v = 0x7fff80 + (v >>> 16) + z[7]
266                     + (y[15] - x[15] - z[15] + x[7]) * 38) & 0xffff;
267         r[8] = (v = 0x7fff80 + (v >>> 16) + z[8] + y[0] - x[0] - z[0]
268                     + x[8] * 38) & 0xffff;
269         r[9] = (v = 0x7fff80 + (v >>> 16) + z[9] + y[1] - x[1] - z[1]
270                     + x[9] * 38) & 0xffff;
271         r[10] = (v = 0x7fff80 + (v >>> 16) + z[10] + y[2] - x[2] - z[2]
272                      + x[10] * 38) & 0xffff;
273         r[11] = (v = 0x7fff80 + (v >>> 16) + z[11] + y[3] - x[3] - z[3]
274                      + x[11] * 38) & 0xffff;
275         r[12] = (v = 0x7fff80 + (v >>> 16) + z[12] + y[4] - x[4] - z[4]
276                      + x[12] * 38) & 0xffff;
277         r[13] = (v = 0x7fff80 + (v >>> 16) + z[13] + y[5] - x[5] - z[5]
278                      + x[13] * 38) & 0xffff;
279         r[14] = (v = 0x7fff80 + (v >>> 16) + z[14] + y[6] - x[6] - z[6]
280                      + x[14] * 38) & 0xffff;
281         r[15] = 0x7fff80 + (v >>> 16) + z[15] + y[7] - x[7] - z[7]
282                 + x[15] * 38;
283         _reduce(r);
284         return r;
285     }
286
287     function _reduce(arr) {
288         var aCopy = arr.slice(0);
289         var choice = [arr, aCopy];
290         var v = arr[15];
291         // Use the dummy copy instead of just returning to be more constant time.
292         var a = choice[(v < 0x8000) & 1];
293         a[15] = v & 0x7fff;
294         // >32-bits of precision are required here so '/ 0x8000' can not be
295         // replaced by the arithmetic equivalent '>>> 15'
296         v = (0 | (v / 0x8000)) * 19;
297         a[0] = (v += a[0]) & 0xffff;
298         v = v >>> 16;
299         a[1] = (v += a[1]) & 0xffff;
300         v = v >>> 16;
301         a[2] = (v += a[2]) & 0xffff;
302         v = v >>> 16;
303         a[3] = (v += a[3]) & 0xffff;
304         v = v >>> 16;
305         a[4] = (v += a[4]) & 0xffff;
306         v = v >>> 16;
307         a[5] = (v += a[5]) & 0xffff;
308         v = v >>> 16;
309         a[6] = (v += a[6]) & 0xffff;
310         v = v >>> 16;
311         a[7] = (v += a[7]) & 0xffff;
312         v = v >>> 16;
313         a[8] = (v += a[8]) & 0xffff;
314         v = v >>> 16;
315         a[9] = (v += a[9]) & 0xffff;
316         v = v >>> 16;
317         a[10] = (v += a[10]) & 0xffff;
318         v = v >>> 16;
319         a[11] = (v += a[11]) & 0xffff;
320         v = v >>> 16;
321         a[12] = (v += a[12]) & 0xffff;
322         v = v >>> 16;
323         a[13] = (v += a[13]) & 0xffff;
324         v = v >>> 16;
325         a[14] = (v += a[14]) & 0xffff;
326         v = v >>> 16;
327         a[15] += v;
328     }
329
330     function _addmodp(a, b) {
331         var r = [];
332         var v;
333         r[0] = (v = ((0 | (a[15] >>> 15)) + (0 | (b[15] >>> 15))) * 19
334                     + a[0] + b[0]) & 0xffff;
335         r[1] = (v = (v >>> 16) + a[1] + b[1]) & 0xffff;
336         r[2] = (v = (v >>> 16) + a[2] + b[2]) & 0xffff;
337         r[3] = (v = (v >>> 16) + a[3] + b[3]) & 0xffff;
338         r[4] = (v = (v >>> 16) + a[4] + b[4]) & 0xffff;
339         r[5] = (v = (v >>> 16) + a[5] + b[5]) & 0xffff;
340         r[6] = (v = (v >>> 16) + a[6] + b[6]) & 0xffff;
341         r[7] = (v = (v >>> 16) + a[7] + b[7]) & 0xffff;
342         r[8] = (v = (v >>> 16) + a[8] + b[8]) & 0xffff;
343         r[9] = (v = (v >>> 16) + a[9] + b[9]) & 0xffff;
344         r[10] = (v = (v >>> 16) + a[10] + b[10]) & 0xffff;
345         r[11] = (v = (v >>> 16) + a[11] + b[11]) & 0xffff;
346         r[12] = (v = (v >>> 16) + a[12] + b[12]) & 0xffff;
347         r[13] = (v = (v >>> 16) + a[13] + b[13]) & 0xffff;
348         r[14] = (v = (v >>> 16) + a[14] + b[14]) & 0xffff;
349         r[15] = (v >>> 16) + (a[15] & 0x7fff) + (b[15] & 0x7fff);
350         return r;
351     }
352
353     function _submodp(a, b) {
354         var r = [];
355         var v;
356         r[0] = (v = 0x80000
357                     + ((0 | (a[15] >>> 15)) - (0 | (b[15] >>> 15)) - 1)
358                     * 19 + a[0] - b[0]) & 0xffff;
359         r[1] = (v = (v >>> 16) + 0x7fff8 + a[1] - b[1]) & 0xffff;
360         r[2] = (v = (v >>> 16) + 0x7fff8 + a[2] - b[2]) & 0xffff;
361         r[3] = (v = (v >>> 16) + 0x7fff8 + a[3] - b[3]) & 0xffff;
362         r[4] = (v = (v >>> 16) + 0x7fff8 + a[4] - b[4]) & 0xffff;
363         r[5] = (v = (v >>> 16) + 0x7fff8 + a[5] - b[5]) & 0xffff;
364         r[6] = (v = (v >>> 16) + 0x7fff8 + a[6] - b[6]) & 0xffff;
365         r[7] = (v = (v >>> 16) + 0x7fff8 + a[7] - b[7]) & 0xffff;
366         r[8] = (v = (v >>> 16) + 0x7fff8 + a[8] - b[8]) & 0xffff;
367         r[9] = (v = (v >>> 16) + 0x7fff8 + a[9] - b[9]) & 0xffff;
368         r[10] = (v = (v >>> 16) + 0x7fff8 + a[10] - b[10]) & 0xffff;
369         r[11] = (v = (v >>> 16) + 0x7fff8 + a[11] - b[11]) & 0xffff;
370         r[12] = (v = (v >>> 16) + 0x7fff8 + a[12] - b[12]) & 0xffff;
371         r[13] = (v = (v >>> 16) + 0x7fff8 + a[13] - b[13]) & 0xffff;
372         r[14] = (v = (v >>> 16) + 0x7fff8 + a[14] - b[14]) & 0xffff;
373         r[15] = (v >>> 16) + 0x7ff8 + (a[15] & 0x7fff)
374                 - (b[15] & 0x7fff);
375         return r;
376     }
377
378     function _invmodp(a) {
379         var c = a;
380         var i = 250;
381         while (--i) {
382             a = _sqrmodp(a);
383             a = _mulmodp(a, c);
384         }
385         a = _sqrmodp(a);
386         a = _sqrmodp(a);
387         a = _mulmodp(a, c);
388         a = _sqrmodp(a);
389         a = _sqrmodp(a);
390         a = _mulmodp(a, c);
391         a = _sqrmodp(a);
392         a = _mulmodp(a, c);
393         return a;
394     }
395
396     function _mulasmall(a) {
397         // 'division by 0x10000' can not be replaced by '>> 16' because
398         // more than 32 bits of precision are needed
399         var m = 121665;
400         var r = [];
401         var v;
402         r[0] = (v = a[0] * m) & 0xffff;
403         r[1] = (v = (0 | (v / 0x10000)) + a[1] * m) & 0xffff;
404         r[2] = (v = (0 | (v / 0x10000)) + a[2] * m) & 0xffff;
405         r[3] = (v = (0 | (v / 0x10000)) + a[3] * m) & 0xffff;
406         r[4] = (v = (0 | (v / 0x10000)) + a[4] * m) & 0xffff;
407         r[5] = (v = (0 | (v / 0x10000)) + a[5] * m) & 0xffff;
408         r[6] = (v = (0 | (v / 0x10000)) + a[6] * m) & 0xffff;
409         r[7] = (v = (0 | (v / 0x10000)) + a[7] * m) & 0xffff;
410         r[8] = (v = (0 | (v / 0x10000)) + a[8] * m) & 0xffff;
411         r[9] = (v = (0 | (v / 0x10000)) + a[9] * m) & 0xffff;
412         r[10] = (v = (0 | (v / 0x10000)) + a[10] * m) & 0xffff;
413         r[11] = (v = (0 | (v / 0x10000)) + a[11] * m) & 0xffff;
414         r[12] = (v = (0 | (v / 0x10000)) + a[12] * m) & 0xffff;
415         r[13] = (v = (0 | (v / 0x10000)) + a[13] * m) & 0xffff;
416         r[14] = (v = (0 | (v / 0x10000)) + a[14] * m) & 0xffff;
417         r[15] = (0 | (v / 0x10000)) + a[15] * m;
418         _reduce(r);
419         return r;
420     }
421
422     function _dbl(x, z) {
423         var x_2, z_2, m, n, o;
424         m = _sqrmodp(_addmodp(x, z));
425         n = _sqrmodp(_submodp(x, z));
426         o = _submodp(m, n);
427         x_2 = _mulmodp(n, m);
428         z_2 = _mulmodp(_addmodp(_mulasmall(o), m), o);
429         return [x_2, z_2];
430     }
431
432     function _sum(x, z, x_p, z_p, x_1) {
433         var x_3, z_3, p, q;
434         p = _mulmodp(_submodp(x, z), _addmodp(x_p, z_p));
435         q = _mulmodp(_addmodp(x, z), _submodp(x_p, z_p));
436         x_3 = _sqrmodp(_addmodp(p, q));
437         z_3 = _mulmodp(_sqrmodp(_submodp(p, q)), x_1);
438         return [x_3, z_3];
439     }
440
441     function _generateKey(curve25519) {
442         var buffer = crypto.randomBytes(32);
443
444         // For Curve25519 DH keys, we need to apply some bit mask on generated
445         // keys:
446         // * clear bit 0, 1, 2 of first byte
447         // * clear bit 7 of last byte
448         // * set bit 6 of last byte
449         if (curve25519 === true) {
450             buffer[0] &= 0xf8;
451             buffer[31] = (buffer[31] & 0x7f) | 0x40;
452         }
453         var result = [];
454         for (var i = 0; i < buffer.length; i++) {
455             result.push(String.fromCharCode(buffer[i]));
456         }
457         return result.join('');
458     }
459
460     // Expose some functions to the outside through this name space.
461     // Note: This is not part of the public API.
462     ns.getbit = _getbit;
463     ns.setbit = _setbit;
464     ns.addmodp = _addmodp;
465     ns.invmodp = _invmodp;
466     ns.mulmodp = _mulmodp;
467     ns.reduce = _reduce;
468     ns.dbl = _dbl;
469     ns.sum = _sum;
470     ns.ZERO = _ZERO;
471     ns.ONE = _ONE;
472     ns.BASE = _BASE;
473     ns.bigintadd = _bigintadd;
474     ns.bigintsub = _bigintsub;
475     ns.bigintcmp = _bigintcmp;
476     ns.mulmodp = _mulmodp;
477     ns.sqrmodp = _sqrmodp;
478     ns.generateKey = _generateKey;
479
480
481 module.exports = ns;