2012-01-07 4 views
1

좋아, 나는 다음과 같은 AES 자바 스크립트 라이브러리를 사용하고 있습니다 :AES 자바 스크립트 및 자바

http://www.movable-type.co.uk/scripts/aes.html

나는 그 자바 스크립트에 의해 암호화 된 패키지 결과적 해독 할 수있는 자바를 쓰기 위해 노력하고있어,하지만 난 계속 오류를 일으키고 모든 종류의 오류가 계속 발생합니다.

예 : javax.crypto.IllegalBlockSizeException : 패딩 된 암호로 해독 할 때 입력 길이가 16의 배수 여야합니다.

다음은 Java 코드입니다. 누구든지 올바른 방향으로 나를 가리 키도록 도와 줄 수 있습니까? 내가 사용

package com.thebodgeitstore.util; 

import java.security.InvalidKeyException; 
import java.security.NoSuchAlgorithmException; 
import java.util.regex.Pattern; 
import javax.crypto.*; 
import javax.crypto.spec.*; 


    public class AES { 
     private SecretKeySpec key; 
     private Cipher cipher; 
     private int size = 128; 

     public AES() throws NoSuchAlgorithmException, NoSuchPaddingException{ 
      KeyGenerator kgen = KeyGenerator.getInstance("AES"); 
      kgen.init(size); // 192 and 256 bits may not be available 
      SecretKey skey = kgen.generateKey(); 
      byte[] raw = skey.getEncoded(); 
      key = new SecretKeySpec(raw, "AES"); 
      cipher = Cipher.getInstance("AES"); 
     } 

     public void setKey(String keyText){ 
      byte[] bText = new byte[size]; 
      bText = keyText.getBytes(); 
      key = new SecretKeySpec(bText, "AES"); 
     } 

     public String encrypt(String message) throws InvalidKeyException, IllegalBlockSizeException, BadPaddingException{ 
      cipher.init(Cipher.ENCRYPT_MODE, key); 
      byte[] encrypted = cipher.doFinal(message.getBytes()); 
      return byteArrayToHexString(encrypted); 
     } 
     public String decrypt(String hexCiphertext) throws IllegalBlockSizeException, BadPaddingException, InvalidKeyException{ 
      cipher.init(Cipher.DECRYPT_MODE, key); 
      byte[] decrypted = cipher.doFinal(hexStringToByteArray(hexCiphertext)); 
      return byteArrayToHexString(decrypted); 
     } 

     private static String byteArrayToHexString(byte [] raw) { 
      String hex = "0x"; 
      String s = new String(raw); 
      for(int x = 0; x < s.length(); x++){ 
       char[] t = s.substring(x, x + 1).toCharArray(); 
       hex += Integer.toHexString((int) t[0]).toUpperCase(); 
      } 
      return hex; 
     } 

     private static byte[] hexStringToByteArray(String hex) { 
      Pattern replace = Pattern.compile("^0x"); 
      String s = replace.matcher(hex).replaceAll(""); 

      byte[] b = new byte[s.length()/2]; 
      for (int i = 0; i < b.length; i++){ 
       int index = i * 2; 
       int v = Integer.parseInt(s.substring(index, index + 2), 16); 
       b[i] = (byte)v; 
      } 
      return b; 
     } 


    } 

자바 스크립트 코드 : 내가 뭘하는지의 목적

/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 
/* AES implementation in JavaScript (c) Chris Veness 2005-2011         */ 
/* - see http://csrc.nist.gov/publications/PubsFIPS.html#197         */ 
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 

var Aes = {}; // Aes namespace 

