5

我已经设法通过 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)
}
//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?


编辑:在 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))
//Outputs unrepresentable characters

任何的想法?

4

4 回答 4

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-compatible format strategy)

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)
于 2013-01-18T16:59:46.430 回答
2
U2FsdGVkX19wbzVqqOr6U5dnuG34WyH+n1A4PX9Z+xBhY3bALGS7DOa/aphgnubc 

该数据是经过base64编码的,原始的看起来像这样:

Salted__po5jSgm[!P8=Yacv,dj`

(请注意,该字符串中有不可表示的字符)

这正好是 32 个字节长。

于 2013-01-18T15:44:55.123 回答
1

虽然,它不直接,但也许你会发现看看https://github.com/dgryski/dkeyczar很有用。

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

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

于 2014-04-14T15:21:39.603 回答
0

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

首先,您需要确保为 encrypt() 提供正确类型的参数。看起来您可能已经在评论中意识到您需要执行 CryptoJS.enc.Hex.parse(symetricKeyHex),尽管您的原始帖子尚未反映这一点。

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

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

于 2013-01-30T04:56:12.277 回答