Home

Awesome

DIDComm Rust + JavaScript/TypeScript + Swift

License Unit Tests Rust Package

The repository consists of the following main components:

The docs below are provided for the main DIDComm Rust.

See wasm/README.md for DIDComm JavaScript/TypeScript docs.

See wrappers/swift/README.md for DIDComm Swift docs.

Usage

To use didcomm, add this to your Cargo.toml:

[dependencies]
didcomm = "0.4"

Run examples

Use cargo run --example {example-name} for example cargo run --example basic.

Assumptions and Limitations

Examples

See examples for details.

A general usage of the API is the following:

1. Build an Encrypted DIDComm message for the given recipient

This is the most common DIDComm message to be used in most of the applications.

A DIDComm encrypted message is an encrypted JWM (JSON Web Messages) that

It is important in privacy-preserving routing. It is what normally moves over network transports in DIDComm applications, and is the safest format for storing DIDComm data at rest.

See Message::pack_encrypted documentation for more details.

Authentication encryption example (most common case):

// --- Build message from ALICE to BOB ---
let msg = Message::build(
    "example-1".to_owned(),
    "example/v1".to_owned(),
    json!("example-body"),
)
.to(ALICE_DID.to_owned())
.from(BOB_DID.to_owned())
.finalize();

// --- Pack encrypted and authenticated message ---
let did_resolver = ExampleDIDResolver::new(vec![ALICE_DID_DOC.clone(), BOB_DID_DOC.clone()]);
let secrets_resolver = ExampleSecretsResolver::new(ALICE_SECRETS.clone());

let (msg, metadata) = msg
    .pack_encrypted(
        BOB_DID,
        Some(ALICE_DID),
        None,
        &did_resolver,
        &secrets_resolver,
        &PackEncryptedOptions::default(),
    )
    .await
    .expect("Unable pack_encrypted");

println!("Encryption metadata is\n{:?}\n", metadata);

// --- Send message ---
println!("Sending message \n{}\n", msg);

// --- Unpacking message ---
let did_resolver = ExampleDIDResolver::new(vec![ALICE_DID_DOC.clone(), BOB_DID_DOC.clone()]);
let secrets_resolver = ExampleSecretsResolver::new(BOB_SECRETS.clone());

let (msg, metadata) = Message::unpack(
    &msg,
    &did_resolver,
    &secrets_resolver,
    &UnpackOptions::default(),
)
.await
.expect("Unable unpack");

println!("Receved message is \n{:?}\n", msg);
println!("Receved message unpack metadata is \n{:?}\n", metadata);

Anonymous encryption example:

let (msg, metadata) = msg
    .pack_encrypted(
        BOB_DID,
        None, // Keep sender as None here
        None,
        &did_resolver,
        &secrets_resolver,
        &PackEncryptedOptions::default(),
    )
    .await
    .expect("Unable pack_encrypted");

Encryption with non-repudiation example:

let (msg, metadata) = msg
    .pack_encrypted(
        BOB_DID,
        Some(ALICE_DID),
        Some(ALICE_DID), // Provide information about signer here
        &did_resolver,
        &secrets_resolver,
        &PackEncryptedOptions::default(),
    )
    .await
    .expect("Unable pack_encrypted");

2. Build an unencrypted but Signed DIDComm message

Signed messages are only necessary when

Adding a signature when one is not needed can degrade rather than enhance security because it relinquishes the sender’s ability to speak off the record.

See Message::pack_signed documentation for more details.

// ALICE
let msg = Message::build(
    "example-1".to_owned(),
    "example/v1".to_owned(),
    json!("example-body"),
)
.to(ALICE_DID.to_owned())
.from(BOB_DID.to_owned())
.finalize();

let (msg, metadata) = msg
    .pack_signed(ALICE_DID, &did_resolver, &secrets_resolver)
    .await
    .expect("Unable pack_signed");

// BOB
let (msg, metadata) = Message::unpack(
    &msg,
    &did_resolver,
    &secrets_resolver,
    &UnpackOptions::default(),
)
.await
.expect("Unable unpack");

3. Build a Plaintext DIDComm message

A DIDComm message in its plaintext form that

They are therefore not normally transported across security boundaries.

// ALICE
let msg = Message::build(
    "example-1".to_owned(),
    "example/v1".to_owned(),
    json!("example-body"),
)
.to(ALICE_DID.to_owned())
.from(BOB_DID.to_owned())
.finalize();

let msg = msg
    .pack_plaintext(&did_resolver)
    .expect("Unable pack_plaintext");

// BOB
let (msg, metadata) = Message::unpack(
    &msg,
    &did_resolver,
    &secrets_resolver,
    &UnpackOptions::default(),
)
.await
.expect("Unable unpack");

Contribution

PRs are welcome!

The following CI checks are run against every PR: