09_public_key/
09_public_key.rs1use localauthentication::prelude::*;
2use std::time::{SystemTime, UNIX_EPOCH};
3
4fn unique_identifier(prefix: &str) -> String {
5 let now = SystemTime::now()
6 .duration_since(UNIX_EPOCH)
7 .unwrap_or_default()
8 .as_nanos();
9 format!("dev.doomfish.localauthentication.{prefix}.{now}")
10}
11
12fn main() -> Result<(), Box<dyn std::error::Error>> {
13 let store = LARightStore::shared()?;
14 let first_right = LARight::new()?;
15 let second_right = LARight::new()?;
16 let first_identifier = unique_identifier("public-key-a");
17 let second_identifier = unique_identifier("public-key-b");
18
19 match store.save_right(&first_right, &first_identifier) {
20 Ok(first) => {
21 let public_key = first.public_key()?;
22 let sign = SecKeyAlgorithm::ecdsa_signature_message_x962_sha256();
23 let encrypt =
24 SecKeyAlgorithm::ecies_encryption_cofactor_variable_iv_x963_sha256_aes_gcm();
25 let exchange = SecKeyAlgorithm::ecdh_key_exchange_cofactor_x963_sha256();
26 let first_private_key = first.key()?;
27
28 println!("public key bytes: {}", public_key.export_bytes()?.len());
29 println!("can verify: {}", public_key.can_verify_using(&sign)?);
30 println!("can encrypt: {}", public_key.can_encrypt_using(&encrypt)?);
31 println!("private key can sign: {}", first_private_key.can_sign_using(&sign)?);
32 println!(
33 "private key can exchange: {}",
34 first_private_key.can_exchange_keys_using(&exchange)?
35 );
36
37 match store.save_right(&second_right, &second_identifier) {
38 Ok(second) => {
39 let second_private_key = second.key()?;
40 if first_private_key.can_exchange_keys_using(&exchange)?
41 && second_private_key.can_exchange_keys_using(&exchange)?
42 {
43 let parameters = SecKeyExchangeParameters::with_requested_size(32)
44 .with_shared_info(b"localauthentication-rs");
45 let first_public_key = first_private_key.public_key()?.export_bytes()?;
46 let second_public_key = second_private_key.public_key()?.export_bytes()?;
47
48 match (
49 first_private_key.exchange_keys_with_public_key(
50 &second_public_key,
51 &exchange,
52 ¶meters,
53 ),
54 second_private_key.exchange_keys_with_public_key(
55 &first_public_key,
56 &exchange,
57 ¶meters,
58 ),
59 ) {
60 (Ok(first_secret), Ok(second_secret)) => {
61 println!("shared secret bytes: {}", first_secret.len());
62 println!("shared secrets match: {}", first_secret == second_secret);
63 }
64 (Err(error), _) | (_, Err(error)) => {
65 println!("key exchange requires additional system support: {error}");
66 }
67 }
68 }
69 store.remove_right(&second)?;
70 }
71 Err(error) => {
72 println!("key-exchange demo needs two persisted keys: {error}");
73 }
74 }
75
76 store.remove_right(&first)?;
77 }
78 Err(error) => {
79 println!("public-key APIs need entitlements on many systems: {error}");
80 }
81 }
82
83 println!("✅ public-key smoke OK");
84 Ok(())
85}