Is it okay to encrypt server-side when using HTTPS? - encryption

I am creating a messaging service for an app I'm developing. Because of the nature of the messages, it is important not only to verify users, but also verify what conversation the message belongs to. So right now I create a public/private key pair for each conversation and use it to encrypt/decrypt the messages. Basically when a user is logged in, they have access to the key pairs of the conversations they belong to, but those key pairs only work for that particular conversation. This allows access to be granted/denied to particular conversations while keeping other conversations between those same parties intact. Right now the data flow is as follows:
Send:
message sent to server => message encrypted based on user's public key and signed using secret key => encrypted message saved to database
Receive:
server receives message from database => server verifies signature using public key and decrypts message using secret key => decrypted message sent to client
All the encryption/decryption on the server is dependent upon the user's JWT token being authenticated.
I have two main questions: 1.) Is it okay to encrypt on the server since the communication between it and the client is using TLS? 2.) Should the keys be stored on the server or in the database?
Also, if this method is insecure, incorrect, or flat out just dumb please let me know.
Thanks in advance.

Related

En/decrypt data using password without database admin being able to decrypt it

This is a more conceptual question, but I'm trying to have some content be made available only to a specific user at a time. To do so, I thought about using a users password as an encryption key. However, the problem with that is that if I encrypt it using the plaintext password, I won't be able to encrypt anything as I'm obviously storing a hashed version in my database. If I encrypt it using the hashed password, then any database admin will be able to read the content of every user.
So basically, I need some kind of public/private key concept where I can encrypt it with a users public key but only they have access to their private key to decrypt it. Using actual RSA keys will be annoying in terms of usability though, as a user would have to write down their private key somewhere.
Is there a clever way for me to store data in a way that only a specific user can see it, somehow accessible through a password they set without being able to see their data as a server admin?
Example, assuming a website:
Random person chooses a receiver person, writes a message. That message should be stored in encrypted form in the database, using some form of public key.
Receiver person enters their password (Not a huge RSA key, optimally, but a standard passphrase), on the server side this password will be treated as some form of private key in order to deencrypt the data and send it back to the client.
So basically, I want to treat a simple passphrase as a private key, and generate a corresponding public key for it.
It looks like you want to use the same password for both authentication and for encryption.
Lets assume that only hashes of passwords are stored in a database (as it should be).
Issues:
"Remember me" function of web/mobile/desktop app will render encryption function impossible because user can log-in without password via token.
Admin can intercept login request to know user's password while it is transmitted in plain-text over https (simple infrastructure reconfiguration allows admin to sniff on traffic).
There is a way to secure transfers by using the same password in case:
you change your authentication procedure in a way that user sends to the server hashes only instead of plain-text password
and will save plain-text password at client side (for "remember me" scenario)
Then you could generate key pair during registration and save encrypted private key at server.
This way you will have access to your private key even after client side reinstallation (web/mobile/desktop).
So upon login you request your private key from server and use password which was used for authentication to decrypt your private key.
If you trust that admin(or whoever else) will not be able to meddle with software (especially in key exchange phase) then you have a way to implement the feature you need.
This will be hacker-proof solution until someone patches your code and every user in system gets wrong public keys of other users.

rsa keys verification

So I'm developing my messanging app with encryption evolved using RSA. Currently I came up with this algorithm:
= Update for auth =
Screenshot:
In this case private keys are generated only from password, and server knows only password hash just to authorize users (unhashed password is never transmitted to server), therefore is unable to generate private keys or decrypt any old message. If server will fake a public key recipent will be unable to verify signature encrypted with sender's private key.
The problem is that server can fake a sender's private, public key and password when he signs up on a service or requests a password change and recipent will be unable to detect it. So, how can I verify that keys were not faked by the server?
So, how can I verify that keys were not faked by the server?
You cannot. So long as the clients only communicate with the server, there's no way for them to distinguish between a "real" remote user and one that's being MITMed or otherwise faked by the server.
I see a couple other serious potential issues here:
Sending an unsalted hash of a password over the wire (during the login process) is hardly better than sending the password in the clear. An attacker can sniff the hash off the wire to log in -- they don't need the actual password! -- and a non-iterated SHA256 is highly vulnerable to brute force attacks.
"private key from pass" (also in the login process) implies that you're using some sort of KDF to generate a private key from the user's password. This has multiple negative implications:
Users are generally pretty bad at choosing passwords. This implies that the private keys will also be weak.
If two users happen to use the same password, they will end up with the same private key.
Any user can attack the password (and hence the private key) of any other user that they've communicated with by running the KDF on candidate passwords.
There is no process specified for negotiating a symmetric encryption key. Using RSA to encrypt messages directly limits each message to the size of the key, and makes it vulnerable to numerous attacks if the data being encrypted is not both random and unique.
In the message exchange, the user sends the server two copies of every message -- one encrypted to the target user's private key, one encrypted to their own private key. In some situations, this may make it possible to recover the message.

