5

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...

Community
  • 1
  • 1
DeepSpace101
  • 13,110
  • 9
  • 77
  • 127
  • Your previous question did not include any often used tags like [tag:cryptography] and [tag:encryption]. Seen by a maximum of 59 followers for the given tags, your question had a snowflake's chance in hell. – Maarten Bodewes Feb 11 '13 at 23:18
  • Only named curves are supported by the Microsoft CNG framework. So if your certificate contains the domain parameters instead of the OID of the curve, then it won't be supported. Could that be the issue? – Maarten Bodewes Feb 11 '13 at 23:44
  • Does your customer require an ECC implementation or an ECC implementation that is FIPS 140-2 certified? I'm not sure .NET is. Anyway, just to point out some other options there's also cryptlib and Mocana (not free, but may have a deal with your customer) – jglouie Feb 12 '13 at 03:07

2 Answers2

1

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.

Community
  • 1
  • 1
-1

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.

Tobi
  • 109
  • 1
  • 1
  • 12
  • Welcome to Stack Overflow. I've made some cosmetic changes to your answer, but it is perilously close to being 'not an answer' but just comments. – Jonathan Leffler Mar 05 '14 at 19:53
  • Can you elaborate "Your combination: ecdsa-with-SHA512 is not the best idea :-)"? – DeepSpace101 Mar 06 '14 at 23:51
  • The exception in the question: "System.Security.Cryptography.CryptographicException: Invalid provider type specified." indicates that ecdsa-with-SHA512 is not supported. And I know that this combination was also not possible with openSSL a year ago. So change to signature to ecdsa-with-SHA128. Also check out: https://www.openssl.org/docs/apps/ciphers.html ECDSA with SHA512 is very un-common. No wonder that .NET doesn't supports it very well. – Tobi Mar 07 '14 at 08:43