1use curve25519_dalek::Scalar;
2
3pub trait DigestibleSecret {
5 fn as_bytes(&self) -> &[u8];
6
7 fn update_digest<D: sha2::digest::Digest>(&self, d: D, domain: impl AsRef<str>) -> D {
9 let domain: &str = domain.as_ref();
10 let bytes: &[u8] = self.as_bytes();
11
12 d.chain_update(encode_usize(domain.len()))
14 .chain_update(domain)
15 .chain_update(encode_usize(bytes.len()))
16 .chain_update(bytes)
17 }
18
19 fn derive_scalar<D>(&self, d: D, domain: impl AsRef<str>) -> Scalar
21 where
22 D: sha2::digest::Digest<OutputSize = typenum::U64>,
23 {
24 Scalar::from_hash(self.update_digest(d, domain))
25 }
26
27 fn derive_bytes<D>(&self, d: D, domain: impl AsRef<str>) -> Vec<u8>
29 where
30 D: sha2::digest::Digest,
31 {
32 self.update_digest(d, domain)
34 .finalize()
35 .as_slice()
36 .to_owned()
37 }
38
39 fn derive_id<D>(&self, d: D, domain: impl AsRef<str>) -> crate::id::Id
43 where
44 D: sha2::digest::Digest<OutputSize = typenum::U32>,
45 {
46 let bytes: [u8; 32] = self.derive_bytes(d, domain).try_into().unwrap();
47
48 bytes.into()
49 }
50
51 fn derive_hs256<D>(&self, d: D, domain: impl AsRef<str>) -> crate::misc::jwt::HS256
55 where
56 D: sha2::digest::Digest,
57 {
58 crate::misc::jwt::HS256(self.derive_bytes(d, domain))
59 }
60
61 fn derive_sealing_key<D>(
63 &self,
64 d: D,
65 domain: impl AsRef<str>,
66 ) -> crate::misc::crypto::SealingKey
67 where
68 D: sha2::digest::Digest<OutputSize = typenum::U32>,
69 {
70 self.update_digest(d, domain).finalize()
71 }
72}
73
74impl DigestibleSecret for &[u8] {
75 fn as_bytes(&self) -> &[u8] {
76 self
77 }
78}
79
80pub const fn encode_usize(size: usize) -> [u8; 8] {
82 if size_of::<usize>() > 8 {
83 panic!("can not (yet) deal with usize of size > 8")
84 }
85 (size as u64).to_be_bytes()
86}