Trying to do RSA using BouncyCastle, but struggling to find your way around the API? In a previous post (see here) I pondered why the RSA implementation in System.Security.Cryptography is restricted to only the most common usage scenarios. I mentioned BouncyCastle as an alternative for those who wanted a more flexible API, but never got around to providing examples where BouncyCastle was used. By request, this post provides usage examples by building a crude and simple, but efficient set of methods for RSA key generation, encryption, and decryption, all built on top of BouncyCastle.
BouncyCastle provides flexibility and control over your encryption approach, which comes at a cost. The BouncyCastle API might be a bit hard to cope with at first, but if you know encryption in general you should be able to find your way around the API without too much effort. This post will be focusing on RSA, since that was my original need, but it should be mentioned that BouncyCastle provides many other asymmetric (and symmetric) algorithms for which the usage is similar to what you find below.
Creating RSA keys
Creating RSA keys is a simple task. The method below lets you specify the key size in bits, and creates a key pair for you.
public AsymmetricCipherKeyPair GenerateKeys(int keySizeInBits)
{
RsaKeyPairGenerator r = new RsaKeyPairGenerator();
r.Init(new KeyGenerationParameters(new SecureRandom(),
keySizeInBits));
AsymmetricCipherKeyPair keys = r.GenerateKeyPair();
return keys;
}
That’s all there is to it.
Encryption
Now that we have a key pair, we are ready to encrypt and decrypt using RSA. In the example below, we use a key (public or private) to encrypt a byte sequence. To encrypt a string, simply convert the string to a byte array using Encoding.GetBytes.
public byte[] Encrypt(byte[] data, AsymmetricKeyParameter key)
{
RsaEngine e = new RsaEngine();
e.Init(true, key);</p>
<p>int blockSize = e.GetInputBlockSize();</p>
<p>List<byte> output = new List<byte>();</p>
<p>for (int chunkPosition = 0; chunkPosition < data.Length;
chunkPosition += blockSize)
{
int chunkSize = Math.Min(blockSize, data.Length -
(chunkPosition * blockSize));
output.AddRange(e.ProcessBlock(data, chunkPosition,
chunkSize));
}
return output.ToArray();
}
The approach above uses a list to gather output for the sake of simplicity. Note that the RSA engine can only process a limited block size at a time (block size depends on the key size). The approach above generalizes the RSA engine, and processes a data set of an arbitrary size.
The above method does not impose constraints on which key you use for encryption. Use the public key or the private key as you see fit for your solution.
Decryption
The Decrypt method is very similar to the Encrypt method:
public byte[] Decrypt(byte[] data, AsymmetricKeyParameter key)
{
RsaEngine e = new RsaEngine();
e.Init(false, key);</p>
<p>int blockSize = e.GetInputBlockSize();</p>
<p>List<byte> output = new List<byte>();</p>
<p>for (int chunkPosition = 0; chunkPosition < data.Length;
chunkPosition += blockSize)
{
int chunkSize = Math.Min(blockSize, data.Length -
(chunkPosition * blockSize));
output.AddRange(e.ProcessBlock(data, chunkPosition,
chunkSize));
}
return output.ToArray();
}
Again, it’s up to you which key you choose to use. If you want to use the common approach, encrypt using a symmetric cipher, hash the data, and sign the hash with your private key using the above Encrypt method. If you want to use another approach like encrypting the actual data using your private key, you are free to do so.
I hope this post helps those of you who want to apply RSA (or any other asymmetric cipher) to more subtle cases than those supported by the .NET framework.
hi! first of all thanks a lot! there is no documentation on the bouncy castle web page, or any where for that matter, on C# coding. I wanted to modify RSA signature for using blinding. but the above code dosen’t work.. i’m unable to makeout what’s wrong. i pasted the code in Class1.cs and called the functions as: Class1 rdc=new Class1(); AsymmetricCipherKeyPair keys = rdc.GenerateKeys(960); byte[] plainbytes = System.Text.Encoding.UTF8.GetBytes(txt1.Text); byte[] cipherbytes = rdc.Encrypt(plainbytes, keys.Private); byte[] plainbytes_de = rdc.Decrypt(cipherbytes, keys.Public); txt2.Text = Convert.ToBase64String(cipherbytes); txt3.Text = Convert.ToBase64String(plainbytes_de);
please tell me what i’m doing wrong… also there is a RsaBlindingEngine in Bouncy Castle… How is it usefull?
i’m sorry my name is lalit not Not Working!
Hi Lalit.
You haven’t stated what you are trying to achieve, so I’ll assume you expect
txt3.Textto contain the plain text fromtxt1.Textto verify that encryption and decryption works as intended. If that is the case, then you should convertplainbytes_deto a string usingEncoding.UTF8.GetString, notConvert.ToBase64String.The RSA blinding engine in BouncyCastle should work fine. Just generate keys, use
RSABlindingFactorGeneratorto generate a blinding factor for you, and useRSABlindingEnginefor encryption/decryption.Good luck!
Thanks a million! That solved the problem (silly mistake on my side)! But I’m stuck again, the constructor of RSABlindingFactorGenerator requires an object of RsaKeyParameters type. Do you know how to make this from the key pair or only the public key?
A simple type-casting solved the problem Again my silly mistake, sorry…
Is http://www.discryptor.net/ using it right?
Hi Harvard! Thanks for your example! I’ve been trying to implement it into my J2ME script for decryption, and “almost” work!
This is my “decryption part” code, and here, you can note some differences with your code:
public String RSADecrypt(byte[] data,RSAKeyParameters key) { RSAEngine e = new RSAEngine(); e.init(false, key); int blockSize = e.getInputBlockSize(); StringBuffer strOut=new StringBuffer(); for (int chunkPosition = 0; chunkPosition <data.length; chunkPosition += blockSize) { int chunkSize = Math.min(blockSize, Math.abs(data.length - (chunkPosition * blockSize))); byte[] pb=e.processBlock(data, chunkPosition, chunkSize); String strBuf=new String(pb); System.out.println(“Got:”+strBuf); strOut.append(strBuf); } return strOut.toString(); }
First, I’ve changed the AsymmetricKeyParameter with RSAKeyParameters, because I’ve already the modulus and private exponent for the private key. It works fine.
Also, where you wrote: int chunkSize = Math.min(blockSize, data.length – (chunkPosition * blockSize));
I wrote: int chunkSize = Math.min(blockSize, Math.abs(data.length – (chunkPosition * blockSize)));
That’s because if not, I got: java.lang.NegativeArraySizeException.
Well, once i did this, and set a crypto message for a decoded “Hello World!” text, I get:
“Got:!dlroW olleH”
If I try to decrypt larger texts, for example:
“I hope this post helps those of you who want to apply RSA (or any other asymmetric cipher) to more subtle cases than those supported by the .NET framework.”
The result is:
Got:op siht epoh I Got:esoht spleh ts Got:aw ohw uoy fo Got:SR ylppa ot tn Got:ehto yna ro( A Got:c cirtemmysa r Got:erom ot )rehpi Got: sesac eltbus Got:pus esoht naht Got: eht yb detrop Got:krowemarf TEN. Got:.
For a final string like: “op siht epoh Iesoht spleh tsaw ohw uoy fo SR ylppa ot tnehto yna ro( Ac cirtemmysa rerom ot )rehpi sesac eltbus pus esoht naht eht yb detropkrowemarf TEN..”
Any idea?
Thanks in advance!
I’ve copied this into a VB.NET application running framework 2.0.
I can’t seem to get it to decrypt more than one block of data. This code in the decrypt method
While chunkPosition < data.Length
Dim chunkSize As Integer = System.Math.Min(blockSize, data.Length – (chunkPosition * blockSize)) output.AddRange(e.ProcessBlock(data, chunkPosition, chunkSize)) chunkPosition += blockSize
End While
Only ever adds one range of bytes to the List, because the e.ProcessBlock line never gives back more than that. Also, the calculation that figures out chunksize returns a huge negative number on the second iteration. I’ve changed this number in the debugger to the same size block as the initial iteration to no avail. Any help?
Pingback: The Dangers of Copy/Paste Coding | Design Limbo
Hi, I want to change cryptoprovider(f/e: “Microsoft Enhanced Cryptographic Provider v1.0″) as keylength when generate pair key with AsymmetricCipherKeyPair class. Can anyone helps with it?
In Encryption List class are used by you. From jar this List is class is coming, this is an User Defined class or it is coming from any jar file, please mention those details.
Sekhar,
The above code is in c# although slightly modified it works great for the Java implementation of bouncycastle!
The list you are reffering to is actualy a data-type in c#. You can see examples of using a list here: http://dotnetperls.com/list
Thanks so much for posting something on this Havard! As other people have said; I could find no examples or documentation on this anywhere. I am using the Java implementation, but your code example is more then enough to get started.
Thanks again!
Charles: Glad to help, thanks for sharing!
Hello all I have a question concerning rsa key pairs. I am currently working for a client to simulate large volumes of encrypted traffic. the issue I am having with the keys is, I already have my private key given to me but its in a file with the certificate and its format is something like this “56 H3 75 …..” there are 10 sets like this. how would I use this to generate the private key or how would I import it.
Hi There,
This doesn’t exactly apply to this post, but I thought I would ask it here anyway as there is very little on using BouncyCastle in C# (as has been noted by previous posts here!).
Is there anyway to create an AsymmetricKeyParameter using a previously generated private key? I am generating a key pair, storing the private key in an encrypted form and then when it is time to create a P12 for the end user to retrieve their certificate, I am decrypting the previously stored private key, but now have no idea how to actually make it into an AsymmetricKeyParameter so as to create the P12 using BouncyCastle.
Is what I am trying to do even possible?
Any help is greatly appreciated.
Cheers, Craig Martin
I have the same question as Craig, what if you already have the private key and want to use it to decrypt. Trying to get this working with AWS
@Craig @zack The
AsymmetricKeyParameteritself is a base class for all asymmetric keys; it does not (and cannot) know what the actual key is. So, you need to construct a key parameter matching the key you want to use. If you’re using an RSA private key, construct anRSAKeyParametersinstance. If you’re using El Gamal, construct anElGamalKeyParametersinstance, and so on. All these concrete key parameter classes inheritAsymmetricKeyParameter.Brandon’s got a point. Any help for that?
Nvm, got it. As chunkPosition gets enlarged by blockSize, it is enough to put
int chunkSize = Math.Min(blockSize, data.Length – chunkPosition );
instead of
int chunkSize = Math.Min(blockSize, data.Length – (chunkPosition * blockSize));
Hi, I am looking for an infrastructure like JCE in java so I can “install” encryption providers. The one I am going to put in now is Bouncy Castle provider and use “PBEWITHMD5AND256BITAES-CBC-OPENSSL” but I want to be able to change the providers and algorithms just by configuration change. I have that in Java with JCE. Is there something like that in C# and are there docs / examples?
Thanks.
Hi Harvard,
Thanks for this. I was actually able to use your suggestions in blinding messages. However, I can’t seem to go through the whole process of blinding a message, signing it, unblinding the signed message, and verifying the signature. I’ve written these codes: http://www.daniweb.com/forums/post1315685.html#post1315685
Please, if you could have a look, perhaps you could tell me what I’m doing wrong.