nucypher_core/
key_frag.rs1use alloc::boxed::Box;
2use alloc::string::String;
3use alloc::vec::Vec;
4use core::fmt;
5
6use serde::{Deserialize, Serialize};
7use umbral_pre::{
8 decrypt_original, encrypt, serde_bytes, Capsule, DecryptionError as UmbralDecryptionError,
9 EncryptionError, KeyFrag, PublicKey, SecretKey, Signature, Signer, VerifiedKeyFrag,
10};
11
12use crate::hrac::HRAC;
13use crate::versioning::{
14 messagepack_deserialize, messagepack_serialize, DeserializationError, ProtocolObject,
15 ProtocolObjectInner,
16};
17
18#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)]
19struct AuthorizedKeyFrag {
20 signature: Signature,
21 kfrag: KeyFrag,
22}
23
24fn signed_message(hrac: &HRAC, kfrag: &KeyFrag) -> Vec<u8> {
25 [hrac.as_ref(), messagepack_serialize(kfrag).as_ref()].concat()
26}
27
28impl AuthorizedKeyFrag {
29 fn new(signer: &Signer, hrac: &HRAC, verified_kfrag: VerifiedKeyFrag) -> Self {
30 let kfrag = verified_kfrag.unverify();
35
36 let signature = signer.sign(&signed_message(hrac, &kfrag));
37
38 Self { signature, kfrag }
39 }
40
41 fn verify(self, hrac: &HRAC, publisher_verifying_key: &PublicKey) -> Option<VerifiedKeyFrag> {
42 if !self
43 .signature
44 .verify(publisher_verifying_key, &signed_message(hrac, &self.kfrag))
45 {
46 return None;
47 }
48
49 Some(self.kfrag.skip_verification())
52 }
53}
54
55impl<'a> ProtocolObjectInner<'a> for AuthorizedKeyFrag {
56 fn brand() -> [u8; 4] {
57 *b"AKFr"
58 }
59
60 fn version() -> (u16, u16) {
61 (3, 0)
62 }
63
64 fn unversioned_to_bytes(&self) -> Box<[u8]> {
65 messagepack_serialize(&self)
66 }
67
68 fn unversioned_from_bytes(minor_version: u16, bytes: &[u8]) -> Option<Result<Self, String>> {
69 if minor_version == 0 {
70 Some(messagepack_deserialize(bytes))
71 } else {
72 None
73 }
74 }
75}
76
77impl<'a> ProtocolObject<'a> for AuthorizedKeyFrag {}
78
79#[allow(clippy::enum_variant_names)]
80#[derive(Debug)]
81pub enum DecryptionError {
82 DecryptionFailed(UmbralDecryptionError),
83 DeserializationFailed(DeserializationError),
84 VerificationFailed,
85}
86
87impl fmt::Display for DecryptionError {
88 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
89 match self {
90 Self::DecryptionFailed(err) => write!(f, "decryption failed: {err}"),
91 Self::DeserializationFailed(err) => write!(f, "deserialization failed: {err}"),
92 Self::VerificationFailed => write!(f, "verification failed"),
93 }
94 }
95}
96
97#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)]
99pub struct EncryptedKeyFrag {
100 capsule: Capsule,
101 #[serde(with = "serde_bytes::as_base64")]
102 ciphertext: Box<[u8]>,
103}
104
105impl EncryptedKeyFrag {
106 pub fn new(
108 signer: &Signer,
109 recipient_key: &PublicKey,
110 hrac: &HRAC,
111 verified_kfrag: VerifiedKeyFrag,
112 ) -> Self {
113 let auth_kfrag = AuthorizedKeyFrag::new(signer, hrac, verified_kfrag);
114 let (capsule, ciphertext) = match encrypt(recipient_key, &auth_kfrag.to_bytes()) {
117 Ok(result) => result,
118 Err(err) => match err {
119 EncryptionError::PlaintextTooLarge => panic!("encryption failed - out of memory?"),
122 },
123 };
124 Self {
125 capsule,
126 ciphertext,
127 }
128 }
129
130 pub fn decrypt(
132 &self,
133 sk: &SecretKey,
134 hrac: &HRAC,
135 publisher_verifying_key: &PublicKey,
136 ) -> Result<VerifiedKeyFrag, DecryptionError> {
137 let auth_kfrag_bytes = decrypt_original(sk, &self.capsule, &self.ciphertext)
138 .map_err(DecryptionError::DecryptionFailed)?;
139 let auth_kfrag = AuthorizedKeyFrag::from_bytes(&auth_kfrag_bytes)
140 .map_err(DecryptionError::DeserializationFailed)?;
141 auth_kfrag
142 .verify(hrac, publisher_verifying_key)
143 .ok_or(DecryptionError::VerificationFailed)
144 }
145}
146
147impl<'a> ProtocolObjectInner<'a> for EncryptedKeyFrag {
148 fn brand() -> [u8; 4] {
149 *b"EKFr"
150 }
151
152 fn version() -> (u16, u16) {
153 (3, 0)
154 }
155
156 fn unversioned_to_bytes(&self) -> Box<[u8]> {
157 messagepack_serialize(&self)
158 }
159
160 fn unversioned_from_bytes(minor_version: u16, bytes: &[u8]) -> Option<Result<Self, String>> {
161 if minor_version == 0 {
162 Some(messagepack_deserialize(bytes))
163 } else {
164 None
165 }
166 }
167}
168
169impl<'a> ProtocolObject<'a> for EncryptedKeyFrag {}