myc

Self-custodial remote signer for Radroots apps
git clone https://radroots.dev/git/myc.git
Log | Files | Refs | README | LICENSE

identity_files.rs (3815B)


      1 use std::path::{Path, PathBuf};
      2 
      3 use radroots_identity::{
      4     IdentityError, RadrootsIdentity, RadrootsIdentityPublic,
      5     encrypted_identity_wrapping_key_path as shared_encrypted_identity_wrapping_key_path,
      6     load_encrypted_identity_with_key_slot, load_identity_profile as load_shared_identity_profile,
      7     rotate_encrypted_identity_with_key_slot, store_encrypted_identity_with_key_slot,
      8     store_identity_profile as store_shared_identity_profile,
      9 };
     10 
     11 const MYC_ENCRYPTED_IDENTITY_KEY_SLOT: &str = "myc_identity";
     12 
     13 pub fn encrypted_identity_wrapping_key_path(path: impl AsRef<Path>) -> PathBuf {
     14     shared_encrypted_identity_wrapping_key_path(path)
     15 }
     16 
     17 pub fn store_encrypted_identity(
     18     path: impl AsRef<Path>,
     19     identity: &RadrootsIdentity,
     20 ) -> Result<(), IdentityError> {
     21     store_encrypted_identity_with_key_slot(path, MYC_ENCRYPTED_IDENTITY_KEY_SLOT, identity)
     22 }
     23 
     24 pub fn rotate_encrypted_identity(path: impl AsRef<Path>) -> Result<(), IdentityError> {
     25     rotate_encrypted_identity_with_key_slot(path, MYC_ENCRYPTED_IDENTITY_KEY_SLOT)
     26 }
     27 
     28 pub fn load_encrypted_identity(path: impl AsRef<Path>) -> Result<RadrootsIdentity, IdentityError> {
     29     load_encrypted_identity_with_key_slot(path, MYC_ENCRYPTED_IDENTITY_KEY_SLOT)
     30 }
     31 
     32 pub fn load_identity_profile(
     33     path: impl AsRef<Path>,
     34 ) -> Result<RadrootsIdentityPublic, IdentityError> {
     35     load_shared_identity_profile(path)
     36 }
     37 
     38 pub fn store_identity_profile(
     39     path: impl AsRef<Path>,
     40     identity: &RadrootsIdentity,
     41 ) -> Result<(), IdentityError> {
     42     store_shared_identity_profile(path, identity)
     43 }
     44 
     45 #[cfg(test)]
     46 mod tests {
     47     use super::*;
     48 
     49     #[test]
     50     fn encrypted_identity_round_trips() {
     51         let temp = tempfile::tempdir().expect("tempdir");
     52         let path = temp.path().join("identity.enc.json");
     53         let identity = RadrootsIdentity::from_secret_key_str(
     54             "1111111111111111111111111111111111111111111111111111111111111111",
     55         )
     56         .expect("identity");
     57 
     58         store_encrypted_identity(&path, &identity).expect("store encrypted identity");
     59 
     60         let loaded = load_encrypted_identity(&path).expect("load encrypted identity");
     61         assert_eq!(loaded.id(), identity.id());
     62         assert_eq!(loaded.secret_key_hex(), identity.secret_key_hex());
     63         assert!(encrypted_identity_wrapping_key_path(&path).is_file());
     64     }
     65 
     66     #[test]
     67     fn encrypted_identity_rotation_rewraps_key() {
     68         let temp = tempfile::tempdir().expect("tempdir");
     69         let path = temp.path().join("identity.enc.json");
     70         let identity = RadrootsIdentity::from_secret_key_str(
     71             "1111111111111111111111111111111111111111111111111111111111111111",
     72         )
     73         .expect("identity");
     74 
     75         store_encrypted_identity(&path, &identity).expect("store encrypted identity");
     76         let key_path = encrypted_identity_wrapping_key_path(&path);
     77         let before = std::fs::read(&key_path).expect("key before");
     78 
     79         rotate_encrypted_identity(&path).expect("rotate encrypted identity");
     80 
     81         let after = std::fs::read(&key_path).expect("key after");
     82         assert_ne!(before, after);
     83         let loaded = load_encrypted_identity(&path).expect("load rotated identity");
     84         assert_eq!(loaded.secret_key_hex(), identity.secret_key_hex());
     85     }
     86 
     87     #[test]
     88     fn identity_profile_round_trips() {
     89         let temp = tempfile::tempdir().expect("tempdir");
     90         let path = temp.path().join("profile.json");
     91         let identity = RadrootsIdentity::from_secret_key_str(
     92             "1111111111111111111111111111111111111111111111111111111111111111",
     93         )
     94         .expect("identity");
     95 
     96         store_identity_profile(&path, &identity).expect("store profile");
     97 
     98         let loaded = load_identity_profile(&path).expect("load profile");
     99         assert_eq!(loaded.id, identity.id());
    100     }
    101 }