@@ -12,8 +12,6 @@ namespace System.Security.Cryptography
1212 [ Experimental ( Experimentals . PostQuantumCryptographyDiagId , UrlFormat = Experimentals . SharedUrlFormat ) ]
1313 public sealed class CompositeMLDsaAlgorithm : IEquatable < CompositeMLDsaAlgorithm >
1414 {
15- internal const int RandomizerSizeInBytes = 32 ;
16-
1715 /// <summary>
1816 /// Gets the name of the algorithm.
1917 /// </summary>
@@ -454,8 +452,8 @@ private static CompositeMLDsaAlgorithm CreateRsa(
454452 mldsaAlgorithm . PrivateSeedSizeInBytes + maxRsaPrivateKeySizeInBytes ,
455453 mldsaAlgorithm . PublicKeySizeInBytes + keySizeInBytes , // Private key contains at least n
456454 mldsaAlgorithm . PublicKeySizeInBytes + maxRsaPublicKeySizeInBytes ,
457- RandomizerSizeInBytes + mldsaAlgorithm . SignatureSizeInBytes + keySizeInBytes ,
458- RandomizerSizeInBytes + mldsaAlgorithm . SignatureSizeInBytes + keySizeInBytes ,
455+ mldsaAlgorithm . SignatureSizeInBytes + keySizeInBytes ,
456+ mldsaAlgorithm . SignatureSizeInBytes + keySizeInBytes ,
459457 oid ) ;
460458 }
461459
@@ -465,29 +463,8 @@ private static CompositeMLDsaAlgorithm CreateECDsa(
465463 int keySizeInBits ,
466464 string oid )
467465 {
468- // The key size calculation depends on the size of the curve algorithm's OID, and only includes the curves
469- // supported at the time of writing this code. If more curves are added, ensure the OID length is accounted for in the calculation.
470- Debug . Assert ( oid is
471- Oids . MLDsa44WithECDsaP256PreHashSha256 or
472- Oids . MLDsa65WithECDsaP256PreHashSha512 or
473- Oids . MLDsa65WithECDsaP384PreHashSha512 or
474- Oids . MLDsa87WithECDsaP384PreHashSha512 or
475- Oids . MLDsa87WithECDsaP521PreHashSha512 or
476- Oids . MLDsa65WithECDsaBrainpoolP256r1PreHashSha512 or
477- Oids . MLDsa87WithECDsaBrainpoolP384r1PreHashSha512 ) ;
478-
479466 int keySizeInBytes = ( keySizeInBits + 7 ) / 8 ;
480467
481- const int MaxUniversalTagLength = 1 ;
482-
483- // long form prefix and 4 bytes for length. CLR arrays and spans only support length up to int.MaxValue.
484- // Padding with leading zero bytes is allowed, but we still limit the length to 4 bytes since the only
485- // plausible scenario would be encoding a 4-byte numeric data type without trimming.
486- // Note this bound also covers indefinite length encodings which require only 1 + 2 bytes of overhead.
487- const int MaxLengthLength = 1 + 4 ;
488-
489- const int MaxPrefixLength = MaxUniversalTagLength + MaxLengthLength ;
490-
491468 // RFC 5915, Section 3
492469 // ECPrivateKey ::= SEQUENCE {
493470 // version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1),
@@ -496,51 +473,32 @@ Oids.MLDsa65WithECDsaBrainpoolP256r1PreHashSha512 or
496473 // publicKey [1] BIT STRING OPTIONAL
497474 // }
498475
499- int maxPrivateKeySizeInBytes =
500- MaxPrefixLength +
501- (
502- // version
503- MaxPrefixLength + 1 + // Version should always be 1
504-
505- // privateKey
506- MaxPrefixLength + keySizeInBytes +
507-
508- // parameters
509- 1 + MaxLengthLength + // Explicit tag
510- (
511- // RFC5480, Section 2.1.1
512- // ECParameters ::= CHOICE {
513- // namedCurve OBJECT IDENTIFIER
514- // -- implicitCurve NULL
515- // -- specifiedCurve SpecifiedECDomain
516- // }
517- // -- implicitCurve and specifiedCurve MUST NOT be used in PKIX.
518- //
519- // So this is a CHOICE with with the only option being a namedCurve OBJECT IDENTIFIER.
520- //
521- // Curve | OID | DER Encoding with prefix | Length without prefix
522- // ----------------|-----------------------|----------------------------------|----------------------
523- // secp256r1 | 1.2.840.10045.3.1.7 | 06 08 2A 86 48 CE 3D 03 01 07 | 8
524- // secp384r1 | 1.3.132.0.34 | 06 05 2B 81 04 00 22 | 5
525- // secp521r1 | 1.3.132.0.35 | 06 05 2B 81 04 00 23 | 5
526- // brainpoolP256r1 | 1.3.36.3.3.2.8.1.1.7 | 06 09 2B 24 03 03 02 08 01 01 07 | 9
527- // brainpoolP384r1 | 1.3.36.3.3.2.8.1.1.11 | 06 09 2B 24 03 03 02 08 01 01 0B | 9
528- MaxPrefixLength + 9 // This doesn't need to be exact, but it does need to consider all supported curves.
529- ) +
530-
531- // publicKey
532- 1 + MaxLengthLength + // Explicit tag
533- 1 + 2 * keySizeInBytes
534- ) ;
476+ int versionSizeInBytes =
477+ 1 + // Tag for INTEGER
478+ 1 + // Length field
479+ 1 ; // Value (always 1)
480+
481+ int privateKeySizeInBytes =
482+ 1 + // Tag for OCTET STRING
483+ GetDerLengthLength ( keySizeInBytes ) + // Length field
484+ keySizeInBytes ; // Value
485+
486+ // parameters and publicKey must be omitted for Composite ML-DSA
487+
488+ int ecPrivateKeySizeInBytes =
489+ 1 + // Tag for SEQUENCE
490+ GetDerLengthLength ( versionSizeInBytes + privateKeySizeInBytes ) + // Length field
491+ versionSizeInBytes + // Version
492+ privateKeySizeInBytes ;
535493
536494 return new CompositeMLDsaAlgorithm (
537495 name ,
538- mldsaAlgorithm . PrivateSeedSizeInBytes + keySizeInBytes , // ECPrivateKey has at least the private key
539- mldsaAlgorithm . PrivateSeedSizeInBytes + maxPrivateKeySizeInBytes ,
496+ mldsaAlgorithm . PrivateSeedSizeInBytes + ecPrivateKeySizeInBytes ,
497+ mldsaAlgorithm . PrivateSeedSizeInBytes + ecPrivateKeySizeInBytes ,
540498 mldsaAlgorithm . PublicKeySizeInBytes + 1 + 2 * keySizeInBytes ,
541499 mldsaAlgorithm . PublicKeySizeInBytes + 1 + 2 * keySizeInBytes ,
542- RandomizerSizeInBytes + mldsaAlgorithm . SignatureSizeInBytes + 2 + 3 * 2 , // 2 non-zero INTEGERS and overhead for 3 ASN.1 values
543- RandomizerSizeInBytes + mldsaAlgorithm . SignatureSizeInBytes + AsymmetricAlgorithmHelpers . GetMaxDerSignatureSize ( keySizeInBits ) ,
500+ mldsaAlgorithm . SignatureSizeInBytes + 2 + 3 * 2 , // 2 non-zero INTEGERS and overhead for 3 ASN.1 values
501+ mldsaAlgorithm . SignatureSizeInBytes + AsymmetricAlgorithmHelpers . GetMaxDerSignatureSize ( keySizeInBits ) ,
544502 oid ) ;
545503 }
546504
@@ -559,9 +517,28 @@ private static CompositeMLDsaAlgorithm CreateEdDsa(
559517 mldsaAlgorithm . PrivateSeedSizeInBytes + keySizeInBytes ,
560518 mldsaAlgorithm . PublicKeySizeInBytes + keySizeInBytes ,
561519 mldsaAlgorithm . PublicKeySizeInBytes + keySizeInBytes ,
562- RandomizerSizeInBytes + mldsaAlgorithm . SignatureSizeInBytes + 2 * keySizeInBytes ,
563- RandomizerSizeInBytes + mldsaAlgorithm . SignatureSizeInBytes + 2 * keySizeInBytes ,
520+ mldsaAlgorithm . SignatureSizeInBytes + 2 * keySizeInBytes ,
521+ mldsaAlgorithm . SignatureSizeInBytes + 2 * keySizeInBytes ,
564522 oid ) ;
565523 }
524+
525+ private static int GetDerLengthLength ( int payloadLength )
526+ {
527+ Debug . Assert ( payloadLength >= 0 ) ;
528+
529+ if ( payloadLength <= 0x7F )
530+ return 1 ;
531+
532+ if ( payloadLength <= 0xFF )
533+ return 2 ;
534+
535+ if ( payloadLength <= 0xFFFF )
536+ return 3 ;
537+
538+ if ( payloadLength <= 0xFFFFFF )
539+ return 4 ;
540+
541+ return 5 ;
542+ }
566543 }
567544}
0 commit comments