Expand description
§dmsg_protocol
Third-party v2 contracts and current implementation boundaries are documented in integration. Registration and dedicated authentication are implemented; generic v2 checkout/membership consumers remain subsequent work, without protocol fallback.
English | 简体中文
Deterministic encoding, document signature verification, and request helpers for dMsg. This crate implements the public protocol on top of dmsg_types. It performs local computation only: no ICP calls, ledger queries, canister storage, network discovery, or account authorization.
Use it to prepare portable COSE documents, verify returned artifacts, construct device approval digests, and check bindings between documents and independently authenticated execution receipts. Common helpers are re-exported at the crate root. Commercial and shared-membership helpers are imported from the public billing and membership modules.
§Installation and dependency direction
During development, use paths relative to your application’s Cargo.toml:
[dependencies]
dmsg_types = { path = "../ic-panda/src/dmsg_types" }
dmsg_protocol = { path = "../ic-panda/src/dmsg_protocol" }Once both versions are published, the corresponding registry dependencies are:
[dependencies]
dmsg_types = "0.4"
dmsg_protocol = "0.4"The runtime dependency is dmsg_protocol → dmsg_types. The reverse reference in the repository is a development dependency used by dmsg_types contract tests and vector generation; applications using only the types do not pull in this protocol crate. Consumers import public DTOs and errors from dmsg_types directly. The examples below also use ed25519-dalek = "3" and, for the approval example, candid = "0.10".
Publication settings do not prove a version is already on crates.io. In this checkout dmsg_types and dmsg_protocol are both version 0.4.0; see the release notes below for publication order.
§API guide
| Task | Entry points | What remains the caller’s responsibility |
|---|---|---|
| Encode protocol records | canonical, decode_canonical, sha256, digest | Use the exact public types, domain and value shape; apply business validation |
| Prepare a document | validate_statement, statement_purpose, prepare_cose | Obtain user consent, choose a trusted key and invoke the signer |
| Assemble/verify | PreparedAttestation::finish, verify_artifact | Establish issuer identity, authorization and current status |
| Describe a signing key | cose_algorithm, public_cose_key, key_thumbprint | Authenticate the key source; do not treat a thumbprint as proof of ownership |
| Identify a signer | account_issuer, validate_uri, validate_namespace | Configure a trusted namespace and bind it to authenticated evidence |
| Prepare ICP approval | prepare_attestation, app_action_statement, approval_message, ATTEST_APPROVAL_DOMAIN, attest_approval_command, DERIVE_APPROVAL_DOMAIN, derive_approval_command, execution_request_id | Obtain current account/device state, sign the Sig_structure and the digest with the device key, submit to the user home |
| Validate request inputs | DeviceInputExt, CoseInitExt, validate_origin, validate_transport_key | Perform server-side authorization, proof-of-possession checks and state transitions |
| Configure a COSE executor | content_root_context, cose_pins::master_key_pin (feature cose-pins) | Create the canister first: the pin depends on its ID; initialize and compare the fetched fingerprint |
| Check execution evidence | signature_digest, execution_receipt_key, match_execution_receipt | Verify IC certificate, expected canister, witness, path and leaf bytes first |
| Bind roots and keys | root_recipients_digest, root_bundle_digest, recovery_device_message, controller_pop_message | Build bundles and proofs in the client; the services recompute and compare |
| Handle names | normalize_handle, price, charge_terms_digest | Execute name/ledger operations in their services |
| Check basic constraints | authenticated, nonzero, expiry, check_sequence, verify | Supply trusted caller/time/state; these helpers do not read or mutate it |
Rustdoc describes parameters, failure behavior and trust boundaries for each entry point. verify is raw strict Ed25519 verification; verify_artifact additionally checks the COSE document profile. authenticated only excludes anonymous and management Principals; it does not establish account membership.
Import commercial helpers from dmsg_protocol::billing::monthly_allowance and dmsg_protocol::{membership::mul_div, integration::required_panda_stake}. Amounts use integer atomic units and business times use UTC Unix milliseconds. Quotes and stake thresholds round up; monthly allowances sum weighted durations before rounding down once. Digest construction performs no authorization; rustdoc describes each validation boundary.
§Sign and verify a document locally
This complete example uses a deterministic test key. Production signing must use securely generated or externally managed keys.
use dmsg_protocol::{account_issuer, key_thumbprint, prepare_attestation, sha256, verify_artifact};
use dmsg_types::{AccountId, Hash, Statement, StatementContent};
use ed25519_dalek::{Signer, SigningKey};
let signer = SigningKey::from_bytes(&[7; 32]); // Test fixture only.
let public = Hash::new(signer.verifying_key().to_bytes());
let original = b"Release 1.0 specification";
let statement = Statement {
issuer: account_issuer("https://example.org/u/", &AccountId([1; 12])),
subject: Some("release/specification".into()),
issued_at: Some(1_800_000_000), // Claimed Unix seconds, not trusted time.
content: StatementContent::Digest {
sha256: sha256(original),
content_type: Some("text/plain".into()),
location: None,
},
};
// The kid is the key's RFC 9679 thumbprint.
let prepared = prepare_attestation(&statement, &public).unwrap();
let thumbprint = prepared.thumbprint;
let signature = signer.sign(&prepared.to_be_signed).to_bytes();
let artifact = prepared.finish(&signature).unwrap();
// The verified statement commits to the original bytes' SHA-256.
assert_eq!(verify_artifact(&artifact).unwrap(), statement);
assert_eq!(key_thumbprint(&artifact.cose_key).unwrap(), thumbprint);prepare_cose returns an unsigned message and Sig_structure = CBOR(["Signature1", protected_bstr, h'', payload_bstr]). Text uses raw UTF-8 (1..4096 bytes); digest documents use the original bytes’ 32-byte SHA-256. FileStatement uses a deterministic CBOR payload combining verbatim text, a file SHA-256 and optional media type/location, under FILE_STATEMENT_PROFILE with the Statement key purpose. Its closed schema and limits are specified in the public protocol. The Rust Statement enum is not an extra wire payload. Issuer, optional subject and claimed issued_at are protected CWT claims; request ID, browser origin and execution deadline are separate execution metadata.
| Algorithm | COSE label | Signer input | Public key (prepare_attestation) / signature (finish) |
|---|---|---|---|
| Ed25519 | -19 | Exact tbs bytes | Raw 32-byte public key; 64-byte signature |
When using an API that hashes internally, pass tbs once rather than hashing it twice. vetKD is not a document-signature algorithm. PreparedAttestation::finish assembles and validates structure but does not verify the signature; verify_artifact does. public_cose_key returns encoded COSE_Key bytes; its input is raw key material. key_thumbprint hashes required public COSE members, excluding kid/alg/key_ops and expanding compressed EC y coordinates. It is not raw-key SHA-256 or a complete key validator.
prepare_attestation names the signing key by its RFC 9679 thumbprint (the kid) and returns the Sig_structure, the encoded public key, the thumbprint and the key purpose. For another kid, sign the message prepare_cose returns and encode the key with public_cose_key. Signature verification is still required before accepting the artifact.
§Construct an ICP device approval
The following constructs a local attestation request and device signatures; it does not contact a canister or grant permission. Real account IDs, device IDs, epochs and sequences must come from the configured, authenticated services. The fixture IDs and keys are for demonstration only.
use candid::Principal;
use dmsg_protocol::{
approval_message, attest_approval_command, execution_request_id, prepare_attestation,
ATTEST_APPROVAL_DOMAIN,
};
use dmsg_types::{AccountId, Approval, AttestRequest, Hash, Statement, StatementContent};
use ed25519_dalek::{Signer, SigningKey};
let account_id = AccountId([1; 12]);
let device_id = Hash::new([2; 32]);
let device_key = SigningKey::from_bytes(&[9; 32]); // Test fixture only.
let device_public: Hash = device_key.verifying_key().to_bytes().into();
let security_epoch = 1;
let sequence = 0;
let statement = Statement {
issuer: "https://example.org/signers/alice".into(),
subject: None,
issued_at: None,
content: StatementContent::Text("Approve release 1.0".into()),
};
// The device signs the exact Sig_structure; the kid is its RFC 9679 thumbprint.
let prepared = prepare_attestation(&statement, &device_public).unwrap();
let mut request = AttestRequest {
account_id,
statement,
origin: "https://example.org".into(),
signature: device_key.sign(&prepared.to_be_signed).to_bytes().into(),
approval: Approval {
device_id,
security_epoch,
sequence,
request_id: execution_request_id(&account_id, security_epoch, device_id, sequence),
expires_at: 1_800_000_060_000, // Unix milliseconds; use a valid live deadline.
signature: Default::default(), // Excluded from the approval digest.
},
};
let home_user = Principal::from_slice(&[1, 1]); // Deployment fixture.
let digest = approval_message(
home_user,
&request.account_id,
ATTEST_APPROVAL_DOMAIN,
&attest_approval_command(&request.statement, &request.origin, &request.signature),
&request.approval,
);
request.approval.signature = device_key.sign(digest.as_slice()).to_bytes().into();
assert_eq!(prepared.thumbprint, dmsg_protocol::key_thumbprint(&prepared.cose_key).unwrap());The approval passes ATTEST_APPROVAL_DOMAIN (dmsg/attest/v1) and attest_approval_command, the triple (statement, origin, signature), to approval_message, wrapped in dmsg/device-approval/v2; the user canister verifies the same triple, the device signature over the Sig_structure, and records a certified receipt. Changing any approved field requires a new approval. Application actions use app_action_statement to build the statement of an AppActionAttestRequest and bind action.origin.
For account mutations, use approval_message with dmsg/account/v2 and (expected_version, command). A recovered device’s root derivation uses DERIVE_APPROVAL_DOMAIN with derive_approval_command, which is (generation, transport_public_key, max_cycles). Sequence consumption, deadline checks and permission decisions happen in the service. After an unknown outcome, reconcile the original request instead of generating a new signing operation.
§Encoding and identity helpers
use dmsg_protocol::{canonical, decode_canonical, digest, normalize_handle};
use dmsg_types::Hash;
let value = Hash::new([0x42; 32]);
let encoded = canonical(&value);
assert_eq!(decode_canonical::<Hash>(&encoded).unwrap(), value);
assert_ne!(digest("example/a/v1", &value), digest("example/b/v1", &value));
assert_eq!(normalize_handle("Alice_01").unwrap(), "alice_01");canonical uses RFC 8949 core deterministic CBOR. digest(domain, value) is SHA256(CBOR([1, domain, value])). Both operate on trusted serializable values and panic if their Serialize implementation fails; neither enforces business semantics. decode_canonical caps input at 65,536 bytes and requires exact re-encoding, returning errors for malformed or noncanonical records. It is not the artifact decoder: external COSE verification must preserve the original protected bytes.
AccountId is 12 binary bytes and 20 characters of canonical Xid text. Hash/OpId are 32-byte strings. Identity adapters require an explicit canonical URI namespace ending in / or :, without query/fragment; they neither discover services nor establish account existence. validate_origin accepts an exact HTTPS origin without a trailing path; Local deployments also accept exact loopback HTTP origins. The user and COSE homes check it against their own deployment environment. Syntax checks do not prove the browser’s actual origin.
Business timestamps and durations use milliseconds, while Statement.issued_at uses seconds and ICRC created_at_time uses nanoseconds. expiry requires a strictly future deadline within the supplied maximum lifetime. check_sequence returns ResultExpired for old sequences and VersionConflict for future/exhausted sequences; it does not update the counter. price uses a fixed PANDA schedule with 8 decimal places and requires an already validated handle; it is not a generic token price oracle.
§Evidence and timestamp boundaries
verify_artifact checks the profile and mathematical signature only. Compare original content with the verified statement yourself: embedded text must match exactly, and a digest or file statement must match the original file’s SHA-256; embedded opinion text does not verify the referenced file. Issuer binding, authorization, current status and timestamp trust are not checked.
Before calling match_execution_receipt, independently verify the IC certificate against a trusted root, the expected user canister, witness, requested path and leaf bytes. execution_receipt_key constructs the single raw path segment b"execution/" || account_id[12] || request_id[32]. The matcher requires schema 2, then matches issuer, signing-bytes digest, public-key thumbprint and raw-signature digest. It does not independently check the receipt’s account/request IDs, origin, deadline or external project permissions. Authenticate the expected path and separately apply any additional policy.
signature_digest is SHA-256 of the raw signature bytes used by execution receipts; it does not verify the signature or dMsg profile.
Verification accepts an opaque token of at most 131,072 bytes at unprotected header 270 without checking it. An encoded COSE_Key is limited to 2,048 bytes and a COSE_Sign1 artifact to 196,608. Trusted timestamp verification, TSA networking, SCITT transparency, archival and chain anchoring are outside this crate.
§Errors, protocol references, and validation
Functions return dmsg_types::Result<T>. Common errors are InvalidInput for malformed semantic inputs, IntegrityFailed for invalid bytes/signatures/bindings, UnsupportedProtocol for unsupported algorithms or profile semantics, and QuotaExceeded for size limits. Consult individual rustdoc entries for exact mappings. Diagnostic strings are not stable machine-readable error codes. Network failures are handled by your transport, not this local crate.
Use the public protocol, CDDL, types guide, and vectors from the same commit. These links follow main and can change. The document profile media types are experimental project names, not registered standards.
Run from the workspace root:
cargo test -p dmsg_protocol -p dmsg_types --locked
RUSTDOCFLAGS="-D warnings" cargo doc -p dmsg_protocol --no-deps --locked
cargo clippy -p dmsg_protocol --all-targets --locked -- -D warnings
cargo run -p dmsg_types --example protocol_vectors --locked > /tmp/dmsg-vectors.json
node scripts/verify-dmsg-vectors.mjs /tmp/dmsg-vectors.jsonThe English README is included as crate documentation and its Rust examples run as doctests. Keep both language versions’ example code identical, translating comments only. missing_docs warnings help maintain API coverage.
For the COSE deployment pin, run cargo run -p dmsg_protocol --features cose-pins --example cose_pins -- <canister-id> Production; it prints the master field of a CoseInit and the content-root public key derived offline from the mainnet master key (pocketic as the third argument selects the keys of PocketIC and the local icp network). For offline verification, run cargo run -p dmsg_protocol --example verify -- artifact.cbor. The input is a CBOR SignedArtifact record containing cose_sign1 and cose_key byte strings, not a bare COSE_Sign1 file. Output reports mathematical verification only. Local performance benchmarks use cargo bench -p dmsg_protocol --bench validation --locked; these measure host Rust execution, not canister instructions or end-to-end latency. Real-Wasm integration tests use POCKET_IC_BIN=/path/to/pocket-ic bash scripts/test-dmsg.sh.
§Release notes for maintainers
Publish dmsg_types first, then dmsg_protocol. The latter’s dependency specifies both a local path and version 0.4.0; Cargo uses the registry version in a published package. Keep that version requirement aligned with the public contracts.
0.2.0 removes 0.1.x public items that no production code used. Replace finish_cose with parse_signing_input(tbs)?.into_signature(public)?.finish(signature), ExecuteRequestExt::approval_message with approval_message over ATTEST_APPROVAL_DOMAIN and attest_approval_command for document attestations or DERIVE_APPROVAL_DOMAIN and derive_approval_command for root derivations, and ExecutionResult::output() with a match on ExecutionOutcome::Completed. dmsg_types::handle::HandleInit gains the required governance field and replaces home_user with environment, issuer_namespace and an append-only user_homes, routed by each account ID’s allocator fingerprint. The new handle_bucket and HANDLE_BUCKET_BITS define where the registry certifies a handle. CoseInit replaces initial_home_user with user_homes and gains governance; PaymentInit replaces home_user with environment, issuer_namespace and user_homes, and PaymentConfiguration lists user_homes; DirectoryInit gains governance. The new agent::check_user_home, validate_user_homes, account_home, is_account_home, validate_custom_domains and MAX_USER_HOMES (64) give every service the same allocator-fingerprint routing. MIN_HANDLE_PRICE, and so price for 7–20-byte names, drops from 5,000 to 100 PANDA to match the live legacy registry. ProductRegistration replaces beneficiary_authority with an append-only beneficiary_authorities list, and validate_subject requires the subject’s authority to be listed; CommerceInit replaces max_subjects and daily_orders with limits: CommerceLimits. dmsg_types::integration::LEASE_RENEW_WINDOW_MS (10 minutes) is the lease renewal window shared by commerce and membership. CommerceLimits gains calls_per_caller, and the new CommerceStats reports a commerce canister’s live counts; PandaServiceConfig replaces commerce_canister with the append-only commerce_homes: Vec<CommerceHome>, the commerce canister of each user home, and gains qualifications_per_minute. ExecutionResult gains cycles_charged, the threshold fee a returned management call consumed, to which COSE and user budgets settle; the new CoseStats reports a COSE executor’s live counters. content_root_context builds the vetKD content-root context, and the optional cose-pins feature adds cose_pins::master_key_pin and the cose_pins example for offline COSE master-key pins.
0.2.0 also removes threshold document signing and hosted controller signing. SignRequest, AppActionSignRequest, AgentEventSignRequest, SigningKeyRef, KeySelector, ExecutionKind, ExecutionOutput, RootTarget, RecoveryPolicy, RecoveryConfirmation, SignRequestExt, KeyRequestExt, recovery_confirmation_message, ES256K support (k256) and the AgentController purpose are gone. Documents are signed by device keys: prepare_attestation returns the Sig_structure and thumbprint and PreparedAttestation::finish attaches the device signature, AttestRequest / AppActionAttestRequest carry the device signature, and the approval binds (statement, origin, signature) under ATTEST_APPROVAL_DOMAIN; ExecutionReceipt is schema 2 without max_cycles. ContentRootRef becomes { generation, suite: "dmsg-root-v2", bundle_digest, recipients_digest, body_digest } with root_recipients_digest and root_bundle_digest; DeriveRootRequest names a committed generation and is only accepted from the device a completed login recovery enrolled (DERIVE_APPROVAL_DOMAIN, derive_approval_command). Recovery is login-based: RecoveryRequest drops generation, request_recovery takes (account_id, request, device_proof) with recovery_device_message, DisputeRecovery { op_id } cancels, SetRecoveryDelay replaces SetRecovery/ConfirmRecovery, and AccountInfo exposes recovery_delay_ms, pending_recovery and recovered_device. RegisterController carries a proof built with controller_pop_message. CoseInit has a single master: MasterKey, KeyDescriptor describes the shared content-root key, ExecutionGrant carries generation and transport_key, and SecuritySnapshot is schema 4 without account status or recovery keys. HandleInit gains registration_homes; AppRegistration drops user_homes and cose_homes; ExecutionWeights drops ecdsa_secp256k1.
0.2.0 also makes application actions application-defined. AppActionCommand, ActionReviewOutcome, ActionRequestedChange and action_input_hash are removed: dMsg no longer contains TokenList commands or encodes TokenList’s input. An application registers AppRegistration.action_schema: Option<ActionSchema>, required exactly with SignAction and checked by validate_action_schema. AppAction.command is an ActionCommand { name, args: ActionArgs } of the closed ActionValue model, and AppAction replaces actor_id with the opaque actor bytes and input_hash, subject_hash, precondition_hash, role_snapshot_hash, signing_policy_hash and rule_set_hash with schema_hash (action_schema_hash); the product commits its own context in intent_hash. validate_action_command(action, schema) checks a command against its schema, and validate_action_admission uses the registration’s schema. The receiver, not dMsg, checks that its executed input projects to the signed command.
0.3.0 removes parse_signing_input, PreparedStatement, PreparedSignature, match_signing_result and agent::delegation_id_prefix, which no production code calls now that devices sign documents. Assemble an artifact with prepare_attestation(statement, signing_pub)?.finish(signature); for another kid, sign the prepare_cose message and encode the key with public_cose_key. Bind an execution receipt with match_execution_receipt. 0.3.0 also removes billing::usage_key, which no service uses now that the user home keys monthly ledgers by account and month, adds account_admission_message for the registration admission ticket a user home verifies, and makes validate_ed25519_key public. The matching dmsg_types changes add user::AdmissionTicket, UserInit.admission_key, CreateAccount.admission and the MAX_HOME_ACCOUNTS (21,000,000), MAX_OPERATION_RECEIPTS, MAX_PENDING_BINDINGS, BINDING_ACCEPT_MS, MAX_ADMISSION_TTL_MS and MAX_HOURLY_ACCOUNT_CALLS constants, and remove ExecutionUsage.held_units. Following agent-protocols 0.11.3, which drops controller succession and lets a restricted controller manage the credentials within its ceiling, controller_pop_message no longer takes superseded generations, HostedController and AccountCommand::RegisterController lose supersedes, and DirectoryInit.delegation_query_url becomes delegation_service, the HTTPS origin of the delegation service.
Cargo omits the path-only dmsg_protocol development dependency from the normalized dmsg_types package manifest. That avoids a publication dependency cycle, but its repository contract tests and vector example still require the checkout’s development dependency. Run these from the workspace; a packaged dmsg_types test suite is not equivalent.
Validate the dmsg_types package first. Once its version is available in the registry, validate dmsg_protocol with cargo package -p dmsg_protocol --locked and cargo publish -p dmsg_protocol --dry-run --locked before publishing. A local checkout containing dmsg_types is not a substitute for its registry availability during normal package resolution. Development interfaces do not promise compatibility with earlier experimental encodings. Production deployment, external services, capacity and audit acceptance require separate validation.
Application-action v1 is a separate profile with an AppAction key purpose. Each
application registers the schema of its own commands; see the profile and
implementation boundary. Rust COSE
preparation/verification supports it; dmsg_user.attest and the document browser
flow explicitly reject it, and attest_app_action is its only entry.
0.4.0 adds connect, the dmsg-connect/1 rules shared by devices, the bridge page and the relay: command validation, proof_message, operation_digest, pairing_id, pairing_mac, the sealing contexts request_aad, wrap_info and response_info, and the structural checks validate_request and validate_grant; their vectors are tests/vectors/client/connect-v1.json. validate_origin no longer accepts chrome-extension:// origins: dMsg has no browser extension, and the client vouches for web origins through dmsg-connect/1. authentication::verify_recorded_leaf verifies a certified leaf kept as evidence, at any certificate time, and verify_attestation checks an artifact with its certified execution receipt end to end. The matching dmsg_types change adds connect with the request, envelope, reply, invitation, grant, proof and device-command payload types.
Modules§
- agent
- Agent Delegation hosted-controller policy and principal documents. Agent Delegation 1.0 rules for self-held controllers and principal publication.
- app_
action - Application-action profile, registered command schemas and admission checks. Application-action encoding and validation against a registered command schema, without product authority claims.
- authentication
- Independent verification of dedicated third-party IC authentication proofs. Independent IC authentication verification. Trust roots are supplied by the relying product.
- billing
- dmsg-commerce/1 arithmetic, calendar boundaries and authenticated leaf keys.
- commerce_
v2 - Pure operational v2 money and product-contract rules. Pure v2 money/contract rules. Ledger, product and SNS replies must be authenticated separately.
- connect
- dmsg-connect/1 digests, sealing contexts and structural checks.
dmsg-connect/1 rules shared by devices, the bridge page, the relay and
the vectors (
docs/protocol/connect-v1_zh.md): page commands, proof and operation digests, pairing IDs and MACs, the sealing contexts, and the structural checks of requests and grants. Nothing here touches a key. - integration
- Third-party authentication, signing and subscription contracts. External integration validation and exact commitments. No network or storage.
- login
- dmsg-login/1 request and callback checks. dmsg-login/1 checks shared by the login page vectors and local clients.
- membership
- Exact threshold arithmetic shared by membership and product contracts.
- product_
book - Shared product-side interval reservation and contract CAS. Shared product-side interval CAS. Product roles/pricing are checked by its adapter before entry.
Structs§
- Prepared
Attestation - Exact signing input of a statement attested by one device key.
Constants§
- ATTEST_
APPROVAL_ DOMAIN - Device-approval domain of every
AttestRequestandAppActionAttestRequest. - COSE_
ALGORITHM - The one document signature algorithm: Ed25519 (COSE -19).
- CTT_
HEADER - COSE header 270: unprotected timestamp token; its presence establishes no TSA trust.
- CWT_
CLAIMS - COSE header 15: protected CWT claims (issuer, optional subject and issued-at).
- DERIVE_
APPROVAL_ DOMAIN - Device-approval domain of every
DeriveRootRequest. - DIGEST_
PROFILE - Experimental dMsg SHA-256 document profile media type (v1), used in protected header 16.
- FILE_
STATEMENT_ CONTENT_ TYPE - Content type of the deterministic CBOR file-statement payload.
- FILE_
STATEMENT_ PROFILE - Experimental dMsg statement about one file (v1), used in protected header 16.
- HANDLE_
BUCKET_ BITS - Leading digest bits that select a handle’s certification bucket.
- HASH_
ALGORITHM - COSE header 258: digest profile hash algorithm, fixed to SHA-256 (-16).
- MAX_
ARTIFACT_ BYTES - Maximum COSE_Sign1 size in bytes (196,608), including optional timestamp evidence.
- MAX_
COSE_ KEY_ BYTES - Maximum encoded public COSE_Key size in bytes (2,048).
- MAX_
FILE_ STATEMENT_ BYTES - Maximum encoded file-statement payload size (16,384 bytes).
- MAX_
KID_ BYTES - Maximum document key identifier size in bytes (256); signing requires a nonempty kid.
- MAX_
TIMESTAMP_ BYTES - Maximum opaque timestamp token size in bytes (131,072).
- MAX_
URI_ BYTES - Maximum canonical identity URI or statement subject size in bytes (8,192).
- MIN_
HANDLE_ PRICE - Lowest registration price in PANDA base units, charged for 7..19-byte names.
- PAYLOAD_
LOCATION - COSE header 260: optional original-content URI in the digest profile.
- PREIMAGE_
CONTENT_ TYPE - COSE header 259: optional original-content media type in the digest profile.
- TEXT_
CONTENT_ TYPE - Required content type of the text profile; not used in the digest profile.
- TEXT_
PROFILE - Experimental dMsg text document profile media type (v1), used in protected header 16.
- TYPE_
HEADER - COSE header 16: protected document profile media type.
Traits§
- Cose
Init Ext - Validate fixed COSE deployment configuration without accessing ICP master keys.
- Device
Input Ext - Local validation of a device enrollment proposal; no device registration or authorization.
Functions§
- account_
admission_ message - Build the digest an admission issuer signs for one caller’s account
creation under
dmsg/account-admission/v1. - account_
issuer - Append canonical Xid text to a namespace accepted by
validate_namespace. - app_
action_ statement - Build the statement an application-action attestation signs.
- approval_
message - Build the digest signed by a device to authorize an operation.
- attest_
approval_ command - Command an attestation approval binds under
ATTEST_APPROVAL_DOMAIN: the statement, the checked origin and the device’s document signature. - authenticated
- Reject anonymous and management-canister Principals.
- canonical
- Encode trusted protocol values using RFC 8949 core deterministic CBOR.
- charge_
terms_ digest - Commit to name-registration ledger charge terms under
dmsg/handle-charge/v1. - check_
sequence - Check an approval sequence against the next expected device sequence.
- content_
root_ context - vetKD context of every content-root key:
canonical(("dmsg/content-root/v2", environment, derivation_version)). - controller_
pop_ message - Build the proof-of-possession digest a controller key signs for its
registration under
dmsg/controller-pop/v1. - decode_
canonical - Decode a protocol record and require byte-for-byte canonical re-encoding.
- derive_
approval_ command - Command a derivation approval binds under
DERIVE_APPROVAL_DOMAIN: the root generation, the transport public key and the cycles ceiling. - digest
- Compute
SHA256(CBOR([1, domain, value]))with deterministic encoding. - execution_
receipt_ key - Return the single certified-tree path segment for an execution receipt.
- execution_
request_ id - Derive an execution ID under
dmsg/execution-request/v2. - expiry
- Check
now < expires_atandexpires_at - now <= maximum. - handle_
bucket - Certification bucket of a canonical handle: the leading
HANDLE_BUCKET_BITSbits ofdigest("dmsg/handle-bucket/v1", handle). - key_
thumbprint - Compute the RFC 9679 SHA-256 thumbprint of required public COSE key members.
- match_
execution_ receipt - Verify an artifact and match it against an already authenticated execution receipt.
- nonzero
- Require at least one nonzero byte; this does not validate length or key structure.
- normalize_
handle - Validate a handle and convert ASCII letters to lowercase.
- prepare_
attestation - Prepare the exact bytes a device signs for a statement.
- prepare_
cose - Prepare a document’s COSE_Sign1 message and exact bytes to sign.
- price
- Return the fixed PANDA registration price in base units (8 decimal places).
- public_
cose_ key - Encode a public-only Ed25519 COSE_Key.
- recovery_
device_ message - Build the proof-of-possession digest a new device signs for a recovery
request under
dmsg/recovery-device/v1. - root_
bundle_ digest - Commitment to a root bundle: its recipients digest and the SHA-256 of its
body. The user home checks both parts at
CommitRoot. - root_
recipients_ digest - Digest of the recipients a root bundle of
generationis wrapped to: the active device IDs in ascending order plus the generation, which names the vetKD recovery identity.devicesmay be given in any order. - sha256
- SHA-256 of the exact supplied bytes, without CBOR framing or domain separation.
Use
digestfor versioned protocol commitments. - signature_
digest - Hash raw signature bytes extracted from a COSE_Sign1 message.
- statement_
purpose - Select Statement for text/files, FileAttestation for digests and AppAction for typed actions.
- validate_
ed25519_ key - Check that
bytesis a 32-byte, non-weak Ed25519 verification key. - validate_
namespace - Validate a fixed identity URI prefix before appending an identity.
- validate_
origin - Validate an exact web origin of at most 256 bytes.
- validate_
statement - Check the supported document profile’s claims and content limits.
- validate_
transport_ key - Validate a 48-byte compressed vetKD transport public key.
- validate_
uri - Validate a canonical absolute ASCII URI without rewriting it or fetching it.
- verify
- Strictly verify an Ed25519 signature over the supplied message bytes.
- verify_
artifact - Verify supported COSE document profiles and their mathematical signature.
- verify_
attestation - Verify an attestation end to end as kept evidence: the artifact’s
signature, the IC certificate of its execution receipt under a pinned
root and home at
execution/<account><request>, and the receipt’s binding to the artifact, account and request. Returns the statement, the receipt and the certificate time in Unix milliseconds.