Skip to content

Commit

Permalink
fix: don't give invalid password error for other keyfile errors (#247)
Browse files Browse the repository at this point in the history
  • Loading branch information
aawsome authored Sep 6, 2024
1 parent 29b244f commit 4bda67a
Show file tree
Hide file tree
Showing 7 changed files with 63 additions and 4 deletions.
2 changes: 1 addition & 1 deletion crates/core/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ pub type RusticResult<T> = Result<T, RusticError>;
#[derive(Error, Debug)]
#[error(transparent)]
/// Errors that can result from rustic.
pub struct RusticError(#[from] RusticErrorKind);
pub struct RusticError(#[from] pub(crate) RusticErrorKind);

// Accessors for anything we do want to expose publicly.
impl RusticError {
Expand Down
11 changes: 8 additions & 3 deletions crates/core/src/repofile/keyfile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@ use serde_with::{base64::Base64, serde_as};
use crate::{
backend::{FileType, ReadBackend},
crypto::{aespoly1305::Key, CryptoKey},
error::{KeyFileErrorKind, RusticErrorKind, RusticResult},
error::{CryptoErrorKind, KeyFileErrorKind, RusticErrorKind, RusticResult},
id::Id,
RusticError,
};

pub(super) mod constants {
Expand Down Expand Up @@ -333,8 +334,12 @@ pub(crate) fn find_key_in_backend<B: ReadBackend>(
key_from_backend(be, id, passwd)
} else {
for id in be.list(FileType::Key).map_err(RusticErrorKind::Backend)? {
if let Ok(key) = key_from_backend(be, &id, passwd) {
return Ok(key);
match key_from_backend(be, &id, passwd) {
Ok(key) => return Ok(key),
Err(RusticError(RusticErrorKind::Crypto(
CryptoErrorKind::DataDecryptionFailed(_),
))) => continue,
err => return err,
}
}
Err(KeyFileErrorKind::NoSuitableKeyFound.into())
Expand Down
1 change: 1 addition & 0 deletions crates/core/tests/fixtures/config
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
q۝�)aiƚ6��U��`\@�i����Mː[�<㴉J�z�+۶'��~N���|{7X�TM�F�8���l n�f����P��qB`om�Œ� ��8�4#��&�"�1�6Q/қ�ו�L�*:p%� ���nc �ᙣ��.�ȗ�_�G�
1 change: 1 addition & 0 deletions crates/core/tests/fixtures/key-failing
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"kdf":"scrypt","N":262144,"r":1,"p":1,"salt":"onIvDlHSFQHnmhBHIGD0WNY3GceOFTaxzxy7YgeSiqva+GhPRrH1+jxuxwcWiEg+WW55C3KurmLNhgZ1DJ75GA==","data":"PZUCr1IJQuOrgE2wKC26phAkP/CIFnvBJ+JEGub8DB4FRJ/nGvVPFr+pQRAE9GUbwHbdKYoZVVciYc0E8S5ggurAcu8VSdoRIg8z4iabKBi1YrTkG0+EZY+rlpm95LMfoDgeY6XxQ6egSd3GSk0WfT//YH7duDkCK3rYIczhOXWOCqzKR85z11YW1pB7uUDc2yiRXm+B5rrivz+ntb0wIg=="}
1 change: 1 addition & 0 deletions crates/core/tests/fixtures/key1
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"kdf":"scrypt","N":32768,"r":8,"p":6,"salt":"onIvDlHSFQHnmhBHIGD0WNY3GceOFTaxzxy7YgeSiqva+GhPRrH1+jxuxwcWiEg+WW55C3KurmLNhgZ1DJ75GA==","data":"PZUCr1IJQuOrgE2wKC26phAkP/CIFnvBJ+JEGub8DB4FRJ/nGvVPFr+pQRAE9GUbwHbdKYoZVVciYc0E8S5ggurAcu8VSdoRIg8z4iabKBi1YrTkG0+EZY+rlpm95LMfoDgeY6XxQ6egSd3GSk0WfT//YH7duDkCK3rYIczhOXWOCqzKR85z11YW1pB7uUDc2yiRXm+B5rrivz+ntb0wIg=="}
1 change: 1 addition & 0 deletions crates/core/tests/fixtures/key2
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"kdf":"scrypt","N":131072,"r":8,"p":1,"data":"WrMLrTa/yGbDAZmftGe10/34wf7YQmzgex78J2U23ngNS/V5alQ0yxeoKghzUgWUja2K2KlnXtrFG9H/SNyNCyiCjZePZyaP21KtqyTJEPWw44WnX60iN0sOvKaoPgutIUMjyIvGej6zCoocu777ZiLbmOWRa1uF3rAcnyja8S1QTP+mST8A18TWTblcBjRPcRmyW/fZmNA7OrccQqz6kA==","salt":"vxXAZGxn56VRe2Zy/MBV1I97Wgi0xVhye89qz9oXruorYgWyewle5ZqkepZwXWhsyIzuWKWIVNsZigAzx064Hg=="}
50 changes: 50 additions & 0 deletions crates/core/tests/keys.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
use std::{fs::File, io::Read, sync::Arc};

use anyhow::Result;
use rstest::rstest;
use rustic_core::{FileType, Id, Repository, RepositoryBackends, RepositoryOptions, WriteBackend};
use rustic_testing::backend::in_memory_backend::InMemoryBackend;
use sha2::{Digest, Sha256};

#[rstest]
#[case("test", true)]
#[case("test2", true)]
#[case("wrong", false)]
fn working_keys(#[case] password: &str, #[case] should_work: bool) -> Result<()> {
let be = InMemoryBackend::new();
add_to_be(&be, FileType::Config, "tests/fixtures/config")?;
add_to_be(&be, FileType::Key, "tests/fixtures/key1")?;
add_to_be(&be, FileType::Key, "tests/fixtures/key2")?;

let be = RepositoryBackends::new(Arc::new(be), None);
let options = RepositoryOptions::default().password(password);
let repo = Repository::new(&options, &be)?;
if should_work {
assert!(repo.open().is_ok());
} else {
assert!(repo.open().is_err_and(|err| err.is_incorrect_password()));
}
Ok(())
}

#[test]
// using an invalid keyfile: Here the scrypt params are not valid
fn failing_key() -> Result<()> {
let be = InMemoryBackend::new();
add_to_be(&be, FileType::Config, "tests/fixtures/config")?;
add_to_be(&be, FileType::Key, "tests/fixtures/key-failing")?;

let be = RepositoryBackends::new(Arc::new(be), None);
let options = RepositoryOptions::default().password("test");
let repo = Repository::new(&options, &be)?;
assert!(repo.open().is_err_and(|err| !err.is_incorrect_password()));
Ok(())
}

fn add_to_be(be: &impl WriteBackend, tpe: FileType, file: &str) -> Result<()> {
let mut bytes = Vec::new();
_ = File::open(file)?.read_to_end(&mut bytes)?;
let id = Id::new(Sha256::digest(&bytes).into());
be.write_bytes(tpe, &id, true, bytes.into())?;
Ok(())
}

0 comments on commit 4bda67a

Please sign in to comment.