mirror of
https://github.com/Rixxc/age-plugin-xwing.git
synced 2025-12-04 14:59:33 +01:00
chore: update x-wing to 0.1.0-pre.2 and refactor code
This commit is contained in:
520
Cargo.lock
generated
520
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -16,6 +16,5 @@ age-core = "0.11.0"
|
||||
age-plugin = "0.6.0"
|
||||
base64 = "0.22.1"
|
||||
clap = { version = "4.5.1", features = ["derive"] }
|
||||
x-wing = { version = "0.0.1-pre.1", features = ["getrandom", "zeroize"] }
|
||||
rand_core = "0.6.4"
|
||||
kem = "0.3.0-pre.0"
|
||||
x-wing = { version = "0.1.0-pre.2", features = ["os_rng", "zeroize"] }
|
||||
rand_core = "0.9.3"
|
||||
|
||||
@@ -41,6 +41,6 @@ echo 'It works!' | age -e -r age1xwing1jfdy5fhryzmfg6y89dka6xr2wup9favgprpq0x542
|
||||
Decryption:
|
||||
|
||||
```sh
|
||||
$ age -d -i x_wing_key.txt secret.enc
|
||||
$ age -d -i age_x_wing.key secret.enc
|
||||
It works!
|
||||
```
|
||||
|
||||
91
src/main.rs
91
src/main.rs
@@ -13,7 +13,6 @@ use age_plugin::{
|
||||
};
|
||||
use base64::prelude::*;
|
||||
use clap::Parser;
|
||||
use kem::{Decapsulate, Encapsulate};
|
||||
use rand_core::OsRng;
|
||||
use std::{
|
||||
array::TryFromSliceError,
|
||||
@@ -21,8 +20,8 @@ use std::{
|
||||
io,
|
||||
};
|
||||
use x_wing::{
|
||||
Ciphertext, DecapsulationKey, EncapsulationKey, CIPHERTEXT_SIZE, DECAPSULATION_KEY_SIZE,
|
||||
ENCAPSULATION_KEY_SIZE,
|
||||
Ciphertext, Decapsulate, DecapsulationKey, Encapsulate, EncapsulationKey, CIPHERTEXT_SIZE,
|
||||
DECAPSULATION_KEY_SIZE, ENCAPSULATION_KEY_SIZE,
|
||||
};
|
||||
|
||||
const PLUGIN_NAME: &str = "xwing";
|
||||
@@ -52,11 +51,13 @@ impl RecipientPlugin {
|
||||
self.recipients
|
||||
.iter()
|
||||
.map(|recipient| {
|
||||
let (ct, ss) = recipient.encapsulate(&mut OsRng).unwrap();
|
||||
let (ct, ss) = recipient
|
||||
.encapsulate(&mut OsRng)
|
||||
.expect("X-Wing encapsulation should not fail with a valid RNG");
|
||||
let wrapped_key = aead_encrypt(&ss, file_key.expose_secret());
|
||||
Stanza {
|
||||
tag: PLUGIN_NAME.to_string(),
|
||||
args: vec![BASE64_STANDARD_NO_PAD.encode(ct.as_bytes())],
|
||||
args: vec![BASE64_STANDARD_NO_PAD.encode(ct.to_bytes())],
|
||||
body: wrapped_key,
|
||||
}
|
||||
})
|
||||
@@ -74,20 +75,18 @@ impl RecipientPluginV1 for RecipientPlugin {
|
||||
if plugin_name != PLUGIN_NAME {
|
||||
return Err(recipient::Error::Recipient {
|
||||
index,
|
||||
message: "This recipient should not be handeled by this plugin".to_string(),
|
||||
message: "This recipient should not be handled by this plugin".to_string(),
|
||||
});
|
||||
}
|
||||
|
||||
let pk: Result<&[u8; ENCAPSULATION_KEY_SIZE], TryFromSliceError> = bytes.try_into();
|
||||
let pk = match pk {
|
||||
Ok(x) => EncapsulationKey::from(x),
|
||||
Err(_) => {
|
||||
return Err(recipient::Error::Recipient {
|
||||
index,
|
||||
message: "Invalid recipient".to_string(),
|
||||
})
|
||||
}
|
||||
};
|
||||
Ok(x) => Ok(EncapsulationKey::from(x)),
|
||||
Err(_) => Err(recipient::Error::Recipient {
|
||||
index,
|
||||
message: "Invalid recipient".to_string(),
|
||||
}),
|
||||
}?;
|
||||
|
||||
self.recipients.push(pk);
|
||||
|
||||
@@ -103,20 +102,16 @@ impl RecipientPluginV1 for RecipientPlugin {
|
||||
if plugin_name != PLUGIN_NAME {
|
||||
return Err(recipient::Error::Identity {
|
||||
index,
|
||||
message: "This Identity should not be handeled by this plugin".to_owned(),
|
||||
message: "This Identity should not be handled by this plugin".to_owned(),
|
||||
});
|
||||
}
|
||||
|
||||
let sk: Result<&[u8; DECAPSULATION_KEY_SIZE], TryFromSliceError> = bytes.try_into();
|
||||
let sk = match sk {
|
||||
Ok(x) => DecapsulationKey::from(x.to_owned()),
|
||||
Err(_) => {
|
||||
return Err(recipient::Error::Identity {
|
||||
index,
|
||||
message: "Invalid identity".to_string(),
|
||||
})
|
||||
}
|
||||
};
|
||||
let sk: [u8; DECAPSULATION_KEY_SIZE] =
|
||||
bytes.try_into().map_err(|_| recipient::Error::Identity {
|
||||
index,
|
||||
message: "Invalid identity".to_string(),
|
||||
})?;
|
||||
let sk = DecapsulationKey::from(sk);
|
||||
|
||||
self.recipients.push(sk.encapsulation_key());
|
||||
|
||||
@@ -145,10 +140,10 @@ struct IdentityPlugin {
|
||||
}
|
||||
|
||||
impl IdentityPlugin {
|
||||
fn decrypt_stanzas(
|
||||
fn decrypt_stanzas<I: Iterator<Item = (usize, Stanza)>>(
|
||||
&self,
|
||||
file_index: usize,
|
||||
stanzas: Vec<(usize, Stanza)>,
|
||||
stanzas: I,
|
||||
) -> Result<FileKey, Vec<identity::Error>> {
|
||||
let mut file_key = None;
|
||||
let mut errors = Vec::new();
|
||||
@@ -216,12 +211,19 @@ impl IdentityPlugin {
|
||||
};
|
||||
|
||||
let unwrapped_file_key = match aead_decrypt(&ss, FILE_KEY_BYTES, &stanza.body) {
|
||||
Ok(file_key) => FileKey::new(Box::new(file_key.try_into().unwrap_or_else(|_| {
|
||||
panic!(
|
||||
"aead_decrypt returned a plaintext with a different size as {}",
|
||||
FILE_KEY_BYTES
|
||||
)
|
||||
}))),
|
||||
Ok(file_key) => match file_key.try_into() {
|
||||
Ok(key_bytes) => FileKey::new(Box::new(key_bytes)),
|
||||
Err(_) => {
|
||||
errors.push(identity::Error::Stanza {
|
||||
file_index,
|
||||
stanza_index,
|
||||
message: format!(
|
||||
"aead_decrypt returned a plaintext with a different size than {FILE_KEY_BYTES}"
|
||||
),
|
||||
});
|
||||
continue;
|
||||
}
|
||||
},
|
||||
Err(e) => {
|
||||
errors.push(identity::Error::Stanza {
|
||||
file_index,
|
||||
@@ -246,7 +248,7 @@ impl IdentityPlugin {
|
||||
Err(vec![identity::Error::Stanza {
|
||||
file_index,
|
||||
stanza_index: 0,
|
||||
message: "No stanzas found to be handeled by this plugin".to_string(),
|
||||
message: "No stanzas found to be handled by this plugin".to_string(),
|
||||
}])
|
||||
}
|
||||
}
|
||||
@@ -261,19 +263,15 @@ impl IdentityPluginV1 for IdentityPlugin {
|
||||
if plugin_name != PLUGIN_NAME {
|
||||
return Err(identity::Error::Identity {
|
||||
index,
|
||||
message: "This Identity should not be handeled by this plugin".to_string(),
|
||||
message: "This Identity should not be handled by this plugin".to_string(),
|
||||
});
|
||||
}
|
||||
|
||||
let bytes: [u8; DECAPSULATION_KEY_SIZE] = match bytes.try_into() {
|
||||
Ok(x) => x,
|
||||
Err(_) => {
|
||||
return Err(identity::Error::Identity {
|
||||
index,
|
||||
message: "Invalid identity".to_string(),
|
||||
})
|
||||
}
|
||||
};
|
||||
let bytes: [u8; DECAPSULATION_KEY_SIZE] =
|
||||
bytes.try_into().map_err(|_| identity::Error::Identity {
|
||||
index,
|
||||
message: "Invalid identity".to_string(),
|
||||
})?;
|
||||
|
||||
self.identities.push(DecapsulationKey::from(bytes));
|
||||
|
||||
@@ -291,8 +289,7 @@ impl IdentityPluginV1 for IdentityPlugin {
|
||||
let x_wing_stanzas = stanzas
|
||||
.into_iter()
|
||||
.enumerate()
|
||||
.filter(|(_, stanza)| stanza.tag == PLUGIN_NAME)
|
||||
.collect();
|
||||
.filter(|(_, stanza)| stanza.tag == PLUGIN_NAME);
|
||||
|
||||
ret.insert(file_index, self.decrypt_stanzas(file_index, x_wing_stanzas));
|
||||
}
|
||||
@@ -318,7 +315,7 @@ fn main() -> io::Result<()> {
|
||||
|
||||
// Here you can assume the binary is being run directly by a user, and perform administrative tasks like generating keys.
|
||||
let (sk, pk) = x_wing::generate_key_pair_from_os_rng();
|
||||
print_new_identity(PLUGIN_NAME, sk.as_bytes(), &pk.as_bytes());
|
||||
print_new_identity(PLUGIN_NAME, sk.as_bytes(), &pk.to_bytes());
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user