Pros and cons of JWE Key Management Modes - security

I've been searching a lot but nothing hit the spot, they are questions about JWE key management.
Scenario:
Server wants to send sensitive data to client, and it chooses to encrypt the data with a symmetric algorithm by a symmetric key, i.e, Content Encryption Key (CEK).
Client will retrieve the CEK to decrypt the encrypted data, but the CEK can't be sent as a clear text together with the encrypted data, so the CEK will need to be encrypted.
Approach:
The JWE specification defines different key management modes as follows
Key Wrapping: the CEK is encrypted for the intended recipient using a symmetric encryption algorithm.
Key Wrapping Diagram
Key Encryption: the CEK is encrypted for the intended recipient using an asymmetric encryption algorithm.
Key Encryption Diagram
Direct Key Agreement: a key agreement algorithm is used to pick the CEK.
Direct Key Agreement Diagram
Key Agreement with Key Wrapping: a key agreement algorithm is used to pick a
symmetric CEK using a symmetric encryption algorithm.
Key Agreement with Key Wrapping Diagram
Direct Encryption: a user-defined symmetric shared key is used as the CEK (no key derivation or generation).
Direct Encryption Diagram
Question:
What are pros and cons of each mode?
Under what circumstance will each mode be preferable?
Any help or advise would be appreciated, thank you very much.

See this answer for the difference between the key management modes and when to use each.

Related

How do password managers encrpty passwords that are shared with a group?

There are password managers that encrypt passwords and data on the client side before storing it on the server.
I understand the Symmetric and Asymmetric Encryptions on a basic level. With Asymmetric Encryption, it requires the Public key of the other user to encrypt it so only him/her can decrypt it with the Private key.
I don't understand how that would happen for a group or even a single user where both the encryptor and decrypter need the data/password.
Thanks for the help.
Typically you encrypt the data itself (the password) with a random symmetric key. You then encrypt that key with each public key you want to provide access. Since passwords are small, in principle you could just encrypt the key directly with the public key, but it's pretty common practice to do the two-step process. Asymmetric encryption is very slow, and not convenient for use on large pieces of data. And if you have a large number of public keys, it's much better to just have a small piece of data (a symmetric key) encrypted multiple times rather than the whole data set.
If it's just a single user, there's no reason for asymmetric encryption. You'd just use symmetric encryption with a single key.

How to store encrypted confidential user information in the database, which will need to be decrypted at runtime?

I am creating an application where I need to store client's information(Like their API Keys and API Secret to access my service, along with other confidential information).
Now, in the database, I want to store these in the encrypted format. In this regard, I decided to with symmetric key cryptography, AES in specific to encrypt the details.
However, for security purposes I want to use a different AES encryption key on a per client basis, so that even if the DB is compromised, all the data cannot be decrypted using a single key.
However, due to obvious reasons, I do not want to store my private keys in the DB with the encrypted informations.
So, I cannot seem to decide how to store my keys, especially since I need to have a binding that which key belongs to which client.
How can I achieve this, and which is the best approach in scenarios like this?
Use a KDF to derive an encryption key from the users password and then use this key to encrypt their private information.
When any action is to be taken that requires their API secret or whatever other private data you are storing, simply request the users password and use it to derive the key again and use the key to decrypt.
If you want users to be able to change their password, add an intermediary random key for each user and use this key to encrypt their data. Use the key derived from their password to encrypt the random key. Then when changing the users password, you only need to decrypt and re-encrypt the random key.

Storing private keys in database

I have the need to store private keys for multiple users, so that my server application can sign files on their behalf.
I want to store the private keys securely, but I couldn't find best practices around this. If I was storing a password I would salt+hash the password to make a hash that can't be easily turned back into the password. However, with a private key I need to store it in a way I can later retrieve it.
I was thinking I would encrypt the private key and then store it in my database. I originally thought each key would be encrypted with a different password (based on some properties of the user). However, those properties would most likely be stored in the database, so if my database got leaked then the attacker has everything.
I could encrypt all private keys with a single password that is only known to my application. Then an attacker would have to steal my database, and my application to do any harm.
Is there a technique/best practice I'm missing?
You could encrypt the private key with a symmetric key based on the users password. Simply store an additional salt and perform the password "hash" to get a separate key. Then use that as key for encrypting the private key. Note that it is required to use a Password Based Key Derivation Function (PBKDF) such as PBKDF2, bcrypt or scrypt to create a secure password hash (given the normal security level of a password).
If the user is not online at the time that a signature needs to be generated, then you should indeed protect the passwords in a sense that only you / our backoffice can decrypt the keys. You can use some user ID + your own secret key to calculate an encryption/decryption key. You may even want to generate a separate RSA key pair to perform hybrid encryption decryption.
Storing private keys on behalf of users is a very dangerous practice. There are a lot of ways for the private key to become exposed (e.g. side channel attacks). To do it professionally you should really be using an HSM somewhere in the process. If this is for any serious data, please consult a professional and a lawyer.

How can I change the AES-256 key after encryption?

