Switch to BLAKE2b & Use the same salt for Argon2 and HKDF
This commit is contained in:
parent
5ada55a93d
commit
ed7a227080
55
Cargo.lock
generated
55
Cargo.lock
generated
@ -8,7 +8,7 @@ version = "0.7.4"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "495ee669413bfbe9e8cace80f4d3d78e6d8c8d99579f97fb93bde351b185f2d4"
|
checksum = "495ee669413bfbe9e8cace80f4d3d78e6d8c8d99579f97fb93bde351b185f2d4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if 1.0.0",
|
"cfg-if",
|
||||||
"cipher",
|
"cipher",
|
||||||
"cpufeatures",
|
"cpufeatures",
|
||||||
"ctr",
|
"ctr",
|
||||||
@ -34,18 +34,6 @@ dependencies = [
|
|||||||
"password-hash",
|
"password-hash",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "arrayref"
|
|
||||||
version = "0.3.6"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "arrayvec"
|
|
||||||
version = "0.5.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "assert_cmd"
|
name = "assert_cmd"
|
||||||
version = "1.0.6"
|
version = "1.0.6"
|
||||||
@ -94,21 +82,6 @@ dependencies = [
|
|||||||
"opaque-debug",
|
"opaque-debug",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "blake3"
|
|
||||||
version = "0.3.8"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "b64485778c4f16a6a5a9d335e80d449ac6c70cdd6a06d2af18a6f6f775a125b3"
|
|
||||||
dependencies = [
|
|
||||||
"arrayref",
|
|
||||||
"arrayvec",
|
|
||||||
"cc",
|
|
||||||
"cfg-if 0.1.10",
|
|
||||||
"constant_time_eq",
|
|
||||||
"crypto-mac 0.8.0",
|
|
||||||
"digest",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bstr"
|
name = "bstr"
|
||||||
version = "0.2.16"
|
version = "0.2.16"
|
||||||
@ -120,18 +93,6 @@ dependencies = [
|
|||||||
"regex-automata",
|
"regex-automata",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "cc"
|
|
||||||
version = "1.0.68"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "4a72c244c1ff497a746a7e1fb3d14bd08420ecda70c8f25c7112f2781652d787"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "cfg-if"
|
|
||||||
version = "0.1.10"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cfg-if"
|
name = "cfg-if"
|
||||||
version = "1.0.0"
|
version = "1.0.0"
|
||||||
@ -144,7 +105,7 @@ version = "0.7.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "fee7ad89dc1128635074c268ee661f90c3f7e83d9fd12910608c36b47d6c3412"
|
checksum = "fee7ad89dc1128635074c268ee661f90c3f7e83d9fd12910608c36b47d6c3412"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if 1.0.0",
|
"cfg-if",
|
||||||
"cipher",
|
"cipher",
|
||||||
"cpufeatures",
|
"cpufeatures",
|
||||||
]
|
]
|
||||||
@ -173,12 +134,6 @@ dependencies = [
|
|||||||
"vec_map",
|
"vec_map",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "constant_time_eq"
|
|
||||||
version = "0.1.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cpufeatures"
|
name = "cpufeatures"
|
||||||
version = "0.1.5"
|
version = "0.1.5"
|
||||||
@ -250,7 +205,7 @@ dependencies = [
|
|||||||
"aes",
|
"aes",
|
||||||
"argon2",
|
"argon2",
|
||||||
"assert_cmd",
|
"assert_cmd",
|
||||||
"blake3",
|
"blake2",
|
||||||
"chacha20",
|
"chacha20",
|
||||||
"clap",
|
"clap",
|
||||||
"cpufeatures",
|
"cpufeatures",
|
||||||
@ -285,7 +240,7 @@ version = "0.2.3"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753"
|
checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if 1.0.0",
|
"cfg-if",
|
||||||
"libc",
|
"libc",
|
||||||
"wasi",
|
"wasi",
|
||||||
]
|
]
|
||||||
@ -544,7 +499,7 @@ version = "3.2.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22"
|
checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if 1.0.0",
|
"cfg-if",
|
||||||
"libc",
|
"libc",
|
||||||
"rand",
|
"rand",
|
||||||
"redox_syscall",
|
"redox_syscall",
|
||||||
|
@ -22,7 +22,7 @@ cpufeatures = "0.1"
|
|||||||
aes = { version = "0.7", features = ["ctr"] }
|
aes = { version = "0.7", features = ["ctr"] }
|
||||||
chacha20 = "0.7"
|
chacha20 = "0.7"
|
||||||
hmac = "0.11"
|
hmac = "0.11"
|
||||||
blake3 = "0.3"
|
blake2 = "0.9"
|
||||||
hkdf = "0.11"
|
hkdf = "0.11"
|
||||||
argon2 = "0.2"
|
argon2 = "0.2"
|
||||||
rpassword = "5.0"
|
rpassword = "5.0"
|
||||||
|
23
README.md
23
README.md
@ -9,7 +9,7 @@ doby started as a fork of [aef](https://github.com/wyhaya/aef) by [wyhaya](https
|
|||||||
* Fast: written in [rust](https://www.rust-lang.org), encrypts with [AES-256-CTR](https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Counter_(CTR)) or [XChaCha20](https://en.wikipedia.org/wiki/Salsa20#XChaCha)
|
* Fast: written in [rust](https://www.rust-lang.org), encrypts with [AES-256-CTR](https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Counter_(CTR)) or [XChaCha20](https://en.wikipedia.org/wiki/Salsa20#XChaCha)
|
||||||
* [HMAC](https://en.wikipedia.org/wiki/HMAC) ciphertext authentication
|
* [HMAC](https://en.wikipedia.org/wiki/HMAC) ciphertext authentication
|
||||||
* Password brute-force resistance with [Argon2](https://en.wikipedia.org/wiki/Argon2)
|
* Password brute-force resistance with [Argon2](https://en.wikipedia.org/wiki/Argon2)
|
||||||
* Increase the plaintext size of only 190 bytes
|
* Increase the plaintext size of only 158 bytes
|
||||||
* Encryption from STDIN/STDOUT or from files
|
* Encryption from STDIN/STDOUT or from files
|
||||||
* Adjustable performance & secuity parameters
|
* Adjustable performance & secuity parameters
|
||||||
|
|
||||||
@ -113,37 +113,36 @@ doby first derives your password with Argon2 (version 19) in Argon2id mode with
|
|||||||
```rust
|
```rust
|
||||||
let master_key: [u8; 32] = argon2id(
|
let master_key: [u8; 32] = argon2id(
|
||||||
password,
|
password,
|
||||||
random_password_salt,
|
random_salt,
|
||||||
argon2_time_cost,
|
argon2_time_cost,
|
||||||
argon2_memory_cost,
|
argon2_memory_cost,
|
||||||
argon2_parallelism,
|
argon2_parallelism,
|
||||||
);
|
);
|
||||||
```
|
```
|
||||||
|
|
||||||
Then, doby uses [HKDF](https://en.wikipedia.org/wiki/HKDF) with a new random salt to compute the `encryption_key` and the `authentication_key`.
|
Then, doby uses [HKDF](https://en.wikipedia.org/wiki/HKDF) with the previous random salt to compute the `encryption_key` and the `authentication_key`.
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
let hkdf = Hkdf::new(
|
let hkdf = Hkdf::new(
|
||||||
random_hkdf_salt,
|
random_salt,
|
||||||
master_key, //ikm
|
master_key, //ikm
|
||||||
blake3, //hash function
|
blake2b, //hash function
|
||||||
);
|
);
|
||||||
let encryption_key: [u8; 32] = hkdf.expand(b"doby_encryption_key");
|
let encryption_key: [u8; 32] = hkdf.expand(b"doby_encryption_key");
|
||||||
let authentication_key: [u8; 32] = hkdf.expand(b"doby_authentication_key");
|
let authentication_key: [u8; 32] = hkdf.expand(b"doby_authentication_key");
|
||||||
```
|
```
|
||||||
|
|
||||||
Next, doby initializes a [BLAKE3](https://en.wikipedia.org/wiki/BLAKE_%28hash_function%29#BLAKE3) HMAC with `authentication_key` and add all public encryption parameters to it.
|
Next, doby initializes a [BLAKE2b](https://en.wikipedia.org/wiki/BLAKE_(hash_function)#BLAKE2) HMAC with `authentication_key` and add all public encryption parameters to it.
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
let hmac = Hmac::new(
|
let hmac = Hmac::new(
|
||||||
authentication_key,
|
authentication_key,
|
||||||
blake3, //hash function
|
blake2b, //hash function
|
||||||
);
|
);
|
||||||
hmac.update(random_password_salt);
|
hmac.update(random_salt);
|
||||||
hmac.update(argon2_time_cost);
|
hmac.update(argon2_time_cost);
|
||||||
hmac.update(argon2_memory_cost);
|
hmac.update(argon2_memory_cost);
|
||||||
hmac.update(argon2_parallelism);
|
hmac.update(argon2_parallelism);
|
||||||
hmac.update(random_hkdf_salt);
|
|
||||||
hmac.update(cipher); //1-byte representation of the symmetric cipher used to encrypt (either AES-CTR or XChaCha20)
|
hmac.update(cipher); //1-byte representation of the symmetric cipher used to encrypt (either AES-CTR or XChaCha20)
|
||||||
hmac.update(random_nonce); //random nonce used for encryption (16 bytes for AES-CTR, 24 for XChaCha20)
|
hmac.update(random_nonce); //random nonce used for encryption (16 bytes for AES-CTR, 24 for XChaCha20)
|
||||||
```
|
```
|
||||||
@ -177,14 +176,14 @@ doby reads the public encryption values from the input header to get all paramet
|
|||||||
```rust
|
```rust
|
||||||
let master_key: [u8; 32] = argon2id(
|
let master_key: [u8; 32] = argon2id(
|
||||||
password,
|
password,
|
||||||
password_salt_read_from_input,
|
salt_read_from_input,
|
||||||
argon2_time_cost_read_from_input,
|
argon2_time_cost_read_from_input,
|
||||||
argon2_memory_cost_read_from_input,
|
argon2_memory_cost_read_from_input,
|
||||||
argon2_parallelism_read_from_input,
|
argon2_parallelism_read_from_input,
|
||||||
);
|
);
|
||||||
```
|
```
|
||||||
|
|
||||||
`encryption_key` and `authentication_key` are computed from `master_key` and the HKDF salt in the same way as during encryption. The HMAC is also initialized and updated with the values read from the header.
|
`encryption_key` and `authentication_key` are computed from `master_key` in the same way as during encryption. The HMAC is also initialized and updated with the values read from the header.
|
||||||
|
|
||||||
Then, doby starts decryption.
|
Then, doby starts decryption.
|
||||||
|
|
||||||
@ -203,7 +202,7 @@ while n != 0 {
|
|||||||
Once the whole ciphertext is decrypted, doby computes and verifies the HMAC.
|
Once the whole ciphertext is decrypted, doby computes and verifies the HMAC.
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
hmac.digest() == last_32_bytes_read
|
hmac.digest() == last_64_bytes_read // the default blake2b output size is 64 bytes
|
||||||
```
|
```
|
||||||
|
|
||||||
If the verification success, the file is successfully decrypted and authenticated.
|
If the verification success, the file is successfully decrypted and authenticated.
|
||||||
|
@ -13,11 +13,11 @@ use hkdf::Hkdf;
|
|||||||
use zeroize::Zeroize;
|
use zeroize::Zeroize;
|
||||||
use crate::Password;
|
use crate::Password;
|
||||||
|
|
||||||
const SALT_LEN: usize = 64;
|
pub const SALT_LEN: usize = 64;
|
||||||
const AES_NONCE_LEN: usize = 16;
|
const AES_NONCE_LEN: usize = 16;
|
||||||
const XCHACHA20_NONCE_LEN: usize = 24;
|
const XCHACHA20_NONCE_LEN: usize = 24;
|
||||||
const HASH_LEN: usize = 32;
|
pub const HASH_LEN: usize = 64;
|
||||||
const KEY_LEN: usize = HASH_LEN;
|
const KEY_LEN: usize = 32;
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq)]
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
pub struct ArgonParams {
|
pub struct ArgonParams {
|
||||||
@ -53,54 +53,47 @@ impl Display for CipherAlgorithm {
|
|||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq)]
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
pub struct EncryptionParams {
|
pub struct EncryptionParams {
|
||||||
password_salt: [u8; SALT_LEN],
|
salt: [u8; SALT_LEN],
|
||||||
pub argon2: ArgonParams,
|
pub argon2: ArgonParams,
|
||||||
hkdf_salt: [u8; SALT_LEN],
|
|
||||||
nonce: Vec<u8>,
|
nonce: Vec<u8>,
|
||||||
pub cipher: CipherAlgorithm,
|
pub cipher: CipherAlgorithm,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EncryptionParams {
|
impl EncryptionParams {
|
||||||
fn get_params_len(&self) -> usize {
|
fn get_params_len(&self) -> usize {
|
||||||
SALT_LEN*2 + 4*2 + 2 + self.cipher.get_nonce_size()
|
SALT_LEN + 4*2 + 2 + self.cipher.get_nonce_size()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new(argon2_params: ArgonParams, cipher: CipherAlgorithm) -> EncryptionParams {
|
pub fn new(argon2_params: ArgonParams, cipher: CipherAlgorithm) -> EncryptionParams {
|
||||||
let mut password_salt = [0; SALT_LEN];
|
let mut salt = [0; SALT_LEN];
|
||||||
OsRng.fill(&mut password_salt);
|
OsRng.fill(&mut salt);
|
||||||
let mut hkdf_salt = [0; SALT_LEN];
|
|
||||||
OsRng.fill(&mut hkdf_salt);
|
|
||||||
let mut nonce = vec![0; cipher.get_nonce_size()];
|
let mut nonce = vec![0; cipher.get_nonce_size()];
|
||||||
OsRng.fill(&mut nonce[..]);
|
OsRng.fill(&mut nonce[..]);
|
||||||
EncryptionParams {
|
EncryptionParams {
|
||||||
password_salt,
|
salt,
|
||||||
argon2: argon2_params,
|
argon2: argon2_params,
|
||||||
hkdf_salt,
|
|
||||||
nonce,
|
nonce,
|
||||||
cipher,
|
cipher,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn write<W: Write>(&self, writer: &mut W) -> io::Result<()> {
|
pub fn write<W: Write>(&self, writer: &mut W) -> io::Result<()> {
|
||||||
writer.write_all(&self.password_salt)?;
|
writer.write_all(&self.salt)?;
|
||||||
writer.write_all(&self.argon2.t_cost.to_be_bytes())?;
|
writer.write_all(&self.argon2.t_cost.to_be_bytes())?;
|
||||||
writer.write_all(&self.argon2.m_cost.to_be_bytes())?;
|
writer.write_all(&self.argon2.m_cost.to_be_bytes())?;
|
||||||
writer.write_all(&self.argon2.parallelism.to_be_bytes())?;
|
writer.write_all(&self.argon2.parallelism.to_be_bytes())?;
|
||||||
writer.write_all(&self.hkdf_salt)?;
|
|
||||||
writer.write_all(&(self.cipher as u8).to_be_bytes())?;
|
writer.write_all(&(self.cipher as u8).to_be_bytes())?;
|
||||||
writer.write_all(&self.nonce)?;
|
writer.write_all(&self.nonce)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
pub fn read<R: Read>(reader: &mut R) -> io::Result<Option<Self>> {
|
pub fn read<R: Read>(reader: &mut R) -> io::Result<Option<Self>> {
|
||||||
let mut password_salt = [0; SALT_LEN];
|
let mut salt = [0; SALT_LEN];
|
||||||
reader.read_exact(&mut password_salt)?;
|
reader.read_exact(&mut salt)?;
|
||||||
let mut t_cost = [0; 4];
|
let mut t_cost = [0; 4];
|
||||||
reader.read_exact(&mut t_cost)?;
|
reader.read_exact(&mut t_cost)?;
|
||||||
let mut m_cost = [0; 4];
|
let mut m_cost = [0; 4];
|
||||||
reader.read_exact(&mut m_cost)?;
|
reader.read_exact(&mut m_cost)?;
|
||||||
let mut parallelism = [0; 1];
|
let mut parallelism = [0; 1];
|
||||||
reader.read_exact(&mut parallelism)?;
|
reader.read_exact(&mut parallelism)?;
|
||||||
let mut hkdf_salt = [0; SALT_LEN];
|
|
||||||
reader.read_exact(&mut hkdf_salt)?;
|
|
||||||
let mut cipher_buff = [0; 1];
|
let mut cipher_buff = [0; 1];
|
||||||
reader.read_exact(&mut cipher_buff)?;
|
reader.read_exact(&mut cipher_buff)?;
|
||||||
match CipherAlgorithm::try_from(cipher_buff[0]) {
|
match CipherAlgorithm::try_from(cipher_buff[0]) {
|
||||||
@ -115,9 +108,8 @@ impl EncryptionParams {
|
|||||||
};
|
};
|
||||||
|
|
||||||
Ok(Some(EncryptionParams {
|
Ok(Some(EncryptionParams {
|
||||||
password_salt,
|
salt,
|
||||||
argon2: argon2_params,
|
argon2: argon2_params,
|
||||||
hkdf_salt,
|
|
||||||
nonce,
|
nonce,
|
||||||
cipher,
|
cipher,
|
||||||
}))
|
}))
|
||||||
@ -140,7 +132,7 @@ impl<S, E> ThenZeroize for Result<S, E> {
|
|||||||
|
|
||||||
pub struct DobyCipher {
|
pub struct DobyCipher {
|
||||||
cipher: Box<dyn StreamCipher>,
|
cipher: Box<dyn StreamCipher>,
|
||||||
hmac: Hmac<blake3::Hasher>,
|
hmac: Hmac<blake2::Blake2b>,
|
||||||
buffer: Vec<u8>,
|
buffer: Vec<u8>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -150,8 +142,8 @@ impl DobyCipher {
|
|||||||
Ok(argon2) => {
|
Ok(argon2) => {
|
||||||
let mut master_key = [0; KEY_LEN];
|
let mut master_key = [0; KEY_LEN];
|
||||||
let password = password.unwrap_or_ask();
|
let password = password.unwrap_or_ask();
|
||||||
argon2.hash_password_into(Algorithm::Argon2id, password.as_bytes(), ¶ms.password_salt, &[], &mut master_key).zeroize(password)?;
|
argon2.hash_password_into(Algorithm::Argon2id, password.as_bytes(), ¶ms.salt, &[], &mut master_key).zeroize(password)?;
|
||||||
let hkdf = Hkdf::<blake3::Hasher>::new(Some(¶ms.hkdf_salt), &master_key);
|
let hkdf = Hkdf::<blake2::Blake2b>::new(Some(¶ms.salt), &master_key);
|
||||||
let mut encryption_key = [0; KEY_LEN];
|
let mut encryption_key = [0; KEY_LEN];
|
||||||
hkdf.expand(b"doby_encryption_key", &mut encryption_key).unwrap();
|
hkdf.expand(b"doby_encryption_key", &mut encryption_key).unwrap();
|
||||||
let mut authentication_key = [0; KEY_LEN];
|
let mut authentication_key = [0; KEY_LEN];
|
||||||
@ -229,17 +221,16 @@ mod tests {
|
|||||||
parallelism: 1,
|
parallelism: 1,
|
||||||
}, CipherAlgorithm::XChaCha20);
|
}, CipherAlgorithm::XChaCha20);
|
||||||
|
|
||||||
assert_eq!(params.get_params_len(), 162);
|
assert_eq!(params.get_params_len(), 98);
|
||||||
|
|
||||||
let mut buff = Vec::with_capacity(162);
|
let mut buff = Vec::with_capacity(98);
|
||||||
params.write(&mut buff).unwrap();
|
params.write(&mut buff).unwrap();
|
||||||
assert_eq!(buff[..64], params.password_salt);
|
assert_eq!(buff[..64], params.salt);
|
||||||
assert_eq!(buff[64..68], vec![0, 0, 0, 0x01]); //t_cost
|
assert_eq!(buff[64..68], vec![0, 0, 0, 0x01]); //t_cost
|
||||||
assert_eq!(buff[68..72], vec![0, 0, 0, 0x08]); //m_cost
|
assert_eq!(buff[68..72], vec![0, 0, 0, 0x08]); //m_cost
|
||||||
assert_eq!(buff[72], 0x01); //parallelism
|
assert_eq!(buff[72], 0x01); //parallelism
|
||||||
assert_eq!(buff[73..137], params.hkdf_salt);
|
assert_eq!(buff[73], CipherAlgorithm::XChaCha20 as u8);
|
||||||
assert_eq!(buff[137], CipherAlgorithm::XChaCha20 as u8);
|
assert_eq!(buff[74..], params.nonce);
|
||||||
assert_eq!(buff[138..], params.nonce);
|
|
||||||
|
|
||||||
let new_params = EncryptionParams::read(&mut buff.as_slice()).unwrap().unwrap();
|
let new_params = EncryptionParams::read(&mut buff.as_slice()).unwrap().unwrap();
|
||||||
assert_eq!(new_params, params);
|
assert_eq!(new_params, params);
|
||||||
|
@ -85,8 +85,8 @@ pub fn encrypt<R: Read, W: Write>(reader: &mut R, writer: &mut W, params: &Encry
|
|||||||
cipher.encrypt_chunk(&mut buff[..n], writer)?;
|
cipher.encrypt_chunk(&mut buff[..n], writer)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cipher.write_hmac(writer)?;
|
|
||||||
}
|
}
|
||||||
|
cipher.write_hmac(writer)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use std::{io::{self, Read, Write}, fs::{self, File, create_dir}, path::PathBuf};
|
use std::{io::{self, Read, Write}, fs::{self, File, create_dir}, path::PathBuf};
|
||||||
use assert_cmd::{Command, cargo::{CargoError, cargo_bin}};
|
use assert_cmd::{Command, cargo::{CargoError, cargo_bin}};
|
||||||
use tempfile::TempDir;
|
use tempfile::TempDir;
|
||||||
use doby::crypto::CipherAlgorithm;
|
use doby::crypto::{CipherAlgorithm, SALT_LEN, HASH_LEN};
|
||||||
|
|
||||||
const PLAINTEXT: &[u8] = b"the plaintext";
|
const PLAINTEXT: &[u8] = b"the plaintext";
|
||||||
const PASSWORD: &str = "the password";
|
const PASSWORD: &str = "the password";
|
||||||
@ -85,7 +85,7 @@ fn force_encrypt() -> io::Result<()> {
|
|||||||
let buff_ciphertext_2 = fs::read(&tmp_ciphertext_2)?;
|
let buff_ciphertext_2 = fs::read(&tmp_ciphertext_2)?;
|
||||||
assert_ne!(buff_ciphertext_1, buff_ciphertext_2);
|
assert_ne!(buff_ciphertext_1, buff_ciphertext_2);
|
||||||
assert_ne!(buff_ciphertext_2, PLAINTEXT);
|
assert_ne!(buff_ciphertext_2, PLAINTEXT);
|
||||||
assert!(buff_ciphertext_2.len() >= buff_ciphertext_1.len()+190);
|
assert!(buff_ciphertext_2.len() >= buff_ciphertext_1.len()+158);
|
||||||
|
|
||||||
let tmp_decrypted_1 = tmp_path.join("decrypted_1");
|
let tmp_decrypted_1 = tmp_path.join("decrypted_1");
|
||||||
doby_cmd().unwrap().arg(tmp_ciphertext_2).arg(&tmp_decrypted_1).assert().success().stdout("").stderr("");
|
doby_cmd().unwrap().arg(tmp_ciphertext_2).arg(&tmp_decrypted_1).assert().success().stdout("").stderr("");
|
||||||
@ -107,8 +107,8 @@ fn test_cipher(cipher_str: &str, cipher_algorithm: CipherAlgorithm) -> io::Resul
|
|||||||
doby_cmd().unwrap().arg("-c").arg(cipher_str).arg(tmp_plaintext).arg(&tmp_ciphertext).assert().success().stdout("").stderr("");
|
doby_cmd().unwrap().arg("-c").arg(cipher_str).arg(tmp_plaintext).arg(&tmp_ciphertext).assert().success().stdout("").stderr("");
|
||||||
|
|
||||||
let ciphertext = fs::read(&tmp_ciphertext)?;
|
let ciphertext = fs::read(&tmp_ciphertext)?;
|
||||||
assert_eq!(ciphertext[4+64*2+4*2+1], cipher_algorithm as u8);
|
assert_eq!(ciphertext[4+SALT_LEN+4*2+1], cipher_algorithm as u8);
|
||||||
assert_eq!(ciphertext.len(), PLAINTEXT.len()+174+cipher_algorithm.get_nonce_size());
|
assert_eq!(ciphertext.len(), PLAINTEXT.len()+14+SALT_LEN+HASH_LEN+cipher_algorithm.get_nonce_size());
|
||||||
|
|
||||||
doby_cmd().unwrap().arg(tmp_ciphertext).assert().success().stdout(PLAINTEXT).stderr("");
|
doby_cmd().unwrap().arg(tmp_ciphertext).assert().success().stdout(PLAINTEXT).stderr("");
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user