Need suggestions on how to create a website with an encrypted database - security

I want to create a website where a user enters content (say a couple of sentences) which eventually gets stored in a backend database (maybe MySQL). But before the content leaves the client side, I want it to get encrypted using something on client like maybe javascript.
The data will travel over the web encrypted, but more importantly, will also be permanently stored in the backend database encrypted.
Is JavaScript appropriate to use for this? Would 256 bit encryption take too long?
Also, how do you query an encrypted database later on if you want to pull down the content that a user may have submitted over the past 2 months?
I'm looking for tips, suggestions and any pointers you guys may have in how to go about learning about and accomplishing this.
Thanks!

You shouldn't implement the encryption for the communication between the client and the server yourself, use SSL (https) for that. As for encrypting data in the database, you can always use MySQL's built-in methods, such as AES_ENCRYPT and AES_DECRYPT, see reference manual for details.

Look at http://www.farfarfar.com/scripts/encrypt/ (encrypt/decrypt).
Tried text/text/XXTEA with success.
However, that's about as far you can go with JS encryption.
As long as you're not using SSL/https, the main disadvantage is:
A fuzz to protect the private key, (it can be done though, like a form field, not submitted, but requires user to enter value on each session.)
About searching/extracting data on encypted data, I belive nothing is going to work.

Well, to point out something: if it's client side encrypted, it'll likely also be easily decrypted, seeing as with languages like javascript, they're being handed the source code of your encryption scheme. Plenty of encryption schemes out there, AES, Blowfish, etc, but if the data is traveling on an encrypted connection, I suppose the encryption of the data only adds very little security, maybe packet sniffers locally installed or something to that effect.
I would also suggestion you look into using compression as well, I myself have used LZMA, Huffman, and even base64 encoding with javascript to at least obscure the content from casual observers. Point being, no matter how good the encryption, you're handing over the process to the client, and they can just view your source and be able to easily reverse the encryption, given that they know the encryption scheme and aren't to lazy to do a bit of Googling or searching on Wikipedia. I personally prefer compression because it also reduces the size of the data being sent, and unless one is trained in analysis of encryption and compression, it is isn't easy to figure out the compression being used from sniffing packets.
EDIT: But if you want high levels of security, I would suggest against using just compression, and instead, using an asymmetric encryption method like RSA or Diffie-Hellman encryption on data traveling between the server and client, as the private key will never be shared.
For client side, javascript or better, a Java application, would work (at least you can't right click -> view source with a Java app in two seconds). 256 bit encryption wouldn't take too long if you're just wanting to save a few sentences like you said. A modern processor with blast through that in milliseconds. Then, when it arrives at the server, encrypt it using AES or another powerful algorithm (note that the US government uses AES 256 for their Top Secret documents) before sending it to the database. (Also want to add that you can also store a hash (MD5 is a function readily available in PHP, you can opt for something like Whirlpool as well, but you'll have to find a library for that) of the data on a separate database, and check against it when you access it to ensure that your database hasn't been compromised)
For querying, I suggest PHP. Read the data, decrypt it, then send to the client (in still encrypted form), or if you want, and have the client decrypt it also, if you don't trust the networks the data is being sent through.
Here's a good source on Javascript and AES: http://point-at-infinity.org/jsaes/
My two saved links using RSA in javascript: http://www.ohdave.com/rsa/ and http://www.hanewin.net/encrypt/rsa/rsa.htm

As for the data being sent over the network encrypted, this is the kind of thing that HTTPS was made for. Nothing is transmitted in the clear. It's encrypted securely enough for most banks to trust it. Don't reinvent the wheel here; it'll never be as round as what a bunch of people who make wheels for a living have come up with.
Have your form submit to an https:// url (rather than http://), and the script/app at that URL talk to the database, encrypting and decrypting the data as needed. Javascript won't easily talk directly to MySQL anyway, and if you do all the encryption client-side, anyone who can get the page can still decrypt it (since by necessity the client would need to be given the decryption key as well).

Check out this blogpost: http://www.ravellosystems.com/blog/all-you-need-to-know-to-configure-ssl-offloading/
It takes you through all the steps you need to do to configure your webs server to serve content under an encrypted channel (a.k.a SSL termination).

Related

ABAP Secure Storage: how to store passwords?

