Using BouncyCastle .NET library for elliptical curve cryptography
Encryption is a process of modifying some information in such a way that only the intended person can understand it. In software world it is normally done using various encryption algorithms. DES, Triple DES, AES are just some example of encryption algorithms. But these algorithms suffer from a basic problem of handing keys. Your encrypted information is as safe as the key you used to encrypt it. If you have encrypted something, you sure want someone to decrypt it. And for that, you need to send him/her the key. If the communication media is safe to send the key, why don’t you just send the information without encryption.
Public key encryption solves the basic problem of handling and transferring keys. It uses different keys for encryption and decryption. Most widely used algorithm for public key encryption is RSA. But it has some problems:
- Encrypted text produced by RSA is pretty long.
- The size of encrypted data depends on the key size but a key size of 2048 bits is recommended if you see your software being used after 2010.
- This algorithm is pretty slow compared to other symmetric key algorithms such as DES, AES etc.
Elliptical curve cryptography is a type of public key encryption but it uses much shorter keys without compromising the encryption strength. Elliptical curve encryption done using 128 bit key gives the same level of security as given by RSA using 3072 bit key.
I needed to use elliptical curve encryption in one of my project and I was searching for its implementation on .NET platform and then I found Bouncy Castle.
That was just a little background. This post is really about using the Bouncy Castle library in a C# project. This library implements generating digital signatures using ECDSA.
Namespaces
Following namespaces will need to be used by us:
using Org.BouncyCastle.Crypto; using Org.BouncyCastle.Crypto.Generators; using Org.BouncyCastle.Crypto.Parameters; using Org.BouncyCastle.Security;
Key Sizes
It is normally possible to use different key sizes. ECDSA supports following key sizes:
192 bit 239 bit 256 bit
Generating Keys
We can use the library itself to generate the random keys:
private static AsymmetricCipherKeyPair GenerateKeys (int keySize) {
var gen = new ECKeyPairGenerator ();
var secureRandom = new SecureRandom ();
var keyGenParam = new KeyGenerationParameters (secureRandom, keySize);
gen.Init (keyGenParam);
return gen.GenerateKeyPair ();
}
Generating Signature
private static AsymmetricCipherKeyPair GenerateKeys (int keySize) {
var gen = new ECKeyPairGenerator ();
var secureRandom = new SecureRandom ();
var keyGenParam = new KeyGenerationParameters (secureRandom, keySize);
gen.Init (keyGenParam);
return gen.GenerateKeyPair ();
}
Verifying Signature
private static bool VerifySignature (AsymmetricCipherKeyPair key, string plainText, byte[] signature) {
var encoder = new ASCIIEncoding ();
var inputData = encoder.GetBytes (plainText);
var signer = SignerUtilities.GetSigner ("ECDSA");
signer.Init (false, key.Public);
signer.BlockUpdate (inputData, 0, inputData.Length);
return signer.VerifySignature (signature);
}
Putting It All Together
Now we just need a function which calls above function in the right sequence so that we can see whether it really works:
private static void ECDSASample (int keySize) {
Console.WriteLine (string.Format ("======= Key Size: {0} =======", keySize));
string s = "Hello World!";
try {
var key = GenerateKeys (keySize);
var signature = GetSignature (s, key);
var signatureOK = VerifySignature (key, s, signature);
//Show it to me
var pubicKey = (ECPublicKeyParameters)(key.Public);
var privateKey = (ECPrivateKeyParameters)(key.Private);
Console.WriteLine ("Input Text: " + s);
Console.WriteLine ("Key ({0} bytes): {1}", privateKey.D.BitLength, privateKey.D);
Console.WriteLine ("Signature ({0} bytes): {1}", signature.Length, ToString (signature));
Console.WriteLine ("Signature verified: {0}", signatureOK);
Console.WriteLine ();
}
catch (Exception ex) {
Console.WriteLine (ex.Message);
}
}
Calling the above function 3 times for all keys sizes shows:
======= Key Size: 192 ======= Input Text: Hello World! Key (192 bytes): 5383271877913095293497459795960978936424465262977103383268 Signature (56 bytes): 303602190096736F03CB7AE4183590FE6185EFA900E6F4CD8B903100CF021900D5C0255ECC05921A9BC9EFD3AADB5B1FD8326CBA614713A3 Signature verified: True ======= Key Size: 239 ======= Input Text: Hello World! Key (236 bytes): 83986687572262518000833780316201230289349432496423690059305652492588142 Signature (66 bytes): 3040021E0DABDA56D88E2DEB633FBA399EBBA5F5E678AE8600791EBF65094B0CDB0A021E381C2A864523F306D808FD45335EF73D62C9B66E9F6F6A846A9E7CA447D8 Signature verified: True ======= Key Size: 256 ======= Input Text: Hello World! Key (255 bytes): 37067712327984319889067683157535631380322797492360190963255045782768937377579 Signature (71 bytes): 3045022100CFDB9F6DFB4C063C5C75CF4DCBC00F2CB79B61540BF982998C0F0810CAED7F2E022053DADF416C793AAB3EA8EB978A764B1E440C86C8BF897039EFCADEC7296790CA Signature verified: True
Summary
I am still confused about a few points:
- Why it uses a key size of 239 bits. It seems so unnatural in binary world.
- If I increase the length on input text and generate the signature, I sometime get a signature with different length. For example key size of 192 generates signature of 56 bytes when I use the string “Hello World” but it generates the signature of 54 bytes with string “Hello World”.
- If I want to serialise the key to disk, which values actually should be saved.
You can download the source file if you wish.
Great…Thank For Share This.
Very useful guide to using BC with ECDSA – thanks.
One small comment: your “Generating Signature” code appears to be a duplicate of the “Generating Keys” code – I assume this is a cut & paste error?
I dont how to implement this code
please guide us
to implement ECC
Can we do( elliptical curve crypto) encryption and Decryption using this lib.
Do you have any sample code to do the encryption and decryption.
Thanks
Hi,
Is it possible in c# to verify a ECDSA signature with the public key (as a byte array), the signature and the data signed?
Thanks
Hi, all my gratitude for sharing this!
pleas can u share some example about AES, SHA, MD5, RSA algorithm ?
thx u !