source: trip-planner-front/node_modules/node-forge/lib/ed25519.js@ ceaed42

Last change on this file since ceaed42 was 6a3a178, checked in by Ema <ema_spirova@…>, 3 years ago

initial commit

  • Property mode set to 100644
File size: 24.4 KB
Line 
1/**
2 * JavaScript implementation of Ed25519.
3 *
4 * Copyright (c) 2017-2019 Digital Bazaar, Inc.
5 *
6 * This implementation is based on the most excellent TweetNaCl which is
7 * in the public domain. Many thanks to its contributors:
8 *
9 * https://github.com/dchest/tweetnacl-js
10 */
11var forge = require('./forge');
12require('./jsbn');
13require('./random');
14require('./sha512');
15require('./util');
16var asn1Validator = require('./asn1-validator');
17var publicKeyValidator = asn1Validator.publicKeyValidator;
18var privateKeyValidator = asn1Validator.privateKeyValidator;
19
20if(typeof BigInteger === 'undefined') {
21 var BigInteger = forge.jsbn.BigInteger;
22}
23
24var ByteBuffer = forge.util.ByteBuffer;
25var NativeBuffer = typeof Buffer === 'undefined' ? Uint8Array : Buffer;
26
27/*
28 * Ed25519 algorithms, see RFC 8032:
29 * https://tools.ietf.org/html/rfc8032
30 */
31forge.pki = forge.pki || {};
32module.exports = forge.pki.ed25519 = forge.ed25519 = forge.ed25519 || {};
33var ed25519 = forge.ed25519;
34
35ed25519.constants = {};
36ed25519.constants.PUBLIC_KEY_BYTE_LENGTH = 32;
37ed25519.constants.PRIVATE_KEY_BYTE_LENGTH = 64;
38ed25519.constants.SEED_BYTE_LENGTH = 32;
39ed25519.constants.SIGN_BYTE_LENGTH = 64;
40ed25519.constants.HASH_BYTE_LENGTH = 64;
41
42ed25519.generateKeyPair = function(options) {
43 options = options || {};
44 var seed = options.seed;
45 if(seed === undefined) {
46 // generate seed
47 seed = forge.random.getBytesSync(ed25519.constants.SEED_BYTE_LENGTH);
48 } else if(typeof seed === 'string') {
49 if(seed.length !== ed25519.constants.SEED_BYTE_LENGTH) {
50 throw new TypeError(
51 '"seed" must be ' + ed25519.constants.SEED_BYTE_LENGTH +
52 ' bytes in length.');
53 }
54 } else if(!(seed instanceof Uint8Array)) {
55 throw new TypeError(
56 '"seed" must be a node.js Buffer, Uint8Array, or a binary string.');
57 }
58
59 seed = messageToNativeBuffer({message: seed, encoding: 'binary'});
60
61 var pk = new NativeBuffer(ed25519.constants.PUBLIC_KEY_BYTE_LENGTH);
62 var sk = new NativeBuffer(ed25519.constants.PRIVATE_KEY_BYTE_LENGTH);
63 for(var i = 0; i < 32; ++i) {
64 sk[i] = seed[i];
65 }
66 crypto_sign_keypair(pk, sk);
67 return {publicKey: pk, privateKey: sk};
68};
69
70/**
71 * Converts a private key from a RFC8410 ASN.1 encoding.
72 *
73 * @param obj - The asn1 representation of a private key.
74 *
75 * @returns {Object} keyInfo - The key information.
76 * @returns {Buffer|Uint8Array} keyInfo.privateKeyBytes - 32 private key bytes.
77 */
78ed25519.privateKeyFromAsn1 = function(obj) {
79 var capture = {};
80 var errors = [];
81 var valid = forge.asn1.validate(obj, privateKeyValidator, capture, errors);
82 if(!valid) {
83 var error = new Error('Invalid Key.');
84 error.errors = errors;
85 throw error;
86 }
87 var oid = forge.asn1.derToOid(capture.privateKeyOid);
88 var ed25519Oid = forge.oids.EdDSA25519;
89 if(oid !== ed25519Oid) {
90 throw new Error('Invalid OID "' + oid + '"; OID must be "' +
91 ed25519Oid + '".');
92 }
93 var privateKey = capture.privateKey;
94 // manually extract the private key bytes from nested octet string, see FIXME:
95 // https://github.com/digitalbazaar/forge/blob/master/lib/asn1.js#L542
96 var privateKeyBytes = messageToNativeBuffer({
97 message: forge.asn1.fromDer(privateKey).value,
98 encoding: 'binary'
99 });
100 // TODO: RFC8410 specifies a format for encoding the public key bytes along
101 // with the private key bytes. `publicKeyBytes` can be returned in the
102 // future. https://tools.ietf.org/html/rfc8410#section-10.3
103 return {privateKeyBytes: privateKeyBytes};
104};
105
106/**
107 * Converts a public key from a RFC8410 ASN.1 encoding.
108 *
109 * @param obj - The asn1 representation of a public key.
110 *
111 * @return {Buffer|Uint8Array} - 32 public key bytes.
112 */
113ed25519.publicKeyFromAsn1 = function(obj) {
114 // get SubjectPublicKeyInfo
115 var capture = {};
116 var errors = [];
117 var valid = forge.asn1.validate(obj, publicKeyValidator, capture, errors);
118 if(!valid) {
119 var error = new Error('Invalid Key.');
120 error.errors = errors;
121 throw error;
122 }
123 var oid = forge.asn1.derToOid(capture.publicKeyOid);
124 var ed25519Oid = forge.oids.EdDSA25519;
125 if(oid !== ed25519Oid) {
126 throw new Error('Invalid OID "' + oid + '"; OID must be "' +
127 ed25519Oid + '".');
128 }
129 var publicKeyBytes = capture.ed25519PublicKey;
130 if(publicKeyBytes.length !== ed25519.constants.PUBLIC_KEY_BYTE_LENGTH) {
131 throw new Error('Key length is invalid.');
132 }
133 return messageToNativeBuffer({
134 message: publicKeyBytes,
135 encoding: 'binary'
136 });
137};
138
139ed25519.publicKeyFromPrivateKey = function(options) {
140 options = options || {};
141 var privateKey = messageToNativeBuffer({
142 message: options.privateKey, encoding: 'binary'
143 });
144 if(privateKey.length !== ed25519.constants.PRIVATE_KEY_BYTE_LENGTH) {
145 throw new TypeError(
146 '"options.privateKey" must have a byte length of ' +
147 ed25519.constants.PRIVATE_KEY_BYTE_LENGTH);
148 }
149
150 var pk = new NativeBuffer(ed25519.constants.PUBLIC_KEY_BYTE_LENGTH);
151 for(var i = 0; i < pk.length; ++i) {
152 pk[i] = privateKey[32 + i];
153 }
154 return pk;
155};
156
157ed25519.sign = function(options) {
158 options = options || {};
159 var msg = messageToNativeBuffer(options);
160 var privateKey = messageToNativeBuffer({
161 message: options.privateKey,
162 encoding: 'binary'
163 });
164 if(privateKey.length === ed25519.constants.SEED_BYTE_LENGTH) {
165 var keyPair = ed25519.generateKeyPair({seed: privateKey});
166 privateKey = keyPair.privateKey;
167 } else if(privateKey.length !== ed25519.constants.PRIVATE_KEY_BYTE_LENGTH) {
168 throw new TypeError(
169 '"options.privateKey" must have a byte length of ' +
170 ed25519.constants.SEED_BYTE_LENGTH + ' or ' +
171 ed25519.constants.PRIVATE_KEY_BYTE_LENGTH);
172 }
173
174 var signedMsg = new NativeBuffer(
175 ed25519.constants.SIGN_BYTE_LENGTH + msg.length);
176 crypto_sign(signedMsg, msg, msg.length, privateKey);
177
178 var sig = new NativeBuffer(ed25519.constants.SIGN_BYTE_LENGTH);
179 for(var i = 0; i < sig.length; ++i) {
180 sig[i] = signedMsg[i];
181 }
182 return sig;
183};
184
185ed25519.verify = function(options) {
186 options = options || {};
187 var msg = messageToNativeBuffer(options);
188 if(options.signature === undefined) {
189 throw new TypeError(
190 '"options.signature" must be a node.js Buffer, a Uint8Array, a forge ' +
191 'ByteBuffer, or a binary string.');
192 }
193 var sig = messageToNativeBuffer({
194 message: options.signature,
195 encoding: 'binary'
196 });
197 if(sig.length !== ed25519.constants.SIGN_BYTE_LENGTH) {
198 throw new TypeError(
199 '"options.signature" must have a byte length of ' +
200 ed25519.constants.SIGN_BYTE_LENGTH);
201 }
202 var publicKey = messageToNativeBuffer({
203 message: options.publicKey,
204 encoding: 'binary'
205 });
206 if(publicKey.length !== ed25519.constants.PUBLIC_KEY_BYTE_LENGTH) {
207 throw new TypeError(
208 '"options.publicKey" must have a byte length of ' +
209 ed25519.constants.PUBLIC_KEY_BYTE_LENGTH);
210 }
211
212 var sm = new NativeBuffer(ed25519.constants.SIGN_BYTE_LENGTH + msg.length);
213 var m = new NativeBuffer(ed25519.constants.SIGN_BYTE_LENGTH + msg.length);
214 var i;
215 for(i = 0; i < ed25519.constants.SIGN_BYTE_LENGTH; ++i) {
216 sm[i] = sig[i];
217 }
218 for(i = 0; i < msg.length; ++i) {
219 sm[i + ed25519.constants.SIGN_BYTE_LENGTH] = msg[i];
220 }
221 return (crypto_sign_open(m, sm, sm.length, publicKey) >= 0);
222};
223
224function messageToNativeBuffer(options) {
225 var message = options.message;
226 if(message instanceof Uint8Array || message instanceof NativeBuffer) {
227 return message;
228 }
229
230 var encoding = options.encoding;
231 if(message === undefined) {
232 if(options.md) {
233 // TODO: more rigorous validation that `md` is a MessageDigest
234 message = options.md.digest().getBytes();
235 encoding = 'binary';
236 } else {
237 throw new TypeError('"options.message" or "options.md" not specified.');
238 }
239 }
240
241 if(typeof message === 'string' && !encoding) {
242 throw new TypeError('"options.encoding" must be "binary" or "utf8".');
243 }
244
245 if(typeof message === 'string') {
246 if(typeof Buffer !== 'undefined') {
247 return Buffer.from(message, encoding);
248 }
249 message = new ByteBuffer(message, encoding);
250 } else if(!(message instanceof ByteBuffer)) {
251 throw new TypeError(
252 '"options.message" must be a node.js Buffer, a Uint8Array, a forge ' +
253 'ByteBuffer, or a string with "options.encoding" specifying its ' +
254 'encoding.');
255 }
256
257 // convert to native buffer
258 var buffer = new NativeBuffer(message.length());
259 for(var i = 0; i < buffer.length; ++i) {
260 buffer[i] = message.at(i);
261 }
262 return buffer;
263}
264
265var gf0 = gf();
266var gf1 = gf([1]);
267var D = gf([
268 0x78a3, 0x1359, 0x4dca, 0x75eb, 0xd8ab, 0x4141, 0x0a4d, 0x0070,
269 0xe898, 0x7779, 0x4079, 0x8cc7, 0xfe73, 0x2b6f, 0x6cee, 0x5203]);
270var D2 = gf([
271 0xf159, 0x26b2, 0x9b94, 0xebd6, 0xb156, 0x8283, 0x149a, 0x00e0,
272 0xd130, 0xeef3, 0x80f2, 0x198e, 0xfce7, 0x56df, 0xd9dc, 0x2406]);
273var X = gf([
274 0xd51a, 0x8f25, 0x2d60, 0xc956, 0xa7b2, 0x9525, 0xc760, 0x692c,
275 0xdc5c, 0xfdd6, 0xe231, 0xc0a4, 0x53fe, 0xcd6e, 0x36d3, 0x2169]);
276var Y = gf([
277 0x6658, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666,
278 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666]);
279var L = new Float64Array([
280 0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58,
281 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14,
282 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10]);
283var I = gf([
284 0xa0b0, 0x4a0e, 0x1b27, 0xc4ee, 0xe478, 0xad2f, 0x1806, 0x2f43,
285 0xd7a7, 0x3dfb, 0x0099, 0x2b4d, 0xdf0b, 0x4fc1, 0x2480, 0x2b83]);
286
287// TODO: update forge buffer implementation to use `Buffer` or `Uint8Array`,
288// whichever is available, to improve performance
289function sha512(msg, msgLen) {
290 // Note: `out` and `msg` are NativeBuffer
291 var md = forge.md.sha512.create();
292 var buffer = new ByteBuffer(msg);
293 md.update(buffer.getBytes(msgLen), 'binary');
294 var hash = md.digest().getBytes();
295 if(typeof Buffer !== 'undefined') {
296 return Buffer.from(hash, 'binary');
297 }
298 var out = new NativeBuffer(ed25519.constants.HASH_BYTE_LENGTH);
299 for(var i = 0; i < 64; ++i) {
300 out[i] = hash.charCodeAt(i);
301 }
302 return out;
303}
304
305function crypto_sign_keypair(pk, sk) {
306 var p = [gf(), gf(), gf(), gf()];
307 var i;
308
309 var d = sha512(sk, 32);
310 d[0] &= 248;
311 d[31] &= 127;
312 d[31] |= 64;
313
314 scalarbase(p, d);
315 pack(pk, p);
316
317 for(i = 0; i < 32; ++i) {
318 sk[i + 32] = pk[i];
319 }
320 return 0;
321}
322
323// Note: difference from C - smlen returned, not passed as argument.
324function crypto_sign(sm, m, n, sk) {
325 var i, j, x = new Float64Array(64);
326 var p = [gf(), gf(), gf(), gf()];
327
328 var d = sha512(sk, 32);
329 d[0] &= 248;
330 d[31] &= 127;
331 d[31] |= 64;
332
333 var smlen = n + 64;
334 for(i = 0; i < n; ++i) {
335 sm[64 + i] = m[i];
336 }
337 for(i = 0; i < 32; ++i) {
338 sm[32 + i] = d[32 + i];
339 }
340
341 var r = sha512(sm.subarray(32), n + 32);
342 reduce(r);
343 scalarbase(p, r);
344 pack(sm, p);
345
346 for(i = 32; i < 64; ++i) {
347 sm[i] = sk[i];
348 }
349 var h = sha512(sm, n + 64);
350 reduce(h);
351
352 for(i = 32; i < 64; ++i) {
353 x[i] = 0;
354 }
355 for(i = 0; i < 32; ++i) {
356 x[i] = r[i];
357 }
358 for(i = 0; i < 32; ++i) {
359 for(j = 0; j < 32; j++) {
360 x[i + j] += h[i] * d[j];
361 }
362 }
363
364 modL(sm.subarray(32), x);
365 return smlen;
366}
367
368function crypto_sign_open(m, sm, n, pk) {
369 var i, mlen;
370 var t = new NativeBuffer(32);
371 var p = [gf(), gf(), gf(), gf()],
372 q = [gf(), gf(), gf(), gf()];
373
374 mlen = -1;
375 if(n < 64) {
376 return -1;
377 }
378
379 if(unpackneg(q, pk)) {
380 return -1;
381 }
382
383 for(i = 0; i < n; ++i) {
384 m[i] = sm[i];
385 }
386 for(i = 0; i < 32; ++i) {
387 m[i + 32] = pk[i];
388 }
389 var h = sha512(m, n);
390 reduce(h);
391 scalarmult(p, q, h);
392
393 scalarbase(q, sm.subarray(32));
394 add(p, q);
395 pack(t, p);
396
397 n -= 64;
398 if(crypto_verify_32(sm, 0, t, 0)) {
399 for(i = 0; i < n; ++i) {
400 m[i] = 0;
401 }
402 return -1;
403 }
404
405 for(i = 0; i < n; ++i) {
406 m[i] = sm[i + 64];
407 }
408 mlen = n;
409 return mlen;
410}
411
412function modL(r, x) {
413 var carry, i, j, k;
414 for(i = 63; i >= 32; --i) {
415 carry = 0;
416 for(j = i - 32, k = i - 12; j < k; ++j) {
417 x[j] += carry - 16 * x[i] * L[j - (i - 32)];
418 carry = (x[j] + 128) >> 8;
419 x[j] -= carry * 256;
420 }
421 x[j] += carry;
422 x[i] = 0;
423 }
424 carry = 0;
425 for(j = 0; j < 32; ++j) {
426 x[j] += carry - (x[31] >> 4) * L[j];
427 carry = x[j] >> 8;
428 x[j] &= 255;
429 }
430 for(j = 0; j < 32; ++j) {
431 x[j] -= carry * L[j];
432 }
433 for(i = 0; i < 32; ++i) {
434 x[i + 1] += x[i] >> 8;
435 r[i] = x[i] & 255;
436 }
437}
438
439function reduce(r) {
440 var x = new Float64Array(64);
441 for(var i = 0; i < 64; ++i) {
442 x[i] = r[i];
443 r[i] = 0;
444 }
445 modL(r, x);
446}
447
448function add(p, q) {
449 var a = gf(), b = gf(), c = gf(),
450 d = gf(), e = gf(), f = gf(),
451 g = gf(), h = gf(), t = gf();
452
453 Z(a, p[1], p[0]);
454 Z(t, q[1], q[0]);
455 M(a, a, t);
456 A(b, p[0], p[1]);
457 A(t, q[0], q[1]);
458 M(b, b, t);
459 M(c, p[3], q[3]);
460 M(c, c, D2);
461 M(d, p[2], q[2]);
462 A(d, d, d);
463 Z(e, b, a);
464 Z(f, d, c);
465 A(g, d, c);
466 A(h, b, a);
467
468 M(p[0], e, f);
469 M(p[1], h, g);
470 M(p[2], g, f);
471 M(p[3], e, h);
472}
473
474function cswap(p, q, b) {
475 for(var i = 0; i < 4; ++i) {
476 sel25519(p[i], q[i], b);
477 }
478}
479
480function pack(r, p) {
481 var tx = gf(), ty = gf(), zi = gf();
482 inv25519(zi, p[2]);
483 M(tx, p[0], zi);
484 M(ty, p[1], zi);
485 pack25519(r, ty);
486 r[31] ^= par25519(tx) << 7;
487}
488
489function pack25519(o, n) {
490 var i, j, b;
491 var m = gf(), t = gf();
492 for(i = 0; i < 16; ++i) {
493 t[i] = n[i];
494 }
495 car25519(t);
496 car25519(t);
497 car25519(t);
498 for(j = 0; j < 2; ++j) {
499 m[0] = t[0] - 0xffed;
500 for(i = 1; i < 15; ++i) {
501 m[i] = t[i] - 0xffff - ((m[i - 1] >> 16) & 1);
502 m[i-1] &= 0xffff;
503 }
504 m[15] = t[15] - 0x7fff - ((m[14] >> 16) & 1);
505 b = (m[15] >> 16) & 1;
506 m[14] &= 0xffff;
507 sel25519(t, m, 1 - b);
508 }
509 for (i = 0; i < 16; i++) {
510 o[2 * i] = t[i] & 0xff;
511 o[2 * i + 1] = t[i] >> 8;
512 }
513}
514
515function unpackneg(r, p) {
516 var t = gf(), chk = gf(), num = gf(),
517 den = gf(), den2 = gf(), den4 = gf(),
518 den6 = gf();
519
520 set25519(r[2], gf1);
521 unpack25519(r[1], p);
522 S(num, r[1]);
523 M(den, num, D);
524 Z(num, num, r[2]);
525 A(den, r[2], den);
526
527 S(den2, den);
528 S(den4, den2);
529 M(den6, den4, den2);
530 M(t, den6, num);
531 M(t, t, den);
532
533 pow2523(t, t);
534 M(t, t, num);
535 M(t, t, den);
536 M(t, t, den);
537 M(r[0], t, den);
538
539 S(chk, r[0]);
540 M(chk, chk, den);
541 if(neq25519(chk, num)) {
542 M(r[0], r[0], I);
543 }
544
545 S(chk, r[0]);
546 M(chk, chk, den);
547 if(neq25519(chk, num)) {
548 return -1;
549 }
550
551 if(par25519(r[0]) === (p[31] >> 7)) {
552 Z(r[0], gf0, r[0]);
553 }
554
555 M(r[3], r[0], r[1]);
556 return 0;
557}
558
559function unpack25519(o, n) {
560 var i;
561 for(i = 0; i < 16; ++i) {
562 o[i] = n[2 * i] + (n[2 * i + 1] << 8);
563 }
564 o[15] &= 0x7fff;
565}
566
567function pow2523(o, i) {
568 var c = gf();
569 var a;
570 for(a = 0; a < 16; ++a) {
571 c[a] = i[a];
572 }
573 for(a = 250; a >= 0; --a) {
574 S(c, c);
575 if(a !== 1) {
576 M(c, c, i);
577 }
578 }
579 for(a = 0; a < 16; ++a) {
580 o[a] = c[a];
581 }
582}
583
584function neq25519(a, b) {
585 var c = new NativeBuffer(32);
586 var d = new NativeBuffer(32);
587 pack25519(c, a);
588 pack25519(d, b);
589 return crypto_verify_32(c, 0, d, 0);
590}
591
592function crypto_verify_32(x, xi, y, yi) {
593 return vn(x, xi, y, yi, 32);
594}
595
596function vn(x, xi, y, yi, n) {
597 var i, d = 0;
598 for(i = 0; i < n; ++i) {
599 d |= x[xi + i] ^ y[yi + i];
600 }
601 return (1 & ((d - 1) >>> 8)) - 1;
602}
603
604function par25519(a) {
605 var d = new NativeBuffer(32);
606 pack25519(d, a);
607 return d[0] & 1;
608}
609
610function scalarmult(p, q, s) {
611 var b, i;
612 set25519(p[0], gf0);
613 set25519(p[1], gf1);
614 set25519(p[2], gf1);
615 set25519(p[3], gf0);
616 for(i = 255; i >= 0; --i) {
617 b = (s[(i / 8)|0] >> (i & 7)) & 1;
618 cswap(p, q, b);
619 add(q, p);
620 add(p, p);
621 cswap(p, q, b);
622 }
623}
624
625function scalarbase(p, s) {
626 var q = [gf(), gf(), gf(), gf()];
627 set25519(q[0], X);
628 set25519(q[1], Y);
629 set25519(q[2], gf1);
630 M(q[3], X, Y);
631 scalarmult(p, q, s);
632}
633
634function set25519(r, a) {
635 var i;
636 for(i = 0; i < 16; i++) {
637 r[i] = a[i] | 0;
638 }
639}
640
641function inv25519(o, i) {
642 var c = gf();
643 var a;
644 for(a = 0; a < 16; ++a) {
645 c[a] = i[a];
646 }
647 for(a = 253; a >= 0; --a) {
648 S(c, c);
649 if(a !== 2 && a !== 4) {
650 M(c, c, i);
651 }
652 }
653 for(a = 0; a < 16; ++a) {
654 o[a] = c[a];
655 }
656}
657
658function car25519(o) {
659 var i, v, c = 1;
660 for(i = 0; i < 16; ++i) {
661 v = o[i] + c + 65535;
662 c = Math.floor(v / 65536);
663 o[i] = v - c * 65536;
664 }
665 o[0] += c - 1 + 37 * (c - 1);
666}
667
668function sel25519(p, q, b) {
669 var t, c = ~(b - 1);
670 for(var i = 0; i < 16; ++i) {
671 t = c & (p[i] ^ q[i]);
672 p[i] ^= t;
673 q[i] ^= t;
674 }
675}
676
677function gf(init) {
678 var i, r = new Float64Array(16);
679 if(init) {
680 for(i = 0; i < init.length; ++i) {
681 r[i] = init[i];
682 }
683 }
684 return r;
685}
686
687function A(o, a, b) {
688 for(var i = 0; i < 16; ++i) {
689 o[i] = a[i] + b[i];
690 }
691}
692
693function Z(o, a, b) {
694 for(var i = 0; i < 16; ++i) {
695 o[i] = a[i] - b[i];
696 }
697}
698
699function S(o, a) {
700 M(o, a, a);
701}
702
703function M(o, a, b) {
704 var v, c,
705 t0 = 0, t1 = 0, t2 = 0, t3 = 0, t4 = 0, t5 = 0, t6 = 0, t7 = 0,
706 t8 = 0, t9 = 0, t10 = 0, t11 = 0, t12 = 0, t13 = 0, t14 = 0, t15 = 0,
707 t16 = 0, t17 = 0, t18 = 0, t19 = 0, t20 = 0, t21 = 0, t22 = 0, t23 = 0,
708 t24 = 0, t25 = 0, t26 = 0, t27 = 0, t28 = 0, t29 = 0, t30 = 0,
709 b0 = b[0],
710 b1 = b[1],
711 b2 = b[2],
712 b3 = b[3],
713 b4 = b[4],
714 b5 = b[5],
715 b6 = b[6],
716 b7 = b[7],
717 b8 = b[8],
718 b9 = b[9],
719 b10 = b[10],
720 b11 = b[11],
721 b12 = b[12],
722 b13 = b[13],
723 b14 = b[14],
724 b15 = b[15];
725
726 v = a[0];
727 t0 += v * b0;
728 t1 += v * b1;
729 t2 += v * b2;
730 t3 += v * b3;
731 t4 += v * b4;
732 t5 += v * b5;
733 t6 += v * b6;
734 t7 += v * b7;
735 t8 += v * b8;
736 t9 += v * b9;
737 t10 += v * b10;
738 t11 += v * b11;
739 t12 += v * b12;
740 t13 += v * b13;
741 t14 += v * b14;
742 t15 += v * b15;
743 v = a[1];
744 t1 += v * b0;
745 t2 += v * b1;
746 t3 += v * b2;
747 t4 += v * b3;
748 t5 += v * b4;
749 t6 += v * b5;
750 t7 += v * b6;
751 t8 += v * b7;
752 t9 += v * b8;
753 t10 += v * b9;
754 t11 += v * b10;
755 t12 += v * b11;
756 t13 += v * b12;
757 t14 += v * b13;
758 t15 += v * b14;
759 t16 += v * b15;
760 v = a[2];
761 t2 += v * b0;
762 t3 += v * b1;
763 t4 += v * b2;
764 t5 += v * b3;
765 t6 += v * b4;
766 t7 += v * b5;
767 t8 += v * b6;
768 t9 += v * b7;
769 t10 += v * b8;
770 t11 += v * b9;
771 t12 += v * b10;
772 t13 += v * b11;
773 t14 += v * b12;
774 t15 += v * b13;
775 t16 += v * b14;
776 t17 += v * b15;
777 v = a[3];
778 t3 += v * b0;
779 t4 += v * b1;
780 t5 += v * b2;
781 t6 += v * b3;
782 t7 += v * b4;
783 t8 += v * b5;
784 t9 += v * b6;
785 t10 += v * b7;
786 t11 += v * b8;
787 t12 += v * b9;
788 t13 += v * b10;
789 t14 += v * b11;
790 t15 += v * b12;
791 t16 += v * b13;
792 t17 += v * b14;
793 t18 += v * b15;
794 v = a[4];
795 t4 += v * b0;
796 t5 += v * b1;
797 t6 += v * b2;
798 t7 += v * b3;
799 t8 += v * b4;
800 t9 += v * b5;
801 t10 += v * b6;
802 t11 += v * b7;
803 t12 += v * b8;
804 t13 += v * b9;
805 t14 += v * b10;
806 t15 += v * b11;
807 t16 += v * b12;
808 t17 += v * b13;
809 t18 += v * b14;
810 t19 += v * b15;
811 v = a[5];
812 t5 += v * b0;
813 t6 += v * b1;
814 t7 += v * b2;
815 t8 += v * b3;
816 t9 += v * b4;
817 t10 += v * b5;
818 t11 += v * b6;
819 t12 += v * b7;
820 t13 += v * b8;
821 t14 += v * b9;
822 t15 += v * b10;
823 t16 += v * b11;
824 t17 += v * b12;
825 t18 += v * b13;
826 t19 += v * b14;
827 t20 += v * b15;
828 v = a[6];
829 t6 += v * b0;
830 t7 += v * b1;
831 t8 += v * b2;
832 t9 += v * b3;
833 t10 += v * b4;
834 t11 += v * b5;
835 t12 += v * b6;
836 t13 += v * b7;
837 t14 += v * b8;
838 t15 += v * b9;
839 t16 += v * b10;
840 t17 += v * b11;
841 t18 += v * b12;
842 t19 += v * b13;
843 t20 += v * b14;
844 t21 += v * b15;
845 v = a[7];
846 t7 += v * b0;
847 t8 += v * b1;
848 t9 += v * b2;
849 t10 += v * b3;
850 t11 += v * b4;
851 t12 += v * b5;
852 t13 += v * b6;
853 t14 += v * b7;
854 t15 += v * b8;
855 t16 += v * b9;
856 t17 += v * b10;
857 t18 += v * b11;
858 t19 += v * b12;
859 t20 += v * b13;
860 t21 += v * b14;
861 t22 += v * b15;
862 v = a[8];
863 t8 += v * b0;
864 t9 += v * b1;
865 t10 += v * b2;
866 t11 += v * b3;
867 t12 += v * b4;
868 t13 += v * b5;
869 t14 += v * b6;
870 t15 += v * b7;
871 t16 += v * b8;
872 t17 += v * b9;
873 t18 += v * b10;
874 t19 += v * b11;
875 t20 += v * b12;
876 t21 += v * b13;
877 t22 += v * b14;
878 t23 += v * b15;
879 v = a[9];
880 t9 += v * b0;
881 t10 += v * b1;
882 t11 += v * b2;
883 t12 += v * b3;
884 t13 += v * b4;
885 t14 += v * b5;
886 t15 += v * b6;
887 t16 += v * b7;
888 t17 += v * b8;
889 t18 += v * b9;
890 t19 += v * b10;
891 t20 += v * b11;
892 t21 += v * b12;
893 t22 += v * b13;
894 t23 += v * b14;
895 t24 += v * b15;
896 v = a[10];
897 t10 += v * b0;
898 t11 += v * b1;
899 t12 += v * b2;
900 t13 += v * b3;
901 t14 += v * b4;
902 t15 += v * b5;
903 t16 += v * b6;
904 t17 += v * b7;
905 t18 += v * b8;
906 t19 += v * b9;
907 t20 += v * b10;
908 t21 += v * b11;
909 t22 += v * b12;
910 t23 += v * b13;
911 t24 += v * b14;
912 t25 += v * b15;
913 v = a[11];
914 t11 += v * b0;
915 t12 += v * b1;
916 t13 += v * b2;
917 t14 += v * b3;
918 t15 += v * b4;
919 t16 += v * b5;
920 t17 += v * b6;
921 t18 += v * b7;
922 t19 += v * b8;
923 t20 += v * b9;
924 t21 += v * b10;
925 t22 += v * b11;
926 t23 += v * b12;
927 t24 += v * b13;
928 t25 += v * b14;
929 t26 += v * b15;
930 v = a[12];
931 t12 += v * b0;
932 t13 += v * b1;
933 t14 += v * b2;
934 t15 += v * b3;
935 t16 += v * b4;
936 t17 += v * b5;
937 t18 += v * b6;
938 t19 += v * b7;
939 t20 += v * b8;
940 t21 += v * b9;
941 t22 += v * b10;
942 t23 += v * b11;
943 t24 += v * b12;
944 t25 += v * b13;
945 t26 += v * b14;
946 t27 += v * b15;
947 v = a[13];
948 t13 += v * b0;
949 t14 += v * b1;
950 t15 += v * b2;
951 t16 += v * b3;
952 t17 += v * b4;
953 t18 += v * b5;
954 t19 += v * b6;
955 t20 += v * b7;
956 t21 += v * b8;
957 t22 += v * b9;
958 t23 += v * b10;
959 t24 += v * b11;
960 t25 += v * b12;
961 t26 += v * b13;
962 t27 += v * b14;
963 t28 += v * b15;
964 v = a[14];
965 t14 += v * b0;
966 t15 += v * b1;
967 t16 += v * b2;
968 t17 += v * b3;
969 t18 += v * b4;
970 t19 += v * b5;
971 t20 += v * b6;
972 t21 += v * b7;
973 t22 += v * b8;
974 t23 += v * b9;
975 t24 += v * b10;
976 t25 += v * b11;
977 t26 += v * b12;
978 t27 += v * b13;
979 t28 += v * b14;
980 t29 += v * b15;
981 v = a[15];
982 t15 += v * b0;
983 t16 += v * b1;
984 t17 += v * b2;
985 t18 += v * b3;
986 t19 += v * b4;
987 t20 += v * b5;
988 t21 += v * b6;
989 t22 += v * b7;
990 t23 += v * b8;
991 t24 += v * b9;
992 t25 += v * b10;
993 t26 += v * b11;
994 t27 += v * b12;
995 t28 += v * b13;
996 t29 += v * b14;
997 t30 += v * b15;
998
999 t0 += 38 * t16;
1000 t1 += 38 * t17;
1001 t2 += 38 * t18;
1002 t3 += 38 * t19;
1003 t4 += 38 * t20;
1004 t5 += 38 * t21;
1005 t6 += 38 * t22;
1006 t7 += 38 * t23;
1007 t8 += 38 * t24;
1008 t9 += 38 * t25;
1009 t10 += 38 * t26;
1010 t11 += 38 * t27;
1011 t12 += 38 * t28;
1012 t13 += 38 * t29;
1013 t14 += 38 * t30;
1014 // t15 left as is
1015
1016 // first car
1017 c = 1;
1018 v = t0 + c + 65535; c = Math.floor(v / 65536); t0 = v - c * 65536;
1019 v = t1 + c + 65535; c = Math.floor(v / 65536); t1 = v - c * 65536;
1020 v = t2 + c + 65535; c = Math.floor(v / 65536); t2 = v - c * 65536;
1021 v = t3 + c + 65535; c = Math.floor(v / 65536); t3 = v - c * 65536;
1022 v = t4 + c + 65535; c = Math.floor(v / 65536); t4 = v - c * 65536;
1023 v = t5 + c + 65535; c = Math.floor(v / 65536); t5 = v - c * 65536;
1024 v = t6 + c + 65535; c = Math.floor(v / 65536); t6 = v - c * 65536;
1025 v = t7 + c + 65535; c = Math.floor(v / 65536); t7 = v - c * 65536;
1026 v = t8 + c + 65535; c = Math.floor(v / 65536); t8 = v - c * 65536;
1027 v = t9 + c + 65535; c = Math.floor(v / 65536); t9 = v - c * 65536;
1028 v = t10 + c + 65535; c = Math.floor(v / 65536); t10 = v - c * 65536;
1029 v = t11 + c + 65535; c = Math.floor(v / 65536); t11 = v - c * 65536;
1030 v = t12 + c + 65535; c = Math.floor(v / 65536); t12 = v - c * 65536;
1031 v = t13 + c + 65535; c = Math.floor(v / 65536); t13 = v - c * 65536;
1032 v = t14 + c + 65535; c = Math.floor(v / 65536); t14 = v - c * 65536;
1033 v = t15 + c + 65535; c = Math.floor(v / 65536); t15 = v - c * 65536;
1034 t0 += c-1 + 37 * (c-1);
1035
1036 // second car
1037 c = 1;
1038 v = t0 + c + 65535; c = Math.floor(v / 65536); t0 = v - c * 65536;
1039 v = t1 + c + 65535; c = Math.floor(v / 65536); t1 = v - c * 65536;
1040 v = t2 + c + 65535; c = Math.floor(v / 65536); t2 = v - c * 65536;
1041 v = t3 + c + 65535; c = Math.floor(v / 65536); t3 = v - c * 65536;
1042 v = t4 + c + 65535; c = Math.floor(v / 65536); t4 = v - c * 65536;
1043 v = t5 + c + 65535; c = Math.floor(v / 65536); t5 = v - c * 65536;
1044 v = t6 + c + 65535; c = Math.floor(v / 65536); t6 = v - c * 65536;
1045 v = t7 + c + 65535; c = Math.floor(v / 65536); t7 = v - c * 65536;
1046 v = t8 + c + 65535; c = Math.floor(v / 65536); t8 = v - c * 65536;
1047 v = t9 + c + 65535; c = Math.floor(v / 65536); t9 = v - c * 65536;
1048 v = t10 + c + 65535; c = Math.floor(v / 65536); t10 = v - c * 65536;
1049 v = t11 + c + 65535; c = Math.floor(v / 65536); t11 = v - c * 65536;
1050 v = t12 + c + 65535; c = Math.floor(v / 65536); t12 = v - c * 65536;
1051 v = t13 + c + 65535; c = Math.floor(v / 65536); t13 = v - c * 65536;
1052 v = t14 + c + 65535; c = Math.floor(v / 65536); t14 = v - c * 65536;
1053 v = t15 + c + 65535; c = Math.floor(v / 65536); t15 = v - c * 65536;
1054 t0 += c-1 + 37 * (c-1);
1055
1056 o[ 0] = t0;
1057 o[ 1] = t1;
1058 o[ 2] = t2;
1059 o[ 3] = t3;
1060 o[ 4] = t4;
1061 o[ 5] = t5;
1062 o[ 6] = t6;
1063 o[ 7] = t7;
1064 o[ 8] = t8;
1065 o[ 9] = t9;
1066 o[10] = t10;
1067 o[11] = t11;
1068 o[12] = t12;
1069 o[13] = t13;
1070 o[14] = t14;
1071 o[15] = t15;
1072}
Note: See TracBrowser for help on using the repository browser.