Integrate DIDComm for Rust
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
| Package | Description |
|---|---|
| Affinidi Messaging - DIDComm for Rust | The package for sending and receiving messages using the DIDComm protocol. It is designed to be used with the Affinidi Messaging SDK. |
| Affinidi Messaging SDK | A Software Development Kit (SDK) to simplify the implementation of Affinidi Messaging into your application. |
| Affinidi Trust Development Kit | Simplifies 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)
.awaitReceive 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
Glad to hear it! Please tell us how we can improve more.
Sorry to hear that. Please tell us how we can improve.
Thank you for sharing your feedback so we can improve your experience.