Reputation: 13752
We are using the PKCS#7 / CMS data format standard to encrypt/decrypt/sign/verify sensitive payloads. Currently we're using 2048 and 4096 bit RSA certificates (and keys) for our PKCS7 / CMS and its fine (see RSA working code below).
We want to add support for ECC (specifically the secp521 curve) but .NET 4.5 has spotty support for ECC despite it being NSA suite B's only PKI algorithm (although at 256 and 384 prime moduli).
Question
What EC Certificate + keys can I use that would be compatible with .NET 4.5 and the code below (perhaps with some edits)? I'm looking for specific curves, in fact creating the certificate + keys via OpenSSL (or other common or free tool) would make for an extremely concrete answer and would be appreciated!
Working, simplified code for RSA-4096 certificate + keys
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;
}
Exception when using ECC certificate + keys
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)
Working, simplified code for RSA-4096 certificate + keys
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;
}
Exception when using ECC certificate + keys
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)
Creating the ECC Certificate
I am using the following batch file to generate my ECC Certificate(s), a representative snippet of which is
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"
Extra Details
In case you don't want to (re)create the certificate per the above linked batch file, here is a dump of the certificate via
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: I had previously asked a question trying to solve the problem in reverse; on doing ECC PKCS7/CMS via BouncyCastle but that got as many hugs as a cactus. This question pursues a much different approach...
Upvotes: 5
Views: 3088
Reputation: 45
First of all, PKCS#7 and Cryptographic Message Syntax (CMS) work differently in terms of signature algorithm OIDs.
In an X.509 certificate, the certificate's signature comes with an OID that is a combination of an (asymmetric) encryption scheme and a message digest algorithm. Examples are:
This works differently in PKCS#7 (aka CMS): The md encryption algorithm OID is separated from the pure hash scheme, i.e. an authenticatedAttribute is part of the PKCS#7 signature, which states the hash algorithm.
Apart from that, a message digest encryption algorithm is specified, which can be one of:
To make a long story short: Your X.509 signing certificate comes in your case with an EC key pair (curve, e.g. secp256r1, secp384r1, secp521r1, ...) - the public EC key is part of your X.509 certificate (namedCurve OID scheme).
You select a hashing scheme (e.g. SHA2-256, SHA2-384, SHA2-512). You specify in PKCS#7 the md encryption algorithm as explained above, you hash your content using your selected message digest algorithm putting this into the PKCS#7 authenticated attribute.
Upvotes: 0
Reputation: 11
It may be worth noting that TLS ciphersuites are not very related to CMS (note that the RFC for CMS has no mentions of TLS), so if your intention is to use CMS, then looking at the list of TLS ciphersuites that OpenSSL supports may not be the right place to look.
Also, as there is no SHA-128, using ecdsa-with-SHA128
appears to be quite the feat. ecdsa-with-SHA256
might actually be a better place to start.
Upvotes: 1
Reputation: 161
Your combination: ecdsa-with-SHA512 is not the best idea :-) Try ecdsa-with-SHA128 instead. If it works, you may increase to ecdsa-with-SHA256.
Hove you already checked the MSDN Blog on Elliptic Curve Diffie-Hellman?
You should consider not using the .NET default crypto libs; better try using OpenSSL and the .NET / OpenSSL Wrapper.
In Detail: OpenSSL provides a list of cyphers: Open SSL ECC TLS 1.2 Cyphers: - 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
The list changes if you choose TLS 1.1!
.NET 4.5 Cyphers: A bit hidden, and the list is not independent from your operating system libs: Check out the class, and the attributes of the Elliptic Curve Digital Signature Algorithm (ECDSA) class: MSDN ECDSA
So now just choose a working combination.
Upvotes: -1