Consider this scenario:
Alice sends a signed message with her key to BOB.
Bob never traded a key with Alice.
Alice's key is signed by a certain X.
X's key is signed by Y, an entity that BOB trusts.
Is Alice's key valid or not for Bob?
we trust Y so the X's key is good! But we can not deduce a trust in X. The latter can sign anything and claim that it is the Alice's key.
Related
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
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.
If you've validated that a persons public key is actually from who you think it is by verifying the fingerprint in person/over the phone, is signing their public key still necessary?
Especially if you plan on not decrypting messages yourself, but only plan on encrypting a message with the valid public key, is key signing still necessary?
I find it useful to sign a key for a couple of reasons:
To reassure me in the future that the key hasn't changed.
To help the key owner prove their key to others via the web-of-trust.
On point 1), it's easy enough to verify a fingerprint now but are you going to do this every time you send that person encrypted mail or check their signature? Signing the key means you can forget the fingerprint.
On point 2), the owner of the public key may appreciate your signature on their key to help convince others that their key belongs to them. For example if I sign Alice's key and Bob has verified my key, Bob can choose to trust Alice's key by virtue of my signature.
In practice, I believe the proper etiquette is to sign Alice's key then export it (gpg --export --armor <alice's key id>) and send it to Alice in an encrypted email. This allows her to choose how to use your signature on her key - she might decide to upload it to a keyserver or just send it directly to someone else. Alternatively she may decide not to reveal her association to you and never use the signed key.
Note: I believe it's poor etiquette to upload someone else's key to a keyserver as you deny them that choice.
If you can verify the person owning the public key you don't have to worry about signing. The ability to verify the public key is from whom you trust it to be is the important thing. In saying this, if you are getting the public from some public key server, then how will you be able to trust its from the user you think it is from? In such a case the signing is a valid consideration.
Following are some useful links related to this.
What does key signing mean from securityexchange
Web Of Trust
Hope this helps.
Your decrypting is done with YOUR private key.
Not signing the (public) key of somebody else, will possibly issue ugly warnings, show nasty icons in your public key list, and not help in any way to manifest your checking process for somebody else, i. e. build the web of trust. So it is more a question of style than a technical difference.
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.
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.