Question

I have a program in which I write and read configuration files. When I write, I encrypt the whole file using the RijndaelManaged object in vb.net, and when I read I decrypt using the same value for the key and init vector.

It all work fine on my development machine and on many others. However, some PC can't encrypt/decrypt files using the same program.

is there anything in this encryption object that prevent it and what would you recommend using instead ?

Thanks

Edit : here is the code I use to encrypt and decrypt : From what I can see, if I encrypt bytes from my main machine, I can decypt it from any PC. However, if I encrypt bytes from my other PC, I cannot decrypt it from any PC. Also, when I looked at the content of the files, they don't look the same at all. Note that the usual way I go around is I create a memorystream from the file (which is usually XML) and I encrypt/decrypt.

Public Shared Function EncryptBytes(ByVal strContenu() As Byte, ByVal initVectorBytes() As Byte, ByVal saltValueBytes() As Byte) As Byte()

    ' Convert our plaintext into a byte array.
    ' Let us assume that plaintext contains UTF8-encoded characters.
    Dim plainTextBytes As Byte() = strContenu
    'plainTextBytes = System.Text.Encoding.Unicode.GetBytes(strMessage)

    Dim strPassPhrase As String = "d%6&?76dhd8?532LDhds8!7?&?8&?dhcv77"

    Dim strHashAlgorithm As String = "SHA1"

    Dim intPswdIterations As Integer = 2

    ' 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.
    Dim password As PasswordDeriveBytes
    password = New PasswordDeriveBytes(strPassPhrase, _
                                       saltValueBytes, _
                                       strHashAlgorithm, _
                                       intPswdIterations)

    ' 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()
    keyBytes = password.GetBytes(32)

    ' Create uninitialized Rijndael encryption object.
    Dim symmetricKey As RijndaelManaged
    symmetricKey = 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 encryptor from the existing key bytes and initialization 
    ' vector. Key size will be defined based on the number of the key 
    ' bytes.
    Dim encryptor As ICryptoTransform
    encryptor = symmetricKey.CreateEncryptor(keyBytes, initVectorBytes)

    ' Define memory stream which will be used to hold encrypted data.
    Dim memoryStream As System.IO.MemoryStream
    memoryStream = New System.IO.MemoryStream()

    ' Define cryptographic stream (always use Write mode for encryption).
    Dim cryptoStream As CryptoStream
    cryptoStream = New CryptoStream(memoryStream, _
                                    encryptor, _
                                    CryptoStreamMode.Write)
    ' Start encrypting.
    cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length)

    ' Finish encrypting.
    cryptoStream.FlushFinalBlock()

    ' Convert our encrypted data from a memory stream into a byte array.
    Dim cipherTextBytes As Byte()
    cipherTextBytes = memoryStream.ToArray()

    ' Close both streams.
    memoryStream.Close()
    cryptoStream.Close()

    ' Convert encrypted data into a base64-encoded string.
    'Dim cipherText As String
    'cipherText = 
    Return cipherTextBytes

    ' Return encrypted string.
    'Return cipherText

End Function

Public Shared Function DecryptBytes(ByVal strContenuEncrypte() As Byte, ByVal initVectorBytes() As Byte, ByVal saltValueBytes() As Byte) As Byte()

    ' 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.

    ' Convert our ciphertext into a byte array.
    Dim cipherTextBytes As Byte() = strContenuEncrypte

    Dim strPassPhrase As String = "d%6&?76dhd8DSDhds8!7?&?8&?dhcv77"

    Dim strHashAlgorithm As String = "SHA1"

    Dim intPswdIterations As Integer = 2

    ' 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.
    Dim password As PasswordDeriveBytes
    password = New PasswordDeriveBytes(strPassPhrase, _
                                       saltValueBytes, _
                                       strHashAlgorithm, _
                                       intPswdIterations)

    ' 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()
    keyBytes = password.GetBytes(32)

    ' Create uninitialized Rijndael encryption object.
    Dim symmetricKey As RijndaelManaged
    symmetricKey = 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
    decryptor = symmetricKey.CreateDecryptor(keyBytes, initVectorBytes)

    ' Define memory stream which will be used to hold encrypted data.
    Dim memoryStream As System.IO.MemoryStream
    memoryStream = New System.IO.MemoryStream(cipherTextBytes)

    ' Define memory stream which will be used to hold encrypted data.
    Dim cryptoStream As CryptoStream
    cryptoStream = 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()
    ReDim plainTextBytes(cipherTextBytes.Length)

    ' Start decrypting.
    Dim decryptedByteCount As Integer
    decryptedByteCount = 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
    plainText = System.Text.Encoding.Unicode.GetString(plainTextBytes, _
                                        0, _
                                        decryptedByteCount)

    ' Return decrypted string.
    Return plainTextBytes


End Function
Was it helpful?

Solution

If you are using Mono instead of the normal .NET as runtime, then PasswordDeriveBytes will fail for any output higher than 20. PasswordDeriveBytes uses an unknown, proprietary, non-deterministic, broken, cryptographically insecure method when more output is requested than the hash output can provide within PasswordDeriveBytes. This has been marked as no-fix by the Mono developers..

The best thing to do is to upgrade to Rfc2898DeriveBytes, which implements PBKDF2 instead of PBKDF1. The PBKDF2 defines how to extend the amount of output so all implementations should behave as specified.

If you require more output than that the hash function provides then it is however more secure to use a KBKDF such as HKDF over the output of PBKDF2. PKBDF2 requires another full set of rounds to create more data, and this may favor the attacker instead of the normal user and will double or triple the CPU load depending on how much bytes are requested.

[EDIT]

Also note that the constructor of PasswordDeriveBytes that takes a password string does not specify the character encoding that is to be used, so you are better off converting it into bytes before feeding it to the constructor.

According to most observations both seem to use UTF-8 though - beware that other runtimes (such as Java) may differ in this regard.

OTHER TIPS

A wild guess: are you writing and reading the files in text-mode? When the encrypted data happens to include a 0x1A (EOF, ctrl-z) reading may stop prematurely and you decrypt to few bytes.

You cant upload a 120Gb file to a byte(). Or you have some crazy machine. Try upload Byte to Byte in Ram

Dim fStream As FileStream = New FileStream("Encrypted.Encrypted", FileMode.Create)
        Dim cryptoStream As New CryptoStream(fStream, Encryptor, CryptoStreamMode.Write)
        Using UploadFile As FileStream = New FileStream(OpenfileDialog.FileName, FileMode.Open)
            For i = 0 To UploadFile.Length - 1
                Dim NewByte As New Byte
                NewByte = UploadFile.ReadByte
                cryptoStream.WriteByte(NewByte)
            Next
        End Using

        cryptoStream.FlushFinalBlock()
        cryptoStream.Close()
        fStream.Close()
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top