You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1072 lines
24 KiB

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