混合加密:ECIES

本文介绍了混合加密方案ECIES(Elliptic Curve Integrated Encryption Scheme),它结合了公钥加密的安全性和对称密钥加密的效率。文章解释了 ECIES 的原理,包括 Alice 如何使用 Bob 的公钥生成共享密钥,加密消息并发送给 Bob,以及 Bob 如何使用私钥解密消息。同时给出了一个Golang中使用Google Tink实现的ECIES的例子。

混合加密: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 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

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