Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. Visual Basic
  4. Securing Local Files [Solved]

Securing Local Files [Solved]

Scheduled Pinned Locked Moved Visual Basic
securitycsharphelp
20 Posts 8 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • D dcu lcr

    actually you can. The solution, however, is in using a .NET secure string for the password and store the secure string in a file. Take a look(bing it) at how to use secure strings with powershell, if you're using win 7 then it should be a piece of cake.

    L. Carlos Rodriguez DCU, LLC Braselton, GA 30517

    L Offline
    L Offline
    Lost User
    wrote on last edited by
    #11

    ..and there is me reading the file, and shouting your password in the streets. Any other solutions?

    Bastard Programmer from Hell :suss: if you can't read my code, try converting it here[^]

    D 1 Reply Last reply
    0
    • S Saul Johnson

      Hello, My VB.NET application currently securely downloads a username and password required to access a web service that contains sensitive data. The problem I face now is storing that username and password on-disk in a secure manner for future use. I've looked into various encryption algorithms etc. but all involve storing some kind of key for decryption locally (rendering the encryption a bit of a joke) or hard-coding the key into the application (difficult-to-maintain and just about as useful as the last option). I welcome any suggestions as to how relatively secure local storage of a username and password might be accomplished. Despite hours of wracking my brains poking about in the System.Security.Cryptography namespace I'm no closer to finding a solution than I was at the start. SixOfTheClock

      A programming language is to a programmer what a fine hat is to one who is fond of fancy garden parties. Just don't try wearing any .NET language on your head. Some of them are sharp.

      B Offline
      B Offline
      BrainiacV
      wrote on last edited by
      #12

      Not sure if this will help, Back in the early days of microcomputers, some publishers tried to encrypt their programs to keep them from being pirated. After you entered a key, a subroutine would be called to decrypt the code. The sneaky bit was that right after the subroutine call, there was additional code, but, the program never reached it. Part of the decryption overlaid the system stack and so the subroutine return went someplace else, rather than the legitimate looking code that followed the decryption. So I guess in a long winded way, I am suggesting the use of misdirection in addition to the indirection that has been suggested above. And then repeat. It won't stop them, but it could really slow them down.

      Psychosis at 10 Film at 11 Those who do not remember the past, are doomed to repeat it. Those who do not remember the past, cannot build upon it.

      S 1 Reply Last reply
      0
      • L Lost User

        ..and there is me reading the file, and shouting your password in the streets. Any other solutions?

        Bastard Programmer from Hell :suss: if you can't read my code, try converting it here[^]

        D Offline
        D Offline
        dcu lcr
        wrote on last edited by
        #13

        ...there's nothing better than making passwords public so you can shout them to the world, that's why we use the.NET secure string functionality for batch files protections at both the DOL and Treasury. But then again, this is the government and we don't know what we're doing.... :doh: Sorry I led you in the wrong path.... :(( Good luck

        L 1 Reply Last reply
        0
        • D dcu lcr

          ...there's nothing better than making passwords public so you can shout them to the world, that's why we use the.NET secure string functionality for batch files protections at both the DOL and Treasury. But then again, this is the government and we don't know what we're doing.... :doh: Sorry I led you in the wrong path.... :(( Good luck

          L Offline
          L Offline
          Lost User
          wrote on last edited by
          #14

          dcu.lcr wrote:

          ...there's nothing better than making passwords public so you can shout them to the world, that's why we use the.NET secure string functionality for batch files protections at both the DOL and Treasury.

          For batch files? :doh: Let me rephrase that; any secret that's stored, isn't.

          dcu.lcr wrote:

          But then again, this is the government and we don't know what we're doing.... :doh:

          You working for the government is not an argument, nor does it validate your statement.

          Bastard Programmer from Hell :suss: if you can't read my code, try converting it here[^]

          1 Reply Last reply
          0
          • S Saul Johnson

            Hello, My VB.NET application currently securely downloads a username and password required to access a web service that contains sensitive data. The problem I face now is storing that username and password on-disk in a secure manner for future use. I've looked into various encryption algorithms etc. but all involve storing some kind of key for decryption locally (rendering the encryption a bit of a joke) or hard-coding the key into the application (difficult-to-maintain and just about as useful as the last option). I welcome any suggestions as to how relatively secure local storage of a username and password might be accomplished. Despite hours of wracking my brains poking about in the System.Security.Cryptography namespace I'm no closer to finding a solution than I was at the start. SixOfTheClock

            A programming language is to a programmer what a fine hat is to one who is fond of fancy garden parties. Just don't try wearing any .NET language on your head. Some of them are sharp.

            O Offline
            O Offline
            ObiWan_MCC
            wrote on last edited by
            #15

            I think you're approaching the issue the wrong way, see, you DON'T need to know the password (nor to store it); all you need to do is checking that it is correct For such a task, all you'll need will be using an MD5 "salted" hash; just to be clear, let's say you have the following code

            // generates the unique (salted) hash of a string
            private static string getKey(string sSalt, string sKey)
            {
            Byte[] originalBytes, encodedBytes;
            MD5 hash = new MD5CryptoServiceProvider();
            // or: SHA256 hash = new SHA256CryptoServiceProvider();

            // generate the hash value
            originalBytes = ASCIIEncoding.Default.GetBytes(sSalt + "." + sKey);
            encodedBytes = hash.ComputeHash(originalBytes);
            
            // turn the hash to a string and return it
            string sResult = BitConverter.ToString(encodedBytes).Replace("-", "");
            // or: string sResult = Convert.ToBase64String(encodedBytes);
            return sResult;
            

            }

            now, in your login form, you ask to enter a username and a password, let's say you get back "jdoe" and "supersecret", at this point, you just call the above function this way

            string hashValue = getKey(userName, userPass);

            and the hashvalue will now contain something like "752dcc62c07fb4652981add596e1427b" now, with this value in your hands, you run a query on your database user table seeking for the user name (jdoe) and, if found, you compare the salted MD5 hash stored as the password with the one you just generated and, if they match, you grant access to the user. At this point, in case you need to use the password "in clear", you may just encrypt the password you received and store it into a session cookie, this will give you VOLATILE (temporary) storage and, while it will allow you to retrieve the password for the session lifetime, you won't in reality store the password anywhere on your server and... retrieving a password from a salted hash isn't exactly an easy task, believe me :) HTH

            O S 2 Replies Last reply
            0
            • O ObiWan_MCC

              I think you're approaching the issue the wrong way, see, you DON'T need to know the password (nor to store it); all you need to do is checking that it is correct For such a task, all you'll need will be using an MD5 "salted" hash; just to be clear, let's say you have the following code

              // generates the unique (salted) hash of a string
              private static string getKey(string sSalt, string sKey)
              {
              Byte[] originalBytes, encodedBytes;
              MD5 hash = new MD5CryptoServiceProvider();
              // or: SHA256 hash = new SHA256CryptoServiceProvider();

              // generate the hash value
              originalBytes = ASCIIEncoding.Default.GetBytes(sSalt + "." + sKey);
              encodedBytes = hash.ComputeHash(originalBytes);
              
              // turn the hash to a string and return it
              string sResult = BitConverter.ToString(encodedBytes).Replace("-", "");
              // or: string sResult = Convert.ToBase64String(encodedBytes);
              return sResult;
              

              }

              now, in your login form, you ask to enter a username and a password, let's say you get back "jdoe" and "supersecret", at this point, you just call the above function this way

              string hashValue = getKey(userName, userPass);

              and the hashvalue will now contain something like "752dcc62c07fb4652981add596e1427b" now, with this value in your hands, you run a query on your database user table seeking for the user name (jdoe) and, if found, you compare the salted MD5 hash stored as the password with the one you just generated and, if they match, you grant access to the user. At this point, in case you need to use the password "in clear", you may just encrypt the password you received and store it into a session cookie, this will give you VOLATILE (temporary) storage and, while it will allow you to retrieve the password for the session lifetime, you won't in reality store the password anywhere on your server and... retrieving a password from a salted hash isn't exactly an easy task, believe me :) HTH

              O Offline
              O Offline
              ObiWan_MCC
              wrote on last edited by
              #16

              forgot; as for encrypting/decrypting, you may use the following code (not mine, but I'm sorry to say I don't remember where I found it)

              // Encrypt the given string using AES. The string can be decrypted using
              // DecryptString(). The sharedSecret parameters must match.
              public string EncryptString(string plainText, string sharedSecret)
              {
              if (string.IsNullOrEmpty(plainText))
              throw new ArgumentNullException("plainText");
              if (string.IsNullOrEmpty(sharedSecret))
              throw new ArgumentNullException("sharedSecret");

              string outStr = null;                       // Encrypted string to return
              RijndaelManaged aesAlg = null;              // RijndaelManaged object used to encrypt the data.
              
              try
              {
                  // generate the key from the shared secret and the salt
                  Rfc2898DeriveBytes key = new Rfc2898DeriveBytes(sharedSecret, this.\_salt);
              
                  // Create a RijndaelManaged object
                  aesAlg = new RijndaelManaged();
                  aesAlg.Key = key.GetBytes(aesAlg.KeySize / 8);
              
                  // Create a decrytor to perform the stream transform.
                  ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);
              
                  // Create the streams used for encryption.
                  using (MemoryStream msEncrypt = new MemoryStream())
                  {
                      // prepend the IV
                      msEncrypt.Write(BitConverter.GetBytes(aesAlg.IV.Length), 0, sizeof(int));
                      msEncrypt.Write(aesAlg.IV, 0, aesAlg.IV.Length);
                      using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
                      {
                          using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
                          {
                              //Write all data to the stream.
                              swEncrypt.Write(plainText);
                          }
                      }
                      outStr = Convert.ToBase64String(msEncrypt.ToArray());
                  }
              }
              finally
              {
                  // Clear the RijndaelManaged object.
                  if (aesAlg != null)
                      aesAlg.Clear();
              }
              
              // Return the encrypted bytes from the memory stream.
              return outStr;
              

              }

              // Decrypt the given string. Assumes the string was encrypted using
              // EncryptString(), using an identical sharedSecret.
              public string DecryptString(string cipherText, string sharedSecret)
              {
              if (string.IsNullOrEmpty(cipherText))
              throw new ArgumentNullException("cipherText");
              if (string.IsNullOrEmpty(sharedSecret))
              throw new ArgumentNullException("shar

              1 Reply Last reply
              0
              • O ObiWan_MCC

                I think you're approaching the issue the wrong way, see, you DON'T need to know the password (nor to store it); all you need to do is checking that it is correct For such a task, all you'll need will be using an MD5 "salted" hash; just to be clear, let's say you have the following code

                // generates the unique (salted) hash of a string
                private static string getKey(string sSalt, string sKey)
                {
                Byte[] originalBytes, encodedBytes;
                MD5 hash = new MD5CryptoServiceProvider();
                // or: SHA256 hash = new SHA256CryptoServiceProvider();

                // generate the hash value
                originalBytes = ASCIIEncoding.Default.GetBytes(sSalt + "." + sKey);
                encodedBytes = hash.ComputeHash(originalBytes);
                
                // turn the hash to a string and return it
                string sResult = BitConverter.ToString(encodedBytes).Replace("-", "");
                // or: string sResult = Convert.ToBase64String(encodedBytes);
                return sResult;
                

                }

                now, in your login form, you ask to enter a username and a password, let's say you get back "jdoe" and "supersecret", at this point, you just call the above function this way

                string hashValue = getKey(userName, userPass);

                and the hashvalue will now contain something like "752dcc62c07fb4652981add596e1427b" now, with this value in your hands, you run a query on your database user table seeking for the user name (jdoe) and, if found, you compare the salted MD5 hash stored as the password with the one you just generated and, if they match, you grant access to the user. At this point, in case you need to use the password "in clear", you may just encrypt the password you received and store it into a session cookie, this will give you VOLATILE (temporary) storage and, while it will allow you to retrieve the password for the session lifetime, you won't in reality store the password anywhere on your server and... retrieving a password from a salted hash isn't exactly an easy task, believe me :) HTH

                S Offline
                S Offline
                Saul Johnson
                wrote on last edited by
                #17

                Hello, Thank you for your answer. This is undoubtedly how I would go about authenticating passwords in any other circumstances but these, generating hashes using MD5 or (my personal preference) SHA-256. I am working with a web service from a Windows Forms application, and a password is required to work with this web service. Usually, I'd show a prompt and ask the user to input the password to authenticate when it starts, but the user requirements state that users must not need to enter any sort of authentication information in order to work with the application in the interest of ease-of-use. What I was looking for was a way to store this username and password locally in such a way that only my application would be able to access and use them. As it seems that this isn't really possible, I've put in place stricter controls and guidelines for where and when the software can be used and used misdirection and obfuscation as suggested by previous answers to make it more difficult for these credentials to be stolen. However, as you correctly say, the only way to really keep a password safe it to authenticate against its hash. SixOfTheClock

                A programming language is to a programmer what a fine hat is to one who is fond of fancy garden parties. Just don't try wearing any .NET language on your head. Some of them are sharp.

                O 1 Reply Last reply
                0
                • B BrainiacV

                  Not sure if this will help, Back in the early days of microcomputers, some publishers tried to encrypt their programs to keep them from being pirated. After you entered a key, a subroutine would be called to decrypt the code. The sneaky bit was that right after the subroutine call, there was additional code, but, the program never reached it. Part of the decryption overlaid the system stack and so the subroutine return went someplace else, rather than the legitimate looking code that followed the decryption. So I guess in a long winded way, I am suggesting the use of misdirection in addition to the indirection that has been suggested above. And then repeat. It won't stop them, but it could really slow them down.

                  Psychosis at 10 Film at 11 Those who do not remember the past, are doomed to repeat it. Those who do not remember the past, cannot build upon it.

                  S Offline
                  S Offline
                  Saul Johnson
                  wrote on last edited by
                  #18

                  Hello, That's a very clever suggestion that I certainly wouldn't have thought of, and I'll undoubtedly be looking into it. Thank you very much indeed. SixOfTheClock

                  A programming language is to a programmer what a fine hat is to one who is fond of fancy garden parties. Just don't try wearing any .NET language on your head. Some of them are sharp.

                  1 Reply Last reply
                  0
                  • J James H

                    Whatever method you use I also like to have a set of "red herring" credentials - that looks likes a password, - e.g. config setting Password with some cyrptic looking string that could be an encrypted string - sends the b'rs of on a wild goose chase

                    S Offline
                    S Offline
                    Saul Johnson
                    wrote on last edited by
                    #19

                    Another way to make things that little bit more difficult to figure out for anyone with mischief on their mind. Excellent thank you. SixOfTheClock

                    A programming language is to a programmer what a fine hat is to one who is fond of fancy garden parties. Just don't try wearing any .NET language on your head. Some of them are sharp.

                    1 Reply Last reply
                    0
                    • S Saul Johnson

                      Hello, Thank you for your answer. This is undoubtedly how I would go about authenticating passwords in any other circumstances but these, generating hashes using MD5 or (my personal preference) SHA-256. I am working with a web service from a Windows Forms application, and a password is required to work with this web service. Usually, I'd show a prompt and ask the user to input the password to authenticate when it starts, but the user requirements state that users must not need to enter any sort of authentication information in order to work with the application in the interest of ease-of-use. What I was looking for was a way to store this username and password locally in such a way that only my application would be able to access and use them. As it seems that this isn't really possible, I've put in place stricter controls and guidelines for where and when the software can be used and used misdirection and obfuscation as suggested by previous answers to make it more difficult for these credentials to be stolen. However, as you correctly say, the only way to really keep a password safe it to authenticate against its hash. SixOfTheClock

                      A programming language is to a programmer what a fine hat is to one who is fond of fancy garden parties. Just don't try wearing any .NET language on your head. Some of them are sharp.

                      O Offline
                      O Offline
                      ObiWan_MCC
                      wrote on last edited by
                      #20

                      I see; given your situation there may be another possible solution; assuming that the webservice you're calling is hosted on a different box (or instance), and given that you don't have the code for the service, you may create your own webservice app, embed the user credentials into such an app and install it on the same (or another) box/instance where the regular webservice lives, this way, your webservice will act as a "proxy" so that your winforms app will call your webservice w/o any credentials and the latter will act as a "proxy" to the real webservice (and will pass it the needed credentials)

                      1 Reply Last reply
                      0
                      Reply
                      • Reply as topic
                      Log in to reply
                      • Oldest to Newest
                      • Newest to Oldest
                      • Most Votes


                      • Login

                      • Don't have an account? Register

                      • Login or register to search.
                      • First post
                        Last post
                      0
                      • Categories
                      • Recent
                      • Tags
                      • Popular
                      • World
                      • Users
                      • Groups