The code below is the latest iteration in an attempt to build a simple encryption/decryption utility for an in-house project. I'm hoping it's something very silly that I'm simply too far into a trench to see.
It's in .Net 4.7 and I've tried to organise it to make it impossible to accidentally have different keys or options occurring during the process. The code should on Linqpad.
Some things I've tried are listed in the TODOs though I've not document all the daft variations I found today.
If anyone else can make it run on Linqpad or Visual studio 2017, I'd be very keen to learn what I am missing here.
Thanks for any advice!
'Linqpad version - should offer to import System.Security.Cryptography
'I'm on .net 4.7 in my main project hence the Tuple setup below.
Dim Testphrase = "Whatever is happening, nothing I google works!"
Sub Main
Dim encrypted = EncryptString(Testphrase, "Password")
Dim Decrypted = DecryptString(encrypted, "Password")
Decrypted.Dump
End Sub
Private Shared AesManaged As AesManaged
Private Shared password As Rfc2898DeriveBytes
'''Makes sure that I use the same parameters both sides of the equation
Private Shared Function GetCryptBits(passphrase As String) As (passwords As Rfc2898DeriveBytes, AesManaged As AesManaged)
If AesManaged Isnot Nothing Then Return (password, AesManaged) 'TODO: Don't rebuild this if you've already got it.
password = New Rfc2898DeriveBytes(passphrase, Encoding.UTF8.GetBytes("SaltBytes"))
AesManaged = New AesManaged() With {.Mode = CipherMode.CBC,
.Padding = PaddingMode.PKCS7,
.BlockSize = 128, .KeySize = 256} 'TODO: I've tried all the padding choices here.TODO: Have tried RijndaelManaged
AesManaged.IV = password.GetBytes(AesManaged.BlockSize / 8)
AesManaged.Key = password.GetBytes(AesManaged.KeySize / 8)
Return (password, AesManaged)
End Function
'Encrypt
Public Shared Function EncryptString(plainText As String, passPhrase As String) As String
Dim B = GetCryptBits(passPhrase)
With B
Dim plainTextBytes As Byte() = Encoding.UTF8.GetBytes(plainText) 'TODO: Where you see UTF8 I've also tried with Unicode
Dim encryptor As ICryptoTransform = B.AesManaged.CreateEncryptor(B.AesManaged.Key, B.AesManaged.IV)
Using MemoryStream As New MemoryStream()
Using CryptoStream As New CryptoStream(MemoryStream, encryptor, CryptoStreamMode.Write)
CryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length)
CryptoStream.FlushFinalBlock()
Dim cipherTextBytes As Byte() = MemoryStream.ToArray()
AesManaged.clear
Return Convert.ToBase64String(cipherTextBytes)
MemoryStream.Close()
CryptoStream.Close()
End Using
End Using
End With
End Function
'Decrypt
Public Shared Function DecryptString(cipherText As String, passPhrase As String) As String
Dim B = GetCryptBits(passPhrase)
With B
Dim cipherTextBytes As Byte() = Convert.FromBase64String(cipherText)
Dim decryptor As ICryptoTransform = B.AesManaged.CreateDecryptor(B.AesManaged.Key, B.AesManaged.IV)
Using MemoryStream As New MemoryStream
Using CryptoStream As New CryptoStream(MemoryStream, decryptor, CryptoStreamMode.Read)
Dim plainTextBytes As Byte() = New Byte(cipherTextBytes.Length - 1) {}
Dim decryptedByteCount As Integer = CryptoStream.Read(plainTextBytes, 0, plainTextBytes.Length) 'TODO: Here I'm getting "Padding is invalid and cannot be removed."
Return Encoding.UTF8.GetString(plainTextBytes, 0, decryptedByteCount)
End Using
End Using
End With
End Function