/** 
* AES Cipher function: encrypt 'input' state with Rijndael algorithm 
* applies Nr rounds (10/12/14) using key schedule w for 'add round key' stage 
* 
* @param {Number[]} input 16-byte (128-bit) input state array 
* @param {Number[][]} w Key schedule as 2D byte-array (Nr+1 x Nb bytes) 
* @returns {Number[]}  Encrypted output state array 
*/ 
Aes.cipher = function(input, w) { // main Cipher function [§5.1] 
    var Nb = 4;    // block size (in words): no of columns in state (fixed at 4 for AES) 
    var Nr = w.length/Nb - 1; // no of rounds: 10/12/14 for 128/192/256-bit keys 

    var state = [[],[],[],[]]; // initialise 4xNb byte-array 'state' with input [§3.4] 
    for (var i=0; i<4*Nb; i++) state[i%4][Math.floor(i/4)] = input[i]; 

    state = Aes.addRoundKey(state, w, 0, Nb); 

    for (var round=1; round<Nr; round++) { 
    state = Aes.subBytes(state, Nb); 
    state = Aes.shiftRows(state, Nb); 
    state = Aes.mixColumns(state, Nb); 
    state = Aes.addRoundKey(state, w, round, Nb); 
    } 

    state = Aes.subBytes(state, Nb); 
    state = Aes.shiftRows(state, Nb); 
    state = Aes.addRoundKey(state, w, Nr, Nb); 

    var output = new Array(4*Nb); // convert state to 1-d array before returning [§3.4] 
    for (var i=0; i<4*Nb; i++) output[i] = state[i%4][Math.floor(i/4)]; 
    return output; 
} 

/** 
* Perform Key Expansion to generate a Key Schedule 
* 
* @param {Number[]} key Key as 16/24/32-byte array 
* @returns {Number[][]} Expanded key schedule as 2D byte-array (Nr+1 x Nb bytes) 
*/ 
Aes.keyExpansion = function(key) { // generate Key Schedule (byte-array Nr+1 x Nb) from Key [§5.2] 
    var Nb = 4;   // block size (in words): no of columns in state (fixed at 4 for AES) 
    var Nk = key.length/4 // key length (in words): 4/6/8 for 128/192/256-bit keys 
    var Nr = Nk + 6;  // no of rounds: 10/12/14 for 128/192/256-bit keys 

    var w = new Array(Nb*(Nr+1)); 
    var temp = new Array(4); 

    for (var i=0; i<Nk; i++) { 
    var r = [key[4*i], key[4*i+1], key[4*i+2], key[4*i+3]]; 
    w[i] = r; 
    } 

    for (var i=Nk; i<(Nb*(Nr+1)); i++) { 
    w[i] = new Array(4); 
    for (var t=0; t<4; t++) temp[t] = w[i-1][t]; 
    if (i % Nk == 0) { 
     temp = Aes.subWord(Aes.rotWord(temp)); 
     for (var t=0; t<4; t++) temp[t] ^= Aes.rCon[i/Nk][t]; 
    } else if (Nk > 6 && i%Nk == 4) { 
     temp = Aes.subWord(temp); 
    } 
    for (var t=0; t<4; t++) w[i][t] = w[i-Nk][t]^temp[t]; 
    } 

    return w; 
} 

/* 
* ---- remaining routines are private, not called externally ---- 
*/ 

Aes.subBytes = function(s, Nb) { // apply SBox to state S [§5.1.1] 
    for (var r=0; r<4; r++) { 
    for (var c=0; c<Nb; c++) s[r][c] = Aes.sBox[s[r][c]]; 
    } 
    return s; 
} 

Aes.shiftRows = function(s, Nb) { // shift row r of state S left by r bytes [§5.1.2] 
    var t = new Array(4); 
    for (var r=1; r<4; r++) { 
    for (var c=0; c<4; c++) t[c] = s[r][(c+r)%Nb]; // shift into temp copy 
    for (var c=0; c<4; c++) s[r][c] = t[c];   // and copy back 
    }   // note that this will work for Nb=4,5,6, but not 7,8 (always 4 for AES): 
    return s; // see asmaes.sourceforge.net/rijndael/rijndaelImplementation.pdf 
} 

