Code:
//ADVANCED ENCRYPTION STANDARD (AES)
//
//VERSION: 1.0.1
//AUTHOR: Robert Williams (Extjs User: vtswingkid)
//
//SUMMARY: This version of AES is based NIST's Processing Standards Publication 197.
// ECB and CBC modes haven been implemented with compatibility to that of openssl.
Ext.namespace('Ext.ux', 'Ext.ux.Crypto');
Ext.ux.Crypto.AES = function(){
//Number of columns (32-bit words) comprising the State. For this
//standard, Nb = 4.
var Nb=4;
//The round constant word array.
var Rcon = [
[0x00, 0x00, 0x00, 0x00],
[0x01, 0x00, 0x00, 0x00],
[0x02, 0x00, 0x00, 0x00],
[0x04, 0x00, 0x00, 0x00],
[0x08, 0x00, 0x00, 0x00],
[0x10, 0x00, 0x00, 0x00],
[0x20, 0x00, 0x00, 0x00],
[0x40, 0x00, 0x00, 0x00],
[0x80, 0x00, 0x00, 0x00],
[0x1b, 0x00, 0x00, 0x00],
[0x36, 0x00, 0x00, 0x00]
];
//Non-linear substitution table used in several byte substitution
//transformations and in the Key Expansion routine to perform a onefor-
//one substitution of a byte value.
var Sbox = [
0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16
];
//Inverse of Sbox
var InvSbox = [
0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,
0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,
0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06,
0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,
0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,
0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d
];
var B64Map="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".split("");
var B64Pad="=";
var InvB64Map = new Array();
for(var i=0;i<B64Map.length;i++)InvB64Map[B64Map[i]]=i;
//Function used in the Key Expansion routine that takes a four-byte
//input word and applies an S-box to each of the four bytes to
//produce an output word.
var SubWord = function(word){
for(var i=0;i<4;i++)word[i]= Sbox[word[i]];
return word;
};
//Function used in the Key Expansion routine that takes a four-byte
//word and performs a cyclic permutation.
var RotWord = function(word){
temp=word[0];
for(var i=0;i<3;i++)word[i]= word[i+1];
word[3]=temp;
return word;
};
//Transformation in the Cipher and Inverse Cipher in which a Round
//Key is added to the State using an XOR operation. The length of a
//Round Key equals the size of the State (i.e., for Nb = 4, the Round
//Key length equals 128 bits/16 bytes).
var AddRoundKey = function(state, round, roundKeys){
var row, col;
for (row=0; row<4; row++) {
for (col=0; col<Nb; col++) state[row][col] ^= roundKeys[round*4+col][row];
}
return state;
};
//Transformation in the Cipher that processes the State using a nonlinear
//byte substitution table (S-box) that operates on each of the
//State bytes independently.
var SubBytes = function(state){
var row,col;
var tmp;
for(row=0; row<4; row++){
for(col=0; col<Nb; col++){
tmp=state[row][col];
state[row][col]=Sbox[state[row][col]];
}
}
return state;
};
//Transformation in the Cipher that processes the State by cyclically
//shifting the last three rows of the State by different offsets.
var ShiftRows = function(state){
var row,col;
var tmp = new Array();
for(row=1; row<4; row++){
for(col=0; col<Nb; col++)tmp[col]=state[row][(col+row)%Nb];
for(col=0; col<Nb; col++)state[row][col]=tmp[col];
}
return state;
};
//Transformation in the Cipher that takes all of the columns of the
//State and mixes their data (independently of one another) to
//produce new columns.
var MixColumns = function(state){
var col, i;
var x1 = new Array(); // times 1
var x2 = new Array(); // times 2
var x3 = new Array(); // times 3
for (col=0; col<Nb; col++) {
for (i=0; i<4; i++) {
x1[i] = state[i][col]; //{01}*Sx
x2[i] = x1[i]<<1; //{02}*Sx
if(x2[i]>0xff)x2[i]^=0x011b;
x3[i] = x1[i] ^ x2[i]; //{03}*Sx
}
//state[0] = ({02}*S0) ^ ({03}*S1) ^ S2 ^ S3
state[0][col] = x2[0] ^ x3[1] ^ x1[2] ^ x1[3];
//state[1] = S0 ^ ({02}*S1) ^ ({03}*S2) ^ S3
state[1][col] = x1[0] ^ x2[1] ^ x3[2] ^ x1[3];
//state[2] = S0 ^ S1 ^ ({02}*S2) ^ ({03}*S3)
state[2][col] = x1[0] ^ x1[1] ^ x2[2] ^ x3[3];
//state[3] = ({03}*S0) ^ S1 ^ S2 ^ ({02}*S3)
state[3][col] = x3[0] ^ x1[1] ^ x1[2] ^ x2[3];
}
return state;
};
//Transformation in the Inverse Cipher that is the inverse of
//SubBytes().
var InvSubBytes = function(state){
var row,col;
var tmp;
for(row=0; row<4; row++){
for(col=0; col<Nb; col++){
tmp=state[row][col];
state[row][col]=InvSbox[state[row][col]];
}
}
return state;
};
//Transformation in the Inverse Cipher that is the inverse of
//ShiftRows().
var InvShiftRows = function(state){
var row,col;
var tmp = new Array();
for(row=1; row<4; row++){
for(col=0; col<Nb; col++)tmp[col]=state[row][(col+(Nb-row))%Nb];
for(col=0; col<Nb; col++)state[row][col]=tmp[col];
}
return state;
};
//Transformation in the Inverse Cipher that is the inverse of
//MixColumns().
var InvMixColumns = function(state){
var col, i;
var x1 = new Array(); // times 0x01
var x2 = new Array(); // times 0x02
var x4 = new Array(); // times 0x04
var x8 = new Array(); // times 0x08
var x9 = new Array(); // times 0x09
var xB = new Array(); // times 0x0b
var xD = new Array(); // times 0x0d
var xE = new Array(); // times 0x0e
for (col=0; col<Nb; col++) {
for (i=0; i<4; i++) {
x1[i] = state[i][col]; //{01}*Sx
x2[i] = x1[i]<<1; //{02}*Sx
if(x2[i]>0xff)x2[i]^=0x011b;
x4[i] = x2[i]<<1; //{04}*Sx
if(x4[i]>0xff)x4[i]^=0x011b;
x8[i] = x4[i]<<1; //{08}*Sx
if(x8[i]>0xff)x8[i]^=0x011b;
x9[i] = x8[i] ^ x1[i]; //{09}*Sx
xB[i] = x8[i] ^ x2[i] ^ x1[i]; //{0b}*Sx
xD[i] = x8[i] ^ x4[i] ^ x1[i]; //{0d}*Sx
xE[i] = x8[i] ^ x4[i] ^ x2[i]; //{0e}*Sx
}
//state[0] = ({0e}*S0) ^ ({0b}*S1) ^ ({0d}*S2) ^ ({09}*S3)
state[0][col] = xE[0] ^ xB[1] ^ xD[2] ^ x9[3];
//state[1] = ({09}*S0) ^ ({0e}*S1) ^ ({0b}*S2) ^ ({0d}*S3)
state[1][col] = x9[0] ^ xE[1] ^ xB[2] ^ xD[3];
//state[2] = ({0d}*S0) ^ ({09}*S1) ^ ({0e}*S2) ^ ({0b}*S3)
state[2][col] = xD[0] ^ x9[1] ^ xE[2] ^ xB[3];
//state[3] = ({0b}*S0) ^ ({0d}*S1) ^ ({09}*S2) ^ ({0e}*S3)
state[3][col] = xB[0] ^ xD[1] ^ x9[2] ^ xE[3];
}
return state;
};
return{
KeyExpansion:function(key){
var i,j;
var temp = new Array();
var Nk; //Number of 32-bit words comprising the Cipher Key. For this
//standard, Nk = 4, 6, or 8.
var Nr; //Number of rounds, which is a function of Nk and Nb (which is
//fixed). For this standard, Nr = 10, 12, or 14.
if(!(key instanceof Array && (key.length==16 || key.length==24 || key.length==32))){
alert("KeyExpansion: key must be an array of length 16, 24, or 32 bytes");
}
Nk=key.length/4;
Nr=Nk+6;
roundKeys=new Array();
for(i=0;i<Nk;i++){
roundKeys[i]=[key[4*i], key[4*i+1], key[4*i+2], key[4*i+3]];
}
for(;i<Nb*(Nr+1);i++){
roundKeys[i]=new Array();
for (j = 0; j < 4; j++)temp[j] = roundKeys[i - 1][j];
if (i % Nk == 0) {
temp = SubWord(RotWord(temp));
for (j = 0; j < 4; j++)temp[j] ^= Rcon[i/Nk][j];
}else if (Nk>6 && i%Nk==4){
temp = SubWord(temp);
}
for (j=0; j<4; j++) roundKeys[i][j] = roundKeys[i-Nk][j] ^ temp[j];
}
return roundKeys
},
Cipher: function(input, roundKeys){
var row,col;
var Nr; //Number of rounds, which is a function of Nk and Nb (which is
//fixed). For this standard, Nr = 10, 12, or 14.
var state=new Array(); //Intermediate Cipher result that can be pictured as a rectangular array
//of bytes, having four rows and Nb columns.
var output=new Array();
var round;
if(!(input instanceof Array && input.length==4*Nb)){
alert("Cipher: input must be an array of length "+(4*Nb));
return null;
}
if(!(roundKeys instanceof Array && (roundKeys.length==Nb*11 || roundKeys.length==Nb*13 || roundKeys.length==Nb*15))){
alert("Cipher: roundKeys must be an array of length "+(Nb*11)+", "+(Nb*13)+", or "+(Nb*15));
return null;
}
Nr = roundKeys.length/Nb - 1;
//copy the input to the state
for(row=0; row<4; row++){
state[row]=new Array();
for(col=0; col<Nb; col++){
state[row][col]=input[row+4*col];
}
}
//PrintState(state, "copy");
//cipher
state=AddRoundKey(state, 0, roundKeys);
for(round=1; round<Nr; round++){
state=SubBytes(state);
state=ShiftRows(state);
state=MixColumns(state);
state=AddRoundKey(state, round, roundKeys);
}
state=SubBytes(state);
state=ShiftRows(state);
state=AddRoundKey(state, Nr, roundKeys);
//PrintState(state, "final");
//copy state to output
for(row=0; row<4; row++){
for(col=0; col<Nb; col++){
output[row+4*col]=state[row][col];
}
}
return output;
},
InvCipher: function(input, roundKeys){
var row,col;
var Nr; //Number of rounds, which is a function of Nk and Nb (which is
//fixed). For this standard, Nr = 10, 12, or 14.
var state=new Array(); //Intermediate Cipher result that can be pictured as a rectangular array
//of bytes, having four rows and Nb columns.
var output=new Array();
var round;
if(!(input instanceof Array && input.length==4*Nb)){
alert("Cipher: input must be an array of length "+(4*Nb));
return null;
}
if(!(roundKeys instanceof Array && (roundKeys.length==Nb*11 || roundKeys.length==Nb*13 || roundKeys.length==Nb*15))){
alert("Cipher: roundKeys must be an array of length "+(Nb*11)+", "+(Nb*13)+", or "+(Nb*15));
return null;
}
Nr = roundKeys.length/Nb - 1;
//copy the input to the state
for(row=0; row<4; row++){
state[row]=new Array();
for(col=0; col<Nb; col++){
state[row][col]=input[row+4*col];
}
}
//PrintState(state, "copy");
//cipher
state=AddRoundKey(state, Nr, roundKeys);
for(round=Nr-1; round>0; round--){
state=InvShiftRows(state);
state=InvSubBytes(state);
state=AddRoundKey(state, round, roundKeys);
state=InvMixColumns(state);
}
state=InvShiftRows(state);
state=InvSubBytes(state);
state=AddRoundKey(state, 0, roundKeys);
//PrintState(state, "final");
//copy state to output
for(row=0; row<4; row++){
for(col=0; col<Nb; col++){
output[row+4*col]=state[row][col];
}
}
return output;
},
StringToKeyIv: function(str, bits){
var h;
var hash = new Array();
var key = new Array();
var iv = new Array();
var nkey=0;
var niv=16;
var i;
if(bits!=128 && bits!=192 && bits!=256){
alert("BytesToKey: bits must be 128, 192, or 256");
return null;
}
nkey=bits/8;
h=Ext.ux.Crypto.SHA1.hash(str).toString();
for(i=0;i<h.length;i+=2)hash[i/2]=parseInt(h.substr(i,1)+h.substr(i+1,1),16);
for(;;){
i=0;
if(nkey){
while(nkey){
key.push(hash[i++]);
nkey--;
if(i==hash.length)break;
}
}
if(niv && i<hash.length){
while(niv){
iv.push(hash[i++]);
niv--;
if(i==hash.length)break;
}
}
if(!nkey && !niv)break;
for(i=0;i<hash.length;i++)hash[i]=String.fromCharCode(hash[i]);
h=Ext.ux.Crypto.SHA1.hash(hash.join("")+str);
for(i=0;i<h.length;i+=2)hash[i/2]=parseInt(h.substr(i,1)+h.substr(i+1,1),16);
}
return {key:key, iv:iv};
},
StringToPaddedData: function(str){
var data=new Array();
var i;
for(i=0;i<str.length;i++)data.push(str.charCodeAt(i));
var m = 16-(i%16);
for(i=0;i<m;i++)data.push(m);
return data;
},
PaddedDataToString: function(data){
var str="";
var i;
var pad=data[data.length-1];
for(i=0;i<(data.length-pad);i++)str+=String.fromCharCode(data[i]);
return str;
},
BytesToB64: function(bytes){
var i;
var b64="";
var brk=64;
//convert 3 bytes to 4 octets
for (i = 0; i + 2 < bytes.length; i += 3) {
b64 += B64Map[bytes[i] >>> 2];
b64 += B64Map[(bytes[i] << 4 & 0x3f) + (bytes[i + 1] >>> 4)];
b64 += B64Map[(bytes[i + 1] << 2 & 0x3f) + (bytes[i + 2] >>> 6)];
b64 += B64Map[bytes[i + 2] & 0x3f];
}
//handle remaining bytes
if (i < bytes.length) {
if (i + 1 < bytes.length) {
//convert 2 bytes to 3octets and 1 pad
b64 += B64Map[bytes[i] >>> 2];
b64 += B64Map[(bytes[i] << 4 & 0x3f) + (bytes[i + 1] >>> 4)];
b64 += B64Map[bytes[i + 1] << 2 & 0x3f];
b64 += B64Pad;
}
else {
//convert 1 bytes to 2octets and 2 pad
b64 += B64Map[bytes[i] >>> 2];
b64 += B64Map[bytes[i] << 4 & 0x3f];
b64 += B64Pad;
b64 += B64Pad;
}
}
//add new lines
for (i = brk; i < b64.length; i += brk) {
b64 = b64.substr(0,i-1)+"\n"+b64.substr(i-1);
}
return b64;
},
B64ToBytes: function(b64){
var i,j,o;
var octets=new Array();
var bytes=new Array();
//remove all none base 64 characters and convert to octets (including "=")
for (i = 0, j=0; i < b64.length; i++) {
if((o=InvB64Map[b64.substr(i,1)])!=null)octets[j++]=o;
}
//convert 4 octets to 3 bytes
for (i = 0, j = 0; i + 3 < octets.length; i+=4) {
bytes[j++]=(octets[i]<<2)+(octets[i+1]>>>4);
bytes[j++]=(octets[i+1]<<4&0xff)+(octets[i+2]>>>2);
bytes[j++]=(octets[i+2]<<6&0xff)+octets[i+3];
}
//handle remaining octets
if (i + 1 < octets.length) {
//convert 2 octets to 1 bytes
bytes[j++]=(octets[i]<<2)+(octets[i+1]>>>4);
if (i + 2 < octets.length) {
//convert 3 octets to 2 bytes
bytes[j++]=(octets[i+1]<<4&0xff)+(octets[i+2]>>>2);
}
}
return bytes;
},
Prepare: function(obj){
var i, ki, data;
var bits=256;
var o = {
mode: "cbc",
b64: false,
data: new Array(),
key: new Array(),
iv: new Array()
};
if(obj.mode=="ecb")o.mode=obj.mode;
if(obj.b64==true)o.b64=obj.b64;
if(typeof obj.pass == "string"){
if(obj.bits==128||obj.bits==192)bits=obj.bits;
ki=Ext.ux.Crypto.AES.StringToKeyIv(obj.pass, bits);
for (i = 0; i < ki.key.length; i++)o.key[i]=ki.key[i];
for (i = 0; i < ki.iv.length; i++)o.iv[i]=ki.iv[i];
}else{
if(!(obj.key instanceof Array) || (obj.key.length!=16&&obj.key.length!=24&&obj.key.length!=32)){
alert("obj.key must be a byte array of length 16, 24, or 32");
return null;
}
for(i=0; i<obj.key.length; i++){
if(typeof obj.key[i]!="number"){
alert("obj.key must be a byte array of length 16, 24, or 32");
return null;
}
o.key[i]=obj.key[i];
}
if(o.mode=="cbc"){
if(!(obj.iv instanceof Array)||obj.iv.length!=16){
alert("obj.iv must be a byte array of length 16");
return null;
}
for (i = 0; i < obj.iv.length; i++) {
if (typeof obj.iv[i] != "number") {
alert("obj.iv must be a byte array of length 16");
return null;
}
o.iv[i] = obj.iv[i];
}
}
}
if(typeof obj.data == "string"){
data=Ext.ux.Crypto.AES.StringToPaddedData(obj.data);
for (i = 0; i < data.length; i++)o.data[i]=data[i];
}else{
if (!(obj.data instanceof Array)||obj.data.length%16) {
alert("obj.data must be a byte array with a multiple of 16 length ");
return null;
}
for(i=0;i<obj.data.length;i++){
if (typeof obj.data[i] != "number") {
alert("obj.data must be a byte array with a multiple of 16 length ");
return null;
}
o.data[i] = obj.data[i];
}
}
o.round=Ext.ux.Crypto.AES.KeyExpansion(o.key);
return o;
},
//Encrypt expects obj specifying what and how to encrypt.
Encrypt: function(obj){
var cipher = new Array();
var input = new Array();
var output;
var i,j;
var roundKeys;
var o;
o=Ext.ux.Crypto.AES.Prepare(obj);
if(o==null)return null;
if(o.mode=="cbc")output=o.iv;
for (j = 0; j < o.data.length / 16; j++) {
for (i = 0; i < 16; i++) {
input[i] = o.data[j * 16 + i];
if(o.mode=="cbc")input[i]^=output[i];
}
output = Ext.ux.Crypto.AES.Cipher(input, o.round);
for (i = 0; i < 16; i++) cipher[j * 16 + i] = output[i];
}
if(o.b64)cipher=Ext.ux.Crypto.AES.BytesToB64(cipher);
return cipher;
},
Decrypt: function(obj){
var plain = new Array();
var input = new Array();
var copy = new Array();
var output;
var i,j;
var roundKeys;
var o;
o=Ext.ux.Crypto.AES.Prepare(obj);
if(o==null)return null;
if(o.b64)o.data=Ext.ux.Crypto.AES.B64ToBytes(obj.data);
if(o.mode=="cbc"){
for(i=0;i<o.iv.length;i++)copy[i]=o.iv[i];
}
for (j = 0; j < o.data.length / 16; j++) {
if (j>0 && o.mode == "cbc") {
for (i = 0; i < 16; i++)copy[i] = input[i];
}
for (i = 0; i < 16; i++) input[i] = o.data[j * 16 + i];
output = Ext.ux.Crypto.AES.InvCipher(input, o.round);
for (i = 0; i < 16; i++) {
plain[j * 16 + i] = output[i];
if(o.mode=="cbc")plain[j *16 + i]^=copy[i];
}
}
return Ext.ux.Crypto.AES.PaddedDataToString(plain);
}
}
}();