程杰 1 year ago
parent
commit
17fc18197c
4 changed files with 939 additions and 937 deletions
  1. 4 2
      project.private.config.json
  2. 402 402
      utils/lib/AES.js
  3. 378 378
      utils/lib/BlockModes.js
  4. 155 155
      utils/lib/Crypto.js

+ 4 - 2
project.private.config.json

@@ -1,6 +1,7 @@
1 1
 {
2 2
   "setting": {
3
-    "urlCheck": false
3
+    "urlCheck": false,
4
+    "compileHotReLoad": true
4 5
   },
5 6
   "condition": {
6 7
     "miniprogram": {
@@ -49,5 +50,6 @@
49 50
     }
50 51
   },
51 52
   "description": "项目私有配置文件。此文件中的内容将覆盖 project.config.json 中的相同字段。项目的改动优先同步到此文件中。详见文档:https://developers.weixin.qq.com/miniprogram/dev/devtools/projectconfig.html",
52
-  "libVersion": "2.28.1"
53
+  "libVersion": "2.28.1",
54
+  "projectname": "%E7%A7%92%E8%BF%87"
53 55
 }

+ 402 - 402
utils/lib/AES.js

@@ -1,402 +1,402 @@
1
-(function(){
2
-
3
-var C = (typeof window === 'undefined') ? require('./Crypto').Crypto : window.Crypto;
4
-
5
-// Shortcuts
6
-var util = C.util,
7
-    charenc = C.charenc,
8
-    UTF8 = charenc.UTF8;
9
-
10
-// Precomputed SBOX
11
-var SBOX = [ 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5,
12
-             0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
13
-             0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0,
14
-             0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
15
-             0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc,
16
-             0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
17
-             0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a,
18
-             0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
19
-             0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0,
20
-             0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
21
-             0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b,
22
-             0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
23
-             0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85,
24
-             0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
25
-             0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5,
26
-             0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
27
-             0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17,
28
-             0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
29
-             0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88,
30
-             0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
31
-             0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c,
32
-             0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
33
-             0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9,
34
-             0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
35
-             0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6,
36
-             0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
37
-             0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e,
38
-             0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
39
-             0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94,
40
-             0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
41
-             0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68,
42
-             0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 ];
43
-
44
-// Compute inverse SBOX lookup table
45
-for (var INVSBOX = [], i = 0; i < 256; i++) INVSBOX[SBOX[i]] = i;
46
-
47
-// Compute mulitplication in GF(2^8) lookup tables
48
-var MULT2 = [],
49
-    MULT3 = [],
50
-    MULT9 = [],
51
-    MULTB = [],
52
-    MULTD = [],
53
-    MULTE = [];
54
-
55
-function xtime(a, b) {
56
-	for (var result = 0, i = 0; i < 8; i++) {
57
-		if (b & 1) result ^= a;
58
-		var hiBitSet = a & 0x80;
59
-		a = (a << 1) & 0xFF;
60
-		if (hiBitSet) a ^= 0x1b;
61
-		b >>>= 1;
62
-	}
63
-	return result;
64
-}
65
-
66
-for (var i = 0; i < 256; i++) {
67
-	MULT2[i] = xtime(i,2);
68
-	MULT3[i] = xtime(i,3);
69
-	MULT9[i] = xtime(i,9);
70
-	MULTB[i] = xtime(i,0xB);
71
-	MULTD[i] = xtime(i,0xD);
72
-	MULTE[i] = xtime(i,0xE);
73
-}
74
-
75
-// Precomputed RCon lookup
76
-var RCON = [0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36];
77
-
78
-// Inner state
79
-var state = [[], [], [], []],
80
-    keylength,
81
-    nrounds,
82
-    keyschedule;
83
-
84
-var AES = C.AES = {
85
-
86
-	/**
87
-	 * Public API
88
-	 */
89
-
90
-	encrypt: function (message, password, options) {
91
-
92
-		options = options || {};
93
-
94
-		// Determine mode
95
-		var mode = options.mode || new C.mode.OFB;
96
-
97
-		// Allow mode to override options
98
-		if (mode.fixOptions) mode.fixOptions(options);
99
-
100
-		var
101
-
102
-			// Convert to bytes if message is a string
103
-			m = (
104
-				message.constructor == String ?
105
-				UTF8.stringToBytes(message) :
106
-				message
107
-			),
108
-
109
-			// Generate random IV
110
-			iv = options.iv || util.randomBytes(AES._blocksize * 4),
111
-
112
-			// Generate key
113
-			k = (
114
-				password.constructor == String ?
115
-				// Derive key from passphrase
116
-				C.PBKDF2(password, iv, 32, { asBytes: true }) :
117
-				// else, assume byte array representing cryptographic key
118
-				password
119
-			);
120
-
121
-		// Encrypt
122
-		AES._init(k);
123
-		mode.encrypt(AES, m, iv);
124
-
125
-		// Return ciphertext
126
-		m = options.iv ? m : iv.concat(m);
127
-		return (options && options.asBytes) ? m : util.bytesToBase64(m);
128
-
129
-	},
130
-
131
-	decrypt: function (ciphertext, password, options) {
132
-
133
-		options = options || {};
134
-
135
-		// Determine mode
136
-		var mode = options.mode || new C.mode.OFB;
137
-
138
-		// Allow mode to override options
139
-		if (mode.fixOptions) mode.fixOptions(options);
140
-
141
-		var
142
-
143
-			// Convert to bytes if ciphertext is a string
144
-			c = (
145
-				ciphertext.constructor == String ?
146
-				util.base64ToBytes(ciphertext):
147
-			    ciphertext
148
-			),
149
-
150
-			// Separate IV and message
151
-			iv = options.iv || c.splice(0, AES._blocksize * 4),
152
-
153
-			// Generate key
154
-			k = (
155
-				password.constructor == String ?
156
-				// Derive key from passphrase
157
-				C.PBKDF2(password, iv, 32, { asBytes: true }) :
158
-				// else, assume byte array representing cryptographic key
159
-				password
160
-			);
161
-
162
-		// Decrypt
163
-		AES._init(k);
164
-		mode.decrypt(AES, c, iv);
165
-
166
-		// Return plaintext
167
-		return (options && options.asBytes) ? c : UTF8.bytesToString(c);
168
-
169
-	},
170
-
171
-
172
-	/**
173
-	 * Package private methods and properties
174
-	 */
175
-
176
-	_blocksize: 4,
177
-
178
-	_encryptblock: function (m, offset) {
179
-
180
-		// Set input
181
-		for (var row = 0; row < AES._blocksize; row++) {
182
-			for (var col = 0; col < 4; col++)
183
-				state[row][col] = m[offset + col * 4 + row];
184
-		}
185
-
186
-		// Add round key
187
-		for (var row = 0; row < 4; row++) {
188
-			for (var col = 0; col < 4; col++)
189
-				state[row][col] ^= keyschedule[col][row];
190
-		}
191
-
192
-		for (var round = 1; round < nrounds; round++) {
193
-
194
-			// Sub bytes
195
-			for (var row = 0; row < 4; row++) {
196
-				for (var col = 0; col < 4; col++)
197
-					state[row][col] = SBOX[state[row][col]];
198
-			}
199
-
200
-			// Shift rows
201
-			state[1].push(state[1].shift());
202
-			state[2].push(state[2].shift());
203
-			state[2].push(state[2].shift());
204
-			state[3].unshift(state[3].pop());
205
-
206
-			// Mix columns
207
-			for (var col = 0; col < 4; col++) {
208
-
209
-				var s0 = state[0][col],
210
-				    s1 = state[1][col],
211
-				    s2 = state[2][col],
212
-				    s3 = state[3][col];
213
-
214
-				state[0][col] = MULT2[s0] ^ MULT3[s1] ^ s2 ^ s3;
215
-				state[1][col] = s0 ^ MULT2[s1] ^ MULT3[s2] ^ s3;
216
-				state[2][col] = s0 ^ s1 ^ MULT2[s2] ^ MULT3[s3];
217
-				state[3][col] = MULT3[s0] ^ s1 ^ s2 ^ MULT2[s3];
218
-
219
-			}
220
-
221
-			// Add round key
222
-			for (var row = 0; row < 4; row++) {
223
-				for (var col = 0; col < 4; col++)
224
-					state[row][col] ^= keyschedule[round * 4 + col][row];
225
-			}
226
-
227
-		}
228
-
229
-		// Sub bytes
230
-		for (var row = 0; row < 4; row++) {
231
-			for (var col = 0; col < 4; col++)
232
-				state[row][col] = SBOX[state[row][col]];
233
-		}
234
-
235
-		// Shift rows
236
-		state[1].push(state[1].shift());
237
-		state[2].push(state[2].shift());
238
-		state[2].push(state[2].shift());
239
-		state[3].unshift(state[3].pop());
240
-
241
-		// Add round key
242
-		for (var row = 0; row < 4; row++) {
243
-			for (var col = 0; col < 4; col++)
244
-				state[row][col] ^= keyschedule[nrounds * 4 + col][row];
245
-		}
246
-
247
-		// Set output
248
-		for (var row = 0; row < AES._blocksize; row++) {
249
-			for (var col = 0; col < 4; col++)
250
-				m[offset + col * 4 + row] = state[row][col];
251
-		}
252
-
253
-	},
254
-
255
-	_decryptblock: function (c, offset) {
256
-
257
-		// Set input
258
-		for (var row = 0; row < AES._blocksize; row++) {
259
-			for (var col = 0; col < 4; col++)
260
-				state[row][col] = c[offset + col * 4 + row];
261
-		}
262
-
263
-		// Add round key
264
-		for (var row = 0; row < 4; row++) {
265
-			for (var col = 0; col < 4; col++)
266
-				state[row][col] ^= keyschedule[nrounds * 4 + col][row];
267
-		}
268
-
269
-		for (var round = 1; round < nrounds; round++) {
270
-
271
-			// Inv shift rows
272
-			state[1].unshift(state[1].pop());
273
-			state[2].push(state[2].shift());
274
-			state[2].push(state[2].shift());
275
-			state[3].push(state[3].shift());
276
-
277
-			// Inv sub bytes
278
-			for (var row = 0; row < 4; row++) {
279
-				for (var col = 0; col < 4; col++)
280
-					state[row][col] = INVSBOX[state[row][col]];
281
-			}
282
-
283
-			// Add round key
284
-			for (var row = 0; row < 4; row++) {
285
-				for (var col = 0; col < 4; col++)
286
-					state[row][col] ^= keyschedule[(nrounds - round) * 4 + col][row];
287
-			}
288
-
289
-			// Inv mix columns
290
-			for (var col = 0; col < 4; col++) {
291
-
292
-				var s0 = state[0][col],
293
-				    s1 = state[1][col],
294
-				    s2 = state[2][col],
295
-				    s3 = state[3][col];
296
-
297
-				state[0][col] = MULTE[s0] ^ MULTB[s1] ^ MULTD[s2] ^ MULT9[s3];
298
-				state[1][col] = MULT9[s0] ^ MULTE[s1] ^ MULTB[s2] ^ MULTD[s3];
299
-				state[2][col] = MULTD[s0] ^ MULT9[s1] ^ MULTE[s2] ^ MULTB[s3];
300
-				state[3][col] = MULTB[s0] ^ MULTD[s1] ^ MULT9[s2] ^ MULTE[s3];
301
-
302
-			}
303
-
304
-		}
305
-
306
-		// Inv shift rows
307
-		state[1].unshift(state[1].pop());
308
-		state[2].push(state[2].shift());
309
-		state[2].push(state[2].shift());
310
-		state[3].push(state[3].shift());
311
-
312
-		// Inv sub bytes
313
-		for (var row = 0; row < 4; row++) {
314
-			for (var col = 0; col < 4; col++)
315
-				state[row][col] = INVSBOX[state[row][col]];
316
-		}
317
-
318
-		// Add round key
319
-		for (var row = 0; row < 4; row++) {
320
-			for (var col = 0; col < 4; col++)
321
-				state[row][col] ^= keyschedule[col][row];
322
-		}
323
-
324
-		// Set output
325
-		for (var row = 0; row < AES._blocksize; row++) {
326
-			for (var col = 0; col < 4; col++)
327
-				c[offset + col * 4 + row] = state[row][col];
328
-		}
329
-
330
-	},
331
-
332
-
333
-	/**
334
-	 * Private methods
335
-	 */
336
-
337
-	_init: function (k) {
338
-		keylength = k.length / 4;
339
-		nrounds = keylength + 6;
340
-		AES._keyexpansion(k);
341
-	},
342
-
343
-	// Generate a key schedule
344
-	_keyexpansion: function (k) {
345
-
346
-		keyschedule = [];
347
-
348
-		for (var row = 0; row < keylength; row++) {
349
-			keyschedule[row] = [
350
-				k[row * 4],
351
-				k[row * 4 + 1],
352
-				k[row * 4 + 2],
353
-				k[row * 4 + 3]
354
-			];
355
-		}
356
-
357
-		for (var row = keylength; row < AES._blocksize * (nrounds + 1); row++) {
358
-
359
-			var temp = [
360
-				keyschedule[row - 1][0],
361
-				keyschedule[row - 1][1],
362
-				keyschedule[row - 1][2],
363
-				keyschedule[row - 1][3]
364
-			];
365
-
366
-			if (row % keylength == 0) {
367
-
368
-				// Rot word
369
-				temp.push(temp.shift());
370
-
371
-				// Sub word
372
-				temp[0] = SBOX[temp[0]];
373
-				temp[1] = SBOX[temp[1]];
374
-				temp[2] = SBOX[temp[2]];
375
-				temp[3] = SBOX[temp[3]];
376
-
377
-				temp[0] ^= RCON[row / keylength];
378
-
379
-			} else if (keylength > 6 && row % keylength == 4) {
380
-
381
-				// Sub word
382
-				temp[0] = SBOX[temp[0]];
383
-				temp[1] = SBOX[temp[1]];
384
-				temp[2] = SBOX[temp[2]];
385
-				temp[3] = SBOX[temp[3]];
386
-
387
-			}
388
-
389
-			keyschedule[row] = [
390
-				keyschedule[row - keylength][0] ^ temp[0],
391
-				keyschedule[row - keylength][1] ^ temp[1],
392
-				keyschedule[row - keylength][2] ^ temp[2],
393
-				keyschedule[row - keylength][3] ^ temp[3]
394
-			];
395
-
396
-		}
397
-
398
-	}
399
-
400
-};
401
-
402
-})();
1
+(function(){
2
+
3
+var C = (typeof window === 'undefined') ? require('./Crypto').Crypto : window.Crypto;
4
+
5
+// Shortcuts
6
+var util = C.util,
7
+    charenc = C.charenc,
8
+    UTF8 = charenc.UTF8;
9
+
10
+// Precomputed SBOX
11
+var SBOX = [ 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5,
12
+             0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
13
+             0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0,
14
+             0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
15
+             0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc,
16
+             0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
17
+             0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a,
18
+             0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
19
+             0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0,
20
+             0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
21
+             0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b,
22
+             0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
23
+             0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85,
24
+             0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
25
+             0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5,
26
+             0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
27
+             0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17,
28
+             0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
29
+             0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88,
30
+             0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
31
+             0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c,
32
+             0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
33
+             0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9,
34
+             0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
35
+             0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6,
36
+             0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
37
+             0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e,
38
+             0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
39
+             0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94,
40
+             0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
41
+             0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68,
42
+             0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 ];
43
+
44
+// Compute inverse SBOX lookup table
45
+for (var INVSBOX = [], i = 0; i < 256; i++) INVSBOX[SBOX[i]] = i;
46
+
47
+// Compute mulitplication in GF(2^8) lookup tables
48
+var MULT2 = [],
49
+    MULT3 = [],
50
+    MULT9 = [],
51
+    MULTB = [],
52
+    MULTD = [],
53
+    MULTE = [];
54
+
55
+function xtime(a, b) {
56
+	for (var result = 0, i = 0; i < 8; i++) {
57
+		if (b & 1) result ^= a;
58
+		var hiBitSet = a & 0x80;
59
+		a = (a << 1) & 0xFF;
60
+		if (hiBitSet) a ^= 0x1b;
61
+		b >>>= 1;
62
+	}
63
+	return result;
64
+}
65
+
66
+for (var i = 0; i < 256; i++) {
67
+	MULT2[i] = xtime(i,2);
68
+	MULT3[i] = xtime(i,3);
69
+	MULT9[i] = xtime(i,9);
70
+	MULTB[i] = xtime(i,0xB);
71
+	MULTD[i] = xtime(i,0xD);
72
+	MULTE[i] = xtime(i,0xE);
73
+}
74
+
75
+// Precomputed RCon lookup
76
+var RCON = [0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36];
77
+
78
+// Inner state
79
+var state = [[], [], [], []],
80
+    keylength,
81
+    nrounds,
82
+    keyschedule;
83
+
84
+var AES = C.AES = {
85
+
86
+	/**
87
+	 * Public API
88
+	 */
89
+
90
+	encrypt: function (message, password, options) {
91
+
92
+		options = options || {};
93
+
94
+		// Determine mode
95
+		var mode = options.mode || new C.mode.OFB;
96
+
97
+		// Allow mode to override options
98
+		if (mode.fixOptions) mode.fixOptions(options);
99
+
100
+		var
101
+
102
+			// Convert to bytes if message is a string
103
+			m = (
104
+				message.constructor == String ?
105
+				UTF8.stringToBytes(message) :
106
+				message
107
+			),
108
+
109
+			// Generate random IV
110
+			iv = options.iv || util.randomBytes(AES._blocksize * 4),
111
+
112
+			// Generate key
113
+			k = (
114
+				password.constructor == String ?
115
+				// Derive key from passphrase
116
+				C.PBKDF2(password, iv, 32, { asBytes: true }) :
117
+				// else, assume byte array representing cryptographic key
118
+				password
119
+			);
120
+
121
+		// Encrypt
122
+		AES._init(k);
123
+		mode.encrypt(AES, m, iv);
124
+
125
+		// Return ciphertext
126
+		m = options.iv ? m : iv.concat(m);
127
+		return (options && options.asBytes) ? m : util.bytesToBase64(m);
128
+
129
+	},
130
+
131
+	decrypt: function (ciphertext, password, options) {
132
+
133
+		options = options || {};
134
+
135
+		// Determine mode
136
+		var mode = options.mode || new C.mode.OFB;
137
+
138
+		// Allow mode to override options
139
+		if (mode.fixOptions) mode.fixOptions(options);
140
+
141
+		var
142
+
143
+			// Convert to bytes if ciphertext is a string
144
+			c = (
145
+				ciphertext.constructor == String ?
146
+				util.base64ToBytes(ciphertext):
147
+			    ciphertext
148
+			),
149
+
150
+			// Separate IV and message
151
+			iv = options.iv || c.splice(0, AES._blocksize * 4),
152
+
153
+			// Generate key
154
+			k = (
155
+				password.constructor == String ?
156
+				// Derive key from passphrase
157
+				C.PBKDF2(password, iv, 32, { asBytes: true }) :
158
+				// else, assume byte array representing cryptographic key
159
+				password
160
+			);
161
+
162
+		// Decrypt
163
+		AES._init(k);
164
+		mode.decrypt(AES, c, iv);
165
+
166
+		// Return plaintext
167
+		return (options && options.asBytes) ? c : UTF8.bytesToString(c);
168
+
169
+	},
170
+
171
+
172
+	/**
173
+	 * Package private methods and properties
174
+	 */
175
+
176
+	_blocksize: 4,
177
+
178
+	_encryptblock: function (m, offset) {
179
+
180
+		// Set input
181
+		for (var row = 0; row < AES._blocksize; row++) {
182
+			for (var col = 0; col < 4; col++)
183
+				state[row][col] = m[offset + col * 4 + row];
184
+		}
185
+
186
+		// Add round key
187
+		for (var row = 0; row < 4; row++) {
188
+			for (var col = 0; col < 4; col++)
189
+				state[row][col] ^= keyschedule[col][row];
190
+		}
191
+
192
+		for (var round = 1; round < nrounds; round++) {
193
+
194
+			// Sub bytes
195
+			for (var row = 0; row < 4; row++) {
196
+				for (var col = 0; col < 4; col++)
197
+					state[row][col] = SBOX[state[row][col]];
198
+			}
199
+
200
+			// Shift rows
201
+			state[1].push(state[1].shift());
202
+			state[2].push(state[2].shift());
203
+			state[2].push(state[2].shift());
204
+			state[3].unshift(state[3].pop());
205
+
206
+			// Mix columns
207
+			for (var col = 0; col < 4; col++) {
208
+
209
+				var s0 = state[0][col],
210
+				    s1 = state[1][col],
211
+				    s2 = state[2][col],
212
+				    s3 = state[3][col];
213
+
214
+				state[0][col] = MULT2[s0] ^ MULT3[s1] ^ s2 ^ s3;
215
+				state[1][col] = s0 ^ MULT2[s1] ^ MULT3[s2] ^ s3;
216
+				state[2][col] = s0 ^ s1 ^ MULT2[s2] ^ MULT3[s3];
217
+				state[3][col] = MULT3[s0] ^ s1 ^ s2 ^ MULT2[s3];
218
+
219
+			}
220
+
221
+			// Add round key
222
+			for (var row = 0; row < 4; row++) {
223
+				for (var col = 0; col < 4; col++)
224
+					state[row][col] ^= keyschedule[round * 4 + col][row];
225
+			}
226
+
227
+		}
228
+
229
+		// Sub bytes
230
+		for (var row = 0; row < 4; row++) {
231
+			for (var col = 0; col < 4; col++)
232
+				state[row][col] = SBOX[state[row][col]];
233
+		}
234
+
235
+		// Shift rows
236
+		state[1].push(state[1].shift());
237
+		state[2].push(state[2].shift());
238
+		state[2].push(state[2].shift());
239
+		state[3].unshift(state[3].pop());
240
+
241
+		// Add round key
242
+		for (var row = 0; row < 4; row++) {
243
+			for (var col = 0; col < 4; col++)
244
+				state[row][col] ^= keyschedule[nrounds * 4 + col][row];
245
+		}
246
+
247
+		// Set output
248
+		for (var row = 0; row < AES._blocksize; row++) {
249
+			for (var col = 0; col < 4; col++)
250
+				m[offset + col * 4 + row] = state[row][col];
251
+		}
252
+
253
+	},
254
+
255
+	_decryptblock: function (c, offset) {
256
+
257
+		// Set input
258
+		for (var row = 0; row < AES._blocksize; row++) {
259
+			for (var col = 0; col < 4; col++)
260
+				state[row][col] = c[offset + col * 4 + row];
261
+		}
262
+
263
+		// Add round key
264
+		for (var row = 0; row < 4; row++) {
265
+			for (var col = 0; col < 4; col++)
266
+				state[row][col] ^= keyschedule[nrounds * 4 + col][row];
267
+		}
268
+
269
+		for (var round = 1; round < nrounds; round++) {
270
+
271
+			// Inv shift rows
272
+			state[1].unshift(state[1].pop());
273
+			state[2].push(state[2].shift());
274
+			state[2].push(state[2].shift());
275
+			state[3].push(state[3].shift());
276
+
277
+			// Inv sub bytes
278
+			for (var row = 0; row < 4; row++) {
279
+				for (var col = 0; col < 4; col++)
280
+					state[row][col] = INVSBOX[state[row][col]];
281
+			}
282
+
283
+			// Add round key
284
+			for (var row = 0; row < 4; row++) {
285
+				for (var col = 0; col < 4; col++)
286
+					state[row][col] ^= keyschedule[(nrounds - round) * 4 + col][row];
287
+			}
288
+
289
+			// Inv mix columns
290
+			for (var col = 0; col < 4; col++) {
291
+
292
+				var s0 = state[0][col],
293
+				    s1 = state[1][col],
294
+				    s2 = state[2][col],
295
+				    s3 = state[3][col];
296
+
297
+				state[0][col] = MULTE[s0] ^ MULTB[s1] ^ MULTD[s2] ^ MULT9[s3];
298
+				state[1][col] = MULT9[s0] ^ MULTE[s1] ^ MULTB[s2] ^ MULTD[s3];
299
+				state[2][col] = MULTD[s0] ^ MULT9[s1] ^ MULTE[s2] ^ MULTB[s3];
300
+				state[3][col] = MULTB[s0] ^ MULTD[s1] ^ MULT9[s2] ^ MULTE[s3];
301
+
302
+			}
303
+
304
+		}
305
+
306
+		// Inv shift rows
307
+		state[1].unshift(state[1].pop());
308
+		state[2].push(state[2].shift());
309
+		state[2].push(state[2].shift());
310
+		state[3].push(state[3].shift());
311
+
312
+		// Inv sub bytes
313
+		for (var row = 0; row < 4; row++) {
314
+			for (var col = 0; col < 4; col++)
315
+				state[row][col] = INVSBOX[state[row][col]];
316
+		}
317
+
318
+		// Add round key
319
+		for (var row = 0; row < 4; row++) {
320
+			for (var col = 0; col < 4; col++)
321
+				state[row][col] ^= keyschedule[col][row];
322
+		}
323
+
324
+		// Set output
325
+		for (var row = 0; row < AES._blocksize; row++) {
326
+			for (var col = 0; col < 4; col++)
327
+				c[offset + col * 4 + row] = state[row][col];
328
+		}
329
+
330
+	},
331
+
332
+
333
+	/**
334
+	 * Private methods
335
+	 */
336
+
337
+	_init: function (k) {
338
+		keylength = k.length / 4;
339
+		nrounds = keylength + 6;
340
+		AES._keyexpansion(k);
341
+	},
342
+
343
+	// Generate a key schedule
344
+	_keyexpansion: function (k) {
345
+
346
+		keyschedule = [];
347
+
348
+		for (var row = 0; row < keylength; row++) {
349
+			keyschedule[row] = [
350
+				k[row * 4],
351
+				k[row * 4 + 1],
352
+				k[row * 4 + 2],
353
+				k[row * 4 + 3]
354
+			];
355
+		}
356
+
357
+		for (var row = keylength; row < AES._blocksize * (nrounds + 1); row++) {
358
+
359
+			var temp = [
360
+				keyschedule[row - 1][0],
361
+				keyschedule[row - 1][1],
362
+				keyschedule[row - 1][2],
363
+				keyschedule[row - 1][3]
364
+			];
365
+
366
+			if (row % keylength == 0) {
367
+
368
+				// Rot word
369
+				temp.push(temp.shift());
370
+
371
+				// Sub word
372
+				temp[0] = SBOX[temp[0]];
373
+				temp[1] = SBOX[temp[1]];
374
+				temp[2] = SBOX[temp[2]];
375
+				temp[3] = SBOX[temp[3]];
376
+
377
+				temp[0] ^= RCON[row / keylength];
378
+
379
+			} else if (keylength > 6 && row % keylength == 4) {
380
+
381
+				// Sub word
382
+				temp[0] = SBOX[temp[0]];
383
+				temp[1] = SBOX[temp[1]];
384
+				temp[2] = SBOX[temp[2]];
385
+				temp[3] = SBOX[temp[3]];
386
+
387
+			}
388
+
389
+			keyschedule[row] = [
390
+				keyschedule[row - keylength][0] ^ temp[0],
391
+				keyschedule[row - keylength][1] ^ temp[1],
392
+				keyschedule[row - keylength][2] ^ temp[2],
393
+				keyschedule[row - keylength][3] ^ temp[3]
394
+			];
395
+
396
+		}
397
+
398
+	}
399
+
400
+};
401
+
402
+})();