Aes.mixColumns = function(s, Nb) { // combine bytes of each col of state S [§5.1.3] 
    for (var c=0; c<4; c++) { 
    var a = new Array(4); // 'a' is a copy of the current column from 's' 
    var b = new Array(4); // 'b' is a•{02} in GF(2^8) 
    for (var i=0; i<4; i++) { 
     a[i] = s[i][c]; 
     b[i] = s[i][c]&0x80 ? s[i][c]<<1^0x011b : s[i][c]<<1; 

    } 
    // a[n]^b[n] is a•{03} in GF(2^8) 
    s[0][c] = b[0]^a[1]^b[1]^a[2]^a[3]; // 2*a0 + 3*a1 + a2 + a3 
    s[1][c] = a[0]^b[1]^a[2]^b[2]^a[3]; // a0 * 2*a1 + 3*a2 + a3 
    s[2][c] = a[0]^a[1]^b[2]^a[3]^b[3]; // a0 + a1 + 2*a2 + 3*a3 
    s[3][c] = a[0]^b[0]^a[1]^a[2]^b[3]; // 3*a0 + a1 + a2 + 2*a3 
    } 
    return s; 
} 

Aes.addRoundKey = function(state, w, rnd, Nb) { // xor Round Key into state S [§5.1.4] 
    for (var r=0; r<4; r++) { 
    for (var c=0; c<Nb; c++) state[r][c] ^= w[rnd*4+c][r]; 
    } 
    return state; 
} 

Aes.subWord = function(w) { // apply SBox to 4-byte word w 
    for (var i=0; i<4; i++) w[i] = Aes.sBox[w[i]]; 
    return w; 
} 

Aes.rotWord = function(w) { // rotate 4-byte word w left by one byte 
    var tmp = w[0]; 
    for (var i=0; i<3; i++) w[i] = w[i+1]; 
    w[3] = tmp; 
    return w; 
} 

// sBox is pre-computed multiplicative inverse in GF(2^8) used in subBytes and keyExpansion [§5.1.1] 
Aes.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]; 

// rCon is Round Constant used for the Key Expansion [1st col is 2^(r-1) in GF(2^8)] [§5.2] 
Aes.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] ]; 


/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 
/* AES Counter-mode implementation in JavaScript (c) Chris Veness 2005-2011      */ 
/* - see http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf      */ 
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 

Aes.Ctr = {}; // Aes.Ctr namespace: a subclass or extension of Aes 

