跳转至

dcp-ai — Rust SDK

Rust 发布 (26/10/2026). Rust dcp-ai 2.11.0 已在 crates.io 发布,包含验证器修复、准入和实验性显式启用 API。dcp-jcs-v1 仍是规范性默认配置。见 Rust 2.11.0.

本文是英文 README的参考译文,更新于 02/11/2026。为保留经过验证的示例,标识符和代码块(包括注释)均保持原文。

Digital Citizenship Protocol(DCP v2.0)的官方 Rust SDK。提供基于 Serde 的类型、混合后量子密码学(Ed25519 + ML-DSA-65 + SLH-DSA-192f + ML-KEM-768)、使用 pq_over_classical 绑定的复合签名、双哈希链、OpenTelemetry 可观测性、DCP-04..09 行为以及可选的 WebAssembly 支持。

验证检查完整性和签名,不会建立对责任主体的信任、准入资格或行动授权。V2 验证器检查主审计链,自 2.11.1 起还检查存在的可选 SHA3-256 次级链接、意图哈希和次级 Merkle 根(不存在的不作要求);2.11.0 不检查次级字段。请参阅已记录的验证限制;需要检查信任时,请使用下文的准入 API。

安装

Rust SDK。 自 2.11.0 起,本 SDK 包含 V2 bundle 构建与签名、基于显式责任主体信任和 strict-v1 的准入、委托链、验证器修复以及实验性显式启用的 dcp-jcs-v2 API。dcp-jcs-v1 仍是规范性默认配置。旧版本接受的无效证据现在可能被拒绝。Rust 尚未实现 A2A 会话加密及其重放窗口;发现和握手辅助功能仍可用。

Rust SDK 2.11.1。 此版本还会在 VERIFICATION.md 的 V2-11 中的二级 SHA3-256 字段存在时验证它们:audit_merkle_root_secondary、每个 prev_hash_secondary 和每个 intent_hash_secondary。不存在的字段不作要求,因此已验证的 bundle 可能没有完整的二级链;存在的字段如果是 null、不是字符串或不一致,则被拒绝。API、结果字段、dcp-jcs-v1 和 hash_alg 的处理均不变。2.11.0 不检查这些字段。下面的安装命令指定的是此版本;它在注册表中的可用情况见已发布版本。

[dependencies]
dcp-ai = "2.11.1"

启用 OpenTelemetry/OTLP 导出:

[dependencies]
dcp-ai = { version = "2.11.1", features = ["otlp"] }

启用 WebAssembly 支持:

[dependencies]
dcp-ai = { version = "2.11.1", features = ["wasm"] }

功能

领域 状态
Ed25519 / ML-DSA-65 / SLH-DSA-192f / ML-KEM-768 提供程序 支持
复合签名(pq_over_classical)及验证 支持
规范化 JSON v2 与域分离 支持
双哈希(SHA-256 + SHA3-256)与 Merkle 根 支持
Bundle 验证(V1 + V2;V2 遵循验证器策略和安全等级,verify_signed_bundle_v2_with_policy) 支持
V2 bundle 构建与签名(dcp_ai::v2::bundle:build_bundle_v2、sign_bundle_v2;wasm 功能的 wasm_build_bundle / wasm_sign_bundle 调用它们;尚无 PQ 检查点) 支持
DCP-05 智能体生命周期(启用 / 活力 / 停用) 支持
DCP-06 数字继承(遗嘱、记忆转移、仪式) 支持
DCP-07 争议解决、仲裁与判例 支持
DCP-08 权利、义务与合规 支持
DCP-09 委托与可验证委托链(create_sub_mandate、verify_mandate_chain、§3.5)、认知阈值与责任主体镜像 支持
DCP-04 A2A 发现、握手与会话 ID 派生 支持
DCP-04 A2A AES-256-GCM 会话加密 推迟到后续版本
会话 nonce 辅助函数、安全等级引擎(compute_security_tier(&intent, Some(&policy_decision)),规范 §14.2;compute_security_tier_with_floor 纳入委托链的等级)、紧急撤销 支持
延迟 PQ 检查点与 PQCheckpointManager 支持
盲化 RPR、多方授权、算法通告辅助函数 支持
通用错误码(所有 SDK 共享 38 个)与 detect_wire_format 支持
OpenTelemetry / OTLP 导出器(可选 otlp 功能) 支持
准入:可信责任主体与 strict-v1 配置 支持
规范化候选方案 dcp-jcs-v2(入口处理、路由器、字节验证器、生成器) 实验性,须显式选择;非规范性

