Categorygithub.com/status-im/doubleratchet
modulepackage
3.0.0+incompatible
Repository: https://github.com/status-im/doubleratchet.git
Documentation: pkg.go.dev

# README

doubleratchet

Go Report Card Build Status Coverage Status GoDoc

The Double Ratchet Algorithm is used by two parties to exchange encrypted messages based on a shared secret key. Typically the parties will use some key agreement protocol (such as X3DH) to agree on the shared secret key. Following this, the parties will use the Double Ratchet to send and receive encrypted messages.

The parties derive new keys for every Double Ratchet message so that earlier keys cannot be calculated from later ones. The parties also send Diffie-Hellman public values attached to their messages. The results of Diffie-Hellman calculations are mixed into the derived keys so that later keys cannot be calculated from earlier ones. These properties gives some protection to earlier or later encrypted messages in case of a compromise of a party's keys.

Project status

The library is in beta version and ready for integration into production projects with care. Let me know if you face any problems or have any questions or suggestions.

Implementation notes

The Double Ratchet logic

  1. No more than 1000 messages can be skipped in a single chain.
  2. Skipped messages from a single ratchet step are deleted after 100 ratchet steps.
  3. Both parties' sending and receiving chains are initialized with the shared key so that both of them could message each other from the very beginning.

Cryptographic primitives

  1. GENERATE_DH(): Curve25519
  2. KDF_RK(rk, dh_out): HKDF with SHA-256
  3. KDF_CK(ck): HMAC with SHA-256 and constant inputs
  4. ENCRYPT(mk, pt, associated_data): AES-256-CTR with HMAC-SHA-256 and IV derived alongside an encryption key

Installation

go get github.com/status-im/doubleratchet

then cd into the project directory and install dependencies:

glide up

If glide is not installed, install it.

Usage

Basic usage example

package main

import (
	"fmt"
	"log"

	"github.com/status-im/doubleratchet"
)

func main() {
	// The shared key both parties have already agreed upon before the communication.
	sk := [32]byte{
		0xeb, 0x8, 0x10, 0x7c, 0x33, 0x54, 0x0, 0x20,
		0xe9, 0x4f, 0x6c, 0x84, 0xe4, 0x39, 0x50, 0x5a,
		0x2f, 0x60, 0xbe, 0x81, 0xa, 0x78, 0x8b, 0xeb,
		0x1e, 0x2c, 0x9, 0x8d, 0x4b, 0x4d, 0xc1, 0x40,
	}

	// Diffie-Hellman key pair generated by one of the parties during key exchange or
	// by any other means. The public key MUST be sent to another party for initialization
	// before the communication begins.
	keyPair, err := doubleratchet.DefaultCrypto{}.GenerateDH()
	if err != nil {
		log.Fatal(err)
	}

	// Bob MUST be created with the shared secret and a DH key pair.
	bob, err := doubleratchet.New([]byte("bob-session-id"), sk, keyPair, nil)
	if err != nil {
		log.Fatal(err)
	}

	// Alice MUST be created with the shared secret and Bob's public key.
	alice, err := doubleratchet.NewWithRemoteKey([]byte("alice-session-id"), sk, keyPair.PublicKey(), nil)
	if err != nil {
		log.Fatal(err)
	}

	// Alice can now encrypt messages under the Double Ratchet session.
	m, err := alice.RatchetEncrypt([]byte("Hi Bob!"), nil)

	if err != nil {
		log.Fatal(err)
	}

	// Which Bob can decrypt.
	plaintext, err := bob.RatchetDecrypt(m, nil)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println(string(plaintext))
}

Options

Additional options can be passed to constructors to customize the algorithm behavior:

doubleratchet.New(
    sk, keyPair,
    
    // Your own cryptography supplement implementing doubleratchet.Crypto.
    WithCrypto(c),
    
    // Custom storage for skipped keys implementing doubleratchet.KeysStorage.
    WithKeysStorage(ks),
    
    // The maximum number of skipped keys. Error will be raised in an attempt to store more keys
    // in a single chain while decrypting.
    WithMaxSkip(1200),
    
    // The number of Diffie-Hellman ratchet steps skipped keys will be stored.
    WithMaxKeep(90),
)

License

MIT

# Functions

No description provided by the author
Load a session from a SessionStorage implementation and apply options.
New creates session with the shared key.
NewWithRemoteKey creates session with the shared key and public key of the other party.
WithCrypto replaces the default cryptographic supplement with the specified.
WithKeysStorage replaces the default keys storage with the specified.
WithMaxKeep specifies how long we keep message keys, counted in number of messages received nolint: golint.
WithMaxMessageKeysPerSession specifies the maximum number of message keys per session nolint: golint.
WithMaxSkip specifies the maximum number of skipped message in a single chain.

# Structs

DefaultCrypto is an implementation of Crypto with cryptographic primitives recommended by the Double Ratchet Algorithm specification.
No description provided by the author
KeysStorageInMemory is an in-memory message keys storage.
Message is a single message exchanged by the parties.
MessageHE contains ciphertext and an encrypted header.
MessageHeader that is prepended to every message.
The double ratchet state.

# Interfaces

Crypto is a cryptography supplement for the library.
DHPair is a general interface for DH pairs representation.
KDFer performs key derivation functions for chains.
KeysStorage is an interface of an abstract in-memory or persistent keys storage.
Session of the party involved in the Double Ratchet Algorithm.
No description provided by the author

# Type aliases

Key is any byte representation of a key.
MessageEncHeader is a binary-encoded representation of a message header.