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

从密码 aes 256 GCM 戈朗中提取标签

从密码 aes 256 GCM 戈朗中提取标签

Go
qq_遁去的一_1 2022-09-12 20:24:41
我在Ruby中有加密和解密,并尝试用Go重写。我一步一步地尝试,所以从Ruby中的加密开始,并尝试在go中解密,这是有效的。但是当我尝试在Go中写入加密并在Ruby中解密时。当我尝试提取标签时,我遇到了困难,我解释了为什么我需要提取auth标签的原因加密 在红宝石中plaintext = "Foo bar"cipher = OpenSSL::Cipher.new('aes-256-gcm')cipher.encryptcipher.iv = iv # string 12 lencipher.key = key # string 32 lencipher.auth_data = # string 12 lencipherText = cipher.update(JSON.generate({value: plaintext})) + cipher.finalauthTag = cipher.auth_taghexString = (iv + cipherText + authTag).unpack('H*').first我尝试连接一个初始向量,一个密文和身份验证标签,所以在解密之前,我可以提取它们,特别是身份验证标签,因为我需要在Ruby中调用Cipher#final之前设置它auth_tag必须在调用密码#解密,密码#key=和密码#iv=之后,但在调用密码#final之前设置标记。执行所有解密后,将在调用密码#final时自动验证标记这是高浪中的函数加密ciphertext := aesgcm.Seal(nil, []byte(iv), []byte(plaintext), []byte(authData))src := iv + string(ciphertext) // + try to add authentication tag herefmt.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').decryptcipher.iv = iv # string 12 lencipher.key = key # string 32 lencipher.auth_data = # string 12 lencipher.auth_tag = auth_tagJSON.parse(cipher.update(cipher_text) + cipher.final)我希望能够在Go中进行加密,并尝试在Ruby中解密。
查看完整描述

2 回答

?
蓝山帝景

TA贡献1843条经验 获得超7个赞

您希望加密流如下所示:


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,您的输入长度应为 16、24 或 32 个字节。新密码文档。key


上述函数中的加密字节将包括前缀(长度为 16、24 或 32 个字节) - 因此可以在解密阶段轻松提取,如下所示:outnonce


// `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)

中,标记字节大小将为 。16

注意:如果是密码。使用新GCM标签大小 - 然后大小显然会有所不同(基本上在字节之间的任何地方)1216

因此,让我们假设标签大小为 ,掌握此知识,并且知道完整的有效负载安排是:16

IV/nonce + raw_ciphertext + auth_tag

解密的一侧是有效载荷的最后16个字节;并且raw_ciphertext是 up 之后的所有字节,直到 开始的位置。auth_tagRubyIV/nonceauth_tag


查看完整回答
反对 回复 2022-09-12
?
海绵宝宝撒

TA贡献1809条经验 获得超8个赞

aesgcm.Seal自动将 GCM 标记附加到密文的末尾。您可以在源代码中看到它:


    var tag [gcmTagSize]byte

    g.auth(tag[:], out[:len(plaintext)], data, &tagMask)

    copy(out[len(plaintext):], tag[:])                   // <---------------- here

所以你已经完成了,你不需要其他任何东西。 已返回末尾附加了 auth 标记的密文。gcm.Seal


同样,您也不需要提取 的 auth 标记,它也会自动执行此操作:gcm.Open


    tag := ciphertext[len(ciphertext)-g.tagSize:]        // <---------------- here

    ciphertext = ciphertext[:len(ciphertext)-g.tagSize]

因此,在解密过程中,您所要做的就是提取IV(nonce)并将其余部分作为密文传递。


查看完整回答
反对 回复 2022-09-12
  • 2 回答
  • 0 关注
  • 141 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号