+ 378 - 378
utils/lib/BlockModes.js

@@ -1,378 +1,378 @@
1
-/*!
2
- * Crypto-JS contribution from Simon Greatrix
3
- */
4
-
5
-(function(){
6
-
7
-var C = (typeof window === 'undefined') ? require('./Crypto').Crypto : window.Crypto;
8
-
9
-// Create pad namespace
10
-var C_pad = C.pad = {};
11
-
12
-// Calculate the number of padding bytes required.
13
-function _requiredPadding(cipher, message) {
14
-    var blockSizeInBytes = cipher._blocksize * 4;
15
-    var reqd = blockSizeInBytes - message.length % blockSizeInBytes;
16
-    return reqd;
17
-};
18
-
19
-// Remove padding when the final byte gives the number of padding bytes.
20
-var _unpadLength = function (message) {
21
-        var pad = message.pop();
22
-        for (var i = 1; i < pad; i++) {
23
-            message.pop();
24
-        }
25
-    };
26
-
27
-// No-operation padding, used for stream ciphers
28
-C_pad.NoPadding = {
29
-        pad : function (cipher,message) {},
30
-        unpad : function (message) {}
31
-    };
32
-
33
-// Zero Padding.
34
-//
35
-// If the message is not an exact number of blocks, the final block is
36
-// completed with 0x00 bytes. There is no unpadding.
37
-C_pad.ZeroPadding = {
38
-    pad : function (cipher, message) {
39
-        var blockSizeInBytes = cipher._blocksize * 4;
40
-        var reqd = message.length % blockSizeInBytes;
41
-        if( reqd!=0 ) {
42
-            for(reqd = blockSizeInBytes - reqd; reqd>0; reqd--) {
43
-                message.push(0x00);
44
-            }
45
-        }
46
-    },
47
-
48
-    unpad : function (message) {}
49
-};
50
-
51
-// ISO/IEC 7816-4 padding.
52
-//
53
-// Pads the plain text with an 0x80 byte followed by as many 0x00
54
-// bytes are required to complete the block.
55
-C_pad.iso7816 = {
56
-    pad : function (cipher, message) {
57
-        var reqd = _requiredPadding(cipher, message);
58
-        message.push(0x80);
59
-        for (; reqd > 1; reqd--) {
60
-            message.push(0x00);
61
-        }
62
-    },
63
-
64
-    unpad : function (message) {
65
-        while (message.pop() != 0x80) {}
66
-    }
67
-};
68
-
69
-// ANSI X.923 padding
70
-//
71
-// The final block is padded with zeros except for the last byte of the
72
-// last block which contains the number of padding bytes.
73
-C_pad.ansix923 = {
74
-    pad : function (cipher, message) {
75
-        var reqd = _requiredPadding(cipher, message);
76
-        for (var i = 1; i < reqd; i++) {
77
-            message.push(0x00);
78
-        }
79
-        message.push(reqd);
80
-    },
81
-
82
-    unpad : _unpadLength
83
-};
84
-
85
-// ISO 10126
86
-//
87
-// The final block is padded with random bytes except for the last
88
-// byte of the last block which contains the number of padding bytes.
89
-C_pad.iso10126 = {
90
-    pad : function (cipher, message) {
91
-        var reqd = _requiredPadding(cipher, message);
92
-        for (var i = 1; i < reqd; i++) {
93
-            message.push(Math.floor(Math.random() * 256));
94
-        }
95
-        message.push(reqd);
96
-    },
97
-
98
-    unpad : _unpadLength
99
-};
100
-
101
-// PKCS7 padding
102
-//
103
-// PKCS7 is described in RFC 5652. Padding is in whole bytes. The
104
-// value of each added byte is the number of bytes that are added,
105
-// i.e. N bytes, each of value N are added.
106
-C_pad.pkcs7 = {
107
-    pad : function (cipher, message) {
108
-        var reqd = _requiredPadding(cipher, message);
109
-        for (var i = 0; i < reqd; i++) {
110
-            message.push(reqd);
111
-        }
112
-    },
113
-
114
-    unpad : _unpadLength
115
-};
116
-
117
-// Create mode namespace
118
-var C_mode = C.mode = {};
119
-
120
-/**
121
- * Mode base "class".
122
- */
123
-var Mode = C_mode.Mode = function (padding) {
124
-    if (padding) {
125
-        this._padding = padding;
126
-    }
127
-};
128
-
129
-Mode.prototype = {
130
-    encrypt: function (cipher, m, iv) {
131
-        this._padding.pad(cipher, m);
132
-        this._doEncrypt(cipher, m, iv);
133
-    },
134
-
135
-    decrypt: function (cipher, m, iv) {
136
-        this._doDecrypt(cipher, m, iv);
137
-        this._padding.unpad(m);
138
-    },
139
-
140
-    // Default padding
141
-    _padding: C_pad.iso7816
142
-};
143
-
144
-
145
-/**
146
- * Electronic Code Book mode.
147
- * 
148
- * ECB applies the cipher directly against each block of the input.
149
- * 
150
- * ECB does not require an initialization vector.
151
- */
152
-var ECB = C_mode.ECB = function () {
153
-    // Call parent constructor
154
-    Mode.apply(this, arguments);
155
-};
156
-
157
-// Inherit from Mode
158
-var ECB_prototype = ECB.prototype = new Mode;
159
-
160
-// Concrete steps for Mode template
161
-ECB_prototype._doEncrypt = function (cipher, m, iv) {
162
-    var blockSizeInBytes = cipher._blocksize * 4;
163
-    // Encrypt each block
164
-    for (var offset = 0; offset < m.length; offset += blockSizeInBytes) {
165
-        cipher._encryptblock(m, offset);
166
-    }
167
-};
168
-ECB_prototype._doDecrypt = function (cipher, c, iv) {
169
-    var blockSizeInBytes = cipher._blocksize * 4;
170
-    // Decrypt each block
171
-    for (var offset = 0; offset < c.length; offset += blockSizeInBytes) {
172
-        cipher._decryptblock(c, offset);
173
-    }
174
-};
175
-
176
-// ECB never uses an IV
177
-ECB_prototype.fixOptions = function (options) {
178
-    options.iv = [];
179
-};
180
-
181
-
182
-/**
183
- * Cipher block chaining
184
- * 
185
- * The first block is XORed with the IV. Subsequent blocks are XOR with the
186
- * previous cipher output.
187
- */
188
-var CBC = C_mode.CBC = function () {
189
-    // Call parent constructor
190
-    Mode.apply(this, arguments);
191
-};
192
-
193
-// Inherit from Mode
194
-var CBC_prototype = CBC.prototype = new Mode;
195
-
196
-// Concrete steps for Mode template
197
-CBC_prototype._doEncrypt = function (cipher, m, iv) {
198
-    var blockSizeInBytes = cipher._blocksize * 4;
199
-
200
-    // Encrypt each block
201
-    for (var offset = 0; offset < m.length; offset += blockSizeInBytes) {
202
-        if (offset == 0) {
203
-            // XOR first block using IV
204
-            for (var i = 0; i < blockSizeInBytes; i++)
205
-            m[i] ^= iv[i];
206
-        } else {
207
-            // XOR this block using previous crypted block
208
-            for (var i = 0; i < blockSizeInBytes; i++)
209
-            m[offset + i] ^= m[offset + i - blockSizeInBytes];
210
-        }
211
-        // Encrypt block
212
-        cipher._encryptblock(m, offset);
213
-    }
214
-};
215
-CBC_prototype._doDecrypt = function (cipher, c, iv) {
216
-    var blockSizeInBytes = cipher._blocksize * 4;
217
-
218
-    // At the start, the previously crypted block is the IV
219
-    var prevCryptedBlock = iv;
220
-
221
-    // Decrypt each block
222
-    for (var offset = 0; offset < c.length; offset += blockSizeInBytes) {
223
-        // Save this crypted block
224
-        var thisCryptedBlock = c.slice(offset, offset + blockSizeInBytes);
225
-        // Decrypt block
226
-        cipher._decryptblock(c, offset);
227
-        // XOR decrypted block using previous crypted block
228
-        for (var i = 0; i < blockSizeInBytes; i++) {
229
-            c[offset + i] ^= prevCryptedBlock[i];
230
-        }
231
-        prevCryptedBlock = thisCryptedBlock;
232
-    }
233
-};
234
-
235
-
236
-/**
237
- * Cipher feed back
238
- * 
239
- * The cipher output is XORed with the plain text to produce the cipher output,
240
- * which is then fed back into the cipher to produce a bit pattern to XOR the
241
- * next block with.
242
- * 
243
- * This is a stream cipher mode and does not require padding.
244
- */
245
-var CFB = C_mode.CFB = function () {
246
-    // Call parent constructor
247
-    Mode.apply(this, arguments);
248
-};
249
-
250
-// Inherit from Mode
251
-var CFB_prototype = CFB.prototype = new Mode;
252
-
253
-// Override padding
254
-CFB_prototype._padding = C_pad.NoPadding;
255
-
256
-// Concrete steps for Mode template
257
-CFB_prototype._doEncrypt = function (cipher, m, iv) {
258
-    var blockSizeInBytes = cipher._blocksize * 4,
259
-        keystream = iv.slice(0);
260
-
261
-    // Encrypt each byte
262
-    for (var i = 0; i < m.length; i++) {
263
-
264
-        var j = i % blockSizeInBytes;
265
-        if (j == 0) cipher._encryptblock(keystream, 0);
266
-
267
-        m[i] ^= keystream[j];
268
-        keystream[j] = m[i];
269
-    }
270
-};
271
-CFB_prototype._doDecrypt = function (cipher, c, iv) {
272
-    var blockSizeInBytes = cipher._blocksize * 4,
273
-        keystream = iv.slice(0);
274
-
275
-    // Encrypt each byte
276
-    for (var i = 0; i < c.length; i++) {
277
-
278
-        var j = i % blockSizeInBytes;
279
-        if (j == 0) cipher._encryptblock(keystream, 0);
280
-
281
-        var b = c[i];
282
-        c[i] ^= keystream[j];
283
-        keystream[j] = b;
284
-    }
285
-};
286
-
287
-
288
-/**
289
- * Output feed back
290
- * 
291
- * The cipher repeatedly encrypts its own output. The output is XORed with the
292
- * plain text to produce the cipher text.
293
- * 
294
- * This is a stream cipher mode and does not require padding.
295
- */
296
-var OFB = C_mode.OFB = function () {
297
-    // Call parent constructor
298
-    Mode.apply(this, arguments);
299
-};
300
-
301
-// Inherit from Mode
302
-var OFB_prototype = OFB.prototype = new Mode;
303
-
304
-// Override padding
305
-OFB_prototype._padding = C_pad.NoPadding;
306
-
307
-// Concrete steps for Mode template
308
-OFB_prototype._doEncrypt = function (cipher, m, iv) {
309
-
310
-    var blockSizeInBytes = cipher._blocksize * 4,
311
-        keystream = iv.slice(0);
312
-
313
-    // Encrypt each byte
314
-    for (var i = 0; i < m.length; i++) {
315
-
316
-        // Generate keystream
317
-        if (i % blockSizeInBytes == 0)
318
-            cipher._encryptblock(keystream, 0);
319
-
320
-        // Encrypt byte
321
-        m[i] ^= keystream[i % blockSizeInBytes];
322
-
323
-    }
324
-};
325
-OFB_prototype._doDecrypt = OFB_prototype._doEncrypt;
326
-
327
-/**
328
- * Counter
329
- * @author Gergely Risko
330
- *
331
- * After every block the last 4 bytes of the IV is increased by one
332
- * with carry and that IV is used for the next block.
333
- *
334
- * This is a stream cipher mode and does not require padding.
335
- */
336
-var CTR = C_mode.CTR = function () {
337
-    // Call parent constructor
338
-    Mode.apply(this, arguments);
339
-};
340
-
341
-// Inherit from Mode
342
-var CTR_prototype = CTR.prototype = new Mode;
343
-
344
-// Override padding
345
-CTR_prototype._padding = C_pad.NoPadding;
346
-
347
-CTR_prototype._doEncrypt = function (cipher, m, iv) {
348
-    var blockSizeInBytes = cipher._blocksize * 4;
349
-    var counter = iv.slice(0);
350
-
351
-    for (var i = 0; i < m.length;) {
352
-        // do not lose iv
353
-        var keystream = counter.slice(0);
354
-
355
-        // Generate keystream for next block
356
-        cipher._encryptblock(keystream, 0);
357
-
358
-        // XOR keystream with block
359
-        for (var j = 0; i < m.length && j < blockSizeInBytes; j++, i++) {
360
-            m[i] ^= keystream[j];
361
-        }
362
-
363
-        // Increase counter
364
-        if(++(counter[blockSizeInBytes-1]) == 256) {
365
-            counter[blockSizeInBytes-1] = 0;
366
-            if(++(counter[blockSizeInBytes-2]) == 256) {
367
-                counter[blockSizeInBytes-2] = 0;
368
-                if(++(counter[blockSizeInBytes-3]) == 256) {
369
-                    counter[blockSizeInBytes-3] = 0;
370
-                    ++(counter[blockSizeInBytes-4]);
371
-                }
372
-            }
373
-        }
374
-    }
375
-};
376
-CTR_prototype._doDecrypt = CTR_prototype._doEncrypt;
377
-
378
-})();
1
+/*!
2
+ * Crypto-JS contribution from Simon Greatrix
3
+ */
4
+
5
+(function(){
6
+
7
+var C = (typeof window === 'undefined') ? require('./Crypto').Crypto : window.Crypto;
8
+
9
+// Create pad namespace
10
+var C_pad = C.pad = {};
11
+
12
+// Calculate the number of padding bytes required.
13
+function _requiredPadding(cipher, message) {
14
+    var blockSizeInBytes = cipher._blocksize * 4;
15
+    var reqd = blockSizeInBytes - message.length % blockSizeInBytes;
16
+    return reqd;
17
+};
18
+
19
+// Remove padding when the final byte gives the number of padding bytes.
20
+var _unpadLength = function (message) {
21
+        var pad = message.pop();
22
+        for (var i = 1; i < pad; i++) {
23
+            message.pop();
24
+        }
25
+    };
26
+
27
+// No-operation padding, used for stream ciphers
28
+C_pad.NoPadding = {
29
+        pad : function (cipher,message) {},
30
+        unpad : function (message) {}
31
+    };
32
+
33
+// Zero Padding.
34
+//
35
+// If the message is not an exact number of blocks, the final block is
36
+// completed with 0x00 bytes. There is no unpadding.
37
+C_pad.ZeroPadding = {
38
+    pad : function (cipher, message) {
39
+        var blockSizeInBytes = cipher._blocksize * 4;
40
+        var reqd = message.length % blockSizeInBytes;
41
+        if( reqd!=0 ) {
42
+            for(reqd = blockSizeInBytes - reqd; reqd>0; reqd--) {
43
+                message.push(0x00);
44
+            }
45
+        }
46
+    },
47
+
48
+    unpad : function (message) {}
49
+};
50
+
51
+// ISO/IEC 7816-4 padding.
52
+//
53
+// Pads the plain text with an 0x80 byte followed by as many 0x00
54
+// bytes are required to complete the block.
55
+C_pad.iso7816 = {
56
+    pad : function (cipher, message) {
57
+        var reqd = _requiredPadding(cipher, message);
58
+        message.push(0x80);
59
+        for (; reqd > 1; reqd--) {
60
+            message.push(0x00);
61
+        }
62
+    },
63
+
64
+    unpad : function (message) {
65
+        while (message.pop() != 0x80) {}
66
+    }
67
+};
68
+
69
+// ANSI X.923 padding
70
+//
71
+// The final block is padded with zeros except for the last byte of the
72
+// last block which contains the number of padding bytes.
73
+C_pad.ansix923 = {
74
+    pad : function (cipher, message) {
75
+        var reqd = _requiredPadding(cipher, message);
76
+        for (var i = 1; i < reqd; i++) {
77
+            message.push(0x00);
78
+        }
79
+        message.push(reqd);
80
+    },
81
+
82
+    unpad : _unpadLength
83
+};
84
+
85
+// ISO 10126
86
+//
87
+// The final block is padded with random bytes except for the last
88
+// byte of the last block which contains the number of padding bytes.
89
+C_pad.iso10126 = {
90
+    pad : function (cipher, message) {
91
+        var reqd = _requiredPadding(cipher, message);
92
+        for (var i = 1; i < reqd; i++) {
93
+            message.push(Math.floor(Math.random() * 256));
94
+        }
95
+        message.push(reqd);
96
+    },
97
+
98
+    unpad : _unpadLength
99
+};
100
+
101
+// PKCS7 padding
102
+//
103
+// PKCS7 is described in RFC 5652. Padding is in whole bytes. The
104
+// value of each added byte is the number of bytes that are added,
105
+// i.e. N bytes, each of value N are added.
106
+C_pad.pkcs7 = {
107
+    pad : function (cipher, message) {
108
+        var reqd = _requiredPadding(cipher, message);
109
+        for (var i = 0; i < reqd; i++) {
110
+            message.push(reqd);
111
+        }
112
+    },
113
+
114
+    unpad : _unpadLength
115
+};
116
+
117
+// Create mode namespace
118
+var C_mode = C.mode = {};
119
+
120
+/**
121
+ * Mode base "class".
122
+ */
123
+var Mode = C_mode.Mode = function (padding) {
124
+    if (padding) {
125
+        this._padding = padding;
126
+    }
127
+};
128
+
129
+Mode.prototype = {
130
+    encrypt: function (cipher, m, iv) {
131
+        this._padding.pad(cipher, m);
132
+        this._doEncrypt(cipher, m, iv);
133
+    },
134
+
135
+    decrypt: function (cipher, m, iv) {
136
+        this._doDecrypt(cipher, m, iv);
137
+        this._padding.unpad(m);
138
+    },
139
+
140
+    // Default padding
141
+    _padding: C_pad.iso7816
142
+};
143
+
144
+
145
+/**
146
+ * Electronic Code Book mode.
147
+ * 
148
+ * ECB applies the cipher directly against each block of the input.
149
+ * 
150
+ * ECB does not require an initialization vector.
151
+ */
152
+var ECB = C_mode.ECB = function () {
153
+    // Call parent constructor
154
+    Mode.apply(this, arguments);
155
+};
156
+
157
+// Inherit from Mode
158
+var ECB_prototype = ECB.prototype = new Mode;
159
+
160
+// Concrete steps for Mode template
161
+ECB_prototype._doEncrypt = function (cipher, m, iv) {
162
+    var blockSizeInBytes = cipher._blocksize * 4;
163
+    // Encrypt each block
164
+    for (var offset = 0; offset < m.length; offset += blockSizeInBytes) {
165
+        cipher._encryptblock(m, offset);
166
+    }
167
+};
168
+ECB_prototype._doDecrypt = function (cipher, c, iv) {
169
+    var blockSizeInBytes = cipher._blocksize * 4;
170
+    // Decrypt each block
171
+    for (var offset = 0; offset < c.length; offset += blockSizeInBytes) {
172
+        cipher._decryptblock(c, offset);
173
+    }
174
+};
175
+
176
+// ECB never uses an IV
177
+ECB_prototype.fixOptions = function (options) {
178
+    options.iv = [];
179
+};
180
+
181
+
182
+/**
183
+ * Cipher block chaining
184
+ * 
185
+ * The first block is XORed with the IV. Subsequent blocks are XOR with the
186
+ * previous cipher output.
187
+ */
188
+var CBC = C_mode.CBC = function () {
189
+    // Call parent constructor
190
+    Mode.apply(this, arguments);
191
+};
192
+
193
+// Inherit from Mode
194
+var CBC_prototype = CBC.prototype = new Mode;
195
+
196
+// Concrete steps for Mode template
197
+CBC_prototype._doEncrypt = function (cipher, m, iv) {
198
+    var blockSizeInBytes = cipher._blocksize * 4;
199
+
200
+    // Encrypt each block
201
+    for (var offset = 0; offset < m.length; offset += blockSizeInBytes) {
202
+        if (offset == 0) {
203
+            // XOR first block using IV
204
+            for (var i = 0; i < blockSizeInBytes; i++)
205
+            m[i] ^= iv[i];
206
+        } else {
207
+            // XOR this block using previous crypted block
208
+            for (var i = 0; i < blockSizeInBytes; i++)
209
+            m[offset + i] ^= m[offset + i - blockSizeInBytes];
210
+        }
211
+        // Encrypt block
212
+        cipher._encryptblock(m, offset);
213
+    }
214
+};
215
+CBC_prototype._doDecrypt = function (cipher, c, iv) {
216
+    var blockSizeInBytes = cipher._blocksize * 4;
217
+
218
+    // At the start, the previously crypted block is the IV
219
+    var prevCryptedBlock = iv;
220
+
221
+    // Decrypt each block
222
+    for (var offset = 0; offset < c.length; offset += blockSizeInBytes) {
223
+        // Save this crypted block
224
+        var thisCryptedBlock = c.slice(offset, offset + blockSizeInBytes);
225
+        // Decrypt block
226
+        cipher._decryptblock(c, offset);
227
+        // XOR decrypted block using previous crypted block
228
+        for (var i = 0; i < blockSizeInBytes; i++) {
229
+            c[offset + i] ^= prevCryptedBlock[i];
230
+        }
231
+        prevCryptedBlock = thisCryptedBlock;
232
+    }
233
+};
234
+
235
+
236
+/**
237
+ * Cipher feed back
238
+ * 
239
+ * The cipher output is XORed with the plain text to produce the cipher output,
240
+ * which is then fed back into the cipher to produce a bit pattern to XOR the
241
+ * next block with.
242
+ * 
243
+ * This is a stream cipher mode and does not require padding.
244
+ */
245
+var CFB = C_mode.CFB = function () {
246
+    // Call parent constructor
247
+    Mode.apply(this, arguments);
248
+};
249
+
250
+// Inherit from Mode
251
+var CFB_prototype = CFB.prototype = new Mode;
252
+
253
+// Override padding
254
+CFB_prototype._padding = C_pad.NoPadding;
255
+
256
+// Concrete steps for Mode template
257
+CFB_prototype._doEncrypt = function (cipher, m, iv) {
258
+    var blockSizeInBytes = cipher._blocksize * 4,
259
+        keystream = iv.slice(0);
260
+
261
+    // Encrypt each byte
262
+    for (var i = 0; i < m.length; i++) {
263
+
264
+        var j = i % blockSizeInBytes;
265
+        if (j == 0) cipher._encryptblock(keystream, 0);
266
+
267
+        m[i] ^= keystream[j];
268
+        keystream[j] = m[i];
269
+    }
270
+};
271
+CFB_prototype._doDecrypt = function (cipher, c, iv) {
272
+    var blockSizeInBytes = cipher._blocksize * 4,
273
+        keystream = iv.slice(0);
274
+
275
+    // Encrypt each byte
276
+    for (var i = 0; i < c.length; i++) {
277
+
278
+        var j = i % blockSizeInBytes;
279
+        if (j == 0) cipher._encryptblock(keystream, 0);
280
+
281
+        var b = c[i];
282
+        c[i] ^= keystream[j];
283
+        keystream[j] = b;
284
+    }
285
+};
286
+
287
+
288
+/**
289
+ * Output feed back
290
+ * 
291
+ * The cipher repeatedly encrypts its own output. The output is XORed with the
292
+ * plain text to produce the cipher text.
293
+ * 
294
+ * This is a stream cipher mode and does not require padding.
295
+ */
296
+var OFB = C_mode.OFB = function () {
297
+    // Call parent constructor
298
+    Mode.apply(this, arguments);
299
+};
300
+
301
+// Inherit from Mode
302
+var OFB_prototype = OFB.prototype = new Mode;
303
+
304
+// Override padding
305
+OFB_prototype._padding = C_pad.NoPadding;
306
+
307
+// Concrete steps for Mode template
308
+OFB_prototype._doEncrypt = function (cipher, m, iv) {
309
+
310
+    var blockSizeInBytes = cipher._blocksize * 4,
311
+        keystream = iv.slice(0);
312
+
313
+    // Encrypt each byte
314
+    for (var i = 0; i < m.length; i++) {
315
+
316
+        // Generate keystream
317
+        if (i % blockSizeInBytes == 0)
318
+            cipher._encryptblock(keystream, 0);
319
+
320
+        // Encrypt byte
321
+        m[i] ^= keystream[i % blockSizeInBytes];
322
+
323
+    }
324
+};
325
+OFB_prototype._doDecrypt = OFB_prototype._doEncrypt;
326
+
327
+/**
328
+ * Counter
329
+ * @author Gergely Risko
330
+ *
331
+ * After every block the last 4 bytes of the IV is increased by one
332
+ * with carry and that IV is used for the next block.
333
+ *
334
+ * This is a stream cipher mode and does not require padding.
335
+ */
336
+var CTR = C_mode.CTR = function () {
337
+    // Call parent constructor
338
+    Mode.apply(this, arguments);
339
+};
340
+
341
+// Inherit from Mode
342
+var CTR_prototype = CTR.prototype = new Mode;
343
+
344
+// Override padding
345
+CTR_prototype._padding = C_pad.NoPadding;
346
+
347
+CTR_prototype._doEncrypt = function (cipher, m, iv) {
348
+    var blockSizeInBytes = cipher._blocksize * 4;
349
+    var counter = iv.slice(0);
350
+
351
+    for (var i = 0; i < m.length;) {
352
+        // do not lose iv
353
+        var keystream = counter.slice(0);
354
+
355
+        // Generate keystream for next block
356
+        cipher._encryptblock(keystream, 0);
357
+
358
+        // XOR keystream with block
359
+        for (var j = 0; i < m.length && j < blockSizeInBytes; j++, i++) {
360
+            m[i] ^= keystream[j];
361
+        }
362
+
363
+        // Increase counter
364
+        if(++(counter[blockSizeInBytes-1]) == 256) {
365
+            counter[blockSizeInBytes-1] = 0;
366
+            if(++(counter[blockSizeInBytes-2]) == 256) {
367
+                counter[blockSizeInBytes-2] = 0;
368
+                if(++(counter[blockSizeInBytes-3]) == 256) {
369
+                    counter[blockSizeInBytes-3] = 0;
370
+                    ++(counter[blockSizeInBytes-4]);
371
+                }
372
+            }
373
+        }
374
+    }
375
+};
376
+CTR_prototype._doDecrypt = CTR_prototype._doEncrypt;
377
+
378
+})();