快速入门

use dcp_ai::crypto::{generate_keypair, sign_object, verify_object, hash_object};
use serde_json::json;

fn main() {
    // 1. Generate Ed25519 keypair
    let (public_key_b64, secret_key_b64) = generate_keypair();
    println!("Public Key: {}", public_key_b64);

    // 2. Sign an object
    let obj = json!({
        "agent_id": "agent-001",
        "action": "api_call"
    });
    let signature = sign_object(&obj, &secret_key_b64).unwrap();

    // 3. Verify signature
    let valid = verify_object(&obj, &signature, &public_key_b64).unwrap();
    println!("Verified: {}", valid); // true

    // 4. SHA-256 hash
    let hash = hash_object(&obj);
    println!("SHA-256: {}", hash);
}

验证已签名的 bundle

// Needs citizenship_bundle.signed.json in the working directory and the signer's public key in place of BASE64_PUBLIC_KEY.
use dcp_ai::verify::verify_signed_bundle;
use serde_json;
use std::fs;

fn main() {
    let data = fs::read_to_string("citizenship_bundle.signed.json").unwrap();
    let signed_bundle: serde_json::Value = serde_json::from_str(&data).unwrap();

    let result = verify_signed_bundle(&signed_bundle, Some("BASE64_PUBLIC_KEY"));
    println!("Verified: {}", result.verified);
    if let Some(errors) = &result.errors {
        println!("Errors: {:?}", errors);
    }
}

API 参考

密码学(dcp_ai::crypto)

函数 签名 说明
generate_keypair() () -> (String, String) 返回 (public_key_b64, secret_key_b64)
sign_object(obj, secret_key_b64) (&Value, &str) -> Result<String, String> 签名并返回 base64
verify_object(obj, sig_b64, pub_b64) (&Value, &str, &str) -> Result<bool, String> 验证签名
canonicalize(obj) (&Value) -> String 确定性 JSON
hash_object(obj) (&Value) -> String SHA-256 十六进制表示
merkle_root_from_hex_leaves(leaves) (&[String]) -> Option<String> Merkle 根

验证(dcp_ai::verify)

// Signature (not runnable)
fn verify_signed_bundle(
    signed_bundle: &Value,
    public_key_b64: Option<&str>,
) -> VerificationResult

验证内容:Ed25519 签名、bundle_hash、merkle_root、intent_hash 链与 prev_hash 链。

类型(dcp_ai::types)

// Declarations, fields elided (not runnable)
pub struct ResponsiblePrincipalRecord { ... }
pub struct AgentPassport { ... }
pub struct Intent { ... }
pub struct IntentTarget { ... }
pub struct PolicyDecision { ... }
pub struct AuditEntry { ... }
pub struct AuditEvidence { ... }
pub struct CitizenshipBundle { ... }
pub struct SignedBundle { ... }
pub struct BundleSignature { ... }
pub struct Signer { ... }
pub struct VerificationResult {
    pub verified: bool,
    pub errors: Vec<String>,
}

所有结构体均实现 Serialize + Deserialize(serde)。

V2 类型(dcp_ai::v2::types)

V2 为 DCP-05 至 DCP-09 的所有产物提供派生了 Serde trait 的结构体:

规范 类型
DCP-05 LifecycleState, CommissioningCertificate, VitalityReport, VitalityMetrics, DecommissioningRecord, TerminationMode, DataDisposition
DCP-06 DigitalTestament, SuccessionRecord, MemoryTransferManifest, MemoryTransferEntry, SuccessorPreference, MemoryClassification, TransitionType, MemoryDisposition
DCP-07 DisputeRecord, ArbitrationResolution, JurisprudenceBundle, ObjectionRecord, DisputeType, EscalationLevel, DisputeStatus, ObjectionType, AuthorityLevel
DCP-08 RightsDeclaration, RightEntry, ObligationRecord, RightsViolationReport, RightType, ComplianceStatus
DCP-09 DelegationMandate, AdvisoryDeclaration, PrincipalMirror, InteractionRecord, AwarenessThreshold, ThresholdRule, AuthorityScopeEntry

