Reputation: 51
I'm trying to copy the encrypted contents of a text file into a memory stream and then decrypt and copy those contents into a new memory stream. When I reach the code where the copy occurs I get a Invalid Data error on debug.
This is the block of code I got:
Function DecryptFile(ByVal sInputFilename As String, ByVal sKey As String) As Byte()
Dim DES As New DESCryptoServiceProvider()
DES.Key() = ASCIIEncoding.ASCII.GetBytes(sKey)
DES.IV = ASCIIEncoding.ASCII.GetBytes(sKey)
Dim desdecrypt As ICryptoTransform = DES.CreateDecryptor()
Dim encryptedByteArray() As Byte
encryptedByteArray = File.ReadAllBytes(sInputFilename)
Dim encryptedMS As MemoryStream = New MemoryStream(encryptedByteArray)
Dim cryptostreamDecr As New CryptoStream(encryptedMS, desdecrypt, CryptoStreamMode.Read)
Dim decryptedMS As MemoryStream = New MemoryStream()
cryptostreamDecr.CopyTo(decryptedMS) 'Error occurs here
cryptostreamDecr.Close()
Return decryptedMS.ToArray()
End Function
I'm following examples I've found scattered around the web and from what I've read, this code should work...
May anyone explain to me what am I doing wrong?
Upvotes: 1
Views: 1272
Reputation: 32248
Here's an example to encrypt/decrypt a string and a file using a Key without explicitly providing an Initialization Vector (so yo don't need to store and retrieve it to decrypt encrypted data).
The Encryption provider I'm using here is TripleDESCryptoServiceProvider.
If you need to use a DES provider, it's exactly the same thing, you just need to change TripleDESCryptoServiceProvider
to DESCryptoServiceProvider.
But, as you can read in the Docs, better move to the AesCryptoServiceProvider, if/when possible.
The Initialization Vector (IV
) is calculated based on the Key specified and it's the same Hashed value if the Key to Decrypt the data is the same as the Key used to Encrypt it.
In this case, you lose some security, but you don't need to store either the Key or the IV
(if the Key is provided by a User, who's responsible for protecting the Key).
The Mode is left to its default: CipherMode.CBC
.
The Padding Mode to its default: PaddingMode.PKCS7
.
Encrypt and decrypt a sting to and from a Base64String:
Dim enc3Des As New TripleDesEncryptor("MyFancyKey")
Dim inputString = "Some fancy string to be encoded to a Base64 string"
Dim encodedB64 = enc3Des.EncryptStringToBase64(inputString)
Dim decoded64 = enc3Des.DecryptBase64String(encoded64)
To encrypt a file, provide the path to the Source file, then save the bytes returned by the Encryption method to a destination file:
Dim enc3Des As New TripleDesEncryptor("MyFancyKey")
Dim plainTextFilePath = [Source file Path]
Dim encryptedFilePath = [Encrypted file Path]
Dim encodedBytes = enc3Des.EncryptFile(plainTextFilePath)
File.WriteAllBytes(encryptedFilePath, encodedBytes)
You can of course decrypt the File when required, using the same Key:
Dim encryptedFilePath = [Encrypted file Path]
Dim decryptedFilePath = [Decrypted file Path]
Dim enc3Des2 As New TripleDesEncryptor("MyFancyKey")
Dim decodedBytes = enc3Des2.DecryptFile(encryptedFilePath)
File.WriteAllBytes(decryptedFilePath, decodedBytes)
The TripleDesEncryptor
helper class:
Imports System.IO
Imports System.Security.Cryptography
Imports System.Text
Public NotInheritable Class TripleDesEncryptor
Private tripleDesProvider As New TripleDESCryptoServiceProvider()
Sub New(key As String)
tripleDesProvider.Key = GetKeyHash(key, tripleDesProvider.LegalKeySizes(0).MaxSize \ 8)
tripleDesProvider.IV = GetKeyHash(key, tripleDesProvider.LegalBlockSizes(0).MaxSize \ 8)
End Sub
Public Function EncryptStringToBase64(inputString As String) As String
Dim dataBytes As Byte() = Encoding.Unicode.GetBytes(inputString)
Return Convert.ToBase64String(Encrypt(dataBytes))
End Function
Public Function EncryptFile(fileName As String) As Byte()
Dim dataBytes As Byte() = File.ReadAllBytes(fileName)
Return Encrypt(dataBytes)
End Function
Private Function Encrypt(dataBytes As Byte()) As Byte()
Using ms As New MemoryStream(),
encStream As New CryptoStream(ms, tripleDesProvider.CreateEncryptor(), CryptoStreamMode.Write)
encStream.Write(dataBytes, 0, dataBytes.Length)
encStream.FlushFinalBlock()
Return ms.ToArray()
End Using
End Function
Public Function DecryptBase64String(base64String As String) As String
Dim dataBytes As Byte() = Convert.FromBase64String(base64String)
Return Encoding.Unicode.GetString(Decrypt(dataBytes))
End Function
Public Function DecryptFile(fileName As String) As Byte()
Dim dataBytes As Byte() = File.ReadAllBytes(fileName)
Return Decrypt(dataBytes)
End Function
Private Function Decrypt(encryptedData As Byte()) As Byte()
Using ms As New MemoryStream(),
decStream As New CryptoStream(ms, tripleDesProvider.CreateDecryptor(), CryptoStreamMode.Write)
decStream.Write(encryptedData, 0, encryptedData.Length)
decStream.FlushFinalBlock()
Return ms.ToArray()
End Using
End Function
Private Function GetKeyHash(key As String, length As Integer) As Byte()
Using sha1 = SHA1.Create()
Dim varHash As Byte() = New Byte(length - 1) {}
Dim keyBytes As Byte() = Encoding.Unicode.GetBytes(key)
Dim hash As Byte() = sha1.ComputeHash(keyBytes).Take(length).ToArray()
Array.Copy(hash, 0, varHash, 0, hash.Length)
hash = Nothing
keyBytes = Nothing
Return varHash
End Using
End Function
End Class
Upvotes: 3
Reputation: 51
Perhaps I should have explained what I'm trying to achieve in the first place. I have a text file that has over 1000 keywords. The vb.net application will, at some point, read these keywords from the text file to do something with them. Now, my approach here is to not let prying eyes to edit the text file, changing the key words or even knowing which keywords are on it. Therefor, what I did was encrypt the keywords and save the encrypted content into a new file and deleted the unencrypted file, so that this way I don't need to care about people checking the encrypted file, because it's just gibberish.
According to Jimi's explanation, posted before, I see now that in order to decrypt the file, I need the same IV I used for encrypting the previous file.
So the only way I see for this to be possible without having an unencrypted file 'lying around' is to store the IV secret key within the application's settings, correct?
Upvotes: 0