Page 1 of 1

RSA Encryption in VB.NET Follow on from MD5 Encryption in VB.NET Rate Topic: ***** 1 Votes

#1 Bort  Icon User is online

  • Ill-informed Mongoloid
  • member icon

Reputation: 409
  • View blog
  • Posts: 3,001
  • Joined: 18-September 06

Posted 15 October 2008 - 07:55 AM

I created a tutorial covering MD5 encryption and how to apply it in your applications (here). This was to help create secure Trial Period code for my applications (see here). These were both coupled with a third tutorial about manipulating the Windows Registry (here).

When I sat down and started working out how they would work together, I realised that having all three parts working together was next to impossible, simply for the reason that MD5 encryption is one way only. Once some data has been encrypted, it cannot then be decrypted, and since the trial period code needed to store a date to be checked when the application starts up, not only did it need to encrypt it, but also decrypt it when it came to checking the date.

So, I started investigating two way encryption and how it works in VB.NET (Thanks for pointing me in the right direction PsychoCoder :) ). This is what I discovered.

First of all, there are no decent tutorials or even explanations of what RSA Encryption is and does on the internet. I found a few which explained or gave code for different aspects of RSA, but nothing that put it all together. Hopefully, this tutorial will correct this.

Secondly, as with the other tutorials I've written recently, once I figured out what the code here was doing, it all became rather easy.

Ok, so on with the show.

RSA Encryption was invented in 1977 by three guys by the names of Rivest, Shamir, and Adlman. This is where it gets it's name. It is recommended you use RSA (or some other type of asynchronous encryption) for encrypting small amounts of data, like passwords.

First of all, what you need to do, as with the MD5 encryption, is import the necessary namespaces:

'Import the cryptography namespaces
Imports System.Security.Cryptography
Imports System.Text



Now, on your form, add 4 TextBoxes, and 3 Buttons. Set the Multiline property for TextBoxes 2, 3 and 4 to True.

Next we will need to declare some variables. Since these will be used throughout our code, I decided to put them just under Public Class Form1, like so:

Public Class Form1
	'Declare global variables
	Dim textbytes, encryptedtextbytes As Byte()
	Dim rsa As New RSACryptoServiceProvider
	Dim encoder As New UTF8Encoding



After this is ready, double-click on Button1 in your IDE and paste the following code:

	Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
		Dim TexttoEncrypt As String = TextBox1.Text
		'Use UTF8 to convert the text string into a byte array
		textbytes = encoder.GetBytes(TexttoEncrypt)
		'encrypt the text
		encryptedtextbytes = rsa.Encrypt(textbytes, True)
		'Convert the encrypted byte array into a Base64 string for display purposes
		TextBox2.Text = Convert.ToBase64String(encryptedtextbytes)
	End Sub



As you can see, before we use RSA to encrypt the data, we need to convert it into Byte format with the UTF8 Encoder. So, in effect, we are actually encrypting the data twice. Once from String to Byte, and then from Byte, to another Byte. The final line converts the encrypted data from Byte format, to Base64 String format in order to display it in TextBox2.

Once more, return to your IDE, but this time double click Button2. Here is your code:

	Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
		'get the decrypted clear text byte array
		textbytes = rsa.Decrypt(encryptedtextbytes, True)
		'convert the byte array to text using the same encoding format that was used for encryption
		TextBox1.Text = encoder.GetString(textbytes)
	End Sub



As you can see here, to get the original data, you need to run the encrypted data through the RSA decryptor, then through the UTF8 Encoder again. When you test this application, after clicking Button1 to encrypt the data, delete the contents of TextBox1. When you click Button2, you should see the original text appear in TextBox1.

Using RSA to encrypt and decrypt data is that simple.

There is one more aspect of RSA that I will look at here, more as a point of interest than any useful application. The way RSA works is that it uses 2 'keys' to encrypt and decrypt the data. The first is a public key (and in this tutorial is used to encrypt the data) , and the second is a private key (to decrypt the data). For encrypting text files and the like, one user could encrypt it using the public key, send the encrypted data to another user, who then uses the private key to unlock the file and decrypt it. These keys are stored in Byte format, which means that if we want to take a look at them, they will need to be converted into a Base64 String, like so:

		'Create an RSAParameters type
		Dim Parameters As New RSAParameters
		'export the key and other algorithm values
		Parameters = rsa.ExportParameters(True)
		'display the private key. Base64 encode the text to make display easier
		TextBox4.Text = Convert.ToBase64String(Parameters.D)
		'display the public key. Base64 encode the text to make display easier
		TextBox3.Text = Convert.ToBase64String(Parameters.Modulus)



