Hi, Habr!
In the comments to our first post, the people demanded
bread and circuses of the code and a
“success story” . And if with the first one everything is more or less normal, then with the second something, somehow does not add up yet. You know, people are all young, our successes are quite modest, we play well in basketball. In a word, today we are just going to just a little bit and tell about the implementation of end-to-end encryption using our services. And the “success story”? What our years, will be still in our blog these most success stories.
Key management
One of the challenges in implementing end-to-end encryption is the secure transfer of encryption keys to the recipient.
The most obvious way to solve a problem is public key cryptography. Each user of the system has a key consisting of two parts: a private part (secret key), which is kept secret and is never transmitted over the network; public part (public key), which should be accessible to all system participants. The private key is usually used for signing and decryption, while using the public key, encryption and signature verification operations are performed.
Based on the definition of the secret and public key, it follows that absolutely any participant in the system is able to encrypt the message using the public key, but only the owner of the secret key is able to decrypt the message.
The first thing that should be taken into account when implementing a public key scheme is the possibility of replacing the public key by a third party. An attacker who has the ability to modify traffic can intercept Alice's public key and change it to his own public key. This leads to the fact that the user Bob, when he tries to send an encrypted message to Alice, actually encrypts it with an attacker key that can decrypt and read the secret data.
One of the possible options to prevent such a situation is the ability to uniquely identify the key holder. In this case, the substitution of the key will become apparent to Bob. As an identifier, you can specify an e-mail address, phone number and other unique, but easily recognizable information. It should be noted that the identifier specified when creating a new key must be verified and confirmed. Otherwise, we risk getting a system in which every user can impersonate anyone.
To verify the name, an identity validation service is required. As a rule, such services will send a randomly generated code to the specified e-mail address or phone number as the name and wait for confirmation from the user.
However, the use of the identity verification service only shifts the problem of trust from the communication channel to the service itself. In fact, nothing prevents the owner of the service from creating a compromised key, allegedly belonging to a third party.
')
In order to completely get rid of the possibility of compromised keys,
key authentication is required.
Key authentication is a way to convince Bob that the key he considers to belong to Alice is in fact Alice’s. There are several ways to solve the key authentication problem. The most obvious among them is the key exchange during a face-to-face meeting or using a more reliable communication channel. Despite the high reliability, this method is not always realizable in the real world. Therefore, one of the following key authentication methods is used.
The first way is to use trusted certificate authorities. When a certain user (trusted center) of the system has unlimited trust and is able to act as a key witness. No key in such a system is considered secure without the signature of a trusted authority.
The second way is to use the web of trust. At the same time, each user of the system is entitled to sign the key of any other user, thereby confirming that the key actually belongs to the specified owner. The more certified signatures under the key, the more credible it is.
Thus, the procedure for creating, storing and transferring keys has a number of pitfalls that are easy to get around using Virgil Security.
Virgil security
Virgil Security provides a set of free cryptographic services, the use of which helps to solve many problems related to security. In particular, the problem of key management.
Today Virgil Security is:
- The Virgil crypto library is an open source shell over mbedTLS that allows all standard encryption and signature algorithms to be used. And also adds hybrid encryption algorithms (ECIES). Virgil crypto library allows you to change the algorithms in the future without rewriting existing data - the principle of crypto agility.
- Virgil identity service is an identity verification service with an open API that allows you to verify the validity of an e-mail address. The service sends to the specified e-mail secret code that must be entered by the user to confirm the fact of possession of the address.
- Virgil keys service is a public key service that allows you to work with a reliable and accessible public key storage. Each key in the repository is tied to a special data structure called VirgilCard. VirgilCard necessarily includes: a unique identifier of the card — id, a key holder’s identifier — an e-mail address, a telephone number, etc., as well as the date the key was created. With the help of Virgil keys service, you can quickly find the public keys of users of the system, as well as delete cards with compromised keys.
- Virgil private keys service is a service of secret keys responsible for downloading, downloading and deleting secret keys. To access the private key, you must confirm possession of the Virgil card to which it is attached.
All of the above services have a wide selection of
ready-made SDKs and can be used to solve the widest range of information security tasks.
Virgil services and end-to-end encryption
Well, now it's time to get some cool. We show how using Virgil Security to implement secure end-to-end encryption. To do this, we implement the following scheme:

