core.js 20 KB

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