6

I've been looking around for hours on Google and Microsoft's Crypto API on how to generate a public and private ECC key pair. The ECDiffieHellmanCng Class (http://msdn.microsoft.com/en-us/library/system.security.cryptography.ecdiffiehellmancng.aspx#Y3081) lists an example but I don't know how to access the private key directly.

For a little background on the program, it's a C# console app for managing TrueCrypt sessions, AES pre-shared key encryption, and ECDH/AES encryption. I need a function to merely create a public/private key pair to save to files, then documentation of how to use those generated keys in a wrapped AES encrypted file (instead of generating it at runtime like the example shows). Also I am aware off all the vulnerabilities that arise with saving files to the harddrive however I'm not worried about that with this program and I'm considering the 2 client computers to be secure.

Also note, I don't want to use the BouncyCastle API.

tshepang
  • 12,111
  • 21
  • 91
  • 136
Jim
  • 587
  • 2
  • 6
  • 19

2 Answers2

13

Most of this related to the CngKey, that can be used in many variations.

    static void test1()
    {
        CngKey k;

        if (CngKey.Exists("myECDH", CngProvider.MicrosoftSoftwareKeyStorageProvider, CngKeyOpenOptions.MachineKey))
        {
            k = CngKey.Open("myECDH", CngProvider.MicrosoftSoftwareKeyStorageProvider, CngKeyOpenOptions.MachineKey);
        }
        else
        {
            k = CngKey.Create(CngAlgorithm.ECDiffieHellmanP256, "myECDH", new CngKeyCreationParameters
        {
            ExportPolicy = CngExportPolicies.AllowPlaintextExport,
            KeyCreationOptions = CngKeyCreationOptions.MachineKey,
            KeyUsage = CngKeyUsages.AllUsages,
            Provider = CngProvider.MicrosoftSoftwareKeyStorageProvider,
            UIPolicy = new CngUIPolicy(CngUIProtectionLevels.None)
        });
        }

        byte[] privateBytes = k.Export(CngKeyBlobFormat.EccPrivateBlob);
        byte[] publicBytes = k.Export(CngKeyBlobFormat.EccPublicBlob);

        //This:
        var privateTester1 =
            new ECDiffieHellmanCng(CngKey.Import(privateBytes, CngKeyBlobFormat.EccPrivateBlob,
                CngProvider.MicrosoftSoftwareKeyStorageProvider));

        //Or that:
        var privateTester2 = new ECDiffieHellmanCng(k);
    }
StayOnTarget
  • 11,743
  • 10
  • 52
  • 81
Henrik N.
  • 556
  • 5
  • 13
  • @henrik-n would you be able to add some notes on how could the privateBytes in your code above be written to a file in PEM/ASN.1 format. I need to generate a CSR and trying to use openssl for that. Can I generate a CSR using .NET? – Sudhanshu Mishra Jul 10 '15 at 05:04
3

Elliptic Curve DiffieHellman is not an encryption algorithm, it is a key agreement protocol. Over an insecure channel, it gives you and the other party a common shared secret. This is frequently used for say an AES key to conduct secure communication.

Given another party's public key, you can get the derived shared secret key material with this api call. Note that as per the remarks section, the CNG APi does some post processing on the derived secret so it may or may not agree with what true-crypt generates.

To get the actual private key(which is not the shared secret), you can use use the following. You may want a different export format, they are listed here

using (ECDiffieHellmanCng alice = new ECDiffieHellmanCng())
    { 
    // Any  code you have  specifies the key your using or generates  one 
    var privatekey = alice.Key.Export(CngKeyBlobFormat.Pkcs8PrivateBlob)
    }

Note you may wind up with an error saying that the export policy does not allow exporting the private key. In that case, you need to create and user a key with a policy that does allow export

imichaelmiers
  • 3,449
  • 2
  • 19
  • 25
  • I might have gotten a little far off from my basic question which was how to make a public/private EC key pair. To my current knowledge, ECDH works in a similar manner to RSA where each client has a public and a private key. The initiating client uses the public key of the other to share a symmetric key. The 2nd client uses his private key to decrypt the symmetric key which was sent to him encrypted by his private key. I just have't found a way to have access to both public and private key without using the Bouncy Castle API. – Jim Apr 23 '12 at 04:17
  • Ah, I see what your asking. As a technical note, its not encryption because you can't choose value sent, its random. I changed my answer to include what I think does what you wanted. – imichaelmiers Apr 23 '12 at 04:33
  • I tried running the code and it gives me the error "The requested operation is not supported.". I then use a try/catch statement to see if it's the error you have forewarned me about however when I run it, it seems to just skip over it somehow-it doesn't return anything. `byte[] alicePrivateKey = null; try{ alicePrivateKey = alice.Key.Export(CngKeyBlobFormat.Pkcs8PrivateBlob); } catch (CryptographicException e) { Console.WriteLine("Error:"+e.Message+"\nSource:"+e.Source); }` – Jim Apr 23 '12 at 05:12
  • I also tried `alice.Key.ExportPolicy = CngExportPolicies.AllowPlaintextExport;` but it says that `ExportPolicy` cannot be set, only gotten. So assuming the error is that with the current policy is "None", how would I set the proper export policy? – Jim Apr 23 '12 at 05:24
  • @imichaelmiers could you please help with my question: http://stackoverflow.com/q/31330363/190476 – Sudhanshu Mishra Jul 13 '15 at 02:24