/** 
* Encrypt a text using AES encryption in Counter mode of operation 
* 
* Unicode multi-byte character safe 
* 
* @param {String} plaintext Source text to be encrypted 
* @param {String} password The password to use to generate a key 
* @param {Number} nBits  Number of bits to be used in the key (128, 192, or 256) 
* @returns {string}   Encrypted text 
*/ 
Aes.Ctr.encrypt = function(plaintext, password, nBits) { 
    var blockSize = 16; // block size fixed at 16 bytes/128 bits (Nb=4) for AES 
    if (!(nBits==128 || nBits==192 || nBits==256)) return ''; // standard allows 128/192/256 bit keys 
    plaintext = Utf8.encode(plaintext); 
    password = Utf8.encode(password); 
    //var t = new Date(); // timer 

    // use AES itself to encrypt password to get cipher key (using plain password as source for key 
    // expansion) - gives us well encrypted key (though hashed key might be preferred for prod'n use) 
    var nBytes = nBits/8; // no bytes in key (16/24/32) 
    var pwBytes = new Array(nBytes); 
    for (var i=0; i<nBytes; i++) { // use 1st 16/24/32 chars of password for key 
    pwBytes[i] = isNaN(password.charCodeAt(i)) ? 0 : password.charCodeAt(i); 
    } 
    var key = Aes.cipher(pwBytes, Aes.keyExpansion(pwBytes)); // gives us 16-byte key 
    key = key.concat(key.slice(0, nBytes-16)); // expand key to 16/24/32 bytes long 

    // initialise 1st 8 bytes of counter block with nonce (NIST SP800-38A §B.2): [0-1] = millisec, 
    // [2-3] = random, [4-7] = seconds, together giving full sub-millisec uniqueness up to Feb 2106 
    var counterBlock = new Array(blockSize); 

    var nonce = (new Date()).getTime(); // timestamp: milliseconds since 1-Jan-1970 
    var nonceMs = nonce%1000; 
    var nonceSec = Math.floor(nonce/1000); 
    var nonceRnd = Math.floor(Math.random()*0xffff); 

    for (var i=0; i<2; i++) counterBlock[i] = (nonceMs >>> i*8) & 0xff; 
    for (var i=0; i<2; i++) counterBlock[i+2] = (nonceRnd >>> i*8) & 0xff; 
    for (var i=0; i<4; i++) counterBlock[i+4] = (nonceSec >>> i*8) & 0xff; 

    // and convert it to a string to go on the front of the ciphertext 
    var ctrTxt = ''; 
    for (var i=0; i<8; i++) ctrTxt += String.fromCharCode(counterBlock[i]); 

    // generate key schedule - an expansion of the key into distinct Key Rounds for each round 
    var keySchedule = Aes.keyExpansion(key); 

    var blockCount = Math.ceil(plaintext.length/blockSize); 
    var ciphertxt = new Array(blockCount); // ciphertext as array of strings 

    for (var b=0; b<blockCount; b++) { 
    // set counter (block #) in last 8 bytes of counter block (leaving nonce in 1st 8 bytes) 
    // done in two stages for 32-bit ops: using two words allows us to go past 2^32 blocks (68GB) 
    for (var c=0; c<4; c++) counterBlock[15-c] = (b >>> c*8) & 0xff; 
    for (var c=0; c<4; c++) counterBlock[15-c-4] = (b/0x100000000 >>> c*8) 

    var cipherCntr = Aes.cipher(counterBlock, keySchedule); // -- encrypt counter block -- 

    // block size is reduced on final block 
    var blockLength = b<blockCount-1 ? blockSize : (plaintext.length-1)%blockSize+1; 
    var cipherChar = new Array(blockLength); 

    for (var i=0; i<blockLength; i++) { // -- xor plaintext with ciphered counter char-by-char -- 
     cipherChar[i] = cipherCntr[i]^plaintext.charCodeAt(b*blockSize+i); 
     cipherChar[i] = String.fromCharCode(cipherChar[i]); 
    } 
    ciphertxt[b] = cipherChar.join(''); 
    } 

    // Array.join is more efficient than repeated string concatenation in IE 
    var ciphertext = ctrTxt + ciphertxt.join(''); 
    ciphertext = stringToHex(ciphertext); // encode in base64 

    //alert((new Date()) - t); 
    return ciphertext; 
} 

