Compare commits
2 Commits
9ac3bd7a53
...
f6fe3912c6
Author | SHA1 | Date |
---|---|---|
Matéo Duparc | f6fe3912c6 | |
Matéo Duparc | 882a917971 |
36
README.md
36
README.md
|
@ -154,6 +154,7 @@ let hmac = Hmac::new(
|
||||||
blake2b, //hash function
|
blake2b, //hash function
|
||||||
);
|
);
|
||||||
hmac.update(random_salt);
|
hmac.update(random_salt);
|
||||||
|
//integers are encoded in big-endian
|
||||||
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);
|
||||||
|
@ -182,6 +183,41 @@ Once the whole plaintext is encrypted, doby computes and appends the HMAC to the
|
||||||
output.write(hmac.digest());
|
output.write(hmac.digest());
|
||||||
```
|
```
|
||||||
|
|
||||||
|
So here is what an encrypted file layout looks like:
|
||||||
|
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<th align="left">Magic bytes</th>
|
||||||
|
<td>4 bytes</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th align="left">Salt</th>
|
||||||
|
<td>64 bytes</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th align="left" rowspan="3">Argon2 parameters</th>
|
||||||
|
<td>Time cost: 4 bytes</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Memory cost: 4 bytes</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Parallelism cost: 1 byte</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th align="left">Encryption cipher</th>
|
||||||
|
<td>1 byte</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th align="left">Ciphertext</th>
|
||||||
|
<td>Exact same size as the plaintext</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th align="left">HMAC</th>
|
||||||
|
<td>64 bytes</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
### Decryption
|
### Decryption
|
||||||
|
|
||||||
doby reads the public encryption values from the input header to get all parameters needed to re-derive the `master_key` from the password with Argon2.
|
doby reads the public encryption values from the input header to get all parameters needed to re-derive the `master_key` from the password with Argon2.
|
||||||
|
|
|
@ -96,11 +96,11 @@ pub fn parse() -> Option<CliArgs> {
|
||||||
|
|
||||||
let cipher = app
|
let cipher = app
|
||||||
.value_of("cipher")
|
.value_of("cipher")
|
||||||
.and_then(|s| Some(if s.to_lowercase() == "aes" {
|
.map(|s| if s.to_lowercase() == "aes" {
|
||||||
CipherAlgorithm::AesCtr
|
CipherAlgorithm::AesCtr
|
||||||
} else {
|
} else {
|
||||||
CipherAlgorithm::XChaCha20
|
CipherAlgorithm::XChaCha20
|
||||||
})
|
}
|
||||||
)
|
)
|
||||||
.unwrap_or_else(|| if aes_ni::get() {
|
.unwrap_or_else(|| if aes_ni::get() {
|
||||||
CipherAlgorithm::AesCtr
|
CipherAlgorithm::AesCtr
|
||||||
|
|
|
@ -17,7 +17,7 @@ impl Password {
|
||||||
|
|
||||||
impl From<Option<&str>> for Password {
|
impl From<Option<&str>> for Password {
|
||||||
fn from(s: Option<&str>) -> Self {
|
fn from(s: Option<&str>) -> Self {
|
||||||
Self(s.map(|s| String::from(s)))
|
Self(s.map(String::from))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,7 +66,7 @@ impl<P: AsRef<Path>> Write for LazyWriter<P> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn encrypt<R: Read, W: Write>(reader: &mut R, writer: &mut W, params: &EncryptionParams, mut cipher: DobyCipher, block_size: usize, already_read: Option<Vec<u8>>) -> io::Result<()> {
|
pub fn encrypt<R: Read, W: Write>(reader: &mut R, writer: &mut W, params: &EncryptionParams, mut cipher: DobyCipher, block_size: usize, already_read: Option<&[u8]>) -> io::Result<()> {
|
||||||
writer.write_all(MAGIC_BYTES)?;
|
writer.write_all(MAGIC_BYTES)?;
|
||||||
params.write(writer)?;
|
params.write(writer)?;
|
||||||
let mut buff = vec![0; block_size];
|
let mut buff = vec![0; block_size];
|
||||||
|
@ -97,7 +97,7 @@ pub fn decrypt<R: Read, W: Write>(reader: &mut R, writer: &mut W, mut cipher: Do
|
||||||
if n == 0 {
|
if n == 0 {
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
writer.write(&buff[..n])?;
|
writer.write_all(&buff[..n])?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(cipher.verify_hmac())
|
Ok(cipher.verify_hmac())
|
||||||
|
|
|
@ -16,9 +16,6 @@ fn run() -> bool {
|
||||||
let mut magic_bytes = vec![0; MAGIC_BYTES.len()];
|
let mut magic_bytes = vec![0; MAGIC_BYTES.len()];
|
||||||
match reader.read(&mut magic_bytes) {
|
match reader.read(&mut magic_bytes) {
|
||||||
Ok(n) => {
|
Ok(n) => {
|
||||||
if n < magic_bytes.len() {
|
|
||||||
magic_bytes.truncate(n);
|
|
||||||
}
|
|
||||||
if magic_bytes == MAGIC_BYTES && !cli_args.force_encrypt { //we probably want to decrypt
|
if magic_bytes == MAGIC_BYTES && !cli_args.force_encrypt { //we probably want to decrypt
|
||||||
match EncryptionParams::read(&mut reader) {
|
match EncryptionParams::read(&mut reader) {
|
||||||
Ok(params) => {
|
Ok(params) => {
|
||||||
|
@ -55,7 +52,7 @@ fn run() -> bool {
|
||||||
¶ms,
|
¶ms,
|
||||||
cipher,
|
cipher,
|
||||||
cli_args.block_size,
|
cli_args.block_size,
|
||||||
Some(magic_bytes)
|
Some(&magic_bytes[..n])
|
||||||
) {
|
) {
|
||||||
Ok(_) => success = true,
|
Ok(_) => success = true,
|
||||||
Err(e) => eprintln!("I/O error while encrypting: {}", e)
|
Err(e) => eprintln!("I/O error while encrypting: {}", e)
|
||||||
|
|
Loading…
Reference in New Issue