Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

age: Take recipients by reference in Encryptor::with_recipients #523

Merged
merged 1 commit into from
Aug 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions age/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,20 @@ to 1.0.0 are beta releases.

### Changed
- Migrated to `i18n-embed 0.15`.
- `age::Encryptor::with_recipients` now takes recipients by reference instead of
by value. This aligns it with `age::Decryptor` (which takes identities by
reference), and also means that errors with recipients are reported earlier.
This causes the following changes to the API:
- `Encryptor::with_recipients` takes `impl Iterator<Item = &'a dyn Recipient>`
instead of `Vec<Box<dyn Recipient + Send>>`.
- Verification of recipients and generation of stanzas now happens in
`Encryptor::with_recipients` instead of `Encryptor::wrap_output` and
`Encryptor::wrap_async_output`.
- `Encryptor::with_recipients` returns `Result<Self, EncryptError>` instead of
`Option<Self>`, and `Encryptor::{wrap_output, wrap_async_output}` return
`io::Result<StreamWriter<W>>` instead of `Result<StreamWriter<W>, EncryptError>`.
- `age::EncryptError` has a new variant `MissingRecipients`, taking the place
of the `None` that `Encryptor::with_recipients` could previously return.
- `age::Decryptor` is now an opaque struct instead of an enum with `Recipients`
and `Passphrase` variants.
- `age::IdentityFile` now has a `C: Callbacks` generic parameter, which defaults
Expand Down
20 changes: 7 additions & 13 deletions age/benches/parser.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use age::{x25519, Decryptor, Encryptor, Recipient};
use age::{x25519, Decryptor, Encryptor};
use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion, Throughput};

#[cfg(unix)]
Expand All @@ -8,25 +8,19 @@ use std::io::Write;