/** 
* Decrypt a text encrypted by AES in counter mode of operation 
* 
* @param {String} ciphertext Source text to be encrypted 
* @param {String} password The password to use to generate a key 
* @param {Number} nBits  Number of bits to be used in the key (128, 192, or 256) 
* @returns {String}   Decrypted text 
*/ 
Aes.Ctr.decrypt = function(ciphertext, password, nBits) { 
    var blockSize = 16; // block size fixed at 16 bytes/128 bits (Nb=4) for AES 
    if (!(nBits==128 || nBits==192 || nBits==256)) return ''; // standard allows 128/192/256 bit keys 
    ciphertext = hexToString(ciphertext); 
    password = Utf8.encode(password); 
    //var t = new Date(); // timer 

    // use AES to encrypt password (mirroring encrypt routine) 
    var nBytes = nBits/8; // no bytes in key 
    var pwBytes = new Array(nBytes); 
    for (var i=0; i<nBytes; i++) { 
    pwBytes[i] = isNaN(password.charCodeAt(i)) ? 0 : password.charCodeAt(i); 
    } 
    var key = Aes.cipher(pwBytes, Aes.keyExpansion(pwBytes)); 
    key = key.concat(key.slice(0, nBytes-16)); // expand key to 16/24/32 bytes long 

    // recover nonce from 1st 8 bytes of ciphertext 
    var counterBlock = new Array(8); 
    ctrTxt = ciphertext.slice(0, 8); 
    for (var i=0; i<8; i++) counterBlock[i] = ctrTxt.charCodeAt(i); 

    // generate key schedule 
    var keySchedule = Aes.keyExpansion(key); 

    // separate ciphertext into blocks (skipping past initial 8 bytes) 
    var nBlocks = Math.ceil((ciphertext.length-8)/blockSize); 
    var ct = new Array(nBlocks); 
    for (var b=0; b<nBlocks; b++) ct[b] = ciphertext.slice(8+b*blockSize, 8+b*blockSize+blockSize); 
    ciphertext = ct; // ciphertext is now array of block-length strings 

    // plaintext will get generated block-by-block into array of block-length strings 
    var plaintxt = new Array(ciphertext.length); 

    for (var b=0; b<nBlocks; b++) { 
    // set counter (block #) in last 8 bytes of counter block (leaving nonce in 1st 8 bytes) 
    for (var c=0; c<4; c++) counterBlock[15-c] = ((b) >>> c*8) & 0xff; 
    for (var c=0; c<4; c++) counterBlock[15-c-4] = (((b+1)/0x100000000-1) >>> c*8) & 0xff; 

    var cipherCntr = Aes.cipher(counterBlock, keySchedule); // encrypt counter block 

    var plaintxtByte = new Array(ciphertext[b].length); 
    for (var i=0; i<ciphertext[b].length; i++) { 
     // -- xor plaintxt with ciphered counter byte-by-byte -- 
     plaintxtByte[i] = cipherCntr[i]^ciphertext[b].charCodeAt(i); 
     plaintxtByte[i] = String.fromCharCode(plaintxtByte[i]); 
    } 
    plaintxt[b] = plaintxtByte.join(''); 
    } 

    // join array of blocks into single plaintext string 
    var plaintext = plaintxt.join(''); 
    plaintext = Utf8.decode(plaintext); // decode from UTF8 back to Unicode multi-byte chars 

    //alert((new Date()) - t); 
    return plaintext; 
} 


/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 
/* Base64 class: Base 64 encoding/decoding (c) Chris Veness 2002-2011       */ 
/* note: depends on Utf8 class                 */ 
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 

var Base64 = {}; // Base64 namespace 

Base64.code = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz/="; 

/** 
* Encode string into Base64, as defined by RFC 4648 [http://tools.ietf.org/html/rfc4648] 
* (instance method extending String object). As per RFC 4648, no newlines are added. 
* 
* @param {String} str The string to be encoded as base-64 
* @param {Boolean} [utf8encode=false] Flag to indicate whether str is Unicode string to be encoded 
* to UTF8 before conversion to base64; otherwise string is assumed to be 8-bit characters 
* @returns {String} Base64-encoded string 
*/ 
Base64.encode = function(str, utf8encode) { // http://tools.ietf.org/html/rfc4648 
    utf8encode = (typeof utf8encode == 'undefined') ? false : utf8encode; 
    var o1, o2, o3, bits, h1, h2, h3, h4, e=[], pad = '', c, plain, coded; 
    var b64 = Base64.code; 

    plain = utf8encode ? str.encodeUTF8() : str; 

    c = plain.length % 3; // pad string to length of multiple of 3 
    if (c > 0) { while (c++ < 3) { pad += '='; plain += '\0'; } } 
    // note: doing padding here saves us doing special-case packing for trailing 1 or 2 chars 

    for (c=0; c<plain.length; c+=3) { // pack three octets into four hexets 
    o1 = plain.charCodeAt(c); 
    o2 = plain.charCodeAt(c+1); 
    o3 = plain.charCodeAt(c+2); 

    bits = o1<<16 | o2<<8 | o3; 

    h1 = bits>>18 & 0x3f; 
    h2 = bits>>12 & 0x3f; 
    h3 = bits>>6 & 0x3f; 
    h4 = bits & 0x3f; 

    // use hextets to index into code string 
    e[c/3] = b64.charAt(h1) + b64.charAt(h2) + b64.charAt(h3) + b64.charAt(h4); 
    } 
    coded = e.join(''); // join() is far faster than repeated string concatenation in IE 

    // replace 'A's from padded nulls with '='s 
    coded = coded.slice(0, coded.length-pad.length) + pad; 

    return coded; 
} 

