# Quick-start
To get started quickly, we'll integrate the encryption & decryption features directly into the sample project, by password protecting the identity.
The branch on which this step is based is master
(opens new window), the end result is 1-quick-start
(opens new window).
# Installation
We will use the web version of the SDK @seald-io/sdk
with the password identity protection module @seald-io/sdk-plugin-ssks-password
:
cd frontend
npm install @seald-io/sdk @seald-io/sdk-plugin-ssks-password
For the moment, there are no changes to make to the backend.
# Configuration
To configure the SDK, you have to connect to your administration dashboard and get the following elements:
appId
: unique UUID for your application;JWT_SECRET_ID
: unique UUID of the shared secret;JWT_SECRET
: shared secret corresponding to theJWTSecret
used to generate JWT.apiURL
: URL of the API server to use;keyStorageURL
: URL of the identity storage server to use.
TIP
JWT secrets can be generated in the settings, tab JWT secrets
.
For more information refer to this documentation.
TIP
To create a developer account, follow the first steps.
To instantiate the SDK, we proceed as follows:
TIP
Since the SDK instance is shared across an entire application in React, it is better to store it in a variable in a seald.js
service file and expose a getter rather than storing it in an immutable variable.
# Seald identity Management
When creating a Seald identity, it must be associated to the Seald developer account, and to the user (whose identifier is noted userId
) in the application in which the SDK is integrated.
This requires generating a JSON Web Token called signupJWT
from the JWT_SECRET
, and the JWT_SECRET_ID
.
# Generating a signupJWT
The generation of a signupJWT
is done offline, and is described in this dedicated guide.
This operation must be done from the backend, but first we will do it on the frontend side to get a working prototype faster. We will use a utility tool, provided by the SDK to simply generate JWT.
WARNING
In production, you must not give the frontend knowledge of JWTSecret
. If it were, it could be used by an attacker to create new accounts associated with your developer account, and in particular to use your quotas.
You can refer to the guide dedicated to JWT generation.
# Creating an identity
Once the token is generated, a new identity can be created as follows:
Once this function is executed, the SDK instance is ready to encrypt and decrypt, and the identity-specific keys are in memory.
# Password-protection of the identity
Once the identity is created, it exists only in memory, it must be saved to be used in a later session.
To do this we will use the @seald-io/sdk-plugin-ssks-password
module which allows to protect the identity keys with a password
.
Once this function is executed, the identity is saved and can be retrieved using the equivalent function sealdSDKInstance.ssksPassword.retrieveIdentity
from a newly instantiated instance.
For more details on this mechanism, refer to the guide dedicated to password protection.
TIP
For faster execution, as an advanced usage of the SDK, you can customize the password derivation into a rawEncryptionKey
and a rawStorageKey
, and pass these instead of the password to ssksPassword.saveIdentity
. For more details, see the "Customize the password derivation" section of the Identity Guide.
# Exposing a createIdentity
and retrieveIdentity
functions
If we gather all the elements studied in the previous paragraphs, we can expose two functions:
# Integrate with account creation and login
The next step is to call these functions when creating the account in the application and when connecting.
To create it during account creation:
To retrieve upon login:
Since the identity is only stored in memory in the browser, if you open a new tab, you will have to retype the password. To get around this problem, we do not try to get the logged-in user's profile from the server:
We will see later how to make this identity persist in the browser.
DANGER
Here we put aside a major security concern: the authentication password should not be used as is to protect the identity. The authentication method must be modified (with a pre-derivation of the password) so that the application server cannot know the password. A dedicated guide is available here.
# Encrypting & decrypting messages
To perform message encryption and decryption, you need to:
- create a shared encryption session between the recipients;
- encrypt messages before sending them;
- decrypt messages after reception.
# Encryption Session
To create a shared encryption session between users userId_1
and userId_2
in the roomId_1
chatroom, we proceed as follows:
This returns an EncryptionSession with a new unique sessionId
assigned by the server.
In this project, we put the chat room identifier roomId
in metadata
.
To encrypt a message with a session, we proceed as follows:
This will give a string of the form:
'{"sessionId":"0000000000000000000000","data":"8RwaOppCD3uIJVFv2LoP3XGXpomj0xsMv4qmMVy30Vdqor2w0+DVCXu3j13PEyN2KfJm6SiSrWDRMDziiiOUjQ=="}'
We can retrieve an instance of the session, either with the sessionId
, or directly with the encrypted message:
Once the session is retrieved, it can be used to decrypt a message:
You can also add / remove recipients from the session:
For more details about the sessions, you can consult the dedicated guide.
# Integration in a chat room
To integrate these functions in the chat, three elements must be modified:
- the sending of messages, which must now encrypt for the recipients of the chat;
- the reception of messages, which must now be decrypted;
- the management of the members of a chatroom, which must now transpose the members of a chatroom into cryptographic rights.
# Encryption upon sending
We have to call the encrypt
function each time a message is posted.
In the Chat.jsx
file there is a handleSumbitMessage
function that we will modify to encrypt:
Also, when creating a multi-user chatroom in ManageDialogRoom.jsx
a 'Hello 👋'
message is sent. It must be encrypted:
# Decryption upon receiving
We need to call the decrypt
function each time a message is collected.
To do this we will create a couple of helper functions in Chat.jsx
that will be used to use the same data model everywhere:
Let's modify the eventListener of the event room:messageSent
:
We are going to modify the retrieval of the history of the messages at the loading of a room:
# Modifying the rights upon editing a room
When the room is multi-user, the creator of the room can add / remove members. The sessions allow to manage these movements.
To do this, when the creator of the room makes these movements on the room, he must make the same movements on the encryption session.
When a room is modified, the session associated with the room must be given during the dispatch:
In ManageDialogRoom.jsx
before making the API call to the server to actually edit the room:
# Conclusion
We were able to quickly integrate encryption into this project, but there are still three 3 issues remain before going into production:
- password pre-derivation;
- identity persistence when opening a new tab by storing the identity in localstorage;
- the generation of license tokens from the backend.