使用Golang解密使用Node.js加密的字符串。

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

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 &quot;aes256&quot;

this.encrypt = function(s){
var cipher = crypto.createCipher(algo, key);

var i = 0;
var encrypted = &quot;&quot;;
while (i &lt; s.length){
	var end = Math.min(s.length-i, 15);
	var chunk = s.substring(i, end+i);
	encrypted += cipher.update(chunk, &quot;utf8&quot;, &quot;base64&quot;);
	i+= end;
}

encrypted += cipher.final(&quot;base64&quot;);
encrypted = encrypted.replace(/\//g,&quot;_&quot;).replace(/\+/g, &quot;-&quot;); // 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 &lt; 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) &lt; aes.BlockSize {
    panic(&quot;ciphertext too short&quot;)
}
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 使用Golang解密使用Node.js加密的字符串。

The key is var key = &quot;random array of characters&quot;; 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?)

huangapple
  • 本文由 发表于 2015年10月22日 21:57:35
  • 转载请务必保留本文链接:https://go.coder-hub.com/33282838.html
匿名

发表评论

匿名网友

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

确定