もちろん、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(KEMとしてP256を使用)、DHKEM_P384_HKDF_SHA384(KEMとしてP384を使用)、DHKEM_P521_HKDF_SHA512(KEMとしてP521を使用)またはDHKEM_X25519_HKDF_SHA256(KEMとしてX25519を使用)のいずれかを使用します。いずれの場合も、鍵の生成には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