18个版本

0.4.1 2023年5月1日
0.4.0 2023年3月2日
0.3.4 2022年8月18日
0.3.3 2022年7月28日
0.3.0 2021年11月29日

#496 in 密码学

48 每月下载次数

Apache-2.0

1.5MB
18K SLoC

Rust 15K SLoC // 0.0% comments Swift 3K SLoC // 0.1% comments

包含(Mach-o库,675KB) wrappers/swift/didcomm/libdidcomm.dylib

DIDComm Rust + JavaScript/TypeScript + Swift

License Unit Tests Rust Package

该仓库包含以下主要组件

以下文档是为主要DIDComm Rust提供的。

有关DIDComm JavaScript/TypeScript文档,请参阅wasm/README.md

有关DIDComm Swift文档,请参阅wrappers/swift/README.md

使用方法

要使用didcomm,请将以下内容添加到您的Cargo.toml

[dependencies]
didcomm = "0.4"

运行示例

使用cargo run --example {example-name},例如 cargo run --example basic

假设和限制

  • 需要Rust 2018版本。
  • 为了使用库,必须在应用级别实现SecretsResolverDIDResolver特质。这些特质的实现超出了DIDComm库的范畴,但我们提供了2个简单的实现ExampleDIDResolverExampleSecretsResolver,允许在测试/演示目的下本地解析已知的DID文档和密钥。
    • 验证材料预计将以JWK、Base58和多基(内部仅Base58)格式。
      • 在Base58和多基格式中,支持仅使用X25519和Ed25519曲线的密钥。
      • 在Base58和多基格式中,私钥的验证材料值包含私钥和公钥部分(连接的字节)。
      • 在多基格式中,验证材料值的字节前缀对应的多码格式代码。
    • SecretsResolver中使用的密钥ID(kids)必须与DID文档验证方法中相应的密钥ID相匹配。
    • DID文档验证方法和密钥中的密钥ID(kids)必须是完整的DID片段,即did#key-id
    • 不支持引用其他DID文档的验证方法(参见引用验证方法)。
  • 以下曲线和算法得到支持
    • 加密
      • 曲线:X25519,P-256
      • 内容加密算法
        • XC20P(仅与ECDH-ES一起使用,anoncrypt的默认值),
        • A256GCM(仅与ECDH-ES一起使用),
        • A256CBC-HS512(authcrypt的默认值)
      • 密钥封装算法:ECDH-ES+A256KW,ECDH-1PU+A256KW
    • 签名
      • 曲线:Ed25519,Secp256k1,P-256
      • 算法:EdDSA(crv=Ed25519),ES256,ES256K
  • 已实现并默认使用前向协议。
  • 支持DID旋转(fromPrior字段)。
  • DIDComm是在以下假设下实现的。

示例

有关详细信息,请参阅示例

API的一般使用方法如下

  • 发送方
    • 构建一个Message(明文,有效负载)。
    • 通过调用以下之一将消息转换为DIDComm消息以进行进一步传输:
      • Message::pack_encrypted来构建加密的DIDComm消息
      • Message::pack_signed来构建签名的DIDComm消息
      • Message::pack_plaintext来构建明文的DIDComm消息
  • 接收方
    • 在接收方调用Message::unpack,这将解密消息,如果需要,则验证签名,并返回一个用于在应用级别进一步处理的Message

1. 为给定的接收方构建加密的DIDComm消息

这是在大多数应用程序中使用的最常见的DIDComm消息。

DIDComm加密消息是一个加密的JWM(JSON Web Messages),

  • 使其内容对所有未经授权的接收者隐藏
  • (可选)仅向那些接收者披露并证明发送者
  • 提供消息完整性保证

它在保护隐私的路由中非常重要。这是DIDComm应用程序在网络传输中通常移动的内容,并且是存储DIDComm数据的最高安全格式。

有关详细信息,请参阅Message::pack_encrypted文档。

身份验证加密示例(最常见的情况)

// --- 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);

匿名加密示例

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");

具有不可否认性的加密示例

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. 构建未加密但签名的DIDComm消息

仅在需要时才需要签名消息

  • 明文的来源必须对第三方可证明
  • 否则,由于接收者事先未知(例如,在广播场景中),认证加密无法证明发送者给接收者,因此无法通过认证加密来证明发送者。

在不需要签名时添加签名可能会降低而不是提高安全性,因为它放弃了发送者不记录发言的能力。

有关更多详细信息,请参阅Message::pack_signed文档。

// 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. 构建明文DIDComm消息

其明文形式的DIDComm消息

  • 没有包装在任何保护信封中
  • 缺乏机密性和完整性保证
  • 可否认

因此,它们通常不会跨安全边界传输。

// 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");

贡献

欢迎PRs!

以下CI检查针对每个PR运行

  • cargo check --all-targets没有警告
  • 所有测试都必须通过cargo tests
  • 代码必须由cargo fmt --all格式化

依赖关系

~3-4MB
~84K SLoC