CryptoJS.AES和Golang

huangapple go评论87阅读模式
英文:

CryptoJS.AES and Golang

问题

我已经成功通过RSA共享了一个随机对称密钥。然而,我无法使用AES加密它。问题似乎是CryptoJS使用的盐和初始化向量。

首先,它的输出大致如下:

U2FsdGVkX19wbzVqqOr6U5dnuG34WyH+n1A4PX9Z+xBhY3bALGS7DOa/aphgnubc 

在谷歌上搜索“U2FsdGVkX”或“cryptoJS.AES输出”都没有用。

另一方面,Golang的AES只需要一个32位密钥和32位长度的输入。这意味着我必须将上述内容分割成相应的块,并找出如何从密钥和上述数据(可能包括盐和初始化向量)中创建32位密钥。

不幸的是,无论是http://code.google.com/p/crypto-js还是任何谷歌搜索都没有给我提供解决方案。

顺便说一下 - 我现在的加密方式:

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)
}
//通过RSA提交对称密钥。这个是有效的,服务器得到了那个密钥
var enc = CryptoJS.AES.encrypt(unencrypted, symetricKey)
//提交enc,现在卡住了 - 在服务器上该怎么处理它?

编辑:在Base64响应之后:
感谢提供Base64输入。
然而,我仍然无法使其工作。
特别是由于编码字符串以"SALTED"开头,我认为可能存在问题。

我现在尝试的编码方式:
在客户端进行编码:

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

在服务器上,enc和symKey变量与客户端上的相同:

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))
//输出不可表示的字符

有什么想法吗?

英文:

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 = &quot;&quot;;
var symHex = &quot;&quot;;
rng.nextBytes(arr);
for(var i = 0; i &lt; 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?

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

Way i try to encode now:<br>
Encoded on Client by:<br>

var unencrypted = &quot;{mail:test,password:test}&quot;
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&#39;t happen here
cipher, err := aes.NewCipher(symKey)
//if err != nil { ....}, doesn&#39;t happen here
byteData := make([]byte, len(encData))
cipher.Decrypt(byteData, encData)
fmt.Println(&quot;Dec: &quot;, string(byteData))
//Outputs unrepresentable characters

Any idea?

答案1

得分: 7

CryptoJS.AES.encrypt的输出是一个CipherParams对象,其中包含密钥、IV、可选的盐和密文。你引用的字符串是一个兼容OpenSSL格式的字符串。

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格式的策略)

CryptoJS的默认加密模式是CBC。在RSA加密的交换过程中,你应该将IV与对称密钥一起传递。在服务器上,通过使用对称密钥、IV和密文字节数组,你可以像这样在Go中解密它:

c, err := aes.NewCipher(key)
cfbdec := cipher.NewCBCDecrypter(c, iv)
plaintext := make([]byte, len(ciphertext))
cfbdec.CryptBlock(plaintext, ciphertext)

英文:

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(&quot;Message&quot;, &quot;Secret Passphrase&quot;);

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)

答案2

得分: 2

这个数据是以base64编码的,原始数据看起来像这样:

Salted__po5jSgm[!P8=Yacv,dj`

(请注意该字符串中有无法表示的字符)

而且它的长度正好是32个字节。

英文:
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.

答案3

得分: 1

虽然它不是直接相关的,但也许你会发现查看https://github.com/dgryski/dkeyczar对你有用。

这是KeyCzar的Go实现,它是由Google安全团队的成员最初开发的开源加密工具包。

希望你能从这个项目中学到一些东西。

英文:

Although, it don't directly but maybe you will find it useful to have a look at https://github.com/dgryski/dkeyczar.

Its Go implementation of KeyCzar, open source cryptographic toolkit originally developed by members of the Google Security Team

I hope you can learn something from this project

答案4

得分: 0

可能有一些问题我们需要解决。

首先,你需要确保你向encrypt()函数提供了正确类型的参数。看起来你可能已经在评论中意识到你需要使用CryptoJS.enc.Hex.parse(symetricKeyHex),尽管你的原始帖子还没有反映出这一点。

其次,你需要决定如何在两端获取或创建IV。CryptoJS可以使用密码短语创建一个,但你试图使用实际密钥而不是密码短语。这意味着你需要像设置密钥一样设置IV。

最后,你需要决定如何传输IV和密文。一个典型且简单的解决方案是将IV前置到密文之前,但实际上任何易于序列化/反序列化的格式都可以正常工作。只需确保你决定的格式在两端是一致的。

英文:

There are probably a few issues we'll need to work through.

First, you need to make sure you're supplying the correct type of arguments to encrypt(). It looks like you may have realized in a comment that you need to do CryptoJS.enc.Hex.parse(symetricKeyHex), though your original post doesn't reflect this yet.

Second, you need to decide how you're getting or creating the IV on both ends. CryptoJS can create one if you use a passphrase, but you're trying to use an actual key rather than a passphrase. That means you'll have to set the IV like you set the key.

Finally, you'll have to decide how you're going to transmit both the IV and the ciphertext. A typical and simple solution is to prepend the IV to the ciphertext, but really anything that's easily serializable/unserializable will work fine. Just make sure that whatever format you decide on is consistent on both ends.

huangapple
  • 本文由 发表于 2013年1月18日 22:14:06
  • 转载请务必保留本文链接:https://go.coder-hub.com/14400729.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定