|
I've been asked to design a contact manager-like application for a friend's business. The application will have multiple user logins and all information is stored in a database (MySQL). Some information that will need to be stored needs to be encrypted because of the sensitivity of it; like credit card information. I'm familiar with using encryption in .NET. However there is one thing which I know how to do, but I'm trying to find the most secure way of doing it:
Normally if an application only has one user, or if fields of a record are tied to only one specific user (in a multi-user system), I could use that users password to encrypt the customer's information in the database (and that way the password wouldn't need to be stored anywhere). In this case though, that won't work. This is because multiple user's may need access to this information; say customer services rep. (CSR) A on Monday enters a customer's information and it is encrypted with CRS A's password. Then on Tuesday CSR B needs to access the same customer's information, they wouldn't be able to because the information wasn't encrypted with CSR B's password.
In a case like this, the application needs some constant password so that encrypted fields that need to be accessed by different people can be. Of course I could always just create a constant like Private Const Key As Byte() = {198, 167, 93, 121, 252, 215} . However I would think there would be a better way where it isn't just plain to see and can't be so easily found using ildasm.exe.
At first I was thinking of using some computer unique piece of information, but then the information wouldn't be accessible from multiple computers.
I know nothing is always 100% secure, and I'm not expecting that; just a better way of doing this to improve the quality and security of this application, and others I create in the future. I may be over-thinking this, like I usually do, but if anybody has any suggestions, or links to articles, that describe a good way to store a system-wide password like this I would greatly appreciate it.
Thanks in advance.
|
|
|
|
|
Why not just allocate user access classes to privileged users, such that when they logon successfully using their own password, they are allocated an access token which gives them the ability to read and/or update certain information.
One of these days I'm going to think of a really clever signature.
|
|
|
|
|
This might be interesting to you ...
http://www.rsa.com/products/bsafe/whitepapers/DDES_WP_0702.pdf[^]
Since you already know .Net encryption, I would build my encryption routines into my data-access layer; storing encrypted data in the database. To keep my sanity, I wouldn't encrypt everything just sensitive stuff.
|
|
|
|
|
@Richard: Not sure what you mean by access token. If the access token is used as an encryption key, then it would need to be the same for everyone all the time, ergo it would need to be saved as a constant somewhere. I can't keep all the database fields as plain text and limit access solely based on user authentication because of legal reasons; certain fields HAVE to be encrypted.
@David: I took a look at that PDF you provided and it describes using an encryption server separate from the database server. I just want to make sure I understand this concept.
On the encryption server there is a database that store say my customer's ID numbers and their encryption key. When my customer's employee starts up the application and logs in, the application connects to the encryption server over HTTPS (or other secure connection) and get the encryption key which is then used to decrypt my customer's client's information in the database? I drew a diagram of how I'm picturing it in my head located here. Is this correct? If so, as long as the request/retrieval of the encryption key is done over HTTPS then it should be secure, right?
|
|
|
|
|
DisIsHoody wrote: If the access token is used as an encryption key No, the access token tells you which information a specific user is allowed to access. This does not prevent you from encrypting everything, but since encryption can only use a single key this is one way to restrict the information available to different users.
One of these days I'm going to think of a really clever signature.
|
|
|
|
|
One way of achieving an encryption that multiple users can use is follows
The system contains the following
PlainText
CipherText
EncryptionKeyShared -- Decrypts above ciphertext
EncryptionKeyUserA -- Encryption key for user A
EncryptionKeyUserB -- Encryption key for user B
First, randomly generate a new EncryptionKeyShared
Then encrypt the plaintext with EncryptionKeyShared
Then encrypt the EncryptionKeyShared with EncryptionKeyUserA gives SecretKeyA
Then encrypt the EncryptionKeyShared with EncryptionKeyUserB gives SecretKeyB
Store the row like this
CiperText, SecretKeyA, SecretKeyB, ...SecretKeyZ
Now to descrypt, user A puts in their password, descrypts SecretKeyA using their password
This gives UserA access to EncrytpionKeyShared which can now be used to decrypt CipherText back to PlainText
Cheers
Matt
|
|
|
|
|
I've never seen this solution before but I like it. One question though. If for example someone got a hold of all the SecretKey(x), would it be easier to determine the EncryptionKeyShared if they knew which algorithm was used (like with some sort of collision search) or does the fact that EncryptionKeyShared was encrypted multiple times with different EncryptionKeyUser(x) not make any difference?
|
|
|
|
|
I don't believe this represents any risk. The types of attacks your talking bout usually require hundreds gigabytes or even thousands of terabytes of collected data to reveal a key.
In addition, if EncryptionKeyShared is random they've no way of knowing if they are getting closer or not.
The method I described is basically how windows manages encryption keys for NTFS encrypted files.
The important part of keeping this secure is make sure that EncryptionkeyShared is created with a cryptographically strong random number generator and is never sent to the client, eg, only the server should make use of EncryptionKeyShared, it should never go to the client.
Cheers
Matt
|
|
|
|
|
Oh -- one thing I forgot, for this method to work, when a user changes their password. You'll also have to encrypt all their EncryptionKeyShared(s) under the new password
Possibly you could just use one EncryptionKeyShared for all data to make this more convenient.
|
|
|
|
|
Matty22 wrote: only the server should make use of EncryptionKeyShared
Now I'm a little lost on how I could implement this. Currently the server is just housing the database with customer information. Each employee will have a computer at their desk which contains the application. When they log in, their password is hashed and compared against the saved hash in on of the tables.
Once they are logged in they will be able to look up records by typing in say a project number. This information will be retrieved from the database either by inline SQL statements or by stored procedures. Either way, if a column has encrypted data in it, it will be transmitted from the database server to the employees application and then be decrypted by the employee's application. For this to happen, the employee's application will need to make use of the EncryptionKeyShared.
The only way to make sure that only the server is making use of the EncryptionKeyShared is to write a server application, or service, that would accept request from the employee's application, retrieve the requested database application, decrypt the necessary columns, and finally transmit the data to the employee's application.
Two complications I see with this is that 1. a server application needs to be created to handle the incoming request from all the employee's computers and synchronize them so there isn't any conflict between data request or race conditions and 2. while the database information is being sent from the database server to the employee's computer the information is not encrypted.
If the database is on a local server then Item 2 may not be much of an issue, but if it is decided to keep the database server off-site, then it seems like have the data encrypted while it is being transmitted from the server to the employee's computer is a much better option then having it in plain text (even if it is going over a HTTPS connection).
Still, Item 1 still make the whole application more complicated; unless I'm missing something where a server application/service doesn't need to be created to implement the EncryptionKeyShared as you have described.
|
|
|
|
|
The server side application that performs the encryption could either be a set of services that the clients make calls to (xml/soap/json) and the data is protected in transit via transport and/or message encryption. Or a web application that the clients use in their browser.
If how your system works at the moment is every client can connect directly to the database without a server application. Then worrying about encryption is pretty pointless anyhow. What stops any of your users from just accessing the database directly by extracting a connection string from your application? What's stopping a client from giving out your current encryption keys to the world? Having clients directly talk to a dbase is generally not how things are done if you are worried about security anyhow. If all your clients are connecting directly to the dbase then I wouldn't be spending your time on encryption, I'd be spending it making a service for your application to call that removes the need for clients to access the dbase directly.
"Two complications I see with this is that 1. a server application needs to be created to handle the incoming request from all the employee's computers and synchronisew them so there isn't any conflict between data request or race conditions and 2. while the database information is being sent from the database server to the employee's computer the information is not encrypted. "
1, All multiuser systems need to deal with race conditions; a service layer doesnt' change any of that. If two users save a record at exactly the same time, how does your application handle this now? If your not dealing with race conditions now, you've already got problems,
2. Why would you think your own hand rolled encryption is more secure than HTTPS/TLS. It almost certainly is not. Besides, you could use HTTPS/TLS + Message layer security if wanted. Read about the differences between transport and message level security/encryption for clarification as to why 2. is not an issue
|
|
|
|
|
Matty22 wrote: Then worrying about encryption is pretty pointless anyhow. What stops any of your users from just accessing the database directly by extracting a connection string from your application?
The data was going to be encrypted before being saved in the database, so even if someone accessed the database directly the information in the tables would be unreadable.
Most of the software I have programmed up to this point has been database applications, web sites, and custom data analysis software that has only been used within the company I was working for so security wasn't a major concern, especially since none of the data was sensitive. The few things that were, such as credit card payments on the websites, was handled by Authorized.NET.
I have a lot of experience programming just not at this scale or type of application; that is why I'm looking for this input. Your comments make a lot of sense and I'm almost certain that I'm going to change my game plan for the design of this application based on the information you've provided. I greatly appreciate you taking the time to respond and point me in the right direction.
I'm going to do some Google search for the differences between transport and message level security/encryption (as you've recommended), however if you know of any good articles, or introductions, that you would recommend I would appreciate it. If you don't have any bookmarked or saved then don't worry about it, I'm sure I can find what I need; you've already provided a wealth of information.
|
|
|
|
|
Hi All,
I am in urgent need for the VB6 Project on topic "Printing Press Management" (with Oracle Database).
Please please please contact me @ maheshkl83@gmail.com if any one of you have the project with you.
I am ready to pay too...
Your quick help is greatly appreciated.
Thanks,
Mahesh KL
|
|
|
|
|
Not going to happen.
First, printing presses are a dying breed in the digital age and, second, VB6 is long since dead too.
For such a specific application, you're going to have to write this one yourself. I'd suggest using .NET over VB6 any day.
|
|
|
|
|
Mahesh KL wrote: I am ready to pay too...
Try Rent-a-coder.
Bastard Programmer from Hell
if you can't read my code, try converting it here[^]
|
|
|
|
|
You should remove your e-mail address from the post, as you can see you are receiving notifications as other users are answering your post.
Putting the e-mail in a public place like this one will give you lots of spam...
|
|
|
|
|
I have a teacher who gave us a compiled application. He did not provide us the code. We have to generate the code in our head and write it out. It must act like his application in every possible way. I have it written out but for some reason when I type in the value of two(2) pieces the two(2) isn't calculated yet every other number I type calculates just fine. Why?
two(2) falls within range of 1-199 so its price would be calculated as rangeA * two(2) pieces = price for two, but no result is returned, my text does not display in the textbox either.
Dim priceArrayElements(20) As Decimal
Dim pieceArrayElements(20) As Integer
Dim addedPieces
Dim totalAveragePieces
Dim addedPrices As Decimal
Dim totalAveragePrices As Decimal
Dim elementCounter As Decimal
Dim rangeA As Decimal = 0.5
Dim rangeB As Decimal = 0.55
Dim rangeC As Decimal = 0.6
Dim rangeD As Decimal = 0.65
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Select Case False
Case IsNumeric(txtPieces.Text)
MessageBox.Show("Pieces completed must be numeric.", "Data Entry Error", MessageBoxButtons.OK, MessageBoxIcon.Information)
txtPieces.Text = ""
Case Not IsNumeric(txtName.Text)
MessageBox.Show("Name is required.", "Data Entry Error", MessageBoxButtons.OK, MessageBoxIcon.Information)
txtName.Text = ""
Case Else
Select Case txtPieces.Text
Case 1 To 199
Try
For i As Integer = 0 To priceArrayElements.Length
priceArrayElements(i) = (Decimal.Parse(txtPieces.Text) * rangeA)
txtEarned.Text = FormatCurrency(priceArrayElements(i).ToString())
Next
Catch ex As Exception
End Try
Case 200 To 399
Try
For i As Integer = 0 To priceArrayElements.Length
priceArrayElements(i) = (Decimal.Parse(txtPieces.Text) * rangeB)
txtEarned.Text = FormatCurrency(priceArrayElements(i).ToString())
Next
Catch ex As Exception
End Try
Case 400 To 599
Try
For i As Integer = 0 To priceArrayElements.Length
priceArrayElements(i) = (Decimal.Parse(txtPieces.Text) * rangeC)
txtEarned.Text = FormatCurrency(priceArrayElements(i).ToString())
Next
Catch ex As Exception
End Try
Case Else
If Int32.Parse(txtPieces.Text) >= 600 Then
Try
For i As Integer = 0 To priceArrayElements.Length
priceArrayElements(i) = (Decimal.Parse(txtPieces.Text) * rangeD)
txtEarned.Text = FormatCurrency(priceArrayElements(i).ToString())
Next
Catch ex As Exception
End Try
End If
End Select
End Select
End Sub
End Class
|
|
|
|
|
Download ILSpy, and check out the code that your teacher wrote
As opposed to suppressing messages, you might want to log them to a file. If the '2' goes wrong due to an exception, you'd at least get a good message telling you what went wrong. Throwing away error-information is always a bad idea.
Bastard Programmer from Hell
if you can't read my code, try converting it here[^]
|
|
|
|
|
Quick thing I noticed:
Herboren wrote: Dim priceArrayElements(20) As Decimal
and
Herboren wrote: For i As Integer = 0 To priceArrayElements.Length
priceArrayElements(i) = (Decimal.Parse(txtPieces.Text) * rangeA)
txtEarned.Text = FormatCurrency(priceArrayElements(i).ToString())
Next
The length of priceArrayElements would be 21 (the total number of elements), however the highest index is 20. So in the for loop the last index it would try to use would be 21, however the highest index would be 20. Shouldn't the for loop be:
For i As Integer = 0 To priceArrayElements.Length - 1
Next
or
For i As Integer = 0 To priceArrayElements.GetUpperBound(0)
Next
|
|
|
|
|
Hi every one,
I have an application in VB 2008 and i have read somewhere there is a control named MDITabControl which includes en every Tab the close box.
I've been looking in the toolbox but i cannot find it, i tried to add it using the option "Choose items" but still cannot find it.
Does anyone know where can i find it and how to add it? Perhaps i need to add a reference to a library.
Anyways, any help would be aprecciated.
|
|
|
|
|
Not a native control; must be part of some third-party library. There are a few of them, with the number one Google result from CodeProject[^]. Unless you can point out where you encountered it, we can only guess which implementation you've seen.
Bastard Programmer from Hell
if you can't read my code, try converting it here[^]
|
|
|
|
|
I AM STARTER IN VISUAL BASIC 8
I WANT TO FIX ONE CONVERTER THAT WILL HAVE A DATAGRID
AND WILL LOAD CSV FILES
THE DATA GRID WILL HAVE 2 DIFFERENT COLUMNS THAT WILL LOAD
ABOUT 450 NUMBERS AND THEN I HAVE 10 TEXTBOXES THAT ANYNUMBER I WILL WRITE WILL THERE WILL CONVERT THE SECOND COLUMN DIGIT BY DIGIT
EXAMPLE
1234/1234
I WANT TO CONVERT THE NUMBERS OF THE SECOND COLUMN
LIKE THAT
1234/3455
I FIX THE CODE THAT WILL LOAD THE CSV FILE BUT I DONT KNOW HOW TO CONNECT THE LOADING FILE WITH THE DATAGRID
Private Sub OPENcsv_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles OPENcsv.Click
' Import
Dim openFileDialog As New OpenFileDialog()
'saveFileDialog.Title = "Open the input CSV file";
openFileDialog.InitialDirectory = Application.StartupPath
openFileDialog.Filter = "CSV files (*.csv)|*.csv|All files (*.*)|*.*"
openFileDialog.FilterIndex = 1
openFileDialog.RestoreDirectory = True
If openFileDialog.ShowDialog() = DialogResult.OK Then
Dim fileInput As String = openFileDialog.FileName
End If
End Sub
ANY HELP
THANK YOU
GEORGE MENIOS
|
|
|
|
|
memas63 wrote: I AM STARTER IN VISUAL BASIC 8
and apparently using the Web too. Using all capital letters is the same as walking into a room and screaming at people.
|
|
|
|
|
I am getting data from a third party soap service. Everything seems to be going fine. However, the client says not all the data that should be coming over is there. I don't have the data source to verify so I thought I'd ask:
Has anyone had a soap service return only part of the data?
The only thing I could think of is the response buffer, or recieved message size. I thought I'd get an error or nothing in either of those cases. Either way, they are set to 20000000 for both. I didn't write this code, I'm just trouble shooting it
My initial instinct, after running the code and rechecking everything is that they have changed something else in the management of this data and it's nothing to do with my software, which just fetches it and puts it in a database. The software hasn't changed in over a year and always worked fine until recently.
If it moves, compile it
|
|
|
|
|
Throw Fiddler on the client so you see what the service is returning.
|
|
|
|