ruby - 从密码 aes 256 GCM Golang 中提取标签

标签 ruby go aes-gcm

我有Ruby加解密,尝试用Go重写。我一步一步地尝试,所以从 ruby​​ 中的加密开始,然后尝试在 go 中解密,它是有效的。但是当我尝试写 encryption 时在 Go 中并在 ruby​​ 中解密。我在尝试提取标签时卡住了,我解释了我需要提取 auth 标签的原因

ruby 加密

plaintext = "Foo bar"
cipher = OpenSSL::Cipher.new('aes-256-gcm')
cipher.encrypt
cipher.iv = iv # string 12 len
cipher.key = key # string 32 len
cipher.auth_data = # string 12 len
cipherText = cipher.update(JSON.generate({value: plaintext})) + cipher.final
authTag = cipher.auth_tag
hexString = (iv + cipherText + authTag).unpack('H*').first

我尝试连接一个初始向量、一个密文和身份验证标签,所以在解密之前我可以提取它们,尤其是身份验证标签,因为我需要在调用 Ruby 中的 Cipher#final 之前设置它

auth_tag

The tag must be set after calling Cipher#decrypt, Cipher#key= and Cipher#iv=, but before calling Cipher#final. After all decryption is performed, the tag is verified automatically in the call to Cipher#final

这里是golang中的函数加密

ciphertext := aesgcm.Seal(nil, []byte(iv), []byte(plaintext), []byte(authData))
src := iv + string(ciphertext) // + try to add authentication tag here
fmt.Printf(hex.EncodeToString([]byte(src)))

如何提取身份验证标签并将其与iv和密文连接,以便我可以使用ruby中的解密功能进行解密

raw_data = [hexString].pack('H*')
cipher_text = raw_data.slice(12, raw_data.length - 28)
auth_tag = raw_data.slice(raw_data.length - 16, 16)

cipher = OpenSSL::Cipher.new('aes-256-gcm').decrypt
cipher.iv = iv # string 12 len
cipher.key = key # string 32 len
cipher.auth_data = # string 12 len
cipher.auth_tag = auth_tag
JSON.parse(cipher.update(cipher_text) + cipher.final)

我希望能够在 Go 中进行加密,并尝试在 Ruby 中进行解密。

最佳答案

您希望您的加密流程是这样的:

func encrypt(in []byte, key []byte) (out []byte, err error) {

    c, err := aes.NewCipher(key)
    if err != nil {
        return
    }

    gcm, err := cipher.NewGCM(c)
    if err != nil {
        return
    }

    nonce := make([]byte, gcm.NonceSize())
    if _, err = io.ReadFull(rand.Reader, nonce); err != nil {
        return
    }

    out = gcm.Seal(nonce, nonce, in, nil) // include the nonce in the preable of 'out'
    return
}

根据 aes.NewCipher,您输入的 key 的长度应为 16、24 或 32 字节文档。

来自上述函数的加密 out 字节将包含 nonce 前缀(长度为 16、24 或 32 字节)——因此可以在解密过程中轻松提取像这样的阶段:

// `in` here is ciphertext
nonce, ciphertext := in[:ns], in[ns:]

ns 的计算方式如下:

c, err := aes.NewCipher(key)
if err != nil {
    return
}

gcm, err := cipher.NewGCM(c)
if err != nil {
    return
}

ns := gcm.NonceSize()
if len(in) < ns {
    err = fmt.Errorf("missing nonce - input shorter than %d bytes", ns)
    return
}

编辑:

如果您在 go 端使用默认密码设置(见上文)进行加密:

gcm, err := cipher.NewGCM(c)

来自 the source标记字节大小将为 16

注:如果cipher.NewGCMWithTagSize使用 - 然后大小将明显不同(基本上在 1216 字节之间的任何地方)

所以让我们假设标签大小是 16,有了这些知识,并且知道完整的有效载荷安排是:

IV/nonce + raw_ciphertext + auth_tag

用于解密的Ruby端的auth_tag,是payload的最后16字节; raw_ciphertext 是 IV/nonce 之后的所有字节,直到 auth_tag 开始。

关于ruby - 从密码 aes 256 GCM Golang 中提取标签,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68350301/

相关文章:

ruby-on-rails - 例如,如何使用 gmail 帐户从 ruby​​ 发送电子邮件?

go - 如何与 Golang echo 框架和 Telegram 机器人配合使用?

java - 使用openssl解密用java加密的aes-gcm

ruby - 运行 Jekyll 时出错 – 库未加载 :/usr/local/opt/ruby/lib/libruby. 3.0.dylib (LoadError)

ruby-on-rails - gem install typhoeus - 未能构建 gem 扩展

html - ResponseWriter 为什么以及何时会生成原始 html?

python - 相当于 python 在 golang 中的编码 ('utf8' )

encryption - OpenSSL 认证加密

java - 与 IV 一起使用时,带有 BouncyCaSTLe 的 AES-GCM 抛出 "mac check in GCM failed"

ruby-on-rails - 使用 Rails 3 的 AJAX