didcomm swift

Swift library for DIDComm V2 protocol with message encryption/decryption, signing, DID authentication, and advanced routing for secure, decentralized communication.

7
2
Swift

DIDCommV2 Swift Package

DIDCommV2 is a comprehensive Swift package designed to facilitate the development of applications utilizing the Decentralized Identity Communication (DIDComm) V2 protocol. It offers Swift developers a robust toolkit for building secure, private communication systems based on decentralized identities.

Swift iOS MacOS WatchOS TvOS

Table of Contents

Installation

Swift Package Manager (SPM)

To integrate DIDCommV2 into your Xcode project using SPM, specify it in your Package.swift:

dependencies: [
    .package(url: "https://github.com/beatt83/didcomm-swift.git", .upToNextMajor(from: "0.1.0"))
]

Features

  • DIDComm V2 Protocol Support: Implements the DIDComm V2 protocol for secure, private messaging based on decentralized identities.
  • Message Encryption and Decryption: Offers tools for encrypting and decrypting messages, ensuring privacy and security in communications.
  • Signature and Verification: Supports message signing for non-repudiation and signature verification for authenticity checks.
  • DID-Based Authentication: Leverages decentralized identifiers for authentication purposes in messaging applications.
  • Message Packing and Unpacking: Provides functionalities for packing and unpacking DIDComm messages, including support for plaintext, signed, and encrypted messages.
  • Flexible API: Designed with a developer-friendly API, making it easy to integrate DIDComm V2 functionalities into Swift applications.
  • Error Handling: Comprehensive error handling mechanism to capture and manage various error scenarios that may occur during DIDComm message processing.
  • Advanced Routing: Supports message routing through mediators, enabling complex message delivery scenarios.

Supported Envelopes

Envelopes
Type Supported
Plain message
Signed message
Encrypted Authenticated message
Encrypted Anonymous message

Signed Envelopes

Algorithms
Type Supported
ES256
ES384
ES512
ES256K

Anonymous Envelopes (ECDH-ES+A256KW)

Encryption AlgorithmsKeys Algorithms
Encryption Supported
A256CBC-HS512
A256GCM
XC20P
Keys Supported
P-256
P-384
P-512
secp256k1
Ed25519
X25519

Authenticated Envelopes (ECDH-1PU+A256KW)

Encryption AlgorithmsKeys Algorithms
Encryption Supported
A256CBC-HS512
Keys Supported
P-256
P-384
P-512
secp256k1
Ed25519
X25519

Other features

Feature Supported
Multiple recipients
From prior JWT
Anon + Sign
Anon + Auth + Sign (Protect sender)
Routing

Usage

The DIDCommV2 Swift Package facilitates creating and processing various types of DIDComm messages, such as plain, signed, and encrypted (both authenticated and anonymous) messages. Here’s how to utilize the package for these scenarios:

Packing and Unpacking a Plain Message

let didcomm = DIDComm(
    didResolver: // ... DID Resolver implementation,
    secretResolver: // ... Secret Resolver implementation
)

let packed = try await didcomm.packPlainText(params: .init(
    message: // ... Message
))

let unpacked = try await didcomm.unpack(params: .init(packedMessage: packed.packedMessage))

// Utilize `unpacked.message` as needed

Packing and Unpacking a Signed Message

let didcomm = DIDComm(
    didResolver: // ... DID Resolver implementation,
    secretResolver: // ... Secret Resolver implementation
)

let packed = try await didcomm.packSigned(params: .init(
    message: // ... Message,
    signFrom: "did:example:alice#key-3" // Replace with actual signer DID Key ID
))

let unpack = try await didcomm.unpack(params: .init(packedMessage: packed.packedMessage))

// Validate `unpack.message` as needed

Packing and Unpacking an Authenticated Encrypted Message

let didcomm = DIDComm(
    didResolver: // ... DID Resolver implementation,
    secretResolver: // ... Secret Resolver implementation
)