Should jwt web token be encrypted?

I was reading article on JWT web token as an access token that is being response to the user. Some of it mention that the web token should be able to be decoded by the user.
Does it means that it is not a good practice to decrypt the entire web token? For example, I suppose to return following JWT web token to user where this piece of information can be decoded.
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ
However, I feel that I do not want to let user able to decode his/her access token, so I use another encryption algorithm to encrypt everything into another form as follow and pass back to user.
So, I would decrypt this new text when I'll get this access token in the server and decode it.
Is it recommended to do it this way if I do not wish to expose some of the value available in claim (such as user id) to the user? If not, what are the alternatives?
JWT (RFC7519) is just a compact way to safely transmit claims from an issuer to the audience over HTTP.
JWT can be:
signed (JWS - RFC7515)
encrypted (JWE - RFC7516)
signed then encrypted (this order is highly recommended). The whole JWS is the payload of the JWE
encrypted then signed.
It makes sense to encrypt a JWS if you want to keep sensitive information hidden from the bearer (client) or third parties.
The real questions are: does the audience support JWE? If yes, which algorithms are supported?
JWT are "signed" and therefore its contents are protected from tampering: you cannot change its contents without invalidating them.
You can optionally "encrypt" the contents and therefore turn them visible only to issuer (the entity creating the token) and the consumer (the entity that is destined to use its contents after verification).
There's a standard for that: JWE
A token contains user data and acts like a temp storage. It is not good to store sensitive data in a token.
At the first level, you should store the user name and maybe role or something like that. You should not include passwords, so it does not need to be encrypted.
Nevertheless, you can encrypt it if you want.
Yes, the best practice is use the JSON Web Encryption (JWE) RFC, the claims in the JWT after decode it are in plain text, so if the user lost the token, the sensitive information as email, username, access permissions can be visible and can be used as a the initial information of any attack.

Securely store and share a secret with ServiceStack across different logins

Given is a ServiceStack REST Service that can sign documents with one of the public/private key algorithm. The prvate key is encrypted using a passphrase only the admin of this privat/public key pair knows.
Know it should be possible that other logins then the admin can sign documents (authorized by roles, permissions, etc.)
Currently they need to provide the passphrase for the private key in every signature request as the service needs to decrypt the private key and sign the document.
But i dont want to give the private key passphrase to other users and i also don't like to send it on every request over the wire.
So what is the best way to store the passphrase on the service side so that authorized logins can sign documents without knowing and sending the passphrase.
Is there a possibility to store it (automatically encrypted/decrypted from ServiceStack) in the user's session/UserAuth object?
Or is there are any other solution? It should work on .net and mono.
I'd recommend you look at Microsoft's guidance on encrypting/decrypting config sections. This way you can store it encrypted in web.config and your back end service can have access to it.
See http://msdn.microsoft.com/en-us/library/zhhddkxy(v=vs.100).aspx

RSA encryption: Is it possible to revoke a public/private key pair in peer-to-peer?

I'm creating an app (C#) that is going to send some messages around the network. Outgoing messages will be signed by a private key, incoming messages decrypted with a private key.
In case someone steals the private key, I want to be able to revoke it (send a revocation message to all other clients). Since I'm the owner of the stolen private key, only I must be able to revoke it.
My question: Is it possible to create a public/private key pair, depended on a so-called "Master public/private key pair" I have created before, to use in my app and if the private key in the app got stolen, I can revoke it, because with the master key I can proof that I'm the owner?
Hope someone understand what I mean ;-)
Mike
Update 1:
I'm developing a peer-to-peer app, so there will be no central server / CA
I'm generating the public/private keys by using the RSACryptoServiceProvider class in C#
Basically you'll design a system where each client can receive messages signed from two private keys: if they receive a message from the second private key, it will discard anything received signed with the first key.
Seems to be simple...
So, I think that you meant that you want to "revoke" the first public/private key in a way that your system will consider this pair invalid independent of same processing, I mean, even if someone hack the client, it won't be able to accept the first compromised key pair, because somehow they're revoked by the second key pair.
Is that it?
If so... no, without some kind of server, I don't think you can "revoke" a key pair. Revoking implies in having a central server telling which keys are valid, or your application doing this check internally (for ex., receiving a message from the second key pair and processing it)
You want to wrap you keys in a X.509 Certificate. The certificates should have a revocation Authority that supports OCSP (Online Certificate Status Protocol). see http://en.wikipedia.org/wiki/Online_Certificate_Status_Protocol
You don't need a second key (and if you did - what if an attacker stole that?) Simply define a 'revocation' message type which indicates the key that signed it is revoked (irrevocably, as it were). If your key gets stolen, you simply have to send out the revocation message using the stolen key, and the key becomes useless to the attacker.
How to distribute the revocation message depends on the system you're using, of course, but I'm assuming here that you have some way to distribute keys already, and therefore revocations can take the same route.

Resources