New to cryptography, and trying to get a high level understanding of e2ee. My current grasp of it is that all of the logic required to implement it can (should?) be done on the front end and the only sort of interaction that changes with the server is that a recipient's public key must first be sent over for the initial encryption of data. Is this more or less correct, or am I misunderstanding?
You are correct.
encrypted by me
and i know that only the recipient can decrypt it
Related
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!)
I am considering building an API system that uses HMAC. The server and client will have a shared secret, the client will sign the requests, the server will validate, and proceed if all is well. The trouble with this sort of system is that the secret has to be stored in a way where it can be retrieved, such as a database. If someone were to steal the secret, they have the key needed to do basically anything that user is authorized to do.
I was thinking that there must be a more secure alternative. Are there any flaws with using RSA?
Client has the "public" key instead of a shared secret. (The public key must still be kept secret for my use case.)
Client will hash the message with SHA-1 or whatever as normal.
Instead of adding the hash to the message directly, the hash will be encrypted via it's public key, and then sent with the message.
Server has the "private" key (to decrypt messages) but has no knowledge of the "public" key. (This is the part that makes this more secure than the normal approach. If the database is stolen, no keys are stolen that can impersonate a user.)
Server will decrypt the hash and validate the message as normal.
Is there anything wrong with this approach? Are there known implementations of this or something similar?
It depends on the asymmetric cryptosystem you chose:
(EC)Diffie-Hellman: It does not work. Publickey is directly derived from the privatekey via the generator, e.g. [d]G = Q
RSA: Usually people chose fixed publickeys like 0x010001. This is done for efficiency reasons. If you take a large enough, fully random e and derive d from it there is no possibility to calculate p and q given d and N OR e and N. Actually they are pretty equally then and the label private and public don't make much sense anymore. All that relies on a smmyetrical property of RSA. Be sure not to walk into textbook RSA issues. And be sure to ask enough clever people about it, this is just my thoughts on it.
If you base your crypto system on a proof of possession of a secret you need to, well - keep it secret :)
But yes, if you dont need the speed of a symmetric authentication then you can use a assymetric signature. Typically it is done with a signed hash, but you can also use a signed hmac.
The terminology is normally, that you sign with a secret key and validate with the public key (even when the signing operation looks like an encryption).
I've implemented a webservice authentication which works pretty much the same like amazon s3.
The authentication is session-less. It works like this:
send a Date HTTP Header in each request
send a HMAC_SHA1 of secretKey+contents of date-header+some-parts-of-the-body (pseudo code: hmac_sha1(secretKey+dateHeader+substr(body,0,100)))
The backend also knows the secretKey (20 char random key).
The backend checks the request by also doing the same HMAC_SHA1 and if the value is equal, the request is "proven" and will be executed.
So. I think thats pretty much was amazon does.
But what about the idea of doing not a symmetric (HMAC_SHA1) instead doing a asymmetric encryption (RSA) of the "parts of the request"?
I would like to avoid having the secretKey on my backend. Better only place the public key on the backend side.
Do you think this is a good idea?
Would it make the system "stronger"?
What's a good max size for encrypting with RSA? 1000bytes?
Thanks
Doing this with RSA you will have the public key on the client-side and the private key on the server-side (a.k.a. backend). You will always end up with some secret key somewhere...
IF you are worried about security:
list all potential risk scenrios (technical and otherwise)
check how probable each scenario is
check how much is "costs" if that specific scenario becomes reality
audit your current security infrastructure
THEN go ahead and take care of the most problematic points (i.e. highest "cost" and/or "highest" probability).
Last summer, I was working on an application that tested the suitability of a prospective customer's computer for integrating our hardware. One of the notions suggested was to use the HTML report generated by the tool as justification for a refund in certain situations.
My immediate reaction was, "well we have to sign these reports to verify their authenticity." The solution I envisioned involved creating a signature for the report, then embedding it in a meta tag. Unfortunately, this scenario would require the application to sign the report, which means it would need a private key. Once the application is storing the private key, we're back at square one with no guarantee of authenticity.
My next idea was to phone home and have a server sign the report, but then the user needs an internet connection just to test hardware compatibility. Plus, the application would need to authenticate with the server, and an interested party could figure out what credentials it was using to do that.
So my question is this. Is there any way, outside of obfuscation, to verify that the application did indeed generate a given report?
As Eugene has rightly pointed that my initial answer was to authenticate the receiver. Let me propose an alternative approach for authenticating the sender
authenticate the sender:
When your application is deployed at your client end, you generate and deploy a self signed PFX certificate which holds the private key.
The details of your client and passphrase for the PFX is set by your client and may be you can get it printed and signed by your client in paper to hold them accountable for the keys which they have just generated..
Now you have a private key which can sign and when exporting the HTML report, you can export the certificate along with the report.
This is a low cost solution and is not as secure as having your private keys in a cryptotoken, as indicated by Eugene, in the previous post.
authenticate the receiver:
Have a RSA 2048 key pair at your receiving end. Export your public key to your senders.
When the sender has generated the report, let the report be encrypted by a symmetric key say AES 256. Let the symmetric key itself be encrypted/wrapped by your public key.
When you receive the encrypted report,use your private key to unwrap/decrypt the symmetric key and in turn decrypt the encrypted report with the symmetric key.
This way, you make sure that only the intended receiver alone can view the report.
I'd say that you need to re-evaluate possible risks and most likely you will find them to be not as important as you could think. The reason is that the report has value for you but less likely for a customer. So it's more or less a business task, not a programming one.
To answer your concrete question, there's no simple way to protect the private key used for signing from being stolen (if one really wants to). For more complex solutions employing a cryptotoken with private key stored inside would work, but cryptotoken is itself a hardware and in your scenario it would unnecessarily complicate the scheme.
I'm not a cryptography expert, I actually only have a little bit of experience using it at all. Anyways, the time has come where one of my applications demands that I have some encryption set up. Please note, the program won't be managing anything super critical that will be able to cause a lot of damage.
Anyways, I was just trying to see if this scheme that I'm using is common and if there are flaws (of which there may be completely stupid & horribly flawed design, that's why I'm asking).
Ok, I have a client -> server communication. The Client I can hard code in the public portion of a 2048-bit RSA key. When the client wants to initiate a secure connection, he sends his username, md5 hash of his password, and a hash of a random UUID, all of which has been encrypted against the server's Public Key. The server receives the information and decrypts using its private key. Checks the database to see if his login + pass work & if they do, create a new entry in the "Sessions" table in the DB. This includes a SessionID, UID (user ID), and the UUID hash. Using the corresponding session ID's UUID as the keyphrase, the server will then send back a message that has the Blowfish encrypted word "Success!" + a random UUID (this message is Digitally Signed so we can determine if it came from the server or not). From that point on, when the client sends info to the server, it will be with a plaintext sess_id & include a Blowfish encrypted message, using the corresponding Session ID's blowfish secret (stored encrypted in the DB) as the key to encrypt / decrypt.
Specifically, I am curious as to whether this system "should work" or if anyone notices that it's glaringly obvious that a vulnerability exists, such as MITM.
Issues I can see off the top of my head (although you have left out most of the details, which is where the devil famously resides):
If you're using a UUID generator rather than a real cryptographic RNG, it likely has insufficient entropy. Don't discount this - in the real world, the favourite way of covertly weakening an encryption system has been to weaken the RNG;
Your initial RSA encryption sounds like it is susceptible to a small-exponent attack, and potentially other creative attacks. There's too much structure there to be comfortable;
It sounds like there's numerous opportunities for replay attacks;
What block cipher mode are you using with Blowfish?
I recommend using TLS/SSL - it's had a lot more friendly eyes looking at it for a lot longer than anything you build yourself ever will.
Just use SSL or DTLS, IKEv2, HIP, EAP or some suitable standard protocol. Don't try to invent your own crypto protocols, nobody has enough expertise to do this on their own. Your protocol doesn't have nearly enough entropy in it, so far as I can see, so your resulting keys will be pretty weak.
From that point on, when the client sends info to the server, it will be with a plaintext sess_id & include a Blowfish encrypted message, using the corresponding Session ID as the key to encrypt / decrypt.
If you're sending the session id in plaintext, and using it as the encryption key, how is that secure?
I see no reason why you can't use standard SSL authentication and let the library implementer worry about the handshaking.