RSAUtils.js 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696
  1. /*
  2. * RSA, a suite of routines for performing RSA public-key computations in JavaScript.
  3. * Copyright 1998-2005 David Shapiro.
  4. * Dave Shapiro
  5. * dave@ohdave.com
  6. * changed by Fuchun, 2010-05-06
  7. * fcrpg2005@gmail.com
  8. */
  9. /*
  10. * Modified by +v then, 2018-03-28
  11. */
  12. var RSAUtils = {}
  13. // var biRadixBase = 2
  14. var biRadixBits = 16
  15. var bitsPerDigit = biRadixBits
  16. var biRadix = 1 << 16 // = 2^16 = 65536
  17. var biHalfRadix = biRadix >>> 1
  18. var biRadixSquared = biRadix * biRadix
  19. var maxDigitVal = biRadix - 1
  20. // var maxInteger = 9999999999999998
  21. // maxDigits:
  22. // Change this to accommodate your largest number size. Use setMaxDigits()
  23. // to change it!
  24. //
  25. // In general, if you're working with numbers of size N bits, you'll need 2*N
  26. // bits of storage. Each digit holds 16 bits. So, a 1024-bit key will need
  27. //
  28. // 1024 * 2 / 16 = 128 digits of storage.
  29. //
  30. var maxDigits
  31. var ZERO_ARRAY
  32. var bigZero, bigOne
  33. var BigInt = function (flag) {
  34. if (typeof flag === 'boolean' && flag === true) {
  35. this.digits = null
  36. } else {
  37. this.digits = ZERO_ARRAY.slice(0)
  38. }
  39. this.isNeg = false
  40. }
  41. RSAUtils.setMaxDigits = function (value) {
  42. maxDigits = value
  43. ZERO_ARRAY = new Array(maxDigits)
  44. for (var iza = 0; iza < ZERO_ARRAY.length; iza++) {
  45. ZERO_ARRAY[iza] = 0
  46. }
  47. bigZero = new BigInt()
  48. bigOne = new BigInt()
  49. bigOne.digits[0] = 1
  50. }
  51. RSAUtils.setMaxDigits(20)
  52. // The maximum number of digits in base 10 you can convert to an
  53. // integer without JavaScript throwing up on you.
  54. var dpl10 = 15
  55. RSAUtils.biFromNumber = function (i) {
  56. var result = new BigInt()
  57. result.isNeg = i < 0
  58. i = Math.abs(i)
  59. var j = 0
  60. while (i > 0) {
  61. result.digits[j++] = i & maxDigitVal
  62. i = Math.floor(i / biRadix)
  63. }
  64. return result
  65. }
  66. // lr10 = 10 ^ dpl10
  67. var lr10 = RSAUtils.biFromNumber(1000000000000000)
  68. RSAUtils.biFromDecimal = function (s) {
  69. var isNeg = s.charAt(0) === '-'
  70. var i = isNeg ? 1 : 0
  71. var result
  72. // Skip leading zeros.
  73. while (i < s.length && s.charAt(i) === '0') ++i
  74. if (i === s.length) {
  75. result = new BigInt()
  76. } else {
  77. var digitCount = s.length - i
  78. var fgl = digitCount % dpl10
  79. if (fgl === 0) fgl = dpl10
  80. result = RSAUtils.biFromNumber(Number(s.substr(i, fgl)))
  81. i += fgl
  82. while (i < s.length) {
  83. result = RSAUtils.biAdd(RSAUtils.biMultiply(result, lr10),
  84. RSAUtils.biFromNumber(Number(s.substr(i, dpl10))))
  85. i += dpl10
  86. }
  87. result.isNeg = isNeg
  88. }
  89. return result
  90. }
  91. RSAUtils.biCopy = function (bi) {
  92. var result = new BigInt(true)
  93. result.digits = bi.digits.slice(0)
  94. result.isNeg = bi.isNeg
  95. return result
  96. }
  97. RSAUtils.reverseStr = function (s) {
  98. var result = ''
  99. for (var i = s.length - 1; i > -1; --i) {
  100. result += s.charAt(i)
  101. }
  102. return result
  103. }
  104. var hexatrigesimalToChar = [
  105. '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
  106. 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
  107. 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
  108. 'u', 'v', 'w', 'x', 'y', 'z'
  109. ]
  110. RSAUtils.biToString = function (x, radix) { // 2 <= radix <= 36
  111. var b = new BigInt()
  112. b.digits[0] = radix
  113. var qr = RSAUtils.biDivideModulo(x, b)
  114. var result = hexatrigesimalToChar[qr[1].digits[0]]
  115. while (RSAUtils.biCompare(qr[0], bigZero) === 1) {
  116. qr = RSAUtils.biDivideModulo(qr[0], b)
  117. // digit = qr[1].digits[0]
  118. result += hexatrigesimalToChar[qr[1].digits[0]]
  119. }
  120. return (x.isNeg ? '-' : '') + RSAUtils.reverseStr(result)
  121. }
  122. RSAUtils.biToDecimal = function (x) {
  123. var b = new BigInt()
  124. b.digits[0] = 10
  125. var qr = RSAUtils.biDivideModulo(x, b)
  126. var result = String(qr[1].digits[0])
  127. while (RSAUtils.biCompare(qr[0], bigZero) === 1) {
  128. qr = RSAUtils.biDivideModulo(qr[0], b)
  129. result += String(qr[1].digits[0])
  130. }
  131. return (x.isNeg ? '-' : '') + RSAUtils.reverseStr(result)
  132. }
  133. var hexToChar = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
  134. 'a', 'b', 'c', 'd', 'e', 'f']
  135. RSAUtils.digitToHex = function (n) {
  136. var mask = 0xf
  137. var result = ''
  138. for (var i = 0; i < 4; ++i) {
  139. result += hexToChar[n & mask]
  140. n >>>= 4
  141. }
  142. return RSAUtils.reverseStr(result)
  143. }
  144. RSAUtils.biToHex = function (x) {
  145. var result = ''
  146. // var n = RSAUtils.biHighIndex(x)
  147. for (var i = RSAUtils.biHighIndex(x); i > -1; --i) {
  148. result += RSAUtils.digitToHex(x.digits[i])
  149. }
  150. return result
  151. }
  152. RSAUtils.charToHex = function (c) {
  153. var ZERO = 48
  154. var NINE = ZERO + 9
  155. var littleA = 97
  156. var littleZ = littleA + 25
  157. var bigA = 65
  158. var bigZ = 65 + 25
  159. var result
  160. if (c >= ZERO && c <= NINE) {
  161. result = c - ZERO
  162. } else if (c >= bigA && c <= bigZ) {
  163. result = 10 + c - bigA
  164. } else if (c >= littleA && c <= littleZ) {
  165. result = 10 + c - littleA
  166. } else {
  167. result = 0
  168. }
  169. return result
  170. }
  171. RSAUtils.hexToDigit = function (s) {
  172. var result = 0
  173. var sl = Math.min(s.length, 4)
  174. for (var i = 0; i < sl; ++i) {
  175. result <<= 4
  176. result |= RSAUtils.charToHex(s.charCodeAt(i))
  177. }
  178. return result
  179. }
  180. RSAUtils.biFromHex = function (s) {
  181. var result = new BigInt()
  182. var sl = s.length
  183. for (var i = sl, j = 0; i > 0; i -= 4, ++j) {
  184. result.digits[j] = RSAUtils.hexToDigit(s.substr(Math.max(i - 4, 0), Math.min(i, 4)))
  185. }
  186. return result
  187. }
  188. RSAUtils.biFromString = function (s, radix) {
  189. var isNeg = s.charAt(0) === '-'
  190. var istop = isNeg ? 1 : 0
  191. var result = new BigInt()
  192. var place = new BigInt()
  193. place.digits[0] = 1 // radix^0
  194. for (var i = s.length - 1; i >= istop; i--) {
  195. var c = s.charCodeAt(i)
  196. var digit = RSAUtils.charToHex(c)
  197. var biDigit = RSAUtils.biMultiplyDigit(place, digit)
  198. result = RSAUtils.biAdd(result, biDigit)
  199. place = RSAUtils.biMultiplyDigit(place, radix)
  200. }
  201. result.isNeg = isNeg
  202. return result
  203. }
  204. RSAUtils.biDump = function (b) {
  205. return (b.isNeg ? '-' : '') + b.digits.join(' ')
  206. }
  207. RSAUtils.biAdd = function (x, y) {
  208. var result
  209. if (x.isNeg !== y.isNeg) {
  210. y.isNeg = !y.isNeg
  211. result = RSAUtils.biSubtract(x, y)
  212. y.isNeg = !y.isNeg
  213. } else {
  214. result = new BigInt()
  215. var c = 0
  216. var n
  217. for (var i = 0; i < x.digits.length; ++i) {
  218. n = x.digits[i] + y.digits[i] + c
  219. result.digits[i] = n % biRadix
  220. c = Number(n >= biRadix)
  221. }
  222. result.isNeg = x.isNeg
  223. }
  224. return result
  225. }
  226. RSAUtils.biSubtract = function (x, y) {
  227. var result
  228. if (x.isNeg !== y.isNeg) {
  229. y.isNeg = !y.isNeg
  230. result = RSAUtils.biAdd(x, y)
  231. y.isNeg = !y.isNeg
  232. } else {
  233. result = new BigInt()
  234. var n, c
  235. c = 0
  236. for (var i = 0; i < x.digits.length; ++i) {
  237. n = x.digits[i] - y.digits[i] + c
  238. result.digits[i] = n % biRadix
  239. // Stupid non-conforming modulus operation.
  240. if (result.digits[i] < 0) result.digits[i] += biRadix
  241. c = 0 - Number(n < 0)
  242. }
  243. // Fix up the negative sign, if any.
  244. if (c === -1) {
  245. c = 0
  246. for (i = 0; i < x.digits.length; ++i) {
  247. n = 0 - result.digits[i] + c
  248. result.digits[i] = n % biRadix
  249. // Stupid non-conforming modulus operation.
  250. if (result.digits[i] < 0) result.digits[i] += biRadix
  251. c = 0 - Number(n < 0)
  252. }
  253. // Result is opposite sign of arguments.
  254. result.isNeg = !x.isNeg
  255. } else {
  256. // Result is same sign.
  257. result.isNeg = x.isNeg
  258. }
  259. }
  260. return result
  261. }
  262. RSAUtils.biHighIndex = function (x) {
  263. var result = x.digits.length - 1
  264. while (result > 0 && x.digits[result] === 0) --result
  265. return result
  266. }
  267. RSAUtils.biNumBits = function (x) {
  268. var n = RSAUtils.biHighIndex(x)
  269. var d = x.digits[n]
  270. var m = (n + 1) * bitsPerDigit
  271. var result
  272. for (result = m; result > m - bitsPerDigit; --result) {
  273. if ((d & 0x8000) !== 0) break
  274. d <<= 1
  275. }
  276. return result
  277. }
  278. RSAUtils.biMultiply = function (x, y) {
  279. var result = new BigInt()
  280. var c
  281. var n = RSAUtils.biHighIndex(x)
  282. var t = RSAUtils.biHighIndex(y)
  283. // var u, uv, k
  284. var uv, k
  285. for (var i = 0; i <= t; ++i) {
  286. c = 0
  287. k = i
  288. for (var j = 0; j <= n; ++j, ++k) {
  289. uv = result.digits[k] + x.digits[j] * y.digits[i] + c
  290. result.digits[k] = uv & maxDigitVal
  291. c = uv >>> biRadixBits
  292. // c = Math.floor(uv / biRadix);
  293. }
  294. result.digits[i + n + 1] = c
  295. }
  296. // Someone give me a logical xor, please.
  297. result.isNeg = x.isNeg !== y.isNeg
  298. return result
  299. }
  300. RSAUtils.biMultiplyDigit = function (x, y) {
  301. var n, c, uv, result
  302. result = new BigInt()
  303. n = RSAUtils.biHighIndex(x)
  304. c = 0
  305. for (var j = 0; j <= n; ++j) {
  306. uv = result.digits[j] + x.digits[j] * y + c
  307. result.digits[j] = uv & maxDigitVal
  308. c = uv >>> biRadixBits
  309. // c = Math.floor(uv / biRadix);
  310. }
  311. result.digits[1 + n] = c
  312. return result
  313. }
  314. RSAUtils.arrayCopy = function (src, srcStart, dest, destStart, n) {
  315. var m = Math.min(srcStart + n, src.length)
  316. for (var i = srcStart, j = destStart; i < m; ++i, ++j) {
  317. dest[j] = src[i]
  318. }
  319. }
  320. var highBitMasks = [0x0000, 0x8000, 0xC000, 0xE000, 0xF000, 0xF800,
  321. 0xFC00, 0xFE00, 0xFF00, 0xFF80, 0xFFC0, 0xFFE0,
  322. 0xFFF0, 0xFFF8, 0xFFFC, 0xFFFE, 0xFFFF]
  323. RSAUtils.biShiftLeft = function (x, n) {
  324. var digitCount = Math.floor(n / bitsPerDigit)
  325. var result = new BigInt()
  326. RSAUtils.arrayCopy(x.digits, 0, result.digits, digitCount,
  327. result.digits.length - digitCount)
  328. var bits = n % bitsPerDigit
  329. var rightBits = bitsPerDigit - bits
  330. for (var i = result.digits.length - 1, i1 = i - 1; i > 0; --i, --i1) {
  331. result.digits[i] = ((result.digits[i] << bits) & maxDigitVal) |
  332. ((result.digits[i1] & highBitMasks[bits]) >>>
  333. (rightBits))
  334. }
  335. result.digits[0] = ((result.digits[i] << bits) & maxDigitVal)
  336. result.isNeg = x.isNeg
  337. return result
  338. }
  339. var lowBitMasks = [0x0000, 0x0001, 0x0003, 0x0007, 0x000F, 0x001F,
  340. 0x003F, 0x007F, 0x00FF, 0x01FF, 0x03FF, 0x07FF,
  341. 0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF]
  342. RSAUtils.biShiftRight = function (x, n) {
  343. var digitCount = Math.floor(n / bitsPerDigit)
  344. var result = new BigInt()
  345. RSAUtils.arrayCopy(x.digits, digitCount, result.digits, 0,
  346. x.digits.length - digitCount)
  347. var bits = n % bitsPerDigit
  348. var leftBits = bitsPerDigit - bits
  349. for (var i = 0, i1 = i + 1; i < result.digits.length - 1; ++i, ++i1) {
  350. result.digits[i] = (result.digits[i] >>> bits) |
  351. ((result.digits[i1] & lowBitMasks[bits]) << leftBits)
  352. }
  353. result.digits[result.digits.length - 1] >>>= bits
  354. result.isNeg = x.isNeg
  355. return result
  356. }
  357. RSAUtils.biMultiplyByRadixPower = function (x, n) {
  358. var result = new BigInt()
  359. RSAUtils.arrayCopy(x.digits, 0, result.digits, n, result.digits.length - n)
  360. return result
  361. }
  362. RSAUtils.biDivideByRadixPower = function (x, n) {
  363. var result = new BigInt()
  364. RSAUtils.arrayCopy(x.digits, n, result.digits, 0, result.digits.length - n)
  365. return result
  366. }
  367. RSAUtils.biModuloByRadixPower = function (x, n) {
  368. var result = new BigInt()
  369. RSAUtils.arrayCopy(x.digits, 0, result.digits, 0, n)
  370. return result
  371. }
  372. RSAUtils.biCompare = function (x, y) {
  373. if (x.isNeg !== y.isNeg) {
  374. return 1 - 2 * Number(x.isNeg)
  375. }
  376. for (var i = x.digits.length - 1; i >= 0; --i) {
  377. if (x.digits[i] !== y.digits[i]) {
  378. if (x.isNeg) {
  379. return 1 - 2 * Number(x.digits[i] > y.digits[i])
  380. } else {
  381. return 1 - 2 * Number(x.digits[i] < y.digits[i])
  382. }
  383. }
  384. }
  385. return 0
  386. }
  387. RSAUtils.biDivideModulo = function (x, y) {
  388. var nb = RSAUtils.biNumBits(x)
  389. var tb = RSAUtils.biNumBits(y)
  390. var origYIsNeg = y.isNeg
  391. var q, r
  392. if (nb < tb) {
  393. // |x| < |y|
  394. if (x.isNeg) {
  395. q = RSAUtils.biCopy(bigOne)
  396. q.isNeg = !y.isNeg
  397. x.isNeg = false
  398. y.isNeg = false
  399. r = RSAUtils.biSubtract(y, x)
  400. // Restore signs, 'cause they're references.
  401. x.isNeg = true
  402. y.isNeg = origYIsNeg
  403. } else {
  404. q = new BigInt()
  405. r = RSAUtils.biCopy(x)
  406. }
  407. return [q, r]
  408. }
  409. q = new BigInt()
  410. r = x
  411. // Normalize Y.
  412. var t = Math.ceil(tb / bitsPerDigit) - 1
  413. var lambda = 0
  414. while (y.digits[t] < biHalfRadix) {
  415. y = RSAUtils.biShiftLeft(y, 1)
  416. ++lambda
  417. ++tb
  418. t = Math.ceil(tb / bitsPerDigit) - 1
  419. }
  420. // Shift r over to keep the quotient constant. We'll shift the
  421. // remainder back at the end.
  422. r = RSAUtils.biShiftLeft(r, lambda)
  423. nb += lambda // Update the bit count for x.
  424. var n = Math.ceil(nb / bitsPerDigit) - 1
  425. var b = RSAUtils.biMultiplyByRadixPower(y, n - t)
  426. while (RSAUtils.biCompare(r, b) !== -1) {
  427. ++q.digits[n - t]
  428. r = RSAUtils.biSubtract(r, b)
  429. }
  430. for (var i = n; i > t; --i) {
  431. var ri = (i >= r.digits.length) ? 0 : r.digits[i]
  432. var ri1 = (i - 1 >= r.digits.length) ? 0 : r.digits[i - 1]
  433. var ri2 = (i - 2 >= r.digits.length) ? 0 : r.digits[i - 2]
  434. var yt = (t >= y.digits.length) ? 0 : y.digits[t]
  435. var yt1 = (t - 1 >= y.digits.length) ? 0 : y.digits[t - 1]
  436. if (ri === yt) {
  437. q.digits[i - t - 1] = maxDigitVal
  438. } else {
  439. q.digits[i - t - 1] = Math.floor((ri * biRadix + ri1) / yt)
  440. }
  441. var c1 = q.digits[i - t - 1] * ((yt * biRadix) + yt1)
  442. var c2 = (ri * biRadixSquared) + ((ri1 * biRadix) + ri2)
  443. while (c1 > c2) {
  444. --q.digits[i - t - 1]
  445. c1 = q.digits[i - t - 1] * ((yt * biRadix) | yt1)
  446. c2 = (ri * biRadix * biRadix) + ((ri1 * biRadix) + ri2)
  447. }
  448. b = RSAUtils.biMultiplyByRadixPower(y, i - t - 1)
  449. r = RSAUtils.biSubtract(r, RSAUtils.biMultiplyDigit(b, q.digits[i - t - 1]))
  450. if (r.isNeg) {
  451. r = RSAUtils.biAdd(r, b)
  452. --q.digits[i - t - 1]
  453. }
  454. }
  455. r = RSAUtils.biShiftRight(r, lambda)
  456. // Fiddle with the signs and stuff to make sure that 0 <= r < y.
  457. q.isNeg = x.isNeg !== origYIsNeg
  458. if (x.isNeg) {
  459. if (origYIsNeg) {
  460. q = RSAUtils.biAdd(q, bigOne)
  461. } else {
  462. q = RSAUtils.biSubtract(q, bigOne)
  463. }
  464. y = RSAUtils.biShiftRight(y, lambda)
  465. r = RSAUtils.biSubtract(y, r)
  466. }
  467. // Check for the unbelievably stupid degenerate case of r === -0.
  468. if (r.digits[0] === 0 && RSAUtils.biHighIndex(r) === 0) r.isNeg = false
  469. return [q, r]
  470. }
  471. RSAUtils.biDivide = function (x, y) {
  472. return RSAUtils.biDivideModulo(x, y)[0]
  473. }
  474. RSAUtils.biModulo = function (x, y) {
  475. return RSAUtils.biDivideModulo(x, y)[1]
  476. }
  477. RSAUtils.biMultiplyMod = function (x, y, m) {
  478. return RSAUtils.biModulo(RSAUtils.biMultiply(x, y), m)
  479. }
  480. RSAUtils.biPow = function (x, y) {
  481. var result = bigOne
  482. var a = x
  483. while (true) {
  484. if ((y & 1) !== 0) result = RSAUtils.biMultiply(result, a)
  485. y >>= 1
  486. if (y === 0) break
  487. a = RSAUtils.biMultiply(a, a)
  488. }
  489. return result
  490. }
  491. RSAUtils.biPowMod = function (x, y, m) {
  492. var result = bigOne
  493. var a = x
  494. var k = y
  495. while (true) {
  496. if ((k.digits[0] & 1) !== 0) result = RSAUtils.biMultiplyMod(result, a, m)
  497. k = RSAUtils.biShiftRight(k, 1)
  498. if (k.digits[0] === 0 && RSAUtils.biHighIndex(k) === 0) break
  499. a = RSAUtils.biMultiplyMod(a, a, m)
  500. }
  501. return result
  502. }
  503. var BarrettMu = function (m) {
  504. this.modulus = RSAUtils.biCopy(m)
  505. this.k = RSAUtils.biHighIndex(this.modulus) + 1
  506. var b2k = new BigInt()
  507. b2k.digits[2 * this.k] = 1 // b2k = b^(2k)
  508. this.mu = RSAUtils.biDivide(b2k, this.modulus)
  509. this.bkplus1 = new BigInt()
  510. this.bkplus1.digits[this.k + 1] = 1 // bkplus1 = b^(k+1)
  511. this.modulo = BarrettMuModulo
  512. this.multiplyMod = BarrettMuMultiplyMod
  513. this.powMod = BarrettMuPowMod
  514. }
  515. function BarrettMuModulo(x) {
  516. var $dmath = RSAUtils
  517. var q1 = $dmath.biDivideByRadixPower(x, this.k - 1)
  518. var q2 = $dmath.biMultiply(q1, this.mu)
  519. var q3 = $dmath.biDivideByRadixPower(q2, this.k + 1)
  520. var r1 = $dmath.biModuloByRadixPower(x, this.k + 1)
  521. var r2term = $dmath.biMultiply(q3, this.modulus)
  522. var r2 = $dmath.biModuloByRadixPower(r2term, this.k + 1)
  523. var r = $dmath.biSubtract(r1, r2)
  524. if (r.isNeg) {
  525. r = $dmath.biAdd(r, this.bkplus1)
  526. }
  527. var rgtem = $dmath.biCompare(r, this.modulus) >= 0
  528. while (rgtem) {
  529. r = $dmath.biSubtract(r, this.modulus)
  530. rgtem = $dmath.biCompare(r, this.modulus) >= 0
  531. }
  532. return r
  533. }
  534. function BarrettMuMultiplyMod(x, y) {
  535. /*
  536. x = this.modulo(x);
  537. y = this.modulo(y);
  538. */
  539. var xy = RSAUtils.biMultiply(x, y)
  540. return this.modulo(xy)
  541. }
  542. function BarrettMuPowMod(x, y) {
  543. var result = new BigInt()
  544. result.digits[0] = 1
  545. var a = x
  546. var k = y
  547. while (true) {
  548. if ((k.digits[0] & 1) !== 0) result = this.multiplyMod(result, a)
  549. k = RSAUtils.biShiftRight(k, 1)
  550. if (k.digits[0] === 0 && RSAUtils.biHighIndex(k) === 0) break
  551. a = this.multiplyMod(a, a)
  552. }
  553. return result
  554. }
  555. var RSAKeyPair = function (encryptionExponent, decryptionExponent, modulus) {
  556. var $dmath = RSAUtils
  557. this.e = $dmath.biFromHex(encryptionExponent)
  558. this.d = $dmath.biFromHex(decryptionExponent)
  559. this.m = $dmath.biFromHex(modulus)
  560. // We can do two bytes per digit, so
  561. // chunkSize = 2 * (number of digits in modulus - 1).
  562. // Since biHighIndex returns the high index, not the number of digits, 1 has
  563. // already been subtracted.
  564. this.chunkSize = 2 * $dmath.biHighIndex(this.m)
  565. this.radix = 16
  566. this.barrett = new BarrettMu(this.m)
  567. }
  568. RSAUtils.getKeyPair = function (encryptionExponent, decryptionExponent, modulus) {
  569. return new RSAKeyPair(encryptionExponent, decryptionExponent, modulus)
  570. }
  571. // var twoDigit = function (n) {
  572. // return (n < 10 ? '0' : '') + String(n)
  573. // }
  574. // Altered by Rob Saunders (rob@robsaunders.net). New routine pads the
  575. // string after it has been converted to an array. This fixes an
  576. // incompatibility with Flash MX's ActionScript.
  577. RSAUtils.encryptedString = function (key, s) {
  578. var a = []
  579. var sl = s.length
  580. var i = 0
  581. while (i < sl) {
  582. a[i] = s.charCodeAt(i)
  583. i++
  584. }
  585. while (a.length % key.chunkSize !== 0) {
  586. a[i++] = 0
  587. }
  588. var al = a.length
  589. var result = ''
  590. var j, k, block
  591. for (i = 0; i < al; i += key.chunkSize) {
  592. block = new BigInt()
  593. j = 0
  594. for (k = i; k < i + key.chunkSize; ++j) {
  595. block.digits[j] = a[k++]
  596. block.digits[j] += a[k++] << 8
  597. }
  598. var crypt = key.barrett.powMod(block, key.e)
  599. var text = key.radix === 16 ? RSAUtils.biToHex(crypt) : RSAUtils.biToString(crypt, key.radix)
  600. result += text + ' '
  601. }
  602. return result.substring(0, result.length - 1) // Remove last space.
  603. }
  604. RSAUtils.decryptedString = function (key, s) {
  605. var blocks = s.split(' ')
  606. var result = ''
  607. var i, j, block
  608. for (i = 0; i < blocks.length; ++i) {
  609. var bi
  610. if (key.radix === 16) {
  611. bi = RSAUtils.biFromHex(blocks[i])
  612. } else {
  613. bi = RSAUtils.biFromString(blocks[i], key.radix)
  614. }
  615. block = key.barrett.powMod(bi, key.d)
  616. for (j = 0; j <= RSAUtils.biHighIndex(block); ++j) {
  617. result += String.fromCharCode(block.digits[j] & 255,
  618. block.digits[j] >> 8)
  619. }
  620. }
  621. // Remove trailing null, if any.
  622. if (result.charCodeAt(result.length - 1) === 0) {
  623. result = result.substring(0, result.length - 1)
  624. }
  625. return result
  626. }
  627. RSAUtils.setMaxDigits(130)
  628. module.exports = {
  629. RSAUtils
  630. };