diff options
| author | DanConwayDev <DanConwayDev@protonmail.com> | 2024-09-04 08:04:48 +0100 |
|---|---|---|
| committer | DanConwayDev <DanConwayDev@protonmail.com> | 2024-09-04 13:30:59 +0100 |
| commit | 949c6459aa7683453a7160423b689ceadb08954b (patch) | |
| tree | 230c26ecb11b99916e5570e548673eb09ecf0a36 /src/lib/login/key_encryption.rs | |
| parent | a825311f2c55661aaab3a163bda9109295c96044 (diff) | |
refactor: organise into lib and bin structure
the make the code more readable
this commit just moves the files, the next commit should fix the imports
Diffstat (limited to 'src/lib/login/key_encryption.rs')
| -rw-r--r-- | src/lib/login/key_encryption.rs | 105 |
1 files changed, 105 insertions, 0 deletions
diff --git a/src/lib/login/key_encryption.rs b/src/lib/login/key_encryption.rs new file mode 100644 index 0000000..3841d50 --- /dev/null +++ b/src/lib/login/key_encryption.rs | |||
| @@ -0,0 +1,105 @@ | |||
| 1 | use anyhow::Result; | ||
| 2 | use nostr::{prelude::*, Keys}; | ||
| 3 | |||
| 4 | pub fn encrypt_key(keys: &Keys, password: &str) -> Result<String> { | ||
| 5 | let log2_rounds: u8 = if password.len() > 20 { | ||
| 6 | // we have enough of entropy - no need to spend CPU time adding much more | ||
| 7 | 1 | ||
| 8 | } else { | ||
| 9 | println!("this may take a few seconds..."); | ||
| 10 | // default (scrypt::Params::RECOMMENDED_LOG_N) is 17 but 30s is too long to wait | ||
| 11 | 15 | ||
| 12 | }; | ||
| 13 | Ok(nostr::nips::nip49::EncryptedSecretKey::new( | ||
| 14 | keys.secret_key()?, | ||
| 15 | password, | ||
| 16 | log2_rounds, | ||
| 17 | KeySecurity::Medium, | ||
| 18 | )? | ||
| 19 | .to_bech32()?) | ||
| 20 | } | ||
| 21 | |||
| 22 | pub fn decrypt_key(encrypted_key: &str, password: &str) -> Result<nostr::Keys> { | ||
| 23 | let encrypted_key = nostr::nips::nip49::EncryptedSecretKey::from_bech32(encrypted_key)?; | ||
| 24 | // to request that log_n gets exposed | ||
| 25 | if encrypted_key.log_n() > 14 { | ||
| 26 | println!("this may take a few seconds..."); | ||
| 27 | } | ||
| 28 | Ok(nostr::Keys::new(encrypted_key.to_secret_key(password)?)) | ||
| 29 | } | ||
| 30 | |||
| 31 | #[cfg(test)] | ||
| 32 | mod tests { | ||
| 33 | use test_utils::*; | ||
| 34 | |||
| 35 | use super::*; | ||
| 36 | |||
| 37 | #[test] | ||
| 38 | fn encrypt_key_produces_string_prefixed_with() -> Result<()> { | ||
| 39 | let s = encrypt_key(&nostr::Keys::generate(), TEST_PASSWORD)?; | ||
| 40 | assert!(s.starts_with("ncryptsec")); | ||
| 41 | Ok(()) | ||
| 42 | } | ||
| 43 | |||
| 44 | #[test] | ||
| 45 | // ensures password encryption hasn't changed | ||
| 46 | fn decrypts_with_strong_password_from_reference_string() -> Result<()> { | ||
| 47 | let decrypted_key = decrypt_key(TEST_KEY_1_ENCRYPTED, TEST_PASSWORD)?; | ||
| 48 | |||
| 49 | assert_eq!( | ||
| 50 | format!( | ||
| 51 | "{}", | ||
| 52 | TEST_KEY_1_KEYS.secret_key().unwrap().to_bech32().unwrap() | ||
| 53 | ), | ||
| 54 | format!( | ||
| 55 | "{}", | ||
| 56 | decrypted_key.secret_key().unwrap().to_bech32().unwrap() | ||
| 57 | ), | ||
| 58 | ); | ||
| 59 | Ok(()) | ||
| 60 | } | ||
| 61 | |||
| 62 | #[test] | ||
| 63 | // ensures password encryption hasn't changed | ||
| 64 | fn decrypts_with_weak_password_from_reference_string() -> Result<()> { | ||
| 65 | let decrypted_key = decrypt_key(TEST_KEY_1_ENCRYPTED_WEAK, TEST_WEAK_PASSWORD)?; | ||
| 66 | |||
| 67 | assert_eq!( | ||
| 68 | format!( | ||
| 69 | "{}", | ||
| 70 | TEST_KEY_1_KEYS.secret_key().unwrap().to_bech32().unwrap() | ||
| 71 | ), | ||
| 72 | format!( | ||
| 73 | "{}", | ||
| 74 | decrypted_key.secret_key().unwrap().to_bech32().unwrap() | ||
| 75 | ), | ||
| 76 | ); | ||
| 77 | Ok(()) | ||
| 78 | } | ||
| 79 | |||
| 80 | #[test] | ||
| 81 | fn decrypts_key_encrypted_using_encrypt_key() -> Result<()> { | ||
| 82 | let key = nostr::Keys::generate(); | ||
| 83 | let s = encrypt_key(&key, TEST_PASSWORD)?; | ||
| 84 | let newkey = decrypt_key(s.as_str(), TEST_PASSWORD)?; | ||
| 85 | |||
| 86 | assert_eq!( | ||
| 87 | format!("{}", key.secret_key().unwrap().to_bech32().unwrap()), | ||
| 88 | format!("{}", newkey.secret_key().unwrap().to_bech32().unwrap()), | ||
| 89 | ); | ||
| 90 | Ok(()) | ||
| 91 | } | ||
| 92 | |||
| 93 | #[test] | ||
| 94 | fn decrypt_key_successfully_decrypts_key_encrypted_using_encrypt_key() -> Result<()> { | ||
| 95 | let key = nostr::Keys::generate(); | ||
| 96 | let s = encrypt_key(&key, TEST_PASSWORD)?; | ||
| 97 | let newkey = decrypt_key(s.as_str(), TEST_PASSWORD)?; | ||
| 98 | |||
| 99 | assert_eq!( | ||
| 100 | format!("{}", key.secret_key().unwrap().to_bech32().unwrap()), | ||
| 101 | format!("{}", newkey.secret_key().unwrap().to_bech32().unwrap()), | ||
| 102 | ); | ||
| 103 | Ok(()) | ||
| 104 | } | ||
| 105 | } | ||