source: frontend/node_modules/node-forge/lib/ed25519.js

Last change on this file was 9af201e, checked in by MBK <marija.karapandzova@…>, 11 days ago

Fix frontend appearance

  • Property mode set to 100644
File size: 24.8 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 if(!_isCanonicalSignatureScalar(sm, 32)) {
384 return -1;
385 }
386
387 for(i = 0; i < n; ++i) {
388 m[i] = sm[i];
389 }
390 for(i = 0; i < 32; ++i) {
391 m[i + 32] = pk[i];
392 }
393 var h = sha512(m, n);
394 reduce(h);
395 scalarmult(p, q, h);
396
397 scalarbase(q, sm.subarray(32));
398 add(p, q);
399 pack(t, p);
400
401 n -= 64;
402 if(crypto_verify_32(sm, 0, t, 0)) {
403 for(i = 0; i < n; ++i) {
404 m[i] = 0;
405 }
406 return -1;
407 }
408
409 for(i = 0; i < n; ++i) {
410 m[i] = sm[i + 64];
411 }
412 mlen = n;
413 return mlen;
414}
415
416function _isCanonicalSignatureScalar(bytes, offset) {
417 var i;
418 // Compare little-endian scalar S against group order L and require S < L.
419 for(i = 31; i >= 0; --i) {
420 if(bytes[offset + i] < L[i]) {
421 return true;
422 }
423 if(bytes[offset + i] > L[i]) {
424 return false;
425 }
426 }
427 // S == L is non-canonical.
428 return false;
429}
430
431function modL(r, x) {
432 var carry, i, j, k;
433 for(i = 63; i >= 32; --i) {
434 carry = 0;
435 for(j = i - 32, k = i - 12; j < k; ++j) {
436 x[j] += carry - 16 * x[i] * L[j - (i - 32)];
437 carry = (x[j] + 128) >> 8;
438 x[j] -= carry * 256;
439 }
440 x[j] += carry;
441 x[i] = 0;
442 }
443 carry = 0;
444 for(j = 0; j < 32; ++j) {
445 x[j] += carry - (x[31] >> 4) * L[j];
446 carry = x[j] >> 8;
447 x[j] &= 255;
448 }
449 for(j = 0; j < 32; ++j) {
450 x[j] -= carry * L[j];
451 }
452 for(i = 0; i < 32; ++i) {
453 x[i + 1] += x[i] >> 8;
454 r[i] = x[i] & 255;
455 }
456}
457
458function reduce(r) {
459 var x = new Float64Array(64);
460 for(var i = 0; i < 64; ++i) {
461 x[i] = r[i];
462 r[i] = 0;
463 }
464 modL(r, x);
465}
466
467function add(p, q) {
468 var a = gf(), b = gf(), c = gf(),
469 d = gf(), e = gf(), f = gf(),
470 g = gf(), h = gf(), t = gf();
471
472 Z(a, p[1], p[0]);
473 Z(t, q[1], q[0]);
474 M(a, a, t);
475 A(b, p[0], p[1]);
476 A(t, q[0], q[1]);
477 M(b, b, t);
478 M(c, p[3], q[3]);
479 M(c, c, D2);
480 M(d, p[2], q[2]);
481 A(d, d, d);
482 Z(e, b, a);
483 Z(f, d, c);
484 A(g, d, c);
485 A(h, b, a);
486
487 M(p[0], e, f);
488 M(p[1], h, g);
489 M(p[2], g, f);
490 M(p[3], e, h);
491}
492
493function cswap(p, q, b) {
494 for(var i = 0; i < 4; ++i) {
495 sel25519(p[i], q[i], b);
496 }
497}
498
499function pack(r, p) {
500 var tx = gf(), ty = gf(), zi = gf();
501 inv25519(zi, p[2]);
502 M(tx, p[0], zi);
503 M(ty, p[1], zi);
504 pack25519(r, ty);
505 r[31] ^= par25519(tx) << 7;
506}
507
508function pack25519(o, n) {
509 var i, j, b;
510 var m = gf(), t = gf();
511 for(i = 0; i < 16; ++i) {
512 t[i] = n[i];
513 }
514 car25519(t);
515 car25519(t);
516 car25519(t);
517 for(j = 0; j < 2; ++j) {
518 m[0] = t[0] - 0xffed;
519 for(i = 1; i < 15; ++i) {
520 m[i] = t[i] - 0xffff - ((m[i - 1] >> 16) & 1);
521 m[i-1] &= 0xffff;
522 }
523 m[15] = t[15] - 0x7fff - ((m[14] >> 16) & 1);
524 b = (m[15] >> 16) & 1;
525 m[14] &= 0xffff;
526 sel25519(t, m, 1 - b);
527 }
528 for (i = 0; i < 16; i++) {
529 o[2 * i] = t[i] & 0xff;
530 o[2 * i + 1] = t[i] >> 8;
531 }
532}
533
534function unpackneg(r, p) {
535 var t = gf(), chk = gf(), num = gf(),
536 den = gf(), den2 = gf(), den4 = gf(),
537 den6 = gf();
538
539 set25519(r[2], gf1);
540 unpack25519(r[1], p);
541 S(num, r[1]);
542 M(den, num, D);
543 Z(num, num, r[2]);
544 A(den, r[2], den);
545
546 S(den2, den);
547 S(den4, den2);
548 M(den6, den4, den2);
549 M(t, den6, num);
550 M(t, t, den);
551
552 pow2523(t, t);
553 M(t, t, num);
554 M(t, t, den);
555 M(t, t, den);
556 M(r[0], t, den);
557
558 S(chk, r[0]);
559 M(chk, chk, den);
560 if(neq25519(chk, num)) {
561 M(r[0], r[0], I);
562 }
563
564 S(chk, r[0]);
565 M(chk, chk, den);
566 if(neq25519(chk, num)) {
567 return -1;
568 }
569
570 if(par25519(r[0]) === (p[31] >> 7)) {
571 Z(r[0], gf0, r[0]);
572 }
573
574 M(r[3], r[0], r[1]);
575 return 0;
576}
577
578function unpack25519(o, n) {
579 var i;
580 for(i = 0; i < 16; ++i) {
581 o[i] = n[2 * i] + (n[2 * i + 1] << 8);
582 }
583 o[15] &= 0x7fff;
584}
585
586function pow2523(o, i) {
587 var c = gf();
588 var a;
589 for(a = 0; a < 16; ++a) {
590 c[a] = i[a];
591 }
592 for(a = 250; a >= 0; --a) {
593 S(c, c);
594 if(a !== 1) {
595 M(c, c, i);
596 }
597 }
598 for(a = 0; a < 16; ++a) {
599 o[a] = c[a];
600 }
601}
602
603function neq25519(a, b) {
604 var c = new NativeBuffer(32);
605 var d = new NativeBuffer(32);
606 pack25519(c, a);
607 pack25519(d, b);
608 return crypto_verify_32(c, 0, d, 0);
609}
610
611function crypto_verify_32(x, xi, y, yi) {
612 return vn(x, xi, y, yi, 32);
613}
614
615function vn(x, xi, y, yi, n) {
616 var i, d = 0;
617 for(i = 0; i < n; ++i) {
618 d |= x[xi + i] ^ y[yi + i];
619 }
620 return (1 & ((d - 1) >>> 8)) - 1;
621}
622
623function par25519(a) {
624 var d = new NativeBuffer(32);
625 pack25519(d, a);
626 return d[0] & 1;
627}
628
629function scalarmult(p, q, s) {
630 var b, i;
631 set25519(p[0], gf0);
632 set25519(p[1], gf1);
633 set25519(p[2], gf1);
634 set25519(p[3], gf0);
635 for(i = 255; i >= 0; --i) {
636 b = (s[(i / 8)|0] >> (i & 7)) & 1;
637 cswap(p, q, b);
638 add(q, p);
639 add(p, p);
640 cswap(p, q, b);
641 }
642}
643
644function scalarbase(p, s) {
645 var q = [gf(), gf(), gf(), gf()];
646 set25519(q[0], X);
647 set25519(q[1], Y);
648 set25519(q[2], gf1);
649 M(q[3], X, Y);
650 scalarmult(p, q, s);
651}
652
653function set25519(r, a) {
654 var i;
655 for(i = 0; i < 16; i++) {
656 r[i] = a[i] | 0;
657 }
658}
659
660function inv25519(o, i) {
661 var c = gf();
662 var a;
663 for(a = 0; a < 16; ++a) {
664 c[a] = i[a];
665 }
666 for(a = 253; a >= 0; --a) {
667 S(c, c);
668 if(a !== 2 && a !== 4) {
669 M(c, c, i);
670 }
671 }
672 for(a = 0; a < 16; ++a) {
673 o[a] = c[a];
674 }
675}
676
677function car25519(o) {
678 var i, v, c = 1;
679 for(i = 0; i < 16; ++i) {
680 v = o[i] + c + 65535;
681 c = Math.floor(v / 65536);
682 o[i] = v - c * 65536;
683 }
684 o[0] += c - 1 + 37 * (c - 1);
685}
686
687function sel25519(p, q, b) {
688 var t, c = ~(b - 1);
689 for(var i = 0; i < 16; ++i) {
690 t = c & (p[i] ^ q[i]);
691 p[i] ^= t;
692 q[i] ^= t;
693 }
694}
695
696function gf(init) {
697 var i, r = new Float64Array(16);
698 if(init) {
699 for(i = 0; i < init.length; ++i) {
700 r[i] = init[i];
701 }
702 }
703 return r;
704}
705
706function A(o, a, b) {
707 for(var i = 0; i < 16; ++i) {
708 o[i] = a[i] + b[i];
709 }
710}
711
712function Z(o, a, b) {
713 for(var i = 0; i < 16; ++i) {
714 o[i] = a[i] - b[i];
715 }
716}
717
718function S(o, a) {
719 M(o, a, a);
720}
721
722function M(o, a, b) {
723 var v, c,
724 t0 = 0, t1 = 0, t2 = 0, t3 = 0, t4 = 0, t5 = 0, t6 = 0, t7 = 0,
725 t8 = 0, t9 = 0, t10 = 0, t11 = 0, t12 = 0, t13 = 0, t14 = 0, t15 = 0,
726 t16 = 0, t17 = 0, t18 = 0, t19 = 0, t20 = 0, t21 = 0, t22 = 0, t23 = 0,
727 t24 = 0, t25 = 0, t26 = 0, t27 = 0, t28 = 0, t29 = 0, t30 = 0,
728 b0 = b[0],
729 b1 = b[1],
730 b2 = b[2],
731 b3 = b[3],
732 b4 = b[4],
733 b5 = b[5],
734 b6 = b[6],
735 b7 = b[7],
736 b8 = b[8],
737 b9 = b[9],
738 b10 = b[10],
739 b11 = b[11],
740 b12 = b[12],
741 b13 = b[13],
742 b14 = b[14],
743 b15 = b[15];
744
745 v = a[0];
746 t0 += v * b0;
747 t1 += v * b1;
748 t2 += v * b2;
749 t3 += v * b3;
750 t4 += v * b4;
751 t5 += v * b5;
752 t6 += v * b6;
753 t7 += v * b7;
754 t8 += v * b8;
755 t9 += v * b9;
756 t10 += v * b10;
757 t11 += v * b11;
758 t12 += v * b12;
759 t13 += v * b13;
760 t14 += v * b14;
761 t15 += v * b15;
762 v = a[1];
763 t1 += v * b0;
764 t2 += v * b1;
765 t3 += v * b2;
766 t4 += v * b3;
767 t5 += v * b4;
768 t6 += v * b5;
769 t7 += v * b6;
770 t8 += v * b7;
771 t9 += v * b8;
772 t10 += v * b9;
773 t11 += v * b10;
774 t12 += v * b11;
775 t13 += v * b12;
776 t14 += v * b13;
777 t15 += v * b14;
778 t16 += v * b15;
779 v = a[2];
780 t2 += v * b0;
781 t3 += v * b1;
782 t4 += v * b2;
783 t5 += v * b3;
784 t6 += v * b4;
785 t7 += v * b5;
786 t8 += v * b6;
787 t9 += v * b7;
788 t10 += v * b8;
789 t11 += v * b9;
790 t12 += v * b10;
791 t13 += v * b11;
792 t14 += v * b12;
793 t15 += v * b13;
794 t16 += v * b14;
795 t17 += v * b15;
796 v = a[3];
797 t3 += v * b0;
798 t4 += v * b1;
799 t5 += v * b2;
800 t6 += v * b3;
801 t7 += v * b4;
802 t8 += v * b5;
803 t9 += v * b6;
804 t10 += v * b7;
805 t11 += v * b8;
806 t12 += v * b9;
807 t13 += v * b10;
808 t14 += v * b11;
809 t15 += v * b12;
810 t16 += v * b13;
811 t17 += v * b14;
812 t18 += v * b15;
813 v = a[4];
814 t4 += v * b0;
815 t5 += v * b1;
816 t6 += v * b2;
817 t7 += v * b3;
818 t8 += v * b4;
819 t9 += v * b5;
820 t10 += v * b6;
821 t11 += v * b7;
822 t12 += v * b8;
823 t13 += v * b9;
824 t14 += v * b10;
825 t15 += v * b11;
826 t16 += v * b12;
827 t17 += v * b13;
828 t18 += v * b14;
829 t19 += v * b15;
830 v = a[5];
831 t5 += v * b0;
832 t6 += v * b1;
833 t7 += v * b2;
834 t8 += v * b3;
835 t9 += v * b4;
836 t10 += v * b5;
837 t11 += v * b6;
838 t12 += v * b7;
839 t13 += v * b8;
840 t14 += v * b9;
841 t15 += v * b10;
842 t16 += v * b11;
843 t17 += v * b12;
844 t18 += v * b13;
845 t19 += v * b14;
846 t20 += v * b15;
847 v = a[6];
848 t6 += v * b0;
849 t7 += v * b1;
850 t8 += v * b2;
851 t9 += v * b3;
852 t10 += v * b4;
853 t11 += v * b5;
854 t12 += v * b6;
855 t13 += v * b7;
856 t14 += v * b8;
857 t15 += v * b9;
858 t16 += v * b10;
859 t17 += v * b11;
860 t18 += v * b12;
861 t19 += v * b13;
862 t20 += v * b14;
863 t21 += v * b15;
864 v = a[7];
865 t7 += v * b0;
866 t8 += v * b1;
867 t9 += v * b2;
868 t10 += v * b3;
869 t11 += v * b4;
870 t12 += v * b5;
871 t13 += v * b6;
872 t14 += v * b7;
873 t15 += v * b8;
874 t16 += v * b9;
875 t17 += v * b10;
876 t18 += v * b11;
877 t19 += v * b12;
878 t20 += v * b13;
879 t21 += v * b14;
880 t22 += v * b15;
881 v = a[8];
882 t8 += v * b0;
883 t9 += v * b1;
884 t10 += v * b2;
885 t11 += v * b3;
886 t12 += v * b4;
887 t13 += v * b5;
888 t14 += v * b6;
889 t15 += v * b7;
890 t16 += v * b8;
891 t17 += v * b9;
892 t18 += v * b10;
893 t19 += v * b11;
894 t20 += v * b12;
895 t21 += v * b13;
896 t22 += v * b14;
897 t23 += v * b15;
898 v = a[9];
899 t9 += v * b0;
900 t10 += v * b1;
901 t11 += v * b2;
902 t12 += v * b3;
903 t13 += v * b4;
904 t14 += v * b5;
905 t15 += v * b6;
906 t16 += v * b7;
907 t17 += v * b8;
908 t18 += v * b9;
909 t19 += v * b10;
910 t20 += v * b11;
911 t21 += v * b12;
912 t22 += v * b13;
913 t23 += v * b14;
914 t24 += v * b15;
915 v = a[10];
916 t10 += v * b0;
917 t11 += v * b1;
918 t12 += v * b2;
919 t13 += v * b3;
920 t14 += v * b4;
921 t15 += v * b5;
922 t16 += v * b6;
923 t17 += v * b7;
924 t18 += v * b8;
925 t19 += v * b9;
926 t20 += v * b10;
927 t21 += v * b11;
928 t22 += v * b12;
929 t23 += v * b13;
930 t24 += v * b14;
931 t25 += v * b15;
932 v = a[11];
933 t11 += v * b0;
934 t12 += v * b1;
935 t13 += v * b2;
936 t14 += v * b3;
937 t15 += v * b4;
938 t16 += v * b5;
939 t17 += v * b6;
940 t18 += v * b7;
941 t19 += v * b8;
942 t20 += v * b9;
943 t21 += v * b10;
944 t22 += v * b11;
945 t23 += v * b12;
946 t24 += v * b13;
947 t25 += v * b14;
948 t26 += v * b15;
949 v = a[12];
950 t12 += v * b0;
951 t13 += v * b1;
952 t14 += v * b2;
953 t15 += v * b3;
954 t16 += v * b4;
955 t17 += v * b5;
956 t18 += v * b6;
957 t19 += v * b7;
958 t20 += v * b8;
959 t21 += v * b9;
960 t22 += v * b10;
961 t23 += v * b11;
962 t24 += v * b12;
963 t25 += v * b13;
964 t26 += v * b14;
965 t27 += v * b15;
966 v = a[13];
967 t13 += v * b0;
968 t14 += v * b1;
969 t15 += v * b2;
970 t16 += v * b3;
971 t17 += v * b4;
972 t18 += v * b5;
973 t19 += v * b6;
974 t20 += v * b7;
975 t21 += v * b8;
976 t22 += v * b9;
977 t23 += v * b10;
978 t24 += v * b11;
979 t25 += v * b12;
980 t26 += v * b13;
981 t27 += v * b14;
982 t28 += v * b15;
983 v = a[14];
984 t14 += v * b0;
985 t15 += v * b1;
986 t16 += v * b2;
987 t17 += v * b3;
988 t18 += v * b4;
989 t19 += v * b5;
990 t20 += v * b6;
991 t21 += v * b7;
992 t22 += v * b8;
993 t23 += v * b9;
994 t24 += v * b10;
995 t25 += v * b11;
996 t26 += v * b12;
997 t27 += v * b13;
998 t28 += v * b14;
999 t29 += v * b15;
1000 v = a[15];
1001 t15 += v * b0;
1002 t16 += v * b1;
1003 t17 += v * b2;
1004 t18 += v * b3;
1005 t19 += v * b4;
1006 t20 += v * b5;
1007 t21 += v * b6;
1008 t22 += v * b7;
1009 t23 += v * b8;
1010 t24 += v * b9;
1011 t25 += v * b10;
1012 t26 += v * b11;
1013 t27 += v * b12;
1014 t28 += v * b13;
1015 t29 += v * b14;
1016 t30 += v * b15;
1017
1018 t0 += 38 * t16;
1019 t1 += 38 * t17;
1020 t2 += 38 * t18;
1021 t3 += 38 * t19;
1022 t4 += 38 * t20;
1023 t5 += 38 * t21;
1024 t6 += 38 * t22;
1025 t7 += 38 * t23;
1026 t8 += 38 * t24;
1027 t9 += 38 * t25;
1028 t10 += 38 * t26;
1029 t11 += 38 * t27;
1030 t12 += 38 * t28;
1031 t13 += 38 * t29;
1032 t14 += 38 * t30;
1033 // t15 left as is
1034
1035 // first car
1036 c = 1;
1037 v = t0 + c + 65535; c = Math.floor(v / 65536); t0 = v - c * 65536;
1038 v = t1 + c + 65535; c = Math.floor(v / 65536); t1 = v - c * 65536;
1039 v = t2 + c + 65535; c = Math.floor(v / 65536); t2 = v - c * 65536;
1040 v = t3 + c + 65535; c = Math.floor(v / 65536); t3 = v - c * 65536;
1041 v = t4 + c + 65535; c = Math.floor(v / 65536); t4 = v - c * 65536;
1042 v = t5 + c + 65535; c = Math.floor(v / 65536); t5 = v - c * 65536;
1043 v = t6 + c + 65535; c = Math.floor(v / 65536); t6 = v - c * 65536;
1044 v = t7 + c + 65535; c = Math.floor(v / 65536); t7 = v - c * 65536;
1045 v = t8 + c + 65535; c = Math.floor(v / 65536); t8 = v - c * 65536;
1046 v = t9 + c + 65535; c = Math.floor(v / 65536); t9 = v - c * 65536;
1047 v = t10 + c + 65535; c = Math.floor(v / 65536); t10 = v - c * 65536;
1048 v = t11 + c + 65535; c = Math.floor(v / 65536); t11 = v - c * 65536;
1049 v = t12 + c + 65535; c = Math.floor(v / 65536); t12 = v - c * 65536;
1050 v = t13 + c + 65535; c = Math.floor(v / 65536); t13 = v - c * 65536;
1051 v = t14 + c + 65535; c = Math.floor(v / 65536); t14 = v - c * 65536;
1052 v = t15 + c + 65535; c = Math.floor(v / 65536); t15 = v - c * 65536;
1053 t0 += c-1 + 37 * (c-1);
1054
1055 // second car
1056 c = 1;
1057 v = t0 + c + 65535; c = Math.floor(v / 65536); t0 = v - c * 65536;
1058 v = t1 + c + 65535; c = Math.floor(v / 65536); t1 = v - c * 65536;
1059 v = t2 + c + 65535; c = Math.floor(v / 65536); t2 = v - c * 65536;
1060 v = t3 + c + 65535; c = Math.floor(v / 65536); t3 = v - c * 65536;
1061 v = t4 + c + 65535; c = Math.floor(v / 65536); t4 = v - c * 65536;
1062 v = t5 + c + 65535; c = Math.floor(v / 65536); t5 = v - c * 65536;
1063 v = t6 + c + 65535; c = Math.floor(v / 65536); t6 = v - c * 65536;
1064 v = t7 + c + 65535; c = Math.floor(v / 65536); t7 = v - c * 65536;
1065 v = t8 + c + 65535; c = Math.floor(v / 65536); t8 = v - c * 65536;
1066 v = t9 + c + 65535; c = Math.floor(v / 65536); t9 = v - c * 65536;
1067 v = t10 + c + 65535; c = Math.floor(v / 65536); t10 = v - c * 65536;
1068 v = t11 + c + 65535; c = Math.floor(v / 65536); t11 = v - c * 65536;
1069 v = t12 + c + 65535; c = Math.floor(v / 65536); t12 = v - c * 65536;
1070 v = t13 + c + 65535; c = Math.floor(v / 65536); t13 = v - c * 65536;
1071 v = t14 + c + 65535; c = Math.floor(v / 65536); t14 = v - c * 65536;
1072 v = t15 + c + 65535; c = Math.floor(v / 65536); t15 = v - c * 65536;
1073 t0 += c-1 + 37 * (c-1);
1074
1075 o[ 0] = t0;
1076 o[ 1] = t1;
1077 o[ 2] = t2;
1078 o[ 3] = t3;
1079 o[ 4] = t4;
1080 o[ 5] = t5;
1081 o[ 6] = t6;
1082 o[ 7] = t7;
1083 o[ 8] = t8;
1084 o[ 9] = t9;
1085 o[10] = t10;
1086 o[11] = t11;
1087 o[12] = t12;
1088 o[13] = t13;
1089 o[14] = t14;
1090 o[15] = t15;
1091}
Note: See TracBrowser for help on using the repository browser.