I've a website that users submit their personal data to, and I'm thinking of encrypting these data using AES-256 and their password is used as a key for that encryption and then I store the encrypted data in a MySQL database...
Now if the user changes his/her password, how would I change the key of the encrypted data?
Should I gather all the data from the database, decrypt their data with the old key, and then encrypting it again with a new key?
You don't need to re-encrypt all of the user's data when they change their password.
Generate a secret key to encrypt a user's data; call this the "content encryption key." Derive a key from the user's password; call this the "key encryption key." Encrypt the "content encryption key" using the "key encryption key." Store the encrypted key along with the salt and the number of iterations used for key derivation.
If they change their password, decrypt the content encryption key with the old password, and re-encrypt it with a key derived from the new password. You should choose a new salt for the new password, and make sure you store it along with the new encrypted key.
Because the content encryption key is randomly chosen from a huge space, you can safely use ECB as the cipher mode when encrypting it.
Don't simply hash the password, even if you use salt or even if you use an as-yet-unbroken algorithm. You need to repeat the hashing operation thousands of times. There are libraries for doing this (correctly) on most platforms. Use a key derivation algorithm (PBKDF2, from PKCS #5) to create a secret key from a password.
This concept follows the draft for password-based S/MIME encryption.
One possibility to consider decouples the key used to encrypt the data from the key used to gain access to the data. Done carefully, this allows the user to change their password as often as they desire, while you only change one record in the database. Separately, you can schedule changes to the key(s) encrypting their data when it is convenient for you.
How does it work?
You encrypt the data D for user U with a randomly generated key, KU,D.
You encrypt the key KU,D with a separate key K1U,K generated from a random salt, S1U (which you keep a record of) and the user's password P1U (which you may or may not keep track of). The encrypted key is E1U.
You store S1U and K1U,K ready for when the user wants to access their data.
When user U wants to access their data, they provide you with their password, P1U, and you look up S1U and regenerate K1U,K from that data, and use that to decrypt E1U, giving you KU,D once more, with which you decrypt their actual data.
You ensure you can detect when the password given is correct so you don't spew forth binary gibberish if the users types the wrong password.
The advantage of this level of indirection comes when the user wants to change their password. If you don't use some technique analogous to this, you will have to get and validate the old password and the new password, decrypt all the data with the old password, and re-encrypt it all with the new password.
With the level of indirection, you still prompt the user for their old password (P1U) and their new password (P2U) and validate them, but you only have to decrypt E1U and then re-encrypt it with a new key K2U,K generated from a new salt S2U and the new password P2U. You do not have to touch the encrypted data at all.
With the level of indirection, the system S can also keep a second encrypted copy of the data key KU,D, encrypted with the system's password. If it becomes necessary or desirable to change the key used for encrypting the data, the system can use its encrypted copy of the key to do so. It can keep a record of which key was last recorded by the user in their key, so when the user returns to look at the data, it can arrange to to change the stored key K2U,D because at that time, it has their password (the rest of the time, it does not).
This is a mild variation on some of the ideas in "Cryptography in the Database: The Last Line of Defense" by Kevin Kenan. The KnU,K keys are examples of a KEK, a Key-Encrypting Key. You could also read about key families in the book, which would help with the management of encrypted data.
First, you generally shouldn't use the password as an AES key. Maybe something like a cryptographic hash (not MD5) of the password + a salt (you would store the salt but not the hash in this case).
One thing you could do is encrypt each user's files with a random key, then encrypt that key with the hashed+salted password. If the user changes passwords, you only have to re-encrypt the key.
That’s silly.
AES uses a 256-bit key, so when you say that you will be using their password for the key, it won’t be nearly as long as the key size requirement.

How to validate a SAML signature value

I have a customer who is sending a Security key. The encryption they are using is triple DES. Every Assertion they send has a signature value which needs to be validated to give them necessary privileges. Can you give me a sample code which does this?
Encryption and signing are two different animals. Triple DES is a symmetric key method (same key used for encryption and decryption). Digital signatures, on the other hand, use asymmetric keys (private/public key pair), where the signature is computed using the private key, and can be validated using the public key. So if your customer wants to include signatures in XML they send you, then they need to provide you with their public key.
For encryption, what is typical in SAML is to use XMLEncryption, which defines an XML format for including encryption key information and encrypted data in your SAML messages. Since exchange of a static symmetric key is problematic -- if it's intercepted, the interceptor can both encrypt and decrypt any messages -- what can be done instead is to use a dynamic symmetric key that gets generated anew for each message, encrypt the message using the key, then encrypt that key with the public key of a private/public encryption key pair and send it along with the message. The encrypted symmetric key can only be decrypted using the private half of the key pair used to encrypt it.
So the most significant difference here, from a key perspective, is that for signing, the customer holds the private key and must share the public key with you, while for encryption, you hold the private key and must share the public key with the customer.
If you want to validate the signature on the SAML Assertion or any of the Signable XML Objects, the OpenSAML WIKI has more information:
https://wiki.shibboleth.net/confluence/plugins/viewsource/viewpagesrc.action?pageId=3277047
You can look for 'Signature Verification Examples'.
This blog post also has an example as well:
https://blog.samlsecurity.com/2012/11/verifying-signatures-with-opensaml.html
To obtain a 'credential' for validation, see here:
https://blog.samlsecurity.com/2011/03/getting-credentials-in-opensaml.html
For info on how to unmarshal XML into an Open SAML object, see here:
https://wiki.shibboleth.net/confluence/display/OpenSAML/OSTwoUsrManJavaCreateFromXML

Resources