@@ -47,14 +47,8 @@ const CERT_SK_ECDSA_SHA2_P256: &str = "sk-ecdsa-sha2-nistp256-cert-v01@openssh.c
4747/// OpenSSH certificate for Ed25519 U2F/FIDO security key
4848const CERT_SK_SSH_ED25519 : & str = "sk-ssh-ed25519-cert-v01@openssh.com" ;
4949
50- /// OpenSSH certificate for ML-DSA-44 public key
51- const CERT_MLDSA_44 : & str = "ssh-mldsa-44-cert-v01@openssh.com" ;
52-
53- /// OpenSSH certificate for ML-DSA-65 public key
54- const CERT_MLDSA_65 : & str = "ssh-mldsa-65-cert-v01@openssh.com" ;
55-
56- /// OpenSSH certificate for ML-DSA-87 public key
57- const CERT_MLDSA_87 : & str = "ssh-mldsa-87-cert-v01@openssh.com" ;
50+ /// OpenSSH certificate for MLDSA44-Ed25519 composite public key
51+ const CERT_MLDSA44_ED25519 : & str = "ssh-mldsa44-ed25519-cert-v01@openssh.com" ;
5852
5953/// ECDSA with SHA-256 + NIST P-256
6054const ECDSA_SHA2_P256 : & str = "ecdsa-sha2-nistp256" ;
@@ -95,14 +89,8 @@ const SK_ECDSA_SHA2_P256: &str = "sk-ecdsa-sha2-nistp256@openssh.com";
9589/// U2F/FIDO security key with Ed25519
9690const SK_SSH_ED25519 : & str = "sk-ssh-ed25519@openssh.com" ;
9791
98- /// ML-DSA-44 (FIPS 204, security category 2)
99- const SSH_MLDSA_44 : & str = "ssh-mldsa-44" ;
100-
101- /// ML-DSA-65 (FIPS 204, security category 3)
102- const SSH_MLDSA_65 : & str = "ssh-mldsa-65" ;
103-
104- /// ML-DSA-87 (FIPS 204, security category 5)
105- const SSH_MLDSA_87 : & str = "ssh-mldsa-87" ;
92+ /// MLDSA44-Ed25519-SHA512 composite signature algorithm
93+ const SSH_MLDSA44_ED25519 : & str = "ssh-mldsa44-ed25519@openssh.com" ;
10694
10795/// SSH key algorithms, i.e. digital signature algorithms used with SSH private/public keys.
10896#[ derive( Clone , Debug , Default , Eq , Hash , PartialEq , PartialOrd , Ord ) ]
@@ -139,11 +127,8 @@ pub enum Algorithm {
139127 /// FIDO/U2F key with Ed25519
140128 SkEd25519 ,
141129
142- /// ML-DSA
143- MlDsa {
144- /// ML-DSA parameter set to use.
145- params : MlDsaParams ,
146- } ,
130+ /// MLDSA44-Ed25519-SHA512 composite signature algorithm.
131+ MlDsa44Ed25519 ,
147132
148133 /// Other
149134 #[ cfg( feature = "alloc" ) ]
@@ -162,9 +147,7 @@ impl Algorithm {
162147 /// - `ssh-rsa`
163148 /// - `sk-ecdsa-sha2-nistp256@openssh.com` (FIDO/U2F key)
164149 /// - `sk-ssh-ed25519@openssh.com` (FIDO/U2F key)
165- /// - `ssh-mldsa-44`
166- /// - `ssh-mldsa-65`
167- /// - `ssh-mldsa-87`
150+ /// - `ssh-mldsa44-ed25519@openssh.com`
168151 ///
169152 /// Any other algorithms are mapped to the [`Algorithm::Other`] variant.
170153 ///
@@ -188,9 +171,7 @@ impl Algorithm {
188171 /// - `ssh-ed25519-cert-v01@openssh.com`
189172 /// - `sk-ecdsa-sha2-nistp256-cert-v01@openssh.com` (FIDO/U2F key)
190173 /// - `sk-ssh-ed25519-cert-v01@openssh.com` (FIDO/U2F key)
191- /// - `ssh-mldsa-44-cert-v01@openssh.com`
192- /// - `ssh-mldsa-65-cert-v01@openssh.com`
193- /// - `ssh-mldsa-87-cert-v01@openssh.com`
174+ /// - `ssh-mldsa44-ed25519-cert-v01@openssh.com`
194175 ///
195176 /// Any other algorithms are mapped to the [`Algorithm::Other`] variant.
196177 ///
@@ -220,15 +201,7 @@ impl Algorithm {
220201 } ) ,
221202 CERT_SK_ECDSA_SHA2_P256 => Ok ( Algorithm :: SkEcdsaSha2NistP256 ) ,
222203 CERT_SK_SSH_ED25519 => Ok ( Algorithm :: SkEd25519 ) ,
223- CERT_MLDSA_44 => Ok ( Algorithm :: MlDsa {
224- params : MlDsaParams :: MlDsa44 ,
225- } ) ,
226- CERT_MLDSA_65 => Ok ( Algorithm :: MlDsa {
227- params : MlDsaParams :: MlDsa65 ,
228- } ) ,
229- CERT_MLDSA_87 => Ok ( Algorithm :: MlDsa {
230- params : MlDsaParams :: MlDsa87 ,
231- } ) ,
204+ CERT_MLDSA44_ED25519 => Ok ( Algorithm :: MlDsa44Ed25519 ) ,
232205 #[ cfg( feature = "alloc" ) ]
233206 _ => Ok ( Algorithm :: Other ( AlgorithmName :: from_certificate_type ( id) ?) ) ,
234207 #[ cfg( not( feature = "alloc" ) ) ]
@@ -254,11 +227,7 @@ impl Algorithm {
254227 } ,
255228 Algorithm :: SkEcdsaSha2NistP256 => SK_ECDSA_SHA2_P256 ,
256229 Algorithm :: SkEd25519 => SK_SSH_ED25519 ,
257- Algorithm :: MlDsa { params } => match params {
258- MlDsaParams :: MlDsa44 => SSH_MLDSA_44 ,
259- MlDsaParams :: MlDsa65 => SSH_MLDSA_65 ,
260- MlDsaParams :: MlDsa87 => SSH_MLDSA_87 ,
261- } ,
230+ Algorithm :: MlDsa44Ed25519 => SSH_MLDSA44_ED25519 ,
262231 #[ cfg( feature = "alloc" ) ]
263232 Algorithm :: Other ( algorithm) => algorithm. as_str ( ) ,
264233 }
@@ -291,11 +260,7 @@ impl Algorithm {
291260 } => CERT_RSA_SHA2_512 ,
292261 Algorithm :: SkEcdsaSha2NistP256 => CERT_SK_ECDSA_SHA2_P256 ,
293262 Algorithm :: SkEd25519 => CERT_SK_SSH_ED25519 ,
294- Algorithm :: MlDsa { params } => match params {
295- MlDsaParams :: MlDsa44 => CERT_MLDSA_44 ,
296- MlDsaParams :: MlDsa65 => CERT_MLDSA_65 ,
297- MlDsaParams :: MlDsa87 => CERT_MLDSA_87 ,
298- } ,
263+ Algorithm :: MlDsa44Ed25519 => CERT_MLDSA44_ED25519 ,
299264 Algorithm :: Other ( algorithm) => return algorithm. certificate_type ( ) ,
300265 }
301266 . to_owned ( )
@@ -325,10 +290,10 @@ impl Algorithm {
325290 matches ! ( self , Algorithm :: Rsa { .. } )
326291 }
327292
328- /// Is the algorithm ML-DSA ?
293+ /// Is the algorithm the MLDSA44-Ed25519 composite scheme ?
329294 #[ must_use]
330- pub fn is_mldsa ( self ) -> bool {
331- matches ! ( self , Algorithm :: MlDsa { .. } )
295+ pub fn is_mldsa44_ed25519 ( self ) -> bool {
296+ matches ! ( self , Algorithm :: MlDsa44Ed25519 )
332297 }
333298
334299 /// Return an error indicating this algorithm is unsupported.
@@ -377,15 +342,7 @@ impl str::FromStr for Algorithm {
377342 SSH_RSA => Ok ( Algorithm :: Rsa { hash : None } ) ,
378343 SK_ECDSA_SHA2_P256 => Ok ( Algorithm :: SkEcdsaSha2NistP256 ) ,
379344 SK_SSH_ED25519 => Ok ( Algorithm :: SkEd25519 ) ,
380- SSH_MLDSA_44 => Ok ( Algorithm :: MlDsa {
381- params : MlDsaParams :: MlDsa44 ,
382- } ) ,
383- SSH_MLDSA_65 => Ok ( Algorithm :: MlDsa {
384- params : MlDsaParams :: MlDsa65 ,
385- } ) ,
386- SSH_MLDSA_87 => Ok ( Algorithm :: MlDsa {
387- params : MlDsaParams :: MlDsa87 ,
388- } ) ,
345+ SSH_MLDSA44_ED25519 => Ok ( Algorithm :: MlDsa44Ed25519 ) ,
389346 #[ cfg( feature = "alloc" ) ]
390347 _ => Ok ( Algorithm :: Other ( AlgorithmName :: from_str ( id) ?) ) ,
391348 #[ cfg( not( feature = "alloc" ) ) ]
@@ -476,108 +433,6 @@ impl str::FromStr for EcdsaCurve {
476433 }
477434}
478435
479- /// ML-DSA parameter sets supported for use with SSH as specified in [FIPS204].
480- ///
481- /// Each parameter set corresponds to a NIST security category.
482- ///
483- /// [FIPS204]: https://csrc.nist.gov/pubs/fips/204/final
484- #[ derive( Copy , Clone , Debug , Eq , Hash , PartialEq , PartialOrd , Ord ) ]
485- pub enum MlDsaParams {
486- /// ML-DSA-44 (security category 2).
487- MlDsa44 ,
488-
489- /// ML-DSA-65 (security category 3)
490- MlDsa65 ,
491-
492- /// ML-DSA-87 (security category 5).
493- MlDsa87 ,
494- }
495-
496- impl MlDsaParams {
497- /// Decode an ML-DSA parameter set from the given SSH algorithm identifier.
498- ///
499- /// # Supported identifiers
500- ///
501- /// - `ssh-mldsa-44`
502- /// - `ssh-mldsa-65`
503- /// - `ssh-mldsa-87`
504- ///
505- /// # Errors
506- /// Returns [`Error::Encoding`] in the event the identifier is not known.
507- pub fn new ( id : & str ) -> Result < Self > {
508- Ok ( id. parse ( ) ?)
509- }
510-
511- /// Get the SSH algorithm identifier which corresponds to this parameter set.
512- #[ must_use]
513- pub fn as_str ( self ) -> & ' static str {
514- match self {
515- MlDsaParams :: MlDsa44 => SSH_MLDSA_44 ,
516- MlDsaParams :: MlDsa65 => SSH_MLDSA_65 ,
517- MlDsaParams :: MlDsa87 => SSH_MLDSA_87 ,
518- }
519- }
520-
521- /// Size in bytes of a FIPS 204 public key for this parameter set.
522- #[ must_use]
523- pub const fn public_key_size ( self ) -> usize {
524- match self {
525- MlDsaParams :: MlDsa44 => 1312 ,
526- MlDsaParams :: MlDsa65 => 1952 ,
527- MlDsaParams :: MlDsa87 => 2592 ,
528- }
529- }
530-
531- /// Size in bytes of a FIPS 204 signature for this parameter set.
532- #[ must_use]
533- pub const fn signature_size ( self ) -> usize {
534- match self {
535- MlDsaParams :: MlDsa44 => 2420 ,
536- MlDsaParams :: MlDsa65 => 3309 ,
537- MlDsaParams :: MlDsa87 => 4627 ,
538- }
539- }
540-
541- /// Size in bytes of the seed (ξ) used to derive an ML-DSA key.
542- ///
543- /// This is 32 bytes for all parameter sets.
544- #[ must_use]
545- pub const fn seed_size ( self ) -> usize {
546- 32
547- }
548- }
549-
550- impl AsRef < str > for MlDsaParams {
551- fn as_ref ( & self ) -> & str {
552- self . as_str ( )
553- }
554- }
555-
556- impl From < MlDsaParams > for Algorithm {
557- fn from ( params : MlDsaParams ) -> Algorithm {
558- Algorithm :: MlDsa { params }
559- }
560- }
561-
562- impl fmt:: Display for MlDsaParams {
563- fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
564- f. write_str ( self . as_str ( ) )
565- }
566- }
567-
568- impl str:: FromStr for MlDsaParams {
569- type Err = LabelError ;
570-
571- fn from_str ( id : & str ) -> core:: result:: Result < Self , LabelError > {
572- match id {
573- SSH_MLDSA_44 => Ok ( MlDsaParams :: MlDsa44 ) ,
574- SSH_MLDSA_65 => Ok ( MlDsaParams :: MlDsa65 ) ,
575- SSH_MLDSA_87 => Ok ( MlDsaParams :: MlDsa87 ) ,
576- _ => Err ( LabelError :: new ( id) ) ,
577- }
578- }
579- }
580-
581436/// Hashing algorithms a.k.a. digest functions.
582437#[ derive( Copy , Clone , Debug , Default , Eq , Hash , PartialEq , PartialOrd , Ord ) ]
583438#[ non_exhaustive]
0 commit comments