Digital signature when only one person has public/private key - encryption

Hello I have a scenarios where a client and a bank must communicate in a secure way and they must use electronic signature but only the bank has public/private key. How will the communication occur? Meaning how will they authenticate each other who will give the key to who how will the encryption occur?

It can't. The bank must have a pair of key (private and public) representing the bank, and the client must also have a pair of keys representing the client. If only the bank has a pair of key only the banks identity can be verified. Example: the bank sends a public message to all clients and signs it with its private key. All the clients can by using the banks public key indeed verify that the message comes from the bank.
However a client can also send an encrypted message to the bank using the banks public key, and only the bank can indeed read this message by using its private key, but the bank can not determine the identity of the client.
The clients identity can of course be determined by other means for instance by a login credentials.

Related

Private key storage issue in OpenPGP encryption

I'm trying to implement OpenPGP end to end encryption on a simple messaging app which will be accessed on the web as well as mobile. I'm stuck at deciding where my private key should be generated and stored. The following two approaches are on the table(i don't want to go with approach 2 but that looks like the only feasible option) :-
Key storage approach 1:-
When the user logs into the Chat client the first time, the client (web/app) will generate a set of public and private keys.
The user's public key will be sent to the backend server. The user's private key will be encrypted and stored on the local storage of the client.
Problems with this approach:-
If the user has not logged into the client even once, how will the sender encrypt the message? (since the public key of the recipient is not available till now)
If the user logs into another client (another browser or different app), how will he get access to the private key? (since that is needed to decrypt the messages in the user's inbox)
Key storage approach 2:-
When the user is created on the backend server, create both public and private keys for the user using PGP on the backend itself. Public key can be stored in plain-text but the user's private key should be encrypted and stored. We can use symmetric encryption with a client-specific passphrase here.
When the user logs into the Chat client (web/app), the encrypted private key will be received from the backend upon login. In order to decrypt any message, then can decrypt their private key using their passphrase, then use the private key to decrypt the message received.
Problems with this approach:-
This is not truly end to end encryption, since who-ever knows the passphrase of the user, can have access to the private key.
Reg. approach 1: If the client hasn't had the opportunity to share their public key, then indeed, you cannot send encrypted messages. It's unclear how you would solve that problem. The private key you can encrypt with a passphrase and upload the encrypted version to your backend so that the client can then download it and have it available on other devices, as you write in your second approach. Or you can go a step further and generate the private from the passphrase.
Your approach 2 may actually not have much worse security properties, depending on how you look at it. You could argue that you have no infrastructure anyway to let clients make sure they have obtained the correct key material. So they cannot distinguish the actual public key of the user from a malicious one provided by the server.
How you design your system is up to you, of course. I suggest you start laying out your requirements. Your problems seems to become smaller if not-yet-known users do not need to receive encrypted messages.

How to encrypt and decrypt messages using Virgil security?

I am trying to integrate Virgil security in my basic chat application but it won't as needed.
While chatting 2 users say A and B. After both users logged in and have some communication between them. Now both users reload/logged out or logged in then old messages was sent was not able to decrypt as new private keys will be generated.
I so not want to stored the public and private key of users in database or in local storage.
I'm Dim from Virgil. Let me help you with this use-case.
I prepared some additional information:
Steps #1 and #2 from Virgil Simple JS Demo (You’ve already seen it)
Step #1. User Registration Step.
users register their Public Keys
At this step:
You authenticate Alice
After you successfully authenticated Alice, you give her a JWT to grant her access to Virgil’s Cloud APIs
Alice generates her Private Key (2) -> stores her Private Key into Local Storage -> creates her Virgil Card
Alice Publishes (3) her Virgil Card on Virgil Cards Service (She uses her JWT to do it).
Then you authenticate Bob (User B): same story as Alice.
At the end, Alice and Bob have their own Private Keys and Virgil Cards (Public Key published into our cloud for users to find each other’s Public Keys).
Step #2. Simple Communication (chat).
Simple e2e encrypted communication
At this step:
Alice looks for & finds Bob’s Public Key at Virgil Cards Service (1)
Alice loads her Private Key from her Local Storage in a browser
Alice signs (with her Private Key) and encrypts (with Bob’s Public Key) a message and sends to Bob through your Application Server
Bob receives the encrypted and signed message
Bob goes to Cards Service to find Alice’s Public Key in order to verify her signature
Bob loads his Private Key from his Local Storage and decrypts the message
As a result, Bob verified Alice’s signature and decrypted the Message from Alice.
And now, comes the problem: Alice decided to use another Browser (or a Device B), but she can’t encrypt Bob’s previous messages on the new device.
Solution: you should transmit her Previous Private Key from Device A to Device B. To do this in the most secure way:
is to encrypt Private Key on a device A with some Additional Secret Key.
transmit encrypted Private Key to Device B.
use the same Additional Secret Key on Device B to decrypt the encrypted Private Key from Device A.
So, as you see you must use some special Additional Secret Key on both devices (some messengers do this with a QR code between the devices) to do it securely. To do it simpler though, we have a special tech for you to you generate the “Additional Secret Key” that will be the same on both devices. We call that Secret Key - a Brain Key. Brain Key - a strong cryptographic asymmetric key based on Alice’s PASSWORD.
You can find more information about this key here: https://developer.virgilsecurity.com/docs/java/use-cases/v1/brainkey
So now, let’s take a look at the next step.
Step #3. Store your Private Key in the Cloud
store somewhere encrypted Private Key
At this step:
Alice enters her Password
Alice generates a Brain Key from her password (1)
Alice encrypts her Private Key with the Brain Key (2)
Alice uploads her encrypted private key somewhere in Cloud (to your app’s backend/database)
As a result, Alice will have her encrypted Private Key in the cloud, that she used to chat with Bob.
Step #4. Alice now uses her new Browser (or new Device)
transmit a Private Key
At this step:
Alice enters her Password (the same that she used previously for Brain Key generation).
This generates her Brain Key (1)
Alice downloads her encrypted Private Key from the Cloud / from your backend/database (2)
Alice decrypts the encrypted Private Key with the Brain Key
As a result, Alice will get her Private Key on a Device B, that she used to chat with Bob on a Device A. This way, the chat conversation survived her device change.
Every time when Alice uses a new device, she can re-generate the same Brain Key and easily get her Private Key, the key that she uses on all her devices to chat with Bob.
David from Virgil here. Thanks for the question and sorry for making you puzzled.
I believe the issue is: while the sample app generated user private & public keys both for Alice and Bob, published the public keys to our Cards service, it hasn’t saved the private keys anywhere. So, the private keys remained in the browser's local storage and as such, didn’t sync to other browsers/devices where your users have logged in next. So in lack of their private keys, your users weren’t able to decrypt their messages... This is a limitation of the sample app and we should fix that ASAP (task created).
In order to get the app working, I.e. make your users be able to log in from another browser and decrypt messages, they need to retrieve their respected private keys from a central location. Now, it'd be too lame for me to recommend to just save the user private keys to your database (and enable others to access it + decrypt your users' messages), so we created a technology called BrainKey to encrypt the user private key with a key that we derive from the user’s password. Similar approach how Apple uses your TouchID-derived key to encrypt your keychain.
This is what you need to do to make it work:
During user signup (on the client device), generate a private key for your user and publish the public key to our Cards service.
Then use the user's password to generate a BrainKey (which technically is a private key).
Generate the public key from the BrainKey and encrypt the user's previously (Step 1) generated private key.
Now, save this encrypted private key to your database for the user.
Every single time your user logs in with her password, re-generate the same BrainKey from her password, download the encrypted private key from your DB, decrypt it with the BrainKey and now you can use this key to decrypt all chat messages that were sent to her.
Here’s a reference and sample code for our BrainKey tech: https://developer.virgilsecurity.com/docs/javascript/use-cases/v1/brainkey
Does it make sense? Would you like to see a sample code that does it? If you join our Slack, we can chat real-time, I’m #dave: https://join.slack.com/t/virgilsecurity/shared_invite/enQtMjg4MDE4ODM3ODA4LTc2OWQwOTQ3YjNhNTQ0ZjJiZDc2NjkzYjYxNTI0YzhmNTY2ZDliMGJjYWQ5YmZiOGU5ZWEzNmJiMWZhYWVmYTM
​David

JWE and JWS, are they "stateless"?

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.

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.

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