Customising SaveFileDialog

rbulph

Junior Contributor
Joined
Feb 17, 2003
Messages
397
I'd like to add a button to the toolstrip in the Save File Dialog, to deal with password protection of files. For the print preview dialog I could do this quite easily by getting a reference to the toolstrip through the Controls property of the dialog. But there is no Controls property of the Save File Dialog. How would I go about this?
 
The simple answer is you can't alter the SafeFileDialog in the manner you suggest. The more complicated answer is that it is possible but its pretty complicated and requires a fair few p/invoke calls.
 
Cags said:
The simple answer is you can't alter the SafeFileDialog in the manner you suggest. The more complicated answer is that it is possible but its pretty complicated and requires a fair few p/invoke calls.
OK, thanks. I'll do this separately from the dialog box then.
 
I've got a problem with password protecting a file. When I use serialization to store the password with the other details of the file, anyone can then open the file with a text editor and the password is right in front of them. So I suppose I have to encode the password before saving it with the file and decode it when opening the file. Does VB provide any support for doing this or will I have to make up an algorithm myself?
 
If the file is password protected then not only should the password be protected, but the entire file should be encrypted. Look in the System.Security.Cryptography namespace. There are a few different encryption streams in there. I would strongly suggest that the entire file be run through an encryption stream.

You might want to hash the user's password and use that as the encryption key. Then you won't have to store the password in the file. If they give the right password, the file will be decrypted. If not, the file will fail to decrypt and an exception will be thrown.
 
If the file is password protected then not only should the password be protected, but the entire file should be encrypted. Look in the System.Security.Cryptography namespace. There are a few different encryption streams in there. I would strongly suggest that the entire file be run through an encryption stream.

You might want to hash the user's password and use that as the encryption key. Then you won't have to store the password in the file. If they give the right password, the file will be decrypted. If not, the file will fail to decrypt and an exception will be thrown.
Finally looking at this now (over two years later!). This seems to be what I need. I suppose I need to have a universal key for encrypting files in cases where the user has specified no password. If this key fails to decrypt the file then I know that I need to prompt the user for the password and try again with that.
 
I'm trying to use the KnowledgeBase article, but it's not working. The decrypted stream is empty. Can anyone see what I'm doing wrong?

Visual Basic:
Imports System.Runtime.Serialization.Formatters.Binary
Imports System.IO
Imports System.Math
Imports System.Security
Imports System.Security.Cryptography
Imports System.Runtime.InteropServices
Imports System.Text

Public Class Form1

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

        Dim j As New saveobject
        j.name = "Wally"
        j.ID = 145

        Dim ms As New MemoryStream

        With New BinaryFormatter
            .Serialize(ms, j)
        End With

        Dim s As String = "Qwertyui"

        EncryptFile(ms, "C:\TestFile.abc", s)

        ms.Flush()
        ms.Close()

        Dim fs As FileStream = New FileStream("C:\TestFile.abc", FileMode.Open, FileAccess.Read)
        Dim ms2 As MemoryStream = DecryptFile(fs, s)

        Dim k As saveobject

        With New BinaryFormatter
            k = .Deserialize(ms2)    'get an error here because ms2 is empty.
        End With

        Text = k.name

    End Sub

    Sub EncryptFile(ByVal sInputFile As MemoryStream, _
                      ByVal sOutputFilename As String, _
                      ByVal sKey As String)


        Dim fsEncrypted As New FileStream(sOutputFilename, _
                                    FileMode.Create, FileAccess.Write)

        Dim DES As New DESCryptoServiceProvider()

        'Set secret key for DES algorithm.
        'A 64-bit key and an IV are required for this provider.
        DES.Key = ASCIIEncoding.ASCII.GetBytes(sKey)

        'Set the initialization vector.
        DES.IV = ASCIIEncoding.ASCII.GetBytes(sKey)

        'Create the DES encryptor from this instance.
        Dim desencrypt As ICryptoTransform = DES.CreateEncryptor()
        'Create the crypto stream that transforms the file stream by using DES encryption.
        Dim cryptostream As New CryptoStream(fsEncrypted, _
                                            desencrypt, _
                                            CryptoStreamMode.Write)

        'Read the file text to the byte array.
        Dim bytearrayinput(sInputFile.Length - 1) As Byte
        sInputFile.Read(bytearrayinput, 0, bytearrayinput.Length)
        'Write out the DES encrypted file.
        cryptostream.Write(bytearrayinput, 0, bytearrayinput.Length)
        cryptostream.Flush()
        cryptostream.Close()

    End Sub

    Function DecryptFile(ByVal InputStream As FileStream, _
        ByVal sKey As String) As MemoryStream

        Dim DES As New DESCryptoServiceProvider()
        'A 64-bit key and an IV are required for this provider.
        'Set the secret key for the DES algorithm.
        DES.Key() = ASCIIEncoding.ASCII.GetBytes(sKey)
        'Set the initialization vector.
        DES.IV = ASCIIEncoding.ASCII.GetBytes(sKey)

        'Create the file stream to read the encrypted file back.
        '   Dim fsread As New FileStream(sInputFilename, FileMode.Open, FileAccess.Read)
        'Create the DES decryptor from the DES instance.
        Dim desdecrypt As ICryptoTransform = DES.CreateDecryptor()
        'Create the crypto stream set to read and to do a DES decryption transform on incoming bytes.
        Dim cryptostreamDecr As New CryptoStream(InputStream, desdecrypt, CryptoStreamMode.Read)
        'Print out the contents of the decrypted file.
        Dim OutputMemoryStream As New MemoryStream
        Dim fsDecrypted As New StreamWriter(OutputMemoryStream)
        fsDecrypted.Write(New StreamReader(cryptostreamDecr).ReadToEnd)
        InputStream.Flush()
        InputStream.Close()
        Return OutputMemoryStream   'Problem - this is empty!

    End Function

End Class

<Serializable()> Friend Class saveobject
    Friend name As String
    Friend ID As Integer
End Class
 
If the file is password protected then not only should the password be protected, but the entire file should be encrypted. Look in the System.Security.Cryptography namespace. There are a few different encryption streams in there. I would strongly suggest that the entire file be run through an encryption stream.

You might want to hash the user's password and use that as the encryption key. Then you won't have to store the password in the file. If they give the right password, the file will be decrypted. If not, the file will fail to decrypt and an exception will be thrown.

I've got this working now, using the code here . But regarding what you're saying about using the user's password as the key, the Key for the DESCryptoServiceProvider has to be eight characters long, so I would have problems storing the user's password there unless I restricted him to having passwords of this length. But I think that I probably don't want to use a standard key for all my files either, since then anyone who got hold of that would be able to open all password protected files relating to my programme. So maybe I should just use the first eight letters of the user's password, padded out if necessary, and in addition store the whole password in the file.

I'll also have the possibility of a password for modifying files. It seems that having the correct Initialisation Vector is not critical for decrypting files, so I can't store it there. Short of double encrypting files I think I will have to store this in the file. But security for this is not so important so that seems alright.
 
Back
Top