1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 | var uint_max = Math.pow(2, 32)
|
8 | function 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 | }
|
13 | function scrub_vec (v) {
|
14 | for (var i = 0; i < v.length; v++) {
|
15 | v[i] = 0
|
16 | }
|
17 | return false
|
18 | }
|
19 |
|
20 | function 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 |
|
29 | Global.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 |
|
73 | var G = new Global()
|
74 |
|
75 | AES.blockSize = 4 * 4
|
76 |
|
77 | AES.prototype.blockSize = AES.blockSize
|
78 |
|
79 | AES.keySize = 256 / 8
|
80 |
|
81 | AES.prototype.keySize = AES.keySize
|
82 |
|
83 | function 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 | }
|
92 | function AES (key) {
|
93 | this._key = bufferToArray(key)
|
94 | this._doReset()
|
95 | }
|
96 |
|
97 | AES.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 |
|
116 | AES.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 |
|
127 | AES.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 |
|
141 | AES.prototype.scrub = function () {
|
142 | scrub_vec(this._keySchedule)
|
143 | scrub_vec(this._invKeySchedule)
|
144 | scrub_vec(this._key)
|
145 | }
|
146 |
|
147 | AES.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 |
|
177 | exports.AES = AES
|