none
How to embed text file RRS feed

  • Question

  • Hello, i am using Visual Studio 2017 and Visual Basic.net. In my project i have Config.txt file (simple text file). File holds various application configuration data, also user password. File must be read and written at the run time. Because of the password i do not want that anybody could easy read that file in C:/Program files/My Application..  directory. I do not need super-duper protection for that file. I have tried various file build types for this file: resource, embedded resource, content etc. But i could not find the right path to this file after the application is installed. So which build type i must select and how to find the path to this file in order my application could access this file after installation?
    Saturday, October 28, 2017 10:14 PM

Answers

  • Hello, i am using Visual Studio 2017 and Visual Basic.net. In my project i have Config.txt file (simple text file). File holds various application configuration data, also user password.

    I'd like to add that it's customary to NOT save a password; set up a routine that will generate a hash of the password (sometimes using "salt") and save that.

    When a user enters a password, run it through that same routine and compare the saved hash (string) to the one generated to know whether or not it's correct.

    Given that, since the hash is one-way only (ergo, you can't get the password back by using the hash), it's harmless if it's found.

    That's not to say that I don't think encryption is worthwhile but I figured I'd add that.

    Also: Do you obfuscate the code?

    If you don't then it's still wide open even with the encryption method that I showed yesterday. The reason is because the encryption key (string) is in the code then you've effectively handed someone the lock and the key and hope they can't figure out how to fit them together. ;-)


    "A problem well stated is a problem half solved.” - Charles F. Kettering


    • Edited by Frank L. Smith Sunday, October 29, 2017 10:52 AM ...typo
    • Marked as answer by ecka3333 Sunday, October 29, 2017 11:10 AM
    Sunday, October 29, 2017 10:52 AM

