From 7c8b3b702cce8de18781586bc9fc8e9b0d1abe51 Mon Sep 17 00:00:00 2001 From: Saoirse Aronson Date: Thu, 4 Jun 2026 17:30:10 +0200 Subject: [PATCH 1/3] Remove KeyPair type KeyPair is really just the same as PrivateKey, it's not necessary to have two distinct types for these purposes and it makes trait abstraction more complex. --- README.md | 4 +- biscuit-auth/README.md | 4 +- biscuit-auth/benches/token.rs | 124 +++++----- biscuit-auth/examples/testcases.rs | 220 +++++++++--------- biscuit-auth/examples/third_party.rs | 6 +- biscuit-auth/src/bwk.rs | 8 +- biscuit-auth/src/crypto/ed25519.rs | 87 ++----- biscuit-auth/src/crypto/mod.rs | 176 ++++++-------- biscuit-auth/src/crypto/p256.rs | 82 ++----- biscuit-auth/src/format/mod.rs | 102 ++++---- biscuit-auth/src/lib.rs | 6 +- biscuit-auth/src/macros.rs | 12 +- biscuit-auth/src/token/authorizer.rs | 60 ++--- biscuit-auth/src/token/authorizer/snapshot.rs | 12 +- biscuit-auth/src/token/builder/biscuit.rs | 12 +- biscuit-auth/src/token/mod.rs | 124 +++++----- biscuit-auth/src/token/third_party.rs | 9 +- biscuit-auth/src/token/unverified.rs | 42 ++-- biscuit-auth/tests/macros.rs | 4 +- biscuit-auth/tests/rights.rs | 3 +- biscuit-capi/src/lib.rs | 32 +-- biscuit-capi/tests/capi.rs | 8 +- 22 files changed, 512 insertions(+), 625 deletions(-) diff --git a/README.md b/README.md index 71338aaf..032851ce 100644 --- a/README.md +++ b/README.md @@ -20,12 +20,12 @@ In this example we will see how we can create a token, add some checks, serializ ```rust extern crate biscuit_auth as biscuit; -use biscuit::{KeyPair, Biscuit, error}; +use biscuit::{PrivateKey, Biscuit, error}; fn main() -> Result<(), error::Token> { // let's generate the root key pair. The root public key will be necessary // to verify the token - let root = KeyPair::new(); + let root = PrivateKey::new(); let public_key = root.public(); // creating a first token diff --git a/biscuit-auth/README.md b/biscuit-auth/README.md index 217504b6..7b71154a 100644 --- a/biscuit-auth/README.md +++ b/biscuit-auth/README.md @@ -20,12 +20,12 @@ In this example we will see how we can create a token, add some checks, serializ ```rust extern crate biscuit_auth as biscuit; -use biscuit::{KeyPair, Biscuit, error}; +use biscuit::{PrivateKey, Biscuit, error}; fn main() -> Result<(), error::Token> { // let's generate the root key pair. The root public key will be necessary // to verify the token - let root = KeyPair::new(); + let root = PrivateKey::new(); let public_key = root.public(); // creating a first token diff --git a/biscuit-auth/benches/token.rs b/biscuit-auth/benches/token.rs index 5d5ff967..0f6e505c 100644 --- a/biscuit-auth/benches/token.rs +++ b/biscuit-auth/benches/token.rs @@ -1,4 +1,4 @@ -/* +/g * Copyright (c) 2019 Geoffroy Couprie and Contributors to the Eclipse Foundation. * SPDX-License-Identifier: Apache-2.0 */ @@ -10,14 +10,14 @@ use biscuit::{ builder::*, builder_ext::{AuthorizerExt, BuilderExt}, datalog::SymbolTable, - AuthorizerLimits, Biscuit, KeyPair, UnverifiedBiscuit, + AuthorizerLimits, Biscuit, PrivateKey, UnverifiedBiscuit, }; use codspeed_bencher_compat::{benchmark_group, benchmark_main, Bencher}; use rand::rngs::OsRng; fn create_block_1(b: &mut Bencher) { let mut rng = OsRng; - let root = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng); + let root = PrivateKey::new_with_rng(Algorithm::Ed25519, &mut rng); let token = Biscuit::builder() .fact(fact("right", &[string("file1"), string("read")])) @@ -48,8 +48,8 @@ fn create_block_1(b: &mut Bencher) { fn append_block_2(b: &mut Bencher) { let mut rng: OsRng = OsRng; - let root = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng); - let keypair2 = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng); + let root = PrivateKey::new_with_rng(Algorithm::Ed25519, &mut rng); + let keypair2 = PrivateKey::new_with_rng(Algorithm::Ed25519, &mut rng); let token = Biscuit::builder() .fact(fact("right", &[string("file1"), string("read")])) @@ -66,7 +66,7 @@ fn append_block_2(b: &mut Bencher) { .check_resource("file1") .check_operation("read"); - let token2 = token.append_with_keypair(&keypair2, block_builder).unwrap(); + let token2 = token.append_with_key(&keypair2, block_builder).unwrap(); let data = token2.to_vec().unwrap(); b.bytes = (data.len() - base_data.len()) as u64; @@ -77,18 +77,18 @@ fn append_block_2(b: &mut Bencher) { .check_resource("file1") .check_operation("read"); - let token2 = token.append_with_keypair(&keypair2, block_builder).unwrap(); + let token2 = token.append_with_key(&keypair2, block_builder).unwrap(); let _data = token2.to_vec().unwrap(); }); } fn append_block_5(b: &mut Bencher) { let mut rng: OsRng = OsRng; - let root = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng); - let keypair2 = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng); - let keypair3 = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng); - let keypair4 = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng); - let keypair5 = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng); + let root = PrivateKey::new_with_rng(Algorithm::Ed25519, &mut rng); + let keypair2 = PrivateKey::new_with_rng(Algorithm::Ed25519, &mut rng); + let keypair3 = PrivateKey::new_with_rng(Algorithm::Ed25519, &mut rng); + let keypair4 = PrivateKey::new_with_rng(Algorithm::Ed25519, &mut rng); + let keypair5 = PrivateKey::new_with_rng(Algorithm::Ed25519, &mut rng); let token = Biscuit::builder() .fact(fact("right", &[string("file1"), string("read")])) @@ -105,7 +105,7 @@ fn append_block_5(b: &mut Bencher) { .check_resource("file1") .check_operation("read"); - let token2 = token.append_with_keypair(&keypair2, block_builder).unwrap(); + let token2 = token.append_with_key(&keypair2, block_builder).unwrap(); let data = token2.to_vec().unwrap(); b.bytes = (data.len() - base_data.len()) as u64; @@ -117,7 +117,7 @@ fn append_block_5(b: &mut Bencher) { .check_operation("read"); let token3 = token2 - .append_with_keypair(&keypair3, block_builder) + .append_with_key(&keypair3, block_builder) .unwrap(); let data = token3.to_vec().unwrap(); @@ -127,7 +127,7 @@ fn append_block_5(b: &mut Bencher) { .check_operation("read"); let token4 = token3 - .append_with_keypair(&keypair4, block_builder) + .append_with_key(&keypair4, block_builder) .unwrap(); let data = token4.to_vec().unwrap(); @@ -137,7 +137,7 @@ fn append_block_5(b: &mut Bencher) { .check_operation("read"); let token5 = token4 - .append_with_keypair(&keypair5, block_builder) + .append_with_key(&keypair5, block_builder) .unwrap(); let _data = token5.to_vec().unwrap(); }); @@ -145,8 +145,8 @@ fn append_block_5(b: &mut Bencher) { fn unverified_append_block_2(b: &mut Bencher) { let mut rng: OsRng = OsRng; - let root = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng); - let keypair2 = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng); + let root = PrivateKey::new_with_rng(Algorithm::Ed25519, &mut rng); + let keypair2 = PrivateKey::new_with_rng(Algorithm::Ed25519, &mut rng); let token = Biscuit::builder() .fact(fact("right", &[string("file1"), string("read")])) @@ -163,7 +163,7 @@ fn unverified_append_block_2(b: &mut Bencher) { .check_resource("file1") .check_operation("read"); - let token2 = token.append_with_keypair(&keypair2, block_builder).unwrap(); + let token2 = token.append_with_key(&keypair2, block_builder).unwrap(); let data = token2.to_vec().unwrap(); b.bytes = (data.len() - base_data.len()) as u64; @@ -174,18 +174,18 @@ fn unverified_append_block_2(b: &mut Bencher) { .check_resource("file1") .check_operation("read"); - let token2 = token.append_with_keypair(&keypair2, block_builder).unwrap(); + let token2 = token.append_with_key(&keypair2, block_builder).unwrap(); let _data = token2.to_vec().unwrap(); }); } fn unverified_append_block_5(b: &mut Bencher) { let mut rng: OsRng = OsRng; - let root = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng); - let keypair2 = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng); - let keypair3 = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng); - let keypair4 = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng); - let keypair5 = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng); + let root = PrivateKey::new_with_rng(Algorithm::Ed25519, &mut rng); + let keypair2 = PrivateKey::new_with_rng(Algorithm::Ed25519, &mut rng); + let keypair3 = PrivateKey::new_with_rng(Algorithm::Ed25519, &mut rng); + let keypair4 = PrivateKey::new_with_rng(Algorithm::Ed25519, &mut rng); + let keypair5 = PrivateKey::new_with_rng(Algorithm::Ed25519, &mut rng); let token = Biscuit::builder() .fact(fact("right", &[string("file1"), string("read")])) @@ -202,7 +202,7 @@ fn unverified_append_block_5(b: &mut Bencher) { .check_resource("file1") .check_operation("read"); - let token2 = token.append_with_keypair(&keypair2, block_builder).unwrap(); + let token2 = token.append_with_key(&keypair2, block_builder).unwrap(); let data = token2.to_vec().unwrap(); b.bytes = (data.len() - base_data.len()) as u64; @@ -214,7 +214,7 @@ fn unverified_append_block_5(b: &mut Bencher) { .check_operation("read"); let token3 = token2 - .append_with_keypair(&keypair3, block_builder) + .append_with_key(&keypair3, block_builder) .unwrap(); let data = token3.to_vec().unwrap(); @@ -224,7 +224,7 @@ fn unverified_append_block_5(b: &mut Bencher) { .check_operation("read"); let token4 = token3 - .append_with_keypair(&keypair4, block_builder) + .append_with_key(&keypair4, block_builder) .unwrap(); let data = token4.to_vec().unwrap(); @@ -234,7 +234,7 @@ fn unverified_append_block_5(b: &mut Bencher) { .check_operation("read"); let token5 = token4 - .append_with_keypair(&keypair5, block_builder) + .append_with_key(&keypair5, block_builder) .unwrap(); let _data = token5.to_vec().unwrap(); }); @@ -242,8 +242,8 @@ fn unverified_append_block_5(b: &mut Bencher) { fn verify_block_2(b: &mut Bencher) { let mut rng: OsRng = OsRng; - let root = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng); - let keypair2 = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng); + let root = PrivateKey::new_with_rng(Algorithm::Ed25519, &mut rng); + let keypair2 = PrivateKey::new_with_rng(Algorithm::Ed25519, &mut rng); let data = { let token = Biscuit::builder() @@ -261,7 +261,7 @@ fn verify_block_2(b: &mut Bencher) { .check_resource("file1") .check_operation("read"); - let token2 = token.append_with_keypair(&keypair2, block_builder).unwrap(); + let token2 = token.append_with_key(&keypair2, block_builder).unwrap(); token2.to_vec().unwrap() }; @@ -302,11 +302,11 @@ fn verify_block_2(b: &mut Bencher) { fn verify_block_5(b: &mut Bencher) { let mut rng: OsRng = OsRng; - let root = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng); - let keypair2 = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng); - let keypair3 = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng); - let keypair4 = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng); - let keypair5 = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng); + let root = PrivateKey::new_with_rng(Algorithm::Ed25519, &mut rng); + let keypair2 = PrivateKey::new_with_rng(Algorithm::Ed25519, &mut rng); + let keypair3 = PrivateKey::new_with_rng(Algorithm::Ed25519, &mut rng); + let keypair4 = PrivateKey::new_with_rng(Algorithm::Ed25519, &mut rng); + let keypair5 = PrivateKey::new_with_rng(Algorithm::Ed25519, &mut rng); let data = { let token = Biscuit::builder() @@ -324,14 +324,14 @@ fn verify_block_5(b: &mut Bencher) { .check_resource("file1") .check_operation("read"); - let token2 = token.append_with_keypair(&keypair2, block_builder).unwrap(); + let token2 = token.append_with_key(&keypair2, block_builder).unwrap(); let block_builder = BlockBuilder::new() .check_resource("file1") .check_operation("read"); let token3 = token2 - .append_with_keypair(&keypair3, block_builder) + .append_with_key(&keypair3, block_builder) .unwrap(); let block_builder = BlockBuilder::new() @@ -339,7 +339,7 @@ fn verify_block_5(b: &mut Bencher) { .check_operation("read"); let token4 = token3 - .append_with_keypair(&keypair4, block_builder) + .append_with_key(&keypair4, block_builder) .unwrap(); let block_builder = BlockBuilder::new() @@ -347,7 +347,7 @@ fn verify_block_5(b: &mut Bencher) { .check_operation("read"); let token5 = token4 - .append_with_keypair(&keypair5, block_builder) + .append_with_key(&keypair5, block_builder) .unwrap(); token5.to_vec().unwrap() }; @@ -390,8 +390,8 @@ fn verify_block_5(b: &mut Bencher) { fn check_signature_2(b: &mut Bencher) { let mut rng: OsRng = OsRng; - let root = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng); - let keypair2 = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng); + let root = PrivateKey::new_with_rng(Algorithm::Ed25519, &mut rng); + let keypair2 = PrivateKey::new_with_rng(Algorithm::Ed25519, &mut rng); let data = { let token = Biscuit::builder() @@ -409,7 +409,7 @@ fn check_signature_2(b: &mut Bencher) { .check_resource("file1") .check_operation("read"); - let token2 = token.append_with_keypair(&keypair2, block_builder).unwrap(); + let token2 = token.append_with_key(&keypair2, block_builder).unwrap(); token2.to_vec().unwrap() }; @@ -437,11 +437,11 @@ fn check_signature_2(b: &mut Bencher) { fn check_signature_5(b: &mut Bencher) { let mut rng: OsRng = OsRng; - let root = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng); - let keypair2 = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng); - let keypair3 = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng); - let keypair4 = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng); - let keypair5 = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng); + let root = PrivateKey::new_with_rng(Algorithm::Ed25519, &mut rng); + let keypair2 = PrivateKey::new_with_rng(Algorithm::Ed25519, &mut rng); + let keypair3 = PrivateKey::new_with_rng(Algorithm::Ed25519, &mut rng); + let keypair4 = PrivateKey::new_with_rng(Algorithm::Ed25519, &mut rng); + let keypair5 = PrivateKey::new_with_rng(Algorithm::Ed25519, &mut rng); let data = { let token = Biscuit::builder() @@ -459,13 +459,13 @@ fn check_signature_5(b: &mut Bencher) { .check_resource("file1") .check_operation("read"); - let token2 = token.append_with_keypair(&keypair2, block_builder).unwrap(); + let token2 = token.append_with_key(&keypair2, block_builder).unwrap(); let block_builder = BlockBuilder::new() .check_resource("file1") .check_operation("read"); let token3 = token2 - .append_with_keypair(&keypair3, block_builder) + .append_with_key(&keypair3, block_builder) .unwrap(); let block_builder = BlockBuilder::new() @@ -473,7 +473,7 @@ fn check_signature_5(b: &mut Bencher) { .check_operation("read"); let token4 = token3 - .append_with_keypair(&keypair4, block_builder) + .append_with_key(&keypair4, block_builder) .unwrap(); let block_builder = BlockBuilder::new() @@ -481,7 +481,7 @@ fn check_signature_5(b: &mut Bencher) { .check_operation("read"); let token5 = token4 - .append_with_keypair(&keypair5, block_builder) + .append_with_key(&keypair5, block_builder) .unwrap(); token5.to_vec().unwrap() }; @@ -510,8 +510,8 @@ fn check_signature_5(b: &mut Bencher) { fn checks_block_2(b: &mut Bencher) { let mut rng: OsRng = OsRng; - let root = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng); - let keypair2 = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng); + let root = PrivateKey::new_with_rng(Algorithm::Ed25519, &mut rng); + let keypair2 = PrivateKey::new_with_rng(Algorithm::Ed25519, &mut rng); let data = { let token = Biscuit::builder() @@ -529,7 +529,7 @@ fn checks_block_2(b: &mut Bencher) { .check_resource("file1") .check_operation("read"); - let token2 = token.append_with_keypair(&keypair2, block_builder).unwrap(); + let token2 = token.append_with_key(&keypair2, block_builder).unwrap(); token2.to_vec().unwrap() }; @@ -571,8 +571,8 @@ fn checks_block_2(b: &mut Bencher) { fn checks_block_create_verifier2(b: &mut Bencher) { let mut rng: OsRng = OsRng; - let root = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng); - let keypair2 = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng); + let root = PrivateKey::new_with_rng(Algorithm::Ed25519, &mut rng); + let keypair2 = PrivateKey::new_with_rng(Algorithm::Ed25519, &mut rng); let data = { let token = Biscuit::builder() @@ -590,7 +590,7 @@ fn checks_block_create_verifier2(b: &mut Bencher) { .check_resource("file1") .check_operation("read"); - let token2 = token.append_with_keypair(&keypair2, block_builder).unwrap(); + let token2 = token.append_with_key(&keypair2, block_builder).unwrap(); token2.to_vec().unwrap() }; @@ -619,8 +619,8 @@ fn checks_block_create_verifier2(b: &mut Bencher) { fn checks_block_verify_only2(b: &mut Bencher) { let mut rng: OsRng = OsRng; - let root = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng); - let keypair2 = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng); + let root = PrivateKey::new_with_rng(Algorithm::Ed25519, &mut rng); + let keypair2 = PrivateKey::new_with_rng(Algorithm::Ed25519, &mut rng); let data = { let token = Biscuit::builder() @@ -638,7 +638,7 @@ fn checks_block_verify_only2(b: &mut Bencher) { .check_resource("file1") .check_operation("read"); - let token2 = token.append_with_keypair(&keypair2, block_builder).unwrap(); + let token2 = token.append_with_key(&keypair2, block_builder).unwrap(); token2.to_vec().unwrap() }; diff --git a/biscuit-auth/examples/testcases.rs b/biscuit-auth/examples/testcases.rs index eedcefa5..17de71f7 100644 --- a/biscuit-auth/examples/testcases.rs +++ b/biscuit-auth/examples/testcases.rs @@ -12,7 +12,7 @@ use biscuit::error; use biscuit::format::convert; use biscuit::macros::*; use biscuit::{builder::*, builder_ext::*, Biscuit}; -use biscuit::{KeyPair, PrivateKey, PublicKey}; +use biscuit::{PrivateKey, PublicKey}; use biscuit_auth::builder; use biscuit_auth::builder::Algorithm; use biscuit_auth::datalog::ExternFunc; @@ -82,10 +82,10 @@ fn main() { fn run(target: String, root_key: Option, test: bool, json: bool) { let root = if let Some(key) = root_key { - KeyPair::from(&PrivateKey::from_bytes_hex(&key, Algorithm::Ed25519).unwrap()) + PrivateKey::from_bytes_hex(&key, Algorithm::Ed25519).unwrap() } else { let mut rng: StdRng = SeedableRng::seed_from_u64(1234); - KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng) + PrivateKey::new_with_rng(Algorithm::Ed25519, &mut rng) }; let mut results = Vec::new(); @@ -316,7 +316,7 @@ enum AuthorizerResult { Err(error::Token), } -fn validate_token(root: &KeyPair, data: &[u8], authorizer_code: &str) -> Validation { +fn validate_token(root: &PrivateKey, data: &[u8], authorizer_code: &str) -> Validation { validate_token_with_limits_and_external_functions( root, data, @@ -327,7 +327,7 @@ fn validate_token(root: &KeyPair, data: &[u8], authorizer_code: &str) -> Validat } fn validate_token_with_limits_and_external_functions( - root: &KeyPair, + root: &PrivateKey, data: &[u8], authorizer_code: &str, run_limits: RunLimits, @@ -513,7 +513,7 @@ fn print_diff(actual: &str, expected: &str) { fn write_or_load_testcase( target: &str, filename: &str, - root: &KeyPair, + root: &PrivateKey, token: &Biscuit, test: bool, ) -> Vec { @@ -531,7 +531,7 @@ fn write_or_load_testcase( } } -fn basic_token(target: &str, root: &KeyPair, test: bool) -> TestResult { +fn basic_token(target: &str, root: &PrivateKey, test: bool) -> TestResult { let mut rng: StdRng = SeedableRng::seed_from_u64(1234); let title = "basic token".to_string(); let filename = "test001_basic".to_string(); @@ -546,9 +546,9 @@ fn basic_token(target: &str, root: &KeyPair, test: bool) -> TestResult { .build_with_rng(root, SymbolTable::default(), &mut rng) .unwrap(); - let keypair2 = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng); + let keypair2 = PrivateKey::new_with_rng(Algorithm::Ed25519, &mut rng); let biscuit2 = biscuit1 - .append_with_keypair( + .append_with_key( &keypair2, block!( r#" @@ -583,13 +583,13 @@ fn basic_token(target: &str, root: &KeyPair, test: bool) -> TestResult { } } -fn different_root_key(target: &str, root: &KeyPair, test: bool) -> TestResult { +fn different_root_key(target: &str, root: &PrivateKey, test: bool) -> TestResult { // using a different seed otherwise it would generate the same root key let mut rng: StdRng = SeedableRng::seed_from_u64(5678); let title = "different root key".to_string(); let filename = "test002_different_root_key".to_string(); - let root2 = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng); + let root2 = PrivateKey::new_with_rng(Algorithm::Ed25519, &mut rng); let biscuit1 = biscuit!( r#" @@ -599,9 +599,9 @@ fn different_root_key(target: &str, root: &KeyPair, test: bool) -> TestResult { .build_with_rng(&root2, SymbolTable::default(), &mut rng) .unwrap(); - let keypair2 = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng); + let keypair2 = PrivateKey::new_with_rng(Algorithm::Ed25519, &mut rng); let biscuit2 = biscuit1 - .append_with_keypair( + .append_with_key( &keypair2, block!( r#" @@ -636,7 +636,7 @@ fn different_root_key(target: &str, root: &KeyPair, test: bool) -> TestResult { } } -fn invalid_signature_format(target: &str, root: &KeyPair, test: bool) -> TestResult { +fn invalid_signature_format(target: &str, root: &PrivateKey, test: bool) -> TestResult { let mut rng: StdRng = SeedableRng::seed_from_u64(1234); let title = "invalid signature format".to_string(); let filename = "test003_invalid_signature_format".to_string(); @@ -651,9 +651,9 @@ fn invalid_signature_format(target: &str, root: &KeyPair, test: bool) -> TestRes .build_with_rng(root, SymbolTable::default(), &mut rng) .unwrap(); - let keypair2 = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng); + let keypair2 = PrivateKey::new_with_rng(Algorithm::Ed25519, &mut rng); let biscuit2 = biscuit1 - .append_with_keypair( + .append_with_key( &keypair2, block!(r#"check if resource($0), operation("read"), right($0, "read")"#), ) @@ -686,7 +686,7 @@ fn invalid_signature_format(target: &str, root: &KeyPair, test: bool) -> TestRes } } -fn random_block(target: &str, root: &KeyPair, test: bool) -> TestResult { +fn random_block(target: &str, root: &PrivateKey, test: bool) -> TestResult { let mut rng: StdRng = SeedableRng::seed_from_u64(1234); let title = "random block".to_string(); let filename = "test004_random_block".to_string(); @@ -701,9 +701,9 @@ fn random_block(target: &str, root: &KeyPair, test: bool) -> TestResult { .build_with_rng(root, SymbolTable::default(), &mut rng) .unwrap(); - let keypair2 = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng); + let keypair2 = PrivateKey::new_with_rng(Algorithm::Ed25519, &mut rng); let biscuit2 = biscuit1 - .append_with_keypair( + .append_with_key( &keypair2, block!(r#"check if resource($0), operation("read"), right($0, "read")"#), ) @@ -739,7 +739,7 @@ fn random_block(target: &str, root: &KeyPair, test: bool) -> TestResult { } } -fn invalid_signature(target: &str, root: &KeyPair, test: bool) -> TestResult { +fn invalid_signature(target: &str, root: &PrivateKey, test: bool) -> TestResult { let mut rng: StdRng = SeedableRng::seed_from_u64(1234); let title = "invalid signature".to_string(); let filename = "test005_invalid_signature".to_string(); @@ -754,9 +754,9 @@ fn invalid_signature(target: &str, root: &KeyPair, test: bool) -> TestResult { .build_with_rng(root, SymbolTable::default(), &mut rng) .unwrap(); - let keypair2 = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng); + let keypair2 = PrivateKey::new_with_rng(Algorithm::Ed25519, &mut rng); let biscuit2 = biscuit1 - .append_with_keypair( + .append_with_key( &keypair2, block!(r#"check if resource($0), operation("read"), right($0, "read")"#), ) @@ -791,7 +791,7 @@ fn invalid_signature(target: &str, root: &KeyPair, test: bool) -> TestResult { } } -fn reordered_blocks(target: &str, root: &KeyPair, test: bool) -> TestResult { +fn reordered_blocks(target: &str, root: &PrivateKey, test: bool) -> TestResult { let mut rng: StdRng = SeedableRng::seed_from_u64(1234); let title = "reordered blocks".to_string(); let filename = "test006_reordered_blocks".to_string(); @@ -806,17 +806,17 @@ fn reordered_blocks(target: &str, root: &KeyPair, test: bool) -> TestResult { .build_with_rng(root, SymbolTable::default(), &mut rng) .unwrap(); - let keypair2 = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng); + let keypair2 = PrivateKey::new_with_rng(Algorithm::Ed25519, &mut rng); let biscuit2 = biscuit1 - .append_with_keypair( + .append_with_key( &keypair2, block!(r#"check if resource($0), operation("read"), right($0, "read")"#), ) .unwrap(); - let keypair3 = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng); + let keypair3 = PrivateKey::new_with_rng(Algorithm::Ed25519, &mut rng); let biscuit3 = biscuit2 - .append_with_keypair(&keypair3, block!(r#"check if resource("file1")"#)) + .append_with_key(&keypair3, block!(r#"check if resource("file1")"#)) .unwrap(); let token = print_blocks(&biscuit3); @@ -848,7 +848,7 @@ fn reordered_blocks(target: &str, root: &KeyPair, test: bool) -> TestResult { } } -fn scoped_rules(target: &str, root: &KeyPair, test: bool) -> TestResult { +fn scoped_rules(target: &str, root: &PrivateKey, test: bool) -> TestResult { let mut rng: StdRng = SeedableRng::seed_from_u64(1234); let title = "scoped rules".to_string(); let filename = "test007_scoped_rules".to_string(); @@ -862,9 +862,9 @@ fn scoped_rules(target: &str, root: &KeyPair, test: bool) -> TestResult { .build_with_rng(root, SymbolTable::default(), &mut rng) .unwrap(); - let keypair2 = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng); + let keypair2 = PrivateKey::new_with_rng(Algorithm::Ed25519, &mut rng); let biscuit2 = biscuit1 - .append_with_keypair( + .append_with_key( &keypair2, block!( r#" @@ -879,8 +879,8 @@ fn scoped_rules(target: &str, root: &KeyPair, test: bool) -> TestResult { .fact(r#"owner("alice", "file2")"#) .unwrap(); - let keypair3 = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng); - let biscuit3 = biscuit2.append_with_keypair(&keypair3, block3).unwrap(); + let keypair3 = PrivateKey::new_with_rng(Algorithm::Ed25519, &mut rng); + let biscuit3 = biscuit2.append_with_key(&keypair3, block3).unwrap(); let token = print_blocks(&biscuit3); let data = write_or_load_testcase(target, &filename, root, &biscuit3, test); @@ -907,7 +907,7 @@ fn scoped_rules(target: &str, root: &KeyPair, test: bool) -> TestResult { } } -fn scoped_checks(target: &str, root: &KeyPair, test: bool) -> TestResult { +fn scoped_checks(target: &str, root: &PrivateKey, test: bool) -> TestResult { let mut rng: StdRng = SeedableRng::seed_from_u64(1234); let title = "scoped checks".to_string(); let filename = "test008_scoped_checks".to_string(); @@ -920,17 +920,17 @@ fn scoped_checks(target: &str, root: &KeyPair, test: bool) -> TestResult { .build_with_rng(root, SymbolTable::default(), &mut rng) .unwrap(); - let keypair2 = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng); + let keypair2 = PrivateKey::new_with_rng(Algorithm::Ed25519, &mut rng); let biscuit2 = biscuit1 - .append_with_keypair( + .append_with_key( &keypair2, block!(r#"check if resource($0), operation("read"), right($0, "read")"#), ) .unwrap(); - let keypair3 = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng); + let keypair3 = PrivateKey::new_with_rng(Algorithm::Ed25519, &mut rng); let biscuit3 = biscuit2 - .append_with_keypair(&keypair3, block!(r#"right("file2", "read")"#)) + .append_with_key(&keypair3, block!(r#"right("file2", "read")"#)) .unwrap(); let token = print_blocks(&biscuit3); @@ -958,7 +958,7 @@ fn scoped_checks(target: &str, root: &KeyPair, test: bool) -> TestResult { } } -fn expired_token(target: &str, root: &KeyPair, test: bool) -> TestResult { +fn expired_token(target: &str, root: &PrivateKey, test: bool) -> TestResult { let mut rng: StdRng = SeedableRng::seed_from_u64(1234); let title = "expired token".to_string(); let filename = "test009_expired_token".to_string(); @@ -976,8 +976,8 @@ fn expired_token(target: &str, root: &KeyPair, test: bool) -> TestResult { .unwrap(), ); - let keypair2 = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng); - let biscuit2 = biscuit1.append_with_keypair(&keypair2, block2).unwrap(); + let keypair2 = PrivateKey::new_with_rng(Algorithm::Ed25519, &mut rng); + let biscuit2 = biscuit1.append_with_key(&keypair2, block2).unwrap(); let token = print_blocks(&biscuit2); let data = write_or_load_testcase(target, &filename, root, &biscuit2, test); @@ -1005,7 +1005,7 @@ fn expired_token(target: &str, root: &KeyPair, test: bool) -> TestResult { } } -fn authorizer_scope(target: &str, root: &KeyPair, test: bool) -> TestResult { +fn authorizer_scope(target: &str, root: &PrivateKey, test: bool) -> TestResult { let mut rng: StdRng = SeedableRng::seed_from_u64(1234); let title = "authorizer scope".to_string(); let filename = "test010_authorizer_scope".to_string(); @@ -1018,9 +1018,9 @@ fn authorizer_scope(target: &str, root: &KeyPair, test: bool) -> TestResult { .build_with_rng(root, SymbolTable::default(), &mut rng) .unwrap(); - let keypair2 = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng); + let keypair2 = PrivateKey::new_with_rng(Algorithm::Ed25519, &mut rng); let biscuit2 = biscuit1 - .append_with_keypair(&keypair2, block!(r#"right("file2", "read")"#)) + .append_with_key(&keypair2, block!(r#"right("file2", "read")"#)) .unwrap(); let token = print_blocks(&biscuit2); @@ -1049,7 +1049,7 @@ fn authorizer_scope(target: &str, root: &KeyPair, test: bool) -> TestResult { } } -fn authorizer_authority_checks(target: &str, root: &KeyPair, test: bool) -> TestResult { +fn authorizer_authority_checks(target: &str, root: &PrivateKey, test: bool) -> TestResult { let mut rng: StdRng = SeedableRng::seed_from_u64(1234); let title = "authorizer authority checks".to_string(); let filename = "test011_authorizer_authority_caveats".to_string(); @@ -1088,7 +1088,7 @@ fn authorizer_authority_checks(target: &str, root: &KeyPair, test: bool) -> Test } } -fn authority_checks(target: &str, root: &KeyPair, test: bool) -> TestResult { +fn authority_checks(target: &str, root: &PrivateKey, test: bool) -> TestResult { let mut rng: StdRng = SeedableRng::seed_from_u64(1234); let title = "authority checks".to_string(); let filename = "test012_authority_caveats".to_string(); @@ -1135,7 +1135,7 @@ fn authority_checks(target: &str, root: &KeyPair, test: bool) -> TestResult { } } -fn block_rules(target: &str, root: &KeyPair, test: bool) -> TestResult { +fn block_rules(target: &str, root: &PrivateKey, test: bool) -> TestResult { let mut rng: StdRng = SeedableRng::seed_from_u64(1234); let title = "block rules".to_string(); let filename = "test013_block_rules".to_string(); @@ -1149,8 +1149,8 @@ fn block_rules(target: &str, root: &KeyPair, test: bool) -> TestResult { .build_with_rng(root, SymbolTable::default(), &mut rng) .unwrap(); - let keypair2 = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng); - let biscuit2 = biscuit1.append_with_keypair(&keypair2, block!(r#" + let keypair2 = PrivateKey::new_with_rng(Algorithm::Ed25519, &mut rng); + let biscuit2 = biscuit1.append_with_key(&keypair2, block!(r#" // generate valid_date("file1") if before Thursday, December 31, 2030 12:59:59 PM UTC valid_date("file1") <- time($0), resource("file1"), $0 <= 2030-12-31T12:59:59Z; @@ -1199,7 +1199,7 @@ fn block_rules(target: &str, root: &KeyPair, test: bool) -> TestResult { } } -fn regex_constraint(target: &str, root: &KeyPair, test: bool) -> TestResult { +fn regex_constraint(target: &str, root: &PrivateKey, test: bool) -> TestResult { let mut rng: StdRng = SeedableRng::seed_from_u64(1234); let title = "regex_constraint".to_string(); let filename = "test014_regex_constraint".to_string(); @@ -1229,7 +1229,7 @@ fn regex_constraint(target: &str, root: &KeyPair, test: bool) -> TestResult { } } -fn multi_queries_checks(target: &str, root: &KeyPair, test: bool) -> TestResult { +fn multi_queries_checks(target: &str, root: &PrivateKey, test: bool) -> TestResult { let mut rng: StdRng = SeedableRng::seed_from_u64(1234); let title = "multi queries checks".to_string(); let filename = "test015_multi_queries_caveats".to_string(); @@ -1258,7 +1258,7 @@ fn multi_queries_checks(target: &str, root: &KeyPair, test: bool) -> TestResult } } -fn check_head_name(target: &str, root: &KeyPair, test: bool) -> TestResult { +fn check_head_name(target: &str, root: &PrivateKey, test: bool) -> TestResult { let mut rng: StdRng = SeedableRng::seed_from_u64(1234); let title = "check head name should be independent from fact names".to_string(); let filename = "test016_caveat_head_name".to_string(); @@ -1267,9 +1267,9 @@ fn check_head_name(target: &str, root: &KeyPair, test: bool) -> TestResult { .build_with_rng(root, SymbolTable::default(), &mut rng) .unwrap(); - let keypair2 = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng); + let keypair2 = PrivateKey::new_with_rng(Algorithm::Ed25519, &mut rng); let biscuit2 = biscuit1 - .append_with_keypair(&keypair2, block!(r#"query("test")"#)) + .append_with_key(&keypair2, block!(r#"query("test")"#)) .unwrap(); let token = print_blocks(&biscuit2); @@ -1288,7 +1288,7 @@ fn check_head_name(target: &str, root: &KeyPair, test: bool) -> TestResult { } } -fn expressions(target: &str, root: &KeyPair, test: bool) -> TestResult { +fn expressions(target: &str, root: &PrivateKey, test: bool) -> TestResult { let mut rng: StdRng = SeedableRng::seed_from_u64(1234); let title = "test expression syntax and all available operations".to_string(); let filename = "test017_expressions".to_string(); @@ -1389,7 +1389,7 @@ fn expressions(target: &str, root: &KeyPair, test: bool) -> TestResult { } } -fn unbound_variables_in_rule(target: &str, root: &KeyPair, test: bool) -> TestResult { +fn unbound_variables_in_rule(target: &str, root: &PrivateKey, test: bool) -> TestResult { let mut rng: StdRng = SeedableRng::seed_from_u64(1234); let title = "invalid block rule with unbound_variables".to_string(); let filename = "test018_unbound_variables_in_rule".to_string(); @@ -1407,8 +1407,8 @@ fn unbound_variables_in_rule(target: &str, root: &KeyPair, test: bool) -> TestRe )) .unwrap(); - let keypair2 = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng); - let biscuit2 = biscuit1.append_with_keypair(&keypair2, block2).unwrap(); + let keypair2 = PrivateKey::new_with_rng(Algorithm::Ed25519, &mut rng); + let biscuit2 = biscuit1.append_with_key(&keypair2, block2).unwrap(); let token = print_blocks(&biscuit2); let data = write_or_load_testcase(target, &filename, root, &biscuit2, test); @@ -1426,7 +1426,7 @@ fn unbound_variables_in_rule(target: &str, root: &KeyPair, test: bool) -> TestRe } } -fn generating_ambient_from_variables(target: &str, root: &KeyPair, test: bool) -> TestResult { +fn generating_ambient_from_variables(target: &str, root: &PrivateKey, test: bool) -> TestResult { let mut rng: StdRng = SeedableRng::seed_from_u64(1234); let title = "invalid block rule generating an #authority or #ambient symbol with a variable" .to_string(); @@ -1436,9 +1436,9 @@ fn generating_ambient_from_variables(target: &str, root: &KeyPair, test: bool) - .build_with_rng(root, SymbolTable::default(), &mut rng) .unwrap(); - let keypair2 = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng); + let keypair2 = PrivateKey::new_with_rng(Algorithm::Ed25519, &mut rng); let biscuit2 = biscuit1 - .append_with_keypair(&keypair2, block!(r#"operation("read") <- operation($any)"#)) + .append_with_key(&keypair2, block!(r#"operation("read") <- operation($any)"#)) .unwrap(); let token = print_blocks(&biscuit2); @@ -1457,7 +1457,7 @@ fn generating_ambient_from_variables(target: &str, root: &KeyPair, test: bool) - } } -fn sealed_token(target: &str, root: &KeyPair, test: bool) -> TestResult { +fn sealed_token(target: &str, root: &PrivateKey, test: bool) -> TestResult { let mut rng: StdRng = SeedableRng::seed_from_u64(1234); let title = "sealed token".to_string(); let filename = "test020_sealed".to_string(); @@ -1472,9 +1472,9 @@ fn sealed_token(target: &str, root: &KeyPair, test: bool) -> TestResult { .build_with_rng(root, SymbolTable::default(), &mut rng) .unwrap(); - let keypair2 = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng); + let keypair2 = PrivateKey::new_with_rng(Algorithm::Ed25519, &mut rng); let biscuit2 = biscuit1 - .append_with_keypair( + .append_with_key( &keypair2, block!(r#"check if resource($0), operation("read"), right($0, "read")"#), ) @@ -1514,7 +1514,7 @@ fn sealed_token(target: &str, root: &KeyPair, test: bool) -> TestResult { } } -fn parsing(target: &str, root: &KeyPair, test: bool) -> TestResult { +fn parsing(target: &str, root: &PrivateKey, test: bool) -> TestResult { let mut rng: StdRng = SeedableRng::seed_from_u64(1234); let title = "parsing".to_string(); let filename = "test021_parsing".to_string(); @@ -1544,7 +1544,7 @@ fn parsing(target: &str, root: &KeyPair, test: bool) -> TestResult { } } -fn default_symbols(target: &str, root: &KeyPair, test: bool) -> TestResult { +fn default_symbols(target: &str, root: &PrivateKey, test: bool) -> TestResult { let mut rng: StdRng = SeedableRng::seed_from_u64(1234); let title = "default_symbols".to_string(); let filename = "test022_default_symbols".to_string(); @@ -1587,7 +1587,7 @@ fn default_symbols(target: &str, root: &KeyPair, test: bool) -> TestResult { } } -fn execution_scope(target: &str, root: &KeyPair, test: bool) -> TestResult { +fn execution_scope(target: &str, root: &PrivateKey, test: bool) -> TestResult { let mut rng: StdRng = SeedableRng::seed_from_u64(1234); let title = "execution scope".to_string(); let filename = "test023_execution_scope".to_string(); @@ -1596,14 +1596,14 @@ fn execution_scope(target: &str, root: &KeyPair, test: bool) -> TestResult { .build_with_rng(root, SymbolTable::default(), &mut rng) .unwrap(); - let keypair2 = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng); + let keypair2 = PrivateKey::new_with_rng(Algorithm::Ed25519, &mut rng); let biscuit2 = biscuit1 - .append_with_keypair(&keypair2, block!("block1_fact(1)")) + .append_with_key(&keypair2, block!("block1_fact(1)")) .unwrap(); - let keypair3 = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng); + let keypair3 = PrivateKey::new_with_rng(Algorithm::Ed25519, &mut rng); let biscuit3 = biscuit2 - .append_with_keypair( + .append_with_key( &keypair3, block!( r#" @@ -1631,14 +1631,14 @@ fn execution_scope(target: &str, root: &KeyPair, test: bool) -> TestResult { } } -fn third_party(target: &str, root: &KeyPair, test: bool) -> TestResult { +fn third_party(target: &str, root: &PrivateKey, test: bool) -> TestResult { let mut rng: StdRng = SeedableRng::seed_from_u64(1234); let title = "third party".to_string(); let filename = "test024_third_party".to_string(); // keep this to conserve the same RNG state - let _ = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng); - let external = KeyPair::from( + let _ = PrivateKey::new_with_rng(Algorithm::Ed25519, &mut rng); + let external = PrivateKey::from( &PrivateKey::from_bytes_hex( "12aca40167fbdd1a11037e9fd440e3d510d9d9dea70a6646aa4aaf84d718d75a", Algorithm::Ed25519, @@ -1669,9 +1669,9 @@ fn third_party(target: &str, root: &KeyPair, test: bool) -> TestResult { ), ) .unwrap(); - let keypair2 = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng); + let keypair2 = PrivateKey::new_with_rng(Algorithm::Ed25519, &mut rng); let biscuit2 = biscuit1 - .append_third_party_with_keypair(external.public(), res, keypair2) + .append_third_party_with_key(external.public(), res, keypair2) .unwrap(); let token = print_blocks(&biscuit2); @@ -1692,7 +1692,7 @@ fn third_party(target: &str, root: &KeyPair, test: bool) -> TestResult { } } -fn check_all(target: &str, root: &KeyPair, test: bool) -> TestResult { +fn check_all(target: &str, root: &PrivateKey, test: bool) -> TestResult { let mut rng: StdRng = SeedableRng::seed_from_u64(1234); let title = "block rules".to_string(); let filename = "test025_check_all".to_string(); @@ -1756,31 +1756,31 @@ fn check_all(target: &str, root: &KeyPair, test: bool) -> TestResult { } } -fn public_keys_interning(target: &str, root: &KeyPair, test: bool) -> TestResult { +fn public_keys_interning(target: &str, root: &PrivateKey, test: bool) -> TestResult { let mut rng: StdRng = SeedableRng::seed_from_u64(1234); let title = "public keys interning".to_string(); let filename = "test026_public_keys_interning".to_string(); // keep this to conserve the same RNG state - let _ = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng); - let _ = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng); - let _ = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng); + let _ = PrivateKey::new_with_rng(Algorithm::Ed25519, &mut rng); + let _ = PrivateKey::new_with_rng(Algorithm::Ed25519, &mut rng); + let _ = PrivateKey::new_with_rng(Algorithm::Ed25519, &mut rng); - let external1 = KeyPair::from( + let external1 = PrivateKey::from( &PrivateKey::from_bytes_hex( "12aca40167fbdd1a11037e9fd440e3d510d9d9dea70a6646aa4aaf84d718d75a", Algorithm::Ed25519, ) .unwrap(), ); - let external2 = KeyPair::from( + let external2 = PrivateKey::from( &PrivateKey::from_bytes_hex( "018e3f6864a1c9ffc2e67939a835d41c808b0084b3d7babf9364f674db19eeb3", Algorithm::Ed25519, ) .unwrap(), ); - let external3 = KeyPair::from( + let external3 = PrivateKey::from( &PrivateKey::from_bytes_hex( "88c637e4844fc3f52290889dc961cb15d809c994b5ef71990d6a2f989bd2f02c", Algorithm::Ed25519, @@ -1817,10 +1817,10 @@ fn public_keys_interning(target: &str, root: &KeyPair, test: bool) -> TestResult .unwrap(); let biscuit2 = biscuit1 - .append_third_party_with_keypair( + .append_third_party_with_key( external1.public(), res1, - KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng), + PrivateKey::new_with_rng(Algorithm::Ed25519, &mut rng), ) .unwrap(); @@ -1841,10 +1841,10 @@ fn public_keys_interning(target: &str, root: &KeyPair, test: bool) -> TestResult .unwrap(); let biscuit3 = biscuit2 - .append_third_party_with_keypair( + .append_third_party_with_key( external2.public(), res2, - KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng), + PrivateKey::new_with_rng(Algorithm::Ed25519, &mut rng), ) .unwrap(); @@ -1865,16 +1865,16 @@ fn public_keys_interning(target: &str, root: &KeyPair, test: bool) -> TestResult .unwrap(); let biscuit4 = biscuit3 - .append_third_party_with_keypair( + .append_third_party_with_key( external2.public(), res3, - KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng), + PrivateKey::new_with_rng(Algorithm::Ed25519, &mut rng), ) .unwrap(); let biscuit5 = biscuit4 - .append_with_keypair( - &KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng), + .append_with_key( + &PrivateKey::new_with_rng(Algorithm::Ed25519, &mut rng), block!( r#" query(4); @@ -1919,7 +1919,7 @@ fn public_keys_interning(target: &str, root: &KeyPair, test: bool) -> TestResult } } -fn integer_wraparound(target: &str, root: &KeyPair, test: bool) -> TestResult { +fn integer_wraparound(target: &str, root: &PrivateKey, test: bool) -> TestResult { let mut rng: StdRng = SeedableRng::seed_from_u64(1234); let title = "integer wraparound".to_string(); let filename = "test027_integer_wraparound".to_string(); @@ -1952,7 +1952,7 @@ fn integer_wraparound(target: &str, root: &KeyPair, test: bool) -> TestResult { } } -fn expressions_v4(target: &str, root: &KeyPair, test: bool) -> TestResult { +fn expressions_v4(target: &str, root: &PrivateKey, test: bool) -> TestResult { let mut rng: StdRng = SeedableRng::seed_from_u64(1234); let title = "test expression syntax and all available operations (v4 blocks)".to_string(); let filename = "test028_expressions_v4".to_string(); @@ -1995,7 +1995,7 @@ fn expressions_v4(target: &str, root: &KeyPair, test: bool) -> TestResult { } } -fn reject_if(target: &str, root: &KeyPair, test: bool) -> TestResult { +fn reject_if(target: &str, root: &PrivateKey, test: bool) -> TestResult { let mut rng: StdRng = SeedableRng::seed_from_u64(1234); let title = "test reject if".to_string(); let filename = "test029_reject_if".to_string(); @@ -2025,7 +2025,7 @@ fn reject_if(target: &str, root: &KeyPair, test: bool) -> TestResult { } } -fn null(target: &str, root: &KeyPair, test: bool) -> TestResult { +fn null(target: &str, root: &PrivateKey, test: bool) -> TestResult { let mut rng: StdRng = SeedableRng::seed_from_u64(1234); let title = "test null".to_string(); let filename = "test030_null".to_string(); @@ -2068,7 +2068,7 @@ fn null(target: &str, root: &KeyPair, test: bool) -> TestResult { } } -fn heterogeneous_equal(target: &str, root: &KeyPair, test: bool) -> TestResult { +fn heterogeneous_equal(target: &str, root: &PrivateKey, test: bool) -> TestResult { let mut rng: StdRng = SeedableRng::seed_from_u64(1234); let title = "test heterogeneous equal".to_string(); let filename = "test031_heterogeneous_equal".to_string(); @@ -2126,7 +2126,7 @@ fn heterogeneous_equal(target: &str, root: &KeyPair, test: bool) -> TestResult { } } -fn closures(target: &str, root: &KeyPair, test: bool) -> TestResult { +fn closures(target: &str, root: &PrivateKey, test: bool) -> TestResult { let mut rng: StdRng = SeedableRng::seed_from_u64(1234); let title = "test laziness and closures".to_string(); let filename = "test032_laziness_closures".to_string(); @@ -2184,7 +2184,7 @@ fn closures(target: &str, root: &KeyPair, test: bool) -> TestResult { } } -fn type_of(target: &str, root: &KeyPair, test: bool) -> TestResult { +fn type_of(target: &str, root: &PrivateKey, test: bool) -> TestResult { let mut rng: StdRng = SeedableRng::seed_from_u64(1234); let title = "test .type()".to_string(); let filename = "test033_typeof".to_string(); @@ -2239,7 +2239,7 @@ fn type_of(target: &str, root: &KeyPair, test: bool) -> TestResult { } } -fn array_map(target: &str, root: &KeyPair, test: bool) -> TestResult { +fn array_map(target: &str, root: &PrivateKey, test: bool) -> TestResult { let mut rng: StdRng = SeedableRng::seed_from_u64(1234); let title = "test array and map operations".to_string(); let filename = "test034_array_map".to_string(); @@ -2298,7 +2298,7 @@ fn array_map(target: &str, root: &KeyPair, test: bool) -> TestResult { } } -fn ffi(target: &str, root: &KeyPair, test: bool) -> TestResult { +fn ffi(target: &str, root: &PrivateKey, test: bool) -> TestResult { let mut rng: StdRng = SeedableRng::seed_from_u64(1234); let title = "test ffi calls (v6 blocks)".to_string(); let filename = "test035_ffi".to_string(); @@ -2345,12 +2345,12 @@ fn ffi(target: &str, root: &KeyPair, test: bool) -> TestResult { } } -fn secp256r1(target: &str, root: &KeyPair, test: bool) -> TestResult { +fn secp256r1(target: &str, root: &PrivateKey, test: bool) -> TestResult { let mut rng: StdRng = SeedableRng::seed_from_u64(1234); let title = "ECDSA secp256r1 signatures".to_string(); let filename = "test036_secp256r1".to_string(); - let keypair2 = KeyPair::new_with_rng(Algorithm::Secp256r1, &mut rng); + let keypair2 = PrivateKey::new_with_rng(Algorithm::Secp256r1, &mut rng); let biscuit1 = biscuit!( r#" right("file1", "read"); @@ -2361,9 +2361,9 @@ fn secp256r1(target: &str, root: &KeyPair, test: bool) -> TestResult { .build_with_key_pair(root, SymbolTable::default(), &keypair2) .unwrap(); - let keypair3 = KeyPair::new_with_rng(Algorithm::Secp256r1, &mut rng); + let keypair3 = PrivateKey::new_with_rng(Algorithm::Secp256r1, &mut rng); let biscuit2 = biscuit1 - .append_with_keypair( + .append_with_key( &keypair3, block!( r#" @@ -2399,13 +2399,13 @@ fn secp256r1(target: &str, root: &KeyPair, test: bool) -> TestResult { } } -fn secp256r1_third_party(target: &str, root: &KeyPair, test: bool) -> TestResult { +fn secp256r1_third_party(target: &str, root: &PrivateKey, test: bool) -> TestResult { let mut rng: StdRng = SeedableRng::seed_from_u64(1234); let title = "ECDSA secp256r1 signature on third-party block".to_string(); let filename = "test037_secp256r1_third_party".to_string(); - let external_keypair = KeyPair::new_with_rng(Algorithm::Secp256r1, &mut rng); - let keypair2 = KeyPair::new_with_rng(Algorithm::Secp256r1, &mut rng); + let external_keypair = PrivateKey::new_with_rng(Algorithm::Secp256r1, &mut rng); + let keypair2 = PrivateKey::new_with_rng(Algorithm::Secp256r1, &mut rng); let biscuit1 = biscuit!( r#" right("file1", "read"); @@ -2427,10 +2427,10 @@ fn secp256r1_third_party(target: &str, root: &KeyPair, test: bool) -> TestResult ), ) .unwrap(); - let keypair3 = KeyPair::new_with_rng(Algorithm::Secp256r1, &mut rng); + let keypair3 = PrivateKey::new_with_rng(Algorithm::Secp256r1, &mut rng); let biscuit2 = biscuit1 - .append_third_party_with_keypair(external_keypair.public(), block, keypair3) + .append_third_party_with_key(external_keypair.public(), block, keypair3) .unwrap(); let token = print_blocks(&biscuit2); @@ -2459,7 +2459,7 @@ fn secp256r1_third_party(target: &str, root: &KeyPair, test: bool) -> TestResult } } -fn try_op(target: &str, root: &KeyPair, test: bool) -> TestResult { +fn try_op(target: &str, root: &PrivateKey, test: bool) -> TestResult { let mut rng: StdRng = SeedableRng::seed_from_u64(1234); let title = "test try operation".to_string(); let filename = "test038_try_op".to_string(); diff --git a/biscuit-auth/examples/third_party.rs b/biscuit-auth/examples/third_party.rs index c572d214..ff5954e1 100644 --- a/biscuit-auth/examples/third_party.rs +++ b/biscuit-auth/examples/third_party.rs @@ -8,14 +8,14 @@ use biscuit_auth::{ builder::{Algorithm, AuthorizerBuilder, BlockBuilder}, builder_ext::AuthorizerExt, datalog::{RunLimits, SymbolTable}, - Biscuit, KeyPair, + Biscuit, PrivateKey, }; use rand::{prelude::StdRng, SeedableRng}; fn main() { let mut rng: StdRng = SeedableRng::seed_from_u64(0); - let root = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng); - let external = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng); + let root = PrivateKey::new_with_rng(Algorithm::Ed25519, &mut rng); + let external = PrivateKey::new_with_rng(Algorithm::Ed25519, &mut rng); let external_pub = hex::encode(external.public().to_bytes()); let biscuit1 = Biscuit::builder() diff --git a/biscuit-auth/src/bwk.rs b/biscuit-auth/src/bwk.rs index 8425b06c..437c2ae7 100644 --- a/biscuit-auth/src/bwk.rs +++ b/biscuit-auth/src/bwk.rs @@ -59,14 +59,14 @@ impl TryFrom for BiscuitWebKey { #[cfg(test)] mod tests { - use crate::KeyPair; + use crate::PrivateKey; use chrono::Utc; use super::*; #[test] fn roundtrips() { - let keypair = KeyPair::new(); + let keypair = PrivateKey::new(); let bwk = BiscuitWebKey { public_key: keypair.public(), key_id: 12, @@ -78,7 +78,7 @@ mod tests { let parsed: BiscuitWebKey = serde_json::from_str(&serialized).unwrap(); assert_eq!(parsed, bwk); - let keypair = KeyPair::new_with_algorithm(Algorithm::Secp256r1); + let keypair = PrivateKey::new_with_algorithm(Algorithm::Secp256r1); let bwk = BiscuitWebKey { public_key: keypair.public(), key_id: 0, @@ -90,7 +90,7 @@ mod tests { let parsed: BiscuitWebKey = serde_json::from_str(&serialized).unwrap(); assert_eq!(parsed, bwk); - let keypair = KeyPair::new(); + let keypair = PrivateKey::new(); let bwk = BiscuitWebKey { public_key: keypair.public(), key_id: 0, diff --git a/biscuit-auth/src/crypto/ed25519.rs b/biscuit-auth/src/crypto/ed25519.rs index 36fb86b5..5ffcb574 100644 --- a/biscuit-auth/src/crypto/ed25519.rs +++ b/biscuit-auth/src/crypto/ed25519.rs @@ -11,50 +11,33 @@ //! //! The implementation is based on [ed25519_dalek](https://github.com/dalek-cryptography/ed25519-dalek). #![allow(non_snake_case)] -use crate::error::Format; +use std::convert::TryInto; +use std::hash::Hash; -use super::error; -use super::Signature; #[cfg(feature = "pem")] use ed25519_dalek::pkcs8::DecodePrivateKey; use ed25519_dalek::Signer; use ed25519_dalek::*; use rand_core::{CryptoRng, RngCore}; -use std::{convert::TryInto, hash::Hash, ops::Drop}; -use zeroize::Zeroize; -/// pair of cryptographic keys used to sign a token's block +use crate::error::Format; + +use super::error; +use super::Signature; + +/// the private part of an ed25519 key pair #[derive(Debug, PartialEq)] -pub struct KeyPair { - pub(super) kp: ed25519_dalek::SigningKey, -} +pub struct PrivateKey(pub(crate) ed25519_dalek::SigningKey); -impl KeyPair { +impl PrivateKey { pub fn new_with_rng(rng: &mut T) -> Self { let kp = ed25519_dalek::SigningKey::generate(rng); - KeyPair { kp } - } - - pub fn from(key: &PrivateKey) -> Self { - KeyPair { - kp: ed25519_dalek::SigningKey::from_bytes(&key.0), - } - } - - /// deserializes from a byte array - pub fn from_bytes(bytes: &[u8]) -> Result { - let bytes: [u8; 32] = bytes - .try_into() - .map_err(|_| Format::InvalidKeySize(bytes.len()))?; - - Ok(KeyPair { - kp: ed25519_dalek::SigningKey::from_bytes(&bytes), - }) + Self(kp) } pub fn sign(&self, data: &[u8]) -> Result { Ok(Signature( - self.kp + self.0 .try_sign(data) .map_err(|s| s.to_string()) .map_err(error::Signature::InvalidSignatureGeneration) @@ -64,33 +47,25 @@ impl KeyPair { )) } - pub fn private(&self) -> PrivateKey { - PrivateKey(self.kp.to_bytes()) - } - - pub fn public(&self) -> PublicKey { - PublicKey(self.kp.verifying_key()) - } - #[cfg(feature = "pem")] pub fn from_private_key_der(bytes: &[u8]) -> Result { let kp = SigningKey::from_pkcs8_der(bytes) .map_err(|e| error::Format::InvalidKey(e.to_string()))?; - Ok(KeyPair { kp }) + Ok(Self(kp)) } #[cfg(feature = "pem")] pub fn from_private_key_pem(str: &str) -> Result { let kp = SigningKey::from_pkcs8_pem(str) .map_err(|e| error::Format::InvalidKey(e.to_string()))?; - Ok(KeyPair { kp }) + Ok(Self(kp)) } #[cfg(feature = "pem")] pub fn to_private_key_der(&self) -> Result>, error::Format> { use ed25519_dalek::pkcs8::EncodePrivateKey; let kp = self - .kp + .0 .to_pkcs8_der() .map_err(|e| error::Format::PKCS8(e.to_string()))?; Ok(kp.to_bytes()) @@ -101,21 +76,15 @@ impl KeyPair { use ed25519_dalek::pkcs8::EncodePrivateKey; use p256::pkcs8::LineEnding; let kp = self - .kp + .0 .to_pkcs8_pem(LineEnding::LF) .map_err(|e| error::Format::PKCS8(e.to_string()))?; Ok(kp) } -} - -/// the private part of a [KeyPair] -#[derive(Debug, PartialEq)] -pub struct PrivateKey(pub(crate) ed25519_dalek::SecretKey); -impl PrivateKey { /// serializes to a byte array pub fn to_bytes(&self) -> Vec { - self.0.to_vec() + self.0.to_bytes().to_vec() } /// deserializes from a byte array @@ -123,27 +92,27 @@ impl PrivateKey { let bytes: [u8; 32] = bytes .try_into() .map_err(|_| Format::InvalidKeySize(bytes.len()))?; - Ok(PrivateKey(bytes)) + Ok(PrivateKey(SigningKey::from_bytes(&bytes))) } #[cfg(feature = "pem")] pub fn from_der(bytes: &[u8]) -> Result { let kp = SigningKey::from_pkcs8_der(bytes) .map_err(|e| error::Format::InvalidKey(e.to_string()))?; - Ok(PrivateKey(kp.to_bytes())) + Ok(PrivateKey(kp)) } #[cfg(feature = "pem")] pub fn from_pem(str: &str) -> Result { let kp = SigningKey::from_pkcs8_pem(str) .map_err(|e| error::Format::InvalidKey(e.to_string()))?; - Ok(PrivateKey(kp.to_bytes())) + Ok(PrivateKey(kp)) } #[cfg(feature = "pem")] pub fn to_der(&self) -> Result>, error::Format> { use ed25519_dalek::pkcs8::EncodePrivateKey; - let kp = ed25519_dalek::SigningKey::from_bytes(&self.0) + let kp = self.0 .to_pkcs8_der() .map_err(|e| error::Format::PKCS8(e.to_string()))?; Ok(kp.to_bytes()) @@ -153,7 +122,7 @@ impl PrivateKey { pub fn to_pem(&self) -> Result, error::Format> { use ed25519_dalek::pkcs8::EncodePrivateKey; use p256::pkcs8::LineEnding; - let kp = ed25519_dalek::SigningKey::from_bytes(&self.0) + let kp = self.0 .to_pkcs8_pem(LineEnding::LF) .map_err(|e| error::Format::PKCS8(e.to_string()))?; Ok(kp) @@ -161,23 +130,17 @@ impl PrivateKey { /// returns the matching public key pub fn public(&self) -> PublicKey { - PublicKey(SigningKey::from_bytes(&self.0).verifying_key()) + PublicKey(self.0.verifying_key()) } } -impl std::clone::Clone for PrivateKey { +impl Clone for PrivateKey { fn clone(&self) -> Self { PrivateKey::from_bytes(&self.to_bytes()).unwrap() } } -impl Drop for PrivateKey { - fn drop(&mut self) { - self.0.zeroize(); - } -} - -/// the public part of a [KeyPair] +/// the public part of an ed25519 keypair #[derive(Debug, Clone, Copy, Eq)] pub struct PublicKey(ed25519_dalek::VerifyingKey); diff --git a/biscuit-auth/src/crypto/mod.rs b/biscuit-auth/src/crypto/mod.rs index e0128032..556be5d3 100644 --- a/biscuit-auth/src/crypto/mod.rs +++ b/biscuit-auth/src/crypto/mod.rs @@ -25,57 +25,42 @@ use std::fmt; use std::hash::Hash; use std::str::FromStr; -/// pair of cryptographic keys used to sign a token's block -#[derive(Debug, PartialEq)] -pub enum KeyPair { - Ed25519(ed25519::KeyPair), - P256(p256::KeyPair), +/// the private part of a signing key pair +#[derive(Debug, Clone, PartialEq)] +pub enum PrivateKey { + Ed25519(ed25519::PrivateKey), + P256(p256::PrivateKey), } -impl KeyPair { - /// Create a new ed25519 keypair with the default OS RNG +impl PrivateKey { + /// Create a new ed25519 private key with the default OS RNG pub fn new() -> Self { Self::new_with_rng(Algorithm::Ed25519, &mut rand::rngs::OsRng) } - /// Create a new keypair with a chosen algorithm and the default OS RNG + /// Create a new private key with a chosen algorithm and the default OS RNG pub fn new_with_algorithm(algorithm: Algorithm) -> Self { Self::new_with_rng(algorithm, &mut rand::rngs::OsRng) } pub fn new_with_rng(algorithm: Algorithm, rng: &mut T) -> Self { match algorithm { - Algorithm::Ed25519 => KeyPair::Ed25519(ed25519::KeyPair::new_with_rng(rng)), - Algorithm::Secp256r1 => KeyPair::P256(p256::KeyPair::new_with_rng(rng)), + Algorithm::Ed25519 => PrivateKey::Ed25519(ed25519::PrivateKey::new_with_rng(rng)), + Algorithm::Secp256r1 => PrivateKey::P256(p256::PrivateKey::new_with_rng(rng)), } } pub fn from(key: &PrivateKey) -> Self { match key { - PrivateKey::Ed25519(key) => KeyPair::Ed25519(ed25519::KeyPair::from(key)), - PrivateKey::P256(key) => KeyPair::P256(p256::KeyPair::from(key)), - } - } - - /// deserializes from a byte array - pub fn from_bytes( - bytes: &[u8], - algorithm: schema::public_key::Algorithm, - ) -> Result { - match algorithm { - schema::public_key::Algorithm::Ed25519 => { - Ok(KeyPair::Ed25519(ed25519::KeyPair::from_bytes(bytes)?)) - } - schema::public_key::Algorithm::Secp256r1 => { - Ok(KeyPair::P256(p256::KeyPair::from_bytes(bytes)?)) - } + PrivateKey::Ed25519(key) => PrivateKey::Ed25519(key.clone()), + PrivateKey::P256(key) => PrivateKey::P256(key.clone()), } } pub fn sign(&self, data: &[u8]) -> Result { match self { - KeyPair::Ed25519(key) => key.sign(data), - KeyPair::P256(key) => key.sign(data), + PrivateKey::Ed25519(key) => key.sign(data), + PrivateKey::P256(key) => key.sign(data), } } @@ -85,10 +70,10 @@ impl KeyPair { algorithm: Algorithm, ) -> Result { match algorithm { - Algorithm::Ed25519 => Ok(KeyPair::Ed25519(ed25519::KeyPair::from_private_key_der( + Algorithm::Ed25519 => Ok(PrivateKey::Ed25519(ed25519::PrivateKey::from_private_key_der( bytes, )?)), - Algorithm::Secp256r1 => Ok(KeyPair::P256(p256::KeyPair::from_private_key_der(bytes)?)), + Algorithm::Secp256r1 => Ok(PrivateKey::P256(p256::PrivateKey::from_private_key_der(bytes)?)), } } @@ -103,10 +88,10 @@ impl KeyPair { algorithm: Algorithm, ) -> Result { match algorithm { - Algorithm::Ed25519 => Ok(KeyPair::Ed25519(ed25519::KeyPair::from_private_key_pem( + Algorithm::Ed25519 => Ok(PrivateKey::Ed25519(ed25519::PrivateKey::from_private_key_pem( str, )?)), - Algorithm::Secp256r1 => Ok(KeyPair::P256(p256::KeyPair::from_private_key_pem(str)?)), + Algorithm::Secp256r1 => Ok(PrivateKey::P256(p256::PrivateKey::from_private_key_pem(str)?)), } } @@ -118,71 +103,40 @@ impl KeyPair { #[cfg(feature = "pem")] pub fn to_private_key_der(&self) -> Result>, error::Format> { match self { - KeyPair::Ed25519(key) => key.to_private_key_der(), - KeyPair::P256(key) => key.to_private_key_der(), + PrivateKey::Ed25519(key) => key.to_private_key_der(), + PrivateKey::P256(key) => key.to_private_key_der(), } } #[cfg(feature = "pem")] pub fn to_private_key_pem(&self) -> Result, error::Format> { match self { - KeyPair::Ed25519(key) => key.to_private_key_pem(), - KeyPair::P256(key) => key.to_private_key_pem(), + PrivateKey::Ed25519(key) => key.to_private_key_pem(), + PrivateKey::P256(key) => key.to_private_key_pem(), } } pub fn private(&self) -> PrivateKey { match self { - KeyPair::Ed25519(key) => PrivateKey::Ed25519(key.private()), - KeyPair::P256(key) => PrivateKey::P256(key.private()), + PrivateKey::Ed25519(key) => PrivateKey::Ed25519(key.clone()), + PrivateKey::P256(key) => PrivateKey::P256(key.clone()), } } pub fn public(&self) -> PublicKey { match self { - KeyPair::Ed25519(key) => PublicKey::Ed25519(key.public()), - KeyPair::P256(key) => PublicKey::P256(key.public()), + PrivateKey::Ed25519(key) => PublicKey::Ed25519(key.public()), + PrivateKey::P256(key) => PublicKey::P256(key.public()), } } pub fn algorithm(&self) -> crate::format::schema::public_key::Algorithm { match self { - KeyPair::Ed25519(_) => crate::format::schema::public_key::Algorithm::Ed25519, - KeyPair::P256(_) => crate::format::schema::public_key::Algorithm::Secp256r1, - } - } -} - -impl std::default::Default for KeyPair { - fn default() -> Self { - Self::new() - } -} - -/// the private part of a [KeyPair] -#[derive(Debug, Clone, PartialEq)] -pub enum PrivateKey { - Ed25519(ed25519::PrivateKey), - P256(p256::PrivateKey), -} - -impl FromStr for PrivateKey { - type Err = error::Format; - fn from_str(s: &str) -> Result { - match s.split_once('/') { - Some(("ed25519-private", bytes)) => Self::from_bytes_hex(bytes, Algorithm::Ed25519), - Some(("secp256r1-private", bytes)) => Self::from_bytes_hex(bytes, Algorithm::Secp256r1), - Some((alg, _)) => Err(error::Format::InvalidKey(format!( - "Unsupported key algorithm {alg}" - ))), - None => Err(error::Format::InvalidKey( - "Missing key algorithm".to_string(), - )), + PrivateKey::Ed25519(_) => crate::format::schema::public_key::Algorithm::Ed25519, + PrivateKey::P256(_) => crate::format::schema::public_key::Algorithm::Secp256r1, } } -} -impl PrivateKey { /// serializes to a byte array pub fn to_bytes(&self) -> zeroize::Zeroizing> { match self { @@ -263,24 +217,32 @@ impl PrivateKey { PrivateKey::P256(key) => key.to_pem(), } } +} - /// returns the matching public key - pub fn public(&self) -> PublicKey { - match self { - PrivateKey::Ed25519(key) => PublicKey::Ed25519(key.public()), - PrivateKey::P256(key) => PublicKey::P256(key.public()), - } + +impl Default for PrivateKey { + fn default() -> Self { + Self::new() } +} - pub fn algorithm(&self) -> crate::format::schema::public_key::Algorithm { - match self { - PrivateKey::Ed25519(_) => crate::format::schema::public_key::Algorithm::Ed25519, - PrivateKey::P256(_) => crate::format::schema::public_key::Algorithm::Secp256r1, +impl FromStr for PrivateKey { + type Err = error::Format; + fn from_str(s: &str) -> Result { + match s.split_once('/') { + Some(("ed25519-private", bytes)) => Self::from_bytes_hex(bytes, Algorithm::Ed25519), + Some(("secp256r1-private", bytes)) => Self::from_bytes_hex(bytes, Algorithm::Secp256r1), + Some((alg, _)) => Err(error::Format::InvalidKey(format!( + "Unsupported key algorithm {alg}" + ))), + None => Err(error::Format::InvalidKey( + "Missing key algorithm".to_string(), + )), } } } -/// the public part of a [KeyPair] +/// the public part of a signing key pair #[derive(Debug, Clone, Copy, PartialEq, Hash, Eq)] pub enum PublicKey { Ed25519(ed25519::PublicKey), @@ -484,8 +446,8 @@ pub enum TokenNext { } pub fn sign_authority_block( - keypair: &KeyPair, - next_key: &KeyPair, + key: &PrivateKey, + next_key: &PrivateKey, message: &[u8], version: u32, ) -> Result { @@ -500,14 +462,14 @@ pub fn sign_authority_block( } }; - let signature = keypair.sign(&to_sign)?; + let signature = key.sign(&to_sign)?; Ok(Signature(signature.to_bytes().to_vec())) } pub fn sign_block( - keypair: &KeyPair, - next_key: &KeyPair, + key: &PrivateKey, + next_key: &PrivateKey, message: &[u8], external_signature: Option<&ExternalSignature>, previous_signature: &Signature, @@ -530,7 +492,7 @@ pub fn sign_block( } }; - Ok(keypair.sign(&to_sign)?) + Ok(key.sign(&to_sign)?) } pub fn verify_authority_block_signature( @@ -733,10 +695,10 @@ pub(crate) fn generate_seal_signature_payload_v0(block: &Block) -> Vec { } impl TokenNext { - pub fn keypair(&self) -> Result { + pub fn private_key(&self) -> Result { match &self { TokenNext::Seal(_) => Err(error::Token::AlreadySealed), - TokenNext::Secret(private) => Ok(KeyPair::from(private)), + TokenNext::Secret(private) => Ok(private.clone()), } } @@ -770,7 +732,7 @@ mod tests { #[test] fn roundtrip_from_string() { - let ed_root = KeyPair::new_with_algorithm(Algorithm::Ed25519); + let ed_root = PrivateKey::new_with_algorithm(Algorithm::Ed25519); assert_eq!( ed_root.public(), ed_root.public().to_string().parse().unwrap() @@ -784,7 +746,7 @@ mod tests { .unwrap() .to_bytes() ); - let p256_root = KeyPair::new_with_algorithm(Algorithm::Secp256r1); + let p256_root = PrivateKey::new_with_algorithm(Algorithm::Secp256r1); assert_eq!( p256_root.public(), p256_root.public().to_string().parse().unwrap() @@ -879,13 +841,13 @@ mod tests { #[cfg(feature = "pem")] #[test] fn ed25519_der() { - let ed25519_kp = KeyPair::new_with_algorithm(Algorithm::Ed25519); + let ed25519_kp = PrivateKey::new_with_algorithm(Algorithm::Ed25519); let der_kp = ed25519_kp.to_private_key_der().unwrap(); let deser = - KeyPair::from_private_key_der_with_algorithm(&der_kp, Algorithm::Ed25519).unwrap(); + PrivateKey::from_private_key_der_with_algorithm(&der_kp, Algorithm::Ed25519).unwrap(); assert_eq!(ed25519_kp, deser); - let deser = KeyPair::from_private_key_der(&der_kp).unwrap(); + let deser = PrivateKey::from_private_key_der(&der_kp).unwrap(); assert_eq!(ed25519_kp, deser); let ed25519_priv = ed25519_kp.private(); @@ -907,12 +869,12 @@ mod tests { #[cfg(feature = "pem")] #[test] fn ed25519_pem() { - let ed25519_kp = KeyPair::new_with_algorithm(Algorithm::Ed25519); + let ed25519_kp = PrivateKey::new_with_algorithm(Algorithm::Ed25519); let pem_kp = ed25519_kp.to_private_key_pem().unwrap(); let deser = - KeyPair::from_private_key_pem_with_algorithm(&pem_kp, Algorithm::Ed25519).unwrap(); + PrivateKey::from_private_key_pem_with_algorithm(&pem_kp, Algorithm::Ed25519).unwrap(); assert_eq!(ed25519_kp, deser); - let deser = KeyPair::from_private_key_pem(&pem_kp).unwrap(); + let deser = PrivateKey::from_private_key_pem(&pem_kp).unwrap(); assert_eq!(ed25519_kp, deser); let ed25519_priv = ed25519_kp.private(); @@ -934,12 +896,12 @@ mod tests { #[cfg(feature = "pem")] #[test] fn p256_der() { - let p256_kp = KeyPair::new_with_algorithm(Algorithm::Secp256r1); + let p256_kp = PrivateKey::new_with_algorithm(Algorithm::Secp256r1); let der_kp = p256_kp.to_private_key_der().unwrap(); let deser = - KeyPair::from_private_key_der_with_algorithm(&der_kp, Algorithm::Secp256r1).unwrap(); + PrivateKey::from_private_key_der_with_algorithm(&der_kp, Algorithm::Secp256r1).unwrap(); assert_eq!(p256_kp, deser); - let deser = KeyPair::from_private_key_der(&der_kp).unwrap(); + let deser = PrivateKey::from_private_key_der(&der_kp).unwrap(); assert_eq!(p256_kp, deser); let p256_priv = p256_kp.private(); @@ -961,12 +923,12 @@ mod tests { #[cfg(feature = "pem")] #[test] fn p256_pem() { - let p256_kp = KeyPair::new_with_algorithm(Algorithm::Secp256r1); + let p256_kp = PrivateKey::new_with_algorithm(Algorithm::Secp256r1); let pem_kp = p256_kp.to_private_key_pem().unwrap(); let deser = - KeyPair::from_private_key_pem_with_algorithm(&pem_kp, Algorithm::Secp256r1).unwrap(); + PrivateKey::from_private_key_pem_with_algorithm(&pem_kp, Algorithm::Secp256r1).unwrap(); assert_eq!(p256_kp, deser); - let deser = KeyPair::from_private_key_pem(&pem_kp).unwrap(); + let deser = PrivateKey::from_private_key_pem(&pem_kp).unwrap(); assert_eq!(p256_kp, deser); let p256_priv = p256_kp.private(); diff --git a/biscuit-auth/src/crypto/p256.rs b/biscuit-auth/src/crypto/p256.rs index 153ede7b..f41b572e 100644 --- a/biscuit-auth/src/crypto/p256.rs +++ b/biscuit-auth/src/crypto/p256.rs @@ -3,31 +3,26 @@ * SPDX-License-Identifier: Apache-2.0 */ #![allow(non_snake_case)] -use crate::error::Format; - -use super::error; -use super::Signature; +use std::hash::Hash; use p256::ecdsa::{signature::Signer, signature::Verifier, SigningKey, VerifyingKey}; use p256::elliptic_curve::rand_core::{CryptoRng, RngCore}; use p256::NistP256; -use std::hash::Hash; -/// pair of cryptographic keys used to sign a token's block +use crate::error::Format; + +use super::error; +use super::Signature; + +/// the private part of an secp256r1 keypair #[derive(Debug, PartialEq)] -pub struct KeyPair { - kp: SigningKey, -} +pub struct PrivateKey(SigningKey); -impl KeyPair { +impl PrivateKey { pub fn new_with_rng(rng: &mut T) -> Self { let kp = SigningKey::random(rng); - KeyPair { kp } - } - - pub fn from(key: &PrivateKey) -> Self { - KeyPair { kp: key.0.clone() } + Self(kp) } /// deserializes from a big endian byte array @@ -41,12 +36,12 @@ impl KeyPair { .map_err(|s| s.to_string()) .map_err(Format::InvalidKey)?; - Ok(KeyPair { kp }) + Ok(Self(kp)) } pub fn sign(&self, data: &[u8]) -> Result { let signature: ecdsa::Signature = self - .kp + .0 .try_sign(data) .map_err(|s| s.to_string()) .map_err(error::Signature::InvalidSignatureGeneration) @@ -54,12 +49,8 @@ impl KeyPair { Ok(Signature(signature.to_der().as_bytes().to_owned())) } - pub fn private(&self) -> PrivateKey { - PrivateKey(self.kp.clone()) - } - pub fn public(&self) -> PublicKey { - PublicKey(*self.kp.verifying_key()) + PublicKey(*self.0.verifying_key()) } #[cfg(feature = "pem")] @@ -68,7 +59,7 @@ impl KeyPair { let kp = SigningKey::from_pkcs8_der(bytes) .map_err(|e| error::Format::InvalidKey(e.to_string()))?; - Ok(KeyPair { kp }) + Ok(Self(kp)) } #[cfg(feature = "pem")] @@ -77,14 +68,14 @@ impl KeyPair { let kp = SigningKey::from_pkcs8_pem(str) .map_err(|e| error::Format::InvalidKey(e.to_string()))?; - Ok(KeyPair { kp }) + Ok(Self(kp)) } #[cfg(feature = "pem")] pub fn to_private_key_der(&self) -> Result>, error::Format> { use p256::pkcs8::EncodePrivateKey; let kp = self - .kp + .0 .to_pkcs8_der() .map_err(|e| error::Format::PKCS8(e.to_string()))?; Ok(kp.to_bytes()) @@ -95,18 +86,12 @@ impl KeyPair { use p256::pkcs8::EncodePrivateKey; use p256::pkcs8::LineEnding; let kp = self - .kp + .0 .to_pkcs8_pem(LineEnding::LF) .map_err(|e| error::Format::PKCS8(e.to_string()))?; Ok(kp) } -} - -/// the private part of a [KeyPair] -#[derive(Debug, PartialEq)] -pub struct PrivateKey(SigningKey); -impl PrivateKey { /// serializes to a big endian byte array pub fn to_bytes(&self) -> zeroize::Zeroizing> { let field_bytes = self.0.to_bytes(); @@ -118,19 +103,6 @@ impl PrivateKey { hex::encode(self.to_bytes()) } - /// deserializes from a big endian byte array - pub fn from_bytes(bytes: &[u8]) -> Result { - // the version of generic-array used by p256 panics if the input length - // is incorrect (including when using `.try_into()`) - if bytes.len() != 32 { - return Err(Format::InvalidKeySize(bytes.len())); - } - SigningKey::from_bytes(bytes.into()) - .map(PrivateKey) - .map_err(|s| s.to_string()) - .map_err(Format::InvalidKey) - } - /// deserializes from an hex-encoded string pub fn from_bytes_hex(str: &str) -> Result { let bytes = hex::decode(str).map_err(|e| error::Format::InvalidKey(e.to_string()))?; @@ -175,20 +147,15 @@ impl PrivateKey { .map_err(|e| error::Format::PKCS8(e.to_string()))?; Ok(kp) } - - /// returns the matching public key - pub fn public(&self) -> PublicKey { - PublicKey(*self.0.verifying_key()) - } } -impl std::clone::Clone for PrivateKey { +impl Clone for PrivateKey { fn clone(&self) -> Self { PrivateKey::from_bytes(&self.to_bytes()).unwrap() } } -/// the public part of a [KeyPair] +/// the public part of an secp256r1 keypair #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub struct PublicKey(VerifyingKey); @@ -299,9 +266,8 @@ mod tests { #[test] fn serialization() { - let kp = KeyPair::new_with_rng(&mut OsRng); - let private = kp.private(); - let public = kp.public(); + let private = PrivateKey::new_with_rng(&mut OsRng); + let public = private.public(); let private_hex = private.to_bytes_hex(); let public_hex = public.to_bytes_hex(); @@ -309,7 +275,7 @@ mod tests { println!("public: {public_hex}"); let message = "hello world"; - let signature = kp.sign(message.as_bytes()).unwrap(); + let signature = private.sign(message.as_bytes()).unwrap(); println!("signature: {}", hex::encode(&signature.0)); let deserialized_priv = PrivateKey::from_bytes_hex(&private_hex).unwrap(); @@ -330,10 +296,6 @@ mod tests { PrivateKey::from_bytes(&[0xaa]).unwrap_err(), error::Format::InvalidKeySize(1) ); - assert_eq!( - KeyPair::from_bytes(&[0xaa]).unwrap_err(), - error::Format::InvalidKeySize(1) - ); PublicKey::from_bytes(&[0xaa]).unwrap_err(); } } diff --git a/biscuit-auth/src/format/mod.rs b/biscuit-auth/src/format/mod.rs index 4ff3c70a..a072e35d 100644 --- a/biscuit-auth/src/format/mod.rs +++ b/biscuit-auth/src/format/mod.rs @@ -8,7 +8,7 @@ //! //! - serialization of Biscuit blocks to Protobuf then `Vec` //! - serialization of a wrapper structure containing serialized blocks and the signature -use super::crypto::{self, KeyPair, PrivateKey, PublicKey, TokenNext}; +use super::crypto::{self, PrivateKey, PublicKey, TokenNext}; use prost::Message; @@ -292,21 +292,21 @@ impl SerializedBiscuit { /// creates a new token pub fn new( root_key_id: Option, - root_keypair: &KeyPair, - next_keypair: &KeyPair, + root_private_key: &PrivateKey, + next_private_key: &PrivateKey, authority: &Block, ) -> Result { let authority_signature_version = block_signature_version( - root_keypair, - next_keypair, + root_private_key, + next_private_key, &None, &Some(authority.version), std::iter::empty(), ); Self::new_inner( root_key_id, - root_keypair, - next_keypair, + root_private_key, + next_private_key, authority, authority_signature_version, ) @@ -315,8 +315,8 @@ impl SerializedBiscuit { /// creates a new token pub(crate) fn new_inner( root_key_id: Option, - root_keypair: &KeyPair, - next_keypair: &KeyPair, + root_private_key: &PrivateKey, + next_private_key: &PrivateKey, authority: &Block, authority_signature_version: u32, ) -> Result { @@ -328,8 +328,8 @@ impl SerializedBiscuit { })?; let signature = crypto::sign_authority_block( - root_keypair, - next_keypair, + root_private_key, + next_private_key, &v, authority_signature_version, )?; @@ -338,24 +338,24 @@ impl SerializedBiscuit { root_key_id, authority: crypto::Block { data: v, - next_key: next_keypair.public(), + next_key: next_private_key.public(), signature, external_signature: None, version: authority_signature_version, }, blocks: vec![], - proof: TokenNext::Secret(next_keypair.private()), + proof: TokenNext::Secret(next_private_key.private()), }) } /// adds a new block, serializes it and sign a new token pub fn append( &self, - next_keypair: &KeyPair, + next_private_key: &PrivateKey, block: &Block, external_signature: Option, ) -> Result { - let keypair = self.proof.keypair()?; + let private_key = self.proof.private_key()?; let mut v = Vec::new(); token_block_to_proto_block(block) @@ -365,8 +365,8 @@ impl SerializedBiscuit { })?; let signature_version = block_signature_version( - &keypair, - next_keypair, + &private_key, + next_private_key, &external_signature, &Some(block.version), // std::iter::once(self.authority.version) @@ -378,8 +378,8 @@ impl SerializedBiscuit { ); let signature = crypto::sign_block( - &keypair, - next_keypair, + &private_key, + next_private_key, &v, external_signature.as_ref(), &self.last_block().signature, @@ -390,7 +390,7 @@ impl SerializedBiscuit { let mut blocks = self.blocks.clone(); blocks.push(crypto::Block { data: v, - next_key: next_keypair.public(), + next_key: next_private_key.public(), signature, external_signature, version: signature_version, @@ -400,22 +400,22 @@ impl SerializedBiscuit { root_key_id: self.root_key_id, authority: self.authority.clone(), blocks, - proof: TokenNext::Secret(next_keypair.private()), + proof: TokenNext::Secret(next_private_key.private()), }) } /// adds a new block, serializes it and sign a new token pub fn append_serialized( &self, - next_keypair: &KeyPair, + next_private_key: &PrivateKey, block: Vec, external_signature: Option, ) -> Result { - let keypair = self.proof.keypair()?; + let private_key = self.proof.private_key()?; let signature_version = block_signature_version( - &keypair, - next_keypair, + &private_key, + next_private_key, &external_signature, // The version block is not directly available, so we don’t take it into account here // `append_serialized` is only used for third-party blocks anyway, so maybe we should make `external_signature` mandatory and not bother @@ -425,8 +425,8 @@ impl SerializedBiscuit { ); let signature = crypto::sign_block( - &keypair, - next_keypair, + &private_key, + next_private_key, &block, external_signature.as_ref(), &self.last_block().signature, @@ -437,7 +437,7 @@ impl SerializedBiscuit { let mut blocks = self.blocks.clone(); blocks.push(crypto::Block { data: block, - next_key: next_keypair.public(), + next_key: next_private_key.public(), signature, external_signature, version: signature_version, @@ -447,7 +447,7 @@ impl SerializedBiscuit { root_key_id: self.root_key_id, authority: self.authority.clone(), blocks, - proof: TokenNext::Secret(next_keypair.private()), + proof: TokenNext::Secret(next_private_key.private()), }) } @@ -515,7 +515,7 @@ impl SerializedBiscuit { } pub fn seal(&self) -> Result { - let keypair = self.proof.keypair()?; + let private_key = self.proof.private_key()?; //FIXME: replace with SHA512 hashing let block = if self.blocks.is_empty() { @@ -526,7 +526,7 @@ impl SerializedBiscuit { let to_sign = crypto::generate_seal_signature_payload_v0(block); - let signature = keypair.sign(&to_sign)?; + let signature = private_key.sign(&to_sign)?; Ok(SerializedBiscuit { root_key_id: self.root_key_id, @@ -548,8 +548,8 @@ pub(crate) enum ThirdPartyVerificationMode { } fn block_signature_version( - block_keypair: &KeyPair, - next_keypair: &KeyPair, + block_private_key: &PrivateKey, + next_private_key: &PrivateKey, external_signature: &Option, block_version: &Option, previous_blocks_sig_versions: I, @@ -568,8 +568,8 @@ where _ => {} } - match (block_keypair, next_keypair) { - (KeyPair::Ed25519(_), KeyPair::Ed25519(_)) => {} + match (block_private_key, next_private_key) { + (PrivateKey::Ed25519(_), PrivateKey::Ed25519(_)) => {} _ => { return NON_ED25519_SIGNATURE_VERSION; } @@ -587,7 +587,7 @@ mod tests { crypto::{ExternalSignature, Signature}, format::block_signature_version, token::{DATALOG_3_1, DATALOG_3_3}, - KeyPair, + PrivateKey, }; #[test] @@ -620,8 +620,8 @@ mod tests { fn test_block_signature_version() { assert_eq!( block_signature_version( - &KeyPair::new(), - &KeyPair::new(), + &PrivateKey::new(), + &PrivateKey::new(), &None, &Some(DATALOG_3_1), std::iter::empty() @@ -631,8 +631,8 @@ mod tests { ); assert_eq!( block_signature_version( - &KeyPair::new_with_algorithm(Algorithm::Secp256r1), - &KeyPair::new_with_algorithm(Algorithm::Ed25519), + &PrivateKey::new_with_algorithm(Algorithm::Secp256r1), + &PrivateKey::new_with_algorithm(Algorithm::Ed25519), &None, &Some(DATALOG_3_1), std::iter::empty() @@ -642,8 +642,8 @@ mod tests { ); assert_eq!( block_signature_version( - &KeyPair::new_with_algorithm(Algorithm::Ed25519), - &KeyPair::new_with_algorithm(Algorithm::Secp256r1), + &PrivateKey::new_with_algorithm(Algorithm::Ed25519), + &PrivateKey::new_with_algorithm(Algorithm::Secp256r1), &None, &Some(DATALOG_3_1), std::iter::empty() @@ -653,8 +653,8 @@ mod tests { ); assert_eq!( block_signature_version( - &KeyPair::new_with_algorithm(Algorithm::Secp256r1), - &KeyPair::new_with_algorithm(Algorithm::Secp256r1), + &PrivateKey::new_with_algorithm(Algorithm::Secp256r1), + &PrivateKey::new_with_algorithm(Algorithm::Secp256r1), &None, &Some(DATALOG_3_1), std::iter::empty() @@ -664,10 +664,10 @@ mod tests { ); assert_eq!( block_signature_version( - &KeyPair::new(), - &KeyPair::new(), + &PrivateKey::new(), + &PrivateKey::new(), &Some(ExternalSignature { - public_key: KeyPair::new().public(), + public_key: PrivateKey::new().public(), signature: Signature::from_vec(Vec::new()) }), &Some(DATALOG_3_1), @@ -678,8 +678,8 @@ mod tests { ); assert_eq!( block_signature_version( - &KeyPair::new(), - &KeyPair::new(), + &PrivateKey::new(), + &PrivateKey::new(), &None, &Some(DATALOG_3_3), std::iter::empty() @@ -689,8 +689,8 @@ mod tests { ); assert_eq!( block_signature_version( - &KeyPair::new(), - &KeyPair::new(), + &PrivateKey::new(), + &PrivateKey::new(), &None, &Some(DATALOG_3_1), std::iter::once(1) diff --git a/biscuit-auth/src/lib.rs b/biscuit-auth/src/lib.rs index 3648912f..207b18e9 100644 --- a/biscuit-auth/src/lib.rs +++ b/biscuit-auth/src/lib.rs @@ -31,12 +31,12 @@ //! ```rust //! extern crate biscuit_auth as biscuit; //! -//! use biscuit::{KeyPair, Biscuit, Authorizer, builder::*, error, macros::*}; +//! use biscuit::{PrivateKey, Biscuit, Authorizer, builder::*, error, macros::*}; //! //! fn main() -> Result<(), error::Token> { //! // let's generate the root key pair. The root public key will be necessary //! // to verify the token -//! let root = KeyPair::new(); +//! let root = PrivateKey::new(); //! let public_key = root.public(); //! //! // creating a first token @@ -251,7 +251,7 @@ pub mod format; pub mod parser; mod token; -pub use crypto::{KeyPair, PrivateKey, PublicKey}; +pub use crypto::{PrivateKey, PublicKey}; pub use token::authorizer::{Authorizer, AuthorizerLimits}; pub use token::builder; pub use token::builder::{Algorithm, AuthorizerBuilder, BiscuitBuilder, BlockBuilder}; diff --git a/biscuit-auth/src/macros.rs b/biscuit-auth/src/macros.rs index c1684b63..eb0a9804 100644 --- a/biscuit-auth/src/macros.rs +++ b/biscuit-auth/src/macros.rs @@ -5,11 +5,11 @@ //! Procedural macros to create tokens and authorizers //! //! ```rust -//! use biscuit_auth::KeyPair; +//! use biscuit_auth::PrivateKey; //! use biscuit_auth::macros::{authorizer, biscuit, block}; //! use std::time::{Duration, SystemTime}; //! -//! let root = KeyPair::new(); +//! let root = PrivateKey::new(); //! //! let user_id = "1234"; //! let biscuit = biscuit!( @@ -99,11 +99,11 @@ pub use biscuit_quote::authorizer_merge; /// block building. /// /// ```rust -/// use biscuit_auth::{Biscuit, KeyPair}; +/// use biscuit_auth::{Biscuit, PrivateKey}; /// use biscuit_auth::macros::biscuit; /// use std::time::{SystemTime, Duration}; /// -/// let root = KeyPair::new(); +/// let root = PrivateKey::new(); /// let biscuit = biscuit!( /// r#" /// user({user_id}); @@ -120,11 +120,11 @@ pub use biscuit_quote::biscuit; /// and replaced by manual block building. /// /// ```rust -/// use biscuit_auth::{Biscuit, KeyPair}; +/// use biscuit_auth::{Biscuit, PrivateKey}; /// use biscuit_auth::macros::{biscuit, biscuit_merge}; /// use std::time::{SystemTime, Duration}; /// -/// let root = KeyPair::new(); +/// let root = PrivateKey::new(); /// /// let mut b = biscuit!( /// r#" diff --git a/biscuit-auth/src/token/authorizer.rs b/biscuit-auth/src/token/authorizer.rs index 31a3b0ca..d46d95e1 100644 --- a/biscuit-auth/src/token/authorizer.rs +++ b/biscuit-auth/src/token/authorizer.rs @@ -127,13 +127,13 @@ impl Authorizer { /// run a query over the authorizer's Datalog engine to gather data /// /// ```rust - /// # use biscuit_auth::KeyPair; + /// # use biscuit_auth::PrivateKey; /// # use biscuit_auth::Biscuit; - /// let keypair = KeyPair::new(); + /// let private = PrivateKey::new(); /// let biscuit = Biscuit::builder() /// .fact("user(\"John Doe\", 42)") /// .expect("parse error") - /// .build(&keypair) + /// .build(&private) /// .unwrap(); /// /// let mut authorizer = biscuit.authorizer().unwrap(); @@ -165,12 +165,12 @@ impl Authorizer { /// If there is more than one result, this function will throw an error. /// /// ```rust - /// # use biscuit_auth::KeyPair; + /// # use biscuit_auth::PrivateKey; /// # use biscuit_auth::Biscuit; - /// let keypair = KeyPair::new(); + /// let private = PrivateKey::new(); /// let builder = Biscuit::builder().fact("user(\"John Doe\", 42)").unwrap(); /// - /// let biscuit = builder.build(&keypair).unwrap(); + /// let biscuit = builder.build(&private).unwrap(); /// /// let mut authorizer = biscuit.authorizer().unwrap(); /// let res: (String, i64) = authorizer.query_exactly_one("data($name, $id) <- user($name, $id)").unwrap(); @@ -252,13 +252,13 @@ impl Authorizer { /// this has access to the facts generated when evaluating all the blocks /// /// ```rust - /// # use biscuit_auth::KeyPair; + /// # use biscuit_auth::PrivateKey; /// # use biscuit_auth::Biscuit; - /// let keypair = KeyPair::new(); + /// let private = PrivateKey::new(); /// let biscuit = Biscuit::builder() /// .fact("user(\"John Doe\", 42)") /// .expect("parse error") - /// .build(&keypair) + /// .build(&private) /// .unwrap(); /// /// let mut authorizer = biscuit.authorizer().unwrap(); @@ -920,7 +920,7 @@ mod tests { use crate::PublicKey; use crate::{ builder::{BiscuitBuilder, BlockBuilder}, - KeyPair, + PrivateKey, }; use super::*; @@ -1052,12 +1052,12 @@ mod tests { #[test] fn query_authorizer_from_token_tuple() { use crate::Biscuit; - use crate::KeyPair; - let keypair = KeyPair::new(); + use crate::PrivateKey; + let private = PrivateKey::new(); let biscuit = Biscuit::builder() .fact("user(\"John Doe\", 42)") .unwrap() - .build(&keypair) + .build(&private) .unwrap(); let mut authorizer = biscuit.authorizer().unwrap(); @@ -1073,12 +1073,12 @@ mod tests { #[test] fn query_authorizer_from_token_string() { use crate::Biscuit; - use crate::KeyPair; - let keypair = KeyPair::new(); + use crate::PrivateKey; + let private = PrivateKey::new(); let biscuit = Biscuit::builder() .fact("user(\"John Doe\")") .unwrap() - .build(&keypair) + .build(&private) .unwrap(); let mut authorizer = biscuit.authorizer().unwrap(); @@ -1091,11 +1091,11 @@ mod tests { #[test] fn query_exactly_one_authorizer_from_token_string() { use crate::Biscuit; - use crate::KeyPair; - let keypair = KeyPair::new(); + use crate::PrivateKey; + let private = PrivateKey::new(); let builder = Biscuit::builder().fact("user(\"John Doe\")").unwrap(); - let biscuit = builder.build(&keypair).unwrap(); + let biscuit = builder.build(&private).unwrap(); let mut authorizer = biscuit.authorizer().unwrap(); let res: (String,) = authorizer @@ -1107,11 +1107,11 @@ mod tests { #[test] fn query_exactly_one_no_results() { use crate::Biscuit; - use crate::KeyPair; - let keypair = KeyPair::new(); + use crate::PrivateKey; + let private = PrivateKey::new(); let builder = Biscuit::builder(); - let biscuit = builder.build(&keypair).unwrap(); + let biscuit = builder.build(&private).unwrap(); let mut authorizer = biscuit.authorizer().unwrap(); let res: Result<(String,), error::Token> = @@ -1125,15 +1125,15 @@ mod tests { #[test] fn query_exactly_one_too_many_results() { use crate::Biscuit; - use crate::KeyPair; - let keypair = KeyPair::new(); + use crate::PrivateKey; + let private = PrivateKey::new(); let builder = Biscuit::builder() .fact("user(\"John Doe\")") .unwrap() .fact("user(\"Jane Doe\")") .unwrap(); - let biscuit = builder.build(&keypair).unwrap(); + let biscuit = builder.build(&private).unwrap(); let mut authorizer = biscuit.authorizer().unwrap(); let res: Result<(String,), error::Token> = @@ -1146,8 +1146,8 @@ mod tests { #[test] fn authorizer_with_scopes() { - let root = KeyPair::new(); - let external = KeyPair::new(); + let root = PrivateKey::new(); + let external = PrivateKey::new(); let mut scope_params = HashMap::new(); scope_params.insert("external_pub".to_string(), external.public()); @@ -1173,13 +1173,13 @@ mod tests { "#, ) .unwrap(); - let res = req.create_block(&external.private(), builder).unwrap(); + let res = req.create_block(&external, builder).unwrap(); let biscuit2 = biscuit1.append_third_party(external.public(), res).unwrap(); let serialized = biscuit2.to_vec().unwrap(); let biscuit2 = Biscuit::from(serialized, root.public()).unwrap(); let builder = AuthorizerBuilder::new(); - let external2 = KeyPair::new(); + let external2 = PrivateKey::new(); let mut scope_params = HashMap::new(); scope_params.insert("external".to_string(), external.public()); @@ -1327,7 +1327,7 @@ mod tests { #[test] fn authorizer_display_before_and_after_authorization() { - let root = KeyPair::new(); + let root = PrivateKey::new(); let token = BiscuitBuilder::new() .code( diff --git a/biscuit-auth/src/token/authorizer/snapshot.rs b/biscuit-auth/src/token/authorizer/snapshot.rs index d7c269a2..b85dc944 100644 --- a/biscuit-auth/src/token/authorizer/snapshot.rs +++ b/biscuit-auth/src/token/authorizer/snapshot.rs @@ -320,12 +320,12 @@ mod tests { use std::time::Duration; use crate::{datalog::RunLimits, Algorithm, AuthorizerBuilder}; - use crate::{Authorizer, BiscuitBuilder, KeyPair}; + use crate::{Authorizer, BiscuitBuilder, PrivateKey}; #[test] fn roundtrip_builder() { - let secp_pubkey = KeyPair::new_with_algorithm(Algorithm::Secp256r1).public(); - let ed_pubkey = KeyPair::new_with_algorithm(Algorithm::Ed25519).public(); + let secp_pubkey = PrivateKey::new_with_algorithm(Algorithm::Secp256r1).public(); + let ed_pubkey = PrivateKey::new_with_algorithm(Algorithm::Ed25519).public(); let builder = AuthorizerBuilder::new() .set_limits(RunLimits { max_facts: 42, @@ -356,8 +356,8 @@ mod tests { #[test] fn roundtrip_with_token() { - let secp_pubkey = KeyPair::new_with_algorithm(Algorithm::Secp256r1).public(); - let ed_pubkey = KeyPair::new_with_algorithm(Algorithm::Ed25519).public(); + let secp_pubkey = PrivateKey::new_with_algorithm(Algorithm::Secp256r1).public(); + let ed_pubkey = PrivateKey::new_with_algorithm(Algorithm::Ed25519).public(); let builder = AuthorizerBuilder::new() .set_limits(RunLimits { max_facts: 42, @@ -393,7 +393,7 @@ mod tests { ]), ) .unwrap() - .build(&KeyPair::new()) + .build(&PrivateKey::new()) .unwrap(); let authorizer_pre_run = builder.build(&biscuit).unwrap(); diff --git a/biscuit-auth/src/token/builder/biscuit.rs b/biscuit-auth/src/token/builder/biscuit.rs index a02bfb1a..a7113338 100644 --- a/biscuit-auth/src/token/builder/biscuit.rs +++ b/biscuit-auth/src/token/builder/biscuit.rs @@ -7,7 +7,7 @@ use crate::builder_ext::BuilderExt; use crate::crypto::PublicKey; use crate::datalog::SymbolTable; use crate::token::default_symbol_table; -use crate::{error, Biscuit, KeyPair}; +use crate::{error, Biscuit, PrivateKey}; use rand::{CryptoRng, RngCore}; use std::fmt; @@ -124,13 +124,13 @@ impl BiscuitBuilder { f } - pub fn build(self, root_key: &KeyPair) -> Result { + pub fn build(self, root_key: &PrivateKey) -> Result { self.build_with_symbols(root_key, default_symbol_table()) } pub fn build_with_symbols( self, - root_key: &KeyPair, + root_key: &PrivateKey, symbols: SymbolTable, ) -> Result { self.build_with_rng(root_key, symbols, &mut rand::rngs::OsRng) @@ -138,7 +138,7 @@ impl BiscuitBuilder { pub fn build_with_rng( self, - root: &KeyPair, + root: &PrivateKey, symbols: SymbolTable, rng: &mut R, ) -> Result { @@ -148,9 +148,9 @@ impl BiscuitBuilder { pub fn build_with_key_pair( self, - root: &KeyPair, + root: &PrivateKey, symbols: SymbolTable, - next: &KeyPair, + next: &PrivateKey, ) -> Result { let authority_block = self.inner.build(symbols.clone()); Biscuit::new_with_key_pair(self.root_key_id, root, next, symbols, authority_block) diff --git a/biscuit-auth/src/token/mod.rs b/biscuit-auth/src/token/mod.rs index 218804c9..3694954b 100644 --- a/biscuit-auth/src/token/mod.rs +++ b/biscuit-auth/src/token/mod.rs @@ -11,7 +11,7 @@ use prost::Message; use rand_core::{CryptoRng, RngCore}; use self::public_keys::PublicKeys; -use super::crypto::{KeyPair, PublicKey, Signature}; +use super::crypto::{PrivateKey, PublicKey, Signature}; use super::datalog::SymbolTable; use super::error; use super::format::SerializedBiscuit; @@ -56,10 +56,10 @@ pub fn default_symbol_table() -> SymbolTable { /// ```rust /// extern crate biscuit_auth as biscuit; /// -/// use biscuit::{KeyPair, Biscuit, builder::*, builder_ext::*}; +/// use biscuit::{PrivateKey, Biscuit, builder::*, builder_ext::*}; /// /// fn main() -> Result<(), biscuit::error::Token> { -/// let root = KeyPair::new(); +/// let root = PrivateKey::new(); /// /// // first we define the authority block for global data, /// // like access rights @@ -171,11 +171,11 @@ impl Biscuit { /// adds a new block to the token /// - /// since the public key is integrated into the token, the keypair can be + /// since the public key is integrated into the token, the private key can be /// discarded right after calling this function pub fn append(&self, block_builder: BlockBuilder) -> Result { - let keypair = KeyPair::new_with_rng(builder::Algorithm::Ed25519, &mut rand::rngs::OsRng); - self.append_with_keypair(&keypair, block_builder) + let key = PrivateKey::new_with_rng(builder::Algorithm::Ed25519, &mut rand::rngs::OsRng); + self.append_with_key(&key, block_builder) } /// returns the list of context elements of each block @@ -250,30 +250,31 @@ impl Biscuit { /// creates a new token, using a provided CSPRNG /// - /// the public part of the root keypair must be used for verification + /// the public part of the root key must be used for verification pub(crate) fn new_with_rng( rng: &mut T, root_key_id: Option, - root: &KeyPair, + root: &PrivateKey, symbols: SymbolTable, authority: Block, ) -> Result { Self::new_with_key_pair( root_key_id, root, - &KeyPair::new_with_rng(builder::Algorithm::Ed25519, rng), + &PrivateKey::new_with_rng(builder::Algorithm::Ed25519, rng), symbols, authority, ) } - /// creates a new token, using provided keypairs (the root keypair, and the keypair used to sign the next block) + /// creates a new token, using provided keys (the root key, and the key used to sign the next + /// block) /// /// the public part of the root keypair must be used for verification pub(crate) fn new_with_key_pair( root_key_id: Option, - root: &KeyPair, - next_keypair: &KeyPair, + root_key: &PrivateKey, + next_key: &PrivateKey, mut symbols: SymbolTable, authority: Block, ) -> Result { @@ -285,7 +286,7 @@ impl Biscuit { let blocks = vec![]; - let container = SerializedBiscuit::new(root_key_id, root, next_keypair, &authority)?; + let container = SerializedBiscuit::new(root_key_id, root_key, next_key, &authority)?; symbols.public_keys.extend(&authority.public_keys)?; @@ -336,7 +337,8 @@ impl Biscuit { }) } - /// deserializes a token and validates the signature using the root public key, with a custom symbol table + /// deserializes a token and validates the signature using the root public key, with a custom + /// symbol table fn from_base64_with_symbols( slice: T, key_provider: KP, @@ -357,11 +359,11 @@ impl Biscuit { /// adds a new block to the token, using the provided CSPRNG /// - /// since the public key is integrated into the token, the keypair can be + /// since the public key is integrated into the token, the key can be /// discarded right after calling this function - pub fn append_with_keypair( + pub fn append_with_key( &self, - keypair: &KeyPair, + key: &PrivateKey, block_builder: BlockBuilder, ) -> Result { let block = block_builder.build(self.symbols.clone()); @@ -374,7 +376,7 @@ impl Biscuit { let mut blocks = self.blocks.clone(); let mut symbols = self.symbols.clone(); - let container = self.container.append(keypair, &block, None)?; + let container = self.container.append(key, &block, None)?; symbols.extend(&block.symbols)?; symbols.public_keys.extend(&block.public_keys)?; @@ -411,16 +413,16 @@ impl Biscuit { external_key: PublicKey, response: ThirdPartyBlock, ) -> Result { - let next_keypair = - KeyPair::new_with_rng(builder::Algorithm::Ed25519, &mut rand::rngs::OsRng); + let next_key = + PrivateKey::new_with_rng(builder::Algorithm::Ed25519, &mut rand::rngs::OsRng); - self.append_third_party_with_keypair(external_key, response, next_keypair) + self.append_third_party_with_key(external_key, response, next_key) } - pub fn append_third_party_with_keypair( + pub fn append_third_party_with_key( &self, external_key: PublicKey, response: ThirdPartyBlock, - next_keypair: KeyPair, + next_key: PrivateKey, ) -> Result { let ThirdPartyBlockContents { payload, @@ -475,7 +477,7 @@ impl Biscuit { let container = self.container - .append_serialized(&next_keypair, payload, Some(external_signature))?; + .append_serialized(&next_key, payload, Some(external_signature))?; blocks.push(block); @@ -733,7 +735,7 @@ mod tests { use super::builder_ext::BuilderExt; use super::*; use crate::builder::CheckKind; - use crate::crypto::KeyPair; + use crate::crypto::PrivateKey; use crate::{error::*, AuthorizerLimits, UnverifiedBiscuit}; use builder::AuthorizerBuilder; use builder_ext::AuthorizerExt; @@ -743,7 +745,7 @@ mod tests { #[test] fn basic() { let mut rng: StdRng = SeedableRng::seed_from_u64(0); - let root = KeyPair::new_with_rng(builder::Algorithm::Ed25519, &mut rng); + let root = PrivateKey::new_with_rng(builder::Algorithm::Ed25519, &mut rng); let serialized1 = { let biscuit1 = Biscuit::builder() @@ -782,7 +784,7 @@ mod tests { ], )); - let keypair2 = KeyPair::new_with_rng(&mut rng); + let keypair2 = PrivateKey::new_with_rng(&mut rng); let biscuit2 = biscuit1_deser.append(&keypair2, block2.to_block()).unwrap(); println!("biscuit2 (1 check): {}", biscuit2); @@ -810,9 +812,9 @@ mod tests { )) .unwrap(); - let keypair2 = KeyPair::new_with_rng(builder::Algorithm::Ed25519, &mut rng); + let keypair2 = PrivateKey::new_with_rng(builder::Algorithm::Ed25519, &mut rng); let biscuit2 = biscuit1_deser - .append_with_keypair(&keypair2, block2) + .append_with_key(&keypair2, block2) .unwrap(); println!("biscuit2 (1 check): {biscuit2}"); @@ -835,9 +837,9 @@ mod tests { )) .unwrap(); - let keypair3 = KeyPair::new_with_rng(builder::Algorithm::Ed25519, &mut rng); + let keypair3 = PrivateKey::new_with_rng(builder::Algorithm::Ed25519, &mut rng); let biscuit3 = biscuit2_deser - .append_with_keypair(&keypair3, block3) + .append_with_key(&keypair3, block3) .unwrap(); biscuit3.to_vec().unwrap() @@ -904,7 +906,7 @@ mod tests { #[test] fn folders() { let mut rng: StdRng = SeedableRng::seed_from_u64(0); - let root = KeyPair::new_with_rng(builder::Algorithm::Ed25519, &mut rng); + let root = PrivateKey::new_with_rng(builder::Algorithm::Ed25519, &mut rng); let biscuit1 = Biscuit::builder() .right("/folder1/file1", "read") @@ -922,8 +924,8 @@ mod tests { .check_right("read") .unwrap(); - let keypair2 = KeyPair::new_with_rng(builder::Algorithm::Ed25519, &mut rng); - let biscuit2 = biscuit1.append_with_keypair(&keypair2, block2).unwrap(); + let keypair2 = PrivateKey::new_with_rng(builder::Algorithm::Ed25519, &mut rng); + let biscuit2 = biscuit1.append_with_key(&keypair2, block2).unwrap(); { let mut authorizer = AuthorizerBuilder::new() @@ -997,7 +999,7 @@ mod tests { #[test] fn constraints() { let mut rng: StdRng = SeedableRng::seed_from_u64(0); - let root = KeyPair::new_with_rng(builder::Algorithm::Ed25519, &mut rng); + let root = PrivateKey::new_with_rng(builder::Algorithm::Ed25519, &mut rng); let biscuit1 = Biscuit::builder() .right("file1", "read") @@ -1012,8 +1014,8 @@ mod tests { .fact("key(1234)") .unwrap(); - let keypair2 = KeyPair::new_with_rng(builder::Algorithm::Ed25519, &mut rng); - let biscuit2 = biscuit1.append_with_keypair(&keypair2, block2).unwrap(); + let keypair2 = PrivateKey::new_with_rng(builder::Algorithm::Ed25519, &mut rng); + let biscuit2 = biscuit1.append_with_key(&keypair2, block2).unwrap(); { let mut authorizer = AuthorizerBuilder::new() @@ -1061,7 +1063,7 @@ mod tests { #[test] fn sealed_token() { let mut rng: StdRng = SeedableRng::seed_from_u64(0); - let root = KeyPair::new_with_rng(builder::Algorithm::Ed25519, &mut rng); + let root = PrivateKey::new_with_rng(builder::Algorithm::Ed25519, &mut rng); let biscuit1 = Biscuit::builder() .right("/folder1/file1", "read") .right("/folder1/file1", "write") @@ -1078,8 +1080,8 @@ mod tests { .check_right("read") .unwrap(); - let keypair2 = KeyPair::new_with_rng(builder::Algorithm::Ed25519, &mut rng); - let biscuit2 = biscuit1.append_with_keypair(&keypair2, block2).unwrap(); + let keypair2 = PrivateKey::new_with_rng(builder::Algorithm::Ed25519, &mut rng); + let biscuit2 = biscuit1.append_with_key(&keypair2, block2).unwrap(); //println!("biscuit2:\n{:#?}", biscuit2); //panic!(); @@ -1130,7 +1132,7 @@ mod tests { use crate::token::builder::*; let mut rng: StdRng = SeedableRng::seed_from_u64(1234); - let root = KeyPair::new_with_rng(builder::Algorithm::Ed25519, &mut rng); + let root = PrivateKey::new_with_rng(builder::Algorithm::Ed25519, &mut rng); let biscuit1 = Biscuit::builder() .fact(fact("right", &[string("file1"), string("read")])) @@ -1173,7 +1175,7 @@ mod tests { #[test] fn authorizer_queries() { let mut rng: StdRng = SeedableRng::seed_from_u64(0); - let root = KeyPair::new_with_rng(builder::Algorithm::Ed25519, &mut rng); + let root = PrivateKey::new_with_rng(builder::Algorithm::Ed25519, &mut rng); let biscuit1 = Biscuit::builder() .right("file1", "read") @@ -1190,16 +1192,16 @@ mod tests { .fact("key(1234)") .unwrap(); - let keypair2 = KeyPair::new_with_rng(builder::Algorithm::Ed25519, &mut rng); - let biscuit2 = biscuit1.append_with_keypair(&keypair2, block2).unwrap(); + let keypair2 = PrivateKey::new_with_rng(builder::Algorithm::Ed25519, &mut rng); + let biscuit2 = biscuit1.append_with_key(&keypair2, block2).unwrap(); let block3 = BlockBuilder::new() .check_expiration_date(SystemTime::now() + Duration::from_secs(10)) .fact("key(5678)") .unwrap(); - let keypair3 = KeyPair::new_with_rng(builder::Algorithm::Ed25519, &mut rng); - let biscuit3 = biscuit2.append_with_keypair(&keypair3, block3).unwrap(); + let keypair3 = PrivateKey::new_with_rng(builder::Algorithm::Ed25519, &mut rng); + let biscuit3 = biscuit2.append_with_key(&keypair3, block3).unwrap(); { println!("biscuit3: {biscuit3}"); @@ -1263,7 +1265,7 @@ mod tests { #[test] fn check_head_name() { let mut rng: StdRng = SeedableRng::seed_from_u64(0); - let root = KeyPair::new_with_rng(builder::Algorithm::Ed25519, &mut rng); + let root = PrivateKey::new_with_rng(builder::Algorithm::Ed25519, &mut rng); let biscuit1 = Biscuit::builder() .check(check( @@ -1281,8 +1283,8 @@ mod tests { .fact(fact("check1", &[string("test")])) .unwrap(); - let keypair2 = KeyPair::new_with_rng(builder::Algorithm::Ed25519, &mut rng); - let biscuit2 = biscuit1.append_with_keypair(&keypair2, block2).unwrap(); + let keypair2 = PrivateKey::new_with_rng(builder::Algorithm::Ed25519, &mut rng); + let biscuit2 = biscuit1.append_with_key(&keypair2, block2).unwrap(); println!("biscuit2: {biscuit2}"); @@ -1323,7 +1325,7 @@ mod tests { #[test] fn check_requires_fact_in_future_block() { let mut rng: StdRng = SeedableRng::seed_from_u64(0); - let root = KeyPair::new_with_rng(&mut rng); + let root = PrivateKey::new_with_rng(&mut rng); let mut builder = Biscuit::builder(&root); @@ -1352,7 +1354,7 @@ mod tests { let mut block2 = BlockBuilder::new(); block2.add_fact(fact("name", &[string("test")])).unwrap(); - let keypair2 = KeyPair::new_with_rng(&mut rng); + let keypair2 = PrivateKey::new_with_rng(&mut rng); let biscuit2 = biscuit1 .append_with_keypair(&keypair2, block2) .unwrap(); @@ -1367,7 +1369,7 @@ mod tests { #[test] fn bytes_constraints() { let mut rng: StdRng = SeedableRng::seed_from_u64(0); - let root = KeyPair::new_with_rng(builder::Algorithm::Ed25519, &mut rng); + let root = PrivateKey::new_with_rng(builder::Algorithm::Ed25519, &mut rng); let biscuit1 = Biscuit::builder() .fact("bytes(hex:0102AB)") @@ -1380,8 +1382,8 @@ mod tests { let block2 = BlockBuilder::new() .rule("has_bytes($0) <- bytes($0), { hex:00000000, hex:0102AB }.contains($0)") .unwrap(); - let keypair2 = KeyPair::new_with_rng(builder::Algorithm::Ed25519, &mut rng); - let biscuit2 = biscuit1.append_with_keypair(&keypair2, block2).unwrap(); + let keypair2 = PrivateKey::new_with_rng(builder::Algorithm::Ed25519, &mut rng); + let biscuit2 = biscuit1.append_with_key(&keypair2, block2).unwrap(); let mut authorizer = AuthorizerBuilder::new() .check("check if bytes($0), { hex:00000000, hex:0102AB }.contains($0)") @@ -1417,7 +1419,7 @@ mod tests { #[test] fn block1_generates_authority_or_ambient() { let mut rng: StdRng = SeedableRng::seed_from_u64(0); - let root = KeyPair::new_with_rng(builder::Algorithm::Ed25519, &mut rng); + let root = PrivateKey::new_with_rng(builder::Algorithm::Ed25519, &mut rng); let serialized1 = { let biscuit1 = Biscuit::builder() @@ -1459,9 +1461,9 @@ mod tests { .rule("right($file, $right) <- right($any1, $any2), resource($file), operation($right)") .unwrap(); - let keypair2 = KeyPair::new_with_rng(builder::Algorithm::Ed25519, &mut rng); + let keypair2 = PrivateKey::new_with_rng(builder::Algorithm::Ed25519, &mut rng); let biscuit2 = biscuit1_deser - .append_with_keypair(&keypair2, block2) + .append_with_key(&keypair2, block2) .unwrap(); println!("biscuit2 (1 check): {biscuit2}"); @@ -1499,7 +1501,7 @@ mod tests { #[test] fn check_all() { let mut rng: StdRng = SeedableRng::seed_from_u64(0); - let root = KeyPair::new_with_rng(builder::Algorithm::Ed25519, &mut rng); + let root = PrivateKey::new_with_rng(builder::Algorithm::Ed25519, &mut rng); let biscuit1 = Biscuit::builder() .check("check if fact($v), $v < 1") @@ -1598,7 +1600,7 @@ mod tests { #[test] fn authority_signature_v1() { let mut rng: StdRng = SeedableRng::seed_from_u64(0); - let root = KeyPair::new_with_rng(builder::Algorithm::Ed25519, &mut rng); + let root = PrivateKey::new_with_rng(builder::Algorithm::Ed25519, &mut rng); let authority_block = Block { symbols: default_symbol_table(), @@ -1612,7 +1614,7 @@ mod tests { scopes: vec![], }; - let next_keypair = KeyPair::new_with_rng(builder::Algorithm::Ed25519, &mut rng); + let next_keypair = PrivateKey::new_with_rng(builder::Algorithm::Ed25519, &mut rng); let token = SerializedBiscuit::new_inner(None, &root, &next_keypair, &authority_block, 1).unwrap(); let serialized = token.to_vec().unwrap(); @@ -1623,7 +1625,7 @@ mod tests { #[test] fn verified_unverified_consistency() { let mut rng: StdRng = SeedableRng::seed_from_u64(0); - let root = KeyPair::new_with_rng(builder::Algorithm::Ed25519, &mut rng); + let root = PrivateKey::new_with_rng(builder::Algorithm::Ed25519, &mut rng); let biscuit1 = Biscuit::builder() .fact("right(\"file1\", \"read\")") .unwrap() diff --git a/biscuit-auth/src/token/third_party.rs b/biscuit-auth/src/token/third_party.rs index 7150c96a..84233acc 100644 --- a/biscuit-auth/src/token/third_party.rs +++ b/biscuit-auth/src/token/third_party.rs @@ -12,7 +12,7 @@ use crate::{ datalog::SymbolTable, error, format::{convert::token_block_to_proto_block, schema, SerializedBiscuit}, - KeyPair, PrivateKey, + PrivateKey, }; use super::THIRD_PARTY_SIGNATURE_VERSION; @@ -115,10 +115,9 @@ impl ThirdPartyRequest { THIRD_PARTY_SIGNATURE_VERSION, ); - let keypair = KeyPair::from(private_key); - let signature = keypair.sign(&signed_payload)?; + let signature = private_key.sign(&signed_payload)?; - let public_key = keypair.public(); + let public_key = private_key.public(); let content = schema::ThirdPartyBlockContents { payload, external_signature: schema::ExternalSignature { @@ -160,7 +159,7 @@ mod tests { #[test] fn third_party_request_roundtrip() { let mut rng: rand::rngs::StdRng = rand::SeedableRng::seed_from_u64(0); - let root = KeyPair::new_with_rng(crate::builder::Algorithm::Ed25519, &mut rng); + let root = PrivateKey::new_with_rng(crate::builder::Algorithm::Ed25519, &mut rng); let biscuit1 = crate::Biscuit::builder() .fact("right(\"file1\", \"read\")") .unwrap() diff --git a/biscuit-auth/src/token/unverified.rs b/biscuit-auth/src/token/unverified.rs index 9eea9c53..8e017042 100644 --- a/biscuit-auth/src/token/unverified.rs +++ b/biscuit-auth/src/token/unverified.rs @@ -7,7 +7,7 @@ use prost::Message; use super::{default_symbol_table, Biscuit, Block}; use crate::{ builder::BlockBuilder, - crypto::{self, PublicKey, Signature}, + crypto::{self, PrivateKey, PublicKey, Signature}, datalog::SymbolTable, error, format::{ @@ -16,7 +16,7 @@ use crate::{ SerializedBiscuit, }, token::{ThirdPartyBlockContents, ThirdPartyRequest}, - KeyPair, RootKeyProvider, + RootKeyProvider, }; /// A token that was parsed without cryptographic signature verification @@ -102,12 +102,12 @@ impl UnverifiedBiscuit { /// adds a new block to the token /// - /// since the public key is integrated into the token, the keypair can be - /// discarded right after calling this function + /// since the public key is integrated into the token, the key can be discarded right after + /// calling this function pub fn append(&self, block_builder: BlockBuilder) -> Result { - let keypair = - KeyPair::new_with_rng(super::builder::Algorithm::Ed25519, &mut rand::rngs::OsRng); - self.append_with_keypair(&keypair, block_builder) + let private = + PrivateKey::new_with_rng(super::builder::Algorithm::Ed25519, &mut rand::rngs::OsRng); + self.append_with_key(&private, block_builder) } /// serializes the token @@ -151,11 +151,11 @@ impl UnverifiedBiscuit { /// adds a new block to the token /// - /// since the public key is integrated into the token, the keypair can be - /// discarded right after calling this function - pub fn append_with_keypair( + /// since the public key is integrated into the token, the key can be discarded right after + /// calling this function + pub fn append_with_key( &self, - keypair: &KeyPair, + key: &PrivateKey, block_builder: BlockBuilder, ) -> Result { let block = block_builder.build(self.symbols.clone()); @@ -168,7 +168,7 @@ impl UnverifiedBiscuit { let mut blocks = self.blocks.clone(); let mut symbols = self.symbols.clone(); - let container = self.container.append(keypair, &block, None)?; + let container = self.container.append(key, &block, None)?; symbols.extend(&block.symbols)?; symbols.public_keys.extend(&block.public_keys)?; @@ -300,15 +300,15 @@ impl UnverifiedBiscuit { } pub fn append_third_party(&self, slice: &[u8]) -> Result { - let next_keypair = - KeyPair::new_with_rng(super::builder::Algorithm::Ed25519, &mut rand::rngs::OsRng); - self.append_third_party_with_keypair(slice, next_keypair) + let next_private_key = + PrivateKey::new_with_rng(super::builder::Algorithm::Ed25519, &mut rand::rngs::OsRng); + self.append_third_party_with_key(slice, next_private_key) } - pub fn append_third_party_with_keypair( + pub fn append_third_party_with_key( &self, slice: &[u8], - next_keypair: KeyPair, + next_key: PrivateKey, ) -> Result { let ThirdPartyBlockContents { payload, @@ -350,7 +350,7 @@ impl UnverifiedBiscuit { let container = self.container - .append_serialized(&next_keypair, payload, Some(external_signature))?; + .append_serialized(&next_key, payload, Some(external_signature))?; let token_block = proto_block_to_token_block(&block, Some(external_key)).unwrap(); for key in &token_block.public_keys.keys { @@ -378,14 +378,14 @@ impl UnverifiedBiscuit { #[cfg(test)] mod tests { - use crate::{BiscuitBuilder, BlockBuilder, KeyPair}; + use crate::{BiscuitBuilder, BlockBuilder, PrivateKey}; use super::UnverifiedBiscuit; #[test] fn consistent_with_biscuit() { - let root_key = KeyPair::new(); - let external_key = KeyPair::new(); + let root_key = PrivateKey::new(); + let external_key = PrivateKey::new(); let biscuit = BiscuitBuilder::new() .fact("test(true)") .unwrap() diff --git a/biscuit-auth/tests/macros.rs b/biscuit-auth/tests/macros.rs index 7ff2653e..11a1b7f9 100644 --- a/biscuit-auth/tests/macros.rs +++ b/biscuit-auth/tests/macros.rs @@ -2,7 +2,7 @@ * Copyright (c) 2019 Geoffroy Couprie and Contributors to the Eclipse Foundation. * SPDX-License-Identifier: Apache-2.0 */ -use biscuit_auth::{builder, datalog::RunLimits, KeyPair, PublicKey}; +use biscuit_auth::{builder, datalog::RunLimits, PrivateKey, PublicKey}; use biscuit_quote::{ authorizer, authorizer_merge, biscuit, biscuit_merge, block, block_merge, check, fact, policy, rule, @@ -256,7 +256,7 @@ fn policy_macro() { #[test] fn json() { - let key_pair = KeyPair::new(); + let key_pair = PrivateKey::new(); let biscuit = biscuit!(r#"user(123)"#).build(&key_pair).unwrap(); let value: serde_json::Value = json!( diff --git a/biscuit-auth/tests/rights.rs b/biscuit-auth/tests/rights.rs index 1b3df28c..20540579 100644 --- a/biscuit-auth/tests/rights.rs +++ b/biscuit-auth/tests/rights.rs @@ -5,7 +5,6 @@ #![allow(unused_must_use)] use biscuit::builder::*; use biscuit::datalog::SymbolTable; -use biscuit::KeyPair; use biscuit::*; use biscuit_auth as biscuit; @@ -13,7 +12,7 @@ use rand::{prelude::StdRng, SeedableRng}; fn main() { let mut rng: StdRng = SeedableRng::seed_from_u64(1234); - let root = KeyPair::new_with_rng(builder::Algorithm::Ed25519, &mut rng); + let root = PrivateKey::new_with_rng(builder::Algorithm::Ed25519, &mut rng); let biscuit1 = Biscuit::builder() .fact(fact( diff --git a/biscuit-capi/src/lib.rs b/biscuit-capi/src/lib.rs index d175aa3a..15e8f1be 100644 --- a/biscuit-capi/src/lib.rs +++ b/biscuit-capi/src/lib.rs @@ -300,7 +300,7 @@ pub extern "C" fn error_check_is_authorizer(check_index: u64) -> bool { } pub struct Biscuit(biscuit_auth::Biscuit); -pub struct KeyPair(biscuit_auth::KeyPair); +pub struct PrivateKey(biscuit_auth::PrivateKey); pub struct PublicKey(biscuit_auth::PublicKey); pub struct BiscuitBuilder(Option); pub struct BlockBuilder(Option); @@ -319,7 +319,7 @@ pub unsafe extern "C" fn key_pair_new<'a>( seed_ptr: *const u8, seed_len: usize, algorithm: SignatureAlgorithm, -) -> Option> { +) -> Option> { let slice = std::slice::from_raw_parts(seed_ptr, seed_len); if slice.len() != 32 { update_last_error(Error::InvalidArgument); @@ -335,13 +335,13 @@ pub unsafe extern "C" fn key_pair_new<'a>( SignatureAlgorithm::Secp256r1 => biscuit_auth::builder::Algorithm::Secp256r1, }; - Some(Box::new(KeyPair(biscuit_auth::KeyPair::new_with_rng( + Some(Box::new(PrivateKey(biscuit_auth::PrivateKey::new_with_rng( algorithm, &mut rng, )))) } #[no_mangle] -pub unsafe extern "C" fn key_pair_public(kp: Option<&KeyPair>) -> Option> { +pub unsafe extern "C" fn key_pair_public(kp: Option<&PrivateKey>) -> Option> { if kp.is_none() { update_last_error(Error::InvalidArgument); } @@ -352,7 +352,7 @@ pub unsafe extern "C" fn key_pair_public(kp: Option<&KeyPair>) -> Option, buffer_ptr: *mut u8) -> usize { +pub unsafe extern "C" fn key_pair_serialize(kp: Option<&PrivateKey>, buffer_ptr: *mut u8) -> usize { if kp.is_none() { update_last_error(Error::InvalidArgument); return 0; @@ -361,7 +361,7 @@ pub unsafe extern "C" fn key_pair_serialize(kp: Option<&KeyPair>, buffer_ptr: *m let output_slice = std::slice::from_raw_parts_mut(buffer_ptr, 32); - output_slice.copy_from_slice(&kp.0.private().to_bytes()[..]); + output_slice.copy_from_slice(&kp.0.to_bytes()[..]); 32 } @@ -370,7 +370,7 @@ pub unsafe extern "C" fn key_pair_serialize(kp: Option<&KeyPair>, buffer_ptr: *m pub unsafe extern "C" fn key_pair_deserialize( buffer_ptr: *mut u8, algorithm: SignatureAlgorithm, -) -> Option> { +) -> Option> { let input_slice = std::slice::from_raw_parts_mut(buffer_ptr, 32); let algorithm = match algorithm { @@ -385,12 +385,12 @@ pub unsafe extern "C" fn key_pair_deserialize( update_last_error(Error::InvalidArgument); None } - Some(privkey) => Some(Box::new(KeyPair(biscuit_auth::KeyPair::from(&privkey)))), + Some(privkey) => Some(Box::new(PrivateKey(biscuit_auth::PrivateKey::from(&privkey)))), } } #[no_mangle] -pub unsafe extern "C" fn key_pair_to_pem(kp: Option<&KeyPair>) -> *const c_char { +pub unsafe extern "C" fn key_pair_to_pem(kp: Option<&PrivateKey>) -> *const c_char { let kp = match kp { Some(kp) => kp, None => { @@ -415,10 +415,10 @@ pub unsafe extern "C" fn key_pair_to_pem(kp: Option<&KeyPair>) -> *const c_char } #[no_mangle] -pub unsafe extern "C" fn key_pair_from_pem(pem: *const c_char) -> Option> { +pub unsafe extern "C" fn key_pair_from_pem(pem: *const c_char) -> Option> { match CStr::from_ptr(pem).to_str() { - Ok(pem_str) => match biscuit_auth::KeyPair::from_private_key_pem(pem_str) { - Ok(kp) => Some(Box::new(KeyPair(kp))), + Ok(pem_str) => match biscuit_auth::PrivateKey::from_private_key_pem(pem_str) { + Ok(kp) => Some(Box::new(PrivateKey(kp))), Err(_) => { update_last_error(Error::InvalidArgument); None @@ -432,7 +432,7 @@ pub unsafe extern "C" fn key_pair_from_pem(pem: *const c_char) -> Option>) {} +pub unsafe extern "C" fn key_pair_free(_kp: Option>) {} /// expects a 32 byte buffer #[no_mangle] @@ -690,7 +690,7 @@ pub unsafe extern "C" fn biscuit_builder_add_check( #[no_mangle] pub unsafe extern "C" fn biscuit_builder_build( builder: Option<&BiscuitBuilder>, - key_pair: Option<&KeyPair>, + key_pair: Option<&PrivateKey>, seed_ptr: *const u8, seed_len: usize, ) -> Option> { @@ -943,7 +943,7 @@ pub unsafe extern "C" fn create_block() -> Box { pub unsafe extern "C" fn biscuit_append_block( biscuit: Option<&Biscuit>, block_builder: Option<&BlockBuilder>, - key_pair: Option<&KeyPair>, + key_pair: Option<&PrivateKey>, ) -> Option> { if biscuit.is_none() { update_last_error(Error::InvalidArgument); @@ -962,7 +962,7 @@ pub unsafe extern "C" fn biscuit_append_block( match biscuit .0 - .append_with_keypair(&key_pair.0, builder.0.clone().expect("builder is none")) + .append_with_key(&key_pair.0, builder.0.clone().expect("builder is none")) { Ok(token) => Some(Box::new(Biscuit(token))), Err(e) => { diff --git a/biscuit-capi/tests/capi.rs b/biscuit-capi/tests/capi.rs index b81fa756..96306dee 100644 --- a/biscuit-capi/tests/capi.rs +++ b/biscuit-capi/tests/capi.rs @@ -15,7 +15,7 @@ fn build() { int main() { char *seed = "abcdefghabcdefghabcdefghabcdefgh"; - KeyPair * root_kp = key_pair_new((const uint8_t *) seed, strlen(seed), 0); + PrivateKey * root_kp = key_pair_new((const uint8_t *) seed, strlen(seed), 0); printf("key_pair creation error? %s\n", error_message()); PublicKey* root = key_pair_public(root_kp); @@ -35,7 +35,7 @@ fn build() { char *seed2 = "ijklmnopijklmnopijklmnopijklmnop"; - KeyPair * kp2 = key_pair_new((const uint8_t *) seed2, strlen(seed2), 0); + PrivateKey * kp2 = key_pair_new((const uint8_t *) seed2, strlen(seed2), 0); Biscuit* b2 = biscuit_append_block(biscuit, bb, kp2); printf("biscuit append error? %s\n", error_message()); @@ -163,7 +163,7 @@ fn serialize_keys() { uint8_t * pub_buf = malloc(32); - KeyPair * kp = key_pair_new((const uint8_t *) seed, strlen(seed), 0); + PrivateKey * kp = key_pair_new((const uint8_t *) seed, strlen(seed), 0); printf("key_pair creation error? %s\n", error_message()); PublicKey * pubkey = key_pair_public(kp); @@ -183,7 +183,7 @@ fn serialize_keys() { const char * kp_pem = key_pair_to_pem(kp); printf("key pair pem: %s\n", kp_pem); - KeyPair * kp2 = key_pair_from_pem(kp_pem); + PrivateKey * kp2 = key_pair_from_pem(kp_pem); if (kp2 == NULL) { printf("key pair from pem error %s\n", error_message()); From 57c6ce4d10161ae550092990c605308d78f9db20 Mon Sep 17 00:00:00 2001 From: Saoirse Aronson Date: Wed, 24 Jun 2026 09:03:48 +0200 Subject: [PATCH 2/3] Abstract biscuits over crypto implementation This commit adds four traits to biscuit-auth: `Sign`, `Verify`, `SerializePublicKey` and `SerializePrivateKey`. Together, these represent the behaviors of private keys and public keys, including those which can be serialized into the token and those which can't. Biscuit themselves become parameterized by the private key type that their proof uses (the public keys used in the token being determined as associated types of that private key type). These public and private keys must be serializable. For issuing a token, the keys used do not need to be serializable, and do not need to be the same as used for the token-internal keys. For third party signing, only the public key needs to be serializable. Some refactors were made to enable this change: 1. The `Keypair` type was eliminated from the code; it's function is fulfilled by the private key type and a third type was not necessary. 2. The useage of public keys in datalog authorizer running doesn't need an actual crypto implementation, just key data, so its replaced by an inert public key type that contains the algorithm tag and bytes. --- biscuit-auth/benches/token.rs | 2 +- biscuit-auth/examples/testcases.rs | 14 +- biscuit-auth/examples/third_party.rs | 2 +- biscuit-auth/src/crypto/mod.rs | 252 +++++++++++------- biscuit-auth/src/crypto/traits.rs | 34 +++ biscuit-auth/src/datalog/symbol.rs | 9 +- biscuit-auth/src/format/convert.rs | 28 +- biscuit-auth/src/format/mod.rs | 163 ++++++----- biscuit-auth/src/lib.rs | 1 + biscuit-auth/src/token/authorizer.rs | 28 +- biscuit-auth/src/token/authorizer/snapshot.rs | 23 +- biscuit-auth/src/token/block.rs | 7 +- biscuit-auth/src/token/builder.rs | 17 +- biscuit-auth/src/token/builder/authorizer.rs | 26 +- biscuit-auth/src/token/builder/biscuit.rs | 27 +- biscuit-auth/src/token/builder/block.rs | 6 +- biscuit-auth/src/token/builder/check.rs | 7 +- biscuit-auth/src/token/builder/policy.rs | 6 +- biscuit-auth/src/token/builder/rule.rs | 8 +- biscuit-auth/src/token/builder/scope.rs | 14 +- biscuit-auth/src/token/mod.rs | 144 ++++++---- biscuit-auth/src/token/public_keys.rs | 104 ++++++-- biscuit-auth/src/token/third_party.rs | 5 +- biscuit-auth/src/token/unverified.rs | 37 ++- biscuit-auth/tests/macros.rs | 51 ++-- biscuit-parser/src/builder.rs | 4 +- 26 files changed, 626 insertions(+), 393 deletions(-) create mode 100644 biscuit-auth/src/crypto/traits.rs diff --git a/biscuit-auth/benches/token.rs b/biscuit-auth/benches/token.rs index 0f6e505c..cfec9a5a 100644 --- a/biscuit-auth/benches/token.rs +++ b/biscuit-auth/benches/token.rs @@ -1,4 +1,4 @@ -/g +/* * Copyright (c) 2019 Geoffroy Couprie and Contributors to the Eclipse Foundation. * SPDX-License-Identifier: Apache-2.0 */ diff --git a/biscuit-auth/examples/testcases.rs b/biscuit-auth/examples/testcases.rs index 17de71f7..f8f6907f 100644 --- a/biscuit-auth/examples/testcases.rs +++ b/biscuit-auth/examples/testcases.rs @@ -177,7 +177,7 @@ fn run(target: String, root_key: Option, test: bool, json: bool) { if json { let s = serde_json::to_string_pretty(&TestCases { - root_private_key: hex::encode(root.private().to_bytes()), + root_private_key: hex::encode(root.to_bytes()), root_public_key: hex::encode(root.public().to_bytes()), testcases: results, }) @@ -188,7 +188,7 @@ fn run(target: String, root_key: Option, test: bool, json: bool) { println!("# Biscuit samples and expected results\n"); println!( "root secret key: {}", - hex::encode(root.private().to_bytes()) + hex::encode(root.to_bytes()) ); println!("root public key: {}", hex::encode(root.public().to_bytes())); @@ -1660,7 +1660,7 @@ fn third_party(target: &str, root: &PrivateKey, test: bool) -> TestResult { let res = req .create_block( - &external.private(), + &external, block!( r#" group("admin"); @@ -1802,7 +1802,7 @@ fn public_keys_interning(target: &str, root: &PrivateKey, test: bool) -> TestRes let res1 = req1 .create_block( - &external1.private(), + &external1, block!( r#" query(1); @@ -1827,7 +1827,7 @@ fn public_keys_interning(target: &str, root: &PrivateKey, test: bool) -> TestRes let req2 = biscuit2.third_party_request().unwrap(); let res2 = req2 .create_block( - &external2.private(), + &external2, block!( r#" query(2); @@ -1851,7 +1851,7 @@ fn public_keys_interning(target: &str, root: &PrivateKey, test: bool) -> TestRes let req3 = biscuit3.third_party_request().unwrap(); let res3 = req3 .create_block( - &external2.private(), + &external2, block!( r#" query(3); @@ -2421,7 +2421,7 @@ fn secp256r1_third_party(target: &str, root: &PrivateKey, test: bool) -> TestRes let req = biscuit1.third_party_request().unwrap(); let block = req .create_block( - &external_keypair.private(), + &external_keypair, block!( r#" check if resource($0), operation("read"), right($0, "read"); from_third(true);"# ), diff --git a/biscuit-auth/examples/third_party.rs b/biscuit-auth/examples/third_party.rs index ff5954e1..2dadbeeb 100644 --- a/biscuit-auth/examples/third_party.rs +++ b/biscuit-auth/examples/third_party.rs @@ -34,7 +34,7 @@ fn main() { let builder = BlockBuilder::new() .fact("external_fact(\"hello\")") .unwrap(); - let res = req.create_block(&external.private(), builder).unwrap(); + let res = req.create_block(&external, builder).unwrap(); let biscuit2 = biscuit1.append_third_party(external.public(), res).unwrap(); diff --git a/biscuit-auth/src/crypto/mod.rs b/biscuit-auth/src/crypto/mod.rs index 556be5d3..bf865eaa 100644 --- a/biscuit-auth/src/crypto/mod.rs +++ b/biscuit-auth/src/crypto/mod.rs @@ -11,20 +11,26 @@ //! //! The implementation is based on [ed25519_dalek](https://github.com/dalek-cryptography/ed25519-dalek). #![allow(non_snake_case)] -use crate::builder::Algorithm; -use crate::format::schema; -use crate::format::ThirdPartyVerificationMode; - -use super::error; mod ed25519; mod p256; +mod traits; -use nom::Finish; -use rand_core::{CryptoRng, RngCore}; use std::fmt; use std::hash::Hash; use std::str::FromStr; +use nom::Finish; +use rand_core::{CryptoRng, RngCore}; +use zeroize::Zeroizing; + +use crate::builder::Algorithm; +use crate::format::schema; +use crate::format::ThirdPartyVerificationMode; + +use super::error; + +pub use self::traits::{Verify, Sign, SerializePublicKey, SerializePrivateKey}; + /// the private part of a signing key pair #[derive(Debug, Clone, PartialEq)] pub enum PrivateKey { @@ -116,13 +122,6 @@ impl PrivateKey { } } - pub fn private(&self) -> PrivateKey { - match self { - PrivateKey::Ed25519(key) => PrivateKey::Ed25519(key.clone()), - PrivateKey::P256(key) => PrivateKey::P256(key.clone()), - } - } - pub fn public(&self) -> PublicKey { match self { PrivateKey::Ed25519(key) => PublicKey::Ed25519(key.public()), @@ -130,10 +129,10 @@ impl PrivateKey { } } - pub fn algorithm(&self) -> crate::format::schema::public_key::Algorithm { + pub fn algorithm(&self) -> Algorithm { match self { - PrivateKey::Ed25519(_) => crate::format::schema::public_key::Algorithm::Ed25519, - PrivateKey::P256(_) => crate::format::schema::public_key::Algorithm::Secp256r1, + PrivateKey::Ed25519(_) => Algorithm::Ed25519, + PrivateKey::P256(_) => Algorithm::Secp256r1, } } @@ -153,8 +152,8 @@ impl PrivateKey { /// serializes to an hex-encoded string, prefixed with the key algorithm pub fn to_prefixed_string(&self) -> String { let algorithm = match self.algorithm() { - schema::public_key::Algorithm::Ed25519 => "ed25519-private", - schema::public_key::Algorithm::Secp256r1 => "secp256r1-private", + Algorithm::Ed25519 => "ed25519-private", + Algorithm::Secp256r1 => "secp256r1-private", }; format!("{algorithm}/{}", self.to_bytes_hex()) } @@ -219,7 +218,6 @@ impl PrivateKey { } } - impl Default for PrivateKey { fn default() -> Self { Self::new() @@ -242,6 +240,39 @@ impl FromStr for PrivateKey { } } +impl Sign for PrivateKey { + type PublicKey = PublicKey; + + fn sign(&self, data: &[u8]) -> Result { + self.sign(data) + } + + fn public(&self) -> Self::PublicKey { + self.public() + } + + fn algorithm(&self) -> Algorithm { + match self { + PrivateKey::Ed25519(_) => Algorithm::Ed25519, + PrivateKey::P256(_) => Algorithm::Secp256r1, + } + } +} + +impl SerializePrivateKey for PrivateKey { + fn new_with_rng(algorithm: Algorithm, rng: &mut R) -> Self { + Self::new_with_rng(algorithm, rng) + } + + fn from_bytes_and_algorithm(algorithm: Algorithm, bytes: &[u8]) -> Result { + Self::from_bytes(bytes, algorithm) + } + + fn to_bytes(&self) -> Zeroizing> { + self.to_bytes() + } +} + /// the public part of a signing key pair #[derive(Debug, Clone, Copy, PartialEq, Hash, Eq)] pub enum PublicKey { @@ -355,10 +386,10 @@ impl PublicKey { } } - pub fn algorithm(&self) -> crate::format::schema::public_key::Algorithm { + pub fn algorithm(&self) -> Algorithm { match self { - PublicKey::Ed25519(_) => crate::format::schema::public_key::Algorithm::Ed25519, - PublicKey::P256(_) => crate::format::schema::public_key::Algorithm::Secp256r1, + PublicKey::Ed25519(_) => Algorithm::Ed25519, + PublicKey::P256(_) => Algorithm::Secp256r1, } } @@ -384,12 +415,47 @@ impl PublicKey { } } +pub fn print(k: &K) -> String { + let bytes = hex::encode(k.to_bytes()); + match k.algorithm() { + Algorithm::Ed25519 => format!("ed25519/{bytes}"), + Algorithm::Secp256r1 => format!("secp256r1/{bytes}"), + } +} + impl fmt::Display for PublicKey { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { self.write(f) } } +impl Verify for PublicKey { + fn verify_signature( + &self, + data: &[u8], + signature: &Signature, + ) -> Result<(), error::Format> { + self.verify_signature(data, signature) + } + + fn algorithm(&self) -> Algorithm { + match self { + PublicKey::Ed25519(_) => Algorithm::Ed25519, + PublicKey::P256(_) => Algorithm::Secp256r1, + } + } +} + +impl SerializePublicKey for PublicKey { + fn from_bytes_and_algorithm(algorithm: Algorithm, bytes: &[u8]) -> Result { + Self::from_bytes(bytes, algorithm) + } + + fn to_bytes(&self) -> Vec { + self.to_bytes() + } +} + #[derive(Clone, Debug)] pub struct Signature(pub(crate) Vec); @@ -425,35 +491,35 @@ impl FromStr for PublicKey { } #[derive(Clone, Debug)] -pub struct Block { +pub struct Block { pub(crate) data: Vec, - pub(crate) next_key: PublicKey, + pub(crate) next_key: NK, pub signature: Signature, - pub external_signature: Option, + pub external_signature: Option>, pub version: u32, } #[derive(Clone, Debug)] -pub struct ExternalSignature { - pub(crate) public_key: PublicKey, +pub struct ExternalSignature { + pub(crate) public_key: EK, pub(crate) signature: Signature, } #[derive(Clone, Debug)] -pub enum TokenNext { - Secret(PrivateKey), +pub enum Proof { + Secret(PK), Seal(Signature), } -pub fn sign_authority_block( - key: &PrivateKey, - next_key: &PrivateKey, +pub fn sign_authority_block( + key: &IK, + next_key: &NK, message: &[u8], version: u32, ) -> Result { let to_sign = match version { - 0 => generate_authority_block_signature_payload_v0(message, &next_key.public()), - 1 => generate_authority_block_signature_payload_v1(message, &next_key.public(), version), + 0 => generate_authority_block_signature_payload_v0(message, next_key), + 1 => generate_authority_block_signature_payload_v1(message, next_key, version), _ => { return Err(error::Format::DeserializationError(format!( "unsupported block version: {version}" @@ -467,19 +533,19 @@ pub fn sign_authority_block( Ok(Signature(signature.to_bytes().to_vec())) } -pub fn sign_block( - key: &PrivateKey, - next_key: &PrivateKey, +pub fn sign_block( + key: &AK, + next_key: &NK, message: &[u8], - external_signature: Option<&ExternalSignature>, + external_signature: Option<&ExternalSignature>, previous_signature: &Signature, version: u32, ) -> Result { let to_sign = match version { - 0 => generate_block_signature_payload_v0(message, &next_key.public(), external_signature), + 0 => generate_block_signature_payload_v0(message, next_key, external_signature), 1 => generate_block_signature_payload_v1( message, - &next_key.public(), + next_key, external_signature, previous_signature, version, @@ -495,9 +561,9 @@ pub fn sign_block( Ok(key.sign(&to_sign)?) } -pub fn verify_authority_block_signature( - block: &Block, - public_key: &PublicKey, +pub fn verify_authority_block_signature( + block: &Block, + public_key: &IK, ) -> Result<(), error::Format> { let to_verify = match block.version { 0 => generate_block_signature_payload_v0( @@ -521,9 +587,9 @@ pub fn verify_authority_block_signature( public_key.verify_signature(&to_verify, &block.signature) } -pub fn verify_block_signature( - block: &Block, - public_key: &PublicKey, +pub fn verify_block_signature( + block: &Block, + public_key: &AK, previous_signature: &Signature, verification_mode: ThirdPartyVerificationMode, ) -> Result<(), error::Format> { @@ -564,11 +630,11 @@ pub fn verify_block_signature( Ok(()) } -pub fn verify_external_signature( +pub fn verify_external_signature( payload: &[u8], - public_key: &PublicKey, + public_key: &AK, previous_signature: &Signature, - external_signature: &ExternalSignature, + external_signature: &ExternalSignature, version: u32, verification_mode: ThirdPartyVerificationMode, ) -> Result<(), error::Format> { @@ -586,9 +652,9 @@ pub fn verify_external_signature( .verify_signature(&to_verify, &external_signature.signature) } -pub(crate) fn generate_authority_block_signature_payload_v0( +pub(crate) fn generate_authority_block_signature_payload_v0( payload: &[u8], - next_key: &PublicKey, + next_key: &NK, ) -> Vec { let mut to_verify = payload.to_vec(); @@ -597,10 +663,10 @@ pub(crate) fn generate_authority_block_signature_payload_v0( to_verify } -pub(crate) fn generate_block_signature_payload_v0( +pub(crate) fn generate_block_signature_payload_v0( payload: &[u8], - next_key: &PublicKey, - external_signature: Option<&ExternalSignature>, + next_key: &NK, + external_signature: Option<&ExternalSignature>, ) -> Vec { let mut to_verify = payload.to_vec(); @@ -612,9 +678,9 @@ pub(crate) fn generate_block_signature_payload_v0( to_verify } -pub(crate) fn generate_authority_block_signature_payload_v1( +pub(crate) fn generate_authority_block_signature_payload_v1( payload: &[u8], - next_key: &PublicKey, + next_key: &NK, version: u32, ) -> Vec { let mut to_verify = b"\0BLOCK\0\0VERSION\0".to_vec(); @@ -632,10 +698,10 @@ pub(crate) fn generate_authority_block_signature_payload_v1( to_verify } -pub(crate) fn generate_block_signature_payload_v1( +pub(crate) fn generate_block_signature_payload_v1( payload: &[u8], - next_key: &PublicKey, - external_signature: Option<&ExternalSignature>, + next_key: &NK, + external_signature: Option<&ExternalSignature>, previous_signature: &Signature, version: u32, ) -> Vec { @@ -662,7 +728,7 @@ pub(crate) fn generate_block_signature_payload_v1( to_verify } -fn generate_external_signature_payload_v0(payload: &[u8], previous_key: &PublicKey) -> Vec { +fn generate_external_signature_payload_v0(payload: &[u8], previous_key: &AK) -> Vec { let mut to_verify = payload.to_vec(); to_verify.extend(&(previous_key.algorithm() as i32).to_le_bytes()); to_verify.extend(&previous_key.to_bytes()); @@ -686,7 +752,7 @@ pub(crate) fn generate_external_signature_payload_v1( to_verify } -pub(crate) fn generate_seal_signature_payload_v0(block: &Block) -> Vec { +pub(crate) fn generate_seal_signature_payload_v0(block: &Block) -> Vec { let mut to_verify = block.data.to_vec(); to_verify.extend(&(block.next_key.algorithm() as i32).to_le_bytes()); to_verify.extend(&block.next_key.to_bytes()); @@ -694,18 +760,18 @@ pub(crate) fn generate_seal_signature_payload_v0(block: &Block) -> Vec { to_verify } -impl TokenNext { - pub fn private_key(&self) -> Result { +impl Proof { + pub fn private_key(&self) -> Result { match &self { - TokenNext::Seal(_) => Err(error::Token::AlreadySealed), - TokenNext::Secret(private) => Ok(private.clone()), + Proof::Seal(_) => Err(error::Token::AlreadySealed), + Proof::Secret(private) => Ok(private.clone()), } } pub fn is_sealed(&self) -> bool { match &self { - TokenNext::Seal(_) => true, - TokenNext::Secret(_) => false, + Proof::Seal(_) => true, + Proof::Secret(_) => false, } } } @@ -738,9 +804,8 @@ mod tests { ed_root.public().to_string().parse().unwrap() ); assert_eq!( - ed_root.private().to_bytes(), + ed_root.to_bytes(), ed_root - .private() .to_prefixed_string() .parse::() .unwrap() @@ -752,9 +817,8 @@ mod tests { p256_root.public().to_string().parse().unwrap() ); assert_eq!( - p256_root.private().to_bytes(), + p256_root.to_bytes(), p256_root - .private() .to_prefixed_string() .parse::() .unwrap() @@ -841,16 +905,15 @@ mod tests { #[cfg(feature = "pem")] #[test] fn ed25519_der() { - let ed25519_kp = PrivateKey::new_with_algorithm(Algorithm::Ed25519); - let der_kp = ed25519_kp.to_private_key_der().unwrap(); + let ed25519_priv = PrivateKey::new_with_algorithm(Algorithm::Ed25519); + let der_kp = ed25519_priv.to_private_key_der().unwrap(); let deser = PrivateKey::from_private_key_der_with_algorithm(&der_kp, Algorithm::Ed25519).unwrap(); - assert_eq!(ed25519_kp, deser); + assert_eq!(ed25519_priv, deser); let deser = PrivateKey::from_private_key_der(&der_kp).unwrap(); - assert_eq!(ed25519_kp, deser); + assert_eq!(ed25519_priv, deser); - let ed25519_priv = ed25519_kp.private(); let der_priv = ed25519_priv.to_der().unwrap(); let deser_priv = PrivateKey::from_der_with_algorithm(&der_priv, Algorithm::Ed25519).unwrap(); @@ -858,7 +921,7 @@ mod tests { let deser_priv = PrivateKey::from_der(&der_priv).unwrap(); assert_eq!(ed25519_priv, deser_priv); - let ed25519_pub = ed25519_kp.public(); + let ed25519_pub = ed25519_priv.public(); let der_pub = ed25519_pub.to_der().unwrap(); let deser_pub = PublicKey::from_der_with_algorithm(&der_pub, Algorithm::Ed25519).unwrap(); assert_eq!(ed25519_pub, deser_pub); @@ -869,15 +932,14 @@ mod tests { #[cfg(feature = "pem")] #[test] fn ed25519_pem() { - let ed25519_kp = PrivateKey::new_with_algorithm(Algorithm::Ed25519); - let pem_kp = ed25519_kp.to_private_key_pem().unwrap(); + let ed25519_priv = PrivateKey::new_with_algorithm(Algorithm::Ed25519); + let pem_kp = ed25519_priv.to_private_key_pem().unwrap(); let deser = PrivateKey::from_private_key_pem_with_algorithm(&pem_kp, Algorithm::Ed25519).unwrap(); - assert_eq!(ed25519_kp, deser); + assert_eq!(ed25519_priv, deser); let deser = PrivateKey::from_private_key_pem(&pem_kp).unwrap(); - assert_eq!(ed25519_kp, deser); + assert_eq!(ed25519_priv, deser); - let ed25519_priv = ed25519_kp.private(); let pem_priv = ed25519_priv.to_pem().unwrap(); let deser_priv = PrivateKey::from_pem_with_algorithm(&pem_priv, Algorithm::Ed25519).unwrap(); @@ -885,7 +947,7 @@ mod tests { let deser_priv = PrivateKey::from_pem(&pem_priv).unwrap(); assert_eq!(ed25519_priv, deser_priv); - let ed25519_pub = ed25519_kp.public(); + let ed25519_pub = ed25519_priv.public(); let pem_pub = ed25519_pub.to_pem().unwrap(); let deser_pub = PublicKey::from_pem_with_algorithm(&pem_pub, Algorithm::Ed25519).unwrap(); assert_eq!(ed25519_pub, deser_pub); @@ -896,15 +958,14 @@ mod tests { #[cfg(feature = "pem")] #[test] fn p256_der() { - let p256_kp = PrivateKey::new_with_algorithm(Algorithm::Secp256r1); - let der_kp = p256_kp.to_private_key_der().unwrap(); + let p256_priv = PrivateKey::new_with_algorithm(Algorithm::Secp256r1); + let der_kp = p256_priv.to_private_key_der().unwrap(); let deser = PrivateKey::from_private_key_der_with_algorithm(&der_kp, Algorithm::Secp256r1).unwrap(); - assert_eq!(p256_kp, deser); + assert_eq!(p256_priv, deser); let deser = PrivateKey::from_private_key_der(&der_kp).unwrap(); - assert_eq!(p256_kp, deser); + assert_eq!(p256_priv, deser); - let p256_priv = p256_kp.private(); let der_priv = p256_priv.to_der().unwrap(); let deser_priv = PrivateKey::from_der_with_algorithm(&der_priv, Algorithm::Secp256r1).unwrap(); @@ -912,7 +973,7 @@ mod tests { let deser_priv = PrivateKey::from_der(&der_priv).unwrap(); assert_eq!(p256_priv, deser_priv); - let p256_pub = p256_kp.public(); + let p256_pub = p256_priv.public(); let der_pub = p256_pub.to_der().unwrap(); let deser_pub = PublicKey::from_der_with_algorithm(&der_pub, Algorithm::Secp256r1).unwrap(); assert_eq!(p256_pub, deser_pub); @@ -923,15 +984,14 @@ mod tests { #[cfg(feature = "pem")] #[test] fn p256_pem() { - let p256_kp = PrivateKey::new_with_algorithm(Algorithm::Secp256r1); - let pem_kp = p256_kp.to_private_key_pem().unwrap(); + let p256_priv = PrivateKey::new_with_algorithm(Algorithm::Secp256r1); + let pem_kp = p256_priv.to_private_key_pem().unwrap(); let deser = PrivateKey::from_private_key_pem_with_algorithm(&pem_kp, Algorithm::Secp256r1).unwrap(); - assert_eq!(p256_kp, deser); + assert_eq!(p256_priv, deser); let deser = PrivateKey::from_private_key_pem(&pem_kp).unwrap(); - assert_eq!(p256_kp, deser); + assert_eq!(p256_priv, deser); - let p256_priv = p256_kp.private(); let pem_priv = p256_priv.to_pem().unwrap(); let deser_priv = PrivateKey::from_pem_with_algorithm(&pem_priv, Algorithm::Secp256r1).unwrap(); @@ -939,7 +999,7 @@ mod tests { let deser_priv = PrivateKey::from_pem(&pem_priv).unwrap(); assert_eq!(p256_priv, deser_priv); - let p256_pub = p256_kp.public(); + let p256_pub = p256_priv.public(); let pem_pub = p256_pub.to_pem().unwrap(); let deser_pub = PublicKey::from_pem_with_algorithm(&pem_pub, Algorithm::Secp256r1).unwrap(); assert_eq!(p256_pub, deser_pub); diff --git a/biscuit-auth/src/crypto/traits.rs b/biscuit-auth/src/crypto/traits.rs new file mode 100644 index 00000000..68d6f8b0 --- /dev/null +++ b/biscuit-auth/src/crypto/traits.rs @@ -0,0 +1,34 @@ +use rand::{CryptoRng, RngCore}; +use zeroize::Zeroizing; + +use crate::builder::Algorithm; +use crate::crypto::Signature; +use crate::error; + +pub trait Verify { + fn verify_signature( + &self, + data: &[u8], + signature: &Signature, + ) -> Result<(), error::Format>; + fn algorithm(&self) -> Algorithm; +} + +pub trait Sign { + type PublicKey: Verify; + + fn sign(&self, data: &[u8]) -> Result; + fn public(&self) -> Self::PublicKey; + fn algorithm(&self) -> Algorithm; +} + +pub trait SerializePublicKey: Verify + Clone + PartialEq + Sized { + fn from_bytes_and_algorithm(algorithm: Algorithm, bytes: &[u8]) -> Result; + fn to_bytes(&self) -> Vec; +} + +pub trait SerializePrivateKey: Sign + Clone + Sized { + fn new_with_rng(algorithm: Algorithm, rng: &mut R) -> Self; + fn from_bytes_and_algorithm(algorithm: Algorithm, bytes: &[u8]) -> Result; + fn to_bytes(&self) -> Zeroizing>; +} diff --git a/biscuit-auth/src/datalog/symbol.rs b/biscuit-auth/src/datalog/symbol.rs index 4b17b1a6..f06f2d41 100644 --- a/biscuit-auth/src/datalog/symbol.rs +++ b/biscuit-auth/src/datalog/symbol.rs @@ -6,13 +6,14 @@ use std::collections::HashSet; use time::{format_description::well_known::Rfc3339, OffsetDateTime}; -pub type SymbolIndex = u64; -use crate::crypto::PublicKey; use crate::token::default_symbol_table; +use crate::token::public_keys::PublicKey; use crate::{error, token::public_keys::PublicKeys}; use super::{Check, Fact, Predicate, Rule, Term, World}; +pub type SymbolIndex = u64; + #[derive(Clone, Debug, PartialEq, Eq)] pub struct SymbolTable { symbols: Vec, @@ -79,7 +80,7 @@ impl SymbolTable { public_keys: Vec, ) -> Result { let mut table = Self::from(symbols)?; - table.public_keys = PublicKeys::from(public_keys); + table.public_keys = PublicKeys::from_keys(public_keys); Ok(table) } @@ -291,7 +292,7 @@ impl SymbolTable { crate::token::Scope::Previous => "previous".to_string(), crate::token::Scope::PublicKey(key_id) => { match self.public_keys.get_key(*key_id) { - Some(key) => key.print(), + Some(key) => key.to_string(), None => "".to_string(), } } diff --git a/biscuit-auth/src/format/convert.rs b/biscuit-auth/src/format/convert.rs index d1932601..acd22f2a 100644 --- a/biscuit-auth/src/format/convert.rs +++ b/biscuit-auth/src/format/convert.rs @@ -6,7 +6,7 @@ use super::schema; use crate::builder::Convert; -use crate::crypto::PublicKey; +use crate::crypto::SerializePublicKey; use crate::datalog::*; use crate::error; use crate::format::schema::Empty; @@ -45,9 +45,9 @@ pub fn token_block_to_proto_block(input: &Block) -> schema::Block { } } -pub fn proto_block_to_token_block( +pub fn proto_block_to_token_block( input: &schema::Block, - external_key: Option, + external_key: Option<&EK>, ) -> Result { let version = input.version.unwrap_or(0); if !(MIN_SCHEMA_VERSION..=MAX_SCHEMA_VERSION).contains(&version) { @@ -104,7 +104,7 @@ pub fn proto_block_to_token_block( let mut public_keys = PublicKeys::new(); for pk in &input.public_keys { - public_keys.insert_fallible(&PublicKey::from_proto(pk)?)?; + public_keys.insert_proto_fallible(pk)?; } let symbols = SymbolTable::from_symbols_and_public_keys(input.symbols.clone(), public_keys.keys.clone())?; @@ -120,7 +120,7 @@ pub fn proto_block_to_token_block( checks, context, version, - external_key, + external_key: external_key.map(crate::token::public_keys::PublicKey::from), public_keys, scopes, }) @@ -142,7 +142,7 @@ pub fn token_block_to_proto_snapshot_block(input: &Block) -> schema::SnapshotBlo .iter() .map(token_scope_to_proto_scope) .collect(), - external_key: input.external_key.map(|key| key.to_proto()), + external_key: input.external_key.as_ref().map(|key| key.to_proto()), } } @@ -191,7 +191,9 @@ pub fn proto_snapshot_block_to_token_block( let external_key = match &input.external_key { None => None, - Some(key) => Some(PublicKey::from_proto(key)?), + Some(key) => Some(crate::token::public_keys::PublicKey::from( + &crate::crypto::PublicKey::from_proto(key)?, + )), }; Ok(Block { @@ -852,3 +854,15 @@ pub fn proto_scope_to_token_scope(input: &schema::Scope) -> Result(key: &K) -> schema::PublicKey { + schema::PublicKey { + algorithm: schema::public_key::Algorithm::from(key.algorithm()) as i32, + key: key.to_bytes(), + } +} + +pub fn public_key_from_proto(key: &schema::PublicKey) -> Result { + let algorithm = crate::Algorithm::from(key.algorithm()); + K::from_bytes_and_algorithm(algorithm, &key.key) +} diff --git a/biscuit-auth/src/format/mod.rs b/biscuit-auth/src/format/mod.rs index a072e35d..565f1670 100644 --- a/biscuit-auth/src/format/mod.rs +++ b/biscuit-auth/src/format/mod.rs @@ -8,13 +8,16 @@ //! //! - serialization of Biscuit blocks to Protobuf then `Vec` //! - serialization of a wrapper structure containing serialized blocks and the signature -use super::crypto::{self, PrivateKey, PublicKey, TokenNext}; +use std::fmt::{self, Debug, Formatter}; + +use super::crypto::{self, PrivateKey, Proof}; use prost::Message; use super::error; use super::token::Block; -use crate::crypto::ExternalSignature; +use crate::Algorithm; +use crate::crypto::{ExternalSignature, SerializePrivateKey, Sign, Verify}; use crate::crypto::Signature; use crate::datalog::SymbolTable; use crate::token::RootKeyProvider; @@ -32,22 +35,23 @@ use self::convert::*; pub(crate) const THIRD_PARTY_SIGNATURE_VERSION: u32 = 1; pub(crate) const DATALOG_3_3_SIGNATURE_VERSION: u32 = 1; pub(crate) const NON_ED25519_SIGNATURE_VERSION: u32 = 1; + /// Intermediate structure for token serialization /// /// This structure contains the blocks serialized to byte arrays. Those arrays /// will be used for the signature -#[derive(Clone, Debug)] -pub struct SerializedBiscuit { +#[derive(Clone)] +pub struct SerializedBiscuit { pub root_key_id: Option, - pub authority: crypto::Block, - pub blocks: Vec, - pub proof: crypto::TokenNext, + pub authority: crypto::Block, + pub blocks: Vec>, + pub proof: crypto::Proof, } -impl SerializedBiscuit { +impl SerializedBiscuit { pub fn from_slice(slice: &[u8], key_provider: KP) -> Result where - KP: RootKeyProvider, + KP: RootKeyProvider, { let deser = SerializedBiscuit::deserialize( slice, @@ -65,7 +69,7 @@ impl SerializedBiscuit { key_provider: KP, ) -> Result where - KP: RootKeyProvider, + KP: RootKeyProvider, { let deser = SerializedBiscuit::deserialize(slice, ThirdPartyVerificationMode::UnsafeLegacy)?; @@ -84,7 +88,7 @@ impl SerializedBiscuit { error::Format::DeserializationError(format!("deserialization error: {e:?}")) })?; - let next_key = PublicKey::from_proto(&data.authority.next_key)?; + let next_key: K::PublicKey = convert::public_key_from_proto(&data.authority.next_key)?; let mut next_key_algorithm = next_key.algorithm(); let signature = Signature::from_vec(data.authority.signature); @@ -105,7 +109,7 @@ impl SerializedBiscuit { let mut blocks = Vec::new(); for block in data.blocks { - let next_key = PublicKey::from_proto(&block.next_key)?; + let next_key: K::PublicKey = convert::public_key_from_proto(&block.next_key)?; next_key_algorithm = next_key.algorithm(); let signature = Signature::from_vec(block.signature); @@ -119,7 +123,7 @@ impl SerializedBiscuit { )); } - let public_key = PublicKey::from_proto(&ex.public_key)?; + let public_key = convert::public_key_from_proto(&ex.public_key)?; let signature = Signature::from_vec(ex.signature); Some(ExternalSignature { @@ -146,18 +150,12 @@ impl SerializedBiscuit { )) } Some(schema::proof::Content::NextSecret(v)) => { - let next_key_algorithm = match next_key_algorithm { - schema::public_key::Algorithm::Ed25519 => crate::builder::Algorithm::Ed25519, - schema::public_key::Algorithm::Secp256r1 => { - crate::builder::Algorithm::Secp256r1 - } - }; - TokenNext::Secret(PrivateKey::from_bytes(&v, next_key_algorithm)?) + Proof::Secret(K::from_bytes_and_algorithm(next_key_algorithm, &v)?) } Some(schema::proof::Content::FinalSignature(v)) => { let signature = Signature::from_vec(v); - TokenNext::Seal(signature) + Proof::Seal(signature) } }; @@ -175,8 +173,6 @@ impl SerializedBiscuit { &self, symbols: &mut SymbolTable, ) -> Result<(schema::Block, Vec), error::Token> { - let mut block_external_keys = Vec::new(); - let authority = schema::Block::decode(&self.authority.data[..]).map_err(|e| { error::Token::Format(error::Format::BlockDeserializationError(format!( "error deserializing authority block: {e:?}" @@ -186,13 +182,8 @@ impl SerializedBiscuit { symbols.extend(&SymbolTable::from(authority.symbols.clone())?)?; for pk in &authority.public_keys { - symbols - .public_keys - .insert_fallible(&PublicKey::from_proto(pk)?)?; + symbols.public_keys.insert_proto_fallible(&pk)?; } - // the authority block should not have an external key - block_external_keys.push(None); - //FIXME: return an error if the authority block has an external key let mut blocks = vec![]; @@ -203,15 +194,10 @@ impl SerializedBiscuit { ))) })?; - if let Some(external_signature) = &block.external_signature { - block_external_keys.push(Some(external_signature.public_key)); - } else { - block_external_keys.push(None); + if block.external_signature.is_none() { symbols.extend(&SymbolTable::from(deser.symbols.clone())?)?; for pk in &deser.public_keys { - symbols - .public_keys - .insert_fallible(&PublicKey::from_proto(pk)?)?; + symbols.public_keys.insert_proto_fallible(&pk)?; } } @@ -225,7 +211,7 @@ impl SerializedBiscuit { pub fn to_proto(&self) -> schema::Biscuit { let authority = schema::SignedBlock { block: self.authority.data.clone(), - next_key: self.authority.next_key.to_proto(), + next_key: convert::public_key_to_proto(&self.authority.next_key), signature: self.authority.signature.to_bytes().to_vec(), external_signature: None, version: if self.authority.version > 0 { @@ -239,12 +225,12 @@ impl SerializedBiscuit { for block in &self.blocks { let b = schema::SignedBlock { block: block.data.clone(), - next_key: block.next_key.to_proto(), + next_key: convert::public_key_to_proto(&block.next_key), signature: block.signature.to_bytes().to_vec(), external_signature: block.external_signature.as_ref().map(|external_signature| { schema::ExternalSignature { signature: external_signature.signature.to_bytes().to_vec(), - public_key: external_signature.public_key.to_proto(), + public_key: convert::public_key_to_proto(&external_signature.public_key), } }), version: if block.version > 0 { @@ -263,10 +249,10 @@ impl SerializedBiscuit { blocks, proof: schema::Proof { content: match &self.proof { - TokenNext::Seal(signature) => Some(schema::proof::Content::FinalSignature( + Proof::Seal(signature) => Some(schema::proof::Content::FinalSignature( signature.to_bytes().to_vec(), )), - TokenNext::Secret(private) => Some(schema::proof::Content::NextSecret( + Proof::Secret(private) => Some(schema::proof::Content::NextSecret( private.to_bytes().to_vec(), )), }, @@ -290,16 +276,16 @@ impl SerializedBiscuit { } /// creates a new token - pub fn new( + pub fn new( root_key_id: Option, - root_private_key: &PrivateKey, - next_private_key: &PrivateKey, + root_private_key: &IK, + next_private_key: &K, authority: &Block, ) -> Result { let authority_signature_version = block_signature_version( root_private_key, next_private_key, - &None, + &None::, &Some(authority.version), std::iter::empty(), ); @@ -313,10 +299,10 @@ impl SerializedBiscuit { } /// creates a new token - pub(crate) fn new_inner( + pub(crate) fn new_inner( root_key_id: Option, - root_private_key: &PrivateKey, - next_private_key: &PrivateKey, + root_private_key: &IK, + next_private_key: &K, authority: &Block, authority_signature_version: u32, ) -> Result { @@ -329,7 +315,7 @@ impl SerializedBiscuit { let signature = crypto::sign_authority_block( root_private_key, - next_private_key, + &next_private_key.public(), &v, authority_signature_version, )?; @@ -344,16 +330,16 @@ impl SerializedBiscuit { version: authority_signature_version, }, blocks: vec![], - proof: TokenNext::Secret(next_private_key.private()), + proof: Proof::Secret(next_private_key.clone()), }) } /// adds a new block, serializes it and sign a new token pub fn append( &self, - next_private_key: &PrivateKey, + next_private_key: &K, block: &Block, - external_signature: Option, + external_signature: Option>, ) -> Result { let private_key = self.proof.private_key()?; @@ -379,7 +365,7 @@ impl SerializedBiscuit { let signature = crypto::sign_block( &private_key, - next_private_key, + &next_private_key.public(), &v, external_signature.as_ref(), &self.last_block().signature, @@ -400,16 +386,16 @@ impl SerializedBiscuit { root_key_id: self.root_key_id, authority: self.authority.clone(), blocks, - proof: TokenNext::Secret(next_private_key.private()), + proof: Proof::Secret(next_private_key.clone()), }) } /// adds a new block, serializes it and sign a new token pub fn append_serialized( &self, - next_private_key: &PrivateKey, + next_private_key: &K, block: Vec, - external_signature: Option, + external_signature: Option>, ) -> Result { let private_key = self.proof.private_key()?; @@ -426,7 +412,7 @@ impl SerializedBiscuit { let signature = crypto::sign_block( &private_key, - next_private_key, + &next_private_key.public(), &block, external_signature.as_ref(), &self.last_block().signature, @@ -447,26 +433,25 @@ impl SerializedBiscuit { root_key_id: self.root_key_id, authority: self.authority.clone(), blocks, - proof: TokenNext::Secret(next_private_key.private()), + proof: Proof::Secret(next_private_key.clone()), }) } /// checks the signature on a deserialized token - pub fn verify(&self, root: &PublicKey) -> Result<(), error::Format> { + pub fn verify(&self, root: &IK) -> Result<(), error::Format> { self.verify_inner(root, ThirdPartyVerificationMode::PreviousSignatureHashing) } - pub(crate) fn verify_inner( + pub(crate) fn verify_inner( &self, - root: &PublicKey, + root: &IK, verification_mode: ThirdPartyVerificationMode, ) -> Result<(), error::Format> { //FIXME: try batched signature verification - let mut current_pub = root; let mut previous_signature; - crypto::verify_authority_block_signature(&self.authority, current_pub)?; - current_pub = &self.authority.next_key; + crypto::verify_authority_block_signature(&self.authority, root)?; + let mut current_pub = &self.authority.next_key; previous_signature = &self.authority.signature; for block in &self.blocks { @@ -488,8 +473,8 @@ impl SerializedBiscuit { } match &self.proof { - TokenNext::Secret(private) => { - if current_pub != &private.public() { + Proof::Secret(private) => { + if *current_pub != private.public() { return Err(error::Format::Signature( error::Signature::InvalidSignature( "the last public key does not match the private key".to_string(), @@ -497,7 +482,7 @@ impl SerializedBiscuit { )); } } - TokenNext::Seal(signature) => { + Proof::Seal(signature) => { //FIXME: replace with SHA512 hashing let block = if self.blocks.is_empty() { &self.authority @@ -513,7 +498,6 @@ impl SerializedBiscuit { Ok(()) } - pub fn seal(&self) -> Result { let private_key = self.proof.private_key()?; @@ -532,25 +516,40 @@ impl SerializedBiscuit { root_key_id: self.root_key_id, authority: self.authority.clone(), blocks: self.blocks.clone(), - proof: TokenNext::Seal(signature), + proof: Proof::Seal(signature), }) } - pub(crate) fn last_block(&self) -> &crypto::Block { + pub(crate) fn last_block(&self) -> &crypto::Block { self.blocks.last().unwrap_or(&self.authority) } } +impl Debug for SerializedBiscuit +where + K: SerializePrivateKey + Debug, + K::PublicKey: Debug, +{ + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + f.debug_struct("SerializedBiscuit") + .field("root_key_id", &self.root_key_id) + .field("authority", &self.authority) + .field("blocks", &self.blocks) + .field("proof", &self.proof) + .finish() + } +} + #[derive(Clone, Copy, Debug, PartialEq)] pub(crate) enum ThirdPartyVerificationMode { UnsafeLegacy, PreviousSignatureHashing, } -fn block_signature_version( - block_private_key: &PrivateKey, - next_private_key: &PrivateKey, - external_signature: &Option, +fn block_signature_version( + block_private_key: &IK, + next_private_key: &AK, + external_signature: &Option>, block_version: &Option, previous_blocks_sig_versions: I, ) -> u32 @@ -568,8 +567,8 @@ where _ => {} } - match (block_private_key, next_private_key) { - (PrivateKey::Ed25519(_), PrivateKey::Ed25519(_)) => {} + match (block_private_key.algorithm(), next_private_key.algorithm()) { + (Algorithm::Ed25519, Algorithm::Ed25519) => {} _ => { return NON_ED25519_SIGNATURE_VERSION; } @@ -622,7 +621,7 @@ mod tests { block_signature_version( &PrivateKey::new(), &PrivateKey::new(), - &None, + &None::, &Some(DATALOG_3_1), std::iter::empty() ), @@ -633,7 +632,7 @@ mod tests { block_signature_version( &PrivateKey::new_with_algorithm(Algorithm::Secp256r1), &PrivateKey::new_with_algorithm(Algorithm::Ed25519), - &None, + &None::, &Some(DATALOG_3_1), std::iter::empty() ), @@ -644,7 +643,7 @@ mod tests { block_signature_version( &PrivateKey::new_with_algorithm(Algorithm::Ed25519), &PrivateKey::new_with_algorithm(Algorithm::Secp256r1), - &None, + &None::, &Some(DATALOG_3_1), std::iter::empty() ), @@ -655,7 +654,7 @@ mod tests { block_signature_version( &PrivateKey::new_with_algorithm(Algorithm::Secp256r1), &PrivateKey::new_with_algorithm(Algorithm::Secp256r1), - &None, + &None::, &Some(DATALOG_3_1), std::iter::empty() ), @@ -680,7 +679,7 @@ mod tests { block_signature_version( &PrivateKey::new(), &PrivateKey::new(), - &None, + &None::, &Some(DATALOG_3_3), std::iter::empty() ), @@ -691,7 +690,7 @@ mod tests { block_signature_version( &PrivateKey::new(), &PrivateKey::new(), - &None, + &None::, &Some(DATALOG_3_1), std::iter::once(1) ), diff --git a/biscuit-auth/src/lib.rs b/biscuit-auth/src/lib.rs index 207b18e9..92d78f27 100644 --- a/biscuit-auth/src/lib.rs +++ b/biscuit-auth/src/lib.rs @@ -252,6 +252,7 @@ pub mod parser; mod token; pub use crypto::{PrivateKey, PublicKey}; +pub use token::public_keys; pub use token::authorizer::{Authorizer, AuthorizerLimits}; pub use token::builder; pub use token::builder::{Algorithm, AuthorizerBuilder, BiscuitBuilder, BlockBuilder}; diff --git a/biscuit-auth/src/token/authorizer.rs b/biscuit-auth/src/token/authorizer.rs index d46d95e1..f58ba4d4 100644 --- a/biscuit-auth/src/token/authorizer.rs +++ b/biscuit-auth/src/token/authorizer.rs @@ -6,6 +6,7 @@ use super::builder::{AuthorizerBuilder, BlockBuilder, Check, Fact, Policy, PolicyKind, Rule}; use super::{Biscuit, Block}; use crate::builder::{CheckKind, Convert}; +use crate::crypto::SerializePrivateKey; use crate::datalog::{self, ExternFunc, Origin, RunLimits, TrustedOrigins}; use crate::error; use crate::time::Instant; @@ -56,7 +57,7 @@ impl Authorizer { } } - pub(crate) fn from_token(token: &Biscuit) -> Result { + pub(crate) fn from_token(token: &Biscuit) -> Result { AuthorizerBuilder::new().build(token) } @@ -917,7 +918,7 @@ mod tests { use token::builder::{self, load_and_translate_block, var}; use token::{public_keys::PublicKeys, DATALOG_3_1}; - use crate::PublicKey; + use crate::token::public_keys::PublicKey as InertPublicKey; use crate::{ builder::{BiscuitBuilder, BlockBuilder}, PrivateKey, @@ -950,12 +951,11 @@ mod tests { let mut scope_params = HashMap::new(); scope_params.insert( "pk".to_string(), - PublicKey::from_bytes( - &hex::decode("6e9e6d5a75cf0c0e87ec1256b4dfed0ca3ba452912d213fcc70f8516583db9db") - .unwrap(), + InertPublicKey::from_bytes( crate::builder::Algorithm::Ed25519, - ) - .unwrap(), + hex::decode("6e9e6d5a75cf0c0e87ec1256b4dfed0ca3ba452912d213fcc70f8516583db9db") + .unwrap(), + ), ); let _authorizer = AuthorizerBuilder::new() .code_with_params( @@ -1150,7 +1150,7 @@ mod tests { let external = PrivateKey::new(); let mut scope_params = HashMap::new(); - scope_params.insert("external_pub".to_string(), external.public()); + scope_params.insert("external_pub".to_string(), InertPublicKey::from(&external.public())); let biscuit1 = Biscuit::builder() .code_with_params( @@ -1182,8 +1182,8 @@ mod tests { let external2 = PrivateKey::new(); let mut scope_params = HashMap::new(); - scope_params.insert("external".to_string(), external.public()); - scope_params.insert("external2".to_string(), external2.public()); + scope_params.insert("external".to_string(), InertPublicKey::from(&external.public())); + scope_params.insert("external2".to_string(), InertPublicKey::from(&external2.public())); let mut authorizer = builder .code_with_params( @@ -1258,7 +1258,7 @@ mod tests { let mut r: Rule = "right($right) <- right($right) trusting {external}" .try_into() .unwrap(); - r.set_scope("external", external.public()).unwrap(); + r.set_scope("external", InertPublicKey::from(&external.public())).unwrap(); r }, AuthorizerLimits { @@ -1288,7 +1288,7 @@ mod tests { let mut r: Rule = "group($group) <- group($group) trusting {external}" .try_into() .unwrap(); - r.set_scope("external", external.public()).unwrap(); + r.set_scope("external", InertPublicKey::from(&external.public())).unwrap(); r }, AuthorizerLimits { @@ -1403,7 +1403,7 @@ allow if true; #[test] fn empty_authorizer_display() { - let authorizer = Authorizer::new(); + let authorizer: Authorizer = Authorizer::new(); assert_eq!("", authorizer.to_string()) } @@ -1418,7 +1418,7 @@ allow if true; &[datalog::var(&mut syms, "unbound")], &[datalog::pred(pred_name, &[datalog::var(&mut syms, "any")])], ); - let mut block = Block { + let mut block: Block = Block { symbols: syms.clone(), facts: vec![], rules: vec![rule], diff --git a/biscuit-auth/src/token/authorizer/snapshot.rs b/biscuit-auth/src/token/authorizer/snapshot.rs index b85dc944..413c8dd8 100644 --- a/biscuit-auth/src/token/authorizer/snapshot.rs +++ b/biscuit-auth/src/token/authorizer/snapshot.rs @@ -18,7 +18,6 @@ use crate::{ schema::{self, GeneratedFacts}, }, token::{default_symbol_table, MAX_SCHEMA_VERSION, MIN_SCHEMA_VERSION}, - PublicKey, }; impl super::Authorizer { @@ -52,9 +51,7 @@ impl super::Authorizer { symbols.insert(&symbol); } for public_key in world.public_keys { - symbols - .public_keys - .insert(&PublicKey::from_proto(&public_key)?); + symbols.public_keys.insert_proto(&public_key); } let authorizer_block = proto_snapshot_block_to_token_block(&world.authorizer_block)?; @@ -193,7 +190,10 @@ impl super::Authorizer { .map(|policy| policy_to_proto_policy(policy, &mut symbols)) .collect(); - let authorizer_block = self.authorizer_block_builder.clone().build(symbols.clone()); + let authorizer_block = self + .authorizer_block_builder + .clone() + .build(symbols.clone()); symbols.extend(&authorizer_block.symbols)?; symbols.public_keys.extend(&authorizer_block.public_keys)?; @@ -321,11 +321,12 @@ mod tests { use crate::{datalog::RunLimits, Algorithm, AuthorizerBuilder}; use crate::{Authorizer, BiscuitBuilder, PrivateKey}; + use crate::token::public_keys::PublicKey as InertPublicKey; #[test] fn roundtrip_builder() { - let secp_pubkey = PrivateKey::new_with_algorithm(Algorithm::Secp256r1).public(); - let ed_pubkey = PrivateKey::new_with_algorithm(Algorithm::Ed25519).public(); + let secp_pubkey = InertPublicKey::from(&PrivateKey::new_with_algorithm(Algorithm::Secp256r1).public()); + let ed_pubkey = InertPublicKey::from(&PrivateKey::new_with_algorithm(Algorithm::Ed25519).public()); let builder = AuthorizerBuilder::new() .set_limits(RunLimits { max_facts: 42, @@ -356,8 +357,8 @@ mod tests { #[test] fn roundtrip_with_token() { - let secp_pubkey = PrivateKey::new_with_algorithm(Algorithm::Secp256r1).public(); - let ed_pubkey = PrivateKey::new_with_algorithm(Algorithm::Ed25519).public(); + let secp_pubkey = InertPublicKey::from(&PrivateKey::new_with_algorithm(Algorithm::Secp256r1).public()); + let ed_pubkey = InertPublicKey::from(&PrivateKey::new_with_algorithm(Algorithm::Ed25519).public()); let builder = AuthorizerBuilder::new() .set_limits(RunLimits { max_facts: 42, @@ -374,8 +375,8 @@ mod tests { "#, HashMap::default(), HashMap::from([ - ("ed_pubkey".to_string(), ed_pubkey), - ("secp_pubkey".to_string(), secp_pubkey), + ("ed_pubkey".to_string(), ed_pubkey.clone()), + ("secp_pubkey".to_string(), secp_pubkey.clone()), ]), ) .unwrap(); diff --git a/biscuit-auth/src/token/block.rs b/biscuit-auth/src/token/block.rs index 49679b3e..e2a612e4 100644 --- a/biscuit-auth/src/token/block.rs +++ b/biscuit-auth/src/token/block.rs @@ -4,12 +4,11 @@ */ use crate::{ builder::{self, Convert}, - crypto::PublicKey, datalog::{Check, Fact, Rule, SymbolTable, Term}, error, }; -use super::{public_keys::PublicKeys, Scope}; +use super::{public_keys::{self, PublicKeys}, Scope}; /// a block contained in a token #[derive(Clone, Debug)] @@ -28,7 +27,7 @@ pub struct Block { /// format version used to generate this block pub version: u32, /// key used in optional external signature - pub external_key: Option, + pub external_key: Option, /// list of public keys referenced by this block pub public_keys: PublicKeys, /// list of scopes defining which blocks are trusted by this block @@ -103,7 +102,7 @@ impl Block { .collect::, error::Format>>()?, context: self.context.clone(), version: self.version, - external_key: self.external_key, + external_key: self.external_key.clone(), public_keys: self.public_keys.clone(), scopes: self .scopes diff --git a/biscuit-auth/src/token/builder.rs b/biscuit-auth/src/token/builder.rs index 08ad7ae7..cc3ab4e9 100644 --- a/biscuit-auth/src/token/builder.rs +++ b/biscuit-auth/src/token/builder.rs @@ -11,7 +11,8 @@ use std::{ // reexport those because the builder uses the same definitions use super::Block; -use crate::crypto::PublicKey; +#[cfg(any(test, feature = "datalog-macro"))] +use crate::token::public_keys::PublicKey; use crate::datalog::SymbolTable; pub use crate::datalog::{ Binary as DatalogBinary, Expression as DatalogExpression, Op as DatalogOp, @@ -214,11 +215,10 @@ mod tests { #[test] fn set_rule_scope_parameters() { let pubkey = PublicKey::from_bytes( - &hex::decode("6e9e6d5a75cf0c0e87ec1256b4dfed0ca3ba452912d213fcc70f8516583db9db") - .unwrap(), Algorithm::Ed25519, - ) - .unwrap(); + hex::decode("6e9e6d5a75cf0c0e87ec1256b4dfed0ca3ba452912d213fcc70f8516583db9db") + .unwrap(), + ); let mut rule = Rule::try_from( "fact($var1, {p2}) <- f1($var1, $var3), f2({p2}, $var3, {p4}), $var3.starts_with({p2}) trusting {pk}", ) @@ -241,11 +241,10 @@ mod tests { params.insert("p3".to_string(), true.into()); params.insert("p4".to_string(), "this will be ignored".into()); let pubkey = PublicKey::from_bytes( - &hex::decode("6e9e6d5a75cf0c0e87ec1256b4dfed0ca3ba452912d213fcc70f8516583db9db") - .unwrap(), Algorithm::Ed25519, - ) - .unwrap(); + hex::decode("6e9e6d5a75cf0c0e87ec1256b4dfed0ca3ba452912d213fcc70f8516583db9db") + .unwrap(), + ); let mut scope_params = HashMap::new(); scope_params.insert("pk".to_string(), pubkey); builder = builder diff --git a/biscuit-auth/src/token/builder/authorizer.rs b/biscuit-auth/src/token/builder/authorizer.rs index 14d7b72f..12f79995 100644 --- a/biscuit-auth/src/token/builder/authorizer.rs +++ b/biscuit-auth/src/token/builder/authorizer.rs @@ -12,6 +12,9 @@ use std::{ use biscuit_parser::parser::parse_source; use prost::Message; +use crate::PrivateKey; +use crate::crypto::SerializePrivateKey; +use crate::token::public_keys::PublicKey; use crate::{ builder::Convert, builder_ext::{AuthorizerExt, BuilderExt}, @@ -25,7 +28,7 @@ use crate::{ schema, }, token::{self, default_symbol_table, Block, MAX_SCHEMA_VERSION, MIN_SCHEMA_VERSION}, - Authorizer, AuthorizerLimits, Biscuit, PublicKey, + Authorizer, AuthorizerLimits, Biscuit, }; use super::{date, fact, BlockBuilder, Check, Fact, Policy, Rule, Scope, Term}; @@ -158,7 +161,7 @@ impl AuthorizerBuilder { res?; } for (name, value) in &scope_params { - let res = match rule.set_scope(name, *value) { + let res = match rule.set_scope(name, value.clone()) { Ok(_) => Ok(()), Err(error::Token::Language( biscuit_parser::error::LanguageError::Parameters { @@ -188,7 +191,7 @@ impl AuthorizerBuilder { res?; } for (name, value) in &scope_params { - let res = match check.set_scope(name, *value) { + let res = match check.set_scope(name, value.clone()) { Ok(_) => Ok(()), Err(error::Token::Language( biscuit_parser::error::LanguageError::Parameters { @@ -217,7 +220,7 @@ impl AuthorizerBuilder { res?; } for (name, value) in &scope_params { - let res = match policy.set_scope(name, *value) { + let res = match policy.set_scope(name, value.clone()) { Ok(_) => Ok(()), Err(error::Token::Language( biscuit_parser::error::LanguageError::Parameters { @@ -318,16 +321,16 @@ impl AuthorizerBuilder { } /// builds the authorizer from a token - pub fn build(self, token: &Biscuit) -> Result { + pub fn build(self, token: &Biscuit) -> Result { self.build_inner(Some(token)) } /// builds the authorizer without a token pub fn build_unauthenticated(self) -> Result { - self.build_inner(None) + self.build_inner::(None) } - fn build_inner(self, token: Option<&Biscuit>) -> Result { + fn build_inner(self, token: Option<&Biscuit>) -> Result { let mut world = World::new(); world.extern_funcs = self.extern_funcs; @@ -340,7 +343,7 @@ impl AuthorizerBuilder { if let Some(token) = token { for (i, block) in token.container.blocks.iter().enumerate() { if let Some(sig) = block.external_signature.as_ref() { - let new_key_id = symbols.public_keys.insert(&sig.public_key); + let new_key_id = symbols.public_keys.insert_serialize(&sig.public_key); public_key_to_block_id .entry(new_key_id as usize) @@ -607,7 +610,7 @@ impl AuthorizerBuilder { for public_key in world.public_keys { symbols .public_keys - .insert(&PublicKey::from_proto(&public_key)?); + .insert_proto(&public_key); } let authorizer_block = proto_snapshot_block_to_token_block(&world.authorizer_block)?; @@ -648,7 +651,10 @@ impl AuthorizerBuilder { .map(|policy| policy_to_proto_policy(policy, &mut symbols)) .collect(); - let authorizer_block = self.authorizer_block_builder.clone().build(symbols.clone()); + let authorizer_block = self + .authorizer_block_builder + .clone() + .build(symbols.clone()); symbols.extend(&authorizer_block.symbols)?; symbols.public_keys.extend(&authorizer_block.public_keys)?; diff --git a/biscuit-auth/src/token/builder/biscuit.rs b/biscuit-auth/src/token/builder/biscuit.rs index a7113338..1dc65aa2 100644 --- a/biscuit-auth/src/token/builder/biscuit.rs +++ b/biscuit-auth/src/token/builder/biscuit.rs @@ -4,10 +4,11 @@ */ use super::{BlockBuilder, Check, Fact, Rule, Scope, Term}; use crate::builder_ext::BuilderExt; -use crate::crypto::PublicKey; +use crate::crypto::SerializePrivateKey; +use crate::token::public_keys::PublicKey; use crate::datalog::SymbolTable; use crate::token::default_symbol_table; -use crate::{error, Biscuit, PrivateKey}; +use crate::{error, Biscuit}; use rand::{CryptoRng, RngCore}; use std::fmt; @@ -124,34 +125,34 @@ impl BiscuitBuilder { f } - pub fn build(self, root_key: &PrivateKey) -> Result { + pub fn build(self, root_key: &K) -> Result, error::Token> { self.build_with_symbols(root_key, default_symbol_table()) } - pub fn build_with_symbols( + pub fn build_with_symbols( self, - root_key: &PrivateKey, + root_key: &K, symbols: SymbolTable, - ) -> Result { + ) -> Result, error::Token> { self.build_with_rng(root_key, symbols, &mut rand::rngs::OsRng) } - pub fn build_with_rng( + pub fn build_with_rng( self, - root: &PrivateKey, + root: &K, symbols: SymbolTable, rng: &mut R, - ) -> Result { + ) -> Result, error::Token> { let authority_block = self.inner.build(symbols.clone()); Biscuit::new_with_rng(rng, self.root_key_id, root, symbols, authority_block) } - pub fn build_with_key_pair( + pub fn build_with_key_pair( self, - root: &PrivateKey, + root: &K, symbols: SymbolTable, - next: &PrivateKey, - ) -> Result { + next: &K, + ) -> Result, error::Token> { let authority_block = self.inner.build(symbols.clone()); Biscuit::new_with_key_pair(self.root_key_id, root, next, symbols, authority_block) } diff --git a/biscuit-auth/src/token/builder/block.rs b/biscuit-auth/src/token/builder/block.rs index bde72dc6..fc9fa0a7 100644 --- a/biscuit-auth/src/token/builder/block.rs +++ b/biscuit-auth/src/token/builder/block.rs @@ -7,7 +7,7 @@ use super::{ Convert, Expression, Fact, Op, Rule, Scope, Term, }; use crate::builder_ext::BuilderExt; -use crate::crypto::PublicKey; +use crate::token::public_keys::PublicKey; use crate::datalog::{get_schema_version, SymbolTable}; use crate::error; use biscuit_parser::parser::parse_block_source; @@ -124,7 +124,7 @@ impl BlockBuilder { res?; } for (name, value) in &scope_params { - let res = match rule.set_scope(name, *value) { + let res = match rule.set_scope(name, value.clone()) { Ok(_) => Ok(()), Err(error::Token::Language( biscuit_parser::error::LanguageError::Parameters { @@ -154,7 +154,7 @@ impl BlockBuilder { res?; } for (name, value) in &scope_params { - let res = match check.set_scope(name, *value) { + let res = match check.set_scope(name, value.clone()) { Ok(_) => Ok(()), Err(error::Token::Language( biscuit_parser::error::LanguageError::Parameters { diff --git a/biscuit-auth/src/token/builder/check.rs b/biscuit-auth/src/token/builder/check.rs index 46cc1815..03c5761f 100644 --- a/biscuit-auth/src/token/builder/check.rs +++ b/biscuit-auth/src/token/builder/check.rs @@ -8,7 +8,8 @@ use nom::Finish; use crate::{ datalog::{self, SymbolTable}, - error, PublicKey, + error, + token::public_keys::PublicKey, }; #[cfg(feature = "datalog-macro")] @@ -61,7 +62,7 @@ impl Check { pub fn set_scope(&mut self, name: &str, pubkey: PublicKey) -> Result<(), error::Token> { let mut found = false; for query in &mut self.queries { - if query.set_scope(name, pubkey).is_ok() { + if query.set_scope(name, pubkey.clone()).is_ok() { found = true; } } @@ -92,7 +93,7 @@ impl Check { /// parameter is not present in the check pub fn set_scope_lenient(&mut self, name: &str, pubkey: PublicKey) -> Result<(), error::Token> { for query in &mut self.queries { - query.set_scope_lenient(name, pubkey)?; + query.set_scope_lenient(name, pubkey.clone())?; } Ok(()) } diff --git a/biscuit-auth/src/token/builder/policy.rs b/biscuit-auth/src/token/builder/policy.rs index 2a1cb478..52984c9e 100644 --- a/biscuit-auth/src/token/builder/policy.rs +++ b/biscuit-auth/src/token/builder/policy.rs @@ -6,7 +6,7 @@ use std::{convert::TryFrom, fmt, str::FromStr}; use nom::Finish; -use crate::{error, PublicKey}; +use crate::{error, token::public_keys::PublicKey}; #[cfg(feature = "datalog-macro")] use super::ToAnyParam; @@ -56,7 +56,7 @@ impl Policy { pub fn set_scope(&mut self, name: &str, pubkey: PublicKey) -> Result<(), error::Token> { let mut found = false; for query in &mut self.queries { - if query.set_scope(name, pubkey).is_ok() { + if query.set_scope(name, pubkey.clone()).is_ok() { found = true; } } @@ -85,7 +85,7 @@ impl Policy { /// replace a scope parameter with the pubkey argument, ignoring unknown parameters pub fn set_scope_lenient(&mut self, name: &str, pubkey: PublicKey) -> Result<(), error::Token> { for query in &mut self.queries { - query.set_scope_lenient(name, pubkey)?; + query.set_scope_lenient(name, pubkey.clone())?; } Ok(()) } diff --git a/biscuit-auth/src/token/builder/rule.rs b/biscuit-auth/src/token/builder/rule.rs index ec4483c0..9962baf6 100644 --- a/biscuit-auth/src/token/builder/rule.rs +++ b/biscuit-auth/src/token/builder/rule.rs @@ -7,8 +7,9 @@ use std::{collections::HashMap, convert::TryFrom, fmt, str::FromStr}; use nom::Finish; use crate::{ + token::public_keys::PublicKey, datalog::{self, SymbolTable}, - error, PublicKey, + error, }; #[cfg(feature = "datalog-macro")] @@ -315,7 +316,7 @@ impl Rule { .map(|scope| { if let Scope::Parameter(name) = &scope { if let Some(Some(pubkey)) = parameters.get(name) { - return Scope::PublicKey(*pubkey); + return Scope::PublicKey(pubkey.clone()); } } scope @@ -455,8 +456,7 @@ impl From for Rule { ( k, v.map(|pk| { - PublicKey::from_bytes(&pk.key, pk.algorithm.into()) - .expect("invalid public key") + PublicKey::from_bytes(pk.algorithm.into(), pk.key) }), ) }) diff --git a/biscuit-auth/src/token/builder/scope.rs b/biscuit-auth/src/token/builder/scope.rs index 497a4d9e..e2d6c0d7 100644 --- a/biscuit-auth/src/token/builder/scope.rs +++ b/biscuit-auth/src/token/builder/scope.rs @@ -4,7 +4,8 @@ */ use std::fmt; -use crate::{datalog::SymbolTable, error, PublicKey}; +use crate::token::public_keys::PublicKey; +use crate::{datalog::SymbolTable, error}; use super::Convert; @@ -27,7 +28,7 @@ impl Convert for Scope { Scope::Authority => crate::token::Scope::Authority, Scope::Previous => crate::token::Scope::Previous, Scope::PublicKey(key) => { - crate::token::Scope::PublicKey(symbols.public_keys.insert(key)) + crate::token::Scope::PublicKey(symbols.public_keys.insert_data(key)) } // The error is caught in the `add_xxx` functions, so this should // not happen™ @@ -43,10 +44,11 @@ impl Convert for Scope { crate::token::Scope::Authority => Scope::Authority, crate::token::Scope::Previous => Scope::Previous, crate::token::Scope::PublicKey(key_id) => Scope::PublicKey( - *symbols + symbols .public_keys .get_key(*key_id) - .ok_or(error::Format::UnknownExternalKey)?, + .ok_or(error::Format::UnknownExternalKey)? + .clone(), ), }) } @@ -57,7 +59,7 @@ impl fmt::Display for Scope { match self { Scope::Authority => write!(f, "authority"), Scope::Previous => write!(f, "previous"), - Scope::PublicKey(pk) => pk.write(f), + Scope::PublicKey(pk) => write!(f, "{pk}"), Scope::Parameter(s) => { write!(f, "{{{s}}}") } @@ -71,7 +73,7 @@ impl From for Scope { biscuit_parser::builder::Scope::Authority => Scope::Authority, biscuit_parser::builder::Scope::Previous => Scope::Previous, biscuit_parser::builder::Scope::PublicKey(pk) => Scope::PublicKey( - PublicKey::from_bytes(&pk.key, pk.algorithm.into()).expect("invalid public key"), + PublicKey::from_bytes(pk.algorithm.into(), pk.key) ), biscuit_parser::builder::Scope::Parameter(s) => Scope::Parameter(s), } diff --git a/biscuit-auth/src/token/mod.rs b/biscuit-auth/src/token/mod.rs index 3694954b..aff7e4c7 100644 --- a/biscuit-auth/src/token/mod.rs +++ b/biscuit-auth/src/token/mod.rs @@ -3,8 +3,10 @@ * SPDX-License-Identifier: Apache-2.0 */ //! main structures to interact with Biscuit tokens -use std::fmt::Display; +use std::fmt::{self, Debug, Display, Formatter}; use std::iter::once; +use std::rc::Rc; +use std::sync::Arc; use builder::{BiscuitBuilder, BlockBuilder}; use prost::Message; @@ -15,8 +17,8 @@ use super::crypto::{PrivateKey, PublicKey, Signature}; use super::datalog::SymbolTable; use super::error; use super::format::SerializedBiscuit; -use crate::crypto::{self}; -use crate::format::convert::proto_block_to_token_block; +use crate::crypto::{self, SerializePrivateKey, Verify}; +use crate::format::convert::{proto_block_to_token_block, public_key_from_proto}; use crate::format::schema::{self, ThirdPartyBlockContents}; use crate::format::{ThirdPartyVerificationMode, THIRD_PARTY_SIGNATURE_VERSION}; use authorizer::Authorizer; @@ -25,7 +27,7 @@ pub mod authorizer; pub(crate) mod block; pub mod builder; pub mod builder_ext; -pub(crate) mod public_keys; +pub mod public_keys; pub(crate) mod third_party; pub mod unverified; pub use block::Block; @@ -80,13 +82,13 @@ pub fn default_symbol_table() -> SymbolTable { /// Ok(()) /// } /// ``` -#[derive(Clone, Debug)] -pub struct Biscuit { +#[derive(Clone)] +pub struct Biscuit { pub(crate) root_key_id: Option, pub(crate) authority: schema::Block, pub(crate) blocks: Vec, pub(crate) symbols: SymbolTable, - pub(crate) container: SerializedBiscuit, + pub(crate) container: SerializedBiscuit, } impl Biscuit { @@ -101,7 +103,7 @@ impl Biscuit { pub fn from(slice: T, key_provider: KP) -> Result where T: AsRef<[u8]>, - KP: RootKeyProvider, + KP: RootKeyProvider, { Biscuit::from_with_symbols(slice.as_ref(), key_provider, default_symbol_table()) } @@ -110,7 +112,7 @@ impl Biscuit { pub fn from_base64(slice: T, key_provider: KP) -> Result where T: AsRef<[u8]>, - KP: RootKeyProvider, + KP: RootKeyProvider, { Biscuit::from_base64_with_symbols(slice, key_provider, default_symbol_table()) } @@ -124,7 +126,7 @@ impl Biscuit { ) -> Result where T: AsRef<[u8]>, - KP: RootKeyProvider, + KP: RootKeyProvider, { let container = SerializedBiscuit::unsafe_from_slice(slice.as_ref(), key_provider) .map_err(error::Token::Format)?; @@ -168,13 +170,16 @@ impl Biscuit { pub fn authorizer(&self) -> Result { Authorizer::from_token(self) } +} + +impl Biscuit { /// adds a new block to the token /// /// since the public key is integrated into the token, the private key can be /// discarded right after calling this function pub fn append(&self, block_builder: BlockBuilder) -> Result { - let key = PrivateKey::new_with_rng(builder::Algorithm::Ed25519, &mut rand::rngs::OsRng); + let key = K::new_with_rng(builder::Algorithm::Ed25519, &mut rand::rngs::OsRng); self.append_with_key(&key, block_builder) } @@ -216,11 +221,11 @@ impl Biscuit { /// Blocks carrying an external public key are _third-party blocks_ /// and their contents can be trusted as coming from the holder of /// the corresponding private key - pub fn external_public_keys(&self) -> Vec> { + pub fn external_public_keys(&self) -> Vec> { let mut res = vec![None]; for block in self.container.blocks.iter() { - res.push(block.external_signature.as_ref().map(|sig| sig.public_key)); + res.push(block.external_signature.as_ref().map(|sig| sig.public_key.clone())); } res @@ -254,14 +259,14 @@ impl Biscuit { pub(crate) fn new_with_rng( rng: &mut T, root_key_id: Option, - root: &PrivateKey, + root: &K, symbols: SymbolTable, authority: Block, - ) -> Result { + ) -> Result, error::Token> { Self::new_with_key_pair( root_key_id, root, - &PrivateKey::new_with_rng(builder::Algorithm::Ed25519, rng), + &K::new_with_rng(root.algorithm(), rng), symbols, authority, ) @@ -273,11 +278,11 @@ impl Biscuit { /// the public part of the root keypair must be used for verification pub(crate) fn new_with_key_pair( root_key_id: Option, - root_key: &PrivateKey, - next_key: &PrivateKey, + root_key: &K, + next_key: &K, mut symbols: SymbolTable, authority: Block, - ) -> Result { + ) -> Result, error::Token> { if !symbols.is_disjoint(&authority.symbols) { return Err(error::Token::Format(error::Format::SymbolTableOverlap)); } @@ -312,7 +317,7 @@ impl Biscuit { symbols: SymbolTable, ) -> Result where - KP: RootKeyProvider, + KP: RootKeyProvider, { let container = SerializedBiscuit::from_slice(slice, key_provider).map_err(error::Token::Format)?; @@ -321,7 +326,7 @@ impl Biscuit { } fn from_serialized_container( - container: SerializedBiscuit, + container: SerializedBiscuit, mut symbols: SymbolTable, ) -> Result { let (authority, blocks) = container.extract_blocks(&mut symbols)?; @@ -346,14 +351,14 @@ impl Biscuit { ) -> Result where T: AsRef<[u8]>, - KP: RootKeyProvider, + KP: RootKeyProvider, { let decoded = base64::decode_config(slice, base64::URL_SAFE)?; Biscuit::from_with_symbols(&decoded, key_provider, symbols) } /// returns the internal representation of the token - pub fn container(&self) -> &SerializedBiscuit { + pub fn container(&self) -> &SerializedBiscuit { &self.container } @@ -363,7 +368,7 @@ impl Biscuit { /// discarded right after calling this function pub fn append_with_key( &self, - key: &PrivateKey, + key: &K, block_builder: BlockBuilder, ) -> Result { let block = block_builder.build(self.symbols.clone()); @@ -410,31 +415,30 @@ impl Biscuit { pub fn append_third_party( &self, - external_key: PublicKey, + external_key: K::PublicKey, response: ThirdPartyBlock, ) -> Result { - let next_key = - PrivateKey::new_with_rng(builder::Algorithm::Ed25519, &mut rand::rngs::OsRng); - + let next_key = K::new_with_rng(builder::Algorithm::Ed25519, &mut rand::rngs::OsRng); self.append_third_party_with_key(external_key, response, next_key) } + pub fn append_third_party_with_key( &self, - external_key: PublicKey, + external_key: K::PublicKey, response: ThirdPartyBlock, - next_key: PrivateKey, + next_key: K, ) -> Result { let ThirdPartyBlockContents { payload, external_signature, } = response.0; - let provided_key = PublicKey::from_proto(&external_signature.public_key)?; + let provided_key = public_key_from_proto(&external_signature.public_key)?; if external_key != provided_key { return Err(error::Token::Format(error::Format::DeserializationError( format!( "deserialization error: unexpected key {}", - provided_key.print() + crypto::print(&provided_key), ), ))); } @@ -446,7 +450,7 @@ impl Biscuit { .blocks .last() .unwrap_or(&self.container.authority) - .next_key; + .next_key.clone(); let external_signature = crypto::ExternalSignature { public_key: external_key, @@ -518,13 +522,13 @@ impl Biscuit { let mut public_keys = PublicKeys::new(); for pk in &block.public_keys { - public_keys.insert(&PublicKey::from_proto(pk)?); + public_keys.insert_proto(pk); } Ok(public_keys) } /// gets the list of public keys from a block - pub fn block_external_key(&self, index: usize) -> Result, error::Token> { + pub fn block_external_key(&self, index: usize) -> Result, error::Token> { let block = if index == 0 { &self.container.authority } else { @@ -537,7 +541,7 @@ impl Biscuit { Ok(block .external_signature .as_ref() - .map(|signature| signature.public_key)) + .map(|signature| signature.public_key.clone())) } /// returns the number of blocks (at least 1) @@ -553,7 +557,7 @@ impl Biscuit { .authority .external_signature .as_ref() - .map(|ex| ex.public_key), + .map(|ex| &ex.public_key), ) .map_err(error::Token::Format)? } else { @@ -568,7 +572,7 @@ impl Biscuit { self.container.blocks[index - 1] .external_signature .as_ref() - .map(|ex| ex.public_key), + .map(|ex| &ex.public_key), ) .map_err(error::Token::Format)? }; @@ -576,7 +580,7 @@ impl Biscuit { Ok(block) } - pub(crate) fn blocks(&self) -> impl Iterator> + use<'_> { + pub(crate) fn blocks(&self) -> impl Iterator> + use<'_, K> { once( proto_block_to_token_block( &self.authority, @@ -584,7 +588,7 @@ impl Biscuit { .authority .external_signature .as_ref() - .map(|ex| ex.public_key), + .map(|ex| &ex.public_key), ) .map_err(error::Token::Format), ) @@ -595,7 +599,7 @@ impl Biscuit { container .external_signature .as_ref() - .map(|ex| ex.public_key), + .map(|ex| &ex.public_key), ) .map_err(error::Token::Format) }, @@ -603,8 +607,25 @@ impl Biscuit { } } -impl Display for Biscuit { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { +impl Debug for Biscuit +where + K: SerializePrivateKey + Debug, + K::PublicKey: Debug, +{ + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + f.debug_struct("Biscuit") + .field("root_key_id", &self.root_key_id) + .field("authority", &self.authority) + .field("blocks", &self.blocks) + .field("symbols", &self.symbols) + .field("container", &self.container) + .finish() + } +} + + +impl Display for Biscuit { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { let authority = self .block(0) .as_ref() @@ -621,12 +642,13 @@ impl Display for Biscuit { write!(f, "Biscuit {{\n symbols: {:?}\n public keys: {:?}\n authority: {}\n blocks: [\n {}\n ]\n}}", self.symbols.strings(), - self.symbols.public_keys.keys.iter().map(|pk| hex::encode(pk.to_bytes())).collect::>(), + self.symbols.public_keys.keys.iter().map(|pk| format!("{}", pk)).collect::>(), authority, blocks.join(",\n\t") ) } } + fn print_block(symbols: &SymbolTable, block: &Block) -> String { let facts: Vec<_> = block.facts.iter().map(|f| symbols.print_fact(f)).collect(); let rules: Vec<_> = block.rules.iter().map(|r| symbols.print_rule(r)).collect(); @@ -667,7 +689,7 @@ fn print_block(symbols: &SymbolTable, block: &Block) -> String { block.version, block.context.as_deref().unwrap_or(""), block.external_key.as_ref().map(|k| hex::encode(k.to_bytes())).unwrap_or_default(), - block.public_keys.keys.iter().map(|k | hex::encode(k.to_bytes())).collect::>(), + block.public_keys.keys.iter().map(|k| format!("{}", k)).collect::>(), block.scopes, facts, rules, @@ -690,41 +712,55 @@ pub enum Scope { /// value will be passed to the implementor of `RootKeyProvider` /// to choose which key will be used. pub trait RootKeyProvider { - fn choose(&self, key_id: Option) -> Result; + type Key: Verify; + + fn choose(&self, key_id: Option) -> Result; } -impl RootKeyProvider for Box { - fn choose(&self, key_id: Option) -> Result { +impl RootKeyProvider for Box> { + type Key = K; + + fn choose(&self, key_id: Option) -> Result { self.as_ref().choose(key_id) } } -impl RootKeyProvider for std::rc::Rc { - fn choose(&self, key_id: Option) -> Result { +impl RootKeyProvider for Rc> { + type Key = K; + + fn choose(&self, key_id: Option) -> Result { self.as_ref().choose(key_id) } } -impl RootKeyProvider for std::sync::Arc { - fn choose(&self, key_id: Option) -> Result { +impl RootKeyProvider for Arc> { + type Key = K; + + fn choose(&self, key_id: Option) -> Result { self.as_ref().choose(key_id) } } impl RootKeyProvider for PublicKey { + type Key = PublicKey; + fn choose(&self, _: Option) -> Result { Ok(*self) } } impl RootKeyProvider for &PublicKey { + type Key = PublicKey; + fn choose(&self, _: Option) -> Result { Ok(**self) } } -impl) -> Result> RootKeyProvider for F { - fn choose(&self, root_key_id: Option) -> Result { +impl) -> Result, K: Verify> RootKeyProvider for F { + type Key = K; + + fn choose(&self, root_key_id: Option) -> Result { self(root_key_id) } } diff --git a/biscuit-auth/src/token/public_keys.rs b/biscuit-auth/src/token/public_keys.rs index e0f05d84..92145020 100644 --- a/biscuit-auth/src/token/public_keys.rs +++ b/biscuit-auth/src/token/public_keys.rs @@ -3,24 +3,27 @@ * SPDX-License-Identifier: Apache-2.0 */ use std::collections::HashSet; +use std::fmt::{self, Display, Formatter}; -use crate::{crypto::PublicKey, error}; +use crate::crypto::SerializePublicKey; +use crate::format::schema; +use crate::{Algorithm, error}; -#[derive(Clone, Debug, PartialEq, Eq, Default)] +#[derive(Default, Clone, Debug, PartialEq, Eq)] pub struct PublicKeys { pub(crate) keys: Vec, } impl PublicKeys { - pub fn new() -> Self { + pub(crate) fn new() -> Self { PublicKeys { keys: vec![] } } - pub fn from(keys: Vec) -> Self { + pub(crate) fn from_keys(keys: Vec) -> Self { PublicKeys { keys } } - pub fn extend(&mut self, other: &PublicKeys) -> Result<(), error::Format> { + pub(crate) fn extend(&mut self, other: &PublicKeys) -> Result<(), error::Format> { if !self.is_disjoint(other) { return Err(error::Format::PublicKeyTableOverlap); } @@ -28,52 +31,117 @@ impl PublicKeys { Ok(()) } - pub fn insert(&mut self, k: &PublicKey) -> u64 { + pub(crate) fn insert(&mut self, k: &PublicKey) -> u64 { match self.keys.iter().position(|key| key == k) { Some(index) => index as u64, None => { - self.keys.push(*k); + self.keys.push(k.clone()); (self.keys.len() - 1) as u64 } } } - pub fn insert_fallible(&mut self, k: &PublicKey) -> Result { + pub(crate) fn insert_serialize(&mut self, k: &K) -> u64 { + self.insert(&PublicKey::from(k)) + } + + pub(crate) fn insert_data(&mut self, k: &PublicKey) -> u64 { match self.keys.iter().position(|key| key == k) { - Some(_) => Err(error::Format::PublicKeyTableOverlap), + Some(index) => index as u64, None => { - self.keys.push(*k); - Ok((self.keys.len() - 1) as u64) + self.keys.push(k.clone()); + (self.keys.len() - 1) as u64 } } } - pub fn get(&self, k: &PublicKey) -> Option { - self.keys.iter().position(|key| key == k).map(|i| i as u64) + pub(crate) fn insert_proto(&mut self, k: &schema::PublicKey) -> u64 { + let k = PublicKey::from_proto(k); + match self.keys.iter().position(|key| *key == k) { + Some(index) => index as u64, + None => { + self.keys.push(k.clone()); + (self.keys.len() - 1) as u64 + } + } } - pub fn current_offset(&self) -> usize { + pub(crate) fn insert_proto_fallible(&mut self, k: &schema::PublicKey) -> Result { + let k = PublicKey::from_proto(k); + match self.keys.iter().position(|key| *key == k) { + Some(_) => Err(error::Format::PublicKeyTableOverlap), + None => { + self.keys.push(k.clone()); + Ok((self.keys.len() - 1) as u64) + } + } + } + + pub(crate) fn current_offset(&self) -> usize { self.keys.len() } - pub fn split_at(&mut self, offset: usize) -> PublicKeys { + pub(crate) fn split_at(&mut self, offset: usize) -> PublicKeys { let mut table = PublicKeys::new(); table.keys = self.keys.split_off(offset); table } - pub fn is_disjoint(&self, other: &PublicKeys) -> bool { + pub(crate) fn is_disjoint(&self, other: &PublicKeys) -> bool { let h1 = self.keys.iter().collect::>(); let h2 = other.keys.iter().collect::>(); h1.is_disjoint(&h2) } - pub fn get_key(&self, i: u64) -> Option<&PublicKey> { + pub(crate) fn get_key(&self, i: u64) -> Option<&PublicKey> { self.keys.get(i as usize) } - pub fn into_inner(self) -> Vec { + pub(crate) fn into_inner(self) -> Vec { self.keys } } + +#[derive(Default, Clone, Debug, PartialEq, Eq, Hash)] +pub struct PublicKey { + algorithm: Algorithm, + key: Vec, +} + +impl PublicKey { + pub fn from_bytes(algorithm: Algorithm, key: Vec) -> PublicKey { + PublicKey { algorithm, key } + } + + pub(crate) fn from(key: &K) -> PublicKey { + PublicKey { + algorithm: key.algorithm(), + key: key.to_bytes(), + } + } + + fn from_proto(key: &schema::PublicKey) -> PublicKey { + PublicKey { + algorithm: key.algorithm().into(), + key: key.key.clone(), + } + } + + pub(crate) fn to_proto(&self) -> schema::PublicKey { + schema::PublicKey { + algorithm: schema::public_key::Algorithm::from(self.algorithm) as i32, + key: self.key.clone(), + } + } + + pub fn to_bytes(&self) -> Vec { + self.key.clone() + } +} + +impl Display for PublicKey { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + write!(f, "{}/{}", self.algorithm, hex::encode(&self.key)) + } +} diff --git a/biscuit-auth/src/token/third_party.rs b/biscuit-auth/src/token/third_party.rs index 84233acc..03bc4350 100644 --- a/biscuit-auth/src/token/third_party.rs +++ b/biscuit-auth/src/token/third_party.rs @@ -6,6 +6,7 @@ use std::cmp::max; use prost::Message; +use crate::crypto::SerializePrivateKey; use crate::{ builder::BlockBuilder, crypto::generate_external_signature_payload_v1, @@ -24,8 +25,8 @@ pub struct ThirdPartyRequest { } impl ThirdPartyRequest { - pub(crate) fn from_container( - container: &SerializedBiscuit, + pub(crate) fn from_container( + container: &SerializedBiscuit, ) -> Result { if container.proof.is_sealed() { return Err(error::Token::AppendOnSealed); diff --git a/biscuit-auth/src/token/unverified.rs b/biscuit-auth/src/token/unverified.rs index 8e017042..d47f4d80 100644 --- a/biscuit-auth/src/token/unverified.rs +++ b/biscuit-auth/src/token/unverified.rs @@ -2,9 +2,12 @@ * Copyright (c) 2019 Geoffroy Couprie and Contributors to the Eclipse Foundation. * SPDX-License-Identifier: Apache-2.0 */ +use std::fmt::{self, Debug, Formatter}; + use prost::Message; use super::{default_symbol_table, Biscuit, Block}; +use crate::crypto::SerializePrivateKey; use crate::{ builder::BlockBuilder, crypto::{self, PrivateKey, PublicKey, Signature}, @@ -26,12 +29,27 @@ use crate::{ /// /// It can be converted to a [Biscuit] using [UnverifiedBiscuit::verify], /// and then used for authorization -#[derive(Clone, Debug)] -pub struct UnverifiedBiscuit { +#[derive(Clone)] +pub struct UnverifiedBiscuit { pub(crate) authority: schema::Block, pub(crate) blocks: Vec, pub(crate) symbols: SymbolTable, - container: SerializedBiscuit, + container: SerializedBiscuit, +} + +impl Debug for UnverifiedBiscuit +where + K: SerializePrivateKey + Debug, + K::PublicKey: Debug, +{ + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + f.debug_struct("UnverifiedBiscuit") + .field("authority", &self.authority) + .field("blocks", &self.blocks) + .field("symbols", &self.symbols) + .field("container", &self.container) + .finish() + } } impl UnverifiedBiscuit { @@ -86,7 +104,7 @@ impl UnverifiedBiscuit { /// checks the signature of the token and convert it to a [Biscuit] for authorization pub fn verify(self, key_provider: KP) -> Result where - KP: RootKeyProvider, + KP: RootKeyProvider, { let key = key_provider.choose(self.root_key_id())?; self.container.verify(&key)?; @@ -259,7 +277,7 @@ impl UnverifiedBiscuit { .authority .external_signature .as_ref() - .map(|ex| ex.public_key), + .map(|ex| &ex.public_key), ) .map_err(error::Token::Format)? } else { @@ -274,7 +292,7 @@ impl UnverifiedBiscuit { self.container.blocks[index - 1] .external_signature .as_ref() - .map(|ex| ex.public_key), + .map(|ex| &ex.public_key), ) .map_err(error::Token::Format)? }; @@ -352,9 +370,8 @@ impl UnverifiedBiscuit { self.container .append_serialized(&next_key, payload, Some(external_signature))?; - let token_block = proto_block_to_token_block(&block, Some(external_key)).unwrap(); - for key in &token_block.public_keys.keys { - symbols.public_keys.insert_fallible(key)?; + for key in &block.public_keys[..] { + symbols.public_keys.insert_proto_fallible(key)?; } blocks.push(block); @@ -396,7 +413,7 @@ mod tests { let req = biscuit.third_party_request().unwrap(); let res = req .create_block( - &external_key.private(), + &external_key, BlockBuilder::new().fact("third_party(true)").unwrap(), ) .unwrap(); diff --git a/biscuit-auth/tests/macros.rs b/biscuit-auth/tests/macros.rs index 11a1b7f9..0b522b20 100644 --- a/biscuit-auth/tests/macros.rs +++ b/biscuit-auth/tests/macros.rs @@ -2,7 +2,8 @@ * Copyright (c) 2019 Geoffroy Couprie and Contributors to the Eclipse Foundation. * SPDX-License-Identifier: Apache-2.0 */ -use biscuit_auth::{builder, datalog::RunLimits, PrivateKey, PublicKey}; +use biscuit_auth::{builder, datalog::RunLimits, PrivateKey}; +use biscuit_auth::public_keys::PublicKey; use biscuit_quote::{ authorizer, authorizer_merge, biscuit, biscuit_merge, block, block_merge, check, fact, policy, rule, @@ -122,12 +123,10 @@ fn authorizer_macro_trailing_comma() { #[test] fn biscuit_macro() { - use biscuit_auth::PublicKey; let pubkey = PublicKey::from_bytes( - &hex::decode("6e9e6d5a75cf0c0e87ec1256b4dfed0ca3ba452912d213fcc70f8516583db9db").unwrap(), biscuit_auth::builder::Algorithm::Ed25519, - ) - .unwrap(); + hex::decode("6e9e6d5a75cf0c0e87ec1256b4dfed0ca3ba452912d213fcc70f8516583db9db").unwrap(), + ); let s = String::from("my_value"); let my_key = "my_value"; @@ -184,12 +183,10 @@ fn biscuit_macro_trailing_comma() { #[test] fn rule_macro() { - use biscuit_auth::PublicKey; let pubkey = PublicKey::from_bytes( - &hex::decode("6e9e6d5a75cf0c0e87ec1256b4dfed0ca3ba452912d213fcc70f8516583db9db").unwrap(), biscuit_auth::builder::Algorithm::Ed25519, - ) - .unwrap(); + hex::decode("6e9e6d5a75cf0c0e87ec1256b4dfed0ca3ba452912d213fcc70f8516583db9db").unwrap(), + ); let mut term_set = BTreeSet::new(); term_set.insert(builder::int(0i64)); let r = rule!( @@ -214,12 +211,10 @@ fn fact_macro() { #[test] fn check_macro() { - use biscuit_auth::PublicKey; let pubkey = PublicKey::from_bytes( - &hex::decode("6e9e6d5a75cf0c0e87ec1256b4dfed0ca3ba452912d213fcc70f8516583db9db").unwrap(), biscuit_auth::builder::Algorithm::Ed25519, - ) - .unwrap(); + hex::decode("6e9e6d5a75cf0c0e87ec1256b4dfed0ca3ba452912d213fcc70f8516583db9db").unwrap(), + ); let mut term_set = BTreeSet::new(); term_set.insert(builder::int(0i64)); let c = check!( @@ -235,12 +230,10 @@ fn check_macro() { #[test] fn policy_macro() { - use biscuit_auth::PublicKey; let pubkey = PublicKey::from_bytes( - &hex::decode("6e9e6d5a75cf0c0e87ec1256b4dfed0ca3ba452912d213fcc70f8516583db9db").unwrap(), biscuit_auth::builder::Algorithm::Ed25519, - ) - .unwrap(); + hex::decode("6e9e6d5a75cf0c0e87ec1256b4dfed0ca3ba452912d213fcc70f8516583db9db").unwrap(), + ); let mut term_set = BTreeSet::new(); term_set.insert(builder::int(0i64)); let p = policy!( @@ -295,13 +288,10 @@ fn json() { #[test] fn ecdsa() { - use biscuit_auth::PublicKey; - let pubkey = PublicKey::from_bytes( - &hex::decode("0245dd01132962da3812911b746b080aed714873c1812e7cefacf13e3880712da0").unwrap(), biscuit_auth::builder::Algorithm::Secp256r1, - ) - .unwrap(); + hex::decode("0245dd01132962da3812911b746b080aed714873c1812e7cefacf13e3880712da0").unwrap(), + ); let mut term_set = BTreeSet::new(); term_set.insert(builder::int(0i64)); let r = rule!( @@ -318,16 +308,19 @@ fn ecdsa() { #[test] fn trusting() { // this should only work with a proper `PublicKey` value, and fail when trying to provide a string instead - let pubkey: PublicKey = - "secp256r1/0245dd01132962da3812911b746b080aed714873c1812e7cefacf13e3880712da0" - .parse() - .unwrap(); - let _ = authorizer!( - r#" + let pubkey = PublicKey::from_bytes( + biscuit_auth::builder::Algorithm::Secp256r1, + hex::decode("0245dd01132962da3812911b746b080aed714873c1812e7cefacf13e3880712da0").unwrap(), + ); + let _ = { + let pubkey = pubkey.clone(); + authorizer!( + r#" nonce("a"); operation("o"); pathname("p"); d($x) <- nonce($x) trusting {pubkey} "# - ); + ) + }; let _ = rule!( r#" data($nonce, $operation, $pathname) diff --git a/biscuit-parser/src/builder.rs b/biscuit-parser/src/builder.rs index 55faa04e..92eb69dc 100644 --- a/biscuit-parser/src/builder.rs +++ b/biscuit-parser/src/builder.rs @@ -164,10 +164,10 @@ impl ToTokens for Scope { let bytes = pk.key.iter(); match pk.algorithm { Algorithm::Ed25519 => quote! { ::biscuit_auth::builder::Scope::PublicKey( - ::biscuit_auth::PublicKey::from_bytes(&[#(#bytes),*], ::biscuit_auth::builder::Algorithm::Ed25519).unwrap() + ::biscuit_auth::public_keys::PublicKey::from_bytes(::biscuit_auth::builder::Algorithm::Ed25519, vec![#(#bytes),*]) )}, Algorithm::Secp256r1 => quote! { ::biscuit_auth::builder::Scope::PublicKey( - ::biscuit_auth::PublicKey::from_bytes(&[#(#bytes),*], ::biscuit_auth::builder::Algorithm::Secp256r1).unwrap() + ::biscuit_auth::public_keys::PublicKey::from_bytes(::biscuit_auth::builder::Algorithm::Secp256r1, vec![#(#bytes),*]) )}, } } From 32bbe30bac859936c3b79133354a9ad15feec692 Mon Sep 17 00:00:00 2001 From: Saoirse Aronson Date: Tue, 30 Jun 2026 17:29:36 +0200 Subject: [PATCH 3/3] Add to CHANGELOG --- biscuit-auth/CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/biscuit-auth/CHANGELOG.md b/biscuit-auth/CHANGELOG.md index 9fa4b208..796ca51c 100644 --- a/biscuit-auth/CHANGELOG.md +++ b/biscuit-auth/CHANGELOG.md @@ -1,3 +1,7 @@ +# `7.0.0` + +- Abstract biscuits over the crypto implementation (#334) + # `6.0.0` - support for `pem` / `der` private and public keys (#212 and #265)