Integrate DIDComm for Rust

Learn how to integrate Affinidi Messaging into your projects to enable secure, private and trusted messaging.

The DIDComm for Rust integration guide provides a step-by-step overview for developers to integrate DIDComm-based communication to enable their application to send DIDComm messages, which enables secure, privacy-preserving, and verifiable messaging between decentralised identifiers (DIDs), allowing users to exchange messages securely and privately without relying on centralised intermediaries.

Key Features

  • Implements the DIDComm v2.1 protocol.

  • Support for DIDComm Messaging Envelope types.

  • Connect and authenticate with different mediator services that follow the DIDComm v2.1 protocol.

Requirements

  • Rust (1.85.0) 2024 Edition

  • Redis 8.0

Required Packages

PackageDescription
Affinidi Messaging - DIDComm for RustThe package for sending and receiving messages using the DIDComm protocol. It is designed to be used with the Affinidi Messaging SDK.
Affinidi Messaging SDKA Software Development Kit (SDK) to simplify the implementation of Affinidi Messaging into your application.
Affinidi Trust Development KitSimplifies development of privacy preserving solutions using decentralised identity and data sharing technologies.

Sample Usage

The examples demonstrate how to construct, sign, encrypt, and send messages according to the DIDComm Messaging spec. Check out these examples if you need more code references.

Instantiate the TDK

Initialise the Trust Development Kit.

let tdk = TDK::new( TDKConfig::builder() .with_environment_name(environment_name.clone()) .build()?, None, ) .await?; let environment = &tdk.get_shared_state().environment; let atm = tdk.atm.clone().unwrap(); let protocols = Protocols::new();

Activate Profiles

Enable profiles needed for communication.

// Activate Alice profile let tdk_alice = if let Some(alice) = environment.profiles.get("Alice") { tdk.add_profile(alice).await; alice } else { return Err(ATMError::ConfigError( format!("Alice not found in Environment: {}", environment_name).to_string(), )); }; let atm_alice = atm .profile_add(&ATMProfile::from_tdk_profile(&atm, tdk_alice).await?, true) .await?; let Some(alice_info) = protocols .mediator .account_get(&atm, &atm_alice, None) .await? else { panic!("Alice account not found on mediator"); }; info!("Alice profile active: {:?}", alice_info); let alice_acl_mode = MediatorACLSet::from_u64(alice_info.acls) .get_access_list_mode() .0; info!("Alice ACL Mode Type: {:?}", alice_acl_mode); // Activate Bob profile let tdk_bob = if let Some(bob) = environment.profiles.get("Bob") { tdk.add_profile(bob).await; bob } else { return Err(ATMError::ConfigError( format!("Bob not found in Environment: {}", environment_name).to_string(), )); }; let atm_bob = atm .profile_add(&ATMProfile::from_tdk_profile(&atm, tdk_bob).await?, true) .await?; let Some(bob_info) = protocols.mediator.account_get(&atm, &atm_bob, None).await? else { panic!("Bob account not found on mediator"); }; info!("Bob profile active: {:?}", bob_info); let bob_acl_mode = MediatorACLSet::from_u64(bob_info.acls) .get_access_list_mode() .0; info!("Bob ACL Mode Type: {:?}", bob_acl_mode);

Add Sender DID to ACL (Access Control List)

To be able to send a message, sender DID should be added to the recipient Access Control List.

// Ensure Bob is added to Alice explicit allow list if let AccessListModeType::ExplicitAllow = alice_acl_mode { protocols .mediator .access_list_add(&atm, &atm_alice, None, &[&bob_info.did_hash]) .await?; } // Ensure Alice is added to Bob explicit allow list if let AccessListModeType::ExplicitAllow = bob_acl_mode { protocols .mediator .access_list_add(&atm, &atm_bob, None, &[&alice_info.did_hash]) .await?; }

Compose Plaintext Message

A plain text message is a simple JSON message with headers and a body.

let now = SystemTime::now() .duration_since(SystemTime::UNIX_EPOCH) .unwrap() .as_secs(); let msg = Message::build( Uuid::new_v4().into(), "Chatty Alice".into(), json!("Hello Bob!"), ) .to(atm_bob.inner.did.clone()) .from(atm_alice.inner.did.clone()) .created_time(now) .expires_time(now + 10) .finalize(); let msg_id = msg.id.clone();

Pack DIDComm Message

Convert the plaintext message into DIDComm message by signing and encrypting it to ensure secure and authenticated transmission.

//Pack encrypted and signed message from Alice to Bob let packed_msg = atm .pack_encrypted( &msg, &atm_bob.inner.did, Some(&atm_alice.inner.did), Some(&atm_alice.inner.did), None, ) .await?;

Send Message

Transmits the packed DIDComm mesage to the recipient.

//Forward message from Alice to Mediator let bobs_mediator_did = tdk_bob.mediator.to_owned().unwrap(); let (_forward_id, forward_msg) = protocols .routing .forward_message( &atm, &atm_alice, false, &packed_msg.0, &bobs_mediator_did, &atm_bob.inner.did, None, None, ) .await?; // Alice sent message to Mediator match atm .send_message(&atm_alice, &forward_msg, &msg_id, false, false) .await

Receive Message

Accepts the incoming DIDComm message.

// Bob gets his message match protocols .message_pickup .live_stream_get(&atm, &atm_bob, &msg_id, Duration::from_secs(5), true) .await?

What’s Next

  Explore Meeting Place, an implementation of Affinidi Messaging

  Integrate Affinidi Messaging into your applications