coven_format/
sealed_key.rs1use crate::error::{require, Error, Rule};
4use crate::wire::{put_blob, wire_struct, Decoder, Encoder, Wire};
5use coven_crypto::{
6 CircleKey, CryptoError, MemberIdentity, MemberKeys, SealingKey, StoreKey, KEY_BOX_HEAD_LEN,
7 KEY_BOX_TAG_LEN,
8};
9use coven_foundation::id_source::{KeyId, MemberId};
10use coven_merge::Audience;
11
12#[derive(Clone, Debug, PartialEq, Eq)]
14pub struct KeyCopyPrefix {
15 pub audience: Audience,
17 pub key: KeyId,
19 pub member: MemberId,
21 pub sealing: SealingKey,
23}
24wire_struct!(KeyCopyPrefix, audience, key, member, sealing);
25impl KeyCopyPrefix {
26 pub fn held_by(&self, member: &MemberIdentity) -> bool {
28 self.member == member.member() && member.credential(&self.sealing).is_some()
29 }
30 pub(crate) const STORE_LEN: usize = 1 + 16 + 16 + 32;
33 pub(crate) const CIRCLE_LEN: usize = Self::STORE_LEN + 16;
35
36 pub(crate) fn material_length(&self) -> usize {
37 match self.audience {
38 Audience::Store => StoreKey::ENCODED_LEN,
39 Audience::Circle(_) => CircleKey::ENCODED_LEN,
40 }
41 }
42}
43
44#[derive(Clone, Debug, PartialEq, Eq)]
46pub struct CopyBox {
47 pub routing: KeyCopyPrefix,
49 pub sealed: Vec<u8>,
51}
52impl Wire for CopyBox {
53 fn put(&self, out: &mut Encoder) -> Result<(), Error> {
54 self.validate()?;
55 self.routing.put(out)?;
56 let tag = self.sealed.len() - KEY_BOX_TAG_LEN;
57 out.bytes(&self.sealed[..KEY_BOX_HEAD_LEN])?;
58 put_blob(&self.sealed[KEY_BOX_HEAD_LEN..tag], out)?;
59 out.bytes(&self.sealed[tag..])
60 }
61 fn get(input: &mut Decoder<'_>) -> Result<Self, Error> {
62 let routing = KeyCopyPrefix::get(input)?;
63 let mut sealed = input.take(KEY_BOX_HEAD_LEN)?.to_vec();
64 let length = u32::get(input)? as usize;
65 require(length == routing.material_length(), "key box ciphertext", Rule::StreamLength)?;
66 sealed.extend_from_slice(input.take(length)?);
67 sealed.extend_from_slice(input.take(KEY_BOX_TAG_LEN)?);
68 Ok(Self { routing, sealed })
69 }
70}
71impl CopyBox {
72 pub(crate) fn validate(&self) -> Result<(), Error> {
73 require(
74 self.sealed.len()
75 == KEY_BOX_HEAD_LEN + self.routing.material_length() + KEY_BOX_TAG_LEN,
76 "key box length",
77 Rule::StreamLength,
78 )
79 }
80 pub fn open_store_key(
83 &self,
84 member: &MemberIdentity,
85 path: &str,
86 prefix: &[u8],
87 ) -> Result<StoreKey, CryptoError> {
88 if self.routing.audience != Audience::Store {
89 return Err(CryptoError::KeyIdentity);
90 }
91 let key = self.credential(member)?.open_store_key(path, prefix, &self.sealed)?;
92 if key.id() != self.routing.key {
93 return Err(CryptoError::KeyIdentity);
94 }
95 Ok(key)
96 }
97 pub fn open_circle_key(
99 &self,
100 member: &MemberIdentity,
101 path: &str,
102 prefix: &[u8],
103 ) -> Result<CircleKey, CryptoError> {
104 let Audience::Circle(circle) = self.routing.audience else {
105 return Err(CryptoError::KeyIdentity);
106 };
107 let key = self.credential(member)?.open_circle_key(path, prefix, &self.sealed)?;
108 if key.circle() != circle || key.id() != self.routing.key {
109 return Err(CryptoError::KeyIdentity);
110 }
111 Ok(key)
112 }
113 fn credential<'m>(&self, member: &'m MemberIdentity) -> Result<&'m MemberKeys, CryptoError> {
114 if self.routing.member != member.member() {
115 return Err(CryptoError::Authentication);
116 }
117 member.credential(&self.routing.sealing).ok_or(CryptoError::Authentication)
118 }
119}
120
121#[cfg(test)]
122#[path = "sealed_key_tests.rs"]
123mod tests;