Well, that's about all I've been able to discover about RSA Encryption, but hopefully it will be enough for you to work out how it works and how you can manipulate it to do what you want with it.

If you have any questions about it, or comments, please post them here, and I will look into it for you.

Happy coding,
Bort

Is This A Good Question/Topic? 2
  • +

Replies To: RSA Encryption in VB.NET

#2 TEH  Icon User is offline

  • D.I.C Head
  • member icon

Reputation: 29
  • View blog
  • Posts: 152
  • Joined: 30-January 08

Posted 06 April 2009 - 04:24 AM

I have created a snipped for that it is in VB.NET snippets and name is RSA Encryption/Decryption.
Was This Post Helpful? 0
  • +
  • -

#3 JoshD  Icon User is offline

  • D.I.C Head

Reputation: 9
  • View blog
  • Posts: 111
  • Joined: 22-March 10

Posted 29 March 2010 - 06:09 PM

Hello! This is fantastic, exactly what i was looking for, and you have given a clear explanation, which has helped me understand MASSIVELY!
Thanks to PsychoCoder for linking me to here!

Please view my current problem with the decryption here: http://www.dreaminco...ndpost&p=974049

Your help would be much appreciated, as im sure it is a really simple fix for someone who knows what they're doing!

Thanks!
JD
Was This Post Helpful? 0
  • +
  • -

#4 JoshD  Icon User is offline

  • D.I.C Head

Reputation: 9
  • View blog
  • Posts: 111
  • Joined: 22-March 10

Posted 07 April 2010 - 11:12 AM

Alright, so this has been really getting on my tits for the last 6 hours.

Previously I came here for help and you pointed me towards the MD5 hash encryption. Which by the way was perfect, easy, and works like a beauty.

However now I have some data that im saving into a database (like before), but THIS time, I need to be able to display it again some time. So for this i need a two-way cryption. So, naturally, RSA being the most common cryption service, i tried that.
And i got it working a beauty... in every program ive used it in except this one which is my coursework.

So heres the code that works in my test program:
'Import the cryptography namespaces
Imports System.Security.Cryptography
Imports System.Text

Public Class Form1
    'Declare global variables
    Dim textbytes, encryptedtextbytes As Byte()
    Dim rsa As New RSACryptoServiceProvider
    Dim encoder As New UTF8Encoding
    Dim encrypted, TextToDecrypt, TextToEncrypt, decrypted As String

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        TextToEncrypt = TextBox1.Text
        encrypt()
        TextBox2.Text = encrypted
    End Sub

    Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
        TextToDecrypt = TextBox2.Text
        decrypt()
        TextBox3.Text = decrypted
    End Sub

    Sub encrypt()
        'Use UTF8 to convert the text string into a byte array
        textbytes = encoder.GetBytes(TextToEncrypt)
        'encrypt the text
        encryptedtextbytes = RSA.Encrypt(textbytes, True)
        'Convert the encrypted byte array into a Base64 string for display purposes
        encrypted = Convert.ToBase64String(encryptedtextbytes)
    End Sub

    Sub decrypt()

        encryptedtextbytes = Convert.FromBase64String(TextToDecrypt)
        'get the decrypted clear text byte array
        textbytes = rsa.Decrypt(encryptedtextbytes, True)
        'convert the byte array to text using the same encoding format that was used for encryption
        decrypted = encoder.GetString(textbytes)
    End Sub
End Class



Heres the code that doesn't work in my coursework (the encryption works fine, though it is encrypted in a different form):
'Import the cryptography namespaces
Imports System.Security.Cryptography
Imports System.Text
'Import the database namespaces
Imports System.Data.OleDb
Public Class Customers
    'Declare global database variables
    Dim conn4 As New OleDbConnection
    Dim connstr4 As String = "PROVIDER=Microsoft.Jet.OLEDB.4.0;Data Source = InControlDB.mdb"
    Dim strSQL4 As String = "SELECT * FROM Customer"
    Dim da4 As New OleDbDataAdapter(strSQL4, conn4)
    Dim ds4 As New DataSet()
    Dim dr As DataRow
    Dim MaxRows As Integer
    'Declare global variables
    Dim textbytes, encryptedtextbytes As Byte()
    Dim rsa As New RSACryptoServiceProvider
    Dim encoder As New UTF8Encoding
    Dim TextToDecrypt, decrypted As String

    Private Sub Customers_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

        conn4.ConnectionString = connstr4

        da4.Fill(ds4)

        da4.SelectCommand = New OleDbCommand("SELECT * FROM Customer")
        da4.SelectCommand.Connection = conn4

        MaxRows = ds4.Tables(0).Rows.Count

        TextToDecrypt = ds4.Tables(0).Rows(1).Item(1)
        decrypt()
        txtName1.Text = decrypted
    End Sub

    Sub decrypt()
        encryptedtextbytes = Convert.FromBase64String(TextToDecrypt)
        'get the decrypted clear text byte array
        textbytes = rsa.Decrypt(encryptedtextbytes, True) '<<< ERROR IS HERE
        'convert the byte array to text using the same encoding format that was used for encryption
        decrypted = encoder.GetString(textbytes)
    End Sub