/** 
* Decode string from Base64, as defined by RFC 4648 [http://tools.ietf.org/html/rfc4648] 
* (instance method extending String object). As per RFC 4648, newlines are not catered for. 
* 
* @param {String} str The string to be decoded from base-64 
* @param {Boolean} [utf8decode=false] Flag to indicate whether str is Unicode string to be decoded 
* from UTF8 after conversion from base64 
* @returns {String} decoded string 
*/ 
Base64.decode = function(str, utf8decode) { 
    utf8decode = (typeof utf8decode == 'undefined') ? false : utf8decode; 
    var o1, o2, o3, h1, h2, h3, h4, bits, d=[], plain, coded; 
    var b64 = Base64.code; 

    coded = utf8decode ? str.decodeUTF8() : str; 


    for (var c=0; c<coded.length; c+=4) { // unpack four hexets into three octets 
    h1 = b64.indexOf(coded.charAt(c)); 
    h2 = b64.indexOf(coded.charAt(c+1)); 
    h3 = b64.indexOf(coded.charAt(c+2)); 
    h4 = b64.indexOf(coded.charAt(c+3)); 

    bits = h1<<18 | h2<<12 | h3<<6 | h4; 

    o1 = bits>>>16 & 0xff; 
    o2 = bits>>>8 & 0xff; 
    o3 = bits & 0xff; 

    d[c/4] = String.fromCharCode(o1, o2, o3); 
    // check for padding 
    if (h4 == 0x40) d[c/4] = String.fromCharCode(o1, o2); 
    if (h3 == 0x40) d[c/4] = String.fromCharCode(o1); 
    } 
    plain = d.join(''); // join() is far faster than repeated string concatenation in IE 

    return utf8decode ? plain.decodeUTF8() : plain; 
} 


/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 
/* Utf8 class: encode/decode between multi-byte Unicode characters and UTF-8 multiple   */ 
/*    single-byte character encoding (c) Chris Veness 2002-2011       */ 
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 

var Utf8 = {}; // Utf8 namespace 

/** 
* Encode multi-byte Unicode string into utf-8 multiple single-byte characters 
* (BMP/basic multilingual plane only) 
* 
* Chars in range U+0080 - U+07FF are encoded in 2 chars, U+0800 - U+FFFF in 3 chars 
* 
* @param {String} strUni Unicode string to be encoded as UTF-8 
* @returns {String} encoded string 
*/ 
Utf8.encode = function(strUni) { 
    // use regular expressions & String.replace callback function for better efficiency 
    // than procedural approaches 
    var strUtf = strUni.replace(
     /[\u0080-\u07ff]/g, // U+0080 - U+07FF => 2 bytes 110yyyyy, 10zzzzzz 
     function(c) { 
     var cc = c.charCodeAt(0); 
     return String.fromCharCode(0xc0 | cc>>6, 0x80 | cc&0x3f); } 
    ); 
    strUtf = strUtf.replace(
     /[\u0800-\uffff]/g, // U+0800 - U+FFFF => 3 bytes 1110xxxx, 10yyyyyy, 10zzzzzz 
     function(c) { 
     var cc = c.charCodeAt(0); 
     return String.fromCharCode(0xe0 | cc>>12, 0x80 | cc>>6&0x3F, 0x80 | cc&0x3f); } 
    ); 
    return strUtf; 
} 