All replies

  • Hello, i am using Visual Studio 2017 and Visual Basic.net. In my project i have Config.txt file (simple text file). File holds various application configuration data, also user password. File must be read and written at the run time. Because of the password i do not want that anybody could easy read that file in C:/Program files/My Application..  directory. I do not need super-duper protection for that file. I have tried various file build types for this file: resource, embedded resource, content etc. But i could not find the right path to this file after the application is installed. So which build type i must select and how to find the path to this file in order my application could access this file after installation?

    Other than the password being "wide-open", Application Settings fits the bill perfectly so unless you want to roll your own (I'll show you how if so), I think it's a good choice.

    As for what to store, use encryption. Have it store the encrypted value and on the way in, decrypt it:

    Based on: https://msdn.microsoft.com/en-us/library/ms172831.aspx
    
    Public NotInheritable Class Simple3Des
        Implements IDisposable
    
        Private TripleDes As New Security.Cryptography.TripleDESCryptoServiceProvider
    
        Sub New(ByVal key As String)
            ' Initialize the crypto provider.
            TripleDes.Key = TruncateHash(key, TripleDes.KeySize \ 8)
            TripleDes.IV = TruncateHash("", TripleDes.BlockSize \ 8)
        End Sub
    
        Public Function EncryptData(ByVal plaintext As String) _
            As String
    
            ' Convert the plaintext string to a byte array. 
            Dim plaintextBytes() As Byte = _
                System.Text.Encoding.Unicode.GetBytes(plaintext)
    
            ' Create the stream. 
            Dim ms As New System.IO.MemoryStream
            ' Create the encoder to write to the stream. 
            Dim encStream As New Security.Cryptography.CryptoStream(ms, _
                TripleDes.CreateEncryptor(), _
                System.Security.Cryptography.CryptoStreamMode.Write)
    
            ' Use the crypto stream to write the byte array to the stream.
            encStream.Write(plaintextBytes, 0, plaintextBytes.Length)
            encStream.FlushFinalBlock()
    
            ' Convert the encrypted stream to a printable string. 
            Return Convert.ToBase64String(ms.ToArray)
        End Function
    
        Public Function DecryptData(ByVal encryptedtext As String) _
            As String
    
            ' Convert the encrypted text string to a byte array. 
            Dim encryptedBytes() As Byte = Convert.FromBase64String(encryptedtext)
    
            ' Create the stream. 
            Dim ms As New System.IO.MemoryStream
            ' Create the decoder to write to the stream. 
            Dim decStream As New Security.Cryptography.CryptoStream(ms, _
                TripleDes.CreateDecryptor(), _
                System.Security.Cryptography.CryptoStreamMode.Write)
    
            ' Use the crypto stream to write the byte array to the stream.
            decStream.Write(encryptedBytes, 0, encryptedBytes.Length)
            decStream.FlushFinalBlock()
    
            ' Convert the plaintext stream to a string. 
            Return System.Text.Encoding.Unicode.GetString(ms.ToArray)
        End Function
    
        Private Function TruncateHash(ByVal key As String, _
                                      ByVal length As Integer) _
                                      As Byte()
    
            Dim sha1 As New Security.Cryptography.SHA1CryptoServiceProvider
    
            ' Hash the key. 
            Dim keyBytes() As Byte = _
                System.Text.Encoding.Unicode.GetBytes(key)
            Dim hash() As Byte = sha1.ComputeHash(keyBytes)
    
            ' Truncate or pad the hash. 
            ReDim Preserve hash(length - 1)
            Return hash
        End Function
    
        Public Sub Dispose() Implements IDisposable.Dispose
            If TripleDes IsNot Nothing Then
                TripleDes.Dispose()
                TripleDes = Nothing
            End If
        End Sub
    End Class
    


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Saturday, October 28, 2017 10:47 PM
  • Hi ecka3333,

    You can find the path of your application after its installation.
    Dim appPath As String = _
        System.Reflection.Assembly.GetExecutingAssembly().Location

    You can save user password in Settings of your project, not in a text file.
        
    The above sample shows form location, form size, folder path and so on.
    My code reading/writing Settings:
        ' --- 設定の読み込み(最小化対応)
        Public Sub prc_Read_MySettings()
            ' --- frm_Main 位置
            If (My.Settings.frm_Main_Location.X <= 0) Then
                frm_Main.StartPosition = FormStartPosition.CenterScreen
            Else
                frm_Main.Location = New Point(My.Settings.frm_Main_Location)
            End If
            ' --- frm_Main サイズ
            If (My.Settings.frm_Main_Size.Height < 100) Then
                frm_Main.Size = frm_Main.MinimumSize
            Else
                frm_Main.Size = New Size(My.Settings.frm_Main_Size)
            End If
        End Sub
        ' --- 設定の書き込み(最小化対応)
        Public Sub prc_Write_MySettings()
            If (frm_Main.WindowState = FormWindowState.Minimized) Then
                My.Settings.frm_Main_Location = New Point(100, 100)
                My.Settings.frm_Main_Size = frm_Main.MinimumSize
            Else
                My.Settings.frm_Main_Location = frm_Main.Location
                My.Settings.frm_Main_Size = frm_Main.Size
            End If
            ' ---
            If (frm_Search.Visible) Then
                If (frm_Search.chk_AutoShow.Checked = True) Then
                    My.Settings.frm_Search_AutoShow = True
                Else
                    My.Settings.frm_Search_AutoShow = False
                End If
            End If
            My.Settings.Save()
    	End Sub
    I hope it will help you.

    Regards,

    Ashidacchi


    • Edited by Ashidacchi Saturday, October 28, 2017 11:56 PM
    Saturday, October 28, 2017 11:51 PM
  • Hello, i am using Visual Studio 2017 and Visual Basic.net. In my project i have Config.txt file (simple text file). File holds various application configuration data, also user password.

    I'd like to add that it's customary to NOT save a password; set up a routine that will generate a hash of the password (sometimes using "salt") and save that.

    When a user enters a password, run it through that same routine and compare the saved hash (string) to the one generated to know whether or not it's correct.

    Given that, since the hash is one-way only (ergo, you can't get the password back by using the hash), it's harmless if it's found.

    That's not to say that I don't think encryption is worthwhile but I figured I'd add that.

    Also: Do you obfuscate the code?

    If you don't then it's still wide open even with the encryption method that I showed yesterday. The reason is because the encryption key (string) is in the code then you've effectively handed someone the lock and the key and hope they can't figure out how to fit them together. ;-)


    "A problem well stated is a problem half solved.” - Charles F. Kettering


    • Edited by Frank L. Smith Sunday, October 29, 2017 10:52 AM ...typo
    • Marked as answer by ecka3333 Sunday, October 29, 2017 11:10 AM
    Sunday, October 29, 2017 10:52 AM
  • Thanks for answers. My code is not obfuscated, because i need just simple protection.  I think i will use password hash method. 

    Talking about 3DES encryption method, the encryption key will be compiled in to the exe file, i think. I am not expert in programming. I want to ask: is it easy to decompile the executable file and to get the key?

    Sunday, October 29, 2017 11:28 AM
  • .. is it easy to decompile the executable file and to get the key?

    It's embarrassingly easy, yes.

    This will seem like an advertisement but I don't mean it to: Watch this video because what he says and shows is exactly right:

    https://youtu.be/zqvRyduULrw

    Even "non-technical" people can figure out how to decompile a dotNET assembly.


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Sunday, October 29, 2017 11:35 AM
  • I think i will use password hash method.

    One of the interesting (and good - for us) things about a hash is that a relatively small change in the input results in a very different hash output.

    For example:

    Public Class Form1
        Private Sub _
            Form1_Load(sender As System.Object, _
                       e As System.EventArgs) _
                       Handles MyBase.Load
    
            Dim myPassword As String = "Abracadabra"
    
            Dim hashed1 As String = CreateHashSHA1(myPassword)
            Dim hashed256 As String = CreateHashSHA256(myPassword)
    
            MessageBox.Show(hashed1, "Hashed String (SHA1)")
            MessageBox.Show(hashed256, "Hashed String (SHA256)")
    
            Stop
    
            ' Since my password itself isn't very strong, even
            ' though you can't reverse a hash, there are
            ' tables (rainbow tables) that are out there with
            ' "pre-hashed" values so a hacker can try that and
            ' often times will be successful.
            ' 
            ' A more secure way then is to "salt" the password
            ' before hashing it. That won't be in their
            ' rainbow table!
            ' 
            ' As an example:
    
            Dim hashedWithSalt1 As String = CreateHashSHA1("NaCl" & myPassword)
            Dim hashedWithSalt256 As String = CreateHashSHA256("NaCl" & myPassword)
    
            MessageBox.Show(hashedWithSalt1, "Hashed & Salted String (SHA1)")
            MessageBox.Show(hashedWithSalt256, "Hashed & Salted String (SHA256)")
    
            Stop
    
        End Sub
    
    
    
        Private Function _
            CreateHashSHA1(ByVal stringToHash As String) As String
    
            Dim retVal As String = Nothing
    
            Try
                If String.IsNullOrWhiteSpace(stringToHash) Then
                    Throw New ArgumentException("The string to hash cannot be null or empty.")
    
                Else
                    Dim b As Byte() = System.Text.Encoding.UTF8.GetBytes(stringToHash.Trim)
    
                    Using hashType As Security.Cryptography.HashAlgorithm = New Security.Cryptography.SHA1Managed
                        Dim hashBytes As Byte() = hashType.ComputeHash(b)
                        retVal = Convert.ToBase64String(hashBytes)
                    End Using
                End If
    
            Catch ex As Exception
                Throw
            End Try
    
            Return retVal
    
        End Function
    
    
    
        Private Function _
            CreateHashSHA256(ByVal stringToHash As String) As String
    
            Dim retVal As String = Nothing
    
            Try
                If String.IsNullOrWhiteSpace(stringToHash) Then
                    Throw New ArgumentException("The string to hash cannot be null or empty.")
    
                Else
                    Dim b As Byte() = System.Text.Encoding.UTF8.GetBytes(stringToHash.Trim)
    
                    Using hashType As Security.Cryptography.HashAlgorithm = New Security.Cryptography.SHA256Managed
                        Dim hashBytes As Byte() = hashType.ComputeHash(b)
                        retVal = Convert.ToBase64String(hashBytes)
                    End Using
                End If
    
            Catch ex As Exception
                Throw
            End Try
    
            Return retVal
    
        End Function
    End Class

    So the unsalted version is probably close to the salted version, right?

    Way not! Have a look:

    Food for thought. :)


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Sunday, October 29, 2017 12:10 PM
  • One more alteration then I'll be quiet.

    Another way you might set it up is to forego converting the byte array to a base 64 string and, instead, iterate through the bytes and for each, create a hexadecimal string, then combine them.

    You can see what I mean (and notice the commented out part - for comparison) in the following:

        Private Function _
            CreateHashSHA1(ByVal stringToHash As String) As String
    
            Dim retVal As String = Nothing
    
            Try
                If String.IsNullOrWhiteSpace(stringToHash) Then
                    Throw New ArgumentException("The string to hash cannot be null or empty.")
    
                Else
                    Dim b As Byte() = System.Text.Encoding.UTF8.GetBytes(stringToHash.Trim)
    
                    Using hashType As Security.Cryptography.HashAlgorithm = New Security.Cryptography.SHA1Managed
                        Dim hashBytes As Byte() = hashType.ComputeHash(b)
                        'retVal = Convert.ToBase64String(hashBytes)
    
                        Dim sb As New System.Text.StringBuilder()
    
                        For i As Integer = 0 To hashBytes.Length - 1
                            sb.Append(hashBytes(i).ToString("X2"))
                        Next
    
                        retVal = sb.ToString
                    End Using
                End If
    
            Catch ex As Exception
                Throw
            End Try
    
            Return retVal
    
        End Function
    
    
    
        Private Function _
            CreateHashSHA256(ByVal stringToHash As String) As String
    
            Dim retVal As String = Nothing
    
            Try
                If String.IsNullOrWhiteSpace(stringToHash) Then
                    Throw New ArgumentException("The string to hash cannot be null or empty.")
    
                Else
                    Dim b As Byte() = System.Text.Encoding.UTF8.GetBytes(stringToHash.Trim)
    
                    Using hashType As Security.Cryptography.HashAlgorithm = New Security.Cryptography.SHA256Managed
                        Dim hashBytes As Byte() = hashType.ComputeHash(b)
                        ' retVal = Convert.ToBase64String(hashBytes)
    
                        Dim sb As New System.Text.StringBuilder()
    
                        For i As Integer = 0 To hashBytes.Length - 1
                            sb.Append(hashBytes(i).ToString("X2"))
                        Next
    
                        retVal = sb.ToString
                    End Using
                End If
    
            Catch ex As Exception
                Throw
            End Try
    
            Return retVal
    
        End Function

    Compare the following with the previous screenshots:


    "A problem well stated is a problem half solved.” - Charles F. Kettering

    Sunday, October 29, 2017 12:35 PM