End Class



Error: Error occurred while decoding OAEP padding.

And that is all it says.

So we are clear, i have tested the pulling of the data from the database by displaying the text stored in the variable TextToDecrypt and it is the right data.
And if i copy and paste that data into my test program into textbox 2 and click button 2 it decrypts like a charm.
SO, all i can think of is that my computer hates me.

Any and all help appreciated.
Thanks.
JD.

EDIT: I have done an encryption in my test program and decrypted it, it worked fine, but when i copied the encrypted data it gave me, stopped it, then started it again, i pasted the encrypted data into the correct textbox and told it to decrypt, it came up with the same error: Error occurred while decoding OAEP padding.

On this basis, my theory is, the cryption must have some sort of Key or something which changes each time, so i need to tell my decrypter what key it used to encrypt the data with as for it to be able to decrypt it.


second EDIT: From my research on the theory of assymetric cryption, i can see that my guess about what i need to do wasn't all that far off, i do infact need to define some keys.
For the encryption a priavte key and for the decryption a public key.
That said... i still have NO idea how to do it.
From some google results i get the feeling its going to include csp parameters ToXmlString/FromXmlString.
But i could not find anything all that helpful.

Please help, thanks.
JD

This post has been edited by JoshD: 08 April 2010 - 03:19 AM

Was This Post Helpful? 0
  • +
  • -

#5 Bort  Icon User is online

  • Ill-informed Mongoloid
  • member icon

Reputation: 409
  • View blog
  • Posts: 3,001
  • Joined: 18-September 06

Posted 08 April 2010 - 03:20 AM

Hmm, odd...I had posted here...

Anyways, researching your problem, since I've never seen that error myself, points to the problem lying with the functions encoder.GetBytes and encoder.GetString. It seems that even if you feed these the exact same string, you won't always get the same result.

Instead it suggests you use Convert.ToBase64String and Convert.FromBase64String in their place.

Let me know how this works out :)
Was This Post Helpful? 0
  • +
  • -

#6 JoshD  Icon User is offline

  • D.I.C Head

Reputation: 9
  • View blog
  • Posts: 111
  • Joined: 22-March 10

Posted 08 April 2010 - 04:08 AM

Well, id worked out it was a problem that you don't always get the same string, however i thought that was on the .encrypt and .decrypt function, which would of been more difficult to solve.

So i tried it:
    Sub encrypt()
        'Use UTF8 to convert the text string into a byte array
        textbytes = Convert.FromBase64String(TextToEncrypt)
        'encrypt the text
        encryptedtextbytes = rsa.Encrypt(textbytes, True)
        'Convert the encrypted byte array into a Base64 string for display purposes
        encrypted = Convert.ToBase64String(encryptedtextbytes)
    End Sub

    Sub decrypt()

        encryptedtextbytes = Convert.FromBase64String(TextToDecrypt)
        'get the decrypted clear text byte array
        textbytes = rsa.Decrypt(encryptedtextbytes, True)
        'convert the byte array to text using the same encoding format that was used for encryption
        decrypted = Convert.ToBase64String(textbytes)
    End Sub


But it didn't work.

Error: Invalid length for a Base-64 char array.

Failed on ver first line of encryption
        textbytes = Convert.FromBase64String(TextToEncrypt)



The word i passed to it was 'Joshua'
So i tested it with 'abc' which threw the same error.

EDIT: Okay, DUH! Answer to this problem is simple, i forgot, strings to be converted FromBase64String or ToBase64String must be multiple of 4's.

However, this still gives a different encryption string each time.
And when stopping the program, starting it again, pasting the encrypted data in and clicking decrypt button, it gives the same error:
Error occurred while decoding OAEP padding.

