Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / security / encryption

Encryption and Decryption of Data using Elliptic Curve Cryptography( ECC ) with Bouncy Castle C# Library

3.69/5 (13 votes)
13 Jan 2016CPOL3 min read 77.9K  
If you want to know how to encrypt data using Elliptic Curve Algorithm in C#, then this tip is for you.

Introduction

This tip will help the reader in understanding how using C# .NET and Bouncy Castle built in library, one can encrypt and decrypt data in Elliptic Curve Cryptography.

Background

Before looking at the actual implementation, let's briefly understand some key elements.

Question: What is ECC?

Answer: ECC is an asymmetric cryptography algorithm which involves some high level calculation using mathematical curves to encrypt and decrypt data. It is similar to RSA as it's asymmetric but it uses a very small length key as compared to RSA.

Question: What is Bouncy Castle?

Answer: Bouncy Castle is an open source library in C# used for encryption. .NET has encryption classes but using Bouncy Castle makes your cryptography work quite easily.

Using the Code

In this tip, we will be writing code for the below mentioned steps of ECC.

ECC is an asymmetric cryptography algorithm which involves the following steps:

Encryption

  1. Define a Curve
  2. Generate public private Key pair using that curve, for both sender and receiver
  3. Generate a Shared secret key from the key pair
  4. From that shared secret key, generate an encryption key
  5. Using that encryption key and symmetric encryption algorithm, encrypt the data to send

Decryption

The sender will either share the curve with receiver or sender and receiver will have the same use for the same curve type. Also, sender will share its public key with receiver.

  1. Generate public private Key pair using the same curve for that curve. For receiver.
  2. Regenerate a shared secret key using private key of receiver and public key of sender.
  3. From that shared secret key, generate an encryption key
  4. Using that encryption key and symmetric encryption algorithm, decrypt the data

Now that we have gone through the steps, let's see each step with code.

Encryption Process

1: Define a Curve
C#
string curveName = "P-521";
var ecP1 = AnssiNamedCurves.GetByName("FRP256v1");
var ecP21 = TeleTrusTNamedCurves.GetByName("brainpoolp512t1");
X9ECParameters ecP = NistNamedCurves.GetByName(curveName);
c = (FpCurve)ecP.Curve;
eCDomainParameters = new ECDomainParameters(ecP.Curve, ecP.G, ecP.N, ecP.H, ecP.GetSeed());
2: Generate public private Key pair using that curve. For Sender and receiver both
C#
senderPrivate = ((ECPrivateKeyParameters)asymmetricCipherKeyPair.Private).D.ToByteArray();
senderPublic = ((ECPublicKeyParameters)asymmetricCipherKeyPair.Public).Q.GetEncoded();
3: Generate a Shared secret key from the key pair
C#
public byte[]  GetSharedSecretValue(bool isEncrypt=true)
      {
          ECDHCBasicAgreement  eLacAgreement=new ECDHCBasicAgreement();
          eLacAgreement.Init(asymmetricCipherKeyPair.Private);
          ECDHCBasicAgreement  acAgreement=new ECDHCBasicAgreement();
          acAgreement.Init(asymmetricCipherKeyPairA.Private);
          BigInteger eLA=  eLacAgreement.CalculateAgreement(asymmetricCipherKeyPairA.Public);
          BigInteger a = acAgreement.CalculateAgreement(asymmetricCipherKeyPair.Public);
          if (eLA.Equals(a) && !isEncrypt)
          {
              return eLA.ToByteArray();
          }
          if (eLA.Equals(a) && isEncrypt)
          {
              return a.ToByteArray();
          }
          return null;
      }
4: From that shared secret key, generate an encryption key
C#
public byte[] DeriveSymmetricKeyFromSharedSecret(byte[] sharedSecret)
       {
           Org.BouncyCastle.Crypto.Agreement.Kdf.ECDHKekGenerator egH=
           		new ECDHKekGenerator( DigestUtilities.GetDigest("SHA256
           egH.Init(new DHKdfParameters(NistObjectIdentifiers.Aes,sharedSecret.Length,sharedSecret));
           byte[] symmetricKey = new byte[ DigestUtilities.GetDigest("SHA256").GetDigestSize()];
           egH.GenerateBytes(symmetricKey, 0,symmetricKey.Length);   

           return symmetricKey;
       }
5: Using that encryption key and symmetric encryption algorithm, encrypt the data to send
C#
public byte[] Encrypt(byte[] data, byte[] derivedKey)
        {
            byte[] output=null;
           try
           {
               KeyParameter keyparam = ParameterUtilities.CreateKeyParameter("DES", derivedKey);
               IBufferedCipher cipher = CipherUtilities.GetCipher("DES/ECB/ISO7816_4PADDING");
               cipher.Init(true, keyparam);
               try
               {
                 output = cipher.DoFinal(data);
                   return output;
               }
               catch (System.Exception ex)
               {
                   throw new CryptoException("Invalid Data");
               }
           }
           catch(Exception ex)
           {

           }

           return output;
       }

Decryption Process

The sender will either share the curve with receiver or sender and receiver will have same use for the same curve type. Also sender will share its public key with receiver.

1: Generate public private Key pair using the same curve for that curve. For receiver.
C#
asymmetricCipherKeyPairA = g.GenerateKeyPair();

           recieverPrivate = ((ECPrivateKeyParameters)asymmetricCipherKeyPairA.Private).D.ToByteArray();

           recieverPublic = ((ECPublicKeyParameters)asymmetricCipherKeyPairA.Public).Q.GetEncoded();
2: Regenerate a shared secret key using private key of receiver and public key of sender.
3: From that shared secret key, generate an encryption key
4: Using that encryption key and symmetric encryption algorithm, decrypt the data.
C#
public byte[] Decrypt(byte[] cipherData, byte[] derivedKey)
     {
          byte[] output=null;
         try
         {
             KeyParameter keyparam = ParameterUtilities.CreateKeyParameter("DES", derivedKey);
             IBufferedCipher cipher = CipherUtilities.GetCipher("DES/ECB/ISO7816_4PADDING");
             cipher.Init(false, keyparam);
             try
             {
                 output = cipher.DoFinal(cipherData);

             }
             catch (System.Exception ex)
             {
                 throw new CryptoException("Invalid Data");
             }
         }
         catch (Exception ex)
         {
         }

         return output;
     }

So, this is how we encrypt and decrypt a message in ECC.

Points of Interest

In order to first understand the working of ECC, I had to go through many specifications and Googling. Then, the main point and reason for me to write this tip is because there was nowhere on the internet where we could have a direct Bouncy Castle C# implementation of ECC given.

Although there is built-in .NET ECDiffieHellman class for ECC, I have not explored it because my main requirement was to use Bouncy Castle.

History

  • 13th January, 2016: First draft

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)