Recipe 16.2. Encrypting and Decrypting a String


Problem

You want to encrypt and later decrypt a string using a private key.

Solution

Sample code folder: Chapter 16\Cryptography

Use the StringEncrypt() and StringDecrypt() functions, presented in this recipe, which wrap calls to a cryptography services provider in the .NET Framework.

Discussion

The StringEncrypt() function processes a plain-text string using a key string and returns a Base64 (MIME) string. This string can be deciphered only by passing it back to the StringDecrypt() function, along with the same key string. The returned Base64 string is comprised of viewable and printable ASCII characters and is suitable for printing, emailing, and storing in standard text files. We'll look at the StringEncrypt() function first:

 Public Function StringEncrypt(ByVal plainText As String, _       ByVal keyText As String) As String    ' ----- Encrypt some text. Return an empty string    '       if there are any problems.    Try       ' ----- Remove any possible null characters.       Dim workText As String = plainText.Replace(vbNullChar, "")       ' ----- Convert plain text to byte array.       Dim workBytes( ) As Byte = Encoding.UTF8.GetBytes(plainText)       ' ----- Convert key string to 32-byte key array.       Dim keyBytes( ) As Byte = _          Encoding.UTF8.GetBytes(GetHash(keyText))       ' ----- Create initialization vector.       Dim IV( ) As Byte = { _          50, 199, 10, 159, 132, 55, 236, 189, _          51, 243, 244, 91, 17, 136, 39, 230}       ' ----- Create the Rijndael engine.       Dim rijndael As New RijndaelManaged       ' ----- Bytes will flow through a memory stream.       Dim memoryStream As New MemoryStream( )       ' ----- Create the cryptography transform.       Dim cryptoTransform As ICryptoTransform       cryptoTransform = _          rijndael.CreateEncryptor(keyBytes, IV)       ' ----- Bytes will be processed by CryptoStream.       Dim cryptoStream As New CryptoStream( _          memoryStream, cryptoTransform, _          CryptoStreamMode.Write)       ' ----- Move the bytes through the processing stream.       cryptoStream.Write(workBytes, 0, workBytes.Length)       cryptoStream.FlushFinalBlock( )       ' ----- Convert binary data to a viewable string.       Dim encrypted As String = _          Convert.ToBase64String(memoryStream.ToArray)       ' ----- Close the streams.       memoryStream.Close( )       cryptoStream.Close( )       ' ----- Return the encrypted string result.       Return encrypted    Catch       Return ""    End Try End Function 

The RijndaelManaged object was chosen for the encryption algorithm, but you may substitute any of the other encryption engines provided in the .NET Framework, such as Triple DES. The Rijndael algorithm was chosen because it is one of the latest and strongest algorithms around. Also known as the Advanced Encryption Algorithm ( AES), it survived intense scrutiny by experts in the industry to become the algorithm the government selected to replace the older Data Encryption Standard (DES) algorithm. It's standard, and it's good.

The StringDecrypt() function is similar to StringEncrypt(), except that the encrypted Base64 string is passed to it along with the same key string as used before, and the original plain-text result is returned:

 Public Function StringDecrypt(ByVal encrypted As String, _       ByVal keyText As String) As String    ' ----- Decrypt a previously encrypted string. The key    '       must match the one used to encrypt the string.    '       Return an empty string on error.    Try       ' ----- Convert encrypted string to a byte array.       Dim workBytes( ) As Byte = _          Convert.FromBase64String(encrypted)       ' ----- Convert key string to 32-byte key array.       Dim keyBytes( ) As Byte = _          Encoding.UTF8.GetBytes(GetHash(keyText))       ' ----- Create initialization vector.       Dim IV( ) As Byte = { _         50, 199, 10, 159, 132, 55, 236, 189, _         51, 243, 244, 91, 17, 136, 39, 230}       ' ----- Decrypted bytes will be stored in       '       a temporary array.       Dim tempBytes(workBytes.Length - 1) As Byte       ' ----- Create the Rijndael engine.       Dim rijndael As New RijndaelManaged       ' ----- Bytes will flow through a memory stream.       Dim memoryStream As New MemoryStream(workBytes)       ' ----- Create the cryptography transform.       Dim cryptoTransform As ICryptoTransform       cryptoTransform = _          rijndael.CreateDecryptor(keyBytes, IV)       ' ----- Bytes will be processed by CryptoStream.       Dim cryptoStream As New CryptoStream( _          memoryStream, cryptoTransform, _          CryptoStreamMode.Read)       ' ----- Move the bytes through the processing stream.       cryptoStream.Read(tempBytes, 0, tempBytes.Length)       ' ----- Close the streams.       memoryStream.Close( )       cryptoStream.Close( )       ' ----- Convert the decrypted bytes to a string.       Dim plainText As String = _          Encoding.UTF8.GetString(tempBytes)       ' ----- Return the decrypted string result.       Return plainText.Replace(vbNullChar, "")    Catch       Return ""    End Try End Function 

Notice that the same initialization vector is used in both functions. This is the actual "secret key" you use to encrypt the content. You can use other sets of bytes to initialize the IV() array, but both the StringEncrypt() and StringDecrypt() functions should use exactly the same values.

The Rijndael encryption object expects an array of 32bytes as the key. The GetHash() function presented in Recipe 16.1 makes it easy to convert any key string to a 32-byte key suitable for the encryption. The values of the key bytes in this case vary only over a range of 16 unique values each, but there still are more than 3 x 1038 possible key combinations. Generally, any unique key string always generates a unique 32-byte hash value as a key, and a brute-force attack based on checking all possible keys generated by GetHash() is, based on today's technology, out of the question.

The following code demonstrates calling the StringEncrypt() and StringDecrypt() functions:

 Dim result As New System.Text.StringBuilder Dim workText As String = _    "The important thing is not to stop questioning. " & _    "--Albert Einstein" Dim keyString As String = "This string is the key" Dim encrypted As String = StringEncrypt(workText, keyString) Dim decrypted As String = StringDecrypt(encrypted, keyString) result.Append("Plain Text: ") result.AppendLine(workText) result.AppendLine( ) result.Append("Encrypted: ") result.AppendLine(encrypted) result.AppendLine( ) result.Append("Decrypted: ") result.Append(decrypted) MsgBox(result.ToString( )) 

The original plain-text string is encrypted and then decrypted using the same key string. The results of each step are displayed in Figure 16-2.

Figure 16-2. Encrypting a string with the AES algorithm


See Also

Recipe 16.9 includes the full source code for the Crypto module.




Visual Basic 2005 Cookbook(c) Solutions for VB 2005 Programmers
Visual Basic 2005 Cookbook: Solutions for VB 2005 Programmers (Cookbooks (OReilly))
ISBN: 0596101775
EAN: 2147483647
Year: 2006
Pages: 400

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net