域分离常量:CTX_LIFECYCLE、CTX_SUCCESSION、CTX_DISPUTE、CTX_RIGHTS、CTX_DELEGATION、CTX_AWARENESS

所有结构体均派生 Debug、Clone、Serialize、Deserialize。枚举使用 #[serde(rename_all = "snake_case")]。可选字段使用 Option<T> 并配合 #[serde(skip_serializing_if = "Option::is_none")]。

收到的审计条目(2.12.0 已准备,尚未发布)。 AuditEventV2 和 AuditEvidenceV2 用于生成条目。把收到的条目解码到它们中再重新编码,会丢失显式的 null(位于 evidence、prev_hash_secondary 和 intent_hash_secondary 中)和任何未知成员,并把缺失的 pq_checkpoint_ref 变成 null。这会改变条目的规范化字节,并可能破坏 prev_hash 链或审计 Merkle 根。要保留收到的条目,请使用 RawAuditEventV2:它保存解码得到的 serde_json::Value,因此任意深度的每个成员(包括未知成员)都保留其存在与否和 null,并按原样序列化该值。它只拒绝不是 JSON 对象的输入(RawAuditEventError)。它保留的是 serde_json 解码的结果而不是原始文本,从不修复或重新签名,并按原样保留无效证据,使验证器以相同原因拒绝它。typed() 是用于读取字段的有损视图。要保留收到的 bundle,请按收到时的样子保留并验证它。

Bundles(dcp_ai::v2::bundle)

函数 说明
build_bundle_v2(&rpr, &passport, &intent, &policy, &audit_entries, session_nonce) 从四个 SignedPayload 和审计轨迹构建 V2 bundle。检查每个 payload_hash 以及每个产物和审计条目的 session_nonce,并将两个审计 Merkle 根写入清单;空轨迹的根为64个零
sign_bundle_v2(bundle, &classical, &pq) 在 CTX_BUNDLE 域下对清单进行复合签名,返回 {bundle, signature},其中 signer.id 为 RPR 的 human_id。在签名前将 session_expires_at 或 intended_verifier 放入清单;若存在 session_expires_at 而缺少 session_issued_at,则将 session_issued_at 设为签名时刻

模式校验(V2-2;在 main 上,不在已发布版本中)。 verify_signed_bundle_v2、…_with_policy 和 …_at会在策略和时钟检查之后、验证器检查清单、载荷哈希、密钥和签名之前,先按 schemas/v2 校验已签名 bundle 的封装和四个载荷;先进行验证的 admit_signed_bundle_v2 和实验性候选验证器也经过同一关卡,而 evaluate_admission_v2 接收先前的结果,不执行该关卡。校验失败的 bundle 返回 verified: false 和 schema: <JSON pointer> <keyword>[ <member>] 错误(最多 16 条,随后是 schema: further errors not listed),不含密码学细节。封闭对象中的未知成员会被拒绝;在开放对象中(例如 intent 的 target),已声明的成员保留其约束,只有附加成员不被检查。清单中的 session_issued_at 和 session_expires_at 存在时必须是字符串,不能是 null。date-time 遵循参考验证器的 ajv-formats 3.0.1 检查,这不是严格的 RFC 3339。它们接收已解析的 serde_json::Value:serde_json 拒绝解析的内容(孤立代理项、1e400)是调用方的解析错误。接受范围变化: 以前能通过验证的模式无效 bundle 现在会被拒绝。没有仅做模式校验的 API。参见覆盖映射。

委托链(dcp_ai::v2::delegation,DCP-09 §3.5)

函数 说明
create_delegation_mandate_with_options(ed, pq, human_classical, human_pq, params, &MandateChainOptions) 由人类签署的根委托,带有可选的 sub_delegation 和 minimum_security_tier
create_sub_mandate(ed, pq, classical, pq_key, &parent, SubMandateParams { .. }) 由父委托的智能体在 DCP-AI.v2.SubMandate 域下签署的子委托
verify_mandate_chain(&chain, &revoked_ids, &MandateChainKeys { human_keys, agent_keys }, now_millis) 从根开始离线验证委托链(追溯至人类的签名、链接与深度、sub_delegation、嵌套有效期、行动及 data_classes 和 limits 的权限收窄、最低等级、撤销状态);返回 MandateChainResult { valid, errors, depth, effective_tier }

