Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CryptoJS.AES and Golang

Tags:

go

cryptojs

i already managed to share a random symetric key via rsa. However i fail to make aes-encryption work with it. Problem seems to be the salt and initialization vector, that cryptoJS uses.

First it's output is along the lines of:

U2FsdGVkX19wbzVqqOr6U5dnuG34WyH+n1A4PX9Z+xBhY3bALGS7DOa/aphgnubc 

Googling for the reoccuring "U2FsdGVkX" or "cryptoJS.AES output" sadly is of no use.

On the other hand, golang's aes requires only a 32bit key and input of 32bit length each. Which means i have to somehow split the above into the corresponding blocks and figure out, how to create the 32bit key out of the secret key and the data above (which proably includes salt + init vector).

Sadly neither http://code.google.com/p/crypto-js nor any google search provide me with a solution.

By the way - my encryption right now:

var arr = new Array(32);
symetricKey = "";
var symHex = "";
rng.nextBytes(arr);
for(var i = 0; i < arr.length; i++){
    symetricKey += String.fromCharCode(arr[i]);
    //symHex= arr[i].toString(16), added a 0 if needed (so length always increases by 2)
}
//submit symetric via rsa. This is working, the server gets that key
var enc = CryptoJS.AES.encrypt(unencrypted, symetricKey)
//submit enc, stuck now - what to do with it on the server?


Edit: After the Base64 response:
Thanks for the base64 input.
However i still don't manage to bring it to work.
Especially since the encoded string starts with "SALTED", i believe, that there might be a problem.

Way i try to encode now:
Encoded on Client by:

var unencrypted = "{mail:test,password:test}"
var enc = CryptoJS.AES.encrypt(unencrypted, symKey)

On Server, the variables enc and symKey are the same as on Client:

baseReader := base64.NewDecoder(base64.StdEncoding, strings.NewReader(enc))
encData, err := ioutil.ReadAll(baseReader)
//if err != nil { ....}, doesn't happen here
cipher, err := aes.NewCipher(symKey)
//if err != nil { ....}, doesn't happen here
byteData := make([]byte, len(encData))
cipher.Decrypt(byteData, encData)
fmt.Println("Dec: ", string(byteData))
//Outputs unrepresentable characters

Any idea?

like image 725
user1977711 Avatar asked Jan 18 '13 14:01

user1977711


2 Answers

The output of CryptoJS.AES.encrypt is a CipherParams object containing the key, IV, optional salt, and ciphertext. The string you were referencing was a OpenSSL-compatible formatted string.

var encrypted = CryptoJS.AES.encrypt("Message", "Secret Passphrase");

alert(encrypted.key);        // 74eb593087a982e2a6f5dded54ecd96d1fd0f3d44a58728cdcd40c55227522223
alert(encrypted.iv);         // 7781157e2629b094f0e3dd48c4d786115
alert(encrypted.salt);       // 7a25f9132ec6a8b34
alert(encrypted.ciphertext); // 73e54154a15d1beeb509d9e12f1e462a0

alert(encrypted);            // U2FsdGVkX1+iX5Ey7GqLND5UFUoV0b7rUJ2eEvHkYqA= (OpenSSL-compatible format strategy)

CryptoJS' default encryption mode is CBC. You should pass the IV along with your symmetric key during your RSA-encrypted exchange. With the symmetric key, IV, and cipher text byte arrays on the server, you can decrypt it in Go similar to this:

c, err := aes.NewCipher(key)
cfbdec := cipher.NewCBCDecrypter(c, iv)
plaintext := make([]byte, len(ciphertext))
cfbdec.CryptBlock(plaintext, ciphertext)
like image 53
Bort Avatar answered Oct 12 '22 10:10

Bort


U2FsdGVkX19wbzVqqOr6U5dnuG34WyH+n1A4PX9Z+xBhY3bALGS7DOa/aphgnubc 

That data is base64 encoded, raw it looks something like this:

Salted__po5jSgm[!P8=Yacv,dj`

(note that there are unrepresentable characters in that string)

And this is exactly 32 bytes long.

like image 26
thwd Avatar answered Oct 12 '22 12:10

thwd