Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
e0b1dae
Added support for a custom salt length when using PSS signature valid…
henning-krause May 16, 2025
05ed28b
Review
henning-krause May 16, 2025
21135d5
Merge branch 'dotnet:main' into 104080-custom-rsapss-salt-length
henning-krause Jun 5, 2025
d705126
Review all usages for RSASignaturePadding to check for missing PSS sa…
henning-krause Jun 6, 2025
3c6288c
Added error handling for apple devices (custom PSS salt length not su…
henning-krause Jun 6, 2025
4d3bd37
Added sign and verify tests for custom salt lengths
henning-krause Jun 10, 2025
d19d017
Added test for max salt length verification
henning-krause Jun 10, 2025
20be62b
Added a test for the RSAPssX509SignatureGenerator
henning-krause Jun 11, 2025
c0d0ce0
Added test for CertificateRequest.LoadSigningRequest
henning-krause Jun 11, 2025
81432d5
More tests for the CertificateRequest
henning-krause Jun 11, 2025
a016382
Added custom salt support for SignedCms
henning-krause Jun 12, 2025
9cde2fa
Add error handling for PSS salt length in CoseSigner
henning-krause Jul 8, 2025
a6dd48a
Updated RSA
henning-krause Aug 27, 2025
71325e3
Merged from main
henning-krause Aug 27, 2025
e2407be
Updated CoseSigner
henning-krause Aug 29, 2025
7b65140
Code fixes
henning-krause Aug 29, 2025
623199c
Code fixes
henning-krause Aug 29, 2025
b14906e
Code fixes
henning-krause Aug 29, 2025
9dcb4ea
Code fixes
henning-krause Aug 29, 2025
fee0f09
Code fixes
henning-krause Aug 29, 2025
a386bac
Code fixes
henning-krause Aug 29, 2025
430a846
Updated a few test cases
henning-krause Sep 1, 2025
e0eb704
CRL Builder tests extended
henning-krause Sep 1, 2025
dd64636
Update src/libraries/System.Security.Cryptography/tests/X509Certifica…
henning-krause Sep 2, 2025
d97581c
Update src/libraries/System.Security.Cryptography/ref/System.Security…
henning-krause Sep 2, 2025
e99f10d
Update src/libraries/Common/src/System/Security/Cryptography/RsaPaddi…
henning-krause Sep 2, 2025
f066e97
Update src/libraries/System.Security.Cryptography.Cng/tests/RSACngPkc…
henning-krause Sep 2, 2025
de11a87
Fixed unit tests
henning-krause Sep 3, 2025
79bb2de
Merge branch '104080-custom-rsapss-salt-length' of https://github.com…
henning-krause Sep 3, 2025
6e64ad1
Merge branch 'main' into 104080-custom-rsapss-salt-length
henning-krause Sep 3, 2025
aeab113
Fixed tests
henning-krause Sep 3, 2025
d70ef9b
Review changes
henning-krause Sep 5, 2025
76065fe
Merge branch 'main' into 104080-custom-rsapss-salt-length
henning-krause Sep 5, 2025
28f4371
Fixed issues from review
henning-krause Sep 9, 2025
a990025
Merge branch 'main' into 104080-custom-rsapss-salt-length
henning-krause Sep 9, 2025
03d9b9a
Fixed tests
henning-krause Sep 10, 2025
e374a19
Fixed assertion
henning-krause Sep 10, 2025
f5459a1
Fixed tests
henning-krause Sep 11, 2025
099ac2a
Review changes
henning-krause Sep 12, 2025
e3fac63
Cleanup
henning-krause Sep 12, 2025
d579770
Fixed apple crypto validation
henning-krause Sep 15, 2025
90beb1c
Merge branch 'main' into 104080-custom-rsapss-salt-length
henning-krause Sep 15, 2025
24b6691
Merge branch 'main' into 104080-custom-rsapss-salt-length
henning-krause Nov 7, 2025
4b292d3
Merged from main
henning-krause Jan 6, 2026
966b17a
Merge branch 'dotnet:main' into 104080-custom-rsapss-salt-length
henning-krause Jan 6, 2026
0264ed5
Merged from main
henning-krause Jan 6, 2026
0c65d90
Changed .net10 #if to .net11
henning-krause Jan 6, 2026
30ff8ef
More #if replacements
henning-krause Jan 6, 2026
d335e43
Merge branch 'main' into 104080-custom-rsapss-salt-length
henning-krause Jan 6, 2026
f9fb07e
Cleaned up more review issues
henning-krause Jan 23, 2026
89d94bf
Merge branch '104080-custom-rsapss-salt-length' of https://github.com…
henning-krause Jan 23, 2026
3dc7da6
Merged from main
henning-krause Mar 24, 2026
92f2c97
Merge branch 'main' into 104080-custom-rsapss-salt-length
bartonjs Apr 27, 2026
bf6072c
Merged from main
henning-krause Jun 9, 2026
35a3dec
Merge branch '104080-custom-rsapss-salt-length' of https://github.com…
henning-krause Jun 9, 2026
f6869a5
Fix issues found in review
henning-krause Jun 9, 2026
ed35977
Review
henning-krause Jun 9, 2026
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
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,7 @@ internal static void EncodePss(HashAlgorithmName hashAlgorithmName, ReadOnlySpan
{
const int MaxStackSaltLength = 128;

int sLen = saltLength;
int hLen = HashLength(hashAlgorithmName);

// https://tools.ietf.org/html/rfc3447#section-9.1.1
Expand All @@ -296,7 +297,7 @@ internal static void EncodePss(HashAlgorithmName hashAlgorithmName, ReadOnlySpan
//
// sLen = hLen in this implementation.

if (emLen < 2 + hLen + saltLength)
if (emLen < 2 + hLen + sLen)
{
throw new CryptographicException(SR.Cryptography_KeyTooSmall);
}
Expand All @@ -323,9 +324,9 @@ internal static void EncodePss(HashAlgorithmName hashAlgorithmName, ReadOnlySpan
// 4. Generate a random salt of length sLen
Debug.Assert(hLen is >= 0 and <= 64);

Span<byte> salt = saltLength > MaxStackSaltLength
? new byte[saltLength]
: stackalloc byte[saltLength];
Span<byte> salt = sLen > MaxStackSaltLength
? new byte[sLen]
: stackalloc byte[sLen];
RandomNumberGenerator.Fill(salt);

// 5. Let M' = an octet string of 8 zeros concat mHash concat salt
Expand All @@ -343,7 +344,7 @@ internal static void EncodePss(HashAlgorithmName hashAlgorithmName, ReadOnlySpan

// 7. Generate PS as zero-valued bytes of length emLen - sLen - hLen - 2.
// 8. Let DB = PS || 0x01 || salt
int psLen = emLen - saltLength - hLen - 2;
int psLen = emLen - sLen - hLen - 2;
db.Slice(0, psLen).Clear();
db[psLen] = 0x01;
salt.CopyTo(db.Slice(psLen + 1));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1392,6 +1392,9 @@ private void VerifyExpectedSignature_Pss(
Modulus = keyParameters.Modulus,
Exponent = keyParameters.Exponent,
};

RSASignaturePadding padding = RSASignaturePadding.Pss;

using (RSA rsaPublic = RSAFactory.Create())
using (RSA rsaPrivate = RSAFactory.Create())
{
Expand All @@ -1410,27 +1413,27 @@ private void VerifyExpectedSignature_Pss(
// Generator for new tests.
if (signature == null)
{
signature = SignData(rsaPrivate, data, hashAlgorithm, RSASignaturePadding.Pss);
signature = SignData(rsaPrivate, data, hashAlgorithm, padding);
Console.WriteLine($"{callerName}: {signature.ByteArrayToHex()}");
}

if (RSAFactory.SupportsPss)
{
Assert.True(
VerifyData(rsaPublic, data, signature, hashAlgorithm, RSASignaturePadding.Pss),
VerifyData(rsaPublic, data, signature, hashAlgorithm, padding),
"Public key verified the signature");

Assert.True(
VerifyData(rsaPrivate, data, signature, hashAlgorithm, RSASignaturePadding.Pss),
VerifyData(rsaPrivate, data, signature, hashAlgorithm, padding),
"Private key verified the signature");
}
else
{
Assert.ThrowsAny<CryptographicException>(
() => VerifyData(rsaPublic, data, signature, hashAlgorithm, RSASignaturePadding.Pss));
() => VerifyData(rsaPublic, data, signature, hashAlgorithm, padding));

Assert.ThrowsAny<CryptographicException>(
() => VerifyData(rsaPrivate, data, signature, hashAlgorithm, RSASignaturePadding.Pss));
() => VerifyData(rsaPrivate, data, signature, hashAlgorithm, padding));
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -732,7 +732,7 @@ public static IEnumerable<object[]> CreateSignature_RsaPssTests() =>
from oid in (string[])([Oids.Sha256, Oids.Sha384, Oids.Sha512, Oids.Sha1])
from byCtor in new[] { true, false }
from saltLength in AreCustomPssSaltLengthsSupported
? new[] { 0, RSASignaturePadding.PssSaltLengthMax, RSASignaturePadding.PssSaltLengthIsHashLength }
? new[] { 0, 63, RSASignaturePadding.PssSaltLengthMax, RSASignaturePadding.PssSaltLengthIsHashLength }
: new[] { RSASignaturePadding.PssSaltLengthIsHashLength }
select new object[] { oid, byCtor, saltLength };

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ public static void ReadRsaPssDocument(bool fromSpan)
Assert.Equal(
"07849DC26FCBB2F3BD5F57BDF214BAE374575F1BD4E6816482324799417CB379",
messageDigestAttr.MessageDigest.ByteArrayToHex());

Assert.IsType<Pkcs9AttributeObject>(signedAttrs[3].Values[0]);
#if !NET
Assert.NotSame(signedAttrs[3].Oid, signedAttrs[3].Values[0].Oid);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,16 @@ namespace System.Security.Cryptography
public sealed class RSASignaturePadding : IEquatable<RSASignaturePadding>
{
/// <summary>
/// Represents a constant value indicating that the salt length should match the hash length.
/// A constant value indicating that the PSS salt length should match the hash length.
/// </summary>
/// <remarks>This value is typically used in cryptographic operations where the salt length is required to
/// be the same as the hash length.</remarks>
public const int PssSaltLengthIsHashLength = RsaPaddingProcessor.PssSaltLengthIsHashLength;

/// <summary>
Comment thread
henning-krause marked this conversation as resolved.
/// Represents the maximum allowable length, in bytes, for a PSS (Probabilistic Signature Scheme) salt.
/// A constant value indicating that the PSS salt length should be the maximum allowable
/// </summary>
/// <remarks>This constant is used to define the upper limit for the salt length in PSS-based
/// <remarks>A constant is used to define the upper limit for the salt length in PSS-based
/// cryptographic operations. The maximum length is determined by the hash algorithm's output size.</remarks>
public const int PssSaltLengthMax = RsaPaddingProcessor.PssSaltLengthMax;
Comment thread
henning-krause marked this conversation as resolved.

Expand All @@ -38,7 +38,7 @@ public sealed class RSASignaturePadding : IEquatable<RSASignaturePadding>
/// </summary>
/// <param name="saltLength">The length of the salt in bytes, or one of the constants <see cref="PssSaltLengthIsHashLength"/> or <see cref="PssSaltLengthMax" />.</param>
/// <returns>A new instance of <see cref="RSASignaturePadding"/> configured for PSS padding with the specified salt length.</returns>
/// <exception cref="ArgumentOutOfRangeException">The <paramref name="saltLength"/> is negative or not one of the special constants.</exception>
/// <exception cref="ArgumentOutOfRangeException">The <paramref name="saltLength"/> has a negative value other than one of the special constants.</exception>
public static RSASignaturePadding CreatePss(int saltLength)
Comment thread
henning-krause marked this conversation as resolved.
{
switch (saltLength)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -490,7 +490,7 @@ private static void CreateAndTestChain(
}
}

[ConditionalTheory(nameof(PlatformSupport.AreCustomSaltLengthsSupportedWithPss))]
[ConditionalTheory(nameof(AreCustomSaltLengthsSupportedWithPss))]
[InlineData(1)]
[InlineData(RSASignaturePadding.PssSaltLengthMax)]
[InlineData(RSASignaturePadding.PssSaltLengthIsHashLength)]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Collections.Generic;
using System.Formats.Asn1;
using System.Net;
using Test.Cryptography;
Expand Down Expand Up @@ -374,19 +375,19 @@ public static void VerifySignature_RSA_PKCS1(string hashAlgorithm)
}
}

public static IEnumerable<object[]> AllRsaPssCustomSaltLength()
{
foreach (string hashAlgorithm in new[] { "SHA256", "SHA384", "SHA512", "SHA1" })
{
foreach (int saltLength in new[] { 0, 1, RSASignaturePadding.PssSaltLengthMax, RSASignaturePadding.PssSaltLengthIsHashLength })
{
yield return new object[] { hashAlgorithm, saltLength };
}
}
}

[ConditionalTheory(typeof(PlatformSupport), nameof(PlatformSupport.AreCustomSaltLengthsSupportedWithPss))]
[InlineData("SHA256", 1)]
[InlineData("SHA384", 1)]
[InlineData("SHA512", 1)]
[InlineData("SHA1", 1)]
[InlineData("SHA256", RSASignaturePadding.PssSaltLengthMax)]
[InlineData("SHA384", RSASignaturePadding.PssSaltLengthMax)]
[InlineData("SHA512", RSASignaturePadding.PssSaltLengthMax)]
[InlineData("SHA1", RSASignaturePadding.PssSaltLengthMax)]
[InlineData("SHA256", RSASignaturePadding.PssSaltLengthIsHashLength)]
[InlineData("SHA384", RSASignaturePadding.PssSaltLengthIsHashLength)]
[InlineData("SHA512", RSASignaturePadding.PssSaltLengthIsHashLength)]
[InlineData("SHA1", RSASignaturePadding.PssSaltLengthIsHashLength)]
[MemberData(nameof(AllRsaPssCustomSaltLength))]
public static void VerifySignature_RSA_PSS_CustomSaltLength(string hashAlgorithm, int saltLength)
{
VerifySignature_RSA_PSSCore(hashAlgorithm, saltLength);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -323,7 +323,7 @@ public static void SelfSign_RSA_PssPadding_CustomSaltLength(int customSaltLength
AsnReader sequence = reader.ReadSequence();
ReadOnlyMemory<byte> tbsCertificate = sequence.ReadEncodedValue();
ReadOnlyMemory<byte> signatureAlgorithm = sequence.ReadEncodedValue();
byte[] signature = sequence.ReadBitString(out var _);
byte[] signature = sequence.ReadBitString(out _);

int testSaltLength = customSaltLength switch
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,15 +79,15 @@ public static void PssPaddingSaltLengths(int saltLengthToTest)
AsnReader rootSequence = asnReader.ReadSequence();
Assert.Equal("1.2.840.113549.1.1.10", rootSequence.ReadObjectIdentifier()); // Make sure it's RSASSA-PSS
AsnReader pssStructure = rootSequence.ReadSequence();
pssStructure.ReadEncodedValue(); // Ignore the hash algorithm OID
pssStructure.ReadEncodedValue(); // Ignore the mask generation function OID
ReadOnlyMemory<byte> hashAlgorithm = pssStructure.ReadEncodedValue(); // Ignore the hash algorithm OID
ReadOnlyMemory<byte> mgf = pssStructure.ReadEncodedValue(); // Ignore the mask generation function OID

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The previous feedback was that the hashAlgorithm and mgf values needed to be verified. You have now captured them into locals, but I don't see you verifying that they're the expected values.

Again, the purpose is to make sure that we're writing down a confirming/correct block when a custom PSS size is specified, and I don't see any other test doing that.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was interrupted last time I worked on this, so I committed early. I'll fix this next time together with the remaining open issues.

Asn1Tag saltTag = new Asn1Tag(TagClass.ContextSpecific, 2, true);

if (pssStructure.HasData && pssStructure.PeekTag().HasSameClassAndValue(saltTag))
{
var saltEntry = pssStructure.ReadSequence(saltTag);
var actualSaltLength = saltEntry.ReadInteger();
var expectedSaltLength = saltLengthToTest switch
AsnReader saltEntry = pssStructure.ReadSequence(saltTag);
Numerics.BigInteger actualSaltLength = saltEntry.ReadInteger();
int expectedSaltLength = saltLengthToTest switch
{
RSASignaturePadding.PssSaltLengthIsHashLength => 32,
RSASignaturePadding.PssSaltLengthMax => 222,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Formats.Asn1;
using System.Security.Cryptography.Asn1;
using Test.Cryptography;
#if NET11_0_OR_GREATER
using System.Formats.Asn1;
#endif

Comment thread
henning-krause marked this conversation as resolved.
namespace System.Security.Cryptography.X509Certificates.Tests.CertificateCreation
{
Expand Down Expand Up @@ -77,6 +75,10 @@ public override byte[] GetSignatureAlgorithmIdentifier(HashAlgorithmName hashAlg
// sha1WithRSAEncryption with RSASSA-PSS parameters
return "300D06092A864886F70D01010A3000".HexToByteArray();
}
else if (_signaturePadding.PssSaltLength == 0)
{
return "303506092a864886f70d01010a3028a009300706052b0e03021aa116301406092a864886f70d010108300706052b0e03021aa203020100".HexToByteArray();
}
else if (_signaturePadding.PssSaltLength == 1)
{
return "303506092a864886f70d01010a3028a009300706052b0e03021aa116301406092a864886f70d010108300706052b0e03021aa203020101".HexToByteArray();
Expand Down
Loading