aes.js 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. // based on the aes implimentation in triple sec
  2. // https://github.com/keybase/triplesec
  3. // which is in turn based on the one from crypto-js
  4. // https://code.google.com/p/crypto-js/
  5. var uint_max = Math.pow(2, 32)
  6. function fixup_uint32 (x) {
  7. var ret, x_pos
  8. ret = x > uint_max || x < 0 ? (x_pos = Math.abs(x) % uint_max, x < 0 ? uint_max - x_pos : x_pos) : x
  9. return ret
  10. }
  11. function scrub_vec (v) {
  12. for (var i = 0; i < v.length; v++) {
  13. v[i] = 0
  14. }
  15. return false
  16. }
  17. function Global () {
  18. this.SBOX = []
  19. this.INV_SBOX = []
  20. this.SUB_MIX = [[], [], [], []]
  21. this.INV_SUB_MIX = [[], [], [], []]
  22. this.init()
  23. this.RCON = [0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36]
  24. }
  25. Global.prototype.init = function () {
  26. var d, i, sx, t, x, x2, x4, x8, xi, _i
  27. d = (function () {
  28. var _i, _results
  29. _results = []
  30. for (i = _i = 0; _i < 256; i = ++_i) {
  31. if (i < 128) {
  32. _results.push(i << 1)
  33. } else {
  34. _results.push((i << 1) ^ 0x11b)
  35. }
  36. }
  37. return _results
  38. })()
  39. x = 0
  40. xi = 0
  41. for (i = _i = 0; _i < 256; i = ++_i) {
  42. sx = xi ^ (xi << 1) ^ (xi << 2) ^ (xi << 3) ^ (xi << 4)
  43. sx = (sx >>> 8) ^ (sx & 0xff) ^ 0x63
  44. this.SBOX[x] = sx
  45. this.INV_SBOX[sx] = x
  46. x2 = d[x]
  47. x4 = d[x2]
  48. x8 = d[x4]
  49. t = (d[sx] * 0x101) ^ (sx * 0x1010100)
  50. this.SUB_MIX[0][x] = (t << 24) | (t >>> 8)
  51. this.SUB_MIX[1][x] = (t << 16) | (t >>> 16)
  52. this.SUB_MIX[2][x] = (t << 8) | (t >>> 24)
  53. this.SUB_MIX[3][x] = t
  54. t = (x8 * 0x1010101) ^ (x4 * 0x10001) ^ (x2 * 0x101) ^ (x * 0x1010100)
  55. this.INV_SUB_MIX[0][sx] = (t << 24) | (t >>> 8)
  56. this.INV_SUB_MIX[1][sx] = (t << 16) | (t >>> 16)
  57. this.INV_SUB_MIX[2][sx] = (t << 8) | (t >>> 24)
  58. this.INV_SUB_MIX[3][sx] = t
  59. if (x === 0) {
  60. x = xi = 1
  61. } else {
  62. x = x2 ^ d[d[d[x8 ^ x2]]]
  63. xi ^= d[d[xi]]
  64. }
  65. }
  66. return true
  67. }
  68. var G = new Global()
  69. AES.blockSize = 4 * 4
  70. AES.prototype.blockSize = AES.blockSize
  71. AES.keySize = 256 / 8
  72. AES.prototype.keySize = AES.keySize
  73. function bufferToArray (buf) {
  74. var len = buf.length / 4
  75. var out = new Array(len)
  76. var i = -1
  77. while (++i < len) {
  78. out[i] = buf.readUInt32BE(i * 4)
  79. }
  80. return out
  81. }
  82. function AES (key) {
  83. this._key = bufferToArray(key)
  84. this._doReset()
  85. }
  86. AES.prototype._doReset = function () {
  87. var invKsRow, keySize, keyWords, ksRow, ksRows, t
  88. keyWords = this._key
  89. keySize = keyWords.length
  90. this._nRounds = keySize + 6
  91. ksRows = (this._nRounds + 1) * 4
  92. this._keySchedule = []
  93. for (ksRow = 0; ksRow < ksRows; ksRow++) {
  94. this._keySchedule[ksRow] = ksRow < keySize ? keyWords[ksRow] : (t = this._keySchedule[ksRow - 1], (ksRow % keySize) === 0 ? (t = (t << 8) | (t >>> 24), t = (G.SBOX[t >>> 24] << 24) | (G.SBOX[(t >>> 16) & 0xff] << 16) | (G.SBOX[(t >>> 8) & 0xff] << 8) | G.SBOX[t & 0xff], t ^= G.RCON[(ksRow / keySize) | 0] << 24) : keySize > 6 && ksRow % keySize === 4 ? t = (G.SBOX[t >>> 24] << 24) | (G.SBOX[(t >>> 16) & 0xff] << 16) | (G.SBOX[(t >>> 8) & 0xff] << 8) | G.SBOX[t & 0xff] : void 0, this._keySchedule[ksRow - keySize] ^ t)
  95. }
  96. this._invKeySchedule = []
  97. for (invKsRow = 0; invKsRow < ksRows; invKsRow++) {
  98. ksRow = ksRows - invKsRow
  99. t = this._keySchedule[ksRow - (invKsRow % 4 ? 0 : 4)]
  100. this._invKeySchedule[invKsRow] = invKsRow < 4 || ksRow <= 4 ? t : G.INV_SUB_MIX[0][G.SBOX[t >>> 24]] ^ G.INV_SUB_MIX[1][G.SBOX[(t >>> 16) & 0xff]] ^ G.INV_SUB_MIX[2][G.SBOX[(t >>> 8) & 0xff]] ^ G.INV_SUB_MIX[3][G.SBOX[t & 0xff]]
  101. }
  102. return true
  103. }
  104. AES.prototype.encryptBlock = function (M) {
  105. M = bufferToArray(new Buffer(M))
  106. var out = this._doCryptBlock(M, this._keySchedule, G.SUB_MIX, G.SBOX)
  107. var buf = new Buffer(16)
  108. buf.writeUInt32BE(out[0], 0)
  109. buf.writeUInt32BE(out[1], 4)
  110. buf.writeUInt32BE(out[2], 8)
  111. buf.writeUInt32BE(out[3], 12)
  112. return buf
  113. }
  114. AES.prototype.decryptBlock = function (M) {
  115. M = bufferToArray(new Buffer(M))
  116. var temp = [M[3], M[1]]
  117. M[1] = temp[0]
  118. M[3] = temp[1]
  119. var out = this._doCryptBlock(M, this._invKeySchedule, G.INV_SUB_MIX, G.INV_SBOX)
  120. var buf = new Buffer(16)
  121. buf.writeUInt32BE(out[0], 0)
  122. buf.writeUInt32BE(out[3], 4)
  123. buf.writeUInt32BE(out[2], 8)
  124. buf.writeUInt32BE(out[1], 12)
  125. return buf
  126. }
  127. AES.prototype.scrub = function () {
  128. scrub_vec(this._keySchedule)
  129. scrub_vec(this._invKeySchedule)
  130. scrub_vec(this._key)
  131. }
  132. AES.prototype._doCryptBlock = function (M, keySchedule, SUB_MIX, SBOX) {
  133. var ksRow, s0, s1, s2, s3, t0, t1, t2, t3
  134. s0 = M[0] ^ keySchedule[0]
  135. s1 = M[1] ^ keySchedule[1]
  136. s2 = M[2] ^ keySchedule[2]
  137. s3 = M[3] ^ keySchedule[3]
  138. ksRow = 4
  139. for (var round = 1; round < this._nRounds; round++) {
  140. t0 = SUB_MIX[0][s0 >>> 24] ^ SUB_MIX[1][(s1 >>> 16) & 0xff] ^ SUB_MIX[2][(s2 >>> 8) & 0xff] ^ SUB_MIX[3][s3 & 0xff] ^ keySchedule[ksRow++]
  141. t1 = SUB_MIX[0][s1 >>> 24] ^ SUB_MIX[1][(s2 >>> 16) & 0xff] ^ SUB_MIX[2][(s3 >>> 8) & 0xff] ^ SUB_MIX[3][s0 & 0xff] ^ keySchedule[ksRow++]
  142. t2 = SUB_MIX[0][s2 >>> 24] ^ SUB_MIX[1][(s3 >>> 16) & 0xff] ^ SUB_MIX[2][(s0 >>> 8) & 0xff] ^ SUB_MIX[3][s1 & 0xff] ^ keySchedule[ksRow++]
  143. t3 = SUB_MIX[0][s3 >>> 24] ^ SUB_MIX[1][(s0 >>> 16) & 0xff] ^ SUB_MIX[2][(s1 >>> 8) & 0xff] ^ SUB_MIX[3][s2 & 0xff] ^ keySchedule[ksRow++]
  144. s0 = t0
  145. s1 = t1
  146. s2 = t2
  147. s3 = t3
  148. }
  149. t0 = ((SBOX[s0 >>> 24] << 24) | (SBOX[(s1 >>> 16) & 0xff] << 16) | (SBOX[(s2 >>> 8) & 0xff] << 8) | SBOX[s3 & 0xff]) ^ keySchedule[ksRow++]
  150. t1 = ((SBOX[s1 >>> 24] << 24) | (SBOX[(s2 >>> 16) & 0xff] << 16) | (SBOX[(s3 >>> 8) & 0xff] << 8) | SBOX[s0 & 0xff]) ^ keySchedule[ksRow++]
  151. t2 = ((SBOX[s2 >>> 24] << 24) | (SBOX[(s3 >>> 16) & 0xff] << 16) | (SBOX[(s0 >>> 8) & 0xff] << 8) | SBOX[s1 & 0xff]) ^ keySchedule[ksRow++]
  152. t3 = ((SBOX[s3 >>> 24] << 24) | (SBOX[(s0 >>> 16) & 0xff] << 16) | (SBOX[(s1 >>> 8) & 0xff] << 8) | SBOX[s2 & 0xff]) ^ keySchedule[ksRow++]
  153. return [
  154. fixup_uint32(t0),
  155. fixup_uint32(t1),
  156. fixup_uint32(t2),
  157. fixup_uint32(t3)
  158. ]
  159. }
  160. exports.AES = AES