Skip to content

Commit

Permalink
Add specific error message for OpenSSH hardware authenticators
Browse files Browse the repository at this point in the history
  • Loading branch information
str4d committed Jan 25, 2024
1 parent 5bedf77 commit 188f7fc
Show file tree
Hide file tree
Showing 9 changed files with 57 additions and 9 deletions.
19 changes: 19 additions & 0 deletions age/i18n/en-US/age.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@
-ssh-keygen = ssh-keygen
-ssh-rsa = ssh-rsa
-ssh-ed25519 = ssh-ed25519
-fido-u2f = FIDO/U2F
-yubikeys = YubiKeys
-piv = PIV
## CLI helpers

Expand Down Expand Up @@ -148,3 +151,19 @@ ssh-unsupported-key-type =
subset of these for backwards compatibility, specifically the '{-ssh-rsa}'
and '{-ssh-ed25519}' key types. This SSH key uses the unsupported key type
'{$key_type}'.
ssh-unsupported-security-key =
Unsupported SSH Hardware Authenticator
--------------------------------------
{-openssh} version 8.2p1 added support for {-fido-u2f} hardware authenticators,
including hardware security keys such as {-yubikeys}. {-rage} does not work with
these SSH key types, because their protocol does not support encryption.
This SSH key uses the incompatible type '{$key_type}'.
If you have a compatible hardware security key, you should use this plugin:
{$age_plugin_yubikey_url}
A hardware security key used with both {-openssh} and this plugin will have a
separate SSH public key and {-age} encryption recipient, because the plugin
implements the {-piv} protocol.
3 changes: 3 additions & 0 deletions age/i18n/es-AR/age.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@
-ssh-keygen = ssh-keygen
-ssh-rsa = ssh-rsa
-ssh-ed25519 = ssh-ed25519
-fido-u2f = FIDO/U2F
-yubikeys = YubiKeys
-piv = PIV
## CLI helpers

Expand Down
3 changes: 3 additions & 0 deletions age/i18n/it/age.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@
-ssh-keygen = ssh-keygen
-ssh-rsa = ssh-rsa
-ssh-ed25519 = ssh-ed25519
-fido-u2f = FIDO/U2F
-yubikeys = YubiKeys
-piv = PIV
## CLI helpers

Expand Down
3 changes: 3 additions & 0 deletions age/i18n/zh-CN/age.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@
-ssh-keygen = ssh-keygen
-ssh-rsa = ssh-rsa
-ssh-ed25519 = ssh-ed25519
-fido-u2f = FIDO/U2F
-yubikeys = YubiKeys
-piv = PIV
## CLI helpers

Expand Down
3 changes: 3 additions & 0 deletions age/i18n/zh-TW/age.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@
-ssh-keygen = ssh-keygen
-ssh-rsa = ssh-rsa
-ssh-ed25519 = ssh-ed25519
-fido-u2f = FIDO/U2F
-yubikeys = YubiKeys
-piv = PIV
## CLI helpers

Expand Down
2 changes: 1 addition & 1 deletion age/src/cli_common/recipients.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ where
ParseRecipientKeyError::RsaModulusTooLarge => Err(ReadError::RsaModulusTooLarge),
ParseRecipientKeyError::Unsupported(key_type) => Err(ReadError::UnsupportedKey(
filename.to_string(),
UnsupportedKey::Type(key_type),
UnsupportedKey::from_key_type(key_type),
)),
},
}
Expand Down
3 changes: 2 additions & 1 deletion age/src/ssh.rs
Original file line number Diff line number Diff line change
Expand Up @@ -415,7 +415,8 @@ mod read_ssh {
UnencryptedKey::SshEd25519(ssh_key_ed25519.clone(), privkey).into()
}),
map(string, |key_type| {
UnsupportedKey::Type(String::from_utf8_lossy(key_type).to_string()).into()
UnsupportedKey::from_key_type(String::from_utf8_lossy(key_type).to_string())
.into()
}),
)),
)
Expand Down
24 changes: 20 additions & 4 deletions age/src/ssh/identity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ use crate::{
error::DecryptError,
fl,
util::read::{base64_arg, wrapped_str_while_encoded},
wlnfl, Callbacks,
wfl, wlnfl, Callbacks,
};

/// An SSH private key for decrypting an age file.
Expand Down Expand Up @@ -136,19 +136,29 @@ pub enum UnsupportedKey {
EncryptedPem,
/// An encrypted SSH key using a specific cipher.
EncryptedSsh(String),
/// An SSH key type we believe to be stored on a hardware security key.
Hardware(String),
/// An SSH key type that we do not support.
Type(String),
}

impl UnsupportedKey {
pub(crate) fn from_key_type(key_type: String) -> Self {
if key_type.starts_with("sk-ssh-") {
Self::Hardware(key_type)
} else {
Self::Type(key_type)
}
}

/// Prints details about this unsupported key.
pub fn display(&self, f: &mut fmt::Formatter, filename: Option<&str>) -> fmt::Result {
if let Some(name) = filename {
wlnfl!(f, "ssh-unsupported-key", name = name)?;
writeln!(f)?;
}
match self {
UnsupportedKey::EncryptedPem => wlnfl!(
UnsupportedKey::EncryptedPem => wfl!(
f,
"ssh-insecure-key-format",
change_passphrase = "ssh-keygen -o -p",
Expand All @@ -159,15 +169,21 @@ impl UnsupportedKey {
"https://github.com/str4d/rage/issues/new?title=Support%20OpenSSH%20key%20encryption%20cipher%20{}",
cipher,
);
wlnfl!(
wfl!(
f,
"ssh-unsupported-cipher",
cipher = cipher.as_str(),
new_issue = new_issue.as_str(),
)?;
}
UnsupportedKey::Hardware(key_type) => wfl!(
f,
"ssh-unsupported-security-key",
key_type = key_type.as_str(),
age_plugin_yubikey_url = "https://str4d.xyz/age-plugin-yubikey",
)?,
UnsupportedKey::Type(key_type) => {
wlnfl!(f, "ssh-unsupported-key-type", key_type = key_type.as_str())?
wfl!(f, "ssh-unsupported-key-type", key_type = key_type.as_str())?
}
}
Ok(())
Expand Down
6 changes: 3 additions & 3 deletions age/src/ssh/recipient.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,9 +129,9 @@ impl TryFrom<Identity> for Recipient {
))
}
}
Identity::Unsupported(UnsupportedKey::Type(key_type)) => {
Err(ParseRecipientKeyError::Unsupported(key_type))
}
Identity::Unsupported(
UnsupportedKey::Hardware(key_type) | UnsupportedKey::Type(key_type),
) => Err(ParseRecipientKeyError::Unsupported(key_type)),
Identity::Unsupported(_) => Err(ParseRecipientKeyError::Ignore),
}
}
Expand Down

0 comments on commit 188f7fc

Please sign in to comment.