JWE and JWS, are they "stateless"? - encryption

Lately I have been reading some about JWT/JWS and JWE.. however.. one part I still dont get is that Im quite sure that I somewhere have read that they all should be "stateless", is this true?
My take on this would be that JWS and JWE would require a shared secret between the "acquirer" and the "issuer" to be able to decrypt the payload (and CEK and what not depending on JWS or JWE).
So my question is.. is JWS and JWE truly stateless? And if thats the case, then how come we dont need to store a secret between the "acquirer" and the "issuer"? Or is the kid used for fetching our secret from for instance a database to decrypt the payload and/or CEK?
To clarify,
Is there a shared secret between the issuer and the acquirer when using JWS and/or JWE to decrypt and encrypt the token? Is this secret stored in a database on the issuer to be able to decrypt the payload and/or the CEK or is the secret/key used to decrypt and encrypt shared some other way?
This question is based on the following article regarding JWT,JWS and JWE:
https://medium.facilelogin.com/jwt-jws-and-jwe-for-not-so-dummies-b63310d201a3

You are right: Depending on your application, it may be stateful.
From my point of view, you could ditinguish two cases:
Your application issues JWE or receives JWS
Your application issues JWS or receives JWE
With the first use case, the JWS signature can be checked using the issuer public keys. These keys are (broadly speaking) shared with the parties by the issuer (this what Google and other authorities do). Same goes when you want to encrypt a token (JWE) to that recipient: you will use its public key.
With the other use case, your application will need to have access on a key set with private keys. Those keys are necessarily stored somewhere (a DB, an environment variable...).
When shared keys are used (rarely used with 3rd parties), you may be in the use case #2 as both the issuer and the recipient have to manage the shared key.

Related

How to encrypt file storage in Firebase (client-side)?

I am building an Electron app and implementing Cloud Storage support. Users can upload files within my app to their account. Me, as an admin, I don't want to be able to read the files through the Firebase admin console. I also want to avoid a user password as people might forget it. Just logging into their account should be enough to access their files.
In my prototype I store user files in data/${user.uid}/. But now I am stuck and don't know which password I should use to encrypt the files.
There are a few questions around this topic which involve DigitalOcean which looks too overkill for what I am doing. Is there anything else I could use as a password that is part of the User object that is not exposed anywhere else?
I came across multiple options for Client Side Encryption in File Storage in Firebase. The encryption itself is simple enough to perform with existing libraries, using a symmetric key (a key that can both encrypt data, and decrypt the encrypted data). As the usual problem goes, we now need to find a secure place to store this all-powerful key.
Option 1 : Store Key on User Device
Pros : This stores the key on the user’s device, so the key is never in the application servers.
Cons : The key, and therefore the data, is not accessible from other devices. It’s not a bad solution depending on the use case and situation.
Option 2 : Google Key Management Service for Encryption
Pros : Encrypting the key with another data key stored in Google Key Management Service. The user’s key encrypts the data, and then the key is encrypted by a KMS key and stored in the database. As Andy rightly points out in his blog, that the KMS key belongs to a different Google account to the Firebase database, so no one user has permission to both read the data and decrypt it. A hacker would need to compromise both accounts to access the unencrypted data.
Cons : User has to manage two accounts.
Option 3 : Stash the Key in User’s Google Account
Pros : When the user logs in, we get the OAuth credentials to request the user’s personal encryption key, or create one if we can’t find one, from the user’s Google account. This way, the key is always fully in the user’s possession, but they never have to deal with it directly. Google Drive provides an API for creating a special application data folder (user consent is required during OAuth). The contents of this folder are not visible to the user, and is only accessible via your application’s credentials.
Cons : User has to be cautious not accidentally deleting their own encryption key.
Option 4 : Asymmetric Key Pair
Pros : User first gets the public keys of the recipients. He then generates a symmetric key for himself with which he encodes the file. He then creates a copy of this symmetric key for each recipient and encrypts it with the respective public keys. Finally, he transfers the encrypted copies of the symmetric key together with the encrypted file to the server and stores them there.If another user wants to download the file, he gets it in the encrypted form together with the copy of the symmetric key that is encrypted for him. He can decrypt the latter using his private key and now has the symmetric key with which he can decode the file.
Option 5 : Public and Private Key Encryption
Pros : Create private & public keys for your users when you sign them up. Encrypt data on User 1's device with User 2's public key. Store the encrypted data in your database. When User 2 reads up the encrypted data, his/her private key will be able to decrypt it.

Is encrypting with private key instead of signing a bad idea?