let packed = try await didcomm.packEncrypted(params: .init(
    message: // ... Message,
    to: ["did:example:charlie"], // Replace with recipient DID
    from: "did:example:alice", // Replace with sender DID
    encAlgAuth: .a256CBCHS512
))

let didcommUnpack = DIDComm(
    didResolver: // ... recipient DID Resolver implementation,
    secretResolver: // ... recipient Secret Resolver implementation
)

let unpacked = try await didcommUnpack.unpack(params: .init(packedMessage: packed.packedMessage))

// Verify `unpacked.message` content

Packing and Unpacking an Anonymous Encrypted Message

let didcomm = DIDComm(
    didResolver: // ... DID Resolver implementation,
    secretResolver: // ... Secret Resolver implementation
)

let packed = try await didcomm.packEncrypted(params: .init(
    message: // ... Message,
    to: ["did:example:charlie"], // Replace with recipient DID
    encAlgAnon: .a256GCM // Assuming A256GCM is supported for anonymous encryption
))

let didcommUnpack = DIDComm(
    didResolver: // ... recipient DID Resolver implementation,
    secretResolver: // ... recipient Secret Resolver implementation
)

let unpacked = try await didcommUnpack.unpack(params: .init(packedMessage: packed.packedMessage))

// Validate `unpacked.message` content

Routing

In DIDComm, messages can be delivered to their final destination through a series of mediators. This process, known as routing, involves wrapping the original message in a series of forward messages for each mediator in the path.

The DIDCommV2 Swift SDK simplifies the handling of routing with the RoutingResult structure. When you pack a message for encryption or signing, the SDK can process and return a RoutingResult that contains the necessary forward messages along with the mediators’ information.

Each ForwardMessageResult within the RoutingResult holds:

  • finalRecipient: The DID of the final recipient.
  • routedBy: An array of mediator DIDs that will forward the message.
  • forwardMessage: The encrypted message that should be sent to the next mediator.

The SDK ensures that only necessary forward messages are generated and retrieved, avoiding redundant routing steps.

Routing Overview Diagram

The diagram below illustrates the DIDComm message routing process. It demonstrates how a message for Bob DID is securely forwarded through a series of mediators before reaching the final recipient. Each mediator receives a forward message containing the next mediator’s DID or the final recipient’s DID, ensuring that the message is reliably transmitted along the specified path.

Screenshot

Forward Message 1 is sent to Bob Mediator 1, which in turn forwards Forward Message 2 to Bob Mediator 2. From there, two branches occur: Forward Message 3 is sent directly to Bob Mediator 3 with a specific routing key, while Forward Message 4 is re-routed through Bob Mediator 2 using a different routing key. This example showcases the flexibility of DIDComm’s routing mechanism to support complex message delivery scenarios.

Usage Case

The following is an example of how you can pack a message that needs to be routed through mediators and then send the forward messages to the appropriate mediators:

/ Initialize the DIDComm instance with your resolver implementations
let didcomm = DIDComm(
    didResolver: // ... Your DID Resolver implementation,
    secretResolver: // ... Your Secret Resolver implementation
)

// Pack an encrypted message with routing
let packed = try await didcomm.packEncrypted(params: .init(
    message: // ... Your Message object,
    to: ["did:example:bob"], // Bob's DID
    from: "did:example:alice", // Alice's DID (optional)
    encAlgAuth: .a256CBCHS512 // Authenticated encryption algorithm
))

// If there's routing involved, process the forward messages
if let routingResults = packed.routingResult {
    for forwardMessageResult in routingResults.forwardMessages {
        // Here you would send `forwardMessageResult.forwardMessage.packedMessage`
        // to the mediator `forwardMessageResult.routedBy`
        // The actual sending mechanism would depend on your transport layer
    }
}

Documentation

You can access here to the documentation.

References

Contributing

We highly appreciate community contributions. To contribute, please fork the repository, push your changes, and open a pull request.

License

This project is licensed under the Apache 2.0 License.