commit 682b0f6a650151b18d0b86c656bde9f55da66f45
parent 38d6d6338c53f0bd4c9731158d3f97004760c6de
Author: Stefan Koch <programming@stefan-koch.name>
Date: Sun, 24 Nov 2019 11:38:28 +0100
let user input password on encrypt and decrypt
Diffstat:
5 files changed, 39 insertions(+), 17 deletions(-)
diff --git a/Cargo.lock b/Cargo.lock
@@ -88,6 +88,7 @@ dependencies = [
"lettre_email 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rmp-serde 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rpassword 4.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.100 (registry+https://github.com/rust-lang/crates.io-index)",
"sodiumoxide 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
"tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -726,6 +727,15 @@ dependencies = [
]
[[package]]
+name = "rpassword"
+version = "4.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
name = "ryu"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1043,6 +1053,7 @@ dependencies = [
"checksum rle-decode-fast 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cabe4fa914dec5870285fa7f71f602645da47c486e68486d2b4ceb4a343e90ac"
"checksum rmp 0.8.8 (registry+https://github.com/rust-lang/crates.io-index)" = "0f594cb7ff8f1c5a7907f6be91f15795c8301e0d5718eb007fb5832723dd716e"
"checksum rmp-serde 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4a31c0798045f039ace94e0166f76478b3ba83116ec7c9d4bc934c5b13b8df21"
+"checksum rpassword 4.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f072d931f11a96546efd97642e1e75e807345aced86b947f9239102f262d0fcd"
"checksum ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c92464b447c0ee8c4fb3824ecc8383b81717b9f1e74ba2e72540aef7b9f82997"
"checksum safemem 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d2b08423011dae9a5ca23f07cf57dac3857f5c885d352b76f6d95f4aea9434d0"
"checksum schannel 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "87f550b06b6cba9c8b8be3ee73f391990116bf527450d2556e9b9ce263b9a021"
diff --git a/Cargo.toml b/Cargo.toml
@@ -15,6 +15,7 @@ evalexpr = "5"
lettre = "0.9"
lettre_email = "0.9"
sodiumoxide = "0.2.5"
+rpassword = "4.0"
[dev-dependencies]
tempfile = "3"
diff --git a/src/crypto.rs b/src/crypto.rs
@@ -7,20 +7,18 @@ use sodiumoxide::crypto::secretbox::{self, Key, Nonce};
use sodiumoxide::crypto::pwhash::{self, Salt};
#[derive(Serialize, Deserialize)]
-pub struct CryptoFile {
+struct CryptoFile {
pwsalt: Salt,
nonce: Nonce,
content: Vec<u8>,
}
-pub struct SaltedKey {
+struct SaltedKey {
pwsalt: Salt,
key: Key,
}
-pub fn gen_key_from_pw(password: &str) -> SaltedKey {
- let salt = pwhash::gen_salt();
-
+fn gen_salted_key(password: &str, salt: Salt) -> SaltedKey {
// cf. https://docs.rs/sodiumoxide/0.2.5/sodiumoxide/crypto/pwhash/index.html#example-key-derivation
let mut k = secretbox::Key([0; secretbox::KEYBYTES]);
{
@@ -36,8 +34,13 @@ pub fn gen_key_from_pw(password: &str) -> SaltedKey {
}
}
+fn gen_salted_key_random_salt(password: &str) -> SaltedKey {
+ let salt = pwhash::gen_salt();
+ gen_salted_key(password, salt)
+}
+
pub fn encrypt_string(plaintext: &str, password: &str) -> Vec<u8> {
- let salted_key = gen_key_from_pw(password);
+ let salted_key = gen_salted_key_random_salt(password);
let nonce = secretbox::gen_nonce();
let ciphertext = secretbox::seal(plaintext.as_bytes(),
&nonce, &salted_key.key);
@@ -51,11 +54,11 @@ pub fn encrypt_string(plaintext: &str, password: &str) -> Vec<u8> {
rmp_serde::to_vec(&f).unwrap()
}
-pub fn decrypt_file(filepath: &str) -> String {
+pub fn decrypt_file(filepath: &str, password: &str) -> Result<String, ()> {
let r = File::open(filepath).unwrap();
let f: CryptoFile = rmp_serde::from_read(r).unwrap();
- let key = secretbox::gen_key();
+ let salted_key = gen_salted_key(password, f.pwsalt);
- let bytes = secretbox::open(&f.content, &f.nonce, &key).unwrap();
- String::from_utf8(bytes).unwrap()
+ secretbox::open(&f.content, &f.nonce, &salted_key.key)
+ .map(|bytes| String::from_utf8(bytes).unwrap())
}
diff --git a/src/lib.rs b/src/lib.rs
@@ -127,14 +127,16 @@ pub fn run(exec_config: &ExecutionConfig) {
}
}
-pub fn encrypt(filepath: String) {
+pub fn encrypt(filepath: String, password: &str) {
let plaintext = "some data";
- let cipher = crypto::encrypt_string(plaintext, "my-password");
+ let cipher = crypto::encrypt_string(plaintext, password);
fs::write(filepath, cipher).expect("Unable to write file");
}
-pub fn decrypt(filepath: String) {
- let plaintext = crypto::decrypt_file(&filepath);
- println!("{}", plaintext);
+pub fn decrypt(filepath: String, password: &str) {
+ match crypto::decrypt_file(&filepath, password) {
+ Ok(plaintext) => println!("{}", plaintext),
+ _ => println!("Cannot decrypt, probably wrong password"),
+ }
}
diff --git a/src/main.rs b/src/main.rs
@@ -1,5 +1,6 @@
use std::env;
+use rpassword;
use getopts::Options;
use cinderella::ExecutionConfig;
@@ -29,7 +30,9 @@ fn encrypt(args: Vec<String>) {
} else {
let filepath = args[2].clone();
- cinderella::encrypt(filepath);
+ let pass = rpassword::read_password_from_tty(Some("Password: ")).unwrap();
+
+ cinderella::encrypt(filepath, &pass);
}
}
@@ -39,7 +42,9 @@ fn decrypt(args: Vec<String>) {
} else {
let filepath = args[2].clone();
- cinderella::decrypt(filepath);
+ let pass = rpassword::read_password_from_tty(Some("Password: ")).unwrap();
+
+ cinderella::decrypt(filepath, &pass);
}
}