密钥封装的公钥加密之美:HPKE

本文介绍了混合公钥加密(HPKE)结合密钥封装(KEM)的加密方法,它使用接收者的公钥来加密数据,使用密钥派生函数(KDF)来派生密钥,并使用带有附加数据的认证加密(AEAD)函数来加密数据,同时还给出了使用Go语言实现的HPKE代码示例。

使用密钥封装的公钥加密之美:HPKE

我们当然可以使用 RSA OAEP 加密数据,但密钥相当大,而且处理过程相当密集。我们的救星一直是椭圆曲线密码学 (ECC)。但是,我们实际上可以使用 ECC 直接加密数据,​​因此我们使用密钥封装方法 (KEM),该方法也用于 PQC 方法。通过这种方式,我们使用 Diffie-Hellman (DH) 密钥交换方法——但以离线方式进行。

假设 Bob 想要为 Alice 加密数据。为此,Bob 将拥有一个私钥 b 和一个公钥 b.G,而 Alice 将拥有一个私钥 a 和一个公钥 a.G。那么椭圆曲线上的基点是 G,其中 a.G 是将点 G 加到自身 a 次。Bob 最初以可信的方式获得 Alice 的公钥 (a.G)。然后,他将采用他的私钥 (b),并执行 Diffie-Hellman 运算以得到 a.B.G 的结果点。接下来,他将其输入到 HKDF 方法中,以扩展并提取到 AES 密钥,以及一些上下文数据。这将导出一个密钥 (SecretKey),它将用于加密一些纯文本:

Bob 还会序列化他的公钥并将其与消息一起发送。这还将具有一个哈希值,该值将表明加密消息和序列化的公钥没有被篡改。

为了解密,Alice 反序列化 Bob 的公钥以生成 b.G。然后,她将采用她的私钥 (a),并执行 Diffie-Hellman 运算以获得 a.b.G。我们将它与上下文一起输入到 HKDF 函数中,它将生成与 Bob 相同的密钥 (SecretKey)。然后,Alice 将能够解密密文并显示消息。

使用混合公钥加密 (HPKE),我们使用接收者的公钥,通过非对称密钥封装机制 (KEM) 来加密明文。该密钥是使用密钥派生函数 (KDF) 派生的,其中数据使用带有附加数据的经过身份验证的加密 (AEAD) 函数进行加密。在这种情况下,我们将使用:DHKEM_P256_HKDF_SHA256(使用 P256 作为 KEM)、DHKEM_P384_HKDF_SHA384(使用 P384 作为 KEM)、DHKEM_P521_HKDF_SHA512(使用 P521 作为 KEM)或 DHKEM_X25519_HKDF_SHA256(使用 X25519 作为 KEM)。在每种情况下,HKDF 都用于生成密钥。

代码在[ 这里]:

package main
import (
       "fmt"
 "os"
 "strconv"
 "github.com/tink-crypto/tink-go/v2/hybrid/hpke"
 "github.com/tink-crypto/tink-go/v2/hybrid"
 "github.com/tink-crypto/tink-go/v2/keyset"
)
func main() {
 msg:="Testing"
 context:="My Context"

 method:=hpke.DHKEM_P256_HKDF_SHA256
 m:=1
 argCount := len(os.Args[1:])
 if (argCount>0) {msg = os.Args[1]}
 if (argCount>1) {context =os.Args[2]}
 if (argCount>2) {m,_ =strconv.Atoi(os.Args[3])}

 if (m==2) {method=hpke.DHKEM_P384_HKDF_SHA384
 } else if (m==3) {method=hpke.DHKEM_P521_HKDF_SHA512
 } else if (m==4) {method=hpke.DHKEM_X25519_HKDF_SHA256
 }
 plaintext := []byte(msg)
 contextInfo := []byte(context)
 params,_ := hpke.NewParameters(hpke.ParametersOpts{
  KEMID:   method,
  KDFID:   hpke.HKDFSHA256,
  AEADID:  hpke.AES256GCM,
  Variant: hpke.VariantTink,
 })

 km := keyset.NewManager()
 keyID, _ := km.AddNewKeyFromParameters(params)
 if err := km.SetPrimary(keyID); err != nil {
 }
 privateKeyHandle, _ := km.Handle()

 publicKeyHandle, _ := privateKeyHandle.Public()

 encrypter, _ := hybrid.NewHybridEncrypt(publicKeyHandle)
 decrypter, _ := hybrid.NewHybridDecrypt(privateKeyHandle)

 ciphertext,_ := encrypter.Encrypt(plaintext, contextInfo)
 decrypted,_ := decrypter.Decrypt(ciphertext, contextInfo)

 fmt.Printf("Plaintext: %s\n\n",msg)
 fmt.Printf("Method: %s\n\n",method)
 fmt.Printf("Private key: %s\n\n",privateKeyHandle)
 fmt.Printf("Public key: %s\n\n",publicKeyHandle)
 fmt.Printf("Ciphertext: %x\n\n",ciphertext)
 fmt.Printf("Decrypted: %s\n",decrypted)

}

DHKEM-P256-HKDF-SHA256 的示例运行在[ 这里]:

Plaintext: Testing
Method: DHKEM-P256-HKDF-SHA256
Private key: primary_key_id:1203322961 key_info:{type_url:"type.googleapis.com/google.crypto.tink.HpkePrivateKey" status:ENABLED key_id:1203322961 output_prefix_type:TINK}
Public key: primary_key_id:1203322961 key_info:{type_url:"type.googleapis.com/google.crypto.tink.HpkePublicKey" status:ENABLED key_id:1203322961 output_prefix_type:TINK}
Ciphertext: 0147b94051043bdeb59abad6caebff20753dadfc0bf8a2d6131b6935f149afdc84b450dda4316d79bae3529eaafec63197a55ffd30c186ffea74bbcb811bfb2b93dacfeaab3b4cc8352534fd5f2e7252abac03553b16d607ea791df7c9
Decrypted: Testing
  • 原文链接: billatnapier.medium.com/...
  • 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
billatnapier
billatnapier
江湖只有他的大名,没有他的介绍。