fn bench(c: &mut Criterion) {
let recipients: Vec<_> = (0..10)
.map(|_| Box::new(x25519::Identity::generate().to_public()))
.map(|_| x25519::Identity::generate().to_public())
.collect();
let mut group = c.benchmark_group("header");

for count in 1..10 {
group.throughput(Throughput::Elements(count as u64));
group.bench_function(BenchmarkId::new("parse", count), |b| {
let mut encrypted = vec![];
let mut output = Encryptor::with_recipients(
recipients
.iter()
.take(count)
.cloned()
.map(|r| r as Box<dyn Recipient + Send>)
.collect(),
)
.unwrap()
.wrap_output(&mut encrypted)
.unwrap();
let mut output =
Encryptor::with_recipients(recipients.iter().take(count).map(|r| r as _))
.unwrap()
.wrap_output(&mut encrypted)
.unwrap();
output.write_all(&[]).unwrap();
output.finish().unwrap();

Expand Down
4 changes: 2 additions & 2 deletions age/benches/throughput.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ fn bench(c: &mut Criterion_) {

group.bench_function(BenchmarkId::new("encrypt", size), |b| {
b.iter(|| {
let mut output = Encryptor::with_recipients(vec![Box::new(recipient.clone())])
let mut output = Encryptor::with_recipients(iter::once(&recipient as _))
.unwrap()
.wrap_output(io::sink())
.unwrap();
Expand All @@ -62,7 +62,7 @@ fn bench(c: &mut Criterion_) {
});

group.bench_function(BenchmarkId::new("decrypt", size), |b| {
let mut output = Encryptor::with_recipients(vec![Box::new(recipient.clone())])
let mut output = Encryptor::with_recipients(iter::once(&recipient as _))
.unwrap()
.wrap_output(&mut ct_buf)
.unwrap();
Expand Down
2 changes: 2 additions & 0 deletions age/i18n/en-US/age.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@ err-invalid-recipient-labels = The first recipient requires one or more invalid
err-key-decryption = Failed to decrypt an encrypted key
err-missing-recipients = Missing recipients.
err-mixed-recipient-passphrase = {-scrypt-recipient} can't be used with other recipients.
err-no-matching-keys = No matching keys found
Expand Down
2 changes: 2 additions & 0 deletions age/i18n/es-AR/age.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ err-header-mac-invalid = MAC de encabezado inválido.
err-key-decryption = No se pudo desencriptar una clave encriptada.
err-missing-recipients = No se encontraron destinatarios.
err-no-matching-keys = No se encontraron claves coincidentes.
err-unknown-format = Formato {-age} desconocido.
Expand Down
2 changes: 2 additions & 0 deletions age/i18n/fr/age.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ err-header-mac-invalid = Le MAC de l'en-tête est invalide
err-key-decryption = Echec du déchiffrement d'une clef chiffrée
err-missing-recipients = Destinataires manquants.
err-no-matching-keys = Aucune clef correspondante n'a été trouvée
err-unknown-format = Format {-age} inconnu.
Expand Down
2 changes: 2 additions & 0 deletions age/i18n/it/age.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ err-header-mac-invalid = Il MAC dell'header è invalido
err-key-decryption = La decifrazione di una chiave crittografata è fallita
err-missing-recipients = Destinatari mancanti.
err-no-matching-keys = Nessuna chiave corrispondente trovata
err-unknown-format = Formato {-age} sconosciuto.
Expand Down
2 changes: 2 additions & 0 deletions age/i18n/ru/age.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ err-header-mac-invalid = Недействительный MAC заголовка
err-key-decryption = Не удалось расшифровать зашифрованный ключ
err-missing-recipients = Отсутствуют получатели.
err-no-matching-keys = Не найдены подходящие ключи
err-unknown-format = Неизвестный формат {-age}.
Expand Down
2 changes: 2 additions & 0 deletions age/i18n/zh-CN/age.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ err-header-mac-invalid = 标头消息认证码 (MAC) 无效
err-key-decryption = 未能解密加密密钥
err-missing-recipients = 缺少接收方。
err-no-matching-keys = 未搜索到匹配的密钥
err-unknown-format = 未知的 {-age} 格式。
Expand Down
2 changes: 2 additions & 0 deletions age/i18n/zh-TW/age.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ err-header-mac-invalid = 標頭消息認證碼 (MAC) 無效
err-key-decryption = 未能解密加密密鑰
err-missing-recipients = 缺少接收方。
err-no-matching-keys = 未搜索到匹配的密鑰
err-unknown-format = 未知的 {-age} 格式。
Expand Down
4 changes: 4 additions & 0 deletions age/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,8 @@
/// The plugin's binary name.
binary_name: String,
},
/// The encryptor was not given any recipients.
MissingRecipients,
/// [`scrypt::Recipient`] was mixed with other recipient types.
///
/// [`scrypt::Recipient`]: crate::scrypt::Recipient
Expand Down Expand Up @@ -219,6 +221,7 @@
Self::MissingPlugin { binary_name } => Self::MissingPlugin {
binary_name: binary_name.clone(),
},
Self::MissingRecipients => Self::MissingRecipients,

Check warning on line 224 in age/src/error.rs

View check run for this annotation

Codecov / codecov/patch

age/src/error.rs#L224

Added line #L224 was not covered by tests
Self::MixedRecipientAndPassphrase => Self::MixedRecipientAndPassphrase,
#[cfg(feature = "plugin")]
Self::Plugin(e) => Self::Plugin(e.clone()),
Expand Down Expand Up @@ -277,6 +280,7 @@
wlnfl!(f, "err-missing-plugin", plugin_name = binary_name.as_str())?;
wfl!(f, "rec-missing-plugin")
}
EncryptError::MissingRecipients => wfl!(f, "err-missing-recipients"),
EncryptError::MixedRecipientAndPassphrase => {
wfl!(f, "err-mixed-recipient-passphrase")
}
Expand Down
2 changes: 1 addition & 1 deletion age/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
//! // Encrypt the plaintext to a ciphertext...
//! # fn encrypt(pubkey: age::x25519::Recipient, plaintext: &[u8]) -> Result<Vec<u8>, age::EncryptError> {
//! let encrypted = {
//! let encryptor = age::Encryptor::with_recipients(vec![Box::new(pubkey)])
//! let encryptor = age::Encryptor::with_recipients(iter::once(&pubkey as _))
//! .expect("we provided a recipient");
//!
//! let mut encrypted = vec![];
Expand Down
6 changes: 3 additions & 3 deletions age/src/primitives/armor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,7 @@ enum ArmorIs<W> {
/// ```
/// # use std::io::Read;
/// use std::io::Write;
/// # use std::iter;
/// use std::iter;
///
/// # fn run_main() -> Result<(), ()> {
/// # let identity = age::x25519::Identity::generate();
Expand All @@ -301,7 +301,7 @@ enum ArmorIs<W> {
///
/// # fn encrypt(recipient: age::x25519::Recipient, plaintext: &[u8]) -> Result<Vec<u8>, age::EncryptError> {
/// let encrypted = {
/// let encryptor = age::Encryptor::with_recipients(vec![Box::new(recipient)])
/// let encryptor = age::Encryptor::with_recipients(iter::once(&recipient as _))
/// .expect("we provided a recipient");
///
/// let mut encrypted = vec![];
Expand Down Expand Up @@ -664,7 +664,7 @@ enum StartPos {
/// # fn run_main() -> Result<(), ()> {
/// # fn encrypt(recipient: age::x25519::Recipient, plaintext: &[u8]) -> Result<Vec<u8>, age::EncryptError> {
/// # let encrypted = {
/// # let encryptor = age::Encryptor::with_recipients(vec![Box::new(recipient)])
/// # let encryptor = age::Encryptor::with_recipients(iter::once(&recipient as _))
/// # .expect("we provided a recipient");
/// # let mut encrypted = vec![];
/// # let mut writer = encryptor.wrap_output(
Expand Down
Loading
Loading