There are about 100,000 different possible ways to encrypt a string. Using standards like AES, CBC, and PKCS7 make things easier – but there are still problems with IVs. Salts, Encoding, etc. (As noted on http://www.Crypto.Stackexchange.com)
For my iOS project (Obj-C), I’m using the FBEncryptor project which is an easy and well documented way to encrypt strings. However, I need code that will be able to decrypt that iOS AES string generated by FBEncryptor on a Windows platform – preferably VB.NET.
I have yet to find another project for VB.NET that is compatible with FBEncryptor.
Does anyone know of any VB.NET encryption projects that work with FBEncryptor? If not, then what do I need to do to make the Rijndael Managed library (provided by Microsoft) work with FBEncryptor?
My VB.NET Code using Rijndael Managed:
Imports System.Security
Imports System.Security.Cryptography
Imports System.IO
Imports System.Runtime.InteropServices
Imports System.Text.RegularExpressions
Imports System.Text
Module Encrypt2
Public saltBytes As Byte()
Dim hashAlgorithm As String = "SHA1"
Public Sub GenerateSalt()
' Define min and max salt sizes.
Dim minSaltSize As Integer
Dim maxSaltSize As Integer
minSaltSize = 8
maxSaltSize = 8
' Generate a random number for the size of the salt.
Dim random As Random
random = New Random()
Dim saltSize As Integer
saltSize = random.Next(minSaltSize, maxSaltSize)
' Allocate a byte array, which will hold the salt.
saltBytes = New Byte(saltSize - 1) {}
' Initialize a random number generator.
Dim rng As RNGCryptoServiceProvider
rng = New RNGCryptoServiceProvider()
' Fill the salt with cryptographically strong byte values.
rng.GetNonZeroBytes(saltBytes)
End Sub
Public Function Encrypt(ByVal plainText As String, ByVal keyword As String) As String
Dim hashAlgorithm As String = "SHA1"
Dim passwordIterations As Integer = 128
Dim initVector As String = "@7781157e2629b09"
Dim keySize As Integer = 256
Dim initVectorBytes As Byte() = Encoding.ASCII.GetBytes(initVector)
Dim plainTextBytes As Byte() = Encoding.ASCII.GetBytes(plainText)
GenerateSalt()
Dim password As New Rfc2898DeriveBytes(keyword, saltBytes, passwordIterations)
Dim keyBytes As Byte() = password.GetBytes(keySize \ 8)
Dim symmetricKey As New RijndaelManaged()
symmetricKey.Mode = CipherMode.CBC
Dim encryptor As ICryptoTransform = symmetricKey.CreateEncryptor(keyBytes, initVectorBytes)
Dim memoryStream As New MemoryStream()
Dim cryptoStream As New CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write)
cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length)
cryptoStream.FlushFinalBlock()
Dim cipherTextBytes As Byte() = memoryStream.ToArray()
memoryStream.Close()
cryptoStream.Clear()
Dim cipherText As String = Convert.ToBase64String(cipherTextBytes)
Return (cipherText)
End Function
Public Function Decrypt(ByVal cipherText As String, ByVal keyword As String) As String
Dim hashAlgorithm As String = "SHA1"
Dim passwordIterations As Integer = 128
Dim initVector As String = "@7781157e2629b09"
Dim keySize As Integer = 256
' Convert strings defining encryption key characteristics into Byte
' arrays. Let us assume that strings only contain ASCII codes.
' If strings include Unicode characters, use Unicode, UTF7, or UTF8
' encoding
Dim initVectorBytes As Byte() = Encoding.ASCII.GetBytes(initVector)
' Convert the Ciphertext into a Byte array
Dim cipherTextBytes As Byte() = Encoding.ASCII.GetBytes(cipherText)
' First we must create a password, from which the key will be
' derived. This password will be generated from the specified
' passphrase and salt value. The password will be created using
' the specified hash algorithm. Password creation can be done in
' several iterations
GenerateSalt()
Dim password As New Rfc2898DeriveBytes(keyword, saltBytes, passwordIterations)
' Use the password to generate pseudo-random bytes for the encryption
' key. Specify the size of the key in bytes (instead of bits)
Dim keyBytes As Byte() = password.GetBytes(keySize \ 8)
' Create uninitialized Rijndael encryption object
Dim symmetricKey As New RijndaelManaged()
' It is reasonable to set encryption mode to Cipher Block Chaining
' (CBC). Use default options for other symmetric key parameters.
symmetricKey.Mode = CipherMode.CBC
' Generate decryptor from the existing key bytes and initialization
' vector. Key size will be defined based on the number of the key
'bytes
Dim decryptor As ICryptoTransform = symmetricKey.CreateDecryptor(keyBytes, initVectorBytes)
' Define memory stream which will be used to hold encrypted data.
Dim memoryStream As New MemoryStream(cipherTextBytes)
' Define cryptographic stream (always user Read mode for encryption).
Dim cryptoStream As New CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read)
' Since at this point we don't know what the size of decrypted data
' will be, allocate the buffer long enough to hold ciphertext;
' plaintext is never longer than ciphertext
Dim plainTextBytes As Byte() = New Byte(cipherTextBytes.Length - 1) {}
' Start decrypting.
Dim decryptedByteCount As Integer = cryptoStream.Read(plainTextBytes, 0, plainTextBytes.Length)
' Close both streams
memoryStream.Close()
cryptoStream.Close()
' Convert decrypted data into a string
' Let us assume that the original plaintext string was UTF8-Encoded.
Dim plainText As String = Encoding.UTF8.GetString(plainTextBytes, 0, decryptedByteCount)
' Return the decrypted string
Return (plainText)
End Function
End Module
You’ll notice that the IV is static and that the password iterations are low. This is because I’m not sure how to generate the IV in the same method as FBEncryptor. You may also notice that when attempting to decrypt, there are problems with the byte length.
Any help will be appreciated! Thanks!
One note. I looked in FBEncryptor. It uses some bad practices. So, if security is important for you I would recommend read up a little bit more regarding that and choose another code which does encryption (or write it on your own).
FBEncryptor does following for encryption
a) Convert string to byte array (based on UTF8 encoding)
b) Convert key to byte array (based on UTF encoding).
c) Copy only first 16 bytes of key
d) Create IV which is 16 butes of 0x00
e) Encrypt byte array from item a) using AES/CBC/PKCS7Padding with IV created in d)
f) The resulting encrypted data is converted to Base64
And it does following for decryption
a) Convert encrypt string from Base64 to byte array
b) Convert key to byte array (based on UTF encoding).
c) Copy only first 16 bytes of key
d) Create IV which is 16 butes of 0x00
e) Decrypt byte array from item a) using AES/CBC/PKCS7Padding with IV created in d)
f) Convert encrypted data from e) to a string using UTF8 encoding
You should do exactly the same thing in VB.NET. I think you have almost all parts
– You will need to drop all SHA1 and salt related stuff and use equivalent of step b).
And you will need to research PKCS7Padding for VB.NET