准入(dcp_ai::v2,spec/profiles/admission)

判断是否将已验证的 V2 bundle 接受为来自运营方已信任责任主体的证据,可选择遵循 strict-v1 配置。信任集合、配置和撤销信息源由运营方指定,绝不从 bundle 或请求中获取。

函数 说明
verify_signed_bundle_v2_at(&b, &policy, now_ms) 在 now_ms(自 Unix 纪元起的毫秒数)运行 verify_signed_bundle_v2_with_policy,所有时间检查均使用该值;其他两个验证函数使用系统时钟。返回 V2VerificationDetails:result 中包含相同的 V2VerificationResult,signer_keys 列出每个已检查复合签名中各组件解析得到的密钥及其验证结果。V2VerificationResult 保持十字段结构,其他两个函数保持原有签名
PrincipalTrustStore::from_json(&json) 加载信任集合(schemas/v2/principal_trust_set.schema.json)
resolve_strict_v1_profile(&json) 加载 strict-v1 配置(schemas/v2/admission_profile.schema.json);policy()、verifier_id()、max_session_duration_seconds() 和 max_revocation_age_seconds() 均为只读
revocation_subjects(&b, &verification) 护照中的 agent_id 和已验证签名者密钥的已排序 kid,供运营方的撤销信息源使用
evaluate_admission_v2(&b, &verification, &AdmissionOptions { .. }) 根据验证结果评估准入,不执行密码学运算或 I/O
admit_signed_bundle_v2(&b, &AdmitOptions { .. }) 在 now_ms(为 None 时使用系统时钟)遵循配置中的策略验证;无配置时使用 policy,之后进行评估

信任集合或配置无法加载、配置没有信任集合、配置与调用方策略同时使用时,均返回 AdmissionConfigError { code, message }。AdmissionResult 使用 §5.2 中的键序列化(verified、verification、principal_trust、profile、profile_compliance、admitted、action_authorized、recorded_decision、trust_set_version、errors);action_authorized 始终为 false。配置中的 verifier_policy 可以缩小 accepted_classical_algs 和 accepted_pq_algs 的范围,验证器会执行这些限制;min_classical、min_pq、accepted_hash_algs 和 max_key_age_days 固定为默认值。

// Fragment, inside a function returning a Result: profile_json, trust_set_json, signed_bundle, now_ms and revocation_source come from your application.
use dcp_ai::v2::{
    evaluate_admission_v2, resolve_strict_v1_profile, revocation_subjects, verify_signed_bundle_v2_at,
    AdmissionOptions, PrincipalTrustStore,
};

let profile = resolve_strict_v1_profile(&profile_json)?;
let trust = PrincipalTrustStore::from_json(&trust_set_json)?;
let verification = verify_signed_bundle_v2_at(&signed_bundle, profile.policy(), now_ms);
// Ask the operator's revocation source about these; None when it cannot answer.
let snapshot: Option<serde_json::Value> = revocation_source(&revocation_subjects(&signed_bundle, &verification));
let result = evaluate_admission_v2(
    &signed_bundle,
    &verification,
    &AdmissionOptions { profile: Some(&profile), trust: Some(&trust), revocation: snapshot.as_ref(), now_ms },
)?;
if result.admitted {
    // Authentic evidence from a trusted principal; not an authorization to act.
}

实验性功能:规范化候选方案 dcp-jcs-v2(须显式选择)

非规范性且未激活:dcp-jcs-v1 仍是唯一的规范化配置,默认设置、构建器、签名器和验证器均不改变。这些模块在 2.11.0 中仅供调用方显式启用。验证通过的候选 bundle 也不赋予信任或准入资格。设计与契约:docs/proposals/canonicalization-candidate(§15 入口处理、§16 路由器、§17 验证器、§18 生成器)。

