baseid_bbs/
credential.rs

1use serde::{Deserialize, Serialize};
2use serde_json::Value;
3
4/// A BBS+ signed credential with individually-addressable claims.
5#[derive(Debug, Clone, Serialize, Deserialize)]
6pub struct BbsCredential {
7    /// Issuer identifier (DID).
8    pub issuer: String,
9    /// Subject identifier (DID), if not a bearer credential.
10    pub subject: Option<String>,
11    /// Credential type identifiers.
12    pub types: Vec<String>,
13    /// Ordered claim entries -- each maps to one BBS+ "message".
14    pub claims: Vec<BbsClaim>,
15    /// The BBS+ signature over all encoded claim messages.
16    pub signature: Vec<u8>,
17    /// Issuer's BLS12-381 G2 public key bytes.
18    pub issuer_public_key: Vec<u8>,
19}
20
21/// A single claim within a BBS+ credential.
22#[derive(Debug, Clone, Serialize, Deserialize)]
23pub struct BbsClaim {
24    /// Claim namespace (empty string for default).
25    pub namespace: String,
26    /// Claim name.
27    pub name: String,
28    /// Claim value.
29    pub value: Value,
30}
31
32/// A BBS+ derived proof with selectively disclosed claims.
33#[derive(Debug, Clone, Serialize, Deserialize)]
34pub struct BbsDerivedProof {
35    /// Issuer identifier.
36    pub issuer: String,
37    /// Subject identifier.
38    pub subject: Option<String>,
39    /// Credential type identifiers.
40    pub types: Vec<String>,
41    /// The zero-knowledge proof bytes.
42    pub proof: Vec<u8>,
43    /// Disclosed claims with their indices in the original credential.
44    pub disclosed_claims: Vec<(usize, BbsClaim)>,
45    /// Total number of claims in the original credential.
46    pub total_claims: usize,
47    /// Issuer's public key bytes.
48    pub issuer_public_key: Vec<u8>,
49    /// Predicate results (claim_name, predicate satisfied).
50    pub predicate_results: Vec<(String, bool)>,
51    /// Presentation header (nonce) used during proof generation.
52    pub nonce: Option<Vec<u8>>,
53}
54
55impl BbsCredential {
56    /// Encode all claims to BBS+ messages (deterministic byte encoding).
57    pub fn encode_messages(&self) -> Vec<Vec<u8>> {
58        self.claims
59            .iter()
60            .map(|claim| {
61                let canonical = serde_json::json!({
62                    "ns": claim.namespace,
63                    "name": claim.name,
64                    "value": claim.value,
65                });
66                serde_json::to_vec(&canonical).unwrap_or_default()
67            })
68            .collect()
69    }
70
71    /// Serialize to bytes.
72    pub fn to_bytes(&self) -> baseid_core::Result<Vec<u8>> {
73        serde_json::to_vec(self).map_err(|e| baseid_core::error::SerializationError::Json(e).into())
74    }
75
76    /// Deserialize from bytes.
77    pub fn from_bytes(bytes: &[u8]) -> baseid_core::Result<Self> {
78        serde_json::from_slice(bytes)
79            .map_err(|e| baseid_core::error::SerializationError::Json(e).into())
80    }
81}
82
83impl BbsDerivedProof {
84    /// Serialize to bytes.
85    pub fn to_bytes(&self) -> baseid_core::Result<Vec<u8>> {
86        serde_json::to_vec(self).map_err(|e| baseid_core::error::SerializationError::Json(e).into())
87    }
88
89    /// Deserialize from bytes.
90    pub fn from_bytes(bytes: &[u8]) -> baseid_core::Result<Self> {
91        serde_json::from_slice(bytes)
92            .map_err(|e| baseid_core::error::SerializationError::Json(e).into())
93    }
94}