Skip to content
Open
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
77 changes: 77 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 5 additions & 1 deletion ssh-key/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ dsa = { version = "0.7", optional = true, default-features = false, features = [
ed25519-dalek = { version = "3", optional = true, default-features = false }
hex = { version = "0.4", optional = true, default-features = false, features = ["alloc"] }
hmac = { version = "0.13", optional = true }
ml-dsa = { version = "0.1", optional = true, default-features = false, features = ["alloc", "zeroize"] }
p256 = { version = "0.14", optional = true, default-features = false, features = ["ecdsa"] }
p384 = { version = "0.14", optional = true, default-features = false, features = ["ecdsa"] }
p521 = { version = "0.14", optional = true, default-features = false, features = ["ecdsa"] }
Expand All @@ -51,7 +52,7 @@ default = ["ecdsa", "rand_core", "std"]
alloc = ["encoding/alloc", "signature/alloc", "zeroize/alloc", ]
std = ["alloc"]

crypto = ["ed25519", "p256", "p384", "p521", "rsa"] # NOTE: `dsa` is obsolete/weak
crypto = ["ed25519", "mldsa-eddsa", "p256", "p384", "p521", "rsa"] # NOTE: `dsa` is obsolete/weak
dsa = ["dep:dsa", "dep:sha1", "alloc", "encoding/bigint", "signature/rand_core"]
ecdsa = ["dep:sec1"]
ed25519 = ["dep:ed25519-dalek", "rand_core"]
Expand All @@ -63,6 +64,9 @@ encryption = [
"rand_core"
]
getrandom = ["cipher/getrandom", "rand_core"]
# MLDSA44-Ed25519-SHA512 composite signatures, as implemented by OpenSSH. Based on
# draft-miller-sshm-mldsa44-ed25519-composite-sigs, which is still a draft
mldsa-eddsa = ["dep:ml-dsa", "ed25519", "alloc", "rand_core"]
p256 = ["dep:p256", "ecdsa"]
p384 = ["dep:p384", "ecdsa"]
p521 = ["dep:p521", "ecdsa"]
Expand Down
3 changes: 2 additions & 1 deletion ssh-key/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ respective SSH key algorithm.
- [x] OpenSSH certificate authority (CA) support i.e. cert builder/signer
- [x] Private key encryption/decryption (`bcrypt-pbkdf` + `aes256-ctr` only)
- [x] Private key generation support: DSA, Ed25519, ECDSA (P-256/P-384/P-521),
and RSA
RSA, and MLDSA44-Ed25519
- [x] FIDO/U2F key support (`sk-*`) as specified in [PROTOCOL.u2f]
- [x] Fingerprint support
- [x] "randomart" fingerprint visualizations
Expand Down Expand Up @@ -73,6 +73,7 @@ respective SSH key algorithm.
| `ssh‑rsa` | ✅ | ✅ | ✅ | ✅️ | ✅️ | ✅ | `rsa` | `alloc` |
| `sk‑ecdsa‑sha2‑nistp256@openssh.com` | ✅ | ✅ | ✅ | ⛔ | ⛔️ | ✅️ | ⛔ | `alloc` |
| `sk‑ssh‑ed25519@openssh.com` | ✅ | ✅ | ✅ | ⛔ | ⛔️ | ✅️️ | `ed25519` | `alloc` |
| `ssh‑mldsa44‑ed25519@openssh.com` | ✅ | ✅ | ✅ | ✅️ | ✅️ | ✅️ | `mldsa-eddsa` | `alloc` |

By default *no SSH signature algorithms are enabled* and you will get an
`Error::AlgorithmUnsupported` error if you try to use them.
Expand Down
21 changes: 21 additions & 0 deletions ssh-key/src/algorithm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ const CERT_SK_ECDSA_SHA2_P256: &str = "sk-ecdsa-sha2-nistp256-cert-v01@openssh.c
/// OpenSSH certificate for Ed25519 U2F/FIDO security key
const CERT_SK_SSH_ED25519: &str = "sk-ssh-ed25519-cert-v01@openssh.com";

/// OpenSSH certificate for MLDSA44-Ed25519 composite public key
const CERT_MLDSA44_ED25519: &str = "ssh-mldsa44-ed25519-cert-v01@openssh.com";

/// ECDSA with SHA-256 + NIST P-256
const ECDSA_SHA2_P256: &str = "ecdsa-sha2-nistp256";

Expand Down Expand Up @@ -86,6 +89,9 @@ const SK_ECDSA_SHA2_P256: &str = "sk-ecdsa-sha2-nistp256@openssh.com";
/// U2F/FIDO security key with Ed25519
const SK_SSH_ED25519: &str = "sk-ssh-ed25519@openssh.com";

/// MLDSA44-Ed25519-SHA512 composite signature algorithm
const SSH_MLDSA44_ED25519: &str = "ssh-mldsa44-ed25519@openssh.com";

/// SSH key algorithms, i.e. digital signature algorithms used with SSH private/public keys.
#[derive(Clone, Debug, Default, Eq, Hash, PartialEq, PartialOrd, Ord)]
#[non_exhaustive]
Expand Down Expand Up @@ -121,6 +127,9 @@ pub enum Algorithm {
/// FIDO/U2F key with Ed25519
SkEd25519,

/// MLDSA44-Ed25519-SHA512 composite signature algorithm.
MlDsa44Ed25519,

/// Other
#[cfg(feature = "alloc")]
Other(AlgorithmName),
Expand All @@ -138,6 +147,7 @@ impl Algorithm {
/// - `ssh-rsa`
/// - `sk-ecdsa-sha2-nistp256@openssh.com` (FIDO/U2F key)
/// - `sk-ssh-ed25519@openssh.com` (FIDO/U2F key)
/// - `ssh-mldsa44-ed25519@openssh.com`
///
/// Any other algorithms are mapped to the [`Algorithm::Other`] variant.
///
Expand All @@ -161,6 +171,7 @@ impl Algorithm {
/// - `ssh-ed25519-cert-v01@openssh.com`
/// - `sk-ecdsa-sha2-nistp256-cert-v01@openssh.com` (FIDO/U2F key)
/// - `sk-ssh-ed25519-cert-v01@openssh.com` (FIDO/U2F key)
/// - `ssh-mldsa44-ed25519-cert-v01@openssh.com`
///
/// Any other algorithms are mapped to the [`Algorithm::Other`] variant.
///
Expand Down Expand Up @@ -190,6 +201,7 @@ impl Algorithm {
}),
CERT_SK_ECDSA_SHA2_P256 => Ok(Algorithm::SkEcdsaSha2NistP256),
CERT_SK_SSH_ED25519 => Ok(Algorithm::SkEd25519),
CERT_MLDSA44_ED25519 => Ok(Algorithm::MlDsa44Ed25519),
#[cfg(feature = "alloc")]
_ => Ok(Algorithm::Other(AlgorithmName::from_certificate_type(id)?)),
#[cfg(not(feature = "alloc"))]
Expand All @@ -215,6 +227,7 @@ impl Algorithm {
},
Algorithm::SkEcdsaSha2NistP256 => SK_ECDSA_SHA2_P256,
Algorithm::SkEd25519 => SK_SSH_ED25519,
Algorithm::MlDsa44Ed25519 => SSH_MLDSA44_ED25519,
#[cfg(feature = "alloc")]
Algorithm::Other(algorithm) => algorithm.as_str(),
}
Expand Down Expand Up @@ -247,6 +260,7 @@ impl Algorithm {
} => CERT_RSA_SHA2_512,
Algorithm::SkEcdsaSha2NistP256 => CERT_SK_ECDSA_SHA2_P256,
Algorithm::SkEd25519 => CERT_SK_SSH_ED25519,
Algorithm::MlDsa44Ed25519 => CERT_MLDSA44_ED25519,
Algorithm::Other(algorithm) => return algorithm.certificate_type(),
}
.to_owned()
Expand Down Expand Up @@ -276,6 +290,12 @@ impl Algorithm {
matches!(self, Algorithm::Rsa { .. })
}

/// Is the algorithm the MLDSA44-Ed25519 composite scheme?
#[must_use]
pub fn is_mldsa44_ed25519(self) -> bool {
matches!(self, Algorithm::MlDsa44Ed25519)
}

/// Return an error indicating this algorithm is unsupported.
#[allow(dead_code)]
pub(crate) fn unsupported_error(self) -> Error {
Expand Down Expand Up @@ -322,6 +342,7 @@ impl str::FromStr for Algorithm {
SSH_RSA => Ok(Algorithm::Rsa { hash: None }),
SK_ECDSA_SHA2_P256 => Ok(Algorithm::SkEcdsaSha2NistP256),
SK_SSH_ED25519 => Ok(Algorithm::SkEd25519),
SSH_MLDSA44_ED25519 => Ok(Algorithm::MlDsa44Ed25519),
#[cfg(feature = "alloc")]
_ => Ok(Algorithm::Other(AlgorithmName::from_str(id)?)),
#[cfg(not(feature = "alloc"))]
Expand Down
2 changes: 2 additions & 0 deletions ssh-key/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,8 @@ mod kdf;
mod comment;
#[cfg(feature = "std")]
mod dot_ssh;
#[cfg(feature = "mldsa-eddsa")]
mod mldsa_eddsa;
#[cfg(feature = "ppk")]
mod ppk;
#[cfg(feature = "alloc")]
Expand Down
Loading