问题内容
我正在尝试将一个 go 程序(https://github.com/mckael/samtv)移植到 node.js,该程序可以通过“smartview”api 控制三星电视
程序中有一个“aes 加密”功能,我在移植到节点时遇到问题。
func (s *smartviewsession) aesencrypt(plaindata []byte) ([]byte, error) {
//logrus.debugf("aesencrypt(%#v) : '%s'", plaindata, string(plaindata))
//logrus.debugf("session id: %d", s.sessionid)
//logrus.debugf("session key: '%x'\n %v", string(s.sessionkey), s.sessionkey)
// create cipher block
block, err := aes.newcipher(s.sessionkey)
if err != nil {
return nil, err
}
bs := block.blocksize()
//logrus.debugf("block size: %d", bs)
// add padding
padding := bs - len(plaindata)%bs
padtext := bytes.repeat([]byte{byte(padding)}, padding)
//logrus.debugf("padding: %d byte(s)", padding)
plaindata = append(plaindata, padtext...)
// encrypt
ciphertext := make([]byte, len(plaindata))
for cipherrange := ciphertext; len(plaindata) > 0; {
block.encrypt(cipherrange, plaindata[:bs])
plaindata = plaindata[bs:]
cipherrange = cipherrange[bs:]
}
//logrus.debugf("ciphertext: %#v", ciphertext)
return ciphertext, nil
}
我现在面临的问题是,我不知道使用了什么algorythim,或者我需要在我的node.js函数中指定“初始向量”来自哪里:
const SESSION_KEY = "59e8ca4b09f2a19ab5421cf55d604c7c";
var aesEncrypt = ((val, algo = "aes-256-cbc") => {
let cipher = crypto.createCipheriv(algo, SESSION_KEY, IV);
let encrypted = cipher.update(val, 'utf8', 'base64');
encrypted += cipher.final('base64');
return encrypted;
});
我可以使用 crypto.createcipher(...)
代替吗?但它已被弃用,而且感觉填充的东西很重要。
我对加密一无所知。 欢迎任何提示。
注意:在go函数中,s.sessionkey
与node.js中的session_key = "59e8ca4b09f2a19ab5421cf55d604c7c"
的值相同
解决方法
go 代码在 ecb 模式下应用 aes 并使用 pkcs#7 填充。 aes 变体隐式源自密钥大小,例如aes-128 用于 16 字节密钥。密文返回为 []byte
。
在 nodejs 代码中,明确指定了 aes 变体以及模式,例如aes-128-ecb
。 ecb模式不应用iv,因此必须在createcipheriv()
中指定为null
。使用填充 pkcs#7(默认)。密文可以返回为 buffer
,它最接近 []byte
。
发布的密钥 59e8ca4b09f2a19ab5421cf55d604c7c
看起来像一个十六进制编码的密钥,它是十六进制解码的 16 字节大,因此对应于 aes-128。十六进制解码可以在 go 中使用 encoding/hex 包来实现,例如与 hex.decodestring("59e8ca4b09f2a19ab5421cf55d604c7c")
。
在 ecb 模式下使用 aes-128(16 字节密钥)和 pkcs#7 填充的 nodejs 代码示例:
var crypto = require('crypto');
const SESSION_KEY = Buffer.from("59e8ca4b09f2a19ab5421cf55d604c7c", "hex");
var aesEncrypt = ((val, algo = "aes-128-ecb") => {
let cipher = crypto.createCipheriv(algo, SESSION_KEY, null);
return Buffer.concat([cipher.update(val, 'utf8'), cipher.final()]);
});
var ciphertext = aesEncrypt("The quick brown fox jumps over the lazy dog");
console.log(ciphertext.toString('base64')); // T/uQforseVFkY93mqwpwCGVVnEFDTT5Gle8a8XUxCfOXCfYUo3uCJ/nwzCIJ9xqf
go 代码使用相同的密钥(十六进制解码)和明文以及密文的 base64 编码给出相同的结果。
为了完整性:密钥也可以采用 utf-8 编码,然后生成 32 字节密钥,例如go 代码中的 key := []byte("59e8ca4b09f2a19ab5421cf55d604c7c")
和 const session_key = buffer.from("59e8ca4b09f2a19ab5421cf55d604c7c", "utf-8")
nodejs 代码。在 nodejs 代码中,还必须应用 aes-256-ecb
。最终,关键规范必须提供有关使用哪种编码的信息。
请注意,ecb 模式不安全。如今,通常使用经过身份验证的加密,例如通过 gcm 模式。
以上就是将 AES 加密功能移植到 node.js的详细内容,更多请关注编程网其它相关文章!