switchyard/adapters/
attest.rs1use crate::types::errors::{Error, ErrorKind};
2use thiserror::Error;
3
4#[derive(Debug, Error)]
5pub enum AttestationError {
6 #[error("attestation signing failed: {msg}")]
7 Signing { msg: String },
8 #[error("attestation verification failed: {msg}")]
9 Verification { msg: String },
10}
11
12impl From<AttestationError> for Error {
13 fn from(e: AttestationError) -> Self {
14 Error {
15 kind: ErrorKind::Io, msg: e.to_string(),
17 }
18 }
19}
20
21#[derive(Clone, Debug)]
22pub struct Signature(pub Vec<u8>);
23
24pub trait Attestor: Send + Sync {
25 fn sign(&self, bundle: &[u8]) -> Result<Signature, AttestationError>;
29 fn key_id(&self) -> String;
31 fn algorithm(&self) -> &'static str {
33 "ed25519"
34 }
35}
36
37pub fn build_attestation_fields<A: Attestor + ?Sized>(
40 att: &A,
41 bundle: &[u8],
42) -> Option<serde_json::Value> {
43 use base64::Engine as _;
44 use sha2::Digest as _;
45 let sig = att.sign(bundle).ok()?;
46 let sig_b64 = base64::engine::general_purpose::STANDARD.encode(sig.0.clone());
47 let mut hasher = sha2::Sha256::new();
48 hasher.update(bundle);
49 let bundle_hash = hex::encode(hasher.finalize());
50 Some(serde_json::json!({
51 "sig_alg": att.algorithm(),
52 "signature": sig_b64,
53 "bundle_hash": bundle_hash,
54 "public_key_id": att.key_id(),
55 }))
56}