I am using a local URL scheme to submit a payload to the client when a user clicks a link and have to make sure that this is only used in my specific web application.
So I am using a key pair, encrypting the payload on the server using the private key, generating a link that the protocol handler on the client can decrypt using the public key, verifying that the payload should be processed.
So is it less secure to send a private-key-encrypted payload instead of a cleartext payload plus signature (and if yes, why)?
Found out that there are other Stack Exchange sites that answer this question very well:
https://crypto.stackexchange.com/questions/2123/rsa-encryption-with-private-key-and-decryption-with-a-public-key
https://security.stackexchange.com/questions/11879/is-encrypting-data-with-a-private-key-dangerous
I should have searched a little bit longer before asking.
What you are doing is signing!
Encrypting is when a payload is being concealed with one’s public key and later decrypted with a private key. When I want to send you a secret message, I will take your public key (because I know it) and encrypt my message. This will make sure that only you can decrypt it with your private key.
Signing works vice versa. If during encryption I want to make sure that only you can decrypt me message, with signing I want to make sure that all recipients of the message can be sure in its authenticity. If you encrypt something with your private (signing), anyone with your public key can decrypt it and verify its sender.
In your case, if you just want to prove your identity (like certificates, jwt tokens, etc.), you would need to use signing methods. If you want to transfer payload securely, use encryption.
Hope this helps!

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

where are encryption key's stored?

I'm new to cryptography . I've read that symmetric and asymmetric algorithms use one and two encryption keys respectively . and these keys must be stored somewhere safe . but when I searched the web to find tutorials about how to do encryption in asp.net I found something strange to me ! for example this tutorial .
there is no public or private key stored or supplied when encrypting or decrypting data ! I can't understand .
another problem I have is that all tutorials I've found till now just are codes without any explanations about what are these codes and why are used . I appreciate any good tutorial suggested .
From RSACryptoServiceProvider Constructor:
If no default key is found, a new key is created.
This constructor creates an Exchange key pair suitable to encrypt session keys so that they can be safely stored and exchanged with other users. The generated key corresponds to a key generated using the AT_KEYEXCHANGE value used in the unmanaged Microsoft Cryptographic API (CAPI).
So it is just generating a new key pair if it cant find one that was created already; you should not use this other than for session based data.
 
A little background (I'm assuming your using Windows), Asymmetric key pairs are associated with certificates. These certificates are what you use to place trust on asymmetric keys. Every certificate can be signed by a certificate authority (who is the authority which issues the asymmetric keys), if you trust the certificate authority, then you trust the asymmetric keys which belong to a certificate signed by that authority. All these certificates are stored in your "Certificate Store", aka "Key Store" (Java), "Key Ring" (Mac).
You can view your certificates by doing Start > Run > certmgr.msc. Your certs are under Personal > Certificates. If you open one up, and go to the Certificate Path tab, you will see the certificate chain up to a certificate authority. If that "root" certificate, which belongs to the certificate authority, is found in your Trusted Root Certification Authorities > Certificates store, then the certificate is considered valid and trusted.
If you want to encrypt something for a user, you should go into his certificate store, and pull out his encryption certificate. To do this, you should open up the "Current User's" key store, and iterate through all the certificates in there, and pick out the ones with the key usage of "Key Encipherment", and if more than one, ask the user's which he wants to use.
If you want to encrypt something using a service account (for example if you were a web server) you should use certificates found in the "Local Machine" key store, and only grant your service account read access to the private key associated with the certificate you want to use.
This can be done using X509Store Class, for example:
X509Store certificateStore = new X509Store("MY", StoreLocation.CurrentUser);
X509Certificate2Collection allCertificates = certificateStore.Certificates;
//Iterate through all certificates
"MY" represents personal certificates, the rest can be found here. CurrentUser represents user keys, the other option is LocalMachine.
Once you have the certificate you want to use, you should use the public key for encryption, and the private key for decryption, in conjunction with a symmetric key. So if you had a big set of data you wanted to encrypt, what you would do is:
Get certificate
Pull public key from certificate
Generate symmetric key (AES)
Encrypt data with symmetric key
Encrypt symmetric key with public key
Store encrypted symmetric key with the encrypted data, along with an identifier (Serial Number) for the certificate you used to encrypt
When you decrypt you should:
Read serial number from encrypted data
Pull certificate, from key store, with that serial number
Pull private key out of that certificate
Decrypt symmetric key with that private key
Decrypt data with that symmetric key
Use data
I have a bunch of code samples which accomplish this if you would like to take a look, just let me know which section you need help with.
That was probably a little confusing, so let me know what you want clarified.

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