I never needed to store passwords in an ABAP System.. now it's time to learn something new...
I need to store a password, which I use on an ABAP System to connect to a different system, so I cant store a (oneway) hash.
I came across some function modules like FIEB_PASSWORD_ENCRYPT (which is using a hardcoded key) or some suggestions of storing a base64 encoded version of the password (gosh!) => both would only prevent anyone from "quickly reading" the password if it is on the screen, not prevent anyone from stealing it.
I also came across SECSTORE (SAP Help Link), which apparently is only usable by SAP components not by custom applications.
Basically, my need is
store password in some DB table in encrypted form
impossible (at least very hard) to get the pw by plain select on that table
get from the DB table in clear form to be able to pass it to the "other system"
I don't want to re-invent the wheel, especially not in a security area.
I think, there MUST be something there that can be used for that purpose...
UPDATE Why do I need that:
I'm accessing an HTTPS System (destination type G) and all connection params are configured in the destination.
unfortunately, a PW needs to be transmitted in body as form parameter
Disclaimer: I am in discussion currently whether this can be turned into basic auth, which is neither more nor less secure (header vs. body). But with basic auth, I can use the destination config, which in turn uses SECSTORE. This discussion is a long story as many parties are involved and the access to the system is multi-layered...
You can use SSF_KRN_ENVELOPE function for encrypt and SSF_KRN_DEVELOPE for decrypt. It use RSA standart so result may be huge. I prefer use ABAP AES class at https://github.com/Sumu-Ning/AES
These functions using system certificates, AES library needs IV and keys so if user has debug or developer authorization he can get get it.
Correct way is using standard ways for communication. For example using SOAP client with basic authentication and save password in SOA manager. Also basic authentication can be used http and https protocols in SM59 configuration.
The option I post here is an option without encryption, but seems "quite secure (tm)". Feel free to comment
store the password in a DB table as plain text
set that table as "N : display/modification not allowed"
create a program for writing the PW into that table
there is no probram that will output the PW.
This means that, in a productive ABAP environment, only someone with at least one of the following permissions can access the PW (correct me if I am wrong)
Debugging permissiosn on production (basically no-one)
direct DB access (basically no-one)

How would I achieve encryption/decryption for users, while also having the ability to decrypt everything serverside

I'm not entirely sure if I should be encrypting data server side or client side to begin with. The data is a json object of some user input. What I need to be able to do:
a) encrypt data at rest [in dynamoDB]
b) decrypt data and send it back to the user when they request it
c) decrypt the entire database to run analytics and ML
First Approach
1)Send the newly inputted user data through HTTPS, then encrypt it server side before it hits the database (in a lambda function). Now the data is encrypted at rest.
2) When a user makes a GET request, have a lambda function that decrypts it before returning it to the user
3) simply run a decryption on the database with the same technique
I'm not sure if this is good or bad, what type of encryption to use, etc.
EDIT: I will be doing server side encryption. If anyone has any suggestions/guides on a simple but good way to do it, perhaps using some npm package, that would be great.
Question 1: Encrypt server side or client side?
The only advantage of client-side encryption would be performance: remove the burden of your server from doing this work, pass it off to the end user machine.
However, there is a very big disadvantage: security. If you are encrypting everybody's data with the same key, then now everybody has access to that key, because it needs to be delivered to the client for decryption. You have entirely defeated the purpose of the security, because the cryptographic key now lives everywhere.
What about encrypting every user's data with different keys? That's a can-of-worms question, because you need to then consider where you are storing all the cryptographic keys. If it is in the same database as the data, you have again defeated the purpose of encryption -- putting the keys and data together is a no-no. You can come up with arbitrary solutions around this, but I assure you there are many considerations and you are inviting a lot of complexity.
Question 2: Is your approach reasonable?
Yes it is, but you need to understand what you are protecting against. Encryption at rest mainly protects a database (including backups) provided that the encryption key never gets put in the same place as the database. Managing the encryption key is something that needs to be carefully considered. There is good guidance on that if you care to research it, but it really is the task of a security architect to design this right.
You can use AES encryption using cryptojs.
Hit the server to get key for using in encryption process.
let AES = CryptoJS.AES()
// AES encryption
let encryptedUsername:String! = AES.encrypt(secretMessage: (username_tf.text)!, secretKey: REQUESTKEY!)
let encryptedPassword:String! = AES.encrypt(secretMessage: (password_tf.text)!, secretKey: REQUESTKEY!)

is client based online encryption practical?

