|
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
|
|
|
|
|
Thank you for this suggested code. I agree this is readable and efficient, and it tests perfectly in my project.
Kind regards.
|
|
|
|
|
You're welcome.
|
|
|
|
|
Hello everybody,
I'm trying to add records to the 'Customer' and the 'Item' classes of my DataContext. The Sub is part of the (partial) DataContext class. Adding new records seems to be a simple thing when I believe all the sources I read, but I'm obviously still wrong with something: 'SubmitChanges' doesn't update the underlying database... This despite the fact that all the DB records (old & new) are printed to the screen before, i.e. seem to be part of the 'Inserts' list. BTW, there are no exceptions thrown.
Can someone please tell me what's wrong with that code?
Public Sub InsertTest()
Dim cust As New Customer ' add new customer
With cust
.First_Name = "Paul"
.Last_Name = "Miller"
End With
Customer.InsertOnSubmit(cust)
Dim item1 As New Item ' add new product item
With item1
.Item_Name = "DVD"
.Item_Price = 19.75
End With
Item.InsertOnSubmit(item1)
Dim item2 As New Item ' add new product item
With item2
.Item_Name = "BlueRay"
.Item_Price = 29.75
End With
Item.InsertOnSubmit(item2)
' ONLY FOR DEBUGGING
' print changed objects
Dim mySet As System.Data.Linq.ChangeSet = Me.GetChangeSet()
Dim liste As Object = mySet.Inserts
For Each entry As Object In liste '<----- prints existing & added entries
Select Case True
Case TypeOf (entry) Is Item
Console.WriteLine(entry.Item_Name)
Case TypeOf (entry) Is Customer
Console.WriteLine(entry.last_name)
Case Else
Console.WriteLine("Objekt vom Typ '{0}'", entry.GetType.Name)
End Select
Next
SubmitChanges() '<---- isn't writing changes to database
Console.ReadLine()
End Sub
modified 3-Sep-12 17:46pm.
|
|
|
|
|
Finally I found out that the underlying database actually did get updated...
It's just not the same database that I can see in the ServerExplorer – all the changes have been written into a local copy of the database, which I found in the "Debug" directory.
|
|
|
|
|
Hi, am not sure if this should be a vb.net or visual studio question, if I am posting at the wrong place please pardon me.
I am currently updating my VB code to VB.NET, it’s a learning process for me and I am trying to conform all my code to 100% VB.NET . I have set up ‘Option Strict’ and that helps with a lot of bad habit. I was wondering if I can do the something for flagging VB6 functions. Visual Studio automatically references the VB6 library which is good if you don’t have time when migrating, however I have time and would like to abstain from VB6 or toggle the library ON/OFF when needed.
Thank you in advance,
-Jay
|
|
|
|
|
Your question doesn't make any sense at all.
What are you talking about when you say "VB6 library"??
No, there is no way to toggle "Option Strict" on and off at the method level. It's the entire file/project or nothing.
|
|
|
|
|
One can enable ‘Option Strict’ per *.vb file by adding “Option Strict On” on the first line of the code.
What I was trying to do is to be able to do same with Microsoft.VisualBasic.dll library. When I start Visual Studio 2008 the Microsoft.VisualBasic.dll library is automatically referenced. I was hoping to be able to turn it off.
|
|
|
|
|
juno101 wrote: One can enable ‘Option Strict’ per *.vb file by adding “Option Strict On” on the
first line of the code.
Yeah, that's why I said "file/project"...
juno101 wrote: What I was trying to do is to be able to do same with Microsoft.VisualBasic.dll
library
Since "Option Strict" has nothing to do with the references in a project, this doesn't make any sense.
juno101 wrote: When I start Visual Studio 2008 the Microsoft.VisualBasic.dll library is
automatically referenced. I was hoping to be able to turn it off.
To what end?? All this would do is rip out VB-specific functions and classes and pretty much gut the ability to use any legacy code since it will all depend on these functions for backward compatibility. For instance, Left(), Right, Instr(), Len(), ...
|
|
|
|
|
Hi Dave, thank you very much for helping me . . . I think we are on the same page now.
Quote: To what end?? All this would do is rip out VB-specific functions and classes
That is the whole point. I am not sure how long Microsoft intends to keep support for the "VB6" functions. And instead of using Object Events that are provided in vb.net I habitually tend to use VB6 functions. If I can turn that 'off' in all the new code that I write then the new code will be independent from VB6. Additionally, I can retrain myself to only use object events. So instead of Len() I would use String.Length . . ..
As for the legacy code I can turn the VB6 library 'ON'.
|
|
|
|
|
Now that's just silly. Just don't use the legacy functions. It's that simple. Besides, that namespace is NOT used for just backwards compatibility. For instance, the VB.NET CodeDom Provider is in therem which provides access to the VB.NET compiler (can also be used to generate source code from IL!) It also provides the ApplicationServices namespace and as well as support for the My namespace.
BTW, it's not "object events". It's object oriented programming.
|
|
|
|
|
Sub Query_Insert_Test()
Try
AddQuery = "Begin Transaction "
AddQuery &= "INSERT INTO tblFoodAndBeverage(Breakfast,Lunch,Dinner,Supper,Snack,Beverage,Grocerries,Sub_Total) VALUES('" & txtBreakFeast.Text & "','" & txtLunch.Text & "','" & txtDinner.Text & "','" & txtSupper.Text & "','" & txtSnack.Text & "','" & txtBeverage.Text & "','" & txtGroceries.Text & "','" & txtSubFnB.Text & "')"
AddQuery &= "INSERT INTO tblExpenses(Date, <big>Food_And_Beverage</big>, Allowance, Total,Wallet) VALUES('" & DateTimePicker1.Value & "',(S<big>ELECT Food_And_BeverageID FROM [tblFoodAndBeverage],[tblExpenses] WHERE tblFoodAndBeverage.Food_And_BeverageID = tblExpenses.ExpensesID and tblExpenses.Date = '" & DateTimePicker1.Value &</big> "'),'" & txtAllowance.Text & "','" & txtTotalUsage.Text & "','" & txtWalletCash.Text & "')"
AddQuery &= "Commit Transaction "
cmd = New SqlCommand(AddQuery, connection)
connection.Open()
Dim Check As Integer = cmd.ExecuteNonQuery()
If Check > 0 Then
MsgBox("Record Inserted.")
connection.Close()
Else
MsgBox("Error. Record not inserted.")
End If
Catch ex As Exception
MessageBox.Show(ex.Message & " #################### " & ex.ToString)
End Try
End Sub
I need to insert the Food_And_BeverageID number to tblExpenses's Food_And_Beverage.
Is there any better query to select only the correct value and also a single row data.
Adding one record is okay but when I need to add another one it doesn't work and display error subquery doesn't allow to return multiple value.
Info the ID's is in Auto Number.
|
|
|
|
|