为了账号安全,请及时绑定邮箱和手机立即绑定

从 PHP 到 Golang 的 aes-256-gcm 解密

从 PHP 到 Golang 的 aes-256-gcm 解密

Go
慕雪6442864 2023-04-17 15:22:45
我有一个在 PHP 中使用的加密函数function Encrypt(?string $Content, string $Key): string {    return openssl_encrypt($Content, 'aes-256-gcm', $Key, OPENSSL_RAW_DATA, $IV = random_bytes(16), $Tag, '', 16) . $IV . $Tag;}搭配解密功能function Decrypt(?string $Ciphertext, string $Key): ?string {    if (strlen($Ciphertext) < 32)        return null;    $Content = substr($Ciphertext, 0, -32);    $IV = substr($Ciphertext, -32, -16);    $Tag = substr($Ciphertext, -16);    try {        return openssl_decrypt($Content, 'aes-256-gcm', $Key, OPENSSL_RAW_DATA, $IV, $Tag);    } catch (Exception $e) {        return null;    }}我将从加密函数加密的数据存储到我的数据库中,现在我试图在 Go 中解密这些相同的值,但我得到了,但我cipher: message authentication failed无法弄清楚我遗漏了什么。c := []byte(`encrypted bytes of sorts`) // the bytes from the dbcontent := c[:len(c)-32]iv := c[len(c)-32 : len(c)-16]tag := c[len(c)-16:]block, err := aes.NewCipher(key[:32])if err != nil {    panic(err.Error())}aesgcm, err := cipher.NewGCMWithNonceSize(block, 16)if err != nil {    panic(err.Error())}fmt.Println(aesgcm.NonceSize(), aesgcm.Overhead()) // making sure iv and tag are both 16 bytesplaintext, err := aesgcm.Open(nil, iv, append(content, tag...), nil)if err != nil {    panic(err.Error())}值得注意的是,我使用的密钥不是 32 字节(它更大),因为我不知道所需的密钥/应该是 32 字节,所以我不完全确定 PHP 正在用它做什么(就像将它截断为 32 与使用具有 32 字节输出的东西散列它与其他东西相比)。查看OpenGo 源代码中的函数,看起来标签应该是文本的最后一个“标签大小”字节,所以这就是为什么我在解析片段后将标签附加到密文。
查看完整描述

1 回答

?
凤凰求蛊

TA贡献1825条经验 获得超4个赞

通常加密的消息看起来像IV+ciphertext+tag,而不是ciphertext+IV+tag。当一个人偏离惯例时,就会遇到各种各样的问题:-)


你看到调用后iv 切片append(ciphertext, tag...)发生了什么吗?您基本上iv用以下内容覆盖了tag:


Before:

924b3ba4 18f49edc1757f3fe88adcaa7ec4c1e7d 15811fd0b712b0b091433073f6a38d7b

After:

924b3ba4 15811fd0b712b0b091433073f6a38d7b 15811fd0b712b0b091433073f6a38d7b

iv作为快速修复,在调用之前复制一份append():


iv := make([]byte, 16)

copy(iv, c[len(c)-32 : len(c)-16])



查看完整回答
反对 回复 2023-04-17
  • 1 回答
  • 0 关注
  • 127 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信