corrade-nucleus-nucleons – Blame information for rev 20

Subversion Repositories:
Rev:
Rev Author Line No. Line
20 office 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 })();