none
DESCryptoServiceProvider can't properly encrypt then decrypt some characters RRS feed

  • Question

  • If I encrypt a file that has extended ASCII (or, perhaps some Unicode) characters (such as the plus-minus sign "±" (hex: B1)), the decryption process replaces the characters with "�" (the UTF-8 "replacement character").

    The encryption/decryption was done using the Module1 module located here: http://support.microsoft.com/kb/301070

    We have found quite a few other characters that decrypt to the replacement character but, because we don't have the original, unencrypted version of the files, it is hard to say which characters they are exactly. I can say the interpunct (the multiplication sign that looks like a dot) and probably some types of single and double quotes appear to decrypt as replacement characters as well.

    To test: Create a file with a single ± (plus-minus sign) in it. Encrypt and decrypt using Module1 here: http://support.microsoft.com/kb/301070

    You should end up with a single replacement character in your decrypted file.

    Thanks in advanced for any help you can provide us.

    Note: I'm using Windows 7

    C:\temp>ver
    Microsoft Windows [Version 6.1.7600]

    Thursday, July 19, 2012 9:12 PM

Answers

  • First, I'm very grateful for your insight and willingness to look into this.

    Yes, you are correct. I basically took out all the references to fsDecrypted and replaced them with this code:

          
            Dim fsout As New FileStream(outfile, FileMode.OpenOrCreate, FileAccess.Write)
    
            Dim bs(4096) As Byte
            Dim read As Integer
    
            While True
                read = cryptostreamDecr.Read(bs, 0, bs.Length)
                If read = 0 Then Exit While
                fsout.Write(bs, 0, read)
            End While

    This works also:

        Dim fsout As New FileStream(outfile, FileMode.OpenOrCreate, FileAccess.Write)
        cryptostreamDecr.CopyTo(fsout)

    Thanks again.


    Friday, July 20, 2012 6:27 PM

All replies

  • The problem has nothing to do with DESCryptoServiceProvider: the DES algorithm works on raw bytes, not characters, so it's completely unaware of encoding and such.

    The issue is in the DecryptFile method, and specifically in the line:

    fsDecrypted.Write(New StreamReader(cryptostreamDecr).ReadToEnd)
    

    This line creates a StreamReader around the CryptoStream, and calls the ReadToEnd method. The default encoding of a StreamReader is UTF-8, and that's what gets used to convert the bytes from the CryptoStream into a string. Since 0xB1 isn't a valid sequence in UTF-8, the StreamReader replaces it with the "replacement character" and that's what gets written to the StreamWriter (which also defaults to UTF-8, but that's immaterial).

    You can specify the encoding in the StreamReader constructor, of course, but I wouldn't advise it in this particular case. You should rather write a DecryptFile method that doesn't attempt to convert the bytes to text at all: that's better left to the methods, or application, that will open the file later.

    You can just adapt what EncryptFile does already (it reads blocks of bytes off the input stream and writes them to the CryptoStream: your method needs to read blocks of bytes off the CryptoStream and write them to the output stream). This is especially easy to do in .NET 4, since it includes the Stream.CopyTo method.

    HTH
    --mc

    Thursday, July 19, 2012 10:46 PM
  • First, I'm very grateful for your insight and willingness to look into this.

    Yes, you are correct. I basically took out all the references to fsDecrypted and replaced them with this code:

          
            Dim fsout As New FileStream(outfile, FileMode.OpenOrCreate, FileAccess.Write)
    
            Dim bs(4096) As Byte
            Dim read As Integer
    
            While True
                read = cryptostreamDecr.Read(bs, 0, bs.Length)
                If read = 0 Then Exit While
                fsout.Write(bs, 0, read)
            End While

    This works also:

        Dim fsout As New FileStream(outfile, FileMode.OpenOrCreate, FileAccess.Write)
        cryptostreamDecr.CopyTo(fsout)

    Thanks again.


    Friday, July 20, 2012 6:27 PM