|
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
|
|
|
|
|
..and there is me reading the file, and shouting your password in the streets. Any other solutions?
Bastard Programmer from Hell
if you can't read my code, try converting it here[^]
|
|
|
|
|
...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....
Sorry I led you in the wrong path....
Good luck
|
|
|
|
|
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?
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....
You working for the government is not an argument, nor does it validate your statement.
Bastard Programmer from Hell
if you can't read my code, try converting it here[^]
|
|
|
|
|
Simplest solution is to NOT store it locally. Store it on your (web)server, and have your app request it when required.
(That's still no guarantee that no-one will duplicate the sensitive data btw)
Bastard Programmer from Hell
if you can't read my code, try converting it here[^]
|
|
|
|
|
Very sensible idea there, and very true about the sensitive data. If the point of my application is to search through and display said sensitive data then it would be impossible to completely secure for that very reason. Thank you for your reply, this seems like a better way to go about it and is well worth testing out.
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.
|
|
|
|
|
You're welcome
|
|
|
|
|
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
|
|
|
|
|
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.
|
|
|
|
|
|
If the app can access it (required, otherwise it could not use the data), then so can I
Bastard Programmer from Hell
if you can't read my code, try converting it here[^]
|
|
|
|
|
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.
|
|
|
|
|
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.
|
|
|
|
|
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
private static string getKey(string sSalt, string sKey)
{
Byte[] originalBytes, encodedBytes;
MD5 hash = new MD5CryptoServiceProvider();
originalBytes = ASCIIEncoding.Default.GetBytes(sSalt + "." + sKey);
encodedBytes = hash.ComputeHash(originalBytes);
string sResult = BitConverter.ToString(encodedBytes).Replace("-", "");
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
|
|
|
|
|
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)
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;
RijndaelManaged aesAlg = null;
try
{
Rfc2898DeriveBytes key = new Rfc2898DeriveBytes(sharedSecret, this._salt);
aesAlg = new RijndaelManaged();
aesAlg.Key = key.GetBytes(aesAlg.KeySize / 8);
ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);
using (MemoryStream msEncrypt = new MemoryStream())
{
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))
{
swEncrypt.Write(plainText);
}
}
outStr = Convert.ToBase64String(msEncrypt.ToArray());
}
}
finally
{
if (aesAlg != null)
aesAlg.Clear();
}
return outStr;
}
public string DecryptString(string cipherText, string sharedSecret)
{
if (string.IsNullOrEmpty(cipherText))
throw new ArgumentNullException("cipherText");
if (string.IsNullOrEmpty(sharedSecret))
throw new ArgumentNullException("sharedSecret");
RijndaelManaged aesAlg = null;
string plaintext = null;
try
{
Rfc2898DeriveBytes key = new Rfc2898DeriveBytes(sharedSecret, this._salt);
byte[] bytes = Convert.FromBase64String(cipherText);
using (MemoryStream msDecrypt = new MemoryStream(bytes))
{
aesAlg = new RijndaelManaged();
aesAlg.Key = key.GetBytes(aesAlg.KeySize / 8);
aesAlg.IV = ReadByteArray(msDecrypt);
ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);
using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
{
using (StreamReader srDecrypt = new StreamReader(csDecrypt))
plaintext = srDecrypt.ReadToEnd();
}
}
}
finally
{
if (aesAlg != null)
aesAlg.Clear();
}
return plaintext;
}
the above should be robust enough for your task, just encrypt the received password calling "EncryptString()" and passing (e.g.) the "session ID" as the key, store it into a session cookie and then use "DecryptString()" to retrieve it when needed (for the current session lifetime)
|
|
|
|
|
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.
|
|
|
|
|
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)
|
|
|
|
|
Having trouble getting exactly the answer I need in google, MSDN.
Desired: A user can select a PictureBox on the form which becomes the activeBrick. Whenever there is an activeBrick selected, arrow keys should move this one pixel at a time around the form within a Panel control called pnlTableau.
I have done this:
Me.KeyPreview = true
My attempted solution was this:
Private Sub BrickMove(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles Me.KeyUp
If activeBrick IsNot Nothing Then
Select Case e.KeyCode
Case Keys.Up
If activeBrick.Top > 0 Then activeBrick.Top -= 1
Case Keys.Down
If activeBrick.Bottom < pnlTableau.Height Then activeBrick.Top += 1
e.Handled = True
Case Keys.Left
If activeBrick.Left > 0 Then activeBrick.Left -= 1
e.Handled = True
Case Keys.Right
If activeBrick.Right < pnlTableau.Width Then activeBrick.Left += 1
e.Handled = True
End Select
End If
Me.Refresh()
End Sub
The Me.Refresh line at the end is because my active PictureBox has a dotted red rectangle around it, which will "drag" if the form is not repainted.
The problem: I have a few radio buttons on the form also. The arrow keys DO move the PictureBox, but the arrow keys also shift the selected radio button, which is not behavior I want. I thought e.Handled = True would suppress this, but it doesn't.
If I move this code to the KeyDown event, the PictureBox does not move at all but the radio buttons are still selected.
Thanks in advance.
|
|
|
|
|
Is the position of the radio button linked to that of the PictureBox(es) in the form design?
|
|
|
|
|
No. The form has several radio buttons to the left of a Panel control. These set options for the PictureBoxes which are dynamically added to the Panel control's control array at runtime.
I presume it is normal behavior for Windows to process arrow keys in this way, just as Tab moves the focus from one control to another. I want the arrow keys to be handled programmatically and to not affect which radio button is selected.
|
|
|
|
|
OK, I misunderstood your question... sorry.
The only thing I could find, if the code was pasted from the actual project, is the e.Handled is missing for the up arrow. Don't know if that helps?
|
|
|
|
|
Thank you but no, the problem occurs with any of the 4 arrow presses.
|
|
|
|
|
The MSDN documentation for the KeyPreview property isn't exactly clear http://msdn.microsoft.com/en-us/library/system.windows.forms.form.keypreview.aspx[^]. It starts off with the statement that the form will receive all KeyXXXX events from the focussed control, but then adds a note that some controls may cancel a keystroke and disable the preview.
There is short thread on stackoverflow[^] which I think you will find interesting. In one of the answers, Hans Passant describes overriding the form's ProcessCmdKey method as a better solution, e.g.
Protected Overrides Function ProcessCmdKey(ByRef msg As Message, keyData As Keys) As Boolean
If activeBrick IsNot Nothing Then
If keyData = Keys.Down OrElse keyData = Keys.Up Then
MoveBrick(keyData)
Return True
End If
End If
Return MyBase.ProcessCmdKey(msg, keyData)
End Function
A quick test suggests that this is much more useful technique than KeyPreview and it does not rely on the uncertain cooperation of the focussed control.
Alan.
|
|
|
|
|
Indeed, this does work perfectly! In my case I had to add 2 OrElses to cover the Left and Right arrows as well, but it was very nice of you to not only find a solution but modify the code I posted directly.
Many thanks.
(Also thank you for the link to stackOverflow. You are right, I did find that interesting.)
|
|
|
|
|
Alan's recommendation works just perfect and leaves the RadioButtons untouched! You can make the 'MoveBrick' function a little bit easier than what you had before.
Private Function MoveBrick(ByVal keyData As Keys) As Boolean
Dim oldLocation As Drawing.Point = activeBrick.Location
Dim newLocation As Drawing.Point = oldLocation
Select Case keyData
Case Is = Keys.Up
newLocation.Y = oldLocation.Y - 1
Case Is = Keys.Down
newLocation.Y = oldLocation.Y + 1
Case Is = Keys.Left
newLocation.X = oldLocation.X - 1
Case Is = Keys.Right
newLocation.X = oldLocation.X + 1
End Select
activeBrick.Location = newLocation
Return True
End Function
|
|
|
|
|