+ 155 - 155
utils/lib/Crypto.js

@@ -1,155 +1,155 @@
1
-if (typeof Crypto == "undefined" || ! Crypto.util)
2
-{
3
-(function(){
4
-
5
-var base64map = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
6
-
7
-// Global Crypto object
8
-// with browser window or with node module
9
-var Crypto = (typeof window === 'undefined') ? exports.Crypto = {} : window.Crypto = {}; 
10
-
11
-// Crypto utilities
12
-var util = Crypto.util = {
13
-
14
-	// Bit-wise rotate left
15
-	rotl: function (n, b) {
16
-		return (n << b) | (n >>> (32 - b));
17
-	},
18
-
19
-	// Bit-wise rotate right
20
-	rotr: function (n, b) {
21
-		return (n << (32 - b)) | (n >>> b);
22
-	},
23
-
24
-	// Swap big-endian to little-endian and vice versa
25
-	endian: function (n) {
26
-
27
-		// If number given, swap endian
28
-		if (n.constructor == Number) {
29
-			return util.rotl(n,  8) & 0x00FF00FF |
30
-			       util.rotl(n, 24) & 0xFF00FF00;
31
-		}
32
-
33
-		// Else, assume array and swap all items
34
-		for (var i = 0; i < n.length; i++)
35
-			n[i] = util.endian(n[i]);
36
-		return n;
37
-
38
-	},
39
-
40
-	// Generate an array of any length of random bytes
41
-	randomBytes: function (n) {
42
-		for (var bytes = []; n > 0; n--)
43
-			bytes.push(Math.floor(Math.random() * 256));
44
-		return bytes;
45
-	},
46
-
47
-	// Convert a byte array to big-endian 32-bit words
48
-	bytesToWords: function (bytes) {
49
-		for (var words = [], i = 0, b = 0; i < bytes.length; i++, b += 8)
50
-			words[b >>> 5] |= (bytes[i] & 0xFF) << (24 - b % 32);
51
-		return words;
52
-	},
53
-
54
-	// Convert big-endian 32-bit words to a byte array
55
-	wordsToBytes: function (words) {
56
-		for (var bytes = [], b = 0; b < words.length * 32; b += 8)
57
-			bytes.push((words[b >>> 5] >>> (24 - b % 32)) & 0xFF);
58
-		return bytes;
59
-	},
60
-
61
-	// Convert a byte array to a hex string
62
-	bytesToHex: function (bytes) {
63
-		for (var hex = [], i = 0; i < bytes.length; i++) {
64
-			hex.push((bytes[i] >>> 4).toString(16));
65
-			hex.push((bytes[i] & 0xF).toString(16));
66
-		}
67
-		return hex.join("");
68
-	},
69
-
70
-	// Convert a hex string to a byte array
71
-	hexToBytes: function (hex) {
72
-		for (var bytes = [], c = 0; c < hex.length; c += 2)
73
-			bytes.push(parseInt(hex.substr(c, 2), 16));
74
-		return bytes;
75
-	},
76
-
77
-	// Convert a byte array to a base-64 string
78
-	bytesToBase64: function (bytes) {
79
-
80
-		// Use browser-native function if it exists
81
-		if (typeof btoa == "function") return btoa(Binary.bytesToString(bytes));
82
-
83
-		for(var base64 = [], i = 0; i < bytes.length; i += 3) {
84
-			var triplet = (bytes[i] << 16) | (bytes[i + 1] << 8) | bytes[i + 2];
85
-			for (var j = 0; j < 4; j++) {
86
-				if (i * 8 + j * 6 <= bytes.length * 8)
87
-					base64.push(base64map.charAt((triplet >>> 6 * (3 - j)) & 0x3F));
88
-				else base64.push("=");
89
-			}
90
-		}
91
-
92
-		return base64.join("");
93
-
94
-	},
95
-
96
-	// Convert a base-64 string to a byte array
97
-	base64ToBytes: function (base64) {
98
-
99
-		// Use browser-native function if it exists
100
-		if (typeof atob == "function") return Binary.stringToBytes(atob(base64));
101
-
102
-		// Remove non-base-64 characters
103
-		base64 = base64.replace(/[^A-Z0-9+\/]/ig, "");
104
-
105
-		for (var bytes = [], i = 0, imod4 = 0; i < base64.length; imod4 = ++i % 4) {
106
-			if (imod4 == 0) continue;
107
-			bytes.push(((base64map.indexOf(base64.charAt(i - 1)) & (Math.pow(2, -2 * imod4 + 8) - 1)) << (imod4 * 2)) |
108
-			           (base64map.indexOf(base64.charAt(i)) >>> (6 - imod4 * 2)));
109
-		}
110
-
111
-		return bytes;
112
-
113
-	}
114
-
115
-};
116
-
117
-// Crypto character encodings
118
-var charenc = Crypto.charenc = {};
119
-
120
-// UTF-8 encoding
121
-var UTF8 = charenc.UTF8 = {
122
-
123
-	// Convert a string to a byte array
124
-	stringToBytes: function (str) {
125
-		return Binary.stringToBytes(unescape(encodeURIComponent(str)));
126
-	},
127
-
128
-	// Convert a byte array to a string
129
-	bytesToString: function (bytes) {
130
-		return decodeURIComponent(escape(Binary.bytesToString(bytes)));
131
-	}
132
-
133
-};
134
-
135
-// Binary encoding
136
-var Binary = charenc.Binary = {
137
-
138
-	// Convert a string to a byte array
139
-	stringToBytes: function (str) {
140
-		for (var bytes = [], i = 0; i < str.length; i++)
141
-			bytes.push(str.charCodeAt(i) & 0xFF);
142
-		return bytes;
143
-	},
144
-
145
-	// Convert a byte array to a string
146
-	bytesToString: function (bytes) {
147
-		for (var str = [], i = 0; i < bytes.length; i++)
148
-			str.push(String.fromCharCode(bytes[i]));
149
-		return str.join("");
150
-	}
151
-
152
-};
153
-
154
-})();
155
-}
1
+if (typeof Crypto == "undefined" || ! Crypto.util)
2
+{
3
+(function(){
4
+
5
+var base64map = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
6
+
7
+// Global Crypto object
8
+// with browser window or with node module
9
+var Crypto = (typeof window === 'undefined') ? exports.Crypto = {} : window.Crypto = {}; 
10
+
11
+// Crypto utilities
12
+var util = Crypto.util = {
13
+
14
+	// Bit-wise rotate left
15
+	rotl: function (n, b) {
16
+		return (n << b) | (n >>> (32 - b));
17
+	},
18
+
19
+	// Bit-wise rotate right
20
+	rotr: function (n, b) {
21
+		return (n << (32 - b)) | (n >>> b);
22
+	},
23
+
24
+	// Swap big-endian to little-endian and vice versa
25
+	endian: function (n) {
26
+
27
+		// If number given, swap endian
28
+		if (n.constructor == Number) {
29
+			return util.rotl(n,  8) & 0x00FF00FF |
30
+			       util.rotl(n, 24) & 0xFF00FF00;
31
+		}
32
+
33
+		// Else, assume array and swap all items
34
+		for (var i = 0; i < n.length; i++)
35
+			n[i] = util.endian(n[i]);
36
+		return n;
37
+
38
+	},
39
+
40
+	// Generate an array of any length of random bytes
41
+	randomBytes: function (n) {
42
+		for (var bytes = []; n > 0; n--)
43
+			bytes.push(Math.floor(Math.random() * 256));
44
+		return bytes;
45
+	},
46
+
47
+	// Convert a byte array to big-endian 32-bit words
48
+	bytesToWords: function (bytes) {
49
+		for (var words = [], i = 0, b = 0; i < bytes.length; i++, b += 8)
50
+			words[b >>> 5] |= (bytes[i] & 0xFF) << (24 - b % 32);
51
+		return words;
52
+	},
53
+
54
+	// Convert big-endian 32-bit words to a byte array
55
+	wordsToBytes: function (words) {
56
+		for (var bytes = [], b = 0; b < words.length * 32; b += 8)
57
+			bytes.push((words[b >>> 5] >>> (24 - b % 32)) & 0xFF);
58
+		return bytes;
59
+	},
60
+
61
+	// Convert a byte array to a hex string
62
+	bytesToHex: function (bytes) {
63
+		for (var hex = [], i = 0; i < bytes.length; i++) {
64
+			hex.push((bytes[i] >>> 4).toString(16));
65
+			hex.push((bytes[i] & 0xF).toString(16));
66
+		}
67
+		return hex.join("");
68
+	},
69
+
70
+	// Convert a hex string to a byte array
71
+	hexToBytes: function (hex) {
72
+		for (var bytes = [], c = 0; c < hex.length; c += 2)
73
+			bytes.push(parseInt(hex.substr(c, 2), 16));
74
+		return bytes;
75
+	},
76
+
77
+	// Convert a byte array to a base-64 string
78
+	bytesToBase64: function (bytes) {
79
+
80
+		// Use browser-native function if it exists
81
+		if (typeof btoa == "function") return btoa(Binary.bytesToString(bytes));
82
+
83
+		for(var base64 = [], i = 0; i < bytes.length; i += 3) {
84
+			var triplet = (bytes[i] << 16) | (bytes[i + 1] << 8) | bytes[i + 2];
85
+			for (var j = 0; j < 4; j++) {
86
+				if (i * 8 + j * 6 <= bytes.length * 8)
87
+					base64.push(base64map.charAt((triplet >>> 6 * (3 - j)) & 0x3F));
88
+				else base64.push("=");
89
+			}
90
+		}
91
+
92
+		return base64.join("");
93
+
94
+	},
95
+
96
+	// Convert a base-64 string to a byte array
97
+	base64ToBytes: function (base64) {
98
+
99
+		// Use browser-native function if it exists
100
+		if (typeof atob == "function") return Binary.stringToBytes(atob(base64));
101
+
102
+		// Remove non-base-64 characters
103
+		base64 = base64.replace(/[^A-Z0-9+\/]/ig, "");
104
+
105
+		for (var bytes = [], i = 0, imod4 = 0; i < base64.length; imod4 = ++i % 4) {
106
+			if (imod4 == 0) continue;
107
+			bytes.push(((base64map.indexOf(base64.charAt(i - 1)) & (Math.pow(2, -2 * imod4 + 8) - 1)) << (imod4 * 2)) |
108
+			           (base64map.indexOf(base64.charAt(i)) >>> (6 - imod4 * 2)));
109
+		}
110
+
111
+		return bytes;
112
+
113
+	}
114
+
115
+};
116
+
117
+// Crypto character encodings
118
+var charenc = Crypto.charenc = {};
119
+
120
+// UTF-8 encoding
121
+var UTF8 = charenc.UTF8 = {
122
+
123
+	// Convert a string to a byte array
124
+	stringToBytes: function (str) {
125
+		return Binary.stringToBytes(unescape(encodeURIComponent(str)));
126
+	},
127
+
128
+	// Convert a byte array to a string
129
+	bytesToString: function (bytes) {
130
+		return decodeURIComponent(escape(Binary.bytesToString(bytes)));
131
+	}
132
+
133
+};
134
+
135
+// Binary encoding
136
+var Binary = charenc.Binary = {
137
+
138
+	// Convert a string to a byte array
139
+	stringToBytes: function (str) {
140
+		for (var bytes = [], i = 0; i < str.length; i++)
141
+			bytes.push(str.charCodeAt(i) & 0xFF);
142
+		return bytes;
143
+	},
144
+
145
+	// Convert a byte array to a string
146
+	bytesToString: function (bytes) {
147
+		for (var str = [], i = 0; i < bytes.length; i++)
148
+			str.push(String.fromCharCode(bytes[i]));
149
+		return str.join("");
150
+	}
151
+
152
+};
153
+
154
+})();
155
+}