Using BouncyCastle .NET library for elliptical curve cryptography

Posted on 16 Jun 2009 04:51 under c# code cryptography .net

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:

  1. Encrypted text produced by RSA is pretty long.
  2. 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.
  3. 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 http://stackoverflow.com/questions/690566/-net-implementation-libraries-of-elliptic-curve-cryptography 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 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);
    }
}

Result

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 though:

  1. Why it uses a key size of 239 bits. It seems so unnatural in binary world.
  2. 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”.
  3. If I want to serialise the key to disk, which values actually should be saved.

Here is the complete source file.

rating: 0+x
Add a New Comment
or Sign in as Wikidot user
(will not be published)
- +