Skip to content

Commit

Permalink
add js library files
Browse files Browse the repository at this point in the history
  • Loading branch information
gwjjeff committed Jan 13, 2012
1 parent e8056e3 commit 99c719c
Show file tree
Hide file tree
Showing 13 changed files with 2,862 additions and 0 deletions.
402 changes: 402 additions & 0 deletions lib/AES.js

Large diffs are not rendered by default.

378 changes: 378 additions & 0 deletions 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;

})();

0 comments on commit 99c719c

Please sign in to comment.