With ECDH (Elliptic Curve Diffie Hellman), Bob generates a scalar value of \(b\) and Alice generates a scalar value of \(a\). Bob computes \(b.G\) and Alice computes \(a.G\), and where \(G\) is the base point on the curve. Bob passes \(b.G\) to Alice, and Alice passes \(a.G\) to Bob. They then both compute \(a.b.G\) as a shared secret. In this case we will use a number of standard curves to produce the shared secret. In this case we will use Cryptography Next Generation (CNG).
Cryptography Next Generation (CNG): ECDH using .NET and C# |
Method
With elliptic curve cryptography, we start with a definition for the curve, such as:
\(y^2 = x^3 + ax + b \pmod p\)
This defines values for \(a\), \(b\) and \(p\). Next we select a base point on the curve (\(G\), and generate a random scalar value (\(D\)). This is the private key, and where the public key is generated from a point multiplcation of:
\(Q=D.G\)
This results in an \((x,y)\) point on the curve.
With ECDH, Bob generates a scalar value of \(b\) and Alice generates a scalar value of \(a\). Bob computes \(b.G\) and Alice computes \(a.G\), and where \(G\) is the base point on the curve. Bob passes \(b.G\) to Alice, and Alice passes \(a.G\) to Bob. They then both compute \(a.b.G\) as a shared secret:
Code
First we create a folder named "bc_ec03", and then go into that folder.We can create a Dotnet console project for .NET 8.0 with:
dotnet new console --framework net8.0
Next we can install the Bouncy Castle library with:
dotnet add package BouncyCastle.Crypto.dll --version 1.8.1
Next some code:
namespace CngECDSA { using System.Net.Mail; using System.Security.Cryptography; using System.Text; class Program { static void Main(string[] args) { var curvename="nistP256"; var h=CngAlgorithm.Sha256; var hashmethod="SHA256"; try { if (args.Length >0) curvename=args[0]; if (args.Length >1) hashmethod=args[1]; if (hashmethod=="SHA256") h=CngAlgorithm.Sha256; else if (hashmethod=="MD5") h=CngAlgorithm.MD5; else if (hashmethod=="SHA1") h=CngAlgorithm.Sha1; else if (hashmethod=="SHA384") h=CngAlgorithm.Sha384; else if (hashmethod=="SHA512") h=CngAlgorithm.Sha512; var c = ECCurve.CreateFromFriendlyName(curvename); var bob = new ECDiffieHellmanCng(c); var alice = new ECDiffieHellmanCng(c); alice.KeyDerivationFunction = ECDiffieHellmanKeyDerivationFunction.Hash; alice.HashAlgorithm = h; bob.KeyDerivationFunction = ECDiffieHellmanKeyDerivationFunction.Hash; bob.HashAlgorithm = h; var bobKey =bob.DeriveKeyMaterial(alice.PublicKey); var aliceKey =alice.DeriveKeyMaterial(bob.PublicKey); Console.WriteLine("Curve:\t\t{0}",curvename); Console.WriteLine("Hash:\t\t{0}",hashmethod); Console.WriteLine("\nBob Share Key:\t\t{0}",Convert.ToHexString(bobKey)); Console.WriteLine("Alice Share Key:\t{0}",Convert.ToHexString(aliceKey)); var b = bob.ExportParameters(true); Console.WriteLine("\nBob Private Key D:\t\t{0}",Convert.ToHexString(b.D)); Console.WriteLine("Bob Private Key (DER):\t\t{0}",Convert.ToHexString(bob.ExportPkcs8PrivateKey())); Console.WriteLine("Bob Private Key (PEM):\n{0}",bob.ExportECPrivateKeyPem()); Console.WriteLine("\nBob Public Key Q:\t\t({0}, {1})",Convert.ToHexString(b.Q.X),Convert.ToHexString(b.Q.Y)); Console.WriteLine("Bob Public Key (DER):\t\t{0}",Convert.ToHexString(bob.ExportSubjectPublicKeyInfo())); Console.WriteLine("Bob Public Key (PEM):\n{0}",bob.ExportSubjectPublicKeyInfoPem()); var a = alice.ExportParameters(true); Console.WriteLine("\nAlice Private Key D:\t\t{0}",Convert.ToHexString(a.D)); Console.WriteLine("Alice Private Key (DER):\t\t{0}",Convert.ToHexString(alice.ExportPkcs8PrivateKey())); Console.WriteLine("Alice Private Key (PEM):\n{0}",alice.ExportECPrivateKeyPem()); Console.WriteLine("\nAlice Public Key Q:\t\t({0}, {1})",Convert.ToHexString(a.Q.X),Convert.ToHexString(a.Q.Y)); Console.WriteLine("Alice Public Key (DER):\t\t{0}",Convert.ToHexString(alice.ExportSubjectPublicKeyInfo())); Console.WriteLine("Alice Public Key (PEM):\n{0}",alice.ExportSubjectPublicKeyInfoPem()); } catch (Exception e) { Console.WriteLine("Error: {0}",e.Message); } } } }
A sample run for secp2561 gives:
Curve: nistP256 Hash: SHA256 Bob Share Key: A2AE0BD0E123717D6D26FCEDBC6F1198DF01E23EF42CFE2B5AE0FDEED26C7AA6 Alice Share Key: A2AE0BD0E123717D6D26FCEDBC6F1198DF01E23EF42CFE2B5AE0FDEED26C7AA6 Bob Private Key D: 778EAC1A3A8CC77C8EB740137BFCF75CDD6D9D073EA6EEEF212629519096D1B3 Bob Private Key (DER): 3081A2020100301306072A8648CE3D020106082A8648CE3D030107047930770201010420778EAC1A3A8CC77C8EB740137BFCF75CDD6D9D073EA6EEEF212629519096D1B3A00A06082A8648CE3D030107A14403420004C3962F074C7F956F4D75C85206364FDF7472FA26F00A50811E0BDC45E612FBDC030C057B4EBCC365F9883238AEC45DA02A27EB383DB3450FAE26078D706BAA4FA00D300B0603551D0F310403020088 Bob Private Key (PEM): -----BEGIN EC PRIVATE KEY----- MHcCAQEEIHeOrBo6jMd8jrdAE3v891zdbZ0HPqbu7yEmKVGQltGzoAoGCCqGSM49 AwEHoUQDQgAEw5YvB0x/lW9NdchSBjZP33Ry+ibwClCBHgvcReYS+9wDDAV7TrzD ZfmIMjiuxF2gKifrOD2zRQ+uJgeNcGuqTw== -----END EC PRIVATE KEY----- Bob Public Key Q: (C3962F074C7F956F4D75C85206364FDF7472FA26F00A50811E0BDC45E612FBDC, 030C057B4EBCC365F9883238AEC45DA02A27EB383DB3450FAE26078D706BAA4F) Bob Public Key (DER): 3059301306072A8648CE3D020106082A8648CE3D03010703420004C3962F074C7F956F4D75C85206364FDF7472FA26F00A50811E0BDC45E612FBDC030C057B4EBCC365F9883238AEC45DA02A27EB383DB3450FAE26078D706BAA4F Bob Public Key (PEM): -----BEGIN PUBLIC KEY----- MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEw5YvB0x/lW9NdchSBjZP33Ry+ibw ClCBHgvcReYS+9wDDAV7TrzDZfmIMjiuxF2gKifrOD2zRQ+uJgeNcGuqTw== -----END PUBLIC KEY----- Alice Private Key D: 54C48C997E61E5876F12837A4450AC59499D3EC2A1EFC646C8870B1418CD5580 Alice Private Key (DER): 3081A2020100301306072A8648CE3D020106082A8648CE3D03010704793077020101042054C48C997E61E5876F12837A4450AC59499D3EC2A1EFC646C8870B1418CD5580A00A06082A8648CE3D030107A144034200045B6B6EB0192524F010D02C0CC03F7894D34008FD21D8A6C210D69BCDAA8E79E3D838F7B26EFD6DC6AE429093261DAF1EFF75E13F40E985991BBFFCCF633A3384A00D300B0603551D0F310403020088 Alice Private Key (PEM): -----BEGIN EC PRIVATE KEY----- MHcCAQEEIFTEjJl+YeWHbxKDekRQrFlJnT7Coe/GRsiHCxQYzVWAoAoGCCqGSM49 AwEHoUQDQgAEW2tusBklJPAQ0CwMwD94lNNACP0h2KbCENabzaqOeePYOPeybv1t xq5CkJMmHa8e/3XhP0DphZkbv/zPYzozhA== -----END EC PRIVATE KEY----- Alice Public Key Q: (5B6B6EB0192524F010D02C0CC03F7894D34008FD21D8A6C210D69BCDAA8E79E3, D838F7B26EFD6DC6AE429093261DAF1EFF75E13F40E985991BBFFCCF633A3384) Alice Public Key (DER): 3059301306072A8648CE3D020106082A8648CE3D030107034200045B6B6EB0192524F010D02C0CC03F7894D34008FD21D8A6C210D69BCDAA8E79E3D838F7B26EFD6DC6AE429093261DAF1EFF75E13F40E985991BBFFCCF633A3384 Alice Public Key (PEM): -----BEGIN PUBLIC KEY----- MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEW2tusBklJPAQ0CwMwD94lNNACP0h 2KbCENabzaqOeePYOPeybv1txq5CkJMmHa8e/3XhP0DphZkbv/zPYzozhA== -----END PUBLIC KEY-----
In this case we have used the NIST P256 curve, and where the shared key is "A2AE0BD0E123717D6D26FCEDBC6F1198DF01E23EF42CFE2B5AE0FDEED26C7AA6". Bob's private key is:
Bob Private Key D: 778EAC1A3A8CC77C8EB740137BFCF75CDD6D9D073EA6EEEF212629519096D1B3 Bob Private Key (DER): 3081A2020100301306072A8648CE3D020106082A8648CE3D030107047930770201010420778EAC1A3A8CC77C8EB740137BFCF75CDD6D9D073EA6EEEF212629519096D1B3A00A06082A8648CE3D030107A14403420004C3962F074C7F956F4D75C85206364FDF7472FA26F00A50811E0BDC45E612FBDC030C057B4EBCC365F9883238AEC45DA02A27EB383DB3450FAE26078D706BAA4FA00D300B0603551D0F310403020088 Bob Private Key (PEM): -----BEGIN EC PRIVATE KEY----- MHcCAQEEIHeOrBo6jMd8jrdAE3v891zdbZ0HPqbu7yEmKVGQltGzoAoGCCqGSM49 AwEHoUQDQgAEw5YvB0x/lW9NdchSBjZP33Ry+ibwClCBHgvcReYS+9wDDAV7TrzD ZfmIMjiuxF2gKifrOD2zRQ+uJgeNcGuqTw== -----END EC PRIVATE KEY-----
In this case D=778EAC1A3A8CC77C8EB740137BFCF75CDD6D9D073EA6EEEF212629519096D1B3. We can also display in a DER format (and which starts with 30 or a PEM format.
For the public key we have:
Bob Public Key Q: (C3962F074C7F956F4D75C85206364FDF7472FA26F00A50811E0BDC45E612FBDC, 030C057B4EBCC365F9883238AEC45DA02A27EB383DB3450FAE26078D706BAA4F) Bob Public Key (DER): 3059301306072A8648CE3D020106082A8648CE3D03010703420004C3962F074C7F956F4D75C85206364FDF7472FA26F00A50811E0BDC45E612FBDC030C057B4EBCC365F9883238AEC45DA02A27EB383DB3450FAE26078D706BAA4F Bob Public Key (PEM): -----BEGIN PUBLIC KEY----- MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEw5YvB0x/lW9NdchSBjZP33Ry+ibw ClCBHgvcReYS+9wDDAV7TrzDZfmIMjiuxF2gKifrOD2zRQ+uJgeNcGuqTw== -----END PUBLIC KEY-----
and where the public key point is (C3962F074C7F956F4D75C85206364FDF7472FA26F00A50811E0BDC45E612FBDC, 030C057B4EBCC365F9883238AEC45DA02A27EB383DB3450FAE26078D706BAA4F). We can also display in a DER or a PEM format.