I assume this would be because the difference is actually in the .encrypt and .decrypt functions like i originally thought. =(

EDIT: This thing at the bottom of your post... i think i can do it with that.
 'Create an RSAParameters type 
                Dim Parameters As New RSAParameters 
                'export the key and other algorithm values 
                Parameters = rsa.ExportParameters(True) 
                'display the private key. Base64 encode the text to make display easier 
                TextBox4.Text = Convert.ToBase64String(Parameters.D) 
                'display the public key. Base64 encode the text to make display easier 
                TextBox3.Text = Convert.ToBase64String(Parameters.Modulus)


That shows us how to get the keys, so now i just need to adjust that code to store the keys somewhere, which i think can be done with KeyContainer or something like that, i will have to look into it.

This post has been edited by JoshD: 08 April 2010 - 05:26 AM

Was This Post Helpful? 0
  • +
  • -

#7 JoshD  Icon User is offline

  • D.I.C Head

Reputation: 9
  • View blog
  • Posts: 111
  • Joined: 22-March 10

Posted 08 April 2010 - 09:19 AM

I got it to work.

Okay, well, the internet was pretty much useless, so using a combination of code examples (that didn't actually work), a couple of hours, and a whole lot of trial and error guess work, i finally got the right code.

I will go through it now.

Step 1: I set this as a Global Variable
    'Key variables
    Dim cp As New CspParameters


Step 2: I gave the variable some meaning
        'set cp container name
        cp.Flags = CspProviderFlags.UseMachineKeyStore
        cp.KeyContainerName = "CryptKeys" 'This name can be anything you choose it to be.


Step 3: I added this line to the very begining of BOTH the encrypt, and decrypt procedures
Dim rsa As New RSACryptoServiceProvider(cp)


And as if by magic, your program remembers.

Now, the key is stored in your computer and used every time.

So now, to test it: run it, encrypt it, decrypt it, copy the encrypted data in textbox2, close it, stop it, run it again, paste into textbox2 and click decrypt. It will decrypt it no problems. =D

I think this means that if you were to copy the program to a different PC, it would no longer remember the key, meaning you can't decrypt your decrypted data anymore, so be careful you dont move accross computers then realise your stuck with a load of encrypted data you can't decrypt. But, i haven't tested moving it to another PC yet.

Im not gonna give you my entire programs code just to explain this so i'll give you an example program using the code Bort gave us:
'Import the cryptography namespaces
Imports System.Security.Cryptography
Imports System.Text

Public Class Form1
    'Declare global variables
    Dim textbytes, encryptedtextbytes As Byte()
    Dim TextToDecrypt, TextToEncrypt, decrypted, encrypted As String
    Dim encoder As New UTF8Encoding
    'Declare key variables
    Dim cp As New CspParameters

    Private Sub Form4_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        'Set cp container name and tell it to use the information at the computer's key store
        cp.Flags = CspProviderFlags.UseMachineKeyStore
        cp.KeyContainerName = "CryptKeyCon"
    End Sub

    Private Sub btnEncrypt_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnEncrypt.Click
        'Define data to be encrypted
        TextToEncrypt = TextBox1.Text
        'Call encryption procedure
        encrypt()
        'Output result
        TextBox2.Text = encrypted
    End Sub

    Private Sub btnDecrypt_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnDecrypt.Click
        'Define data to be decrypted
        TextToDecrypt = TextBox2.Text
        'Call decryption procedure
        decrypt()
        'Output result
        TextBox3.Text = decrypted
    End Sub

    Sub encrypt()
        'Declare cryption provider
        Dim rsa As New RSACryptoServiceProvider(cp)

        'Use UTF8 to convert the text string into a byte array
        textbytes = Encoder.GetBytes(TextToEncrypt)
        'Encrypt the text
        encryptedtextbytes = rsa.Encrypt(textbytes, True)
        'Convert the encrypted byte array into a Base64 string for display purposes
        encrypted = Convert.ToBase64String(encryptedtextbytes)
    End Sub

    Sub decrypt()
        'Declare cryption provider
        Dim rsa As New RSACryptoServiceProvider(cp)

        'Convert the Base64 string to encrypted byte array for decryption
        encryptedtextbytes = Convert.FromBase64String(TextToDecrypt)
        'Get the decrypted clear text byte array
        textbytes = rsa.Decrypt(encryptedtextbytes, True)
        'Convert the byte array to text using the same encoding format that was used for encryption
        decrypted = encoder.GetString(textbytes)
    End Sub

End Class



Maybe you could add this or link to this post at the end of your tutorial for others to easily get at if they have the same problem. =)

Thanks.
JD.

This post has been edited by JoshD: 09 April 2010 - 02:45 AM

Was This Post Helpful? 3
  • +
  • -

#8 Guest_Mahmoud*


Reputation:

Posted 13 July 2010 - 10:25 AM

I know it's too late but really thanks a lot you explained a very important thing i was looking for in my program .
Was This Post Helpful? 0

Page 1 of 1