ECDSA and C#

Prof Bill Buchanan OBE FRSE
3 min readOct 28, 2023

Overall, Microsoft has been a little sluggish in getting into elliptic curve cryptography (ECC), but now .NET and Powershell support it. In fact, Powershell is now supported on Linux, Mac OSX and Windows. So, let’s see if we can create a signature that is used by Bitcoin and Ethereum: ECDSA (Elliptic Curve Digital Signature Algorithm). With ECDSA we use an elliptic curve to produce a digital signature. Overall, we take a hash of a message and then create a signature using a private key. The public key can then be used to verify the signature.

In this case, we will use a range of curves, such as 192-bit, 256-bit, 384-bit and 521-bit curves, and create with a range of hashing methods (such as MD5, SHA-1 and SHA-256). Common curve types include Brainpool, secp, and NIST. To set up a NIST P-256 curve, we create with:

ECDsa ecc = System.Security.Cryptography.ECDsa.Create(System.Security.Cryptography.ECCurve.CreateFromFriendlyName("nistp256));

The supported curves are:

and the hashing methods for the signature are:

We can then export the keys with:

ECParameters s = ecc.ExportExplicitParameters(true);

To select an SHA-1 hashing method for a word of “hello”:

byte[] hash1 = System.Security.Cryptography.HashAlgorithm.Create(hashmethod).ComputeHash(System.Text.Encoding.UTF8.GetBytes("Hello"));

The signature is then created with:

byte[] hash1 = System.Security.Cryptography.HashAlgorithm.Create(hashmethod).ComputeHash(System.Text.Encoding.UTF8.GetBytes(word));
ECDsa ecdsa = System.Security.Cryptography.ECDsa.Create(e);
byte[] ecdsa_sig = ecdsa.SignHash(hash1);

To verify, we need to provide the hash of the message and the signature:

bool rtn = ecdsa.VerifyHash(hash1, ecdsa_sig);
if (rtn == true) str1 = str1 + "\n\nSignature verifies";
else str1 = str1 + "Signature not verified!";

The coding is [here]:

public string sigs(string word, string curvename, string hashmethod)
{
ECDsa ecc = System.Security.Cryptography.ECDsa.Create(System.Security.Cryptography.ECCurve.CreateFromFriendlyName(curvename));
ECParameters s = ecc.ExportExplicitParameters(true);
ECParameters e = ecc.ExportParameters(true);

string str1 = "Message: " + word;
str1 = str1+"\nHash: " + hashmethod;
str1 = str1+"\nCurve: " + e.Curve.Oid.FriendlyName;
str1 = str1 + "\nCurve: " + e.Curve.Oid.Value;
str1 = str1 + "\nA=" + BitConverter.ToString(s.Curve.A).Replace("-", string.Empty);
str1 = str1 + "\nB=" + BitConverter.ToString(s.Curve.B).Replace("-", string.Empty);
str1 = str1 + "\nGx=" + BitConverter.ToString(s.Curve.G.X).Replace("-", string.Empty);
str1 = str1 + "\nGy=" + BitConverter.ToString(s.Curve.G.Y).Replace("-", string.Empty);
str1 = str1 + "\nP=" + BitConverter.ToString(s.Curve.Prime).Replace("-", string.Empty);
str1 = str1 + "\nOrder=" + BitConverter.ToString(s.Curve.Order).Replace("-", string.Empty);
str1 = str1 + "\n\nPrivate key:";
str1 = str1 + "\nD=" + BitConverter.ToString(e.D).Replace("-", string.Empty);
str1 = str1 + "\n\nPublic key:";
str1 = str1 + "\nQx=" + BitConverter.ToString(e.Q.X).Replace("-", string.Empty);
str1 = str1 + "\nQy=" + BitConverter.ToString(e.Q.Y).Replace("-", string.Empty);

byte[] hash1 = System.Security.Cryptography.HashAlgorithm.Create(hashmethod).ComputeHash(System.Text.Encoding.UTF8.GetBytes(word));
ECDsa ecdsa = System.Security.Cryptography.ECDsa.Create(e);
byte[] ecdsa_sig = ecdsa.SignHash(hash1);

str1 = str1 + "\n\nECDSA (Hex)=" + BitConverter.ToString(ecdsa_sig).Replace("-", string.Empty);
str1 = str1 + "\nECDSA (Base64)=" + System.Convert.ToBase64String(ecdsa_sig).Replace("-", string.Empty);
bool rtn = ecdsa.VerifyHash(hash1, ecdsa_sig);

if (rtn == true) str1 = str1 + "\n\nSignature verifies";
else str1 = str1 + "Signature not verified!";
return (str1);

}

and a sample test for secp256k1 [here]:

Curve: secp256k1
Curve:
A=0000000000000000000000000000000000000000000000000000000000000000
B=0000000000000000000000000000000000000000000000000000000000000007
Gx=79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798
Gy=483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8
P=FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F
Order=FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141
Private key:
D=7C28BF7A06AA97061E470280E3A0954074F2D6FC2D07ACCFB66FBAE8016B7BA2
Public key:
Qx=FE88C5697960D2CB36B2B99BE963F4410FDAED39BC1FA81C45555A79C75F15C6
Qy=7730131BDE73BEDDA4D7E7D993B477D2172E014620AA5496DA67906AD8743443
ECDSA (Hex)=753E1D84AC1B39C5D273B2C12F5D1D95D1798EC47C0FBF48DB07904CFC74B0DD7EF534D5B3F9181CCB41D382F096DE2D328C632AE9C726C1B174F78169CE0B7E
ECDSA (Base64)=dT4dhKwbOcXSc7LBL10dldF5jsR8D79I2weQTPx0sN1+9TTVs/kYHMtB04Lwlt4tMoxjKunHJsGxdPeBac4Lfg==
Signature verifies

--

--

Prof Bill Buchanan OBE FRSE
Prof Bill Buchanan OBE FRSE

Written by Prof Bill Buchanan OBE FRSE

Professor of Cryptography. Serial innovator. Believer in fairness, justice & freedom. Based in Edinburgh. Old World Breaker. New World Creator. Building trust.