OSDN Git Service

- add crypto-js library(for new hash access method).
[feedblog/feedblog.git] / js / crypto-js / components / aes.js
1 /*
2 CryptoJS v3.1.2
3 code.google.com/p/crypto-js
4 (c) 2009-2013 by Jeff Mott. All rights reserved.
5 code.google.com/p/crypto-js/wiki/License
6 */
7 (function () {\r
8     // Shortcuts\r
9     var C = CryptoJS;\r
10     var C_lib = C.lib;\r
11     var BlockCipher = C_lib.BlockCipher;\r
12     var C_algo = C.algo;\r
13 \r
14     // Lookup tables\r
15     var SBOX = [];\r
16     var INV_SBOX = [];\r
17     var SUB_MIX_0 = [];\r
18     var SUB_MIX_1 = [];\r
19     var SUB_MIX_2 = [];\r
20     var SUB_MIX_3 = [];\r
21     var INV_SUB_MIX_0 = [];\r
22     var INV_SUB_MIX_1 = [];\r
23     var INV_SUB_MIX_2 = [];\r
24     var INV_SUB_MIX_3 = [];\r
25 \r
26     // Compute lookup tables\r
27     (function () {\r
28         // Compute double table\r
29         var d = [];\r
30         for (var i = 0; i < 256; i++) {\r
31             if (i < 128) {\r
32                 d[i] = i << 1;\r
33             } else {\r
34                 d[i] = (i << 1) ^ 0x11b;\r
35             }\r
36         }\r
37 \r
38         // Walk GF(2^8)\r
39         var x = 0;\r
40         var xi = 0;\r
41         for (var i = 0; i < 256; i++) {\r
42             // Compute sbox\r
43             var sx = xi ^ (xi << 1) ^ (xi << 2) ^ (xi << 3) ^ (xi << 4);\r
44             sx = (sx >>> 8) ^ (sx & 0xff) ^ 0x63;\r
45             SBOX[x] = sx;\r
46             INV_SBOX[sx] = x;\r
47 \r
48             // Compute multiplication\r
49             var x2 = d[x];\r
50             var x4 = d[x2];\r
51             var x8 = d[x4];\r
52 \r
53             // Compute sub bytes, mix columns tables\r
54             var t = (d[sx] * 0x101) ^ (sx * 0x1010100);\r
55             SUB_MIX_0[x] = (t << 24) | (t >>> 8);\r
56             SUB_MIX_1[x] = (t << 16) | (t >>> 16);\r
57             SUB_MIX_2[x] = (t << 8)  | (t >>> 24);\r
58             SUB_MIX_3[x] = t;\r
59 \r
60             // Compute inv sub bytes, inv mix columns tables\r
61             var t = (x8 * 0x1010101) ^ (x4 * 0x10001) ^ (x2 * 0x101) ^ (x * 0x1010100);\r
62             INV_SUB_MIX_0[sx] = (t << 24) | (t >>> 8);\r
63             INV_SUB_MIX_1[sx] = (t << 16) | (t >>> 16);\r
64             INV_SUB_MIX_2[sx] = (t << 8)  | (t >>> 24);\r
65             INV_SUB_MIX_3[sx] = t;\r
66 \r
67             // Compute next counter\r
68             if (!x) {\r
69                 x = xi = 1;\r
70             } else {\r
71                 x = x2 ^ d[d[d[x8 ^ x2]]];\r
72                 xi ^= d[d[xi]];\r
73             }\r
74         }\r
75     }());\r
76 \r
77     // Precomputed Rcon lookup\r
78     var RCON = [0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36];\r
79 \r
80     /**\r
81      * AES block cipher algorithm.\r
82      */\r
83     var AES = C_algo.AES = BlockCipher.extend({\r
84         _doReset: function () {\r
85             // Shortcuts\r
86             var key = this._key;\r
87             var keyWords = key.words;\r
88             var keySize = key.sigBytes / 4;\r
89 \r
90             // Compute number of rounds\r
91             var nRounds = this._nRounds = keySize + 6\r
92 \r
93             // Compute number of key schedule rows\r
94             var ksRows = (nRounds + 1) * 4;\r
95 \r
96             // Compute key schedule\r
97             var keySchedule = this._keySchedule = [];\r
98             for (var ksRow = 0; ksRow < ksRows; ksRow++) {\r
99                 if (ksRow < keySize) {\r
100                     keySchedule[ksRow] = keyWords[ksRow];\r
101                 } else {\r
102                     var t = keySchedule[ksRow - 1];\r
103 \r
104                     if (!(ksRow % keySize)) {\r
105                         // Rot word\r
106                         t = (t << 8) | (t >>> 24);\r
107 \r
108                         // Sub word\r
109                         t = (SBOX[t >>> 24] << 24) | (SBOX[(t >>> 16) & 0xff] << 16) | (SBOX[(t >>> 8) & 0xff] << 8) | SBOX[t & 0xff];\r
110 \r
111                         // Mix Rcon\r
112                         t ^= RCON[(ksRow / keySize) | 0] << 24;\r
113                     } else if (keySize > 6 && ksRow % keySize == 4) {\r
114                         // Sub word\r
115                         t = (SBOX[t >>> 24] << 24) | (SBOX[(t >>> 16) & 0xff] << 16) | (SBOX[(t >>> 8) & 0xff] << 8) | SBOX[t & 0xff];\r
116                     }\r
117 \r
118                     keySchedule[ksRow] = keySchedule[ksRow - keySize] ^ t;\r
119                 }\r
120             }\r
121 \r
122             // Compute inv key schedule\r
123             var invKeySchedule = this._invKeySchedule = [];\r
124             for (var invKsRow = 0; invKsRow < ksRows; invKsRow++) {\r
125                 var ksRow = ksRows - invKsRow;\r
126 \r
127                 if (invKsRow % 4) {\r
128                     var t = keySchedule[ksRow];\r
129                 } else {\r
130                     var t = keySchedule[ksRow - 4];\r
131                 }\r
132 \r
133                 if (invKsRow < 4 || ksRow <= 4) {\r
134                     invKeySchedule[invKsRow] = t;\r
135                 } else {\r
136                     invKeySchedule[invKsRow] = INV_SUB_MIX_0[SBOX[t >>> 24]] ^ INV_SUB_MIX_1[SBOX[(t >>> 16) & 0xff]] ^\r
137                                                INV_SUB_MIX_2[SBOX[(t >>> 8) & 0xff]] ^ INV_SUB_MIX_3[SBOX[t & 0xff]];\r
138                 }\r
139             }\r
140         },\r
141 \r
142         encryptBlock: function (M, offset) {\r
143             this._doCryptBlock(M, offset, this._keySchedule, SUB_MIX_0, SUB_MIX_1, SUB_MIX_2, SUB_MIX_3, SBOX);\r
144         },\r
145 \r
146         decryptBlock: function (M, offset) {\r
147             // Swap 2nd and 4th rows\r
148             var t = M[offset + 1];\r
149             M[offset + 1] = M[offset + 3];\r
150             M[offset + 3] = t;\r
151 \r
152             this._doCryptBlock(M, offset, this._invKeySchedule, INV_SUB_MIX_0, INV_SUB_MIX_1, INV_SUB_MIX_2, INV_SUB_MIX_3, INV_SBOX);\r
153 \r
154             // Inv swap 2nd and 4th rows\r
155             var t = M[offset + 1];\r
156             M[offset + 1] = M[offset + 3];\r
157             M[offset + 3] = t;\r
158         },\r
159 \r
160         _doCryptBlock: function (M, offset, keySchedule, SUB_MIX_0, SUB_MIX_1, SUB_MIX_2, SUB_MIX_3, SBOX) {\r
161             // Shortcut\r
162             var nRounds = this._nRounds;\r
163 \r
164             // Get input, add round key\r
165             var s0 = M[offset]     ^ keySchedule[0];\r
166             var s1 = M[offset + 1] ^ keySchedule[1];\r
167             var s2 = M[offset + 2] ^ keySchedule[2];\r
168             var s3 = M[offset + 3] ^ keySchedule[3];\r
169 \r
170             // Key schedule row counter\r
171             var ksRow = 4;\r
172 \r
173             // Rounds\r
174             for (var round = 1; round < nRounds; round++) {\r
175                 // Shift rows, sub bytes, mix columns, add round key\r
176                 var 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++];\r
177                 var 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++];\r
178                 var 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++];\r
179                 var 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++];\r
180 \r
181                 // Update state\r
182                 s0 = t0;\r
183                 s1 = t1;\r
184                 s2 = t2;\r
185                 s3 = t3;\r
186             }\r
187 \r
188             // Shift rows, sub bytes, add round key\r
189             var t0 = ((SBOX[s0 >>> 24] << 24) | (SBOX[(s1 >>> 16) & 0xff] << 16) | (SBOX[(s2 >>> 8) & 0xff] << 8) | SBOX[s3 & 0xff]) ^ keySchedule[ksRow++];\r
190             var t1 = ((SBOX[s1 >>> 24] << 24) | (SBOX[(s2 >>> 16) & 0xff] << 16) | (SBOX[(s3 >>> 8) & 0xff] << 8) | SBOX[s0 & 0xff]) ^ keySchedule[ksRow++];\r
191             var t2 = ((SBOX[s2 >>> 24] << 24) | (SBOX[(s3 >>> 16) & 0xff] << 16) | (SBOX[(s0 >>> 8) & 0xff] << 8) | SBOX[s1 & 0xff]) ^ keySchedule[ksRow++];\r
192             var t3 = ((SBOX[s3 >>> 24] << 24) | (SBOX[(s0 >>> 16) & 0xff] << 16) | (SBOX[(s1 >>> 8) & 0xff] << 8) | SBOX[s2 & 0xff]) ^ keySchedule[ksRow++];\r
193 \r
194             // Set output\r
195             M[offset]     = t0;\r
196             M[offset + 1] = t1;\r
197             M[offset + 2] = t2;\r
198             M[offset + 3] = t3;\r
199         },\r
200 \r
201         keySize: 256/32\r
202     });\r
203 \r
204     /**\r
205      * Shortcut functions to the cipher's object interface.\r
206      *\r
207      * @example\r
208      *\r
209      *     var ciphertext = CryptoJS.AES.encrypt(message, key, cfg);\r
210      *     var plaintext  = CryptoJS.AES.decrypt(ciphertext, key, cfg);\r
211      */\r
212     C.AES = BlockCipher._createHelper(AES);\r
213 }());\r