Skip to content

Commit

Permalink
Migrate away from Path towards PathBuf, see rust-lang/rust#23286
Browse files Browse the repository at this point in the history
  • Loading branch information
brainstorm committed Aug 14, 2023
1 parent 8d655c5 commit 91dfea3
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 51 deletions.
17 changes: 9 additions & 8 deletions src/bin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ fn retrieve_private_key(sk: Option<PathBuf>, generate: bool) -> Result<Vec<u8>,
let seckey_path = sk;

if generate && seckey_path.is_none() {
let skey = keys::generate_private_key();
let skey = keys::generate_private_key()?;
log::info!("Generating Private Key: {:02x?}", skey.iter().format(""));
Ok(skey)
}
Expand All @@ -95,7 +95,7 @@ fn retrieve_private_key(sk: Option<PathBuf>, generate: bool) -> Result<Vec<u8>,
}),
};

get_private_key(&path, callback)
get_private_key(path.to_owned(), callback)
}
}

Expand All @@ -111,7 +111,7 @@ fn build_recipients(recipient_pk: &[PathBuf], sk: &[u8]) -> Result<HashSet<Keys>
Ok(Keys {
method: 0,
privkey: sk.to_vec(),
recipient_pubkey: get_public_key(Path::new(pk))?,
recipient_pubkey: get_public_key(PathBuf::from(pk))?,
})
})
.collect()
Expand All @@ -138,7 +138,7 @@ fn run_encrypt(sk: Option<PathBuf>, recipient_pk: &[PathBuf], range: Option<Stri

fn run_decrypt(sk: Option<PathBuf>, sender_pk: Option<PathBuf>, range: Option<String>) -> Result<(), Crypt4GHError> {
let sender_pubkey = match sender_pk {
Some(path) => Some(keys::get_public_key(&path)?),
Some(path) => Some(keys::get_public_key(path)?),
None => None,
};

Expand Down Expand Up @@ -193,13 +193,13 @@ fn run_reencrypt(sk: Option<PathBuf>, recipient_pk: &[PathBuf], trim: bool) -> R
crypt4gh::reencrypt(&keys, &recipient_keys, &mut io::stdin(), &mut io::stdout(), trim)
}

fn run_keygen(sk: &Path, pk: &Path, comment: Option<String>, nocrypt: bool, force: bool) -> Result<(), Crypt4GHError> {
fn run_keygen(sk: PathBuf, pk: PathBuf, comment: Option<String>, nocrypt: bool, force: bool) -> Result<(), Crypt4GHError> {
// Prepare key files

let seckey = sk;
let pubkey = &pk;
let pubkey = pk;

for key in &[seckey, pubkey] {
for key in &[seckey, pubkey.to_owned()] {
// If key exists and it is a file
if key.is_file() {
// Force overwrite?
Expand All @@ -221,6 +221,7 @@ fn run_keygen(sk: &Path, pk: &Path, comment: Option<String>, nocrypt: bool, forc
// Comment
let comment = comment;
let do_crypt = !nocrypt;

let passphrase_callback = move || {
if do_crypt {
prompt_password(format!("Passphrase for {}: ", seckey.display()))
Expand Down Expand Up @@ -263,7 +264,7 @@ fn run() -> Result<(), Crypt4GHError> {
comment,
nocrypt,
force,
} => run_keygen(&sk, &pk, comment, nocrypt, force)?,
} => run_keygen(sk, pk, comment, nocrypt, force)?,
}

Ok(())
Expand Down
2 changes: 1 addition & 1 deletion src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ pub enum Crypt4GHError {
#[error("Invalid key format")]
InvalidKeyFormat,
#[error("Invalid PEM file length. The file ({0:?}) is not 3 lines long")]
InvalidPEMFormatLength(&'static Path),
InvalidPEMFormatLength(PathBuf),
#[error("Invalid PEM file header or footer: -----BEGIN or -----END")]
InvalidPEMHeaderOrFooter,
#[error("Invalid SSH key format")]
Expand Down
80 changes: 39 additions & 41 deletions src/keys.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,11 @@
#![warn(rustdoc::missing_doc_code_examples)]

use aes::cipher::{StreamCipher, generic_array::GenericArray};
use rand::{SeedableRng, Rng};
use rand_chacha;

use std::collections::HashMap;
use std::fs::File;
use std::io::{BufRead, BufReader, Cursor, Read, Write, BufWriter};
use std::path::Path;
use std::sync::Arc;
use std::path::PathBuf;

use base64::engine::general_purpose;
use base64::Engine;
Expand Down Expand Up @@ -57,9 +54,8 @@ lazy_static! {
.collect();
}

fn read_lines<P>(filename: P) -> Result<Vec<String>, Crypt4GHError>
fn read_lines(filename: &PathBuf) -> Result<Vec<String>, Crypt4GHError>
where
P: AsRef<Path>,
{
let file = File::open(filename)?;
Ok(BufReader::new(file)
Expand All @@ -68,13 +64,14 @@ where
.collect())
}

fn load_from_pem(filepath: &'static Path) -> Result<Vec<u8>, Crypt4GHError> {
fn load_from_pem(filepath: &PathBuf) -> Result<Vec<u8>, Crypt4GHError> {
// Read lines
let lines = read_lines(filepath).map_err(|e| Crypt4GHError::ReadLinesError(filepath.into(), e.into()))?;
let lines = read_lines(&filepath)
.map_err(|e| Crypt4GHError::ReadLinesError(filepath.to_owned(), Box::new(e)))?;

// Check format
if lines.len() < 3 {
return Err(Crypt4GHError::InvalidPEMFormatLength(filepath));
return Err(Crypt4GHError::InvalidPEMFormatLength(filepath.into()));
}

if lines.first().unwrap().starts_with("-----BEGIN ") ||
Expand All @@ -83,7 +80,7 @@ fn load_from_pem(filepath: &'static Path) -> Result<Vec<u8>, Crypt4GHError> {
}

// Decode with base64
general_purpose::STANDARD.decode(&lines[1..lines.len() - 1].join("")).map_err(|e| Crypt4GHError::BadBase64Error(e.into()))
general_purpose::STANDARD.decode(&lines[1..lines.len() - 1].join("")).map_err(move |e| Crypt4GHError::BadBase64Error(e.into()))
}

fn decode_string_ssh(stream: &mut impl BufRead) -> Result<Vec<u8>, Crypt4GHError> {
Expand Down Expand Up @@ -124,9 +121,10 @@ fn derive_key(
match alg {
"scrypt" => {
// TODO: Review last param of ScryptParams (length of what, exactly?) carefully.
// TODO: Why is the output not used?
// Added "dklen" for now since it seemed fitting, but needs proper review.
let params = scrypt::Params::new(14, 8, 1, dklen);
scrypt::scrypt(
let _ = scrypt::scrypt(
passphrase.as_bytes(),
&salt.unwrap_or_else(|| {
log::warn!("Using default salt = [0_u8; 8]");
Expand All @@ -137,7 +135,7 @@ fn derive_key(
);
},
"bcrypt" => {
bcrypt_pbkdf::bcrypt_pbkdf(
let _ = bcrypt_pbkdf::bcrypt_pbkdf(
passphrase.as_bytes(),
&salt.unwrap_or_else(|| {
log::warn!("Using default salt = [0_u8; 8]");
Expand Down Expand Up @@ -335,7 +333,8 @@ fn decipher(ciphername: &str, data: &[u8], private_ciphertext: &[u8]) -> Result<
assert!((private_ciphertext.len() % block_size(ciphername)?) == 0);

// Decipher
match ciphername {
// TODO: Why is this match not used? Was it used upstream?
let _ = match ciphername {
"aes128-ctr" => {
type Aes128Ctr = ctr::Ctr128LE<aes::Aes128>;
let iv_ga = GenericArray::from_slice(iv);
Expand Down Expand Up @@ -425,41 +424,40 @@ fn get_skpk_from_decrypted_private_blob(blob: &[u8]) -> Result<([u8; 32], [u8; 3
/// or if the key is not one of the two supported formats. Returns the decode key.
/// If the key is encrypted, the `callback` should return the passphrase of the key.
pub fn get_private_key(
key_path: &Path,
key_path: PathBuf,
callback: impl Fn() -> Result<String, Crypt4GHError>,
) -> Result<Vec<u8>, Crypt4GHError> {
todo!();
// let data = load_from_pem(key_path)?;

// if data.starts_with(C4GH_MAGIC_WORD) {
// log::info!("Loading a Crypt4GH private key");
// let mut stream = BufReader::new(data.as_slice());
// stream
// .read_exact(&mut [0_u8; C4GH_MAGIC_WORD.len()])
// .map_err(|e| Crypt4GHError::ReadMagicWord(e.into()))?;
// parse_c4gh_private_key(stream, callback)
// }
// else if data.starts_with(SSH_MAGIC_WORD) {
// log::info!("Loading an OpenSSH private key");
// let mut stream = BufReader::new(data.as_slice());
// stream
// .read_exact(&mut [0_u8; SSH_MAGIC_WORD.len()])
// .map_err(|e| Crypt4GHError::ReadMagicWord(e.into()))?;
// let (seckey, pubkey) = parse_ssh_private_key(stream, callback)?;
// Ok(vec![seckey, pubkey].concat())
// }
// else {
// Err(Crypt4GHError::InvalidKeyFormat)
// }
let data = load_from_pem(&key_path)?;

if data.starts_with(C4GH_MAGIC_WORD) {
log::info!("Loading a Crypt4GH private key");
let mut stream = BufReader::new(data.as_slice());
stream
.read_exact(&mut [0_u8; C4GH_MAGIC_WORD.len()])
.map_err(|e| Crypt4GHError::ReadMagicWord(e.into()))?;
parse_c4gh_private_key(stream, callback)
}
else if data.starts_with(SSH_MAGIC_WORD) {
log::info!("Loading an OpenSSH private key");
let mut stream = BufReader::new(data.as_slice());
stream
.read_exact(&mut [0_u8; SSH_MAGIC_WORD.len()])
.map_err(|e| Crypt4GHError::ReadMagicWord(e.into()))?;
let (seckey, pubkey) = parse_ssh_private_key(stream, callback)?;
Ok(vec![seckey, pubkey].concat())
}
else {
Err(Crypt4GHError::InvalidKeyFormat)
}
}

/// Reads and decodes the public key stored in `key_path`.
///
/// It supports `Crypt4GH` and OpenSSH public keys. Fails if it can not read the file
/// or if the key is not one of the two supported formats. Returns the decoded key.
pub fn get_public_key(key_path: &Path) -> Result<Vec<u8>, Crypt4GHError> {
pub fn get_public_key(key_path: PathBuf) -> Result<Vec<u8>, Crypt4GHError> {
// Read lines from public key file
match read_lines(key_path) {
match read_lines(&key_path) {
Ok(lines_vec) => {
// Empty key
if lines_vec.is_empty() {
Expand Down Expand Up @@ -537,8 +535,8 @@ pub fn generate_private_key() -> Result<Vec<u8>, Crypt4GHError> {
/// The passphrase callback should return a string that will be used to encode the keys. You can add
/// an optional comment at the end of the keys.
pub fn generate_keys(
seckey: &Path,
pubkey: &Path,
seckey: PathBuf,
pubkey: PathBuf,
passphrase_callback: impl Fn() -> Result<String, Crypt4GHError>,
comment: Option<String>,
) -> Result<(), Crypt4GHError> {
Expand Down
2 changes: 1 addition & 1 deletion tests/edit_list_gen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use std::io::Write;
use std::path::Path;

use rand::Rng;
use sodiumoxide::crypto::aead::chacha20poly1305_ietf;
//use sodiumoxide::crypto::aead::chacha20poly1305_ietf;

pub fn generate(sk: &str, recipient_pk: &str, input: &str, outfile: &mut File, passphrase: &str) {
let mut rng = rand::thread_rng();
Expand Down

0 comments on commit 91dfea3

Please sign in to comment.