Go 加密不同于使用相同密钥和 iv 的 Ruby 加密
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
为什么我得到不同的结果?
谢谢,
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*')
我有以下 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
为什么我得到不同的结果?
谢谢,
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*')