/* This Source Code Form is subject to the terms of the Mozilla Public *License,v.2.0.IfacopyoftheMPLwasnotdistributedwiththis
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
usecrate::error::{Error, Result}; use base64::{
engine::general_purpose::{STANDARD, URL_SAFE_NO_PAD},
Engine,
}; use rc_crypto::{
aead::{self, OpeningKey, SealingKey},
rand,
};
/// Decrypt the provided ciphertext with the given iv, and decodes the /// result as a utf8 string. pubfn decrypt(&self, enc_base64: &str, iv_base64: &str, hmac_base16: &str) -> Result<String> { // Decode the expected_hmac into bytes to avoid issues if a client happens to encode // this as uppercase. This shouldn't happen in practice, but doing it this way is more // robust and avoids an allocation. letmut decoded_hmac = vec![0u8; 32]; if base16::decode_slice(hmac_base16, &mut decoded_hmac).is_err() {
log::warn!("Garbage HMAC verification string: contained non base16 characters"); return Err(Error::HmacMismatch);
} let iv = STANDARD.decode(iv_base64)?; let ciphertext_bytes = STANDARD.decode(enc_base64)?; let key_bytes = [self.encryption_key(), self.hmac_key()].concat(); let key = OpeningKey::new(&aead::LEGACY_SYNC_AES_256_CBC_HMAC_SHA256, &key_bytes)?; let nonce = aead::Nonce::try_assume_unique_for_key(
&aead::LEGACY_SYNC_AES_256_CBC_HMAC_SHA256,
&iv,
)?; let ciphertext_and_hmac = [ciphertext_bytes, decoded_hmac].concat(); let cleartext_bytes = aead::open(&key, nonce, aead::Aad::empty(), &ciphertext_and_hmac)?; let cleartext = String::from_utf8(cleartext_bytes)?;
Ok(cleartext)
}
/// Encrypt using the provided IV. pubfn encrypt_bytes_with_iv(
&self,
cleartext_bytes: &[u8],
iv: &[u8],
) -> Result<(String, String)> { let key_bytes = [self.encryption_key(), self.hmac_key()].concat(); let key = SealingKey::new(&aead::LEGACY_SYNC_AES_256_CBC_HMAC_SHA256, &key_bytes)?; let nonce =
aead::Nonce::try_assume_unique_for_key(&aead::LEGACY_SYNC_AES_256_CBC_HMAC_SHA256, iv)?; let ciphertext_and_hmac = aead::seal(&key, nonce, aead::Aad::empty(), cleartext_bytes)?; let ciphertext_len = ciphertext_and_hmac.len() - key.algorithm().tag_len(); // Do the string conversions here so we don't have to split and copy to 2 vectors. let (ciphertext, hmac_signature) = ciphertext_and_hmac.split_at(ciphertext_len); let enc_base64 = STANDARD.encode(ciphertext); let hmac_base16 = base16::encode_lower(&hmac_signature);
Ok((enc_base64, hmac_base16))
}
/// Generate a random iv and encrypt with it. Return both the encrypted bytes /// and the generated iv. pubfn encrypt_bytes_rand_iv(
&self,
cleartext_bytes: &[u8],
) -> Result<(String, String, String)> { letmut iv = [0u8; 16];
rand::fill(&mut iv)?; let (enc_base64, hmac_base16) = self.encrypt_bytes_with_iv(cleartext_bytes, &iv)?; let iv_base64 = STANDARD.encode(iv);
Ok((enc_base64, iv_base64, hmac_base16))
}
#[test] fn test_decrypt() { let key_bundle = KeyBundle::from_base64(ENC_KEY_B64, HMAC_KEY_B64).unwrap(); let ciphertext = CIPHERTEXT_B64_PIECES.join(""); let s = key_bundle.decrypt(&ciphertext, IV_B64, HMAC_B16).unwrap();
let cleartext =
String::from_utf8(STANDARD.decode(CLEARTEXT_B64_PIECES.join("")).unwrap()).unwrap();
assert_eq!(&cleartext, &s);
}
#[test] fn test_encrypt() { let key_bundle = KeyBundle::from_base64(ENC_KEY_B64, HMAC_KEY_B64).unwrap(); let iv = STANDARD.decode(IV_B64).unwrap();
let cleartext_bytes = STANDARD.decode(CLEARTEXT_B64_PIECES.join("")).unwrap(); let (enc_base64, _hmac_base16) = key_bundle
.encrypt_bytes_with_iv(&cleartext_bytes, &iv)
.unwrap();
let expect_ciphertext = CIPHERTEXT_B64_PIECES.join("");
assert_eq!(&enc_base64, &expect_ciphertext);
let (enc_base64_2, iv_base64_2, hmac_base16_2) =
key_bundle.encrypt_bytes_rand_iv(&cleartext_bytes).unwrap();
assert_ne!(&enc_base64_2, &expect_ciphertext);
let s = key_bundle
.decrypt(&enc_base64_2, &iv_base64_2, &hmac_base16_2)
.unwrap();
assert_eq!(&cleartext_bytes, &s.as_bytes());
}
}
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.12 Sekunden
(vorverarbeitet am 2026-06-27)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.