我们使用 PKCS#7 / CMS 数据格式标准来加密/解密/签名/验证敏感负载。目前,我们的 PKCS7 / CMS 使用 2048 和 4096 位 RSA 证书(和密钥),这很好(请参阅下面的 RSA 工作代码)。
我们希望添加对 ECC(特别是 secp521 曲线)的支持,但 .NET 4.5 对 ECC 的支持参差不齐,尽管它是 NSA suite B 唯一的 PKI 算法(尽管素数模数为 256 和 384)。
问题
我可以使用哪些与 .NET 4.5 兼容的 EC 证书 + 密钥 以及下面的代码(也许进行了一些编辑)?我正在寻找特定的曲线,实际上是在创建 通过 OpenSSL(或其他常见或免费工具)的证书 + 密钥将构成一个非常具体的 回答并将不胜感激!
工作,简化代码用于 RSA-4096 证书 + 密钥
public byte[] Encrypt(byte[] plainBytes, X509Certificate2 recipientCert)
{
// create ContentInfo
ContentInfo plainContent = new ContentInfo(plainBytes);
// EnvelopedCms represents encrypted data
//Oid encryptAlgoOid = new Oid("2.16.840.1.101.3.4.1.46"); // AES-256-GCM, .NET doesn't have it :(
Oid encryptAlgoOid = new Oid("2.16.840.1.101.3.4.1.42"); // AES-256-CBC
EnvelopedCms encryptedData = new EnvelopedCms(plainContent, new AlgorithmIdentifier(encryptAlgoOid));
// add a recipient
CmsRecipient recipient = new CmsRecipient(recipientCert);
// encrypt data with public key of recipient
encryptedData.Encrypt(recipient);
// create PKCS #7 byte array
byte[] encryptedBytes = encryptedData.Encode();
// return encrypted data
return encryptedBytes;
}
使用ECC证书+密钥时出现异常
System.Security.Cryptography.CryptographicException: Unknown error "-1073741637".
at System.Security.Cryptography.Pkcs.EnvelopedCms.EncryptContent(CmsRecipientCollection recipients)
at System.Security.Cryptography.Pkcs.EnvelopedCms.Encrypt(CmsRecipientCollection recipients)
at System.Security.Cryptography.Pkcs.EnvelopedCms.Encrypt(CmsRecipient recipient)
工作,简化代码用于 RSA-4096 证书 + 密钥
public byte[] Sign(byte[] data, X509Certificate2 signingCert)
{
// create ContentInfo
ContentInfo content = new ContentInfo(data);
// SignedCms represents signed data
SignedCms signedMessage = new SignedCms(content, detached:true)
// create a signer
CmsSigner signer = new CmsSigner(signingCert);
// sign the data
signedMessage.ComputeSignature(signer);
// create PKCS #7 byte array
byte[] signedBytes = signedMessage.Encode();
// return signed data
return signedBytes;
}
使用ECC证书+密钥时出现异常
System.Security.Cryptography.CryptographicException: Invalid provider type specified.
at System.Security.Cryptography.Pkcs.PkcsUtils.CreateSignerEncodeInfo(CmsSigner signer, Boolean silent)
at System.Security.Cryptography.Pkcs.SignedCms.Sign(CmsSigner signer, Boolean silent)
at System.Security.Cryptography.Pkcs.SignedCms.ComputeSignature(CmsSigner signer, Boolean silent)
at System.Security.Cryptography.Pkcs.SignedCms.ComputeSignature(CmsSigner signer)
创建ECC证书
我正在使用 以下批处理文件 生成我的 ECC 证书,其代表性片段是
openssl ecparam -out test-ecparams.pem -name secp521r1
openssl req -newkey ec:test-ecparams.pem -sha512 -keyout test-key.pem -keyform PEM -out test-csr.pem -outform PEM -subj '/C=US/CN=ECC-cert-test'
openssl x509 -req -days 365 -in test-csr.pem -signkey test-key.pem -out test-cert.pem -sha512
openssl pkcs12 -export -aes256 -out test.pfx -in test-cert.pem -inkey test-key.pem -name "ECC-cert-test-friendlyname"
额外详情
如果您不想根据上述链接的批处理文件(重新)创建证书,这里是通过以下方式转储的证书
openssl asn1parse -in test-cert.pem -i -dump
0:d=0 hl=4 l= 450 cons: SEQUENCE
4:d=1 hl=4 l= 291 cons: SEQUENCE
8:d=2 hl=2 l= 9 prim: INTEGER :ECEA16A0348AEAE1
19:d=2 hl=2 l= 10 cons: SEQUENCE
21:d=3 hl=2 l= 8 prim: OBJECT :ecdsa-with-SHA512
31:d=2 hl=2 l= 37 cons: SEQUENCE
33:d=3 hl=2 l= 11 cons: SET
35:d=4 hl=2 l= 9 cons: SEQUENCE
37:d=5 hl=2 l= 3 prim: OBJECT :countryName
42:d=5 hl=2 l= 2 prim: PRINTABLESTRING :US
46:d=3 hl=2 l= 22 cons: SET
48:d=4 hl=2 l= 20 cons: SEQUENCE
50:d=5 hl=2 l= 3 prim: OBJECT :commonName
55:d=5 hl=2 l= 13 prim: UTF8STRING :ECC-cert-test
70:d=2 hl=2 l= 30 cons: SEQUENCE
72:d=3 hl=2 l= 13 prim: UTCTIME :130212015455Z
87:d=3 hl=2 l= 13 prim: UTCTIME :140212015455Z
102:d=2 hl=2 l= 37 cons: SEQUENCE
104:d=3 hl=2 l= 11 cons: SET
106:d=4 hl=2 l= 9 cons: SEQUENCE
108:d=5 hl=2 l= 3 prim: OBJECT :countryName
113:d=5 hl=2 l= 2 prim: PRINTABLESTRING :US
117:d=3 hl=2 l= 22 cons: SET
119:d=4 hl=2 l= 20 cons: SEQUENCE
121:d=5 hl=2 l= 3 prim: OBJECT :commonName
126:d=5 hl=2 l= 13 prim: UTF8STRING :ECC-cert-test
141:d=2 hl=3 l= 155 cons: SEQUENCE
144:d=3 hl=2 l= 16 cons: SEQUENCE
146:d=4 hl=2 l= 7 prim: OBJECT :id-ecPublicKey
155:d=4 hl=2 l= 5 prim: OBJECT :secp521r1
162:d=3 hl=3 l= 134 prim: BIT STRING
0000 - 00 04 00 3b b5 16 53 81-4a e5 40 3e c3 43 6f 09 ...;..S.J.@>.Co.
0010 - 19 22 6f f2 45 81 71 41-3f 75 1e 89 74 a0 2a eb ."o.E.qA?u..t.*.
0020 - 8b d5 c5 1e 9c 50 6b 2e-2d 3c 69 da 5b 91 55 71 .....Pk.-<i.[.Uq
0030 - 46 8e ef a7 b2 13 ad e0-9c 26 6d 99 6b d3 42 e1 F........&m.k.B.
0040 - 3d 7a 21 2c 01 be 7b e8-43 c0 c0 79 ef 1e f4 4d =z!,..{.C..y...M
0050 - 7d 7d 52 56 30 17 57 2a-96 05 57 64 7d 8a e1 7a }}RV0.W*..Wd}..z
0060 - 3a 40 ff cd d6 03 e0 a2-00 3b 16 a9 26 91 d3 e9 :@.......;..&...
0070 - d2 d9 db 5e 7f 00 7a ba-61 d3 8b b5 9f c2 8e ba ...^..z.a.......
0080 - ef 16 e9 c6 b9 47 .....G
299:d=1 hl=2 l= 10 cons: SEQUENCE
301:d=2 hl=2 l= 8 prim: OBJECT :ecdsa-with-SHA512
311:d=1 hl=3 l= 140 prim: BIT STRING
0000 - 00 30 81 88 02 42 01 53-a8 eb 32 30 84 b6 80 ab .0...B.S..20....
0010 - 12 f2 03 2a fb 39 f6 3b-72 54 6e 1b 48 cd 52 0e ...*.9.;rTn.H.R.
0020 - a7 64 96 02 52 75 5d bc-5d 85 65 b1 a4 f1 05 1b .d..Ru].].e.....
0030 - 7b 9c 5d 7b e2 b3 21 88-f4 f3 d8 04 7f 45 68 ac {.]{..!......Eh.
0040 - f3 77 7a fa ff 12 17 fc-02 42 01 8f ab 6d 0a fb .wz......B...m..
0050 - dd 70 37 f4 53 03 91 13-97 63 3e 77 37 78 86 e4 .p7.S....c>w7x..
0060 - e7 4f 1c 06 51 99 2a e0-0b c1 6c ea 44 bd b2 41 .O..Q.*...l.D..A
0070 - 78 be 67 b6 00 74 fd b2-4d 11 2e a6 58 2e b5 02 x.g..t..M...X...
0080 - 77 ef 98 b2 ca be 68 b1-d3 27 e2 fb w.....h..'..
PS:我之前曾提出过一个试图逆向解决问题的问题;通过 BouncyCastle 进行ECC PKCS7/CMS,但这得到了像仙人掌一样多的拥抱。这个问题采用了一种截然不同的方法......
可能值得注意的是,TLS 密码套件与 CMS 关系不大(请注意,CMS 的 RFC 没有提及 TLS),因此,如果您打算使用 CMS,请查看 OpenSSL 的 TLS 密码套件列表支撑可能不是合适的地方。
此外,由于没有 SHA-128,使用
ecdsa-with-SHA128
似乎是一项壮举。 ecdsa-with-SHA256
实际上可能是一个更好的起点。
首先,PKCS#7 和加密消息语法 (CMS) 在签名算法 OID 方面的工作方式不同。
在 X.509 证书中,证书的签名附带一个 OID,该 OID 是(非对称)加密方案和消息摘要算法的组合。 例子有:
这在 PKCS#7(又名 CMS)中的工作方式有所不同:md 加密算法 OID 与纯哈希方案分离,即,authentiatedAttribute 是 PKCS#7 签名的一部分,它说明了哈希算法。
除此之外,还指定了消息摘要加密算法,可以是以下之一:
您选择哈希方案(例如 SHA2-256、SHA2-384、SHA2-512)。您在 PKCS#7 中指定 md 加密算法,如上所述,您使用所选的消息摘要算法对内容进行哈希处理,并将其放入 PKCS#7 身份验证属性中。
您是否已查看关于
Elliptic Curve Diffie-Hellman 的 MSDN 博客?
您应该考虑不使用 .NET 默认加密库;最好尝试使用OpenSSL 和 .NET / OpenSSL Wrapper。
详细信息:OpenSSL 提供了密码列表: 打开 SSL ECC TLS 1.2 密码: - TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 ECDH-ECDSA-AES128-SHA256 - TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 ECDH-ECDSA-AES256-SHA384 - TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 ECDH-ECDSA-AES128-GCM-SHA256 - TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 ECDH-ECDSA-AES256-GCM-SHA384如果您选择 TLS 1.1,列表会发生变化!
.NET 4.5 密码: 有点隐藏,并且该列表并不独立于您的操作系统库: 查看椭圆曲线数字签名算法 (ECDSA) 类的类和属性:所以现在只需选择一个工作组合即可。