/** 
* Decode utf-8 encoded string back into multi-byte Unicode characters 
* 
* @param {String} strUtf UTF-8 string to be decoded back to Unicode 
* @returns {String} decoded string 
*/ 
Utf8.decode = function(strUtf) { 
    // note: decode 3-byte chars first as decoded 2-byte strings could appear to be 3-byte char! 
    var strUni = strUtf.replace(
     /[\u00e0-\u00ef][\u0080-\u00bf][\u0080-\u00bf]/g, // 3-byte chars 
     function(c) { // (note parentheses for precence) 
     var cc = ((c.charCodeAt(0)&0x0f)<<12) | ((c.charCodeAt(1)&0x3f)<<6) | (c.charCodeAt(2)&0x3f); 
     return String.fromCharCode(cc); } 
    ); 
    strUni = strUni.replace(
     /[\u00c0-\u00df][\u0080-\u00bf]/g,     // 2-byte chars 
     function(c) { // (note parentheses for precence) 
     var cc = (c.charCodeAt(0)&0x1f)<<6 | c.charCodeAt(1)&0x3f; 
     return String.fromCharCode(cc); } 
    ); 
    return strUni; 
} 

function encryptForm(key, form){ 
    var params = form_to_params(form); 

    if(params.length > 0) 
     return Aes.Ctr.encrypt(params, key, 128); 
    return false; 
} 


function stringToHex (s) { 
    var r = "0x"; 
    var hexes = new Array ("0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f"); 
    for (var i=0; i<s.length; i++) {r += hexes [s.charCodeAt(i) >> 4] + hexes [s.charCodeAt(i) & 0xf];} 
    return r; 
} 

function hexToString (h) { 
    var r = ""; 
    for (var i= (h.substr(0, 2)=="0x")?2:0; i<h.length; i+=2) {r += String.fromCharCode (parseInt (h.substr (i, 2), 16));} 
    return r; 
} 

, 그것은 정말 사용되는지 AES 암호화의 포맷하지 이잖아요하지, 난 그냥 뭔가 어디 필요 둘 다 동의합니다. 내가 두 가지 사이에 다른 패딩 설정을 가지고 있다고 생각하지만, 나는 완전히 확신하지 못합니다.

답변

4

현재 JavaScript AES CTR 모드는 Java "AES/ECB/PKCS5Padding" 모드 (기본은 "AES")와 일치하지 않으므로 작동하지 않습니다. CTR 모드는 Java에서 사용할 수 있으며 "AES/CTR/NoPadding"을 통해 액세스 할 수 있습니다. IVParameterSpec (AES 용 블록 크기 사용 : 16 바이트)을 사용하여 설정할 수있는 암호화 (NONECE, NONCE)가 필요합니다.

JavaScript 카운터 모드 암호화를 통해 걸을 필요가 없다고 가정합니다.

+0

좋아, 당신이 말할 때 나는 필요 "AES/CTR/NoPadding을" 내가 변경 그게 : 의 KeyGenerator kgen = KeyGenerator.getInstance ("AES/CTR/NoPadding"); 맞습니까? 왜냐하면 내가 그렇게 할 때, 내가 받고있어 : javax.servlet.ServletException : java.security.NoSuchAlgorithmException : AES/CTR/NoPadding KeyGenerator 사용할 수 없음 간단한 질문이 있다면 사과드립니다. 도움을 주셔서 감사합니다. – Doug

+0

좋아요, 알아 냈습니다. CTR/Nopadding을 얻으려면 Bouncey Castle의 라이브러리를 추가해야했습니다. 나는 모든 것을 작동 시키려고 아직도 노력하고 있습니다. 그러나 이것이 내가 알 필요가있는 것이 분명합니다. 감사! – Doug

+0

자기가가는 길에 다행이야. 이전의 주석에 관해서는, AES 키 (키는 모드에 대해 모른다)가 필요하기 때문에''AES ''만 사용하면됩니다. 암호문에는''AES/CTR/NoPadding ''이 필요합니다. 런타임 버전이 6 이상이면 JDK/JRE와 함께 제공되는 SunJCE에서 사용할 수 있어야합니다. –