1#[cfg(not(feature = "std"))]
2use alloc::vec::Vec;
3
4use ed25519_dalek::{Signer, SigningKey};
5use logline_core::LogLine;
6
7use crate::errors::{SealError, VerifyError};
8use crate::{
9 canonize,
10 version::{CANON_VERSION, FORMAT_ID},
11 SignedFact,
12};
13
14pub fn seal_value<T: serde::Serialize>(
15 value: &T,
16 sk: &SigningKey,
17) -> Result<SignedFact, SealError> {
18 let canonical = canonize(value)?;
19 let cid = blake3::hash(&canonical);
20 let sig = sk.sign(cid.as_bytes());
21 let vk = sk.verifying_key();
22
23 Ok(SignedFact {
24 canonical,
25 cid: *cid.as_bytes(),
26 signature: sig.to_bytes(),
27 public_key: vk.to_bytes(),
28 hash_alg: "blake3",
29 sig_alg: "ed25519",
30 canon_ver: CANON_VERSION,
31 format_id: FORMAT_ID,
32 })
33}
34
35pub fn verify_seal(f: &SignedFact) -> Result<(), VerifyError> {
36 let recomputed = blake3::hash(&f.canonical);
38 if recomputed.as_bytes() != &f.cid {
39 return Err(VerifyError::CanonicalMismatch);
40 }
41 let vk = f.verifying_key();
42 vk.verify_strict(recomputed.as_bytes(), &f.signature_obj())
43 .map_err(|_| VerifyError::BadSignature)
44}
45
46pub fn seal_logline(line: &LogLine, sk: &SigningKey) -> Result<SignedFact, SealError> {
48 seal_value(line, sk)
50}