Zeroize passphrases

Signed-off-by: Alexis Sellier <alexis@radicle.xyz>
This commit is contained in:
Alexis Sellier 2022-11-03 16:52:29 +01:00
parent 6e8e1e0972
commit dc79130988
No known key found for this signature in database
3 changed files with 19 additions and 8 deletions

View File

@ -7,6 +7,9 @@ use zeroize::Zeroizing;
use crate::{KeyPair, PublicKey, SecretKey, Signature, Signer, SignerError};
/// A secret key passphrase.
pub type Passphrase = Zeroizing<String>;
#[derive(Debug, Error)]
pub enum Error {
#[error(transparent)]
@ -83,7 +86,10 @@ impl Keystore {
/// Load the secret key from the store, decrypting it with the given passphrase.
/// Returns `None` if it wasn't found.
pub fn secret_key(&self, passphrase: &str) -> Result<Option<Zeroizing<SecretKey>>, Error> {
pub fn secret_key(
&self,
passphrase: Passphrase,
) -> Result<Option<Zeroizing<SecretKey>>, Error> {
let path = self.path.join("radicle");
if !path.exists() {
return Ok(None);
@ -135,7 +141,7 @@ impl Signer for MemorySigner {
impl MemorySigner {
/// Load this signer from a keystore, given a secret key passphrase.
pub fn load(keystore: &Keystore, passphrase: &str) -> Result<Self, MemorySignerError> {
pub fn load(keystore: &Keystore, passphrase: Passphrase) -> Result<Self, MemorySignerError> {
let public = keystore
.public_key()?
.ok_or_else(|| MemorySignerError::NotFound(keystore.path().to_path_buf()))?;
@ -177,10 +183,13 @@ mod tests {
let public = store.init("test", "hunter").unwrap();
assert_eq!(public, store.public_key().unwrap().unwrap());
let secret = store.secret_key("hunter").unwrap().unwrap();
let secret = store
.secret_key("hunter".to_owned().into())
.unwrap()
.unwrap();
assert_eq!(PublicKey::from(secret.public_key()), public);
store.secret_key("blunder").unwrap_err(); // Wrong passphrase.
store.secret_key("blunder".to_owned().into()).unwrap_err(); // Wrong passphrase.
}
#[test]
@ -189,7 +198,7 @@ mod tests {
let store = Keystore::new(&tmp.path());
let public = store.init("test", "hunter").unwrap();
let signer = MemorySigner::load(&store, "hunter").unwrap();
let signer = MemorySigner::load(&store, "hunter".to_owned().into()).unwrap();
assert_eq!(public, *signer.public_key());
}

View File

@ -57,8 +57,9 @@ fn main() -> anyhow::Result<()> {
Err(err) => {
let passphrase = env::var(profile::env::RAD_PASSPHRASE)
.context("Either ssh-agent must be initialized, or `RAD_PASSPHRASE` must be set")
.context(err)?;
MemorySigner::load(&profile.keystore, &passphrase)?.boxed()
.context(err)?
.into();
MemorySigner::load(&profile.keystore, passphrase)?.boxed()
}
};
let handle = client.handle();

View File

@ -18,9 +18,10 @@ fn main() -> anyhow::Result<()> {
let mut passphrase = String::new();
io::stdin().lock().read_line(&mut passphrase)?;
let passphrase = passphrase.trim().to_owned().into();
let secret = profile
.keystore
.secret_key(passphrase.trim())?
.secret_key(passphrase)?
.ok_or_else(|| anyhow!("Key not found in {:?}", profile.keystore.path()))?;
agent.register(&secret)?;