1use prost::Message;
6
7use super::{default_symbol_table, Biscuit, Block};
8use crate::{
9 builder::BlockBuilder,
10 crypto::{self, PublicKey, Signature},
11 datalog::SymbolTable,
12 error,
13 format::{
14 convert::proto_block_to_token_block,
15 schema::{self, public_key::Algorithm},
16 SerializedBiscuit,
17 },
18 token::{ThirdPartyBlockContents, ThirdPartyRequest},
19 KeyPair, RootKeyProvider,
20};
21
22#[derive(Clone, Debug)]
30pub struct UnverifiedBiscuit {
31 pub(crate) authority: schema::Block,
32 pub(crate) blocks: Vec<schema::Block>,
33 pub(crate) symbols: SymbolTable,
34 container: SerializedBiscuit,
35}
36
37impl UnverifiedBiscuit {
38 pub fn from<T>(slice: T) -> Result<Self, error::Token>
40 where
41 T: AsRef<[u8]>,
42 {
43 Self::from_with_symbols(slice.as_ref(), default_symbol_table())
44 }
45
46 pub fn unsafe_deprecated_deserialize<T>(slice: T) -> Result<Self, error::Token>
50 where
51 T: AsRef<[u8]>,
52 {
53 let container = SerializedBiscuit::deserialize(
54 slice.as_ref(),
55 crate::format::ThirdPartyVerificationMode::UnsafeLegacy,
56 )?;
57 let mut symbols = default_symbol_table();
58
59 let (authority, blocks) = container.extract_blocks(&mut symbols)?;
60
61 Ok(UnverifiedBiscuit {
62 authority,
63 blocks,
64 symbols,
65 container,
66 })
67 }
68
69 pub fn from_base64<T>(slice: T) -> Result<Self, error::Token>
71 where
72 T: AsRef<[u8]>,
73 {
74 Self::from_base64_with_symbols(slice, default_symbol_table())
75 }
76
77 #[deprecated(since = "4.1.0", note = "please use `verify` instead")]
78 pub fn check_signature<F>(self, f: F) -> Result<Biscuit, error::Format>
80 where
81 F: Fn(Option<u32>) -> PublicKey,
82 {
83 self.verify(|kid| Ok(f(kid)))
84 }
85
86 pub fn verify<KP>(self, key_provider: KP) -> Result<Biscuit, error::Format>
88 where
89 KP: RootKeyProvider,
90 {
91 let key = key_provider.choose(self.root_key_id())?;
92 self.container.verify(&key)?;
93
94 Ok(Biscuit {
95 root_key_id: self.container.root_key_id,
96 authority: self.authority,
97 blocks: self.blocks,
98 symbols: self.symbols,
99 container: self.container,
100 })
101 }
102
103 pub fn append(&self, block_builder: BlockBuilder) -> Result<Self, error::Token> {
108 let keypair =
109 KeyPair::new_with_rng(super::builder::Algorithm::Ed25519, &mut rand::rngs::OsRng);
110 self.append_with_keypair(&keypair, block_builder)
111 }
112
113 pub fn to_vec(&self) -> Result<Vec<u8>, error::Token> {
115 self.container.to_vec().map_err(error::Token::Format)
116 }
117
118 pub fn to_base64(&self) -> Result<String, error::Token> {
120 self.container
121 .to_vec()
122 .map_err(error::Token::Format)
123 .map(|v| base64::encode_config(v, base64::URL_SAFE))
124 }
125
126 pub fn from_with_symbols(slice: &[u8], mut symbols: SymbolTable) -> Result<Self, error::Token> {
128 let container = SerializedBiscuit::deserialize(
129 slice,
130 crate::format::ThirdPartyVerificationMode::PreviousSignatureHashing,
131 )?;
132
133 let (authority, blocks) = container.extract_blocks(&mut symbols)?;
134
135 Ok(UnverifiedBiscuit {
136 authority,
137 blocks,
138 symbols,
139 container,
140 })
141 }
142
143 pub fn from_base64_with_symbols<T>(slice: T, symbols: SymbolTable) -> Result<Self, error::Token>
145 where
146 T: AsRef<[u8]>,
147 {
148 let decoded = base64::decode_config(slice, base64::URL_SAFE)?;
149 Self::from_with_symbols(&decoded, symbols)
150 }
151
152 pub fn append_with_keypair(
157 &self,
158 keypair: &KeyPair,
159 block_builder: BlockBuilder,
160 ) -> Result<Self, error::Token> {
161 let block = block_builder.build(self.symbols.clone());
162
163 if !self.symbols.is_disjoint(&block.symbols) {
164 return Err(error::Token::Format(error::Format::SymbolTableOverlap));
165 }
166
167 let authority = self.authority.clone();
168 let mut blocks = self.blocks.clone();
169 let mut symbols = self.symbols.clone();
170
171 let container = self.container.append(keypair, &block, None)?;
172
173 symbols.extend(&block.symbols)?;
174 symbols.public_keys.extend(&block.public_keys)?;
175
176 let deser = schema::Block::decode(
177 &container
178 .blocks
179 .last()
180 .expect("a new block was just added so the list is not empty")
181 .data[..],
182 )
183 .map_err(|e| {
184 error::Token::Format(error::Format::BlockDeserializationError(format!(
185 "error deserializing block: {:?}",
186 e
187 )))
188 })?;
189 blocks.push(deser);
190
191 Ok(UnverifiedBiscuit {
192 authority,
193 blocks,
194 symbols,
195 container,
196 })
197 }
198
199 pub fn root_key_id(&self) -> Option<u32> {
201 self.container.root_key_id
202 }
203
204 pub fn revocation_identifiers(&self) -> Vec<Vec<u8>> {
209 let mut res = vec![self.container.authority.signature.to_bytes().to_vec()];
210
211 for block in self.container.blocks.iter() {
212 res.push(block.signature.to_bytes().to_vec());
213 }
214
215 res
216 }
217
218 pub fn external_public_keys(&self) -> Vec<Option<PublicKey>> {
224 let mut res = vec![None];
225
226 for block in self.container.blocks.iter() {
227 res.push(block.external_signature.as_ref().map(|sig| sig.public_key));
228 }
229
230 res
231 }
232
233 pub fn block_count(&self) -> usize {
235 1 + self.container.blocks.len()
236 }
237
238 pub fn print_block_source(&self, index: usize) -> Result<String, error::Token> {
240 self.block(index).map(|block| {
241 let symbols = if block.external_key.is_some() {
242 &block.symbols
243 } else {
244 &self.symbols
245 };
246 block.print_source(symbols)
247 })
248 }
249
250 pub fn block_version(&self, index: usize) -> Result<u32, error::Token> {
252 self.block(index).map(|block| block.version)
253 }
254
255 pub(crate) fn block(&self, index: usize) -> Result<Block, error::Token> {
256 let mut block = if index == 0 {
257 proto_block_to_token_block(
258 &self.authority,
259 self.container
260 .authority
261 .external_signature
262 .as_ref()
263 .map(|ex| ex.public_key),
264 )
265 .map_err(error::Token::Format)?
266 } else {
267 if index > self.blocks.len() + 1 {
268 return Err(error::Token::Format(
269 error::Format::BlockDeserializationError("invalid block index".to_string()),
270 ));
271 }
272
273 proto_block_to_token_block(
274 &self.blocks[index - 1],
275 self.container.blocks[index - 1]
276 .external_signature
277 .as_ref()
278 .map(|ex| ex.public_key),
279 )
280 .map_err(error::Token::Format)?
281 };
282
283 block.symbols.public_keys = self.symbols.public_keys.clone();
286 Ok(block)
287 }
288
289 pub fn seal(&self) -> Result<UnverifiedBiscuit, error::Token> {
293 let container = self.container.seal()?;
294 let mut token = self.clone();
295 token.container = container;
296 Ok(token)
297 }
298
299 pub fn third_party_request(&self) -> Result<ThirdPartyRequest, error::Token> {
300 ThirdPartyRequest::from_container(&self.container)
301 }
302
303 pub fn append_third_party(&self, slice: &[u8]) -> Result<Self, error::Token> {
304 let next_keypair =
305 KeyPair::new_with_rng(super::builder::Algorithm::Ed25519, &mut rand::rngs::OsRng);
306 self.append_third_party_with_keypair(slice, next_keypair)
307 }
308
309 pub fn append_third_party_with_keypair(
310 &self,
311 slice: &[u8],
312 next_keypair: KeyPair,
313 ) -> Result<Self, error::Token> {
314 let ThirdPartyBlockContents {
315 payload,
316 external_signature,
317 } = schema::ThirdPartyBlockContents::decode(slice).map_err(|e| {
318 error::Format::DeserializationError(format!("deserialization error: {:?}", e))
319 })?;
320
321 let algorithm =
322 Algorithm::from_i32(external_signature.public_key.algorithm).ok_or_else(|| {
323 error::Format::DeserializationError(
324 "deserialization error: invalid external key algorithm".to_string(),
325 )
326 })?;
327 let external_key =
328 PublicKey::from_bytes(&external_signature.public_key.key, algorithm.into()).map_err(
329 |e| {
330 error::Format::BlockSignatureDeserializationError(format!(
331 "block external public key deserialization error: {:?}",
332 e
333 ))
334 },
335 )?;
336
337 let signature = Signature::from_vec(external_signature.signature);
338
339 let block = schema::Block::decode(&payload[..]).map_err(|e| {
340 error::Token::Format(error::Format::DeserializationError(format!(
341 "deserialization error: {:?}",
342 e
343 )))
344 })?;
345
346 let external_signature = crypto::ExternalSignature {
347 public_key: external_key,
348 signature,
349 };
350
351 let mut symbols = self.symbols.clone();
352 let mut blocks = self.blocks.clone();
353
354 let container =
355 self.container
356 .append_serialized(&next_keypair, payload, Some(external_signature))?;
357
358 let token_block = proto_block_to_token_block(&block, Some(external_key)).unwrap();
359 for key in &token_block.public_keys.keys {
360 symbols.public_keys.insert_fallible(key)?;
361 }
362
363 blocks.push(block);
364
365 Ok(UnverifiedBiscuit {
366 authority: self.authority.clone(),
367 blocks,
368 symbols,
369 container,
370 })
371 }
372
373 pub fn append_third_party_base64<T>(&self, slice: T) -> Result<Self, error::Token>
374 where
375 T: AsRef<[u8]>,
376 {
377 let decoded = base64::decode_config(slice, base64::URL_SAFE)?;
378 self.append_third_party(&decoded)
379 }
380}
381
382#[cfg(test)]
383mod tests {
384 use crate::{BiscuitBuilder, BlockBuilder, KeyPair};
385
386 use super::UnverifiedBiscuit;
387
388 #[test]
389 fn consistent_with_biscuit() {
390 let root_key = KeyPair::new();
391 let external_key = KeyPair::new();
392 let biscuit = BiscuitBuilder::new()
393 .fact("test(true)")
394 .unwrap()
395 .build(&root_key)
396 .unwrap()
397 .append(BlockBuilder::new().fact("test(false)").unwrap())
398 .unwrap();
399 let req = biscuit.third_party_request().unwrap();
400 let res = req
401 .create_block(
402 &external_key.private(),
403 BlockBuilder::new().fact("third_party(true)").unwrap(),
404 )
405 .unwrap();
406 let biscuit = biscuit
407 .append_third_party(external_key.public(), res)
408 .unwrap();
409
410 let unverified = UnverifiedBiscuit::from_base64(biscuit.to_base64().unwrap()).unwrap();
411
412 unverified.clone().verify(root_key.public()).unwrap();
413
414 assert_eq!(unverified.blocks, biscuit.blocks);
415
416 assert_eq!(
417 unverified.external_public_keys(),
418 biscuit.external_public_keys()
419 );
420 }
421}