diff --git a/CHANGELOG.md b/CHANGELOG.md index 7f62517c..a5617b5e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ## [Unreleased] +### Changes + +- Held email credential admission is available behind `[held_credentials]`, off by default. With the flag off, a held presentation is refused before any verifier work. Adds the `held_credential_nonce` table (migration `m20261105_000000_held_credential_nonce`). The migration is forward-only once it has run. + ## [1.21.6] - 2026-10-21 ### Release notes diff --git a/Cargo.lock b/Cargo.lock index cc5c798e..22a3a97f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -9947,6 +9947,7 @@ dependencies = [ "clap", "core-foundation 0.9.4", "core-foundation-sys", + "curve25519-dalek", "ed25519-dalek", "flate2", "futures", @@ -10009,6 +10010,7 @@ dependencies = [ "tracing-log", "tracing-opentelemetry", "tracing-subscriber", + "url", "uuid", "x509-parser 0.16.0", ] diff --git a/test/m1-realdata-e2e/Cargo.lock b/test/m1-realdata-e2e/Cargo.lock index f914258f..642217af 100644 --- a/test/m1-realdata-e2e/Cargo.lock +++ b/test/m1-realdata-e2e/Cargo.lock @@ -8037,6 +8037,7 @@ dependencies = [ "hmac 0.12.1", "hyper 0.14.32", "if-addrs", + "k256", "lazy_static", "libc", "multer", @@ -8063,6 +8064,7 @@ dependencies = [ "serde_json", "serde_with 3.16.1", "sha2 0.10.9", + "sha3", "sqlx-core", "subtle", "tempfile", @@ -8081,6 +8083,7 @@ dependencies = [ "tracing-log", "tracing-opentelemetry", "tracing-subscriber", + "url", "uuid", ] diff --git a/test/w5-policy-runtime-node-e2e/Cargo.lock b/test/w5-policy-runtime-node-e2e/Cargo.lock index 1f4098e9..c3d0abd1 100644 --- a/test/w5-policy-runtime-node-e2e/Cargo.lock +++ b/test/w5-policy-runtime-node-e2e/Cargo.lock @@ -8485,6 +8485,7 @@ dependencies = [ "hmac 0.12.1", "hyper 0.14.32", "if-addrs", + "k256", "lazy_static", "libc", "multer", @@ -8511,6 +8512,7 @@ dependencies = [ "serde_json", "serde_with 3.16.1", "sha2 0.10.9", + "sha3", "sqlx-core", "subtle", "tempfile", @@ -8529,6 +8531,7 @@ dependencies = [ "tracing-log", "tracing-opentelemetry", "tracing-subscriber", + "url", "uuid", ] diff --git a/tinycloud-core/src/migrations/m20261105_000000_held_credential_nonce.rs b/tinycloud-core/src/migrations/m20261105_000000_held_credential_nonce.rs new file mode 100644 index 00000000..863e318b --- /dev/null +++ b/tinycloud-core/src/migrations/m20261105_000000_held_credential_nonce.rs @@ -0,0 +1,194 @@ +//! TC-1452: `held_credential_nonce` table. A presentation for a held credential +//! spends its nonce by deleting the row whose audience, nonce and account all +//! match, so a nonce is single use and bound to the account it was minted for. +//! Every consume first prunes rows with `expires_at <= now`, so `expires_at` is +//! indexed to keep that prune from scanning the table. + +use sea_orm_migration::prelude::*; + +use crate::models::held_credential_nonce; + +const EXPIRES_AT_INDEX: &str = "idx_held_credential_nonce_expires_at"; + +#[derive(DeriveMigrationName)] +pub struct Migration; + +#[async_trait::async_trait] +impl MigrationTrait for Migration { + async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> { + manager + .create_table( + Table::create() + .table(held_credential_nonce::Entity) + .if_not_exists() + .col( + ColumnDef::new(held_credential_nonce::Column::Audience) + .string() + .not_null(), + ) + .col( + ColumnDef::new(held_credential_nonce::Column::Nonce) + .string() + .not_null(), + ) + .col( + ColumnDef::new(held_credential_nonce::Column::Account) + .string() + .not_null(), + ) + .col( + ColumnDef::new(held_credential_nonce::Column::ExpiresAt) + .big_integer() + .not_null(), + ) + .primary_key( + Index::create() + .col(held_credential_nonce::Column::Audience) + .col(held_credential_nonce::Column::Nonce), + ) + .to_owned(), + ) + .await?; + manager + .create_index( + Index::create() + .name(EXPIRES_AT_INDEX) + .table(held_credential_nonce::Entity) + .col(held_credential_nonce::Column::ExpiresAt) + .if_not_exists() + .to_owned(), + ) + .await + } + + async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> { + manager + .drop_index( + Index::drop() + .name(EXPIRES_AT_INDEX) + .table(held_credential_nonce::Entity) + .if_exists() + .to_owned(), + ) + .await?; + manager + .drop_table( + Table::drop() + .table(held_credential_nonce::Entity) + .if_exists() + .to_owned(), + ) + .await + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::test_support::PostgresTestSchema; + use sea_orm::{ConnectionTrait, Database, DatabaseConnection, DbBackend, Statement}; + + /// Columns of the expires_at index on SQLite, in key order. Empty when absent. + async fn sqlite_index_columns(db: &DatabaseConnection) -> Vec { + db.query_all(Statement::from_string( + DbBackend::Sqlite, + format!("PRAGMA index_info('{EXPIRES_AT_INDEX}')"), + )) + .await + .unwrap() + .iter() + .map(|row| row.try_get("", "name").unwrap()) + .collect() + } + + async fn sqlite_table_exists(db: &DatabaseConnection) -> bool { + db.query_one(Statement::from_string( + DbBackend::Sqlite, + "SELECT name FROM sqlite_master WHERE type = 'table' AND name = 'held_credential_nonce'" + .to_string(), + )) + .await + .unwrap() + .is_some() + } + + /// Definition of the expires_at index on Postgres, or `None` when absent. + async fn postgres_index_def(db: &DatabaseConnection) -> Option { + db.query_one(Statement::from_string( + DbBackend::Postgres, + format!( + "SELECT indexdef FROM pg_indexes \ + WHERE schemaname = current_schema() AND indexname = '{EXPIRES_AT_INDEX}'" + ), + )) + .await + .unwrap() + .map(|row| row.try_get("", "indexdef").unwrap()) + } + + async fn postgres_table_exists(db: &DatabaseConnection) -> bool { + db.query_one(Statement::from_string( + DbBackend::Postgres, + "SELECT to_regclass('held_credential_nonce') IS NOT NULL AS present".to_string(), + )) + .await + .unwrap() + .unwrap() + .try_get("", "present") + .unwrap() + } + + #[tokio::test] + async fn sqlite_expires_at_index_follows_up_and_down() { + let directory = tempfile::tempdir().unwrap(); + let url = format!( + "sqlite://{}?mode=rwc", + directory.path().join("nonce.db").display() + ); + let db = Database::connect(url).await.unwrap(); + let manager = SchemaManager::new(&db); + + Migration.up(&manager).await.unwrap(); + assert_eq!(sqlite_index_columns(&db).await, ["expires_at"]); + + Migration.down(&manager).await.unwrap(); + assert!(sqlite_index_columns(&db).await.is_empty()); + assert!(!sqlite_table_exists(&db).await); + + Migration.up(&manager).await.unwrap(); + assert_eq!(sqlite_index_columns(&db).await, ["expires_at"]); + } + + #[tokio::test] + async fn postgres_expires_at_index_follows_up_and_down() { + // The state a node upgrading to this migration boots with: this migration + // and everything after it still unapplied. + let this = crate::migrations::Migrator::migrations() + .iter() + .position(|migration| migration.name() == Migration.name()) + .unwrap() as u32; + let Some(fixture) = PostgresTestSchema::migrated_through( + "postgres_expires_at_index_follows_up_and_down", + Some(this), + ) + .await + else { + return; + }; + let db = &fixture.conn; + let manager = SchemaManager::new(db); + assert!(postgres_index_def(db).await.is_none()); + + Migration.up(&manager).await.unwrap(); + let def = postgres_index_def(db).await.expect("index created by up"); + assert!(def.ends_with("(expires_at)"), "{def}"); + + Migration.down(&manager).await.unwrap(); + assert!(postgres_index_def(db).await.is_none()); + assert!(!postgres_table_exists(db).await); + + Migration.up(&manager).await.unwrap(); + let def = postgres_index_def(db).await.expect("index recreated by up"); + assert!(def.ends_with("(expires_at)"), "{def}"); + } +} diff --git a/tinycloud-core/src/migrations/mod.rs b/tinycloud-core/src/migrations/mod.rs index 634b25de..5abea056 100644 --- a/tinycloud-core/src/migrations/mod.rs +++ b/tinycloud-core/src/migrations/mod.rs @@ -29,6 +29,7 @@ pub mod m20261015_000000_delegation_cursor_index; pub mod m20261017_000000_epoch_order_space_index; pub mod m20261018_000000_epoch_head; pub mod m20261020_000000_current_kv_key_c_index; +pub mod m20261105_000000_held_credential_nonce; pub struct Migrator; @@ -66,6 +67,7 @@ impl MigratorTrait for Migrator { Box::new(m20261017_000000_epoch_order_space_index::Migration), Box::new(m20261018_000000_epoch_head::Migration), Box::new(m20261020_000000_current_kv_key_c_index::Migration), + Box::new(m20261105_000000_held_credential_nonce::Migration), ] } } diff --git a/tinycloud-core/src/models/held_credential_nonce.rs b/tinycloud-core/src/models/held_credential_nonce.rs new file mode 100644 index 00000000..3a162534 --- /dev/null +++ b/tinycloud-core/src/models/held_credential_nonce.rs @@ -0,0 +1,21 @@ +use sea_orm::entity::prelude::*; + +/// A nonce minted for held-credential presentation, bound to one audience and +/// one canonical `did:pkh:eip155` account. A row is spent by deleting it, so +/// the table holds only unspent nonces. +#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)] +#[sea_orm(table_name = "held_credential_nonce")] +pub struct Model { + #[sea_orm(primary_key, auto_increment = false)] + pub audience: String, + #[sea_orm(primary_key, auto_increment = false)] + pub nonce: String, + pub account: String, + /// Unix seconds after which the nonce can no longer be spent. + pub expires_at: i64, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation {} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/tinycloud-core/src/models/mod.rs b/tinycloud-core/src/models/mod.rs index 8e7f85a0..23ff1d84 100644 --- a/tinycloud-core/src/models/mod.rs +++ b/tinycloud-core/src/models/mod.rs @@ -15,6 +15,7 @@ pub mod encryption_network_member; pub mod encryption_nonce; pub mod epoch; pub mod epoch_head; +pub mod held_credential_nonce; pub mod hook_delivery; pub mod hook_subscription; pub mod invocation; diff --git a/tinycloud-node-server/Cargo.toml b/tinycloud-node-server/Cargo.toml index e9cb7897..1a1d6fe1 100644 --- a/tinycloud-node-server/Cargo.toml +++ b/tinycloud-node-server/Cargo.toml @@ -20,6 +20,10 @@ path = "src/main.rs" anyhow = "1" # Canonical-point check for pinned issuer keys (issuer_set.rs). ed25519-dalek = { version = "2", default-features = false, features = ["std"] } +k256 = { version = "0.13.4", features = ["ecdsa"] } +sha3 = "0.10" +# WHATWG URL parsing for the SIWE origin check (held_email.rs). +url = "2" aes-gcm = "0.10" async-trait.workspace = true # No default HTTPS client: the SDK's default pulls in rustls with aws-lc-rs, @@ -118,6 +122,8 @@ default-features = false features = ["sqlite", "postgres", "mysql", "tokio", "verification-count-test-hook"] [dev-dependencies] +# Builds the small-order-R forgery vector in held_email tests (TC-1541 item 2); already in the lock. +curve25519-dalek = "4" # Parse production Rust items in the DID resolver source guard (tests only). syn = { version = "2", features = ["full", "visit"] } quote = "1" @@ -133,8 +139,6 @@ chrono = { version = "0.4", default-features = false, features = ["clock", "serd # zlib compressibility of raw stored bytes in tests/at_rest_harness.rs (TC-887). # Already in the lock through ssi-status; adds no new crate. flate2 = "1" -k256 = { version = "0.13.4", features = ["ecdsa"] } -sha3 = "0.10" # The Rust half of the JS SDK: builds the same host and session SIWE # delegations a real `signIn` sends (tests/postgres_round_trip_budget.rs). tinycloud-sdk-wasm = { path = "../tinycloud-sdk-wasm" } diff --git a/tinycloud-node-server/src/config.rs b/tinycloud-node-server/src/config.rs index 8e2c2dc2..1c836e29 100644 --- a/tinycloud-node-server/src/config.rs +++ b/tinycloud-node-server/src/config.rs @@ -49,6 +49,10 @@ pub struct Config { pub public_spaces: PublicSpacesConfig, #[serde(default)] pub share_email: ShareEmailConfig, + /// TC-1452: admission of held email credential presentations. Default OFF; + /// inert until enabled. + #[serde(default)] + pub held_credentials: HeldCredentialsConfig, #[serde(default)] pub retention: RetentionConfig, #[serde(default)] @@ -181,6 +185,15 @@ fn default_share_clock_skew() -> i64 { fn default_share_challenge_ttl() -> u64 { 120 } +/// TC-1452: held email credential admission. Inert unless `enabled`. +#[derive(Serialize, Deserialize, Debug, Default, Clone, Hash, PartialEq, Eq)] +#[serde(default)] +pub struct HeldCredentialsConfig { + /// Default OFF. When off, held presentations are refused before any work. + pub enabled: bool, + /// The relying-party audience a SIWE message must name. Required when enabled. + pub audience: Option, +} fn default_share_space_name() -> String { "default".to_owned() } diff --git a/tinycloud-node-server/src/held_email.rs b/tinycloud-node-server/src/held_email.rs new file mode 100644 index 00000000..7440ad00 --- /dev/null +++ b/tinycloud-node-server/src/held_email.rs @@ -0,0 +1,2666 @@ +//! Admission for a presentation of a held email credential (profile +//! `tinycloud.email-held/v1`, vct `opencredentials.email/v1`). +//! +//! Port of the TypeScript verifier in `held-credentials/` (verify.ts, siwe.ts, +//! encoding.ts, did.ts, crypto.ts, rows.ts). Refusal codes keep the TypeScript +//! names. Verification is two-phase so the nonce is spent before any signature +//! work: `precheck` (no side effects), then the caller consumes the nonce, then +//! `verify`. Only the nonce store touches the database. + +use crate::issuer_set::{IssuerSet, IssuerWindowError}; +use base64::{decode_config, encode_config, URL_SAFE_NO_PAD}; +use ed25519_dalek::{Signature, VerifyingKey}; +use k256::ecdsa::{RecoveryId, Signature as EcdsaSignature, VerifyingKey as EcdsaVerifyingKey}; +use serde::de::{self, MapAccess, SeqAccess, Visitor}; +use serde::{Deserialize, Deserializer}; +use serde_json::{Map, Value}; +use sha2::{Digest, Sha256}; +use sha3::Keccak256; +use std::collections::{BTreeMap, BTreeSet}; +use std::fmt; +use time::{format_description::well_known::Rfc3339, OffsetDateTime}; +use tinycloud_core::{ + models::held_credential_nonce, + sea_orm::{ColumnTrait, DbErr, EntityTrait, QueryFilter}, + RecoveringConnection, +}; + +/// A refusal code. The string is the wire code; callers map it to a status. +pub type Refusal = &'static str; + +pub const PROFILE: &str = "tinycloud.email-held/v1"; +pub const PROFILE_VERSION: i64 = 1; +pub const VCT: &str = "opencredentials.email/v1"; +const HOLDER_CHAIN: &str = "1"; +const BINDING_DOMAIN: &str = "tinycloud.credentials/account-binding/v1"; +const MAX_LIFETIME_SECONDS: i64 = 365 * 24 * 60 * 60; +const STATUS_METHODS: &[&str] = &["none"]; +const DISCLOSABLE: &[&str] = &["email", "emailDomain"]; +// Size caps, as the upstream verifier's HELD_LIMITS. +const MAX_SD_JWT_CHARS: usize = 16384; +const MAX_SIWE_MESSAGE_CHARS: usize = 2048; +const MAX_SIWE_SIGNATURE_CHARS: usize = 132; +const MAX_DISCLOSURES: usize = 8; +const MAX_DISCLOSURE_CHARS: usize = 1024; +const MAX_HEADER_CHARS: usize = 1024; +const MAX_PAYLOAD_CHARS: usize = 4096; +const MAX_SIGNATURE_CHARS: usize = 128; +const HEADER_MEMBERS: &[&str] = &["alg", "typ", "kid"]; +const SHARED_SIGNED: &[&str] = &[ + "iss", + "sub", + "iat", + "nbf", + "exp", + "jti", + "vct", + "profile", + "profileVersion", + "holderBinding", + "status", + "_sd_alg", + "_sd", +]; +const RESERVED: &[&str] = &[ + "iss", + "sub", + "iat", + "nbf", + "exp", + "jti", + "vct", + "profile", + "profileVersion", + "holderBinding", + "status", + "_sd_alg", + "_sd", + "...", + "cnf", +]; +const PRESENTATION_STATEMENT: &str = "Present a TinyCloud held credential"; +const SD_HASH_PREFIX: &str = "urn:tinycloud:sd-hash:"; +/// DID methods a held credential's issuer may use. +const HELD_ISSUER_DID_METHODS: &[&str] = &["web"]; +const MAX_SAFE_INTEGER: i64 = (1 << 53) - 1; + +pub(crate) const BAD_CONFIG: Refusal = "bad-config"; +/// The authenticated account owner is not a canonical `did:pkh:eip155` account. +/// Refused as a client error (403), unlike `BAD_CONFIG`, which is a server 500. +pub(crate) const ACCOUNT_OWNER_INVALID: Refusal = "account-owner-invalid"; +const BAD_PRESENTATION: Refusal = "bad-presentation"; +const BAD_HEADER: Refusal = "bad-header"; +const DID_METHOD_NOT_ALLOWED: Refusal = "did-method-not-allowed"; +const ISSUER_NOT_ACCEPTED: Refusal = "issuer-not-accepted"; +const UNKNOWN_ISSUER: Refusal = "unknown-issuer"; +const ISSUER_NOT_YET_VALID: Refusal = "issuer-not-yet-valid"; +const ISSUER_STOPPED: Refusal = "issuer-stopped"; +const ISSUER_RETIRED: Refusal = "issuer-retired"; +const BAD_SIGNATURE: Refusal = "bad-signature"; +const BAD_PAYLOAD: Refusal = "bad-payload"; +const PROFILE_MISMATCH: Refusal = "profile-mismatch"; +const PROFILE_NOT_ACCEPTED: Refusal = "profile-not-accepted"; +const NOT_YET_VALID: Refusal = "not-yet-valid"; +const EXPIRED: Refusal = "expired"; +const BAD_LIFETIME: Refusal = "bad-lifetime"; +const BAD_STATUS: Refusal = "bad-status"; +const BAD_SUBJECT: Refusal = "bad-subject"; +const BAD_HOLDER_BINDING: Refusal = "bad-holder-binding"; +const BAD_DISCLOSURE: Refusal = "bad-disclosure"; +const BAD_SIWE: Refusal = "bad-siwe"; +const BAD_SIWE_SIGNATURE: Refusal = "bad-siwe-signature"; +const BAD_NONCE: Refusal = "bad-nonce"; +const NONCE_ACCOUNT_MISMATCH: Refusal = "nonce-account-mismatch"; + +/// An issuer the relying party accepts. `kid: None` accepts any key of `did`. +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct AcceptedIssuer { + pub did: String, + pub kid: Option, +} + +/// A profile the relying party accepts, by identifier and version. +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct AcceptedProfile { + pub id: String, + pub version: i64, +} + +/// Everything the verifier reads from the request and the node, all immutable. +pub struct HeldPolicy<'a> { + pub now: OffsetDateTime, + pub audience: &'a str, + /// The CACAO-authenticated account, as `did:pkh:eip155:…`. + pub caller_account: &'a str, + pub accepted_issuers: &'a [AcceptedIssuer], + pub accepted_profiles: &'a [AcceptedProfile], + pub issuers: &'a IssuerSet, +} + +/// The two parts of a held presentation, as the request carries them. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub struct HeldPresentation<'a> { + pub sd_jwt: &'a str, + pub siwe_message: &'a str, + pub siwe_signature: &'a str, +} + +/// Output of phase A. Holds the parsed SIWE and the nonce to consume. +#[derive(Debug, Clone)] +pub struct Precheck { + pub nonce: String, + /// Canonical account key used for the nonce store. + pub account_key: String, + account: Pkh, + siwe: Siwe, +} + +/// A credential that passed every check. +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct VerifiedHeld { + pub issuer: String, + pub subject: String, + pub subject_address: String, + pub expires_at: i64, + pub credential_id: String, + pub profile: String, + pub profile_version: i64, + pub vct: String, + pub claims: BTreeMap, +} + +/// Reads the `presentation` object: exactly `sdJwt` and `siwe`, and `siwe` +/// holds exactly `message` and `signature`. +pub fn read_presentation(value: &Value) -> Result, Refusal> { + let object = value.as_object().ok_or(BAD_PRESENTATION)?; + if object.len() != 2 { + return Err(BAD_PRESENTATION); + } + let sd_jwt = object + .get("sdJwt") + .and_then(Value::as_str) + .ok_or(BAD_PRESENTATION)?; + let siwe = object + .get("siwe") + .and_then(Value::as_object) + .ok_or(BAD_PRESENTATION)?; + if siwe.len() != 2 { + return Err(BAD_PRESENTATION); + } + let siwe_message = siwe + .get("message") + .and_then(Value::as_str) + .ok_or(BAD_PRESENTATION)?; + let siwe_signature = siwe + .get("signature") + .and_then(Value::as_str) + .ok_or(BAD_PRESENTATION)?; + Ok(HeldPresentation { + sd_jwt, + siwe_message, + siwe_signature, + }) +} + +/// Phase A: no side effects. Checks inputs, parses the SIWE, and checks its +/// domain and nonce. The caller consumes `Precheck::nonce` next. +pub fn precheck( + input: &HeldPresentation<'_>, + policy: &HeldPolicy<'_>, +) -> Result { + if policy.accepted_issuers.is_empty() || policy.accepted_profiles.is_empty() { + return Err(BAD_CONFIG); + } + if !valid_audience(policy.audience) { + return Err(BAD_CONFIG); + } + let account = parse_pkh(policy.caller_account).ok_or(ACCOUNT_OWNER_INVALID)?; + if !input.sd_jwt.is_ascii() { + return Err(BAD_PRESENTATION); + } + if input.sd_jwt.len() > MAX_SD_JWT_CHARS + || input.siwe_message.len() > MAX_SIWE_MESSAGE_CHARS + || input.siwe_signature.len() > MAX_SIWE_SIGNATURE_CHARS + { + return Err(BAD_PRESENTATION); + } + let siwe = parse_siwe(input.siwe_message)?; + if siwe.domain != policy.audience { + return Err(BAD_SIWE); + } + if !valid_nonce(&siwe.nonce) { + return Err(BAD_NONCE); + } + Ok(Precheck { + nonce: siwe.nonce.clone(), + account_key: account.canonical(), + account, + siwe, + }) +} + +/// Phase B: every remaining check, in refusal order. Runs after the nonce is +/// consumed, so a refusal here leaves the nonce spent. +pub fn verify( + input: &HeldPresentation<'_>, + pre: &Precheck, + policy: &HeldPolicy<'_>, +) -> Result { + // Split the SD-JWT: `jwt~disclosure…~`, with a trailing empty part. + let parts: Vec<&str> = input.sd_jwt.split('~').collect(); + if parts.len() < 2 || !parts[parts.len() - 1].is_empty() { + return Err(BAD_PRESENTATION); + } + let disclosures = &parts[1..parts.len() - 1]; + if disclosures.iter().any(|part| part.is_empty()) { + return Err(BAD_PRESENTATION); + } + let segments: Vec<&str> = parts[0].split('.').collect(); + if segments.len() != 3 || segments.iter().any(|segment| segment.is_empty()) { + return Err(BAD_PRESENTATION); + } + if disclosures.len() > MAX_DISCLOSURES + || disclosures + .iter() + .any(|part| part.len() > MAX_DISCLOSURE_CHARS) + || segments[0].len() > MAX_HEADER_CHARS + || segments[1].len() > MAX_PAYLOAD_CHARS + || segments[2].len() > MAX_SIGNATURE_CHARS + { + return Err(BAD_PRESENTATION); + } + + // Protected header. + let header = decode_object(segments[0], BAD_HEADER)?; + if header.get("alg").and_then(Value::as_str) != Some("EdDSA") + || header.get("typ").and_then(Value::as_str) != Some("vc+sd-jwt") + { + return Err(BAD_HEADER); + } + if header + .keys() + .any(|key| !HEADER_MEMBERS.contains(&key.as_str())) + { + return Err(BAD_HEADER); + } + let kid = header + .get("kid") + .and_then(Value::as_str) + .ok_or(BAD_HEADER)?; + let hash = kid + .find('#') + .filter(|&index| index >= 1) + .ok_or(BAD_HEADER)?; + let issuer_did = &kid[..hash]; + if !is_kid_fragment(&kid[hash + 1..]) { + return Err(BAD_HEADER); + } + let method = did_method(issuer_did).ok_or(DID_METHOD_NOT_ALLOWED)?; + if !HELD_ISSUER_DID_METHODS.contains(&method) { + return Err(DID_METHOD_NOT_ALLOWED); + } + + // Policy: the requirement must accept this issuer, and the pinned set must hold it. + let issuer_accepted = policy.accepted_issuers.iter().any(|accepted| { + accepted.did == issuer_did + && accepted + .kid + .as_deref() + .is_none_or(|required| required == kid) + }); + if !issuer_accepted { + return Err(ISSUER_NOT_ACCEPTED); + } + let entry = policy + .issuers + .resolve_pinned_issuer(issuer_did, kid) + .ok_or(UNKNOWN_ISSUER)?; + entry.check_now(policy.now).map_err(window_refusal)?; + + // Signature over `header.payload` with the pinned key, strictly. + let signature_bytes = b64url_strict(segments[2]).ok_or(BAD_SIGNATURE)?; + let signature = Signature::from_slice(&signature_bytes).map_err(|_| BAD_SIGNATURE)?; + let key = VerifyingKey::from_bytes(&entry.public_key).map_err(|_| BAD_SIGNATURE)?; + let signing_input = format!("{}.{}", segments[0], segments[1]); + key.verify_strict(signing_input.as_bytes(), &signature) + .map_err(|_| BAD_SIGNATURE)?; + + // Payload. + let payload = decode_object(segments[1], BAD_PAYLOAD)?; + if payload.get("iss").and_then(Value::as_str) != Some(issuer_did) { + return Err(BAD_PAYLOAD); + } + let iat = safe_int(payload.get("iat")).ok_or(BAD_PAYLOAD)?; + let exp = safe_int(payload.get("exp")).ok_or(BAD_PAYLOAD)?; + let nbf = safe_int(payload.get("nbf")).ok_or(BAD_PAYLOAD)?; + if nbf != iat { + return Err(BAD_PAYLOAD); + } + // Clamp into the representable range. Every configured instant lies inside it, so the + // window comparisons are unchanged; `nbf` is compared as an integer below. + let issued_at = OffsetDateTime::from_unix_timestamp(iat.clamp( + OffsetDateTime::new_utc(time::Date::MIN, time::Time::MIDNIGHT).unix_timestamp(), + OffsetDateTime::new_utc(time::Date::MAX, time::Time::MAX).unix_timestamp(), + )) + .map_err(|_| BAD_PAYLOAD)?; + entry.check_issued_at(issued_at).map_err(window_refusal)?; + + let profile = payload + .get("profile") + .and_then(Value::as_str) + .ok_or(BAD_PAYLOAD)?; + let profile_version = safe_int(payload.get("profileVersion")).ok_or(BAD_PAYLOAD)?; + let vct = payload + .get("vct") + .and_then(Value::as_str) + .ok_or(BAD_PAYLOAD)?; + if profile != PROFILE || profile_version != PROFILE_VERSION { + return Err(PROFILE_MISMATCH); + } + let profile_accepted = policy + .accepted_profiles + .iter() + .any(|accepted| accepted.id == PROFILE && accepted.version == PROFILE_VERSION); + if !profile_accepted { + return Err(PROFILE_NOT_ACCEPTED); + } + if vct != VCT || !entry.admits(vct, profile) { + return Err(PROFILE_MISMATCH); + } + + for key in payload.keys() { + let name = key.as_str(); + if !SHARED_SIGNED.contains(&name) { + return Err(BAD_PAYLOAD); + } + } + if payload.get("_sd_alg").and_then(Value::as_str) != Some("sha-256") { + return Err(BAD_PAYLOAD); + } + let sd_digests: Vec<&str> = payload + .get("_sd") + .and_then(Value::as_array) + .and_then(|digests| { + digests + .iter() + .map(Value::as_str) + .collect::>>() + }) + .ok_or(BAD_PAYLOAD)?; + let distinct: BTreeSet<&str> = sd_digests.iter().copied().collect(); + if distinct.len() != sd_digests.len() { + return Err(BAD_PAYLOAD); + } + + let now = policy.now.unix_timestamp(); + if now < nbf { + return Err(NOT_YET_VALID); + } + if now >= exp { + return Err(EXPIRED); + } + let lifetime = exp - iat; + if lifetime <= 0 || lifetime > MAX_LIFETIME_SECONDS { + return Err(BAD_LIFETIME); + } + let jti = payload + .get("jti") + .and_then(Value::as_str) + .filter(|value| is_uuid_v4_urn(value)) + .ok_or(BAD_PAYLOAD)?; + let status = payload + .get("status") + .and_then(Value::as_object) + .ok_or(BAD_STATUS)?; + let status_method = status.get("method").and_then(Value::as_str); + if status.len() != 1 || !status_method.is_some_and(|m| STATUS_METHODS.contains(&m)) { + return Err(BAD_STATUS); + } + + let sub = payload + .get("sub") + .and_then(Value::as_str) + .ok_or(BAD_SUBJECT)?; + let subject = parse_pkh(sub) + .filter(|did| did.chain == HOLDER_CHAIN) + .ok_or(BAD_SUBJECT)?; + + let binding = payload + .get("holderBinding") + .and_then(Value::as_object) + .ok_or(BAD_HOLDER_BINDING)?; + if binding.len() != 2 + || binding.get("signingDomain").and_then(Value::as_str) != Some(BINDING_DOMAIN) + { + return Err(BAD_HOLDER_BINDING); + } + let binding_did = binding + .get("did") + .and_then(Value::as_str) + .and_then(parse_pkh) + .ok_or(BAD_HOLDER_BINDING)?; + if binding_did != subject { + return Err(BAD_HOLDER_BINDING); + } + + // Disclosures: each must hash into `_sd`, appear once, and name a disclosable claim. + let mut seen_digests = BTreeSet::new(); + let mut seen_names = BTreeSet::new(); + let mut claims = BTreeMap::new(); + for disclosure in disclosures { + let digest = b64url(&sha256(disclosure.as_bytes())); + if !sd_digests.contains(&digest.as_str()) || !seen_digests.insert(digest) { + return Err(BAD_DISCLOSURE); + } + let decoded = b64url_strict(disclosure).ok_or(BAD_DISCLOSURE)?; + let array = match strict_json(std::str::from_utf8(&decoded).map_err(|_| BAD_DISCLOSURE)?) { + Some(Value::Array(items)) if items.len() == 3 => items, + _ => return Err(BAD_DISCLOSURE), + }; + let salt_ok = array[0].as_str().is_some(); + let name = array[1].as_str().ok_or(BAD_DISCLOSURE)?; + let value = array[2].as_str().ok_or(BAD_DISCLOSURE)?; + if !salt_ok + || RESERVED.contains(&name) + || !DISCLOSABLE.contains(&name) + || !seen_names.insert(name.to_owned()) + { + return Err(BAD_DISCLOSURE); + } + claims.insert(name.to_owned(), value.to_owned()); + } + validate_disclosed(&claims)?; + + // SIWE against the credential. + let siwe = &pre.siwe; + if !uri_matches_audience(&siwe.uri, policy.audience) + || siwe.version != "1" + || siwe.statement != PRESENTATION_STATEMENT + || siwe.chain_id != HOLDER_CHAIN + || siwe.address.to_ascii_lowercase() != subject.address + || siwe.resources.len() != 1 + { + return Err(BAD_SIWE); + } + let expected_resource = format!( + "{SD_HASH_PREFIX}{}", + b64url(&sha256(input.sd_jwt.as_bytes())) + ); + if siwe.resources[0] != expected_resource { + return Err(BAD_SIWE); + } + let now = truncate_to_millis(policy.now); + let expired = siwe + .expiration + .is_some_and(|expiry| now >= truncate_to_millis(expiry)); + let early = siwe + .not_before + .is_some_and(|start| now < truncate_to_millis(start)); + if expired || early { + return Err(BAD_SIWE); + } + let signature_hex = input + .siwe_signature + .strip_prefix("0x") + .ok_or(BAD_SIWE_SIGNATURE)?; + let siwe_signature = hex::decode(signature_hex) + .ok() + .filter(|bytes| bytes.len() == 65) + .ok_or(BAD_SIWE_SIGNATURE)?; + let signer = recover_eip191_address(input.siwe_message.as_bytes(), &siwe_signature) + .ok_or(BAD_SIWE_SIGNATURE)?; + if signer != subject.address { + return Err(BAD_SIWE_SIGNATURE); + } + + // The signed-in account must be the holder. + if pre.account != subject { + return Err(NONCE_ACCOUNT_MISMATCH); + } + + Ok(VerifiedHeld { + issuer: issuer_did.to_owned(), + subject: subject.display_did(), + subject_address: subject.address, + expires_at: exp, + credential_id: jti.to_owned(), + profile: profile.to_owned(), + profile_version, + vct: vct.to_owned(), + claims, + }) +} + +/// Consumes a nonce bound to `(audience, account)` that is still live at `now`. +/// A nonce is live while `now < expires_at`. Returns `false` if it was not +/// outstanding, so the caller refuses with `nonce-replayed`. A mismatched +/// account or an expired nonce matches no row and spends nothing. Rows already +/// expired are pruned on every call, so the table holds only live nonces. +pub async fn consume_nonce( + conn: &RecoveringConnection, + audience: &str, + nonce: &str, + account_key: &str, + now: OffsetDateTime, +) -> Result { + let now = now.unix_timestamp(); + held_credential_nonce::Entity::delete_many() + .filter(held_credential_nonce::Column::ExpiresAt.lte(now)) + .exec(conn) + .await?; + let deleted = held_credential_nonce::Entity::delete_many() + .filter(held_credential_nonce::Column::Audience.eq(audience)) + .filter(held_credential_nonce::Column::Nonce.eq(nonce)) + .filter(held_credential_nonce::Column::Account.eq(account_key)) + .filter(held_credential_nonce::Column::ExpiresAt.gt(now)) + .exec(conn) + .await?; + Ok(deleted.rows_affected == 1) +} + +/// Records an outstanding nonce that stops being spendable at `expires_at` +/// (unix seconds). Used only by tests until the mint slice lands. +#[cfg(test)] +pub async fn record_nonce( + conn: &RecoveringConnection, + audience: &str, + nonce: &str, + account_key: &str, + expires_at: i64, +) -> Result<(), DbErr> { + use tinycloud_core::sea_orm::{ActiveModelTrait, Set}; + held_credential_nonce::ActiveModel { + audience: Set(audience.to_owned()), + nonce: Set(nonce.to_owned()), + account: Set(account_key.to_owned()), + expires_at: Set(expires_at), + } + .insert(conn) + .await?; + Ok(()) +} + +fn window_refusal(error: IssuerWindowError) -> Refusal { + match error { + IssuerWindowError::NotYetValid => ISSUER_NOT_YET_VALID, + IssuerWindowError::Stopped => ISSUER_STOPPED, + IssuerWindowError::Retired => ISSUER_RETIRED, + } +} + +/// Decodes a base64url JSON object, refusing duplicate keys at every depth. +fn decode_object(segment: &str, refusal: Refusal) -> Result, Refusal> { + let bytes = b64url_strict(segment).ok_or(refusal)?; + let text = std::str::from_utf8(&bytes).map_err(|_| refusal)?; + match strict_json(text) { + Some(Value::Object(object)) => Ok(object), + _ => Err(refusal), + } +} + +/// A JSON value parsed with duplicate keys refused at any depth. +struct StrictJson(Value); + +impl<'de> Deserialize<'de> for StrictJson { + fn deserialize>(deserializer: D) -> Result { + struct StrictVisitor; + + impl<'de> Visitor<'de> for StrictVisitor { + type Value = StrictJson; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("a JSON value") + } + + fn visit_bool(self, value: bool) -> Result { + Ok(StrictJson(Value::Bool(value))) + } + + fn visit_i64(self, value: i64) -> Result { + Ok(StrictJson(Value::from(value))) + } + + fn visit_u64(self, value: u64) -> Result { + Ok(StrictJson(Value::from(value))) + } + + fn visit_f64(self, value: f64) -> Result { + serde_json::Number::from_f64(value) + .map(|number| StrictJson(Value::Number(number))) + .ok_or_else(|| E::custom("non-finite number")) + } + + fn visit_str(self, value: &str) -> Result { + Ok(StrictJson(Value::String(value.to_owned()))) + } + + fn visit_string(self, value: String) -> Result { + Ok(StrictJson(Value::String(value))) + } + + fn visit_unit(self) -> Result { + Ok(StrictJson(Value::Null)) + } + + fn visit_none(self) -> Result { + Ok(StrictJson(Value::Null)) + } + + fn visit_seq>(self, mut seq: A) -> Result { + let mut items = Vec::new(); + while let Some(StrictJson(item)) = seq.next_element()? { + items.push(item); + } + Ok(StrictJson(Value::Array(items))) + } + + fn visit_map>(self, mut map: A) -> Result { + let mut object = Map::new(); + while let Some(key) = map.next_key::()? { + if object.contains_key(&key) { + return Err(de::Error::custom("duplicate key")); + } + let StrictJson(value) = map.next_value()?; + object.insert(key, value); + } + Ok(StrictJson(Value::Object(object))) + } + } + + deserializer.deserialize_any(StrictVisitor) + } +} + +fn strict_json(text: &str) -> Option { + serde_json::from_str::(text) + .ok() + .map(|StrictJson(value)| value) +} + +/// An integer literal within the JSON-safe range. `1.0` is refused. +fn safe_int(value: Option<&Value>) -> Option { + let number = value?.as_number()?.as_i64()?; + (number.abs() <= MAX_SAFE_INTEGER).then_some(number) +} + +/// Unpadded base64url, canonical: no foreign characters, no stray trailing bits. +fn b64url_strict(text: &str) -> Option> { + if text.len() % 4 == 1 + || !text + .bytes() + .all(|b| b.is_ascii_alphanumeric() || b == b'-' || b == b'_') + { + return None; + } + let bytes = decode_config(text, URL_SAFE_NO_PAD).ok()?; + (encode_config(&bytes, URL_SAFE_NO_PAD) == text).then_some(bytes) +} + +fn b64url(bytes: &[u8]) -> String { + encode_config(bytes, URL_SAFE_NO_PAD) +} + +fn sha256(bytes: &[u8]) -> [u8; 32] { + Sha256::digest(bytes).into() +} + +fn keccak(bytes: &[u8]) -> [u8; 32] { + Keccak256::digest(bytes).into() +} + +fn is_kid_fragment(fragment: &str) -> bool { + !fragment.is_empty() + && fragment + .bytes() + .all(|b| b.is_ascii_alphanumeric() || matches!(b, b'.' | b'_' | b'-')) +} + +/// The method of a `did::` string, using the `did:[a-z0-9]+:` grammar. The id +/// is not checked here; an empty id is refused later as an unaccepted issuer. +fn did_method(did: &str) -> Option<&str> { + let mut parts = did.splitn(3, ':'); + if parts.next()? != "did" { + return None; + } + let method = parts.next()?; + parts.next()?; + (!method.is_empty() + && method + .bytes() + .all(|b| b.is_ascii_lowercase() || b.is_ascii_digit())) + .then_some(method) +} + +/// A `did:pkh:eip155` principal. `address` is lowercase `0x…`. +#[derive(Debug, Clone, PartialEq, Eq)] +struct Pkh { + chain: String, + address: String, +} + +impl Pkh { + fn canonical(&self) -> String { + format!("did:pkh:eip155:{}:{}", self.chain, self.address) + } + + /// The `did:pkh` with the EIP-55 checksummed address, as TS `canonicalPkhDid`. + fn display_did(&self) -> String { + format!( + "did:pkh:eip155:{}:{}", + self.chain, + checksum_address(&self.address) + ) + } +} + +/// Parses `did:pkh:eip155::
`. Chain is `0` or a decimal with no +/// leading zero, up to 16 digits. The address must be all-lowercase or valid EIP-55. +fn parse_pkh(did: &str) -> Option { + let rest = did.strip_prefix("did:pkh:eip155:")?; + let (chain, address) = rest.split_once(':')?; + let chain_ok = !chain.is_empty() + && chain.bytes().all(|b| b.is_ascii_digit()) + && (chain == "0" || (!chain.starts_with('0') && chain.len() <= 16)); + if !chain_ok || address.len() != 42 || !address.starts_with("0x") { + return None; + } + let hex_part = &address[2..]; + hex::decode(hex_part).ok()?; + // TS `parsePkhDid`: an all-lowercase body is accepted; any other body must be EIP-55. + if hex_part != hex_part.to_ascii_lowercase() && !eip55_ok(hex_part) { + return None; + } + Some(Pkh { + chain: chain.to_owned(), + address: address.to_ascii_lowercase(), + }) +} + +/// EIP-55 checksum of a `0x…` address, as `toChecksumAddress`. +fn checksum_address(address: &str) -> String { + let lower = address[2..].to_ascii_lowercase(); + let digest = keccak(lower.as_bytes()); + let body: String = lower + .char_indices() + .map(|(index, c)| { + let nibble = if index % 2 == 0 { + digest[index / 2] >> 4 + } else { + digest[index / 2] & 0x0f + }; + if c.is_ascii_alphabetic() && nibble >= 8 { + c.to_ascii_uppercase() + } else { + c + } + }) + .collect(); + format!("0x{body}") +} + +/// EIP-55: each letter's case must match the keccak-derived checksum, which is +/// `toChecksumAddress(address) === address`. All-lower and all-upper spellings +/// pass only when the checksum happens to agree with them. +fn eip55_ok(hex40: &str) -> bool { + checksum_address(&format!("0x{}", hex40.to_ascii_lowercase())) == format!("0x{hex40}") +} + +/// EIP-191 `personal_sign` recovery over the raw message bytes. Accepts v in +/// {27, 28, 0, 1}. High-S is refused: `recover_from_prehash` calls `verify_prehash` +/// on the recovered key, which enforces low-S. TS beta.37 recovers high-S signatures; +/// the replay records that as a `deviation` in `s1-differential.json`. +fn recover_eip191_address(message: &[u8], signature: &[u8]) -> Option { + let mut prefixed = format!("\x19Ethereum Signed Message:\n{}", message.len()).into_bytes(); + prefixed.extend_from_slice(message); + let digest = keccak(&prefixed); + let v = match signature[64] { + 27 | 28 => signature[64] - 27, + 0 | 1 => signature[64], + _ => return None, + }; + let recovery_id = RecoveryId::from_byte(v)?; + let rs = EcdsaSignature::from_slice(&signature[..64]).ok()?; + let key = EcdsaVerifyingKey::recover_from_prehash(&digest, &rs, recovery_id).ok()?; + let point = key.to_encoded_point(false); + let hash = keccak(&point.as_bytes()[1..]); + Some(format!("0x{}", hex::encode(&hash[12..]))) +} + +/// Audience: a lowercase host with an optional port in `1..=65535`, not 443. +pub(crate) fn valid_audience(audience: &str) -> bool { + let (host, port) = match audience.rsplit_once(':') { + Some((host, port)) => (host, Some(port)), + None => (audience, None), + }; + let is_edge = |b: u8| b.is_ascii_lowercase() || b.is_ascii_digit(); + let host_ok = !host.is_empty() + && host.bytes().all(|b| is_edge(b) || b == b'.' || b == b'-') + && host.bytes().next().is_some_and(is_edge) + && host.bytes().last().is_some_and(is_edge); + let port_ok = match port { + None => true, + Some(port) => { + port.len() <= 5 + && !port.starts_with('0') + && port.bytes().all(|b| b.is_ascii_digit()) + && port + .parse::() + .is_ok_and(|value| value <= 65535 && value != 443) + } + }; + host_ok && port_ok +} + +fn valid_nonce(nonce: &str) -> bool { + nonce.len() >= 22 && nonce.bytes().all(|b| b.is_ascii_alphanumeric()) +} + +/// `urn:uuid:` plus a lowercase RFC 4122 version-4 UUID: the upstream +/// JTI_UUID_V4 pattern. +fn is_uuid_v4_urn(value: &str) -> bool { + let Some(uuid) = value.strip_prefix("urn:uuid:") else { + return false; + }; + uuid.len() == 36 + && uuid.bytes().enumerate().all(|(index, byte)| match index { + 8 | 13 | 18 | 23 => byte == b'-', + 14 => byte == b'4', + 19 => matches!(byte, b'8' | b'9' | b'a' | b'b'), + _ => byte.is_ascii_digit() || (b'a'..=b'f').contains(&byte), + }) +} + +fn is_eth_address(line: &str) -> bool { + line.len() == 42 + && line.starts_with("0x") + && hex::decode(&line[2..]).is_ok() + && eip55_ok(&line[2..]) +} + +/// A parsed EIP-4361 message, strictly. Only the fields the verifier reads. +#[derive(Debug, Clone)] +struct Siwe { + domain: String, + address: String, + statement: String, + uri: String, + version: String, + chain_id: String, + nonce: String, + expiration: Option, + not_before: Option, + resources: Vec, +} + +const SIWE_HEADER_SUFFIX: &str = " wants you to sign in with your Ethereum account:"; + +fn parse_siwe(message: &str) -> Result { + let lines: Vec<&str> = message.split('\n').collect(); + let domain = lines + .first() + .and_then(|line| line.strip_suffix(SIWE_HEADER_SUFFIX)) + .filter(|domain| !domain.is_empty() && !domain.bytes().any(|b| b.is_ascii_whitespace())) + .ok_or(BAD_SIWE)?; + let address = lines + .get(1) + .copied() + .filter(|line| is_eth_address(line)) + .ok_or(BAD_SIWE)?; + if lines.get(2) != Some(&"") { + return Err(BAD_SIWE); + } + let statement = lines + .get(3) + .copied() + .filter(|line| !line.is_empty()) + .ok_or(BAD_SIWE)?; + if lines.get(4) != Some(&"") { + return Err(BAD_SIWE); + } + let mut index = 5; + let uri = take_field(&lines, &mut index, "URI: ")?; + let version = take_field(&lines, &mut index, "Version: ")?; + let chain_id = take_field(&lines, &mut index, "Chain ID: ")?; + let nonce = take_field(&lines, &mut index, "Nonce: ")?; + let issued_at = take_field(&lines, &mut index, "Issued At: ")?; + let expiration = take_optional(&lines, &mut index, "Expiration Time: ")?; + let not_before = take_optional(&lines, &mut index, "Not Before: ")?; + let mut resources = Vec::new(); + if lines.get(index) == Some(&"Resources:") { + index += 1; + while let Some(item) = lines.get(index).and_then(|line| line.strip_prefix("- ")) { + if item.is_empty() { + return Err(BAD_SIWE); + } + resources.push(item.to_owned()); + index += 1; + } + } + if index != lines.len() { + return Err(BAD_SIWE); + } + if !chain_id.bytes().all(|b| b.is_ascii_digit()) + || nonce.len() < 8 + || !nonce.bytes().all(|b| b.is_ascii_alphanumeric()) + { + return Err(BAD_SIWE); + } + parse_rfc3339(issued_at)?; + Ok(Siwe { + domain: domain.to_owned(), + address: address.to_owned(), + statement: statement.to_owned(), + uri: uri.to_owned(), + version: version.to_owned(), + chain_id: chain_id.to_owned(), + nonce: nonce.to_owned(), + expiration: expiration.map(parse_rfc3339).transpose()?, + not_before: not_before.map(parse_rfc3339).transpose()?, + resources, + }) +} + +fn take_field<'a>(lines: &[&'a str], index: &mut usize, prefix: &str) -> Result<&'a str, Refusal> { + let value = lines + .get(*index) + .and_then(|line| line.strip_prefix(prefix)) + .filter(|value| !value.is_empty()) + .ok_or(BAD_SIWE)?; + *index += 1; + Ok(value) +} + +fn take_optional<'a>( + lines: &[&'a str], + index: &mut usize, + prefix: &str, +) -> Result, Refusal> { + if lines + .get(*index) + .is_some_and(|line| line.starts_with(prefix)) + { + Ok(Some(take_field(lines, index, prefix)?)) + } else { + Ok(None) + } +} + +/// RFC 3339 with the exact shape `YYYY-MM-DDTHH:MM:SS[.frac](Z|±HH:MM)`. +fn parse_rfc3339(text: &str) -> Result { + if !rfc3339_shape(text) { + return Err(BAD_SIWE); + } + OffsetDateTime::parse(text, &Rfc3339).map_err(|_| BAD_SIWE) +} + +/// TS compares SIWE times as JavaScript `Date` values, which keep milliseconds only. +fn truncate_to_millis(time: OffsetDateTime) -> OffsetDateTime { + let nanos = time.nanosecond() - time.nanosecond() % 1_000_000; + time.replace_nanosecond(nanos).unwrap_or(time) +} + +fn rfc3339_shape(text: &str) -> bool { + let bytes = text.as_bytes(); + let digits = |from: usize, len: usize| { + bytes.len() >= from + len && bytes[from..from + len].iter().all(u8::is_ascii_digit) + }; + let separators_ok = bytes.get(4) == Some(&b'-') + && bytes.get(7) == Some(&b'-') + && bytes.get(10) == Some(&b'T') + && bytes.get(13) == Some(&b':') + && bytes.get(16) == Some(&b':'); + if !(separators_ok + && digits(0, 4) + && digits(5, 2) + && digits(8, 2) + && digits(11, 2) + && digits(14, 2) + && digits(17, 2) + && bytes[17] <= b'5') + { + return false; + } + let mut index = 19; + if bytes.get(index) == Some(&b'.') { + index += 1; + let start = index; + while bytes.get(index).is_some_and(u8::is_ascii_digit) { + index += 1; + } + if index == start { + return false; + } + if index - start > 9 { + return false; + } + } + let tail = &bytes[index..]; + if tail == b"Z" { + return true; + } + tail.len() == 6 + && (tail[0] == b'+' || tail[0] == b'-') + && tail[1..3].iter().all(u8::is_ascii_digit) + && tail[3] == b':' + && tail[4..6].iter().all(u8::is_ascii_digit) +} + +/// The SIWE URI: https, no userinfo, and its origin (host, plus the port when it is +/// not the https default) equals the audience, as WHATWG `URL.origin` does. +fn uri_matches_audience(uri: &str, audience: &str) -> bool { + let Ok(parsed) = url::Url::parse(uri) else { + return false; + }; + let Some(host) = parsed.host_str() else { + return false; + }; + let origin = match parsed.port() { + Some(port) => format!("{host}:{port}"), + None => host.to_owned(), + }; + parsed.scheme() == "https" + && parsed.username().is_empty() + && parsed.password().is_none() + && origin == audience +} + +/// Checks the disclosed values against the email row's rules. +fn validate_disclosed(claims: &BTreeMap) -> Result<(), Refusal> { + if let Some(email) = claims.get("email") { + let ok = email.is_ascii() + && email == &email.to_ascii_lowercase() + && email.matches('@').count() == 1 + && (3..=320).contains(&email.len()) + && email.bytes().all(|b| b > 0x20 && b != 0x7f) + && !email.starts_with('@') + && !email.ends_with('@'); + if !ok { + return Err(BAD_DISCLOSURE); + } + } + if let Some(domain) = claims.get("emailDomain") { + if domain.is_empty() + || domain.contains('@') + || !domain.is_ascii() + || domain != &domain.to_ascii_lowercase() + { + return Err(BAD_DISCLOSURE); + } + } + if let (Some(email), Some(domain)) = (claims.get("email"), claims.get("emailDomain")) { + if email.rsplit('@').next() != Some(domain.as_str()) { + return Err(BAD_DISCLOSURE); + } + } + Ok(()) +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::config::HeldCredentialsConfig; + use crate::issuer_set::CredentialIssuerConfig; + use crate::policy_v3::{ + canonical_digest_base64url, validate_held_email_admission, ClaimPresentationContext, + PolicyV3Runtime, + }; + use ed25519_dalek::{Signer, SigningKey}; + use serde_json::json; + use tinycloud_auth::share_email_evidence::IssuerKey; + use tinycloud_core::keys::StaticSecret; + use tinycloud_core::migrations::Migrator; + use tinycloud_core::sea_orm::Database; + use tinycloud_core::sea_orm_migration::MigratorTrait; + + const AUDIENCE: &str = "verifier.example"; + const HOLDER: &str = "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266"; + const CALLER: &str = "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266"; + const OTHER_ACCOUNT: &str = "did:pkh:eip155:1:0x1111111111111111111111111111111111111111"; + const ANVIL_KEY: &str = "ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80"; + const TEST_ISSUER: &str = "did:web:issuer.credentials.org"; + const TEST_KID: &str = "did:web:issuer.credentials.org#k1"; + const ISSUED_AT: &str = "2026-01-01T00:59:00Z"; + const NOW: &str = "2026-01-01T01:00:00Z"; + const IAT: i64 = 1_767_225_600; + const DAY: i64 = 86_400; + const NONCE: &str = "heldtestnonce0000000001"; + + struct Fixture { + set: IssuerSet, + issuers: Vec, + profiles: Vec, + now: OffsetDateTime, + caller: String, + } + + impl Fixture { + fn new(set: IssuerSet, issuer_did: &str) -> Self { + Self { + set, + issuers: vec![AcceptedIssuer { + did: issuer_did.to_owned(), + kid: None, + }], + profiles: vec![AcceptedProfile { + id: PROFILE.to_owned(), + version: PROFILE_VERSION, + }], + now: OffsetDateTime::parse(NOW, &Rfc3339).unwrap(), + caller: CALLER.to_owned(), + } + } + + fn policy(&self) -> HeldPolicy<'_> { + HeldPolicy { + now: self.now, + audience: AUDIENCE, + caller_account: &self.caller, + accepted_issuers: &self.issuers, + accepted_profiles: &self.profiles, + issuers: &self.set, + } + } + } + + fn oc_vector() -> Value { + serde_json::from_str(include_str!("../tests/fixtures/held-email-v1/vector.json")).unwrap() + } + + /// OC fixture as an admission case: fixture policy plus the SD-JWT and a SIWE message + /// signed by the subject's account bound to the SD-JWT. + fn oc_case(nonce: &str) -> (Fixture, String, String) { + let vector = oc_vector(); + let configured: Vec = + serde_json::from_value(vector["issuerSet"]["issuers"].clone()).unwrap(); + let set = IssuerSet::load(&configured).unwrap(); + let mut fixture = Fixture::new(set, "did:web:issuer.credentials.org"); + fixture.now = OffsetDateTime::parse(vector["now"].as_str().unwrap(), &Rfc3339).unwrap(); + fixture.caller = vector["account"].as_str().unwrap().to_owned(); + let sd_jwt = vector["sdJwt"].as_str().unwrap().to_owned(); + let message = siwe_message(nonce, &sd_jwt); + (fixture, sd_jwt, message) + } + + fn test_key() -> SigningKey { + let mut seed = [0u8; 32]; + for (i, byte) in seed.iter_mut().enumerate() { + *byte = (i as u8).wrapping_mul(37).wrapping_add(11); + } + SigningKey::from_bytes(&seed) + } + + fn issuer_config(key: &SigningKey) -> CredentialIssuerConfig { + CredentialIssuerConfig { + issuer_did: TEST_ISSUER.to_owned(), + kid: TEST_KID.to_owned(), + alg: "EdDSA".to_owned(), + public_key: b64url(&key.verifying_key().to_bytes()), + vcts: vec![VCT.to_owned()], + profiles: vec![PROFILE.to_owned()], + not_before: "2025-01-01T00:00:00Z".to_owned(), + retired_at: None, + not_after: None, + } + } + + fn own_fixture(key: &SigningKey) -> Fixture { + Fixture::new(IssuerSet::load(&[issuer_config(key)]).unwrap(), TEST_ISSUER) + } + + fn disclosure(salt: &str, name: &str, value: &str) -> String { + b64url(json!([salt, name, value]).to_string().as_bytes()) + } + + fn digest(disclosure: &str) -> String { + b64url(&sha256(disclosure.as_bytes())) + } + + fn email_disclosures() -> Vec { + vec![ + disclosure("salt-email", "email", "alice@example.com"), + disclosure("salt-domain", "emailDomain", "example.com"), + ] + } + + fn default_header() -> Value { + json!({"alg": "EdDSA", "typ": "vc+sd-jwt", "kid": TEST_KID}) + } + + fn default_payload(disclosures: &[String]) -> Value { + json!({ + "iss": TEST_ISSUER, + "sub": CALLER, + "iat": IAT, + "nbf": IAT, + "exp": IAT + 30 * DAY, + "jti": "urn:uuid:0b6d2c4e-8a1f-4d3e-9b7a-1c2d3e4f5a6b", + "vct": VCT, + "profile": PROFILE, + "profileVersion": PROFILE_VERSION, + "holderBinding": { + "did": CALLER, + "signingDomain": "tinycloud.credentials/account-binding/v1" + }, + "status": {"method": "none"}, + "_sd_alg": "sha-256", + "_sd": disclosures.iter().map(|d| digest(d)).collect::>(), + }) + } + + fn signing_input(header: &str, payload: &str) -> String { + format!( + "{}.{}", + b64url(header.as_bytes()), + b64url(payload.as_bytes()) + ) + } + + fn assemble(signing_input: &str, signature: &[u8], disclosures: &[String]) -> String { + let mut sd_jwt = format!("{signing_input}.{}~", b64url(signature)); + for disclosure in disclosures { + sd_jwt.push_str(disclosure); + sd_jwt.push('~'); + } + sd_jwt + } + + fn mint(key: &SigningKey, header: &str, payload: &str, disclosures: &[String]) -> String { + let input = signing_input(header, payload); + let signature = key.sign(input.as_bytes()).to_bytes(); + assemble(&input, &signature, disclosures) + } + + /// Honest credential with both email disclosures; `mutate` edits the payload before signing. + fn credential(key: &SigningKey, header: Value, mutate: impl FnOnce(&mut Value)) -> String { + let disclosures = email_disclosures(); + let mut payload = default_payload(&disclosures); + mutate(&mut payload); + mint(key, &header.to_string(), &payload.to_string(), &disclosures) + } + + fn sign_siwe(message: &str) -> String { + sign_siwe_with(ANVIL_KEY, message) + } + + fn sign_siwe_with(key_hex: &str, message: &str) -> String { + let prefixed = format!("\x19Ethereum Signed Message:\n{}{}", message.len(), message); + let digest = keccak(prefixed.as_bytes()); + let key = k256::ecdsa::SigningKey::from_slice(&hex::decode(key_hex).unwrap()).unwrap(); + let (signature, recovery) = key.sign_prehash_recoverable(&digest).unwrap(); + let mut bytes = signature.to_bytes().to_vec(); + bytes.push(recovery.to_byte() + 27); + format!("0x{}", hex::encode(bytes)) + } + + fn siwe_message(nonce: &str, sd_jwt: &str) -> String { + [ + format!("{AUDIENCE} wants you to sign in with your Ethereum account:"), + HOLDER.to_owned(), + String::new(), + PRESENTATION_STATEMENT.to_owned(), + String::new(), + format!("URI: https://{AUDIENCE}"), + "Version: 1".to_owned(), + "Chain ID: 1".to_owned(), + format!("Nonce: {nonce}"), + format!("Issued At: {ISSUED_AT}"), + "Resources:".to_owned(), + format!( + "- urn:tinycloud:sd-hash:{}", + b64url(&sha256(sd_jwt.as_bytes())) + ), + ] + .join("\n") + } + + fn body(sd_jwt: &str, message: &str, signature: &str) -> Value { + json!({"sdJwt": sd_jwt, "siwe": {"message": message, "signature": signature}}) + } + + /// Presentation signed with the Anvil test key over a SIWE message bound to `sd_jwt`. + fn request_for(sd_jwt: &str) -> Value { + let message = siwe_message(NONCE, sd_jwt); + body(sd_jwt, &message, &sign_siwe(&message)) + } + + /// Handler order: precheck, consume nonce, then verify. + async fn admit( + conn: &RecoveringConnection, + fixture: &Fixture, + request: &Value, + ) -> Result { + let input = read_presentation(request)?; + let policy = fixture.policy(); + let pre = precheck(&input, &policy)?; + let fresh = consume_nonce(conn, AUDIENCE, &pre.nonce, &pre.account_key, policy.now) + .await + .expect("nonce store"); + if !fresh { + return Err("nonce-replayed"); + } + verify(&input, &pre, &policy) + } + + fn refused(outcome: Result) -> Refusal { + match outcome { + Ok(_) => panic!("presentation was accepted"), + Err(code) => code, + } + } + + async fn conn() -> RecoveringConnection { + let db = Database::connect("sqlite::memory:").await.unwrap(); + Migrator::up(&db, None).await.unwrap(); + db.into() + } + + async fn seed( + conn: &RecoveringConnection, + fixture: &Fixture, + request: &Value, + ) -> Result<(), Refusal> { + let input = read_presentation(request)?; + let pre = precheck(&input, &fixture.policy())?; + record_nonce( + conn, + AUDIENCE, + &pre.nonce, + &pre.account_key, + fixture.policy().now.unix_timestamp() + 3600, + ) + .await + .expect("nonce store"); + Ok(()) + } + + async fn outcome(fixture: &Fixture, request: &Value) -> Refusal { + let conn = conn().await; + if let Err(code) = seed(&conn, fixture, request).await { + return code; + } + refused(admit(&conn, fixture, request).await) + } + + #[tokio::test] + async fn oc_vector_is_accepted_once_and_its_nonce_is_spent() { + let (fixture, sd_jwt, message) = oc_case(NONCE); + let request = body(&sd_jwt, &message, &sign_siwe(&message)); + let conn = conn().await; + seed(&conn, &fixture, &request).await.expect("seed"); + let verified = admit(&conn, &fixture, &request) + .await + .expect("OC vector is accepted"); + assert_eq!( + verified.claims.get("email").map(String::as_str), + Some("alice@example.com") + ); + assert_eq!( + refused(admit(&conn, &fixture, &request).await), + "nonce-replayed" + ); + } + + /// Requirement and policy projection for `validate_held_email_admission`. The projection + /// pins the digest of the request-local requirement the presenter sends. + fn held_requirement_and_policy() -> (Value, Value) { + let requirement = held_requirement(); + let policy = policy_for(&requirement); + (requirement, policy) + } + + fn held_requirement() -> Value { + json!({ + "type": "TinyCloudCredentialRequirement", + "version": 1, + "profile": {"id": PROFILE, "version": PROFILE_VERSION}, + "credentialType": {"id": VCT, "version": 1}, + "claims": {"email": "alice@example.com", "emailDomain": "example.com"}, + "maxAgeSeconds": 31_536_000, + }) + } + + /// The policy projection that binds `requirement` by its digest. + fn policy_for(requirement: &Value) -> Value { + json!({"credentialRequirement": { + "type": "TinyCloudPolicyCredentialRequirement", + "version": 1, + "requirementDigest": canonical_digest_base64url(requirement), + "descriptorDigest": b64url(&sha256(b"held-email-descriptor")), + "issuerDid": TEST_ISSUER, + "issuerKid": TEST_KID, + "profile": requirement["profile"], + "credentialType": requirement["credentialType"], + }}) + } + + /// The held requirement with `edit` applied, bound by a digest computed after the edit. + fn held_case(edit: impl FnOnce(&mut Value)) -> (Value, Value) { + let mut requirement = held_requirement(); + edit(&mut requirement); + let policy = policy_for(&requirement); + (requirement, policy) + } + + fn handler_runtime( + conn: &RecoveringConnection, + key: &SigningKey, + held: bool, + ) -> PolicyV3Runtime { + let runtime = PolicyV3Runtime::new( + conn.clone(), + "did:web:node.example", + StaticSecret::new(vec![7; 32]).unwrap(), + ) + .with_credential_issuers(IssuerSet::load(&[issuer_config(key)]).unwrap()); + if !held { + return runtime; + } + runtime + .with_held_credentials(&HeldCredentialsConfig { + enabled: true, + audience: Some(AUDIENCE.to_owned()), + }) + .unwrap() + } + + /// Runs `validate_held_email_admission` as `mint` does and returns only the outcome code. + async fn handler_admit( + runtime: &PolicyV3Runtime, + requirement: &Value, + policy: &Value, + presentation: &Value, + caller: &str, + consume: bool, + ) -> Result<(), String> { + let context = ClaimPresentationContext { + challenge_id: "held-test-challenge", + nonce: NONCE, + policy_cid: "held-test-policy", + owner_did: CALLER, + recipient_did: "did:web:verifier.example", + authenticated_account_owner: Some(caller), + now: OffsetDateTime::parse(NOW, &Rfc3339).unwrap(), + }; + validate_held_email_admission( + requirement, + presentation, + policy, + &context, + runtime, + consume, + ) + .await + .map(|_| ()) + .map_err(|(_, code)| code) + } + + /// Records the nonce the way the nonce mint route would. The route is tracked separately, + /// so tests stand in for it here. + async fn seed_handler(conn: &RecoveringConnection, key: &SigningKey, presentation: &Value) { + seed(conn, &own_fixture(key), presentation) + .await + .expect("seed"); + } + + #[tokio::test] + async fn handler_refuses_held_presentations_when_the_flag_is_off() { + let key = test_key(); + let (requirement, policy) = held_requirement_and_policy(); + let presentation = request_for(&credential(&key, default_header(), |_| {})); + let conn = conn().await; + let runtime = handler_runtime(&conn, &key, false); + assert_eq!( + handler_admit(&runtime, &requirement, &policy, &presentation, CALLER, true).await, + Err("held-credentials-disabled".to_owned()) + ); + } + + #[tokio::test] + async fn held_admission_is_accepted_once_then_replayed() { + let key = test_key(); + let (requirement, policy) = held_requirement_and_policy(); + let presentation = request_for(&credential(&key, default_header(), |_| {})); + let conn = conn().await; + let runtime = handler_runtime(&conn, &key, true); + seed_handler(&conn, &key, &presentation).await; + handler_admit(&runtime, &requirement, &policy, &presentation, CALLER, true) + .await + .expect("honest held presentation is admitted"); + assert_eq!( + handler_admit(&runtime, &requirement, &policy, &presentation, CALLER, true).await, + Err("nonce-replayed".to_owned()) + ); + } + + /// Spec §4.4: the nonce is spent before any signature check, so a refused presentation + /// cannot be retried against the same nonce. + #[tokio::test] + async fn refused_presentation_still_spends_the_nonce() { + let key = test_key(); + let other = SigningKey::from_bytes(&[9; 32]); + let (requirement, policy) = held_requirement_and_policy(); + let presentation = request_for(&credential(&other, default_header(), |_| {})); + let conn = conn().await; + let runtime = handler_runtime(&conn, &key, true); + seed_handler(&conn, &key, &presentation).await; + assert_eq!( + handler_admit(&runtime, &requirement, &policy, &presentation, CALLER, true).await, + Err("bad-signature".to_owned()) + ); + assert_eq!( + handler_admit(&runtime, &requirement, &policy, &presentation, CALLER, true).await, + Err("nonce-replayed".to_owned()) + ); + } + + /// Spec §4.4 step 2: a nonce is consumed for the caller only. Another account presenting + /// the subject's nonce spends nothing, so the subject can still admit it. + #[tokio::test] + async fn other_account_cannot_spend_the_subjects_nonce() { + let key = test_key(); + let (requirement, policy) = held_requirement_and_policy(); + let presentation = request_for(&credential(&key, default_header(), |_| {})); + let conn = conn().await; + let runtime = handler_runtime(&conn, &key, true); + seed_handler(&conn, &key, &presentation).await; + assert_eq!( + handler_admit( + &runtime, + &requirement, + &policy, + &presentation, + OTHER_ACCOUNT, + true + ) + .await, + Err("nonce-replayed".to_owned()) + ); + handler_admit(&runtime, &requirement, &policy, &presentation, CALLER, true) + .await + .expect("subject still holds its unspent nonce"); + } + + #[tokio::test] + async fn locked_reevaluation_verifies_without_spending_the_nonce_again() { + let key = test_key(); + let (requirement, policy) = held_requirement_and_policy(); + let presentation = request_for(&credential(&key, default_header(), |_| {})); + let conn = conn().await; + let runtime = handler_runtime(&conn, &key, true); + seed_handler(&conn, &key, &presentation).await; + handler_admit(&runtime, &requirement, &policy, &presentation, CALLER, true) + .await + .expect("first admission"); + handler_admit( + &runtime, + &requirement, + &policy, + &presentation, + CALLER, + false, + ) + .await + .expect("locked re-evaluation accepts the spent nonce"); + } + + #[tokio::test] + async fn requirement_for_another_email_is_not_satisfied() { + let key = test_key(); + let (requirement, policy) = held_case(|r| r["claims"]["email"] = json!("bob@example.com")); + let presentation = request_for(&credential(&key, default_header(), |_| {})); + let conn = conn().await; + let runtime = handler_runtime(&conn, &key, true); + seed_handler(&conn, &key, &presentation).await; + assert_eq!( + handler_admit(&runtime, &requirement, &policy, &presentation, CALLER, true).await, + Err("credential-requirement-not-satisfied".to_owned()) + ); + } + + /// The max age is checked before the nonce is spent, so a refused requirement leaves the + /// nonce available for a correct one. + #[tokio::test] + async fn max_age_other_than_the_pinned_year_is_refused_before_the_nonce_is_spent() { + let key = test_key(); + let (requirement, policy) = held_case(|r| r["maxAgeSeconds"] = json!(60)); + let presentation = request_for(&credential(&key, default_header(), |_| {})); + let conn = conn().await; + let runtime = handler_runtime(&conn, &key, true); + seed_handler(&conn, &key, &presentation).await; + assert_eq!( + handler_admit(&runtime, &requirement, &policy, &presentation, CALLER, true).await, + Err("credential-requirement-invalid".to_owned()) + ); + let (good, good_policy) = held_requirement_and_policy(); + handler_admit(&runtime, &good, &good_policy, &presentation, CALLER, true) + .await + .expect("the nonce is still unspent after the refused max age"); + } + + #[tokio::test] + async fn issuer_kid_other_than_the_pinned_kid_is_not_accepted() { + let key = test_key(); + let (requirement, mut policy) = held_requirement_and_policy(); + policy["credentialRequirement"]["issuerKid"] = json!("other-kid"); + let presentation = request_for(&credential(&key, default_header(), |_| {})); + let conn = conn().await; + let runtime = handler_runtime(&conn, &key, true); + seed_handler(&conn, &key, &presentation).await; + assert_eq!( + handler_admit(&runtime, &requirement, &policy, &presentation, CALLER, true).await, + Err("issuer-not-accepted".to_owned()) + ); + } + + #[tokio::test] + async fn upper_case_email_disclosure_is_refused() { + let key = test_key(); + let disclosures = vec![ + disclosure("upper-salt-email", "email", "Alice@example.com"), + disclosure("upper-salt-domain", "emailDomain", "example.com"), + ]; + let sd_jwt = mint( + &key, + &default_header().to_string(), + &default_payload(&disclosures).to_string(), + &disclosures, + ); + let presentation = request_for(&sd_jwt); + let (requirement, policy) = held_requirement_and_policy(); + let conn = conn().await; + let runtime = handler_runtime(&conn, &key, true); + seed_handler(&conn, &key, &presentation).await; + assert_eq!( + handler_admit(&runtime, &requirement, &policy, &presentation, CALLER, true).await, + Err("bad-disclosure".to_owned()) + ); + } + + #[tokio::test] + async fn credential_type_other_than_the_held_vct_is_a_type_mismatch() { + let key = test_key(); + let (requirement, policy) = + held_case(|r| r["credentialType"]["id"] = json!("opencredentials.other/v1")); + let presentation = request_for(&credential(&key, default_header(), |_| {})); + let conn = conn().await; + let runtime = handler_runtime(&conn, &key, true); + seed_handler(&conn, &key, &presentation).await; + assert_eq!( + handler_admit(&runtime, &requirement, &policy, &presentation, CALLER, true).await, + Err("credential-type-mismatch".to_owned()) + ); + } + + #[tokio::test] + async fn flipped_siwe_signature_is_refused() { + let (fixture, sd_jwt, message) = oc_case("heldtestnonce0000000002"); + let mut signature = sign_siwe(&message); + let last = signature.pop().unwrap(); + signature.push(if last == '0' { '1' } else { '0' }); + let request = body(&sd_jwt, &message, &signature); + assert_eq!(outcome(&fixture, &request).await, "bad-siwe-signature"); + } + + #[tokio::test] + async fn minted_credential_is_accepted_with_declared_disclosures() { + let key = test_key(); + let fixture = own_fixture(&key); + let sd_jwt = credential(&key, default_header(), |_| {}); + let conn = conn().await; + let request = request_for(&sd_jwt); + seed(&conn, &fixture, &request).await.expect("seed"); + let verified = admit(&conn, &fixture, &request) + .await + .expect("minted credential is accepted"); + assert_eq!( + verified.claims.get("emailDomain").map(String::as_str), + Some("example.com") + ); + } + + #[tokio::test] + async fn missing_kid_header_is_refused() { + let key = test_key(); + let fixture = own_fixture(&key); + let header = json!({"alg": "EdDSA", "typ": "vc+sd-jwt"}); + let sd_jwt = credential(&key, header, |_| {}); + assert_eq!(outcome(&fixture, &request_for(&sd_jwt)).await, "bad-header"); + } + + /// TC-1541 item 1. With the explicit list and a legacy single issuer loaded together, a + /// kid-less header is still refused on the held path, and a kid-bearing credential from + /// the explicit entry is still accepted. + #[tokio::test] + async fn kidless_header_is_refused_with_the_combined_issuer_set() { + let key = test_key(); + let legacy_did = "did:web:legacy-held.example"; + let legacy_kid = "did:web:legacy-held.example#k1"; + let legacy_key = IssuerKey::new( + legacy_did, + VCT, + 1, + legacy_kid, + SigningKey::from_bytes(&[9u8; 32]) + .verifying_key() + .to_bytes(), + ); + let set = IssuerSet::load_with_legacy(&[issuer_config(&key)], Some(&legacy_key)).unwrap(); + assert!(set.resolve_pinned_issuer(legacy_did, legacy_kid).is_some()); + let fixture = Fixture::new(set, TEST_ISSUER); + + let kidless = credential(&key, json!({"alg": "EdDSA", "typ": "vc+sd-jwt"}), |_| {}); + assert_eq!( + outcome(&fixture, &request_for(&kidless)).await, + "bad-header" + ); + + let conn = conn().await; + let request = request_for(&credential(&key, default_header(), |_| {})); + seed(&conn, &fixture, &request).await.expect("seed"); + admit(&conn, &fixture, &request) + .await + .expect("kid-bearing credential is accepted with the combined set"); + } + + /// TC-1541 item 2. Dalek's `verify` accepts a signature whose `R` is the identity point + /// (small order) when `S·B = k·A`; `verify_strict` refuses it. The forgery is built from + /// the test key's own secret scalar, so the vector is a genuine instance of that case. + #[tokio::test] + async fn small_order_r_signature_is_refused_on_the_held_path() { + use curve25519_dalek::{ + constants::ED25519_BASEPOINT_POINT, edwards::CompressedEdwardsY, scalar::Scalar, + traits::Identity, + }; + use ed25519_dalek::Verifier; + + let key = test_key(); + let verifying = key.verifying_key(); + let disclosures = email_disclosures(); + let header = default_header().to_string(); + let payload = default_payload(&disclosures).to_string(); + let input = signing_input(&header, &payload); + + // RFC 8032 secret scalar: the clamped low half of SHA-512(seed). + let expanded = sha2::Sha512::digest(key.to_bytes()); + let mut clamped = [0u8; 32]; + clamped.copy_from_slice(&expanded[..32]); + clamped[0] &= 248; + clamped[31] &= 127; + clamped[31] |= 64; + let secret = Scalar::from_bytes_mod_order(clamped); + assert_eq!( + (secret * ED25519_BASEPOINT_POINT).compress().to_bytes(), + verifying.to_bytes(), + "derived scalar must match the pinned public key" + ); + + // R is the identity (small order). With S = k·a, S·B − k·A = identity = R. + let r = CompressedEdwardsY::identity(); + let k = Scalar::from_hash( + sha2::Sha512::new() + .chain_update(r.as_bytes()) + .chain_update(verifying.to_bytes()) + .chain_update(input.as_bytes()), + ); + let mut signature = [0u8; 64]; + signature[..32].copy_from_slice(r.as_bytes()); + signature[32..].copy_from_slice((k * secret).as_bytes()); + let forged = Signature::from_bytes(&signature); + + // The vector discriminates: plain `verify` accepts it, `verify_strict` refuses it. + assert!(verifying.verify(input.as_bytes(), &forged).is_ok()); + assert!(verifying.verify_strict(input.as_bytes(), &forged).is_err()); + + let sd_jwt = assemble(&input, &signature, &disclosures); + let fixture = own_fixture(&key); + assert_eq!( + outcome(&fixture, &request_for(&sd_jwt)).await, + "bad-signature" + ); + } + + #[tokio::test] + async fn typ_other_than_vc_sd_jwt_is_refused() { + let key = test_key(); + let fixture = own_fixture(&key); + let header = json!({"alg": "EdDSA", "typ": "JWT", "kid": TEST_KID}); + let sd_jwt = credential(&key, header, |_| {}); + assert_eq!(outcome(&fixture, &request_for(&sd_jwt)).await, "bad-header"); + } + + #[tokio::test] + async fn duplicate_payload_key_is_refused_even_when_signed() { + let key = test_key(); + let fixture = own_fixture(&key); + let disclosures = email_disclosures(); + let payload = default_payload(&disclosures).to_string().replacen( + '{', + "{\"jti\":\"urn:uuid:7c1e4b2a-9d3f-4e5a-8b6c-0d1e2f3a4b5c\",", + 1, + ); + let sd_jwt = mint(&key, &default_header().to_string(), &payload, &disclosures); + assert_eq!( + outcome(&fixture, &request_for(&sd_jwt)).await, + "bad-payload" + ); + } + + #[tokio::test] + async fn payload_altered_after_signing_is_refused() { + let key = test_key(); + let fixture = own_fixture(&key); + let disclosures = email_disclosures(); + let header = default_header().to_string(); + let signed = signing_input(&header, &default_payload(&disclosures).to_string()); + let mut altered = default_payload(&disclosures); + altered["jti"] = json!("urn:uuid:9e8d7c6b-5a4f-4e3d-8c2b-1a0f9e8d7c6b"); + let signature = key.sign(signed.as_bytes()).to_bytes(); + let sd_jwt = assemble( + &signing_input(&header, &altered.to_string()), + &signature, + &disclosures, + ); + assert_eq!( + outcome(&fixture, &request_for(&sd_jwt)).await, + "bad-signature" + ); + } + + #[tokio::test] + async fn descriptor_digest_is_refused_for_the_email_row() { + let key = test_key(); + let fixture = own_fixture(&key); + let sd_jwt = credential(&key, default_header(), |p| { + p["descriptorDigest"] = json!("unexpected"); + }); + assert_eq!( + outcome(&fixture, &request_for(&sd_jwt)).await, + "bad-payload" + ); + } + + #[tokio::test] + async fn repeated_sd_digest_is_refused() { + let key = test_key(); + let fixture = own_fixture(&key); + let sd_jwt = credential(&key, default_header(), |p| { + let first = p["_sd"][0].clone(); + p["_sd"].as_array_mut().unwrap().push(first); + }); + assert_eq!( + outcome(&fixture, &request_for(&sd_jwt)).await, + "bad-payload" + ); + } + + #[tokio::test] + async fn header_member_outside_alg_typ_kid_is_refused() { + let key = test_key(); + let fixture = own_fixture(&key); + let mut header = default_header(); + header["x5c"] = json!(["AAAA"]); + let sd_jwt = credential(&key, header, |_| {}); + assert_eq!(outcome(&fixture, &request_for(&sd_jwt)).await, "bad-header"); + } + + #[tokio::test] + async fn non_v4_jti_is_refused() { + let key = test_key(); + let fixture = own_fixture(&key); + let sd_jwt = credential(&key, default_header(), |p| { + p["jti"] = json!("urn:uuid:held-test-0001"); + }); + assert_eq!( + outcome(&fixture, &request_for(&sd_jwt)).await, + "bad-payload" + ); + } + + #[tokio::test] + async fn oversized_presentation_is_refused_before_decoding() { + let key = test_key(); + let fixture = own_fixture(&key); + let sd_jwt = "a".repeat(16385); + assert_eq!( + outcome(&fixture, &request_for(&sd_jwt)).await, + "bad-presentation" + ); + } + + /// `MAX_SD_JWT_CHARS` is inclusive: 16384 passes `precheck`, 16385 is refused. + #[test] + fn sd_jwt_cap_admits_16384_chars_and_refuses_16385() { + let key = test_key(); + let fixture = own_fixture(&key); + let policy = fixture.policy(); + let at_cap = "a".repeat(16384); + let message = siwe_message(NONCE, &at_cap); + let signature = sign_siwe(&message); + let input = HeldPresentation { + sd_jwt: &at_cap, + siwe_message: &message, + siwe_signature: &signature, + }; + assert!( + precheck(&input, &policy).is_ok(), + "16384 chars is at the cap" + ); + + let over = "a".repeat(16385); + let message = siwe_message(NONCE, &over); + let signature = sign_siwe(&message); + let input = HeldPresentation { + sd_jwt: &over, + siwe_message: &message, + siwe_signature: &signature, + }; + assert_eq!( + precheck(&input, &policy).err(), + Some(BAD_PRESENTATION), + "16385 chars exceeds the cap" + ); + } + + /// `MAX_SIWE_MESSAGE_CHARS` is inclusive. A 2048-byte message is not refused + /// by the cap, so it reaches `parse_siwe`, which refuses it as `bad-siwe` + /// because its first line lacks the header. A 2049-byte message is refused + /// by the cap before parsing. + #[test] + fn siwe_message_cap_admits_2048_bytes_and_refuses_2049() { + let key = test_key(); + let fixture = own_fixture(&key); + let policy = fixture.policy(); + let at_cap = "a".repeat(2048); + let signature = sign_siwe(&at_cap); + let input = HeldPresentation { + sd_jwt: "a", + siwe_message: &at_cap, + siwe_signature: &signature, + }; + assert_eq!( + precheck(&input, &policy).err(), + Some(BAD_SIWE), + "2048 bytes passes the cap and reaches the parser" + ); + + let over = "a".repeat(2049); + let signature = sign_siwe(&over); + let input = HeldPresentation { + sd_jwt: "a", + siwe_message: &over, + siwe_signature: &signature, + }; + assert_eq!( + precheck(&input, &policy).err(), + Some(BAD_PRESENTATION), + "2049 bytes exceeds the cap" + ); + } + + #[test] + fn did_pkh_accepts_all_lowercase_or_exact_eip55_only() { + assert!(parse_pkh(CALLER).is_some()); + let lower = CALLER.to_ascii_lowercase(); + let upper = format!("did:pkh:eip155:1:0x{}", HOLDER[2..].to_ascii_uppercase()); + assert!(parse_pkh(&lower).is_some()); + assert!(parse_pkh(&upper).is_none()); + } + + #[test] + fn siwe_address_requires_the_exact_eip55_checksum() { + let lowered = siwe_message(NONCE, "x").replacen(HOLDER, &HOLDER.to_ascii_lowercase(), 1); + assert_eq!(parse_siwe(&lowered).err(), Some(BAD_SIWE)); + assert!(parse_siwe(&siwe_message(NONCE, "x")).is_ok()); + } + + #[test] + fn fractional_seconds_are_capped_at_nine_digits() { + assert!(rfc3339_shape("2026-01-01T00:00:00.123456789Z")); + assert!(!rfc3339_shape("2026-01-01T00:00:00.1234567890Z")); + } + + #[test] + fn seconds_must_be_at_most_59() { + assert!(rfc3339_shape("2026-01-01T00:00:59Z")); + assert!(!rfc3339_shape("2026-01-01T00:00:60Z")); + assert!(!rfc3339_shape("2026-01-01T00:00:61Z")); + } + + #[test] + fn jti_must_be_a_lowercase_v4_uuid_urn() { + assert!(is_uuid_v4_urn( + "urn:uuid:5f1c9a2e-7b3d-4e8a-9c61-2d4b8e7f0a13" + )); + assert!(!is_uuid_v4_urn( + "urn:uuid:5F1C9A2E-7B3D-4E8A-9C61-2D4B8E7F0A13" + )); + assert!(!is_uuid_v4_urn( + "urn:uuid:5f1c9a2e-7b3d-1e8a-9c61-2d4b8e7f0a13" + )); + assert!(!is_uuid_v4_urn( + "urn:uuid:5f1c9a2e-7b3d-4e8a-1c61-2d4b8e7f0a13" + )); + } + + #[test] + fn email_domain_must_be_ascii_and_email_must_not_start_or_end_with_at() { + let check = |name: &str, value: &str| { + let mut claims = BTreeMap::new(); + claims.insert(name.to_owned(), value.to_owned()); + validate_disclosed(&claims) + }; + assert_eq!(check("emailDomain", "exämple.com"), Err(BAD_DISCLOSURE)); + assert_eq!(check("email", "@example.com"), Err(BAD_DISCLOSURE)); + assert_eq!(check("email", "user@"), Err(BAD_DISCLOSURE)); + assert_eq!(check("email", "user@example.com"), Ok(())); + } + + #[tokio::test] + async fn lifetime_over_365_days_is_refused() { + let key = test_key(); + let fixture = own_fixture(&key); + let sd_jwt = credential(&key, default_header(), |p| { + p["exp"] = json!(IAT + 366 * DAY) + }); + assert_eq!( + outcome(&fixture, &request_for(&sd_jwt)).await, + "bad-lifetime" + ); + } + + #[tokio::test] + async fn status_other_than_none_is_refused() { + let key = test_key(); + let fixture = own_fixture(&key); + let sd_jwt = credential(&key, default_header(), |p| { + p["status"] = json!({"method": "revoked"}) + }); + assert_eq!(outcome(&fixture, &request_for(&sd_jwt)).await, "bad-status"); + } + + #[tokio::test] + async fn subject_with_invalid_eip55_casing_is_refused() { + let key = test_key(); + let fixture = own_fixture(&key); + let mangled = CALLER.replacen("Fd6", "FD6", 1); + let sd_jwt = credential(&key, default_header(), |p| { + p["sub"] = json!(mangled); + p["holderBinding"]["did"] = json!(mangled); + }); + assert_eq!( + outcome(&fixture, &request_for(&sd_jwt)).await, + "bad-subject" + ); + } + + #[tokio::test] + async fn subject_with_all_lowercase_body_is_accepted_and_reported_checksummed() { + let key = test_key(); + let fixture = own_fixture(&key); + let lower = CALLER.to_ascii_lowercase(); + let sd_jwt = credential(&key, default_header(), |p| { + p["sub"] = json!(lower); + p["holderBinding"]["did"] = json!(lower); + }); + let request = request_for(&sd_jwt); + let conn = conn().await; + seed(&conn, &fixture, &request).await.expect("seed"); + let verified = admit(&conn, &fixture, &request) + .await + .expect("all-lowercase body is accepted"); + assert_eq!(verified.subject, CALLER); + assert_eq!(verified.subject_address, HOLDER.to_ascii_lowercase()); + } + + #[tokio::test] + async fn disclosure_without_matching_digest_is_refused() { + let key = test_key(); + let fixture = own_fixture(&key); + let mut disclosures = email_disclosures(); + disclosures.push(disclosure("salt-stray", "emailDomain", "other.example")); + let payload = default_payload(&email_disclosures()).to_string(); + let sd_jwt = mint(&key, &default_header().to_string(), &payload, &disclosures); + assert_eq!( + outcome(&fixture, &request_for(&sd_jwt)).await, + "bad-disclosure" + ); + } + + #[tokio::test] + async fn credential_at_or_after_expiry_is_refused() { + let key = test_key(); + let mut fixture = own_fixture(&key); + fixture.now = OffsetDateTime::from_unix_timestamp(IAT + 30 * DAY).unwrap(); + let sd_jwt = credential(&key, default_header(), |_| {}); + assert_eq!(outcome(&fixture, &request_for(&sd_jwt)).await, "expired"); + } + + #[tokio::test] + async fn credential_before_not_before_is_refused() { + let key = test_key(); + let mut fixture = own_fixture(&key); + fixture.now = OffsetDateTime::from_unix_timestamp(IAT - 60).unwrap(); + let sd_jwt = credential(&key, default_header(), |_| {}); + assert_eq!( + outcome(&fixture, &request_for(&sd_jwt)).await, + "not-yet-valid" + ); + } + + #[tokio::test] + async fn siwe_uri_authority_other_than_audience_is_refused() { + let key = test_key(); + let fixture = own_fixture(&key); + let sd_jwt = credential(&key, default_header(), |_| {}); + let message = siwe_message(NONCE, &sd_jwt).replacen( + "URI: https://verifier.example", + "URI: https://evil.example", + 1, + ); + let request = body(&sd_jwt, &message, &sign_siwe(&message)); + assert_eq!(outcome(&fixture, &request).await, "bad-siwe"); + } + + #[test] + fn caller_must_be_the_subject_account() { + let key = test_key(); + let mut fixture = own_fixture(&key); + fixture.caller = OTHER_ACCOUNT.to_owned(); + let sd_jwt = credential(&key, default_header(), |_| {}); + let request = request_for(&sd_jwt); + let input = read_presentation(&request).unwrap(); + let policy = fixture.policy(); + let pre = precheck(&input, &policy).unwrap(); + assert_eq!( + refused(verify(&input, &pre, &policy)), + "nonce-account-mismatch" + ); + } + + #[tokio::test] + async fn issuer_stopped_at_now_is_refused() { + let key = test_key(); + let mut config = issuer_config(&key); + config.not_after = Some("2026-01-01T00:30:00Z".to_owned()); + let fixture = Fixture::new(IssuerSet::load(&[config]).unwrap(), TEST_ISSUER); + let sd_jwt = credential(&key, default_header(), |_| {}); + assert_eq!( + outcome(&fixture, &request_for(&sd_jwt)).await, + "issuer-stopped" + ); + } + + #[tokio::test] + async fn credential_issued_after_issuer_retirement_is_refused() { + let key = test_key(); + let mut config = issuer_config(&key); + config.retired_at = Some("2025-12-31T23:00:00Z".to_owned()); + let fixture = Fixture::new(IssuerSet::load(&[config]).unwrap(), TEST_ISSUER); + let sd_jwt = credential(&key, default_header(), |_| {}); + assert_eq!( + outcome(&fixture, &request_for(&sd_jwt)).await, + "issuer-retired" + ); + } + + #[tokio::test] + async fn issuer_outside_the_policy_accepted_list_is_refused() { + let key = test_key(); + let mut fixture = own_fixture(&key); + fixture.issuers = vec![AcceptedIssuer { + did: "did:web:other.example".to_owned(), + kid: None, + }]; + let sd_jwt = credential(&key, default_header(), |_| {}); + assert_eq!( + outcome(&fixture, &request_for(&sd_jwt)).await, + "issuer-not-accepted" + ); + } + + #[tokio::test] + async fn policy_kid_pin_must_match_the_presented_kid() { + let key = test_key(); + let mut fixture = own_fixture(&key); + fixture.issuers = vec![AcceptedIssuer { + did: TEST_ISSUER.to_owned(), + kid: Some(format!("{TEST_ISSUER}#k2")), + }]; + let sd_jwt = credential(&key, default_header(), |_| {}); + assert_eq!( + outcome(&fixture, &request_for(&sd_jwt)).await, + "issuer-not-accepted" + ); + } + + #[tokio::test] + async fn credential_type_outside_the_issuer_entry_is_refused() { + let key = test_key(); + let mut config = issuer_config(&key); + config.vcts = vec!["urn:example:other-credential".to_owned()]; + let fixture = Fixture::new(IssuerSet::load(&[config]).unwrap(), TEST_ISSUER); + let sd_jwt = credential(&key, default_header(), |_| {}); + assert_eq!( + outcome(&fixture, &request_for(&sd_jwt)).await, + "profile-mismatch" + ); + } + + #[tokio::test] + async fn siwe_domain_other_than_audience_is_refused() { + let key = test_key(); + let fixture = own_fixture(&key); + let sd_jwt = credential(&key, default_header(), |_| {}); + let message = siwe_message(NONCE, &sd_jwt).replacen( + &format!("{AUDIENCE} wants"), + "evil.example wants", + 1, + ); + let request = body(&sd_jwt, &message, &sign_siwe(&message)); + assert_eq!(outcome(&fixture, &request).await, "bad-siwe"); + } + + #[tokio::test] + async fn siwe_resource_must_hash_the_presented_sd_jwt() { + let key = test_key(); + let fixture = own_fixture(&key); + let sd_jwt = credential(&key, default_header(), |_| {}); + let message = siwe_message(NONCE, "a-different-sd-jwt"); + let request = body(&sd_jwt, &message, &sign_siwe(&message)); + assert_eq!(outcome(&fixture, &request).await, "bad-siwe"); + } + + #[tokio::test] + async fn siwe_expiration_time_in_the_past_is_refused() { + let key = test_key(); + let fixture = own_fixture(&key); + let sd_jwt = credential(&key, default_header(), |_| {}); + let message = siwe_message(NONCE, &sd_jwt).replacen( + &format!("Issued At: {ISSUED_AT}"), + &format!("Issued At: {ISSUED_AT}\nExpiration Time: 2025-12-31T00:00:00Z"), + 1, + ); + let request = body(&sd_jwt, &message, &sign_siwe(&message)); + assert_eq!(outcome(&fixture, &request).await, "bad-siwe"); + } + + #[tokio::test] + async fn siwe_expiration_is_compared_at_millisecond_precision() { + let key = test_key(); + let mut fixture = own_fixture(&key); + fixture.now = OffsetDateTime::parse(NOW, &Rfc3339).unwrap(); + let sd_jwt = credential(&key, default_header(), |_| {}); + // TS keeps milliseconds only: `NOW` plus 0.5ms truncates to `NOW`, which is not after `now`. + let sub_ms = NOW.replace('Z', ".0005Z"); + let message = siwe_message(NONCE, &sd_jwt).replacen( + &format!("Issued At: {ISSUED_AT}"), + &format!("Issued At: {ISSUED_AT}\nExpiration Time: {sub_ms}"), + 1, + ); + let request = body(&sd_jwt, &message, &sign_siwe(&message)); + assert_eq!(outcome(&fixture, &request).await, "bad-siwe"); + } + + #[tokio::test] + async fn siwe_not_before_is_compared_at_millisecond_precision() { + let key = test_key(); + let mut fixture = own_fixture(&key); + fixture.now = OffsetDateTime::parse(NOW, &Rfc3339).unwrap(); + let sd_jwt = credential(&key, default_header(), |_| {}); + // TS keeps milliseconds only: `NOW` plus 0.5ms truncates to `NOW`, so `now` is not before it. + let sub_ms = NOW.replace('Z', ".0005Z"); + let message = siwe_message(NONCE, &sd_jwt).replacen( + &format!("Issued At: {ISSUED_AT}"), + &format!("Issued At: {ISSUED_AT}\nNot Before: {sub_ms}"), + 1, + ); + let request = body(&sd_jwt, &message, &sign_siwe(&message)); + let conn = conn().await; + seed(&conn, &fixture, &request).await.expect("seed"); + admit(&conn, &fixture, &request) + .await + .expect("not-before truncates to NOW, so it is not in the future"); + } + + #[tokio::test] + async fn siwe_signed_by_another_key_is_refused() { + let key = test_key(); + let fixture = own_fixture(&key); + let sd_jwt = credential(&key, default_header(), |_| {}); + let message = siwe_message(NONCE, &sd_jwt); + // Anvil account 1: a valid secp256k1 key whose address is not the subject. + let other_key = "59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d"; + let request = body(&sd_jwt, &message, &sign_siwe_with(other_key, &message)); + assert_eq!(outcome(&fixture, &request).await, "bad-siwe-signature"); + } + + #[tokio::test] + async fn holder_binding_must_name_the_subject() { + let key = test_key(); + let fixture = own_fixture(&key); + let sd_jwt = credential(&key, default_header(), |payload| { + payload["holderBinding"]["did"] = json!(OTHER_ACCOUNT); + }); + assert_eq!( + outcome(&fixture, &request_for(&sd_jwt)).await, + "bad-holder-binding" + ); + } + + #[tokio::test] + async fn subject_on_another_chain_is_refused() { + let key = test_key(); + let fixture = own_fixture(&key); + let other_chain = format!("did:pkh:eip155:10:{HOLDER}"); + let sd_jwt = credential(&key, default_header(), |payload| { + payload["sub"] = json!(other_chain); + }); + assert_eq!( + outcome(&fixture, &request_for(&sd_jwt)).await, + "bad-subject" + ); + } + + #[tokio::test] + async fn payload_iss_must_name_the_kid_issuer() { + let key = test_key(); + let fixture = own_fixture(&key); + let sd_jwt = credential(&key, default_header(), |payload| { + payload["iss"] = json!("did:web:other.example"); + }); + assert_eq!( + outcome(&fixture, &request_for(&sd_jwt)).await, + "bad-payload" + ); + } + + #[tokio::test] + async fn disclosure_must_be_listed_in_sd() { + let key = test_key(); + let fixture = own_fixture(&key); + let first = digest(&email_disclosures()[0]); + let sd_jwt = credential(&key, default_header(), |payload| { + payload["_sd"] = json!([first]); + }); + assert_eq!( + outcome(&fixture, &request_for(&sd_jwt)).await, + "bad-disclosure" + ); + } + + #[test] + fn malformed_caller_account_is_a_client_refusal_not_a_server_fault() { + let key = test_key(); + let mut fixture = own_fixture(&key); + fixture.caller = "did:pkh:eip155:1:not-an-address".to_owned(); + let sd_jwt = credential(&key, default_header(), |_| {}); + let request = request_for(&sd_jwt); + let input = read_presentation(&request).unwrap(); + assert_eq!( + precheck(&input, &fixture.policy()).err(), + Some("account-owner-invalid") + ); + } + + #[tokio::test] + async fn nonce_is_spent_only_by_the_account_it_was_recorded_for() { + let conn = conn().await; + let owner = CALLER.to_ascii_lowercase(); + let now = OffsetDateTime::from_unix_timestamp(1_000_000).unwrap(); + record_nonce(&conn, AUDIENCE, NONCE, &owner, 1_000_600) + .await + .unwrap(); + assert!(!consume_nonce(&conn, AUDIENCE, NONCE, OTHER_ACCOUNT, now) + .await + .unwrap()); + assert!(consume_nonce(&conn, AUDIENCE, NONCE, &owner, now) + .await + .unwrap()); + assert!(!consume_nonce(&conn, AUDIENCE, NONCE, &owner, now) + .await + .unwrap()); + } + + #[tokio::test] + async fn expired_nonce_is_refused_and_spends_nothing() { + let conn = conn().await; + let owner = CALLER.to_ascii_lowercase(); + record_nonce(&conn, AUDIENCE, NONCE, &owner, 1_000_600) + .await + .unwrap(); + let late = OffsetDateTime::from_unix_timestamp(1_000_601).unwrap(); + assert!(!consume_nonce(&conn, AUDIENCE, NONCE, &owner, late) + .await + .unwrap()); + } + + #[tokio::test] + async fn nonce_expiry_boundary_is_exclusive() { + let conn = conn().await; + let owner = CALLER.to_ascii_lowercase(); + record_nonce(&conn, AUDIENCE, NONCE, &owner, 1_000_600) + .await + .unwrap(); + let at_expiry = OffsetDateTime::from_unix_timestamp(1_000_600).unwrap(); + assert!(!consume_nonce(&conn, AUDIENCE, NONCE, &owner, at_expiry) + .await + .unwrap()); + } + + #[tokio::test] + async fn expired_rows_are_pruned_on_consume() { + let conn = conn().await; + let owner = CALLER.to_ascii_lowercase(); + record_nonce(&conn, AUDIENCE, "stale", &owner, 1_000_100) + .await + .unwrap(); + record_nonce(&conn, AUDIENCE, NONCE, &owner, 1_000_600) + .await + .unwrap(); + let now = OffsetDateTime::from_unix_timestamp(1_000_200).unwrap(); + assert!(consume_nonce(&conn, AUDIENCE, NONCE, &owner, now) + .await + .unwrap()); + let remaining = held_credential_nonce::Entity::find() + .all(&conn) + .await + .unwrap(); + assert!(remaining.is_empty()); + } + + #[test] + fn kidless_lookup_never_resolves_a_pinned_key() { + let key = test_key(); + let configured = IssuerSet::load(&[issuer_config(&key)]).unwrap(); + assert!(configured + .resolve_pinned_issuer(TEST_ISSUER, TEST_KID) + .is_some()); + assert!(configured.resolve_pinned_issuer(TEST_ISSUER, "").is_none()); + + let legacy_key = IssuerKey::new( + TEST_ISSUER, + VCT, + 1, + TEST_KID, + key.verifying_key().to_bytes(), + ); + let legacy = IssuerSet::from_legacy(&legacy_key); + assert!(legacy + .resolve_pinned_issuer(TEST_ISSUER, TEST_KID) + .is_some()); + assert!(legacy.resolve_pinned_issuer(TEST_ISSUER, "").is_none()); + } + + /// Replays the TS differential table, `tests/fixtures/held-email-v1/s1-differential.json`, + /// generated from the published `@tinycloud/sdk-core` 3.3.0-beta.37 `held-credentials` verifier. + #[tokio::test] + async fn s1_differential_table_matches_ts_verdicts() { + let table: Value = serde_json::from_str(include_str!( + "../tests/fixtures/held-email-v1/s1-differential.json" + )) + .unwrap(); + let cases = table.as_array().unwrap(); + let mut diverging = Vec::new(); + for case in cases { + let name = case["name"].as_str().unwrap(); + let expected = case["ts"]["code"].as_str().unwrap(); + let actual = replay(case).await; + match case.get("deviation") { + Some(deviation) => { + let rust = deviation["rust"].as_str().unwrap(); + assert!( + !deviation["reason"].as_str().unwrap().is_empty(), + "{name}: empty deviation reason" + ); + // A deviation must name the Rust result exactly and must only sit on a + // case where Rust and TS actually disagree. + if actual != rust || actual == expected { + diverging.push(format!( + "{name}: deviation rust={rust} ts={expected}, replay gives {actual}" + )); + } + } + None if actual != expected => { + diverging.push(format!("{name}: rust={actual} ts={expected}")); + } + None => {} + } + } + assert!( + diverging.is_empty(), + "{} of {} cases differ from TS without a matching deviation:\n{}", + diverging.len(), + cases.len(), + diverging.join("\n") + ); + } + + /// One table case through the production order (precheck, consume nonce, verify). + /// Returns `"ok"` on accept with the TS issuer and subject, otherwise the Rust refusal. + async fn replay(case: &Value) -> String { + let policy = &case["policy"]; + assert_eq!(policy["audience"], AUDIENCE); + let configured: Vec = + match serde_json::from_value(policy["issuers"].clone()) { + Ok(configured) => configured, + Err(err) => return format!("config-invalid: {err}"), + }; + let set = match IssuerSet::load(&configured) { + Ok(set) => set, + // Rust rejects a bad set at startup (`credential_issuer_set()?` in lib.rs), so no + // presentation reaches verify. TS reports the same condition per presentation. + Err(_) => return "bad-issuer-set".to_owned(), + }; + let fixture = Fixture { + set, + issuers: policy["acceptedIssuers"] + .as_array() + .unwrap() + .iter() + .map(|issuer| AcceptedIssuer { + did: issuer["issuerDid"].as_str().unwrap().to_owned(), + kid: issuer["kid"].as_str().map(str::to_owned), + }) + .collect(), + profiles: policy["acceptedProfiles"] + .as_array() + .unwrap() + .iter() + .map(|profile| AcceptedProfile { + id: profile["id"].as_str().unwrap().to_owned(), + version: profile["version"].as_i64().unwrap(), + }) + .collect(), + now: OffsetDateTime::parse(policy["now"].as_str().unwrap(), &Rfc3339).unwrap(), + caller: policy["caller"].as_str().unwrap().to_owned(), + }; + let conn = conn().await; + for entry in case["nonceStore"].as_array().unwrap() { + let (audience, nonce) = entry["key"].as_str().unwrap().split_once('\n').unwrap(); + record_nonce( + &conn, + audience, + nonce, + &parse_pkh(entry["account"].as_str().unwrap()) + .expect("nonceStore account is did:pkh") + .canonical(), + fixture.now.unix_timestamp() + 3600, + ) + .await + .expect("nonce store"); + } + let request = json!({"sdJwt": case["sdJwt"], "siwe": case["siwe"]}); + match admit(&conn, &fixture, &request).await { + Ok(verified) + if Some(verified.issuer.as_str()) == case["ts"]["issuer"].as_str() + && Some(verified.subject.as_str()) == case["ts"]["subject"].as_str() => + { + "ok".to_owned() + } + Ok(_) => "ok-identity-diverges".to_owned(), + Err(code) => code.to_owned(), + } + } + + #[test] + fn siwe_uri_must_be_https_with_no_userinfo_and_the_exact_audience_host() { + let audience = "tinycloud.example"; + for (uri, expected) in [ + ("https://tinycloud.example/nonce", true), + ("https://TINYCLOUD.example/", true), + ("https://tinycloud.example:443/x?y#z", true), + ("https://tinycloud.example:8443/", false), + ("https://user@tinycloud.example/", false), + ("https://user:pw@tinycloud.example/", false), + ("https://tinycloud.example.evil/", false), + ("https://evil.example/@tinycloud.example", false), + ("https://tinycloud.example./", false), + ("http://tinycloud.example/", false), + ("tinycloud.example", false), + ("", false), + ] { + assert_eq!(uri_matches_audience(uri, audience), expected, "{uri}"); + } + } + + #[test] + fn siwe_uri_origin_includes_the_audience_port() { + let audience = "verifier.example:8443"; + for (uri, expected) in [ + ("https://verifier.example:8443/nonce", true), + ("https://VERIFIER.example:8443/", true), + ("https://verifier.example/", false), + ("https://verifier.example:9443/", false), + ("https://verifier.example:443/", false), + ] { + assert_eq!(uri_matches_audience(uri, audience), expected, "{uri}"); + } + } + + /// High-S SIWE signatures (`n - s` with the flipped recovery byte) are refused: + /// `recover_from_prehash` verifies with `verify_prehash`, which enforces low-S. + /// TS beta.37 accepts them; the difference is recorded as a deviation in the table. + #[test] + fn siwe_high_s_signature_is_refused_and_low_s_still_recovers() { + use k256::elliptic_curve::PrimeField; + let message = siwe_message(NONCE, "held-placeholder~"); + let low = sign_siwe(&message); + let bytes = hex::decode(low.trim_start_matches("0x")).unwrap(); + let mut s_bytes = [0u8; 32]; + s_bytes.copy_from_slice(&bytes[32..64]); + let s = k256::Scalar::from_repr(s_bytes.into()).unwrap(); + let high_s = (-s).to_bytes(); + assert_ne!(&high_s[..], &bytes[32..64]); + let mut high = bytes[..32].to_vec(); + high.extend_from_slice(&high_s); + high.push(if bytes[64] == 27 { 28 } else { 27 }); + let prefixed_message = message.as_bytes(); + assert_eq!(recover_eip191_address(prefixed_message, &high), None); + assert_eq!( + recover_eip191_address(prefixed_message, &bytes) + .unwrap() + .to_lowercase(), + HOLDER.to_lowercase() + ); + } +} diff --git a/tinycloud-node-server/src/lib.rs b/tinycloud-node-server/src/lib.rs index 4a65c225..8ca93c87 100644 --- a/tinycloud-node-server/src/lib.rs +++ b/tinycloud-node-server/src/lib.rs @@ -32,6 +32,7 @@ pub mod config; pub mod dstack; pub mod egress; pub mod epoch_head_backfill; +pub mod held_email; pub mod hooks; pub mod invocation_replay; pub mod issuer_set; @@ -726,6 +727,8 @@ pub async fn app_with_control( if !credential_issuers.is_empty() { policy_v3_runtime = policy_v3_runtime.with_credential_issuers(credential_issuers); } + policy_v3_runtime = + policy_v3_runtime.with_held_credentials(&tinycloud_config.held_credentials)?; #[cfg(feature = "duckdb")] let duckdb_service = DuckDbService::new( diff --git a/tinycloud-node-server/src/policy_v3.rs b/tinycloud-node-server/src/policy_v3.rs index ad0f7e2c..b7906c8e 100644 --- a/tinycloud-node-server/src/policy_v3.rs +++ b/tinycloud-node-server/src/policy_v3.rs @@ -21,10 +21,9 @@ use time::{format_description::well_known::Rfc3339, Duration, OffsetDateTime}; use tinycloud_auth::authorization::TinyCloudDelegation; use tinycloud_auth::multihash_codetable::MultihashDigest; use tinycloud_auth::share_email_evidence::{verify_detached_ed25519, IssuerKey}; -use tinycloud_auth::ssi::{ - dids::DIDBuf, - jwk::{Algorithm, Base64urlUInt, OctetParams, Params, JWK}, -}; +use tinycloud_auth::ssi::dids::DIDBuf; +#[cfg(test)] +use tinycloud_auth::ssi::jwk::{Algorithm, Base64urlUInt, OctetParams, Params, JWK}; use tinycloud_auth::{ identity::{did_principal_matches, parse_pkh_did}, resource::{ResourceId, SpaceId}, @@ -48,7 +47,11 @@ use tinycloud_core::{ RecoveringConnection, }; -use crate::{authorization::AuthHeaderGetter, config::ShareEmailConfig}; +use crate::{ + authorization::AuthHeaderGetter, + config::{HeldCredentialsConfig, ShareEmailConfig}, + held_email, +}; pub const POLICY_SESSION_PROFILE: &str = "policy-session-ucan/v1"; pub const POLICY_V1_SCHEMA: &str = "xyz.tinycloud.policy/policy/v1"; @@ -85,6 +88,7 @@ const MAX_SEALED_ENVELOPE_BYTES: usize = 4 * 1024 * 1024; // freshness bound for its non-revocable status. This is pinned here rather // than trusting the unsigned transport envelope around the SD-JWT. const EMAIL_PROOF_STATUS_FRESHNESS_SECONDS: i64 = 300; +const HELD_EMAIL_MAX_AGE_SECONDS: i64 = 31_536_000; const INVITATION_REQUEST_SCHEMA: &str = "xyz.tinycloud.credentials/invitation-request/v1"; const DELIVERY_ADMISSION_SCHEMA: &str = "xyz.tinycloud.policy/delivery-admission/v0"; /// OpenCredentials profile whose signed `emailDomain` claim backs domain shares. @@ -101,6 +105,13 @@ struct DeliveryRuntime { invitation_origin: String, } +/// Audience-bound runtime for held email credentials (TC-1452). Absent unless +/// `held_credentials.enabled` is set; held presentations are refused without it. +#[derive(Clone)] +struct HeldCredentialRuntime { + audience: String, +} + #[derive(Clone)] pub struct PolicyV3Runtime { pub conn: RecoveringConnection, @@ -109,6 +120,7 @@ pub struct PolicyV3Runtime { credential_issuers: IssuerSet, delivery: Option, sqlite_writer_lock: Option>>, + held_credentials: Option, } impl PolicyV3Runtime { @@ -124,6 +136,7 @@ impl PolicyV3Runtime { credential_issuers: IssuerSet::default(), delivery: None, sqlite_writer_lock: None, + held_credentials: None, } } @@ -139,6 +152,24 @@ impl PolicyV3Runtime { self } + /// Enable held email credential admission (TC-1452). A no-op when the + /// feature is disabled. When enabled, the audience is required and must be + /// a valid host, so a misconfigured node refuses to start. + pub fn with_held_credentials(mut self, config: &HeldCredentialsConfig) -> anyhow::Result { + if !config.enabled { + return Ok(self); + } + let audience = config + .audience + .clone() + .ok_or_else(|| anyhow::anyhow!("held credential audience is missing"))?; + if !held_email::valid_audience(&audience) { + return Err(anyhow::anyhow!("held credential audience is invalid")); + } + self.held_credentials = Some(HeldCredentialRuntime { audience }); + Ok(self) + } + /// Install one OpenCredentials issuer as a one-entry set (the legacy /// single-issuer configuration). pub fn with_credential_issuer(self, issuer: IssuerKey) -> Self { @@ -812,6 +843,7 @@ fn session_expiry( root_expires_at: &str, policy_expires_at: Option<&str>, account_expires_at: Option, + credential_expires_at: Option, ) -> Result { let invalid = || (Status::BadRequest, "session-expiry-invalid".to_owned()); let mut expires = match requested { @@ -837,6 +869,9 @@ fn session_expiry( if let Some(account) = account_expires_at { expires = expires.min(account); } + if let Some(credential) = credential_expires_at { + expires = expires.min(credential); + } Ok(expires) } @@ -2099,9 +2134,18 @@ pub async fn mint( let accountless_credential_admission = credential_admission && request.presentation.get("schema").and_then(Value::as_str) == Some(CREDENTIAL_PRESENTATION_V4_SCHEMA); + // A held presentation carries its SD-JWT inside `presentation`, so the + // request has no credential envelope. Every other credential admission + // still requires one. + let held_admission = credential_admission + && !accountless_credential_admission + && held_email::read_presentation(&request.presentation).is_ok(); + if held_admission && runtime.held_credentials.is_none() { + return Err((Status::Forbidden, "held-credentials-disabled".into())); + } if credential_admission { if request.requirement.is_null() - || request.credential.is_null() + || request.credential.is_null() == !held_admission || !request.claim.is_null() || if accountless_credential_admission { !request.account_authorization_cid.is_missing() @@ -2217,7 +2261,17 @@ pub async fn mint( now, }; let credential_admission_result = if credential_admission { - Some(if accountless_credential_admission { + Some(if held_admission { + validate_held_email_admission( + &request.requirement, + &request.presentation, + ®istered_policy, + &claim_context, + runtime, + true, + ) + .await? + } else if accountless_credential_admission { validate_credential_admission_v4( &request.requirement, &request.credential, @@ -2268,6 +2322,7 @@ pub async fn mint( (!credential_admission).then_some(&request.claim), &request.presentation, &evaluation_context, + !held_admission, )?; validate_requested_policy_capabilities( requested, @@ -2400,6 +2455,9 @@ pub async fn mint( account_owner_proof .as_ref() .and_then(|proof| proof.expires_at), + credential_admission_result + .as_ref() + .and_then(|admission| admission.credential_expires_at), )? .unix_timestamp(); if expires <= not_before { @@ -2593,7 +2651,17 @@ pub async fn mint( .requested_capabilities .as_array() .ok_or((Status::Forbidden, "requested-capabilities-invalid".into()))?; - Some(if accountless_credential_admission { + Some(if held_admission { + validate_held_email_admission( + &request.requirement, + &request.presentation, + &locked_policy, + &locked_claim_context, + runtime, + false, + ) + .await? + } else if accountless_credential_admission { validate_credential_admission_v4( &request.requirement, &request.credential, @@ -2659,6 +2727,7 @@ pub async fn mint( node_did: &runtime.node_did, now, }, + !held_admission, )?; if canonical_value_set(&final_allow.approved_capabilities) != canonical_value_set(&allow.approved_capabilities) @@ -4316,7 +4385,7 @@ fn is_base64url_digest(value: &str) -> bool { .all(|byte| byte.is_ascii_alphanumeric() || matches!(byte, b'-' | b'_')) } -fn canonical_digest_base64url(value: &Value) -> String { +pub(crate) fn canonical_digest_base64url(value: &Value) -> String { base64::encode_config(Sha256::digest(canonical_json_value(value)), URL_SAFE_NO_PAD) } @@ -5122,14 +5191,14 @@ fn validate_registration_projection( Ok(policy) } -struct ClaimPresentationContext<'a> { - challenge_id: &'a str, - nonce: &'a str, - policy_cid: &'a str, - owner_did: &'a str, - recipient_did: &'a str, - authenticated_account_owner: Option<&'a str>, - now: OffsetDateTime, +pub(crate) struct ClaimPresentationContext<'a> { + pub(crate) challenge_id: &'a str, + pub(crate) nonce: &'a str, + pub(crate) policy_cid: &'a str, + pub(crate) owner_did: &'a str, + pub(crate) recipient_did: &'a str, + pub(crate) authenticated_account_owner: Option<&'a str>, + pub(crate) now: OffsetDateTime, } fn validate_claim_and_presentation( @@ -5369,7 +5438,7 @@ fn credential_evidence_digest(value: &Value) -> Result )) } -struct CredentialAdmission { +pub(crate) struct CredentialAdmission { claim_jti: String, credential_id: String, presentation_jti: Option, @@ -5377,6 +5446,7 @@ struct CredentialAdmission { envelope_digest_hex: String, presentation_digest_hex: String, credential_space_owner_did: Option, + credential_expires_at: Option, } struct AccountOwnerProof { @@ -5672,6 +5742,7 @@ fn validate_credential_admission_v3( presentation.clone(), )))), credential_space_owner_did: Some(account_owner.to_owned()), + credential_expires_at: None, }) } @@ -5732,9 +5803,173 @@ fn validate_credential_admission_v4( envelope_digest_hex: digest_value(credential), presentation_digest_hex: hex::encode(Sha256::digest(canonical_json_value(presentation))), credential_space_owner_did: None, + credential_expires_at: None, + }) +} + +/// Held email admission (TC-1452). `consume` is true at the first admission +/// site only; the locked re-evaluation verifies the same presentation without +/// spending the nonce a second time. +pub(crate) async fn validate_held_email_admission( + requirement: &Value, + presentation: &Value, + policy: &Value, + context: &ClaimPresentationContext<'_>, + runtime: &PolicyV3Runtime, + consume: bool, +) -> Result { + let held = runtime + .held_credentials + .as_ref() + .ok_or((Status::Forbidden, "held-credentials-disabled".into()))?; + let projection = validate_policy_credential_requirement( + policy + .get("credentialRequirement") + .ok_or((Status::Forbidden, "credential-requirement-missing".into()))?, + )?; + validate_request_local_requirement(requirement, projection)?; + if runtime.credential_issuers.is_empty() { + return Err(( + Status::ServiceUnavailable, + "credential-issuer-unavailable".into(), + )); + } + let requirement_invalid = || { + ( + Status::Forbidden, + String::from("credential-requirement-invalid"), + ) + }; + if projection + .get("credentialType") + .and_then(|value| value.get("id")) + .and_then(Value::as_str) + != Some(held_email::VCT) + { + return Err((Status::Forbidden, "credential-type-mismatch".into())); + } + held_email_max_age_pinned(requirement)?; + let issuer_did = projection + .get("issuerDid") + .and_then(Value::as_str) + .ok_or_else(requirement_invalid)?; + let accepted_issuers = [held_email::AcceptedIssuer { + did: issuer_did.to_owned(), + kid: projection + .get("issuerKid") + .and_then(Value::as_str) + .map(str::to_owned), + }]; + let profile = projection.get("profile").ok_or_else(requirement_invalid)?; + let accepted_profiles = [held_email::AcceptedProfile { + id: profile + .get("id") + .and_then(Value::as_str) + .ok_or_else(requirement_invalid)? + .to_owned(), + version: profile + .get("version") + .and_then(Value::as_i64) + .ok_or_else(requirement_invalid)?, + }]; + let caller_account = context + .authenticated_account_owner + .ok_or((Status::Forbidden, "account-owner-missing".into()))?; + let view = held_email::HeldPolicy { + now: context.now, + audience: &held.audience, + caller_account, + accepted_issuers: &accepted_issuers, + accepted_profiles: &accepted_profiles, + issuers: &runtime.credential_issuers, + }; + let input = held_email::read_presentation(presentation).map_err(held_refusal)?; + let pre = held_email::precheck(&input, &view).map_err(held_refusal)?; + if consume { + let spent = held_email::consume_nonce( + &runtime.conn, + &held.audience, + &pre.nonce, + &pre.account_key, + context.now, + ) + .await + .map_err(db_error)?; + if !spent { + return Err((Status::Forbidden, "nonce-replayed".into())); + } + } + let verified = held_email::verify(&input, &pre, &view).map_err(held_refusal)?; + requirement_claims_satisfied(requirement, &verified.claims)?; + let sd_jwt_digest = Sha256::digest(input.sd_jwt.as_bytes()); + let credential_expires_at = OffsetDateTime::from_unix_timestamp(verified.expires_at) + .map_err(|_| (Status::Forbidden, "credential-expiry-invalid".to_owned()))?; + Ok(CredentialAdmission { + claim_jti: presentation_replay_key(held_email::PROFILE, context.recipient_did, &pre.nonce), + credential_id: verified.credential_id, + presentation_jti: Some(pre.nonce.clone()), + credential_digest: encode_config(sd_jwt_digest, URL_SAFE_NO_PAD), + envelope_digest_hex: hex::encode(sd_jwt_digest), + presentation_digest_hex: hex::encode(Sha256::digest(canonical_json_value(presentation))), + credential_space_owner_did: None, + credential_expires_at: Some(credential_expires_at), }) } +/// The held email row pins `maxAgeSeconds` to exactly 31 536 000 so requirement +/// digests stay stable. The value never shortens a credential's life, so any +/// other value, including an absent one, is refused rather than enforced. +fn held_email_max_age_pinned(requirement: &Value) -> Result<(), (Status, String)> { + if requirement.get("maxAgeSeconds").and_then(Value::as_i64) == Some(HELD_EMAIL_MAX_AGE_SECONDS) + { + Ok(()) + } else { + Err(( + Status::Forbidden, + "credential-requirement-invalid".to_owned(), + )) + } +} + +fn held_refusal(code: held_email::Refusal) -> (Status, String) { + let status = if code == held_email::BAD_CONFIG { + Status::InternalServerError + } else { + Status::Forbidden + }; + (status, code.into()) +} + +fn requirement_claims_satisfied( + requirement: &Value, + disclosed: &std::collections::BTreeMap, +) -> Result<(), (Status, String)> { + let claims = requirement + .get("claims") + .and_then(Value::as_object) + .ok_or((Status::Forbidden, "credential-requirement-invalid".into()))?; + for (name, expected) in claims { + let expected = expected + .as_str() + .ok_or((Status::Forbidden, "credential-requirement-invalid".into()))?; + if disclosed.get(name).map(String::as_str) != Some(expected) { + return Err(( + Status::Forbidden, + "credential-requirement-not-satisfied".into(), + )); + } + } + for name in disclosed.keys() { + if !claims.contains_key(name) { + return Err(( + Status::Forbidden, + "credential-requirement-not-satisfied".into(), + )); + } + } + Ok(()) +} + fn presentation_replay_key(schema: &str, holder_did: &str, presentation_jti: &str) -> String { let value = serde_json::json!({ "schema": schema, @@ -6366,12 +6601,12 @@ fn verify_issuer_signature( message: &[u8], signature: &[u8], ) -> Result<(), (Status, String)> { - let key = JWK::from(Params::OKP(OctetParams { - curve: "Ed25519".to_owned(), - public_key: Base64urlUInt(public_key.to_vec()), - private_key: None, - })); - tinycloud_auth::ssi::claims::jws::verify_bytes(Algorithm::EdDSA, message, &key, signature) + let verifying_key = ed25519_dalek::VerifyingKey::from_bytes(public_key) + .map_err(|_| (Status::Forbidden, "credential-signature-invalid".into()))?; + let signature = ed25519_dalek::Signature::from_slice(signature) + .map_err(|_| (Status::Forbidden, "credential-signature-invalid".into()))?; + verifying_key + .verify_strict(message, &signature) .map_err(|_| (Status::Forbidden, "credential-signature-invalid".into())) } @@ -6394,6 +6629,7 @@ fn evaluate_current_allow( legacy_claim: Option<&Value>, presentation: &Value, context: &CurrentAllowContext<'_>, + check_presentation_capabilities: bool, ) -> Result { let CurrentAllowContext { challenge, @@ -6426,7 +6662,10 @@ fn evaluate_current_allow( return Err((Status::Forbidden, "policy-evaluator-denied".into())); } } - let mut capability_sources = vec![(presentation, "presentation-capabilities-mismatch")]; + let mut capability_sources = Vec::new(); + if check_presentation_capabilities { + capability_sources.push((presentation, "presentation-capabilities-mismatch")); + } if let Some(claim) = legacy_claim { capability_sources.push((claim, "claim-capabilities-mismatch")); } @@ -6499,6 +6738,191 @@ fn db_error(error: impl std::fmt::Display) -> (Status, String) { #[cfg(test)] mod tests { + #[test] + fn held_email_max_age_is_pinned_to_the_row_value() { + let pinned = |seconds: serde_json::Value| { + held_email_max_age_pinned(&serde_json::json!({"maxAgeSeconds": seconds})) + }; + assert!(pinned(serde_json::json!(31_536_000)).is_ok()); + assert!(pinned(serde_json::json!(60)).is_err()); + assert!(pinned(serde_json::json!(300)).is_err()); + assert!(held_email_max_age_pinned(&serde_json::json!({})).is_err()); + } + + #[test] + fn v3_issuer_signature_refuses_small_order_key_and_r() { + use ed25519_dalek::Verifier; + // Identity point encoding (y = 1, x = 0) as both public key and R with S = 0. + // Non-strict verification accepts this forgery; verify_strict must refuse it. + let mut identity = [0u8; 32]; + identity[0] = 1; + let mut forged = [0u8; 64]; + forged[..32].copy_from_slice(&identity); + let weak_key = ed25519_dalek::VerifyingKey::from_bytes(&identity).unwrap(); + let weak_sig = ed25519_dalek::Signature::from_slice(&forged).unwrap(); + assert!(weak_key.verify(b"held", &weak_sig).is_ok()); + assert_eq!( + super::verify_issuer_signature(&identity, b"held", &forged) + .unwrap_err() + .1, + "credential-signature-invalid" + ); + let signing = ed25519_dalek::SigningKey::from_bytes(&[9u8; 32]); + let good = ed25519_dalek::Signer::sign(&signing, b"held").to_bytes(); + assert!( + super::verify_issuer_signature(signing.verifying_key().as_bytes(), b"held", &good) + .is_ok() + ); + } + + #[test] + fn v3_issuer_signature_refuses_non_canonical_s_at_group_order() { + // Identity point as key and R, with S = L (the group order), little-endian. + // S >= L is non-canonical; verify_strict must refuse it. + let mut identity = [0u8; 32]; + identity[0] = 1; + let group_order_le: [u8; 32] = [ + 0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, + 0xde, 0x14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10, + ]; + let mut forged = [0u8; 64]; + forged[..32].copy_from_slice(&identity); + forged[32..].copy_from_slice(&group_order_le); + assert_eq!( + super::verify_issuer_signature(&identity, b"held", &forged) + .unwrap_err() + .1, + "credential-signature-invalid" + ); + } + + #[test] + fn v3_issuer_signature_refuses_real_key_with_s_plus_group_order() { + // A valid signature with S replaced by S + L (same scalar mod L, non-canonical). + // Uses a real key so the S >= L check is exercised on a genuine signature. + const GROUP_ORDER_LE: [u8; 32] = [ + 0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, + 0xde, 0x14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10, + ]; + let signing = ed25519_dalek::SigningKey::from_bytes(&[9u8; 32]); + let public = *signing.verifying_key().as_bytes(); + let good = ed25519_dalek::Signer::sign(&signing, b"held").to_bytes(); + assert!(super::verify_issuer_signature(&public, b"held", &good).is_ok()); + let mut malleated = good; + let mut carry = 0u16; + for i in 0..32 { + let sum = good[32 + i] as u16 + GROUP_ORDER_LE[i] as u16 + carry; + malleated[32 + i] = sum as u8; + carry = sum >> 8; + } + assert_eq!(carry, 0, "S + L must fit in 32 bytes"); + assert_ne!(malleated, good); + assert_eq!( + super::verify_issuer_signature(&public, b"held", &malleated) + .unwrap_err() + .1, + "credential-signature-invalid" + ); + } + + #[tokio::test] + async fn held_credentials_are_off_unless_enabled_with_a_valid_audience() { + use crate::config::HeldCredentialsConfig; + let conn = tinycloud_core::sea_orm::Database::connect("sqlite::memory:") + .await + .unwrap(); + let runtime = || { + super::PolicyV3Runtime::new( + conn.clone(), + "did:key:z6MkNodeTestOnly", + StaticSecret::new(vec![7; 32]).unwrap(), + ) + }; + let off = runtime() + .with_held_credentials(&HeldCredentialsConfig { + enabled: false, + audience: None, + }) + .unwrap(); + assert!(off.held_credentials.is_none()); + let missing = runtime().with_held_credentials(&HeldCredentialsConfig { + enabled: true, + audience: None, + }); + assert!(missing.is_err()); + let malformed = runtime().with_held_credentials(&HeldCredentialsConfig { + enabled: true, + audience: Some("not a host".to_owned()), + }); + assert!(malformed.is_err()); + let on = runtime() + .with_held_credentials(&HeldCredentialsConfig { + enabled: true, + audience: Some("relying-party.example".to_owned()), + }) + .unwrap(); + assert_eq!( + on.held_credentials + .as_ref() + .map(|held| held.audience.as_str()), + Some("relying-party.example") + ); + } + + #[test] + fn malformed_account_owner_maps_to_forbidden_not_internal_error() { + let (status, body) = super::held_refusal(crate::held_email::ACCOUNT_OWNER_INVALID); + assert_eq!(status, rocket::http::Status::Forbidden); + assert_eq!(body, "account-owner-invalid"); + let (status, _) = super::held_refusal(crate::held_email::BAD_CONFIG); + assert_eq!(status, rocket::http::Status::InternalServerError); + } + + #[test] + fn held_requirement_claims_must_match_the_disclosed_values() { + let requirement = serde_json::json!({"claims": {"email": "alice@example.com"}}); + let disclosed = |email: &str| { + std::collections::BTreeMap::from([("email".to_owned(), email.to_owned())]) + }; + assert!( + super::requirement_claims_satisfied(&requirement, &disclosed("alice@example.com")) + .is_ok() + ); + // Reviewer repro: a bob@other.example credential must not admit alice@example.com. + assert_eq!( + super::requirement_claims_satisfied(&requirement, &disclosed("bob@other.example")) + .unwrap_err() + .1, + "credential-requirement-not-satisfied" + ); + assert!(super::requirement_claims_satisfied( + &requirement, + &std::collections::BTreeMap::new() + ) + .is_err()); + } + + #[test] + fn held_disclosures_beyond_the_requirement_are_refused() { + let requirement = serde_json::json!({"claims": {"emailDomain": "example.com"}}); + let disclosed = std::collections::BTreeMap::from([ + ("email".to_owned(), "alice@example.com".to_owned()), + ("emailDomain".to_owned(), "example.com".to_owned()), + ]); + // Requirement asks only for the domain; disclosing the full email is refused. + assert_eq!( + super::requirement_claims_satisfied(&requirement, &disclosed) + .unwrap_err() + .1, + "credential-requirement-not-satisfied" + ); + let domain_only = std::collections::BTreeMap::from([( + "emailDomain".to_owned(), + "example.com".to_owned(), + )]); + assert!(super::requirement_claims_satisfied(&requirement, &domain_only).is_ok()); + } + #[tokio::test] async fn policy_registration_refuses_both_local_web_roots_before_resolution() { use crate::did_resolution_test_support::*; @@ -6905,6 +7329,12 @@ mod tests { let mut untrusted_signer = original.clone(); untrusted_signer["signature"]["signerDid"] = json!("did:key:zUntrustedSigner"); assert!(validate(&untrusted_signer).is_err()); + let mut non_array = original.clone(); + non_array["requestedCapabilities"] = json!("not-an-array"); + assert_eq!( + validate(&non_array).unwrap_err().1, + "presentation-capabilities-mismatch" + ); assert!(validate(&original).is_ok()); } @@ -7096,6 +7526,7 @@ mod tests { issued, header, projection["issuerKid"].clone(), + "opencredentials.email/v1", ) } @@ -7112,6 +7543,7 @@ mod tests { issued: OffsetDateTime, header: Value, envelope_kid: Value, + vct: &str, ) -> Value { let disclose = |salt: &str, name: &str, value: &str| { encode_config( @@ -7128,7 +7560,7 @@ mod tests { let payload = json!({ "iss": projection["issuerDid"], "sub": holder, "iat": issued.unix_timestamp(), "nbf": issued.unix_timestamp(), "exp": expires.unix_timestamp(), - "jti": "credential-email-domain", "vct": "opencredentials.email/v1", + "jti": "credential-email-domain", "vct": vct, "profile": projection["profile"]["id"], "profileVersion": 1, "descriptorDigest": projection["descriptorDigest"], "holderBinding": {"did": holder, "signingDomain": "tinycloud.credentials/holder-binding/v1"}, @@ -7233,6 +7665,7 @@ mod tests { self.issued, header, json!(envelope_kid), + "opencredentials.email/v1", ) } } @@ -7390,6 +7823,44 @@ mod tests { assert!(fixture.verify(&other, &legacy).is_err()); } + #[test] + fn kidless_header_is_refused_for_a_configured_entry_in_the_combined_set() { + // TC-1541 item 1: legacy issuer and configured list share one set. A + // header without `kid` must not vouch for a configured entry, but the + // legacy entry keeps accepting one. + let (configured_key, legacy_key) = (keypair(), keypair()); + let configured_kid = format!("{ORG_A}#issuing-1"); + let legacy_kid = format!("{ORG_A}#controller"); + let legacy = IssuerKey::new( + ORG_A, + "opencredentials.email/v1", + 1, + legacy_kid.clone(), + legacy_key.public().to_bytes(), + ); + let set = IssuerSet::load_with_legacy( + &[issuer_config(ORG_A, "issuing-1", &configured_key)], + Some(&legacy), + ) + .unwrap(); + let unpinned = SetFixture::new(ORG_A, None, DOMAIN_PROFILE); + let bare = json!({"alg": "EdDSA", "typ": "vc+sd-jwt"}); + let kidless = unpinned.mint(&configured_key, bare, &configured_kid); + assert_eq!( + unpinned.verify(&kidless, &set).err(), + forbidden("credential-signature-invalid") + ); + // The same credential carrying its kid verifies, so the refusal is the + // missing header kid and nothing else. + let with_kid = json!({"alg": "EdDSA", "typ": "vc+sd-jwt", "kid": configured_kid}); + let keyed = unpinned.mint(&configured_key, with_kid, &configured_kid); + assert!(unpinned.verify(&keyed, &set).is_ok()); + let legacy_fixture = SetFixture::new(ORG_A, Some(&legacy_kid), DOMAIN_PROFILE); + let legacy_bare = json!({"alg": "EdDSA", "typ": "vc+sd-jwt"}); + let legacy_credential = legacy_fixture.mint(&legacy_key, legacy_bare, &legacy_kid); + assert!(legacy_fixture.verify(&legacy_credential, &set).is_ok()); + } + #[test] fn issuer_set_with_two_issuers_keeps_each_org_to_its_own_policies() { let (key_a, key_b) = (keypair(), keypair()); @@ -7774,6 +8245,73 @@ mod tests { assert!(validate_request_local_requirement(&substituted, projection).is_err()); } + #[test] + fn signed_vct_other_than_the_requirement_credential_type_is_refused() { + let requirement = json!({ + "type": "TinyCloudCredentialRequirement", "version": 1, + "profile": {"id": "tinycloud.email-domain-proof/v1", "version": 1}, + "credentialType": {"id": "opencredentials.email/v1", "version": 1}, + "claims": {"emailDomain": "tinycloud.xyz"}, + "maxAgeSeconds": 300 + }); + let projection_value = json!({ + "type": POLICY_CREDENTIAL_REQUIREMENT_V1, "version": 1, + "requirementDigest": canonical_digest_base64url(&requirement), + "descriptorDigest": "DdDdDdDdDdDdDdDdDdDdDdDdDdDdDdDdDdDdDdDdDdD", + "issuerDid": "did:web:issuer.credentials.org", + "issuerKid": "did:web:issuer.credentials.org#controller", + "profile": {"id": "tinycloud.email-domain-proof/v1", "version": 1}, + "credentialType": {"id": "opencredentials.email/v1", "version": 1} + }); + let projection = validate_policy_credential_requirement(&projection_value).unwrap(); + let holder = "did:key:z6MkehRgf7yJbgaGfYsdoAsKdBPE3dj2CYhowQdcjqSJgvVd"; + let issuer_key = tinycloud_core::libp2p::identity::ed25519::Keypair::generate(); + let trusted = IssuerKey::new( + "did:web:issuer.credentials.org", + "opencredentials.email/v1", + 1, + "did:web:issuer.credentials.org#controller", + issuer_key.public().to_bytes(), + ); + let issued = parse_time("2026-09-25T12:00:00Z").unwrap(); + let now = issued + Duration::seconds(30); + let verify = |credential: &Value| { + verify_opencredentials_credential( + credential, + &requirement, + projection, + &IssuerSet::from_legacy(&trusted), + holder, + now, + ) + }; + // Only the issuer-signed `vct` differs. The signature and disclosure + // digests stay valid, so the refusal must come from the disclosed + // `vct` comparison against the requirement's credential type. + let mint = |vct: &str| { + email_domain_credential_with_header( + &issuer_key, + &projection_value, + holder, + "alice@tinycloud.xyz", + "tinycloud.xyz", + "tinycloud.xyz", + issued, + json!({"alg": "EdDSA", "typ": "vc+sd-jwt", "kid": projection_value["issuerKid"]}), + projection_value["issuerKid"].clone(), + vct, + ) + }; + assert!(verify(&mint("opencredentials.email/v1")).is_ok()); + assert_eq!( + verify(&mint("opencredentials.phone/v1")).err(), + Some(( + Status::Forbidden, + "credential-holder-binding-invalid".into() + )) + ); + } + #[test] fn wrong_issuer_holder_and_malformed_or_untrusted_evidence_are_denied() { let vector: Value = serde_json::from_str(include_str!( @@ -8206,6 +8744,7 @@ mod tests { &at(7200), policy, account.map(|seconds| now + Duration::seconds(seconds)), + None, ) }; // Older clients send nothing and keep the 60-second session. @@ -8243,6 +8782,30 @@ mod tests { } } + #[test] + fn session_expiry_never_outlives_the_held_credential() { + let now = parse_time("2026-10-01T12:00:00Z").unwrap(); + let requested = format_time(now + Duration::seconds(3600)); + let root = format_time(now + Duration::seconds(7200)); + let credential = now + Duration::seconds(120); + assert_eq!( + session_expiry( + now, + Some(requested.as_str()), + &root, + None, + None, + Some(credential) + ) + .unwrap(), + credential + ); + assert_eq!( + session_expiry(now, Some(requested.as_str()), &root, None, None, None).unwrap(), + now + Duration::seconds(3600) + ); + } + #[test] fn v3_delivery_admits_any_mailbox_at_exactly_the_matched_domain() { let (owner, registration, delivery, mut request) = delivery_fixture(); @@ -8817,6 +9380,50 @@ mod tests { admission.credential_space_owner_did.as_deref(), Some(account_owner_did.as_str()) ); + let mut non_array_capabilities = presentation.clone(); + non_array_capabilities["requestedCapabilities"] = json!("not-an-array"); + let refusal = validate_credential_admission_v3( + &requirement, + &credential, + &non_array_capabilities, + &policy, + &ClaimPresentationContext { + challenge_id, + nonce, + policy_cid: presentation["policyCid"].as_str().unwrap(), + owner_did: policy["ownerDid"].as_str().unwrap(), + recipient_did: holder_did.as_str(), + authenticated_account_owner: Some(&account_owner_did), + now, + }, + &runtime, + presentation["requestedCapabilities"].as_array().unwrap(), + ); + assert_eq!( + refusal.err().map(|(_, error)| error).as_deref(), + Some("presentation-capabilities-mismatch") + ); + let refusal = validate_credential_admission_v3( + &requirement, + &credential, + &presentation, + &policy, + &ClaimPresentationContext { + challenge_id, + nonce, + policy_cid: presentation["policyCid"].as_str().unwrap(), + owner_did: policy["ownerDid"].as_str().unwrap(), + recipient_did: holder_did.as_str(), + authenticated_account_owner: Some(&account_owner_did), + now, + }, + &runtime, + &[], + ); + assert_eq!( + refusal.err().map(|(_, error)| error).as_deref(), + Some("credential-presentation-binding-invalid") + ); let binding_material = json!({"enforcerDid": enforcer_did, "nodeAudience": runtime.node_did}); @@ -10752,3 +11359,11 @@ mod test_harness; #[cfg(test)] #[path = "policy_v3/root_revocation_tests.rs"] mod root_revocation_tests; + +#[cfg(test)] +#[path = "policy_v3/held_route_tests.rs"] +mod held_route_tests; + +#[cfg(test)] +#[path = "policy_v3/held_fixtures.rs"] +mod held_fixtures; diff --git a/tinycloud-node-server/src/policy_v3/held_fixtures.rs b/tinycloud-node-server/src/policy_v3/held_fixtures.rs new file mode 100644 index 00000000..b77829d7 --- /dev/null +++ b/tinycloud-node-server/src/policy_v3/held_fixtures.rs @@ -0,0 +1,363 @@ +//! Real-time held-credential fixtures for the mint-path tests in +//! `held_route_tests.rs`. +//! +//! The checked-in held vector is pinned to 2026-01-01, so these fixtures build +//! their SD-JWT, SIWE message, and account authorization at the server's +//! current time. The SD-JWT is signed with the harness issuer key that the held +//! issuer config pins. The account authorization follows the v2 `/delegate` +//! flow, and the account owner uses the same fixed secret as that flow. + +use super::test_harness::*; +use super::*; +use rocket::http::{ContentType, Status}; +use serde_json::{json, Value}; +use sha3::Keccak256; +use time::{Duration, OffsetDateTime}; +use tinycloud_auth::{ + authorization::HeaderEncode, + cacaos::{ + siwe::{encode_eip55, Message, Version}, + siwe_cacao::{Header as SiweHeader, Signature as SiweSignature, SiweCacao}, + }, + siwe_recap::{Ability as RecapAbility, Capability as RecapCapability}, +}; +use tinycloud_core::{models::space, sea_orm::ActiveValue::Set, types::SpaceIdWrap}; + +const HELD_EMAIL: &str = "alice@example.test"; +const HELD_PROFILE: &str = "tinycloud.email-held/v1"; +pub(super) const HELD_VCT: &str = "opencredentials.email/v1"; +const HELD_AUDIENCE: &str = "relying-party.example"; +const HELD_STATEMENT: &str = "Present a TinyCloud held credential"; +const BINDING_DOMAIN: &str = "tinycloud.credentials/account-binding/v1"; + +/// Secret for the account owner. The v2 flow uses the same key, so the account +/// DID here matches the owner the account authorization is issued for. +const ACCOUNT_SECRET: [u8; 32] = [0x47; 32]; + +/// Process-unique serial. Nonces and credential `jti` values derive from it, so +/// every presentation a test builds is distinct. +fn serial() -> u64 { + static NEXT: std::sync::atomic::AtomicU64 = std::sync::atomic::AtomicU64::new(1); + NEXT.fetch_add(1, std::sync::atomic::Ordering::Relaxed) +} + +/// A SIWE nonce: alphanumeric and at least 22 characters. +pub(super) fn held_nonce() -> String { + format!("heldnonce{:012}{:08}", std::process::id(), serial()) +} + +fn held_jti() -> String { + format!("urn:uuid:00000000-0000-4000-8000-{:012x}", serial()) +} + +fn b64(bytes: &[u8]) -> String { + base64::encode_config(bytes, base64::URL_SAFE_NO_PAD) +} + +fn disclosure(salt: &str, name: &str, value: &str) -> String { + b64(json!([salt, name, value]).to_string().as_bytes()) +} + +/// The account `did:pkh` and its EIP-55 address. +pub(super) struct HeldAccount { + key: k256::ecdsa::SigningKey, + address: [u8; 20], + pub(super) did: String, +} + +impl HeldAccount { + pub(super) fn new() -> anyhow::Result { + let key = k256::ecdsa::SigningKey::from_bytes(&ACCOUNT_SECRET.into())?; + let public = key.verifying_key().to_encoded_point(false); + let digest = Keccak256::digest(&public.as_bytes()[1..]); + let address: [u8; 20] = digest[12..].try_into()?; + let did = format!("did:pkh:eip155:1:0x{}", encode_eip55(&address)); + Ok(Self { key, address, did }) + } + + fn address(&self) -> String { + format!("0x{}", encode_eip55(&self.address)) + } +} + +fn eip191_sign(key: &k256::ecdsa::SigningKey, message: &str) -> anyhow::Result { + let prefixed = format!("\x19Ethereum Signed Message:\n{}{}", message.len(), message); + let digest = Keccak256::digest(prefixed.as_bytes()); + let (signature, recovery) = key.sign_prehash_recoverable(&digest)?; + let mut bytes = signature.to_bytes().to_vec(); + bytes.push(recovery.to_byte() + 27); + Ok(format!("0x{}", hex::encode(bytes))) +} + +pub(super) struct HeldPresentation { + pub(super) sd_jwt: String, + pub(super) message: String, + pub(super) signature: String, +} + +/// Builds an SD-JWT that discloses only `email`, plus a SIWE message whose +/// `Resources` entry binds the SD-JWT. The credential is valid from one minute +/// before now until `lifetime_seconds` from now. +pub(super) fn held_presentation( + h: &Harness, + account: &HeldAccount, + nonce: &str, + lifetime_seconds: i64, + vct: &str, +) -> anyhow::Result { + let now_unix = now().unix_timestamp(); + let issued = now_unix - 60; + let issuer_did = h.vector["policyProjection"]["issuerDid"] + .as_str() + .expect("vector issuerDid") + .to_owned(); + let kid = h.vector["policyProjection"]["issuerKid"].clone(); + let disclosures = vec![disclosure( + &format!("salt{}", serial()), + "email", + HELD_EMAIL, + )]; + let digests: Vec = disclosures + .iter() + .map(|d| b64(&Sha256::digest(d.as_bytes()))) + .collect(); + let header = json!({"alg": "EdDSA", "typ": "vc+sd-jwt", "kid": kid}); + let payload = json!({ + "iss": issuer_did, + "sub": account.did, + "iat": issued, + "nbf": issued, + "exp": now_unix + lifetime_seconds, + "jti": held_jti(), + "vct": vct, + "profile": HELD_PROFILE, + "profileVersion": 1, + "holderBinding": {"did": account.did, "signingDomain": BINDING_DOMAIN}, + "status": {"method": "none"}, + "_sd_alg": "sha-256", + "_sd": digests, + }); + let signing_input = format!( + "{}.{}", + b64(header.to_string().as_bytes()), + b64(payload.to_string().as_bytes()) + ); + let signature = h.issuer.sign(signing_input.as_bytes()); + let mut sd_jwt = format!("{signing_input}.{}~", b64(&signature)); + for disclosure in &disclosures { + sd_jwt.push_str(disclosure); + sd_jwt.push('~'); + } + let message = [ + format!("{HELD_AUDIENCE} wants you to sign in with your Ethereum account:"), + account.address(), + String::new(), + HELD_STATEMENT.to_owned(), + String::new(), + format!("URI: https://{HELD_AUDIENCE}"), + "Version: 1".to_owned(), + "Chain ID: 1".to_owned(), + format!("Nonce: {nonce}"), + format!("Issued At: {}", format_time(now())), + "Resources:".to_owned(), + format!( + "- urn:tinycloud:sd-hash:{}", + b64(&Sha256::digest(sd_jwt.as_bytes())) + ), + ] + .join("\n"); + let signature = eip191_sign(&account.key, &message)?; + Ok(HeldPresentation { + sd_jwt, + message, + signature, + }) +} + +/// A presentation whose SIWE nonce is recorded as outstanding in the app's own +/// store. The production writer is not wired while the flag is off, so the +/// test writes the row the way a future mint slice would. +pub(super) async fn outstanding_presentation( + h: &Harness, + account: &HeldAccount, + lifetime_seconds: i64, +) -> anyhow::Result { + outstanding_presentation_with_vct(h, account, lifetime_seconds, HELD_VCT).await +} + +/// Same as [`outstanding_presentation`], with the disclosed `vct` set to `vct`. +pub(super) async fn outstanding_presentation_with_vct( + h: &Harness, + account: &HeldAccount, + lifetime_seconds: i64, + vct: &str, +) -> anyhow::Result { + let nonce = held_nonce(); + crate::held_email::record_nonce( + &h.client.rocket().state::().unwrap().conn, + HELD_AUDIENCE, + &nonce, + // The consume check keys on `Pkh::canonical`, which is lowercase. + &account.did.to_ascii_lowercase(), + now().unix_timestamp() + 86_400, + ) + .await?; + held_presentation(h, account, &nonce, lifetime_seconds, vct) +} + +/// Imports the account's SDK session CACAO through `/delegate`, inserts the +/// credentials space row, and returns the stored CID and the space it authorizes. +pub(super) async fn import_account_authorization( + h: &Harness, + account: &HeldAccount, +) -> anyhow::Result<(String, String)> { + let credentials_space = SpaceId::new(account.did.parse::()?, "credentials".parse()?); + let now = OffsetDateTime::now_utc().replace_nanosecond(0)?; + let issued = now - Duration::seconds(5); + let expires = now + Duration::seconds(600); + let mut recap = RecapCapability::::new(); + let credential_namespace = + credentials_space + .clone() + .to_resource("kv".parse()?, Some("v1/".parse()?), None, None); + for ability in ["tinycloud.kv/get", "tinycloud.kv/put"] { + recap.with_action( + credential_namespace.as_uri(), + ability.parse::()?, + [std::collections::BTreeMap::::new()], + ); + } + let account_message = recap.build_message(Message { + scheme: Some("https".parse()?), + domain: "tinycloud.test".parse()?, + address: account.address, + statement: None, + uri: h.holder.did().parse()?, + version: Version::V1, + chain_id: 1, + nonce: held_nonce(), + issued_at: issued.into(), + expiration_time: Some(expires.into()), + not_before: None, + request_id: None, + resources: vec![], + })?; + let (signature, recovery_id) = account + .key + .sign_prehash_recoverable(&account_message.eip191_hash()?)?; + let mut signature_bytes = [0_u8; 65]; + signature_bytes[..64].copy_from_slice(signature.to_bytes().as_ref()); + signature_bytes[64] = u8::from(recovery_id) + 27; + let authorization = TinyCloudDelegation::Cacao(Box::new(SiweCacao::new( + account_message.into(), + SiweSignature::from(signature_bytes), + SiweHeader, + ))) + .encode()?; + let response = h + .client + .post("/delegate") + .header(rocket::http::Header::new("Authorization", authorization)) + .dispatch() + .await; + let status = response.status(); + let body = response.into_string().await.unwrap_or_default(); + anyhow::ensure!(status == Status::Ok, "account /delegate: {status} {body}"); + let account_cid: tinycloud_auth::ipld_core::cid::Cid = serde_json::from_str::(&body)? + ["cid"] + .as_str() + .ok_or_else(|| anyhow::anyhow!("missing account delegation cid"))? + .parse()?; + h.client + .rocket() + .state::() + .unwrap() + .load_signed_delegation(account_cid) + .await + .map_err(anyhow::Error::msg)? + .ok_or_else(|| anyhow::anyhow!("missing stored account authorization"))?; + space::ActiveModel { + id: Set(SpaceIdWrap(credentials_space.clone())), + } + .insert(&h.client.rocket().state::().unwrap().conn) + .await?; + Ok((account_cid.to_string(), credentials_space.to_string())) +} + +/// The held requirement the policy is registered against and the mint sends. +pub(super) fn held_requirement() -> Value { + json!({ + "type": "TinyCloudCredentialRequirement", + "version": 1, + "profile": {"id": HELD_PROFILE, "version": 1}, + "credentialType": {"id": HELD_VCT, "version": 1}, + "claims": {"email": HELD_EMAIL}, + "maxAgeSeconds": HELD_EMAIL_MAX_AGE_SECONDS, + }) +} + +fn held_projection(h: &Harness, requirement: &Value) -> Value { + json!({ + "type": "TinyCloudPolicyCredentialRequirement", + "version": 1, + "requirementDigest": canonical_digest_base64url(requirement), + "descriptorDigest": h.vector["policyProjection"]["descriptorDigest"], + "issuerDid": h.vector["policyProjection"]["issuerDid"], + "issuerKid": h.vector["policyProjection"]["issuerKid"], + "profile": {"id": HELD_PROFILE, "version": 1}, + "credentialType": {"id": HELD_VCT, "version": 1}, + }) +} + +/// Registers a policy whose credential requirement is the held requirement. +/// The vector projection cannot be reused: it pins the v3 profile. +pub(super) async fn register_held(h: &Harness) -> anyhow::Result { + let projection = held_projection(h, &held_requirement()); + let (status, body, registered) = h + .register_with_projection(policy_window(), projection) + .await?; + anyhow::ensure!(status == Status::Ok, "register held: {status} {body}"); + Ok(registered) +} + +/// Mints through `POST /policy/v3/delegations` with a fresh challenge. The body +/// has no `credential` field, which is the held shape. +pub(super) async fn mint_held( + h: &Harness, + policy: &Registered, + presentation: &HeldPresentation, + account_cid: &str, + credential_space: &str, + requested_expires_at: &str, +) -> anyhow::Result<(Status, String)> { + let (status, body) = h.challenge(policy).await; + anyhow::ensure!(status == Status::Ok, "challenge: {status} {body}"); + let challenge: Value = serde_json::from_str(&body)?; + let response = h + .client + .post("/policy/v3/delegations") + .header(ContentType::JSON) + .body( + json!({ + "policyCid": policy.policy_cid, + "challengeId": challenge["challengeId"], + "nonce": challenge["nonce"], + "requirement": held_requirement(), + "presentation": { + "sdJwt": presentation.sd_jwt, + "siwe": { + "message": presentation.message, + "signature": presentation.signature, + }, + }, + "accountAuthorizationCid": account_cid, + "credentialSpaceId": credential_space, + "requestedExpiresAt": requested_expires_at, + }) + .to_string(), + ) + .dispatch() + .await; + let status = response.status(); + Ok((status, response.into_string().await.unwrap_or_default())) +} diff --git a/tinycloud-node-server/src/policy_v3/held_route_tests.rs b/tinycloud-node-server/src/policy_v3/held_route_tests.rs new file mode 100644 index 00000000..12f0fb74 --- /dev/null +++ b/tinycloud-node-server/src/policy_v3/held_route_tests.rs @@ -0,0 +1,234 @@ +//! Held-credential admission through the real `POST /policy/v3/delegations` +//! route. The default harness keeps the held flag off: a held presentation must +//! be refused by the flag gate before the verifier runs and before any nonce is +//! spent. `Harness::new_with_held` turns the flag on for the request-shape tests. + +use super::held_fixtures::*; +use super::test_harness::*; +use super::*; + +async fn held_presentation_is_refused_while_the_flag_is_off( + backend: Backend, +) -> anyhow::Result<()> { + let Some(h) = Harness::new( + backend, + Shape::KeySession, + "held_presentation_is_refused_while_the_flag_is_off", + ) + .await? + else { + return Ok(()); + }; + h.grant_owner(Window::until(now() + Duration::days(2))) + .await?; + let policy = h.register_ok(policy_window()).await?; + let (status, body) = h.mint_held_presentation(&policy).await?; + assert_eq!(status, Status::Forbidden, "{body}"); + assert!(body.contains("held-credentials-disabled"), "{body}"); + Ok(()) +} + +async fn held_request_with_a_credential_field_is_refused_by_the_shape_gate( + backend: Backend, +) -> anyhow::Result<()> { + let Some(h) = Harness::new_with_held( + backend, + Shape::KeySession, + "held_request_with_a_credential_field_is_refused_by_the_shape_gate", + true, + ) + .await? + else { + return Ok(()); + }; + h.grant_owner(Window::until(now() + Duration::days(2))) + .await?; + let policy = register_held(&h).await?; + let (status, body) = h.mint_held_with_credential(&policy).await?; + assert_eq!(status, Status::BadRequest, "{body}"); + assert!( + body.contains("credential-admission-request-invalid"), + "{body}" + ); + Ok(()) +} + +on_both_backends!(held_request_with_a_credential_field_is_refused_by_the_shape_gate); + +on_both_backends!(held_presentation_is_refused_while_the_flag_is_off); + +async fn held_mint_admits_once_and_returns_an_authorization( + backend: Backend, +) -> anyhow::Result<()> { + let Some(h) = Harness::new_with_held( + backend, + Shape::KeySession, + "held_mint_admits_once_and_returns_an_authorization", + true, + ) + .await? + else { + return Ok(()); + }; + h.grant_owner(Window::until(now() + Duration::days(2))) + .await?; + let account = HeldAccount::new()?; + let (account_cid, space) = import_account_authorization(&h, &account).await?; + let policy = register_held(&h).await?; + let presentation = outstanding_presentation(&h, &account, 86_400).await?; + let requested = format_time(now() + Duration::seconds(3600)); + let (status, body) = + mint_held(&h, &policy, &presentation, &account_cid, &space, &requested).await?; + assert_eq!(status, Status::Ok, "{body}"); + let json: Value = serde_json::from_str(&body)?; + assert!( + json["authorization"] + .as_str() + .is_some_and(|token| token.split('.').count() == 3), + "{body}" + ); + Ok(()) +} + +async fn held_nonce_cannot_be_replayed_with_a_fresh_challenge( + backend: Backend, +) -> anyhow::Result<()> { + let Some(h) = Harness::new_with_held( + backend, + Shape::KeySession, + "held_nonce_cannot_be_replayed_with_a_fresh_challenge", + true, + ) + .await? + else { + return Ok(()); + }; + h.grant_owner(Window::until(now() + Duration::days(2))) + .await?; + let account = HeldAccount::new()?; + let (account_cid, space) = import_account_authorization(&h, &account).await?; + let policy = register_held(&h).await?; + let presentation = outstanding_presentation(&h, &account, 86_400).await?; + let requested = format_time(now() + Duration::seconds(3600)); + let (first, body) = + mint_held(&h, &policy, &presentation, &account_cid, &space, &requested).await?; + assert_eq!(first, Status::Ok, "{body}"); + // Same SIWE nonce, new challenge: the nonce is the single-use key. + let (second, body) = + mint_held(&h, &policy, &presentation, &account_cid, &space, &requested).await?; + assert_eq!(second, Status::Forbidden, "{body}"); + assert!(body.contains("nonce-replayed"), "{body}"); + Ok(()) +} + +async fn held_session_expiry_is_clamped_to_the_credential_expiry( + backend: Backend, +) -> anyhow::Result<()> { + let Some(h) = Harness::new_with_held( + backend, + Shape::KeySession, + "held_session_expiry_is_clamped_to_the_credential_expiry", + true, + ) + .await? + else { + return Ok(()); + }; + h.grant_owner(Window::until(now() + Duration::days(2))) + .await?; + let account = HeldAccount::new()?; + let (account_cid, space) = import_account_authorization(&h, &account).await?; + let policy = register_held(&h).await?; + let issued_at = now().unix_timestamp(); + // The credential lives 120 seconds; the request asks for an hour. + let presentation = outstanding_presentation(&h, &account, 120).await?; + let requested = format_time(now() + Duration::seconds(3600)); + let (status, body) = + mint_held(&h, &policy, &presentation, &account_cid, &space, &requested).await?; + assert_eq!(status, Status::Ok, "{body}"); + let token = serde_json::from_str::(&body)?["authorization"] + .as_str() + .ok_or_else(|| anyhow::anyhow!("missing authorization: {body}"))? + .to_owned(); + let payload = token + .split('.') + .nth(1) + .ok_or_else(|| anyhow::anyhow!("malformed authorization"))?; + let claims: Value = + serde_json::from_slice(&base64::decode_config(payload, base64::URL_SAFE_NO_PAD)?)?; + let exp = claims["exp"] + .as_i64() + .ok_or_else(|| anyhow::anyhow!("missing exp: {claims}"))?; + assert!( + exp - issued_at <= 130, + "session exp {exp} exceeds the 120s credential lifetime from {issued_at}" + ); + Ok(()) +} + +async fn held_presentation_with_the_required_vct_is_admitted( + backend: Backend, +) -> anyhow::Result<()> { + let Some(h) = Harness::new_with_held( + backend, + Shape::KeySession, + "held_presentation_with_the_required_vct_is_admitted", + true, + ) + .await? + else { + return Ok(()); + }; + h.grant_owner(Window::until(now() + Duration::days(2))) + .await?; + let account = HeldAccount::new()?; + let (account_cid, space) = import_account_authorization(&h, &account).await?; + let policy = register_held(&h).await?; + let presentation = outstanding_presentation_with_vct(&h, &account, 86_400, HELD_VCT).await?; + let requested = format_time(now() + Duration::seconds(3600)); + let (status, body) = + mint_held(&h, &policy, &presentation, &account_cid, &space, &requested).await?; + assert_eq!(status, Status::Ok, "{body}"); + Ok(()) +} + +async fn held_presentation_with_a_mismatched_vct_is_refused( + backend: Backend, +) -> anyhow::Result<()> { + let Some(h) = Harness::new_with_held( + backend, + Shape::KeySession, + "held_presentation_with_a_mismatched_vct_is_refused", + true, + ) + .await? + else { + return Ok(()); + }; + h.grant_owner(Window::until(now() + Duration::days(2))) + .await?; + let account = HeldAccount::new()?; + let (account_cid, space) = import_account_authorization(&h, &account).await?; + let policy = register_held(&h).await?; + // Issuer-signed with a `vct` other than the held credential type. The + // signature and disclosure digests stay valid, so the refusal comes from + // `held_email::verify` (`vct != VCT`), not from the signature checks. + let presentation = + outstanding_presentation_with_vct(&h, &account, 86_400, "opencredentials.phone/v1").await?; + let requested = format_time(now() + Duration::seconds(3600)); + let (status, body) = + mint_held(&h, &policy, &presentation, &account_cid, &space, &requested).await?; + assert_eq!(status, Status::Forbidden, "{body}"); + assert!(body.contains("profile-mismatch"), "{body}"); + Ok(()) +} + +on_both_backends!(held_mint_admits_once_and_returns_an_authorization); + +on_both_backends!(held_nonce_cannot_be_replayed_with_a_fresh_challenge); + +on_both_backends!(held_session_expiry_is_clamped_to_the_credential_expiry); + +on_both_backends!(held_presentation_with_the_required_vct_is_admitted); + +on_both_backends!(held_presentation_with_a_mismatched_vct_is_refused); diff --git a/tinycloud-node-server/src/policy_v3/test_harness.rs b/tinycloud-node-server/src/policy_v3/test_harness.rs index 571d78bf..d4e1b8ae 100644 --- a/tinycloud-node-server/src/policy_v3/test_harness.rs +++ b/tinycloud-node-server/src/policy_v3/test_harness.rs @@ -413,12 +413,22 @@ pub(super) struct Harness { pub content_space: SpaceId, pub content_resource: tinycloud_auth::resource::ResourceId, pub network: String, - issuer: tinycloud_core::libp2p::identity::ed25519::Keypair, - vector: Value, + pub(super) issuer: tinycloud_core::libp2p::identity::ed25519::Keypair, + pub(super) vector: Value, } impl Harness { pub async fn new(backend: Backend, shape: Shape, test: &str) -> anyhow::Result> { + Self::new_with_held(backend, shape, test, false).await + } + + /// Same harness, with the held-credentials flag set. An enabled flag needs an audience. + pub async fn new_with_held( + backend: Backend, + shape: Shape, + test: &str, + held: bool, + ) -> anyhow::Result> { let Some(db) = TestDatabase::new(backend, test).await? else { return Ok(None); }; @@ -442,7 +452,7 @@ impl Harness { None, ); let network = format!("urn:tinycloud:encryption:{}:mainnet", space_owner.did()); - let client = Self::boot_app(&db, &vector, &issuer).await?; + let client = Self::boot_app(&db, &vector, &issuer, held).await?; let harness = Self { client, _db: db, @@ -464,6 +474,7 @@ impl Harness { db: &TestDatabase, vector: &Value, issuer: &tinycloud_core::libp2p::identity::ed25519::Keypair, + held: bool, ) -> anyhow::Result { let mut config = crate::config::Config::default(); config.storage.datadir = db.datadir().into(); @@ -482,8 +493,29 @@ impl Harness { .as_str() .unwrap() .to_owned(); - config.share_email.issuer_public_key = - Some(encode_config(issuer.public().to_bytes(), URL_SAFE_NO_PAD)); + // Held harnesses pin the issuer through one explicit `credential_issuers` + // entry (profile `tinycloud.email-held/v1`) and carry no legacy key. + if held { + config.share_email.credential_issuers = + vec![crate::issuer_set::CredentialIssuerConfig { + issuer_did: config.share_email.issuer_did.clone(), + kid: config.share_email.issuer_kid.clone(), + alg: "EdDSA".to_owned(), + public_key: encode_config(issuer.public().to_bytes(), URL_SAFE_NO_PAD), + vcts: vec!["opencredentials.email/v1".to_owned()], + profiles: vec!["tinycloud.email-held/v1".to_owned()], + not_before: "2020-01-01T00:00:00Z".to_owned(), + retired_at: None, + not_after: None, + }]; + } else { + config.share_email.issuer_public_key = + Some(encode_config(issuer.public().to_bytes(), URL_SAFE_NO_PAD)); + } + config.held_credentials = crate::config::HeldCredentialsConfig { + enabled: held, + audience: held.then(|| "relying-party.example".to_owned()), + }; let figment = Figment::from(rocket::Config { address: "127.0.0.1".parse()?, log_level: rocket::config::LogLevel::Off, @@ -625,8 +657,18 @@ impl Harness { /// Register a policy over the content whose roots span `root`, signed /// by the policy owner. pub async fn register(&self, root: Window) -> anyhow::Result<(Status, String, Registered)> { - let owner_did = self.owner.did().to_owned(); let projection = self.vector["policyProjection"].clone(); + self.register_with_projection(root, projection).await + } + + /// Register a policy over the content whose roots span `root`, with the + /// credential requirement projection `projection`. + pub(super) async fn register_with_projection( + &self, + root: Window, + projection: Value, + ) -> anyhow::Result<(Status, String, Registered)> { + let owner_did = self.owner.did().to_owned(); let created = (now() - Duration::seconds(60)).min(root.not_before); let ceiling = vec![ json!({ @@ -954,6 +996,80 @@ impl Harness { .map_err(|(status, body)| anyhow::anyhow!("mint: {status} {body}")) } + /// POST a shape-valid held presentation (`{sdJwt, siwe}`) to the mint + /// route after a fresh challenge. Used where the verifier must not run + /// (the held flag is off), so the body needs only the held shape. + pub async fn mint_held_presentation( + &self, + policy: &Registered, + ) -> anyhow::Result<(Status, String)> { + let (status, body) = self.challenge(policy).await; + if status != Status::Ok { + return Ok((status, body)); + } + let challenge: Value = serde_json::from_str(&body)?; + let response = self + .client + .post("/policy/v3/delegations") + .header(ContentType::JSON) + .body( + json!({ + "policyCid": policy.policy_cid, + "challengeId": challenge["challengeId"], + "nonce": challenge["nonce"], + "requirement": self.vector["sdkRequirement"], + "presentation": { + "sdJwt": "held-placeholder~", + "siwe": {"message": "placeholder", "signature": "0x00"} + }, + "requestedExpiresAt": format_time(now() + Duration::seconds(300)), + }) + .to_string(), + ) + .dispatch() + .await; + let status = response.status(); + Ok((status, response.into_string().await.unwrap_or_default())) + } + + /// A held-shaped request whose `credential` field is set. The request-shape gate + /// refuses it before any verifier work. + pub async fn mint_held_with_credential( + &self, + policy: &Registered, + ) -> anyhow::Result<(Status, String)> { + let (status, body) = self.challenge(policy).await; + if status != Status::Ok { + return Ok((status, body)); + } + let challenge: Value = serde_json::from_str(&body)?; + let response = self + .client + .post("/policy/v3/delegations") + .header(ContentType::JSON) + .body( + json!({ + "policyCid": policy.policy_cid, + "challengeId": challenge["challengeId"], + "nonce": challenge["nonce"], + "requirement": self.vector["sdkRequirement"], + "accountAuthorizationCid": "placeholder", + "credentialSpaceId": "placeholder", + "credential": {}, + "presentation": { + "sdJwt": "held-placeholder~", + "siwe": {"message": "placeholder", "signature": "0x00"} + }, + "requestedExpiresAt": format_time(now() + Duration::seconds(300)), + }) + .to_string(), + ) + .dispatch() + .await; + let status = response.status(); + Ok((status, response.into_string().await.unwrap_or_default())) + } + /// The holder reads the content under a minted session. pub async fn read(&self, session: &str) -> anyhow::Result<(Status, Vec)> { let s0 = decode_delegation(session).map_err(|(_, error)| anyhow::anyhow!(error))?; diff --git a/tinycloud-node-server/tests/fixtures/held-email-v1/PROVENANCE.json b/tinycloud-node-server/tests/fixtures/held-email-v1/PROVENANCE.json new file mode 100644 index 00000000..4fad1799 --- /dev/null +++ b/tinycloud-node-server/tests/fixtures/held-email-v1/PROVENANCE.json @@ -0,0 +1,10 @@ +{ + "sourceRepository": "https://github.com/TinyCloudLabs/opencredentials", + "sourceCommit": "103b460b1b2950e05ced8e7ecfe1b26d4a4217d6", + "sourcePath": "rust/opencredentials_witness/specs/credential-acquisition-v1/held-email/vector.json", + "profile": "tinycloud.email-held/v1", + "profileVersion": 1, + "vct": "opencredentials.email/v1", + "copiedUnmodified": true, + "crossCheck": "js-sdk held-credentials verifier (tinycloud sdk-core), held-email vector script" +} diff --git a/tinycloud-node-server/tests/fixtures/held-email-v1/gen-s1-differential.mjs b/tinycloud-node-server/tests/fixtures/held-email-v1/gen-s1-differential.mjs new file mode 100644 index 00000000..554941e6 --- /dev/null +++ b/tinycloud-node-server/tests/fixtures/held-email-v1/gen-s1-differential.mjs @@ -0,0 +1,747 @@ +// Generator for s1-differential.json. Usage: +// TS_VERIFIER= VIEM_ROOT= \ +// OUT= node gen-s1-differential.mjs +// See s1-differential.provenance.json for the pinned verifier and output hashes. +import { createHash, createPrivateKey, createPublicKey, sign as edSign } from "node:crypto"; +import { createRequire } from "node:module"; +import { readFileSync, writeFileSync } from "node:fs"; + +const require = createRequire(process.env.VIEM_ROOT ?? `${process.cwd()}/`); +const { privateKeyToAccount } = require("viem/accounts"); +const { getAddress } = require("viem"); +const TS = await import(process.env.TS_VERIFIER ?? "@tinycloud/sdk-core/dist/held-credentials/index.js"); +const { parseIssuerSet, verifyHeldPresentation, InMemoryNonceStore } = TS; + +const AUDIENCE = "verifier.example"; +const CALLER = "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266"; +const OTHER = "did:pkh:eip155:1:0x1111111111111111111111111111111111111111"; +const HOLDER = "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266"; +const ANVIL_KEY = "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80"; +const ISSUER = "did:web:issuer.credentials.org"; +const KID = "did:web:issuer.credentials.org#k1"; +const PROFILE = "tinycloud.email-held/v1"; +const VCT = "opencredentials.email/v1"; +const BINDING = "tinycloud.credentials/account-binding/v1"; +const DAY = 86400; +const IAT = 1767225600; +const NOW = "2026-01-01T01:00:00Z"; +const ISSUED_AT = "2026-01-01T00:59:00Z"; +const NONCE_OK = "heldtestnonce0000000001"; + +const seed = Buffer.from(Array.from({ length: 32 }, (_, i) => (i * 37 + 11) & 0xff)); +const priv = createPrivateKey({ + key: Buffer.concat([Buffer.from("302e020100300506032b657004220420", "hex"), seed]), + format: "der", + type: "pkcs8", +}); +const pubX = createPublicKey(priv).export({ format: "jwk" }).x; +const account = privateKeyToAccount(ANVIL_KEY); + +const b64 = (s) => Buffer.from(s).toString("base64url"); +const sha = (s) => createHash("sha256").update(s).digest("base64url"); +const disc = (salt, name, value) => b64(JSON.stringify([salt, name, value])); +const digest = (d) => sha(Buffer.from(d, "ascii")); +const edSignB64 = (input) => edSign(null, Buffer.from(input, "ascii"), priv).toString("base64url"); + +const EMAIL_D = disc("salt-email", "email", "alice@example.com"); +const DOMAIN_D = disc("salt-domain", "emailDomain", "example.com"); + +const issuerConfig = (over = {}) => ({ + issuerDid: ISSUER, + kid: KID, + alg: "EdDSA", + publicKey: pubX, + vcts: [VCT], + profiles: [PROFILE], + notBefore: "2025-01-01T00:00:00Z", + retiredAt: null, + notAfter: null, + ...over, +}); + +const basePayload = (disclosures) => ({ + iss: ISSUER, + sub: CALLER, + iat: IAT, + nbf: IAT, + exp: IAT + 30 * DAY, + jti: "urn:uuid:0b6d2c4e-8a1f-4d3e-9b7a-1c2d3e4f5a6b", + vct: VCT, + profile: PROFILE, + profileVersion: 1, + holderBinding: { did: CALLER, signingDomain: BINDING }, + status: { method: "none" }, + _sd_alg: "sha-256", + _sd: disclosures.map(digest), +}); + +const baseHeader = { alg: "EdDSA", typ: "vc+sd-jwt", kid: KID }; + +// header/payload: object (JSON-stringified) or raw string. sig: "valid" | raw string. +function jwt({ header = baseHeader, payload, disclosures = [EMAIL_D, DOMAIN_D], sig = "valid", raw }) { + if (raw !== undefined) return raw; + const hs = typeof header === "string" ? header : JSON.stringify(header); + const ps = typeof payload === "string" ? payload : JSON.stringify(payload ?? basePayload([EMAIL_D, DOMAIN_D])); + const input = `${b64(hs)}.${b64(ps)}`; + const s = sig === "valid" ? edSignB64(input) : sig; + return [`${input}.${s}`, ...disclosures, ""].join("~"); +} + +function siweMessage(f) { + const lines = [ + `${f.domain ?? AUDIENCE} wants you to sign in with your Ethereum account:`, + f.address ?? HOLDER, + "", + f.statement ?? "Present a TinyCloud held credential", + "", + `URI: ${f.uri ?? `https://${AUDIENCE}`}`, + `Version: ${f.version ?? "1"}`, + `Chain ID: ${f.chainId ?? "1"}`, + `Nonce: ${f.nonce}`, + `Issued At: ${ISSUED_AT}`, + ]; + if (f.expirationTime) lines.push(`Expiration Time: ${f.expirationTime}`); + if (f.notBefore) lines.push(`Not Before: ${f.notBefore}`); + lines.push("Resources:", ...(f.resources ?? []).map((r) => `- ${r}`)); + return lines.join("\n"); +} + +async function sign(message) { + return account.signMessage({ message }); +} + +const SD_HASH = (sdJwt) => `urn:tinycloud:sd-hash:${sha(Buffer.from(sdJwt, "ascii"))}`; + +// Case constructor. `o` may set sdJwt (already built), siwe fields, policy overrides. +const cases = []; +function add(name, o = {}) { + cases.push({ name, o }); +} + +// Build a case body, computing TS outcome. +async function build(c) { + const o = c.o; + const policy = { + now: o.now ?? NOW, + caller: o.caller ?? CALLER, + audience: o.audience ?? AUDIENCE, + issuers: o.issuers ?? [issuerConfig()], + acceptedIssuers: o.acceptedIssuers ?? [{ issuerDid: ISSUER }], + acceptedProfiles: o.acceptedProfiles ?? [{ id: PROFILE, version: 1 }], + }; + const sdJwt = o.sdJwt ?? jwt(o.jwt ?? {}); + const nonceBoundTo = o.nonceBoundTo ?? policy.caller; + const issueNonce = o.nonce ?? undefined; + const store = new InMemoryNonceStore(); + const nonce = o.noNonce ? (o.nonceValue ?? NONCE_OK) : issueNonce ?? store.issue(AUDIENCE, nonceBoundTo); + if (!o.noNonce && issueNonce !== undefined) store.nonces.set(`${AUDIENCE}\n${nonce}`, nonceBoundTo); + const sdHashResource = o.resources ?? [SD_HASH(sdJwt)]; + const message = + o.message ?? + siweMessage({ + domain: o.domain, + address: o.address, + statement: o.statement, + uri: o.uri, + version: o.version, + chainId: o.chainId, + nonce, + expirationTime: o.expirationTime, + notBefore: o.siweNotBefore, + resources: sdHashResource, + }); + const signature = o.signature ?? (await sign(message)); + const body = { sdJwt, siwe: { message, signature } }; + return { body, policy, nonce, store, nonces: [...store.nonces.entries()], message, sdJwt, signature }; +} + +async function tsOutcome(b) { + let raw; + try { + raw = parseIssuerSet({ format: "tinycloud.credentials-issuers/v1", version: 1, issuers: b.policy.issuers }, { didMethods: { issuer: ["web"] } }); + } catch (e) { + return { code: e.code ?? "bad-issuer-set", detail: String(e.message) }; + } + try { + const r = await verifyHeldPresentation(b.body, { + now: new Date(b.policy.now), + issuerSet: raw, + acceptedIssuers: b.policy.acceptedIssuers, + acceptedProfiles: b.policy.acceptedProfiles.map((p) => ({ profile: p.id, profileVersion: p.version })), + didMethods: { issuer: ["web"] }, + audience: b.policy.audience, + nonceStore: b.store, + callerAccount: b.policy.caller, + }); + return { code: "ok", subject: r.subject, issuer: r.issuer }; + } catch (e) { + return { code: e.code ?? "THREW:" + String(e.message), detail: String(e.message) }; + } +} + +// ---- mutation catalogue ------------------------------------------------- +const P = (mut) => { + const p = basePayload([EMAIL_D, DOMAIN_D]); + mut(p); + return p; +}; + +add("base-valid"); +// presentation shape +add("pres-nonascii-sdjwt", { sdJwt: jwt({}).replace("eyJ", "eyJ\u00e9") }); +add("pres-no-trailing-tilde", { sdJwt: jwt({}).slice(0, -1) }); +add("pres-zero-disclosures", { sdJwt: jwt({ disclosures: [] }) }); +add("pres-empty-disclosure", { sdJwt: jwt({}).replace(`~${EMAIL_D}~`, `~~${EMAIL_D}~`) }); +add("pres-extra-tilde-end", { sdJwt: jwt({}) + "~" }); +add("pres-sdjwt-with-kbjwt", { sdJwt: jwt({}) + "eyJhbGciOi.kb.sig" }); +add("pres-jwt-two-segments", { sdJwt: jwt({ raw: "aGVhZGVy.cGF5bG9hZA~" + EMAIL_D + "~" }) }); +add("pres-jwt-empty-sig", { sdJwt: jwt({ sig: "" }) }); +add("pres-jwt-four-segments", { sdJwt: jwt({ raw: `${b64(JSON.stringify(baseHeader))}.${b64(JSON.stringify(basePayload([EMAIL_D, DOMAIN_D])))}.x.y~${EMAIL_D}~${DOMAIN_D}~` }) }); +add("pres-too-many-disclosures", { sdJwt: jwt({ disclosures: [EMAIL_D, DOMAIN_D, EMAIL_D, DOMAIN_D, EMAIL_D, DOMAIN_D, EMAIL_D, DOMAIN_D, EMAIL_D] }) }); +add("pres-long-sdjwt", { sdJwt: jwt({ payload: { ...basePayload([EMAIL_D, DOMAIN_D]), pad: "x".repeat(17000) } }) }); + +// header +add("hdr-alg-none", { jwt: { header: { ...baseHeader, alg: "none" } } }); +add("hdr-typ-wrong", { jwt: { header: { ...baseHeader, typ: "JWT" } } }); +add("hdr-extra-member", { jwt: { header: { ...baseHeader, x5c: "a" } } }); +add("hdr-no-kid", { jwt: { header: { alg: "EdDSA", typ: "vc+sd-jwt" } } }); +add("hdr-kid-no-hash", { jwt: { header: { ...baseHeader, kid: ISSUER } } }); +add("hdr-kid-hash-first", { jwt: { header: { ...baseHeader, kid: "#k1" } } }); +add("hdr-kid-bad-char", { jwt: { header: { ...baseHeader, kid: `${ISSUER}#k 1` } } }); +add("hdr-kid-empty-frag", { jwt: { header: { ...baseHeader, kid: `${ISSUER}#` } } }); +add("hdr-kid-number", { jwt: { header: { ...baseHeader, kid: 7 } } }); +add("hdr-kid-pkh", { jwt: { header: { ...baseHeader, kid: "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266#k1" } } }); +add("hdr-kid-did-method-uppercase", { jwt: { header: { ...baseHeader, kid: "did:WEB:issuer.credentials.org#k1" } } }); +add("hdr-kid-empty-did-id", { jwt: { header: { ...baseHeader, kid: "did:web:#k1" } } }); +add("hdr-kid-no-method", { jwt: { header: { ...baseHeader, kid: "issuer.credentials.org#k1" } } }); +add("hdr-array", { jwt: { header: "[1,2]" } }); +add("hdr-dup-key", { jwt: { header: '{"alg":"EdDSA","alg":"EdDSA","typ":"vc+sd-jwt","kid":"' + KID + '"}' } }); +add("hdr-not-json", { jwt: { header: "not json" } }); + +// signature +add("sig-flipped", { jwt: { sig: (() => { const s = edSignB64(`${b64(JSON.stringify(baseHeader))}.${b64(JSON.stringify(basePayload([EMAIL_D, DOMAIN_D])))}`); return s.slice(0, -2) + (s.at(-2) === "A" ? "B" : "A") + s.at(-1); })() } }); +add("sig-short", { jwt: { sig: "AAAA" } }); +add("sig-nonb64", { jwt: { sig: "@@@@" } }); +add("sig-padded", { jwt: { sig: edSignB64("x") + "==" } }); + +// payload +add("pl-iss-mismatch", { jwt: { payload: P((p) => (p.iss = "did:web:other.example")) } }); +add("pl-iat-missing", { jwt: { payload: P((p) => delete p.iat) } }); +add("pl-iat-float", { jwt: { payload: P((p) => { p.iat = IAT + 0.5; p.nbf = IAT + 0.5; }) } }); +add("pl-iat-string", { jwt: { payload: P((p) => { p.iat = String(IAT); p.nbf = String(IAT); }) } }); +add("pl-nbf-ne-iat", { jwt: { payload: P((p) => (p.nbf = IAT + 1)) } }); +add("pl-exp-missing", { jwt: { payload: P((p) => delete p.exp) } }); +add("pl-iat-huge-safe", { jwt: { payload: P((p) => { p.iat = 9007199254740991; p.nbf = p.iat; p.exp = p.iat + 1; }) } }); +add("pl-iat-year-10000", { jwt: { payload: P((p) => { p.iat = 253402300800; p.nbf = p.iat; p.exp = p.iat + 60; }) } }); +add("pl-iat-negative", { jwt: { payload: P((p) => { p.iat = -1; p.nbf = -1; p.exp = 60; }) } }); +add("pl-not-yet-valid", { jwt: { payload: P((p) => { p.iat = IAT + 7200; p.nbf = p.iat; p.exp = p.iat + DAY; }) } }); +add("pl-expired", { jwt: { payload: P((p) => { p.iat = IAT - 90 * DAY; p.nbf = p.iat; p.exp = IAT - 60 * DAY; }) } }); +add("pl-exp-eq-iat", { jwt: { payload: P((p) => (p.exp = IAT)) } }); +add("pl-lifetime-over-365d", { jwt: { payload: P((p) => (p.exp = IAT + 366 * DAY)) } }); +add("pl-lifetime-exactly-365d", { jwt: { payload: P((p) => (p.exp = IAT + 365 * DAY)) } }); +add("pl-profile-missing", { jwt: { payload: P((p) => delete p.profile) } }); +add("pl-profile-other", { jwt: { payload: P((p) => (p.profile = "tinycloud.other/v1")) } }); +add("pl-profile-version-2", { jwt: { payload: P((p) => (p.profileVersion = 2)) } }); +add("pl-profile-version-string", { jwt: { payload: P((p) => (p.profileVersion = "1")) } }); +add("pl-vct-other", { jwt: { payload: P((p) => (p.vct = "opencredentials.other/v1")) } }); +add("pl-vct-missing", { jwt: { payload: P((p) => delete p.vct) } }); +add("pl-extra-claim", { jwt: { payload: P((p) => (p.extra = "x")) } }); +add("pl-sd-alg-wrong", { jwt: { payload: P((p) => (p._sd_alg = "sha-512")) } }); +add("pl-sd-not-array", { jwt: { payload: P((p) => (p._sd = "x")) } }); +add("pl-sd-nonstring", { jwt: { payload: P((p) => (p._sd = [digest(EMAIL_D), 3])) } }); +add("pl-sd-duplicate", { jwt: { payload: P((p) => (p._sd = [digest(EMAIL_D), digest(EMAIL_D)])) } }); +add("pl-jti-not-uuid", { jwt: { payload: P((p) => (p.jti = "urn:uuid:abc")) } }); +add("pl-jti-v1", { jwt: { payload: P((p) => (p.jti = "urn:uuid:0b6d2c4e-8a1f-1d3e-9b7a-1c2d3e4f5a6b")) } }); +add("pl-jti-not-urn", { jwt: { payload: P((p) => (p.jti = "0b6d2c4e-8a1f-4d3e-9b7a-1c2d3e4f5a6b")) } }); +add("pl-status-other", { jwt: { payload: P((p) => (p.status = { method: "bitstring" })) } }); +add("pl-status-extra", { jwt: { payload: P((p) => (p.status = { method: "none", idx: 1 })) } }); +add("pl-status-missing", { jwt: { payload: P((p) => delete p.status) } }); +add("pl-sub-not-pkh", { jwt: { payload: P((p) => (p.sub = "mailto:alice@example.com")) } }); +add("pl-sub-other-chain", { jwt: { payload: P((p) => { p.sub = CALLER.replace("eip155:1:", "eip155:10:"); p.holderBinding.did = p.sub; }) } }); +add("pl-sub-missing", { jwt: { payload: P((p) => delete p.sub) } }); +add("pl-binding-extra", { jwt: { payload: P((p) => (p.holderBinding.x = 1)) } }); +add("pl-binding-domain", { jwt: { payload: P((p) => (p.holderBinding.signingDomain = "other/v1")) } }); +add("pl-binding-did-mismatch", { jwt: { payload: P((p) => (p.holderBinding.did = OTHER)) } }); +add("pl-binding-missing", { jwt: { payload: P((p) => delete p.holderBinding) } }); +add("pl-payload-array", { jwt: { payload: "[]" } }); +add("pl-payload-dup-key", { jwt: { payload: `{"iss":"${ISSUER}","iss":"${ISSUER}"}` } }); + +// disclosures +const withDisc = (ds) => ({ jwt: { disclosures: ds, payload: basePayload(ds) } }); +add("disc-digest-not-in-sd", { jwt: { disclosures: [disc("other", "email", "alice@example.com"), DOMAIN_D] } }); +add("disc-repeated", { jwt: { disclosures: [EMAIL_D, EMAIL_D], payload: { ...basePayload([EMAIL_D]), _sd: [digest(EMAIL_D)] } } }); +add("disc-not-base64", { jwt: { disclosures: ["@@@", DOMAIN_D] } }); +add("disc-not-array", { jwt: { disclosures: [b64(JSON.stringify({ a: 1 })), DOMAIN_D] } }); +add("disc-len-2", withDisc([b64(JSON.stringify(["s", "email"])), DOMAIN_D])); +add("disc-name-number", withDisc([b64(JSON.stringify(["s", 1, "x"])), DOMAIN_D])); +add("disc-salt-number", withDisc([b64(JSON.stringify([1, "email", "alice@example.com"])), DOMAIN_D])); +add("disc-value-number", withDisc([b64(JSON.stringify(["s", "email", 1])), DOMAIN_D])); +add("disc-value-array", withDisc([b64(JSON.stringify(["s", "email", ["a"]])), DOMAIN_D])); +add("disc-name-reserved-iss", withDisc([b64(JSON.stringify(["s", "iss", "x"])), DOMAIN_D])); +add("disc-name-signed-optional", withDisc([b64(JSON.stringify(["s", "vct", "x"])), DOMAIN_D])); +add("disc-name-not-disclosable", withDisc([disc("s", "nickname", "x"), DOMAIN_D])); +add("disc-claim-twice", { jwt: { disclosures: [EMAIL_D, disc("salt-email-2", "email", "bob@example.com"), DOMAIN_D], payload: basePayload([EMAIL_D, disc("salt-email-2", "email", "bob@example.com"), DOMAIN_D]) } }); +add("disc-missing-domain", { jwt: { disclosures: [EMAIL_D], payload: basePayload([EMAIL_D]) } }); +add("disc-missing-email", { jwt: { disclosures: [DOMAIN_D], payload: basePayload([DOMAIN_D]) } }); +add("disc-domain-mismatch", withDisc([EMAIL_D, disc("salt-domain", "emailDomain", "other.com")])); +add("disc-email-invalid", withDisc([disc("salt-email", "email", "not-an-email"), DOMAIN_D])); +add("disc-email-uppercase", withDisc([disc("salt-email", "email", "Alice@Example.com"), DOMAIN_D])); +add("disc-email-unicode", withDisc([disc("salt-email", "email", "älice@example.com"), DOMAIN_D])); +add("disc-email-empty", withDisc([disc("salt-email", "email", ""), DOMAIN_D])); +add("disc-empty-salt", withDisc([disc("", "email", "alice@example.com"), DOMAIN_D])); +add("disc-no-disclosures-at-all", { jwt: { disclosures: [], payload: basePayload([]) } }); +add("disc-only-sd-no-disclosure-but-sd-present", { jwt: { disclosures: [EMAIL_D, DOMAIN_D], payload: basePayload([EMAIL_D]) } }); + +// SIWE / caller / nonce +add("siwe-domain-other", { domain: "other.example" }); +add("siwe-uri-http", { uri: `http://${AUDIENCE}` }); +add("siwe-uri-userinfo", { uri: `https://u@${AUDIENCE}` }); +add("siwe-uri-port-443", { uri: `https://${AUDIENCE}:443` }); +add("siwe-uri-uppercase-host", { uri: `https://VERIFIER.example` }); +add("siwe-uri-path", { uri: `https://${AUDIENCE}/x` }); +add("siwe-uri-other-host", { uri: `https://evil.example` }); +add("siwe-version-2", { version: "2" }); +add("siwe-statement-other", { statement: "Sign in" }); +add("siwe-chain-10", { chainId: "10" }); +add("siwe-address-other", { address: OTHER }); +add("siwe-address-lowercase", { address: HOLDER.toLowerCase() }); +add("siwe-resource-other", { resources: ["urn:tinycloud:sd-hash:AAAA"] }); +add("siwe-two-resources", { resources: [`urn:tinycloud:sd-hash:x`, `urn:tinycloud:sd-hash:y`] }); +add("siwe-no-resources", { resources: [] }); +add("siwe-expired", { expirationTime: "2025-12-31T00:00:00Z" }); +add("siwe-expiration-equal-now", { expirationTime: NOW }); +add("siwe-not-before-future", { siweNotBefore: "2026-01-02T00:00:00Z" }); +add("siwe-expiration-bad-rfc3339", { expirationTime: "2026-13-01T00:00:00Z" }); +add("siwe-sig-no-0x", { signature: "00".repeat(65) }); +add("siwe-sig-uppercase-0X", { signature: "0X" + "00".repeat(65) }); +add("siwe-sig-short", { signature: "0x" + "00".repeat(64) }); +add("siwe-sig-long", { signature: "0x" + "00".repeat(66) }); +add("siwe-sig-other-key", { signature: null, message: null, signOther: true }); +add("siwe-nonce-short", { nonce: "shortnonce" }); +add("siwe-nonce-punct", { nonce: "heldtestnonce000000000!" }); +add("siwe-nonce-unknown", { noNonce: true }); +add("siwe-nonce-bound-other", { nonceBoundTo: OTHER }); +add("caller-other-account", { caller: OTHER, nonceBoundTo: OTHER }); +add("caller-chain-10", { caller: CALLER.replace("eip155:1:", "eip155:10:"), nonceBoundTo: CALLER.replace("eip155:1:", "eip155:10:") }); +add("time-now-before-nbf", { now: "2025-12-31T23:59:00Z" }); +add("time-now-at-exp", { now: new Date((IAT + 30 * DAY) * 1000).toISOString() }); +add("time-now-after-exp", { now: new Date((IAT + 31 * DAY) * 1000).toISOString() }); + +// issuer set / policy +add("iss-kid-not-accepted", { acceptedIssuers: [{ issuerDid: ISSUER, kid: "did:web:issuer.credentials.org#k2" }] }); +add("iss-did-not-accepted", { acceptedIssuers: [{ issuerDid: "did:web:other.example" }] }); +add("iss-no-accepted", { acceptedIssuers: [] }); +add("iss-kid-accepted-exact", { acceptedIssuers: [{ issuerDid: ISSUER, kid: KID }] }); +add("iss-entry-missing-kid", { issuers: [issuerConfig({ kid: "did:web:issuer.credentials.org#k2" })] }); +add("iss-not-yet-valid-key", { issuers: [issuerConfig({ notBefore: "2026-01-01T02:00:00Z" })] }); +add("iss-key-stopped", { issuers: [issuerConfig({ notAfter: "2026-01-01T00:30:00Z" })] }); +add("iss-credential-predates-key", { issuers: [issuerConfig({ notBefore: "2026-01-01T00:00:01Z" })] }); +add("iss-retired-before-iat", { issuers: [issuerConfig({ retiredAt: "2026-01-01T00:00:00Z" })] }); +add("iss-retired-after-iat", { issuers: [issuerConfig({ retiredAt: "2026-01-01T00:30:00Z" })] }); +add("iss-vct-not-admitted", { issuers: [issuerConfig({ vcts: ["other/v1"] })] }); +add("iss-profile-not-admitted", { issuers: [issuerConfig({ profiles: ["other/v1"] })] }); +add("iss-profile-not-accepted", { acceptedProfiles: [{ id: "other/v1", version: 1 }] }); +add("iss-profile-version-not-accepted", { acceptedProfiles: [{ id: PROFILE, version: 2 }] }); +add("iss-bad-alg", { issuers: [issuerConfig({ alg: "ES256" })] }); +add("iss-bad-pubkey", { issuers: [issuerConfig({ publicKey: "AAAA" })] }); + +// Add a stray signature-by-other-key case by name +const OTHER_SEED = Buffer.alloc(32, 9); +const otherPriv = createPrivateKey({ key: Buffer.concat([Buffer.from("302e020100300506032b657004220420", "hex"), OTHER_SEED]), format: "der", type: "pkcs8" }); +add("sig-other-issuer-key", { jwt: { sig: (() => { const hs = b64(JSON.stringify(baseHeader)); const ps = b64(JSON.stringify(basePayload([EMAIL_D, DOMAIN_D]))); return edSign(null, Buffer.from(`${hs}.${ps}`), otherPriv).toString("base64url"); })() } }); + +// ---- added categories (held-email differential) --------------------------- +// Verdicts come from the published verifier. Names are unique (checked below). + +const plWith = (mut) => { + const p = basePayload([EMAIL_D, DOMAIN_D]); + mut(p); + return p; +}; +const PAYLOAD_JSON = JSON.stringify(basePayload([EMAIL_D, DOMAIN_D])); +const ADDR_HEX = HOLDER.slice(2); +const firstLower = HOLDER.replace(/[a-f]/, (c) => c.toUpperCase()); + +// A. did:pkh casing and encoding. The seeded nonce is bound to the case DID only when that DID is a canonical did:pkh:eip155 account (lowercase or exact EIP-55); otherwise to CALLER, so the replay's nonceStore parses. The verdict is decided at caller parsing, before any nonce is spent. +const canonicalPkh = (did) => { + const m = /^did:pkh:eip155:1:(0x[0-9a-fA-F]{40})$/.exec(did); + return m !== null && (m[1] === m[1].toLowerCase() || getAddress(m[1]) === m[1]); +}; +const pkhCase = (did, addr) => ({ + caller: did, + nonce: NONCE_OK, + nonceBoundTo: canonicalPkh(did) ? did : CALLER, + address: addr, + jwt: { payload: plWith((p) => { p.sub = did; p.holderBinding.did = did; }) }, +}); +[ + ["pkh-lowercase-address", `did:pkh:eip155:1:${HOLDER.toLowerCase()}`, HOLDER.toLowerCase()], + ["pkh-uppercase-hex-digits", `did:pkh:eip155:1:0x${ADDR_HEX.toUpperCase()}`, `0x${ADDR_HEX.toUpperCase()}`], + ["pkh-bad-eip55-one-letter", `did:pkh:eip155:1:${firstLower}`, firstLower], + ["pkh-no-0x", `did:pkh:eip155:1:${ADDR_HEX}`, ADDR_HEX], + ["pkh-short-address", `did:pkh:eip155:1:${HOLDER.slice(0, -2)}`, HOLDER.slice(0, -2)], + ["pkh-method-uppercase", `did:PKH:eip155:1:${HOLDER}`, HOLDER], + ["pkh-namespace-uppercase", `did:pkh:EIP155:1:${HOLDER}`, HOLDER], + ["pkh-chain-leading-zero", `did:pkh:eip155:01:${HOLDER}`, HOLDER], + ["pkh-trailing-space", `did:pkh:eip155:1:${HOLDER} `, `${HOLDER} `], + ["pkh-zero-address", `did:pkh:eip155:1:0x${"0".repeat(40)}`, `0x${"0".repeat(40)}`], +].forEach(([name, did, addr]) => add(name, pkhCase(did, addr))); + +// B. SIWE signature encodings. The base message is signed once with a fixed nonce. +async function signedSiwe() { + const message = siweMessage({ nonce: NONCE_OK, resources: [SD_HASH(jwt({}))] }); + return { message, signature: await sign(message) }; +} +const BASE = await signedSiwe(); +const SECP_N = 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141n; +const sigR = (sig) => sig.slice(2, 66); +const sigS = (sig) => BigInt("0x" + sig.slice(66, 130)); +const sigV = (sig) => sig.slice(130, 132); +const sigJoin = (r, s, v) => "0x" + r + s.toString(16).padStart(64, "0") + v; +const vFlip = (v) => { + if (v !== "1b" && v !== "1c") throw new Error(`unexpected v ${v}`); + return v === "1b" ? "1c" : "1b"; +}; +const SIWE_SIG = BASE.signature; +[ + ["siwe-enc-v-0-1", SIWE_SIG.slice(0, -2) + (sigV(SIWE_SIG) === "1b" ? "00" : "01")], + ["siwe-enc-v-29", SIWE_SIG.slice(0, -2) + "1d"], + ["siwe-enc-hex-uppercase", "0x" + SIWE_SIG.slice(2).toUpperCase()], + ["siwe-enc-no-prefix", SIWE_SIG.slice(2)], + ["siwe-enc-leading-space", " " + SIWE_SIG], + ["siwe-enc-nonhex-char", SIWE_SIG.slice(0, 10) + "g" + SIWE_SIG.slice(11)], + ["siwe-enc-high-s", sigJoin(sigR(SIWE_SIG), SECP_N - sigS(SIWE_SIG), vFlip(sigV(SIWE_SIG)))], + ["siwe-enc-high-s-same-v", sigJoin(sigR(SIWE_SIG), SECP_N - sigS(SIWE_SIG), sigV(SIWE_SIG))], + ["siwe-enc-r-zero", sigJoin("0".repeat(64), sigS(SIWE_SIG), sigV(SIWE_SIG))], + ["siwe-enc-s-zero", sigJoin(sigR(SIWE_SIG), 0n, sigV(SIWE_SIG))], + ["siwe-enc-no-v", SIWE_SIG.slice(0, -2)], +].forEach(([name, signature]) => add(name, { nonce: NONCE_OK, message: BASE.message, signature })); + +// C. WHATWG-style URI forms in the SIWE URI line (audience stays verifier.example). +[ + ["uri-trailing-slash", "https://verifier.example/"], + ["uri-trailing-dot", "https://verifier.example."], + ["uri-backslash", "https://verifier.example\\"], + ["uri-double-backslash", "https:\\\\verifier.example"], + ["uri-single-slash", "https:/verifier.example"], + ["uri-pct-dot", "https://verifier%2Eexample"], + ["uri-ipv6-loopback", "https://[::1]/"], + ["uri-query", "https://verifier.example?x=1"], + ["uri-fragment", "https://verifier.example#frag"], + ["uri-empty-port", "https://verifier.example:"], + ["uri-port-leading-zero", "https://verifier.example:0443"], + ["uri-port-plus", "https://verifier.example:+443"], + ["uri-scheme-upper", "HTTPS://verifier.example"], + ["uri-tab", "https://verifier.example\t"], +].forEach(([name, uri]) => add(name, { uri })); + +// D. Ports in the SIWE domain and URI lines. +[ + ["port-domain-443", { domain: `${AUDIENCE}:443` }], + ["port-domain-8443", { domain: `${AUDIENCE}:8443` }], + ["port-domain-empty", { domain: `${AUDIENCE}:` }], + ["port-uri-http-80", { uri: `http://${AUDIENCE}:80` }], + ["port-uri-65535", { uri: `https://${AUDIENCE}:65535` }], + ["port-uri-00443", { uri: `https://${AUDIENCE}:00443` }], +].forEach(([name, o]) => add(name, o)); + +// E. RFC 3339 edges for SIWE expiration and not-before. +[ + ["rfc3339-exp-millis", { expirationTime: "2026-01-01T02:00:00.000Z" }], + ["rfc3339-exp-fraction-half", { expirationTime: "2026-01-01T02:00:00.5Z" }], + ["rfc3339-exp-offset-zero", { expirationTime: "2026-01-01T02:00:00+00:00" }], + ["rfc3339-exp-lowercase-z", { expirationTime: "2026-01-01T02:00:00z" }], + ["rfc3339-exp-space-separator", { expirationTime: "2026-01-01 02:00:00Z" }], + ["rfc3339-exp-feb-30", { expirationTime: "2026-02-30T00:00:00Z" }], + ["rfc3339-exp-hour-24", { expirationTime: "2026-01-01T24:00:00Z" }], + ["rfc3339-exp-leap-second", { expirationTime: "2026-06-30T23:59:60Z" }], + ["rfc3339-exp-1ms-after-now", { expirationTime: "2026-01-01T01:00:00.001Z" }], + ["rfc3339-exp-sub-ms-equals-now", { expirationTime: "2026-01-01T01:00:00.0001Z" }], + ["rfc3339-exp-comma-fraction", { expirationTime: "2026-01-01T02:00:00,000Z" }], + ["rfc3339-nbf-sub-ms-past", { siweNotBefore: "2026-01-01T01:00:00.0009Z" }], + ["rfc3339-nbf-1ms-future", { siweNotBefore: "2026-01-01T01:00:00.001Z" }], + ["rfc3339-exp-year-9999", { expirationTime: "9999-12-31T23:59:59Z" }], +].forEach(([name, o]) => add(name, o)); + +// F. SIWE message layout. Each variant is a text transform of the signed base message. +const T = BASE.message; +[ + ["layout-crlf", T.replaceAll("\n", "\r\n")], + ["layout-no-blank-after-address", T.replace("\n\n", "\n")], + ["layout-trailing-newline", T + "\n"], + ["layout-extra-line", T.replace("Nonce:", "Extra: x\nNonce:")], + ["layout-no-statement", T.replace("Present a TinyCloud held credential\n", "")], + ["layout-no-issued-at", T.replace(/Issued At: .*\n/, "")], + ["layout-uri-lowercase-key", T.replace("URI:", "uri:")], + ["layout-duplicate-uri", T.replace("Version:", `URI: https://${AUDIENCE}\nVersion:`)], + ["layout-resource-no-space", T.replace("- urn", "-urn")], + ["layout-no-resources-header", T.replace("Resources:\n", "")], +].forEach(([name, message]) => add(name, { nonce: NONCE_OK, message })); + +// G. JSON forms of the payload (numbers, BOM, depth, prototype keys, surrogates). Signed as written. +[ + ["json-iat-exponent", PAYLOAD_JSON.replace(`"iat":${IAT}`, `"iat":1.7672256e9`)], + ["json-iat-leading-zero", PAYLOAD_JSON.replace(`"iat":${IAT}`, `"iat":01767225600`)], + ["json-bom-prefix", "\uFEFF" + PAYLOAD_JSON], + ["json-leading-space", " " + PAYLOAD_JSON], + ["json-trailing-garbage", PAYLOAD_JSON + "x"], + ["json-proto-key", PAYLOAD_JSON.slice(0, -1) + ',"__proto__":{"x":1}}'], + ["json-constructor-key", PAYLOAD_JSON.slice(0, -1) + ',"constructor":{"prototype":{}}}'], + ["json-deep-nesting", PAYLOAD_JSON.slice(0, -1) + `,"deep":${"[".repeat(200)}${"]".repeat(200)}}`], + ["json-duplicate-sub", PAYLOAD_JSON.slice(0, -1) + `,"sub":"${CALLER}"}`], + ["json-iat-null", PAYLOAD_JSON.replace(`"iat":${IAT}`, `"iat":null`)], + ["json-iat-plus-sign", PAYLOAD_JSON.replace(`"iat":${IAT}`, `"iat":+${IAT}`)], + ["json-sub-lone-surrogate", PAYLOAD_JSON.replace(CALLER, CALLER + "\\ud800")], +].forEach(([name, payload]) => add(name, { jwt: { payload } })); + +// H. Header and kid forms. Signed by the issuer key, so only the header text differs. +[ + ["hdr-alg-lowercase", { ...baseHeader, alg: "eddsa" }], + ["hdr-alg-trailing-space", { ...baseHeader, alg: "EdDSA " }], + ["hdr-typ-uppercase", { ...baseHeader, typ: "VC+SD-JWT" }], + ["hdr-kid-percent-hash", { ...baseHeader, kid: `${ISSUER}%23k1` }], + ["hdr-kid-trailing-space", { ...baseHeader, kid: `${KID} ` }], + ["hdr-kid-unicode-fragment", { ...baseHeader, kid: `${ISSUER}#kä` }], + ["hdr-kid-uppercase-fragment", { ...baseHeader, kid: `${ISSUER}#K1` }], + ["hdr-kid-double-hash", { ...baseHeader, kid: `${ISSUER}#k1#k1` }], + ["hdr-crit-member", { ...baseHeader, crit: ["x"] }], + ["hdr-typ-missing", { alg: baseHeader.alg, kid: baseHeader.kid }], +].forEach(([name, header]) => add(name, { jwt: { header } })); + +// I. Ed25519 malleability (S + L, S = L, S >= L) and small-order R, signed over the valid header and payload. +const L_ORDER = 2n ** 252n + 27742317777372353535851937790883648493n; +const toLE32 = (n) => { + const b = Buffer.alloc(32); + let x = n; + for (let i = 0; i < 32; i++) { + b[i] = Number(x & 0xffn); + x >>= 8n; + } + return b; +}; +const fromLE32 = (b) => [...b].reduceRight((acc, byte) => (acc << 8n) | BigInt(byte), 0n); +const EDSIG = edSign(null, Buffer.from(`${b64(JSON.stringify(baseHeader))}.${b64(PAYLOAD_JSON)}`, "ascii"), priv); +const ED_R = EDSIG.subarray(0, 32); +const ED_S = fromLE32(EDSIG.subarray(32)); +const edSigOf = (r, s) => Buffer.concat([r, s]).toString("base64url"); +const IDENTITY = Buffer.from("01" + "00".repeat(31), "hex"); +const NONCANON_P = Buffer.from("ed" + "ff".repeat(30) + "7f", "hex"); +[ + ["sig-ed-s-plus-l", edSigOf(ED_R, toLE32(ED_S + L_ORDER))], + ["sig-ed-s-plus-2l", edSigOf(ED_R, toLE32(ED_S + 2n * L_ORDER))], + ["sig-ed-s-equals-l", edSigOf(ED_R, toLE32(L_ORDER))], + ["sig-ed-s-all-ff", edSigOf(ED_R, Buffer.alloc(32, 0xff))], + ["sig-ed-r-identity-s-zero", edSigOf(IDENTITY, Buffer.alloc(32))], + ["sig-ed-r-identity-s-original", edSigOf(IDENTITY, toLE32(ED_S))], + ["sig-ed-r-noncanonical-p", edSigOf(NONCANON_P, toLE32(ED_S))], + ["sig-ed-r-all-zero", edSigOf(Buffer.alloc(32), toLE32(ED_S))], + ["sig-ed-s-zero", edSigOf(ED_R, Buffer.alloc(32))], +].forEach(([name, sig]) => add(name, { jwt: { sig } })); + +// J. Issuer-set configuration variants. +[ + ["cfg-notafter-before-notbefore", { notBefore: "2026-01-01T00:00:00Z", notAfter: "2025-06-01T00:00:00Z" }], + ["cfg-retired-at-garbage", { retiredAt: "tomorrow" }], + ["cfg-notbefore-no-z", { notBefore: "2025-01-01T00:00:00" }], + ["cfg-notbefore-offset", { notBefore: "2025-01-01T01:00:00+01:00" }], + ["cfg-publickey-33-bytes", { publicKey: Buffer.alloc(33, 1).toString("base64url") }], + ["cfg-publickey-padded", { publicKey: `${pubX}=` }], + ["cfg-vcts-empty", { vcts: [] }], + ["cfg-profiles-duplicate", { profiles: [PROFILE, PROFILE] }], + ["cfg-kid-uppercase-method", { kid: "did:WEB:issuer.credentials.org#k1" }], + ["cfg-issuerdid-pkh", { issuerDid: CALLER }], + ["cfg-alg-lowercase", { alg: "eddsa" }], + ["cfg-publickey-identity", { publicKey: IDENTITY.toString("base64url") }], +].forEach(([name, over]) => add(name, { issuers: [issuerConfig(over)] })); + +// K. OC vector (opencredentials held-email vector, same holder as the Anvil account) and mutations. +const VEC = JSON.parse(readFileSync(new URL("./vector.json", import.meta.url), "utf8")); +const vecSegs = VEC.sdJwt.split("~"); +const vecJwt = vecSegs[0].split("."); +const vecDisc = vecSegs.slice(1).filter((d) => d !== ""); +const vecClaims = JSON.parse(Buffer.from(vecJwt[1], "base64url").toString()); +const flipAt = (s, i) => s.slice(0, i) + (s[i] === "A" ? "B" : "A") + s.slice(i + 1); +const rebuildSdJwt = (jwtParts, discs) => [jwtParts.join("."), ...discs, ""].join("~"); +const OC_BASE = { sdJwt: VEC.sdJwt, caller: VEC.account, nonceBoundTo: VEC.account, issuers: VEC.issuerSet.issuers, now: VEC.now }; +add("oc-base", OC_BASE); +for (const [label, k] of [["header", 0], ["payload", 1], ["signature", 2]]) { + for (const q of [0.25, 0.5, 0.75]) { + const parts = [...vecJwt]; + parts[k] = flipAt(parts[k], Math.floor(parts[k].length * q)); + add(`oc-flip-${label}-${q * 100}`, { ...OC_BASE, sdJwt: rebuildSdJwt(parts, vecDisc) }); + } +} +for (const q of [0.25, 0.5, 0.75]) { + const discs = [...vecDisc]; + discs[0] = flipAt(discs[0], Math.floor(discs[0].length * q)); + add(`oc-flip-disclosure-${q * 100}`, { ...OC_BASE, sdJwt: rebuildSdJwt(vecJwt, discs) }); +} +const atSec = (sec) => new Date(sec * 1000).toISOString(); +[ + ["oc-window-iat-minus-1", vecClaims.iat - 1], + ["oc-window-iat", vecClaims.iat], + ["oc-window-exp-minus-1", vecClaims.exp - 1], + ["oc-window-exp", vecClaims.exp], + ["oc-window-exp-plus-1", vecClaims.exp + 1], +].forEach(([name, sec]) => add(name, { ...OC_BASE, now: atSec(sec) })); + +// L. Disclosure values with a matching _sd digest for each disclosure (withDisc). Each reaches its named rule. +const emailValues = [ + ["trailing-space", "alice@example.com "], + ["trailing-newline", "alice@example.com\n"], + ["leading-space", " alice@example.com"], + ["short-local", "a@example.com"], + ["no-tld", "alice@example"], + ["double-dot-domain", "alice@example..com"], + ["leading-hyphen-label", "alice@-example.com"], + ["trailing-dot", "alice@example.com."], + ["upper-domain", "alice@EXAMPLE.com"], + ["upper-local", "ALICE@example.com"], + ["plus-tag", "alice+tag@example.com"], + ["subdomain", "alice@sub.example.com"], + ["ip-literal", "alice@[127.0.0.1]"], + ["nul-byte", "alice@example.com\u0000"], + ["zero-width-space", "alice@example.com\u200b"], + ["cyrillic-a-domain", "alice@ex\u0430mple.com"], + ["mailto-prefix", "mailto:alice@example.com"], + ["double-at", "alice@@example.com"], + ["quoted-local", '"alice"@example.com'], + ["local-65-chars", "a".repeat(65) + "@example.com"], + ["combining-accent", "alice@example.com\u0301"], + ["long-total-255", "alice@" + "a".repeat(250) + ".com"], +]; +const domainValues = [ + ["upper", "EXAMPLE.COM"], + ["trailing-dot", "example.com."], + ["empty", ""], + ["wildcard", "*.example.com"], + ["idn-umlaut", "exämple.com"], + ["path", "example.com/x"], + ["port", "example.com:443"], + ["localhost", "localhost"], + ["ipv4", "192.168.0.1"], + ["single-label", "example"], + ["trailing-space", "example.com "], + ["punycode", "xn--example.com"], +]; +const saltValues = [ + ["one-char", "a"], + ["non-ascii", "\u00e9"], + ["long-128", "x".repeat(128)], + ["padded-looking", "c2FsdA=="], + ["space", "salt with space"], + ["zero", "0"], + ["newline", "salt\n"], + ["quote", 'salt"'], +]; +const nameValues = [ + ["capital", "Email"], + ["trailing-space", "email "], + ["hyphen", "e-mail"], + ["proto", "__proto__"], + ["constructor", "constructor"], + ["to-string", "toString"], + ["sd-reserved", "_sd"], + ["domain-trailing-space", "emailDomain "], +]; +const typedValues = [ + ["null", null], + ["true", true], + ["false", false], + ["empty-object", {}], + ["empty-array", []], + ["zero", 0], + ["negative", -1], + ["fraction", 1.5], + ["exponent", 1e21], + ["nested-object", { email: "alice@example.com" }], + ["array-of-string", ["alice@example.com"]], + ["large-int", 9007199254740993], +]; +for (const [slug, v] of emailValues) { + const domain = v.includes("@") ? v.split("@").pop() : "example.com"; + add(`discv-email-${slug}`, withDisc([disc("salt-email", "email", v), disc("salt-domain", "emailDomain", domain)])); +} +for (const [slug, v] of domainValues) add(`discv-domain-${slug}`, withDisc([disc("salt-email", "email", `alice@${v}`), disc("salt-domain", "emailDomain", v)])); +for (const [slug, s] of saltValues) add(`discv-salt-${slug}`, withDisc([disc(s, "email", "alice@example.com"), DOMAIN_D])); +for (const [slug, n] of nameValues) add(`discv-name-${slug}`, withDisc([disc("salt-email", n, "alice@example.com"), DOMAIN_D])); +for (const [slug, v] of typedValues) add(`discv-value-${slug}`, withDisc([disc("salt-email", "email", v), DOMAIN_D])); + +{ + const seen = new Set(); + for (const c of cases) { + if (seen.has(c.name)) throw new Error(`duplicate case name: ${c.name}`); + seen.add(c.name); + } +} + +const out = []; +// Known Rust-vs-TS divergences. Annotations only: the TS verdict is always the verifier's. Each +// `rust` value is checked against the Rust replay, so a stale or wrong annotation fails the test. +const PKH_DEVIATION = { + rust: "account-owner-invalid", + reason: "Refused by precheck before nonce consume. TS reports bad-config for the same DID; Rust maps the account-owner refusal to 403.", +}; +const DEVIATIONS = { + "pkh-uppercase-hex-digits": PKH_DEVIATION, + "pkh-bad-eip55-one-letter": PKH_DEVIATION, + "pkh-no-0x": PKH_DEVIATION, + "pkh-short-address": PKH_DEVIATION, + "pkh-method-uppercase": PKH_DEVIATION, + "pkh-namespace-uppercase": PKH_DEVIATION, + "pkh-chain-leading-zero": PKH_DEVIATION, + "pkh-trailing-space": PKH_DEVIATION, + "siwe-enc-high-s": { + rust: "bad-siwe-signature", + reason: "Rust refuses high-S ECDSA signatures (recover_from_prehash). TS accepts. Known deviation, decided to keep the Rust refusal.", + }, + "json-sub-lone-surrogate": { + rust: "bad-payload", + reason: "Rust rejects the lone surrogate while decoding the payload JSON; TS decodes it and rejects the subject. Both refuse the presentation.", + }, + "cfg-notafter-before-notbefore": { + rust: "bad-issuer-set", + reason: "Rust fails closed for the whole issuer set at startup (credential_issuer_set()?); TS stops only the affected issuer per presentation. Stricter than TS; the presentation is refused either way.", + }, +}; +for (const c of cases) { + let b; + if (c.o.signOther) { + c.o.signature = undefined; + } + if (c.o.signOther) { + const base = await build({ o: { ...c.o, signature: "0x" + "00".repeat(65) } }); + b = base; + } else { + b = await build(c); + } + if (c.o.signOther) { + // Sign the SIWE message with a non-subject key. + const other = privateKeyToAccount("0x" + "11".repeat(32)); + const msg = b.message; + b.body.siwe.signature = await other.signMessage({ message: msg }); + } + const ts = await tsOutcome(b); + out.push({ + name: c.name, + policy: { + now: b.policy.now, + caller: b.policy.caller, + audience: b.policy.audience, + issuers: b.policy.issuers, + acceptedIssuers: b.policy.acceptedIssuers, + acceptedProfiles: b.policy.acceptedProfiles, + }, + sdJwt: b.sdJwt, + siwe: { message: b.message, signature: b.body.siwe.signature }, + nonceStore: b.nonces.map(([key, account]) => ({ key, account })), + ts, + ...(DEVIATIONS[c.name] ? { deviation: DEVIATIONS[c.name] } : {}), + }); +} + +writeFileSync(process.env.OUT ?? "cases.json", JSON.stringify(out, null, 1)); +const summary = {}; +for (const r of out) summary[r.ts.code] = (summary[r.ts.code] ?? 0) + 1; +console.log(JSON.stringify(summary, null, 1)); +console.log("cases:", out.length); diff --git a/tinycloud-node-server/tests/fixtures/held-email-v1/s1-differential.json b/tinycloud-node-server/tests/fixtures/held-email-v1/s1-differential.json new file mode 100644 index 00000000..90274a59 --- /dev/null +++ b/tinycloud-node-server/tests/fixtures/held-email-v1/s1-differential.json @@ -0,0 +1,17087 @@ +[ + { + "name": "base-valid", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 8e8c51a843589ee7fc38b57550fed180\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:eQXOZSXekF4OXymmuUiq0bSeG_wfOw3b2JlaG4CGhkU", + "signature": "0x030f3e2440b4a6bb597430f53b361a9769de52e238c0bbc61281c424a9e5881f183d95135c4d7edfaeea192ff0684ebe2837c6862a5e04792b95b4d25cd2faff1c" + }, + "nonceStore": [ + { + "key": "verifier.example\n8e8c51a843589ee7fc38b57550fed180", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "ok", + "subject": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "issuer": "did:web:issuer.credentials.org" + } + }, + { + "name": "pres-nonascii-sdjwt", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJéhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: eef5b065d700f483536bca42efdd3be3\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:L4WO-1iH9j6LnGqxVVGrs6pMJsNYte_WNLRuWkWMxLY", + "signature": "0x95e0443c13a2d431b8f8a1e42791fdd7df2771c9b0862528fc56890aff35443355df46cf34b78905abf53648cdb9d77d05f2370b2dd234d7c7f95c6a9a115e3a1c" + }, + "nonceStore": [ + { + "key": "verifier.example\neef5b065d700f483536bca42efdd3be3", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-presentation", + "detail": "bad-presentation: sdJwt must be an ASCII string" + } + }, + { + "name": "pres-no-trailing-tilde", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 164eb5919bec90707b20b44b711221af\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:-2tpLO8-kyb2m5e0b7bqEr1cs9696FNoz34PwHyyGhI", + "signature": "0xe16802a6c87ff345f1bb202021ab81a1fdd517c8e90e1017636bf507f901615d146b6ffd6bcd4bc5d0f8ead21343b4c82a8fe8d05b7ed398a116ac99b22a22081b" + }, + "nonceStore": [ + { + "key": "verifier.example\n164eb5919bec90707b20b44b711221af", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-presentation", + "detail": "bad-presentation: sdJwt must end with ~ and carry no key-binding JWT" + } + }, + { + "name": "pres-zero-disclosures", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: ab3678607c5fa8cc7734be8a75ed7aff\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:oFUOKOI3XSk6H9aHnIKa35x2c-LF7RCLthuYOss2qA4", + "signature": "0x7910fca2e2884be090f8f5f741b6904d4dd00e6c5622dcbe59ad08629965f8486f5959879cbcfedb62c1109fb7b8c231177062fa7f18d145db66a329f43e54ac1c" + }, + "nonceStore": [ + { + "key": "verifier.example\nab3678607c5fa8cc7734be8a75ed7aff", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "ok", + "subject": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "issuer": "did:web:issuer.credentials.org" + } + }, + { + "name": "pres-empty-disclosure", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: fa875e21d886f4a969a29f57200a6a7a\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:WTtZtUveuEUvuAuMmLXrc2qI1s-N6uDTP00fXgabHB4", + "signature": "0x5b1c155765817ec16f2f7fa763aac5d066023fe839d1773609e2ae5d0bbb94072293aee165fe3c2084026a2fea1b8a319368a0e1fedfc9ac7f86824a682decba1b" + }, + "nonceStore": [ + { + "key": "verifier.example\nfa875e21d886f4a969a29f57200a6a7a", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-presentation", + "detail": "bad-presentation: empty disclosure" + } + }, + { + "name": "pres-extra-tilde-end", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 1a15f2b85d15529685d0b32c2c507965\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:kbHAYdWIU9lrVkng9K2fMdF0opB30JkVBjFqFzGLuZQ", + "signature": "0xa9c78e96c1d7bf906e3203ecf1edfc7ce29e992a2a3b50db366c77f3801153ab061641b5502f6e3c90945e67024eda486de530cfd283931984ec7faaed1a45d01c" + }, + "nonceStore": [ + { + "key": "verifier.example\n1a15f2b85d15529685d0b32c2c507965", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-presentation", + "detail": "bad-presentation: empty disclosure" + } + }, + { + "name": "pres-sdjwt-with-kbjwt", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~eyJhbGciOi.kb.sig", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 49b8457512752ae191cf5e62b8e06263\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:DXvSJ2R7p_HTfl9fE7Ip7rnk_D6Pex9WoSLpt_iHNYo", + "signature": "0xf815b653775c9eaf190b6d63363bb68c15cc28007fd6a99c1fe5ea9c265c2a617d2d50db4a8a1029b55ae2db86eb0f5f4d8782474e5a438ca4a2e7c4f71d33341b" + }, + "nonceStore": [ + { + "key": "verifier.example\n49b8457512752ae191cf5e62b8e06263", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-presentation", + "detail": "bad-presentation: sdJwt must end with ~ and carry no key-binding JWT" + } + }, + { + "name": "pres-jwt-two-segments", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "aGVhZGVy.cGF5bG9hZA~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 2d6c7d607e5847319d57551c918b5a16\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:BbOYE8frR9s1_D0UHvqfkadxlsoGdDBgu_WmtTU04u4", + "signature": "0x38b2fde7f2388aae2df5a4e8077b6a3714055ed3e99f77917fdc38c0c8b687fb538ae0b682d816eec2743029ccd5b17b530bfea2b1ccb1f7e4085bd6d38f7cf71b" + }, + "nonceStore": [ + { + "key": "verifier.example\n2d6c7d607e5847319d57551c918b5a16", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-presentation", + "detail": "bad-presentation: JWT must have three segments" + } + }, + { + "name": "pres-jwt-empty-sig", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 78096fe2bcc53a234e64c101a2d9f5fb\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:4RAhYwBRvKTEtpYsNCwXe7vTNpPmNKYqRjkEGGpuwRQ", + "signature": "0xecb241e17b59058606b8c804c095580c694159e46fa401c9f2896f388620886d5108f924329e57e0410f99ae46b0ccc1af83388bd72a8ee270f32c35ef85fd5b1b" + }, + "nonceStore": [ + { + "key": "verifier.example\n78096fe2bcc53a234e64c101a2d9f5fb", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-presentation", + "detail": "bad-presentation: JWT must have three segments" + } + }, + { + "name": "pres-jwt-four-segments", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.x.y~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 98bd73b5c180c43633f5ad2bbf278d8e\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:mUJy3WJBjT-eENusmdrx1jEsaCH6EHHA_LMmtfH_Bnc", + "signature": "0xf8a3391a4947dc66a5cb990aa8ac1ace05ba8842670e0659ed9a80b6a44794b430f7804c60a62f9cc35cc8743c0760123b0aea77b8cd6ed4eaec536449a1c0101b" + }, + "nonceStore": [ + { + "key": "verifier.example\n98bd73b5c180c43633f5ad2bbf278d8e", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-presentation", + "detail": "bad-presentation: JWT must have three segments" + } + }, + { + "name": "pres-too-many-disclosures", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 853310c2837b93c21e55dc60de0eaf3d\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:CHGvE2O805vueqnaJr9Sf-R98t7w4ijgO3i6jYGNbyQ", + "signature": "0x41c33bfe52dcbd16097be116155e27e9accc08d8b4181b9c1a099a45a3616c1210de9d19bbcf41d30193fccd0d65f2154bf326119ed48bfd1497dbf7b65a2ae21b" + }, + "nonceStore": [ + { + "key": "verifier.example\n853310c2837b93c21e55dc60de0eaf3d", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-presentation", + "detail": "bad-presentation: too many disclosures" + } + }, + { + "name": "pres-long-sdjwt", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXSwicGFkIjoieHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHgifQ.Cy8DbQHkblHdhKZGQpY7qO4VOkHIcxtF2kyAswvcWYGiDrMJ_v_jJzF484hDYCoRAQPShtcTRgfFsGmkpR52Aw~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: a083d919a365360b30f489a1a4ae045c\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:1wqP2B5X7lkAkdbLr2EVNQPDbf1ke-UqgEknG5NeRD8", + "signature": "0xfc7de2be507ebcb4b699b8a61ddd2a9b75c89d209386cff8ca924fcf75d1271023eeafe6290608eccd2f163b5245474b5147c9ceef9a4882f563db0382acaf691b" + }, + "nonceStore": [ + { + "key": "verifier.example\na083d919a365360b30f489a1a4ae045c", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-presentation", + "detail": "bad-presentation: sdJwt is too long" + } + }, + { + "name": "hdr-alg-none", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJub25lIiwidHlwIjoidmMrc2Qtand0Iiwia2lkIjoiZGlkOndlYjppc3N1ZXIuY3JlZGVudGlhbHMub3JnI2sxIn0.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.P79f-01iD_wOTWusohSxASwXdsZK2AfTEv8Or8qomLpQ4U8V0UWI057hnnEIFG4RmVC4ogOpwDlm1Hp7EQIaCA~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 892a2cbc9b47355606b4a2e1c992cbc9\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:kodY0x07kqXnGcIZCZBeq671i3aZXD2o3jsaPnC8Dqw", + "signature": "0x4af3e3e4c94854c30d66b35e37b7fd4c42d32f36f8ac84b8765e9c42677f390e73800f01ce928c905c6f8e989b520789b023872111d352d4395ac04e50c99f5b1c" + }, + "nonceStore": [ + { + "key": "verifier.example\n892a2cbc9b47355606b4a2e1c992cbc9", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-header", + "detail": "bad-header: alg must be EdDSA" + } + }, + { + "name": "hdr-typ-wrong", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6IkpXVCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.6uB5mli9mbUICCIHKHqQLkp3EHR8WhMTEUvJky9VRCkDUJawwbq4-9m5pprYhWGvJTCaIQYYSBHyJYpNF-wCBA~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 025ce868236dc40f1c0a88720cdcc67b\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:8kXv5GsUBo4Jm_MVdOkxjZty7jAS6v81S07RA3FiTTQ", + "signature": "0x2972b5e3f1fcf59bee4aab86a4be90283bfc91c003776355858daf7f3c47eb4f0f115107bd86224efada51f782d26ce0f6acdf1ba38bc069ebd460408cba3fc21c" + }, + "nonceStore": [ + { + "key": "verifier.example\n025ce868236dc40f1c0a88720cdcc67b", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-header", + "detail": "bad-header: typ must be vc+sd-jwt" + } + }, + { + "name": "hdr-extra-member", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSIsIng1YyI6ImEifQ.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.dDUtznOqD_5eGQVpGRKYKSqy8o7sbAeD5iRcxfGQ41hxeUIIpnFYJqRCbX_l_EKQ37Y7bgB2f5paVfqoqqUUBg~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 24d19f375ae35ffa5b8ba85d7d2810eb\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:63GYsGoMQAXM01T0eX0XpwNaNpqpCtcnj_FVFyF0WJQ", + "signature": "0x76eead7a0aa97b05e9f7d5b71063c9f8cf12813c95e14e1475453c5e2463f7543e4635c9b7136c106e1755c11e3b59c0744e30c80c1310f2d22c6da252ed63de1b" + }, + "nonceStore": [ + { + "key": "verifier.example\n24d19f375ae35ffa5b8ba85d7d2810eb", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-header", + "detail": "bad-header: unexpected header member x5c" + } + }, + { + "name": "hdr-no-kid", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.-f7FvZnrzXlRbcC1MshaAfhjop0L0051HwPkfNQBkIIypEgIgGgS44wS0uYgFK_1NSaF6bVat7WeDxSPSAKZCA~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 35969f781111062bac0fbcf91ee403a6\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:O72kKoIbT4Xp1NbRSjgW_1b4J52uRE1vY0giGqnQxOo", + "signature": "0xa3912de6b5f1a6cb5962b76780808abcc273242a747bce8428285e45b9b5f33374fb25af6e031b795132bd8d7c5b32e4fe3fdfcc096e0f7a5bae5abbaa438cb41b" + }, + "nonceStore": [ + { + "key": "verifier.example\n35969f781111062bac0fbcf91ee403a6", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-header", + "detail": "bad-header: kid is required" + } + }, + { + "name": "hdr-kid-no-hash", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.FAHSay4snUawZA5xCpOtbePnbUeMwgXYh3DqIivCHbm9i417kgjM18coIiffJzK5Y6RK2Bd4TDc0i4br4212AQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: ffd5514ee89c294d4116808f6c910203\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:UCieXjC4GyWpRoWb5jVTLQ1wG3kwhm1iOz4-0sxNphM", + "signature": "0x66a8a081b448fce20bfc001ea73e0a90463860e3a5f4803f48555bbdb88b79be6159f6627d7b081a1a812bf2c083777b399f41e565742b8eadb908e1d5bf95f21c" + }, + "nonceStore": [ + { + "key": "verifier.example\nffd5514ee89c294d4116808f6c910203", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-header", + "detail": "bad-header: kid must be a DID URL with a fragment" + } + }, + { + "name": "hdr-kid-hash-first", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6IiNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.S7kXFDXRuK32xyq9ebB9JCbeSasCWdzD-1sH3ZqDlFGKWT2EQMv1qS0xV3LJdn2m7AOch-N_OyKuGRaAmKOcAg~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 6c8f44b043d3485dfce769ba845c16c7\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:edFiTDA1GigZifm6tnOJ0spKjtnp9oY3ZZjx9t0Urzw", + "signature": "0xef3af83400ee8dcc71c95f3700ac480b02861088c16ab24948838632805e20d47f40c9ed999154f3a83b1d36e44e85a7347cc29c1891d22f1be54c4b80aa773d1c" + }, + "nonceStore": [ + { + "key": "verifier.example\n6c8f44b043d3485dfce769ba845c16c7", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-header", + "detail": "bad-header: kid must be a DID URL with a fragment" + } + }, + { + "name": "hdr-kid-bad-char", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrIDEifQ.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ir0n26XCy2rgzDyR2McD9bdEuvwTuvSsuDvgbG7xyvAGj-F1wd2Myeq3x9O3cIe2kHbpqRfnmFq9BzNrEBGsAg~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: f86cb45011c79ffb7e2f38da992724f0\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:MwngGV6K1N8m2KZ8eK1jnirci89gHvavdUWe87sk7aU", + "signature": "0x99a18e74b5ebdc814974dd0bda3a08657db9d631450fcdf4598730ff5db91a372bcc9d5bb9df55291369009ec7a5006b9bc3f89cf6fa21bfc82aa062daed856e1b" + }, + "nonceStore": [ + { + "key": "verifier.example\nf86cb45011c79ffb7e2f38da992724f0", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-header", + "detail": "bad-header: kid must be issuerDid#fragment" + } + }, + { + "name": "hdr-kid-empty-frag", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyMifQ.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.vl78T0nwQC9YvG2rEE69ZtjSYUq7UXILS2_eZEinrjAzIw3CriSu_VGoV7ReOZslha11s0GekEBozYJsDawTDg~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: d092447a617fc815b90e0006a428ccc2\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:y8DMwe7AMlH0bw4rQeptGGdqcDHIYHYDP9w_ouK2Z7w", + "signature": "0xf41bef7bdeadc10d1f408ba86336e0d64928a6e91941c8ece45946f9c6cd3f285d606bb94cdc0656cc2f11f0cc81ef103392c8f4d1fc31e600e1e45aff91fcf21b" + }, + "nonceStore": [ + { + "key": "verifier.example\nd092447a617fc815b90e0006a428ccc2", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-header", + "detail": "bad-header: kid must be issuerDid#fragment" + } + }, + { + "name": "hdr-kid-number", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6N30.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.2oBPHwq44FMRKVcJw-iSJ9dQa5RL3nZkUKZcEipKyg50xyMdnIckAgLtD5eIYKDgQosBTHlcccLGPH43xcbbAw~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: fe455974f72e2e86d018b353ca6e4789\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:BFsTgsMihGKmcs1wgmJ6EmLCTDdheGrduIxFF4hJiow", + "signature": "0x5ceba8d572a8ca24e47a9d702fb5c426749acf654dc9657ab3f30185e302f4d2437a077705feb5115b46028bd306a20901bb8799967b369ef2c33b0ed1f81fb61c" + }, + "nonceStore": [ + { + "key": "verifier.example\nfe455974f72e2e86d018b353ca6e4789", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-header", + "detail": "bad-header: kid is required" + } + }, + { + "name": "hdr-kid-pkh", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2I2sxIn0.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.RdykFkLzD4YOxrMkxAG5ZIF8ndySK0IVfYwKe7pQnMKW8_z1O0RsvP7O1BPY2iSziEeyOqJnOR5RpdMBLd6qCw~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: d699f272252245d1d0c73db9e5fe80b1\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:a40hU3XRn4yOGGIVlygdu7UmX1-rl5TApHzgHPW-hew", + "signature": "0xbbef0dbb3c32929b9e80f901c69a0edca219c623b9b7b78ec1cbe0b7bfad736a0dc4c6814fee00e95d9a6c82b94d1a76bee235df6fa424279e4ea9ba9dd83f5a1b" + }, + "nonceStore": [ + { + "key": "verifier.example\nd699f272252245d1d0c73db9e5fe80b1", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "did-method-not-allowed", + "detail": "did-method-not-allowed: issuer DID method pkh is not on the allow-list" + } + }, + { + "name": "hdr-kid-did-method-uppercase", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDpXRUI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.b6Y5bLxVR3B_a7TrLiqUxLEZqFZiSryGAdo58H0uRUjBsitcctegfrPdcPDfV3gijOYY618b8jRvBNwErkXKAA~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 1427da11465319bddb5d631551953123\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:COREPpLcu_xVj0EaKHLHbU5lNlk83A6swwfBVPkldtU", + "signature": "0xe619e55c45189de86c92b6552530ef81f3bc09907ce8b0db26b77c74f3078b8f32bc99b69e5ed803714839c663c3fe97a4a9dd6c96f1b965afe4f27caaabfe801b" + }, + "nonceStore": [ + { + "key": "verifier.example\n1427da11465319bddb5d631551953123", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "did-method-not-allowed", + "detail": "did-method-not-allowed: issuer DID method null is not on the allow-list" + } + }, + { + "name": "hdr-kid-empty-did-id", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6I2sxIn0.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.5peekU9yzOB8C_mYmlOJrm7JOCfYVmEq3hE_8h3if7_xO4TRRFcKZcLv8dEOUkpBdzH35QTvP-vCDEquBPulCA~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: ea96984feb5c4dd260f99c8dff6ee154\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:RdAVKHt1jK1iw8sn9UzHQxFsu2OlJO6ASl6s6Rn_rgc", + "signature": "0x93db5eff62a1bf39fea1ba9a4a00a2456057f90d617ab1835439552c6b59e13d3e4337d412f861a2fa12ba95dff7ebb5470dac3016808a4e0c19085877e8cb5f1c" + }, + "nonceStore": [ + { + "key": "verifier.example\nea96984feb5c4dd260f99c8dff6ee154", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "issuer-not-accepted", + "detail": "issuer-not-accepted: issuer is not accepted by this policy" + } + }, + { + "name": "hdr-kid-no-method", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6Imlzc3Vlci5jcmVkZW50aWFscy5vcmcjazEifQ.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.8435jTTsOQ1xW9ZkbPeEd_g-pRQaBmvc_LUjKllBA3NKhqfTsWwftwkse-IExSJbSbFWP0CLbrHVgTac6M4lBA~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: c6c385f3201f73903a34540b4efdc61c\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:wu8rLAVq43CdJr2w-mV_bQU4GtHbNVj4geO-MNxwDA4", + "signature": "0x9e5ddd6ba35eff1ed9d676d694ce36fa5eac15d4f97a989c67b3f77b115372fe6edaeae0d263139c3c5b0dc66cc978e6cadd0fd01f09899729f7f413b3bf49141c" + }, + "nonceStore": [ + { + "key": "verifier.example\nc6c385f3201f73903a34540b4efdc61c", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "did-method-not-allowed", + "detail": "did-method-not-allowed: issuer DID method null is not on the allow-list" + } + }, + { + "name": "hdr-array", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "WzEsMl0.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.leVyfsZCkY1wrbV8E9MQ0c0gLb3OJKkMa27JkJsYNRvEYdRarURil6r1rbxY0KVFIBQ60QnwkNzuiJQ5VCTLCg~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: fd2f49f113cab78387519b0ce53b2594\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:mYouCD2aiqjzYU8zUZ0UiM2Uq5gA-icfZFh49gPzvaY", + "signature": "0x701a991d39b15adf82e996135303004c33356124b6cac13a79d643c0a256b9157913e6249cc985e2efcdae629f2534ff2b64dbfca52df4126222124d3b02e4e31b" + }, + "nonceStore": [ + { + "key": "verifier.example\nfd2f49f113cab78387519b0ce53b2594", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-header", + "detail": "bad-header: header must be an object" + } + }, + { + "name": "hdr-dup-key", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsImFsZyI6IkVkRFNBIiwidHlwIjoidmMrc2Qtand0Iiwia2lkIjoiZGlkOndlYjppc3N1ZXIuY3JlZGVudGlhbHMub3JnI2sxIn0.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.Nm4elZadQa8XGBUyclKPySZGtd7-ebDdxzTPQqaiautVVvMSfvkaC8-DPmZ2Lafwuu8-GlsnQEdvFI-nwxTlAw~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: bf22d583503932fc7f309f61ee453214\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:2OrcQ1KcMjUawPuIW072Isja9Vr-XwYZFtDF8rg6bVg", + "signature": "0x8f38091416ea3159c6f94eedb512d4e1a97bc0fe3a1288618089bf468314ba3b6518a743b47324e3a84727f64093b29da50b17003571426d0cdb4f0b8f633a741c" + }, + "nonceStore": [ + { + "key": "verifier.example\nbf22d583503932fc7f309f61ee453214", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-header", + "detail": "bad-header: invalid JSON: duplicate key" + } + }, + { + "name": "hdr-not-json", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "bm90IGpzb24.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.xOVL3zBZedydXjvOlAuT_DATH0ScYJICnTR9zS1DmA17coFZWKyXDncUPtAjFh7MXJMGy0z_U4YCBvmeFnicAQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: ee69d45e70453d34719570276f853aaa\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:PBbnrumKWcnwI3AeCstUFuqx482FK6dtxYRHyml6RMw", + "signature": "0x90d6d049703c04023cb5b50a15e4a036e8c8af8a740e84a2c06e158e2140912b6a676f1f4f173eaf1f1f3499d87f04efdf4b62e9f8e1d0f65dc4d9c3e37710201c" + }, + "nonceStore": [ + { + "key": "verifier.example\nee69d45e70453d34719570276f853aaa", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-header", + "detail": "bad-header: invalid JSON: unexpected token" + } + }, + { + "name": "sig-flipped", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRAQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 78b0925dafbd41935b4e35a4f680526e\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:BwLKXUa-k-ebl5IBViEOq02Kl0ytn5bl4Q_5eJiOOKs", + "signature": "0xd4b5dcc3d3fcd5f3ee41ff35435e231075ff4a02192cfe0ac63091741c63f3d857c78c5766ab5d1aa3f6373e085edda0336aff6599c27d34371fdfd414c7aa081b" + }, + "nonceStore": [ + { + "key": "verifier.example\n78b0925dafbd41935b4e35a4f680526e", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-signature", + "detail": "bad-signature: issuer signature did not verify" + } + }, + { + "name": "sig-short", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.AAAA~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 8d006feeb4623cebeef5420ef78d9dd6\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:7DGadqzmH2ntBnkOiTKs4Zya-qUfWyxVj9QdtGs40IY", + "signature": "0x419538b164d86294c8b9438a5fa10f14e6eaa327fffb4aad46354b7a086dc5a25829bdaafbbcbac6f17f935e1125fd27c0fcd907f84b3ab04d9fb72bb58cea1e1c" + }, + "nonceStore": [ + { + "key": "verifier.example\n8d006feeb4623cebeef5420ef78d9dd6", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-signature", + "detail": "bad-signature: issuer signature did not verify" + } + }, + { + "name": "sig-nonb64", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.@@@@~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: fd7f997020a4367a24f5063aabda4389\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:UdV8LqXqAaYtmtC0iGRfQRlkjBpSXHyWX3Hs-eSULgE", + "signature": "0x0c32a798735ff6d12e976261ba650a049a1c571ed5599dc613812908440c97a76266ea3d6024fcbc5d33764037c38fadee67a33979f9228206c2c123ee9d33f91b" + }, + "nonceStore": [ + { + "key": "verifier.example\nfd7f997020a4367a24f5063aabda4389", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-signature", + "detail": "bad-signature: not unpadded base64url" + } + }, + { + "name": "sig-padded", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.8FT1tdiJQ3voq4GuA50qkt2Hd0h1GDv6PIzEyl8eykEd7dHR-JHcB3UO4StFJmnVN1ybMph5lerVUUvNvZ-GCA==~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 286bbad708dd4bfd038c7fa940610294\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:v3E9-DRaitURVsdXczLYLEc52x8j8x0T4pvS__Avan8", + "signature": "0xf26ca0d7143d71480b1ce5b6237b9a0301c31c4b5d7a652f2279b183dbb2e190114fbb5dc87d722f6d9d6c6ba239242ca242050406f96a1b3aee28215b3aafb51c" + }, + "nonceStore": [ + { + "key": "verifier.example\n286bbad708dd4bfd038c7fa940610294", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-signature", + "detail": "bad-signature: not unpadded base64url" + } + }, + { + "name": "pl-iss-mismatch", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOm90aGVyLmV4YW1wbGUiLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.lxCPIaGygpUeDBIB5y1Uj4yJOVai8RTuNpoUWfa44hRs52QxxjHQz9hACnPfzaF_t1jjPRxR4zK68FQ_n4E3Bw~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 9624c6821ae88f81615a3a4a28cc6707\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:aAN2RXnplHUn1dd8w1XCIhJSrZNj_ZEp0VBWEvI2_Dw", + "signature": "0x600f8f392193c80bea7007e21871d11e7319e770505aca19702a18ca2913986b4d8ccc3b60bbe6786787b175fbfac9e8bfb59a95f0ea122e24e60c4faa3716281b" + }, + "nonceStore": [ + { + "key": "verifier.example\n9624c6821ae88f81615a3a4a28cc6707", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-payload", + "detail": "bad-payload: iss must equal the DID part of kid" + } + }, + { + "name": "pl-iat-missing", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsIm5iZiI6MTc2NzIyNTYwMCwiZXhwIjoxNzY5ODE3NjAwLCJqdGkiOiJ1cm46dXVpZDowYjZkMmM0ZS04YTFmLTRkM2UtOWI3YS0xYzJkM2U0ZjVhNmIiLCJ2Y3QiOiJvcGVuY3JlZGVudGlhbHMuZW1haWwvdjEiLCJwcm9maWxlIjoidGlueWNsb3VkLmVtYWlsLWhlbGQvdjEiLCJwcm9maWxlVmVyc2lvbiI6MSwiaG9sZGVyQmluZGluZyI6eyJkaWQiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsInNpZ25pbmdEb21haW4iOiJ0aW55Y2xvdWQuY3JlZGVudGlhbHMvYWNjb3VudC1iaW5kaW5nL3YxIn0sInN0YXR1cyI6eyJtZXRob2QiOiJub25lIn0sIl9zZF9hbGciOiJzaGEtMjU2IiwiX3NkIjpbIjhFa2tTeUt0Y2xnNGNFdlR1ZmlLa2FCUmk2aEIxZ3hPc3NGZmwzTmthTzgiLCJXMGhUdUhlWmdSN2h6dF9KQXRESURXLWNMcVgyLV9HUURWS2Uwd2JHLWl3Il19.Upus4leRUZ4Dkk1BqnEL6OndySs4f5cQ-PHVuQ8tIwqP7VXryv6iZ7bqHzNHuFhNVqMaXMhxJm9QAyHyH_4hCQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 479b52838888053646da068f8795ce35\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:5mCr1ZmVWssPGD2VzJuysi0YBfJ5VqNsSEXwFd7lb3w", + "signature": "0x04488183af7c1959952f0f2defa68916f474a308048155876f4dc39998b3ff7e65fcbfa7a493cfbc1f78c13c6f267cd4c35bbb32b86e6def2837aeac650d1add1b" + }, + "nonceStore": [ + { + "key": "verifier.example\n479b52838888053646da068f8795ce35", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-payload", + "detail": "bad-payload: iat is required" + } + }, + { + "name": "pl-iat-float", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMC41LCJuYmYiOjE3NjcyMjU2MDAuNSwiZXhwIjoxNzY5ODE3NjAwLCJqdGkiOiJ1cm46dXVpZDowYjZkMmM0ZS04YTFmLTRkM2UtOWI3YS0xYzJkM2U0ZjVhNmIiLCJ2Y3QiOiJvcGVuY3JlZGVudGlhbHMuZW1haWwvdjEiLCJwcm9maWxlIjoidGlueWNsb3VkLmVtYWlsLWhlbGQvdjEiLCJwcm9maWxlVmVyc2lvbiI6MSwiaG9sZGVyQmluZGluZyI6eyJkaWQiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsInNpZ25pbmdEb21haW4iOiJ0aW55Y2xvdWQuY3JlZGVudGlhbHMvYWNjb3VudC1iaW5kaW5nL3YxIn0sInN0YXR1cyI6eyJtZXRob2QiOiJub25lIn0sIl9zZF9hbGciOiJzaGEtMjU2IiwiX3NkIjpbIjhFa2tTeUt0Y2xnNGNFdlR1ZmlLa2FCUmk2aEIxZ3hPc3NGZmwzTmthTzgiLCJXMGhUdUhlWmdSN2h6dF9KQXRESURXLWNMcVgyLV9HUURWS2Uwd2JHLWl3Il19.T0PJsozo0lEQhU6cfkuH6bBpFXX3BnrXLtcTu4gd0YqKdxMJsxV6aPjTrikfQ5fNFtpBNwjArTUTWNNfBf7zBg~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 2268125b68ddc65c5685a2f48433c72d\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:VopPfdA630vNZN3v5S_N1O_zJSLPGXN0-XOIR9i69jE", + "signature": "0xad6c140ddfe2c6dd684e4eadf16a9b21d7f905410bbb3d816386c29f7574a869303d5dd22a8296e7cf17baa40d42f26fd31acb3c102805a82415b3509ee7d38f1c" + }, + "nonceStore": [ + { + "key": "verifier.example\n2268125b68ddc65c5685a2f48433c72d", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-payload", + "detail": "bad-payload: invalid JSON: unexpected token" + } + }, + { + "name": "pl-iat-string", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6IjE3NjcyMjU2MDAiLCJuYmYiOiIxNzY3MjI1NjAwIiwiZXhwIjoxNzY5ODE3NjAwLCJqdGkiOiJ1cm46dXVpZDowYjZkMmM0ZS04YTFmLTRkM2UtOWI3YS0xYzJkM2U0ZjVhNmIiLCJ2Y3QiOiJvcGVuY3JlZGVudGlhbHMuZW1haWwvdjEiLCJwcm9maWxlIjoidGlueWNsb3VkLmVtYWlsLWhlbGQvdjEiLCJwcm9maWxlVmVyc2lvbiI6MSwiaG9sZGVyQmluZGluZyI6eyJkaWQiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsInNpZ25pbmdEb21haW4iOiJ0aW55Y2xvdWQuY3JlZGVudGlhbHMvYWNjb3VudC1iaW5kaW5nL3YxIn0sInN0YXR1cyI6eyJtZXRob2QiOiJub25lIn0sIl9zZF9hbGciOiJzaGEtMjU2IiwiX3NkIjpbIjhFa2tTeUt0Y2xnNGNFdlR1ZmlLa2FCUmk2aEIxZ3hPc3NGZmwzTmthTzgiLCJXMGhUdUhlWmdSN2h6dF9KQXRESURXLWNMcVgyLV9HUURWS2Uwd2JHLWl3Il19.SXUmFKnJlsqekcyW2IvmGxBSI8eRcssztkAgngIIMnbxlYjlOqW933GIPlrzTTKoem8eb9_t_UtJzimU5IhnAw~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 744fbecffd6b70c0ee368715e922a431\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:1GtrYXZfg9Tvakj0V7NzJucnkrCC_ra7R04tjy8k1oY", + "signature": "0x887d5b16ae524df04357f5f84ed17fc4c2d366c77ddcfc6465134ee91599f1266b11b3c098595d9bee83b06aab6f33b8933b24122da996829eda47c72d3f5f481b" + }, + "nonceStore": [ + { + "key": "verifier.example\n744fbecffd6b70c0ee368715e922a431", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-payload", + "detail": "bad-payload: iat is required" + } + }, + { + "name": "pl-nbf-ne-iat", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAxLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.k6lwIIb4UBlpVXrHJAR9T7zCXODw4i9tX8ASaQvreHxBUjVHt0KGhbk9n363pUa8xt0uWNCQNy2AaZAKEm2-AQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 14a08004c1ea8d3e7d1c6894fe18654e\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:Yao7wS5414D_GLXjs46MpXXYqx1l0bsTZA5UW9kCVL8", + "signature": "0xb8101a3b3345cbc391aa7b2f4403b6d167da822190a01c681b6c054ee3416f95098e1f8ade54e4c51c0a2dc67983b08351d151a875f9d0f060e42ca8a8751fdb1c" + }, + "nonceStore": [ + { + "key": "verifier.example\n14a08004c1ea8d3e7d1c6894fe18654e", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-payload", + "detail": "bad-payload: nbf must equal iat" + } + }, + { + "name": "pl-exp-missing", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJqdGkiOiJ1cm46dXVpZDowYjZkMmM0ZS04YTFmLTRkM2UtOWI3YS0xYzJkM2U0ZjVhNmIiLCJ2Y3QiOiJvcGVuY3JlZGVudGlhbHMuZW1haWwvdjEiLCJwcm9maWxlIjoidGlueWNsb3VkLmVtYWlsLWhlbGQvdjEiLCJwcm9maWxlVmVyc2lvbiI6MSwiaG9sZGVyQmluZGluZyI6eyJkaWQiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsInNpZ25pbmdEb21haW4iOiJ0aW55Y2xvdWQuY3JlZGVudGlhbHMvYWNjb3VudC1iaW5kaW5nL3YxIn0sInN0YXR1cyI6eyJtZXRob2QiOiJub25lIn0sIl9zZF9hbGciOiJzaGEtMjU2IiwiX3NkIjpbIjhFa2tTeUt0Y2xnNGNFdlR1ZmlLa2FCUmk2aEIxZ3hPc3NGZmwzTmthTzgiLCJXMGhUdUhlWmdSN2h6dF9KQXRESURXLWNMcVgyLV9HUURWS2Uwd2JHLWl3Il19.mjqOEzZs2M3ruoJbZRSu5fWQ8bmAGx4vKCw2xbNSuG_XwtZ1oJCM8ZyzM1bvtt888llRAyrEfWEQL-ICr4aUBg~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 9183bfa152d7c26dd61aee752de37db8\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:UZFq6k8gv1gZT84Hb6ttaxoBCNdGH7riYOeT6AYRM74", + "signature": "0x7a019d5f4a6a1d73b2558a176ca843cb7fc9a1522a82832315fc0dbf1e2c2af77ecd3f248de003ad1da84556b9583eb3413abe89f456ebf803f0b61c32610b831c" + }, + "nonceStore": [ + { + "key": "verifier.example\n9183bfa152d7c26dd61aee752de37db8", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-payload", + "detail": "bad-payload: exp is required" + } + }, + { + "name": "pl-iat-huge-safe", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6OTAwNzE5OTI1NDc0MDk5MSwibmJmIjo5MDA3MTk5MjU0NzQwOTkxLCJleHAiOjkwMDcxOTkyNTQ3NDA5OTIsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.0PK94agf5fyzlPlcjGkbOnb_S-244eS8S4871wrGGtmlrD6gV01IeTjaL69CW086zpi7nfVWOmF4pzehCwd4Dw~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 60fec22e9ea5ba0dc9997b403d8b3271\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:vfDM6DB7z7E74qPVVMYn81Rq_-TmbiZD-hhf6zRMIi4", + "signature": "0x37f8f9554f03b95c44394fec2aed139862527942f3e8fb4245f2a46bb44f04a8640b89ec17784b3514ebb5bae613b02ddb96ea62ea0e992e4a97447e9f9c1fdd1c" + }, + "nonceStore": [ + { + "key": "verifier.example\n60fec22e9ea5ba0dc9997b403d8b3271", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-payload", + "detail": "bad-payload: exp is required" + } + }, + { + "name": "pl-iat-year-10000", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MjUzNDAyMzAwODAwLCJuYmYiOjI1MzQwMjMwMDgwMCwiZXhwIjoyNTM0MDIzMDA4NjAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.nbksv6AWV6CaQujCzNKUfHzlha22rO5v2nRv6s9n-pKqk19NALHl4EhyGhJXLAIFK9hHmt9AcwRtn_Tr7FECBg~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 82e9ef39b8a4db36b18e02524c6ceed4\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:rtdga3imRaMxB1MBsYhOKFpGE_YTAdoXsoS-YotYJhU", + "signature": "0x4f18287ad1c9283761c52fa8691edf2b0ef2bc3928cd59ec77cc5095f8588ee908a8655c2631912d6ba2d271c0bae235b30b52f5bbfc0650aec16097d83da6fc1b" + }, + "nonceStore": [ + { + "key": "verifier.example\n82e9ef39b8a4db36b18e02524c6ceed4", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "not-yet-valid", + "detail": "not-yet-valid: credential is not yet valid" + } + }, + { + "name": "pl-iat-negative", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6LTEsIm5iZiI6LTEsImV4cCI6NjAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.5BTxlufbYPPFM0IOoLZwvyksDfPIADC3D8KW3gD4u3LboHDUw5FHoelO4cmsxskQ7wfVtEOeKtEt3uz3b5vFAw~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: d3212c3c5d5073400d019604a407c8c8\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:oZxZJ2FTfF1NiiXkIc6Whf4_enpKnaaFKPhNG1sRXo0", + "signature": "0x89ef9397e77bb85e514c97972766a2d784160d8f05658eb8d4aba21ccb32b98640f9524686bb92e1fe61025d5bfe604da513a5fb283b2ae1201f5cadd859fd731b" + }, + "nonceStore": [ + { + "key": "verifier.example\nd3212c3c5d5073400d019604a407c8c8", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "issuer-not-yet-valid", + "detail": "issuer-not-yet-valid: credential predates the issuer key" + } + }, + { + "name": "pl-not-yet-valid", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIzMjgwMCwibmJmIjoxNzY3MjMyODAwLCJleHAiOjE3NjczMTkyMDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.P-6ihi0u20QKtsaX-Nrt3NVRh3FOz8lVwbOWanQVVdkkevN8RfsQgVW0luH-P9ID2aMmA05Ocltuz2u4tTi7Bg~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: ae7d6ffa6e196812f0c299570514eb47\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:RSPY7lPjLZbZ2G529tD9n_tjLt958vwSXjny8o-XQuQ", + "signature": "0xd1c3461a5aeebf6875f8f04f9424167294171ec978b4f15513750c7edfb4c7301ab40636e2a18b8410702110a7967143e58d1b570983652f980b40178813bdef1c" + }, + "nonceStore": [ + { + "key": "verifier.example\nae7d6ffa6e196812f0c299570514eb47", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "not-yet-valid", + "detail": "not-yet-valid: credential is not yet valid" + } + }, + { + "name": "pl-expired", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc1OTQ0OTYwMCwibmJmIjoxNzU5NDQ5NjAwLCJleHAiOjE3NjIwNDE2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.vYNtnb74-0uqK557Q7rKFG0lh5OPPJjMmVXBIxZHPAWINBy8zocuFrlph42CV3Z0bG2yqv0svm1L9AJLBX0tBg~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 2d8892c17c44c95d6d3364fe82a61a61\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:iNsEZ8cjiCDcGSqanUjZVKry2HWQW7YCEPw49ALa-5s", + "signature": "0x4d5969c6eba6674729a36055ed383fa4c8db9490981eed1b1aa10c6c6c38ce7d7a67739a7c0d8553d1a09c11930d7676bf3eddbb97bc44139e285e0a818738981c" + }, + "nonceStore": [ + { + "key": "verifier.example\n2d8892c17c44c95d6d3364fe82a61a61", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "expired", + "detail": "expired: credential has expired" + } + }, + { + "name": "pl-exp-eq-iat", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3NjcyMjU2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.tpdUGU952n5Jh_wTsr7RWoeu1kJgHeW2CsOZ-qatZgJ617vG-ZrEHdrYovxvWrhuKu8egy5NXAhCeCcSV1NYDg~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 3fa2f54606e6622fcbb0a5312807dc0d\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:4asXjJJs-I8SS3M3YG6Cy6I5IRXVyKhpb6k8sRbeoyQ", + "signature": "0x8340273b307ebce1340596b8ec91e99144d54bc678d43d3ee672caca2b723c0d0986881e539dc1f49ad0348d64a47484fc5540f7fb6a36c1251c4f0de26043521b" + }, + "nonceStore": [ + { + "key": "verifier.example\n3fa2f54606e6622fcbb0a5312807dc0d", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "expired", + "detail": "expired: credential has expired" + } + }, + { + "name": "pl-lifetime-over-365d", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3OTg4NDgwMDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.uql-y1d0tnKwSJ0v1JoKWjUye0trQW0Pm03q8qpAbKpMg5JTIh2xdxlwgyy3CB94hbZBAeI-56KqYIuERckNAw~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 5c377d00daf89712fe482667e3333a8e\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:18QO1d8jCuehi8P0gr9JkFYB9zPizjPj3UsEDSlQxsk", + "signature": "0xd9c3f142e7772e69f5d11838082441ef65c8ee2568cb4a4b66a492d62fd3790258bb27c7405c20cb6e24243de734fbd0bff64dab541ebadd931fbeffe9a224cd1b" + }, + "nonceStore": [ + { + "key": "verifier.example\n5c377d00daf89712fe482667e3333a8e", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-lifetime", + "detail": "bad-lifetime: exp - iat is outside the row's lifetime" + } + }, + { + "name": "pl-lifetime-exactly-365d", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3OTg3NjE2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.jdNAb-JCjxWOzZ4BBvvMzv4Pa_-GwXM7qWpee7qL2khDGng-vhJuPKXn2CWVnBM-REzW1teGb1mzdnUPE0UOAw~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 7d8bc881af940a1130d47130973a4874\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:B_Qt3DfVPezumOpIWv4KE877ZPYBCDJj7UbLpFScYvM", + "signature": "0xd621f6ec0d08a312a933cfdae953b682efd237e470ed0096a454bad108ce0239618d55cb0e1ab0da6d5766167466c65ba316e19b3a1f040ede2eaaa0c8497c571b" + }, + "nonceStore": [ + { + "key": "verifier.example\n7d8bc881af940a1130d47130973a4874", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "ok", + "subject": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "issuer": "did:web:issuer.credentials.org" + } + }, + { + "name": "pl-profile-missing", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.KbqXiwzMFgSXLEOrqQzoNsH1C5Un0v2ehlWZtMYCMwpX9MUbW09qc3oLHaS3VuyDkuIK4a9-UHSW-scLidO4BA~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 00ab534710061f53f549229b8b34bab0\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:h5TxjSlrDaUpxW1bfeqwjAOtVq3VCh12pv0R331gcYs", + "signature": "0x70945bbcf18ce28ccaaf2ca999fa728a773185d73e7714739e996d338e97bf2a7d06a4f1c5a3b30dd9369730674c57e49b8285643217cda754a74cff6c8a10891b" + }, + "nonceStore": [ + { + "key": "verifier.example\n00ab534710061f53f549229b8b34bab0", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-payload", + "detail": "bad-payload: profile, profileVersion and vct are required" + } + }, + { + "name": "pl-profile-other", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQub3RoZXIvdjEiLCJwcm9maWxlVmVyc2lvbiI6MSwiaG9sZGVyQmluZGluZyI6eyJkaWQiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsInNpZ25pbmdEb21haW4iOiJ0aW55Y2xvdWQuY3JlZGVudGlhbHMvYWNjb3VudC1iaW5kaW5nL3YxIn0sInN0YXR1cyI6eyJtZXRob2QiOiJub25lIn0sIl9zZF9hbGciOiJzaGEtMjU2IiwiX3NkIjpbIjhFa2tTeUt0Y2xnNGNFdlR1ZmlLa2FCUmk2aEIxZ3hPc3NGZmwzTmthTzgiLCJXMGhUdUhlWmdSN2h6dF9KQXRESURXLWNMcVgyLV9HUURWS2Uwd2JHLWl3Il19.6zfBUQXNhhkYFGOTBuUwdSW13Uyz_RTTBFPuRLaONYfXNerEfLDootrcVq2THrOCsGkygJOOJUfka4awNH1wCw~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: e43ef7bc70414fa21970b5f1902bd9c7\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:YDKG5CDBxI8cU_ZbHDW46u5bvLavK_dLeriVj2EHXuk", + "signature": "0x9aec094ff8669e513f8cb9daac9cf74daa4938ab92f92c79c9150abc2d49d4641b3308bee6c7ac79c92561f3e38494f83baa21532aebc72a37be248300617c8f1b" + }, + "nonceStore": [ + { + "key": "verifier.example\ne43ef7bc70414fa21970b5f1902bd9c7", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "profile-mismatch", + "detail": "profile-mismatch: unknown profile" + } + }, + { + "name": "pl-profile-version-2", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoyLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.fFT-S0_BT9rxK8Gg8-hTrDXUbunmUCpYXReMfQVU4KwQlkJ5VcQRltqRLK8rVl1AiRRD441gp-qVItDx6Li8BQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: d4d63c9a15ac6b28c94d45e2b7497034\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:4xPkypqPfoBO0_92VPZPo7Ypxdhgnxgq9qpoAnzW1eo", + "signature": "0x043f1ad1a8c8ac4e944dcfe95cd089723dd072ffba79f1213e8920eb86ef6e547ba8009a6334a9b6e42090cdfc02fd0929909b5b961cd7a6de64a4eb7da586731b" + }, + "nonceStore": [ + { + "key": "verifier.example\nd4d63c9a15ac6b28c94d45e2b7497034", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "profile-mismatch", + "detail": "profile-mismatch: unknown profile" + } + }, + { + "name": "pl-profile-version-string", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoiMSIsImhvbGRlckJpbmRpbmciOnsiZGlkIjoiZGlkOnBraDplaXAxNTU6MToweGYzOUZkNmU1MWFhZDg4RjZGNGNlNmFCODgyNzI3OWNmZkZiOTIyNjYiLCJzaWduaW5nRG9tYWluIjoidGlueWNsb3VkLmNyZWRlbnRpYWxzL2FjY291bnQtYmluZGluZy92MSJ9LCJzdGF0dXMiOnsibWV0aG9kIjoibm9uZSJ9LCJfc2RfYWxnIjoic2hhLTI1NiIsIl9zZCI6WyI4RWtrU3lLdGNsZzRjRXZUdWZpS2thQlJpNmhCMWd4T3NzRmZsM05rYU84IiwiVzBoVHVIZVpnUjdoenRfSkF0RElEVy1jTHFYMi1fR1FEVktlMHdiRy1pdyJdfQ.cHn2V2eBOrQbjiX435qI6tFSG4r_cgax44fXfLTkD4f1rEMUxk2ES3cie1n8x__9iUbHjdObV6SePP5FuvSEAQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 68bce4342110a7b167c75dd0545cb826\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:gRAR0iVR-vqEEJvmeoq_jXgXYMfMIcINvz4lXx48UwY", + "signature": "0xe12be7e27e5d493e2b409e777457a24458d482d540e456f3f6f21ad00a9ee08a2e56278d2770d950c36c9595f219c554cae8c06c939864bcc174343d722a6b731b" + }, + "nonceStore": [ + { + "key": "verifier.example\n68bce4342110a7b167c75dd0545cb826", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-payload", + "detail": "bad-payload: profile, profileVersion and vct are required" + } + }, + { + "name": "pl-vct-other", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5vdGhlci92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.YJvnESR971pao5ax8puOJu3MhkuNzjKK1TrPnp9U8WMW2x0g9HdUbiVn_TUGuWaAIrmqBqAFny4hD8Bfd5BmBw~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: b18665a344d9139780b34a2b1accf701\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:UEtQNHdtStwC2DOQGVhRhsStNZynTsJHz6gyS9rZZak", + "signature": "0x6c8f37bee77ad9804d9ec5828c8a812a6c52030d05a275fe707df5e06b25f24d1befb236696adca598750cca65a1fe5812a1616ed066178926ced715ae08cee81b" + }, + "nonceStore": [ + { + "key": "verifier.example\nb18665a344d9139780b34a2b1accf701", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "profile-mismatch", + "detail": "profile-mismatch: vct is not the row's vct" + } + }, + { + "name": "pl-vct-missing", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.nwZQu-a158MHKbRk3A0vSh18hoOOixCgWyoopEAzCOEwjZmk8hgbBS__hEf-1DPzXBqdCtm700qHFF99DSh1DQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: ab4b1a50745a0971d52c1b4ee181bf50\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:pkFXSbbW8i51y3pOv6bm3p36pHqdu13vECOnQXqQTSw", + "signature": "0xc3fd963f4f7514c54f4205aea4d2575a4e626a885e637c5936d1b4e84af4fd3b6297b39c3f625fdb81e8d70754383911153a7dc594b747c830ca9c682a4d25991b" + }, + "nonceStore": [ + { + "key": "verifier.example\nab4b1a50745a0971d52c1b4ee181bf50", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-payload", + "detail": "bad-payload: profile, profileVersion and vct are required" + } + }, + { + "name": "pl-extra-claim", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXSwiZXh0cmEiOiJ4In0.3Zn66dK0wKl8r3FKw-NIStIZonYrtkSvTr9HG3MyqUVYKbLfxRh6PELHnbVU3zxARChsSkmqN_vYpCHX5suGBA~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 20c324ce2f031c532242c4e523f5e31b\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:kJa2aPO6AaCe6T9XOFD0qWaDYf19aJ6iRwsNRjvddlg", + "signature": "0x60b80298edea390a06aff41c49d7f34d16643c3650e5e1a1035f0d8d4826db1d4410654b458bdb1f7598b2c9ab69ed3ff47039448388d3cee876e51f694953c51b" + }, + "nonceStore": [ + { + "key": "verifier.example\n20c324ce2f031c532242c4e523f5e31b", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-payload", + "detail": "bad-payload: unexpected claim extra" + } + }, + { + "name": "pl-sd-alg-wrong", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS01MTIiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.IEc05_iKpnPfueClZq6TdwZmdOGd-MDo6i0UF-fVfLBqFbx7SWRPkRWXN7oJJZ1kFqMYKbjAkYAavlfOXiOhCg~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 3663fe07dc06bc3a52b3cc874e01d011\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:D0qrXoV_TeD6k4EDIRmX7Y9fXFcrKLeheUFel8Y2pe0", + "signature": "0x15d4e48d0f2e3ab70b2800e174a0ee3dea2ed1a37edb183ec32372cc717907d403a1b5793a808e72e54daf392e09dbdc3d5c51e7e5fd0552529f80298702cf9f1b" + }, + "nonceStore": [ + { + "key": "verifier.example\n3663fe07dc06bc3a52b3cc874e01d011", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-payload", + "detail": "bad-payload: _sd_alg must be sha-256" + } + }, + { + "name": "pl-sd-not-array", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOiJ4In0.jQBTqowp7XJIgOzv3IG91VgK7rVz7J95IajHVV-kcvzyPK4AjBiPantx7WDPgLnS3nc41RUNpJ_hsVtniMojAw~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 593e908bb91cc33a1d3538cbe0fa3473\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:xF9ycIFbx6G-WmH_zsUBQG27Akgd_lN9p35suZ3bEtc", + "signature": "0x8954f82ab0bf3656e4cbda978ceddb24e0f80a89b68641bcb2ccd82aae4cb58148fe964533564be3ec545d7365a0f434c4a6e36f1216057d4b6a133bf16e1e201b" + }, + "nonceStore": [ + { + "key": "verifier.example\n593e908bb91cc33a1d3538cbe0fa3473", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-payload", + "detail": "bad-payload: _sd must be a list of digests" + } + }, + { + "name": "pl-sd-nonstring", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsM119.vKplon_vgzlCsXj13mzF3-H8L-StG5ypF3ubAx8caNtrI5-04lEUeN5uYIl-d02jgS3JfdP5jT9h58CCvzGdBg~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 079818e11244431ca5e3f587a45424d7\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:JpoLGNmrJbN3QZwxDqGgpOzkmn04Av7zshUsRVBFMTw", + "signature": "0x37b227d37968b8218cd65be2cad97389baf9bb13662a606814842b5abf8868807db3d7e12de26cc6081336b51de6b896f387009e52302d8f4ff2c80662dc25161c" + }, + "nonceStore": [ + { + "key": "verifier.example\n079818e11244431ca5e3f587a45424d7", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-payload", + "detail": "bad-payload: _sd must be a list of digests" + } + }, + { + "name": "pl-sd-duplicate", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIjhFa2tTeUt0Y2xnNGNFdlR1ZmlLa2FCUmk2aEIxZ3hPc3NGZmwzTmthTzgiXX0.R1EAHWhG4ujtFLVANGbSAa_rPOk3ghfiLNjf-ByrEePc8VaB-WW1r1d8fSiyge_LHHDr560JIgRqpTpNEDuDCQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 6bc8fe9b7b24f26d163844bb4087cb4a\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:oGFq8utQiGJcDtgNw7ym8l1E-9rMbYGL4zleCIkITDM", + "signature": "0xb3622cca03d079cd1f0737851e39b579f183d030ba9b952d952d8c0ed86e911d49489c1546c4879a422aed8e58b3ae8eba33c70c31c4565484f8a098bd87355f1b" + }, + "nonceStore": [ + { + "key": "verifier.example\n6bc8fe9b7b24f26d163844bb4087cb4a", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-payload", + "detail": "bad-payload: _sd must not repeat a digest (RFC 9901 section 7.1)" + } + }, + { + "name": "pl-jti-not-uuid", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOmFiYyIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.t7VAuAQO9hzvKGuGf85Uv_VzzX5acN2TJWooQlbrZdTtUb0mEJuQ0iuxmNxRKhwjsRqcC-bAn0RZU46J_Pv7Cw~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 7324151097a2dacbe0a105e1f5815017\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:u8NTyBeaOImj307P1EorIwKkO3lXW1bUpPnVI64Js_A", + "signature": "0xf8110a8b7777810db54000f8c3461ee7740a0ca39e44d94d81681700ed55b36c63e97799c36d85cd7076768b07732970cf9385c0d2a4280df6cab505a32e68f41c" + }, + "nonceStore": [ + { + "key": "verifier.example\n7324151097a2dacbe0a105e1f5815017", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-payload", + "detail": "bad-payload: jti must be a urn:uuid v4" + } + }, + { + "name": "pl-jti-v1", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtMWQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.VvACpd3Xp_xMKBVRE6kRD3ioXlbKAxOojYlTaWQEIYgNk1KUQlnkNRZfggOOnOwLKucCa8VmiXpq9HuFtN0LBQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 708f075fdf998659e9e2af4a0453e3e4\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:vZ9Sbf0ox8J8JfYU0c0nN2hSWe-ihNQOHMXGwj-Mcpk", + "signature": "0x1d106b3d177b52fc8318e60c6823747b4e248507ceb96c28928a3d94de1177e93370a8a161c0b1d0307562fe9d4535d8b59d4f4944a740e50a233fc6c591b8081c" + }, + "nonceStore": [ + { + "key": "verifier.example\n708f075fdf998659e9e2af4a0453e3e4", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-payload", + "detail": "bad-payload: jti must be a urn:uuid v4" + } + }, + { + "name": "pl-jti-not-urn", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6IjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ARes-9lLZTDKBexAcLzyE0gOQWMgHsguEc388TcGmVrU9nhIi4rQGAxjgBs3cSG0GARQy3mnvPXi1FuCqVylCA~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 9a308c2b97083030831c980be1308011\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:u-1ySLfGnmdeqrvnLrQfnU2VWVy_P4INyW1S6Ymoaf4", + "signature": "0x2ccefa3bc6f9f25dd930777c22c860cae98a7ae4da8f9f3e0a69b0129cc6687643b6ab06c8249d5177521e9db336e516448cd548d0bf4e643b959654b43464221b" + }, + "nonceStore": [ + { + "key": "verifier.example\n9a308c2b97083030831c980be1308011", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-payload", + "detail": "bad-payload: jti must be a urn:uuid v4" + } + }, + { + "name": "pl-status-other", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6ImJpdHN0cmluZyJ9LCJfc2RfYWxnIjoic2hhLTI1NiIsIl9zZCI6WyI4RWtrU3lLdGNsZzRjRXZUdWZpS2thQlJpNmhCMWd4T3NzRmZsM05rYU84IiwiVzBoVHVIZVpnUjdoenRfSkF0RElEVy1jTHFYMi1fR1FEVktlMHdiRy1pdyJdfQ.3SgPyBJO_oNfkzPAmduU9pe05eITvHwLUR1mrMu94wDhpUDlkHlMOSyJ-hnyL7O_fM3_4TTx9G3XpXqhIEdSCw~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 2d73289559be3dcf66def73616d9d161\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:LGiwIh4oP4B4nzAQPYpi2gCW6Vah2PWFIXoWDU6W1kE", + "signature": "0xf9785ed8eacee62143122d94b36059a3331f21b722185f9a97cd67ba5194e16b11f085a49d3b3ad382a2c7e22f38d6bb6e479289c324e5b105646aa9e692f2231c" + }, + "nonceStore": [ + { + "key": "verifier.example\n2d73289559be3dcf66def73616d9d161", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-status", + "detail": "bad-status: status method is not accepted" + } + }, + { + "name": "pl-status-extra", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUiLCJpZHgiOjF9LCJfc2RfYWxnIjoic2hhLTI1NiIsIl9zZCI6WyI4RWtrU3lLdGNsZzRjRXZUdWZpS2thQlJpNmhCMWd4T3NzRmZsM05rYU84IiwiVzBoVHVIZVpnUjdoenRfSkF0RElEVy1jTHFYMi1fR1FEVktlMHdiRy1pdyJdfQ.SZU3OUimlZ6b2Vn-Ts-5RDTNRfK_3raO6T0FhrvQiIM0TVAWV9GvV_EGv3h-B01mdJw2nTryx5m2HqDWFmrZAw~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 3e77375181fccd3336ff24f6327324ce\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:FhmkD9DxPkS7YSNt10XYVKQKw2PKev-GQFRZ5kdLM8I", + "signature": "0x64d586cf3a595a8333bcf8349e4773c16556fede3985ff85a9362ae74d9eba7c4b483ce56f35520de2ce3a49dd8bc38f7fd6780c3a75fda5724a75d06f48e10a1c" + }, + "nonceStore": [ + { + "key": "verifier.example\n3e77375181fccd3336ff24f6327324ce", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-status", + "detail": "bad-status: status method is not accepted" + } + }, + { + "name": "pl-status-missing", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.tHwIQ7P5_PV_sEAEuMa_JhEPnPudRlP-FmNkwc6NUF7KULbYOtJZNhRSYnoEW2ZBsmN-7-JmeczOcTmDQZRlBg~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 80ee4d5bf83ec1da32ac23472856b59a\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:0j6CXxJRXYguag5OZ2HniRsMJKr1jIIgAm2emm1yvbU", + "signature": "0xc559de0ee5948a8cd661faa537aec9d69c84595f447a984c691e261315ccfbfb25a6dd27c8d9985f44c699585a656d43b05c97b694103014fca930e1896c4b341c" + }, + "nonceStore": [ + { + "key": "verifier.example\n80ee4d5bf83ec1da32ac23472856b59a", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-status", + "detail": "bad-status: status method is not accepted" + } + }, + { + "name": "pl-sub-not-pkh", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJtYWlsdG86YWxpY2VAZXhhbXBsZS5jb20iLCJpYXQiOjE3NjcyMjU2MDAsIm5iZiI6MTc2NzIyNTYwMCwiZXhwIjoxNzY5ODE3NjAwLCJqdGkiOiJ1cm46dXVpZDowYjZkMmM0ZS04YTFmLTRkM2UtOWI3YS0xYzJkM2U0ZjVhNmIiLCJ2Y3QiOiJvcGVuY3JlZGVudGlhbHMuZW1haWwvdjEiLCJwcm9maWxlIjoidGlueWNsb3VkLmVtYWlsLWhlbGQvdjEiLCJwcm9maWxlVmVyc2lvbiI6MSwiaG9sZGVyQmluZGluZyI6eyJkaWQiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsInNpZ25pbmdEb21haW4iOiJ0aW55Y2xvdWQuY3JlZGVudGlhbHMvYWNjb3VudC1iaW5kaW5nL3YxIn0sInN0YXR1cyI6eyJtZXRob2QiOiJub25lIn0sIl9zZF9hbGciOiJzaGEtMjU2IiwiX3NkIjpbIjhFa2tTeUt0Y2xnNGNFdlR1ZmlLa2FCUmk2aEIxZ3hPc3NGZmwzTmthTzgiLCJXMGhUdUhlWmdSN2h6dF9KQXRESURXLWNMcVgyLV9HUURWS2Uwd2JHLWl3Il19.fFOyIK4yx2swOXAAsD4KH-MW2aerieUFw4GAga1qCk3OCMuR5yGOKPDp54zpjpP7fnhuoKaU4aZat1CRqwgHDw~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 307562290edbab09d44de5ca9d0a880b\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:V9VJdQ8HlXI9PLg95FpAakjmYzFNgpeBKl6aTQ4ZsGw", + "signature": "0x61768ff88dfdcc433623daff8bef45dbb700c368076c13ad3331c2a374d0452619080ab03d805a3e03988625b529f86359d2c06d8aa1807790fd169df5b4799b1b" + }, + "nonceStore": [ + { + "key": "verifier.example\n307562290edbab09d44de5ca9d0a880b", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-subject", + "detail": "bad-subject: sub is not an eip155 did:pkh on the row's chain" + } + }, + { + "name": "pl-sub-other-chain", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxMDoweGYzOUZkNmU1MWFhZDg4RjZGNGNlNmFCODgyNzI3OWNmZkZiOTIyNjYiLCJpYXQiOjE3NjcyMjU2MDAsIm5iZiI6MTc2NzIyNTYwMCwiZXhwIjoxNzY5ODE3NjAwLCJqdGkiOiJ1cm46dXVpZDowYjZkMmM0ZS04YTFmLTRkM2UtOWI3YS0xYzJkM2U0ZjVhNmIiLCJ2Y3QiOiJvcGVuY3JlZGVudGlhbHMuZW1haWwvdjEiLCJwcm9maWxlIjoidGlueWNsb3VkLmVtYWlsLWhlbGQvdjEiLCJwcm9maWxlVmVyc2lvbiI6MSwiaG9sZGVyQmluZGluZyI6eyJkaWQiOiJkaWQ6cGtoOmVpcDE1NToxMDoweGYzOUZkNmU1MWFhZDg4RjZGNGNlNmFCODgyNzI3OWNmZkZiOTIyNjYiLCJzaWduaW5nRG9tYWluIjoidGlueWNsb3VkLmNyZWRlbnRpYWxzL2FjY291bnQtYmluZGluZy92MSJ9LCJzdGF0dXMiOnsibWV0aG9kIjoibm9uZSJ9LCJfc2RfYWxnIjoic2hhLTI1NiIsIl9zZCI6WyI4RWtrU3lLdGNsZzRjRXZUdWZpS2thQlJpNmhCMWd4T3NzRmZsM05rYU84IiwiVzBoVHVIZVpnUjdoenRfSkF0RElEVy1jTHFYMi1fR1FEVktlMHdiRy1pdyJdfQ.vycAgBCKI6jgaxdTq3a9REnBNaQDxFubWZi-tKCc0iYHPJGETK3hLjtlcLUGJVGt6hROPHW7eLCFA8wTyipwBQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: f4f6ceb7ffeca98fe02dd5e799722aa4\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:E2A1LOfNO15uvnRRIruQ6O9SGk-xCVMg09e5VjeLY0M", + "signature": "0x8ae310710d13d6ff04cb2109229d44d1b3672121c6f2397eb7db3bd524f6fc4e72eb01ae012eab66c7e17c3e660bdce4c63001b7da4cff4f3f4194353e48874e1c" + }, + "nonceStore": [ + { + "key": "verifier.example\nf4f6ceb7ffeca98fe02dd5e799722aa4", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-subject", + "detail": "bad-subject: sub is not an eip155 did:pkh on the row's chain" + } + }, + { + "name": "pl-sub-missing", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJpYXQiOjE3NjcyMjU2MDAsIm5iZiI6MTc2NzIyNTYwMCwiZXhwIjoxNzY5ODE3NjAwLCJqdGkiOiJ1cm46dXVpZDowYjZkMmM0ZS04YTFmLTRkM2UtOWI3YS0xYzJkM2U0ZjVhNmIiLCJ2Y3QiOiJvcGVuY3JlZGVudGlhbHMuZW1haWwvdjEiLCJwcm9maWxlIjoidGlueWNsb3VkLmVtYWlsLWhlbGQvdjEiLCJwcm9maWxlVmVyc2lvbiI6MSwiaG9sZGVyQmluZGluZyI6eyJkaWQiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsInNpZ25pbmdEb21haW4iOiJ0aW55Y2xvdWQuY3JlZGVudGlhbHMvYWNjb3VudC1iaW5kaW5nL3YxIn0sInN0YXR1cyI6eyJtZXRob2QiOiJub25lIn0sIl9zZF9hbGciOiJzaGEtMjU2IiwiX3NkIjpbIjhFa2tTeUt0Y2xnNGNFdlR1ZmlLa2FCUmk2aEIxZ3hPc3NGZmwzTmthTzgiLCJXMGhUdUhlWmdSN2h6dF9KQXRESURXLWNMcVgyLV9HUURWS2Uwd2JHLWl3Il19.RgECJr0pLo8RHYYYOkb3rIv-dKpFjdBmII8NIbv13eD3vGDxG2_0PiLQzmWXtOI_L2UTcGf7jDnKzYA9ELQVCA~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 257c08fb992725b430b744a25c5c77fc\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:_EherA4M8yJp1J3cnb196CbVcNtNG06gGk7MWjieSJo", + "signature": "0xa03a0385e3bb175278a4b884778e11f039c4f3d65aa356b7dec6693bf400d6810a8a3d35c3f0083face0ae3416ebb9db2afc60277d51dd9d9f437ce9c57d887a1c" + }, + "nonceStore": [ + { + "key": "verifier.example\n257c08fb992725b430b744a25c5c77fc", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-subject", + "detail": "bad-subject: sub is not an eip155 did:pkh on the row's chain" + } + }, + { + "name": "pl-binding-extra", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEiLCJ4IjoxfSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.bTocW-cCCFWEGomDxU10UDfe1Ih-Nrt8y1LNk9KT0ggFobgD__3J5OsMTuMuvqIp318iC6MDbeG-j_mIfYuQAA~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 8282a0153d969d533af961c831ede05d\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:tMPzuK9m-kHnh4SJ0FsS1TLGGkddphsh-JdPHzYnPbM", + "signature": "0x805e0984b983edffd00141c233d7c054fa249011c0613d4e1146556bb7f458c67ef841ea9158bb568e9bed079f99c22a78f44ea79d533fdefc87b9d7103cc04d1c" + }, + "nonceStore": [ + { + "key": "verifier.example\n8282a0153d969d533af961c831ede05d", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-holder-binding", + "detail": "bad-holder-binding: holderBinding does not match the row and sub" + } + }, + { + "name": "pl-binding-domain", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6Im90aGVyL3YxIn0sInN0YXR1cyI6eyJtZXRob2QiOiJub25lIn0sIl9zZF9hbGciOiJzaGEtMjU2IiwiX3NkIjpbIjhFa2tTeUt0Y2xnNGNFdlR1ZmlLa2FCUmk2aEIxZ3hPc3NGZmwzTmthTzgiLCJXMGhUdUhlWmdSN2h6dF9KQXRESURXLWNMcVgyLV9HUURWS2Uwd2JHLWl3Il19.bF2t5c0AkddGPi-N7JVJmtuhbYtIhAdaZPX_RA8wF0-ESF0S2ttWcyksVZ3FTdsDsNHbXHmZAsTJa8NibyziCA~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: b23c208dc36da134c22f00a512282958\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:vmgS6G6KA13JO8m-KlvC7LmZ7kxH3DxeE7FlyBNN7T0", + "signature": "0x49cd6c997b6adf455480ab19d14ee8757be85df7bb4e4461fb0442ae685108454e90b2db8af439a24bd9bd3fc906fad27779c290d43fafcd8cf210bb7337dfd91c" + }, + "nonceStore": [ + { + "key": "verifier.example\nb23c208dc36da134c22f00a512282958", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-holder-binding", + "detail": "bad-holder-binding: holderBinding does not match the row and sub" + } + }, + { + "name": "pl-binding-did-mismatch", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHgxMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExMTExIiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.YTDcUMGrTaOl5nvCFnZG289O2p3RTA-tQRqKqXatMkMDiGi2CMffnRgqv4rx9H-iJjq4gHCHrp-TkjNgqkbgCw~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 1fcad4048c430f04499cabc46c7fa975\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:0ZawXoBvlVwvXP5i8jc7ZmlvPjrwo2fhVTLGFauhRyg", + "signature": "0xd5b9f8ce7ab60c4b5428dd88cbac7fce435cdee8e65e6029e50f1412313b6215762504848e23cc0105582b9d0a42c0b0be7ec1916696df71f2992836f9d9c7a51c" + }, + "nonceStore": [ + { + "key": "verifier.example\n1fcad4048c430f04499cabc46c7fa975", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-holder-binding", + "detail": "bad-holder-binding: holderBinding does not match the row and sub" + } + }, + { + "name": "pl-binding-missing", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJzdGF0dXMiOnsibWV0aG9kIjoibm9uZSJ9LCJfc2RfYWxnIjoic2hhLTI1NiIsIl9zZCI6WyI4RWtrU3lLdGNsZzRjRXZUdWZpS2thQlJpNmhCMWd4T3NzRmZsM05rYU84IiwiVzBoVHVIZVpnUjdoenRfSkF0RElEVy1jTHFYMi1fR1FEVktlMHdiRy1pdyJdfQ.PXMbCL5wG0LNTdh2vqoEEmXIx7341vu134Tbph4-nezemi2SUsxmlqesCKPiUtFzLoICuu_t7uoHRYu0eulBDA~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 4b10df1d9298b563b654b027cb6c2767\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:0Aq25_dJZ1fHJLrsBkeMq4MztqozTrNHNNckfu_7Ysw", + "signature": "0xf96f5aee8f6e92431564e8de942ca29de0b1af89a552b9ca23331f02a82e742e53442b46523d88827b9d37357d04c371b19c1120b223e831fbcab4aa1ab0019f1b" + }, + "nonceStore": [ + { + "key": "verifier.example\n4b10df1d9298b563b654b027cb6c2767", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-holder-binding", + "detail": "bad-holder-binding: holderBinding does not match the row and sub" + } + }, + { + "name": "pl-payload-array", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.W10.7NPNyK5PluXLCwNUrBN9Ma43hwYFSjkvJt6gsQb0Xd6u4exFtt_kJyl96Dzspy3aFlCuwDfVzBoARAzZt9yFAQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 10199e64ddca03a77d619adc0a2ce856\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:QHrcOBX1TvJuC2sFOLJbeB67m6qkjSPjgCnpmJyzpaQ", + "signature": "0x3a4113e3388747923d9566ede37058c3949547f0eda624027cc6ff7cd54b80f52eb1d42c5741f8ef71f89db361e27bab78aa5dfd5c651291af9f93dce9e930b61c" + }, + "nonceStore": [ + { + "key": "verifier.example\n10199e64ddca03a77d619adc0a2ce856", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-payload", + "detail": "bad-payload: payload must be an object" + } + }, + { + "name": "pl-payload-dup-key", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmcifQ.RUA9WrfnZZ8jtawZ12tHuQl_8QhWCnCBLvd1WntvvIH_efknODrheq0p89ueG29H4JKbWNa0o3Xse4HL_YutCg~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 4e279cd83116bf721d0af06d9544fd37\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:P6-2DCyXYHn56zUTDay3TNch8jI_JeRH7SXCwbh-Gp4", + "signature": "0x397579d595a3f1e5abd4c99c0051ba79e5993f98b553824705d56528375c0fc7129b48dd798dc35e361144cbffcf93c7c6bf9887f7482cea59a42dc0980c22951c" + }, + "nonceStore": [ + { + "key": "verifier.example\n4e279cd83116bf721d0af06d9544fd37", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-payload", + "detail": "bad-payload: invalid JSON: duplicate key" + } + }, + { + "name": "disc-digest-not-in-sd", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJvdGhlciIsImVtYWlsIiwiYWxpY2VAZXhhbXBsZS5jb20iXQ~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 2e7e347b50c86a0a594cb9aaa78dc7dd\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:yfEyfuHIc-Ja8yEhVYdtR1xWFWAGOTgYVy5V6j38TRk", + "signature": "0x1a2a5f2c52d56786cace7d7a7f7d6909988da5efd4cf39ce712861ada8697b686bc4cebff5c6d5dc0b3b2b59f7c0e8676c4f3a830f903566f00bd0be963b85351b" + }, + "nonceStore": [ + { + "key": "verifier.example\n2e7e347b50c86a0a594cb9aaa78dc7dd", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-disclosure", + "detail": "bad-disclosure: disclosure digest is not in _sd" + } + }, + { + "name": "disc-repeated", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCJdfQ.xrxQU4OVUZTBLRWypC_eK4groxR68Gaqe4dFCXMsIl_6xRymjhOshJ64M7UzvIZ4ywsuZxZtYYA8LMIm5ePuCA~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 968637ccd919018e1f4506baa53732bf\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:Xz_FnI9MAJxFHg_wq08MhzZ61NThlqfVcjV8hPTyBC4", + "signature": "0x60347ae6f3f1967312fe67ab28fbad733cdb89c05c2a472990cc6068391f1dfe4a4dd4e96fd54fcf44c7635218402ca7f32bd52daba940120e91f3122875735c1c" + }, + "nonceStore": [ + { + "key": "verifier.example\n968637ccd919018e1f4506baa53732bf", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-disclosure", + "detail": "bad-disclosure: repeated disclosure" + } + }, + { + "name": "disc-not-base64", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~@@@~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 610f87e1ed58568109e1e8963f449d39\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:w3LkmVaPOV8iDOB-Q3DJiW4B53RNh6LsHzdBPAZnm4Y", + "signature": "0x970e8bc8af585593e2e840bd5298af8886fdd32de4f42e370298c6cbeacac1571602ab1bc45a69a2830586e17a8d0cbff11d4b56c6f1e8c4a085f37d7e0560781c" + }, + "nonceStore": [ + { + "key": "verifier.example\n610f87e1ed58568109e1e8963f449d39", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-disclosure", + "detail": "bad-disclosure: disclosure digest is not in _sd" + } + }, + { + "name": "disc-not-array", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~eyJhIjoxfQ~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: d527984f41940852c7fa6ea3e7752481\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:b1ewFded7AjrVLI8AKyd3BlPQ7c24rFy6JuIugEtj-w", + "signature": "0x83570a7b57256807980dde7b9629cb573067cb84bec7200285b1c936bd632acf5d2aa4c42c0193371c38140eb38f194e88856fac7fdfb0532ecac97fe77045b81c" + }, + "nonceStore": [ + { + "key": "verifier.example\nd527984f41940852c7fa6ea3e7752481", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-disclosure", + "detail": "bad-disclosure: disclosure digest is not in _sd" + } + }, + { + "name": "disc-len-2", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsidEg0VXlNMHkwcTJEUG8tajhQQVI3UVdqa1Zrb3dacUxGekVZbWVLSVBsZyIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.vbQvrBGHdCGKeyCZlbF5GQiKWCkIipBLbQBFZOiv6VTLHxYL81bCbx2SvvpKCRwJkK1QKKKda8l5OpoSYOA9Ag~WyJzIiwiZW1haWwiXQ~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 798ac73c6b6d9e5bb1d8d67ed3276745\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:HDIRKe3WACoOODT5pgTd4JEB9jlrvl7xfbl3IByjs30", + "signature": "0xfdb69f74cc7d4b6926b3c0a2e22364ea89568eb6fac1cfa2716dabf030d9e4140273fd13afd99bf92bb91e0302013694168832ba6c5a3088eb1be9b822a7a52c1c" + }, + "nonceStore": [ + { + "key": "verifier.example\n798ac73c6b6d9e5bb1d8d67ed3276745", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-disclosure", + "detail": "bad-disclosure: disclosure must be [salt, name, value]" + } + }, + { + "name": "disc-name-number", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiT1kwSEdlNjhia2M0ZjA3bnl2WjB2ZnJVT1phMENEZl9jbExDellZeV9IOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.IEKQUu0nqrohsDRexfIWNBzHVT5AjWNQ_137MOYA2YzIVIZBhtyD8orNdHl20zjw3MG3_6kT1zEeMp04ykZZBg~WyJzIiwxLCJ4Il0~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 991173afc106e61c3072389a969f0e13\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:JQzPKbPdTD3JJlvgSMZjlXNufq84rKwo97nSQY4Wt4M", + "signature": "0xbaccd0f326c6b248ff3fa1b3faba045ccb8fdd7284e2b12ccfeb80593c9c8600572f3d10711d3b8fa7b2b2d6e8c3251ebb912ab25c37e6c4c43d0692c3ea79bc1b" + }, + "nonceStore": [ + { + "key": "verifier.example\n991173afc106e61c3072389a969f0e13", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-disclosure", + "detail": "bad-disclosure: disclosure must be [salt, name, value]" + } + }, + { + "name": "disc-salt-number", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsid1JVc3JETmtvYzVmdEFfbUFGa1Y0WHZBcXp6czJPNEJ6dTA5bjVnSjNhYyIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.wzYIpzoBYDOHYlEzUFAipTyMDoVo5jzfwghzhomlV96jXWlJ2zQhKZT9Hv9kaQPPjbco-BQjLOU3umSWHorCCA~WzEsImVtYWlsIiwiYWxpY2VAZXhhbXBsZS5jb20iXQ~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: a249d696edd2f3dcd4858cdeb5fff73d\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:ElUpEsodMOUWSltwBQUTfp47mNxjaUL1bsWNf_Abr3o", + "signature": "0x8190834f5d57e74dfeee1a1ae094f31a648a01c646ba8bbe872409b353169683612cc1f739b4782d48e572d266f930699e7cffc9cdcdd2a582c70b25dab27cd71c" + }, + "nonceStore": [ + { + "key": "verifier.example\na249d696edd2f3dcd4858cdeb5fff73d", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-disclosure", + "detail": "bad-disclosure: disclosure must be [salt, name, value]" + } + }, + { + "name": "disc-value-number", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiNzA4OWl5VEVMUTJlVHlqQ0lYTmtNNXc0UVZhbW50UWJwRURVTmJydnBnOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.yFsZdFcjB0i9UtqSBDPoH_z4S4FE4M3j4-5Ktz59lG30jyDQ4PKBm4UsMBfoPbXEqFljaq5QLHhA9H6QUFOcAw~WyJzIiwiZW1haWwiLDFd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 1f78d31f128ab4e373ff9ead65e5b828\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:ixSWAr943VCXf_AAz3MyyB3haHoUUeagcDhk8WL6JWg", + "signature": "0xf01d85b441088fa3481bac2a7b1215c954f7c7355a807f453f38ad79532bb40078f4ea54cda6da76a4b46c2850a36bf844f46e5aa7084c2820c0ce0233b39cd41b" + }, + "nonceStore": [ + { + "key": "verifier.example\n1f78d31f128ab4e373ff9ead65e5b828", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-disclosure", + "detail": "bad-disclosure: disclosed value must be a string (no nested _sd or array elements)" + } + }, + { + "name": "disc-value-array", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiY1JGRkxoNkxHV2c5Rmo3RWZfSm84MGFVLVRDbktVUjhSa29tS3MzT0lhRSIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.OIFwX0NLDj9ZSuPP2fHAVEn8Ciigvd3kxeHiy-cBttJUaBSUITyWL1gVzO42Vs0Q1Bd0FcUyjj-rV4S46XvADQ~WyJzIiwiZW1haWwiLFsiYSJdXQ~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: fd88f96c7df3b68d7e2c4e61ea94dd04\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:5ZpdF9L78447mosRfOUENi4_F7r36pdm8Nram7i6F1w", + "signature": "0xc00516076f92c6fdb73b4501cd198b8c0bb03adf26cd93634ee685ec51e0be621d732d0aa629e7fc8439ea451cd78f04f154fed8cd261c0cc8d664c26ea0d1f11c" + }, + "nonceStore": [ + { + "key": "verifier.example\nfd88f96c7df3b68d7e2c4e61ea94dd04", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-disclosure", + "detail": "bad-disclosure: disclosed value must be a string (no nested _sd or array elements)" + } + }, + { + "name": "disc-name-reserved-iss", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiaXJINmVOTjFnbDB0TldvWVg3aWp6aHJBZUx5N05rUmpjZjFsQ1NwaG9WSSIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.onW-uhCBUXZIeHTMOJ0DdZYgfSiD43vvrzyYwdRARjkgyfwQcub7-mLuiub99WSin5J8bWx4xf69qYI46fdvBQ~WyJzIiwiaXNzIiwieCJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: febf4d4522a0aed799b7f3c8d89c5270\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:owsVm_9F_85XyPY_IwDI6DEwGYV_pma0fCuDZhE6v5E", + "signature": "0x34b4921cc10aef04064b8e631d76098fdcdac6bc0f13a55b96115d8c4ba7e26f568cd793d5f65bba9d01e80b8b2f227af90bd1ae0bce7544236f1b456c2f2f421b" + }, + "nonceStore": [ + { + "key": "verifier.example\nfebf4d4522a0aed799b7f3c8d89c5270", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-disclosure", + "detail": "bad-disclosure: claim name collides with a signed claim" + } + }, + { + "name": "disc-name-signed-optional", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiR1lkaHM3aE5zNXlJRmQxYnF6VmY4eTJTdzdxLTdXYjJLVGhCaGZSV2d3QSIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ODKtT7aGokFD8WSVyapkEsYAXQNgtxrs0Wd6WBnHrVo-30y3HpfuuEwyutH47YcNSc8qo58oghLTczdsGnJEBw~WyJzIiwidmN0IiwieCJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 812cfba8db246d4076cf2d53dd4317e1\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:u9fWG1M6xTewLeE1sa_O3Dc6RmPowZVNedWTFZ2oIPw", + "signature": "0xf9af316dc7313abe735a9d413ad17d20895868e36ccb37e768b15ad7dd372f403d64264c952ae3e0dcc0b9ccf8a818b876bfa69722233e1087d3ba1dab3a25c51b" + }, + "nonceStore": [ + { + "key": "verifier.example\n812cfba8db246d4076cf2d53dd4317e1", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-disclosure", + "detail": "bad-disclosure: claim name collides with a signed claim" + } + }, + { + "name": "disc-name-not-disclosable", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsidGFGWEVvQy0xTVYxUUFBOTlvck90QUZvdzJaMDFmNWIzdVRwMXZ6WlB0dyIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.24wq_mvBWLL120WtC74XsZyb_9NpVmI71eipJO32szIvHepqszwJSpZ5B0rDnyaSDjAW4KKoNMwxXFYWMeSODA~WyJzIiwibmlja25hbWUiLCJ4Il0~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: c594ec2dd94662fb7c2ec74e90f8ffd5\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:fxX6ta1Mo1hFKsnBMUiK1IMwITCdHm8O0fA2xAapEl8", + "signature": "0xcb365fa02bb81a6ce41df283ccc53ee96bf25b4f247f77115b0d330c995ac3333fa0a90731277288ed6108e91039126a7294105bc9e5f696aca1ac2f39266dc51b" + }, + "nonceStore": [ + { + "key": "verifier.example\nc594ec2dd94662fb7c2ec74e90f8ffd5", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-disclosure", + "detail": "bad-disclosure: claim is not disclosable for this profile" + } + }, + { + "name": "disc-claim-twice", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIi1RMXBnVHppc29FU282ZEE0RmFMeWlkemI1Z3I1UEs1ajhlZ080aW4tc28iLCJXMGhUdUhlWmdSN2h6dF9KQXRESURXLWNMcVgyLV9HUURWS2Uwd2JHLWl3Il19.JBwUb4o3BPKYuXXadW4lQ8DZnCLYA8zSXeuU4me6tFkjlHwcbPrvSX9B7iGPNgGEe9XuYLOpMTg3FpD9leUwBQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWVtYWlsLTIiLCJlbWFpbCIsImJvYkBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: a25327cdab712a0a06a5592eab04e264\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:Qc2eUDt3e7MevHTWI9nir-wnfhBlETNAFXG2TCORy4g", + "signature": "0x188146394b4a79839a57b4465134aa956947e024b3433b81b9c9ee08821f8eb950d816abb8e05c38dfeab0209452c17899be93bdae259bc97fde50026b7328721c" + }, + "nonceStore": [ + { + "key": "verifier.example\na25327cdab712a0a06a5592eab04e264", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-disclosure", + "detail": "bad-disclosure: claim disclosed twice" + } + }, + { + "name": "disc-missing-domain", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCJdfQ.xrxQU4OVUZTBLRWypC_eK4groxR68Gaqe4dFCXMsIl_6xRymjhOshJ64M7UzvIZ4ywsuZxZtYYA8LMIm5ePuCA~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 2d4f26d9e5504e99b986e6646d9e34e2\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:TKQtLNzUcu5dTjYBrVvDNfOfyRbi6qvqYW0uqYHZ1GY", + "signature": "0x4f0dcdc19abe033661c19ef524e99923fda1f23289a0e8c9d19d6f3006a881034f91591c608334140703d94aaeb8584307439902c60fb5bbb2c254f734f13d4a1c" + }, + "nonceStore": [ + { + "key": "verifier.example\n2d4f26d9e5504e99b986e6646d9e34e2", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "ok", + "subject": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "issuer": "did:web:issuer.credentials.org" + } + }, + { + "name": "disc-missing-email", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiVzBoVHVIZVpnUjdoenRfSkF0RElEVy1jTHFYMi1fR1FEVktlMHdiRy1pdyJdfQ.AZZO682jQENQ5xMnwXiBr9DaoTa8WCLjeoznBfCJGcel9PNKxnkO2pXY8fpQEsTXuAjbkFSWLDj8GQzPlyzOCg~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: c549263ac7338a69143fa9619e942b7f\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:WCpnT7Mchs4R9WKuvqMTQWk3_se8ylSznBzoek3djik", + "signature": "0xbb699c0083d50e42be46863f8f747d7a098c46637ada831c110641d9bc36f2fe2ebca781c49826893be50a441d84e5111eaaa800914a1743c4643b8424e264351c" + }, + "nonceStore": [ + { + "key": "verifier.example\nc549263ac7338a69143fa9619e942b7f", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "ok", + "subject": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "issuer": "did:web:issuer.credentials.org" + } + }, + { + "name": "disc-domain-mismatch", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIm9rOWN6cjBqdGFtazBhVkpIaXBhb1FXVFVvamhrWlF3RFlua0dta3dvTzgiXX0.yvO7_LjYo0GTQN6Fm7_ZWjghufCCyGnEJhMbZpPG5SKl1JsZtIsc7FJp0dkAQbDJWS9uaFDowXsFd805BQG7DA~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwib3RoZXIuY29tIl0~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: a61105db3e1f35e539c2e3dc80fd50f5\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:-NtxLKLtjufYyQsG4ucY3DNm4jqkxxQRiVyPBD7BwMM", + "signature": "0x1a1d64adeff67a27accc5102f24a694ff66f30721a16e62154deb554b9dd9cfa024299c496266b13153948466b7b786cd1f817a2137c839aa90378b3d4cf2c6a1c" + }, + "nonceStore": [ + { + "key": "verifier.example\na61105db3e1f35e539c2e3dc80fd50f5", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-disclosure", + "detail": "bad-disclosure: emailDomain does not match email" + } + }, + { + "name": "disc-email-invalid", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiZ2MyTEdsNUV0VERpSFVpNVZ3UzhYZVZWUDhZMVdKSEh2bFpDY0ZvMXF6RSIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.S2GLDdIsr7jcdZKGRqOthS5vcpVcysaggqcYBwXjN664k7YCY7m2EQRRprlgWUJCbpMPjVcWl0MaM7OF7U7kDA~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJub3QtYW4tZW1haWwiXQ~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 99488502d81778e79ade663751d96dd2\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:QsRuCc830q6ebiAalEP_1ZNV--y4gc1GFaSgQiHcSHA", + "signature": "0x5b8fb9c22596721e87e4a95ca23d62f640e028d6a8e0d0fe22b85481afa25f495972bb621b5aa7d13fc3c82bef2146bedf5f793f7950aa5f1b871ed5c202de171c" + }, + "nonceStore": [ + { + "key": "verifier.example\n99488502d81778e79ade663751d96dd2", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-disclosure", + "detail": "bad-disclosure: email needs a non-empty local part and domain" + } + }, + { + "name": "disc-email-uppercase", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiUEtEcDlSZl9KTFpsMjN4dUlxSkczRng1dkVQVjdoa2cweVU1QTI2WGkwOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.fUakscLo3ezbNBFaeRwXDPKEpyH9iqrsbJ1_oSy6N92sDvBWKFGjrJTDJZajl0RLZSDY7koPme-pg7QwFmmcDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJBbGljZUBFeGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: fc957f5f026de92c6f71c27e4d105c39\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:YGucMvQbRlRdof1m5kgEYEC-yPWvEIDfjg2sBZ2c8oE", + "signature": "0x7a6a2bbecda187a61527ea9f3a733ca4bcc8ff48c5c367ecd04e492c3615fef41f52f75e5e0d39b72dc20bf021944e0559c454ecc71dcf7e3f59a5b1fb290c791b" + }, + "nonceStore": [ + { + "key": "verifier.example\nfc957f5f026de92c6f71c27e4d105c39", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-disclosure", + "detail": "bad-disclosure: email is not a canonical lowercase address" + } + }, + { + "name": "disc-email-unicode", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiRV9BN05yTkxVRTctSm8wWEFEa3NvLXExSmlKVU1ER1BudFE1NTY3eGFJQSIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.6UXNYxvqrw9INXDQT67dGxj_HFPJovtcVfS8soBUAbVTFFmG5XDpDIal6PkwUZIKGCetvG3e23tbehrusqR-CQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCLDpGxpY2VAZXhhbXBsZS5jb20iXQ~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 469a59b7a7d5bdb36dc54da563b23956\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:sQlJMUkgFqyAIHiYZ04_vTiOwOsEA26nRUoBF_icckc", + "signature": "0x50e30a773b1389aebfee1abf743b8728e73f4ae3d06d81929d351e5b2d0103d06c356c4dd03cfaa44489feadf1da159bf928edfd1dedf77007fc4c5a4edbab9c1c" + }, + "nonceStore": [ + { + "key": "verifier.example\n469a59b7a7d5bdb36dc54da563b23956", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-disclosure", + "detail": "bad-disclosure: email must be ASCII" + } + }, + { + "name": "disc-email-empty", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiVkM3X0g0NWx0VEs5UUtSV2RlTnJlUHY0cENQcHM4WmlSdW16cVYzeTVQZyIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.XQBWlYRUmDkxLSsuF9mS53eS2L5p7IyoA-5CRDF_7wEo36fezvywtQwfPdwmxPvZ2Z-fIUaTrB5uNANjBnYMBw~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCIiXQ~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 9144af999427ec8ceb2af01cf1b4980f\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:uYVOjnX6LsdtomyOm4aFS0Iv-zPZCc84IjK89e_hO0E", + "signature": "0x70a5735e3f70fce47037c9a0d4c57d119224fa49afc09fb1a78e713d16fb8731480de94904f89faf30e1d0b713fdceb34425ab45ec31cf6a4ea81ef62d09cc5c1c" + }, + "nonceStore": [ + { + "key": "verifier.example\n9144af999427ec8ceb2af01cf1b4980f", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-disclosure", + "detail": "bad-disclosure: email needs a non-empty local part and domain" + } + }, + { + "name": "disc-empty-salt", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsidEluY2Rzdmp1cGtkRWI0TEk1TTBMQm1KUkpUNnFpUE5hSzFMVzVwTkRfayIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.dhCwFHRUk3kLfHYxOXSZI-YFqRWP-DEMI65H_2h3H0vPF7bXnonIPQAW6qSWMdOuoSS9REX9eb4XtO3YPr_RAw~WyIiLCJlbWFpbCIsImFsaWNlQGV4YW1wbGUuY29tIl0~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 057836456f128a814af53bc121b1cb99\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:bl-QbVTiwiCywU7pXsUex10bPCK1TYk01qNMpq1saPU", + "signature": "0xa7b343ed9ecf3ebde8812778a2cc219f78c7dd20fabc01ef32f2ee5a82f33c941da3ed0e49b48841929d7ad1742bac573d6d5cb932e8762cd9e481b5f83187911b" + }, + "nonceStore": [ + { + "key": "verifier.example\n057836456f128a814af53bc121b1cb99", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "ok", + "subject": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "issuer": "did:web:issuer.credentials.org" + } + }, + { + "name": "disc-no-disclosures-at-all", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOltdfQ.DpE0PzfTXN0kDOfUk8CxD1qF7yqO7ZkmeBohzIJR6rXiSijclC2dFTmFMrf4zuYEbYMesWlWxVUzixLHvEQDCg~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: c9a5b3466959e3e80d91ddb00f0eb680\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:iiQMk1ND31iqlKLewaBbtwN-f7wEjpg_Gvhj3i6YR40", + "signature": "0xc63aa89b6d2262e07e1502e023b30e1d71cfc77e6a7e5e8e491312eece66a41a70f65000c4be29d3d11dae82bf938fd6405bade268e0f38c900a7ba719b0174c1b" + }, + "nonceStore": [ + { + "key": "verifier.example\nc9a5b3466959e3e80d91ddb00f0eb680", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "ok", + "subject": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "issuer": "did:web:issuer.credentials.org" + } + }, + { + "name": "disc-only-sd-no-disclosure-but-sd-present", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCJdfQ.xrxQU4OVUZTBLRWypC_eK4groxR68Gaqe4dFCXMsIl_6xRymjhOshJ64M7UzvIZ4ywsuZxZtYYA8LMIm5ePuCA~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: f577dc282392fe778ad70f9175b4801d\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:XA1XNx562nopqNGGSg1twFS2qxH7pLHRNnkrWqBDO0s", + "signature": "0xe02c246b1a2dd1904a181fbf170d52602e54a8871f55d86d4a466d54e9e199a73aadc7f6894016a5e7b9afd2fd0de3956a8d11083ad73b1aaf3bd71e670521391c" + }, + "nonceStore": [ + { + "key": "verifier.example\nf577dc282392fe778ad70f9175b4801d", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-disclosure", + "detail": "bad-disclosure: disclosure digest is not in _sd" + } + }, + { + "name": "siwe-domain-other", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "other.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: b9e1e9cbd9ee0b19318504cf9cf60519\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:eQXOZSXekF4OXymmuUiq0bSeG_wfOw3b2JlaG4CGhkU", + "signature": "0x8b536d72556cd629d52f4d90da3c6499ee8f1db9a531a169f67b90f23779187c3700b5b8d17877084167c347dd1d25c83810941ce5a549060d0be8cda3cfe00f1b" + }, + "nonceStore": [ + { + "key": "verifier.example\nb9e1e9cbd9ee0b19318504cf9cf60519", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-siwe", + "detail": "bad-siwe: domain is not this verifier's audience" + } + }, + { + "name": "siwe-uri-http", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: http://verifier.example\nVersion: 1\nChain ID: 1\nNonce: c755b2da9361a07258ef648a83a80c82\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:eQXOZSXekF4OXymmuUiq0bSeG_wfOw3b2JlaG4CGhkU", + "signature": "0xfe5c1ce8336f310f7065ef33ae6e7cd759c75632bb5dc72bc66fad8f5762f3e80095dbf534e556b4088f9d657be72bb650f04b81f478caba26adb64ef57997171c" + }, + "nonceStore": [ + { + "key": "verifier.example\nc755b2da9361a07258ef648a83a80c82", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-siwe", + "detail": "bad-siwe: uri must be an https origin matching the audience" + } + }, + { + "name": "siwe-uri-userinfo", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://u@verifier.example\nVersion: 1\nChain ID: 1\nNonce: 1ee291980783b7dfcfc0ebcb56f9d56f\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:eQXOZSXekF4OXymmuUiq0bSeG_wfOw3b2JlaG4CGhkU", + "signature": "0xd6bf141c67971c3622819ed6b329b75733019e403a12ca8260d6a192a632165f230449d1bc2b6ce81b317d68867834a7f523c33e2e027f530904677ef568fd091b" + }, + "nonceStore": [ + { + "key": "verifier.example\n1ee291980783b7dfcfc0ebcb56f9d56f", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-siwe", + "detail": "bad-siwe: uri must be an https origin matching the audience" + } + }, + { + "name": "siwe-uri-port-443", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example:443\nVersion: 1\nChain ID: 1\nNonce: 129393be3c5d30bebdb3d45c183a5b4f\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:eQXOZSXekF4OXymmuUiq0bSeG_wfOw3b2JlaG4CGhkU", + "signature": "0xfd3dee254fe58d2d10cf85cac9e44e163be2d63f4d944eb07953f36a28bc5d594c85cb57be50a05641bc56c4f08637596c007ef05b65758124ec2041752209981b" + }, + "nonceStore": [ + { + "key": "verifier.example\n129393be3c5d30bebdb3d45c183a5b4f", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "ok", + "subject": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "issuer": "did:web:issuer.credentials.org" + } + }, + { + "name": "siwe-uri-uppercase-host", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://VERIFIER.example\nVersion: 1\nChain ID: 1\nNonce: 92c2a401b297a551c7655a1a57b3bd79\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:eQXOZSXekF4OXymmuUiq0bSeG_wfOw3b2JlaG4CGhkU", + "signature": "0x698a2e1f4b50695d78aaa566d32e6b32c21bb791b256499532452bb6341afc621d2701a7cf276208e03fc874c778662c82c5e717e808a671eb20afd6f9ca72411b" + }, + "nonceStore": [ + { + "key": "verifier.example\n92c2a401b297a551c7655a1a57b3bd79", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "ok", + "subject": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "issuer": "did:web:issuer.credentials.org" + } + }, + { + "name": "siwe-uri-path", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example/x\nVersion: 1\nChain ID: 1\nNonce: 86bf24159eaab4524dcc2ff0d8e9f83d\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:eQXOZSXekF4OXymmuUiq0bSeG_wfOw3b2JlaG4CGhkU", + "signature": "0x0b43acf15f1223f401ee35e81b553860db0bc6a5d80342d344ae9f3e4027a5005c2a7c5afdc59fc35b2b54dbb47f1d2ea9e0f6230cc75487a98c9f8d23ba92cd1c" + }, + "nonceStore": [ + { + "key": "verifier.example\n86bf24159eaab4524dcc2ff0d8e9f83d", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "ok", + "subject": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "issuer": "did:web:issuer.credentials.org" + } + }, + { + "name": "siwe-uri-other-host", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://evil.example\nVersion: 1\nChain ID: 1\nNonce: 4e98687ed82f73b6c8dd1fd5789e053c\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:eQXOZSXekF4OXymmuUiq0bSeG_wfOw3b2JlaG4CGhkU", + "signature": "0x56f3aa0be3196b87b8750bc87fd50abd754bb4259b6f5adea0c3cfd1385eb55b31fbd987cde3b7cae05ee2d2b25d124a5c4e2506b7b0e8a7908550ac4abeb0c11c" + }, + "nonceStore": [ + { + "key": "verifier.example\n4e98687ed82f73b6c8dd1fd5789e053c", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-siwe", + "detail": "bad-siwe: uri must be an https origin matching the audience" + } + }, + { + "name": "siwe-version-2", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 2\nChain ID: 1\nNonce: 1e7ce88e5b668ae4ae50482777c88250\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:eQXOZSXekF4OXymmuUiq0bSeG_wfOw3b2JlaG4CGhkU", + "signature": "0x9623ee7bf4f493d1651d7b4980386899f0e4dfde094dfe86d277a58c2fa115637d7b70d3cba7927c552d1ab3922eb4bd3b57cbb72a768eb3c5ca1454476507441b" + }, + "nonceStore": [ + { + "key": "verifier.example\n1e7ce88e5b668ae4ae50482777c88250", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-siwe", + "detail": "bad-siwe: version must be 1" + } + }, + { + "name": "siwe-statement-other", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nSign in\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 4fd9fd463ecf140f414e266707adc242\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:eQXOZSXekF4OXymmuUiq0bSeG_wfOw3b2JlaG4CGhkU", + "signature": "0x4ecf8b476e6943bd9d894ab9c54c770b01447f108b2faa00c1ec616921a7f14c51179741b6cc7347df0d87ec7ddea785fb43d0396c17552fe7ccfbf698bbe2ad1b" + }, + "nonceStore": [ + { + "key": "verifier.example\n4fd9fd463ecf140f414e266707adc242", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-siwe", + "detail": "bad-siwe: unexpected statement" + } + }, + { + "name": "siwe-chain-10", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 10\nNonce: b4edf044e00a95aa9bc3dab2a0fe12e2\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:eQXOZSXekF4OXymmuUiq0bSeG_wfOw3b2JlaG4CGhkU", + "signature": "0xd34487e1813f526c81d1f4169c818a8bf566dfd95943a974056fb385ebe388d57f176038ccd8ea71c716201869d00b0e0ce93241fac9fb696fd2e5c8ad8b67d01b" + }, + "nonceStore": [ + { + "key": "verifier.example\nb4edf044e00a95aa9bc3dab2a0fe12e2", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-siwe", + "detail": "bad-siwe: chain id must equal the credential subject's" + } + }, + { + "name": "siwe-address-other", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\ndid:pkh:eip155:1:0x1111111111111111111111111111111111111111\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 41cfc8c4d4fd1d7bf8bba020b67e8d09\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:eQXOZSXekF4OXymmuUiq0bSeG_wfOw3b2JlaG4CGhkU", + "signature": "0x25600d608cd9294e6c0b8aeb62b02431ec918ef79e87130e7ac9ee5797a1382d76cc8cb9b31bc9eabc5536d19a20eda48c832a73221b04e17d7bff52a18a42841c" + }, + "nonceStore": [ + { + "key": "verifier.example\n41cfc8c4d4fd1d7bf8bba020b67e8d09", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-siwe", + "detail": "bad-siwe: address" + } + }, + { + "name": "siwe-address-lowercase", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 27e0043b6491cf18e3b4cf0d5c2758a1\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:eQXOZSXekF4OXymmuUiq0bSeG_wfOw3b2JlaG4CGhkU", + "signature": "0x87e3dd86dad534ae1c53d5b2ce2b657cfffa75ebd36192d8f4192fce0bdc976a001ce9d8f57119b226a98c581da1cb43f62e6c067da7a62129f36956ff30e1fc1b" + }, + "nonceStore": [ + { + "key": "verifier.example\n27e0043b6491cf18e3b4cf0d5c2758a1", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-siwe", + "detail": "bad-siwe: address must be EIP-55 checksummed" + } + }, + { + "name": "siwe-resource-other", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: f6c3a097a51c69b2316ea4b55e07ccc5\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:AAAA", + "signature": "0xb6aabeb7ec8405cf42186ee2e8d2f279448f3812f27945e119bb06dfb22c793d5d09eec5f4cf4d7bac2d872148751499170a68645fc08d5b620476710ae6a92e1b" + }, + "nonceStore": [ + { + "key": "verifier.example\nf6c3a097a51c69b2316ea4b55e07ccc5", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-siwe", + "detail": "bad-siwe: resources must be exactly the sd_hash of this presentation" + } + }, + { + "name": "siwe-two-resources", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: d9c38d90408c8e14ae62b549036a363b\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:x\n- urn:tinycloud:sd-hash:y", + "signature": "0x344c8329c600c02edf9743691279a187814f1df5b5f441e3caa801f95350f45323a673ec7932315868e1490bc452118a486f04133d1c98a0fb8ffa090380e5f51c" + }, + "nonceStore": [ + { + "key": "verifier.example\nd9c38d90408c8e14ae62b549036a363b", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-siwe", + "detail": "bad-siwe: resources must be exactly the sd_hash of this presentation" + } + }, + { + "name": "siwe-no-resources", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: ef97706aed59c86278f1dcf54e29070a\nIssued At: 2026-01-01T00:59:00Z\nResources:", + "signature": "0xa23bab41089f6dcb3e257c417715668b6a926b0551b568ff2c01d85692ec823c0c64c76197fc1ed673a85351dd48bfe02cfdcbf529041cbb8c4f7ea757a789171b" + }, + "nonceStore": [ + { + "key": "verifier.example\nef97706aed59c86278f1dcf54e29070a", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-siwe", + "detail": "bad-siwe: resources must be exactly the sd_hash of this presentation" + } + }, + { + "name": "siwe-expired", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 9a8bcabe268898997addb916be928340\nIssued At: 2026-01-01T00:59:00Z\nExpiration Time: 2025-12-31T00:00:00Z\nResources:\n- urn:tinycloud:sd-hash:eQXOZSXekF4OXymmuUiq0bSeG_wfOw3b2JlaG4CGhkU", + "signature": "0x1baf40e9df86a9dc0bf6d636b25b3fd8a7ca80b70edb0597ceb7b3a5e01faf073be639e7bd0e06e13d5ee50974b354ee2963470e394fca9f06539e798ed143d81b" + }, + "nonceStore": [ + { + "key": "verifier.example\n9a8bcabe268898997addb916be928340", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-siwe", + "detail": "bad-siwe: SIWE has expired" + } + }, + { + "name": "siwe-expiration-equal-now", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 1537985f13fe106eede2b55c06d14427\nIssued At: 2026-01-01T00:59:00Z\nExpiration Time: 2026-01-01T01:00:00Z\nResources:\n- urn:tinycloud:sd-hash:eQXOZSXekF4OXymmuUiq0bSeG_wfOw3b2JlaG4CGhkU", + "signature": "0xfa578aa072ec96fbe35e9e9fe7fd440051b508bde71acab480ee083013c19d78074f259755cfd24f477db9c40bbb55983e174b1b95889d42872228c04a647dd71c" + }, + "nonceStore": [ + { + "key": "verifier.example\n1537985f13fe106eede2b55c06d14427", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-siwe", + "detail": "bad-siwe: SIWE has expired" + } + }, + { + "name": "siwe-not-before-future", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 3edf60f04f3d832e95082fa34392f7db\nIssued At: 2026-01-01T00:59:00Z\nNot Before: 2026-01-02T00:00:00Z\nResources:\n- urn:tinycloud:sd-hash:eQXOZSXekF4OXymmuUiq0bSeG_wfOw3b2JlaG4CGhkU", + "signature": "0x055b189eb6ac69d472f2582051e9c85d4037eb7019ff06e5eba9ac21f88f1ff965ed824cc5b1e47e2820440f0a1f051f403144561416b82aabde489b3a2e5b461b" + }, + "nonceStore": [ + { + "key": "verifier.example\n3edf60f04f3d832e95082fa34392f7db", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-siwe", + "detail": "bad-siwe: SIWE is not yet valid" + } + }, + { + "name": "siwe-expiration-bad-rfc3339", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: c00ab8252f186b091251fc94cd3cfd97\nIssued At: 2026-01-01T00:59:00Z\nExpiration Time: 2026-13-01T00:00:00Z\nResources:\n- urn:tinycloud:sd-hash:eQXOZSXekF4OXymmuUiq0bSeG_wfOw3b2JlaG4CGhkU", + "signature": "0xbf6974a21d6b3e5be50170afaff020aac6f296cc0d9fc2fecc35e6dad34359355dc7a10472976222b6f869e215442af527500a20f029f3cee5354a2eea7735281b" + }, + "nonceStore": [ + { + "key": "verifier.example\nc00ab8252f186b091251fc94cd3cfd97", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-siwe", + "detail": "bad-siwe: Expiration Time is not RFC 3339" + } + }, + { + "name": "siwe-sig-no-0x", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 41d3cb2d2d455683aebb9516d0fc2a1e\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:eQXOZSXekF4OXymmuUiq0bSeG_wfOw3b2JlaG4CGhkU", + "signature": "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + "nonceStore": [ + { + "key": "verifier.example\n41d3cb2d2d455683aebb9516d0fc2a1e", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-siwe-signature", + "detail": "bad-siwe-signature: not hex" + } + }, + { + "name": "siwe-sig-uppercase-0X", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 394ba60062c45d2d315fd0e76325c499\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:eQXOZSXekF4OXymmuUiq0bSeG_wfOw3b2JlaG4CGhkU", + "signature": "0X0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + "nonceStore": [ + { + "key": "verifier.example\n394ba60062c45d2d315fd0e76325c499", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-siwe-signature", + "detail": "bad-siwe-signature: not hex" + } + }, + { + "name": "siwe-sig-short", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 9adbe3c39beb08af42d0d008181a84c6\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:eQXOZSXekF4OXymmuUiq0bSeG_wfOw3b2JlaG4CGhkU", + "signature": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + "nonceStore": [ + { + "key": "verifier.example\n9adbe3c39beb08af42d0d008181a84c6", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-siwe-signature", + "detail": "bad-siwe-signature: signature does not recover the credential subject" + } + }, + { + "name": "siwe-sig-long", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: edd70bc176be1eadca2b395d1d3919f3\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:eQXOZSXekF4OXymmuUiq0bSeG_wfOw3b2JlaG4CGhkU", + "signature": "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + "nonceStore": [ + { + "key": "verifier.example\nedd70bc176be1eadca2b395d1d3919f3", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-presentation", + "detail": "bad-presentation: siwe signature is too long" + } + }, + { + "name": "siwe-sig-other-key", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: c18ed6b1d2b3751d908e9dd09ba6a912\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:eQXOZSXekF4OXymmuUiq0bSeG_wfOw3b2JlaG4CGhkU", + "signature": "0x5197757fe9ec0ebc9d65fe9e278bf304ccb3bb192d1ca12aa93d297f3f1b7a691219f23878f9b19eac5dbbfd23d007c4508dba37e8ce957cbf9d8917b2aa97c41b" + }, + "nonceStore": [ + { + "key": "verifier.example\nc18ed6b1d2b3751d908e9dd09ba6a912", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-siwe-signature", + "detail": "bad-siwe-signature: signature does not recover the credential subject" + } + }, + { + "name": "siwe-nonce-short", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: shortnonce\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:eQXOZSXekF4OXymmuUiq0bSeG_wfOw3b2JlaG4CGhkU", + "signature": "0x5cdce203e8c550106198b275c51ceec787b489f00162f3cf45654d03d9bd12d63c784c0a62e616874c6fde4ec1f985a29441cb711cda55885821a5a067ec6d861b" + }, + "nonceStore": [ + { + "key": "verifier.example\nshortnonce", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-nonce", + "detail": "bad-nonce: nonce must be at least 22 base62 characters (or 32 hex)" + } + }, + { + "name": "siwe-nonce-punct", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: heldtestnonce000000000!\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:eQXOZSXekF4OXymmuUiq0bSeG_wfOw3b2JlaG4CGhkU", + "signature": "0xf3e9a14ab925c1f38148a7b451fac541674f92acc23f5cc34dd6fece9e16e94069debe36405d682f6db3a68bf3bce6036d0061fe02b427a18fa8c930c09ce0291b" + }, + "nonceStore": [ + { + "key": "verifier.example\nheldtestnonce000000000!", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-siwe", + "detail": "bad-siwe: nonce must be alphanumeric" + } + }, + { + "name": "siwe-nonce-unknown", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: heldtestnonce0000000001\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:eQXOZSXekF4OXymmuUiq0bSeG_wfOw3b2JlaG4CGhkU", + "signature": "0xaf781f15e005fd726c9fc34b14d3b21cb34012b5b601e8b0c2291a551101159946c2abb115e50f9391a76207389a1d87e1f0adfb5606aa4acc1f42b07b35cb711c" + }, + "nonceStore": [], + "ts": { + "code": "nonce-replayed", + "detail": "nonce-replayed: nonce is unknown, already used, or bound to another account" + } + }, + { + "name": "siwe-nonce-bound-other", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: e5210d1ac4b338d6a54136262d227208\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:eQXOZSXekF4OXymmuUiq0bSeG_wfOw3b2JlaG4CGhkU", + "signature": "0x063babd30f02c964536b84b8ede1d8092726443abee4c290e879fd7fe12389c45add1ce385b36dd05e4fb9388354752a36321b20e23b6a6d823693c94d1394e71c" + }, + "nonceStore": [ + { + "key": "verifier.example\ne5210d1ac4b338d6a54136262d227208", + "account": "did:pkh:eip155:1:0x1111111111111111111111111111111111111111" + } + ], + "ts": { + "code": "nonce-replayed", + "detail": "nonce-replayed: nonce is unknown, already used, or bound to another account" + } + }, + { + "name": "caller-other-account", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0x1111111111111111111111111111111111111111", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 2325d6c0795e459aab50292e12dffe34\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:eQXOZSXekF4OXymmuUiq0bSeG_wfOw3b2JlaG4CGhkU", + "signature": "0x23e36ffec1fa523795d1ba8eaa13c4463c6ddc5556dd59d0ad69ab7388d7b56b502debbbb3dea83bc5d30d17ef5762db39269d7055a3bff60ee7347e270e0fdf1b" + }, + "nonceStore": [ + { + "key": "verifier.example\n2325d6c0795e459aab50292e12dffe34", + "account": "did:pkh:eip155:1:0x1111111111111111111111111111111111111111" + } + ], + "ts": { + "code": "nonce-account-mismatch", + "detail": "nonce-account-mismatch: subject is not the authenticated caller" + } + }, + { + "name": "caller-chain-10", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:10:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 26da981fa2f5d520e15b6de4e2c2dc66\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:eQXOZSXekF4OXymmuUiq0bSeG_wfOw3b2JlaG4CGhkU", + "signature": "0x486c808ffa21067b5b23e4785ce7173ba6c9ed88f24e725cbaecf361e2ecffa352bb8c98ef98e843430c2787e158a46058b110c74b2056f00eb12708bbbed90b1c" + }, + "nonceStore": [ + { + "key": "verifier.example\n26da981fa2f5d520e15b6de4e2c2dc66", + "account": "did:pkh:eip155:10:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "nonce-account-mismatch", + "detail": "nonce-account-mismatch: subject is not the authenticated caller" + } + }, + { + "name": "time-now-before-nbf", + "policy": { + "now": "2025-12-31T23:59:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: e5be4d34cbe9883adb288e53ea69bbb3\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:eQXOZSXekF4OXymmuUiq0bSeG_wfOw3b2JlaG4CGhkU", + "signature": "0xa29d41ea2d8573c065464428530e749998e54a5fa226d32148e5545166fab2b320c154aa683d176d92641a01a1b495a9dc79f4b05f539f791ffe4d824d3513381c" + }, + "nonceStore": [ + { + "key": "verifier.example\ne5be4d34cbe9883adb288e53ea69bbb3", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "not-yet-valid", + "detail": "not-yet-valid: credential is not yet valid" + } + }, + { + "name": "time-now-at-exp", + "policy": { + "now": "2026-01-31T00:00:00.000Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: a9ea52a7f648c5ef2e5b9ae9358c7ea4\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:eQXOZSXekF4OXymmuUiq0bSeG_wfOw3b2JlaG4CGhkU", + "signature": "0x173cb612eb6916d1c27fbb121870283c35a54cf3dcc4a195e01976ab69dbaade190f5f830c0254e3d9efc4bb45b0c27e5c0d8d889608bd64c0f7f7ccc6ba44231c" + }, + "nonceStore": [ + { + "key": "verifier.example\na9ea52a7f648c5ef2e5b9ae9358c7ea4", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "expired", + "detail": "expired: credential has expired" + } + }, + { + "name": "time-now-after-exp", + "policy": { + "now": "2026-02-01T00:00:00.000Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 033b7fe229c8d15703f8306eada5c3e0\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:eQXOZSXekF4OXymmuUiq0bSeG_wfOw3b2JlaG4CGhkU", + "signature": "0xb294bb465c333dbc264f8c6eaa8213b9f05df28189d8e68354aaaae0e59c415169c64c72723d7ca763ff9fd87fcd70debe00e695780e13f456b2ec5e3e7ec1181c" + }, + "nonceStore": [ + { + "key": "verifier.example\n033b7fe229c8d15703f8306eada5c3e0", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "expired", + "detail": "expired: credential has expired" + } + }, + { + "name": "iss-kid-not-accepted", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k2" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 2aa0cf46a7dac1af78848d3c799cc4b2\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:eQXOZSXekF4OXymmuUiq0bSeG_wfOw3b2JlaG4CGhkU", + "signature": "0xbbfc404b1e8660ecf94657885ba6e3db73583e2a708571b242edb669a19b345d29baa386c0110abb4e6986c4dba005ee00a0d3fa18a5adf4343b2b7e4f9bccdd1b" + }, + "nonceStore": [ + { + "key": "verifier.example\n2aa0cf46a7dac1af78848d3c799cc4b2", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "issuer-not-accepted", + "detail": "issuer-not-accepted: issuer is not accepted by this policy" + } + }, + { + "name": "iss-did-not-accepted", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:other.example" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 5aba0004365fceb59c72b233fb4275e0\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:eQXOZSXekF4OXymmuUiq0bSeG_wfOw3b2JlaG4CGhkU", + "signature": "0x104dcae70b1b7f7071687fddf00d380fc4716ce67ca4fca3a454b440f47d99ef2ab0c47b5e0b3677a587b859c53adbd3d7294bbc48b4ca789088b59d737fd9d21b" + }, + "nonceStore": [ + { + "key": "verifier.example\n5aba0004365fceb59c72b233fb4275e0", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "issuer-not-accepted", + "detail": "issuer-not-accepted: issuer is not accepted by this policy" + } + }, + { + "name": "iss-no-accepted", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: e740b54aef99c4fc3cd5e3579620e7f0\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:eQXOZSXekF4OXymmuUiq0bSeG_wfOw3b2JlaG4CGhkU", + "signature": "0xac540f3fea27c5269bbb08bd165f47f997585ed044b5a4545d860005990ab83803457cedcf337dab2d6f707746dc457678bb1bb01c210c41ab5624db381e149b1c" + }, + "nonceStore": [ + { + "key": "verifier.example\ne740b54aef99c4fc3cd5e3579620e7f0", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-config", + "detail": "bad-config: acceptedIssuers must not be empty" + } + }, + { + "name": "iss-kid-accepted-exact", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 6cfff9b480f324da4da697818b9a9e48\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:eQXOZSXekF4OXymmuUiq0bSeG_wfOw3b2JlaG4CGhkU", + "signature": "0x55eaae728061ff264c673e4efd81068fb925b2b78c13355576d771e038dd279538fb36e22f558053473c5ad25cc940d001b4e9b372410b0511bdaf56d0c2d1af1c" + }, + "nonceStore": [ + { + "key": "verifier.example\n6cfff9b480f324da4da697818b9a9e48", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "ok", + "subject": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "issuer": "did:web:issuer.credentials.org" + } + }, + { + "name": "iss-entry-missing-kid", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k2", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 034662e5b8d87cef43b5e98e803b34ef\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:eQXOZSXekF4OXymmuUiq0bSeG_wfOw3b2JlaG4CGhkU", + "signature": "0x9167191fca462f15e6386c8f5281b059c5837474f1e0e68d34ba48ec14bfefa177a8f0d5c1e457f5d16b4577f63baeb2adbc9fc20f3b990d1a33b0a596b4de631b" + }, + "nonceStore": [ + { + "key": "verifier.example\n034662e5b8d87cef43b5e98e803b34ef", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "unknown-issuer", + "detail": "unknown-issuer: no issuer-set entry for this kid" + } + }, + { + "name": "iss-not-yet-valid-key", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2026-01-01T02:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 9dc6da6324614462855bf59969091212\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:eQXOZSXekF4OXymmuUiq0bSeG_wfOw3b2JlaG4CGhkU", + "signature": "0x35c82b3603337d973b559926102678cff2f1d417ce6004e41405224bf880feda580a67ec7c51d0f722d70bbf460d9cb4f8af14bba46fe50197f5449035f39ce31b" + }, + "nonceStore": [ + { + "key": "verifier.example\n9dc6da6324614462855bf59969091212", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "issuer-not-yet-valid", + "detail": "issuer-not-yet-valid: issuer key is not yet valid" + } + }, + { + "name": "iss-key-stopped", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": "2026-01-01T00:30:00Z" + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: b6414e5de4969f4865c95660dcd5a73e\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:eQXOZSXekF4OXymmuUiq0bSeG_wfOw3b2JlaG4CGhkU", + "signature": "0x5204e4d42af9368a5b76baae1af7378e36b3db84881ef32829e7007d677f865b042c483355b6587e778d7a1c8331ad7a0cdb7899749ae023746182ad11ed626d1b" + }, + "nonceStore": [ + { + "key": "verifier.example\nb6414e5de4969f4865c95660dcd5a73e", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "issuer-stopped", + "detail": "issuer-stopped: issuer key is past its hard stop" + } + }, + { + "name": "iss-credential-predates-key", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2026-01-01T00:00:01Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 8fa8273b351a7bd8bd7368d454bcc663\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:eQXOZSXekF4OXymmuUiq0bSeG_wfOw3b2JlaG4CGhkU", + "signature": "0xe28475c4ce025381488016b5ea7044bc6b11e14448beb12849d7a54b50966b4c45c09a75e393bf43620c917b2863fed3085394e8968e66f33a5ed37df41df2631b" + }, + "nonceStore": [ + { + "key": "verifier.example\n8fa8273b351a7bd8bd7368d454bcc663", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "issuer-not-yet-valid", + "detail": "issuer-not-yet-valid: credential predates the issuer key" + } + }, + { + "name": "iss-retired-before-iat", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": "2026-01-01T00:00:00Z", + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: faf8b7e754c9a02f9de1e70f616b34a1\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:eQXOZSXekF4OXymmuUiq0bSeG_wfOw3b2JlaG4CGhkU", + "signature": "0xa8b64d4f3e090a5c89a735d6449901417509feab997732886d3fd5acfa3be3b72e6a8a76abee7252f2654e205ba5beb65d98f7eaebcc596954df58bad054b1c91c" + }, + "nonceStore": [ + { + "key": "verifier.example\nfaf8b7e754c9a02f9de1e70f616b34a1", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "issuer-retired", + "detail": "issuer-retired: issued at or after the issuer key was retired" + } + }, + { + "name": "iss-retired-after-iat", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": "2026-01-01T00:30:00Z", + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: af332c8a730867662bcf8af9a68235fa\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:eQXOZSXekF4OXymmuUiq0bSeG_wfOw3b2JlaG4CGhkU", + "signature": "0x0e7520a318de27f704bcd5fc8a835b9e4f53291f4daf9ebdd96eced0d54beeb15f98623bfdfbc1469615e858bcfcb5b1a320ae18bbbfd93b0a060e2816a499e21b" + }, + "nonceStore": [ + { + "key": "verifier.example\naf332c8a730867662bcf8af9a68235fa", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "ok", + "subject": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "issuer": "did:web:issuer.credentials.org" + } + }, + { + "name": "iss-vct-not-admitted", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "other/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 6ae6f7ea1e9d9bcc07bac1609446b015\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:eQXOZSXekF4OXymmuUiq0bSeG_wfOw3b2JlaG4CGhkU", + "signature": "0xcc4f9c5ecd98dd151b517bc0faf9a3dbf0ca2843e5b2c7977a4584ef3f1ec7026878de4d32c570d2e2a5804732f46c58320ed1e39f491cc50826eb9f720e9ada1b" + }, + "nonceStore": [ + { + "key": "verifier.example\n6ae6f7ea1e9d9bcc07bac1609446b015", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "profile-mismatch", + "detail": "profile-mismatch: issuer entry does not admit this vct and profile" + } + }, + { + "name": "iss-profile-not-admitted", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "other/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: da589bacb4e037562e57b82ef521e650\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:eQXOZSXekF4OXymmuUiq0bSeG_wfOw3b2JlaG4CGhkU", + "signature": "0x933680da464eb4ed9bfc564abc7d65ad5fcf275beef910e709a75e2af191200a5f70a8d8f925b0cba33395dd0bb1a977a531ebd2e5ff43b638db74238fc6121a1b" + }, + "nonceStore": [ + { + "key": "verifier.example\nda589bacb4e037562e57b82ef521e650", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "profile-mismatch", + "detail": "profile-mismatch: issuer entry does not admit this vct and profile" + } + }, + { + "name": "iss-profile-not-accepted", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "other/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 3d29f5109c6920658c615d70146a19e5\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:eQXOZSXekF4OXymmuUiq0bSeG_wfOw3b2JlaG4CGhkU", + "signature": "0x0f3ade2d7440f9f4957722d64cb169aa87f52b6825e7dc8dc3580c9207df78734b3a1cae2c6a22da4d46a4febd7ee1861ec1328364e26704de39b388be3f14fe1b" + }, + "nonceStore": [ + { + "key": "verifier.example\n3d29f5109c6920658c615d70146a19e5", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "profile-not-accepted", + "detail": "profile-not-accepted: profile is not accepted by this caller" + } + }, + { + "name": "iss-profile-version-not-accepted", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 2 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 70a6582334ec6a33fb2dc1efd3921b5c\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:eQXOZSXekF4OXymmuUiq0bSeG_wfOw3b2JlaG4CGhkU", + "signature": "0x545f01a4a509e59d8f0eb4ebf67ceb6d3055f67bbf6692f78efc2defcd95e2276af7e3ad04e93fd29e05ca8d2848059cec30d3a358e9eb3061204b006bd598cf1c" + }, + "nonceStore": [ + { + "key": "verifier.example\n70a6582334ec6a33fb2dc1efd3921b5c", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "profile-not-accepted", + "detail": "profile-not-accepted: profile is not accepted by this caller" + } + }, + { + "name": "iss-bad-alg", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "ES256", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: bdd05075c97c21e631f732bbaad4a855\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:eQXOZSXekF4OXymmuUiq0bSeG_wfOw3b2JlaG4CGhkU", + "signature": "0x80b274b2a39886d5dab5f4043e60c2bb42b2919d81c249deafb9899f2c018c4427121d411f51d8a6247d72d5d4fe341b77cad160ee4356d9096218e870ee90fe1c" + }, + "nonceStore": [ + { + "key": "verifier.example\nbdd05075c97c21e631f732bbaad4a855", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-issuer-set", + "detail": "bad-issuer-set: alg must be EdDSA" + } + }, + { + "name": "iss-bad-pubkey", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "AAAA", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 26d0328b884ee6a4d83c1c917e53afed\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:eQXOZSXekF4OXymmuUiq0bSeG_wfOw3b2JlaG4CGhkU", + "signature": "0x6d9c9e1bc1cffe2810a9c04c42d11b114d52d8d1588524201f1ec4aa9c684fa21923aa71dad934828b72bac5ce6da415f1776d4ea1747e4ff7330ff76e62a9be1c" + }, + "nonceStore": [ + { + "key": "verifier.example\n26d0328b884ee6a4d83c1c917e53afed", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-issuer-set", + "detail": "bad-issuer-set: publicKey is not a strict 32-byte Ed25519 key" + } + }, + { + "name": "sig-other-issuer-key", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.7wsKxCQUTnKUwgsd4pbkFrd3YHPf0gIZKqTytY1I7Bvp2y644x6g_mh_6uVHo2c9s7EU88E69Udlx-MENJ9VAA~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: e05259fa8c3cd08325a07710eb6efb19\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:G8e6pFkRkLHlBekMjW5CJ6Eow2d8VYD3WfrYNRI8cLE", + "signature": "0x3528c13c7684c32da260c0937bd97cfd0c3692094dfd228ef185a349625f173b1c9f2028c6e0be47560d01b4a6cfdf07139473e0cda7e2ecf88e4f87722289e11c" + }, + "nonceStore": [ + { + "key": "verifier.example\ne05259fa8c3cd08325a07710eb6efb19", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-signature", + "detail": "bad-signature: issuer signature did not verify" + } + }, + { + "name": "pkh-lowercase-address", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5ZmQ2ZTUxYWFkODhmNmY0Y2U2YWI4ODI3Mjc5Y2ZmZmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlmZDZlNTFhYWQ4OGY2ZjRjZTZhYjg4MjcyNzljZmZmYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.71AQiSeu5rN-QSK9jcEKZ5rBQK6P5s1v4cWOqlG7uVN9Zyvf6VO5lrjK7-iQOLBD8k09O1GCEG_xP2hpl6FMAw~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: heldtestnonce0000000001\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:7yfwSOUa3bUcFOrXdKfkbpzHPlZrb9BoKAcyf-VaJdE", + "signature": "0x04dbff92d38792077c85608e85d9c736ef306c90c3b5b06c1f2a0ad7bb6ee9875fe604264ac6f2157e24081fc6a2b8d4e0495659842f68e77480d7fff3f2a0871b" + }, + "nonceStore": [ + { + "key": "verifier.example\nheldtestnonce0000000001", + "account": "did:pkh:eip155:1:0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266" + } + ], + "ts": { + "code": "bad-siwe", + "detail": "bad-siwe: address must be EIP-55 checksummed" + } + }, + { + "name": "pkh-uppercase-hex-digits", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xF39FD6E51AAD88F6F4CE6AB8827279CFFFB92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4RjM5RkQ2RTUxQUFEODhGNkY0Q0U2QUI4ODI3Mjc5Q0ZGRkI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhGMzlGRDZFNTFBQUQ4OEY2RjRDRTZBQjg4MjcyNzlDRkZGQjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.c16KP3Um6civbF5nCeA8T5_UcKqUL_mon7ISN1OvC-h9mgNAQmqI-rUV7qGdK6iduCdL5keGrFj6wGibXirKAw~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xF39FD6E51AAD88F6F4CE6AB8827279CFFFB92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: heldtestnonce0000000001\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:WpGRBwi0lIvpX91XtYkOCE1qiLAVDUgIft9JPGcnp6M", + "signature": "0xc3b6774e3405d09b0c43158a757dce24afbf0e69960d7c02c2d2f4a9b19811513a801f66788841c033b1f7c142a3f060e8b722e27025e6224dd6d5468bf0c0b31c" + }, + "nonceStore": [ + { + "key": "verifier.example\nheldtestnonce0000000001", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-config", + "detail": "bad-config: callerAccount must be a did:pkh:eip155 account" + }, + "deviation": { + "rust": "account-owner-invalid", + "reason": "Refused by precheck before nonce consume. TS reports bad-config for the same DID; Rust maps the account-owner refusal to 403." + } + }, + { + "name": "pkh-bad-eip55-one-letter", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xF39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4RjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhGMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.YtIMKDRGj15QK0svvmVgJH93CRz0F2rQ7MXBo7Xtvqujxx0WmfbetVSIk9GUCRaJgym7Pe5GeAnR1ZIXTngIDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xF39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: heldtestnonce0000000001\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:w6udd0KXE77wM0cRKHJY4IyU3iATGbsumadaZdnRVJs", + "signature": "0x4db11dc21090afb630a27b03fefebb19b6627ddc16db64ba85b24d92ada6e4e649c19a7fe41d984793717a552fa840e46c0eebd1bc990da76bedb0e5889090061c" + }, + "nonceStore": [ + { + "key": "verifier.example\nheldtestnonce0000000001", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-config", + "detail": "bad-config: callerAccount must be a did:pkh:eip155 account" + }, + "deviation": { + "rust": "account-owner-invalid", + "reason": "Refused by precheck before nonce consume. TS reports bad-config for the same DID; Rust maps the account-owner refusal to 403." + } + }, + { + "name": "pkh-no-0x", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:f39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOmYzOUZkNmU1MWFhZDg4RjZGNGNlNmFCODgyNzI3OWNmZkZiOTIyNjYiLCJpYXQiOjE3NjcyMjU2MDAsIm5iZiI6MTc2NzIyNTYwMCwiZXhwIjoxNzY5ODE3NjAwLCJqdGkiOiJ1cm46dXVpZDowYjZkMmM0ZS04YTFmLTRkM2UtOWI3YS0xYzJkM2U0ZjVhNmIiLCJ2Y3QiOiJvcGVuY3JlZGVudGlhbHMuZW1haWwvdjEiLCJwcm9maWxlIjoidGlueWNsb3VkLmVtYWlsLWhlbGQvdjEiLCJwcm9maWxlVmVyc2lvbiI6MSwiaG9sZGVyQmluZGluZyI6eyJkaWQiOiJkaWQ6cGtoOmVpcDE1NToxOmYzOUZkNmU1MWFhZDg4RjZGNGNlNmFCODgyNzI3OWNmZkZiOTIyNjYiLCJzaWduaW5nRG9tYWluIjoidGlueWNsb3VkLmNyZWRlbnRpYWxzL2FjY291bnQtYmluZGluZy92MSJ9LCJzdGF0dXMiOnsibWV0aG9kIjoibm9uZSJ9LCJfc2RfYWxnIjoic2hhLTI1NiIsIl9zZCI6WyI4RWtrU3lLdGNsZzRjRXZUdWZpS2thQlJpNmhCMWd4T3NzRmZsM05rYU84IiwiVzBoVHVIZVpnUjdoenRfSkF0RElEVy1jTHFYMi1fR1FEVktlMHdiRy1pdyJdfQ.EkVwtamZjmltvYC3lm-cdmSkgHskFARES6HW4yuHiv4AhSFddxUaom4bItL-310B4ZYcJUH-KQFBcYRHghrwAQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\nf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: heldtestnonce0000000001\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:4AfZ6axcMeI_3fxPFZe8euQt-9K0wAINbTiXCHY7_ik", + "signature": "0xa2d80a00a55cb282ea1648447fc474123b907663b09500272ef5f6aaaa2455e42a53d10d029cfa7df3580a66045c02b43678a916a75b7930ae46b861764bffca1b" + }, + "nonceStore": [ + { + "key": "verifier.example\nheldtestnonce0000000001", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-config", + "detail": "bad-config: callerAccount must be a did:pkh:eip155 account" + }, + "deviation": { + "rust": "account-owner-invalid", + "reason": "Refused by precheck before nonce consume. TS reports bad-config for the same DID; Rust maps the account-owner refusal to 403." + } + }, + { + "name": "pkh-short-address", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb922", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjIiLCJpYXQiOjE3NjcyMjU2MDAsIm5iZiI6MTc2NzIyNTYwMCwiZXhwIjoxNzY5ODE3NjAwLCJqdGkiOiJ1cm46dXVpZDowYjZkMmM0ZS04YTFmLTRkM2UtOWI3YS0xYzJkM2U0ZjVhNmIiLCJ2Y3QiOiJvcGVuY3JlZGVudGlhbHMuZW1haWwvdjEiLCJwcm9maWxlIjoidGlueWNsb3VkLmVtYWlsLWhlbGQvdjEiLCJwcm9maWxlVmVyc2lvbiI6MSwiaG9sZGVyQmluZGluZyI6eyJkaWQiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjIiLCJzaWduaW5nRG9tYWluIjoidGlueWNsb3VkLmNyZWRlbnRpYWxzL2FjY291bnQtYmluZGluZy92MSJ9LCJzdGF0dXMiOnsibWV0aG9kIjoibm9uZSJ9LCJfc2RfYWxnIjoic2hhLTI1NiIsIl9zZCI6WyI4RWtrU3lLdGNsZzRjRXZUdWZpS2thQlJpNmhCMWd4T3NzRmZsM05rYU84IiwiVzBoVHVIZVpnUjdoenRfSkF0RElEVy1jTHFYMi1fR1FEVktlMHdiRy1pdyJdfQ.FIpCTe8Vq1hq8-eAqSM3U_pm8sD9eULovOpg_LfrVq4gueNqvFttaTt4xzI27EdDJVD3XX4scd9On2Ku6XqGDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb922\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: heldtestnonce0000000001\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:7610ufG4PvtY4cOBMQDEqMfyBCOnQgvnIXy4U6G6thg", + "signature": "0x469759e3ee95c42a4555f82df0776694d8bf6a124d3fd26fd158955f47699f6565b1225ccadffab7c5cd55f375cfb9697966cef4b89acfca922c8342d81c2eeb1b" + }, + "nonceStore": [ + { + "key": "verifier.example\nheldtestnonce0000000001", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-config", + "detail": "bad-config: callerAccount must be a did:pkh:eip155 account" + }, + "deviation": { + "rust": "account-owner-invalid", + "reason": "Refused by precheck before nonce consume. TS reports bad-config for the same DID; Rust maps the account-owner refusal to 403." + } + }, + { + "name": "pkh-method-uppercase", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:PKH:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6UEtIOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpQS0g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.8aJfPyDVwYLNjDyE8NFgLFbJEzLcu6UU9NMrN0tXpihXejdhVbFYrvnlqL2rVdnM0JoSqCS6wSyImTmc_dUbAA~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: heldtestnonce0000000001\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:-fklJ23DpnnOrR5aGUrrfdwbB4vqSoW53kXghhrk1mM", + "signature": "0xfceeb2febcc18bbe9f48a15b789a869c85b788ff8aaf9c585a077146c7baa5824973589813b0423c875ef283614c7cec5ca72df049749e52e340f0e33dabf07c1c" + }, + "nonceStore": [ + { + "key": "verifier.example\nheldtestnonce0000000001", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-config", + "detail": "bad-config: callerAccount must be a did:pkh:eip155 account" + }, + "deviation": { + "rust": "account-owner-invalid", + "reason": "Refused by precheck before nonce consume. TS reports bad-config for the same DID; Rust maps the account-owner refusal to 403." + } + }, + { + "name": "pkh-namespace-uppercase", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:EIP155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOkVJUDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6RUlQMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.U8daQ_Mg3tUhTe228QBTvDe1UUWBu1MeboPfNrqvjnWHMuof22gzklw0sfVfb-yfTmU3C7AUb_zxB5pcLlCUCg~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: heldtestnonce0000000001\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:z9H43snN2dgVfyYz04FpJUxP44OTvzpusJB8atiwOUM", + "signature": "0x9f8a39589b0b4e48b744d2e1f4d8f191b4a012036b96a55701d44d0ea74f6c18246f1fb9370b896d60badd114bc90f4f30e4a5344c713ae419bb0702875a22c21c" + }, + "nonceStore": [ + { + "key": "verifier.example\nheldtestnonce0000000001", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-config", + "detail": "bad-config: callerAccount must be a did:pkh:eip155 account" + }, + "deviation": { + "rust": "account-owner-invalid", + "reason": "Refused by precheck before nonce consume. TS reports bad-config for the same DID; Rust maps the account-owner refusal to 403." + } + }, + { + "name": "pkh-chain-leading-zero", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:01:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NTowMToweGYzOUZkNmU1MWFhZDg4RjZGNGNlNmFCODgyNzI3OWNmZkZiOTIyNjYiLCJpYXQiOjE3NjcyMjU2MDAsIm5iZiI6MTc2NzIyNTYwMCwiZXhwIjoxNzY5ODE3NjAwLCJqdGkiOiJ1cm46dXVpZDowYjZkMmM0ZS04YTFmLTRkM2UtOWI3YS0xYzJkM2U0ZjVhNmIiLCJ2Y3QiOiJvcGVuY3JlZGVudGlhbHMuZW1haWwvdjEiLCJwcm9maWxlIjoidGlueWNsb3VkLmVtYWlsLWhlbGQvdjEiLCJwcm9maWxlVmVyc2lvbiI6MSwiaG9sZGVyQmluZGluZyI6eyJkaWQiOiJkaWQ6cGtoOmVpcDE1NTowMToweGYzOUZkNmU1MWFhZDg4RjZGNGNlNmFCODgyNzI3OWNmZkZiOTIyNjYiLCJzaWduaW5nRG9tYWluIjoidGlueWNsb3VkLmNyZWRlbnRpYWxzL2FjY291bnQtYmluZGluZy92MSJ9LCJzdGF0dXMiOnsibWV0aG9kIjoibm9uZSJ9LCJfc2RfYWxnIjoic2hhLTI1NiIsIl9zZCI6WyI4RWtrU3lLdGNsZzRjRXZUdWZpS2thQlJpNmhCMWd4T3NzRmZsM05rYU84IiwiVzBoVHVIZVpnUjdoenRfSkF0RElEVy1jTHFYMi1fR1FEVktlMHdiRy1pdyJdfQ.fhLfM9TVOT1w_YBF1ZEXxbxT8UCVRtOBpbiAbs50fUb-rNwX55_ZPo7OV5nDDA3br-Wnxu6mKHs0c3VVMAjxAA~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: heldtestnonce0000000001\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:laz72WmsRJ93DMIEs6OiQEg8HZ-lu1kajnxyQo2Cdbs", + "signature": "0x24a748597f46f63d9e4ac3c2d55a2be52b283520c37391dfb931ac07feafd52a4d600a683da452078820764ad6d766cc898f89d5094cccd14fa1600b27a0abd31c" + }, + "nonceStore": [ + { + "key": "verifier.example\nheldtestnonce0000000001", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-config", + "detail": "bad-config: callerAccount must be a did:pkh:eip155 account" + }, + "deviation": { + "rust": "account-owner-invalid", + "reason": "Refused by precheck before nonce consume. TS reports bad-config for the same DID; Rust maps the account-owner refusal to 403." + } + }, + { + "name": "pkh-trailing-space", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 ", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiAiLCJpYXQiOjE3NjcyMjU2MDAsIm5iZiI6MTc2NzIyNTYwMCwiZXhwIjoxNzY5ODE3NjAwLCJqdGkiOiJ1cm46dXVpZDowYjZkMmM0ZS04YTFmLTRkM2UtOWI3YS0xYzJkM2U0ZjVhNmIiLCJ2Y3QiOiJvcGVuY3JlZGVudGlhbHMuZW1haWwvdjEiLCJwcm9maWxlIjoidGlueWNsb3VkLmVtYWlsLWhlbGQvdjEiLCJwcm9maWxlVmVyc2lvbiI6MSwiaG9sZGVyQmluZGluZyI6eyJkaWQiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiAiLCJzaWduaW5nRG9tYWluIjoidGlueWNsb3VkLmNyZWRlbnRpYWxzL2FjY291bnQtYmluZGluZy92MSJ9LCJzdGF0dXMiOnsibWV0aG9kIjoibm9uZSJ9LCJfc2RfYWxnIjoic2hhLTI1NiIsIl9zZCI6WyI4RWtrU3lLdGNsZzRjRXZUdWZpS2thQlJpNmhCMWd4T3NzRmZsM05rYU84IiwiVzBoVHVIZVpnUjdoenRfSkF0RElEVy1jTHFYMi1fR1FEVktlMHdiRy1pdyJdfQ.sy_Dn6b4xNJ2-wkKVFbARiyy6So4eBLQ9_2_4djVzGiN9TWGkxBuJ79Ae8KmBeyF2acu_jiQOi6LaX_ZV51WAw~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 \n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: heldtestnonce0000000001\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:Okkm22tEcysIaJGfVgkk-AeGNcdbKcfvrEI_Be-lMic", + "signature": "0xa4697b4049a5649df5a1889450b3137b8aef7fa09c54abc1f66f900ee11972532768b779bc61a77fed2015360a72eaf33e3047062e81ad45f14351330cea3e0b1c" + }, + "nonceStore": [ + { + "key": "verifier.example\nheldtestnonce0000000001", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-config", + "detail": "bad-config: callerAccount must be a did:pkh:eip155 account" + }, + "deviation": { + "rust": "account-owner-invalid", + "reason": "Refused by precheck before nonce consume. TS reports bad-config for the same DID; Rust maps the account-owner refusal to 403." + } + }, + { + "name": "pkh-zero-address", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0x0000000000000000000000000000000000000000", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMCIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHgwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwIiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.4uCcJcYP6hQfT4Wci6Rx6xzIfmj9iUgYmW8Wgmej3JWq5SgHAIiFqrBrQEnqaN--5jFGGt4JofjVs4GG04jFDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0x0000000000000000000000000000000000000000\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: heldtestnonce0000000001\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:sQ8AoH7wiDf5fAFyv6XlQwquoyhYXOgMStH_5HMo6oU", + "signature": "0x3ff7b5e6b9f0021757510a25682b24d2cdb97008a1e9375e6646078fe3c3c04648c693e44503be9f1e9495a8c4869a4a4372638bee05eace1658eaeac9279eda1b" + }, + "nonceStore": [ + { + "key": "verifier.example\nheldtestnonce0000000001", + "account": "did:pkh:eip155:1:0x0000000000000000000000000000000000000000" + } + ], + "ts": { + "code": "bad-siwe-signature", + "detail": "bad-siwe-signature: signature does not recover the credential subject" + } + }, + { + "name": "siwe-enc-v-0-1", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: heldtestnonce0000000001\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:eQXOZSXekF4OXymmuUiq0bSeG_wfOw3b2JlaG4CGhkU", + "signature": "0xaf781f15e005fd726c9fc34b14d3b21cb34012b5b601e8b0c2291a551101159946c2abb115e50f9391a76207389a1d87e1f0adfb5606aa4acc1f42b07b35cb7101" + }, + "nonceStore": [ + { + "key": "verifier.example\nheldtestnonce0000000001", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "ok", + "subject": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "issuer": "did:web:issuer.credentials.org" + } + }, + { + "name": "siwe-enc-v-29", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: heldtestnonce0000000001\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:eQXOZSXekF4OXymmuUiq0bSeG_wfOw3b2JlaG4CGhkU", + "signature": "0xaf781f15e005fd726c9fc34b14d3b21cb34012b5b601e8b0c2291a551101159946c2abb115e50f9391a76207389a1d87e1f0adfb5606aa4acc1f42b07b35cb711d" + }, + "nonceStore": [ + { + "key": "verifier.example\nheldtestnonce0000000001", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-siwe-signature", + "detail": "bad-siwe-signature: signature does not recover the credential subject" + } + }, + { + "name": "siwe-enc-hex-uppercase", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: heldtestnonce0000000001\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:eQXOZSXekF4OXymmuUiq0bSeG_wfOw3b2JlaG4CGhkU", + "signature": "0xAF781F15E005FD726C9FC34B14D3B21CB34012B5B601E8B0C2291A551101159946C2ABB115E50F9391A76207389A1D87E1F0ADFB5606AA4ACC1F42B07B35CB711C" + }, + "nonceStore": [ + { + "key": "verifier.example\nheldtestnonce0000000001", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "ok", + "subject": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "issuer": "did:web:issuer.credentials.org" + } + }, + { + "name": "siwe-enc-no-prefix", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: heldtestnonce0000000001\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:eQXOZSXekF4OXymmuUiq0bSeG_wfOw3b2JlaG4CGhkU", + "signature": "af781f15e005fd726c9fc34b14d3b21cb34012b5b601e8b0c2291a551101159946c2abb115e50f9391a76207389a1d87e1f0adfb5606aa4acc1f42b07b35cb711c" + }, + "nonceStore": [ + { + "key": "verifier.example\nheldtestnonce0000000001", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-siwe-signature", + "detail": "bad-siwe-signature: not hex" + } + }, + { + "name": "siwe-enc-leading-space", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: heldtestnonce0000000001\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:eQXOZSXekF4OXymmuUiq0bSeG_wfOw3b2JlaG4CGhkU", + "signature": " 0xaf781f15e005fd726c9fc34b14d3b21cb34012b5b601e8b0c2291a551101159946c2abb115e50f9391a76207389a1d87e1f0adfb5606aa4acc1f42b07b35cb711c" + }, + "nonceStore": [ + { + "key": "verifier.example\nheldtestnonce0000000001", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-presentation", + "detail": "bad-presentation: siwe signature is too long" + } + }, + { + "name": "siwe-enc-nonhex-char", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: heldtestnonce0000000001\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:eQXOZSXekF4OXymmuUiq0bSeG_wfOw3b2JlaG4CGhkU", + "signature": "0xaf781f15g005fd726c9fc34b14d3b21cb34012b5b601e8b0c2291a551101159946c2abb115e50f9391a76207389a1d87e1f0adfb5606aa4acc1f42b07b35cb711c" + }, + "nonceStore": [ + { + "key": "verifier.example\nheldtestnonce0000000001", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-siwe-signature", + "detail": "bad-siwe-signature: not hex" + } + }, + { + "name": "siwe-enc-high-s", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: heldtestnonce0000000001\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:eQXOZSXekF4OXymmuUiq0bSeG_wfOw3b2JlaG4CGhkU", + "signature": "0xaf781f15e005fd726c9fc34b14d3b21cb34012b5b601e8b0c2291a5511011599b93d544eea1af06c6e589df8c765e276d8be2eeb5941f5f0f3b31bdc550075d01b" + }, + "nonceStore": [ + { + "key": "verifier.example\nheldtestnonce0000000001", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "ok", + "subject": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "issuer": "did:web:issuer.credentials.org" + }, + "deviation": { + "rust": "bad-siwe-signature", + "reason": "Rust refuses high-S ECDSA signatures (recover_from_prehash). TS accepts. Known deviation, decided to keep the Rust refusal." + } + }, + { + "name": "siwe-enc-high-s-same-v", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: heldtestnonce0000000001\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:eQXOZSXekF4OXymmuUiq0bSeG_wfOw3b2JlaG4CGhkU", + "signature": "0xaf781f15e005fd726c9fc34b14d3b21cb34012b5b601e8b0c2291a5511011599b93d544eea1af06c6e589df8c765e276d8be2eeb5941f5f0f3b31bdc550075d01c" + }, + "nonceStore": [ + { + "key": "verifier.example\nheldtestnonce0000000001", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-siwe-signature", + "detail": "bad-siwe-signature: signature does not recover the credential subject" + } + }, + { + "name": "siwe-enc-r-zero", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: heldtestnonce0000000001\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:eQXOZSXekF4OXymmuUiq0bSeG_wfOw3b2JlaG4CGhkU", + "signature": "0x000000000000000000000000000000000000000000000000000000000000000046c2abb115e50f9391a76207389a1d87e1f0adfb5606aa4acc1f42b07b35cb711c" + }, + "nonceStore": [ + { + "key": "verifier.example\nheldtestnonce0000000001", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-siwe-signature", + "detail": "bad-siwe-signature: signature does not recover the credential subject" + } + }, + { + "name": "siwe-enc-s-zero", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: heldtestnonce0000000001\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:eQXOZSXekF4OXymmuUiq0bSeG_wfOw3b2JlaG4CGhkU", + "signature": "0xaf781f15e005fd726c9fc34b14d3b21cb34012b5b601e8b0c2291a551101159900000000000000000000000000000000000000000000000000000000000000001c" + }, + "nonceStore": [ + { + "key": "verifier.example\nheldtestnonce0000000001", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-siwe-signature", + "detail": "bad-siwe-signature: signature does not recover the credential subject" + } + }, + { + "name": "siwe-enc-no-v", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: heldtestnonce0000000001\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:eQXOZSXekF4OXymmuUiq0bSeG_wfOw3b2JlaG4CGhkU", + "signature": "0xaf781f15e005fd726c9fc34b14d3b21cb34012b5b601e8b0c2291a551101159946c2abb115e50f9391a76207389a1d87e1f0adfb5606aa4acc1f42b07b35cb71" + }, + "nonceStore": [ + { + "key": "verifier.example\nheldtestnonce0000000001", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-siwe-signature", + "detail": "bad-siwe-signature: signature does not recover the credential subject" + } + }, + { + "name": "uri-trailing-slash", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example/\nVersion: 1\nChain ID: 1\nNonce: d9ea82583acba3dd621f056a60f3814c\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:eQXOZSXekF4OXymmuUiq0bSeG_wfOw3b2JlaG4CGhkU", + "signature": "0xaf3b2e35bf2b5ec533ccc6a05b6f869f4c70d6caea19937ad849b473812dae847e7bc375c2c0b75f72e7f0cd9ab2ed9bd92dffb9745cd7ae2dde590c7470f7031b" + }, + "nonceStore": [ + { + "key": "verifier.example\nd9ea82583acba3dd621f056a60f3814c", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "ok", + "subject": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "issuer": "did:web:issuer.credentials.org" + } + }, + { + "name": "uri-trailing-dot", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example.\nVersion: 1\nChain ID: 1\nNonce: 39fa430970f1985fa09a392791138179\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:eQXOZSXekF4OXymmuUiq0bSeG_wfOw3b2JlaG4CGhkU", + "signature": "0xb74718725e1b8183441c86d48b1b4c23b5da44e604fddc5de792fc2cafb0c8a92a1fa622897c0f20554367c11404c759e4d9d63edbaa5e359bca921e9009ac361b" + }, + "nonceStore": [ + { + "key": "verifier.example\n39fa430970f1985fa09a392791138179", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-siwe", + "detail": "bad-siwe: uri must be an https origin matching the audience" + } + }, + { + "name": "uri-backslash", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\\\nVersion: 1\nChain ID: 1\nNonce: 5cdc0f34c98766f994c201fd39653232\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:eQXOZSXekF4OXymmuUiq0bSeG_wfOw3b2JlaG4CGhkU", + "signature": "0xda1280d087fed3a9285a041f4b911170c36dca3ea15d0f966952f7c75df7a7cb5c9d25f782efab3d052a6ebc89132b2b194e646515983b19833d1b8291226de11b" + }, + "nonceStore": [ + { + "key": "verifier.example\n5cdc0f34c98766f994c201fd39653232", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "ok", + "subject": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "issuer": "did:web:issuer.credentials.org" + } + }, + { + "name": "uri-double-backslash", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https:\\\\verifier.example\nVersion: 1\nChain ID: 1\nNonce: a7b0212edfdf2646d9ef1a29069bd16b\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:eQXOZSXekF4OXymmuUiq0bSeG_wfOw3b2JlaG4CGhkU", + "signature": "0x86fb113f886c0bbac4cca9f6eea0f40e0f6d5163cc70d33288b14cd89ba6cae803d087360c82a506d1a302cbf4b5d642c2668fb066f96a1333db67cccf0efcfa1b" + }, + "nonceStore": [ + { + "key": "verifier.example\na7b0212edfdf2646d9ef1a29069bd16b", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "ok", + "subject": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "issuer": "did:web:issuer.credentials.org" + } + }, + { + "name": "uri-single-slash", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https:/verifier.example\nVersion: 1\nChain ID: 1\nNonce: 9518ad83ad58e333bab1fd023d28bd41\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:eQXOZSXekF4OXymmuUiq0bSeG_wfOw3b2JlaG4CGhkU", + "signature": "0x8551dab0da79cb1f95f94f0b0f6edc4831695c6e95318c04f71171f59d86d10715ea1cc9c842810fbfdbaa14f2b7adcd6d79731d873d98a6a2d382ae2ae6fe0b1c" + }, + "nonceStore": [ + { + "key": "verifier.example\n9518ad83ad58e333bab1fd023d28bd41", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "ok", + "subject": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "issuer": "did:web:issuer.credentials.org" + } + }, + { + "name": "uri-pct-dot", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier%2Eexample\nVersion: 1\nChain ID: 1\nNonce: 45288285fe6f4d0a54cfccc08d0e249a\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:eQXOZSXekF4OXymmuUiq0bSeG_wfOw3b2JlaG4CGhkU", + "signature": "0xfcf9465e48bac889f08e5583cdf2220a498288c7f546fb0810725aa0502425ea0e4e34652cbd6ebf7abf7d58c3b9d9efeb279ea5dcd9f55d9cd84917ec3257421b" + }, + "nonceStore": [ + { + "key": "verifier.example\n45288285fe6f4d0a54cfccc08d0e249a", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "ok", + "subject": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "issuer": "did:web:issuer.credentials.org" + } + }, + { + "name": "uri-ipv6-loopback", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://[::1]/\nVersion: 1\nChain ID: 1\nNonce: b938c48d3d79dd536b38ed5bb374f025\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:eQXOZSXekF4OXymmuUiq0bSeG_wfOw3b2JlaG4CGhkU", + "signature": "0x3805b2e97019b02ceb42001193a6f1b0897fbfee23dc0c3c4dfdfb26da3c003e4c28cc5aa4dc71347cbf31ff41fd7e5d4140fb7280be2ce33a4a1be6f1ad70031c" + }, + "nonceStore": [ + { + "key": "verifier.example\nb938c48d3d79dd536b38ed5bb374f025", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-siwe", + "detail": "bad-siwe: uri must be an https origin matching the audience" + } + }, + { + "name": "uri-query", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example?x=1\nVersion: 1\nChain ID: 1\nNonce: d9123a9a7f81931afd7d0e03c294d74f\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:eQXOZSXekF4OXymmuUiq0bSeG_wfOw3b2JlaG4CGhkU", + "signature": "0xb14edcc3ba283da7f150c48e8a79a317562a53c1485dd0d050dd1aefe6a402eb03f44a6c5248c8fb05da2b710d3715e2ec633009a7e7845562b7f27c991856191b" + }, + "nonceStore": [ + { + "key": "verifier.example\nd9123a9a7f81931afd7d0e03c294d74f", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "ok", + "subject": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "issuer": "did:web:issuer.credentials.org" + } + }, + { + "name": "uri-fragment", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example#frag\nVersion: 1\nChain ID: 1\nNonce: dc702457108acf8bbe152e06eadc45f5\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:eQXOZSXekF4OXymmuUiq0bSeG_wfOw3b2JlaG4CGhkU", + "signature": "0x8d3f0c63b07d961bb978dd9ab468e35894dd8312f56bd711d227ff0579bd9168693c02f817e506322b5c6551b41478f2cf79f0dbbd7aca0767ec8acfb4b309011c" + }, + "nonceStore": [ + { + "key": "verifier.example\ndc702457108acf8bbe152e06eadc45f5", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "ok", + "subject": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "issuer": "did:web:issuer.credentials.org" + } + }, + { + "name": "uri-empty-port", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example:\nVersion: 1\nChain ID: 1\nNonce: 949761baf9b3b0b1c6f68ae3e760114a\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:eQXOZSXekF4OXymmuUiq0bSeG_wfOw3b2JlaG4CGhkU", + "signature": "0x654ff93091ae3125600b1780df9c283eb7b999683d0ba97e99b1e394f1e7583d7f359c85a029d33bb943ccbe4012d008301842bc4d2ec95a27274950872a44ee1b" + }, + "nonceStore": [ + { + "key": "verifier.example\n949761baf9b3b0b1c6f68ae3e760114a", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "ok", + "subject": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "issuer": "did:web:issuer.credentials.org" + } + }, + { + "name": "uri-port-leading-zero", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example:0443\nVersion: 1\nChain ID: 1\nNonce: 1ee2f27938966c0dd3d0fc452d0d9480\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:eQXOZSXekF4OXymmuUiq0bSeG_wfOw3b2JlaG4CGhkU", + "signature": "0x46511638c1b4fc2b8a76c5724d5924870786e59b7a40b341492b175f732eb6c17cdf761cfa2e44f17022b5a32ca45c97ac27321bf12393012678d0c9a9d8d7d11b" + }, + "nonceStore": [ + { + "key": "verifier.example\n1ee2f27938966c0dd3d0fc452d0d9480", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "ok", + "subject": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "issuer": "did:web:issuer.credentials.org" + } + }, + { + "name": "uri-port-plus", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example:+443\nVersion: 1\nChain ID: 1\nNonce: 4d213b65dae94aaf4406fba052805ab8\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:eQXOZSXekF4OXymmuUiq0bSeG_wfOw3b2JlaG4CGhkU", + "signature": "0x8195348e288346d2154e302501c204180d273bd00a49985ae2067b00a1cc4c2f048261918639adf322ee019a5f3a0fa24accf5818bb33c67dbe584d25edc360f1c" + }, + "nonceStore": [ + { + "key": "verifier.example\n4d213b65dae94aaf4406fba052805ab8", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-siwe", + "detail": "bad-siwe: uri must be an https origin matching the audience" + } + }, + { + "name": "uri-scheme-upper", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: HTTPS://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 0b6e588aadb4548f1056c2173ecca676\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:eQXOZSXekF4OXymmuUiq0bSeG_wfOw3b2JlaG4CGhkU", + "signature": "0x06289b468e50647b42f033837b7debe7859de372d360088e0fbfe14f7ac020c63c1dfc2485dcb483c506e39b6eec80a510a562a0e4c5ccae0f5758e2f2280c941c" + }, + "nonceStore": [ + { + "key": "verifier.example\n0b6e588aadb4548f1056c2173ecca676", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "ok", + "subject": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "issuer": "did:web:issuer.credentials.org" + } + }, + { + "name": "uri-tab", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\t\nVersion: 1\nChain ID: 1\nNonce: f1acc283c34d35d104f7f8f9fe0ff222\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:eQXOZSXekF4OXymmuUiq0bSeG_wfOw3b2JlaG4CGhkU", + "signature": "0x9cad28fa23d51660ea31c3ec98356d551e8900425488fa558620e91a350c99581e463314d995873c09f84241e23d92f509e02820e466f039f2c4b64c7b056d411c" + }, + "nonceStore": [ + { + "key": "verifier.example\nf1acc283c34d35d104f7f8f9fe0ff222", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "ok", + "subject": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "issuer": "did:web:issuer.credentials.org" + } + }, + { + "name": "port-domain-443", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example:443 wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 57acf26062fc1fb1b83f72cb3f35758e\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:eQXOZSXekF4OXymmuUiq0bSeG_wfOw3b2JlaG4CGhkU", + "signature": "0x6540b6e51cd8c647054c5fd9cc0f8e029e8a1b379e6fa844cce4079dd484cfcf37c8dc2860d13ab743c27eb250fb2a50203a112a8beafc39f871549250bddeda1c" + }, + "nonceStore": [ + { + "key": "verifier.example\n57acf26062fc1fb1b83f72cb3f35758e", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-siwe", + "detail": "bad-siwe: domain is not this verifier's audience" + } + }, + { + "name": "port-domain-8443", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example:8443 wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 6d500ee7ab0ac24e3adbbb8963c6402f\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:eQXOZSXekF4OXymmuUiq0bSeG_wfOw3b2JlaG4CGhkU", + "signature": "0xe59ab5284e3b31b261c81ad49763d0806bffeaceb820dcab4ba884bb989974ee613acc22683c70aef739373daac9f876aea4798b9f6d819111efc94e0f598dd01b" + }, + "nonceStore": [ + { + "key": "verifier.example\n6d500ee7ab0ac24e3adbbb8963c6402f", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-siwe", + "detail": "bad-siwe: domain is not this verifier's audience" + } + }, + { + "name": "port-domain-empty", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example: wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: d5cf7232fc507b4c10473220d70e4fb8\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:eQXOZSXekF4OXymmuUiq0bSeG_wfOw3b2JlaG4CGhkU", + "signature": "0x9d528b30d052cafe24a41ba8913caa784fc0db1c1a563167b61fee387a57473a47d8e64f38204c668b30d391abd7df6e8d2de029926489f73b7b3f373aba58df1b" + }, + "nonceStore": [ + { + "key": "verifier.example\nd5cf7232fc507b4c10473220d70e4fb8", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-siwe", + "detail": "bad-siwe: domain is not this verifier's audience" + } + }, + { + "name": "port-uri-http-80", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: http://verifier.example:80\nVersion: 1\nChain ID: 1\nNonce: 7ce47e41253b6188f67f1f7f8c722bfb\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:eQXOZSXekF4OXymmuUiq0bSeG_wfOw3b2JlaG4CGhkU", + "signature": "0x3d4eb3fc1cc40b61a43419c32fcde4bdc28f842b0915e9e28bd0b466fd4f789e7a7faed540ca47b26703b023a47caa2113b7a958292ad1d18ed56d0b635281771b" + }, + "nonceStore": [ + { + "key": "verifier.example\n7ce47e41253b6188f67f1f7f8c722bfb", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-siwe", + "detail": "bad-siwe: uri must be an https origin matching the audience" + } + }, + { + "name": "port-uri-65535", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example:65535\nVersion: 1\nChain ID: 1\nNonce: 3d2ed19f55fcf97591bd0f19ba4ef14a\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:eQXOZSXekF4OXymmuUiq0bSeG_wfOw3b2JlaG4CGhkU", + "signature": "0x4d5cd7165f2ea6daad8e7be4297e32f4fe0760de77dadd728107d1f0a12ca76b70871ebff6eba04a30925b5c473bd842209184324b544a4d8442292a8c41cb721c" + }, + "nonceStore": [ + { + "key": "verifier.example\n3d2ed19f55fcf97591bd0f19ba4ef14a", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-siwe", + "detail": "bad-siwe: uri must be an https origin matching the audience" + } + }, + { + "name": "port-uri-00443", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example:00443\nVersion: 1\nChain ID: 1\nNonce: 0d6ec2f84a4e1f6d91d2818b90ab2388\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:eQXOZSXekF4OXymmuUiq0bSeG_wfOw3b2JlaG4CGhkU", + "signature": "0x4458be2105dad154eef29944a126faf31cf1603a7ec5dc106233b9a915acefde0636cb8b1a91abc0970444eb4efde8af6226a29184a15adf1825fec5feb9934a1b" + }, + "nonceStore": [ + { + "key": "verifier.example\n0d6ec2f84a4e1f6d91d2818b90ab2388", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "ok", + "subject": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "issuer": "did:web:issuer.credentials.org" + } + }, + { + "name": "rfc3339-exp-millis", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: da6ea69c7d0ece213db9d4585a4afb74\nIssued At: 2026-01-01T00:59:00Z\nExpiration Time: 2026-01-01T02:00:00.000Z\nResources:\n- urn:tinycloud:sd-hash:eQXOZSXekF4OXymmuUiq0bSeG_wfOw3b2JlaG4CGhkU", + "signature": "0xb6e9cac7e795fd4ff886b8bd05e530d516e45355c7276e9556c7a849c0057dfe5a675554fa9c97ef5b5bd8381b79215163faa043acc0ebaaa64459b58a81ccd01b" + }, + "nonceStore": [ + { + "key": "verifier.example\nda6ea69c7d0ece213db9d4585a4afb74", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "ok", + "subject": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "issuer": "did:web:issuer.credentials.org" + } + }, + { + "name": "rfc3339-exp-fraction-half", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: f410bc453586bceb671841c9bafbb9da\nIssued At: 2026-01-01T00:59:00Z\nExpiration Time: 2026-01-01T02:00:00.5Z\nResources:\n- urn:tinycloud:sd-hash:eQXOZSXekF4OXymmuUiq0bSeG_wfOw3b2JlaG4CGhkU", + "signature": "0x7b67e1cf6268cf2716f1f77e59639b0cb2d3c2d32ad38791db990ef978dff1ff7597a6e1e9dd41fa4c924cfd98b1281210ee45627280a40495d28fdb6b74470c1c" + }, + "nonceStore": [ + { + "key": "verifier.example\nf410bc453586bceb671841c9bafbb9da", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "ok", + "subject": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "issuer": "did:web:issuer.credentials.org" + } + }, + { + "name": "rfc3339-exp-offset-zero", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 0d34d23a74605cdea545b09a15c1660a\nIssued At: 2026-01-01T00:59:00Z\nExpiration Time: 2026-01-01T02:00:00+00:00\nResources:\n- urn:tinycloud:sd-hash:eQXOZSXekF4OXymmuUiq0bSeG_wfOw3b2JlaG4CGhkU", + "signature": "0x6e5de4adad7c3d90cdc60d95ede3a23de5addf2f23eec4f56edd284df423b1850116a785738f4b2f68bbbbc7f3c42a1af82a19e3cf3c353f109467267351d0ff1c" + }, + "nonceStore": [ + { + "key": "verifier.example\n0d34d23a74605cdea545b09a15c1660a", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "ok", + "subject": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "issuer": "did:web:issuer.credentials.org" + } + }, + { + "name": "rfc3339-exp-lowercase-z", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: eae970935725caeb3d752c1a909a8dbc\nIssued At: 2026-01-01T00:59:00Z\nExpiration Time: 2026-01-01T02:00:00z\nResources:\n- urn:tinycloud:sd-hash:eQXOZSXekF4OXymmuUiq0bSeG_wfOw3b2JlaG4CGhkU", + "signature": "0xf5e6bc32a4d43354125023ccf92af16c44aaa82c6993cbbefc1c46cdd8479b9a6ac1e09f5b2fe50726151220052c93f065b919c0cb7784ba6ef15fd506e40da61c" + }, + "nonceStore": [ + { + "key": "verifier.example\neae970935725caeb3d752c1a909a8dbc", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-siwe", + "detail": "bad-siwe: Expiration Time is not RFC 3339" + } + }, + { + "name": "rfc3339-exp-space-separator", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: c0efb3cf0802ca1f07b69571f732a274\nIssued At: 2026-01-01T00:59:00Z\nExpiration Time: 2026-01-01 02:00:00Z\nResources:\n- urn:tinycloud:sd-hash:eQXOZSXekF4OXymmuUiq0bSeG_wfOw3b2JlaG4CGhkU", + "signature": "0x1aa75573bdd75170c514bd2cefb917d335f21ba90d8dd558d6a018ceb95fdbd052028dfb873db6325fd9edefd7535b00e20f588abb4d1103f22c138962f433131b" + }, + "nonceStore": [ + { + "key": "verifier.example\nc0efb3cf0802ca1f07b69571f732a274", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-siwe", + "detail": "bad-siwe: Expiration Time is not RFC 3339" + } + }, + { + "name": "rfc3339-exp-feb-30", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 7ff3a5f0eb20d8244c7d99f1abbbe087\nIssued At: 2026-01-01T00:59:00Z\nExpiration Time: 2026-02-30T00:00:00Z\nResources:\n- urn:tinycloud:sd-hash:eQXOZSXekF4OXymmuUiq0bSeG_wfOw3b2JlaG4CGhkU", + "signature": "0x3b153523c3d5564c87a9ac91b69f45361b34562081d75a4922bd7a85fc8910cd0c4ca30dfaf70e2ecf0617ef42b98893234fc37b5209c3abbfaa1d3c5a1512691b" + }, + "nonceStore": [ + { + "key": "verifier.example\n7ff3a5f0eb20d8244c7d99f1abbbe087", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-siwe", + "detail": "bad-siwe: Expiration Time is not RFC 3339" + } + }, + { + "name": "rfc3339-exp-hour-24", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 5ae60fd72eff50046297278276408ce5\nIssued At: 2026-01-01T00:59:00Z\nExpiration Time: 2026-01-01T24:00:00Z\nResources:\n- urn:tinycloud:sd-hash:eQXOZSXekF4OXymmuUiq0bSeG_wfOw3b2JlaG4CGhkU", + "signature": "0xf1666b9a15394ddefe96dd26424fbbf1d6514de18faa49d805c4ad86074911a9794b4522e85f5a9563e7c9a321daf2fd7fdab0c08d53e8a31a16391fa97c0d7a1c" + }, + "nonceStore": [ + { + "key": "verifier.example\n5ae60fd72eff50046297278276408ce5", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-siwe", + "detail": "bad-siwe: Expiration Time is not RFC 3339" + } + }, + { + "name": "rfc3339-exp-leap-second", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 6b4bbd9b5a3e59998c5ec2cd4baf55f8\nIssued At: 2026-01-01T00:59:00Z\nExpiration Time: 2026-06-30T23:59:60Z\nResources:\n- urn:tinycloud:sd-hash:eQXOZSXekF4OXymmuUiq0bSeG_wfOw3b2JlaG4CGhkU", + "signature": "0x909e36386b085f28f5c5505141e9d605868c224bbdae099bdb061fdd0df4d3f91297da78574ad1d5c749bf5bbdffd547cfea93f19cfecf6affb8ebd5089af9711b" + }, + "nonceStore": [ + { + "key": "verifier.example\n6b4bbd9b5a3e59998c5ec2cd4baf55f8", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-siwe", + "detail": "bad-siwe: Expiration Time is not RFC 3339" + } + }, + { + "name": "rfc3339-exp-1ms-after-now", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 9aabeb1205d1e0856d4def96a63c4319\nIssued At: 2026-01-01T00:59:00Z\nExpiration Time: 2026-01-01T01:00:00.001Z\nResources:\n- urn:tinycloud:sd-hash:eQXOZSXekF4OXymmuUiq0bSeG_wfOw3b2JlaG4CGhkU", + "signature": "0xbb2ee18cfcef7c15ea5f8f6b2a305de2fae89875e75349d1c6a901cb7e8a39927fc9433dffcd73ad93b2896bc65abc5dbd970c301fd2b2253465400794f7f8f61b" + }, + "nonceStore": [ + { + "key": "verifier.example\n9aabeb1205d1e0856d4def96a63c4319", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "ok", + "subject": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "issuer": "did:web:issuer.credentials.org" + } + }, + { + "name": "rfc3339-exp-sub-ms-equals-now", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 63c3eafd40a7b95898179a664e84fc07\nIssued At: 2026-01-01T00:59:00Z\nExpiration Time: 2026-01-01T01:00:00.0001Z\nResources:\n- urn:tinycloud:sd-hash:eQXOZSXekF4OXymmuUiq0bSeG_wfOw3b2JlaG4CGhkU", + "signature": "0xac6a52956c9991c58799884e4edf1eee603e4199ee7c4f1cdd8ef5aa54ce5f7e41b7a5a7f20770e9b9b1ca84a8960b51691db95619a0e9c2ffe3b4224270d84d1c" + }, + "nonceStore": [ + { + "key": "verifier.example\n63c3eafd40a7b95898179a664e84fc07", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-siwe", + "detail": "bad-siwe: SIWE has expired" + } + }, + { + "name": "rfc3339-exp-comma-fraction", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 039220704a72b3ee46a76ac297a4df55\nIssued At: 2026-01-01T00:59:00Z\nExpiration Time: 2026-01-01T02:00:00,000Z\nResources:\n- urn:tinycloud:sd-hash:eQXOZSXekF4OXymmuUiq0bSeG_wfOw3b2JlaG4CGhkU", + "signature": "0xbc3339e05b68a74b1e4c18b4651af04083036b3481845cf51f3f0a988bb9a0113f97a275485ee7b11c51cfd7ec15063cd96894a9110e256ba6969ae4e061c9981c" + }, + "nonceStore": [ + { + "key": "verifier.example\n039220704a72b3ee46a76ac297a4df55", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-siwe", + "detail": "bad-siwe: Expiration Time is not RFC 3339" + } + }, + { + "name": "rfc3339-nbf-sub-ms-past", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 64d8f84993c171a62923775182a4f756\nIssued At: 2026-01-01T00:59:00Z\nNot Before: 2026-01-01T01:00:00.0009Z\nResources:\n- urn:tinycloud:sd-hash:eQXOZSXekF4OXymmuUiq0bSeG_wfOw3b2JlaG4CGhkU", + "signature": "0x7498c8e52d18eb5687c62f4b15e4bdec21d5f925467687b9a14b9e82449294473e6c49a0ec75bb57672560edbe8204397ab69d18a2572f412e193393fea386271c" + }, + "nonceStore": [ + { + "key": "verifier.example\n64d8f84993c171a62923775182a4f756", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "ok", + "subject": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "issuer": "did:web:issuer.credentials.org" + } + }, + { + "name": "rfc3339-nbf-1ms-future", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: c2f3ed7b207bf33b10bcea784dbf9371\nIssued At: 2026-01-01T00:59:00Z\nNot Before: 2026-01-01T01:00:00.001Z\nResources:\n- urn:tinycloud:sd-hash:eQXOZSXekF4OXymmuUiq0bSeG_wfOw3b2JlaG4CGhkU", + "signature": "0xb7a72c4c47205b234f11ba6f219a6fc150afc7c4288c6721e1dc559eb11f23b406ffc65f06a87b857e77925f064961036a2cb0227cf271649bb5b7cd56db6db51c" + }, + "nonceStore": [ + { + "key": "verifier.example\nc2f3ed7b207bf33b10bcea784dbf9371", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-siwe", + "detail": "bad-siwe: SIWE is not yet valid" + } + }, + { + "name": "rfc3339-exp-year-9999", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: b36968a4125f7a239f033c6801ff6798\nIssued At: 2026-01-01T00:59:00Z\nExpiration Time: 9999-12-31T23:59:59Z\nResources:\n- urn:tinycloud:sd-hash:eQXOZSXekF4OXymmuUiq0bSeG_wfOw3b2JlaG4CGhkU", + "signature": "0xa5ea230dca4f0e3cb452ef3b985b4963453090c4defb6a7dd9f8733acaa4a5885e2116815108f47ab97f05c1de634d304d28fb074487105c30a8436d8f76be2b1c" + }, + "nonceStore": [ + { + "key": "verifier.example\nb36968a4125f7a239f033c6801ff6798", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "ok", + "subject": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "issuer": "did:web:issuer.credentials.org" + } + }, + { + "name": "layout-crlf", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\r\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\r\n\r\nPresent a TinyCloud held credential\r\n\r\nURI: https://verifier.example\r\nVersion: 1\r\nChain ID: 1\r\nNonce: heldtestnonce0000000001\r\nIssued At: 2026-01-01T00:59:00Z\r\nResources:\r\n- urn:tinycloud:sd-hash:eQXOZSXekF4OXymmuUiq0bSeG_wfOw3b2JlaG4CGhkU", + "signature": "0x71258c61446a352618bbcf51e989eadcae96bab2bd1d9378f45b284f6cbc433753fabb6643f11a9d43dc5d3f68e52e4698f38a9c0e04ca67168ae2eae4d3c0d01c" + }, + "nonceStore": [ + { + "key": "verifier.example\nheldtestnonce0000000001", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-siwe", + "detail": "bad-siwe: header line" + } + }, + { + "name": "layout-no-blank-after-address", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: heldtestnonce0000000001\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:eQXOZSXekF4OXymmuUiq0bSeG_wfOw3b2JlaG4CGhkU", + "signature": "0x2866c84bf6767718eaf0db873b79f0586828e5f33cccc1bf9e6246e6fabd35de66746dcc134b8f63daf3526576c79e2b33aa72e9766bfc99bf5bd5313208ec741c" + }, + "nonceStore": [ + { + "key": "verifier.example\nheldtestnonce0000000001", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-siwe", + "detail": "bad-siwe: layout" + } + }, + { + "name": "layout-trailing-newline", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: heldtestnonce0000000001\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:eQXOZSXekF4OXymmuUiq0bSeG_wfOw3b2JlaG4CGhkU\n", + "signature": "0x25fc8c3bdf6d79a1bef5f189f079647c40e0642dbf14e249d04149e78066da6610876d6113b3c7ec06722bb2fd446d1110537f6f2162a900b8956d62fc6d3f791b" + }, + "nonceStore": [ + { + "key": "verifier.example\nheldtestnonce0000000001", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-siwe", + "detail": "bad-siwe: trailing content" + } + }, + { + "name": "layout-extra-line", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nExtra: x\nNonce: heldtestnonce0000000001\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:eQXOZSXekF4OXymmuUiq0bSeG_wfOw3b2JlaG4CGhkU", + "signature": "0x6f98ba6144f03fec45158e2b49db2ebd24410e4afb02cd645f8c2a14fb1050b578a8929498edd7dc6b8fd416bd047c20da2ba16cb1dbac34054e836c1dc89a3f1c" + }, + "nonceStore": [ + { + "key": "verifier.example\nheldtestnonce0000000001", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-siwe", + "detail": "bad-siwe: missing Nonce" + } + }, + { + "name": "layout-no-statement", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: heldtestnonce0000000001\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:eQXOZSXekF4OXymmuUiq0bSeG_wfOw3b2JlaG4CGhkU", + "signature": "0xb32c93fa00a7cd11952e4b933f6cfffb516abb6f26772568dd121bb3e10d9c5c6be542a26c13c0801a28ef994aefc13c811b8f676f866d3c2d270377425b91321c" + }, + "nonceStore": [ + { + "key": "verifier.example\nheldtestnonce0000000001", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-siwe", + "detail": "bad-siwe: statement" + } + }, + { + "name": "layout-no-issued-at", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: heldtestnonce0000000001\nResources:\n- urn:tinycloud:sd-hash:eQXOZSXekF4OXymmuUiq0bSeG_wfOw3b2JlaG4CGhkU", + "signature": "0x52fb40437fc3659b0bfe1d3ce6425a181c0ab86f9ac662723276f7eebb62d9b97497040f58e0470c68ef560fd3647a772b3e6034d44157314a63402f9abaf5741c" + }, + "nonceStore": [ + { + "key": "verifier.example\nheldtestnonce0000000001", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-siwe", + "detail": "bad-siwe: missing Issued At" + } + }, + { + "name": "layout-uri-lowercase-key", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nuri: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: heldtestnonce0000000001\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:eQXOZSXekF4OXymmuUiq0bSeG_wfOw3b2JlaG4CGhkU", + "signature": "0x76ad00f6dd42abe1082451acdf59eb75c841150c99e19c67c273bc15dcafe92759ab107f2df27c6bba186baf62c60e1f808fc9b2a4bbd8fa75a106cf41e93a291b" + }, + "nonceStore": [ + { + "key": "verifier.example\nheldtestnonce0000000001", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-siwe", + "detail": "bad-siwe: missing URI" + } + }, + { + "name": "layout-duplicate-uri", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: heldtestnonce0000000001\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:eQXOZSXekF4OXymmuUiq0bSeG_wfOw3b2JlaG4CGhkU", + "signature": "0x5571c51b3e3474dff72f5fc9d0ec054e3e5205feaf6c98b3c18fc72def149d2870d92b890f4082624ed4d321094b37cfa796e1837ce48ade13d31fcc4e99e9a41c" + }, + "nonceStore": [ + { + "key": "verifier.example\nheldtestnonce0000000001", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-siwe", + "detail": "bad-siwe: missing Version" + } + }, + { + "name": "layout-resource-no-space", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: heldtestnonce0000000001\nIssued At: 2026-01-01T00:59:00Z\nResources:\n-urn:tinycloud:sd-hash:eQXOZSXekF4OXymmuUiq0bSeG_wfOw3b2JlaG4CGhkU", + "signature": "0x2d9e0a9f9411c4d86a466ad211705d255123209ecc4fb21797d949c95e65b48241367b0b50ef176de25b7bb079b7076841343627a1171bb2f80c91a6ff0c5f851c" + }, + "nonceStore": [ + { + "key": "verifier.example\nheldtestnonce0000000001", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-siwe", + "detail": "bad-siwe: trailing content" + } + }, + { + "name": "layout-no-resources-header", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: heldtestnonce0000000001\nIssued At: 2026-01-01T00:59:00Z\n- urn:tinycloud:sd-hash:eQXOZSXekF4OXymmuUiq0bSeG_wfOw3b2JlaG4CGhkU", + "signature": "0x350d6928464a4366b6bda7e98ec267401965a0788e7e49ac7ba55eeb5bdfaf932eb1320710186c3a98ce45e4e487bbb40aab17b4d4ccbe7859e2cfd4ee4522351b" + }, + "nonceStore": [ + { + "key": "verifier.example\nheldtestnonce0000000001", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-siwe", + "detail": "bad-siwe: trailing content" + } + }, + { + "name": "json-iat-exponent", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MS43NjcyMjU2ZTksIm5iZiI6MTc2NzIyNTYwMCwiZXhwIjoxNzY5ODE3NjAwLCJqdGkiOiJ1cm46dXVpZDowYjZkMmM0ZS04YTFmLTRkM2UtOWI3YS0xYzJkM2U0ZjVhNmIiLCJ2Y3QiOiJvcGVuY3JlZGVudGlhbHMuZW1haWwvdjEiLCJwcm9maWxlIjoidGlueWNsb3VkLmVtYWlsLWhlbGQvdjEiLCJwcm9maWxlVmVyc2lvbiI6MSwiaG9sZGVyQmluZGluZyI6eyJkaWQiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsInNpZ25pbmdEb21haW4iOiJ0aW55Y2xvdWQuY3JlZGVudGlhbHMvYWNjb3VudC1iaW5kaW5nL3YxIn0sInN0YXR1cyI6eyJtZXRob2QiOiJub25lIn0sIl9zZF9hbGciOiJzaGEtMjU2IiwiX3NkIjpbIjhFa2tTeUt0Y2xnNGNFdlR1ZmlLa2FCUmk2aEIxZ3hPc3NGZmwzTmthTzgiLCJXMGhUdUhlWmdSN2h6dF9KQXRESURXLWNMcVgyLV9HUURWS2Uwd2JHLWl3Il19.KnGqPrkLr4niyS1vI_lZYK5RMmLFQPnstAocI1zhUsyv7tf2xyPv1b5RqJFUQ4_srGEQSgFUXrpQShPBXiPDBg~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: b4f20f4c0f07fa26dad65f80c9073365\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:oqVSQOtA9emNY32C1buRNtjSpQOKq7Zr9Wnoba08lFk", + "signature": "0x0fb456cf45b3614a8a3083504a056dabe48a2012045e15e4e2aec5484717f0a038b7e64194ada2d9d2c1cc7804e07df410a355cf04a85e7ec9f3768fd1a341051b" + }, + "nonceStore": [ + { + "key": "verifier.example\nb4f20f4c0f07fa26dad65f80c9073365", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-payload", + "detail": "bad-payload: invalid JSON: unexpected token" + } + }, + { + "name": "json-iat-leading-zero", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MDE3NjcyMjU2MDAsIm5iZiI6MTc2NzIyNTYwMCwiZXhwIjoxNzY5ODE3NjAwLCJqdGkiOiJ1cm46dXVpZDowYjZkMmM0ZS04YTFmLTRkM2UtOWI3YS0xYzJkM2U0ZjVhNmIiLCJ2Y3QiOiJvcGVuY3JlZGVudGlhbHMuZW1haWwvdjEiLCJwcm9maWxlIjoidGlueWNsb3VkLmVtYWlsLWhlbGQvdjEiLCJwcm9maWxlVmVyc2lvbiI6MSwiaG9sZGVyQmluZGluZyI6eyJkaWQiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsInNpZ25pbmdEb21haW4iOiJ0aW55Y2xvdWQuY3JlZGVudGlhbHMvYWNjb3VudC1iaW5kaW5nL3YxIn0sInN0YXR1cyI6eyJtZXRob2QiOiJub25lIn0sIl9zZF9hbGciOiJzaGEtMjU2IiwiX3NkIjpbIjhFa2tTeUt0Y2xnNGNFdlR1ZmlLa2FCUmk2aEIxZ3hPc3NGZmwzTmthTzgiLCJXMGhUdUhlWmdSN2h6dF9KQXRESURXLWNMcVgyLV9HUURWS2Uwd2JHLWl3Il19.sTM1aIKuvb-4tXLDpKWh-nePKCsToccRte22S-sCBD0oT92EtFIR3gaJzxAFXST-Eym906k5m2hVEQehSErqBA~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 79b2ae28ab0407bd1acad60265e302bf\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:P4dLhDMCjfRH0j3rrNSouO_HeaIGzmif7m86bA4xzuY", + "signature": "0x77d813f885ba72b7e75849758ea327e433c05485e792d8e8d04952aff6cd376d32325d06b1714c78eef66cbca1f0ac4c30ffa1ddf168c4949bd5b8a817c7ffc61b" + }, + "nonceStore": [ + { + "key": "verifier.example\n79b2ae28ab0407bd1acad60265e302bf", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-payload", + "detail": "bad-payload: invalid JSON: unexpected token" + } + }, + { + "name": "json-bom-prefix", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.77u_eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.6tAK5070PWe5F5xs1A3pKGouF6FrsQOwWEWgdTkwvqoevK9w7zq0Xr-9tTkYxo3KhJy3KAJcteSwhLJxzulFAw~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 7b8991bc038481cef6d224ca69c97197\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:DnlkvpTCjHwQ7_OTS8AtFcWx_eKV3sPMXosdUUoxc8k", + "signature": "0x34cb934df491ba8a55f47fa9d0bd4a1259e196780b7af8355b196b9d065934f134067c647989b461e4923ac0f9ffd0b04c206027d4e6843a95ec826d3dbbe1a81c" + }, + "nonceStore": [ + { + "key": "verifier.example\n7b8991bc038481cef6d224ca69c97197", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-payload", + "detail": "bad-payload: invalid JSON: unexpected token" + } + }, + { + "name": "json-leading-space", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.IHsiaXNzIjoiZGlkOndlYjppc3N1ZXIuY3JlZGVudGlhbHMub3JnIiwic3ViIjoiZGlkOnBraDplaXAxNTU6MToweGYzOUZkNmU1MWFhZDg4RjZGNGNlNmFCODgyNzI3OWNmZkZiOTIyNjYiLCJpYXQiOjE3NjcyMjU2MDAsIm5iZiI6MTc2NzIyNTYwMCwiZXhwIjoxNzY5ODE3NjAwLCJqdGkiOiJ1cm46dXVpZDowYjZkMmM0ZS04YTFmLTRkM2UtOWI3YS0xYzJkM2U0ZjVhNmIiLCJ2Y3QiOiJvcGVuY3JlZGVudGlhbHMuZW1haWwvdjEiLCJwcm9maWxlIjoidGlueWNsb3VkLmVtYWlsLWhlbGQvdjEiLCJwcm9maWxlVmVyc2lvbiI6MSwiaG9sZGVyQmluZGluZyI6eyJkaWQiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsInNpZ25pbmdEb21haW4iOiJ0aW55Y2xvdWQuY3JlZGVudGlhbHMvYWNjb3VudC1iaW5kaW5nL3YxIn0sInN0YXR1cyI6eyJtZXRob2QiOiJub25lIn0sIl9zZF9hbGciOiJzaGEtMjU2IiwiX3NkIjpbIjhFa2tTeUt0Y2xnNGNFdlR1ZmlLa2FCUmk2aEIxZ3hPc3NGZmwzTmthTzgiLCJXMGhUdUhlWmdSN2h6dF9KQXRESURXLWNMcVgyLV9HUURWS2Uwd2JHLWl3Il19.5AjEv-GkWxY93DyB_1rIlHPwqEbFNTel9n-WkEC5ypzDdWybwx68Ug1qxPo5BmYLl3xmjUZ2DceUGu24Yrr_Bw~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 11765238dfa3b8dd9b4c0f8f271a7d4f\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:ldWgOx7gPRuklFYuzrHx2fS6kXBa1TgHDqYuGZCcfEE", + "signature": "0x82228e0191c0a6c37f2aae79b7a73811711af692f14b5f3dc0a86c29bdd7d3ea720fd5b05f2226ee28902315f1181467ac3de442a358e6a52dcf2582001cfd691c" + }, + "nonceStore": [ + { + "key": "verifier.example\n11765238dfa3b8dd9b4c0f8f271a7d4f", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "ok", + "subject": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "issuer": "did:web:issuer.credentials.org" + } + }, + { + "name": "json-trailing-garbage", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX14.marALBewZXyagna0WrHL7rxqIsKtqcHzZXy59hAAp7eWreFJYmNI9raF4oJY4mdZd2wMSCF9uf79fzV_K6kMCA~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 1ea29ce0319541001e80b670f6f0de63\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:sthzyKC5voZSr_R-WWkf5vMg1LMfSpYagCRYuluMgU0", + "signature": "0x1667d582d1b79ca4f38229a680ac524e967243e2b174b2d63afb5d6b4f2c8ecb6add39b2f780e42581765816c2724f75cb3209bd11641cb0d360fb223a17e73f1b" + }, + "nonceStore": [ + { + "key": "verifier.example\n1ea29ce0319541001e80b670f6f0de63", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-payload", + "detail": "bad-payload: invalid JSON: trailing data" + } + }, + { + "name": "json-proto-key", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXSwiX19wcm90b19fIjp7IngiOjF9fQ.7EzshEDN33KWQNrQyGghxOPUgddxspacKxT29HXtj_Zx3iLe9HP4OZHHqG6XXKhQvdxvMz6zZLZBNVnf-SemAA~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: de7ed49037888425e8c606ab327d8fca\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:08o-pmyyrhq3oIAJRm0qfUfMOx2nRc7w9RgLv8Izt6Q", + "signature": "0x90e70ba0e4ba28b79f7de3f4a33518510ee1cfb62859ef4c084cc48743008c950de8e410c2ba73aad20d03c8a2df212cfc4d48a99484c57529a55e07dffc2e781b" + }, + "nonceStore": [ + { + "key": "verifier.example\nde7ed49037888425e8c606ab327d8fca", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-payload", + "detail": "bad-payload: unexpected claim __proto__" + } + }, + { + "name": "json-constructor-key", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXSwiY29uc3RydWN0b3IiOnsicHJvdG90eXBlIjp7fX19._2teU-bUaY6zWFlBRXIcJZKJfjGxkJ9rYO014HYHjHJnMDODoqIgNlaYnxzt0K4WDUnOHiy_qDF0cdAkAlTAAA~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 2bb001e0a8abba3d3ef55bdb3ecb5ac1\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:Yq8xAbp3JJNOhfGphiNxfPEsreuyDxxNslzrSjoxqJ8", + "signature": "0x234ffbdaa61dc7e8022d36fcefd2af915606b445be43cf2b06dbe89369b3d7230b9ade73b4aa75c24a9845a85dde191db002589df4a706eda5588b3426c0daf21c" + }, + "nonceStore": [ + { + "key": "verifier.example\n2bb001e0a8abba3d3ef55bdb3ecb5ac1", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-payload", + "detail": "bad-payload: unexpected claim constructor" + } + }, + { + "name": "json-deep-nesting", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXSwiZGVlcCI6W1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tdXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXV1dXX0.smE7QbNjWYf4uNnBrd1zghJoxH3eDVWUvay3lNkPhDmgVtLsf-vrXpHVy9OfeoJfwJKifje1mw341MLD1NjKBA~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 730e7733ce1312c85a7d3edc10deeb5e\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:Ptlm84EIvjRODyajBuJnWzzRGxUr9rqaPf2nGKdtRgM", + "signature": "0xe6377f43790577d159e6170db7424022d4b78b8eaecf63d774966016cf0b7c8044dc8ebbce969e9f9fc448d81011a7c3ad020ea80a904a3ec8b5566bf6a3740c1c" + }, + "nonceStore": [ + { + "key": "verifier.example\n730e7733ce1312c85a7d3edc10deeb5e", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-payload", + "detail": "bad-payload: invalid JSON: nesting too deep" + } + }, + { + "name": "json-duplicate-sub", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXSwic3ViIjoiZGlkOnBraDplaXAxNTU6MToweGYzOUZkNmU1MWFhZDg4RjZGNGNlNmFCODgyNzI3OWNmZkZiOTIyNjYifQ.B_OwuAxlLHBcOEibX4WJiDiMjoea6xYcraEGKMFFTCJC8LNQTzYCX0QsuIx5UkXZcDvFvfzpMX_6tc5ebNtUBQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 9d2de9d69c016944e9f5b4df2a51eda3\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:UUl1QHQskBeSQ6m2tbCjEOznXCNEVckRlhSSABRoWbo", + "signature": "0x0a07e41de8b1b056d285aa3824a782394bc49f4b37f6b77286d6853c5c05a45b4f0fd8f6b82a1b2cbafa8c6d191a7f89edaddae73571ac7e5bf6411d25f11ddd1b" + }, + "nonceStore": [ + { + "key": "verifier.example\n9d2de9d69c016944e9f5b4df2a51eda3", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-payload", + "detail": "bad-payload: invalid JSON: duplicate key" + } + }, + { + "name": "json-iat-null", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6bnVsbCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.67rZctZKhShP8TDoavEF_8bz7fif_07JSrWqW0XPRdfxU4OGb1EwmxxM8WFVu9CMPsK1V1LQOzfag9jBj_pKCQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 37fe3cfda4681990ce496217d36192a7\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:J9stboUQL7xX43V9kx3cgX4xxaPG3Xl-zIiDyrXb33M", + "signature": "0x67cd5592e723c8008ddf0203be7f06a5ea0e257796fd0131f8eb01bdc487cadb7a114a20dd89fdfcb319c36f16ea4a6c3919c928fafd7f67f612f72d4e6c18341b" + }, + "nonceStore": [ + { + "key": "verifier.example\n37fe3cfda4681990ce496217d36192a7", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-payload", + "detail": "bad-payload: iat is required" + } + }, + { + "name": "json-iat-plus-sign", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6KzE3NjcyMjU2MDAsIm5iZiI6MTc2NzIyNTYwMCwiZXhwIjoxNzY5ODE3NjAwLCJqdGkiOiJ1cm46dXVpZDowYjZkMmM0ZS04YTFmLTRkM2UtOWI3YS0xYzJkM2U0ZjVhNmIiLCJ2Y3QiOiJvcGVuY3JlZGVudGlhbHMuZW1haWwvdjEiLCJwcm9maWxlIjoidGlueWNsb3VkLmVtYWlsLWhlbGQvdjEiLCJwcm9maWxlVmVyc2lvbiI6MSwiaG9sZGVyQmluZGluZyI6eyJkaWQiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsInNpZ25pbmdEb21haW4iOiJ0aW55Y2xvdWQuY3JlZGVudGlhbHMvYWNjb3VudC1iaW5kaW5nL3YxIn0sInN0YXR1cyI6eyJtZXRob2QiOiJub25lIn0sIl9zZF9hbGciOiJzaGEtMjU2IiwiX3NkIjpbIjhFa2tTeUt0Y2xnNGNFdlR1ZmlLa2FCUmk2aEIxZ3hPc3NGZmwzTmthTzgiLCJXMGhUdUhlWmdSN2h6dF9KQXRESURXLWNMcVgyLV9HUURWS2Uwd2JHLWl3Il19.5bivLFwWgEUnLhk7xyJS1sSdF2zPBRYi5UGWENL_gUwTk1lihDCitDejm-Sut5cjrfZrKsDzY2lRWPEZ6GK-DQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: e4de153a9fb6a1b8f2a4fcdb2dafff54\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:OZYsLe5EzvTFl-Ulo2rM9nCNfc41CT-iGPI0ZbsutZc", + "signature": "0x6bce84552671aa8f10e8aba9e76a4cd2ee485bd6f05b59e2825ae5e5fe94765a787ca418c6a194b2867bb9da5e961129a2c8d69ba98b21a105ca92995e7e9db41c" + }, + "nonceStore": [ + { + "key": "verifier.example\ne4de153a9fb6a1b8f2a4fcdb2dafff54", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-payload", + "detail": "bad-payload: invalid JSON: unexpected token" + } + }, + { + "name": "json-sub-lone-surrogate", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2Nlx1ZDgwMCIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.tta__uFQpeY7CNkMmAFh67euVGMzJS-khZ0HSH4zcAp1fnoifkqf5-WIaXGB8kmwJaIuCucWLMs7wkBI5KUFCw~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 1561ad8aafed2d4bae10dcbf7e5133e6\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:5VR7DryOo1m_rfh0TT670y16AA3OGD6-UF6hnfeYir0", + "signature": "0x27a9148db83c1b3379479641d95b133ef96295cb1ec8e56085221633cc9d875e25c01178bc59199183a50e3d2d65a0bd29a9e5e1422a093379aaeeec78ab92031b" + }, + "nonceStore": [ + { + "key": "verifier.example\n1561ad8aafed2d4bae10dcbf7e5133e6", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-subject", + "detail": "bad-subject: sub is not an eip155 did:pkh on the row's chain" + }, + "deviation": { + "rust": "bad-payload", + "reason": "Rust rejects the lone surrogate while decoding the payload JSON; TS decodes it and rejects the subject. Both refuse the presentation." + } + }, + { + "name": "hdr-alg-lowercase", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJlZGRzYSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.FGAqjl6KHDN_cWK2RKnZndTMc6b7XhXsa1O7BCylRbm_VogzZnDo-TRfGgHZ4jfeHSWPbrvFNywlYXuHZMXlCw~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: b664940ded67aa5c4879f019edad59be\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:q8M3eKGG_O2-xPEaOig6WKyaGCefl36tZHskIAXkZ78", + "signature": "0xa20216776c7aeda9c7819cb743966c19a76d3f4a6c522930cde683bf5c0c333d72d1840b774055eea86c68dacb95bd0a4e83dc28b868a564e418fdfe8badc4301b" + }, + "nonceStore": [ + { + "key": "verifier.example\nb664940ded67aa5c4879f019edad59be", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-header", + "detail": "bad-header: alg must be EdDSA" + } + }, + { + "name": "hdr-alg-trailing-space", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSAiLCJ0eXAiOiJ2YytzZC1qd3QiLCJraWQiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmcjazEifQ.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.5iKlrD-Qf_UIMD-T99MQ108lOFmB9KcV92vgMlBDeXb-WkdfoizhnW_JcSX1qdAGzNUvNZyXfcK_32wpREp_DQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 725e1ac9f4fd059a668410b1f66b4f50\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:ozqivChOHiW5s5wpXrCVQaWcSZvgt2vblDQX0Zd5sm4", + "signature": "0xb231903fb631824261d55a0147e388d7ae092370a0feff508737bee94d24ef0d54b033a81370f2337399982d291d8929a34e9f62fa6787f71ebc8ab4efe1dd6f1c" + }, + "nonceStore": [ + { + "key": "verifier.example\n725e1ac9f4fd059a668410b1f66b4f50", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-header", + "detail": "bad-header: alg must be EdDSA" + } + }, + { + "name": "hdr-typ-uppercase", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6IlZDK1NELUpXVCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.gvpglrhHaIjgBJtEaeq7AacKas8ApYIG2SGgWPDhSQFQJjaj2fVHsQrtzsLn-fXSWBy_dUddWzlmirwux_5kCA~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: fce396cad623d050736ce25e8b19e8e7\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:G5nL5EbwWdZ1lp9rJVaqw6Tkh4eDZPe3hpDWmSwrJh4", + "signature": "0xe5020dc835acfd196e514ccee8f3a360fc1ac7451f2a8452c36129698ca942b035bb29f551073c59ff5a586aba6417e19876f63ef55e21726d3dcc2f8cd6cd0d1c" + }, + "nonceStore": [ + { + "key": "verifier.example\nfce396cad623d050736ce25e8b19e8e7", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-header", + "detail": "bad-header: typ must be vc+sd-jwt" + } + }, + { + "name": "hdr-kid-percent-hash", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyUyM2sxIn0.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.xbH78TXtdiCpsd7kt8_7hPFP_x6nXuhoCzwlKjKjWQN6XQA36dqcUILvZFFZbgWj4DlIItdhZfMA0u-IFiVsCA~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: b0b287c60e82f701e0c7e45aaa510cd7\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:pupYD_266XWHETPTbcoGgubLdsFNZHorYdu-HtidSzU", + "signature": "0xb712b50d54a834c332db79893b1bd60c8650785687415c1acb332a3809674e2c48e58f4c4c06ad1bed544dbfb3f0c5531220015600cc0081964cf86ae1101ad31c" + }, + "nonceStore": [ + { + "key": "verifier.example\nb0b287c60e82f701e0c7e45aaa510cd7", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-header", + "detail": "bad-header: kid must be a DID URL with a fragment" + } + }, + { + "name": "hdr-kid-trailing-space", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSAifQ.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.OhVLcoGAv3BuvfE03jEQIzkTEpHg96xRJnsOpj3dGoKFfX6IG2w1PzX9xS-Hb-QKWltbQQAAfhoBBQV-A_tiAQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 6708d92e40ae759f06c535ce3054453b\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:IuwMS-NBxSHLFzy4a2WDMT5iwzcLombxGKLRbkyl3to", + "signature": "0x9024e499f978a1dcd1f58579fd640162b7d2a8ba29dcfa9c9cf23968a1e2004f2072117ad4505d9ba044785efbc39de20855886721350bd1753cc996af2c90401c" + }, + "nonceStore": [ + { + "key": "verifier.example\n6708d92e40ae759f06c535ce3054453b", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-header", + "detail": "bad-header: kid must be issuerDid#fragment" + } + }, + { + "name": "hdr-kid-unicode-fragment", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrw6QifQ.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.4J70D0GuexD64cEN6IZBlWCiPSX7vuVovs6ayNyHQe2fQ_r9V8ub3r1-OCMISDo8p2v_80UpaXwfWUfaIxgNDw~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 6dc29ad2be1dce17ab7dfcf2434d51a0\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:4r-y6Na6g-pFflEGyzNc_JK4UtOUiMHa9_w7cXbfohc", + "signature": "0xe5d4ce0932e8929b6f7ec4306aeedcd942000a64d554aa7989041d84bcf515892efff26ba4cc418055c9147bd05defa9328f9691d6946a2a5a7ee1a0dc0356281b" + }, + "nonceStore": [ + { + "key": "verifier.example\n6dc29ad2be1dce17ab7dfcf2434d51a0", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-header", + "detail": "bad-header: kid must be issuerDid#fragment" + } + }, + { + "name": "hdr-kid-uppercase-fragment", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNLMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.mXJ2lYsOiaYY79jaZIz8aPTzxX_miLHfQRfqlDKPAVjIzxso0XjY6936jIgzFmjtFiC3sl0FkN8mG6HrnZzpDw~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 94f6182d35033fbc888d13e88c7f2ab3\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:hPP5k0ipaXrgBmNXX1sLwhmkZfq9nr-2--YQXQypOVQ", + "signature": "0xba37b617b3bc40a3a9ed72c61b16695cf5c040656c3762edb6076c7835e11a0542701af7b52df4f399662ae3f2e72cfba28582e8a52af6b230223f836817e69d1c" + }, + "nonceStore": [ + { + "key": "verifier.example\n94f6182d35033fbc888d13e88c7f2ab3", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "unknown-issuer", + "detail": "unknown-issuer: no issuer-set entry for this kid" + } + }, + { + "name": "hdr-kid-double-hash", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.sClDdBTxeHezugNYxR3wQ32sj3jQWtyoQJAm5jBs-k-dz44vFsVYkW9BJVMdqq9ihMYnn3e4Gy5GouBMwtmHBA~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 760cb40bdfcaea3c9ae198d255a9c0d4\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:t3_H2oNTkvRtk-f7ZoobwLoAtne8UKWG_ndQ0cvwdSo", + "signature": "0xcca45daf5be41de2589adf8a47591812797a967fcb3c63415c7c576a4ca7358f1d352f410c2fcfb124e4559136a4466939f188995c2249a791f738581c1b57751c" + }, + "nonceStore": [ + { + "key": "verifier.example\n760cb40bdfcaea3c9ae198d255a9c0d4", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-header", + "detail": "bad-header: kid must be issuerDid#fragment" + } + }, + { + "name": "hdr-crit-member", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSIsImNyaXQiOlsieCJdfQ.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.lL5piZd85BDtKW6QBW7eyI7gvyVx4c1Z-dnQfT-qLMdWHbeRW0R0sE9lJN7w2dQjbMMkJeSZuGLsvK0i-5IuBA~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 8f84f26e4b80e5c84fa1b991b82ddb7e\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:mNMiG6TuQou4T6c-uoWfyX2cl08FXnZsB5V5pu4Z5fs", + "signature": "0x0a69e1f7a11e700d9efb1ada2b25cae0de455da8e3ef6347caf803fa4098c97f540f28dd39567ba6607f7aab1bba648e86e4926a4e7127011ebca613e642847b1c" + }, + "nonceStore": [ + { + "key": "verifier.example\n8f84f26e4b80e5c84fa1b991b82ddb7e", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-header", + "detail": "bad-header: unexpected header member crit" + } + }, + { + "name": "hdr-typ-missing", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.rpScMsuL_yCGgCTcHNpVHsDdt46a5VkHidcI9Cscg-Hk1sNnsadWBYNtcaAF7MewiFnkUgUUBcBmUTWI1w9ABQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: d0431dad8f61924d19e8a91bd2e742c8\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:qffTE8zSM5KDiq8F2p6fllCqSi07J_kQnLOiC4ZdLpU", + "signature": "0xf6b4a446c8ba420af3004bf8967c3a2b76f14eec60686c5698410074d1d3af8067c72b3d67a2dd5b3f21cf42e6548f064252caaaebdfda3d6e1b6d9fb50120d71c" + }, + "nonceStore": [ + { + "key": "verifier.example\nd0431dad8f61924d19e8a91bd2e742c8", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-header", + "detail": "bad-header: typ must be vc+sd-jwt" + } + }, + { + "name": "sig-ed-s-plus-l", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnaaa6FQs1_c4gwnYhhHI5-Rxk1GgS_TxMziQ7LP7ncRHQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 9c1709cc2c727045d4142231e9ac49e3\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:xrVhxth1mx23Ffbu1FqVTK8QxXKMB_IrWAwzNo9zXNM", + "signature": "0x4a6c485bcbd14bcb51d071e13ca40e740de25d4d7f492b07918b800deab69ff11374c3fa9adb631bc12c94fe5be3696808c925508231667f33ff3b1f52efb8af1b" + }, + "nonceStore": [ + { + "key": "verifier.example\n9c1709cc2c727045d4142231e9ac49e3", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-signature", + "detail": "bad-signature: issuer signature did not verify" + } + }, + { + "name": "sig-ed-s-plus-2l", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnaHP5etzcLuOuPDWbslHX6mxk1GgS_TxMziQ7LP7ncRLQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 2260807954d944d9d0e811307d9454e6\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:NBi2QiCTuBGIWy2fuAfJKVG2YZRwPzMMODhD5bKLHCU", + "signature": "0xae8c859134f7a72a9bb517d0899084d281e28772ca491e73324dbe1dd6849b564ae0860dedf01f27507cc47d11fe12f36d9ea663be277b87054ddbaa2c8e0c3b1b" + }, + "nonceStore": [ + { + "key": "verifier.example\n2260807954d944d9d0e811307d9454e6", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-signature", + "detail": "bad-signature: issuer signature did not verify" + } + }, + { + "name": "sig-ed-s-equals-l", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnbt0_VcGmMSWNac96Le-d4UAAAAAAAAAAAAAAAAAAAAEA~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 5da74723c5464a98b12ac43afdc14790\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:dLwWNBGdpWXB6Mat3HWH0KzC5vxzk7RofkgVeLtKEVo", + "signature": "0x46a622242439dc7a0475e5a14767a2c8f4f3dd826976f17d175f7c8eb768d4cc35b13fd18ca18076a0ccf31236f1dd8bcf72c66b0ea0d0d13deea2646b23495c1b" + }, + "nonceStore": [ + { + "key": "verifier.example\n5da74723c5464a98b12ac43afdc14790", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-signature", + "detail": "bad-signature: issuer signature did not verify" + } + }, + { + "name": "sig-ed-s-all-ff", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnb__________________________________________w~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 10f001ec7a9fb19dfd2d52c66c531c98\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:5Dd65mgQA1XHaQIgizNiNEZnfm-V_M3pmbL_Ol4MJMk", + "signature": "0x0b628ffc3b7a27867a26de022a4577e6058a2165017dd1ee5fedae3a64ca4c334a31934f9231e14ea010276a9297b63928593e5adae33c32fabccbc5b7ed2c411c" + }, + "nonceStore": [ + { + "key": "verifier.example\n10f001ec7a9fb19dfd2d52c66c531c98", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-signature", + "detail": "bad-signature: issuer signature did not verify" + } + }, + { + "name": "sig-ed-r-identity-s-zero", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: b7f7385945888591553e669305f1e195\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:mPYXBcZru09gx0w0C0mTJ-is0rOq9kcRzH-29ID_adI", + "signature": "0x5626e7667ed54fe6363d3e39acb2cc44ba1c6914636bf040aadcbd6d808e80aa5662a27355f5082859ad6a68225de24cc24c157db338ba1e18dca5757c5f02181b" + }, + "nonceStore": [ + { + "key": "verifier.example\nb7f7385945888591553e669305f1e195", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-signature", + "detail": "bad-signature: issuer signature did not verify" + } + }, + { + "name": "sig-ed-r-identity-s-original", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACtl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 06de1e60682aa60e0e056e7a9600a3cd\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:0Z-ohxvhNDy9j-UvftpmtJOjHWPHEDm4rKPTOwrmCqA", + "signature": "0x1a62ea7204b2ad9bff314e3d5b85f4702d3c649f523b016f232bc771f14d7cc926b789f17ba614f7ac49184368f8ad83ae660530038abdcd5b53bbf4156b83c51b" + }, + "nonceStore": [ + { + "key": "verifier.example\n06de1e60682aa60e0e056e7a9600a3cd", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-signature", + "detail": "bad-signature: issuer signature did not verify" + } + }, + { + "name": "sig-ed-r-noncanonical-p", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.7f_______________________________________3-tl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 6d221fe58554ade8e1409c730c9206c3\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:vokqEwNZH9-EAjwsOypO9UBlwRuYRxXG6HMJVN9YLLg", + "signature": "0x62745480675473e937cc15038c5cc8c69be901f1bf80a36d5061a60225f9af33698ae311ba69330eef73057c3430fb92ca1f78ec3a48bf1b503f4354087552e11b" + }, + "nonceStore": [ + { + "key": "verifier.example\n6d221fe58554ade8e1409c730c9206c3", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-signature", + "detail": "bad-signature: issuer signature did not verify" + } + }, + { + "name": "sig-ed-r-all-zero", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACtl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 2e9ff6b3afebef4499576a6b359a1b09\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:kKo3bnZPk6gKk3GDN2hFMaKX3-MDzEaw2gr_yD2unYk", + "signature": "0x904c8796eb74984428ea185f7914926ecbb4fafe7fe62a72b09d702bcaf1f5cf0a3e7f388bbb30ce041550ba1649f7e507f7b0dcfa4ca4ba58369025986e4d081b" + }, + "nonceStore": [ + { + "key": "verifier.example\n2e9ff6b3afebef4499576a6b359a1b09", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-signature", + "detail": "bad-signature: issuer signature did not verify" + } + }, + { + "name": "sig-ed-s-zero", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 4626028bd0fe2ed267b2eb2f9a0d0427\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:Mvf4NfvMTguXdyT8ER3y8_tu8m0QvT3dnIaViXIP-eo", + "signature": "0xec990d62dada1494c549fa1bb800931b16cea5bdbb215d86a3ee66654c81489915f57f0ecb72fb15128348a9febd2fcebb8e4a574d0c6f137226e3ec884551e41b" + }, + "nonceStore": [ + { + "key": "verifier.example\n4626028bd0fe2ed267b2eb2f9a0d0427", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-signature", + "detail": "bad-signature: issuer signature did not verify" + } + }, + { + "name": "cfg-notafter-before-notbefore", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2026-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": "2025-06-01T00:00:00Z" + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 95822f52aa39d2ef207684cd11cb6321\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:eQXOZSXekF4OXymmuUiq0bSeG_wfOw3b2JlaG4CGhkU", + "signature": "0x0b5beb68763bbe57f78a660fc9ccb45b3fc14d5a213f7a9a659c1a6b4e1581c2700e4a4ac5ff7e36646abd56b023fc9a8a9679cafd5c247c150926b163d234101c" + }, + "nonceStore": [ + { + "key": "verifier.example\n95822f52aa39d2ef207684cd11cb6321", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "issuer-stopped", + "detail": "issuer-stopped: issuer key is past its hard stop" + }, + "deviation": { + "rust": "bad-issuer-set", + "reason": "Rust fails closed for the whole issuer set at startup (credential_issuer_set()?); TS stops only the affected issuer per presentation. Stricter than TS; the presentation is refused either way." + } + }, + { + "name": "cfg-retired-at-garbage", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": "tomorrow", + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 23eafae3a46958f3a6478cd8481c3d76\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:eQXOZSXekF4OXymmuUiq0bSeG_wfOw3b2JlaG4CGhkU", + "signature": "0x0c13f2190eebe23b8ab3ecfb88fc841d90a0242066b63d53adb8d86df7be5c2d3790181335d74e6894d99445139609c419969bf00698acc371f73920667cef641c" + }, + "nonceStore": [ + { + "key": "verifier.example\n23eafae3a46958f3a6478cd8481c3d76", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-issuer-set", + "detail": "bad-issuer-set: retiredAt must be RFC 3339 UTC ending in Z" + } + }, + { + "name": "cfg-notbefore-no-z", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 13c6a6500ab3019d48514f54787a525e\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:eQXOZSXekF4OXymmuUiq0bSeG_wfOw3b2JlaG4CGhkU", + "signature": "0x485ca573bef7287227f2f25239657f29d4b5fd01a7ac8e4b62e2709122adcdb3586d60fcabc7c3dbe068ec3fa8a88cc07523d563f2b3e8ecff0f7857d13a1ceb1c" + }, + "nonceStore": [ + { + "key": "verifier.example\n13c6a6500ab3019d48514f54787a525e", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-issuer-set", + "detail": "bad-issuer-set: notBefore must be RFC 3339 UTC ending in Z" + } + }, + { + "name": "cfg-notbefore-offset", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T01:00:00+01:00", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 43f06f2ac375e53dabf548d95eef0550\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:eQXOZSXekF4OXymmuUiq0bSeG_wfOw3b2JlaG4CGhkU", + "signature": "0xd73bb12d3aa73d90ca253315cf16a7e3045e4aca66654b00db933909f6aedcc84828a02913bfd1d3c4e0bb6beafb7333f6dabdfd0e93602276b414baeccc54171b" + }, + "nonceStore": [ + { + "key": "verifier.example\n43f06f2ac375e53dabf548d95eef0550", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-issuer-set", + "detail": "bad-issuer-set: notBefore must be RFC 3339 UTC ending in Z" + } + }, + { + "name": "cfg-publickey-33-bytes", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEB", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 21d44faecd71b2b8dbcb30c1014bdf10\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:eQXOZSXekF4OXymmuUiq0bSeG_wfOw3b2JlaG4CGhkU", + "signature": "0x90f44812b59286df75e781a081f458e366b0c9bfffbafd2098c56dc004d35d395ffd32de3d72f06aebddc4f33246a70080123440eab80225a5bb55bf1331c27a1c" + }, + "nonceStore": [ + { + "key": "verifier.example\n21d44faecd71b2b8dbcb30c1014bdf10", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-issuer-set", + "detail": "bad-issuer-set: publicKey is not a strict 32-byte Ed25519 key" + } + }, + { + "name": "cfg-publickey-padded", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc=", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: a13c7023f793c2bddd469e94fa0682a8\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:eQXOZSXekF4OXymmuUiq0bSeG_wfOw3b2JlaG4CGhkU", + "signature": "0x0ef9ca32aea5ee62594a53d163b5c00d927f0063714495f80f0d121b4ca15a104eb7f01ff4297a3d831a20364a6d29f727589bb9302b299c70c906f8f95420f01c" + }, + "nonceStore": [ + { + "key": "verifier.example\na13c7023f793c2bddd469e94fa0682a8", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-issuer-set", + "detail": "bad-issuer-set: not unpadded base64url" + } + }, + { + "name": "cfg-vcts-empty", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 66c7a859d1ed3d272221f4f88a5f24d9\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:eQXOZSXekF4OXymmuUiq0bSeG_wfOw3b2JlaG4CGhkU", + "signature": "0x164b3af893016a9633f66332427a9db38cadfab4dbae3349bb1d495e2fc4bb3a2f819368d8889ddeac7da3a243fc4b553c581716ecfb4dfea272ec520f90ee871b" + }, + "nonceStore": [ + { + "key": "verifier.example\n66c7a859d1ed3d272221f4f88a5f24d9", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-issuer-set", + "detail": "bad-issuer-set: vcts must be a non-empty list of strings" + } + }, + { + "name": "cfg-profiles-duplicate", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1", + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: d2527f408acf862295b9a84acf296739\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:eQXOZSXekF4OXymmuUiq0bSeG_wfOw3b2JlaG4CGhkU", + "signature": "0xf0dade8036418279cff85d23fd17b5a7bc4f90ac79f0621140ab275a6670a3b1674e01b9a6e496dbaf0ae088844bd66bf55fea880a6c2da7949bab7a01341e111b" + }, + "nonceStore": [ + { + "key": "verifier.example\nd2527f408acf862295b9a84acf296739", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "ok", + "subject": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "issuer": "did:web:issuer.credentials.org" + } + }, + { + "name": "cfg-kid-uppercase-method", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:WEB:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 1b7bc612f9e3ebfd80f11cb699d0f6ec\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:eQXOZSXekF4OXymmuUiq0bSeG_wfOw3b2JlaG4CGhkU", + "signature": "0x7b45f0c5f71e45554a1aec2c8fe9c5f1bd848bd8f1c880b51dfab0dc5dd59ff82723325b5b5f26132daf334733cfef6ad0f447e6b96ce52c43b30c56b90f73d81c" + }, + "nonceStore": [ + { + "key": "verifier.example\n1b7bc612f9e3ebfd80f11cb699d0f6ec", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-issuer-set", + "detail": "bad-issuer-set: kid must be issuerDid#fragment" + } + }, + { + "name": "cfg-issuerdid-pkh", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: b6bcb7d1c8df038c8f0bdc3e76b7e4e0\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:eQXOZSXekF4OXymmuUiq0bSeG_wfOw3b2JlaG4CGhkU", + "signature": "0x8afc1a5ecac8c88e1a6eac28e9b76e002ea3f9c57f7c1b48628e06d9b323f76912b59bf2a6b20b3090f5d56a26ef29e16fcf0d4dd7f125e69e46a387e76c5d151b" + }, + "nonceStore": [ + { + "key": "verifier.example\nb6bcb7d1c8df038c8f0bdc3e76b7e4e0", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-issuer-set", + "detail": "bad-issuer-set: issuerDid is not canonical" + } + }, + { + "name": "cfg-alg-lowercase", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "eddsa", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: af704ffcbaf5dca64ddeb051d2076cc6\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:eQXOZSXekF4OXymmuUiq0bSeG_wfOw3b2JlaG4CGhkU", + "signature": "0xaae8cb404c59d09400d1339efd5d886e40ce401978996d0bb427f1007471f1f8210c91b2c841b803071e64dd01355bc39f79ae63b393bf14b95dba5dd8a10c621b" + }, + "nonceStore": [ + { + "key": "verifier.example\naf704ffcbaf5dca64ddeb051d2076cc6", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-issuer-set", + "detail": "bad-issuer-set: alg must be EdDSA" + } + }, + { + "name": "cfg-publickey-identity", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOEVra1N5S3RjbGc0Y0V2VHVmaUtrYUJSaTZoQjFneE9zc0ZmbDNOa2FPOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ezAyidkujgUqM6KGCkOUinqaKncCoFEjdQDhQuMNKnatl6vzmPzJijaKanVoKcB8xk1GgS_TxMziQ7LP7ncRDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: c702ea60c1c2121f8be96f9604ec6b11\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:eQXOZSXekF4OXymmuUiq0bSeG_wfOw3b2JlaG4CGhkU", + "signature": "0x206a4031713458f66a66f9956a297b2c3425dc3d8c92e1adb10f977b1a3b93e829820672c985d2c36e485723c6ad78c341b27bf924f4c29cb8285e87c0327f601c" + }, + "nonceStore": [ + { + "key": "verifier.example\nc702ea60c1c2121f8be96f9604ec6b11", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-issuer-set", + "detail": "bad-issuer-set: publicKey is not a strict 32-byte Ed25519 key" + } + }, + { + "name": "oc-base", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "alg": "EdDSA", + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#controller", + "notAfter": null, + "notBefore": "2025-01-01T00:00:00Z", + "profiles": [ + "tinycloud.email-held/v1" + ], + "publicKey": "6kpsY-KcUgq-9VB7Ey7F-ZVHdq6-vnuSQh7qaRRG0iw", + "retiredAt": null, + "vcts": [ + "opencredentials.email/v1" + ] + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNjb250cm9sbGVyIn0.eyJfc2QiOlsiOUZSM1NySExrSW4tc01vOUIyQ3RIZWtIRTlWdFVjQkpkZDBOdlFDYUJpNCIsIklYb1BsMDRYeEc2YnRNOUE1YzZPYkxmdHBHVmt4UXFrdGxCMl96Vnl2RW8iXSwiX3NkX2FsZyI6InNoYS0yNTYiLCJleHAiOjE3Njk4MTc2MDAsImhvbGRlckJpbmRpbmciOnsiZGlkIjoiZGlkOnBraDplaXAxNTU6MToweGYzOUZkNmU1MWFhZDg4RjZGNGNlNmFCODgyNzI3OWNmZkZiOTIyNjYiLCJzaWduaW5nRG9tYWluIjoidGlueWNsb3VkLmNyZWRlbnRpYWxzL2FjY291bnQtYmluZGluZy92MSJ9LCJpYXQiOjE3NjcyMjU2MDAsImlzcyI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyIsImp0aSI6InVybjp1dWlkOjVmMWM5YTJlLTdiM2QtNGU4YS05YzYxLTJkNGI4ZTdmMGExMyIsIm5iZiI6MTc2NzIyNTYwMCwicHJvZmlsZSI6InRpbnljbG91ZC5lbWFpbC1oZWxkL3YxIiwicHJvZmlsZVZlcnNpb24iOjEsInN0YXR1cyI6eyJtZXRob2QiOiJub25lIn0sInN1YiI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2IiwidmN0Ijoib3BlbmNyZWRlbnRpYWxzLmVtYWlsL3YxIn0.N-SNVObviWKHuCgoAlp5rPw_B_URBh3NbRlEzQN5RbqjygjBBo4gwhbZ-Bw7aMR9aXZs2vpkAI27Ev-nO3UsBg~WyIwMHFGc0Jjd1hFckhwWkdoZXp2RlNBIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyIwTDg2bnAxQ3NPVHZTT0pwVmQxdHhRIiwiZW1haWxEb21haW4iLCJleGFtcGxlLmNvbSJd~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: e4f0f7a6c4cd179b3dbb9386eb6e23f1\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:jRXBuzz_SdM1I9uL9jv4kGkXzwbDa52wG9P8UD8C4_Y", + "signature": "0x8b24d3e012473f61e4ca0559b8480a154b979aa5a13afc6c21f5c617047fd6c7650d194aedaabc3453ca057c216b055f00326b1289403fd693cc6475ac22d9761c" + }, + "nonceStore": [ + { + "key": "verifier.example\ne4f0f7a6c4cd179b3dbb9386eb6e23f1", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "ok", + "subject": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "issuer": "did:web:issuer.credentials.org" + } + }, + { + "name": "oc-flip-header-25", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "alg": "EdDSA", + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#controller", + "notAfter": null, + "notBefore": "2025-01-01T00:00:00Z", + "profiles": [ + "tinycloud.email-held/v1" + ], + "publicKey": "6kpsY-KcUgq-9VB7Ey7F-ZVHdq6-vnuSQh7qaRRG0iw", + "retiredAt": null, + "vcts": [ + "opencredentials.email/v1" + ] + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCIAInZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNjb250cm9sbGVyIn0.eyJfc2QiOlsiOUZSM1NySExrSW4tc01vOUIyQ3RIZWtIRTlWdFVjQkpkZDBOdlFDYUJpNCIsIklYb1BsMDRYeEc2YnRNOUE1YzZPYkxmdHBHVmt4UXFrdGxCMl96Vnl2RW8iXSwiX3NkX2FsZyI6InNoYS0yNTYiLCJleHAiOjE3Njk4MTc2MDAsImhvbGRlckJpbmRpbmciOnsiZGlkIjoiZGlkOnBraDplaXAxNTU6MToweGYzOUZkNmU1MWFhZDg4RjZGNGNlNmFCODgyNzI3OWNmZkZiOTIyNjYiLCJzaWduaW5nRG9tYWluIjoidGlueWNsb3VkLmNyZWRlbnRpYWxzL2FjY291bnQtYmluZGluZy92MSJ9LCJpYXQiOjE3NjcyMjU2MDAsImlzcyI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyIsImp0aSI6InVybjp1dWlkOjVmMWM5YTJlLTdiM2QtNGU4YS05YzYxLTJkNGI4ZTdmMGExMyIsIm5iZiI6MTc2NzIyNTYwMCwicHJvZmlsZSI6InRpbnljbG91ZC5lbWFpbC1oZWxkL3YxIiwicHJvZmlsZVZlcnNpb24iOjEsInN0YXR1cyI6eyJtZXRob2QiOiJub25lIn0sInN1YiI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2IiwidmN0Ijoib3BlbmNyZWRlbnRpYWxzLmVtYWlsL3YxIn0.N-SNVObviWKHuCgoAlp5rPw_B_URBh3NbRlEzQN5RbqjygjBBo4gwhbZ-Bw7aMR9aXZs2vpkAI27Ev-nO3UsBg~WyIwMHFGc0Jjd1hFckhwWkdoZXp2RlNBIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyIwTDg2bnAxQ3NPVHZTT0pwVmQxdHhRIiwiZW1haWxEb21haW4iLCJleGFtcGxlLmNvbSJd~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: a82847aa7c1bdfe5bc064f0c31e6c454\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:4Mj6iNPtXn3MT42rM_PS9_pXLXHJgJZCxVlN5Dxn-n4", + "signature": "0x3f919de5377da08a6c34986134c312464e83e0e10f472939cc6972124bd04c37673d24851f686b904bab3c181fd7cfabee58917568c3e07f0ce031d0aa58ca271c" + }, + "nonceStore": [ + { + "key": "verifier.example\na82847aa7c1bdfe5bc064f0c31e6c454", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-header", + "detail": "bad-header: invalid JSON: expected colon" + } + }, + { + "name": "oc-flip-header-50", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "alg": "EdDSA", + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#controller", + "notAfter": null, + "notBefore": "2025-01-01T00:00:00Z", + "profiles": [ + "tinycloud.email-held/v1" + ], + "publicKey": "6kpsY-KcUgq-9VB7Ey7F-ZVHdq6-vnuSQh7qaRRG0iw", + "retiredAt": null, + "vcts": [ + "opencredentials.email/v1" + ] + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRAZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNjb250cm9sbGVyIn0.eyJfc2QiOlsiOUZSM1NySExrSW4tc01vOUIyQ3RIZWtIRTlWdFVjQkpkZDBOdlFDYUJpNCIsIklYb1BsMDRYeEc2YnRNOUE1YzZPYkxmdHBHVmt4UXFrdGxCMl96Vnl2RW8iXSwiX3NkX2FsZyI6InNoYS0yNTYiLCJleHAiOjE3Njk4MTc2MDAsImhvbGRlckJpbmRpbmciOnsiZGlkIjoiZGlkOnBraDplaXAxNTU6MToweGYzOUZkNmU1MWFhZDg4RjZGNGNlNmFCODgyNzI3OWNmZkZiOTIyNjYiLCJzaWduaW5nRG9tYWluIjoidGlueWNsb3VkLmNyZWRlbnRpYWxzL2FjY291bnQtYmluZGluZy92MSJ9LCJpYXQiOjE3NjcyMjU2MDAsImlzcyI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyIsImp0aSI6InVybjp1dWlkOjVmMWM5YTJlLTdiM2QtNGU4YS05YzYxLTJkNGI4ZTdmMGExMyIsIm5iZiI6MTc2NzIyNTYwMCwicHJvZmlsZSI6InRpbnljbG91ZC5lbWFpbC1oZWxkL3YxIiwicHJvZmlsZVZlcnNpb24iOjEsInN0YXR1cyI6eyJtZXRob2QiOiJub25lIn0sInN1YiI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2IiwidmN0Ijoib3BlbmNyZWRlbnRpYWxzLmVtYWlsL3YxIn0.N-SNVObviWKHuCgoAlp5rPw_B_URBh3NbRlEzQN5RbqjygjBBo4gwhbZ-Bw7aMR9aXZs2vpkAI27Ev-nO3UsBg~WyIwMHFGc0Jjd1hFckhwWkdoZXp2RlNBIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyIwTDg2bnAxQ3NPVHZTT0pwVmQxdHhRIiwiZW1haWxEb21haW4iLCJleGFtcGxlLmNvbSJd~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 6b1df7b7984f13df4bde70f43c80bbc2\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:gd-4Z-K9EnUsDf298o-YjpRIWG5___LEhKLiQ3PpDCA", + "signature": "0x1a57af9ddd3198d285adcb30dc06593d0ce96712a536d1e659f920f27c7521476898326728360ffaa379efd7fba5c8ba43514e47f9e287b36b3d9eadfdd38f5b1b" + }, + "nonceStore": [ + { + "key": "verifier.example\n6b1df7b7984f13df4bde70f43c80bbc2", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "did-method-not-allowed", + "detail": "did-method-not-allowed: issuer DID method null is not on the allow-list" + } + }, + { + "name": "oc-flip-header-75", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "alg": "EdDSA", + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#controller", + "notAfter": null, + "notBefore": "2025-01-01T00:00:00Z", + "profiles": [ + "tinycloud.email-held/v1" + ], + "publicKey": "6kpsY-KcUgq-9VB7Ey7F-ZVHdq6-vnuSQh7qaRRG0iw", + "retiredAt": null, + "vcts": [ + "opencredentials.email/v1" + ] + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRAYWxzLm9yZyNjb250cm9sbGVyIn0.eyJfc2QiOlsiOUZSM1NySExrSW4tc01vOUIyQ3RIZWtIRTlWdFVjQkpkZDBOdlFDYUJpNCIsIklYb1BsMDRYeEc2YnRNOUE1YzZPYkxmdHBHVmt4UXFrdGxCMl96Vnl2RW8iXSwiX3NkX2FsZyI6InNoYS0yNTYiLCJleHAiOjE3Njk4MTc2MDAsImhvbGRlckJpbmRpbmciOnsiZGlkIjoiZGlkOnBraDplaXAxNTU6MToweGYzOUZkNmU1MWFhZDg4RjZGNGNlNmFCODgyNzI3OWNmZkZiOTIyNjYiLCJzaWduaW5nRG9tYWluIjoidGlueWNsb3VkLmNyZWRlbnRpYWxzL2FjY291bnQtYmluZGluZy92MSJ9LCJpYXQiOjE3NjcyMjU2MDAsImlzcyI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyIsImp0aSI6InVybjp1dWlkOjVmMWM5YTJlLTdiM2QtNGU4YS05YzYxLTJkNGI4ZTdmMGExMyIsIm5iZiI6MTc2NzIyNTYwMCwicHJvZmlsZSI6InRpbnljbG91ZC5lbWFpbC1oZWxkL3YxIiwicHJvZmlsZVZlcnNpb24iOjEsInN0YXR1cyI6eyJtZXRob2QiOiJub25lIn0sInN1YiI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2IiwidmN0Ijoib3BlbmNyZWRlbnRpYWxzLmVtYWlsL3YxIn0.N-SNVObviWKHuCgoAlp5rPw_B_URBh3NbRlEzQN5RbqjygjBBo4gwhbZ-Bw7aMR9aXZs2vpkAI27Ev-nO3UsBg~WyIwMHFGc0Jjd1hFckhwWkdoZXp2RlNBIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyIwTDg2bnAxQ3NPVHZTT0pwVmQxdHhRIiwiZW1haWxEb21haW4iLCJleGFtcGxlLmNvbSJd~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: dc4220538815f8c3732c0929e13cab61\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:HDi9iEmcDGSY9zLDEm5C0XKeIaQc7YfIlMGse_ca-sE", + "signature": "0xce348f815d92588d9d51d50e0daa8b21d2d75df342b55c865c40996fdc0a7df0153697f3aae23aaa580ca0c98b56233efcb7c0bd73c94c428d7331cf1281c34f1b" + }, + "nonceStore": [ + { + "key": "verifier.example\ndc4220538815f8c3732c0929e13cab61", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "issuer-not-accepted", + "detail": "issuer-not-accepted: issuer is not accepted by this policy" + } + }, + { + "name": "oc-flip-payload-25", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "alg": "EdDSA", + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#controller", + "notAfter": null, + "notBefore": "2025-01-01T00:00:00Z", + "profiles": [ + "tinycloud.email-held/v1" + ], + "publicKey": "6kpsY-KcUgq-9VB7Ey7F-ZVHdq6-vnuSQh7qaRRG0iw", + "retiredAt": null, + "vcts": [ + "opencredentials.email/v1" + ] + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNjb250cm9sbGVyIn0.eyJfc2QiOlsiOUZSM1NySExrSW4tc01vOUIyQ3RIZWtIRTlWdFVjQkpkZDBOdlFDYUJpNCIsIklYb1BsMDRYeEc2YnRNOUE1YzZPYkxmdHBHVmt4UXFrdGxCMl96Vnl2RW8iXSwiX3NkX2FsZyI6InNoYS0yNTYiLCJleHAiOjE3Njk4MTc2MDAsImhvbGRlckJpbARpbmciOnsiZGlkIjoiZGlkOnBraDplaXAxNTU6MToweGYzOUZkNmU1MWFhZDg4RjZGNGNlNmFCODgyNzI3OWNmZkZiOTIyNjYiLCJzaWduaW5nRG9tYWluIjoidGlueWNsb3VkLmNyZWRlbnRpYWxzL2FjY291bnQtYmluZGluZy92MSJ9LCJpYXQiOjE3NjcyMjU2MDAsImlzcyI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyIsImp0aSI6InVybjp1dWlkOjVmMWM5YTJlLTdiM2QtNGU4YS05YzYxLTJkNGI4ZTdmMGExMyIsIm5iZiI6MTc2NzIyNTYwMCwicHJvZmlsZSI6InRpbnljbG91ZC5lbWFpbC1oZWxkL3YxIiwicHJvZmlsZVZlcnNpb24iOjEsInN0YXR1cyI6eyJtZXRob2QiOiJub25lIn0sInN1YiI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2IiwidmN0Ijoib3BlbmNyZWRlbnRpYWxzLmVtYWlsL3YxIn0.N-SNVObviWKHuCgoAlp5rPw_B_URBh3NbRlEzQN5RbqjygjBBo4gwhbZ-Bw7aMR9aXZs2vpkAI27Ev-nO3UsBg~WyIwMHFGc0Jjd1hFckhwWkdoZXp2RlNBIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyIwTDg2bnAxQ3NPVHZTT0pwVmQxdHhRIiwiZW1haWxEb21haW4iLCJleGFtcGxlLmNvbSJd~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: c7c3d8d9be4d280cb9ba9220612807d1\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:YlRxsLld05BAruApHi7yv5iGCi4_1ewtaBtaseTj2Ss", + "signature": "0x412a5d87153322413e6ffa76a7a3ea56cab91e3839981dca175c3e38e8e3d840038e3ac25f952367c18aeccd0eb1d8da246fddae23e8f84917d2abbc81a9cdfe1c" + }, + "nonceStore": [ + { + "key": "verifier.example\nc7c3d8d9be4d280cb9ba9220612807d1", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-signature", + "detail": "bad-signature: issuer signature did not verify" + } + }, + { + "name": "oc-flip-payload-50", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "alg": "EdDSA", + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#controller", + "notAfter": null, + "notBefore": "2025-01-01T00:00:00Z", + "profiles": [ + "tinycloud.email-held/v1" + ], + "publicKey": "6kpsY-KcUgq-9VB7Ey7F-ZVHdq6-vnuSQh7qaRRG0iw", + "retiredAt": null, + "vcts": [ + "opencredentials.email/v1" + ] + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNjb250cm9sbGVyIn0.eyJfc2QiOlsiOUZSM1NySExrSW4tc01vOUIyQ3RIZWtIRTlWdFVjQkpkZDBOdlFDYUJpNCIsIklYb1BsMDRYeEc2YnRNOUE1YzZPYkxmdHBHVmt4UXFrdGxCMl96Vnl2RW8iXSwiX3NkX2FsZyI6InNoYS0yNTYiLCJleHAiOjE3Njk4MTc2MDAsImhvbGRlckJpbmRpbmciOnsiZGlkIjoiZGlkOnBraDplaXAxNTU6MToweGYzOUZkNmU1MWFhZDg4RjZGNGNlNmFCODgyNzI3OWNmZkZiOTIyNjYiLCJzaWduaW5nRG9tYWluIjoidGlueWNsb3VkLmNyZWRlbnRpYWxzL2FjY291bnQtYmluZGluZy92MSJ9LCJpYXQiOjE3NjcyMjUAMDAsImlzcyI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyIsImp0aSI6InVybjp1dWlkOjVmMWM5YTJlLTdiM2QtNGU4YS05YzYxLTJkNGI4ZTdmMGExMyIsIm5iZiI6MTc2NzIyNTYwMCwicHJvZmlsZSI6InRpbnljbG91ZC5lbWFpbC1oZWxkL3YxIiwicHJvZmlsZVZlcnNpb24iOjEsInN0YXR1cyI6eyJtZXRob2QiOiJub25lIn0sInN1YiI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2IiwidmN0Ijoib3BlbmNyZWRlbnRpYWxzLmVtYWlsL3YxIn0.N-SNVObviWKHuCgoAlp5rPw_B_URBh3NbRlEzQN5RbqjygjBBo4gwhbZ-Bw7aMR9aXZs2vpkAI27Ev-nO3UsBg~WyIwMHFGc0Jjd1hFckhwWkdoZXp2RlNBIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyIwTDg2bnAxQ3NPVHZTT0pwVmQxdHhRIiwiZW1haWxEb21haW4iLCJleGFtcGxlLmNvbSJd~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 769338d7e4931942d4215cfcfcdbbd01\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:8wMvqFwyyt1cywJ8onMzwtPhUW5NyHUl6CO1_3MHRWY", + "signature": "0x49aeaee31e8bde4b83ed823879b1a997e1afb6dc927eb5b746342e8ca92d62e45c62fa01bd8c476031291bc67da7e8752f6f78852d240ccb8a7ab7907c62a8681c" + }, + "nonceStore": [ + { + "key": "verifier.example\n769338d7e4931942d4215cfcfcdbbd01", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-signature", + "detail": "bad-signature: issuer signature did not verify" + } + }, + { + "name": "oc-flip-payload-75", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "alg": "EdDSA", + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#controller", + "notAfter": null, + "notBefore": "2025-01-01T00:00:00Z", + "profiles": [ + "tinycloud.email-held/v1" + ], + "publicKey": "6kpsY-KcUgq-9VB7Ey7F-ZVHdq6-vnuSQh7qaRRG0iw", + "retiredAt": null, + "vcts": [ + "opencredentials.email/v1" + ] + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNjb250cm9sbGVyIn0.eyJfc2QiOlsiOUZSM1NySExrSW4tc01vOUIyQ3RIZWtIRTlWdFVjQkpkZDBOdlFDYUJpNCIsIklYb1BsMDRYeEc2YnRNOUE1YzZPYkxmdHBHVmt4UXFrdGxCMl96Vnl2RW8iXSwiX3NkX2FsZyI6InNoYS0yNTYiLCJleHAiOjE3Njk4MTc2MDAsImhvbGRlckJpbmRpbmciOnsiZGlkIjoiZGlkOnBraDplaXAxNTU6MToweGYzOUZkNmU1MWFhZDg4RjZGNGNlNmFCODgyNzI3OWNmZkZiOTIyNjYiLCJzaWduaW5nRG9tYWluIjoidGlueWNsb3VkLmNyZWRlbnRpYWxzL2FjY291bnQtYmluZGluZy92MSJ9LCJpYXQiOjE3NjcyMjU2MDAsImlzcyI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyIsImp0aSI6InVybjp1dWlkOjVmMWM5YTJlLTdiM2QtNGU4YS05YzYxLTJkNGI4ZTdmMGExMyIsIm5iZiI6MTc2NzIyNTYwMCwicHJvZmlsZSI6InRpbnljbG91ZC5lbWFpbC1oZWxkL3YxIAwicHJvZmlsZVZlcnNpb24iOjEsInN0YXR1cyI6eyJtZXRob2QiOiJub25lIn0sInN1YiI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2IiwidmN0Ijoib3BlbmNyZWRlbnRpYWxzLmVtYWlsL3YxIn0.N-SNVObviWKHuCgoAlp5rPw_B_URBh3NbRlEzQN5RbqjygjBBo4gwhbZ-Bw7aMR9aXZs2vpkAI27Ev-nO3UsBg~WyIwMHFGc0Jjd1hFckhwWkdoZXp2RlNBIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyIwTDg2bnAxQ3NPVHZTT0pwVmQxdHhRIiwiZW1haWxEb21haW4iLCJleGFtcGxlLmNvbSJd~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: fa18f4b1e29d83a4fc7a1ff60435dbb5\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:2mSoEHba6vcAaYQjtsLNqq4PkeUvy5OV_LvVtpmNNMY", + "signature": "0x4bc983c37ab19634ee8d82ecdbc0b93b33d0db28fe3ced20c0793da0f4910fed0b3917c9da70ac755bc9d2844931425be91ee9c2483633c9e5fc90a4b6d4b2a71c" + }, + "nonceStore": [ + { + "key": "verifier.example\nfa18f4b1e29d83a4fc7a1ff60435dbb5", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-signature", + "detail": "bad-signature: issuer signature did not verify" + } + }, + { + "name": "oc-flip-signature-25", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "alg": "EdDSA", + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#controller", + "notAfter": null, + "notBefore": "2025-01-01T00:00:00Z", + "profiles": [ + "tinycloud.email-held/v1" + ], + "publicKey": "6kpsY-KcUgq-9VB7Ey7F-ZVHdq6-vnuSQh7qaRRG0iw", + "retiredAt": null, + "vcts": [ + "opencredentials.email/v1" + ] + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNjb250cm9sbGVyIn0.eyJfc2QiOlsiOUZSM1NySExrSW4tc01vOUIyQ3RIZWtIRTlWdFVjQkpkZDBOdlFDYUJpNCIsIklYb1BsMDRYeEc2YnRNOUE1YzZPYkxmdHBHVmt4UXFrdGxCMl96Vnl2RW8iXSwiX3NkX2FsZyI6InNoYS0yNTYiLCJleHAiOjE3Njk4MTc2MDAsImhvbGRlckJpbmRpbmciOnsiZGlkIjoiZGlkOnBraDplaXAxNTU6MToweGYzOUZkNmU1MWFhZDg4RjZGNGNlNmFCODgyNzI3OWNmZkZiOTIyNjYiLCJzaWduaW5nRG9tYWluIjoidGlueWNsb3VkLmNyZWRlbnRpYWxzL2FjY291bnQtYmluZGluZy92MSJ9LCJpYXQiOjE3NjcyMjU2MDAsImlzcyI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyIsImp0aSI6InVybjp1dWlkOjVmMWM5YTJlLTdiM2QtNGU4YS05YzYxLTJkNGI4ZTdmMGExMyIsIm5iZiI6MTc2NzIyNTYwMCwicHJvZmlsZSI6InRpbnljbG91ZC5lbWFpbC1oZWxkL3YxIiwicHJvZmlsZVZlcnNpb24iOjEsInN0YXR1cyI6eyJtZXRob2QiOiJub25lIn0sInN1YiI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2IiwidmN0Ijoib3BlbmNyZWRlbnRpYWxzLmVtYWlsL3YxIn0.N-SNVObviWKHuCgoAlp5rAw_B_URBh3NbRlEzQN5RbqjygjBBo4gwhbZ-Bw7aMR9aXZs2vpkAI27Ev-nO3UsBg~WyIwMHFGc0Jjd1hFckhwWkdoZXp2RlNBIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyIwTDg2bnAxQ3NPVHZTT0pwVmQxdHhRIiwiZW1haWxEb21haW4iLCJleGFtcGxlLmNvbSJd~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 2415b38419925bf65723eca77844f6b7\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:oHeit5uv5H7TPU6GC2pqnz1umQJZsFem67K0ce-BLkI", + "signature": "0x5c689c7ac85f66ebcb5d661381b1911559a225fadd0b88a461c724eb66390d665ba7060cacce779cf063b84f4c6adf2949ceada1750d0cf44c083af7867f17711b" + }, + "nonceStore": [ + { + "key": "verifier.example\n2415b38419925bf65723eca77844f6b7", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-signature", + "detail": "bad-signature: issuer signature did not verify" + } + }, + { + "name": "oc-flip-signature-50", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "alg": "EdDSA", + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#controller", + "notAfter": null, + "notBefore": "2025-01-01T00:00:00Z", + "profiles": [ + "tinycloud.email-held/v1" + ], + "publicKey": "6kpsY-KcUgq-9VB7Ey7F-ZVHdq6-vnuSQh7qaRRG0iw", + "retiredAt": null, + "vcts": [ + "opencredentials.email/v1" + ] + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNjb250cm9sbGVyIn0.eyJfc2QiOlsiOUZSM1NySExrSW4tc01vOUIyQ3RIZWtIRTlWdFVjQkpkZDBOdlFDYUJpNCIsIklYb1BsMDRYeEc2YnRNOUE1YzZPYkxmdHBHVmt4UXFrdGxCMl96Vnl2RW8iXSwiX3NkX2FsZyI6InNoYS0yNTYiLCJleHAiOjE3Njk4MTc2MDAsImhvbGRlckJpbmRpbmciOnsiZGlkIjoiZGlkOnBraDplaXAxNTU6MToweGYzOUZkNmU1MWFhZDg4RjZGNGNlNmFCODgyNzI3OWNmZkZiOTIyNjYiLCJzaWduaW5nRG9tYWluIjoidGlueWNsb3VkLmNyZWRlbnRpYWxzL2FjY291bnQtYmluZGluZy92MSJ9LCJpYXQiOjE3NjcyMjU2MDAsImlzcyI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyIsImp0aSI6InVybjp1dWlkOjVmMWM5YTJlLTdiM2QtNGU4YS05YzYxLTJkNGI4ZTdmMGExMyIsIm5iZiI6MTc2NzIyNTYwMCwicHJvZmlsZSI6InRpbnljbG91ZC5lbWFpbC1oZWxkL3YxIiwicHJvZmlsZVZlcnNpb24iOjEsInN0YXR1cyI6eyJtZXRob2QiOiJub25lIn0sInN1YiI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2IiwidmN0Ijoib3BlbmNyZWRlbnRpYWxzLmVtYWlsL3YxIn0.N-SNVObviWKHuCgoAlp5rPw_B_URBh3NbRlEzQN5RbqAygjBBo4gwhbZ-Bw7aMR9aXZs2vpkAI27Ev-nO3UsBg~WyIwMHFGc0Jjd1hFckhwWkdoZXp2RlNBIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyIwTDg2bnAxQ3NPVHZTT0pwVmQxdHhRIiwiZW1haWxEb21haW4iLCJleGFtcGxlLmNvbSJd~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 6f03fdf5fa54ce7fe0621e04bc4b04ba\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:326oK2wbq0IkkUsd6AYoIOM4RHJiRKxfJWhr8lQAOMQ", + "signature": "0xfdf159d9b3a9668ec0a7be67d732f57dda9139bdd7c27014f2301ddb3f9d2c057f31cc5f706d252d4d881bfb51356505a3376ffb072f5345ad37679438521c951b" + }, + "nonceStore": [ + { + "key": "verifier.example\n6f03fdf5fa54ce7fe0621e04bc4b04ba", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-signature", + "detail": "bad-signature: issuer signature did not verify" + } + }, + { + "name": "oc-flip-signature-75", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "alg": "EdDSA", + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#controller", + "notAfter": null, + "notBefore": "2025-01-01T00:00:00Z", + "profiles": [ + "tinycloud.email-held/v1" + ], + "publicKey": "6kpsY-KcUgq-9VB7Ey7F-ZVHdq6-vnuSQh7qaRRG0iw", + "retiredAt": null, + "vcts": [ + "opencredentials.email/v1" + ] + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNjb250cm9sbGVyIn0.eyJfc2QiOlsiOUZSM1NySExrSW4tc01vOUIyQ3RIZWtIRTlWdFVjQkpkZDBOdlFDYUJpNCIsIklYb1BsMDRYeEc2YnRNOUE1YzZPYkxmdHBHVmt4UXFrdGxCMl96Vnl2RW8iXSwiX3NkX2FsZyI6InNoYS0yNTYiLCJleHAiOjE3Njk4MTc2MDAsImhvbGRlckJpbmRpbmciOnsiZGlkIjoiZGlkOnBraDplaXAxNTU6MToweGYzOUZkNmU1MWFhZDg4RjZGNGNlNmFCODgyNzI3OWNmZkZiOTIyNjYiLCJzaWduaW5nRG9tYWluIjoidGlueWNsb3VkLmNyZWRlbnRpYWxzL2FjY291bnQtYmluZGluZy92MSJ9LCJpYXQiOjE3NjcyMjU2MDAsImlzcyI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyIsImp0aSI6InVybjp1dWlkOjVmMWM5YTJlLTdiM2QtNGU4YS05YzYxLTJkNGI4ZTdmMGExMyIsIm5iZiI6MTc2NzIyNTYwMCwicHJvZmlsZSI6InRpbnljbG91ZC5lbWFpbC1oZWxkL3YxIiwicHJvZmlsZVZlcnNpb24iOjEsInN0YXR1cyI6eyJtZXRob2QiOiJub25lIn0sInN1YiI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2IiwidmN0Ijoib3BlbmNyZWRlbnRpYWxzLmVtYWlsL3YxIn0.N-SNVObviWKHuCgoAlp5rPw_B_URBh3NbRlEzQN5RbqjygjBBo4gwhbZ-Bw7aMR9AXZs2vpkAI27Ev-nO3UsBg~WyIwMHFGc0Jjd1hFckhwWkdoZXp2RlNBIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyIwTDg2bnAxQ3NPVHZTT0pwVmQxdHhRIiwiZW1haWxEb21haW4iLCJleGFtcGxlLmNvbSJd~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 09f89112df75fcd98745d2445a4778af\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:mRGucAUbI3FU9TeWD5806PRW2dcBsb00B8gCmevI1cE", + "signature": "0xf30a28de746aadfa4246cb5feea373cd8561577700716daa5eb67d7e39be5288715d182060870cf4140b7ef840c502963aa1c96fd945d347660c265711a313271c" + }, + "nonceStore": [ + { + "key": "verifier.example\n09f89112df75fcd98745d2445a4778af", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-signature", + "detail": "bad-signature: issuer signature did not verify" + } + }, + { + "name": "oc-flip-disclosure-25", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "alg": "EdDSA", + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#controller", + "notAfter": null, + "notBefore": "2025-01-01T00:00:00Z", + "profiles": [ + "tinycloud.email-held/v1" + ], + "publicKey": "6kpsY-KcUgq-9VB7Ey7F-ZVHdq6-vnuSQh7qaRRG0iw", + "retiredAt": null, + "vcts": [ + "opencredentials.email/v1" + ] + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNjb250cm9sbGVyIn0.eyJfc2QiOlsiOUZSM1NySExrSW4tc01vOUIyQ3RIZWtIRTlWdFVjQkpkZDBOdlFDYUJpNCIsIklYb1BsMDRYeEc2YnRNOUE1YzZPYkxmdHBHVmt4UXFrdGxCMl96Vnl2RW8iXSwiX3NkX2FsZyI6InNoYS0yNTYiLCJleHAiOjE3Njk4MTc2MDAsImhvbGRlckJpbmRpbmciOnsiZGlkIjoiZGlkOnBraDplaXAxNTU6MToweGYzOUZkNmU1MWFhZDg4RjZGNGNlNmFCODgyNzI3OWNmZkZiOTIyNjYiLCJzaWduaW5nRG9tYWluIjoidGlueWNsb3VkLmNyZWRlbnRpYWxzL2FjY291bnQtYmluZGluZy92MSJ9LCJpYXQiOjE3NjcyMjU2MDAsImlzcyI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyIsImp0aSI6InVybjp1dWlkOjVmMWM5YTJlLTdiM2QtNGU4YS05YzYxLTJkNGI4ZTdmMGExMyIsIm5iZiI6MTc2NzIyNTYwMCwicHJvZmlsZSI6InRpbnljbG91ZC5lbWFpbC1oZWxkL3YxIiwicHJvZmlsZVZlcnNpb24iOjEsInN0YXR1cyI6eyJtZXRob2QiOiJub25lIn0sInN1YiI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2IiwidmN0Ijoib3BlbmNyZWRlbnRpYWxzLmVtYWlsL3YxIn0.N-SNVObviWKHuCgoAlp5rPw_B_URBh3NbRlEzQN5RbqjygjBBo4gwhbZ-Bw7aMR9aXZs2vpkAI27Ev-nO3UsBg~WyIwMHFGc0Jjd1hFckAwWkdoZXp2RlNBIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyIwTDg2bnAxQ3NPVHZTT0pwVmQxdHhRIiwiZW1haWxEb21haW4iLCJleGFtcGxlLmNvbSJd~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: ef56ac3bbf8fe113433dcd2d13cad883\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:_u5gP9-GMQNLeEAjhQeCE6zKuEVyTWn-570E0zRfxtY", + "signature": "0x3d7f29d2e5e4183648bf5c2287e9b121cea2c1d8ab025838dc038e53712c80595d3e3917630795f55c17827b0999ba8ecb9fff85b8818a4c0793d0611fc3a3de1b" + }, + "nonceStore": [ + { + "key": "verifier.example\nef56ac3bbf8fe113433dcd2d13cad883", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-disclosure", + "detail": "bad-disclosure: disclosure digest is not in _sd" + } + }, + { + "name": "oc-flip-disclosure-50", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "alg": "EdDSA", + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#controller", + "notAfter": null, + "notBefore": "2025-01-01T00:00:00Z", + "profiles": [ + "tinycloud.email-held/v1" + ], + "publicKey": "6kpsY-KcUgq-9VB7Ey7F-ZVHdq6-vnuSQh7qaRRG0iw", + "retiredAt": null, + "vcts": [ + "opencredentials.email/v1" + ] + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNjb250cm9sbGVyIn0.eyJfc2QiOlsiOUZSM1NySExrSW4tc01vOUIyQ3RIZWtIRTlWdFVjQkpkZDBOdlFDYUJpNCIsIklYb1BsMDRYeEc2YnRNOUE1YzZPYkxmdHBHVmt4UXFrdGxCMl96Vnl2RW8iXSwiX3NkX2FsZyI6InNoYS0yNTYiLCJleHAiOjE3Njk4MTc2MDAsImhvbGRlckJpbmRpbmciOnsiZGlkIjoiZGlkOnBraDplaXAxNTU6MToweGYzOUZkNmU1MWFhZDg4RjZGNGNlNmFCODgyNzI3OWNmZkZiOTIyNjYiLCJzaWduaW5nRG9tYWluIjoidGlueWNsb3VkLmNyZWRlbnRpYWxzL2FjY291bnQtYmluZGluZy92MSJ9LCJpYXQiOjE3NjcyMjU2MDAsImlzcyI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyIsImp0aSI6InVybjp1dWlkOjVmMWM5YTJlLTdiM2QtNGU4YS05YzYxLTJkNGI4ZTdmMGExMyIsIm5iZiI6MTc2NzIyNTYwMCwicHJvZmlsZSI6InRpbnljbG91ZC5lbWFpbC1oZWxkL3YxIiwicHJvZmlsZVZlcnNpb24iOjEsInN0YXR1cyI6eyJtZXRob2QiOiJub25lIn0sInN1YiI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2IiwidmN0Ijoib3BlbmNyZWRlbnRpYWxzLmVtYWlsL3YxIn0.N-SNVObviWKHuCgoAlp5rPw_B_URBh3NbRlEzQN5RbqjygjBBo4gwhbZ-Bw7aMR9aXZs2vpkAI27Ev-nO3UsBg~WyIwMHFGc0Jjd1hFckhwWkdoZXp2RlNBIiwiAW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyIwTDg2bnAxQ3NPVHZTT0pwVmQxdHhRIiwiZW1haWxEb21haW4iLCJleGFtcGxlLmNvbSJd~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: ab10870ab935b5b6c6a204f920b96f5c\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:iuZocvLBX46DizHXJKJLJ911uKJzHPgJRqMQ1mkY4mY", + "signature": "0x106ea8eb2113cadf1db0bb94318984005c240bba435aa16d5016f2025a45541d6c42a0c4eb8e0efa18fa3bbb7a69a515aa4a0c3db93d208ebd2b16161b4301171c" + }, + "nonceStore": [ + { + "key": "verifier.example\nab10870ab935b5b6c6a204f920b96f5c", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-disclosure", + "detail": "bad-disclosure: disclosure digest is not in _sd" + } + }, + { + "name": "oc-flip-disclosure-75", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "alg": "EdDSA", + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#controller", + "notAfter": null, + "notBefore": "2025-01-01T00:00:00Z", + "profiles": [ + "tinycloud.email-held/v1" + ], + "publicKey": "6kpsY-KcUgq-9VB7Ey7F-ZVHdq6-vnuSQh7qaRRG0iw", + "retiredAt": null, + "vcts": [ + "opencredentials.email/v1" + ] + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNjb250cm9sbGVyIn0.eyJfc2QiOlsiOUZSM1NySExrSW4tc01vOUIyQ3RIZWtIRTlWdFVjQkpkZDBOdlFDYUJpNCIsIklYb1BsMDRYeEc2YnRNOUE1YzZPYkxmdHBHVmt4UXFrdGxCMl96Vnl2RW8iXSwiX3NkX2FsZyI6InNoYS0yNTYiLCJleHAiOjE3Njk4MTc2MDAsImhvbGRlckJpbmRpbmciOnsiZGlkIjoiZGlkOnBraDplaXAxNTU6MToweGYzOUZkNmU1MWFhZDg4RjZGNGNlNmFCODgyNzI3OWNmZkZiOTIyNjYiLCJzaWduaW5nRG9tYWluIjoidGlueWNsb3VkLmNyZWRlbnRpYWxzL2FjY291bnQtYmluZGluZy92MSJ9LCJpYXQiOjE3NjcyMjU2MDAsImlzcyI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyIsImp0aSI6InVybjp1dWlkOjVmMWM5YTJlLTdiM2QtNGU4YS05YzYxLTJkNGI4ZTdmMGExMyIsIm5iZiI6MTc2NzIyNTYwMCwicHJvZmlsZSI6InRpbnljbG91ZC5lbWFpbC1oZWxkL3YxIiwicHJvZmlsZVZlcnNpb24iOjEsInN0YXR1cyI6eyJtZXRob2QiOiJub25lIn0sInN1YiI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2IiwidmN0Ijoib3BlbmNyZWRlbnRpYWxzLmVtYWlsL3YxIn0.N-SNVObviWKHuCgoAlp5rPw_B_URBh3NbRlEzQN5RbqjygjBBo4gwhbZ-Bw7aMR9aXZs2vpkAI27Ev-nO3UsBg~WyIwMHFGc0Jjd1hFckhwWkdoZXp2RlNBIiwiZW1haWwiLCJhbGljZUAleGFtcGxlLmNvbSJd~WyIwTDg2bnAxQ3NPVHZTT0pwVmQxdHhRIiwiZW1haWxEb21haW4iLCJleGFtcGxlLmNvbSJd~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 373bcd02e35a0893abba2175047150a5\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:7oUcIBwsmCtpAk9I5pt-gyBpteidRqnbNIv-XUAM1zY", + "signature": "0x6f4d78781abd4d2211760830ec182514602c956c4c881d474c2aac82a5d8754766cbcc2c338a3fa777309c5eeefb3ac7ea687a5bcaeefa00a77aaf24b6ba5c511b" + }, + "nonceStore": [ + { + "key": "verifier.example\n373bcd02e35a0893abba2175047150a5", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-disclosure", + "detail": "bad-disclosure: disclosure digest is not in _sd" + } + }, + { + "name": "oc-window-iat-minus-1", + "policy": { + "now": "2025-12-31T23:59:59.000Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "alg": "EdDSA", + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#controller", + "notAfter": null, + "notBefore": "2025-01-01T00:00:00Z", + "profiles": [ + "tinycloud.email-held/v1" + ], + "publicKey": "6kpsY-KcUgq-9VB7Ey7F-ZVHdq6-vnuSQh7qaRRG0iw", + "retiredAt": null, + "vcts": [ + "opencredentials.email/v1" + ] + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNjb250cm9sbGVyIn0.eyJfc2QiOlsiOUZSM1NySExrSW4tc01vOUIyQ3RIZWtIRTlWdFVjQkpkZDBOdlFDYUJpNCIsIklYb1BsMDRYeEc2YnRNOUE1YzZPYkxmdHBHVmt4UXFrdGxCMl96Vnl2RW8iXSwiX3NkX2FsZyI6InNoYS0yNTYiLCJleHAiOjE3Njk4MTc2MDAsImhvbGRlckJpbmRpbmciOnsiZGlkIjoiZGlkOnBraDplaXAxNTU6MToweGYzOUZkNmU1MWFhZDg4RjZGNGNlNmFCODgyNzI3OWNmZkZiOTIyNjYiLCJzaWduaW5nRG9tYWluIjoidGlueWNsb3VkLmNyZWRlbnRpYWxzL2FjY291bnQtYmluZGluZy92MSJ9LCJpYXQiOjE3NjcyMjU2MDAsImlzcyI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyIsImp0aSI6InVybjp1dWlkOjVmMWM5YTJlLTdiM2QtNGU4YS05YzYxLTJkNGI4ZTdmMGExMyIsIm5iZiI6MTc2NzIyNTYwMCwicHJvZmlsZSI6InRpbnljbG91ZC5lbWFpbC1oZWxkL3YxIiwicHJvZmlsZVZlcnNpb24iOjEsInN0YXR1cyI6eyJtZXRob2QiOiJub25lIn0sInN1YiI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2IiwidmN0Ijoib3BlbmNyZWRlbnRpYWxzLmVtYWlsL3YxIn0.N-SNVObviWKHuCgoAlp5rPw_B_URBh3NbRlEzQN5RbqjygjBBo4gwhbZ-Bw7aMR9aXZs2vpkAI27Ev-nO3UsBg~WyIwMHFGc0Jjd1hFckhwWkdoZXp2RlNBIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyIwTDg2bnAxQ3NPVHZTT0pwVmQxdHhRIiwiZW1haWxEb21haW4iLCJleGFtcGxlLmNvbSJd~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: b527dc9f710f39ad72ac170603bab2e9\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:jRXBuzz_SdM1I9uL9jv4kGkXzwbDa52wG9P8UD8C4_Y", + "signature": "0x3c0b8f79ae7d6962bf89bb8e8cfb68aae15e824aaede622db8fc39b414bef4892bda8f69ad64f5ca86620e5fd9f5025f41c0a224ef066df7fabe5e3873cfb8151b" + }, + "nonceStore": [ + { + "key": "verifier.example\nb527dc9f710f39ad72ac170603bab2e9", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "not-yet-valid", + "detail": "not-yet-valid: credential is not yet valid" + } + }, + { + "name": "oc-window-iat", + "policy": { + "now": "2026-01-01T00:00:00.000Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "alg": "EdDSA", + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#controller", + "notAfter": null, + "notBefore": "2025-01-01T00:00:00Z", + "profiles": [ + "tinycloud.email-held/v1" + ], + "publicKey": "6kpsY-KcUgq-9VB7Ey7F-ZVHdq6-vnuSQh7qaRRG0iw", + "retiredAt": null, + "vcts": [ + "opencredentials.email/v1" + ] + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNjb250cm9sbGVyIn0.eyJfc2QiOlsiOUZSM1NySExrSW4tc01vOUIyQ3RIZWtIRTlWdFVjQkpkZDBOdlFDYUJpNCIsIklYb1BsMDRYeEc2YnRNOUE1YzZPYkxmdHBHVmt4UXFrdGxCMl96Vnl2RW8iXSwiX3NkX2FsZyI6InNoYS0yNTYiLCJleHAiOjE3Njk4MTc2MDAsImhvbGRlckJpbmRpbmciOnsiZGlkIjoiZGlkOnBraDplaXAxNTU6MToweGYzOUZkNmU1MWFhZDg4RjZGNGNlNmFCODgyNzI3OWNmZkZiOTIyNjYiLCJzaWduaW5nRG9tYWluIjoidGlueWNsb3VkLmNyZWRlbnRpYWxzL2FjY291bnQtYmluZGluZy92MSJ9LCJpYXQiOjE3NjcyMjU2MDAsImlzcyI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyIsImp0aSI6InVybjp1dWlkOjVmMWM5YTJlLTdiM2QtNGU4YS05YzYxLTJkNGI4ZTdmMGExMyIsIm5iZiI6MTc2NzIyNTYwMCwicHJvZmlsZSI6InRpbnljbG91ZC5lbWFpbC1oZWxkL3YxIiwicHJvZmlsZVZlcnNpb24iOjEsInN0YXR1cyI6eyJtZXRob2QiOiJub25lIn0sInN1YiI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2IiwidmN0Ijoib3BlbmNyZWRlbnRpYWxzLmVtYWlsL3YxIn0.N-SNVObviWKHuCgoAlp5rPw_B_URBh3NbRlEzQN5RbqjygjBBo4gwhbZ-Bw7aMR9aXZs2vpkAI27Ev-nO3UsBg~WyIwMHFGc0Jjd1hFckhwWkdoZXp2RlNBIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyIwTDg2bnAxQ3NPVHZTT0pwVmQxdHhRIiwiZW1haWxEb21haW4iLCJleGFtcGxlLmNvbSJd~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 9b2cfddbd68805948acec2c0daeab7ff\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:jRXBuzz_SdM1I9uL9jv4kGkXzwbDa52wG9P8UD8C4_Y", + "signature": "0x9267927123a265039db11b2f1721d216e22e56a535be3fae8c95ce2ec9cdda265c16334308626f7dd1e457248c39ccd9023df0a350ac6013899c17e603ddf0c91c" + }, + "nonceStore": [ + { + "key": "verifier.example\n9b2cfddbd68805948acec2c0daeab7ff", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "ok", + "subject": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "issuer": "did:web:issuer.credentials.org" + } + }, + { + "name": "oc-window-exp-minus-1", + "policy": { + "now": "2026-01-30T23:59:59.000Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "alg": "EdDSA", + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#controller", + "notAfter": null, + "notBefore": "2025-01-01T00:00:00Z", + "profiles": [ + "tinycloud.email-held/v1" + ], + "publicKey": "6kpsY-KcUgq-9VB7Ey7F-ZVHdq6-vnuSQh7qaRRG0iw", + "retiredAt": null, + "vcts": [ + "opencredentials.email/v1" + ] + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNjb250cm9sbGVyIn0.eyJfc2QiOlsiOUZSM1NySExrSW4tc01vOUIyQ3RIZWtIRTlWdFVjQkpkZDBOdlFDYUJpNCIsIklYb1BsMDRYeEc2YnRNOUE1YzZPYkxmdHBHVmt4UXFrdGxCMl96Vnl2RW8iXSwiX3NkX2FsZyI6InNoYS0yNTYiLCJleHAiOjE3Njk4MTc2MDAsImhvbGRlckJpbmRpbmciOnsiZGlkIjoiZGlkOnBraDplaXAxNTU6MToweGYzOUZkNmU1MWFhZDg4RjZGNGNlNmFCODgyNzI3OWNmZkZiOTIyNjYiLCJzaWduaW5nRG9tYWluIjoidGlueWNsb3VkLmNyZWRlbnRpYWxzL2FjY291bnQtYmluZGluZy92MSJ9LCJpYXQiOjE3NjcyMjU2MDAsImlzcyI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyIsImp0aSI6InVybjp1dWlkOjVmMWM5YTJlLTdiM2QtNGU4YS05YzYxLTJkNGI4ZTdmMGExMyIsIm5iZiI6MTc2NzIyNTYwMCwicHJvZmlsZSI6InRpbnljbG91ZC5lbWFpbC1oZWxkL3YxIiwicHJvZmlsZVZlcnNpb24iOjEsInN0YXR1cyI6eyJtZXRob2QiOiJub25lIn0sInN1YiI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2IiwidmN0Ijoib3BlbmNyZWRlbnRpYWxzLmVtYWlsL3YxIn0.N-SNVObviWKHuCgoAlp5rPw_B_URBh3NbRlEzQN5RbqjygjBBo4gwhbZ-Bw7aMR9aXZs2vpkAI27Ev-nO3UsBg~WyIwMHFGc0Jjd1hFckhwWkdoZXp2RlNBIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyIwTDg2bnAxQ3NPVHZTT0pwVmQxdHhRIiwiZW1haWxEb21haW4iLCJleGFtcGxlLmNvbSJd~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: b47c588985f7f469eeb9fe0e030b838f\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:jRXBuzz_SdM1I9uL9jv4kGkXzwbDa52wG9P8UD8C4_Y", + "signature": "0x57f8005dfdd71021a628136fa807449c701a29a1f626eac3944e318fcf0afaad4e7eff7a1466aa3a75e9b276e78d1bd86276ba3b5fd82bf8b53f716230a0926e1b" + }, + "nonceStore": [ + { + "key": "verifier.example\nb47c588985f7f469eeb9fe0e030b838f", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "ok", + "subject": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "issuer": "did:web:issuer.credentials.org" + } + }, + { + "name": "oc-window-exp", + "policy": { + "now": "2026-01-31T00:00:00.000Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "alg": "EdDSA", + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#controller", + "notAfter": null, + "notBefore": "2025-01-01T00:00:00Z", + "profiles": [ + "tinycloud.email-held/v1" + ], + "publicKey": "6kpsY-KcUgq-9VB7Ey7F-ZVHdq6-vnuSQh7qaRRG0iw", + "retiredAt": null, + "vcts": [ + "opencredentials.email/v1" + ] + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNjb250cm9sbGVyIn0.eyJfc2QiOlsiOUZSM1NySExrSW4tc01vOUIyQ3RIZWtIRTlWdFVjQkpkZDBOdlFDYUJpNCIsIklYb1BsMDRYeEc2YnRNOUE1YzZPYkxmdHBHVmt4UXFrdGxCMl96Vnl2RW8iXSwiX3NkX2FsZyI6InNoYS0yNTYiLCJleHAiOjE3Njk4MTc2MDAsImhvbGRlckJpbmRpbmciOnsiZGlkIjoiZGlkOnBraDplaXAxNTU6MToweGYzOUZkNmU1MWFhZDg4RjZGNGNlNmFCODgyNzI3OWNmZkZiOTIyNjYiLCJzaWduaW5nRG9tYWluIjoidGlueWNsb3VkLmNyZWRlbnRpYWxzL2FjY291bnQtYmluZGluZy92MSJ9LCJpYXQiOjE3NjcyMjU2MDAsImlzcyI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyIsImp0aSI6InVybjp1dWlkOjVmMWM5YTJlLTdiM2QtNGU4YS05YzYxLTJkNGI4ZTdmMGExMyIsIm5iZiI6MTc2NzIyNTYwMCwicHJvZmlsZSI6InRpbnljbG91ZC5lbWFpbC1oZWxkL3YxIiwicHJvZmlsZVZlcnNpb24iOjEsInN0YXR1cyI6eyJtZXRob2QiOiJub25lIn0sInN1YiI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2IiwidmN0Ijoib3BlbmNyZWRlbnRpYWxzLmVtYWlsL3YxIn0.N-SNVObviWKHuCgoAlp5rPw_B_URBh3NbRlEzQN5RbqjygjBBo4gwhbZ-Bw7aMR9aXZs2vpkAI27Ev-nO3UsBg~WyIwMHFGc0Jjd1hFckhwWkdoZXp2RlNBIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyIwTDg2bnAxQ3NPVHZTT0pwVmQxdHhRIiwiZW1haWxEb21haW4iLCJleGFtcGxlLmNvbSJd~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 79ba16ea8994a1f5c80629cc24161048\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:jRXBuzz_SdM1I9uL9jv4kGkXzwbDa52wG9P8UD8C4_Y", + "signature": "0x2615c1d3e908243d694594fcf4e5ba8d0c8da55e87438bfb70ce04f5150434a945ca0ae9b77b18682ff5f2610398da804c027ad69c84496448d5e6a1bc54d1291c" + }, + "nonceStore": [ + { + "key": "verifier.example\n79ba16ea8994a1f5c80629cc24161048", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "expired", + "detail": "expired: credential has expired" + } + }, + { + "name": "oc-window-exp-plus-1", + "policy": { + "now": "2026-01-31T00:00:01.000Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "alg": "EdDSA", + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#controller", + "notAfter": null, + "notBefore": "2025-01-01T00:00:00Z", + "profiles": [ + "tinycloud.email-held/v1" + ], + "publicKey": "6kpsY-KcUgq-9VB7Ey7F-ZVHdq6-vnuSQh7qaRRG0iw", + "retiredAt": null, + "vcts": [ + "opencredentials.email/v1" + ] + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNjb250cm9sbGVyIn0.eyJfc2QiOlsiOUZSM1NySExrSW4tc01vOUIyQ3RIZWtIRTlWdFVjQkpkZDBOdlFDYUJpNCIsIklYb1BsMDRYeEc2YnRNOUE1YzZPYkxmdHBHVmt4UXFrdGxCMl96Vnl2RW8iXSwiX3NkX2FsZyI6InNoYS0yNTYiLCJleHAiOjE3Njk4MTc2MDAsImhvbGRlckJpbmRpbmciOnsiZGlkIjoiZGlkOnBraDplaXAxNTU6MToweGYzOUZkNmU1MWFhZDg4RjZGNGNlNmFCODgyNzI3OWNmZkZiOTIyNjYiLCJzaWduaW5nRG9tYWluIjoidGlueWNsb3VkLmNyZWRlbnRpYWxzL2FjY291bnQtYmluZGluZy92MSJ9LCJpYXQiOjE3NjcyMjU2MDAsImlzcyI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyIsImp0aSI6InVybjp1dWlkOjVmMWM5YTJlLTdiM2QtNGU4YS05YzYxLTJkNGI4ZTdmMGExMyIsIm5iZiI6MTc2NzIyNTYwMCwicHJvZmlsZSI6InRpbnljbG91ZC5lbWFpbC1oZWxkL3YxIiwicHJvZmlsZVZlcnNpb24iOjEsInN0YXR1cyI6eyJtZXRob2QiOiJub25lIn0sInN1YiI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2IiwidmN0Ijoib3BlbmNyZWRlbnRpYWxzLmVtYWlsL3YxIn0.N-SNVObviWKHuCgoAlp5rPw_B_URBh3NbRlEzQN5RbqjygjBBo4gwhbZ-Bw7aMR9aXZs2vpkAI27Ev-nO3UsBg~WyIwMHFGc0Jjd1hFckhwWkdoZXp2RlNBIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyIwTDg2bnAxQ3NPVHZTT0pwVmQxdHhRIiwiZW1haWxEb21haW4iLCJleGFtcGxlLmNvbSJd~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 58bbfb17f81300d626f5677446216e85\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:jRXBuzz_SdM1I9uL9jv4kGkXzwbDa52wG9P8UD8C4_Y", + "signature": "0xf3b68406b2178b7c21b312c118da9bcf1a82a7ad6aa286abab316c277f7329153835b9a99104506342092ccd4fc245a5c1d85798499561413f9d8ccde69b017f1b" + }, + "nonceStore": [ + { + "key": "verifier.example\n58bbfb17f81300d626f5677446216e85", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "expired", + "detail": "expired: credential has expired" + } + }, + { + "name": "discv-email-trailing-space", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiV1BMMm4wczFSZVdsc3Y5dTFWdU1td0VnbEFnd3JfaTk1T1l4M1ZwMGF5TSIsIlFMc2FOWUxUVTJUbG9YZXZ2NldxdnI2dUxSTXB4eEdoRlo0Rnp1NlNkODAiXX0.TiQ2yVrxFWvFvZZGYr08WVBr7jomOOvOOseGH27Snn-gG4s5s8OKXhZeN82vnTKZO7lMi_sbIBT4YW4LrcF4Bg~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSAiXQ~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20gIl0~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 91207b2dfeccf1e3c0c56cf3d739e1c8\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:Zh1hhBmuQBLXRyl5XK2Wsz1MShKLQskz4vMFf0XQPvw", + "signature": "0x4e2ef16dfd9698e56f1e4c6ccb302978f6986bd73d4d2644465c1d804735d2245b2a4f1d0594a1682d3a561ed9b1fc887cd76497f5b38f65ae2a5d81e72b6a0b1c" + }, + "nonceStore": [ + { + "key": "verifier.example\n91207b2dfeccf1e3c0c56cf3d739e1c8", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-disclosure", + "detail": "bad-disclosure: email is not a canonical lowercase address" + } + }, + { + "name": "discv-email-trailing-newline", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiaFlUMktkX1ZrNWZZYzNIcWtRMmtmaFpLYWxNWHpYeXZvRXB2WFNmOGN0WSIsIm1ldmtNNUxVd0Qtd0xiRUdmclBmdHBiZm5rUFowSkZCanlmeUpfQTJ4aGMiXX0.pfH-R_m6fEnTZqqPs42Cfgyr74PoafHt0R21hFSyRH44j4ue7txFgxcxSbcqTlySeTcwGDs25VFM8152ZrV1Bw~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbVxuIl0~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb21cbiJd~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 74391a9607dfee88f0127ffca05790f5\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:-VlQQ2-VSdWbNcLBNWiRyun06193j7BF6hEtrXTf-3M", + "signature": "0x1b87ad80f142e16a55d70075535b07fb303ef84724b13b934b6d8f6c22696ae6762217282e56a907015ead3e3cc05633de1077f4a098814574c2c219a30d6c931c" + }, + "nonceStore": [ + { + "key": "verifier.example\n74391a9607dfee88f0127ffca05790f5", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-disclosure", + "detail": "bad-disclosure: email is not a canonical lowercase address" + } + }, + { + "name": "discv-email-leading-space", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiLWlBTnVQczZra1Yzcmx2clJYTUNNOTJzX1FMWGxxWFlGb1AyNHJJQUkzTSIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.hDs1f8KgfF8s0T9keoCs_Gs5wKEc1HgKat7PuRBVsl2SbUfTlBlbTy-iA5wv9rGbdyAaGIgxwbmmWqJm-IrvDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCIgYWxpY2VAZXhhbXBsZS5jb20iXQ~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 3df3258f3588be478a9aefd0ef7ee522\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:OXJO6bHh7NPwfr2sTxH2Gu_IdADOmFgWpV6sAbDA8iw", + "signature": "0xb98ff6f47636d3379737301b4081d447625b309b1b38c9e91b86935d2733f4272bd4f9fd2d1b2d17b5962093bab811af34fc5097b6f1c90c7d83423db263e9be1b" + }, + "nonceStore": [ + { + "key": "verifier.example\n3df3258f3588be478a9aefd0ef7ee522", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-disclosure", + "detail": "bad-disclosure: email is not a canonical lowercase address" + } + }, + { + "name": "discv-email-short-local", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiZnV4bEpXdFVCV1VEYzhQQjZhOWRORUZpQ2otbDBCRVRubWNMOWNjMjJXcyIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.IcSXO25MXKyz5bxYyb_EWt-b6CK4BRjNYzWzfrrnRdXn8UzQhZI0FskFILObkba44fK64yOhlEA9N8LQ2AO3Cw~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhQGV4YW1wbGUuY29tIl0~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 86b50bd3447963eae4e73be8b3b261e0\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:QtV3zl7lhE474vI8ypL3MoibDAE7ODtSU6hfGiSVor4", + "signature": "0x3489c334ab4bf5fb86b3f3fde65de8ea911eaf39522f9fc977db5ab4764fcf5c264ac1f91c03b30981e64bebd59699c6ff76c289f18f748687cd2e85ebe070411b" + }, + "nonceStore": [ + { + "key": "verifier.example\n86b50bd3447963eae4e73be8b3b261e0", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "ok", + "subject": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "issuer": "did:web:issuer.credentials.org" + } + }, + { + "name": "discv-email-no-tld", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiU085RFdsZHJmTXRhSURtaC1fa3AzRnRqa3hIMjZJNTJHRGZMQUJfVUc3ZyIsIjVvZl9vZEF3SnBnNktuaXpRN3gtZGl5cTZOZ1BIRWgtVy0zWDNvTnBoSUUiXX0.KIkl-PbtxgGNzkYJKoWfLmrcibcZf6wtxt0E6tqlUv4LIDlkVyl1h25OCPr6aWPamVyQ2RvP-vKO6Ib-leZXBQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlIl0~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZSJd~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 7d246588386393f754fe8a5fbf9208b7\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:MpnJDXFr8CK0dQXf9xul2IFn7ve3g2G2NFUVIHfrwmo", + "signature": "0xffc25d7d63f65a3f02b02fd8896077132af7319803a87ffdf3dc1dc08863a76c18df669a539ca772f6cd0fcaa319247c1ffd4d894c4acffa91e91cbc09e4db121c" + }, + "nonceStore": [ + { + "key": "verifier.example\n7d246588386393f754fe8a5fbf9208b7", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "ok", + "subject": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "issuer": "did:web:issuer.credentials.org" + } + }, + { + "name": "discv-email-double-dot-domain", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiaUhqbUo1SzJOWHEtdnZpeGo1cy1obmZrWnE4MzNmRVBTSHQwQW1EQmdjRSIsIm1yU3p2TUp1UnF5NWRyRjRjSDlDZHpfNnZxb2R1OFV4WEREMF9yeHVmeEkiXX0.ckb8KAYp1xDBhn2fWl_XkyHVJj_DoQWbOia7A5Fo0X_djNOdJN5EZpdlvkWFMSXpc4pHaCTXUuXHbwWSRghOCw~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLi5jb20iXQ~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS4uY29tIl0~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 66156ba6ccecb9af923eedea8392aace\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:Ep_FR8EoAhB0jVZ1T8tlLNVK56WILBg7lxW5btt-1yw", + "signature": "0xe90df27d5880f24d29d532ea3fac0f284e65722ccab3bb41e433ce7a0806f64b6163af815e423cac97210f883eb0793bc93b52f76bf3215a4f63bea85f711dbd1c" + }, + "nonceStore": [ + { + "key": "verifier.example\n66156ba6ccecb9af923eedea8392aace", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "ok", + "subject": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "issuer": "did:web:issuer.credentials.org" + } + }, + { + "name": "discv-email-leading-hyphen-label", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiWDZCekxVc0loWjRKUW1MbTM1TGFZVGZ3U3U3aVRhLW1CbnFRSFJ6RVprayIsInhkTHNBS3JNdzRQY0wtbEdWUE1Ra2pMeU04cGtadXNRMFZiZlVHcm5kTzgiXX0._kaMIXAfduYN1-A-CKIrvu-oapGHmbUF1IBdDylp8od5V-jOnrDD2YRJy7snxy_2d4zUlQ7ZRasmhPOhzCNgBw~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUAtZXhhbXBsZS5jb20iXQ~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiLWV4YW1wbGUuY29tIl0~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 4337627ddcf7add070aa6829d42254a8\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:4xOAU6X8j3ITUjxycqCZsFexC2ADULA2t23FzSo72Yo", + "signature": "0xd0b1bde0701ac9ee4950f5be3b4eee45c2263d0033e1ac1a777052b89f9b8f8326bf80719c33d74439028f66e6214995f909b159aa14b63c618a4c31435c6b9f1b" + }, + "nonceStore": [ + { + "key": "verifier.example\n4337627ddcf7add070aa6829d42254a8", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "ok", + "subject": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "issuer": "did:web:issuer.credentials.org" + } + }, + { + "name": "discv-email-trailing-dot", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsieW9ybDU5UFAwSHNNY1lWTEhBQXZNRWk3YWR3OFBaTEd0LXZmQW90aWxsYyIsIndJVG9qM1VmUFFvbnRvTl9NMXJ4YjVQU0N1UkYycjJIdFdaM3UxSXJaZW8iXX0.7lQQpSiE5QicjuexjgcoNvbCHpbe1xjLGSLYuQRSM89tT_JJOe52fSQj_AsI9AC7mtkyiJXhhIbGxMzBfvWnCA~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbS4iXQ~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20uIl0~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 177820537d30850dbd2be73d37e6f5b5\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:ScqlOo1ExEFxmV4TBwC8snEPU5XiqQds0HBrh0_Yr5A", + "signature": "0xb6e4c26a2fe8235df86796fcf043051520c7cffb77a3ecf1c4e968da2e7c8c4b6bb042a7a0483aa3258a640d5c0cd978cbf1e379e4225679179857d3d3ba2a971b" + }, + "nonceStore": [ + { + "key": "verifier.example\n177820537d30850dbd2be73d37e6f5b5", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "ok", + "subject": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "issuer": "did:web:issuer.credentials.org" + } + }, + { + "name": "discv-email-upper-domain", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiZDB1UF96b1dTM1VvSGlUR1Fua0lxTHlkWUhsVDhjelhlbE1rSFd6VG0zRSIsIkN4RFlyQl9VbFZDdjdpZlUzUkdHVmhuNk1va3ViemI1RnRxQXNCTTA5MnMiXX0.kPrhga8gF1XBU6S4KjlT50vUbZNcLjNf2ivQAepekQcDs06DwZJF8brX9PgtcfOcMuYvdXBzKO1lz875kU2jAQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBFWEFNUExFLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiRVhBTVBMRS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 7a765c7fa9a411cd57da238620aa5335\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:ZfIMNEIZruK7MQ66KbBnCM1C4lyR2Z0Rxd202N_gO6k", + "signature": "0x00adf2a0bb11c1ca0aa4a3445be3caf6193971461568dc778bf269ce057e5f1f11c722e8d41e2f4a4b1939f0af9567cbeb349afe1ecbd6a84914b23fb13bfc141c" + }, + "nonceStore": [ + { + "key": "verifier.example\n7a765c7fa9a411cd57da238620aa5335", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-disclosure", + "detail": "bad-disclosure: email is not a canonical lowercase address" + } + }, + { + "name": "discv-email-upper-local", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsidnVUeXFsV3hmdVZCMXE2dDlwbzROUWVLY0dOSTFIX3VYVUZIY3hydEZlUSIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.p_J2TLpXq78q0UaVpmvYvLlkZ13xPOV8VIJr5IN8JyM5cwYR7dIZ6NEc1nRZ1Hq-ocYoPep8UPUN4-agBKe_CQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJBTElDRUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: ba19ea545a82f3d9de46805f5582a5be\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:y26SXRSpOnxdA9XtploaUci_IXcheTeiCN-GaL5bjCI", + "signature": "0xc5efda1fa3bb353ef1ee4c77cdbea9c7b62f66ea0c87ce946e5d738cb8f91e1652877371b43ec1dcca8023d84d5099902a7d9f22563568c2d98cbddf387db95b1b" + }, + "nonceStore": [ + { + "key": "verifier.example\nba19ea545a82f3d9de46805f5582a5be", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-disclosure", + "detail": "bad-disclosure: email is not a canonical lowercase address" + } + }, + { + "name": "discv-email-plus-tag", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsia0Jma29aYVJmN2U1UzlnSnZvdklGdkRiSzRZZmpkMkVlSUFJTHRMYWdBVSIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ShdaCbtq3m0CirtcJygyX3GAboqspgsFh_YzNYy1-zvaQSs-uauC8TEIsPk_ADmfL8GtRbM3DC2ttueHCcr5CQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZSt0YWdAZXhhbXBsZS5jb20iXQ~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 912f3d1fe91b2256ebb705cae8b79d1a\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:399piHDj9wyXGetwB7p20njPlocbDT3e5a80zZyFtS8", + "signature": "0x25ead8002c4cd758bd4928c87acddfd31f3ba58ab4e1a99f5e4cac2f0f9a49a8560d09bb844eb8edd6a03025a3f7fd9c269ee6f70a563faede5cf8205df302081b" + }, + "nonceStore": [ + { + "key": "verifier.example\n912f3d1fe91b2256ebb705cae8b79d1a", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "ok", + "subject": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "issuer": "did:web:issuer.credentials.org" + } + }, + { + "name": "discv-email-subdomain", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiQlF0aGJDQlBQbGlVdjZTYWxLR1lqb1dUM2NSWEotVTRPTEZzaFUzdVRwSSIsIjRwTWFxMVZ4T21lVXlLbkM3eWR4bFFlX2V0Rmk1MFA4QnJRbElyX3FzZVEiXX0.4WlPdyk5Nos62r1m45oIqWGhlBkLbyr-wJikwEPvukF9C4rtnx76CGZ74tGCiZEiuOh1EjDF3MQEi7eeHOhcBQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBzdWIuZXhhbXBsZS5jb20iXQ~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwic3ViLmV4YW1wbGUuY29tIl0~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 59a627efadb949d0e0fc1f5eb7a54cec\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:i4z6MFXCielzYvmOhB0eRbp8-H-VHkNyvWcidJpKDX0", + "signature": "0x20e1f621fbd02b0e29cff5198b889f43de4c49ba562defae9378ba67c212f2de2afa3a21bb724c12a81bcc7b5336de79a6aa8744e492d52dca9923acf5e55e271b" + }, + "nonceStore": [ + { + "key": "verifier.example\n59a627efadb949d0e0fc1f5eb7a54cec", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "ok", + "subject": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "issuer": "did:web:issuer.credentials.org" + } + }, + { + "name": "discv-email-ip-literal", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsibURMeVkyMXJjdWU5N3BmVzRaMzA3Q0RKYjZaVm96UGdMNlhGMkpLZ09lQSIsIjhka2lQSjQ0d3M0dXpVSE53bjE0MUxUb1RsRFU2S0VXTW4xYTZnTFplUTgiXX0.62zDAtFld73iV2eNpU5bPiHF2xr9--EXdziRfFpHyF3WE0lRDfgfowQFoAWB7JHV2uLSARdLLTS_YyjROEB7Aw~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBbMTI3LjAuMC4xXSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiWzEyNy4wLjAuMV0iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: cd4bed9eeb6366a02c1841ff47011adc\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:0JiyqfEe-UIY3wmhHDz8fqNPKMCbHeYzhvbfJU9pCU4", + "signature": "0xe9218c954d3160bc9489baf8c7c61bcf81a5b4bc3ae98902713925df4b0489110d82dacf8ceb14a7bc58563d1963ae87227bda5dc0944a0f5dc50bb844e9559f1b" + }, + "nonceStore": [ + { + "key": "verifier.example\ncd4bed9eeb6366a02c1841ff47011adc", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "ok", + "subject": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "issuer": "did:web:issuer.credentials.org" + } + }, + { + "name": "discv-email-nul-byte", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiM2MzemRqSzQzNHFTckFZM09YMEY2WFF4VnA4T0Y1Ynp6YmNfWFBQVkJ3QSIsIkV0RVNpZGxuSmpoaXBJakNYSlJSNlJqcENmaXMxQ2tIMjN6aWUxWDBGQjgiXX0.ND99bjXpYEA7hPQdk2kPwCTTG0HcTl-ETm43sHd0g_obayQInpHd89-L_JK5Sx1hj_G_UteOWI6rzFTlO5fcBA~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbVx1MDAwMCJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb21cdTAwMDAiXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 6083942c810d628212fc59193e607ac1\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:5WdfMCnGN7U3dMumcS3G3yi9cHy-mtw2xRN1eHLW3ag", + "signature": "0x5cf41cb971c1e9eaa740cc76fbce96dc2de0ea3cf2e3655750fc9946e8924fe24be43a13209cc8c65af8e8105ba8b7c9d103e2808895b30d163f651ebf38eba11c" + }, + "nonceStore": [ + { + "key": "verifier.example\n6083942c810d628212fc59193e607ac1", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-disclosure", + "detail": "bad-disclosure: email is not a canonical lowercase address" + } + }, + { + "name": "discv-email-zero-width-space", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiSXNhaEFRNV9laUpyZEJ6YUtIaG5fN3d4ZE9qaE5jVC1GQ3RTLVZORWljWSIsImN5V2NvUkdydm5aZThnNmlKZXlNbmtQeE1tVDVMeFljc2VDWUtYSUZ1X2MiXX0.C_t5p72OaMl6EJuxkGSjXL1nWxDyatzqhkDYQfdVdLYWi0j9HXpDkBPppj5tX41adP2NkW8v3buNaSu4_fdtBQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbeKAiyJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb23igIsiXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 742f40057ab593280d2de2fd679b8cae\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:BYSDSM68XZEzC5cqE6Nn4STJmojEjBbYX3CILngcGGo", + "signature": "0x75e093081eaf689ca3ddeea2a96be7ad4ebfea56fd94dcf3c9f9a8e8ce6dc2e478b3ba8972b5c35410d846e69de3dc4fd042e2126bc8506322c76387f29d83b01c" + }, + "nonceStore": [ + { + "key": "verifier.example\n742f40057ab593280d2de2fd679b8cae", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-disclosure", + "detail": "bad-disclosure: email must be ASCII" + } + }, + { + "name": "discv-email-cyrillic-a-domain", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsib0JRTTFOSVdPZjdoS1lJaTNSRzQ3S3VpQlhnZVlLR2N4Ql94QzNVN2lvNCIsIldxdWpwY3BXM0FZQmxOWDNzMG9PMkZzd3pUQlhpeTNkQlZJZjFsME9fZVEiXX0.48n364MQ95_NMdXx5W0es_P6_odLKBgM3hSplRC9QUFh23vSWiSxdbV8oxWTWEt_u-2LJRjcGwpLxBW4FKOyCQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleNCwbXBsZS5jb20iXQ~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXjQsG1wbGUuY29tIl0~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 508a4cab02a636373fce43037e223481\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:5rcU9u_-RutMOp-DJZRfzS9CQ_1iKyrJVitUgvLaE2A", + "signature": "0x648db93bd8ae1b9cd92d6d4f94ad5b1ab4f63fe43e7af1c116cff99cca8d27410f7b74baec2f74ab6811b952b4232bc43adf29b78f475d34c1278f8bc57df1e51b" + }, + "nonceStore": [ + { + "key": "verifier.example\n508a4cab02a636373fce43037e223481", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-disclosure", + "detail": "bad-disclosure: email must be ASCII" + } + }, + { + "name": "discv-email-mailto-prefix", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiYkxNYmRYR3poanZ6Wmw0aUN2ZFVZR2dwMndhTnhaYWI4Rk44VEt1ZWxKVSIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.B_lvSu42s2eRGM3_RGqGSDFrMrp760XAgot4p8jzE2DnWmn7bxpEsEvjWMG8TXTa4WEKv_3t15Fg29fC69olDA~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJtYWlsdG86YWxpY2VAZXhhbXBsZS5jb20iXQ~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: cd7b55d752f275a5c76220dbabf12f6c\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:Om9EQSFl_e7u5szAM7LJarJXMr3iz6cxXz1uIEm6R2E", + "signature": "0xc8b3f588d32cfd173545f8f666806f2a78cb45edaa5957170506c8cfe17ee9eb4716601b047729cef210c617c8574a96e74a38f6cbf5a8c9c4cd7f20c1212abf1b" + }, + "nonceStore": [ + { + "key": "verifier.example\ncd7b55d752f275a5c76220dbabf12f6c", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "ok", + "subject": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "issuer": "did:web:issuer.credentials.org" + } + }, + { + "name": "discv-email-double-at", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiVC16WXBTdnI5QXFHZXNRT0V5NjF2QmlnNDVnakg3WkU0U1JadnQ0S1pXNCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.7mFjXVpsAdqYIkEfu4duZQFosIia3kXUloXP5U6075jqGlqW08nhDHNv3EzSBHuOJ8nICC9UXzBkbSgrvnKUBA~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBAZXhhbXBsZS5jb20iXQ~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 185d99cf65faf117e58d361fc613acb5\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:J2wYFjMQMLXggIipgJyGd7guHJ-nPbkFQvALDgxsXWQ", + "signature": "0xdd0f62268577fcc33ed779d8428dec30a61196a9a32255113f39d7f39d5e579d0e0f9af00e7728324c74c360b1cc15d806583d840349cad2e690b6dfbc47dbc61b" + }, + "nonceStore": [ + { + "key": "verifier.example\n185d99cf65faf117e58d361fc613acb5", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-disclosure", + "detail": "bad-disclosure: email is not a canonical lowercase address" + } + }, + { + "name": "discv-email-quoted-local", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOFJldVBQWThvTURhQ01jM2M2N1pMSVJLNXNTWHI0UVBwa1BDczZHbXZJVSIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0._UjN6JCAGftTVN6-kqBkBgzPW1d80ak37b4ovod8fDOuySYPkhJ-MMBB5_GDZHs_2rgMvWqjL78fTo-FpVVjDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJcImFsaWNlXCJAZXhhbXBsZS5jb20iXQ~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: b24c92338dc8268fb978e57c183ac553\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:lPUH0k-pzy7HDOrvoS_t__jMWeuBF9qA9Ml_MhN4pow", + "signature": "0x02951823a57a2f6c5c4df0cdfb74826e66b612240297980ecfa2a6c952f832941165c16d482dfdab75ea215e8ddba7a88d88a23090bf0132d301f1b88e8e03d81b" + }, + "nonceStore": [ + { + "key": "verifier.example\nb24c92338dc8268fb978e57c183ac553", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "ok", + "subject": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "issuer": "did:web:issuer.credentials.org" + } + }, + { + "name": "discv-email-local-65-chars", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsidkNTM0s5M1BIU2VYZEhVM2tqVkxpamd0TDZhdWV0dXBocm1pdmtYSGJhRSIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ZqOt5BCmQtDv0Rzcv3EowMmSsyQ1Un-wjVIEOz39ySsAWqC1jtO5zh5PAIZ6EiFakAjD64l5M6cPSuFN9szcBQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: dfb2e36b4b9da5d98ce78d5504a98261\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:_QG7drvboCrhco8Rc5mYUdGDqhmVGsZoCp2XIGq6LtU", + "signature": "0x5d4e4ab6dbffe673e95ca258484433ea5a660f5861172448188e1505b9b64f870cb26bd04b71d80eba0cecaa46106ffa77ccbe66f5df86686246aecd8d46a3541c" + }, + "nonceStore": [ + { + "key": "verifier.example\ndfb2e36b4b9da5d98ce78d5504a98261", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "ok", + "subject": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "issuer": "did:web:issuer.credentials.org" + } + }, + { + "name": "discv-email-combining-accent", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiRTlTWDVyS3pBcnNVNU1uNlBtSUh4MlpydXBrdTJ6VmplOExkekE5bWRfdyIsIk1GeG1QYnFCMnVrUk1mS3pJY20xS01sb3ZBUjdLeWNiN05WNk11bFZPcjAiXX0.O5hmXgfbDPkAxXcln8teZXn3i4GNbbwwVVCfUf89iNsuCnzhDtm_cWezmpqSqL-vR5t2X7J-l5R8OZ3tfUueDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbcyBIl0~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb23MgSJd~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: dfe63270431fe8982eb67d25a98e36fd\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:CvnoWgM_IChPyHakks0OWXk_eCAb16KMyUl1r9M3wdE", + "signature": "0xd7a424adf917a080b2095e59c882be73142a4bbd7aba3d4658b039106c3eb487604b0ce02f7b1e87ea164c9579c89950291a50b96f41ebe6961f84c61b9721ad1b" + }, + "nonceStore": [ + { + "key": "verifier.example\ndfe63270431fe8982eb67d25a98e36fd", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-disclosure", + "detail": "bad-disclosure: email must be ASCII" + } + }, + { + "name": "discv-email-long-total-255", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiTkdiSzQ2bVlDQ3ZzMGNZQTA0T2lkMjRLdlVsNGVuU0k1WFIyZUZmbmhvbyIsIjBRX2R4UXV2YlRHSnhNNUZKX3BUel9mTDVwMFJjc1NsOU9ZWVI2ZnNfd28iXX0.f0iOQ7q1wF5VI_eb8W32GTgf1iijDrLmMaCBZj2ikdLnqR-pxMc3ky17t04Xg2EG8AlAmrli58kG1m3jSkh2BA~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: f49d30f504c9f88d2bc819eb75b10ae8\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:aMkYUcpJQBlt4-ZRf0fm4Vdg_-21-h3qx_BrAktc7-I", + "signature": "0xfcbceee0f1b5d9d88badccfdbf897c606db68f0c8e3880aa438f1c654a1e8eae6ddde5a5c670462a7b654cd08fb2de7937a5b87a07c816b0dd00db53ca194c3f1b" + }, + "nonceStore": [ + { + "key": "verifier.example\nf49d30f504c9f88d2bc819eb75b10ae8", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "ok", + "subject": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "issuer": "did:web:issuer.credentials.org" + } + }, + { + "name": "discv-domain-upper", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiclcycWxMSlJZZXFKZWRGOWp6Z3ptUlNPRnVjQzRURkJVeENRVmZIZFgzSSIsIko1U3JGdVVuVk8ybkJJRElqLTQ5b2VxVUY3RnI1NWhjUF82Sm5LaGc5UnciXX0.XrZSKEnutw3qse1-joMu_rdzepyhYj70kRi6VnmukokhfIc5VOKa5_PlhhbJIMBl8UHqn6-qVaGKOq0H7N8BCg~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBFWEFNUExFLkNPTSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiRVhBTVBMRS5DT00iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 952af34f5e83ee44adc0f7246d7b745c\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:Uo74C1QUr0YA8sEcilpQYq2aQgUqe1OUXrpVgs8vA2w", + "signature": "0xb5acbf8b3d4e12f2f56df1e867416e11111e3812cc0be7eb1e76da65f7962bcf481e9478ab0de4ed9ad37f1b9d1aa1f89fd897731f82d9f6cf594541ded7972b1b" + }, + "nonceStore": [ + { + "key": "verifier.example\n952af34f5e83ee44adc0f7246d7b745c", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-disclosure", + "detail": "bad-disclosure: email is not a canonical lowercase address" + } + }, + { + "name": "discv-domain-trailing-dot", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsieW9ybDU5UFAwSHNNY1lWTEhBQXZNRWk3YWR3OFBaTEd0LXZmQW90aWxsYyIsIndJVG9qM1VmUFFvbnRvTl9NMXJ4YjVQU0N1UkYycjJIdFdaM3UxSXJaZW8iXX0.7lQQpSiE5QicjuexjgcoNvbCHpbe1xjLGSLYuQRSM89tT_JJOe52fSQj_AsI9AC7mtkyiJXhhIbGxMzBfvWnCA~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbS4iXQ~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20uIl0~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: a6713d68f349350e0b22b72783866b2e\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:ScqlOo1ExEFxmV4TBwC8snEPU5XiqQds0HBrh0_Yr5A", + "signature": "0xf24687d8b3371564a2ca541ceeda625e5553ac19c73234b970f69d92bdddffa8760d70daf2db12260bc9dda8d92d5fd085b600b7883c7bb275c1bbb3020ded191b" + }, + "nonceStore": [ + { + "key": "verifier.example\na6713d68f349350e0b22b72783866b2e", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "ok", + "subject": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "issuer": "did:web:issuer.credentials.org" + } + }, + { + "name": "discv-domain-empty", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiWWYwOUVMeDJaQlFscnJNRUxrM1dVQUlyUjVIUFBnMDBLY3BUaEVQSnhnUSIsImE3RmY2akJ5NldZMm5XQ3JNT3N5WWRzSmxUQjhSYXZJMVlTajZnaDVPaVUiXX0.iuy6tiBLzc56OJyONukNNTVy6T3UaJNOeJb6gCRToiEVPwfWqIZnDcuMNEqNyH13gWoaxIk8ILl1HA7sq5qlDg~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUAiXQ~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiIl0~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 9dce16b52b53e4b39c6e4003b8ace3a5\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:fpGooiTBCPIE3_XoHsKc1vaC5CoubDwhQwjAP-tQYOA", + "signature": "0x7155ff5f4f21434c13eb53c83698157eba5bf0ffcee5ffad335d7994fc309bad41fa6107bc8c4fe1a0025121625fe9421ace1c931462e42e2566cc01cf0411ff1b" + }, + "nonceStore": [ + { + "key": "verifier.example\n9dce16b52b53e4b39c6e4003b8ace3a5", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-disclosure", + "detail": "bad-disclosure: email needs a non-empty local part and domain" + } + }, + { + "name": "discv-domain-wildcard", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiUmlRMmhKM0JvNDh6ckloSVZMRkVaLV9MWmZybUYwTUF4ZklXVzVZLWlNNCIsInhOV0NaOXhRQ2VqOGhHcExiM0hqb1d1RDlVUmZSUHFNMHVyY1RwZkY5cEUiXX0.XrZh5QFncz9JsokvinqNgEdgLQdglIs2b2ibS_rgJ_5JE7c0FeUKWGl2kCbg8yPNgSVxqMlxzGk8NEPW2Us1CA~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUAqLmV4YW1wbGUuY29tIl0~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiKi5leGFtcGxlLmNvbSJd~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 49b2a8247f28db64eb61b5577e5e7671\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:x8J5f4pG9jCh55LhFAddtst5m1uDQdktFOzrPgQ1qt0", + "signature": "0x7df2d6ba8a45cb2e03f872aa4f20f5a58e601c0068923df3ab08a34d443c21be2fc6b48def4fcb9789978c91805e32c9f356024b64379f263dfa3c2ff5b88fd61b" + }, + "nonceStore": [ + { + "key": "verifier.example\n49b2a8247f28db64eb61b5577e5e7671", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "ok", + "subject": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "issuer": "did:web:issuer.credentials.org" + } + }, + { + "name": "discv-domain-idn-umlaut", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsicEVfOGpoMzQwWHhFRHdkMTkxYVdDeUNYYXJTWW9QUU0xa0FWZHhVMDNOVSIsIk1rVEoyRnhZTWV2ZFNORWZJYkJidk11TXZXNkFreUVoSmVoZ2p4RDVhYTQiXX0.UGZfmJLPdL2W0ypPrHLD9jywhZk5mmtCQI6rchElwTsSFIuSypgSdubnWaHnnMsbfHzpSxnwEmIrUw8wpGS3CQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleMOkbXBsZS5jb20iXQ~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXjDpG1wbGUuY29tIl0~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 2b9c39bb23488d5614f05694d8c2681e\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:-dBiCB4TrbRRnxi9O6c7x3FVVoUzBhLFJKJzvW3tNJ0", + "signature": "0xf1644d8ac57050824726d7d1ed74c50b36c700c425cfd4d6cf7490c8ff17e85d4ee795c58bfd11f34aee4c452fec79d7d92c04a6ad12b5366c04e58ce2d7bcb31c" + }, + "nonceStore": [ + { + "key": "verifier.example\n2b9c39bb23488d5614f05694d8c2681e", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-disclosure", + "detail": "bad-disclosure: email must be ASCII" + } + }, + { + "name": "discv-domain-path", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiVHl3dTNoWmtRc2VkR2RNd3hGX0FrcFRGTnNiY1c5RE9rYUZhMXdIZWVxdyIsIlBPbU9FdlZtSVJGd2ttci1QYnctYURsRGV3OXUxTktXOGJGbTcyZnR0bXMiXX0.gzkf9raqLJ3SwwteRo8JMre8ug7nn_5INGcizC6RRSP_TjSk4h96JXhUiUybu_xgNf6p4iKWH_N1L3zJBygbDw~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbS94Il0~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20veCJd~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: f29e0729c7ff5249e878bc1c41ac8201\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:vYiIDOzV8wjLEgie0zhTQ-21_J16UBX4MAIGww8Kdig", + "signature": "0xbd671768270290226fe00b43c198f6a4d1bf687561a6e216211cb9a602cf1c0d54a397b029fe3203b4c9e58dd18d8f3c387c6f630012679d494bbbae24c115a91c" + }, + "nonceStore": [ + { + "key": "verifier.example\nf29e0729c7ff5249e878bc1c41ac8201", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "ok", + "subject": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "issuer": "did:web:issuer.credentials.org" + } + }, + { + "name": "discv-domain-port", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiblpsQnhlX0VKOElQYUx3b0VDT2ZjZHZqOGpYLVh1TXFoXzM4alpBNGY5USIsInpWWC1EaF9TX2xjekVwZjR3ODBOeUlzaU41M09XZ2JKa2V6VllKVWxtb0EiXX0.NXQWFhLyRHuofduP76sLvgMpPXdLYCGXNLfXrjALyBWGuXJWYFD_Qq8vmZUT9D9nevfp9KHXYR0jIxsBLQEvAg~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbTo0NDMiXQ~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb206NDQzIl0~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 98d389a8b43cf67a5bd682e835fd2f35\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:jN8s231tx9XingYdq-shT9WjumzudE0_p0SaunvSCWM", + "signature": "0xecd17ee33929dd27410bb8d599d901a0f20dcc593bcfc49edd5b13b4ba03feb714abdc5724d6a857fd5e4ce3e7924f8822c7c5f162e7376475449822fa4951571b" + }, + "nonceStore": [ + { + "key": "verifier.example\n98d389a8b43cf67a5bd682e835fd2f35", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "ok", + "subject": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "issuer": "did:web:issuer.credentials.org" + } + }, + { + "name": "discv-domain-localhost", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsicUg5b3I3U3NPaWUzOF9WVk5KejB2NG9DTkZnMjZ2Q0JNLXNHd0N5WjZyNCIsIlZlWGM2eUZwRGl0c1dGaEZfaHpVUG9yX2MwZlducUUtcXJ1ZUUwalR4cHMiXX0.OIPLsBzA6ktBfiqhQGpI00jqgzZhMoQMR4A-7RELhlXTBNZBmoKHviD1F6pbOh8usm3fLEXsFf0Zc16XStbdDA~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBsb2NhbGhvc3QiXQ~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwibG9jYWxob3N0Il0~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: dd552daf5bd60a91de40f19d79218370\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:4yyXT5f6CKutpm8HvRLlXTf0qCZu7wN62n52Q1GwKco", + "signature": "0x436ae12cd8d840bb36c2518796695e2164ba492e618dcd7c97a8a113e8397e0f1d00512ac9845941a37d07a094aa5a2b8caf0f99f346622b7f2ba56b6a1fbf6a1b" + }, + "nonceStore": [ + { + "key": "verifier.example\ndd552daf5bd60a91de40f19d79218370", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "ok", + "subject": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "issuer": "did:web:issuer.credentials.org" + } + }, + { + "name": "discv-domain-ipv4", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiMDJpWHlMWnNOSmhBeFhGeTVneFV3eXdqQkFHTjU5ZVZRMm9wRFZTMXFBZyIsIkJpT1RGT2RWNTh3aHpveVpKLUZQRkdQUTBUVXNUYVBYY0U4b2wtTVlaTzgiXX0.ItVyhPtyS8kVGTn9E5VNKEnLUixhNt_00asvA_WZVjGlaQ769VMBJ5KhHg8fBiBiIS481GKxLTk6sOTfpbnlCg~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUAxOTIuMTY4LjAuMSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiMTkyLjE2OC4wLjEiXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: f1c8c2d3cbdf57de32d1e12d324ca085\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:DU-0h1XWHAHQfvmjew1blH3se7a2EDcKobLe6HT8S6c", + "signature": "0x903bf0ca21d2f14cb85bfa3eff9c3321ae553ca9d631523f9abc2c9de7b7c59d1efbd16e778fd0a14b48a971414b3f53cbd1e5b834b04f5c56f562f6d46a9b631c" + }, + "nonceStore": [ + { + "key": "verifier.example\nf1c8c2d3cbdf57de32d1e12d324ca085", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "ok", + "subject": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "issuer": "did:web:issuer.credentials.org" + } + }, + { + "name": "discv-domain-single-label", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiU085RFdsZHJmTXRhSURtaC1fa3AzRnRqa3hIMjZJNTJHRGZMQUJfVUc3ZyIsIjVvZl9vZEF3SnBnNktuaXpRN3gtZGl5cTZOZ1BIRWgtVy0zWDNvTnBoSUUiXX0.KIkl-PbtxgGNzkYJKoWfLmrcibcZf6wtxt0E6tqlUv4LIDlkVyl1h25OCPr6aWPamVyQ2RvP-vKO6Ib-leZXBQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlIl0~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZSJd~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 8f5ed3e80e47260736dd0530bd21e041\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:MpnJDXFr8CK0dQXf9xul2IFn7ve3g2G2NFUVIHfrwmo", + "signature": "0x424de24f48ff7c37356c6c6baa0b430cbc315aeb7c06e798aec1b738f45e665625f153c522362010fb17108c083cc0321ad2876da264cb2f3a1c0df7a7c39b681b" + }, + "nonceStore": [ + { + "key": "verifier.example\n8f5ed3e80e47260736dd0530bd21e041", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "ok", + "subject": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "issuer": "did:web:issuer.credentials.org" + } + }, + { + "name": "discv-domain-trailing-space", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiV1BMMm4wczFSZVdsc3Y5dTFWdU1td0VnbEFnd3JfaTk1T1l4M1ZwMGF5TSIsIlFMc2FOWUxUVTJUbG9YZXZ2NldxdnI2dUxSTXB4eEdoRlo0Rnp1NlNkODAiXX0.TiQ2yVrxFWvFvZZGYr08WVBr7jomOOvOOseGH27Snn-gG4s5s8OKXhZeN82vnTKZO7lMi_sbIBT4YW4LrcF4Bg~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSAiXQ~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20gIl0~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 4992b6fae8ca90cb2d4a3686cb6e9b8b\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:Zh1hhBmuQBLXRyl5XK2Wsz1MShKLQskz4vMFf0XQPvw", + "signature": "0xbceb18f3413ad356a36eba48927b8ed7f31e5089ba2eb28a21a9754d201744487d85e056c1cd484a6b3b99c060a1f76ce64ed577f87bb199a3b71c0eca3764111b" + }, + "nonceStore": [ + { + "key": "verifier.example\n4992b6fae8ca90cb2d4a3686cb6e9b8b", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-disclosure", + "detail": "bad-disclosure: email is not a canonical lowercase address" + } + }, + { + "name": "discv-domain-punycode", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsidmNwT1FHOHkzcThoYmFRZERCNU5ZVWQxMnFDZHlLUV85YklaSThQNEJSdyIsImhfeGRDSGlXVzUwdHR1SnI2VF9IQXk4QWY1RmNaSU9lU0JLQjB1MnFpN1UiXX0.WH2Pf4KAHAfa0LPXsK7Hc4riEtsjHPSZEhBk6K3BHc-yE63C4vq6HE5Qtd8X1Vbh0WIRJsZs6RJNiR8TmP1zBA~WyJzYWx0LWVtYWlsIiwiZW1haWwiLCJhbGljZUB4bi0tZXhhbXBsZS5jb20iXQ~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwieG4tLWV4YW1wbGUuY29tIl0~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 50506e6319d4593cbe9c6b6f461680f5\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:YTvpgb6-GBMYFqF2JClVqzjMqyUGI5n-JrwJQ5h_dhM", + "signature": "0x1c7a727393ca892e13bc931dd7b7cc560e11fd37d4c615a5ed9e95402d1125f72099ae6710af02c1d8e88da9a2618dfc8d1b3a1f29494b6053329823cca6b8ab1b" + }, + "nonceStore": [ + { + "key": "verifier.example\n50506e6319d4593cbe9c6b6f461680f5", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "ok", + "subject": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "issuer": "did:web:issuer.credentials.org" + } + }, + { + "name": "discv-salt-one-char", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiVzlwV25iZGZmd1lOTnY2TVhzcmRPT2dzVHBZMWJQa3V2bWdyQ280d0FITSIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.RA9nqm3iQK622q34HK-c9szOH8UGj57WVahk6-c_aVP-GwgvliYSQRd3G0egtYtJO9rdYTNOZI7meK2hTITHAw~WyJhIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 684738db554d4c46b2d56822c6bf5d9d\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:7nhzgTSyZtv1eY6Hz8o92IECqDnUjCTvJ3w3xrnIvfo", + "signature": "0xa5935af95bb3af3626057f6eb44c1026d377d4adfcb894e45eb95a27a85cbb3e021e6df1c87a36e3b2bf2fe88d0271ebfba08c73d97dc97993bf19dffd55b20b1b" + }, + "nonceStore": [ + { + "key": "verifier.example\n684738db554d4c46b2d56822c6bf5d9d", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "ok", + "subject": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "issuer": "did:web:issuer.credentials.org" + } + }, + { + "name": "discv-salt-non-ascii", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiOFhKSHlRUU5UXzZIM0s0TFFxWnBSZy0xR3hGYjVpV0VvdHE4UWo1dW9PWSIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.-G4rm4aH8FkhuQIoV861JaCYazyiW55D-ZY2UITEMdcaYa1aQN3pZrZiFi8-SbbwF42o_I1y_GHIfaQsdsLxAA~WyLDqSIsImVtYWlsIiwiYWxpY2VAZXhhbXBsZS5jb20iXQ~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 9f83c68c8f246523daeb1b1b3f38a429\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:sBIEnB_S31ubLl9DOStj3d820pB-kZmC_oj2oclUlXk", + "signature": "0x79dc8a5ff809b3c949fdca03bf76fb50afc5391db4658767196f51b2c10082894c56145caac6fd61d0944d9a6d39a93d8a3e9615b3b3974e66aa344b0e508fec1b" + }, + "nonceStore": [ + { + "key": "verifier.example\n9f83c68c8f246523daeb1b1b3f38a429", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "ok", + "subject": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "issuer": "did:web:issuer.credentials.org" + } + }, + { + "name": "discv-salt-long-128", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsidFYwSHZXNDlSVGdrNjNURl8wSXJWNDVVWHpMQXNYLS00MG1sNlMxcXB6RSIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.A-BADJkBOY3TY4TYiU0Qy0gvnMP_MO1a7qpV8OGyZKu-68buLO5GsxeoEvRZv4s6H5-odC5yyhn8mxdYSp3FBQ~WyJ4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eCIsImVtYWlsIiwiYWxpY2VAZXhhbXBsZS5jb20iXQ~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: d3298ff0d8fd8542bfe22328c40b8bd7\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:uEZKzS8SBcBurJqyTS-Y0v7cl5SdZbac5JF_c-mbrD8", + "signature": "0x9be00d86ad68d9ce283c14b6c28dcc2e8093c49bcad69d1fba629c457bc782fa16769f41ec0df9dfefb9b5152b0d5185d18b05b5d6727ded493677fd1302e6ec1b" + }, + "nonceStore": [ + { + "key": "verifier.example\nd3298ff0d8fd8542bfe22328c40b8bd7", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "ok", + "subject": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "issuer": "did:web:issuer.credentials.org" + } + }, + { + "name": "discv-salt-padded-looking", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiSXUzSFMyelY0YW00aFFieHFhb1R1SnVGR3ZYbXo1bzZCcy1aWm93ZzlzZyIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.SVAh5nyMyp_bRo2kPpi-v_MFzLY2kFKTylO7ZGsQw0hyroZAKtaQyDGDM_1vrwy9mralkQt97A3q63aIDKdHCw~WyJjMkZzZEE9PSIsImVtYWlsIiwiYWxpY2VAZXhhbXBsZS5jb20iXQ~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 39aa1127c8b0a6e119572c28b0e45fb2\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:yK9OQkGanFbVViatmivSysJBvfFFchmK2mHpMoVc2yM", + "signature": "0x7c4064992005ee10596e4608790d6f88736ce856a7aacc8ee368a6d23b070887277bf523e53ad01a4d09d24e21dfed80acd10d1c6a038249b900f6823b9b9ba01b" + }, + "nonceStore": [ + { + "key": "verifier.example\n39aa1127c8b0a6e119572c28b0e45fb2", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "ok", + "subject": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "issuer": "did:web:issuer.credentials.org" + } + }, + { + "name": "discv-salt-space", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiSWdmcTQwWjlFWFRrTHNDWmM3V0ZremFfa0ZCYWRmd2ZqM0gxS3o2eTdpOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.6zE3FQ8BtL2y6bUOr5VlULZn-_uhuBgl5XO5g6WOrPZ0a-xMOK-mZ-vs-kHrnVwhdanog7E9K6MaEXO3_BKOBQ~WyJzYWx0IHdpdGggc3BhY2UiLCJlbWFpbCIsImFsaWNlQGV4YW1wbGUuY29tIl0~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: c6b802d839b435a2a92bc1cabc464e98\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:xlVNFj4ZdAzjeRMPe8xusZ2vacdXX2pQGz4VwB-YPXI", + "signature": "0x019053d17dfc3b37a5a4ec8b090f00992d96a4a44ccb31e069926c5c810f386e0084ea45a4aa01bc22bc5d5dedca29b0e597a084e980e66af28757c7dfb3db7e1b" + }, + "nonceStore": [ + { + "key": "verifier.example\nc6b802d839b435a2a92bc1cabc464e98", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "ok", + "subject": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "issuer": "did:web:issuer.credentials.org" + } + }, + { + "name": "discv-salt-zero", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiR190RjJNanB4UVJMbkZETjctMUVWSVlUakNkb3dZemhLckhFNHlLb1duTSIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.G2GeAJiv1upCwWAQeo59dZMpT2Um4dLsrfXOP3PqTdqXOLpcwiTlZCiVSQ2xatGYbrVCIEKhGZHZrxUcr5_JAA~WyIwIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 03fbf58e5108de440932dfa1ed368533\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:-IrH1kzLdvuONyWykVJ2FvFnaxrL0cLKK7OI2Lxnbdc", + "signature": "0x78439e895bf741e527009b7862e8edba028ba76f231926bc00c8aea95c888df90bb784a499da87093cedeb9bffe6c84656794190a1341cb534d5ca6ade8cdf751c" + }, + "nonceStore": [ + { + "key": "verifier.example\n03fbf58e5108de440932dfa1ed368533", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "ok", + "subject": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "issuer": "did:web:issuer.credentials.org" + } + }, + { + "name": "discv-salt-newline", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiSU9RWVdJNlZMNTRWWUIwbm9zR2dpTHBpMGtuOVh1cEU0T21wcE4xSzdHUSIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.gRKMH7PcXSoMDP0tYbpBLzV1Wva1KtxaOAPSnTBaMZPDtlU1dNpe_OdMxwQbcK7jgsZlHsLvMJelo03QSwC9CA~WyJzYWx0XG4iLCJlbWFpbCIsImFsaWNlQGV4YW1wbGUuY29tIl0~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 641ae2b25ff85fd40f9945a0f2af89ee\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:4blSHjNoDR9URUE-xoLjUPnrKgyfOYPPV2cQTT3m-Dk", + "signature": "0xaeeb38ee58f445047ad56fa19c82187e413b618e1cd7d5557708f09c734c29ac7709f7357da3540a2507d160e935fa9c187ae14196d7685e6d180b748872a6921b" + }, + "nonceStore": [ + { + "key": "verifier.example\n641ae2b25ff85fd40f9945a0f2af89ee", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "ok", + "subject": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "issuer": "did:web:issuer.credentials.org" + } + }, + { + "name": "discv-salt-quote", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsidm1VbFVwb2t4VUhXYUxOamVMRFItSm9sMlVGQ3g4QU15VU9FRG5CbnZNUSIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.niFfwxnaq9Ap-8-J69ymzzIDPW6ABIq_456p_Q5AiEWA9cCtjfdfJXaafIarD3959bI152Rn1k82ghKNnB8uAw~WyJzYWx0XCIiLCJlbWFpbCIsImFsaWNlQGV4YW1wbGUuY29tIl0~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 1ca579550db7e397948f094165a5f88f\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:ZwdgWyI8Kh6V84ZpwI-jwpq87lW-xIBKPucbk15dGCI", + "signature": "0x08815d55c070e2754b61f506ec0d92f94f1b2f80a7430ee0127f2bb70230039e2a04102f0f3a9af5561b4275ac927694bfed4db1dfc500228fad4ce5176a29901c" + }, + "nonceStore": [ + { + "key": "verifier.example\n1ca579550db7e397948f094165a5f88f", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "ok", + "subject": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "issuer": "did:web:issuer.credentials.org" + } + }, + { + "name": "discv-name-capital", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsib3ViTjRtLTJUbjZHR2d2OFNZQmdVWkhFYXoxSndiRGVSTU02SVRaajI0QSIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.gxBgBVq6XXAyJyJV7dW_qu2dcOxMC1BnV_5c5eNPJS5G5SEkXwiI54TZB2NHGoFEioLvq7C7MeUHndwJSdeiCw~WyJzYWx0LWVtYWlsIiwiRW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 3170fbee96af916160e799fde977c4dd\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:XCvZdI6W-eDknGkLufE3i_xS7-CKoBjN1LD97xwM1wY", + "signature": "0xf3402adf020ce6c2479152a41ca1fcc1c11981d0fed19a55bb048d2462e049c319ccc51f154622482e803d1538c865abedf03e0a0ba2aeb06a3a5a99f02dc5ef1c" + }, + "nonceStore": [ + { + "key": "verifier.example\n3170fbee96af916160e799fde977c4dd", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-disclosure", + "detail": "bad-disclosure: claim is not disclosable for this profile" + } + }, + { + "name": "discv-name-trailing-space", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiTkpDd1JOc21BQ1JLeGpsYjVhcEhLcGVFcmd0N182bkhOYVRCaUNPdTV6YyIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.jGMl-eWvmzyHBWb89uXobA3m8UST7Oq1kIXboVBkvt0MeI5TgZ3IGtqZjZonBJASI0rxtgY8zZF33lUImLLOBQ~WyJzYWx0LWVtYWlsIiwiZW1haWwgIiwiYWxpY2VAZXhhbXBsZS5jb20iXQ~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 4c9fec11b44a718324610d4ad5c5a387\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:oVMsm1TWoC2c0GwUVWlkR0zFer02-F8mrx2cTjlgqig", + "signature": "0xe7fe89a2cd84873ac3d443ba5e18d19392661dd7b150df7ee21a90de9848764f1175cc59de3f03626838619abe8467ac3ba3f1ca66eac859a70402471470824c1b" + }, + "nonceStore": [ + { + "key": "verifier.example\n4c9fec11b44a718324610d4ad5c5a387", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-disclosure", + "detail": "bad-disclosure: claim is not disclosable for this profile" + } + }, + { + "name": "discv-name-hyphen", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiRGgzZG9kc05QS0V0eVI4cXY5T0xZNnRHQkxfZUNjT1cyN0J0OGdYb2ZfSSIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.8s2HRti3uzoQD8f4mNikX_rCzotxQD-W9pkIQafgrFL9tOoEPpDk32TfvzZG0PZEOLqOoD2Xba-UWQhOKtgcDA~WyJzYWx0LWVtYWlsIiwiZS1tYWlsIiwiYWxpY2VAZXhhbXBsZS5jb20iXQ~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: c8c98e44c53ebe980f42f65c543d18f0\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:K9_XmF0KA5QnEpVy1UDlpQhuIVOftfEAiAT4fd75Nys", + "signature": "0xc0e651ee512c9653977ffb3972bfffb4b073c90f9cf2b7c6d73dfaada8a27b3737eda1d87ca15f6e93bdbc93c3d8b57a824d438913714cad8371ffc45e4045211b" + }, + "nonceStore": [ + { + "key": "verifier.example\nc8c98e44c53ebe980f42f65c543d18f0", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-disclosure", + "detail": "bad-disclosure: claim is not disclosable for this profile" + } + }, + { + "name": "discv-name-proto", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsid2JiTHIxWTR2R2lwU0s4Y3YtZ3BfRE9GbmwwcGltbGV5emhWOG9xTXZlWSIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.17hga2Fy67AoFyDkm_ehewB4tCyMD1IRVMuJC62djazr9iGIEgsqfZAh0fU8g4fnSOvmiLsAG4T0PD1aJYnRDQ~WyJzYWx0LWVtYWlsIiwiX19wcm90b19fIiwiYWxpY2VAZXhhbXBsZS5jb20iXQ~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: f99ec918d2f9a74ff0fc9fab1bdb8d75\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:SbiEVbP2UV0WbEoZmCl2DW34A4-ZMhi4EmLMhmaGYhs", + "signature": "0xcaa86f80551e8ff603fccf96dfa8f45c22ab3ebfb5d11523cd4ffb8f51a2a67516e7bbd42bed6d0f13931e6c381334a693c4fd3ec9b2961ff2858f2f864fdcb61c" + }, + "nonceStore": [ + { + "key": "verifier.example\nf99ec918d2f9a74ff0fc9fab1bdb8d75", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-disclosure", + "detail": "bad-disclosure: claim is not disclosable for this profile" + } + }, + { + "name": "discv-name-constructor", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsidlB2VWg0QkZlbl9tUkVJWFdWblloSVF1WjhpSXRPV0k0U0VJMHJFT2p6NCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.xVRsm2m-0qjKCRfkQiF4AvaOJOFqiFsu1GtdoMaE92lmytU0bugx_u9-8zPd0MWpQ4YLpngtweRoLexvL1q2Cw~WyJzYWx0LWVtYWlsIiwiY29uc3RydWN0b3IiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 82938cdafee2dc6b202ced9a1d0341e2\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:d7na4V36uYMP_1PQ_mTW1lZV9ygjd9kTAaiDNy_1Cy4", + "signature": "0x4c2976b32c66a834d9d4dc25f287c548bd4e7efe29c7ca66bc39ee1a8074787d10084dbbefa72809551ce05dad48b830c680b2e34a6c155dc060392ad612bd411b" + }, + "nonceStore": [ + { + "key": "verifier.example\n82938cdafee2dc6b202ced9a1d0341e2", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-disclosure", + "detail": "bad-disclosure: claim is not disclosable for this profile" + } + }, + { + "name": "discv-name-to-string", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsielAzX1BaazQ4MkROZkMxVlRvVEl2eGFWUXdMczBtQjB1NjJITzdjVGltQSIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ycCDfqW22FmLdgsdy28vCwHDhKGaunPcP6wADEGZnN0xqFOwLX1--byeKPJl425eew961Kf04lzVy1AFlC4FCg~WyJzYWx0LWVtYWlsIiwidG9TdHJpbmciLCJhbGljZUBleGFtcGxlLmNvbSJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 166bd15db668ed727a09cda9577441b5\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:30n7fctxmmtark1i9doqvVCcCc_Dr-2BS56YfXlZBOY", + "signature": "0xefd7c20381430ef9159d0c3575f6a81e75c680fbe4000e07776254e8b0d92bc83fdc262ad762b475cd8f79c4a329ec86c09969b073231d3b266168d3115310501c" + }, + "nonceStore": [ + { + "key": "verifier.example\n166bd15db668ed727a09cda9577441b5", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-disclosure", + "detail": "bad-disclosure: claim is not disclosable for this profile" + } + }, + { + "name": "discv-name-sd-reserved", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiTGo2Mm5ZT2Rud25WdWlMeVdTdmx3b2Y1Uk5UaGFlck9lS04xOG9nenZjMCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.1ZqJwbchdFFezJavkodCJ-tTDjpCFRxmU4cGPhoHgtn3Rz06Nztg1xCeO-BRIDUIfGZeG-vXDtwvoQlJvZ_sDg~WyJzYWx0LWVtYWlsIiwiX3NkIiwiYWxpY2VAZXhhbXBsZS5jb20iXQ~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 0e4119e55566830d30e5f245a40a8873\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:VYz_b3QM2793ANuEtZ2aEPnKoeJk7Ju7UjxNtf-_HZ4", + "signature": "0x5da69a9e172b3c2d5a15c3426e61bd85df43408dd62291df3c8a82438c7cbe1d2c2478d52eb8649c803e4a4ade89ea8183553a759b7110445fab7027961921081c" + }, + "nonceStore": [ + { + "key": "verifier.example\n0e4119e55566830d30e5f245a40a8873", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-disclosure", + "detail": "bad-disclosure: claim name collides with a signed claim" + } + }, + { + "name": "discv-name-domain-trailing-space", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiTFVhUUYxOGtqZ3dLd0RQVGI4ZHNkQ3FNUDhSUzZHU1plcl9ZOGU5TUdjcyIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.pBGGUOsDkfzB6T7t-TmwBRpPoemAtH9eFPn6hxuPkuUZFfapMt84HoiKzJwIBrWntJdh2LYgQ1gn7cL_dEOtDQ~WyJzYWx0LWVtYWlsIiwiZW1haWxEb21haW4gIiwiYWxpY2VAZXhhbXBsZS5jb20iXQ~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: a62a61f81ff5f0da4d256d2bb0553ba9\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:L9GKqLSbFIPTxDgj3xA5uZgToF5Ew8mzyIICb02AFmE", + "signature": "0xe786f9772da075080f8511f7b7ceb203ec71f44a9378d5f7c20333726e685c660549b0002b778c7fca4b2bf709c1fc660d8035154a1195dd04bc14fdc9b22a651c" + }, + "nonceStore": [ + { + "key": "verifier.example\na62a61f81ff5f0da4d256d2bb0553ba9", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-disclosure", + "detail": "bad-disclosure: claim is not disclosable for this profile" + } + }, + { + "name": "discv-value-null", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsidEdZdHc1dERwc05uYjE1b1dnU3Z4dnlVRV9GNTMzLVNNREJnbjJTMmFiTSIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.WG3aDarfPs2cGG1u19_ICljFoK1rggBUHZV671Hv4GMKKn8GN5JWYm9DvrYaIzEMHjME7BGWsO9G3Jl7hPFrBg~WyJzYWx0LWVtYWlsIiwiZW1haWwiLG51bGxd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 2493798a0cf6089b8035fdec61bb9f34\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:jBUzzvdXTwEdY84vB9JtY3ZA7c1nZabrcK_d5HbrP5w", + "signature": "0xa5a22067dbd9936ddd1da47d80449330659125d6a038f6cd8baf5fcc7973b15544ccc1bcf0fe57d3af8b209defe767dcfa10bb7ce5910483114f0b662f89647d1c" + }, + "nonceStore": [ + { + "key": "verifier.example\n2493798a0cf6089b8035fdec61bb9f34", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-disclosure", + "detail": "bad-disclosure: disclosed value must be a string (no nested _sd or array elements)" + } + }, + { + "name": "discv-value-true", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiazgyMVZZTWdocXd1ZklReVhOSFFXNkdvU2VJdFJsSTVnVmM1NUtqMlU1NCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.a5aE-AbQTFK0if8rUEyuImHO5wxYVHTcFWuo2nWS9-mwAiTGIwKvw2Fc78k2KWTd94nKPVVA-ZUR8cgt7aG5CA~WyJzYWx0LWVtYWlsIiwiZW1haWwiLHRydWVd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: e877f7566aeea428a7be39c1e067cc19\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:06a-vUA8qAB7sFRw_i4nwdfkSIhPt62nPNkd8xs9JMU", + "signature": "0x1f8783f943c30dba79057e02c44a2c24facfd47eedcb6a9ef4189a34d2c0fa2e6c3ee49f4207fc54fc5e139072eb50f2d317e624fd36c154d8b35e96083c35841c" + }, + "nonceStore": [ + { + "key": "verifier.example\ne877f7566aeea428a7be39c1e067cc19", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-disclosure", + "detail": "bad-disclosure: disclosed value must be a string (no nested _sd or array elements)" + } + }, + { + "name": "discv-value-false", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiZGQ4UFd2c2h3QnVEeGVYYWhuNmRqQW9jTkVBOUZDNUJYaWtFVTRtNnFaTSIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.a4RDasRat7MD-y-U1CdAAtykybj41rAyucHiiGjx3WoY_6pCABkSXk1eT-nBV8aEVrLPBg1uMp0EBklGeCxNAA~WyJzYWx0LWVtYWlsIiwiZW1haWwiLGZhbHNlXQ~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 94f8685f6cacbed61bf48353d116ecc3\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:T6vn2FJegq1SOtXHzyMFY8ee_IaQeqYkCuWczKfW57w", + "signature": "0xd956498c7f369b547ded85353b809ea4b57e62fc81496684674b635cbe64dd501385ecdf046717840688ce38a07a2976347b52ea0c4fd33e532111a5272d54771c" + }, + "nonceStore": [ + { + "key": "verifier.example\n94f8685f6cacbed61bf48353d116ecc3", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-disclosure", + "detail": "bad-disclosure: disclosed value must be a string (no nested _sd or array elements)" + } + }, + { + "name": "discv-value-empty-object", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiWGZwcy1UQm1SMjlWOEtiNzdoekhnOU91T2xkdGxKT2xUdkVITFN5QWdmdyIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.oWHm1zLWKrFZ5fbLYo4lwq7bsX4q74yBlNC5WzHCnOscK7iYF8qKwuK69556zRqcgbT1UrKRnDNwTi-l-o_zAQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLHt9XQ~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 6aba42da47d59b34cd1f8cc31ecddb22\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:TBuu6n9re6Nu8heva8s3M1hGgX_Y96FnOJ-OpONFL5M", + "signature": "0xc7016490aa397afaf49b99c71d1ce8991ec240be590b89b50b5926ef8c7197ff317895b29c615b3b8d665e17bc234db768e2cdc3e0a96e2a3d28e05e417bca0f1c" + }, + "nonceStore": [ + { + "key": "verifier.example\n6aba42da47d59b34cd1f8cc31ecddb22", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-disclosure", + "detail": "bad-disclosure: disclosed value must be a string (no nested _sd or array elements)" + } + }, + { + "name": "discv-value-empty-array", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiTGYxN0hTUmRhcUlFN0hDc3pBaDY3czhUeW1CY3dfSnRuMExkZzlZY2hOMCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.hm0uqaASTA9WDodC4sBMvyLhq8NLkmvZEWaDM_pSFSgpxRiLnF4CdaivgJSbcxvZSlh6EXbda1OsDoCCuXLoAA~WyJzYWx0LWVtYWlsIiwiZW1haWwiLFtdXQ~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 0b681c548edc3b9199a3ac74bb2b577a\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:u6zoXzdGgDEWKA279X27TigSn5iVQ-BEwm_NDLlsGF8", + "signature": "0x75d4a642428ad5e007af7ef7bba9e41e798b020183c4bcc65e3013b6b6c89eb50db3a9a96f52207a2492e86364bca23f1c0b48de00478b77f4a40b789dc120431b" + }, + "nonceStore": [ + { + "key": "verifier.example\n0b681c548edc3b9199a3ac74bb2b577a", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-disclosure", + "detail": "bad-disclosure: disclosed value must be a string (no nested _sd or array elements)" + } + }, + { + "name": "discv-value-zero", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiSko2UTZaMTJ0cGdWTFJNcEQzc1d4aUhtcnJrSFZfcnhGSll6c1hUd1M3ZyIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0._10Ob9-egx8XzyHXUGYR_aXaZSM-l7GTFr6ojumoELGQdakHtHnFqvrEKEIZxMU70FmO7VzsQ4FDWL0h0wSXAg~WyJzYWx0LWVtYWlsIiwiZW1haWwiLDBd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: ae564a3c0aad6ac57c9e365a25352b5c\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:DFJRuEqYKaNlEqsTOIwJM4QFlcHipBftPcFkm2XqX2g", + "signature": "0x9022aa7ebf325380e16e87193c8270dbc47f66f0629f3c7399fdc18056977d940e08949c2882346f5e937e17961003abba1e1b588a2e6ba405166020b9cf17bc1c" + }, + "nonceStore": [ + { + "key": "verifier.example\nae564a3c0aad6ac57c9e365a25352b5c", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-disclosure", + "detail": "bad-disclosure: disclosed value must be a string (no nested _sd or array elements)" + } + }, + { + "name": "discv-value-negative", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiX19JX3JfcFZPaFUxeEw4YzAzdk01WlJiVmpQbUNsRXdKZVRlVVF1NGxkMCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.IFxibSskCXBIUb5W97XhZ7TbN_ZVmekhXEMAgdN6y05L0ss7JgSn_5UB13CMwRpMkQuG23gjl6QZexMvbplJDQ~WyJzYWx0LWVtYWlsIiwiZW1haWwiLC0xXQ~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 0f2c9ce618b2cf7cb0d87db2053badc9\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:07q9AOK1wwbI8dRkrY8z_kwoXeZucVMU6ElWXuVO6cA", + "signature": "0x9c2e56606b4fbecd0af028bf242307e1dba5c024a795e27972c09849484af0ce3e1647f31aec571ac3b8d2bbf4c458358a53dcb75e378389559f6b581ed00b2c1c" + }, + "nonceStore": [ + { + "key": "verifier.example\n0f2c9ce618b2cf7cb0d87db2053badc9", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-disclosure", + "detail": "bad-disclosure: disclosed value must be a string (no nested _sd or array elements)" + } + }, + { + "name": "discv-value-fraction", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiUWhzRTJYUDluOXotcEsyYTdoa29iWDN2WWRLLVNGNHNXOTVCZkh0N245NCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.1pWeYFFQjffL--uqGrhxdGQfuO654rJ_ActKPHXr4tru_XHoBAkRxaWm83zDnwvBClznvPPRJxw_AEhF7_PvDA~WyJzYWx0LWVtYWlsIiwiZW1haWwiLDEuNV0~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 3816e7ce02b1cb975646765c94fc3850\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:yhmWhc4msAgrXfS4cQb66_FDGsR2UW6WjpANBQYbj3c", + "signature": "0x13fb173c5d80f3b3eb17d190f0bb3275acdb1d196c255bb4b67e8b30cd89435277674d152a0c5cb57723d22cd69d47b9f3fa374417f956ddaa5dc723db42776c1c" + }, + "nonceStore": [ + { + "key": "verifier.example\n3816e7ce02b1cb975646765c94fc3850", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-disclosure", + "detail": "bad-disclosure: invalid JSON: unexpected token" + } + }, + { + "name": "discv-value-exponent", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiWVNWMDQyVjRvSHBvTk83elprWjVfV0lDRmk2ZTdfWG9hWlBRN05UMnY5WSIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.O7hJ9EI7f7IJ4HkOpw17SiDz8QC1mfzYIj8c12ecGkzDFyZHx1t1iSFtDa6zExNVAqWrhR_7UR2y5GmfxWK0AA~WyJzYWx0LWVtYWlsIiwiZW1haWwiLDFlKzIxXQ~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 097ac01c99ecfb7c4413b7a3a67f3b4a\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:E9_z-8FCtqD1z6Uk3J6rn_6oB9LELc3LfdFeZITjXxs", + "signature": "0x6b2595afa077186332609e9b21b10997a7c0956ec456c5e399469c0d9cb26aa215ed0d5db0582310dc7d368a98f7c4b06e56bc43135b79b756ec08bba63d93261b" + }, + "nonceStore": [ + { + "key": "verifier.example\n097ac01c99ecfb7c4413b7a3a67f3b4a", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-disclosure", + "detail": "bad-disclosure: invalid JSON: unexpected token" + } + }, + { + "name": "discv-value-nested-object", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiZGRKMVlkNVc2NDZxZURnVFZhTDhXRTM3SGhPdzloeG9QNi1ReFVVNy1WNCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.ZyXylO2gdbJW89CjwJq-Yv4aMQcg2OLXf58e1IFUDDu8SgyX7OGjRs0ikZWyjVzRBG4Pt5X1dpjxY2ODpkWOBw~WyJzYWx0LWVtYWlsIiwiZW1haWwiLHsiZW1haWwiOiJhbGljZUBleGFtcGxlLmNvbSJ9XQ~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 1513c2d257534d8319d21006b8be9e88\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:ENQAVUYHlkgH9dFIfJ94bk-Qa8cdsl-i5mjtdBKxtb8", + "signature": "0x82729e865867264144071fc93b6cf091bc5ed58f0887894638fa28afc8938deb436fc20cb838f4d9d7a61585136cec4346a196d46bb77f810c75da363bf7289a1b" + }, + "nonceStore": [ + { + "key": "verifier.example\n1513c2d257534d8319d21006b8be9e88", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-disclosure", + "detail": "bad-disclosure: disclosed value must be a string (no nested _sd or array elements)" + } + }, + { + "name": "discv-value-array-of-string", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsiQXUzeEcwdl9zSmlQWE1LeWpza1d6MDlrTlIzZjl2eGx4R0hUd3RDR2t3dyIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.VhHjvCY9mhbCIdgwZfDntBnEc0M6UKJob9FYZdQhdl_RipNaWJ-tsbZ09jy0gQteq_GGmKbW3Vqs6BRtj3OrCg~WyJzYWx0LWVtYWlsIiwiZW1haWwiLFsiYWxpY2VAZXhhbXBsZS5jb20iXV0~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 29692350bd938ffed84dbceae8a907d1\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:PB8a1znBEJSg60llWQJv_qxXZWmQcXUvxEvKE6UY_g8", + "signature": "0x81abb62a9ff3931d5c297d533559e9f6537730909aec026d6f54473aec35228223e343bb6b254175faa6f4426b6417bef3393fe28a31137cd9b9438a163bfbf91c" + }, + "nonceStore": [ + { + "key": "verifier.example\n29692350bd938ffed84dbceae8a907d1", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-disclosure", + "detail": "bad-disclosure: disclosed value must be a string (no nested _sd or array elements)" + } + }, + { + "name": "discv-value-large-int", + "policy": { + "now": "2026-01-01T01:00:00Z", + "caller": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "audience": "verifier.example", + "issuers": [ + { + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#k1", + "alg": "EdDSA", + "publicKey": "JMOklPoimWJmRLllqRMtp5z-ZxUf3ELeYAzwkJfbgkc", + "vcts": [ + "opencredentials.email/v1" + ], + "profiles": [ + "tinycloud.email-held/v1" + ], + "notBefore": "2025-01-01T00:00:00Z", + "retiredAt": null, + "notAfter": null + } + ], + "acceptedIssuers": [ + { + "issuerDid": "did:web:issuer.credentials.org" + } + ], + "acceptedProfiles": [ + { + "id": "tinycloud.email-held/v1", + "version": 1 + } + ] + }, + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNrMSJ9.eyJpc3MiOiJkaWQ6d2ViOmlzc3Vlci5jcmVkZW50aWFscy5vcmciLCJzdWIiOiJkaWQ6cGtoOmVpcDE1NToxOjB4ZjM5RmQ2ZTUxYWFkODhGNkY0Y2U2YUI4ODI3Mjc5Y2ZmRmI5MjI2NiIsImlhdCI6MTc2NzIyNTYwMCwibmJmIjoxNzY3MjI1NjAwLCJleHAiOjE3Njk4MTc2MDAsImp0aSI6InVybjp1dWlkOjBiNmQyYzRlLThhMWYtNGQzZS05YjdhLTFjMmQzZTRmNWE2YiIsInZjdCI6Im9wZW5jcmVkZW50aWFscy5lbWFpbC92MSIsInByb2ZpbGUiOiJ0aW55Y2xvdWQuZW1haWwtaGVsZC92MSIsInByb2ZpbGVWZXJzaW9uIjoxLCJob2xkZXJCaW5kaW5nIjp7ImRpZCI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2Iiwic2lnbmluZ0RvbWFpbiI6InRpbnljbG91ZC5jcmVkZW50aWFscy9hY2NvdW50LWJpbmRpbmcvdjEifSwic3RhdHVzIjp7Im1ldGhvZCI6Im5vbmUifSwiX3NkX2FsZyI6InNoYS0yNTYiLCJfc2QiOlsicGxrSHNCeGlDQkZDcHRHcDBacC01UWhoY2F2YllIOUljTzFTbXpxWDdsOCIsIlcwaFR1SGVaZ1I3aHp0X0pBdERJRFctY0xxWDItX0dRRFZLZTB3YkctaXciXX0.npbWPOHVFSLw71yh94Ay64QDViGaY_CHdQ-uV74h9WYmMkbeTm-ZiMgKaxV6f1WGKhaYp_MCRw-GfBntbcJDBw~WyJzYWx0LWVtYWlsIiwiZW1haWwiLDkwMDcxOTkyNTQ3NDA5OTJd~WyJzYWx0LWRvbWFpbiIsImVtYWlsRG9tYWluIiwiZXhhbXBsZS5jb20iXQ~", + "siwe": { + "message": "verifier.example wants you to sign in with your Ethereum account:\n0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266\n\nPresent a TinyCloud held credential\n\nURI: https://verifier.example\nVersion: 1\nChain ID: 1\nNonce: 303619b84b76abbfdcef0800d5607d71\nIssued At: 2026-01-01T00:59:00Z\nResources:\n- urn:tinycloud:sd-hash:YPPqo0Rp36ASgOQHDgYRb2mPO7zM3NBEf4LLmp7FVQ8", + "signature": "0xe6bcc8472230e197637291fbf3aa7479b5e7ea0670b03588c6448a553c215ccf01e54e0c272e77cd7157b1aeae3cdf9f1e0c7ae870a4605f7a7e753e0d24655c1c" + }, + "nonceStore": [ + { + "key": "verifier.example\n303619b84b76abbfdcef0800d5607d71", + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" + } + ], + "ts": { + "code": "bad-disclosure", + "detail": "bad-disclosure: disclosed value must be a string (no nested _sd or array elements)" + } + } +] \ No newline at end of file diff --git a/tinycloud-node-server/tests/fixtures/held-email-v1/s1-differential.provenance.json b/tinycloud-node-server/tests/fixtures/held-email-v1/s1-differential.provenance.json new file mode 100644 index 00000000..cf111b02 --- /dev/null +++ b/tinycloud-node-server/tests/fixtures/held-email-v1/s1-differential.provenance.json @@ -0,0 +1,23 @@ +{ + "generatedBy": "gen-s1-differential.mjs (committed alongside this file); runs the TS verifier over mutated presentations and writes the cases table", + "generatorSha256": "e9e72fce03e0b47b87f2d354dfe952348c406922ac1c33de59ca554c1c09270f", + "package": "@tinycloud/sdk-core", + "packageVersion": "3.3.0-beta.37", + "verifierSource": { + "registry": "https://registry.npmjs.org", + "gitHead": "c9bb5550de7cce9330d41995dd1157062c75916b", + "status": "published", + "install": "private temp install of @tinycloud/sdk-core@3.3.0-beta.37 (npm install, no workspace link)" + }, + "verifierFile": "dist/held-credentials/index.js", + "verifierSha256": "04db65be52bafd81629842079b318654dccd8bbba680e9128f202249080dcc65", + "node": "v22.23.2", + "cases": 333, + "casesSha256": "45386c3abd155633b2ae693b0a3dea98bf2c2b315a8300aa421f0b836ef5004b", + "reconstruction": "The reviewer's 188-case differential file was not saved. This table was rebuilt from the category list in review f41449f6: 126 generic cases and 62 disclosure-value cases, added to the 145 base cases. Case bytes are not identical to the reviewer's file. Verdicts come from the published verifier only.", + "reproduction": "Re-running the generator yields different SIWE nonces (the SDK's InMemoryNonceStore issues random nonces), so bytes differ. Verdicts are compared, not file hashes. Regenerating from the published verifier reproduces all 145 base verdicts unchanged and yields 0 THREW cases. The 188 added cases were regenerated in the same run. Eleven cases carry a `deviation` annotation (8 did:pkh casing/encoding rows refused as account-owner-invalid instead of bad-config; siwe-enc-high-s; json-sub-lone-surrogate; cfg-notafter-before-notbefore). The Rust replay requires each annotation to name the exact Rust result and to sit only on a case where Rust and TS disagree.", + "keyMaterial": "public test vectors only: Anvil account; test issuer did:web:issuer.credentials.org with a fixed-seed Ed25519 test key", + "specIssuer": "did:web:issuer.credentials.org (spec sections 3.3 and 6). The table is spec-aligned.", + "regenerationStatus": "REGENERATED from published @tinycloud/sdk-core 3.3.0-beta.37 (gitHead c9bb5550de7cce9330d41995dd1157062c75916b). Verifier sha256 matches the beta.37 dist file. Update packageVersion, verifierSha256, cases, and casesSha256 on the next regeneration.", + "consumedBy": "held_email::tests::s1_differential_table_matches_ts_verdicts" +} diff --git a/tinycloud-node-server/tests/fixtures/held-email-v1/vector.json b/tinycloud-node-server/tests/fixtures/held-email-v1/vector.json new file mode 100644 index 00000000..48044a2b --- /dev/null +++ b/tinycloud-node-server/tests/fixtures/held-email-v1/vector.json @@ -0,0 +1,27 @@ +{ + "account": "did:pkh:eip155:1:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "email": "alice@example.com", + "issuerSet": { + "format": "tinycloud.credentials-issuers/v1", + "issuers": [ + { + "alg": "EdDSA", + "issuerDid": "did:web:issuer.credentials.org", + "kid": "did:web:issuer.credentials.org#controller", + "notAfter": null, + "notBefore": "2025-01-01T00:00:00Z", + "profiles": [ + "tinycloud.email-held/v1" + ], + "publicKey": "6kpsY-KcUgq-9VB7Ey7F-ZVHdq6-vnuSQh7qaRRG0iw", + "retiredAt": null, + "vcts": [ + "opencredentials.email/v1" + ] + } + ], + "version": 1 + }, + "now": "2026-01-01T01:00:00Z", + "sdJwt": "eyJhbGciOiJFZERTQSIsInR5cCI6InZjK3NkLWp3dCIsImtpZCI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyNjb250cm9sbGVyIn0.eyJfc2QiOlsiOUZSM1NySExrSW4tc01vOUIyQ3RIZWtIRTlWdFVjQkpkZDBOdlFDYUJpNCIsIklYb1BsMDRYeEc2YnRNOUE1YzZPYkxmdHBHVmt4UXFrdGxCMl96Vnl2RW8iXSwiX3NkX2FsZyI6InNoYS0yNTYiLCJleHAiOjE3Njk4MTc2MDAsImhvbGRlckJpbmRpbmciOnsiZGlkIjoiZGlkOnBraDplaXAxNTU6MToweGYzOUZkNmU1MWFhZDg4RjZGNGNlNmFCODgyNzI3OWNmZkZiOTIyNjYiLCJzaWduaW5nRG9tYWluIjoidGlueWNsb3VkLmNyZWRlbnRpYWxzL2FjY291bnQtYmluZGluZy92MSJ9LCJpYXQiOjE3NjcyMjU2MDAsImlzcyI6ImRpZDp3ZWI6aXNzdWVyLmNyZWRlbnRpYWxzLm9yZyIsImp0aSI6InVybjp1dWlkOjVmMWM5YTJlLTdiM2QtNGU4YS05YzYxLTJkNGI4ZTdmMGExMyIsIm5iZiI6MTc2NzIyNTYwMCwicHJvZmlsZSI6InRpbnljbG91ZC5lbWFpbC1oZWxkL3YxIiwicHJvZmlsZVZlcnNpb24iOjEsInN0YXR1cyI6eyJtZXRob2QiOiJub25lIn0sInN1YiI6ImRpZDpwa2g6ZWlwMTU1OjE6MHhmMzlGZDZlNTFhYWQ4OEY2RjRjZTZhQjg4MjcyNzljZmZGYjkyMjY2IiwidmN0Ijoib3BlbmNyZWRlbnRpYWxzLmVtYWlsL3YxIn0.N-SNVObviWKHuCgoAlp5rPw_B_URBh3NbRlEzQN5RbqjygjBBo4gwhbZ-Bw7aMR9aXZs2vpkAI27Ev-nO3UsBg~WyIwMHFGc0Jjd1hFckhwWkdoZXp2RlNBIiwiZW1haWwiLCJhbGljZUBleGFtcGxlLmNvbSJd~WyIwTDg2bnAxQ3NPVHZTT0pwVmQxdHhRIiwiZW1haWxEb21haW4iLCJleGFtcGxlLmNvbSJd~" +}