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/CHANGELOG.md b/biscuit-auth/CHANGELOG.md index 9fa4b208..2b51e035 100644 --- a/biscuit-auth/CHANGELOG.md +++ b/biscuit-auth/CHANGELOG.md @@ -1,3 +1,32 @@ +# `7.0.0` + +- Abstract biscuits over the crypto implementation (#334) Tokens are generic over the key type used + to sign them and four new traits are added: `Sign` and `SerializePrivateKey` for private keys and + `Verify` and `SerializePublicKey` for public keys. +- New `PublicKeyData` type representing the inert data representation of a public key as it is + stored in a token, as well as `PublicKeys`, the block's public key table. (#334) +- `Term` implements `From` with the `uuid` feature. +- Scope parameters are `Into` so they can take anything which can be converted into a + public key (including `&K: SerializePublicKey`). + +## Breaking changes + +- `KeyPair` is removed; use `PrivateKey` directly instead of `KeyPair`. APIs that previously took a + keypair are replaced with APIs that take a `PrivateKey` (i.e. `append_with_keypair` -> + `append_with_key`, `append_third_party_with_keypair` -> `append_third_party_with_key`). +- `Biscuit` and `UnverifiedBiscuit` are generic over the private key type contained in their + proof. These are defaulted to `PrivateKey`, so this change should be transparent for most users + who use the default crypto types. +- `RootKeyProvider` has an associated `Key` type, which is the type of the root key that is + provided. +- All `algorithm()` methods return `builder::Algorithm` instead of + `format::schema::public_key::Algorithm`. +- Datalog scopes now take `PublicKeyData` instead of the cryptographic `PublicKey` type. +- The `ToAnyParam` trait and `AnyParam` enum are removed; users who were implementing `ToAnyParam` + for custom types should implement `From for Term` instead. +- The `set_macro_param` and `set_macro_scope_param` methods are removed; macros now call + `set_lenient` and `set_scope_lenient`. + # `6.0.0` - support for `pem` / `der` private and public keys (#212 and #265) 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..cfec9a5a 100644 --- a/biscuit-auth/benches/token.rs +++ b/biscuit-auth/benches/token.rs @@ -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..44713025 100644 --- a/biscuit-auth/examples/testcases.rs +++ b/biscuit-auth/examples/testcases.rs @@ -11,8 +11,9 @@ use biscuit::datalog::SymbolTable; use biscuit::error; use biscuit::format::convert; use biscuit::macros::*; +use biscuit::public_keys::PublicKeyData; use biscuit::{builder::*, builder_ext::*, Biscuit}; -use biscuit::{KeyPair, PrivateKey, PublicKey}; +use biscuit::PrivateKey; use biscuit_auth::builder; use biscuit_auth::builder::Algorithm; use biscuit_auth::datalog::ExternFunc; @@ -82,10 +83,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(); @@ -177,7 +178,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 +189,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())); @@ -316,7 +317,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 +328,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, @@ -380,7 +381,7 @@ fn validate_token_with_limits_and_external_functions( .world .public_keys .iter() - .map(|k| PublicKey::from_proto(k).unwrap()) + .map(PublicKeyData::from_proto) .collect(), ) .unwrap(); @@ -513,7 +514,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 +532,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 +547,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 +584,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 +600,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 +637,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 +652,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 +687,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 +702,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 +740,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 +755,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 +792,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 +807,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 +849,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 +863,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 +880,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 +908,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 +921,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 +959,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 +977,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 +1006,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 +1019,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 +1050,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 +1089,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 +1136,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 +1150,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 +1200,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 +1230,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 +1259,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 +1268,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 +1289,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 +1390,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 +1408,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 +1427,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 +1437,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 +1458,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 +1473,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 +1515,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 +1545,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 +1588,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 +1597,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 +1632,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, @@ -1651,7 +1652,7 @@ fn third_party(target: &str, root: &KeyPair, test: bool) -> TestResult { right("read"); check if group("admin") trusting {external_pub} "#, - external_pub = external.public() + external_pub = PublicKeyData::from(&external.public()) ) .build_with_rng(root, SymbolTable::default(), &mut rng) .unwrap(); @@ -1660,7 +1661,7 @@ fn third_party(target: &str, root: &KeyPair, test: bool) -> TestResult { let res = req .create_block( - &external.private(), + &external, block!( r#" group("admin"); @@ -1669,9 +1670,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 +1693,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 +1757,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, @@ -1793,7 +1794,7 @@ fn public_keys_interning(target: &str, root: &KeyPair, test: bool) -> TestResult query(0); check if true trusting previous, {k1}; "#, - k1 = external1.public() + k1 = PublicKeyData::from(&external1.public()) ) .build_with_rng(root, SymbolTable::default(), &mut rng) .unwrap(); @@ -1802,7 +1803,7 @@ fn public_keys_interning(target: &str, root: &KeyPair, test: bool) -> TestResult let res1 = req1 .create_block( - &external1.private(), + &external1, block!( r#" query(1); @@ -1810,79 +1811,79 @@ fn public_keys_interning(target: &str, root: &KeyPair, test: bool) -> TestResult check if query(2), query(3) trusting {k2}; check if query(1) trusting {k1}; "#, - k1 = external1.public(), - k2 = external2.public(), + k1 = PublicKeyData::from(&external1.public()), + k2 = PublicKeyData::from(&external2.public()), ), ) .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(); let req2 = biscuit2.third_party_request().unwrap(); let res2 = req2 .create_block( - &external2.private(), + &external2, block!( r#" query(2); check if query(2), query(3) trusting {k2}; check if query(1) trusting {k1}; "#, - k1 = external1.public(), - k2 = external2.public(), + k1 = PublicKeyData::from(&external1.public()), + k2 = PublicKeyData::from(&external2.public()), ), ) .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(); let req3 = biscuit3.third_party_request().unwrap(); let res3 = req3 .create_block( - &external2.private(), + &external2, block!( r#" query(3); check if query(2), query(3) trusting {k2}; check if query(1) trusting {k1}; "#, - k1 = external1.public(), - k2 = external2.public(), + k1 = PublicKeyData::from(&external1.public()), + k2 = PublicKeyData::from(&external2.public()), ), ) .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); check if query(2) trusting {k2}; check if query(4) trusting {k3}; "#, - k2 = external2.public(), - k3 = external3.public(), + k2 = PublicKeyData::from(&external2.public()), + k3 = PublicKeyData::from(&external3.public()), ), ) .unwrap(); @@ -1919,7 +1920,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 +1953,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 +1996,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 +2026,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 +2069,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 +2127,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 +2185,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 +2240,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 +2299,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 +2346,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 +2362,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 +2400,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"); @@ -2413,7 +2414,7 @@ fn secp256r1_third_party(target: &str, root: &KeyPair, test: bool) -> TestResult right("file1", "write"); check if from_third(true) trusting {external_pub}; "#, - external_pub = external_keypair.public(), + external_pub = PublicKeyData::from(&external_keypair.public()), ) .build_with_key_pair(root, SymbolTable::default(), &keypair2) .unwrap(); @@ -2421,16 +2422,16 @@ fn secp256r1_third_party(target: &str, root: &KeyPair, test: bool) -> TestResult 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);"# ), ) .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 +2460,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(); @@ -2516,8 +2517,7 @@ fn print_blocks(token: &Biscuit) -> Vec { public_keys: token .block_public_keys(i) .unwrap() - .into_inner() - .iter() + .into_iter() .map(|k| k.print()) .collect(), external_key: token.block_external_key(i).unwrap().map(|k| k.print()), diff --git a/biscuit-auth/examples/third_party.rs b/biscuit-auth/examples/third_party.rs index c572d214..2dadbeeb 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() @@ -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/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..f96dd19e 100644 --- a/biscuit-auth/src/crypto/mod.rs +++ b/biscuit-auth/src/crypto/mod.rs @@ -11,71 +11,62 @@ //! //! 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; -/// pair of cryptographic keys used to sign a token's block -#[derive(Debug, PartialEq)] -pub enum KeyPair { - Ed25519(ed25519::KeyPair), - P256(p256::KeyPair), +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 { + 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 +76,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 +94,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 +109,33 @@ 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(), - } - } - - pub fn private(&self) -> PrivateKey { - match self { - KeyPair::Ed25519(key) => PrivateKey::Ed25519(key.private()), - KeyPair::P256(key) => PrivateKey::P256(key.private()), + PrivateKey::Ed25519(key) => key.to_private_key_pem(), + PrivateKey::P256(key) => key.to_private_key_pem(), } } 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 { + pub fn algorithm(&self) -> 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(_) => Algorithm::Ed25519, + PrivateKey::P256(_) => Algorithm::Secp256r1, } } -} -impl PrivateKey { /// serializes to a byte array pub fn to_bytes(&self) -> zeroize::Zeroizing> { match self { @@ -199,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()) } @@ -263,24 +216,64 @@ 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() + } +} + +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(), + )), } } +} + +impl Sign for PrivateKey { + type PublicKey = PublicKey; - pub fn algorithm(&self) -> crate::format::schema::public_key::Algorithm { + fn sign(&self, data: &[u8]) -> Result { + self.sign(data) + } + + fn public(&self) -> Self::PublicKey { + self.public() + } + + 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, } } } -/// the public part of a [KeyPair] +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 { Ed25519(ed25519::PublicKey), @@ -393,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, } } @@ -422,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); @@ -463,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( - keypair: &KeyPair, - next_key: &KeyPair, +pub fn sign_authority_block( + key: &RK, + 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}" @@ -500,24 +528,24 @@ 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, +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, @@ -530,12 +558,12 @@ pub fn sign_block( } }; - Ok(keypair.sign(&to_sign)?) + 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: &RK, ) -> Result<(), error::Format> { let to_verify = match block.version { 0 => generate_block_signature_payload_v0( @@ -559,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> { @@ -602,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> { @@ -624,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(); @@ -635,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(); @@ -650,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(); @@ -670,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 { @@ -700,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()); @@ -724,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()); @@ -732,18 +760,18 @@ pub(crate) fn generate_seal_signature_payload_v0(block: &Block) -> Vec { to_verify } -impl TokenNext { - pub fn keypair(&self) -> Result { +impl Proof { + pub fn private_key(&self) -> Result { match &self { - TokenNext::Seal(_) => Err(error::Token::AlreadySealed), - TokenNext::Secret(private) => Ok(KeyPair::from(private)), + 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, } } } @@ -770,29 +798,27 @@ 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() ); assert_eq!( - ed_root.private().to_bytes(), + ed_root.to_bytes(), ed_root - .private() .to_prefixed_string() .parse::() .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() ); assert_eq!( - p256_root.private().to_bytes(), + p256_root.to_bytes(), p256_root - .private() .to_prefixed_string() .parse::() .unwrap() @@ -879,16 +905,15 @@ mod tests { #[cfg(feature = "pem")] #[test] fn ed25519_der() { - let ed25519_kp = KeyPair::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 = - KeyPair::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(); - assert_eq!(ed25519_kp, deser); + PrivateKey::from_private_key_der_with_algorithm(&der_kp, Algorithm::Ed25519).unwrap(); + assert_eq!(ed25519_priv, deser); + let deser = PrivateKey::from_private_key_der(&der_kp).unwrap(); + 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(); @@ -896,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); @@ -907,15 +932,14 @@ mod tests { #[cfg(feature = "pem")] #[test] fn ed25519_pem() { - let ed25519_kp = KeyPair::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 = - KeyPair::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(); - assert_eq!(ed25519_kp, deser); + PrivateKey::from_private_key_pem_with_algorithm(&pem_kp, Algorithm::Ed25519).unwrap(); + assert_eq!(ed25519_priv, deser); + let deser = PrivateKey::from_private_key_pem(&pem_kp).unwrap(); + 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(); @@ -923,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); @@ -934,15 +958,14 @@ mod tests { #[cfg(feature = "pem")] #[test] fn p256_der() { - let p256_kp = KeyPair::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 = - KeyPair::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(); - assert_eq!(p256_kp, deser); + PrivateKey::from_private_key_der_with_algorithm(&der_kp, Algorithm::Secp256r1).unwrap(); + assert_eq!(p256_priv, deser); + let deser = PrivateKey::from_private_key_der(&der_kp).unwrap(); + 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(); @@ -950,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); @@ -961,15 +984,14 @@ mod tests { #[cfg(feature = "pem")] #[test] fn p256_pem() { - let p256_kp = KeyPair::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 = - KeyPair::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(); - assert_eq!(p256_kp, deser); + PrivateKey::from_private_key_pem_with_algorithm(&pem_kp, Algorithm::Secp256r1).unwrap(); + assert_eq!(p256_priv, deser); + let deser = PrivateKey::from_private_key_pem(&pem_kp).unwrap(); + 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(); @@ -977,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/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/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..45341ace 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::PublicKeyData; 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, @@ -76,10 +77,10 @@ impl SymbolTable { pub fn from_symbols_and_public_keys( symbols: Vec, - public_keys: Vec, + 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..a511b6ae 100644 --- a/biscuit-auth/src/format/convert.rs +++ b/biscuit-auth/src/format/convert.rs @@ -6,12 +6,12 @@ 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; use crate::format::schema::MapEntry; -use crate::token::public_keys::PublicKeys; +use crate::token::public_keys::{PublicKeyData, PublicKeys}; use crate::token::Scope; use crate::token::{authorizer::AuthorizerPolicies, Block}; use crate::token::{DATALOG_3_1, DATALOG_3_2, DATALOG_3_3, MAX_SCHEMA_VERSION, MIN_SCHEMA_VERSION}; @@ -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_fallible(&PublicKeyData::from_proto(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(PublicKeyData::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()), } } @@ -189,10 +189,10 @@ pub fn proto_snapshot_block_to_token_block( detected_schema_version.check_compatibility(version)?; - let external_key = match &input.external_key { - None => None, - Some(key) => Some(PublicKey::from_proto(key)?), - }; + let external_key = input + .external_key + .as_ref() + .map(PublicKeyData::from_proto); Ok(Block { symbols: SymbolTable::new(), @@ -852,3 +852,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 4ff3c70a..32f5af4c 100644 --- a/biscuit-auth/src/format/mod.rs +++ b/biscuit-auth/src/format/mod.rs @@ -8,17 +8,21 @@ //! //! - 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 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; use crate::token::DATALOG_3_3; +use crate::token::public_keys::PublicKeyData; /// Structures generated from the Protobuf schema pub mod schema; /*{ @@ -32,22 +36,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 +70,7 @@ impl SerializedBiscuit { key_provider: KP, ) -> Result where - KP: RootKeyProvider, + KP: RootKeyProvider, { let deser = SerializedBiscuit::deserialize(slice, ThirdPartyVerificationMode::UnsafeLegacy)?; @@ -84,7 +89,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 +110,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 +124,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 +151,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 +174,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 +183,9 @@ impl SerializedBiscuit { symbols.extend(&SymbolTable::from(authority.symbols.clone())?)?; for pk in &authority.public_keys { - symbols - .public_keys - .insert_fallible(&PublicKey::from_proto(pk)?)?; + let data = PublicKeyData::from_proto(pk); + symbols.public_keys.insert_fallible(&data)?; } - // 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 +196,11 @@ 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)?)?; + let data = PublicKeyData::from_proto(pk); + symbols.public_keys.insert_fallible(&data)?; } } @@ -225,7 +214,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 +228,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 +252,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,33 +279,33 @@ impl SerializedBiscuit { } /// creates a new token - pub fn new( + pub fn new( root_key_id: Option, - root_keypair: &KeyPair, - next_keypair: &KeyPair, + root_private_key: &RK, + next_private_key: &K, authority: &Block, ) -> Result { let authority_signature_version = block_signature_version( - root_keypair, - next_keypair, - &None, + 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, ) } /// creates a new token - pub(crate) fn new_inner( + pub(crate) fn new_inner( root_key_id: Option, - root_keypair: &KeyPair, - next_keypair: &KeyPair, + root_private_key: &RK, + next_private_key: &K, authority: &Block, authority_signature_version: u32, ) -> Result { @@ -328,8 +317,8 @@ impl SerializedBiscuit { })?; let signature = crypto::sign_authority_block( - root_keypair, - next_keypair, + root_private_key, + &next_private_key.public(), &v, authority_signature_version, )?; @@ -338,24 +327,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: Proof::Secret(next_private_key.clone()), }) } /// adds a new block, serializes it and sign a new token pub fn append( &self, - next_keypair: &KeyPair, + next_private_key: &K, block: &Block, - external_signature: Option, + 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 +354,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 +367,8 @@ impl SerializedBiscuit { ); let signature = crypto::sign_block( - &keypair, - next_keypair, + &private_key, + &next_private_key.public(), &v, external_signature.as_ref(), &self.last_block().signature, @@ -390,7 +379,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 +389,22 @@ impl SerializedBiscuit { root_key_id: self.root_key_id, authority: self.authority.clone(), blocks, - proof: TokenNext::Secret(next_keypair.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_keypair: &KeyPair, + next_private_key: &K, block: Vec, - external_signature: Option, + 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 +414,8 @@ impl SerializedBiscuit { ); let signature = crypto::sign_block( - &keypair, - next_keypair, + &private_key, + &next_private_key.public(), &block, external_signature.as_ref(), &self.last_block().signature, @@ -437,7 +426,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,26 +436,25 @@ impl SerializedBiscuit { root_key_id: self.root_key_id, authority: self.authority.clone(), blocks, - proof: TokenNext::Secret(next_keypair.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: &RK) -> Result<(), error::Format> { self.verify_inner(root, ThirdPartyVerificationMode::PreviousSignatureHashing) } - pub(crate) fn verify_inner( + pub(crate) fn verify_inner( &self, - root: &PublicKey, + root: &RK, 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 +476,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 +485,7 @@ impl SerializedBiscuit { )); } } - TokenNext::Seal(signature) => { + Proof::Seal(signature) => { //FIXME: replace with SHA512 hashing let block = if self.blocks.is_empty() { &self.authority @@ -513,9 +501,8 @@ impl SerializedBiscuit { Ok(()) } - 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,31 +513,46 @@ 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, 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_keypair: &KeyPair, - next_keypair: &KeyPair, - external_signature: &Option, +fn block_signature_version( + block_private_key: &RK, + next_private_key: &AK, + external_signature: &Option>, block_version: &Option, previous_blocks_sig_versions: I, ) -> u32 @@ -568,8 +570,8 @@ where _ => {} } - match (block_keypair, next_keypair) { - (KeyPair::Ed25519(_), KeyPair::Ed25519(_)) => {} + match (block_private_key.algorithm(), next_private_key.algorithm()) { + (Algorithm::Ed25519, Algorithm::Ed25519) => {} _ => { return NON_ED25519_SIGNATURE_VERSION; } @@ -587,7 +589,7 @@ mod tests { crypto::{ExternalSignature, Signature}, format::block_signature_version, token::{DATALOG_3_1, DATALOG_3_3}, - KeyPair, + PrivateKey, }; #[test] @@ -620,9 +622,9 @@ mod tests { fn test_block_signature_version() { assert_eq!( block_signature_version( - &KeyPair::new(), - &KeyPair::new(), - &None, + &PrivateKey::new(), + &PrivateKey::new(), + &None::, &Some(DATALOG_3_1), std::iter::empty() ), @@ -631,9 +633,9 @@ mod tests { ); assert_eq!( block_signature_version( - &KeyPair::new_with_algorithm(Algorithm::Secp256r1), - &KeyPair::new_with_algorithm(Algorithm::Ed25519), - &None, + &PrivateKey::new_with_algorithm(Algorithm::Secp256r1), + &PrivateKey::new_with_algorithm(Algorithm::Ed25519), + &None::, &Some(DATALOG_3_1), std::iter::empty() ), @@ -642,9 +644,9 @@ mod tests { ); assert_eq!( block_signature_version( - &KeyPair::new_with_algorithm(Algorithm::Ed25519), - &KeyPair::new_with_algorithm(Algorithm::Secp256r1), - &None, + &PrivateKey::new_with_algorithm(Algorithm::Ed25519), + &PrivateKey::new_with_algorithm(Algorithm::Secp256r1), + &None::, &Some(DATALOG_3_1), std::iter::empty() ), @@ -653,9 +655,9 @@ mod tests { ); assert_eq!( block_signature_version( - &KeyPair::new_with_algorithm(Algorithm::Secp256r1), - &KeyPair::new_with_algorithm(Algorithm::Secp256r1), - &None, + &PrivateKey::new_with_algorithm(Algorithm::Secp256r1), + &PrivateKey::new_with_algorithm(Algorithm::Secp256r1), + &None::, &Some(DATALOG_3_1), std::iter::empty() ), @@ -664,10 +666,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,9 +680,9 @@ mod tests { ); assert_eq!( block_signature_version( - &KeyPair::new(), - &KeyPair::new(), - &None, + &PrivateKey::new(), + &PrivateKey::new(), + &None::, &Some(DATALOG_3_3), std::iter::empty() ), @@ -689,9 +691,9 @@ mod tests { ); assert_eq!( block_signature_version( - &KeyPair::new(), - &KeyPair::new(), - &None, + &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..d2304a21 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,10 @@ pub mod format; pub mod parser; mod token; -pub use crypto::{KeyPair, PrivateKey, PublicKey}; +pub use crypto::{ + PrivateKey, PublicKey, SerializePrivateKey, SerializePublicKey, Sign, Signature, Verify, +}; +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/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..437374eb 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) } @@ -127,13 +128,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 +166,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 +253,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(); @@ -917,10 +918,10 @@ 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::PublicKeyData; use crate::{ builder::{BiscuitBuilder, BlockBuilder}, - KeyPair, + PrivateKey, }; use super::*; @@ -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(), + PublicKeyData::from_bytes( crate::builder::Algorithm::Ed25519, - ) - .unwrap(), + hex::decode("6e9e6d5a75cf0c0e87ec1256b4dfed0ca3ba452912d213fcc70f8516583db9db") + .unwrap(), + ), ); let _authorizer = AuthorizerBuilder::new() .code_with_params( @@ -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,11 +1146,11 @@ 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()); + scope_params.insert("external_pub".to_string(), PublicKeyData::from(&external.public())); let biscuit1 = Biscuit::builder() .code_with_params( @@ -1173,17 +1173,17 @@ 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()); - scope_params.insert("external2".to_string(), external2.public()); + scope_params.insert("external".to_string(), PublicKeyData::from(&external.public())); + scope_params.insert("external2".to_string(), PublicKeyData::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", PublicKeyData::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", PublicKeyData::from(&external.public())).unwrap(); r }, AuthorizerLimits { @@ -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( @@ -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 d7c269a2..e87f7a3b 100644 --- a/biscuit-auth/src/token/authorizer/snapshot.rs +++ b/biscuit-auth/src/token/authorizer/snapshot.rs @@ -18,8 +18,8 @@ use crate::{ schema::{self, GeneratedFacts}, }, token::{default_symbol_table, MAX_SCHEMA_VERSION, MIN_SCHEMA_VERSION}, - PublicKey, }; +use crate::token::public_keys::PublicKeyData; impl super::Authorizer { pub fn from_snapshot(input: schema::AuthorizerSnapshot) -> Result { @@ -52,9 +52,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(&PublicKeyData::from_proto(&public_key)); } let authorizer_block = proto_snapshot_block_to_token_block(&world.authorizer_block)?; @@ -193,7 +191,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)?; @@ -320,12 +321,13 @@ mod tests { use std::time::Duration; use crate::{datalog::RunLimits, Algorithm, AuthorizerBuilder}; - use crate::{Authorizer, BiscuitBuilder, KeyPair}; + use crate::{Authorizer, BiscuitBuilder, PrivateKey}; + use crate::token::public_keys::PublicKeyData; #[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 = PublicKeyData::from(&PrivateKey::new_with_algorithm(Algorithm::Secp256r1).public()); + let ed_pubkey = PublicKeyData::from(&PrivateKey::new_with_algorithm(Algorithm::Ed25519).public()); let builder = AuthorizerBuilder::new() .set_limits(RunLimits { max_facts: 42, @@ -356,8 +358,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 = PublicKeyData::from(&PrivateKey::new_with_algorithm(Algorithm::Secp256r1).public()); + let ed_pubkey = PublicKeyData::from(&PrivateKey::new_with_algorithm(Algorithm::Ed25519).public()); let builder = AuthorizerBuilder::new() .set_limits(RunLimits { max_facts: 42, @@ -374,8 +376,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(); @@ -393,7 +395,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/block.rs b/biscuit-auth/src/token/block.rs index 49679b3e..ec125ca0 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..13a1a2e4 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(test)] +use crate::token::public_keys::PublicKeyData; use crate::datalog::SymbolTable; pub use crate::datalog::{ Binary as DatalogBinary, Expression as DatalogExpression, Op as DatalogOp, @@ -162,17 +163,6 @@ pub fn parameter(p: &str) -> Term { Term::Parameter(p.to_string()) } -#[cfg(feature = "datalog-macro")] -pub enum AnyParam { - Term(Term), - PublicKey(PublicKey), -} - -#[cfg(feature = "datalog-macro")] -pub trait ToAnyParam { - fn to_any_param(&self) -> AnyParam; -} - #[cfg(test)] mod tests { use std::{collections::HashMap, convert::TryFrom}; @@ -213,12 +203,11 @@ mod tests { #[test] fn set_rule_scope_parameters() { - let pubkey = PublicKey::from_bytes( - &hex::decode("6e9e6d5a75cf0c0e87ec1256b4dfed0ca3ba452912d213fcc70f8516583db9db") - .unwrap(), + let pubkey = PublicKeyData::from_bytes( 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}", ) @@ -240,12 +229,11 @@ mod tests { params.insert("p2".to_string(), 1i64.into()); 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(), + let pubkey = PublicKeyData::from_bytes( 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..8ca2b56c 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::PublicKeyData; 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}; @@ -116,7 +119,7 @@ impl AuthorizerBuilder { mut self, source: T, params: HashMap, - scope_params: HashMap, + scope_params: HashMap, ) -> Result { let source = source.as_ref(); @@ -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,9 @@ 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(&PublicKeyData::from(&sig.public_key)); public_key_to_block_id .entry(new_key_id as usize) @@ -607,7 +612,7 @@ impl AuthorizerBuilder { for public_key in world.public_keys { symbols .public_keys - .insert(&PublicKey::from_proto(&public_key)?); + .insert(&PublicKeyData::from_proto(&public_key)); } let authorizer_block = proto_snapshot_block_to_token_block(&world.authorizer_block)?; @@ -648,7 +653,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 a02bfb1a..85999dcc 100644 --- a/biscuit-auth/src/token/builder/biscuit.rs +++ b/biscuit-auth/src/token/builder/biscuit.rs @@ -4,21 +4,23 @@ */ use super::{BlockBuilder, Check, Fact, Rule, Scope, Term}; use crate::builder_ext::BuilderExt; -use crate::crypto::PublicKey; +use crate::crypto::{SerializePrivateKey, Sign}; +use crate::token::public_keys::PublicKeyData; use crate::datalog::SymbolTable; use crate::token::default_symbol_table; -use crate::{error, Biscuit, KeyPair}; +use crate::{Biscuit, PrivateKey, error}; use rand::{CryptoRng, RngCore}; use std::fmt; +use std::marker::PhantomData; use std::time::SystemTime; use std::{collections::HashMap, convert::TryInto, fmt::Write}; /// creates a Biscuit -#[derive(Clone, Default)] -pub struct BiscuitBuilder { +pub struct BiscuitBuilder { inner: BlockBuilder, root_key_id: Option, + _marker: PhantomData, } impl BiscuitBuilder { @@ -26,10 +28,23 @@ impl BiscuitBuilder { BiscuitBuilder { inner: BlockBuilder::new(), root_key_id: None, + _marker: PhantomData, } } +} - pub fn merge(mut self, other: BlockBuilder) -> Self { +impl Default for BiscuitBuilder { + fn default() -> BiscuitBuilder { + BiscuitBuilder { + inner: BlockBuilder::new(), + root_key_id: None, + _marker: PhantomData, + } + } +} + +impl BiscuitBuilder { + pub fn merge(mut self, other: BlockBuilder) -> BiscuitBuilder { self.inner = self.inner.merge(other); self } @@ -69,7 +84,7 @@ impl BiscuitBuilder { mut self, source: T, params: HashMap, - scope_params: HashMap, + scope_params: HashMap, ) -> Result { self.inner = self.inner.code_with_params(source, params, scope_params)?; Ok(self) @@ -124,39 +139,49 @@ impl BiscuitBuilder { f } - pub fn build(self, root_key: &KeyPair) -> Result { + pub fn build(self, root_key: &RK) -> 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: &KeyPair, + root_key: &RK, 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: &KeyPair, + root: &RK, 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: &KeyPair, + root: &RK, symbols: SymbolTable, - next: &KeyPair, - ) -> 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) } } +impl Clone for BiscuitBuilder { + fn clone(&self) -> BiscuitBuilder { + BiscuitBuilder { + inner: self.inner.clone(), + root_key_id: self.root_key_id, + _marker: PhantomData, + } + } +} + impl fmt::Display for BiscuitBuilder { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self.root_key_id { diff --git a/biscuit-auth/src/token/builder/block.rs b/biscuit-auth/src/token/builder/block.rs index bde72dc6..d895c80c 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::PublicKeyData; use crate::datalog::{get_schema_version, SymbolTable}; use crate::error; use biscuit_parser::parser::parse_block_source; @@ -82,7 +82,7 @@ impl BlockBuilder { mut self, source: T, params: HashMap, - scope_params: HashMap, + scope_params: HashMap, ) -> Result { let input = source.as_ref(); @@ -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..17ee284f 100644 --- a/biscuit-auth/src/token/builder/check.rs +++ b/biscuit-auth/src/token/builder/check.rs @@ -8,11 +8,10 @@ use nom::Finish; use crate::{ datalog::{self, SymbolTable}, - error, PublicKey, + error, + token::public_keys::PublicKeyData, }; -#[cfg(feature = "datalog-macro")] -use super::ToAnyParam; use super::{display_rule_body, Convert, Rule, Term}; /// Builder for a Biscuit check @@ -58,10 +57,15 @@ impl Check { } /// replace a scope parameter with the pubkey argument - pub fn set_scope(&mut self, name: &str, pubkey: PublicKey) -> Result<(), error::Token> { + pub fn set_scope>( + &mut self, + name: &str, + pubkey: T, + ) -> Result<(), error::Token> { + let pubkey = pubkey.into(); 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; } } @@ -90,35 +94,16 @@ impl Check { /// replace a scope parameter with the term argument, without raising an error if the /// 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)?; - } - Ok(()) - } - - #[cfg(feature = "datalog-macro")] - pub fn set_macro_param( + pub fn set_scope_lenient>( &mut self, name: &str, - param: T, + pubkey: T, ) -> Result<(), error::Token> { - use super::AnyParam; - - match param.to_any_param() { - AnyParam::Term(t) => self.set_lenient(name, t), - AnyParam::PublicKey(p) => self.set_scope_lenient(name, p), + let pubkey = pubkey.into(); + for query in &mut self.queries { + query.set_scope_lenient(name, pubkey.clone())?; } - } - - // TODO maybe introduce a conversion trait to support refs, multiple values, non-pk scopes - #[cfg(feature = "datalog-macro")] - pub fn set_macro_scope_param( - &mut self, - name: &str, - param: PublicKey, - ) -> Result<(), error::Token> { - self.set_scope_lenient(name, param) + Ok(()) } pub fn validate_parameters(&self) -> Result<(), error::Token> { diff --git a/biscuit-auth/src/token/builder/fact.rs b/biscuit-auth/src/token/builder/fact.rs index 4a247f87..6fc03514 100644 --- a/biscuit-auth/src/token/builder/fact.rs +++ b/biscuit-auth/src/token/builder/fact.rs @@ -11,8 +11,6 @@ use crate::{ error, }; -#[cfg(feature = "datalog-macro")] -use super::ToAnyParam; use super::{Convert, Predicate, Term}; /// Builder for a Datalog fact @@ -114,20 +112,6 @@ impl Fact { } } - #[cfg(feature = "datalog-macro")] - pub fn set_macro_param( - &mut self, - name: &str, - param: T, - ) -> Result<(), error::Token> { - use super::AnyParam; - - match param.to_any_param() { - AnyParam::Term(t) => self.set_lenient(name, t), - AnyParam::PublicKey(_) => Ok(()), - } - } - pub(super) fn apply_parameters(&mut self) { if let Some(parameters) = self.parameters.clone() { self.predicate.terms = self diff --git a/biscuit-auth/src/token/builder/policy.rs b/biscuit-auth/src/token/builder/policy.rs index 2a1cb478..81ff1a67 100644 --- a/biscuit-auth/src/token/builder/policy.rs +++ b/biscuit-auth/src/token/builder/policy.rs @@ -6,10 +6,8 @@ use std::{convert::TryFrom, fmt, str::FromStr}; use nom::Finish; -use crate::{error, PublicKey}; +use crate::{error, token::public_keys::PublicKeyData}; -#[cfg(feature = "datalog-macro")] -use super::ToAnyParam; use super::{display_rule_body, Rule, Term}; #[derive(Debug, Clone, PartialEq, Eq)] @@ -53,10 +51,15 @@ impl Policy { } /// replace a scope parameter with the pubkey argument - pub fn set_scope(&mut self, name: &str, pubkey: PublicKey) -> Result<(), error::Token> { + pub fn set_scope>( + &mut self, + name: &str, + pubkey: T, + ) -> Result<(), error::Token> { + let pubkey = pubkey.into(); 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; } } @@ -83,35 +86,16 @@ 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)?; - } - Ok(()) - } - - #[cfg(feature = "datalog-macro")] - pub fn set_macro_param( + pub fn set_scope_lenient>( &mut self, name: &str, - param: T, + pubkey: T, ) -> Result<(), error::Token> { - use super::AnyParam; - - match param.to_any_param() { - AnyParam::Term(t) => self.set_lenient(name, t), - AnyParam::PublicKey(p) => self.set_scope_lenient(name, p), + let pubkey = pubkey.into(); + for query in &mut self.queries { + query.set_scope_lenient(name, pubkey.clone())?; } - } - - // TODO maybe introduce a conversion trait to support refs, multiple values, non-pk scopes - #[cfg(feature = "datalog-macro")] - pub fn set_macro_scope_param( - &mut self, - name: &str, - param: PublicKey, - ) -> Result<(), error::Token> { - self.set_scope_lenient(name, param) + Ok(()) } pub fn validate_parameters(&self) -> Result<(), error::Token> { diff --git a/biscuit-auth/src/token/builder/rule.rs b/biscuit-auth/src/token/builder/rule.rs index ec4483c0..bd4cd63c 100644 --- a/biscuit-auth/src/token/builder/rule.rs +++ b/biscuit-auth/src/token/builder/rule.rs @@ -7,12 +7,11 @@ use std::{collections::HashMap, convert::TryFrom, fmt, str::FromStr}; use nom::Finish; use crate::{ + token::public_keys::PublicKeyData, datalog::{self, SymbolTable}, - error, PublicKey, + error, }; -#[cfg(feature = "datalog-macro")] -use super::ToAnyParam; use super::{Convert, Expression, Predicate, Scope, Term}; /// Builder for a Datalog rule @@ -23,7 +22,7 @@ pub struct Rule { pub expressions: Vec, pub parameters: Option>>, pub scopes: Vec, - pub scope_parameters: Option>>, + pub scope_parameters: Option>>, } impl Rule { @@ -199,7 +198,11 @@ impl Rule { } /// replace a scope parameter with the pubkey argument - pub fn set_scope(&mut self, name: &str, pubkey: PublicKey) -> Result<(), error::Token> { + pub fn set_scope>( + &mut self, + name: &str, + pubkey: T, + ) -> Result<(), error::Token> { if let Some(parameters) = self.scope_parameters.as_mut() { match parameters.get_mut(name) { None => Err(error::Token::Language( @@ -209,7 +212,7 @@ impl Rule { }, )), Some(v) => { - *v = Some(pubkey); + *v = Some(pubkey.into()); Ok(()) } } @@ -225,12 +228,16 @@ impl Rule { /// replace a scope parameter with the public key argument, without raising an error if the /// parameter is not present in the rule scope - pub fn set_scope_lenient(&mut self, name: &str, pubkey: PublicKey) -> Result<(), error::Token> { + pub fn set_scope_lenient>( + &mut self, + name: &str, + pubkey: T, + ) -> Result<(), error::Token> { if let Some(parameters) = self.scope_parameters.as_mut() { match parameters.get_mut(name) { None => Ok(()), Some(v) => { - *v = Some(pubkey); + *v = Some(pubkey.into()); Ok(()) } } @@ -244,30 +251,6 @@ impl Rule { } } - #[cfg(feature = "datalog-macro")] - pub fn set_macro_param( - &mut self, - name: &str, - param: T, - ) -> Result<(), error::Token> { - use super::AnyParam; - - match param.to_any_param() { - AnyParam::Term(t) => self.set_lenient(name, t), - AnyParam::PublicKey(pubkey) => self.set_scope_lenient(name, pubkey), - } - } - - // TODO maybe introduce a conversion trait to support refs, multiple values, non-pk scopes - #[cfg(feature = "datalog-macro")] - pub fn set_macro_scope_param( - &mut self, - name: &str, - param: PublicKey, - ) -> Result<(), error::Token> { - self.set_scope_lenient(name, param) - } - pub(super) fn apply_parameters(&mut self) { if let Some(parameters) = self.parameters.clone() { self.head.terms = self @@ -315,7 +298,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 +438,7 @@ impl From for Rule { ( k, v.map(|pk| { - PublicKey::from_bytes(&pk.key, pk.algorithm.into()) - .expect("invalid public key") + PublicKeyData::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..fd4de6fc 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::PublicKeyData; +use crate::{datalog::SymbolTable, error}; use super::Convert; @@ -16,7 +17,7 @@ pub enum Scope { /// Trusts the current block and all previous ones Previous, /// Trusts the current block and any block signed by the public key - PublicKey(PublicKey), + PublicKey(PublicKeyData), /// Used for parameter substitution Parameter(String), } @@ -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"), + PublicKeyData::from_bytes(pk.algorithm.into(), pk.key) ), biscuit_parser::builder::Scope::Parameter(s) => Scope::Parameter(s), } diff --git a/biscuit-auth/src/token/builder/term.rs b/biscuit-auth/src/token/builder/term.rs index a516a090..8af1edc9 100644 --- a/biscuit-auth/src/token/builder/term.rs +++ b/biscuit-auth/src/token/builder/term.rs @@ -15,8 +15,6 @@ use crate::{ }; use super::{set, Convert, Fact}; -#[cfg(feature = "datalog-macro")] -use super::{AnyParam, ToAnyParam}; /// Builder for a Datalog value #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] @@ -393,26 +391,12 @@ impl fmt::Display for Term { } } -#[cfg(feature = "datalog-macro")] -impl ToAnyParam for Term { - fn to_any_param(&self) -> AnyParam { - AnyParam::Term(self.clone()) - } -} - impl From for Term { fn from(i: i64) -> Self { Term::Integer(i) } } -#[cfg(feature = "datalog-macro")] -impl ToAnyParam for i64 { - fn to_any_param(&self) -> AnyParam { - AnyParam::Term((*self).into()) - } -} - impl TryFrom for i64 { type Error = error::Token; fn try_from(value: Term) -> Result { @@ -431,13 +415,6 @@ impl From for Term { } } -#[cfg(feature = "datalog-macro")] -impl ToAnyParam for bool { - fn to_any_param(&self) -> AnyParam { - AnyParam::Term((*self).into()) - } -} - impl TryFrom for bool { type Error = error::Token; fn try_from(value: Term) -> Result { @@ -456,26 +433,12 @@ impl From for Term { } } -#[cfg(feature = "datalog-macro")] -impl ToAnyParam for String { - fn to_any_param(&self) -> AnyParam { - AnyParam::Term((self.clone()).into()) - } -} - impl From<&str> for Term { fn from(s: &str) -> Self { Term::Str(s.into()) } } -#[cfg(feature = "datalog-macro")] -impl ToAnyParam for &str { - fn to_any_param(&self) -> AnyParam { - AnyParam::Term(self.to_string().into()) - } -} - impl TryFrom for String { type Error = error::Token; fn try_from(value: Term) -> Result { @@ -494,13 +457,6 @@ impl From> for Term { } } -#[cfg(feature = "datalog-macro")] -impl ToAnyParam for Vec { - fn to_any_param(&self) -> AnyParam { - AnyParam::Term((self.clone()).into()) - } -} - impl TryFrom for Vec { type Error = error::Token; fn try_from(value: Term) -> Result { @@ -519,17 +475,10 @@ impl From<&[u8]> for Term { } } -#[cfg(feature = "datalog-macro")] -impl ToAnyParam for [u8] { - fn to_any_param(&self) -> AnyParam { - AnyParam::Term(self.into()) - } -} - -#[cfg(all(feature = "uuid", feature = "datalog-macro"))] -impl ToAnyParam for uuid::Uuid { - fn to_any_param(&self) -> AnyParam { - AnyParam::Term(Term::Bytes(self.as_bytes().to_vec())) +#[cfg(feature = "uuid")] +impl From for Term { + fn from(u: uuid::Uuid) -> Self { + Term::Bytes(u.as_bytes().to_vec()) } } @@ -540,13 +489,6 @@ impl From for Term { } } -#[cfg(feature = "datalog-macro")] -impl ToAnyParam for SystemTime { - fn to_any_param(&self) -> AnyParam { - AnyParam::Term((*self).into()) - } -} - impl TryFrom for SystemTime { type Error = error::Token; fn try_from(value: Term) -> Result { @@ -565,13 +507,6 @@ impl From> for Term { } } -#[cfg(feature = "datalog-macro")] -impl ToAnyParam for BTreeSet { - fn to_any_param(&self) -> AnyParam { - AnyParam::Term((self.clone()).into()) - } -} - impl> TryFrom for BTreeSet { type Error = error::Token; fn try_from(value: Term) -> Result { @@ -584,7 +519,7 @@ impl> TryFrom for BTreeSet } } -// TODO: From and ToAnyParam for arrays and maps +// TODO: From for arrays and maps impl TryFrom for Term { type Error = &'static str; diff --git a/biscuit-auth/src/token/mod.rs b/biscuit-auth/src/token/mod.rs index 218804c9..76419d14 100644 --- a/biscuit-auth/src/token/mod.rs +++ b/biscuit-auth/src/token/mod.rs @@ -3,20 +3,21 @@ * 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; use rand_core::{CryptoRng, RngCore}; -use self::public_keys::PublicKeys; -use super::crypto::{KeyPair, PublicKey, Signature}; +use self::public_keys::{PublicKeyData, PublicKeys}; 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, PrivateKey, PublicKey, Signature, SerializePrivateKey, Verify, Sign}; +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 +26,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; @@ -56,10 +57,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 @@ -80,13 +81,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 +102,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 +111,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 +125,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,14 +169,17 @@ 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 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 = K::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 @@ -216,11 +220,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 @@ -250,33 +254,34 @@ impl Biscuit { /// creates a new token, using a provided CSPRNG /// - /// the public part of the root keypair must be used for verification - pub(crate) fn new_with_rng( + /// 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: &RK, symbols: SymbolTable, authority: Block, - ) -> Result { + ) -> Result, error::Token> { Self::new_with_key_pair( root_key_id, root, - &KeyPair::new_with_rng(builder::Algorithm::Ed25519, rng), + &K::new_with_rng(root.algorithm(), 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( + pub(crate) fn new_with_key_pair( root_key_id: Option, - root: &KeyPair, - next_keypair: &KeyPair, + root_key: &RK, + 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)); } @@ -285,7 +290,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)?; @@ -311,7 +316,7 @@ impl Biscuit { symbols: SymbolTable, ) -> Result where - KP: RootKeyProvider, + KP: RootKeyProvider, { let container = SerializedBiscuit::from_slice(slice, key_provider).map_err(error::Token::Format)?; @@ -320,7 +325,7 @@ impl Biscuit { } fn from_serialized_container( - container: SerializedBiscuit, + container: SerializedBiscuit, mut symbols: SymbolTable, ) -> Result { let (authority, blocks) = container.extract_blocks(&mut symbols)?; @@ -336,7 +341,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, @@ -344,24 +350,24 @@ 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 } /// 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: &K, block_builder: BlockBuilder, ) -> Result { let block = block_builder.build(self.symbols.clone()); @@ -374,7 +380,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)?; @@ -408,31 +414,30 @@ impl Biscuit { pub fn append_third_party( &self, - external_key: PublicKey, + external_key: K::PublicKey, response: ThirdPartyBlock, ) -> Result { - let next_keypair = - KeyPair::new_with_rng(builder::Algorithm::Ed25519, &mut rand::rngs::OsRng); - - self.append_third_party_with_keypair(external_key, response, next_keypair) + 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_keypair( + + pub fn append_third_party_with_key( &self, - external_key: PublicKey, + external_key: K::PublicKey, response: ThirdPartyBlock, - next_keypair: KeyPair, + 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), ), ))); } @@ -444,7 +449,7 @@ impl Biscuit { .blocks .last() .unwrap_or(&self.container.authority) - .next_key; + .next_key.clone(); let external_signature = crypto::ExternalSignature { public_key: external_key, @@ -475,7 +480,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); @@ -516,13 +521,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(&PublicKeyData::from_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 { @@ -535,7 +540,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) @@ -551,7 +556,7 @@ impl Biscuit { .authority .external_signature .as_ref() - .map(|ex| ex.public_key), + .map(|ex| &ex.public_key), ) .map_err(error::Token::Format)? } else { @@ -566,7 +571,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)? }; @@ -574,7 +579,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, @@ -582,7 +587,7 @@ impl Biscuit { .authority .external_signature .as_ref() - .map(|ex| ex.public_key), + .map(|ex| &ex.public_key), ) .map_err(error::Token::Format), ) @@ -593,7 +598,7 @@ impl Biscuit { container .external_signature .as_ref() - .map(|ex| ex.public_key), + .map(|ex| &ex.public_key), ) .map_err(error::Token::Format) }, @@ -601,8 +606,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() @@ -619,12 +641,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(); @@ -665,7 +688,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, @@ -688,41 +711,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) } } @@ -733,7 +770,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 +780,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 +819,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 +847,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 +872,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 +941,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 +959,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 +1034,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 +1049,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 +1098,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 +1115,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 +1167,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 +1210,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 +1227,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 +1300,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 +1318,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 +1360,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 +1389,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 +1404,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 +1417,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 +1454,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 +1496,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 +1536,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 +1635,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 +1649,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 +1660,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/public_keys.rs b/biscuit-auth/src/token/public_keys.rs index e0f05d84..aa0cefd3 100644 --- a/biscuit-auth/src/token/public_keys.rs +++ b/biscuit-auth/src/token/public_keys.rs @@ -3,24 +3,30 @@ * SPDX-License-Identifier: Apache-2.0 */ use std::collections::HashSet; +use std::fmt::{self, Display, Formatter}; +use std::str::FromStr; -use crate::{crypto::PublicKey, error}; +use nom::Finish; -#[derive(Clone, Debug, PartialEq, Eq, Default)] +use crate::crypto::SerializePublicKey; +use crate::format::schema; +use crate::{Algorithm, error}; + +#[derive(Default, Clone, Debug, PartialEq, Eq)] pub struct PublicKeys { - pub(crate) keys: Vec, + 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 +34,142 @@ impl PublicKeys { Ok(()) } - pub fn insert(&mut self, k: &PublicKey) -> u64 { + pub(crate) fn insert(&mut self, k: &PublicKeyData) -> 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_fallible(&mut self, k: &PublicKeyData) -> Result { match self.keys.iter().position(|key| key == k) { Some(_) => Err(error::Format::PublicKeyTableOverlap), None => { - self.keys.push(*k); + self.keys.push(k.clone()); Ok((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 fn current_offset(&self) -> usize { + 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<&PublicKeyData> { self.keys.get(i as usize) } - pub fn into_inner(self) -> Vec { + pub(crate) fn into_inner(self) -> Vec { self.keys } } + +impl IntoIterator for PublicKeys { + type Item = PublicKeyData; + type IntoIter = std::vec::IntoIter; + + fn into_iter(self) -> Self::IntoIter { + self.keys.into_iter() + } +} + +impl<'a> IntoIterator for &'a PublicKeys { + type Item = &'a PublicKeyData; + type IntoIter = std::slice::Iter<'a, PublicKeyData>; + + fn into_iter(self) -> Self::IntoIter { + self.keys.iter() + } +} + +#[derive(Default, Clone, Debug, PartialEq, Eq, Hash)] +pub struct PublicKeyData { + algorithm: Algorithm, + key: Vec, +} + +impl PublicKeyData { + pub fn from_bytes(algorithm: Algorithm, key: Vec) -> PublicKeyData { + PublicKeyData { algorithm, key } + } + + pub fn from_proto(key: &schema::PublicKey) -> PublicKeyData { + PublicKeyData { + 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 algorithm(&self) -> Algorithm { + self.algorithm + } + + pub fn to_bytes(&self) -> Vec { + self.key.clone() + } + + pub fn print(&self) -> String { + self.to_string() + } +} + +/// lowers a public key from any crypto implementation into its serialized +/// representation +impl From<&K> for PublicKeyData { + fn from(key: &K) -> PublicKeyData { + PublicKeyData { + algorithm: key.algorithm(), + key: key.to_bytes(), + } + } +} + +impl From for PublicKeyData { + fn from(key: crate::crypto::PublicKey) -> PublicKeyData { + (&key).into() + } +} + +impl Display for PublicKeyData { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + write!(f, "{}/{}", self.algorithm, hex::encode(&self.key)) + } +} + +impl FromStr for PublicKeyData { + type Err = error::Format; + + fn from_str(s: &str) -> Result { + let (_, public_key) = biscuit_parser::parser::public_key(s) + .finish() + .map_err(|e| error::Format::InvalidKey(e.to_string()))?; + + Ok(PublicKeyData::from_bytes( + public_key.algorithm.into(), + public_key.key, + )) + } +} diff --git a/biscuit-auth/src/token/third_party.rs b/biscuit-auth/src/token/third_party.rs index 7150c96a..6709adc3 100644 --- a/biscuit-auth/src/token/third_party.rs +++ b/biscuit-auth/src/token/third_party.rs @@ -6,13 +6,17 @@ use std::cmp::max; use prost::Message; +use crate::Sign; +use crate::crypto::{SerializePrivateKey, SerializePublicKey}; use crate::{ builder::BlockBuilder, crypto::generate_external_signature_payload_v1, datalog::SymbolTable, error, - format::{convert::token_block_to_proto_block, schema, SerializedBiscuit}, - KeyPair, PrivateKey, + format::{ + convert::{public_key_to_proto, token_block_to_proto_block}, + schema, SerializedBiscuit, + }, }; use super::THIRD_PARTY_SIGNATURE_VERSION; @@ -24,8 +28,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); @@ -92,10 +96,10 @@ impl ThirdPartyRequest { Self::deserialize(&decoded) } - /// Creates a [`ThirdPartyBlock`] signed with the third party service's [`PrivateKey`] - pub fn create_block( + /// Creates a [`ThirdPartyBlock`] signed with the third party service's private key + pub fn create_block>( self, - private_key: &PrivateKey, + private_key: &EK, block_builder: BlockBuilder, ) -> Result { let symbols = SymbolTable::new(); @@ -115,15 +119,14 @@ 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 { signature: signature.to_bytes().to_vec(), - public_key: public_key.to_proto(), + public_key: public_key_to_proto(&public_key), }, }; @@ -157,10 +160,12 @@ impl ThirdPartyBlock { mod tests { use super::*; + use crate::PrivateKey; + #[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..64917460 100644 --- a/biscuit-auth/src/token/unverified.rs +++ b/biscuit-auth/src/token/unverified.rs @@ -2,12 +2,16 @@ * 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::token::public_keys::PublicKeyData; use crate::{ builder::BlockBuilder, - crypto::{self, PublicKey, Signature}, + crypto::{self, PrivateKey, PublicKey, Signature}, datalog::SymbolTable, error, format::{ @@ -16,7 +20,7 @@ use crate::{ SerializedBiscuit, }, token::{ThirdPartyBlockContents, ThirdPartyRequest}, - KeyPair, RootKeyProvider, + RootKeyProvider, }; /// A token that was parsed without cryptographic signature verification @@ -26,12 +30,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 +105,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)?; @@ -102,12 +121,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 +170,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 +187,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)?; @@ -259,7 +278,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 +293,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)? }; @@ -300,15 +319,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,11 +369,11 @@ 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 { - symbols.public_keys.insert_fallible(key)?; + for key in &block.public_keys[..] { + let data = PublicKeyData::from_proto(key); + symbols.public_keys.insert_fallible(&data)?; } blocks.push(block); @@ -378,14 +397,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() @@ -396,7 +415,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 7ff2653e..a419509f 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, KeyPair, PublicKey}; +use biscuit_auth::{builder, datalog::RunLimits, PrivateKey, PublicKey}; +use biscuit_auth::public_keys::PublicKeyData; use biscuit_quote::{ authorizer, authorizer_merge, biscuit, biscuit_merge, block, block_merge, check, fact, policy, rule, @@ -122,12 +123,9 @@ 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(); + let pubkey = "ed25519/6e9e6d5a75cf0c0e87ec1256b4dfed0ca3ba452912d213fcc70f8516583db9db" + .parse::() + .unwrap(); let s = String::from("my_value"); let my_key = "my_value"; @@ -184,12 +182,9 @@ 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(); + let pubkey = "ed25519/6e9e6d5a75cf0c0e87ec1256b4dfed0ca3ba452912d213fcc70f8516583db9db" + .parse::() + .unwrap(); let mut term_set = BTreeSet::new(); term_set.insert(builder::int(0i64)); let r = rule!( @@ -214,12 +209,9 @@ 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(); + let pubkey = "ed25519/6e9e6d5a75cf0c0e87ec1256b4dfed0ca3ba452912d213fcc70f8516583db9db" + .parse::() + .unwrap(); let mut term_set = BTreeSet::new(); term_set.insert(builder::int(0i64)); let c = check!( @@ -235,12 +227,9 @@ 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(); + let pubkey = "ed25519/6e9e6d5a75cf0c0e87ec1256b4dfed0ca3ba452912d213fcc70f8516583db9db" + .parse::() + .unwrap(); let mut term_set = BTreeSet::new(); term_set.insert(builder::int(0i64)); let p = policy!( @@ -256,7 +245,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!( @@ -295,13 +284,9 @@ fn json() { #[test] fn ecdsa() { - use biscuit_auth::PublicKey; - - let pubkey = PublicKey::from_bytes( - &hex::decode("0245dd01132962da3812911b746b080aed714873c1812e7cefacf13e3880712da0").unwrap(), - biscuit_auth::builder::Algorithm::Secp256r1, - ) - .unwrap(); + let pubkey = "secp256r1/0245dd01132962da3812911b746b080aed714873c1812e7cefacf13e3880712da0" + .parse::() + .unwrap(); let mut term_set = BTreeSet::new(); term_set.insert(builder::int(0i64)); let r = rule!( @@ -317,17 +302,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#" + // this should only work with a proper `PublicKeyData` value, and fail when trying to provide a string instead + let pubkey = "secp256r1/0245dd01132962da3812911b746b080aed714873c1812e7cefacf13e3880712da0" + .parse::() + .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) @@ -337,3 +324,32 @@ fn trusting() { "#, ); } + +#[test] +fn trusting_key_types() { + // scope parameters accept anything that converts into `PublicKeyData`: the + // serialized form itself, the default key type by value, and any key + // implementing `SerializePublicKey` by reference + let key = "secp256r1/0245dd01132962da3812911b746b080aed714873c1812e7cefacf13e3880712da0" + .parse::() + .unwrap(); + let expected = r#"data($x) <- nonce($x) trusting secp256r1/0245dd01132962da3812911b746b080aed714873c1812e7cefacf13e3880712da0"#; + + let owned = { + let pubkey = key.clone(); + rule!(r#"data($x) <- nonce($x) trusting {pubkey}"#) + }; + assert_eq!(owned.to_string(), expected); + + let by_ref = { + let pubkey = &key; + rule!(r#"data($x) <- nonce($x) trusting {pubkey}"#) + }; + assert_eq!(by_ref.to_string(), expected); + + let data = { + let pubkey = PublicKeyData::from(&key); + rule!(r#"data($x) <- nonce($x) trusting {pubkey}"#) + }; + assert_eq!(data.to_string(), expected); +} 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()); diff --git a/biscuit-parser/src/builder.rs b/biscuit-parser/src/builder.rs index 55faa04e..bb69f70c 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::PublicKeyData::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::PublicKeyData::from_bytes(::biscuit_auth::builder::Algorithm::Secp256r1, vec![#(#bytes),*]) )}, } } diff --git a/biscuit-quote/CHANGELOG.md b/biscuit-quote/CHANGELOG.md index 2f52c3e9..68ba2270 100644 --- a/biscuit-quote/CHANGELOG.md +++ b/biscuit-quote/CHANGELOG.md @@ -1,3 +1,9 @@ +# `0.4.0` + +- macro parameters are set through `set_lenient` and `set_scope_lenient` instead of the dedicated + `set_macro_param` and `set_macro_scope_param` methods, which are removed. This requires + `biscuit-auth` 7.0.0. + # `0.3.0` - [biscuit-datalog 3.3](https://www.biscuitsec.org/blog/biscuit-3-3/) support (#217 and #271) diff --git a/biscuit-quote/src/lib.rs b/biscuit-quote/src/lib.rs index af0dd74b..5f3b3d19 100644 --- a/biscuit-quote/src/lib.rs +++ b/biscuit-quote/src/lib.rs @@ -449,7 +449,7 @@ impl Item { }; self.middle.extend(quote! { - __biscuit_auth_item.set_macro_param(#name, #expr).unwrap(); + __biscuit_auth_item.set_lenient(#name, #expr).unwrap(); }); } @@ -463,7 +463,7 @@ impl Item { }; self.middle.extend(quote! { - __biscuit_auth_item.set_macro_scope_param(#name, #expr).unwrap(); + __biscuit_auth_item.set_scope_lenient(#name, #expr).unwrap(); }); } }