Skip to content

Commit 8fbb919

Browse files
authored
Fix compatibility with legacy secrets (#14)
Fix compatibility with legacy secrets We have secrets in our vaults, where it seems that the encrypted key is bigger than a standard AES256 key. We need to allow for such keys to stay compatible. The OpenSSL documentation says that keys are of fixed size, but it seems we rely on an undocumented/undefined behavior.
1 parent 5a5121f commit 8fbb919

File tree

3 files changed

+29
-29
lines changed

3 files changed

+29
-29
lines changed

src/crypto/mod.rs

Lines changed: 26 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,17 @@ const IV_SIZE: usize = 128 / 8;
1212

1313
#[derive(Clone)]
1414
pub struct CryptedFileContent {
15-
crypted_password: Vec<u8>,
16-
content: Vec<u8>,
15+
encrypted_key: Vec<u8>,
16+
encrypted_content: Vec<u8>,
1717
}
1818

1919
impl CryptedFileContent {
20-
pub fn get_crypted_password(&self) -> &[u8] {
21-
self.crypted_password.as_slice()
20+
pub fn get_encrypted_key(&self) -> &[u8] {
21+
self.encrypted_key.as_slice()
2222
}
2323

24-
pub fn get_content(&self) -> &[u8] {
25-
self.content.as_slice()
24+
pub fn get_encrypted_content(&self) -> &[u8] {
25+
self.encrypted_content.as_slice()
2626
}
2727
}
2828

@@ -48,22 +48,22 @@ impl Crypto {
4848
public_key: &PublicKey,
4949
uncrypted_vault_file: &UncryptedVaultFile,
5050
) -> Result<CryptedFileContent> {
51-
// at first, we need a password, we store the password in the "key"
52-
let mut password = [0; KEY_SIZE];
53-
rand_priv_bytes(&mut password)
51+
// at first, we need an AES key, we store the AES key using RSA
52+
let mut aes_key = [0; KEY_SIZE];
53+
rand_priv_bytes(&mut aes_key)
5454
.context("could not create random bytes to encrypt vault_file.")?;
5555

5656
let mut iv = vec![0; IV_SIZE];
5757
rand_bytes(&mut iv).context("could not create random bytes for iv.")?;
5858

59-
let key = Crypto::key_encrypt(public_key, &password)
60-
.context("could not encrypt using public_key")?;
59+
let key = Crypto::key_encrypt(public_key, &aes_key)
60+
.context("could not encrypt the AES key using the public RSA key")?;
6161

6262
let cipher = Cipher::aes_256_cbc();
6363

6464
let mut content = encrypt(
6565
cipher,
66-
&password,
66+
&aes_key,
6767
Some(&iv),
6868
uncrypted_vault_file.get_content(),
6969
)
@@ -74,29 +74,29 @@ impl Crypto {
7474
content_with_iv.append(&mut content);
7575

7676
Ok(CryptedFileContent {
77-
crypted_password: key,
78-
content: content_with_iv,
77+
encrypted_key: key,
78+
encrypted_content: content_with_iv,
7979
})
8080
}
8181

8282
pub fn decrypt(pem: &Pem, crypted_vault_file: &VaultFile) -> Result<UncryptedVaultFile> {
83-
// at first, we need to extract the password using the private key.
84-
let password = Self::key_decrypt(
83+
// at first, we need to extract the AES key using the private RSA key.
84+
let aes_key = Self::key_decrypt(
8585
pem.get_private_key(),
8686
crypted_vault_file.get_keyfile_content(),
8787
)
88-
.context("could not decrypt password using private key")?;
88+
.context("could not decrypt AES key using the private RSA key")?;
8989

9090
let cipher = Cipher::aes_256_cbc();
9191

9292
ensure!(
9393
crypted_vault_file.get_secret_content().len() >= IV_SIZE,
94-
"crypted size is to small, couldnt read enought for IV"
94+
"crypted size is to small, couldnt read enough for IV"
9595
);
9696

9797
let (iv, content) = crypted_vault_file.get_secret_content().split_at(IV_SIZE);
9898

99-
let content = decrypt(cipher, password.as_slice(), Some(iv), content)
99+
let content = decrypt(cipher, aes_key.as_slice(), Some(iv), content)
100100
.context("could not encrypt using content")?;
101101

102102
Ok(UncryptedVaultFile { content })
@@ -123,7 +123,7 @@ impl Crypto {
123123
Ok(encrypted_data)
124124
}
125125

126-
pub fn key_decrypt(private_key: &PrivateKey, encrypted_key: &[u8]) -> Result<[u8; KEY_SIZE]> {
126+
pub fn key_decrypt(private_key: &PrivateKey, encrypted_key: &[u8]) -> Result<Vec<u8>> {
127127
let rsa = Rsa::private_key_from_pem(private_key.get_data())
128128
.with_context(|| format!("invalid private key {}", &private_key.get_name()))?;
129129

@@ -136,13 +136,13 @@ impl Crypto {
136136
.private_decrypt(encrypted_key, decrypted_data.as_mut_slice(), Padding::PKCS1)
137137
.context("could not decrypt")?;
138138

139-
assert!(size >= KEY_SIZE);
140-
141-
let mut key = [0; KEY_SIZE];
142-
143-
key.copy_from_slice(&decrypted_data[..KEY_SIZE]);
139+
// Older versions of vault seem to have created files, which produced keys that are bigger
140+
// than the expected KEY_SIZE. For compatibility reasons, we have to allow keys that
141+
// are bigger than KEY_SIZE. The OpenSSL documentation says that keys are of fixed size,
142+
// but it seems we rely on an undocumented/undefined behavior.
143+
let decrypted_key = decrypted_data[..size].to_vec();
144144

145-
Ok(key)
145+
Ok(decrypted_key)
146146
}
147147
}
148148

src/main.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ type Result<T> = anyhow::Result<T>;
3131

3232
fn main() {
3333
if let Err(error) = run() {
34-
eprintln!("Vault error: {error}");
34+
eprintln!("Vault error: {error:?}");
3535
std::process::exit(1);
3636
}
3737
}

src/proto/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@ impl<'a> VaultFile<'a> {
2828

2929
pub fn from_crypted_file_content(file_content: &'a CryptedFileContent) -> Self {
3030
VaultFile {
31-
keyfile_content: Cow::Borrowed(file_content.get_crypted_password()),
32-
secret_content: Cow::Borrowed(file_content.get_content()),
31+
keyfile_content: Cow::Borrowed(file_content.get_encrypted_key()),
32+
secret_content: Cow::Borrowed(file_content.get_encrypted_content()),
3333
}
3434
}
3535

0 commit comments

Comments
 (0)