本文介绍了混合加密方案ECIES(Elliptic Curve Integrated Encryption Scheme),它结合了公钥加密的安全性和对称密钥加密的效率。文章解释了 ECIES 的原理,包括 Alice 如何使用 Bob 的公钥生成共享密钥,加密消息并发送给 Bob,以及 Bob 如何使用私钥解密消息。同时给出了一个Golang中使用Google Tink实现的ECIES的例子。
如果你从事网络安全工作,你应该知道公钥密码学非常擅长使用公钥来保护方法,并且对称密钥加密快速而高效。那么当我们把两者结合起来会发生什么呢?为此,我们得到了混合加密,例如 ECIES(椭圆曲线集成加密方案)。
使用 ECIES,Alice 创建一个密钥对 a 和 Q_A,其中 Q_A 是她的公钥。然后她将 Q_A 传递给 Bob。Alice 现在生成 S=r.Q_A,这是曲线上的另一点。然后使用 S 的值来创建对称密钥 (S_k) — 通常只是取点 S 的 x 坐标点。然后 Alice 使用 S_k 加密消息,然后将她的公钥 (Q_A) 和密文 (C ) 传递给 Bob。Bob 可以从他的私钥 (b) 和 Q_A 重新生成 S 的值以及相同的对称密钥 (S_k)。然后他将能够解密消息:
Google Tink 中 Golang 中 ECIES 的实现是 [ 这里]:
package main
import (
"fmt"
"os"
"strconv"
"github.com/tink-crypto/tink-go/v2/aead/aesgcm"
"github.com/tink-crypto/tink-go/v2/hybrid/ecies"
"github.com/tink-crypto/tink-go/v2/hybrid"
"github.com/tink-crypto/tink-go/v2/keyset"
)
func main() {
msg:="Testing"
context:="My Context"
keysize:=32
curve:=ecies.NISTP256
curveType:=0
argCount := len(os.Args[1:])
if (argCount>0) {msg = os.Args[1]}
if (argCount>1) {context =os.Args[2]}
if (argCount>2) {keysize,_= strconv.Atoi(os.Args[3])}
if (argCount>3) {curveType,_= strconv.Atoi(os.Args[4])}
if (curveType==0) {curve=ecies.NISTP256
} else if (curveType==1) {curve=ecies.NISTP384
} else if (curveType==2) {curve=ecies.NISTP521}
plaintext := []byte(msg)
contextInfo := []byte(context)
demParameters, _ := aesgcm.NewParameters(aesgcm.ParametersOpts{
KeySizeInBytes: keysize,
IVSizeInBytes: 12,
TagSizeInBytes: 16,
Variant: aesgcm.VariantNoPrefix,
})
params, _ := ecies.NewParameters(ecies.ParametersOpts{
CurveType: curve,
HashType: ecies.SHA256,
Variant: ecies.VariantTink,
NISTCurvePointFormat: ecies.CompressedPointFormat,
DEMParameters: demParameters,
Salt: []byte{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10},
})
km := keyset.NewManager()
keyID, _ := km.AddNewKeyFromParameters(params)
if err := km.SetPrimary(keyID); err != nil {
fmt.Printf("km.SetPrimary() err = %v, want nil", err)
}
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("Curve: %s\n\n",curve)
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)
}
secp256k1 曲线的示例运行是 [ 这里]:
Plaintext: Testing 123
Curve: NIST_P256
Private key: primary_key_id:3767711238 key_info:{type_url:"type.googleapis.com/google.crypto.tink.EciesAeadHkdfPrivateKey" status:ENABLED key_id:3767711238 output_prefix_type:TINK}
Public key: primary_key_id:3767711238 key_info:{type_url:"type.googleapis.com/google.crypto.tink.EciesAeadHkdfPublicKey" status:ENABLED key_id:3767711238 output_prefix_type:TINK}
Ciphertext: 01e092b60602cce0c2922299e73014a3a3cda806376528859a6a6db76aa4570d716e24ab74984dbcf72af68d3ca6ef68d094e715f4e508445f6e3db287635bb60fa0e4b91e33a65659be55c232
Decrypted: Testing 123
在 S_k 的生成中使用 Alice 的公钥的巨大优势在于它相当于数字签名。如果 Alice 没有密钥对,她可以生成一个随机标量值 (r) 并生成 R=rG。然后她可以使用 S= r.Q_b 来导出共享密钥。R 的值将与密文 (C) 一起传递:
这难道不是一个很棒的方法吗?它的核心是我们用于几乎每个 Web 页面连接的 ECDH 方法,但它是在离线方法中完成的。因此,我们拥有了公钥加密的强大功能以及对称密钥加密的速度。
- 原文链接: billatnapier.medium.com/...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!