模块 API
dcp_ai::v2::experimental_candidate_ingress experimental_candidate_ingress(&[u8]):CandidateIngressOutcome::Accept { value, canonical, canonical_sha256 } 或 Reject { class, offset }
dcp_ai::v2::experimental_candidate_router CandidateRouter::new(CandidateRouterConfig { transport, accepted_profiles, historical });解码器 HistoricalAdapter::serde_json_from_slice(),均不是默认选项
dcp_ai::v2::experimental_candidate_verify CandidateVerifier::new(config) 和 verify_at(input, policy, now_ms)
dcp_ai::v2::experimental_candidate_produce sign_payload(context, &CandidateInput, &CandidateKeys) 和 sign_bundle(&BundleParts, &BundleSigner, &BundleOptions);输入的域或形式问题返回 ProduceError::Reject(在任何签名器运行之前),另有 Usage、Provider
use dcp_ai::providers::{ed25519::Ed25519Provider, ml_dsa_65::MlDsa65Provider};
use dcp_ai::v2::composite_ops::CompositeKeyInfo;
use dcp_ai::v2::crypto_provider::CryptoProvider;
use dcp_ai::v2::experimental_candidate_ingress::{experimental_candidate_ingress, CandidateIngressOutcome};
use dcp_ai::v2::experimental_candidate_produce::{sign_payload, CandidateInput, CandidateKeys};

fn main() {
    // The ingress decides on the original bytes: 1.0 is the integer 1, members are sorted.
    if let Ok(CandidateIngressOutcome::Accept { canonical, .. }) = experimental_candidate_ingress(br#"{"b":1.0,"a":[]}"#) {
        println!("{}", String::from_utf8(canonical).unwrap()); // {"a":[],"b":1}
    }
    if let Ok(CandidateIngressOutcome::Reject { class, offset }) = experimental_candidate_ingress(br#"{"a":1,"a":2}"#) {
        println!("{} {}", class.as_str(), offset); // DUPLICATE_KEY 7
    }

    // A producer signs an artifact from those bytes (hybrid keys, today's composite signature).
    let key = |p: &dyn CryptoProvider| {
        let k = p.generate_keypair().unwrap();
        CompositeKeyInfo { kid: k.kid, alg: p.alg().to_string(), secret_key_b64: k.secret_key_b64, public_key_b64: k.public_key_b64 }
    };
    let keys = CandidateKeys { classical: key(&Ed25519Provider), pq: Some(key(&MlDsa65Provider)) };
    let input = CandidateInput::Bytes(br#"{"intent_id":"intent:1","risk":1.0}"#.to_vec());
    let artifact = sign_payload("DCP-AI.v2.Intent", &input, &keys).unwrap();
    println!("{}", artifact.signed_payload["payload_hash"]); // "sha256:..." of {"intent_id":"intent:1","risk":1}
}

wasm 功能

启用 wasm 功能后,crate 会暴露 WebAssembly 绑定:

// Declarations of the wasm-bindgen exports, bodies elided (not runnable)
// Available via wasm-bindgen
fn wasm_verify_signed_bundle(json: &str, pub_key: Option<String>) -> String;
fn wasm_verify_signed_bundle_v2(json: &str, policy_json: Option<String>) -> String; // default policy when None; V1 bundles are rejected under a policy
fn wasm_hash_object(json: &str) -> String;
fn wasm_generate_keypair() -> String;
fn wasm_build_bundle(rpr_json: &str, passport_json: &str, intent_json: &str, policy_json: &str, audit_entries_json: &str, session_nonce: &str) -> String;
fn wasm_sign_bundle(bundle_json: &str, classical_sk_b64: &str, classical_kid: &str, pq_sk_b64: &str, pq_kid: &str) -> String;

为 WASM 编译:

cargo build --target wasm32-unknown-unknown --features wasm

开发

# Build
cargo build

# Tests
cargo test

# Build with WASM
cargo build --features wasm

# Build for WASM target
cargo build --target wasm32-unknown-unknown --features wasm

依赖

  • serde + serde_json — 序列化
  • sha2 — SHA-256
  • sha3 — SHA3-256(双哈希链)
  • ed25519-dalek — Ed25519 密码学
  • fips203 / fips204 / fips205 — ML-KEM-768、ML-DSA-65 和 SLH-DSA-192f(FIPS 203 / 204 / 205)
  • rand — 随机数生成
  • base64 — Base64 编码
  • hex — 十六进制编码
  • wasm-bindgen(可选)— WASM 绑定

许可证

Apache-2.0