1. #11
    Ext JS Premium Member
    Join Date
    Mar 2007
    Location
    Virginia, USA
    Posts
    504
    Vote Rating
    0
    vtswingkid is on a distinguished road

      0  

    Default


    I have encrypted and decrypted fine in javascript...

    Do you know what openssl method I can use to encrypt decrypt that will be compatible?

    openssl enc -aes-256-cbc ?

  2. #12
    Ext JS Premium Member
    Join Date
    Mar 2007
    Location
    Virginia, USA
    Posts
    504
    Vote Rating
    0
    vtswingkid is on a distinguished road

      0  

    Default


    I took the nist documents and implemented the foward and reverse cipher. Then I wrapped those with both the cbc and ecb algorithms. I'll submit them soon. I still would like to figure out how openssl generates the key and iv from a standard text password. But in the mean time the key and iv (in the case of cbc) can be passed in.

    For simplicity I'll just post it under and aes extension. You could add it to crypto if you like it though.

  3. #13
    Ext JS Premium Member
    Join Date
    Mar 2007
    Location
    Virginia, USA
    Posts
    504
    Vote Rating
    0
    vtswingkid is on a distinguished road

      0  

    Thumbs up Ext.ux.Crypto.AES

    Ext.ux.Crypto.AES


    I have written a new AES extension for crypto. It is compatible with openssl.

    I do not yet support salts, and I am using sha1 digest for the key and iv creation...

    examples:

    echo -n "test" | openssl enc -aes256 -a -md sha1 -pass pass:testpass

    feed that output to AES

    Ext.ux.Crypto.AES.Decrypt({pass:"testpass", data:output, b64:true});

    similarly...

    var out2=Ext.ux.Crypto.AES.Encrypt({pass:"testpass2", data:"test2", b64:true, mode:"ecb", bits:192});

    decrypt out2 with openssl

    echo -n out2 | openssl enc -d -eas-192-ecb -a -md sha1 -pass pass:testpass2

    options for Decrypt and Encrypt include:
    pass: ascii password string
    data: ascii string, byte array
    b64: true/false (default false)
    mode: "ecb"/"cbc" (default "cbc")
    bits: 128/192/256 (default 256)
    key: byte array of length 16/24/32 (generated if pass is provided)
    iv: byte array of length 16 (generated if pass is provided)

    I also provided access to all of the base routines that Encrypt and Decrypt make use of incase you want to by pass some things.

    Here is the code.

    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);
        }
      }
    }();
    Last edited by vtswingkid; 13 Feb 2008 at 1:51 PM. Reason: 1.0.1 Fixed Base64 for longer strings and IE compatibility

  4. #14
    Sencha User
    Join Date
    May 2007
    Posts
    32
    Vote Rating
    0
    Diddy433 is on a distinguished road

      0  

    Default


    Has anyone looked into updating the AES crypto functionality to use base64 encoding or is this already implemented? I see that in October 2008 Chris Vennuss updated his AES script to use base64.

  5. #15
    Sencha User
    Join Date
    Jan 2008
    Location
    Ireland
    Posts
    11
    Vote Rating
    0
    dbraiden is on a distinguished road

      0  

    Default


    I finally got this to work.

    If you need to decrypt this using openssl you will need to specify the -nosalt option.

    Hope that helps

    Dave

  6. #16
    Sencha User
    Join Date
    Jan 2010
    Location
    Brno, Czech Republic
    Posts
    35
    Vote Rating
    1
    honzakuchar is on a distinguished road

      0  

    Question Source, download and example?

    Source, download and example?


    Hi, I really want try this extension. :-) It looks great from description! But where can I view examples or download source? Examples (from http://www.sencha.com/learn/legacy/Extension:Crypto) cannot be accessed:
    - AES: http://ext.vosandhowden.com/ux/crypto/aes.cfm
    - TEA: http://ext.vosandhowden.com/ux/crypto/tea.cfm
    - SHA-1: http://ext.vosandhowden.com/ux/crypto/sha1.cfm

    Regards.
    Jan Kuchar

  7. #17
    Ext JS Premium Member
    Join Date
    Mar 2007
    Location
    Virginia, USA
    Posts
    504
    Vote Rating
    0
    vtswingkid is on a distinguished road

      0  

    Default


    My code contributions in this thread are public domain.