我們當然可以使用 RSA OAEP 加密資料,但金鑰相當大,而且處理過程相當密集。我們的救星一直是橢圓曲線密碼學 (ECC) 的使用。但是,我們實際上可以使用 ECC 直接加密資料,因此我們使用金鑰封裝方法 (KEM),該方法也用於 PQC 方法。透過這種方式,我們使用迪菲-赫爾曼 (DH) 金鑰交換方法——但以離線方式進行。
假設 Bob 想要為 Alice 加密資料。為此,Bob 將擁有一個私鑰 b 和一個公鑰 b.G,而 Alice 將擁有一個私鑰 a 和一個公鑰 a.G。然後,橢圓曲線上的基點是 G,其中a.G 是點 G 加到自身 a 次。Bob 最初以受信任的方式取得 Alice 的公鑰 (a.G)。然後,他將取得他的私鑰 (b),並執行迪菲-赫爾曼運算以產生 a.B.G 的結果點。接下來,他將其饋送到 HKDF 方法中,以擴展並提取到 AES 金鑰中,以及一些上下文資料。這將導出一個秘密金鑰 (SecretKey),該金鑰將用於加密一些明文:
Bob 還將序列化他的公鑰並與訊息一起發送。這也將具有一個雜湊值,該雜湊值將顯示加密訊息和序列化的公鑰未被篡改。
為了進行解密,Alice 反序列化 Bob 的公鑰以產生 b.G。然後,她將取得她的私鑰 (a),並執行迪菲-赫爾曼運算以取得 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 都用於產生金鑰。
程式碼位於 [here]:
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 的範例執行位於 [here]:
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