英文:
Go encryption differs from Ruby encryption using same key and iv
问题
我有以下的Ruby代码:
require 'base64'
require 'openssl'
data = '503666666'
key = '4768c01c4f598828ef80d9982d95f888fb952c5b12189c002123e87f751e3e82'
nonce = '4eFi6Q3PX1478767\n'
nonce = Base64.decode64(nonce)
c = OpenSSL::Cipher.new('aes-256-gcm')
c.encrypt
c.key = key
c.iv = nonce
result = c.update(data) + c.final
tag = c.auth_tag
puts Base64.encode64(result + tag) # => J3AVfNG84bz2UuXcfre7LVjSbMpX9XBq6g==\n
我想在Golang中复制这段代码。以下是我目前的代码:
package main
import (
"fmt"
"crypto/aes"
"crypto/cipher"
"encoding/base64"
"encoding/hex"
)
func main() {
data := []byte("503666666")
key, err := hex.DecodeString("4768c01c4f598828ef80d9982d95f888fb952c5b12189c002123e87f751e3e82")
if err != nil {
panic(err)
}
nonceB64 := "4eFi6Q3PX1478767\n"
nonce, err := base64.StdEncoding.DecodeString(nonceB64)
if err != nil {
panic(err)
}
block, err := aes.NewCipher(key)
if err != nil {
panic(err.Error())
}
aesgcm, err := cipher.NewGCM(block)
if err != nil {
panic(err.Error())
}
ciphertext := aesgcm.Seal(nil, nonce, data, nil)
fmt.Printf("%s\n", base64.StdEncoding.EncodeToString(ciphertext))
}
然而,Go版本的输出结果是:
+S52HGbLV1xp+GnF0v8VNOqc5J2GY2+SqA==
而不是:
J3AVfNG84bz2UuXcfre7LVjSbMpX9XBq6g==\n
为什么会得到不同的结果?
谢谢。
英文:
I have the following Ruby code:
require 'base64'
require 'openssl'
data = '503666666'
key = '4768c01c4f598828ef80d9982d95f888fb952c5b12189c002123e87f751e3e82'
nonce = '4eFi6Q3PX1478767\n'
nonce = Base64.decode64(nonce)
c = OpenSSL::Cipher.new('aes-256-gcm')
c.encrypt
c.key = key
c.iv = nonce
result = c.update(data) + c.final
tag = c.auth_tag
puts Base64.encode64(result + tag) # => J3AVfNG84bz2UuXcfre7LVjSbMpX9XBq6g==\n
that I'm trying to replicate in Golang.
Here's what I have so far:
package main
import (
"fmt"
"crypto/aes"
"crypto/cipher"
"encoding/base64"
"encoding/hex"
)
func main() {
data := []byte("503666666")
key, err := hex.DecodeString(`4768c01c4f598828ef80d9982d95f888fb952c5b12189c002123e87f751e3e82`)
if err != nil {
panic(err)
}
nonceB64 := "4eFi6Q3PX1478767\n"
nonce, err := base64.StdEncoding.DecodeString(nonceB64)
if err != nil {
panic(err)
}
block, err := aes.NewCipher(key)
if err != nil {
panic(err.Error())
}
aesgcm, err := cipher.NewGCM(block)
if err != nil {
panic(err.Error())
}
ciphertext := aesgcm.Seal(nil, nonce, data, nil)
fmt.Printf("%s\n", base64.StdEncoding.EncodeToString(ciphertext))
}
However the outcome from the Go version is:
> +S52HGbLV1xp+GnF0v8VNOqc5J2GY2+SqA==
vs.
> J3AVfNG84bz2UuXcfre7LVjSbMpX9XBq6g==\n
Why am I getting different results?
Thanks,
答案1
得分: 5
AES 256密码需要一个32字节的密钥。Ruby代码将密钥设置为由十六进制数字组成的64字节字符串。在使用之前,OpenSSL会将字符串截断为32字节(将Ruby代码中的key
更改为'4768c01c4f598828ef80d9982d95f888'
,将得到相同的输出)。
然而,Go代码在使用之前会对密钥进行十六进制解码,将64个十六进制数字转换为所需的32字节密钥。
如果你想要修改Go代码以使其与Ruby的结果相匹配,那么你需要截断密钥并删除十六进制解码步骤:
key := []byte("4768c01c4f598828ef80d9982d95f888")
然而,我认为Go版本的密钥处理更好。如果你想要将Ruby版本修改为与Go版本相匹配,你可以在使用之前对密钥进行十六进制解码:
key = [key].pack('H*')
英文:
The AES 256 cipher requires a 32 byte key. The Ruby code is setting the key to a 64 byte string consisting of hexadecimal digits. OpenSSL is truncating the string to 32 bytes before use (change key
to '4768c01c4f598828ef80d9982d95f888'
in the Ruby code and you'll get the same output).
The Go code however is hex decoding the key before use, converting the 64 hexadecimal digits to the 32 bytes required for the key.
If you want to change the Go code so that it matches the Ruby result, then you'll need to truncate the key and remove the hex decoding step:
key := []byte("4768c01c4f598828ef80d9982d95f888")
However, I'd argue that the key handling in the Go version of the code is better. If you want to change the Ruby version to match the Go version, you can hex decode the key before use:
key = [key].pack('H*')
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论