quantum_sign/format/
mod.rs1#![forbid(unsafe_code)]
2
3use ciborium::{de, ser};
7use serde::{Deserialize, Serialize};
8use serde_bytes::ByteBuf;
9use serde_tuple::{Deserialize_tuple, Serialize_tuple};
10use std::io;
11use sha2::{Digest, Sha256};
12
13#[derive(Debug, thiserror::Error)]
15pub enum Error {
16 #[error("CBOR encode error: {0}")]
17 Encode(String),
18 #[error("CBOR decode error: {0}")]
19 Decode(String),
20 #[error("I/O error: {0}")]
21 Io(#[from] io::Error),
22}
23
24#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
26pub struct Signer {
27 pub kid: String,
28 #[serde(with = "serde_bytes")]
29 #[serde(default)]
30 pub claims: Vec<u8>,
31}
32
33#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
35pub struct Transparency {
36 #[serde(with = "serde_bytes")]
37 pub root: Vec<u8>,
38 #[serde(with = "serde_bytes")]
39 pub proof: Vec<u8>,
40}
41
42#[derive(Debug, Clone, PartialEq, Eq, Serialize_tuple, Deserialize_tuple)]
44pub struct QSig {
45 pub version: u8,
46 pub alg: String,
47 #[serde(with = "serde_bytes")]
48 pub digest: Vec<u8>,
49 #[serde(with = "serde_bytes")]
50 pub sig: Vec<u8>,
51 pub co_sig: Vec<ByteBuf>,
52 pub tst: Option<ByteBuf>,
53 pub tlog: Option<Transparency>,
54 pub signer: Signer,
55 pub time_unix: i64,
56 pub domain_sep: String,
57 #[serde(default)]
58 pub meta: Option<ByteBuf>,
59}
60
61impl QSig {
62 pub fn encode_to_vec(&self) -> Result<Vec<u8>, Error> {
64 let mut buf = Vec::new();
65 ser::into_writer(self, &mut buf).map_err(|e| Error::Encode(e.to_string()))?;
66 Ok(buf)
67 }
68
69 pub fn decode(bytes: &[u8]) -> Result<Self, Error> {
71 de::from_reader(bytes).map_err(|e| Error::Decode(e.to_string()))
72 }
73
74 #[allow(clippy::too_many_arguments)]
76 pub fn new(
77 version: u8,
78 alg: String,
79 digest: Vec<u8>,
80 sig: Vec<u8>,
81 co_sig: Vec<Vec<u8>>,
82 tst: Option<Vec<u8>>,
83 tlog: Option<Transparency>,
84 signer: Signer,
85 time_unix: i64,
86 domain_sep: String,
87 meta: Option<Vec<u8>>,
88 ) -> Self {
89 Self {
90 version,
91 alg,
92 digest,
93 sig,
94 co_sig: co_sig.into_iter().map(ByteBuf::from).collect(),
95 tst: tst.map(ByteBuf::from),
96 tlog,
97 signer,
98 time_unix,
99 domain_sep,
100 meta: meta.map(ByteBuf::from),
101 }
102 }
103
104 pub fn timestamp(&self) -> Option<&[u8]> {
106 self.tst.as_ref().map(ByteBuf::as_ref)
107 }
108
109 pub fn co_signatures(&self) -> impl Iterator<Item = &[u8]> {
111 self.co_sig.iter().map(ByteBuf::as_ref)
112 }
113
114 pub fn encode_core_view(&self) -> Result<Vec<u8>, Error> {
118 let mut core = self.clone();
119 core.tst = None;
120 core.tlog = None;
121 core.encode_to_vec()
122 }
123
124 pub fn core_leaf_hash_sha256(&self) -> Result<[u8; 32], Error> {
126 let core = self.encode_core_view()?;
127 let mut h = Sha256::new();
128 h.update(&core);
129 let digest = h.finalize();
130 let mut out = [0u8; 32];
131 out.copy_from_slice(&digest);
132 Ok(out)
133 }
134}