3

I am trining to encrypt/decrypt between Java and JavaScript using Web Crypto API (http://www.w3.org/TR/WebCryptoAPI/#SP800-38B). I found useful information in this forum but now I am stuck...

Java:

    String charset = "UTF-8";

    String secret = "hallo1234567890x";
    String salt = "fqpq6V_Vggn-fR_EiEKFBA";
    byte [] iv = "1111111111111111".getBytes(charset);

    // Get Key
    byte[] key = (salt).getBytes(charset);
    key = Arrays.copyOf(key, 16);

    // Generate specs
    SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES");

    // Instantiate cipher
    Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
    cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, new IvParameterSpec(iv));

    byte[] encrypted = cipher.doFinal((secret).getBytes());

    //output:
    System.out.print("byte array: ");
    for(int i=0; i<encrypted.length; i++){
        System.out.print(encrypted[i] + "\t");          
    }
    System.out.println("");

    System.out.println("encrypted string Base64: " + new Base64().encodeAsString(encrypted));

The output:

   byte array: -116 101 -89 89  33  8   -42 77  -82 79  -39 38  112 68  44  16  
   encrypted string Base64: jGWnWSEI1k2uT9kmcEQsEA==

JavaScript:

var my_key = "fqpq6V_Vggn-fR_EiEKFBA"; 
var my_counter = new Uint8Array(16); 
for(var i=0;i<16;i++){
    my_counter[i] = 1;
}
var my_data = str2ab("hallo1234567890x");

For importKey I use folowing parameters:

    kty: "oct",
    k: my_key,
    alg: "A128CBC",
    ext: true,

    name: "AES-CBC",

For decrypt I use parameters:

    name: "AES-CBC",
    iv: my_counter, 

I get folowing ArrayBuffer as output: [213, 168, 98, 252, 218, 52, 221, 67, 4, 31, 93, 40, 60, 199, 161, 64, 145, 92, 95, 160, 158, 47, 212, 189, 56, 180, 27, 45, 122, 169, 133, 181, 61, 5, 26, 240, 135, 108, 251, 239, 209, 214, 86, 141, 171, 96, 175, 188]

With window.btoa(arraybuffer); it is: "W29iamVjdCBBcnJheUJ1ZmZlcl0=".

I use ab2str(buf) and str2ab(str) frome: Converting between strings and ArrayBuffers.

function ab2str(buf) {
   return String.fromCharCode.apply(null, new Uint16Array(buf));
}

function str2ab(str) {
   var buf = new ArrayBuffer(str.length*2); // 2 bytes for each char
   var bufView = new Uint16Array(buf);
   for (var i=0, strLen=str.length; i<strLen; i++) {
       bufView[i] = str.charCodeAt(i);
   }
   return buf;
}

What is missing so that the Java and JavaScript outputs are the same?

Community
  • 1
  • 1
zero
  • 31
  • 4

1 Answers1

0

Your IVs don't match. A 1 byte is not the same as a "1" in ASCII which is actually 49 in the ASCII table.

Artjom B.
  • 61,146
  • 24
  • 125
  • 222
  • Thanks and yes, there are other problem(s) in the code... I think the problem is the Java encrypts a String and JavaScript a ArrayBuffer. If I convert the ArrayBuffer back to Sting I get charakters that cant be convertet with – zero May 27 '15 at 08:42
  • window.btoa(arraybuffer); -> Error Message: "The string to be decoded contains characters outside of the Latin1 range." – zero May 27 '15 at 08:43
  • You can't use `btoa()` to convert an ArrayBuffer into a string. The "W29iamVjdCBBcnJheUJ1ZmZlcl0=" that you got out is actually Base64 encoded "[object ArrayBuffer]". You probably need to write the reverse function to `str2ab()`. Btw, can you share `str2ab()`? – Artjom B. May 27 '15 at 09:07
  • sorry, I ment `window.btoa(str2ab(arraybuffer));` (see `str2ab()` and `ab2str()` above) – zero May 28 '15 at 10:47