如何在Windows的.net框架中使用ECC X509证书中的公钥加密数据? [英] How can I encrypt data using a public key from ECC X509 certificate in .net framework on windows?

查看:94
本文介绍了如何在Windows的.net框架中使用ECC X509证书中的公钥加密数据?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用:


  • Windows 10(1709版,OS Build 17025.1000)

  • .net framework 4.7

  • VS 2017(版本:15.3.5)

这是什么我做到了:


  1. 使用OpenSSL和脚本的 https://gist.github.com/sidshetye/4759690 进行了以下修改:

a)在256位素数域上使用NIST / P-256曲线

a) Used NIST/P-256 curve over a 256 bit prime field

b)使用SHA-256

b) Used SHA-256

将证书(从上一步中生成的文件)加载到X509Certificate2对象中

Load the certificate from file (generated in previous step) into X509Certificate2 object

将PFX文件导入Windows信任库(用于测试)。这是成功的。

Imported the PFX file into windows trust store (for testing). This is successful.

我被困在最后一步,因为所有使用X509Certificate2对象的示例主要仅使用RSA,而我使用的是ECC证书。对于RSA证书,X509Certificate2上有一个 GetRSAPublicKey 扩展方法,而RSA类具有 Encrypt 方法。但是,ECC证书没有这种方法。

I am stuck at the last step because all the examples that use X509Certificate2 object predominantly use only RSA and I am using ECC certificate. For RSA certificate, there is a GetRSAPublicKey extention method on X509Certificate2 and RSA class has Encrypt method. However there is no such method for ECC certificates.

接下来,我偶然发现了这篇文章(),并尝试进行以下操作(即使对于为什么ECC证书公钥是奇怪的)被强制转换为RSA类型):

Next, I stumbled on this post (Load a Certificate Using X509Certificate2 with ECC Public Key) and tried following (even though it appeared bizarre as to why ECC cert public key is being coerced into RSA type):

RSACryptoServiceProvider csp = (RSACryptoServiceProvider)cert.PublicKey.Key

我遇到以下异常:不支持证书密钥算法。

接下来,我偶然发现了这篇文章(将基于ECC的证书从Windows证书存储区导入CngKey ),该方法基本上是尝试创建CNGKey类型并使用它实例化ECDsaCng。但是,即使我可以使用ECDiffieHellmanCng做到这一点,也没有加密方法。

Next I stumbled on this post (Importing ECC-based certificate from the Windows Certificate Store into CngKey) which basically tried to create CNGKey type and instantiate ECDsaCng with it. However even if I can do it with ECDiffieHellmanCng, there is no Encrypt method on it.

因此,我不确定我如何进一步使用ECC X509证书的公共身份。

So I am not really sure how can I proceed further to use ECC X509 certificate's public key to encrypt data.

推荐答案

背景



非对称算法有三种不同的目的(我知道)

Background

Asymmetric algorithms have three different purposes (that I know of)


  1. 加密


    • RSA是唯一可以直接执行此操作的标准算法。


  • RSA

  • DSA

  • ECDSA

  • ElGamal签名

  • RSA
  • DSA
  • ECDSA
  • ElGamal Signature

  • Diffie-Hellman(DH)

  • ECDH

  • ElGamal加密(非对称启动阶段)

  • MQV

  • ECMQV

  • Diffie-Hellman (DH)
  • ECDH
  • ElGamal encryption (the asymmetric startup phase)
  • MQV
  • ECMQV

由于RSA加密的空间有限,并且在90年代对于RSA来说很难加密的主要用途是在 K ey Transfer,也就是说,加密消息仅仅是DES / 3DES(尚未发明AES)的对称加密密钥- https://tools.ietf.org/html/rfc2313#section-8

Because RSA encryption is space limited, and was hard for computers in the '90s, RSA encryption's primary use was in "Key Transfer", which is to say that the "encrypted message" was just the symmetric encryption key for DES/3DES (AES not yet having been invented) - https://tools.ietf.org/html/rfc2313#section-8.

密钥协商(或传输)方案始终必须与协议/方案结合才能进行加密操作。这样的方案包括

Key agreement (or transfer) schemes always have to be combined with a protocol/scheme to result in an encryption operation. Such schemes include


  • TLS(nee SSL)

  • CMS或S / MIME加密数据

  • IES(集成加密方案)

  • ECIES(椭圆曲线集成加密方案)

  • ElGamal加密(整体)

  • PGP加密

  • TLS (nee SSL)
  • CMS or S/MIME encrypted-data
  • IES (Integrated Encryption Scheme)
  • ECIES (Elliptic Curve Integrated Encryption Scheme)
  • ElGamal encryption (holistically)
  • PGP encryption

所以您可能想要的是ECIES。

So what you probably want is ECIES.

当前(.NET Framework 4.7.1,.NET Core 2.0)不支持获取ECDiffieHellman对象

