npm package: @jetit/cryptomancer
Description: `@jetit/cryptomancer` is a library that provides an implementation of forward secrecy encryption for secure communication between clients and servers built on top of [TweetNacl](https://github.com/dchest/tweetnacl-js) using the [Double Ratchet Algorithm](
Author: Surfboard Payments
Latest version: 2.3.1

# @jetit/cryptomancer

`@jetit/cryptomancer` is a library that provides an implementation of forward secrecy encryption for secure communication between clients and servers built on top of [TweetNacl](https://github.com/dchest/tweetnacl-js) using the [Double Ratchet Algorithm](https://en.wikipedia.org/wiki/Double_Ratchet_Algorithm).

## Installation

To install Cryptomancer, you can use npm or yarn:

```shell
npm install @jetit/cryptomancer
```

or

```shell
yarn add @jetit/cryptomancer
```

## Usage

The library exposes all the code required to achieve secure communication using forward secrecy in a client-server environment. You can also build peer-peer networks by implementing both client/server in each node. The library also offers server signature verification using RSA2048 PKCS1-v1_5 to enable server validation. The below steps show implementation details on the client and the server.

The below diagram shows the setup and message exchange between client and server

![](https://storage.googleapis.com/sp-customer-report/External%20Images/cryptomancer.png
)

### Server

To initialize Cryptomancer as the server, you can use the `server` method provided by the library. Here's an example of how to use it:

```Typescript
import { Server } from '@jetit/cryptomancer';

const server: Server.CryptomancerServer = Server.cryptomancer();

// Step 1: Configure the RSA private key for signature
server.setRsaPrivateKey('RSA_PRIVATE_KEY');

// Step 4: Set the peer's identity public key
server.setPeerIdentityKey('PEER_IDENTITY_PUBLIC_KEY');

// Step 5: Get the identity public key 
const  identityDetails  = await server.getIdentityPublicKey();

// Send the identityDetails, signature to client

// Step 8: Set the peer's handshake public key
server.setPeerHandshakePublicKey('PEER_HANDSHAKE_PUBLIC_KEY');

// Step 9: Get the handshake public key
const handshakeDetails = await server.getHandshakePublicKey();

// Send the handshakeDetails, signature to client

// Step 12: Decrypt a received message
const decryptedMessage = await server.decrypt(encryptedMessage);
console.log(decryptedMessage);

// Step 14: Encrypt and send a message
const message = 'Hello, client!';
const encryptedMessage = await server.encrypt(message);

// Send the encrypted message to the client

```

### Client

To initialize `cryptomancer` as the client, you can use the `client` method.

```Typescript
import { Client } from '@jetit/cryptomancer';

const client: Client.CryptomancerClient = Client.cryptomancer();

// Step 2: Get the RSA public Key from server, Configure the RSA public key for verification
client.setRsaPublicKey('RSA_PUBLIC_KEY');

// Step 3: Get the identity public key
const identityPublicKey = await client.getIdentityPublicKey();

// Send the identityPublicKey to server

// Step 6: Set the peer's identity public key
client.setPeerIdentityKey('PEER_IDENTITY_DETAILS');

// Step 7: Get the handshake public key
const handshakePublicKey = await client.getHandshakePublicKey();

// Send the handshakePublicKey to server

// Step 10: Set the peer's handshake public key
client.setPeerHandshakePublicKey('PEER_HANDSHAKE_DETAILS');

// Step 11: Encrypt and send a message
const message = 'Hello, server!';
const encryptedMessage = await client.encrypt(message);

// Send the encrypted message to the server

// Step 13: Decrypt a received message
const decryptedMessage = await client.decrypt(serverEncryptedMessage);
console.log(decryptedMessage);
```

### Server Session Serialization Support

```Typescript
import { fs } from 'fs';

// Step 1: Serialize the session
const serializedServerSession = server.serialize();

// Step 2: Save session for usage later
fs.saveFileSync('server_session.txt', serializedServerSession);

// Step 3: Get saved session details
const existingSession = fs.readFileSync('server_session.txt')

// Step 4: Resume previous session
const deserializedServerSession: Server.CryptomancerServer = Server.cryptomance();

deserializedServerSession.resume(existingSession);
deserializedServerSession.setRsaPrivateKey('RSA_PRIVATE_KEY');

const message1 = 'Hello, client!';
const encryptedMessage1 = await deserializedServerSession.encrypt(message1);

```

## API Reference

### Client Methods

-   `setRsaPublicKey(key: string): void`: Configures the RSA public key for verification. This step is optional.

-   `getIdentityPublicKey(): Promise<string>`: Retrieves the client's identity public key.

-   `setPeerIdentityKey(peerIdentity:string): Promise<void>`: Sets the peer's identity public key. The peer's RSA signature is also required.

-   `getHandshakePublicKey(): Promise<string>`: Retrieves the client's handshake public key.

-   `setPeerHandshakePublicKey(peerHandshake: string,): Promise<void>`: Sets the peer's handshake public key.

-   `encrypt(message: string): Promise<IFSMessage>`: Encrypts a message using the Ratchet algorithm.

-   `decrypt(message: string): Promise<DecryptedMessage>`: Decrypts a received message using the Ratchet algorithm.

### Server Methods

-   `setRsaPrivateKey(key: string): void`: Configures the RSA private key for signature. This step is optional.

-   `getIdentityPublicKey(): Promise<string>`: Retrieves the server's identity public key and signature. The signature is generated using the RSA private key.

-   `setPeerIdentityKey(identityPublicKey: string): Promise<void>`: Sets the peer's identity public key.

-   `getHandshakePublicKey(): Promise<string>`: Retrieves the server's handshake public key.

-   `setPeerHandshakePublicKey(handshakePublicKey: string): Promise<void>`: Sets the peer's handshake public key.

-   `encrypt(message: string): Promise<string>`: Encrypts a message using the Ratchet algorithm.

-   `decrypt(message: string): Promise<DecryptedMessage>`: Decrypts a received message using the Ratchet algorithm.

-   `serialize(): string`: Serializes the current ratchet session into an encoded string. This allows for storing or transferring the session state.

-   `resume(session: string): void`: Resumes a ratchet session using a serialized session string. The session string should be previously generated using the `serialize()` method. This allows for restoring a previous session state.

## Acknowledgments

-   The Double Ratchet Algorithm: [Wikipedia](https://en.wikipedia.org/wiki/Double_Ratchet_Algorithm)
-   Forward Secrecy Implementation: [GitHub](https://github.com/alax/forward-secrecy)
-   TweetNacl: [GitHub](https://github.com/dchest/tweetnacl-js)
-   Curve25519: [Wikipedia](https://en.wikipedia.org/wiki/Curve25519)
-   Salsa20: [Wikipedia](https://en.wikipedia.org/wiki/Salsa20)