Generated
+2
-3
@@ -18,7 +18,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "age-core"
|
name = "age-core"
|
||||||
version = "0.5.0"
|
version = "0.5.0"
|
||||||
source = "git+https://github.com/str4d/rage.git?rev=a9b5e88aa5816b284ebea23fc84d0203a3c4fdbb#a9b5e88aa5816b284ebea23fc84d0203a3c4fdbb"
|
source = "git+https://github.com/str4d/rage.git?rev=4aa52a2dbb5feed86dcafa3afe8d554975ca5518#4aa52a2dbb5feed86dcafa3afe8d554975ca5518"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64",
|
"base64",
|
||||||
"c2-chacha",
|
"c2-chacha",
|
||||||
@@ -35,7 +35,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "age-plugin"
|
name = "age-plugin"
|
||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
source = "git+https://github.com/str4d/rage.git?rev=a9b5e88aa5816b284ebea23fc84d0203a3c4fdbb#a9b5e88aa5816b284ebea23fc84d0203a3c4fdbb"
|
source = "git+https://github.com/str4d/rage.git?rev=4aa52a2dbb5feed86dcafa3afe8d554975ca5518#4aa52a2dbb5feed86dcafa3afe8d554975ca5518"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"age-core",
|
"age-core",
|
||||||
"bech32",
|
"bech32",
|
||||||
@@ -51,7 +51,6 @@ dependencies = [
|
|||||||
"age-plugin",
|
"age-plugin",
|
||||||
"base64",
|
"base64",
|
||||||
"bech32",
|
"bech32",
|
||||||
"chrono",
|
|
||||||
"console",
|
"console",
|
||||||
"dialoguer",
|
"dialoguer",
|
||||||
"env_logger",
|
"env_logger",
|
||||||
|
|||||||
+2
-3
@@ -26,7 +26,6 @@ age-core = "0.5"
|
|||||||
age-plugin = "0.0"
|
age-plugin = "0.0"
|
||||||
base64 = "0.13"
|
base64 = "0.13"
|
||||||
bech32 = "0.8"
|
bech32 = "0.8"
|
||||||
chrono = "0.4"
|
|
||||||
console = "0.14"
|
console = "0.14"
|
||||||
dialoguer = "0.8"
|
dialoguer = "0.8"
|
||||||
env_logger = "0.8"
|
env_logger = "0.8"
|
||||||
@@ -46,5 +45,5 @@ flate2 = "1"
|
|||||||
man = "0.3"
|
man = "0.3"
|
||||||
|
|
||||||
[patch.crates-io]
|
[patch.crates-io]
|
||||||
age-core = { git = "https://github.com/str4d/rage.git", rev = "a9b5e88aa5816b284ebea23fc84d0203a3c4fdbb" }
|
age-core = { git = "https://github.com/str4d/rage.git", rev = "4aa52a2dbb5feed86dcafa3afe8d554975ca5518" }
|
||||||
age-plugin = { git = "https://github.com/str4d/rage.git", rev = "a9b5e88aa5816b284ebea23fc84d0203a3c4fdbb" }
|
age-plugin = { git = "https://github.com/str4d/rage.git", rev = "4aa52a2dbb5feed86dcafa3afe8d554975ca5518" }
|
||||||
|
|||||||
+7
-4
@@ -12,7 +12,7 @@ use crate::{
|
|||||||
p256::Recipient,
|
p256::Recipient,
|
||||||
util::POLICY_EXTENSION_OID,
|
util::POLICY_EXTENSION_OID,
|
||||||
yubikey::{self, Stub},
|
yubikey::{self, Stub},
|
||||||
PLUGIN_NAME, USABLE_SLOTS,
|
BINARY_NAME, USABLE_SLOTS,
|
||||||
};
|
};
|
||||||
|
|
||||||
const DEFAULT_PIN_POLICY: PinPolicy = PinPolicy::Once;
|
const DEFAULT_PIN_POLICY: PinPolicy = PinPolicy::Once;
|
||||||
@@ -123,13 +123,13 @@ impl IdentityBuilder {
|
|||||||
.name
|
.name
|
||||||
.unwrap_or(format!("age identity {}", hex::encode(stub.tag)));
|
.unwrap_or(format!("age identity {}", hex::encode(stub.tag)));
|
||||||
|
|
||||||
Certificate::generate_self_signed(
|
let cert = Certificate::generate_self_signed(
|
||||||
yubikey,
|
yubikey,
|
||||||
SlotId::Retired(slot),
|
SlotId::Retired(slot),
|
||||||
serial,
|
serial,
|
||||||
None,
|
None,
|
||||||
&[
|
&[
|
||||||
RelativeDistinguishedName::organization(PLUGIN_NAME),
|
RelativeDistinguishedName::organization(BINARY_NAME),
|
||||||
RelativeDistinguishedName::organizational_unit(env!("CARGO_PKG_VERSION")),
|
RelativeDistinguishedName::organizational_unit(env!("CARGO_PKG_VERSION")),
|
||||||
RelativeDistinguishedName::common_name(&name),
|
RelativeDistinguishedName::common_name(&name),
|
||||||
],
|
],
|
||||||
@@ -140,10 +140,13 @@ impl IdentityBuilder {
|
|||||||
)],
|
)],
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
|
let (_, cert) = x509_parser::parse_x509_certificate(cert.as_ref()).unwrap();
|
||||||
|
let created = cert.validity().not_before.to_rfc2822();
|
||||||
|
|
||||||
Ok((
|
Ok((
|
||||||
Stub::new(yubikey.serial(), slot, &recipient),
|
Stub::new(yubikey.serial(), slot, &recipient),
|
||||||
recipient,
|
recipient,
|
||||||
chrono::Local::now().to_rfc3339_opts(chrono::SecondsFormat::Secs, true),
|
created,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-2
@@ -19,7 +19,8 @@ mod yubikey;
|
|||||||
|
|
||||||
use error::Error;
|
use error::Error;
|
||||||
|
|
||||||
const PLUGIN_NAME: &str = "age-plugin-yubikey";
|
const PLUGIN_NAME: &str = "yubikey";
|
||||||
|
const BINARY_NAME: &str = "age-plugin-yubikey";
|
||||||
const RECIPIENT_PREFIX: &str = "age1yubikey";
|
const RECIPIENT_PREFIX: &str = "age1yubikey";
|
||||||
const IDENTITY_PREFIX: &str = "age-plugin-yubikey-";
|
const IDENTITY_PREFIX: &str = "age-plugin-yubikey-";
|
||||||
const STANZA_TAG: &str = "piv-p256";
|
const STANZA_TAG: &str = "piv-p256";
|
||||||
@@ -157,7 +158,7 @@ fn identity(opts: PluginOptions) -> Result<(), Error> {
|
|||||||
.as_ref()
|
.as_ref()
|
||||||
.and_then(|cert| cert.subject().iter_organization().next())
|
.and_then(|cert| cert.subject().iter_organization().next())
|
||||||
{
|
{
|
||||||
Some(org) => org.as_str() == Ok(PLUGIN_NAME),
|
Some(org) => org.as_str() == Ok(BINARY_NAME),
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
+31
-77
@@ -4,11 +4,10 @@ use age_plugin::{
|
|||||||
recipient::{self, RecipientPluginV1},
|
recipient::{self, RecipientPluginV1},
|
||||||
Callbacks,
|
Callbacks,
|
||||||
};
|
};
|
||||||
use bech32::{FromBase32, Variant};
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::io;
|
use std::io;
|
||||||
|
|
||||||
use crate::{format, p256::Recipient, yubikey, IDENTITY_PREFIX, RECIPIENT_PREFIX};
|
use crate::{format, p256::Recipient, yubikey, PLUGIN_NAME};
|
||||||
|
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
pub(crate) struct RecipientPlugin {
|
pub(crate) struct RecipientPlugin {
|
||||||
@@ -17,76 +16,46 @@ pub(crate) struct RecipientPlugin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl RecipientPluginV1 for RecipientPlugin {
|
impl RecipientPluginV1 for RecipientPlugin {
|
||||||
fn add_recipients<'a, I: Iterator<Item = &'a str>>(
|
fn add_recipient(
|
||||||
&mut self,
|
&mut self,
|
||||||
recipients: I,
|
index: usize,
|
||||||
) -> Result<(), Vec<recipient::Error>> {
|
plugin_name: &str,
|
||||||
let errors: Vec<_> = recipients
|
bytes: &[u8],
|
||||||
.enumerate()
|
) -> Result<(), recipient::Error> {
|
||||||
.filter_map(|(index, recipient)| {
|
if let Some(pk) = if plugin_name == PLUGIN_NAME {
|
||||||
if let Some(pk) = bech32::decode(recipient)
|
Recipient::from_bytes(&bytes)
|
||||||
.ok()
|
|
||||||
.and_then(|(hrp, data, variant)| {
|
|
||||||
if hrp == RECIPIENT_PREFIX && variant == Variant::Bech32 {
|
|
||||||
Some(data)
|
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
} {
|
||||||
})
|
|
||||||
.and_then(|data| Vec::from_base32(&data).ok())
|
|
||||||
.and_then(|bytes| Recipient::from_bytes(&bytes))
|
|
||||||
{
|
|
||||||
self.recipients.push(pk);
|
self.recipients.push(pk);
|
||||||
None
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
Some(recipient::Error::Recipient {
|
Err(recipient::Error::Recipient {
|
||||||
index,
|
index,
|
||||||
message: "Invalid recipient".to_owned(),
|
message: "Invalid recipient".to_owned(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
|
||||||
.collect();
|
|
||||||
if errors.is_empty() {
|
|
||||||
Ok(())
|
|
||||||
} else {
|
|
||||||
Err(errors)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_identities<'a, I: Iterator<Item = &'a str>>(
|
fn add_identity(
|
||||||
&mut self,
|
&mut self,
|
||||||
identities: I,
|
index: usize,
|
||||||
) -> Result<(), Vec<recipient::Error>> {
|
plugin_name: &str,
|
||||||
let errors: Vec<_> = identities
|
bytes: &[u8],
|
||||||
.enumerate()
|
) -> Result<(), recipient::Error> {
|
||||||
.filter_map(|(index, identity)| {
|
if let Some(stub) = if plugin_name == PLUGIN_NAME {
|
||||||
if let Some(stub) = bech32::decode(identity)
|
yubikey::Stub::from_bytes(&bytes, index)
|
||||||
.ok()
|
|
||||||
.and_then(|(hrp, data, variant)| {
|
|
||||||
if hrp == IDENTITY_PREFIX.to_lowercase() && variant == Variant::Bech32 {
|
|
||||||
Some(data)
|
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
} {
|
||||||
})
|
|
||||||
.and_then(|data| Vec::from_base32(&data).ok())
|
|
||||||
.and_then(|bytes| yubikey::Stub::from_bytes(&bytes, index))
|
|
||||||
{
|
|
||||||
self.yubikeys.push(stub);
|
self.yubikeys.push(stub);
|
||||||
None
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
Some(recipient::Error::Identity {
|
Err(recipient::Error::Identity {
|
||||||
index,
|
index,
|
||||||
message: "Invalid Yubikey stub".to_owned(),
|
message: "Invalid Yubikey stub".to_owned(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
|
||||||
.collect();
|
|
||||||
if errors.is_empty() {
|
|
||||||
Ok(())
|
|
||||||
} else {
|
|
||||||
Err(errors)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn wrap_file_keys(
|
fn wrap_file_keys(
|
||||||
@@ -135,40 +104,25 @@ pub(crate) struct IdentityPlugin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl IdentityPluginV1 for IdentityPlugin {
|
impl IdentityPluginV1 for IdentityPlugin {
|
||||||
fn add_identities<'a, I: Iterator<Item = &'a str>>(
|
fn add_identity(
|
||||||
&mut self,
|
&mut self,
|
||||||
identities: I,
|
index: usize,
|
||||||
) -> Result<(), Vec<identity::Error>> {
|
plugin_name: &str,
|
||||||
let errors: Vec<_> = identities
|
bytes: &[u8],
|
||||||
.enumerate()
|
) -> Result<(), identity::Error> {
|
||||||
.filter_map(|(index, identity)| {
|
if let Some(stub) = if plugin_name == PLUGIN_NAME {
|
||||||
if let Some(stub) = bech32::decode(identity)
|
yubikey::Stub::from_bytes(&bytes, index)
|
||||||
.ok()
|
|
||||||
.and_then(|(hrp, data, variant)| {
|
|
||||||
if hrp == IDENTITY_PREFIX.to_lowercase() && variant == Variant::Bech32 {
|
|
||||||
Some(data)
|
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
} {
|
||||||
})
|
|
||||||
.and_then(|data| Vec::from_base32(&data).ok())
|
|
||||||
.and_then(|bytes| yubikey::Stub::from_bytes(&bytes, index))
|
|
||||||
{
|
|
||||||
self.yubikeys.push(stub);
|
self.yubikeys.push(stub);
|
||||||
None
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
Some(identity::Error::Identity {
|
Err(identity::Error::Identity {
|
||||||
index,
|
index,
|
||||||
message: "Invalid Yubikey stub".to_owned(),
|
message: "Invalid Yubikey stub".to_owned(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
|
||||||
.collect();
|
|
||||||
if errors.is_empty() {
|
|
||||||
Ok(())
|
|
||||||
} else {
|
|
||||||
Err(errors)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn unwrap_file_keys(
|
fn unwrap_file_keys(
|
||||||
|
|||||||
+2
-2
@@ -5,7 +5,7 @@ use yubikey_piv::{
|
|||||||
Key, YubiKey,
|
Key, YubiKey,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{error::Error, p256::Recipient, yubikey::Stub, PLUGIN_NAME, USABLE_SLOTS};
|
use crate::{error::Error, p256::Recipient, yubikey::Stub, BINARY_NAME, USABLE_SLOTS};
|
||||||
|
|
||||||
pub(crate) const POLICY_EXTENSION_OID: &[u64] = &[1, 3, 6, 1, 4, 1, 41482, 3, 8];
|
pub(crate) const POLICY_EXTENSION_OID: &[u64] = &[1, 3, 6, 1, 4, 1, 41482, 3, 8];
|
||||||
|
|
||||||
@@ -63,7 +63,7 @@ pub(crate) fn touch_policy_to_str(policy: Option<TouchPolicy>) -> &'static str {
|
|||||||
pub(crate) fn extract_name(cert: &X509Certificate, all: bool) -> Option<(String, bool)> {
|
pub(crate) fn extract_name(cert: &X509Certificate, all: bool) -> Option<(String, bool)> {
|
||||||
// Look at Subject Organization to determine if we created this.
|
// Look at Subject Organization to determine if we created this.
|
||||||
match cert.subject().iter_organization().next() {
|
match cert.subject().iter_organization().next() {
|
||||||
Some(org) if org.as_str() == Ok(PLUGIN_NAME) => {
|
Some(org) if org.as_str() == Ok(BINARY_NAME) => {
|
||||||
// We store the identity name as a Common Name attribute.
|
// We store the identity name as a Common Name attribute.
|
||||||
let name = cert
|
let name = cert
|
||||||
.subject()
|
.subject()
|
||||||
|
|||||||
Reference in New Issue
Block a user