I was thinking about creating a Web app that would let people enter text (using SSL connection) and it would be encrypted before saving to the DB. The goal would be to have it so that only users could decrypt it.
You could have the users enter the key along with their data, and enter it again when they want to see the data, and not store the key. That would be kind of painful for the user, though.
However, if you stored the key on the server you'd have access to it and could potentially decrypt their data.
I don't think it's possible to do it without either having the user enter the key every time or storing the key, but is there some way that I'm not thinking of? Like maybe generating a key from information only the user knows? Something involving cookies?
You should look into public key cryptography. The basic idea is that you can encrypt information using a public key that only the holder of the private key can decrypt. In your scenario, the server would have a record of all the users' public keys and use them to encrypt the information. Then your users would use their private keys, which the server never sees, to decrypt the data.
If you're looking for a way to store the private key client-side, you could look into PersistJS.
Sounds like you could do something using PGP. As a previous post mentioned you would have a public and private key. The private key can be secured by a passphrase. That way you could have the private key potentially stored on the db, since it would still require a passphrase to use it.
The huge problem is that if the user should forget that passphrase, they could lose that data. You could get around that by using an Alternate Decryption Key (ADK). That key is automatically encrypted with everything and can be split between multiple individuals.
From an information security perspective, this only makes sense if the encryption/decryption is done on the user's computer, and not your server (since there's no guarantee that you're not storing the key and/or the plaintext). JavaScript is out of the question, so you need a client application*.
Also, public-key cryptography is computationally expensive. You might want to keep that in mind if you have a lot of users and decide to do encryption/decryption on the server.
* or a Java applet, but that's so 90's. Silverlight or Flash could potentially work, too.
Related
I was wondering in which use case i should use these methods when encrypting and decrypting files in my node.js application.
The Problem
I want to encrypt some files in my server, after asking other people, i realized that the most recommended method is encrypt those files (larges) using a private key.
Now, i was looking for the docs and saw these methods
crypto.publicEncrypt(pubKey, buffer)
crypto.publicDecrypt(pubKey, buffer)
crypto.privateEncrypt(privKey, buffer)
crypo.privateDecrypt(privKey, buffer)
this is very confusing because i don't know what of them i must to use now, ahm... i don't know what is the most appropriate way to do this securely.
tl;dr encrypt with the public key. Keep your private key safe.
Unfortunately, these methods are poorly named. privateEncrypt should be called something like sign and publicDecrypt should be called something like verify.
When using public-key encryption (also known as asymmetric encryption), one key can be used to write a cipher and the other key can undo that operation. Your public key is potentially known to everyone, and your private key is secret.
If you want to keep something secret, except from the owner of a certain key, you want to encrypt a message with their public key. So if Alice wants to receive encrypted messages, she'll share her public key A_pub and her secret key A_priv, she'll keep to herself.. You'll encrypt your message crypto.publicEncrypt(A_pub, buffer). She'll then decrypt that message with crypto.privateDecrypt(A_priv, buffer).
Doing it the other way is known as a digitial signature.
I am currently working on a project with a lot of security and I am having a bit of a problem choosing a technical solution to satisfy my customer need.
First things first, let me explain you the customer need.
For my customer's website, at some point a user needs to generate a private key and public key client side (gui : browser) then send the public key to the server and save the private key (crypted by a user choosen password) locally. The private key needs to be saved because it is used once in a second part of the process (the user needs to enter his password in order to decrypt it), once used we can dispose of the private key.
I have to add that the customer requests backward compatibility to IE7.
First technical choice : Java Applet
The first thing we looked up is to use a Java Applet, generates the keys just fine, but we enconter a problem on Safari Mac OSX, the appet is sandboxed and the user needs to perform a complicated action to disable sandbox mod. Our customer does not want this as it is not user firendly.
Second solution : Saving crypted private key in a cookie
We kept the java applet, but it does not save anything on disk, it is only used to perform cryptographic actions. We passed from the applet a crypted private key to the javascript to save in a cookie. We did it fine and we can retrieve the crypted private key from the cookie store and pass it to the applet to decrypt (with a popup requesting the user to enter his password).
Question
We know that it is technically doable to save a crypted private key in a cookie, but the question is : is it secured, what kind of risks are we taking saving that private key in a the cookie store of the browser?
It would help me a lot if one of you could help me!
Cheers
The main problem is that cookies are only meant for things you are sending to the server. They are not meant for storage and you should not be sending your private key anywhere, ever.
Cookies can be stolen via XSS (always assume you have an XSS vuln in your site) and the attacker can then try to decrypt it.
On the grand scale of things you could do a lot worse. Assuming your crypto is solid, the private key is probably safe, but the big issue is that you shouldn't be using cookies like this. Using Web Storage is probably a far better solution here.
I´d say that saving your private key in a cookies isn´t a really good choice since they are not supposed to hold sensitive information due security reasons, and our colleagues already told other reasons.
It´s also important to notice that the user may clear all his cookies at any given time or disable it at all.
The applet would meet better your customer requirements and would let you for example prompt the user to save a keystore file with the private key, this kind file was designed to hold this kind of information.
Cookies are sent in each request. This is really really bad because you want the private key to not sent over the network as much as possible.
Assuming you can't have local storage (IE7), the only way I know to store info on the cient side is cookies. I'd say : use local storage as much as possible, and when you can't, store the private key on the server side. At least, you'll be sending it once. it's bad, but less than really really bad ...
Or maybe you could store cookies on a dedicated subdomain that you never use again, but in order to read the cookie, even on the client side with javascript, you need to be on a page of that subdomain, and that means sending the key over the network again everytime you want to use it.
As far as I know.
You could use localstorage then just deploy localstorage polyfill for IE7
I'm wondering if it's possible to encrypt text client side.
The situation is that I have a block of text I want to encrypt, and then save the encrypted text to a file. Only after a certain amount of time has passed will my program decrypt it. Another requirement I have is to be able to transfer the file with the encrypted text and be able to decrypt it with other copies of my program on various machines.
The problem is where to store the key. The only implementation I can think of that would work is if I store the key server side, and have it return the key after a certain time has passed.
Is there a way to do this client side (i.e. without any internet access)?
You can surely encrypt text on the client side, but the real problem is key management.
If the assumption is no Internet access, then you're going to have to package a certificate in the client that contains both keys, private to encrypt, public to decrypt, unless you use a symmetric key. Was going to suggest just generating a local, temporary symmetric key, but you state you must be able to decrypt the text on other machines that won't have it, so that won't work. At first blush, and maybe I'm overlooking something obvious, is packaging a cert on the client with public and private keys, and that introduces its own set of problems, eg protecting the cert with the private key.
I'd like to encrypt the user data I store on my server so that it is safe if my server were to be compromised. Is the following a good way to do it:
Each user's password is the passphrase to a GPG keypair. All the user's data is encrypted using the public key before being saved to the database. The password is discarded and the keypair is kept only for the duration of the session, so the data can only be decrypted when the password is supplied.
From the point of view of someone compromising your server, the only way to ensure the data is safe is the way you are doing, when the user have to supply the key to decrypt every time.
Any other technique leaves some weakness that could be exploited.
But you have to be sure the other way (I mean when user provides the password) is secure too, using https and preventions against session attacks, cross scripting and etc.
If you do not have specific hardware to do an extra line of protection as when they are generated pseudo-random numbers based on time (as do the banks tokens) or something like that, the best idea is to keep the keys with the user or to use a third part storage with greater security as the SQL on Azure or Amazon.
I used the same approach after thought a lot about where to put my encrytion keys to make data obscure even if my server got compromised. The only secure way I found was "with the user".
your approach protects you from only 1 attack: stealing your database (and only if you encrypted keys properly). if your server gets compromised they can take your ssl private key and listen your network traffic (with users' keys)
I have a database that contains sensitive information. I can encrypt / decrypt the data on the read write operations. The problem is that I need to store the key in the application. If someone has hacked their way in such they have access to the database then they can also grab the application (java) decomplie it and pull the key.
This seems like a speed bump at best. What other solutions are available?
The only thing you can do is make it difficult to extract the key from your application. You can't make it impossible. If you give someone a box with contents that you're trying to protect, you have to give them the key if you want them to be able to access the contents. Once you give them the key they can do whatever they want… if they take the trouble of finding the key.
This is a case of Bob and Eve being the same person, you want to give Bob access but stop Eve from seeing it.
This is DRM, it doesn't work.
I am assuming you have some way to verify the credentials of the user before allowing them to access the database?
Usually the architecture for these kinds of things is as follows:
Database
Server
Client
The Client connects to the Server, which then connects to the Database.
The Server makes sure the Client authenticates correctly before allowing them access to sensitive information. The decryption key is stored only on the server. Noone should have access to the server, and especially the file that contains the key. This way the clients do not have any encryption/decryption they have to do, and do not have to store any keys.
Read up on keystores.
Require the user to enter a passphrase to access their data. Burying the key in the code is security by obscurity.
Store the keys in a CSP container. Consider the Java CSP here .
This is IMO the safest way possible. But you can also consider storing the key in a file which is protected by the operating system using some kind of ACL.
require the user to log in using a strong password; use the password as the key for a symmetric encryption algorithm to decrypt the asymmetric database key
keep the db key in secure memory while the application is running (if that is an option)
Encrypt the key (using DPAPI), put it in a file, put an ACL on that file etc...