Please note that the encryption uses
ECIES scheme. This means that the message is encrypted using the AES symmetric algorithm using an ephemeral symmetric key, which can only be recovered if you have the recipient's private key. Encryption is performed using the recipient's public key.
To work with Virgil Security services we need to get a secret token and a public / private key pair. To do this, register on the site
Virgil Security . After that, proceed to the implementation of e2ee.
- Download and install VirgilSDK using NPM:
npm install virgil-sdk
- Initializing the work with Virgil Security services:
var virgil = new VirgilSDK("%ACCESS_TOKEN%");
- We generate a pair of keys:
var keyPair = virgil.crypto.generateKeyPair(); console.log(keyPair.publicKey); console.log(keyPair.privateKey);
And we get the following result:----- BEGIN PUBLIC KEY -----
MFswFQYHKoZIzj0CAQYKKwYBBAGXVQEFAQNCAAQO8ohmBRyclmcfQ38Lwmvv4Cau
jyX6vWn8kJrR0RRfFQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
----- END PUBLIC KEY -----
----- BEGIN EC PRIVATE KEY -----
MHkCAQEEIFB + lOUvbb4WX + e3zLkAcYpvZR3qpQI8Ru / tcnciCMkIoAwGCisGAQQB
l1UBBQGhRANCAAQO8ohmBRyclmcfQ38Lwmvv4CaujyX6vWn8kJrRRRfFQAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
----- END EC PRIVATE KEY -----
- We publish the public key. This requires a validation token that confirms the identity of the key holder. You can get a validation token in two ways: first, you can use the Virgil Identity service, which will check whether the key owner really has access to the email address and generates a validation token. Or, you can use the application's private key and use it to generate the validation token yourself. In this case, the developer avoids the need to trust a third-party identification service. Let's use the received validation token and save the public key on the server:
var options = { public_key: keyPair.publicKey, private_key: keyPair.privateKey, identity: { type: 'member', value: 'Darth Vader', validation_token: '%VALIDATION_TOKEN%' } }; virgil.cards.create(options).then(function (card){ myCard = card; console.log(card); });
As a result, the following key map will be created on the public key server: { "id":"3e5a5d8b-e0b9-4be6-aa6b-66e3374c05b3", "authorized_by":"com.virgilsecurity.twilio-ip-messaging-demo", "hash":"QiWtZjZyIQhqZK7+3nZmIEWFBU+qI64EzSuqBcY+E7ZtKPwd4ZyU6gdfU/VzbTn6dHtfahCzHasN...", "data":null, "created_at":"2016-05-03T14:34:08+0000", "public_key":{ "id":"359abe31-3344-453a-a292-fd98a83e500a", "public_key":"-----BEGIN PUBLIC KEY-----\nMFswFQYHKoZIzj0CAQYKKwYBBAGXVQEFAQNCAAQ...", "created_at":"2016-05-03T14:34:08+0000" }, "identity":{ "id":"965ea277-ab78-442c-93fe-6bf1d70aeb4b", "type":"member", "value":"Darth Vader", "created_at":"2016-05-03T14:34:08+0000" } }
- Create a channel through which encrypted messages will be transmitted. This will not be as difficult as it seems. Recently, we have become partners with the Twilio company, which, in particular, provides an API for implementing IP messenger. An example of a ready-made IP messenger with built-in end-to-end encryption can be found here .
- To send a secret message, we will find the public keys of the interlocutors and use it for encryption.
The encrypted message looks like this:MIIDBQIBADCCAv4GCSqGSIb3DQEHA6CCAu8wggLrAgECMYICvDCCAVoCAQKgJgQkMDg3YjgwYmMtMzNjYi00MTI1LWI4YTgtYTE
3OTEwM2Y3ZjRkMBUGByqGSM49AgEGCisGAQQBl1UBBQEEggEUMIIBEAIBADBbMBUGByqGSM49AgEGCisGAQQBl1UBBQEDQgAEcd
8fhKqYlZxvcmmodg7Z3PNhE1LXLJqobouEcRfZaRMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAYBgcogYxxAgUCM
A0GCWCGSAFlAwQCAgUAMEEwDQYJYIZIAWUDBAICBQAEMEaJMAvX7S+52BpI5hYyFOc0noIc+qdFFrQanNAtNGBAX/Pxeg5yJ2iA
JijyZ8ut9zBRMB0GCWCGSAFlAwQBKgQQ81bklcNOyU/QTatCigSzoAQwHnAcbXk0daExIIS+sr6aIvVuF/o6j+1Rs5bvq2WVN41
k/Oir5x7KZTSR7v3nx+fTMIIBWgIBAqAmBCRmNzM4YTUwNi1hMDYwLTQ1MDgtYTJkYS04NjY1NjZlYzg0ODMwFQYHKoZIzj0CAQ
YKKwYBBAGXVQEFAQSCARQwggEQAgEAMFswFQYHKoZIzj0CAQYKKwYBBAGXVQEFAQNCAARJ5C3hsYuI2Sf14k60Dz5Mv5yD/AsVA
zPfsmlreGTC2gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMBgGByiBjHECBQIwDQYJYIZIAWUDBAICBQAwQTANBglg
hkgBZQMEAgIFAAQwhu7WM1rff9RYsQ+dmfX9Os3Irwm4cm5bIvUlcGXlCfmEsrjTyTg5MGjYLtxbYtL9MFEwHQYJYIZIAWUDBAE
qBBCfKdP/gZnkVwJvv4Hdf2eWBDC3czBjV/yPGeGTqBIilHSsrqwK7lVMTBuKR+mR3eNdh+yBIAcOk4rveSUbDuWagDIwJgYJKo
ZIhvcNAQcBMBkGCWCGSAFlAwQBLgQMfjkCvK3UgXdorcYUmtCHHuSm4yfBacMsniMADAeos7qN7OmNsFU1
- The recipient decrypts the message using the secret key:
And see the following:Darth Vader: Luke. I am your father!
Simple enough. You write just a few lines of code and get full end-to-end encryption with the ability to authenticate keys. At the same time, Virgil Security services do not have access to users' private keys, which excludes the possibility of reading secret data.