/base/000_base/node_modules/cryptojs/lib/BlockModes.js |
@@ -0,0 +1,378 @@ |
/*! |
* Crypto-JS contribution from Simon Greatrix |
*/ |
|
(function(){ |
|
var C = (typeof window === 'undefined') ? require('./Crypto').Crypto : window.Crypto; |
|
// Create pad namespace |
var C_pad = C.pad = {}; |
|
// Calculate the number of padding bytes required. |
function _requiredPadding(cipher, message) { |
var blockSizeInBytes = cipher._blocksize * 4; |
var reqd = blockSizeInBytes - message.length % blockSizeInBytes; |
return reqd; |
}; |
|
// Remove padding when the final byte gives the number of padding bytes. |
var _unpadLength = function (message) { |
var pad = message.pop(); |
for (var i = 1; i < pad; i++) { |
message.pop(); |
} |
}; |
|
// No-operation padding, used for stream ciphers |
C_pad.NoPadding = { |
pad : function (cipher,message) {}, |
unpad : function (message) {} |
}; |
|
// Zero Padding. |
// |
// If the message is not an exact number of blocks, the final block is |
// completed with 0x00 bytes. There is no unpadding. |
C_pad.ZeroPadding = { |
pad : function (cipher, message) { |
var blockSizeInBytes = cipher._blocksize * 4; |
var reqd = message.length % blockSizeInBytes; |
if( reqd!=0 ) { |
for(reqd = blockSizeInBytes - reqd; reqd>0; reqd--) { |
message.push(0x00); |
} |
} |
}, |
|
unpad : function (message) {} |
}; |
|
// ISO/IEC 7816-4 padding. |
// |
// Pads the plain text with an 0x80 byte followed by as many 0x00 |
// bytes are required to complete the block. |
C_pad.iso7816 = { |
pad : function (cipher, message) { |
var reqd = _requiredPadding(cipher, message); |
message.push(0x80); |
for (; reqd > 1; reqd--) { |
message.push(0x00); |
} |
}, |
|
unpad : function (message) { |
while (message.pop() != 0x80) {} |
} |
}; |
|
// ANSI X.923 padding |
// |
// The final block is padded with zeros except for the last byte of the |
// last block which contains the number of padding bytes. |
C_pad.ansix923 = { |
pad : function (cipher, message) { |
var reqd = _requiredPadding(cipher, message); |
for (var i = 1; i < reqd; i++) { |
message.push(0x00); |
} |
message.push(reqd); |
}, |
|
unpad : _unpadLength |
}; |
|
// ISO 10126 |
// |
// The final block is padded with random bytes except for the last |
// byte of the last block which contains the number of padding bytes. |
C_pad.iso10126 = { |
pad : function (cipher, message) { |
var reqd = _requiredPadding(cipher, message); |
for (var i = 1; i < reqd; i++) { |
message.push(Math.floor(Math.random() * 256)); |
} |
message.push(reqd); |
}, |
|
unpad : _unpadLength |
}; |
|
// PKCS7 padding |
// |
// PKCS7 is described in RFC 5652. Padding is in whole bytes. The |
// value of each added byte is the number of bytes that are added, |
// i.e. N bytes, each of value N are added. |
C_pad.pkcs7 = { |
pad : function (cipher, message) { |
var reqd = _requiredPadding(cipher, message); |
for (var i = 0; i < reqd; i++) { |
message.push(reqd); |
} |
}, |
|
unpad : _unpadLength |
}; |
|
// Create mode namespace |
var C_mode = C.mode = {}; |
|
/** |
* Mode base "class". |
*/ |
var Mode = C_mode.Mode = function (padding) { |
if (padding) { |
this._padding = padding; |
} |
}; |
|
Mode.prototype = { |
encrypt: function (cipher, m, iv) { |
this._padding.pad(cipher, m); |
this._doEncrypt(cipher, m, iv); |
}, |
|
decrypt: function (cipher, m, iv) { |
this._doDecrypt(cipher, m, iv); |
this._padding.unpad(m); |
}, |
|
// Default padding |
_padding: C_pad.iso7816 |
}; |
|
|
/** |
* Electronic Code Book mode. |
* |
* ECB applies the cipher directly against each block of the input. |
* |
* ECB does not require an initialization vector. |
*/ |
var ECB = C_mode.ECB = function () { |
// Call parent constructor |
Mode.apply(this, arguments); |
}; |
|
// Inherit from Mode |
var ECB_prototype = ECB.prototype = new Mode; |
|
// Concrete steps for Mode template |
ECB_prototype._doEncrypt = function (cipher, m, iv) { |
var blockSizeInBytes = cipher._blocksize * 4; |
// Encrypt each block |
for (var offset = 0; offset < m.length; offset += blockSizeInBytes) { |
cipher._encryptblock(m, offset); |
} |
}; |
ECB_prototype._doDecrypt = function (cipher, c, iv) { |
var blockSizeInBytes = cipher._blocksize * 4; |
// Decrypt each block |
for (var offset = 0; offset < c.length; offset += blockSizeInBytes) { |
cipher._decryptblock(c, offset); |
} |
}; |
|
// ECB never uses an IV |
ECB_prototype.fixOptions = function (options) { |
options.iv = []; |
}; |
|
|
/** |
* Cipher block chaining |
* |
* The first block is XORed with the IV. Subsequent blocks are XOR with the |
* previous cipher output. |
*/ |
var CBC = C_mode.CBC = function () { |
// Call parent constructor |
Mode.apply(this, arguments); |
}; |
|
// Inherit from Mode |
var CBC_prototype = CBC.prototype = new Mode; |
|
// Concrete steps for Mode template |
CBC_prototype._doEncrypt = function (cipher, m, iv) { |
var blockSizeInBytes = cipher._blocksize * 4; |
|
// Encrypt each block |
for (var offset = 0; offset < m.length; offset += blockSizeInBytes) { |
if (offset == 0) { |
// XOR first block using IV |
for (var i = 0; i < blockSizeInBytes; i++) |
m[i] ^= iv[i]; |
} else { |
// XOR this block using previous crypted block |
for (var i = 0; i < blockSizeInBytes; i++) |
m[offset + i] ^= m[offset + i - blockSizeInBytes]; |
} |
// Encrypt block |
cipher._encryptblock(m, offset); |
} |
}; |
CBC_prototype._doDecrypt = function (cipher, c, iv) { |
var blockSizeInBytes = cipher._blocksize * 4; |
|
// At the start, the previously crypted block is the IV |
var prevCryptedBlock = iv; |
|
// Decrypt each block |
for (var offset = 0; offset < c.length; offset += blockSizeInBytes) { |
// Save this crypted block |
var thisCryptedBlock = c.slice(offset, offset + blockSizeInBytes); |
// Decrypt block |
cipher._decryptblock(c, offset); |
// XOR decrypted block using previous crypted block |
for (var i = 0; i < blockSizeInBytes; i++) { |
c[offset + i] ^= prevCryptedBlock[i]; |
} |
prevCryptedBlock = thisCryptedBlock; |
} |
}; |
|
|
/** |
* Cipher feed back |
* |
* The cipher output is XORed with the plain text to produce the cipher output, |
* which is then fed back into the cipher to produce a bit pattern to XOR the |
* next block with. |
* |
* This is a stream cipher mode and does not require padding. |
*/ |
var CFB = C_mode.CFB = function () { |
// Call parent constructor |
Mode.apply(this, arguments); |
}; |
|
// Inherit from Mode |
var CFB_prototype = CFB.prototype = new Mode; |
|
// Override padding |
CFB_prototype._padding = C_pad.NoPadding; |
|
// Concrete steps for Mode template |
CFB_prototype._doEncrypt = function (cipher, m, iv) { |
var blockSizeInBytes = cipher._blocksize * 4, |
keystream = iv.slice(0); |
|
// Encrypt each byte |
for (var i = 0; i < m.length; i++) { |
|
var j = i % blockSizeInBytes; |
if (j == 0) cipher._encryptblock(keystream, 0); |
|
m[i] ^= keystream[j]; |
keystream[j] = m[i]; |
} |
}; |
CFB_prototype._doDecrypt = function (cipher, c, iv) { |
var blockSizeInBytes = cipher._blocksize * 4, |
keystream = iv.slice(0); |
|
// Encrypt each byte |
for (var i = 0; i < c.length; i++) { |
|
var j = i % blockSizeInBytes; |
if (j == 0) cipher._encryptblock(keystream, 0); |
|
var b = c[i]; |
c[i] ^= keystream[j]; |
keystream[j] = b; |
} |
}; |
|
|
/** |
* Output feed back |
* |
* The cipher repeatedly encrypts its own output. The output is XORed with the |
* plain text to produce the cipher text. |
* |
* This is a stream cipher mode and does not require padding. |
*/ |
var OFB = C_mode.OFB = function () { |
// Call parent constructor |
Mode.apply(this, arguments); |
}; |
|
// Inherit from Mode |
var OFB_prototype = OFB.prototype = new Mode; |
|
// Override padding |
OFB_prototype._padding = C_pad.NoPadding; |
|
// Concrete steps for Mode template |
OFB_prototype._doEncrypt = function (cipher, m, iv) { |
|
var blockSizeInBytes = cipher._blocksize * 4, |
keystream = iv.slice(0); |
|
// Encrypt each byte |
for (var i = 0; i < m.length; i++) { |
|
// Generate keystream |
if (i % blockSizeInBytes == 0) |
cipher._encryptblock(keystream, 0); |
|
// Encrypt byte |
m[i] ^= keystream[i % blockSizeInBytes]; |
|
} |
}; |
OFB_prototype._doDecrypt = OFB_prototype._doEncrypt; |
|
/** |
* Counter |
* @author Gergely Risko |
* |
* After every block the last 4 bytes of the IV is increased by one |
* with carry and that IV is used for the next block. |
* |
* This is a stream cipher mode and does not require padding. |
*/ |
var CTR = C_mode.CTR = function () { |
// Call parent constructor |
Mode.apply(this, arguments); |
}; |
|
// Inherit from Mode |
var CTR_prototype = CTR.prototype = new Mode; |
|
// Override padding |
CTR_prototype._padding = C_pad.NoPadding; |
|
CTR_prototype._doEncrypt = function (cipher, m, iv) { |
var blockSizeInBytes = cipher._blocksize * 4; |
var counter = iv.slice(0); |
|
for (var i = 0; i < m.length;) { |
// do not lose iv |
var keystream = counter.slice(0); |
|
// Generate keystream for next block |
cipher._encryptblock(keystream, 0); |
|
// XOR keystream with block |
for (var j = 0; i < m.length && j < blockSizeInBytes; j++, i++) { |
m[i] ^= keystream[j]; |
} |
|
// Increase counter |
if(++(counter[blockSizeInBytes-1]) == 256) { |
counter[blockSizeInBytes-1] = 0; |
if(++(counter[blockSizeInBytes-2]) == 256) { |
counter[blockSizeInBytes-2] = 0; |
if(++(counter[blockSizeInBytes-3]) == 256) { |
counter[blockSizeInBytes-3] = 0; |
++(counter[blockSizeInBytes-4]); |
} |
} |
} |
} |
}; |
CTR_prototype._doDecrypt = CTR_prototype._doEncrypt; |
|
})(); |