0

In .NET there are two P256 curve algorithms that can be used with CngKey:

What confuses me is it appears to be possible to create a signature using CngAlgorithm.ECDiffieHellmanP256.

Sample code:

// create private key and data
var privateKey = CngKey.Create(CngAlgorithm.ECDiffieHellmanP256);
Console.WriteLine($"privateKey: {privateKey.Algorithm} {privateKey.KeyUsage}");

// sign data
var data = new byte[] { 1, 2, 3 };
byte[] signature;
using (var dsa = new ECDsaCng(privateKey))
{
    signature = dsa.SignData(data);
    Console.WriteLine($"Signature: {Convert.ToBase64String(signature)}");
}

// create stand-alone public key, just to be sure this is working as expected
var publicKeyBlob = privateKey.Export(CngKeyBlobFormat.EccPublicBlob);
var publicKey = CngKey.Import(publicKeyBlob, CngKeyBlobFormat.EccPublicBlob);
Console.WriteLine($"Public key: {publicKey.Algorithm} {publicKey.KeyUsage} {Convert.ToBase64String(publicKeyBlob)}");

// verify signature
using (var dsa = new ECDsaCng(publicKey))
{
    var verified = dsa.VerifyData(data, signature);
    Console.WriteLine($"Verified: {verified}");
}

output:

privateKey: ECDH_P256 AllUsages
Signature: I1+Bapp8jxC7hUbTQTDTqscR9uoM/bo0OG1WVxgJUWYWq6jmW38a51JnuVRMXMKHosLOClt+AlrjiL/hG7TaqQ==
Public key: ECDH_P256 AllUsages RUNLMSAAAAC9amJDYvEJF+6HXyIhHoOiyUyu3grcH7leeuiOjMAiGbKwFoLssph+NCpY35g2dSHvNgaU11AavV/gAkPH6UPm
Verified: True

Just to show the similarity; if I switch to use CngAlgorithm.ECDsaP256:

privateKey: ECDSA_P256 AllUsages
Signature: meQ2ywrGWCOnVCaa0bm74Z0Sj37epzSJ5bz/b0x31hGvTn8zk3hcRt5If1+r1PgoR0A1cmSBDF4QUkY0UQjPhw==
Public key: ECDSA_P256 AllUsages RUNTMSAAAADfyG3BtOqGrI63Kh+FPy6V0EmpVX/4mBSbDQ+RxEerlaQCIVq0STrl87D+Re1b+iZ7a8/+S74cHrFNILqYqLXi
Verified: True

Note that doing this the other way around -- trying to create a DH object using a DSA key -- with new ECDiffieHellmanCng(CngKey.Create(CngAlgorithm.ECDsaP256)) results in:

ArgumentException: Keys used with the ECDiffieHellmanCng algorithm must have an algorithm group of ECDiffieHellman.Parameter name: key

This implies there is some kind of difference between the key types.


Is it actually safe to use ECDH keys in this way (eg: is this code generating a secure digital signature)?

Is there a benefit to using ECDSA keys over ECDH keys (other than if you explicitly didn't want to allow key exchange)?

gregmac
  • 24,276
  • 10
  • 87
  • 118

1 Answers1

1

ECDiffieHellmanCng(CngKey.Create(CngAlgorithm.ECDsaP256))
This implies there is some kind of difference between the key types.

When you try to initialize an ECDiffieHellmanCng using a CngKey during runtime is verifies that the CngKey that you provided is part of a particular list of algorithms, MSDN calls them the Elliptic Curve Diffie-Hellman (ECDH) algorithm group, which has four valid AlgorithmGroup names ECDH,ECDiffieHellman,ECDiffieHellmanCng, and System.Security.Cryptography.ECDiffieHellmanCng, which all refer to the same implementation.

When you create a CngKey with CngAlgorithm.ECDiffieHellmanP256 you get a valid ECDH key who's AlgorithmGroup is ECDH, which is valid as a parameter to create a ECDiffieHellmanCng to perform key exchanges.

However, when you create a CngKey with CngAlgorithm.ECDsaP256 you get a key with an AlgorithmGroup of ECDSA which is not a valid AlgorithmGroup to create a ECDiffieHellmanCng to perform key exchanges.

The ECDSA AlgorithmGroup is used to denote a CngKey who's purpose to to perform Elliptic-curve Digital Signatures, and explicitly not perform key exchanges. This key can't be used with a ECDiffieHellmanCng to perform key exchanges because it most probably does not contain enough, valid and/or secure information to perform key exchanges with another party.

You're able to construct valid EC signatures using ECDsaCng with both ECDH and ECDSA CngKeys because they both contain enough, valid, or secure information to construct and perform a digital signatures. However, the reverse is not the same due to the limitations MSDN created when performing key exchanges, with their implementation of ECDiffieHellmanCng, in addition to the probable missing information/format the ECDSA CngKey key prevents the proper calculation of a key exchange.

We can verify this information with a short test script

CngKey ECDHKey = CngKey.Create(CngAlgorithm.ECDiffieHellmanP256);

CngKey ECDSAKey = CngKey.Create(CngAlgorithm.ECDsaP256);

Console.WriteLine(ECDHKey.Algorithm);
Console.WriteLine(ECDHKey.AlgorithmGroup);

Console.WriteLine(ECDSAKey.Algorithm);
Console.WriteLine(ECDSAKey.AlgorithmGroup);

using var ECDH = new ECDiffieHellmanCng(key: ECDHKey);

Console.WriteLine($"Signature Algorithm: {ECDH.SignatureAlgorithm}");

var ECDSA = new ECDsaCng(key: ECDHKey);

Console.WriteLine($"Signature Algorithm: {ECDSA.SignatureAlgorithm}");

ECDSA.Dispose();

ECDSA = new ECDsaCng(key: ECDSAKey);

Console.WriteLine($"Signature Algorithm: {ECDSA.SignatureAlgorithm}");

ECDSA.Dispose();

// outputs
ECDH_P256
ECDH
ECDSA_P256
ECDSA
Signature Algorithm: 
Signature Algorithm: ECDsa
Signature Algorithm: ECDsa

We can see that the ECDH contains the correct parameters and information to construct both a ECDSA Curve and a ECDH Curve, but the ECDSA Key can only be used with the ECDSA curve (ECDsaCng) because it's purpose is for performing signatures.

Is there a benefit to using ECDSA keys over ECDH keys (other than if you explicitly didn't want to allow key exchange)?

Is it actually safe to use ECDH keys in this way (eg: is this code generating a secure digital signature)?

I found a post over at ECDSA vs ECDH that covers the nuances involved between the two, and even provided some information above as to why these keys perform different functions. Here's an excerpt that I think would be immediately useful.

"ECDH is a key exchange method that two parties can use to negotiate a secure key over an insecure communication channel. It's a variation of the DH (Diffie-Hellman) key exchange method. ECDH stands for Elliptic-curve Diffie–Hellman. Yet ECDH is just a method, that means you cannot just use it with one specific elliptic curve, you can use it with many different elliptic curves.

ECDSA is a signature algorithm that can be used to sign a piece of data in such a way, that any change to the data would cause signature validation to fail, yet an attacker would not be able to correctly re-sign data after such a change. It is a variation of DSA (Digital Signature Algorithm). ECDSA stands for Elliptic Curve Digital Signature Algorithm. Also ECDSA only describes a method which can be used with different elliptic curves." -Mecki

DekuDesu
  • 2,224
  • 1
  • 5
  • 19