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..796ca51c 100644 --- a/biscuit-auth/CHANGELOG.md +++ b/biscuit-auth/CHANGELOG.md @@ -1,3 +1,7 @@ +# `7.0.0` + +- Abstract biscuits over the crypto implementation (#334) + # `6.0.0` - support for `pem` / `der` private and public keys (#212 and #265) 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..f8f6907f 100644 --- a/biscuit-auth/examples/testcases.rs +++ b/biscuit-auth/examples/testcases.rs @@ -12,7 +12,7 @@ use biscuit::error; use biscuit::format::convert; use biscuit::macros::*; use biscuit::{builder::*, builder_ext::*, Biscuit}; -use biscuit::{KeyPair, PrivateKey, PublicKey}; +use biscuit::{PrivateKey, PublicKey}; use biscuit_auth::builder; use biscuit_auth::builder::Algorithm; use biscuit_auth::datalog::ExternFunc; @@ -82,10 +82,10 @@ fn main() { fn run(target: String, root_key: Option, test: bool, json: bool) { let root = if let Some(key) = root_key { - KeyPair::from(&PrivateKey::from_bytes_hex(&key, Algorithm::Ed25519).unwrap()) + PrivateKey::from_bytes_hex(&key, Algorithm::Ed25519).unwrap() } else { let mut rng: StdRng = SeedableRng::seed_from_u64(1234); - KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng) + PrivateKey::new_with_rng(Algorithm::Ed25519, &mut rng) }; let mut results = Vec::new(); @@ -177,7 +177,7 @@ fn run(target: String, root_key: Option, test: bool, json: bool) { if json { let s = serde_json::to_string_pretty(&TestCases { - root_private_key: hex::encode(root.private().to_bytes()), + root_private_key: hex::encode(root.to_bytes()), root_public_key: hex::encode(root.public().to_bytes()), testcases: results, }) @@ -188,7 +188,7 @@ fn run(target: String, root_key: Option, test: bool, json: bool) { println!("# Biscuit samples and expected results\n"); println!( "root secret key: {}", - hex::encode(root.private().to_bytes()) + hex::encode(root.to_bytes()) ); println!("root public key: {}", hex::encode(root.public().to_bytes())); @@ -316,7 +316,7 @@ enum AuthorizerResult { Err(error::Token), } -fn validate_token(root: &KeyPair, data: &[u8], authorizer_code: &str) -> Validation { +fn validate_token(root: &PrivateKey, data: &[u8], authorizer_code: &str) -> Validation { validate_token_with_limits_and_external_functions( root, data, @@ -327,7 +327,7 @@ fn validate_token(root: &KeyPair, data: &[u8], authorizer_code: &str) -> Validat } fn validate_token_with_limits_and_external_functions( - root: &KeyPair, + root: &PrivateKey, data: &[u8], authorizer_code: &str, run_limits: RunLimits, @@ -513,7 +513,7 @@ fn print_diff(actual: &str, expected: &str) { fn write_or_load_testcase( target: &str, filename: &str, - root: &KeyPair, + root: &PrivateKey, token: &Biscuit, test: bool, ) -> Vec { @@ -531,7 +531,7 @@ fn write_or_load_testcase( } } -fn basic_token(target: &str, root: &KeyPair, test: bool) -> TestResult { +fn basic_token(target: &str, root: &PrivateKey, test: bool) -> TestResult { let mut rng: StdRng = SeedableRng::seed_from_u64(1234); let title = "basic token".to_string(); let filename = "test001_basic".to_string(); @@ -546,9 +546,9 @@ fn basic_token(target: &str, root: &KeyPair, test: bool) -> TestResult { .build_with_rng(root, SymbolTable::default(), &mut rng) .unwrap(); - let keypair2 = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng); + let keypair2 = PrivateKey::new_with_rng(Algorithm::Ed25519, &mut rng); let biscuit2 = biscuit1 - .append_with_keypair( + .append_with_key( &keypair2, block!( r#" @@ -583,13 +583,13 @@ fn basic_token(target: &str, root: &KeyPair, test: bool) -> TestResult { } } -fn different_root_key(target: &str, root: &KeyPair, test: bool) -> TestResult { +fn different_root_key(target: &str, root: &PrivateKey, test: bool) -> TestResult { // using a different seed otherwise it would generate the same root key let mut rng: StdRng = SeedableRng::seed_from_u64(5678); let title = "different root key".to_string(); let filename = "test002_different_root_key".to_string(); - let root2 = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng); + let root2 = PrivateKey::new_with_rng(Algorithm::Ed25519, &mut rng); let biscuit1 = biscuit!( r#" @@ -599,9 +599,9 @@ fn different_root_key(target: &str, root: &KeyPair, test: bool) -> TestResult { .build_with_rng(&root2, SymbolTable::default(), &mut rng) .unwrap(); - let keypair2 = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng); + let keypair2 = PrivateKey::new_with_rng(Algorithm::Ed25519, &mut rng); let biscuit2 = biscuit1 - .append_with_keypair( + .append_with_key( &keypair2, block!( r#" @@ -636,7 +636,7 @@ fn different_root_key(target: &str, root: &KeyPair, test: bool) -> TestResult { } } -fn invalid_signature_format(target: &str, root: &KeyPair, test: bool) -> TestResult { +fn invalid_signature_format(target: &str, root: &PrivateKey, test: bool) -> TestResult { let mut rng: StdRng = SeedableRng::seed_from_u64(1234); let title = "invalid signature format".to_string(); let filename = "test003_invalid_signature_format".to_string(); @@ -651,9 +651,9 @@ fn invalid_signature_format(target: &str, root: &KeyPair, test: bool) -> TestRes .build_with_rng(root, SymbolTable::default(), &mut rng) .unwrap(); - let keypair2 = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng); + let keypair2 = PrivateKey::new_with_rng(Algorithm::Ed25519, &mut rng); let biscuit2 = biscuit1 - .append_with_keypair( + .append_with_key( &keypair2, block!(r#"check if resource($0), operation("read"), right($0, "read")"#), ) @@ -686,7 +686,7 @@ fn invalid_signature_format(target: &str, root: &KeyPair, test: bool) -> TestRes } } -fn random_block(target: &str, root: &KeyPair, test: bool) -> TestResult { +fn random_block(target: &str, root: &PrivateKey, test: bool) -> TestResult { let mut rng: StdRng = SeedableRng::seed_from_u64(1234); let title = "random block".to_string(); let filename = "test004_random_block".to_string(); @@ -701,9 +701,9 @@ fn random_block(target: &str, root: &KeyPair, test: bool) -> TestResult { .build_with_rng(root, SymbolTable::default(), &mut rng) .unwrap(); - let keypair2 = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng); + let keypair2 = PrivateKey::new_with_rng(Algorithm::Ed25519, &mut rng); let biscuit2 = biscuit1 - .append_with_keypair( + .append_with_key( &keypair2, block!(r#"check if resource($0), operation("read"), right($0, "read")"#), ) @@ -739,7 +739,7 @@ fn random_block(target: &str, root: &KeyPair, test: bool) -> TestResult { } } -fn invalid_signature(target: &str, root: &KeyPair, test: bool) -> TestResult { +fn invalid_signature(target: &str, root: &PrivateKey, test: bool) -> TestResult { let mut rng: StdRng = SeedableRng::seed_from_u64(1234); let title = "invalid signature".to_string(); let filename = "test005_invalid_signature".to_string(); @@ -754,9 +754,9 @@ fn invalid_signature(target: &str, root: &KeyPair, test: bool) -> TestResult { .build_with_rng(root, SymbolTable::default(), &mut rng) .unwrap(); - let keypair2 = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng); + let keypair2 = PrivateKey::new_with_rng(Algorithm::Ed25519, &mut rng); let biscuit2 = biscuit1 - .append_with_keypair( + .append_with_key( &keypair2, block!(r#"check if resource($0), operation("read"), right($0, "read")"#), ) @@ -791,7 +791,7 @@ fn invalid_signature(target: &str, root: &KeyPair, test: bool) -> TestResult { } } -fn reordered_blocks(target: &str, root: &KeyPair, test: bool) -> TestResult { +fn reordered_blocks(target: &str, root: &PrivateKey, test: bool) -> TestResult { let mut rng: StdRng = SeedableRng::seed_from_u64(1234); let title = "reordered blocks".to_string(); let filename = "test006_reordered_blocks".to_string(); @@ -806,17 +806,17 @@ fn reordered_blocks(target: &str, root: &KeyPair, test: bool) -> TestResult { .build_with_rng(root, SymbolTable::default(), &mut rng) .unwrap(); - let keypair2 = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng); + let keypair2 = PrivateKey::new_with_rng(Algorithm::Ed25519, &mut rng); let biscuit2 = biscuit1 - .append_with_keypair( + .append_with_key( &keypair2, block!(r#"check if resource($0), operation("read"), right($0, "read")"#), ) .unwrap(); - let keypair3 = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng); + let keypair3 = PrivateKey::new_with_rng(Algorithm::Ed25519, &mut rng); let biscuit3 = biscuit2 - .append_with_keypair(&keypair3, block!(r#"check if resource("file1")"#)) + .append_with_key(&keypair3, block!(r#"check if resource("file1")"#)) .unwrap(); let token = print_blocks(&biscuit3); @@ -848,7 +848,7 @@ fn reordered_blocks(target: &str, root: &KeyPair, test: bool) -> TestResult { } } -fn scoped_rules(target: &str, root: &KeyPair, test: bool) -> TestResult { +fn scoped_rules(target: &str, root: &PrivateKey, test: bool) -> TestResult { let mut rng: StdRng = SeedableRng::seed_from_u64(1234); let title = "scoped rules".to_string(); let filename = "test007_scoped_rules".to_string(); @@ -862,9 +862,9 @@ fn scoped_rules(target: &str, root: &KeyPair, test: bool) -> TestResult { .build_with_rng(root, SymbolTable::default(), &mut rng) .unwrap(); - let keypair2 = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng); + let keypair2 = PrivateKey::new_with_rng(Algorithm::Ed25519, &mut rng); let biscuit2 = biscuit1 - .append_with_keypair( + .append_with_key( &keypair2, block!( r#" @@ -879,8 +879,8 @@ fn scoped_rules(target: &str, root: &KeyPair, test: bool) -> TestResult { .fact(r#"owner("alice", "file2")"#) .unwrap(); - let keypair3 = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng); - let biscuit3 = biscuit2.append_with_keypair(&keypair3, block3).unwrap(); + let keypair3 = PrivateKey::new_with_rng(Algorithm::Ed25519, &mut rng); + let biscuit3 = biscuit2.append_with_key(&keypair3, block3).unwrap(); let token = print_blocks(&biscuit3); let data = write_or_load_testcase(target, &filename, root, &biscuit3, test); @@ -907,7 +907,7 @@ fn scoped_rules(target: &str, root: &KeyPair, test: bool) -> TestResult { } } -fn scoped_checks(target: &str, root: &KeyPair, test: bool) -> TestResult { +fn scoped_checks(target: &str, root: &PrivateKey, test: bool) -> TestResult { let mut rng: StdRng = SeedableRng::seed_from_u64(1234); let title = "scoped checks".to_string(); let filename = "test008_scoped_checks".to_string(); @@ -920,17 +920,17 @@ fn scoped_checks(target: &str, root: &KeyPair, test: bool) -> TestResult { .build_with_rng(root, SymbolTable::default(), &mut rng) .unwrap(); - let keypair2 = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng); + let keypair2 = PrivateKey::new_with_rng(Algorithm::Ed25519, &mut rng); let biscuit2 = biscuit1 - .append_with_keypair( + .append_with_key( &keypair2, block!(r#"check if resource($0), operation("read"), right($0, "read")"#), ) .unwrap(); - let keypair3 = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng); + let keypair3 = PrivateKey::new_with_rng(Algorithm::Ed25519, &mut rng); let biscuit3 = biscuit2 - .append_with_keypair(&keypair3, block!(r#"right("file2", "read")"#)) + .append_with_key(&keypair3, block!(r#"right("file2", "read")"#)) .unwrap(); let token = print_blocks(&biscuit3); @@ -958,7 +958,7 @@ fn scoped_checks(target: &str, root: &KeyPair, test: bool) -> TestResult { } } -fn expired_token(target: &str, root: &KeyPair, test: bool) -> TestResult { +fn expired_token(target: &str, root: &PrivateKey, test: bool) -> TestResult { let mut rng: StdRng = SeedableRng::seed_from_u64(1234); let title = "expired token".to_string(); let filename = "test009_expired_token".to_string(); @@ -976,8 +976,8 @@ fn expired_token(target: &str, root: &KeyPair, test: bool) -> TestResult { .unwrap(), ); - let keypair2 = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng); - let biscuit2 = biscuit1.append_with_keypair(&keypair2, block2).unwrap(); + let keypair2 = PrivateKey::new_with_rng(Algorithm::Ed25519, &mut rng); + let biscuit2 = biscuit1.append_with_key(&keypair2, block2).unwrap(); let token = print_blocks(&biscuit2); let data = write_or_load_testcase(target, &filename, root, &biscuit2, test); @@ -1005,7 +1005,7 @@ fn expired_token(target: &str, root: &KeyPair, test: bool) -> TestResult { } } -fn authorizer_scope(target: &str, root: &KeyPair, test: bool) -> TestResult { +fn authorizer_scope(target: &str, root: &PrivateKey, test: bool) -> TestResult { let mut rng: StdRng = SeedableRng::seed_from_u64(1234); let title = "authorizer scope".to_string(); let filename = "test010_authorizer_scope".to_string(); @@ -1018,9 +1018,9 @@ fn authorizer_scope(target: &str, root: &KeyPair, test: bool) -> TestResult { .build_with_rng(root, SymbolTable::default(), &mut rng) .unwrap(); - let keypair2 = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng); + let keypair2 = PrivateKey::new_with_rng(Algorithm::Ed25519, &mut rng); let biscuit2 = biscuit1 - .append_with_keypair(&keypair2, block!(r#"right("file2", "read")"#)) + .append_with_key(&keypair2, block!(r#"right("file2", "read")"#)) .unwrap(); let token = print_blocks(&biscuit2); @@ -1049,7 +1049,7 @@ fn authorizer_scope(target: &str, root: &KeyPair, test: bool) -> TestResult { } } -fn authorizer_authority_checks(target: &str, root: &KeyPair, test: bool) -> TestResult { +fn authorizer_authority_checks(target: &str, root: &PrivateKey, test: bool) -> TestResult { let mut rng: StdRng = SeedableRng::seed_from_u64(1234); let title = "authorizer authority checks".to_string(); let filename = "test011_authorizer_authority_caveats".to_string(); @@ -1088,7 +1088,7 @@ fn authorizer_authority_checks(target: &str, root: &KeyPair, test: bool) -> Test } } -fn authority_checks(target: &str, root: &KeyPair, test: bool) -> TestResult { +fn authority_checks(target: &str, root: &PrivateKey, test: bool) -> TestResult { let mut rng: StdRng = SeedableRng::seed_from_u64(1234); let title = "authority checks".to_string(); let filename = "test012_authority_caveats".to_string(); @@ -1135,7 +1135,7 @@ fn authority_checks(target: &str, root: &KeyPair, test: bool) -> TestResult { } } -fn block_rules(target: &str, root: &KeyPair, test: bool) -> TestResult { +fn block_rules(target: &str, root: &PrivateKey, test: bool) -> TestResult { let mut rng: StdRng = SeedableRng::seed_from_u64(1234); let title = "block rules".to_string(); let filename = "test013_block_rules".to_string(); @@ -1149,8 +1149,8 @@ fn block_rules(target: &str, root: &KeyPair, test: bool) -> TestResult { .build_with_rng(root, SymbolTable::default(), &mut rng) .unwrap(); - let keypair2 = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng); - let biscuit2 = biscuit1.append_with_keypair(&keypair2, block!(r#" + let keypair2 = PrivateKey::new_with_rng(Algorithm::Ed25519, &mut rng); + let biscuit2 = biscuit1.append_with_key(&keypair2, block!(r#" // generate valid_date("file1") if before Thursday, December 31, 2030 12:59:59 PM UTC valid_date("file1") <- time($0), resource("file1"), $0 <= 2030-12-31T12:59:59Z; @@ -1199,7 +1199,7 @@ fn block_rules(target: &str, root: &KeyPair, test: bool) -> TestResult { } } -fn regex_constraint(target: &str, root: &KeyPair, test: bool) -> TestResult { +fn regex_constraint(target: &str, root: &PrivateKey, test: bool) -> TestResult { let mut rng: StdRng = SeedableRng::seed_from_u64(1234); let title = "regex_constraint".to_string(); let filename = "test014_regex_constraint".to_string(); @@ -1229,7 +1229,7 @@ fn regex_constraint(target: &str, root: &KeyPair, test: bool) -> TestResult { } } -fn multi_queries_checks(target: &str, root: &KeyPair, test: bool) -> TestResult { +fn multi_queries_checks(target: &str, root: &PrivateKey, test: bool) -> TestResult { let mut rng: StdRng = SeedableRng::seed_from_u64(1234); let title = "multi queries checks".to_string(); let filename = "test015_multi_queries_caveats".to_string(); @@ -1258,7 +1258,7 @@ fn multi_queries_checks(target: &str, root: &KeyPair, test: bool) -> TestResult } } -fn check_head_name(target: &str, root: &KeyPair, test: bool) -> TestResult { +fn check_head_name(target: &str, root: &PrivateKey, test: bool) -> TestResult { let mut rng: StdRng = SeedableRng::seed_from_u64(1234); let title = "check head name should be independent from fact names".to_string(); let filename = "test016_caveat_head_name".to_string(); @@ -1267,9 +1267,9 @@ fn check_head_name(target: &str, root: &KeyPair, test: bool) -> TestResult { .build_with_rng(root, SymbolTable::default(), &mut rng) .unwrap(); - let keypair2 = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng); + let keypair2 = PrivateKey::new_with_rng(Algorithm::Ed25519, &mut rng); let biscuit2 = biscuit1 - .append_with_keypair(&keypair2, block!(r#"query("test")"#)) + .append_with_key(&keypair2, block!(r#"query("test")"#)) .unwrap(); let token = print_blocks(&biscuit2); @@ -1288,7 +1288,7 @@ fn check_head_name(target: &str, root: &KeyPair, test: bool) -> TestResult { } } -fn expressions(target: &str, root: &KeyPair, test: bool) -> TestResult { +fn expressions(target: &str, root: &PrivateKey, test: bool) -> TestResult { let mut rng: StdRng = SeedableRng::seed_from_u64(1234); let title = "test expression syntax and all available operations".to_string(); let filename = "test017_expressions".to_string(); @@ -1389,7 +1389,7 @@ fn expressions(target: &str, root: &KeyPair, test: bool) -> TestResult { } } -fn unbound_variables_in_rule(target: &str, root: &KeyPair, test: bool) -> TestResult { +fn unbound_variables_in_rule(target: &str, root: &PrivateKey, test: bool) -> TestResult { let mut rng: StdRng = SeedableRng::seed_from_u64(1234); let title = "invalid block rule with unbound_variables".to_string(); let filename = "test018_unbound_variables_in_rule".to_string(); @@ -1407,8 +1407,8 @@ fn unbound_variables_in_rule(target: &str, root: &KeyPair, test: bool) -> TestRe )) .unwrap(); - let keypair2 = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng); - let biscuit2 = biscuit1.append_with_keypair(&keypair2, block2).unwrap(); + let keypair2 = PrivateKey::new_with_rng(Algorithm::Ed25519, &mut rng); + let biscuit2 = biscuit1.append_with_key(&keypair2, block2).unwrap(); let token = print_blocks(&biscuit2); let data = write_or_load_testcase(target, &filename, root, &biscuit2, test); @@ -1426,7 +1426,7 @@ fn unbound_variables_in_rule(target: &str, root: &KeyPair, test: bool) -> TestRe } } -fn generating_ambient_from_variables(target: &str, root: &KeyPair, test: bool) -> TestResult { +fn generating_ambient_from_variables(target: &str, root: &PrivateKey, test: bool) -> TestResult { let mut rng: StdRng = SeedableRng::seed_from_u64(1234); let title = "invalid block rule generating an #authority or #ambient symbol with a variable" .to_string(); @@ -1436,9 +1436,9 @@ fn generating_ambient_from_variables(target: &str, root: &KeyPair, test: bool) - .build_with_rng(root, SymbolTable::default(), &mut rng) .unwrap(); - let keypair2 = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng); + let keypair2 = PrivateKey::new_with_rng(Algorithm::Ed25519, &mut rng); let biscuit2 = biscuit1 - .append_with_keypair(&keypair2, block!(r#"operation("read") <- operation($any)"#)) + .append_with_key(&keypair2, block!(r#"operation("read") <- operation($any)"#)) .unwrap(); let token = print_blocks(&biscuit2); @@ -1457,7 +1457,7 @@ fn generating_ambient_from_variables(target: &str, root: &KeyPair, test: bool) - } } -fn sealed_token(target: &str, root: &KeyPair, test: bool) -> TestResult { +fn sealed_token(target: &str, root: &PrivateKey, test: bool) -> TestResult { let mut rng: StdRng = SeedableRng::seed_from_u64(1234); let title = "sealed token".to_string(); let filename = "test020_sealed".to_string(); @@ -1472,9 +1472,9 @@ fn sealed_token(target: &str, root: &KeyPair, test: bool) -> TestResult { .build_with_rng(root, SymbolTable::default(), &mut rng) .unwrap(); - let keypair2 = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng); + let keypair2 = PrivateKey::new_with_rng(Algorithm::Ed25519, &mut rng); let biscuit2 = biscuit1 - .append_with_keypair( + .append_with_key( &keypair2, block!(r#"check if resource($0), operation("read"), right($0, "read")"#), ) @@ -1514,7 +1514,7 @@ fn sealed_token(target: &str, root: &KeyPair, test: bool) -> TestResult { } } -fn parsing(target: &str, root: &KeyPair, test: bool) -> TestResult { +fn parsing(target: &str, root: &PrivateKey, test: bool) -> TestResult { let mut rng: StdRng = SeedableRng::seed_from_u64(1234); let title = "parsing".to_string(); let filename = "test021_parsing".to_string(); @@ -1544,7 +1544,7 @@ fn parsing(target: &str, root: &KeyPair, test: bool) -> TestResult { } } -fn default_symbols(target: &str, root: &KeyPair, test: bool) -> TestResult { +fn default_symbols(target: &str, root: &PrivateKey, test: bool) -> TestResult { let mut rng: StdRng = SeedableRng::seed_from_u64(1234); let title = "default_symbols".to_string(); let filename = "test022_default_symbols".to_string(); @@ -1587,7 +1587,7 @@ fn default_symbols(target: &str, root: &KeyPair, test: bool) -> TestResult { } } -fn execution_scope(target: &str, root: &KeyPair, test: bool) -> TestResult { +fn execution_scope(target: &str, root: &PrivateKey, test: bool) -> TestResult { let mut rng: StdRng = SeedableRng::seed_from_u64(1234); let title = "execution scope".to_string(); let filename = "test023_execution_scope".to_string(); @@ -1596,14 +1596,14 @@ fn execution_scope(target: &str, root: &KeyPair, test: bool) -> TestResult { .build_with_rng(root, SymbolTable::default(), &mut rng) .unwrap(); - let keypair2 = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng); + let keypair2 = PrivateKey::new_with_rng(Algorithm::Ed25519, &mut rng); let biscuit2 = biscuit1 - .append_with_keypair(&keypair2, block!("block1_fact(1)")) + .append_with_key(&keypair2, block!("block1_fact(1)")) .unwrap(); - let keypair3 = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng); + let keypair3 = PrivateKey::new_with_rng(Algorithm::Ed25519, &mut rng); let biscuit3 = biscuit2 - .append_with_keypair( + .append_with_key( &keypair3, block!( r#" @@ -1631,14 +1631,14 @@ fn execution_scope(target: &str, root: &KeyPair, test: bool) -> TestResult { } } -fn third_party(target: &str, root: &KeyPair, test: bool) -> TestResult { +fn third_party(target: &str, root: &PrivateKey, test: bool) -> TestResult { let mut rng: StdRng = SeedableRng::seed_from_u64(1234); let title = "third party".to_string(); let filename = "test024_third_party".to_string(); // keep this to conserve the same RNG state - let _ = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng); - let external = KeyPair::from( + let _ = PrivateKey::new_with_rng(Algorithm::Ed25519, &mut rng); + let external = PrivateKey::from( &PrivateKey::from_bytes_hex( "12aca40167fbdd1a11037e9fd440e3d510d9d9dea70a6646aa4aaf84d718d75a", Algorithm::Ed25519, @@ -1660,7 +1660,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 +1669,9 @@ fn third_party(target: &str, root: &KeyPair, test: bool) -> TestResult { ), ) .unwrap(); - let keypair2 = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng); + let keypair2 = PrivateKey::new_with_rng(Algorithm::Ed25519, &mut rng); let biscuit2 = biscuit1 - .append_third_party_with_keypair(external.public(), res, keypair2) + .append_third_party_with_key(external.public(), res, keypair2) .unwrap(); let token = print_blocks(&biscuit2); @@ -1692,7 +1692,7 @@ fn third_party(target: &str, root: &KeyPair, test: bool) -> TestResult { } } -fn check_all(target: &str, root: &KeyPair, test: bool) -> TestResult { +fn check_all(target: &str, root: &PrivateKey, test: bool) -> TestResult { let mut rng: StdRng = SeedableRng::seed_from_u64(1234); let title = "block rules".to_string(); let filename = "test025_check_all".to_string(); @@ -1756,31 +1756,31 @@ fn check_all(target: &str, root: &KeyPair, test: bool) -> TestResult { } } -fn public_keys_interning(target: &str, root: &KeyPair, test: bool) -> TestResult { +fn public_keys_interning(target: &str, root: &PrivateKey, test: bool) -> TestResult { let mut rng: StdRng = SeedableRng::seed_from_u64(1234); let title = "public keys interning".to_string(); let filename = "test026_public_keys_interning".to_string(); // keep this to conserve the same RNG state - let _ = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng); - let _ = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng); - let _ = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng); + let _ = PrivateKey::new_with_rng(Algorithm::Ed25519, &mut rng); + let _ = PrivateKey::new_with_rng(Algorithm::Ed25519, &mut rng); + let _ = PrivateKey::new_with_rng(Algorithm::Ed25519, &mut rng); - let external1 = KeyPair::from( + let external1 = PrivateKey::from( &PrivateKey::from_bytes_hex( "12aca40167fbdd1a11037e9fd440e3d510d9d9dea70a6646aa4aaf84d718d75a", Algorithm::Ed25519, ) .unwrap(), ); - let external2 = KeyPair::from( + let external2 = PrivateKey::from( &PrivateKey::from_bytes_hex( "018e3f6864a1c9ffc2e67939a835d41c808b0084b3d7babf9364f674db19eeb3", Algorithm::Ed25519, ) .unwrap(), ); - let external3 = KeyPair::from( + let external3 = PrivateKey::from( &PrivateKey::from_bytes_hex( "88c637e4844fc3f52290889dc961cb15d809c994b5ef71990d6a2f989bd2f02c", Algorithm::Ed25519, @@ -1802,7 +1802,7 @@ fn public_keys_interning(target: &str, root: &KeyPair, test: bool) -> TestResult let res1 = req1 .create_block( - &external1.private(), + &external1, block!( r#" query(1); @@ -1817,17 +1817,17 @@ fn public_keys_interning(target: &str, root: &KeyPair, test: bool) -> TestResult .unwrap(); let biscuit2 = biscuit1 - .append_third_party_with_keypair( + .append_third_party_with_key( external1.public(), res1, - KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng), + PrivateKey::new_with_rng(Algorithm::Ed25519, &mut rng), ) .unwrap(); let req2 = biscuit2.third_party_request().unwrap(); let res2 = req2 .create_block( - &external2.private(), + &external2, block!( r#" query(2); @@ -1841,17 +1841,17 @@ fn public_keys_interning(target: &str, root: &KeyPair, test: bool) -> TestResult .unwrap(); let biscuit3 = biscuit2 - .append_third_party_with_keypair( + .append_third_party_with_key( external2.public(), res2, - KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng), + PrivateKey::new_with_rng(Algorithm::Ed25519, &mut rng), ) .unwrap(); let req3 = biscuit3.third_party_request().unwrap(); let res3 = req3 .create_block( - &external2.private(), + &external2, block!( r#" query(3); @@ -1865,16 +1865,16 @@ fn public_keys_interning(target: &str, root: &KeyPair, test: bool) -> TestResult .unwrap(); let biscuit4 = biscuit3 - .append_third_party_with_keypair( + .append_third_party_with_key( external2.public(), res3, - KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng), + PrivateKey::new_with_rng(Algorithm::Ed25519, &mut rng), ) .unwrap(); let biscuit5 = biscuit4 - .append_with_keypair( - &KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng), + .append_with_key( + &PrivateKey::new_with_rng(Algorithm::Ed25519, &mut rng), block!( r#" query(4); @@ -1919,7 +1919,7 @@ fn public_keys_interning(target: &str, root: &KeyPair, test: bool) -> TestResult } } -fn integer_wraparound(target: &str, root: &KeyPair, test: bool) -> TestResult { +fn integer_wraparound(target: &str, root: &PrivateKey, test: bool) -> TestResult { let mut rng: StdRng = SeedableRng::seed_from_u64(1234); let title = "integer wraparound".to_string(); let filename = "test027_integer_wraparound".to_string(); @@ -1952,7 +1952,7 @@ fn integer_wraparound(target: &str, root: &KeyPair, test: bool) -> TestResult { } } -fn expressions_v4(target: &str, root: &KeyPair, test: bool) -> TestResult { +fn expressions_v4(target: &str, root: &PrivateKey, test: bool) -> TestResult { let mut rng: StdRng = SeedableRng::seed_from_u64(1234); let title = "test expression syntax and all available operations (v4 blocks)".to_string(); let filename = "test028_expressions_v4".to_string(); @@ -1995,7 +1995,7 @@ fn expressions_v4(target: &str, root: &KeyPair, test: bool) -> TestResult { } } -fn reject_if(target: &str, root: &KeyPair, test: bool) -> TestResult { +fn reject_if(target: &str, root: &PrivateKey, test: bool) -> TestResult { let mut rng: StdRng = SeedableRng::seed_from_u64(1234); let title = "test reject if".to_string(); let filename = "test029_reject_if".to_string(); @@ -2025,7 +2025,7 @@ fn reject_if(target: &str, root: &KeyPair, test: bool) -> TestResult { } } -fn null(target: &str, root: &KeyPair, test: bool) -> TestResult { +fn null(target: &str, root: &PrivateKey, test: bool) -> TestResult { let mut rng: StdRng = SeedableRng::seed_from_u64(1234); let title = "test null".to_string(); let filename = "test030_null".to_string(); @@ -2068,7 +2068,7 @@ fn null(target: &str, root: &KeyPair, test: bool) -> TestResult { } } -fn heterogeneous_equal(target: &str, root: &KeyPair, test: bool) -> TestResult { +fn heterogeneous_equal(target: &str, root: &PrivateKey, test: bool) -> TestResult { let mut rng: StdRng = SeedableRng::seed_from_u64(1234); let title = "test heterogeneous equal".to_string(); let filename = "test031_heterogeneous_equal".to_string(); @@ -2126,7 +2126,7 @@ fn heterogeneous_equal(target: &str, root: &KeyPair, test: bool) -> TestResult { } } -fn closures(target: &str, root: &KeyPair, test: bool) -> TestResult { +fn closures(target: &str, root: &PrivateKey, test: bool) -> TestResult { let mut rng: StdRng = SeedableRng::seed_from_u64(1234); let title = "test laziness and closures".to_string(); let filename = "test032_laziness_closures".to_string(); @@ -2184,7 +2184,7 @@ fn closures(target: &str, root: &KeyPair, test: bool) -> TestResult { } } -fn type_of(target: &str, root: &KeyPair, test: bool) -> TestResult { +fn type_of(target: &str, root: &PrivateKey, test: bool) -> TestResult { let mut rng: StdRng = SeedableRng::seed_from_u64(1234); let title = "test .type()".to_string(); let filename = "test033_typeof".to_string(); @@ -2239,7 +2239,7 @@ fn type_of(target: &str, root: &KeyPair, test: bool) -> TestResult { } } -fn array_map(target: &str, root: &KeyPair, test: bool) -> TestResult { +fn array_map(target: &str, root: &PrivateKey, test: bool) -> TestResult { let mut rng: StdRng = SeedableRng::seed_from_u64(1234); let title = "test array and map operations".to_string(); let filename = "test034_array_map".to_string(); @@ -2298,7 +2298,7 @@ fn array_map(target: &str, root: &KeyPair, test: bool) -> TestResult { } } -fn ffi(target: &str, root: &KeyPair, test: bool) -> TestResult { +fn ffi(target: &str, root: &PrivateKey, test: bool) -> TestResult { let mut rng: StdRng = SeedableRng::seed_from_u64(1234); let title = "test ffi calls (v6 blocks)".to_string(); let filename = "test035_ffi".to_string(); @@ -2345,12 +2345,12 @@ fn ffi(target: &str, root: &KeyPair, test: bool) -> TestResult { } } -fn secp256r1(target: &str, root: &KeyPair, test: bool) -> TestResult { +fn secp256r1(target: &str, root: &PrivateKey, test: bool) -> TestResult { let mut rng: StdRng = SeedableRng::seed_from_u64(1234); let title = "ECDSA secp256r1 signatures".to_string(); let filename = "test036_secp256r1".to_string(); - let keypair2 = KeyPair::new_with_rng(Algorithm::Secp256r1, &mut rng); + let keypair2 = PrivateKey::new_with_rng(Algorithm::Secp256r1, &mut rng); let biscuit1 = biscuit!( r#" right("file1", "read"); @@ -2361,9 +2361,9 @@ fn secp256r1(target: &str, root: &KeyPair, test: bool) -> TestResult { .build_with_key_pair(root, SymbolTable::default(), &keypair2) .unwrap(); - let keypair3 = KeyPair::new_with_rng(Algorithm::Secp256r1, &mut rng); + let keypair3 = PrivateKey::new_with_rng(Algorithm::Secp256r1, &mut rng); let biscuit2 = biscuit1 - .append_with_keypair( + .append_with_key( &keypair3, block!( r#" @@ -2399,13 +2399,13 @@ fn secp256r1(target: &str, root: &KeyPair, test: bool) -> TestResult { } } -fn secp256r1_third_party(target: &str, root: &KeyPair, test: bool) -> TestResult { +fn secp256r1_third_party(target: &str, root: &PrivateKey, test: bool) -> TestResult { let mut rng: StdRng = SeedableRng::seed_from_u64(1234); let title = "ECDSA secp256r1 signature on third-party block".to_string(); let filename = "test037_secp256r1_third_party".to_string(); - let external_keypair = KeyPair::new_with_rng(Algorithm::Secp256r1, &mut rng); - let keypair2 = KeyPair::new_with_rng(Algorithm::Secp256r1, &mut rng); + let external_keypair = PrivateKey::new_with_rng(Algorithm::Secp256r1, &mut rng); + let keypair2 = PrivateKey::new_with_rng(Algorithm::Secp256r1, &mut rng); let biscuit1 = biscuit!( r#" right("file1", "read"); @@ -2421,16 +2421,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 +2459,7 @@ fn secp256r1_third_party(target: &str, root: &KeyPair, test: bool) -> TestResult } } -fn try_op(target: &str, root: &KeyPair, test: bool) -> TestResult { +fn try_op(target: &str, root: &PrivateKey, test: bool) -> TestResult { let mut rng: StdRng = SeedableRng::seed_from_u64(1234); let title = "test try operation".to_string(); let filename = "test038_try_op".to_string(); diff --git a/biscuit-auth/examples/third_party.rs b/biscuit-auth/examples/third_party.rs index c572d214..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..bf865eaa 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: &IK, + next_key: &NK, message: &[u8], version: u32, ) -> Result { let to_sign = match version { - 0 => generate_authority_block_signature_payload_v0(message, &next_key.public()), - 1 => generate_authority_block_signature_payload_v1(message, &next_key.public(), version), + 0 => generate_authority_block_signature_payload_v0(message, next_key), + 1 => generate_authority_block_signature_payload_v1(message, next_key, version), _ => { return Err(error::Format::DeserializationError(format!( "unsupported block version: {version}" @@ -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: &IK, ) -> 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..f06f2d41 100644 --- a/biscuit-auth/src/datalog/symbol.rs +++ b/biscuit-auth/src/datalog/symbol.rs @@ -6,13 +6,14 @@ use std::collections::HashSet; use time::{format_description::well_known::Rfc3339, OffsetDateTime}; -pub type SymbolIndex = u64; -use crate::crypto::PublicKey; use crate::token::default_symbol_table; +use crate::token::public_keys::PublicKey; use crate::{error, token::public_keys::PublicKeys}; use super::{Check, Fact, Predicate, Rule, Term, World}; +pub type SymbolIndex = u64; + #[derive(Clone, Debug, PartialEq, Eq)] pub struct SymbolTable { symbols: Vec, @@ -79,7 +80,7 @@ impl SymbolTable { public_keys: Vec, ) -> Result { let mut table = Self::from(symbols)?; - table.public_keys = PublicKeys::from(public_keys); + table.public_keys = PublicKeys::from_keys(public_keys); Ok(table) } @@ -291,7 +292,7 @@ impl SymbolTable { crate::token::Scope::Previous => "previous".to_string(), crate::token::Scope::PublicKey(key_id) => { match self.public_keys.get_key(*key_id) { - Some(key) => key.print(), + Some(key) => key.to_string(), None => "".to_string(), } } diff --git a/biscuit-auth/src/format/convert.rs b/biscuit-auth/src/format/convert.rs index d1932601..acd22f2a 100644 --- a/biscuit-auth/src/format/convert.rs +++ b/biscuit-auth/src/format/convert.rs @@ -6,7 +6,7 @@ use super::schema; use crate::builder::Convert; -use crate::crypto::PublicKey; +use crate::crypto::SerializePublicKey; use crate::datalog::*; use crate::error; use crate::format::schema::Empty; @@ -45,9 +45,9 @@ pub fn token_block_to_proto_block(input: &Block) -> schema::Block { } } -pub fn proto_block_to_token_block( +pub fn proto_block_to_token_block( input: &schema::Block, - external_key: Option, + external_key: Option<&EK>, ) -> Result { let version = input.version.unwrap_or(0); if !(MIN_SCHEMA_VERSION..=MAX_SCHEMA_VERSION).contains(&version) { @@ -104,7 +104,7 @@ pub fn proto_block_to_token_block( let mut public_keys = PublicKeys::new(); for pk in &input.public_keys { - public_keys.insert_fallible(&PublicKey::from_proto(pk)?)?; + public_keys.insert_proto_fallible(pk)?; } let symbols = SymbolTable::from_symbols_and_public_keys(input.symbols.clone(), public_keys.keys.clone())?; @@ -120,7 +120,7 @@ pub fn proto_block_to_token_block( checks, context, version, - external_key, + external_key: external_key.map(crate::token::public_keys::PublicKey::from), public_keys, scopes, }) @@ -142,7 +142,7 @@ pub fn token_block_to_proto_snapshot_block(input: &Block) -> schema::SnapshotBlo .iter() .map(token_scope_to_proto_scope) .collect(), - external_key: input.external_key.map(|key| key.to_proto()), + external_key: input.external_key.as_ref().map(|key| key.to_proto()), } } @@ -191,7 +191,9 @@ pub fn proto_snapshot_block_to_token_block( let external_key = match &input.external_key { None => None, - Some(key) => Some(PublicKey::from_proto(key)?), + Some(key) => Some(crate::token::public_keys::PublicKey::from( + &crate::crypto::PublicKey::from_proto(key)?, + )), }; Ok(Block { @@ -852,3 +854,15 @@ pub fn proto_scope_to_token_scope(input: &schema::Scope) -> Result(key: &K) -> schema::PublicKey { + schema::PublicKey { + algorithm: schema::public_key::Algorithm::from(key.algorithm()) as i32, + key: key.to_bytes(), + } +} + +pub fn public_key_from_proto(key: &schema::PublicKey) -> Result { + let algorithm = crate::Algorithm::from(key.algorithm()); + K::from_bytes_and_algorithm(algorithm, &key.key) +} diff --git a/biscuit-auth/src/format/mod.rs b/biscuit-auth/src/format/mod.rs index 4ff3c70a..565f1670 100644 --- a/biscuit-auth/src/format/mod.rs +++ b/biscuit-auth/src/format/mod.rs @@ -8,13 +8,16 @@ //! //! - serialization of Biscuit blocks to Protobuf then `Vec` //! - serialization of a wrapper structure containing serialized blocks and the signature -use super::crypto::{self, 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; @@ -32,22 +35,23 @@ use self::convert::*; pub(crate) const THIRD_PARTY_SIGNATURE_VERSION: u32 = 1; pub(crate) const DATALOG_3_3_SIGNATURE_VERSION: u32 = 1; pub(crate) const NON_ED25519_SIGNATURE_VERSION: u32 = 1; + /// Intermediate structure for token serialization /// /// This structure contains the blocks serialized to byte arrays. Those arrays /// will be used for the signature -#[derive(Clone, Debug)] -pub struct SerializedBiscuit { +#[derive(Clone)] +pub struct SerializedBiscuit { pub root_key_id: Option, - pub authority: crypto::Block, - pub blocks: Vec, - pub proof: crypto::TokenNext, + pub authority: crypto::Block, + pub blocks: Vec>, + pub proof: crypto::Proof, } -impl SerializedBiscuit { +impl SerializedBiscuit { pub fn from_slice(slice: &[u8], key_provider: KP) -> Result where - KP: RootKeyProvider, + KP: RootKeyProvider, { let deser = SerializedBiscuit::deserialize( slice, @@ -65,7 +69,7 @@ impl SerializedBiscuit { key_provider: KP, ) -> Result where - KP: RootKeyProvider, + KP: RootKeyProvider, { let deser = SerializedBiscuit::deserialize(slice, ThirdPartyVerificationMode::UnsafeLegacy)?; @@ -84,7 +88,7 @@ impl SerializedBiscuit { error::Format::DeserializationError(format!("deserialization error: {e:?}")) })?; - let next_key = PublicKey::from_proto(&data.authority.next_key)?; + let next_key: K::PublicKey = convert::public_key_from_proto(&data.authority.next_key)?; let mut next_key_algorithm = next_key.algorithm(); let signature = Signature::from_vec(data.authority.signature); @@ -105,7 +109,7 @@ impl SerializedBiscuit { let mut blocks = Vec::new(); for block in data.blocks { - let next_key = PublicKey::from_proto(&block.next_key)?; + let next_key: K::PublicKey = convert::public_key_from_proto(&block.next_key)?; next_key_algorithm = next_key.algorithm(); let signature = Signature::from_vec(block.signature); @@ -119,7 +123,7 @@ impl SerializedBiscuit { )); } - let public_key = PublicKey::from_proto(&ex.public_key)?; + let public_key = convert::public_key_from_proto(&ex.public_key)?; let signature = Signature::from_vec(ex.signature); Some(ExternalSignature { @@ -146,18 +150,12 @@ impl SerializedBiscuit { )) } Some(schema::proof::Content::NextSecret(v)) => { - let next_key_algorithm = match next_key_algorithm { - schema::public_key::Algorithm::Ed25519 => crate::builder::Algorithm::Ed25519, - schema::public_key::Algorithm::Secp256r1 => { - crate::builder::Algorithm::Secp256r1 - } - }; - TokenNext::Secret(PrivateKey::from_bytes(&v, next_key_algorithm)?) + Proof::Secret(K::from_bytes_and_algorithm(next_key_algorithm, &v)?) } Some(schema::proof::Content::FinalSignature(v)) => { let signature = Signature::from_vec(v); - TokenNext::Seal(signature) + Proof::Seal(signature) } }; @@ -175,8 +173,6 @@ impl SerializedBiscuit { &self, symbols: &mut SymbolTable, ) -> Result<(schema::Block, Vec), error::Token> { - let mut block_external_keys = Vec::new(); - let authority = schema::Block::decode(&self.authority.data[..]).map_err(|e| { error::Token::Format(error::Format::BlockDeserializationError(format!( "error deserializing authority block: {e:?}" @@ -186,13 +182,8 @@ impl SerializedBiscuit { symbols.extend(&SymbolTable::from(authority.symbols.clone())?)?; for pk in &authority.public_keys { - symbols - .public_keys - .insert_fallible(&PublicKey::from_proto(pk)?)?; + symbols.public_keys.insert_proto_fallible(&pk)?; } - // the authority block should not have an external key - block_external_keys.push(None); - //FIXME: return an error if the authority block has an external key let mut blocks = vec![]; @@ -203,15 +194,10 @@ impl SerializedBiscuit { ))) })?; - if let Some(external_signature) = &block.external_signature { - block_external_keys.push(Some(external_signature.public_key)); - } else { - block_external_keys.push(None); + if block.external_signature.is_none() { symbols.extend(&SymbolTable::from(deser.symbols.clone())?)?; for pk in &deser.public_keys { - symbols - .public_keys - .insert_fallible(&PublicKey::from_proto(pk)?)?; + symbols.public_keys.insert_proto_fallible(&pk)?; } } @@ -225,7 +211,7 @@ impl SerializedBiscuit { pub fn to_proto(&self) -> schema::Biscuit { let authority = schema::SignedBlock { block: self.authority.data.clone(), - next_key: self.authority.next_key.to_proto(), + next_key: convert::public_key_to_proto(&self.authority.next_key), signature: self.authority.signature.to_bytes().to_vec(), external_signature: None, version: if self.authority.version > 0 { @@ -239,12 +225,12 @@ impl SerializedBiscuit { for block in &self.blocks { let b = schema::SignedBlock { block: block.data.clone(), - next_key: block.next_key.to_proto(), + next_key: convert::public_key_to_proto(&block.next_key), signature: block.signature.to_bytes().to_vec(), external_signature: block.external_signature.as_ref().map(|external_signature| { schema::ExternalSignature { signature: external_signature.signature.to_bytes().to_vec(), - public_key: external_signature.public_key.to_proto(), + public_key: convert::public_key_to_proto(&external_signature.public_key), } }), version: if block.version > 0 { @@ -263,10 +249,10 @@ impl SerializedBiscuit { blocks, proof: schema::Proof { content: match &self.proof { - TokenNext::Seal(signature) => Some(schema::proof::Content::FinalSignature( + Proof::Seal(signature) => Some(schema::proof::Content::FinalSignature( signature.to_bytes().to_vec(), )), - TokenNext::Secret(private) => Some(schema::proof::Content::NextSecret( + Proof::Secret(private) => Some(schema::proof::Content::NextSecret( private.to_bytes().to_vec(), )), }, @@ -290,33 +276,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: &IK, + 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: &IK, + next_private_key: &K, authority: &Block, authority_signature_version: u32, ) -> Result { @@ -328,8 +314,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 +324,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 +351,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 +364,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 +376,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 +386,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 +411,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 +423,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 +433,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: &IK) -> Result<(), error::Format> { self.verify_inner(root, ThirdPartyVerificationMode::PreviousSignatureHashing) } - pub(crate) fn verify_inner( + pub(crate) fn verify_inner( &self, - root: &PublicKey, + root: &IK, verification_mode: ThirdPartyVerificationMode, ) -> Result<(), error::Format> { //FIXME: try batched signature verification - let mut current_pub = root; let mut previous_signature; - crypto::verify_authority_block_signature(&self.authority, current_pub)?; - current_pub = &self.authority.next_key; + crypto::verify_authority_block_signature(&self.authority, root)?; + let mut current_pub = &self.authority.next_key; previous_signature = &self.authority.signature; for block in &self.blocks { @@ -488,8 +473,8 @@ impl SerializedBiscuit { } match &self.proof { - TokenNext::Secret(private) => { - if current_pub != &private.public() { + Proof::Secret(private) => { + if *current_pub != private.public() { return Err(error::Format::Signature( error::Signature::InvalidSignature( "the last public key does not match the private key".to_string(), @@ -497,7 +482,7 @@ impl SerializedBiscuit { )); } } - TokenNext::Seal(signature) => { + Proof::Seal(signature) => { //FIXME: replace with SHA512 hashing let block = if self.blocks.is_empty() { &self.authority @@ -513,9 +498,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 +510,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: &IK, + next_private_key: &AK, + external_signature: &Option>, block_version: &Option, previous_blocks_sig_versions: I, ) -> u32 @@ -568,8 +567,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 +586,7 @@ mod tests { crypto::{ExternalSignature, Signature}, format::block_signature_version, token::{DATALOG_3_1, DATALOG_3_3}, - KeyPair, + PrivateKey, }; #[test] @@ -620,9 +619,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 +630,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 +641,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 +652,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 +663,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 +677,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 +688,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..92d78f27 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,8 @@ pub mod format; pub mod parser; mod token; -pub use crypto::{KeyPair, PrivateKey, PublicKey}; +pub use crypto::{PrivateKey, PublicKey}; +pub use token::public_keys; pub use token::authorizer::{Authorizer, AuthorizerLimits}; pub use token::builder; pub use token::builder::{Algorithm, AuthorizerBuilder, BiscuitBuilder, BlockBuilder}; diff --git a/biscuit-auth/src/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..f58ba4d4 100644 --- a/biscuit-auth/src/token/authorizer.rs +++ b/biscuit-auth/src/token/authorizer.rs @@ -6,6 +6,7 @@ use super::builder::{AuthorizerBuilder, BlockBuilder, Check, Fact, Policy, PolicyKind, Rule}; use super::{Biscuit, Block}; use crate::builder::{CheckKind, Convert}; +use crate::crypto::SerializePrivateKey; use crate::datalog::{self, ExternFunc, Origin, RunLimits, TrustedOrigins}; use crate::error; use crate::time::Instant; @@ -56,7 +57,7 @@ impl Authorizer { } } - pub(crate) fn from_token(token: &Biscuit) -> Result { + pub(crate) fn from_token(token: &Biscuit) -> Result { AuthorizerBuilder::new().build(token) } @@ -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::PublicKey as InertPublicKey; 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(), + InertPublicKey::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(), InertPublicKey::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(), InertPublicKey::from(&external.public())); + scope_params.insert("external2".to_string(), InertPublicKey::from(&external2.public())); let mut authorizer = builder .code_with_params( @@ -1258,7 +1258,7 @@ mod tests { let mut r: Rule = "right($right) <- right($right) trusting {external}" .try_into() .unwrap(); - r.set_scope("external", external.public()).unwrap(); + r.set_scope("external", InertPublicKey::from(&external.public())).unwrap(); r }, AuthorizerLimits { @@ -1288,7 +1288,7 @@ mod tests { let mut r: Rule = "group($group) <- group($group) trusting {external}" .try_into() .unwrap(); - r.set_scope("external", external.public()).unwrap(); + r.set_scope("external", InertPublicKey::from(&external.public())).unwrap(); r }, AuthorizerLimits { @@ -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..413c8dd8 100644 --- a/biscuit-auth/src/token/authorizer/snapshot.rs +++ b/biscuit-auth/src/token/authorizer/snapshot.rs @@ -18,7 +18,6 @@ use crate::{ schema::{self, GeneratedFacts}, }, token::{default_symbol_table, MAX_SCHEMA_VERSION, MIN_SCHEMA_VERSION}, - PublicKey, }; impl super::Authorizer { @@ -52,9 +51,7 @@ impl super::Authorizer { symbols.insert(&symbol); } for public_key in world.public_keys { - symbols - .public_keys - .insert(&PublicKey::from_proto(&public_key)?); + symbols.public_keys.insert_proto(&public_key); } let authorizer_block = proto_snapshot_block_to_token_block(&world.authorizer_block)?; @@ -193,7 +190,10 @@ impl super::Authorizer { .map(|policy| policy_to_proto_policy(policy, &mut symbols)) .collect(); - let authorizer_block = self.authorizer_block_builder.clone().build(symbols.clone()); + let authorizer_block = self + .authorizer_block_builder + .clone() + .build(symbols.clone()); symbols.extend(&authorizer_block.symbols)?; symbols.public_keys.extend(&authorizer_block.public_keys)?; @@ -320,12 +320,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::PublicKey as InertPublicKey; #[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 = InertPublicKey::from(&PrivateKey::new_with_algorithm(Algorithm::Secp256r1).public()); + let ed_pubkey = InertPublicKey::from(&PrivateKey::new_with_algorithm(Algorithm::Ed25519).public()); let builder = AuthorizerBuilder::new() .set_limits(RunLimits { max_facts: 42, @@ -356,8 +357,8 @@ mod tests { #[test] fn roundtrip_with_token() { - let secp_pubkey = KeyPair::new_with_algorithm(Algorithm::Secp256r1).public(); - let ed_pubkey = KeyPair::new_with_algorithm(Algorithm::Ed25519).public(); + let secp_pubkey = InertPublicKey::from(&PrivateKey::new_with_algorithm(Algorithm::Secp256r1).public()); + let ed_pubkey = InertPublicKey::from(&PrivateKey::new_with_algorithm(Algorithm::Ed25519).public()); let builder = AuthorizerBuilder::new() .set_limits(RunLimits { max_facts: 42, @@ -374,8 +375,8 @@ mod tests { "#, HashMap::default(), HashMap::from([ - ("ed_pubkey".to_string(), ed_pubkey), - ("secp_pubkey".to_string(), secp_pubkey), + ("ed_pubkey".to_string(), ed_pubkey.clone()), + ("secp_pubkey".to_string(), secp_pubkey.clone()), ]), ) .unwrap(); @@ -393,7 +394,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..e2a612e4 100644 --- a/biscuit-auth/src/token/block.rs +++ b/biscuit-auth/src/token/block.rs @@ -4,12 +4,11 @@ */ use crate::{ builder::{self, Convert}, - crypto::PublicKey, datalog::{Check, Fact, Rule, SymbolTable, Term}, error, }; -use super::{public_keys::PublicKeys, Scope}; +use super::{public_keys::{self, PublicKeys}, Scope}; /// a block contained in a token #[derive(Clone, Debug)] @@ -28,7 +27,7 @@ pub struct Block { /// format version used to generate this block pub version: u32, /// key used in optional external signature - pub external_key: Option, + pub external_key: Option, /// list of public keys referenced by this block pub public_keys: PublicKeys, /// list of scopes defining which blocks are trusted by this block @@ -103,7 +102,7 @@ impl Block { .collect::, error::Format>>()?, context: self.context.clone(), version: self.version, - external_key: self.external_key, + external_key: self.external_key.clone(), public_keys: self.public_keys.clone(), scopes: self .scopes diff --git a/biscuit-auth/src/token/builder.rs b/biscuit-auth/src/token/builder.rs index 08ad7ae7..cc3ab4e9 100644 --- a/biscuit-auth/src/token/builder.rs +++ b/biscuit-auth/src/token/builder.rs @@ -11,7 +11,8 @@ use std::{ // reexport those because the builder uses the same definitions use super::Block; -use crate::crypto::PublicKey; +#[cfg(any(test, feature = "datalog-macro"))] +use crate::token::public_keys::PublicKey; use crate::datalog::SymbolTable; pub use crate::datalog::{ Binary as DatalogBinary, Expression as DatalogExpression, Op as DatalogOp, @@ -214,11 +215,10 @@ mod tests { #[test] fn set_rule_scope_parameters() { let pubkey = PublicKey::from_bytes( - &hex::decode("6e9e6d5a75cf0c0e87ec1256b4dfed0ca3ba452912d213fcc70f8516583db9db") - .unwrap(), Algorithm::Ed25519, - ) - .unwrap(); + hex::decode("6e9e6d5a75cf0c0e87ec1256b4dfed0ca3ba452912d213fcc70f8516583db9db") + .unwrap(), + ); let mut rule = Rule::try_from( "fact($var1, {p2}) <- f1($var1, $var3), f2({p2}, $var3, {p4}), $var3.starts_with({p2}) trusting {pk}", ) @@ -241,11 +241,10 @@ mod tests { params.insert("p3".to_string(), true.into()); params.insert("p4".to_string(), "this will be ignored".into()); let pubkey = PublicKey::from_bytes( - &hex::decode("6e9e6d5a75cf0c0e87ec1256b4dfed0ca3ba452912d213fcc70f8516583db9db") - .unwrap(), Algorithm::Ed25519, - ) - .unwrap(); + hex::decode("6e9e6d5a75cf0c0e87ec1256b4dfed0ca3ba452912d213fcc70f8516583db9db") + .unwrap(), + ); let mut scope_params = HashMap::new(); scope_params.insert("pk".to_string(), pubkey); builder = builder diff --git a/biscuit-auth/src/token/builder/authorizer.rs b/biscuit-auth/src/token/builder/authorizer.rs index 14d7b72f..12f79995 100644 --- a/biscuit-auth/src/token/builder/authorizer.rs +++ b/biscuit-auth/src/token/builder/authorizer.rs @@ -12,6 +12,9 @@ use std::{ use biscuit_parser::parser::parse_source; use prost::Message; +use crate::PrivateKey; +use crate::crypto::SerializePrivateKey; +use crate::token::public_keys::PublicKey; use crate::{ builder::Convert, builder_ext::{AuthorizerExt, BuilderExt}, @@ -25,7 +28,7 @@ use crate::{ schema, }, token::{self, default_symbol_table, Block, MAX_SCHEMA_VERSION, MIN_SCHEMA_VERSION}, - Authorizer, AuthorizerLimits, Biscuit, PublicKey, + Authorizer, AuthorizerLimits, Biscuit, }; use super::{date, fact, BlockBuilder, Check, Fact, Policy, Rule, Scope, Term}; @@ -158,7 +161,7 @@ impl AuthorizerBuilder { res?; } for (name, value) in &scope_params { - let res = match rule.set_scope(name, *value) { + let res = match rule.set_scope(name, value.clone()) { Ok(_) => Ok(()), Err(error::Token::Language( biscuit_parser::error::LanguageError::Parameters { @@ -188,7 +191,7 @@ impl AuthorizerBuilder { res?; } for (name, value) in &scope_params { - let res = match check.set_scope(name, *value) { + let res = match check.set_scope(name, value.clone()) { Ok(_) => Ok(()), Err(error::Token::Language( biscuit_parser::error::LanguageError::Parameters { @@ -217,7 +220,7 @@ impl AuthorizerBuilder { res?; } for (name, value) in &scope_params { - let res = match policy.set_scope(name, *value) { + let res = match policy.set_scope(name, value.clone()) { Ok(_) => Ok(()), Err(error::Token::Language( biscuit_parser::error::LanguageError::Parameters { @@ -318,16 +321,16 @@ impl AuthorizerBuilder { } /// builds the authorizer from a token - pub fn build(self, token: &Biscuit) -> Result { + pub fn build(self, token: &Biscuit) -> Result { self.build_inner(Some(token)) } /// builds the authorizer without a token pub fn build_unauthenticated(self) -> Result { - self.build_inner(None) + self.build_inner::(None) } - fn build_inner(self, token: Option<&Biscuit>) -> Result { + fn build_inner(self, token: Option<&Biscuit>) -> Result { let mut world = World::new(); world.extern_funcs = self.extern_funcs; @@ -340,7 +343,7 @@ impl AuthorizerBuilder { if let Some(token) = token { for (i, block) in token.container.blocks.iter().enumerate() { if let Some(sig) = block.external_signature.as_ref() { - let new_key_id = symbols.public_keys.insert(&sig.public_key); + let new_key_id = symbols.public_keys.insert_serialize(&sig.public_key); public_key_to_block_id .entry(new_key_id as usize) @@ -607,7 +610,7 @@ impl AuthorizerBuilder { for public_key in world.public_keys { symbols .public_keys - .insert(&PublicKey::from_proto(&public_key)?); + .insert_proto(&public_key); } let authorizer_block = proto_snapshot_block_to_token_block(&world.authorizer_block)?; @@ -648,7 +651,10 @@ impl AuthorizerBuilder { .map(|policy| policy_to_proto_policy(policy, &mut symbols)) .collect(); - let authorizer_block = self.authorizer_block_builder.clone().build(symbols.clone()); + let authorizer_block = self + .authorizer_block_builder + .clone() + .build(symbols.clone()); symbols.extend(&authorizer_block.symbols)?; symbols.public_keys.extend(&authorizer_block.public_keys)?; diff --git a/biscuit-auth/src/token/builder/biscuit.rs b/biscuit-auth/src/token/builder/biscuit.rs index a02bfb1a..1dc65aa2 100644 --- a/biscuit-auth/src/token/builder/biscuit.rs +++ b/biscuit-auth/src/token/builder/biscuit.rs @@ -4,10 +4,11 @@ */ use super::{BlockBuilder, Check, Fact, Rule, Scope, Term}; use crate::builder_ext::BuilderExt; -use crate::crypto::PublicKey; +use crate::crypto::SerializePrivateKey; +use crate::token::public_keys::PublicKey; use crate::datalog::SymbolTable; use crate::token::default_symbol_table; -use crate::{error, Biscuit, KeyPair}; +use crate::{error, Biscuit}; use rand::{CryptoRng, RngCore}; use std::fmt; @@ -124,34 +125,34 @@ impl BiscuitBuilder { f } - pub fn build(self, root_key: &KeyPair) -> Result { + pub fn build(self, root_key: &K) -> Result, error::Token> { self.build_with_symbols(root_key, default_symbol_table()) } - pub fn build_with_symbols( + pub fn build_with_symbols( self, - root_key: &KeyPair, + root_key: &K, symbols: SymbolTable, - ) -> Result { + ) -> Result, error::Token> { self.build_with_rng(root_key, symbols, &mut rand::rngs::OsRng) } - pub fn build_with_rng( + pub fn build_with_rng( self, - root: &KeyPair, + root: &K, symbols: SymbolTable, rng: &mut R, - ) -> Result { + ) -> Result, error::Token> { let authority_block = self.inner.build(symbols.clone()); Biscuit::new_with_rng(rng, self.root_key_id, root, symbols, authority_block) } - pub fn build_with_key_pair( + pub fn build_with_key_pair( self, - root: &KeyPair, + root: &K, 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) } diff --git a/biscuit-auth/src/token/builder/block.rs b/biscuit-auth/src/token/builder/block.rs index bde72dc6..fc9fa0a7 100644 --- a/biscuit-auth/src/token/builder/block.rs +++ b/biscuit-auth/src/token/builder/block.rs @@ -7,7 +7,7 @@ use super::{ Convert, Expression, Fact, Op, Rule, Scope, Term, }; use crate::builder_ext::BuilderExt; -use crate::crypto::PublicKey; +use crate::token::public_keys::PublicKey; use crate::datalog::{get_schema_version, SymbolTable}; use crate::error; use biscuit_parser::parser::parse_block_source; @@ -124,7 +124,7 @@ impl BlockBuilder { res?; } for (name, value) in &scope_params { - let res = match rule.set_scope(name, *value) { + let res = match rule.set_scope(name, value.clone()) { Ok(_) => Ok(()), Err(error::Token::Language( biscuit_parser::error::LanguageError::Parameters { @@ -154,7 +154,7 @@ impl BlockBuilder { res?; } for (name, value) in &scope_params { - let res = match check.set_scope(name, *value) { + let res = match check.set_scope(name, value.clone()) { Ok(_) => Ok(()), Err(error::Token::Language( biscuit_parser::error::LanguageError::Parameters { diff --git a/biscuit-auth/src/token/builder/check.rs b/biscuit-auth/src/token/builder/check.rs index 46cc1815..03c5761f 100644 --- a/biscuit-auth/src/token/builder/check.rs +++ b/biscuit-auth/src/token/builder/check.rs @@ -8,7 +8,8 @@ use nom::Finish; use crate::{ datalog::{self, SymbolTable}, - error, PublicKey, + error, + token::public_keys::PublicKey, }; #[cfg(feature = "datalog-macro")] @@ -61,7 +62,7 @@ impl Check { pub fn set_scope(&mut self, name: &str, pubkey: PublicKey) -> Result<(), error::Token> { let mut found = false; for query in &mut self.queries { - if query.set_scope(name, pubkey).is_ok() { + if query.set_scope(name, pubkey.clone()).is_ok() { found = true; } } @@ -92,7 +93,7 @@ impl Check { /// parameter is not present in the check pub fn set_scope_lenient(&mut self, name: &str, pubkey: PublicKey) -> Result<(), error::Token> { for query in &mut self.queries { - query.set_scope_lenient(name, pubkey)?; + query.set_scope_lenient(name, pubkey.clone())?; } Ok(()) } diff --git a/biscuit-auth/src/token/builder/policy.rs b/biscuit-auth/src/token/builder/policy.rs index 2a1cb478..52984c9e 100644 --- a/biscuit-auth/src/token/builder/policy.rs +++ b/biscuit-auth/src/token/builder/policy.rs @@ -6,7 +6,7 @@ use std::{convert::TryFrom, fmt, str::FromStr}; use nom::Finish; -use crate::{error, PublicKey}; +use crate::{error, token::public_keys::PublicKey}; #[cfg(feature = "datalog-macro")] use super::ToAnyParam; @@ -56,7 +56,7 @@ impl Policy { pub fn set_scope(&mut self, name: &str, pubkey: PublicKey) -> Result<(), error::Token> { let mut found = false; for query in &mut self.queries { - if query.set_scope(name, pubkey).is_ok() { + if query.set_scope(name, pubkey.clone()).is_ok() { found = true; } } @@ -85,7 +85,7 @@ impl Policy { /// replace a scope parameter with the pubkey argument, ignoring unknown parameters pub fn set_scope_lenient(&mut self, name: &str, pubkey: PublicKey) -> Result<(), error::Token> { for query in &mut self.queries { - query.set_scope_lenient(name, pubkey)?; + query.set_scope_lenient(name, pubkey.clone())?; } Ok(()) } diff --git a/biscuit-auth/src/token/builder/rule.rs b/biscuit-auth/src/token/builder/rule.rs index ec4483c0..9962baf6 100644 --- a/biscuit-auth/src/token/builder/rule.rs +++ b/biscuit-auth/src/token/builder/rule.rs @@ -7,8 +7,9 @@ use std::{collections::HashMap, convert::TryFrom, fmt, str::FromStr}; use nom::Finish; use crate::{ + token::public_keys::PublicKey, datalog::{self, SymbolTable}, - error, PublicKey, + error, }; #[cfg(feature = "datalog-macro")] @@ -315,7 +316,7 @@ impl Rule { .map(|scope| { if let Scope::Parameter(name) = &scope { if let Some(Some(pubkey)) = parameters.get(name) { - return Scope::PublicKey(*pubkey); + return Scope::PublicKey(pubkey.clone()); } } scope @@ -455,8 +456,7 @@ impl From for Rule { ( k, v.map(|pk| { - PublicKey::from_bytes(&pk.key, pk.algorithm.into()) - .expect("invalid public key") + PublicKey::from_bytes(pk.algorithm.into(), pk.key) }), ) }) diff --git a/biscuit-auth/src/token/builder/scope.rs b/biscuit-auth/src/token/builder/scope.rs index 497a4d9e..e2d6c0d7 100644 --- a/biscuit-auth/src/token/builder/scope.rs +++ b/biscuit-auth/src/token/builder/scope.rs @@ -4,7 +4,8 @@ */ use std::fmt; -use crate::{datalog::SymbolTable, error, PublicKey}; +use crate::token::public_keys::PublicKey; +use crate::{datalog::SymbolTable, error}; use super::Convert; @@ -27,7 +28,7 @@ impl Convert for Scope { Scope::Authority => crate::token::Scope::Authority, Scope::Previous => crate::token::Scope::Previous, Scope::PublicKey(key) => { - crate::token::Scope::PublicKey(symbols.public_keys.insert(key)) + crate::token::Scope::PublicKey(symbols.public_keys.insert_data(key)) } // The error is caught in the `add_xxx` functions, so this should // not happen™ @@ -43,10 +44,11 @@ impl Convert for Scope { crate::token::Scope::Authority => Scope::Authority, crate::token::Scope::Previous => Scope::Previous, crate::token::Scope::PublicKey(key_id) => Scope::PublicKey( - *symbols + symbols .public_keys .get_key(*key_id) - .ok_or(error::Format::UnknownExternalKey)?, + .ok_or(error::Format::UnknownExternalKey)? + .clone(), ), }) } @@ -57,7 +59,7 @@ impl fmt::Display for Scope { match self { Scope::Authority => write!(f, "authority"), Scope::Previous => write!(f, "previous"), - Scope::PublicKey(pk) => pk.write(f), + Scope::PublicKey(pk) => write!(f, "{pk}"), Scope::Parameter(s) => { write!(f, "{{{s}}}") } @@ -71,7 +73,7 @@ impl From for Scope { biscuit_parser::builder::Scope::Authority => Scope::Authority, biscuit_parser::builder::Scope::Previous => Scope::Previous, biscuit_parser::builder::Scope::PublicKey(pk) => Scope::PublicKey( - PublicKey::from_bytes(&pk.key, pk.algorithm.into()).expect("invalid public key"), + PublicKey::from_bytes(pk.algorithm.into(), pk.key) ), biscuit_parser::builder::Scope::Parameter(s) => Scope::Parameter(s), } diff --git a/biscuit-auth/src/token/mod.rs b/biscuit-auth/src/token/mod.rs index 218804c9..aff7e4c7 100644 --- a/biscuit-auth/src/token/mod.rs +++ b/biscuit-auth/src/token/mod.rs @@ -3,20 +3,22 @@ * 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 super::crypto::{PrivateKey, PublicKey, Signature}; use super::datalog::SymbolTable; use super::error; use super::format::SerializedBiscuit; -use crate::crypto::{self}; -use crate::format::convert::proto_block_to_token_block; +use crate::crypto::{self, SerializePrivateKey, Verify}; +use crate::format::convert::{proto_block_to_token_block, public_key_from_proto}; use crate::format::schema::{self, ThirdPartyBlockContents}; use crate::format::{ThirdPartyVerificationMode, THIRD_PARTY_SIGNATURE_VERSION}; use authorizer::Authorizer; @@ -25,7 +27,7 @@ pub mod authorizer; pub(crate) mod block; pub mod builder; pub mod builder_ext; -pub(crate) mod public_keys; +pub mod public_keys; pub(crate) mod third_party; pub mod unverified; pub use block::Block; @@ -56,10 +58,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 +82,13 @@ pub fn default_symbol_table() -> SymbolTable { /// Ok(()) /// } /// ``` -#[derive(Clone, Debug)] -pub struct Biscuit { +#[derive(Clone)] +pub struct Biscuit { pub(crate) root_key_id: Option, pub(crate) authority: schema::Block, pub(crate) blocks: Vec, pub(crate) symbols: SymbolTable, - pub(crate) container: SerializedBiscuit, + pub(crate) container: SerializedBiscuit, } impl Biscuit { @@ -101,7 +103,7 @@ impl Biscuit { pub fn from(slice: T, key_provider: KP) -> Result where T: AsRef<[u8]>, - KP: RootKeyProvider, + KP: RootKeyProvider, { Biscuit::from_with_symbols(slice.as_ref(), key_provider, default_symbol_table()) } @@ -110,7 +112,7 @@ impl Biscuit { pub fn from_base64(slice: T, key_provider: KP) -> Result where T: AsRef<[u8]>, - KP: RootKeyProvider, + KP: RootKeyProvider, { Biscuit::from_base64_with_symbols(slice, key_provider, default_symbol_table()) } @@ -124,7 +126,7 @@ impl Biscuit { ) -> Result where T: AsRef<[u8]>, - KP: RootKeyProvider, + KP: RootKeyProvider, { let container = SerializedBiscuit::unsafe_from_slice(slice.as_ref(), key_provider) .map_err(error::Token::Format)?; @@ -168,14 +170,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 +221,11 @@ impl Biscuit { /// Blocks carrying an external public key are _third-party blocks_ /// and their contents can be trusted as coming from the holder of /// the corresponding private key - pub fn external_public_keys(&self) -> Vec> { + pub fn external_public_keys(&self) -> Vec> { let mut res = vec![None]; for block in self.container.blocks.iter() { - res.push(block.external_signature.as_ref().map(|sig| sig.public_key)); + res.push(block.external_signature.as_ref().map(|sig| sig.public_key.clone())); } res @@ -250,33 +255,34 @@ impl Biscuit { /// creates a new token, using a provided CSPRNG /// - /// the public part of the root keypair must be used for verification + /// the public part of the root key must be used for verification pub(crate) fn new_with_rng( rng: &mut T, root_key_id: Option, - root: &KeyPair, + root: &K, 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( root_key_id: Option, - root: &KeyPair, - next_keypair: &KeyPair, + root_key: &K, + next_key: &K, mut symbols: SymbolTable, authority: Block, - ) -> Result { + ) -> Result, error::Token> { if !symbols.is_disjoint(&authority.symbols) { return Err(error::Token::Format(error::Format::SymbolTableOverlap)); } @@ -285,7 +291,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 +317,7 @@ impl Biscuit { symbols: SymbolTable, ) -> Result where - KP: RootKeyProvider, + KP: RootKeyProvider, { let container = SerializedBiscuit::from_slice(slice, key_provider).map_err(error::Token::Format)?; @@ -320,7 +326,7 @@ impl Biscuit { } fn from_serialized_container( - container: SerializedBiscuit, + container: SerializedBiscuit, mut symbols: SymbolTable, ) -> Result { let (authority, blocks) = container.extract_blocks(&mut symbols)?; @@ -336,7 +342,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 +351,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 +381,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 +415,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 +450,7 @@ impl Biscuit { .blocks .last() .unwrap_or(&self.container.authority) - .next_key; + .next_key.clone(); let external_signature = crypto::ExternalSignature { public_key: external_key, @@ -475,7 +481,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 +522,13 @@ impl Biscuit { let mut public_keys = PublicKeys::new(); for pk in &block.public_keys { - public_keys.insert(&PublicKey::from_proto(pk)?); + public_keys.insert_proto(pk); } Ok(public_keys) } /// gets the list of public keys from a block - pub fn block_external_key(&self, index: usize) -> Result, error::Token> { + pub fn block_external_key(&self, index: usize) -> Result, error::Token> { let block = if index == 0 { &self.container.authority } else { @@ -535,7 +541,7 @@ impl Biscuit { Ok(block .external_signature .as_ref() - .map(|signature| signature.public_key)) + .map(|signature| signature.public_key.clone())) } /// returns the number of blocks (at least 1) @@ -551,7 +557,7 @@ impl Biscuit { .authority .external_signature .as_ref() - .map(|ex| ex.public_key), + .map(|ex| &ex.public_key), ) .map_err(error::Token::Format)? } else { @@ -566,7 +572,7 @@ impl Biscuit { self.container.blocks[index - 1] .external_signature .as_ref() - .map(|ex| ex.public_key), + .map(|ex| &ex.public_key), ) .map_err(error::Token::Format)? }; @@ -574,7 +580,7 @@ impl Biscuit { Ok(block) } - pub(crate) fn blocks(&self) -> impl Iterator> + use<'_> { + pub(crate) fn blocks(&self) -> impl Iterator> + use<'_, K> { once( proto_block_to_token_block( &self.authority, @@ -582,7 +588,7 @@ impl Biscuit { .authority .external_signature .as_ref() - .map(|ex| ex.public_key), + .map(|ex| &ex.public_key), ) .map_err(error::Token::Format), ) @@ -593,7 +599,7 @@ impl Biscuit { container .external_signature .as_ref() - .map(|ex| ex.public_key), + .map(|ex| &ex.public_key), ) .map_err(error::Token::Format) }, @@ -601,8 +607,25 @@ impl Biscuit { } } -impl Display for Biscuit { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { +impl Debug for Biscuit +where + K: SerializePrivateKey + Debug, + K::PublicKey: Debug, +{ + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + f.debug_struct("Biscuit") + .field("root_key_id", &self.root_key_id) + .field("authority", &self.authority) + .field("blocks", &self.blocks) + .field("symbols", &self.symbols) + .field("container", &self.container) + .finish() + } +} + + +impl Display for Biscuit { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { let authority = self .block(0) .as_ref() @@ -619,12 +642,13 @@ impl Display for Biscuit { write!(f, "Biscuit {{\n symbols: {:?}\n public keys: {:?}\n authority: {}\n blocks: [\n {}\n ]\n}}", self.symbols.strings(), - self.symbols.public_keys.keys.iter().map(|pk| hex::encode(pk.to_bytes())).collect::>(), + self.symbols.public_keys.keys.iter().map(|pk| format!("{}", pk)).collect::>(), authority, blocks.join(",\n\t") ) } } + fn print_block(symbols: &SymbolTable, block: &Block) -> String { let facts: Vec<_> = block.facts.iter().map(|f| symbols.print_fact(f)).collect(); let rules: Vec<_> = block.rules.iter().map(|r| symbols.print_rule(r)).collect(); @@ -665,7 +689,7 @@ fn print_block(symbols: &SymbolTable, block: &Block) -> String { block.version, block.context.as_deref().unwrap_or(""), block.external_key.as_ref().map(|k| hex::encode(k.to_bytes())).unwrap_or_default(), - block.public_keys.keys.iter().map(|k | hex::encode(k.to_bytes())).collect::>(), + block.public_keys.keys.iter().map(|k| format!("{}", k)).collect::>(), block.scopes, facts, rules, @@ -688,41 +712,55 @@ pub enum Scope { /// value will be passed to the implementor of `RootKeyProvider` /// to choose which key will be used. pub trait RootKeyProvider { - fn choose(&self, key_id: Option) -> Result; + type Key: Verify; + + fn choose(&self, key_id: Option) -> Result; } -impl RootKeyProvider for Box { - fn choose(&self, key_id: Option) -> Result { +impl RootKeyProvider for Box> { + type Key = K; + + fn choose(&self, key_id: Option) -> Result { self.as_ref().choose(key_id) } } -impl RootKeyProvider for std::rc::Rc { - fn choose(&self, key_id: Option) -> Result { +impl RootKeyProvider for Rc> { + type Key = K; + + fn choose(&self, key_id: Option) -> Result { self.as_ref().choose(key_id) } } -impl RootKeyProvider for std::sync::Arc { - fn choose(&self, key_id: Option) -> Result { +impl RootKeyProvider for Arc> { + type Key = K; + + fn choose(&self, key_id: Option) -> Result { self.as_ref().choose(key_id) } } impl RootKeyProvider for PublicKey { + type Key = PublicKey; + fn choose(&self, _: Option) -> Result { Ok(*self) } } impl RootKeyProvider for &PublicKey { + type Key = PublicKey; + fn choose(&self, _: Option) -> Result { Ok(**self) } } -impl) -> Result> RootKeyProvider for F { - fn choose(&self, root_key_id: Option) -> Result { +impl) -> Result, K: Verify> RootKeyProvider for F { + type Key = K; + + fn choose(&self, root_key_id: Option) -> Result { self(root_key_id) } } @@ -733,7 +771,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 +781,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 +820,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 +848,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 +873,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 +942,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 +960,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 +1035,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 +1050,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 +1099,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 +1116,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 +1168,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 +1211,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 +1228,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 +1301,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 +1319,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 +1361,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 +1390,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 +1405,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 +1418,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 +1455,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 +1497,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 +1537,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 +1636,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 +1650,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 +1661,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..92145020 100644 --- a/biscuit-auth/src/token/public_keys.rs +++ b/biscuit-auth/src/token/public_keys.rs @@ -3,24 +3,27 @@ * SPDX-License-Identifier: Apache-2.0 */ use std::collections::HashSet; +use std::fmt::{self, Display, Formatter}; -use crate::{crypto::PublicKey, error}; +use crate::crypto::SerializePublicKey; +use crate::format::schema; +use crate::{Algorithm, error}; -#[derive(Clone, Debug, PartialEq, Eq, Default)] +#[derive(Default, Clone, Debug, PartialEq, Eq)] pub struct PublicKeys { pub(crate) keys: Vec, } impl PublicKeys { - pub fn new() -> Self { + pub(crate) fn new() -> Self { PublicKeys { keys: vec![] } } - pub fn from(keys: Vec) -> Self { + pub(crate) fn from_keys(keys: Vec) -> Self { PublicKeys { keys } } - pub fn extend(&mut self, other: &PublicKeys) -> Result<(), error::Format> { + pub(crate) fn extend(&mut self, other: &PublicKeys) -> Result<(), error::Format> { if !self.is_disjoint(other) { return Err(error::Format::PublicKeyTableOverlap); } @@ -28,52 +31,117 @@ impl PublicKeys { Ok(()) } - pub fn insert(&mut self, k: &PublicKey) -> u64 { + pub(crate) fn insert(&mut self, k: &PublicKey) -> u64 { match self.keys.iter().position(|key| key == k) { Some(index) => index as u64, None => { - self.keys.push(*k); + self.keys.push(k.clone()); (self.keys.len() - 1) as u64 } } } - pub fn insert_fallible(&mut self, k: &PublicKey) -> Result { + pub(crate) fn insert_serialize(&mut self, k: &K) -> u64 { + self.insert(&PublicKey::from(k)) + } + + pub(crate) fn insert_data(&mut self, k: &PublicKey) -> u64 { match self.keys.iter().position(|key| key == k) { - Some(_) => Err(error::Format::PublicKeyTableOverlap), + Some(index) => index as u64, None => { - self.keys.push(*k); - Ok((self.keys.len() - 1) as u64) + self.keys.push(k.clone()); + (self.keys.len() - 1) as u64 } } } - pub fn get(&self, k: &PublicKey) -> Option { - self.keys.iter().position(|key| key == k).map(|i| i as u64) + pub(crate) fn insert_proto(&mut self, k: &schema::PublicKey) -> u64 { + let k = PublicKey::from_proto(k); + match self.keys.iter().position(|key| *key == k) { + Some(index) => index as u64, + None => { + self.keys.push(k.clone()); + (self.keys.len() - 1) as u64 + } + } } - pub fn current_offset(&self) -> usize { + pub(crate) fn insert_proto_fallible(&mut self, k: &schema::PublicKey) -> Result { + let k = PublicKey::from_proto(k); + match self.keys.iter().position(|key| *key == k) { + Some(_) => Err(error::Format::PublicKeyTableOverlap), + None => { + self.keys.push(k.clone()); + Ok((self.keys.len() - 1) as u64) + } + } + } + + pub(crate) fn current_offset(&self) -> usize { self.keys.len() } - pub fn split_at(&mut self, offset: usize) -> PublicKeys { + pub(crate) fn split_at(&mut self, offset: usize) -> PublicKeys { let mut table = PublicKeys::new(); table.keys = self.keys.split_off(offset); table } - pub fn is_disjoint(&self, other: &PublicKeys) -> bool { + pub(crate) fn is_disjoint(&self, other: &PublicKeys) -> bool { let h1 = self.keys.iter().collect::>(); let h2 = other.keys.iter().collect::>(); h1.is_disjoint(&h2) } - pub fn get_key(&self, i: u64) -> Option<&PublicKey> { + pub(crate) fn get_key(&self, i: u64) -> Option<&PublicKey> { self.keys.get(i as usize) } - pub fn into_inner(self) -> Vec { + pub(crate) fn into_inner(self) -> Vec { self.keys } } + +#[derive(Default, Clone, Debug, PartialEq, Eq, Hash)] +pub struct PublicKey { + algorithm: Algorithm, + key: Vec, +} + +impl PublicKey { + pub fn from_bytes(algorithm: Algorithm, key: Vec) -> PublicKey { + PublicKey { algorithm, key } + } + + pub(crate) fn from(key: &K) -> PublicKey { + PublicKey { + algorithm: key.algorithm(), + key: key.to_bytes(), + } + } + + fn from_proto(key: &schema::PublicKey) -> PublicKey { + PublicKey { + algorithm: key.algorithm().into(), + key: key.key.clone(), + } + } + + pub(crate) fn to_proto(&self) -> schema::PublicKey { + schema::PublicKey { + algorithm: schema::public_key::Algorithm::from(self.algorithm) as i32, + key: self.key.clone(), + } + } + + pub fn to_bytes(&self) -> Vec { + self.key.clone() + } +} + +impl Display for PublicKey { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + write!(f, "{}/{}", self.algorithm, hex::encode(&self.key)) + } +} diff --git a/biscuit-auth/src/token/third_party.rs b/biscuit-auth/src/token/third_party.rs index 7150c96a..03bc4350 100644 --- a/biscuit-auth/src/token/third_party.rs +++ b/biscuit-auth/src/token/third_party.rs @@ -6,13 +6,14 @@ use std::cmp::max; use prost::Message; +use crate::crypto::SerializePrivateKey; use crate::{ builder::BlockBuilder, crypto::generate_external_signature_payload_v1, datalog::SymbolTable, error, format::{convert::token_block_to_proto_block, schema, SerializedBiscuit}, - KeyPair, PrivateKey, + PrivateKey, }; use super::THIRD_PARTY_SIGNATURE_VERSION; @@ -24,8 +25,8 @@ pub struct ThirdPartyRequest { } impl ThirdPartyRequest { - pub(crate) fn from_container( - container: &SerializedBiscuit, + pub(crate) fn from_container( + container: &SerializedBiscuit, ) -> Result { if container.proof.is_sealed() { return Err(error::Token::AppendOnSealed); @@ -115,10 +116,9 @@ impl ThirdPartyRequest { THIRD_PARTY_SIGNATURE_VERSION, ); - let keypair = KeyPair::from(private_key); - let signature = keypair.sign(&signed_payload)?; + let signature = private_key.sign(&signed_payload)?; - let public_key = keypair.public(); + let public_key = private_key.public(); let content = schema::ThirdPartyBlockContents { payload, external_signature: schema::ExternalSignature { @@ -160,7 +160,7 @@ mod tests { #[test] fn third_party_request_roundtrip() { let mut rng: rand::rngs::StdRng = rand::SeedableRng::seed_from_u64(0); - let root = KeyPair::new_with_rng(crate::builder::Algorithm::Ed25519, &mut rng); + let root = PrivateKey::new_with_rng(crate::builder::Algorithm::Ed25519, &mut rng); let biscuit1 = crate::Biscuit::builder() .fact("right(\"file1\", \"read\")") .unwrap() diff --git a/biscuit-auth/src/token/unverified.rs b/biscuit-auth/src/token/unverified.rs index 9eea9c53..d47f4d80 100644 --- a/biscuit-auth/src/token/unverified.rs +++ b/biscuit-auth/src/token/unverified.rs @@ -2,12 +2,15 @@ * Copyright (c) 2019 Geoffroy Couprie and Contributors to the Eclipse Foundation. * SPDX-License-Identifier: Apache-2.0 */ +use std::fmt::{self, Debug, Formatter}; + use prost::Message; use super::{default_symbol_table, Biscuit, Block}; +use crate::crypto::SerializePrivateKey; use crate::{ builder::BlockBuilder, - crypto::{self, PublicKey, Signature}, + crypto::{self, PrivateKey, PublicKey, Signature}, datalog::SymbolTable, error, format::{ @@ -16,7 +19,7 @@ use crate::{ SerializedBiscuit, }, token::{ThirdPartyBlockContents, ThirdPartyRequest}, - KeyPair, RootKeyProvider, + RootKeyProvider, }; /// A token that was parsed without cryptographic signature verification @@ -26,12 +29,27 @@ use crate::{ /// /// It can be converted to a [Biscuit] using [UnverifiedBiscuit::verify], /// and then used for authorization -#[derive(Clone, Debug)] -pub struct UnverifiedBiscuit { +#[derive(Clone)] +pub struct UnverifiedBiscuit { pub(crate) authority: schema::Block, pub(crate) blocks: Vec, pub(crate) symbols: SymbolTable, - container: SerializedBiscuit, + container: SerializedBiscuit, +} + +impl Debug for UnverifiedBiscuit +where + K: SerializePrivateKey + Debug, + K::PublicKey: Debug, +{ + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + f.debug_struct("UnverifiedBiscuit") + .field("authority", &self.authority) + .field("blocks", &self.blocks) + .field("symbols", &self.symbols) + .field("container", &self.container) + .finish() + } } impl UnverifiedBiscuit { @@ -86,7 +104,7 @@ impl UnverifiedBiscuit { /// checks the signature of the token and convert it to a [Biscuit] for authorization pub fn verify(self, key_provider: KP) -> Result where - KP: RootKeyProvider, + KP: RootKeyProvider, { let key = key_provider.choose(self.root_key_id())?; self.container.verify(&key)?; @@ -102,12 +120,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 +169,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 +186,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 +277,7 @@ impl UnverifiedBiscuit { .authority .external_signature .as_ref() - .map(|ex| ex.public_key), + .map(|ex| &ex.public_key), ) .map_err(error::Token::Format)? } else { @@ -274,7 +292,7 @@ impl UnverifiedBiscuit { self.container.blocks[index - 1] .external_signature .as_ref() - .map(|ex| ex.public_key), + .map(|ex| &ex.public_key), ) .map_err(error::Token::Format)? }; @@ -300,15 +318,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 +368,10 @@ 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[..] { + symbols.public_keys.insert_proto_fallible(key)?; } blocks.push(block); @@ -378,14 +395,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 +413,7 @@ mod tests { let req = biscuit.third_party_request().unwrap(); let res = req .create_block( - &external_key.private(), + &external_key, BlockBuilder::new().fact("third_party(true)").unwrap(), ) .unwrap(); diff --git a/biscuit-auth/tests/macros.rs b/biscuit-auth/tests/macros.rs index 7ff2653e..0b522b20 100644 --- a/biscuit-auth/tests/macros.rs +++ b/biscuit-auth/tests/macros.rs @@ -2,7 +2,8 @@ * Copyright (c) 2019 Geoffroy Couprie and Contributors to the Eclipse Foundation. * SPDX-License-Identifier: Apache-2.0 */ -use biscuit_auth::{builder, datalog::RunLimits, KeyPair, PublicKey}; +use biscuit_auth::{builder, datalog::RunLimits, PrivateKey}; +use biscuit_auth::public_keys::PublicKey; use biscuit_quote::{ authorizer, authorizer_merge, biscuit, biscuit_merge, block, block_merge, check, fact, policy, rule, @@ -122,12 +123,10 @@ fn authorizer_macro_trailing_comma() { #[test] fn biscuit_macro() { - use biscuit_auth::PublicKey; let pubkey = PublicKey::from_bytes( - &hex::decode("6e9e6d5a75cf0c0e87ec1256b4dfed0ca3ba452912d213fcc70f8516583db9db").unwrap(), biscuit_auth::builder::Algorithm::Ed25519, - ) - .unwrap(); + hex::decode("6e9e6d5a75cf0c0e87ec1256b4dfed0ca3ba452912d213fcc70f8516583db9db").unwrap(), + ); let s = String::from("my_value"); let my_key = "my_value"; @@ -184,12 +183,10 @@ fn biscuit_macro_trailing_comma() { #[test] fn rule_macro() { - use biscuit_auth::PublicKey; let pubkey = PublicKey::from_bytes( - &hex::decode("6e9e6d5a75cf0c0e87ec1256b4dfed0ca3ba452912d213fcc70f8516583db9db").unwrap(), biscuit_auth::builder::Algorithm::Ed25519, - ) - .unwrap(); + hex::decode("6e9e6d5a75cf0c0e87ec1256b4dfed0ca3ba452912d213fcc70f8516583db9db").unwrap(), + ); let mut term_set = BTreeSet::new(); term_set.insert(builder::int(0i64)); let r = rule!( @@ -214,12 +211,10 @@ fn fact_macro() { #[test] fn check_macro() { - use biscuit_auth::PublicKey; let pubkey = PublicKey::from_bytes( - &hex::decode("6e9e6d5a75cf0c0e87ec1256b4dfed0ca3ba452912d213fcc70f8516583db9db").unwrap(), biscuit_auth::builder::Algorithm::Ed25519, - ) - .unwrap(); + hex::decode("6e9e6d5a75cf0c0e87ec1256b4dfed0ca3ba452912d213fcc70f8516583db9db").unwrap(), + ); let mut term_set = BTreeSet::new(); term_set.insert(builder::int(0i64)); let c = check!( @@ -235,12 +230,10 @@ fn check_macro() { #[test] fn policy_macro() { - use biscuit_auth::PublicKey; let pubkey = PublicKey::from_bytes( - &hex::decode("6e9e6d5a75cf0c0e87ec1256b4dfed0ca3ba452912d213fcc70f8516583db9db").unwrap(), biscuit_auth::builder::Algorithm::Ed25519, - ) - .unwrap(); + hex::decode("6e9e6d5a75cf0c0e87ec1256b4dfed0ca3ba452912d213fcc70f8516583db9db").unwrap(), + ); let mut term_set = BTreeSet::new(); term_set.insert(builder::int(0i64)); let p = policy!( @@ -256,7 +249,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 +288,10 @@ fn json() { #[test] fn ecdsa() { - use biscuit_auth::PublicKey; - let pubkey = PublicKey::from_bytes( - &hex::decode("0245dd01132962da3812911b746b080aed714873c1812e7cefacf13e3880712da0").unwrap(), biscuit_auth::builder::Algorithm::Secp256r1, - ) - .unwrap(); + hex::decode("0245dd01132962da3812911b746b080aed714873c1812e7cefacf13e3880712da0").unwrap(), + ); let mut term_set = BTreeSet::new(); term_set.insert(builder::int(0i64)); let r = rule!( @@ -318,16 +308,19 @@ fn ecdsa() { #[test] fn trusting() { // this should only work with a proper `PublicKey` value, and fail when trying to provide a string instead - let pubkey: PublicKey = - "secp256r1/0245dd01132962da3812911b746b080aed714873c1812e7cefacf13e3880712da0" - .parse() - .unwrap(); - let _ = authorizer!( - r#" + let pubkey = PublicKey::from_bytes( + biscuit_auth::builder::Algorithm::Secp256r1, + hex::decode("0245dd01132962da3812911b746b080aed714873c1812e7cefacf13e3880712da0").unwrap(), + ); + let _ = { + let pubkey = pubkey.clone(); + authorizer!( + r#" nonce("a"); operation("o"); pathname("p"); d($x) <- nonce($x) trusting {pubkey} "# - ); + ) + }; let _ = rule!( r#" data($nonce, $operation, $pathname) diff --git a/biscuit-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..92eb69dc 100644 --- a/biscuit-parser/src/builder.rs +++ b/biscuit-parser/src/builder.rs @@ -164,10 +164,10 @@ impl ToTokens for Scope { let bytes = pk.key.iter(); match pk.algorithm { Algorithm::Ed25519 => quote! { ::biscuit_auth::builder::Scope::PublicKey( - ::biscuit_auth::PublicKey::from_bytes(&[#(#bytes),*], ::biscuit_auth::builder::Algorithm::Ed25519).unwrap() + ::biscuit_auth::public_keys::PublicKey::from_bytes(::biscuit_auth::builder::Algorithm::Ed25519, vec![#(#bytes),*]) )}, Algorithm::Secp256r1 => quote! { ::biscuit_auth::builder::Scope::PublicKey( - ::biscuit_auth::PublicKey::from_bytes(&[#(#bytes),*], ::biscuit_auth::builder::Algorithm::Secp256r1).unwrap() + ::biscuit_auth::public_keys::PublicKey::from_bytes(::biscuit_auth::builder::Algorithm::Secp256r1, vec![#(#bytes),*]) )}, } }