英文:
Golang Decrypting strings that were encrypted with Node.js
问题
我有一堆密码用node.js加密并存储在mongodb中的内部应用程序。我想将这个应用程序转换为Go语言,但是在处理node.js加密时遇到了问题。我查看了node.js的源代码,发现它使用了OpenSSL的evpBytesToKey方法。我在网上找到了一个Golang的实现,但是我仍然无法解密用node.js加密的密码。"algo"是"aes256"
。
以下是node.js的加密代码:
this.encrypt = function(s){
var cipher = crypto.createCipher(algo, key);
var i = 0;
var encrypted = "";
while (i < s.length){
var end = Math.min(s.length-i, 15);
var chunk = s.substring(i, end+i);
encrypted += cipher.update(chunk, "utf8", "base64");
i+= end;
}
encrypted += cipher.final("base64");
encrypted = encrypted.replace(/\//g,"_").replace(/\+/g, "-"); // base64 url encode
return encrypted;
}
以下是Go语言的代码:
func evpBytesToKey(password string, keyLen int) (key []byte, iv []byte) {
const md5Len = 16
cnt := (keyLen-1)/md5Len + 1
m := make([]byte, cnt*md5Len)
key = make([]byte, keyLen)
iv = make([]byte, md5Len)
copy(m, md5sum([]byte(password)))
// 重复调用md5直到生成足够的字节。
// 每次调用md5使用的数据是:前一个md5摘要 + 密码。
d := make([]byte, md5Len+len(password))
start := 0
for i := 1; i < cnt; i++ {
start += md5Len
copy(d, m[start-md5Len:start])
copy(d[md5Len:], password)
copy(m[start:], md5sum(d))
}
return m[:keyLen], iv
}
func Decrypt(key string, b64 string) string {
text := decodeBase64(b64) // base64.StdEncoding.DecodeString辅助方法
block, err := aes.NewCipher(evpBytesToKey(key,32))
if err != nil {
panic(err)
}
if len(text) < aes.BlockSize {
panic("ciphertext too short")
}
iv := text[:aes.BlockSize]
text = text[aes.BlockSize:]
fmt.Println(iv)
fmt.Println(text)
cfb := cipher.NewCFBDecrypter(block, iv)
cfb.XORKeyStream(text, text)
return string(text)
}
这是一些示例数据:
8PTcrR0Nf0sltmdtvLUrFg==
(你告诉我它解密后是什么)
密钥是var key = "random array of characters";
。
这超出了我的个人加密经验和培训。这是我最后的障碍...感谢您提供的任何帮助和指导。
英文:
I have a bunch passwords for an internal app that were encrypted with node.js and stored (irrelevantly) in mongodb. I would like to convert this application to Go, but I'm getting tripped up on the node.js encryption. I've looked through the node.js source code for this, and it's using the OpenSSL evpBytesToKey method. I've found a Golang implementation of this on the web, but I still can't decrypt the password in Go that was encrypted with node.js. "algo" is "aes256"
this.encrypt = function(s){
var cipher = crypto.createCipher(algo, key);
var i = 0;
var encrypted = "";
while (i < s.length){
var end = Math.min(s.length-i, 15);
var chunk = s.substring(i, end+i);
encrypted += cipher.update(chunk, "utf8", "base64");
i+= end;
}
encrypted += cipher.final("base64");
encrypted = encrypted.replace(/\//g,"_").replace(/\+/g, "-"); // base64 url encode
return encrypted;
}
And the Go code:
func evpBytesToKey(password string, keyLen int) (key []byte, iv []byte) {
const md5Len = 16
cnt := (keyLen-1)/md5Len + 1
m := make([]byte, cnt*md5Len)
key = make([]byte, keyLen)
iv = make([]byte, md5Len)
copy(m, md5sum([]byte(password)))
// Repeatedly call md5 until bytes generated is enough.
// Each call to md5 uses data: prev md5 sum + password.
d := make([]byte, md5Len+len(password))
start := 0
for i := 1; i < cnt; i++ {
start += md5Len
copy(d, m[start-md5Len:start])
copy(d[md5Len:], password)
copy(m[start:], md5sum(d))
}
return m[:keyLen], iv
}
And the decrypt function
func Decrypt(key string, b64 string) string {
text := decodeBase64(b64) // base64.StdEncoding.DecodeString helper method
block, err := aes.NewCipher(evpBytesToKey(key,32))
if err != nil {
panic(err)
}
if len(text) < aes.BlockSize {
panic("ciphertext too short")
}
iv := text[:aes.BlockSize]
text = text[aes.BlockSize:]
fmt.Println(iv)
fmt.Println(text)
cfb := cipher.NewCFBDecrypter(block, iv)
cfb.XORKeyStream(text, text)
return string(text)
}
Here is some sample data:
8PTcrR0Nf0sltmdtvLUrFg==
(you tell ME what it decrypts to
The key is var key = "random array of characters";
literally.
This is above my personal encryption experience and training. It is my last roadblock... Thanks for any help and guidance you can provide.
答案1
得分: 1
在OpenSSL中,'aes256'等同于'aes-256-cbc'。所以你使用NewCFBDecrypter
似乎有些问题。除此之外,IV/密钥生成需要进行一些调整才能真正生成一个IV。
这个测试脚本给我输出的至少是ASCII码。
我通过让OpenSSL为我生成IV/密钥来找到要查找的IV/密钥(这样可以更容易地调试genIvAndKey
)。
请注意,你仍然需要确定在实际密码和填充之间如何分割(使用unicode.IsPrint
?)。
英文:
In OpenSSL 'aes256' is equivalent to 'aes-256-cbc'. So your use of NewCFBDecrypter
seems off. Other than that the IV/key generation needed to be tweaked a little to actually generate an IV.
This test script gives me an output that's at least ASCII.
http://play.golang.org/p/zsPMd8QN0b
I found the IV / key to look for by having OpenSSL generate it for me (made debugging genIvAndKey
a little easier).
Note that you still need to determine where to split between the actual password and the padding. (unicode.IsPrint
?)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论