Encryption and Decryption
In the previous section, you saw how hashing works. Hashing is a one-way process, which means that once a value is hashed, you can't obtain its original value by reversing the process. This characteristic is particularly well suited for authentications as well as digitally signing a document.
In reality, there are many situations that require information to be performed in a two-way process. For example, if you send a secret message to a recipient, you would need to be able to "scramble" it so that only the recipient can see it. This process of scrambling is known as encryption. Undoing the scrambling process to obtain the original message is known as decryption. There are two main types of encryption, symmetric and asymmetric.
Symmetric Encryption
Symmetric encryption is also sometimes known as private key encryption. With private key encryption, you encrypt a secret message using a key that only you know. To decrypt the message, you need to use the same key. Private key encryption is effective only if the key can be kept a secret. If too many people know the key, its effectiveness is reduced.
Imagine you are trying to send a secret message to your faraway friend, Susan, using a private key. In order for Susan to decrypt the secret message, she must know the private key. So you need to send it to her. But if the secrecy of the key is compromised somehow (such as people eavesdropping on your conversation), then the message is no longer secure. Moreover, if Susan tells another friend about the private key, her friend can then also decrypt the message. Despite the potential weakness of private key encryption, it is very easy to implement and, computationally, it does not take up too many resources.
For private key encryption (symmetric) encryptions, the .NET framework supports the DES, RC2, Rijndael, and TripleDES algorithms.
To demonstrate symmetric encryption, I will use the
RijndaelManaged class in the following
SymmetricEncryption() function. Three parameters are required--the string to be encrypted, the private key, and the initialization vector (IV). The IV is a random number used in the encryption process to ensure that no two strings will give the same cipher text (the encrypted text) after the encryption process. You will need the same IV later on when decrypting the cipher text.
Code:
Private Function SymmetricEncryption( _
ByVal str As String, _
ByVal key As Byte(), _
ByVal IV As Byte()) As String
Dim memStream As New IO.MemoryStream
Try
'---creates a new instance of the RijndaelManaged class---
Dim RMCrypto As New RijndaelManaged
'---creates a new instance of the CryptoStream class---
Dim CryptStream As New CryptoStream(memStream, _
RMCrypto.CreateEncryptor(key, IV), _
CryptoStreamMode.Write)
Dim SWriter As New StreamWriter(CryptStream)
'---encrypting the string---
SWriter.Write(str)
SWriter.Close()
CryptStream.Close()
'---return the encrypted data as a string---
Return System.Convert.ToBase64String(memStream.ToArray)
Catch err As Exception
Console.WriteLine(err.ToString)
Return (String.Empty)
End Try
End Function In the previous function, the encrypted string is returned as a Base64-encoded string. Note the allowable key sizes for the
RijndaelManaged class. You can check the allowable key sizes using the following code:
Code:
Dim ks() As KeySizes
Dim RMCrypto As New RijndaelManaged
ks = RMCrypto.LegalKeySizes
'---print out the various key sizes---
Console.WriteLine(ks(0).MaxSize) ' 256
Console.WriteLine(ks(0).MinSize) ' 128
Console.WriteLine(ks(0).SkipSize) ' 64 The valid key sizes are: 16 bytes (128 bit), 24 bytes (128 bits + 64 bits), and 32 bytes (256 bits).
Also, you can get the system to generate a random key and IV (which you need to supply in the current example) automatically:
Code:
'---generate key---
RMCrypto.GenerateKey()
Dim key As Byte() = RMCrypto.Key
Console.WriteLine("Key : " & System.Convert.ToBase64String(key))
'---generate IV---
RMCrypto.GenerateIV()
Dim IV As Byte() = RMCrypto.IV
Console.WriteLine("IV : " & System.Convert.ToBase64String(IV)) If the IV is null when it is used, the GenerateIV() method is called automatically. Valid size for the IV is 16 bytes.
To decrypt a string encrypted using the RijndaelManaged class, you can use the following
SymmetricDecryption() function:
Code:
Private Function SymmetricDecryption( _
ByVal str As String, _
ByVal key As Byte(), _
ByVal IV As Byte()) _
As String
Try
Dim s As String
'---converts the encrypted string into a byte array---
Dim b As Byte() = System.Convert.FromBase64String(str)
'---converts the byte array into a memory stream for
' decryption---
Dim memStream As New MemoryStream(b)
Dim RMCrypto As New RijndaelManaged
Dim CryptStream As New CryptoStream(memStream, _
RMCrypto.CreateDecryptor(key, IV), _
CryptoStreamMode.Read)
'---decrypting the stream---
Dim SReader As New StreamReader(CryptStream)
s = SReader.ReadToEnd
'---converts the decrypted stream into a string---
s.ToString()
SReader.Close()
Return s
Catch err As Exception
Console.WriteLine(err.ToString)
Return String.Empty
End Try
End Function The following code snippet shows how to use the
SymmetricEncryption() and
SymmetricDecryption() functions to encrypt and decrypt a string:
Code:
'---encrypt the string---
Dim cipherText As String = _
SymmetricEncryption("This is a string", key, IV)
Console.WriteLine("Ciphertext: " & cipherText)
'---decrypt the string---
Console.WriteLine("Original string: " & _
SymmetricDecryption(cipherText, key, IV))