UNPKG

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