使用Go解密使用MCRYPT_RIJNDAEL_256在php中加密的字符串。

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

Decrypting using Go a string encrypted in php using MCRYPT_RIJNDAEL_256

问题

在PHP中,mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CBC); 返回的值是32,因此表明AES-256需要一个32字节的初始化向量。但这是误导性的,正如在mcrypt_encrypt的注释中所说:

>此外,MCRYPT_RIJNDAEL_256并不是AES-256,它是Rijndael分组密码的另一种变体。如果你想在mcrypt中使用AES-256,你必须使用带有32字节密钥的MCRYPT_RIJNDAEL_128。OpenSSL更明显地显示了你正在使用的模式(例如'aes-128-cbc'与'aes-256-ctr')。

因此,当使用32字节的IV时,以下示例在Go中无法工作(会导致恐慌)。

score := decodePost(c.PostForm("score"))
iv := decodePost(c.PostForm("iv"))

aesKey := getAESKey()
baseAES, err := aes.NewCipher([]byte(aesKey))
if err != nil {
	c.AbortWithError(500, err)
	return
}
block := cipher.NewCBCDecrypter(baseAES, []byte(iv))
block.CryptBlocks(score, score)

引用自crypto/cipher文档:

>iv的长度必须与块的块大小相同,并且必须与用于加密数据的iv匹配。

(当然,Go中的AES块大小为16字节)。

那么,最后,我该如何在Go中解密这样的字符串?

英文:

In PHP, mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CBC); returns a value of 32, thus apparently saying that AES-256 wants an Initialization Vector of 32 bytes. But this is deceiving, as said in the comments for mcrypt_encrypt:

>Also, MCRYPT_RIJNDAEL_256 is not AES-256, it's a different variant of the Rijndael block cipher. If you want AES-256 in mcrypt, you have to use MCRYPT_RIJNDAEL_128 with a 32-byte key. OpenSSL makes it more obvious which mode you are using (i.e. 'aes-128-cbc' vs 'aes-256-ctr').

So of course, with an IV of 32 bytes, the following example does not work in Go (it causes a panic).

score := decodePost(c.PostForm("score"))
iv := decodePost(c.PostForm("iv"))

aesKey := getAESKey()
baseAES, err := aes.NewCipher([]byte(aesKey))
if err != nil {
	c.AbortWithError(500, err)
	return
}
block := cipher.NewCBCDecrypter(baseAES, []byte(iv))
block.CryptBlocks(score, score)

Quoting from the docs of crypto/cipher:

>The length of iv must be the same as the Block's block size and must match the iv used to encrypt the data.

(And of course, the AES block size in Go is 16 bytes).

So, finally, how can I decrypt such string in Go?

答案1

得分: 2

由于Golang中只有内置的标准AES加密算法,你需要自己实现Rijndael加密算法。

我在这里找到一个实现:https://github.com/celso-wo/rijndael256/blob/master/rijndael256.go

英文:

Since in Golang you have only built-in standard AES crypto, you need to implement the Rijndael crypto yourself.

I found one here: https://github.com/celso-wo/rijndael256/blob/master/rijndael256.go

答案2

得分: 0

几年后,我的一个同事告诉我,他再次遇到了这个问题,并且他发现这个代码片段是算法的一个很好的实现,而其它由itscaro发布的代码似乎不起作用:

https://gist.github.com/slifer2015/0d182d99280758a154e3fe12e48664d4

这基本上是来自Go crypto/aes库的代码,经过调整以使用32字节的IV和Rijnadael256算法。

由于我还没有时间验证这个解决方案,所以我暂时不会接受这个解决方案,但如果我有时间,我会编写一些测试来确保该代码确实能够像PHP实现一样精确地进行加密/解密。

作为一个警告:始终仔细阅读你在互联网上找到的加密代码,并且只有在确实需要支持解码你无法控制的数据时,才使用这个算法。对于常规的对称和非对称加密,Go的crypto包提供了安全、经过实战验证和得到良好支持的加密解决方案,如RSA、Ed25519和AES。

英文:

Several years later, I've been told by a colleague of mine which stumbled upon this issue again that this gist is a good implementation of the algorithm, while alas the one posted by itscaro didn't seem to work:

https://gist.github.com/slifer2015/0d182d99280758a154e3fe12e48664d4

This is essentially the code from the Go crypto/aes library, adjusted to use the 32 byte IV and Rijnadael256 algorithm.

As I've not yet had the time to verify this solution myself I will not yet accept this solution, though if I have time I'll write some tests to make sure that the code does manage to encrypt/decrypt precisely as the PHP implementation.

Just as a warning: always read carefully crypto code you find on the internet, and please only use this algorithm if you do find yourself as well in need of supporting it to decode data outside of your control. For normal symmetric and asymmetric encryption, the go crypto packages provide safe and battle-tested well-supported cryptographic solutions such as RSA, Ed25519 and AES.

huangapple
  • 本文由 发表于 2017年8月16日 19:33:09
  • 转载请务必保留本文链接:https://go.coder-hub.com/45712450.html
匿名

发表评论

匿名网友

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

确定