I'm wondering whether a mechanism exists that allows client to client encryption. For example, when enabled, any information that is entered on one client can only be decrypted using a specific key.
Similar to how regular public key transactions work, but server agnostic.
A use case:
Everything on my Facebook profile is encrypted, and no body would be able to view that information (not even facebook). The users that I give the key would be able to decrypt that information.
This would allow complete control of data stored online.
The same idea can be applied for pictures uploaded to the internet.
One issue that I see is to have a practical mechanism to manage keys and a secure way to distribute keys to other users.
Has anyone done something like this before?
In case of Facebook I can imagine encrypting the data with OpenPGP keys into armored (text) format. Then you can place encrypted block to facebook or anywhere else. Other users would take the block, decrypt it on the client side and see it.
The same applies with other social networks and places where you can store some text block.
You can easily do encryption in some client application and even in Javascript (if you manage to make JavaScript load local user's keys somehow).

Mobile API Security Paradigm

I've coded the mobile api using Node.js, Redis & MongoDB. However right now I am looking for a concrete way to provide security in our system. The question I have inspired by the infamous principle of Auguste Kerckhoff;
"It must not be required to be secret, and it must be able to fall into the hands of the enemy without inconvenience"
After inspecting this principle I figure out that there is no safe way to secure data after a sniffer capturing the entire data package. Of course there are alternate ways like using an API key, using encryption algorithms like MD5 & MD6,Triple DES,SHA1 etc. However this also won't work if the entire data package is captured. And there is security precaution standarts like HTTPS, SSL certificates. However again if someone with talent captures the data package it can act just like a verified user in our system.
How would it be possible to apply a security method such that even though the entire data package is captured, the system would be able to distinguish the request coming from an outer source not from our verified user.
PS: I thought that applying a custom encryption algorithm with timestamp in order to prevent this problem could be a bit chaotic.
According to Kerckhoffs's principle "A cryptosystem should be secure even if everything about the system, except the key, is public knowledge." So the way cryptosystem, works is that the key is the only thing that can be used to decipher the system. If the key is fallen to the enemy then its all over.
In practice when you communicate over the internet or try to
authenticate your email account with the password. Your password is
never sent to, nor stored on the server in plain text. If you do then,
its not secure. The best security practice is not to store the
password at all (not even encrypted), but to store the salted hash of
the encrypted password.
That is one hash for one user. It is one way, you cannot get back user info, just test if it is in the database or not. Now even if the enemy takes control of the database, it cannot access your username/passwords.
Now coming to the point, it does not matter what you transmit in the communication channel, because the communication channel is the enemy!!! It is available to other users, anyone can sniff it. It is like enemies scanning each other on the radio.
The hash that has been sent over the channel can be sniffed and be used for authentication. True, but server can differentiate between spoofed attempt and the actual attempt, using HTTPS connection. Server tracks the HTTPS sessions and would ask to revalidate if something like this happens. HTTPS blocks use of sniffed data / MITM attacks. Even if sniffer gets hash (temporary ticket), he cannot do anything malicious, username and password cannot be cracked.
Thanks to Kerckhoff, our passwords are safe.
How to implement it on node.js ?? look for passport.js package. It implements the current standard OpenAuth.

How can you encrypt users' data server-side without ruining the experience?

Many users – myself included – would like the security of having everything they do on a web service encrypted. That is, they don't won't any one at the web service to be able to look at their: posts, info, tasks, etc...
This is also major complaint in this discussion of an otherwise cool service: http://news.ycombinator.com/item?id=1549115
Since this data needs to be recoverable, some sort of two-way encryption is required. But unless you're prompting the user for the encryption key on every request, this key will need to be stored on the server, and the point of encrypting the data is basically lost.
What is a way to securely encrypt user data without degrading the user experience (asking for some key on every request)?
-- UPDATE --
From #Borealid's answer, I've focused on two possibilities: challenge-response protocols, where no data (password included) is sent in the "clear", and non-challenge-response protocols, where data (password included) is sent in the "clear" (although over HTTPS).
Challenge-response protocols (specifically SRP: http://srp.stanford.edu/)
It seems that its implementation would need to rely on either a fully AJAX site or using web storage. This is so the browser can persist the challenge-response data during encryption and also the encryption key between different "pages". (I'm assuming after authentication is completed I would send them back the encrypted encryption key, which they would decrypt client-side to obtain the real encryption key.)
The problem is that I'm either:
fully AJAX, which I don't like because I love urls and don't won't a user to live exclusively on a single url, or
I have to store data encryption keys in web storage, which based on http://dev.w3.org/html5/webstorage/ will persist even after the browser is closed and could be a security vulnerability
In addition, as SRP takes more than one request ( http://srp.stanford.edu/design.html ), there needs to be some persistence on the server-side. This is just another difficulty.
Traditionally
If I'm ok transmitting passwords and data in the clear (although over HTTPS), then the client-side issues above are not present.
On registration, I'll generate a random unique encryption key for the user, and encrypt it using their password and a random salt.
In the database, I'll store the user's password hash and salt (through bcrypt), encrypted encryption key, encryption key salt, and encryption iv.
After an authentication, I'll also need to use their password to decrypt the encryption key so that they may view and enter new data. I store this encryption key only temporarily and delete it when they explicitly "log out".
The problems with this approach is that (like #Borealid points out) evil sysadmins can still look at your data when you are logged in.
I'm also not sure how to store the encryption keys when users are logged in. If they are in the same data store, a stolen database would reveal all data of those who were logged in at the time of theft.
Is there a better in-memory data store for storing these encryption keys (and challenge data during an SRP authentication)? Is this something Redis would be good for?
If the data need to be recoverable in the event of user error, you can't use something like a cookie (which could get deleted). And as you point out, server-side keys don't actually secure the user against malicious sysadmins; they only help with things like databases stolen offline.
However, if you're running a normal web service, you've already gotten pretty lucky - the user, in order to be unique and non-ephemeral, must be logged in. This means they go through some authentication step which proves their identity. In order to prove their identity, most web sites use a passed credential (a password).
So long as you don't use a challenge-response authentication protocol, which most web sites don't, you can use an encryption key derived from a combination of a server-side secret and the user's password. Store the encryption key only while the user is authenticated.
If you do this, the users are still vulnerable to sysadmins peeking while they're using the service (or stealing their passwords). You might want to go a step further. To go one up, don't send the password to the server at all. Instead, use a challenge-response protocol for authentication to your website, and encrypt the data with a derivative of the user's password via JavaScript before uploading anything.
This is foolproof security: if you try to steal the user's password, the user can see what you're doing because the code for the theft is right there in the page you sent them. Your web service never touches their data unencrypted. This is also no hindrance to the normal user experience. The user just enters their password to log in, as per normal.
This method is what is used by Lacie's storage cloud service. It's very well done.
Note: when I say "use foo to encrypt", I really mean "use foo to encrypt a secure symmetric key which is then used with a random salt to encrypt". Know your cryptography. I'm only talking about the secret, not the methodology.
None of those other solutions are going to maintain the feature set requested -- which specifically wants to preserve the user experience. If you look at the site referenced in the link, they email you a nightly past journal entry. You're not going to get that with JavaScript trickery per above because you don't have the browser to depend on. So basically this is all leading you down a path to a degraded user experience.
What you would want, or more precisely the best solution you're going to find in this space, is not so much what wuala does per above, but rather something like hush.com. The handling of user data needs to be done on the client side at all times -- this is generally accomplished via full client-side Java (like the Facebook photo uploader, etc), but HTML/JavaScript might get you there these days. JavaScript encryption is pretty poor, so you may be better off ignoring it.
OK, so now you've got client-side Java running a Journal entry encryption service. The next feature was to email past journal entries to users every night. Well, you're not going to get that in an unencrypted email obviously. This is where you're going to need to change the user experience one way or the other. The simplest solution is not to email the entry and instead to provide for instance a journal entry browser in the Java app that reminds them of some old entry once they get to the website based on a link in the daily email. A much more complex solution would be to use JavaScript encryption to decrypt the entry as an attachment inline in the email. This isn't rocket science but there is a fairly huge amount of trickery involved. This is the general path used by several web email encryption services such as IronPort. You can get a demo email by going to http://www.ironport.com/securedemo/.
As much as I'd love to see a properly encrypted version of all this, my final comment would be that journal entries are not state secrets. Given a solid privacy policy and good site security semantics, I'm sure 99% of your users will feel just fine about things. Doing all this right with true security will take an enormous amount of effort per above and at least some design/UE changes.
You should look into the MIT project CryptDB which supports querying an encrypted database using a subset of SQL. (see the forbes article, mefi thread, or Homomorphic encryption on wikipedia)
There is the Tahoe-LAFS project for cloud storage too, which conceivably could be leveraged into a fully anonymous social networking application, one day in the distant future.
If you want to perform computations on a server without even the server being able to see the data, you may be interested in knowing about fully homomorphic encryption. A fully homomorphic encryption scheme lets you perform arbitrary computations on encrypted data, even if you can't decrypt it. However, this is still a topic of research.
For now, I guess your best bet would be to encrypt all posts and assign meaningless (e.g. sequential) IDs to each one. For a more in-depth discussion of how to encrypt server-side data with today's technology, look up.

Resources