Currently (.NET Framework 4.7.1, .NET Core 2.0) there's no support to get an ECDiffieHellman object from a certificate in .NET.

游戏结束了,对吧?好吧,可能不是。除非带有ECDH密钥的证书明确使用id-ecDH算法标识符(相对于更标准的id-ecc标识符),否则可以将其作为ECDSA打开。然后,您可以强制该对象成为ECDH:

Game over, right? Well, probably not. Unless a certificate carrying an ECDH key explicitly uses the id-ecDH algorithm identifier (vs the more standard id-ecc one) it can be opened as ECDSA. Then, you can coerce that object into being ECDH:

using (ECDsa ecdsa = cert.GetECDsaPublicKey())
{
    return ECDiffieHellman.Create(ecdsa.ExportParameters(false));
}

(对于私钥,可以执行类似的操作密钥是可导出的,否则需要复杂的东西,但您不需要它)

让我们继续前进,切断接收者的公共对象:

Let's go ahead and carve off the recipient public object:

ECDiffieHellmanPublicKey recipientPublic = GetECDHFromCertificate(cert).PublicKey;
ECCurve curve = recipientPublic.ExportParameters().Curve;

所以现在我们转到 http://www.secg.org/sec1-v2.pdf 第5.1节(椭圆曲线集成加密方案)

So now we turn to http://www.secg.org/sec1-v2.pdf section 5.1 (Elliptic Curve Integrated Encryption Scheme)


  1. 选择将SHA-2-256作为哈希函数的ANSI-X9.63-KDF。

  2. 选择HMAC–SHA-256–256。

  3. 在CBC模式下选择AES–256。

  4. 选择椭圆曲线Diffie-Hellman基本语言。

  5. 您已经选择了secp256r1。

  6. 是硬编码的。完成。

  7. 点压缩很烦人,请选择不使用它。

  8. 我省略了SharedInfo。

  9. 不使用XOR,不适用。

  1. Choose ANSI-X9.63-KDF with SHA-2-256 as the hash function.
  2. Choose HMAC–SHA-256–256.
  3. Choose AES–256 in CBC mode.
  4. Choose Elliptic Curve Diffie-Hellman Primitive.
  5. You already chose secp256r1.
  6. Hard-coded. Done.
  7. Point compression's annoying, choose not to use it.
  8. I'm omitting SharedInfo. That probably makes me a bad person.
  9. Not using XOR, N/A.



加密



Encrypt


  1. 在右曲线上制作一个临时密钥。

  1. Make an ephemeral key on the right curve.

ECDiffieHellman ephem = ECDiffieHellman.Create(curve);


  • 我们决定不。

  • We decided no.

    ECParameters ephemPublicParams = ephem.ExportParameters(false);
    int pointLen = ephemPublicParams.Q.X.Length;
    byte[] rBar = new byte[pointLen * 2 + 1];
    rBar[0] = 0x04;
    Buffer.BlockCopy(ephemPublicParams.Q.X, 0, rBar, 1, pointLen);
    Buffer.BlockCopy(ephemPublicParams.Q.Y, 0, rBar, 1 + pointLen, pointLen);
    


  • 继续前进无法直接执行此操作。

  • Can't directly do this, moving on.

    KDF时间。

    // This is why we picked AES 256, HMAC-SHA-2-256(-256) and SHA-2-256,
    // the KDF is dead simple.
    byte[] ek = ephem.DeriveKeyFromHash(
        recipientPublic,
        HashAlgorithmName.SHA256,
        null,
        new byte[] { 0, 0, 0, 1 });
    
    byte[] mk = ephem.DeriveKeyFromHash(
        recipientPublic,
        HashAlgorithmName.SHA256,
        null,
        new byte[] { 0, 0, 0, 2 });
    


  • 加密内容。

  • Encrypt stuff.

    byte[] em;
    
    // ECIES uses AES with the all zero IV. Since the key is never reused,
    // there's not risk in that.
    using (Aes aes = Aes.Create())
    using (ICryptoTransform encryptor = aes.CreateEncryptor(ek, new byte[16]))
    {
        if (!encryptor.CanTransformMultipleBlocks)
        {
            throw new InvalidOperationException();
        }
    
        em = encryptor.TransformFinalBlock(message, 0, message.Length);
    }
    


  • MAC it

  • MAC it

    byte[] d;
    
    using (HMAC hmac = new HMACSHA256(mk))
    {
        d = hmac.ComputeHash(em);
    }
    


  • 完成

  • Finish

    // Either
    return Tuple.Create(rBar, em, d);
    // Or
    return rBar.Concat(em).Concat(d).ToArray();
    




  • 解密



    向读者介绍左侧练习。

    Decrypt

    Left as an exercise to the reader.

    这篇关于如何在Windows的.net框架中使用ECC X509证书中的公钥加密数据?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