Use seperate nonces for thumbnails and full images
Prevents vulnerability via nonce re-use
This commit is contained in:
parent
69f6830c3e
commit
dd2748cbe0
|
@ -5,14 +5,18 @@ use crypto::ciphers::{
|
|||
};
|
||||
use crypto::utils::rand;
|
||||
|
||||
const NONCE: [u8; 12] = [0xd0, 0xc3, 0x75, 0x56, 0x58, 0xc1, 0x7e, 0x5f, 0xd6, 0xcc, 0xb6, 0x76];
|
||||
/// A nonce used for encrypting the gallery's index, as well as all full images
|
||||
pub const NONCE_A: [u8; 12] = [0xd0, 0xc3, 0x75, 0x56, 0x58, 0xc1, 0x7e, 0x5f, 0xd6, 0xcc, 0xb6, 0x76];
|
||||
|
||||
pub fn encrypt(key: &[u8; 32], plaintext: &[u8]) -> Vec<u8> {
|
||||
/// A nonce used for encrypting all thumbnails
|
||||
pub const NONCE_B: [u8; 12] = [0x77, 0xe7, 0xf7, 0x64, 0x33, 0x80, 0x25, 0x49, 0xec, 0xef, 0x57, 0x3f];
|
||||
|
||||
pub fn encrypt(key: &[u8; 32], nonce: &[u8; 12], plaintext: &[u8]) -> Vec<u8> {
|
||||
let mut result = vec![0; plaintext.len() + 16];
|
||||
let (cyphertext, tag) = result.split_at_mut(plaintext.len());
|
||||
Aes256Gcm::try_encrypt(
|
||||
key,
|
||||
&NONCE,
|
||||
nonce,
|
||||
&[],
|
||||
plaintext,
|
||||
cyphertext,
|
||||
|
@ -20,12 +24,12 @@ pub fn encrypt(key: &[u8; 32], plaintext: &[u8]) -> Vec<u8> {
|
|||
result
|
||||
}
|
||||
|
||||
pub fn decrypt<'p>(key: &[u8; 32], encrypted: &[u8], plaintext_dest: &'p mut Vec<u8>) -> Option<&'p mut Vec<u8>> {
|
||||
pub fn decrypt<'p>(key: &[u8; 32], nonce: &[u8; 12], encrypted: &[u8], plaintext_dest: &'p mut Vec<u8>) -> Option<&'p mut Vec<u8>> {
|
||||
let (cyphertext, tag) = encrypted.split_at(encrypted.len() - 16);
|
||||
plaintext_dest.resize(cyphertext.len(), 0);
|
||||
let e = Aes256Gcm::try_decrypt(
|
||||
key,
|
||||
&NONCE,
|
||||
nonce,
|
||||
&[],
|
||||
plaintext_dest,
|
||||
cyphertext,
|
||||
|
|
|
@ -106,8 +106,8 @@ fn create(server: &str, args: CreateArgs) {
|
|||
let key = crypto::make_key();
|
||||
(
|
||||
key,
|
||||
crypto::encrypt(&key, &raw_dat),
|
||||
crypto::encrypt(&key, &thumbnail),
|
||||
crypto::encrypt(&key, &crypto::NONCE_A, &raw_dat),
|
||||
crypto::encrypt(&key, &crypto::NONCE_B, &thumbnail),
|
||||
blurhash,
|
||||
format
|
||||
)
|
||||
|
@ -148,6 +148,7 @@ fn create(server: &str, args: CreateArgs) {
|
|||
let index_key = crypto::make_key();
|
||||
let encrypted_index = crypto::encrypt(
|
||||
&index_key,
|
||||
&crypto::NONCE_A,
|
||||
&index.write_to_bytes()
|
||||
.expect("Error serializing protocol buffers")
|
||||
);
|
||||
|
@ -196,7 +197,7 @@ fn download(server: &str, args: DownloadArgs) -> Result<(), AviaryDownloadError>
|
|||
print!("Downloading index... ");
|
||||
let encrypted_index = upload::get_data(&download_agent, &index_url, 500_000, &mut download_buffer)
|
||||
.map_err(AviaryDownloadError::from_download_error(true))?;
|
||||
let serialized_index = crypto::decrypt(&key, &encrypted_index, &mut decrypt_buffer)
|
||||
let serialized_index = crypto::decrypt(&key, &crypto::NONCE_A, &encrypted_index, &mut decrypt_buffer)
|
||||
.ok_or(AviaryDownloadError::KeyMismatch)?;
|
||||
let index = protobuf::index::Index::parse_from_bytes(&serialized_index)
|
||||
.map_err(|_| AviaryDownloadError::CorruptIndex("Index was not a valid protobuf structure"))?;
|
||||
|
@ -281,6 +282,7 @@ fn download(server: &str, args: DownloadArgs) -> Result<(), AviaryDownloadError>
|
|||
stdout().flush().unwrap();
|
||||
let decrypted_thumb = crypto::decrypt(
|
||||
&key,
|
||||
&crypto::NONCE_B,
|
||||
encrypted_thumbnail,
|
||||
&mut decrypt_buffer
|
||||
).ok_or(AviaryDownloadError::ExpiredImage)?;
|
||||
|
|
Loading…
Reference in a new issue