I have a Silverlight app that connects to a php webservice. I want to encrypt the communication between the webservice and the Silverlight client. I'm not relying on SSL. I'm encrypting/decrypting the POST string myself using AES 256bit Key and IV.
The big questions then are:
How do I generate a random unique key/iv pair in PHP.
How do I share this key/iv pair between the web service and silverlight client in a secure way.
It seems impossible without having some kind of hard coded key or iv on the client. Which would compromise security.
This is a public website, there are no logins. Just the requirement of secure communication.
I can hard code the seed for the key/iv (which is hashed with SHA256 with a time stamp salt and then assigned as the key or iv) in PHP source code, that's on the server so that is pretty safe. However on the client the seed for the key/iv pair would be visible, if it is hard coded.
Further more using a time stamp as the basis for uniqueness/randomness is definitely not ok, since timestamps are predictable. It does however provide a common factor between the C# code and the PHP code.
The only other option that I can think of would be to have a 3rd service involved that provides the key/iv to the Silverlight client, as well as the php webservice. This of course start the cycle anew, with the question of how to store the credentials for accessing the key/iv distribution service on the Silverlight client.
Sounds like the solution is then asymmetric encryption, since sensitive data will be viewed only on the administrative back end of the website. Unfortunately Silverlight has no asymmetric encryption classes. The solution? Roll my own Diffie-Hellman key exchange! Plug that key into AES256!
The answers to your questions are: "SSL".
Symmetric encryption expands a shared secret of relatively small size (e.g. a 256-bit key) into a secure data transmission tunnel which ensures confidentiality and integrity. This is not as easy as it may seem; there are many small but deadly details.
Asymmetric cryptography is about establishing that shared secret over an insecure network. RSA encryption, Diffie-Hellman... are algorithms which can help you with that. You still have to begin somewhere; i.e., if you use the public key of the server (its RSA public key, its half of Diffie-Hellman...) then you must have some way to know that you are using the right public key, not the public key of some bad guy who intercepts the communication and feeds you his own key instead. There are ways to do that, mainly with hardcoding a public key within the client application, public key which is either the server public key or a key which can be used to sign it (that's certification). Of course, with Silverlight the client code is also downloaded, hence potentially tweaked by the same bad guy, so you would have to sign the code and have the browser verify that signature.
All this is hard work and has scores of pitfalls. The SSL protocol went through all of them, and was patiently but painfully updated and fixed. It took many years and many smart people, and there was much grinding of teeth. A similar protocol is SSH (some encoding details differ but the principles are the same). If you want to design your own protocol, then chances are that you will reenact most of the weaknesses and issues that plagued SSL and SSH. Simply using SSL or SSH would save you much time and trouble.
You could use a public/private key encryption system like RSA. The client would encrypt a packet using the well-known public key of the server, send the encrypted data, and the server would decrypt it using the secret private key. Anyone can send the server data encrypted using the public key, but only the server can decrypt it. Just like SSL does.
Which brings us back to the question: why aren't you using SSL?
Related
I'll start by saying I understand wanting to make data as safe as possible.
I have an app and I would like to just encrypt all of the information that can be used to personally identify someone in the database.
So I have read that it is terrible to store your key on the same server as the data. Okay so separate servers, no problem. Then I've read that It's terrible to put the key in the code on the app server (away from the data). People say that the proper way to store an encryption key is by using a HSM or a Key vault like Azure Key Vault. Ok, I am on-board with that but if my code has access to the HSM or the Azure Key Vault (which it would need to have in order to decrypt or access the data AT ALL...
If my code is stolen from the app server (which is why storing the key in the code itself would be insecure) Why couldn't an attacker just use the same method that my code uses to decrypt the data from the HSM or Key vault?
Assuming that it isn't safe to just store the key inside of the code itself.. How is it any different to have a method or a function that can decrypt the data in the code? That would essentially tell the attacker how to get the key from the vault anyway, wouldn't it?
What is the extra vector or layer that using an HSM or Keyvault prevents?
I don't mind paying for and implementing the extra layer. I am genuinely curious as I can't really see any difference.
I think your question is mainly about protecting secret keys in software vs. hardware key management solutions. the following links have useful information about their differences:
Usage of software/hardware-backed Android Keystore and possible security/usability drawbacks
https://www.itprotoday.com/iaaspaas/software-vs-hsm-protected-keys-azure-key-vault
if I understand your question correctly, it's because the application never sees the actual cryptographic keys. the HSM just exposes the primitive crypto operations, but never the keys themselves.
an attacker would therefore need to be logged into your "app server" in order to perform the operations, which is (hopefully) relatively easy to revoke/deny. if you had the keys available to the code itself then they could continue using the keys on any existing encrypted data until it has been re-encrypted after rotating in a new key. this also has associated assurance difficulties, e.g. how do you know the attacker didn't manipulate some data while this rotation was happening
I am currently working on a service which requires users to pick a 4-digit password/pin, because it is a mobile service. I am encrypting those passwords with either 256 or 2048bit encryption and it will be hashed. The account is blocked after 4 wrong entries, and can only be entered by mobile phone. Would it be hard to crack those PINs? I am asking this because sensitive information is being stored. The database is connected to a web application, the application is loaded to the phone using twilio. The thing I am most scared for is that the database is being hacked via the web. What would be a good way to keep sensitive data secure?
If someone gets hold of the database, you would be pretty much screwed:
If you just encrypt the 4-digit passwords, an attacker can just build a table of the 10000 possible encrypted strings and can trivially decrypt the PINs.
If you use salt strings (and encrypt not PIN, but PIN+salt and store crypted(PIN+salt) alongside with salt), people have to make a per-password effort, but there are still only 10000 possibilities for each password (which is not very much).
Which means, yes, by all means you should keep the database off the web. (If the web application is only ever accessed through twilio, you can reject connections from any other IP range).
Since you're using twilio, just make sure that twilo only talks to your web service using a secure protocol and reject any requests that you aren't sure are coming from a trusted source (that is, twilo). No real need for a pin at all.
This is a huge webpage on how to setup ssl between your web server and twilo. It even has a php example.
http://www.twilio.com/docs/security
If you use PKCS#1 1.5 or 2.0 RSA encryption (view the standards) you will also encrypt a random padding. This means that in transit, the PIN's cannot be compared, as long as the padding is kept secret and is truly random (this is not a salt which should be made public).
As for the database, it would be a good idea to move it out of the normal operations as much as possible. Create a simple service that just checks the PIN after decryption, make sure you don't have buffer overruns etc. on that, and if possible, use a different machine and access rights than the production server. Really test this part well, as the interface is small, it should not be difficult.
If you and the phones are up to it, you might want to try ECC, but that's not for the meek. RSA encrypt normally uses a small public exponent (0x010001 is highly recommended) so it is faster than ECC for the phone. On the server (and during key creation) ECC is much faster. I would not recommend symmetric cryptography (AES/3DES) for this.
Oh, and include the public encryption key in the application (for implicit trust), don't send it over from the server. Keep the private key secret and inaccessible for anything other than the already mentioned service.
The interface you describe sounds secure to me. It's secure enough for ATMs!
Are the encrypted PINs easy to crack? Yes, there's only 10000 possible combinations and a rainbow table can be generated of all the possible encrypted values unless you salt. However that would require access to the encrypted PINs which means the attacker already has a copy of your database.
So really you need to ensure your database server is secure. There's a lot of variables that could make it insecure so it's a big question. Instead you could rely on third-party solutions like Amazon S3 or others and concentrate on coding instead of security. Let them do the hard work!
You should use good quality password salting technique to prevent against hacking passwords. Check the wikipedia article to know more about salting. Salt Article
Recently we've been diving into using OpenSSL to help encrypt/decrypt some data we have. Each "client" will have Public/Private key pair and X509 Certificate given to them by a local Certificate Authority. I'm now looking into encrypting/decrypting data with that key pair.
Everything I've looked into show using the methods RSA_public_encrypt and RSA_private_decrypt for RSA encryption. But the amount of data I can encrypt at once is limited by RSA_size(rsa) - 41 for the padding type RSA_PKCS1_OAEP_PADDING. So my question is how to encrypt larger amounts of data while sticking to our RSA scheme (no static keyphrases, etc). I was thinking about breaking the data up into chunks and then encrypting it but that seems like it's defeating the point of padding.
Any help would be appreciated.
Even if you break the data, you will find out, that the speed is prohibitively slow. The right method is
Generate random key for symmetric algorithm
encrypt the data using symmetric algorithm and the random key
encrypt the random key using your public key and store it in the encrypted form next (or before) the data.
You should use a standard like CMS (the basis of the S/MIME support in your email client) or PGP. There are libraries for both of these standards for just about every platform.
You will find that they are very similar in their approach to bulk data encryption, using a symmetric cipher to encrypt data and encrypting that secret key with the public key of the "message" recipients. This approach is secure and fast.
However, these standards go further, securely handling things you might not have thought about yet, like encrypting the data for multiple recipients, attaching meta-data to the encrypted content, etc. You also get interoperability with other software. For example, if you use S/MIME, you can use just about any email client on any platform to decrypt. In fact, depending on your integration requirements, you might not need to write any software yourself.
Using one of these well-established protocols won't solve all of your security problems, but it will make it more difficult to do something really dumb.
In some project we have very that even our staff is not suppose to have access to. In theory, we have policies to ensure they don't. In practice, we are in Africa and policies don't mean a lot, no matter how strongly you enforce it.
I would like to know is there is a way to encrypt data in your database so:
each user password encrypt and decrypt its own data, and its own data only;
data is decrypted as late as possible in the process to ensure maximum security to the user. Ideally it would be on the client side I guess, but I'd love to hear that it's possible to do some crazy thing I don't know about on the server side.
data is still searchable. Is that even possible?
My first idea was: "if a customer want THAT level of protection, then give him its own hosting on a virtual machine and encrypt the hardrive, then all maintenance must be done with it's allowance".
I can't come up with a fancy strategy just how I've implemented this:
Keep in mind that you have to re-encrypt everything when the user changes his password. I'm using always the same encryption key but the key is encrypted using the user's plaintext password. So I just have to re-encrypt the key. The user's password is stored as a salted hash so nobody can decrypt the key and the data even if he sees the hash.
It works like this:
User enters his plaintext password
Create salted hash
Check if the generated hash matches the one in the database (authentication)
If yes, then decrypt the key for the data using his plaintext password
Decrypt stored data using the key
This won't give you 100% security but improves it.
Here are a few things I can think of:
You should encrypt data stored when it is stored in the and when you read it back. Use a solution that integrates at an RDBMS level rather than the data layer.
For the transport of data to and from the application, use HTTPS web services.
If you have a Desktop application, do not store any data and log files etc locally.
If it is a web app, make the app HTTPS as well.
Security is bound to make the app a little slower than using plain data, but that's the price you will pay.
It really depends on what and where (on the client or server) you are doing with the data.
For example, your application don't need to know the password itself to verify it during authentification. Best practice for this use case is to store only a cryptographic hash (e.g. sha1) of the password and a random salt. That is sufficient to verify it, but giving only the hash and salt, it would take a nearly infinte amount of time to figure out the plain password.
Encryption can be a soultion if you have to exchange data over unsecure channels. But keep in mind that in order to process the data you have to decrypt them. So if de- and encryption is done on the same machine, it's rather pointless. And if decryption is required it doesn't matter how late you are going to do it, because of the key must be given anyway.
You can use encryption to secure the communication between the server and the client, for example. You could even generate messages on the server that only the client will be able to read and vice versa using asynchronous encryption. So once the message was generated on the server and encrypted using the client's public key even the server isn't able to read the message anymore, because of the private key only the client knows is required for the decryption.
What you denfinetly can not solve by cryptography is, when you have data on the server, that the server should be able to read in order to process them but human users unrestricted with priveleages to this server shouldn't.
I am trying to devise a security scheme for encrypting the application level data between a silverlight client, and a php webservice that I created. Since I am dealing with a public website the information I am pulling from the service is public, but the information I'm submitting to the webservice is not public. There is also a back end to the website for administration, so naturally all application data being pushed and pulled from the webservice to the silverlight administration back end must also be encrypted.
Silverlight does not support asymmetric encryption, which would work for the public website. Symmetric encryption would only work on the back end because users do not log in to the public website, so no password based keys could be derived. Still symmetric encryption would be great, but I cannot securely save the private key in the silverlight client. Because it would either have to be hardcoded or read from some kind of config file. None of that is considered secure. So... plan B.
My final alternative would be then to implement the Diffie-Hellman algorithm, which supports symmetric encryption by means of key agreement. However Diffie-Hellman is vulnerable to man-in-the-middle attacks. In other words, there is no guarantee that either side is sure of each others identity, making it possible for communication to be intercepted and altered without the receiving party knowing about it. It is thus recommended to use a private shared key to encrypt the key agreement handshaking, so that the identity of either party is confirmed.
This brings me back to my initial problem that resulted in me needing to use Diffie-Hellman, how can I use a private key in a silverlight client without hardcoding it either in the code or an xml file.
I'm all out of love on this one... is there any answer to this?
EDIT:
Remember that this is about a custom PHP web service that I rolled out on my own.
I found an RSA implementation i can use in Silverlight. It seems pretty safe to use this to encrypt the handshake for the DiffieHellman key agreement between the Silverlight client and PHP web service, and subsequently also use it to encrypt the symmetric key that was agreed upon (which is itself generated from the result of the key exchange by hashing it).
After this I'm pretty much guaranteed that all communication going to the web service has not been intercepted, modified and then retransmitted (MITM). However I believe it is still possible; technically, for an attacker to impersonate the silverlight client and send messages to the webservice (assuming they discover the url).
Security from unauthorized access is provided since the attacker does not know the "secret api" of my custom webservice, hence they are unable to communicate with it.
The only way to break this would be to brute force the webservice with whatever strings an attacker may suspect to be valid to try and get a response from the web service. I don't think you can brute force a variable length string. It sounds impractical.
Does anyone see a problem with this approach?
SSL/TLS suffers from the same problem that any Diffie-Hellman-based implementation you come up with would have, in that it can still be broken by a man-in-the-middle attack.
The reason TLS is secure and trusted is because the client, when receiving the server's certificate, authenticates it by checking that it is signed with another certificate from a known trusted identity - say, VeriSign. Thus far, this makes it impossible to enact a man-in-the-middle attack without having VeriSign's private key - when the interloper sends a fake certificate proclaiming to be the server, the client would easily detect that this certificate is not signed using the trusted identity's certificate, and bails out of the connection, displaying a warning to the user.
For your purposes, it's likely easiest to use TLS. To make it secure, you would generate a certificate for your server, and then embed in your client the public key for that certificate. The client can then verify that it is talking to your server, without having to expose the private key, which you don't have to distribute.
EDIT: In response to your comment on Jerry's answer, if your hosting provider doesn't allow SSL/TLS connections at all, preventing a man-in-the-middle attack will be tricky. If this is your only reason for avoiding TLS, I would suggest getting your provider to turn it on, or finding a provider that allows for it.
EDIT: In response to your edited question: even if you're now using RSA in your Silverlight client to send data to your web service, you cannot guarantee that the client itself has not been modified. It's quite possible for an attacker to dig into your client, determine the algorithm you're using to perform the encryption/handshake, and then write code to impersonate your client (or indeed, modify the client to include their code). Once they've done that, they can start analyzing your API and use it to make calls to your web service.
It's the same with SSL/TLS - the client can validate the identity of the host using the host's certificate, and as long as the host's server is secured, the client can trust the output from the host; however, there is no mechanism in which the host can 100% validate that the client is who they say they are, as the client will be run on a machine which does not have a controlled execution environment.
However - despite the above being true, and that it's possible that an attacker can compromise your system in this way, it's likely not probable -- unless you're working on a public-facing system that attracts a lot of attention/use, or a system that deals directly with money in some form, the attacker needs to make some effort before being able to send their own input to your web service.
Your best bet is to validate the input received by your web service thoroughly, and don't leave dangling APIs accessible that your regular client would never use.
The obvious solution would be to use WCF to establish an SSL or TLS connection instead of attempting to build that into the application.
I recommend starting with this JavaScript+PHP DH key Exchange protocol:
http://enanocms.org/News:Article/2008/02/20/Diffie_Hellman_key_exchange_implemented
You can then re-write the javascript in silverlight. I recommend using Wireshark to dump packets then you can use Meld or whatever to diff the packets to see where your implementation is differs from the original.
Good Luck!
(Disclaimer: I totally agree with the Enano dev team, this is not a full replacement of SSL and SSL should be used whenever possible.)