Skip to main content

warrant_core/
model.rs

1use serde_json::Value;
2
3use crate::canonical::canonical_json_bytes;
4use crate::crypto::verify_ed25519_signature;
5use crate::error::{Error, Result};
6
7#[derive(Debug, Clone, PartialEq, Eq)]
8pub struct WarrantMeta {
9    pub version: u64,
10    pub tool: String,
11    pub created: String,
12    pub issuer: String,
13}
14
15#[derive(Debug, Clone, PartialEq, Eq)]
16pub struct SignatureBlock {
17    pub algorithm: String,
18    pub public_key_b64: String,
19    pub value_b64: String,
20}
21
22#[derive(Debug, Clone, PartialEq)]
23pub struct ParsedWarrant {
24    pub meta: WarrantMeta,
25    pub capabilities: Value,
26    /// Canonicalization source object, excluding `[signature]`.
27    pub unsigned_payload: Value,
28    pub signature: SignatureBlock,
29}
30
31impl ParsedWarrant {
32    pub fn canonical_payload_bytes(&self) -> Result<Vec<u8>> {
33        canonical_json_bytes(&self.unsigned_payload)
34    }
35
36    pub fn verify_signature(&self) -> Result<()> {
37        if !self.signature.algorithm.eq_ignore_ascii_case("ed25519") {
38            return Err(Error::UnsupportedAlgorithm(
39                self.signature.algorithm.clone(),
40            ));
41        }
42        let payload = self.canonical_payload_bytes()?;
43        verify_ed25519_signature(
44            &self.signature.public_key_b64,
45            &payload,
46            &self.signature.value_b64,
47        )
48    }
49
50    pub(crate) fn new(
51        meta: WarrantMeta,
52        capabilities: Value,
53        signature: SignatureBlock,
54        unsigned_payload: Value,
55    ) -> Result<Self> {
56        if !unsigned_payload.is_object() {
57            return Err(Error::InvalidRoot);
58        }
59        Ok(Self {
60            meta,
61            capabilities,
62            unsigned_payload,
63            signature,
64        })
65    }
66}