Skip to content

Commit

Permalink
Obsolete all constructors for Rfc2898DeriveBytes (#111678)
Browse files Browse the repository at this point in the history
  • Loading branch information
vcsjones authored Jan 23, 2025
1 parent 92e1cdd commit 6ad67d1
Show file tree
Hide file tree
Showing 7 changed files with 32 additions and 17 deletions.
1 change: 1 addition & 0 deletions docs/project/list-of-diagnostics.md
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ The PR that reveals the implementation of the `<IncludeInternalObsoleteAttribute
| __`SYSLIB0057`__ | Loading certificate data through the constructor or Import is obsolete. Use X509CertificateLoader instead to load certificates. |
| __`SYSLIB0058`__ | KeyExchangeAlgorithm, KeyExchangeStrength, CipherAlgorithm, CipherAlgorithmStrength, HashAlgorithm and HashStrength properties of SslStream are obsolete. Use NegotiatedCipherSuite instead. |
| __`SYSLIB0059`__ | SystemEvents.EventsThreadShutdown callbacks are not run before the process exits. Use AppDomain.ProcessExit instead. |
| __`SYSLIB0060`__ | The constructors on Rfc2898DeriveBytes are obsolete. Use the static Pbkdf2 method instead. |

## Analyzer Warnings

Expand Down
6 changes: 4 additions & 2 deletions src/libraries/Common/src/System/Obsoletions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -133,8 +133,7 @@ internal static class Obsoletions
internal const string EncryptionPolicyMessage = "EncryptionPolicy.NoEncryption and AllowEncryption significantly reduce security and should not be used in production code.";
internal const string EncryptionPolicyDiagId = "SYSLIB0040";

internal const string Rfc2898OutdatedCtorMessage = "The default hash algorithm and iteration counts in Rfc2898DeriveBytes constructors are outdated and insecure. Use a constructor that accepts the hash algorithm and the number of iterations.";
internal const string Rfc2898OutdatedCtorDiagId = "SYSLIB0041";
// SYSLIB0041 is no longer used and is superseded by SYSLIB0060.

internal const string EccXmlExportImportMessage = "ToXmlString and FromXmlString have no implementation for ECC types, and are obsolete. Use a standard import and export format such as ExportSubjectPublicKeyInfo or ImportSubjectPublicKeyInfo for public keys and ExportPkcs8PrivateKey or ImportPkcs8PrivateKey for private keys.";
internal const string EccXmlExportImportDiagId = "SYSLIB0042";
Expand Down Expand Up @@ -190,6 +189,9 @@ internal static class Obsoletions
internal const string SystemEventsEventsThreadShutdownMessage = "SystemEvents.EventsThreadShutdown callbacks are not run before the process exits. Use AppDomain.ProcessExit instead.";
internal const string SystemEventsEventsThreadShutdownDiagId = "SYSLIB0059";

internal const string Rfc2898DeriveBytesCtorMessage = "The constructors on Rfc2898DeriveBytes are obsolete. Use the static Pbkdf2 method instead.";
internal const string Rfc2898DeriveBytesCtorDiagId = "SYSLIB0060";

// When adding a new diagnostic ID, add it to the table in docs\project\list-of-diagnostics.md as well.
// Keep new const identifiers above this comment.
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1134,17 +1134,21 @@ private static Rfc2898DeriveBytes OpenPbkdf2(
{
#if NET || NETSTANDARD2_1_OR_GREATER || NET472_OR_GREATER
#pragma warning disable CA5379
#pragma warning disable SYSLIB0060
return new Rfc2898DeriveBytes(
password,
salt,
iterationCount,
prf);
#pragma warning restore SYSLIB0060
#pragma warning restore CA5379
#else
if (prf == HashAlgorithmName.SHA1)
{
#pragma warning disable CA5379
#pragma warning disable SYSLIB0060
return new Rfc2898DeriveBytes(password, salt, iterationCount);
#pragma warning restore SYSLIB0060
#pragma warning restore CA5379
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1973,18 +1973,21 @@ public override void GenerateKey() { }
}
public partial class Rfc2898DeriveBytes : System.Security.Cryptography.DeriveBytes
{
[System.ObsoleteAttribute("The default hash algorithm and iteration counts in Rfc2898DeriveBytes constructors are outdated and insecure. Use a constructor that accepts the hash algorithm and the number of iterations.", DiagnosticId="SYSLIB0041", UrlFormat="https://aka.ms/dotnet-warnings/{0}")]
[System.ObsoleteAttribute("The constructors on Rfc2898DeriveBytes are obsolete. Use the static Pbkdf2 method instead.", DiagnosticId="SYSLIB0060", UrlFormat="https://aka.ms/dotnet-warnings/{0}")]
public Rfc2898DeriveBytes(byte[] password, byte[] salt, int iterations) { }
[System.ObsoleteAttribute("The constructors on Rfc2898DeriveBytes are obsolete. Use the static Pbkdf2 method instead.", DiagnosticId="SYSLIB0060", UrlFormat="https://aka.ms/dotnet-warnings/{0}")]
public Rfc2898DeriveBytes(byte[] password, byte[] salt, int iterations, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) { }
[System.ObsoleteAttribute("The default hash algorithm and iteration counts in Rfc2898DeriveBytes constructors are outdated and insecure. Use a constructor that accepts the hash algorithm and the number of iterations.", DiagnosticId="SYSLIB0041", UrlFormat="https://aka.ms/dotnet-warnings/{0}")]
[System.ObsoleteAttribute("The constructors on Rfc2898DeriveBytes are obsolete. Use the static Pbkdf2 method instead.", DiagnosticId="SYSLIB0060", UrlFormat="https://aka.ms/dotnet-warnings/{0}")]
public Rfc2898DeriveBytes(string password, byte[] salt) { }
[System.ObsoleteAttribute("The default hash algorithm and iteration counts in Rfc2898DeriveBytes constructors are outdated and insecure. Use a constructor that accepts the hash algorithm and the number of iterations.", DiagnosticId="SYSLIB0041", UrlFormat="https://aka.ms/dotnet-warnings/{0}")]
[System.ObsoleteAttribute("The constructors on Rfc2898DeriveBytes are obsolete. Use the static Pbkdf2 method instead.", DiagnosticId="SYSLIB0060", UrlFormat="https://aka.ms/dotnet-warnings/{0}")]
public Rfc2898DeriveBytes(string password, byte[] salt, int iterations) { }
[System.ObsoleteAttribute("The constructors on Rfc2898DeriveBytes are obsolete. Use the static Pbkdf2 method instead.", DiagnosticId="SYSLIB0060", UrlFormat="https://aka.ms/dotnet-warnings/{0}")]
public Rfc2898DeriveBytes(string password, byte[] salt, int iterations, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) { }
[System.ObsoleteAttribute("The default hash algorithm and iteration counts in Rfc2898DeriveBytes constructors are outdated and insecure. Use a constructor that accepts the hash algorithm and the number of iterations.", DiagnosticId="SYSLIB0041", UrlFormat="https://aka.ms/dotnet-warnings/{0}")]
[System.ObsoleteAttribute("The constructors on Rfc2898DeriveBytes are obsolete. Use the static Pbkdf2 method instead.", DiagnosticId="SYSLIB0060", UrlFormat="https://aka.ms/dotnet-warnings/{0}")]
public Rfc2898DeriveBytes(string password, int saltSize) { }
[System.ObsoleteAttribute("The default hash algorithm and iteration counts in Rfc2898DeriveBytes constructors are outdated and insecure. Use a constructor that accepts the hash algorithm and the number of iterations.", DiagnosticId="SYSLIB0041", UrlFormat="https://aka.ms/dotnet-warnings/{0}")]
[System.ObsoleteAttribute("The constructors on Rfc2898DeriveBytes are obsolete. Use the static Pbkdf2 method instead.", DiagnosticId="SYSLIB0060", UrlFormat="https://aka.ms/dotnet-warnings/{0}")]
public Rfc2898DeriveBytes(string password, int saltSize, int iterations) { }
[System.ObsoleteAttribute("The constructors on Rfc2898DeriveBytes are obsolete. Use the static Pbkdf2 method instead.", DiagnosticId="SYSLIB0060", UrlFormat="https://aka.ms/dotnet-warnings/{0}")]
public Rfc2898DeriveBytes(string password, int saltSize, int iterations, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) { }
public System.Security.Cryptography.HashAlgorithmName HashAlgorithm { get { throw null; } }
public int IterationCount { get { throw null; } set { } }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,29 +29,31 @@ public partial class Rfc2898DeriveBytes : DeriveBytes
/// </summary>
public HashAlgorithmName HashAlgorithm { get; }

[Obsolete(Obsoletions.Rfc2898OutdatedCtorMessage, DiagnosticId = Obsoletions.Rfc2898OutdatedCtorDiagId, UrlFormat = Obsoletions.SharedUrlFormat)]
[Obsolete(Obsoletions.Rfc2898DeriveBytesCtorMessage, DiagnosticId = Obsoletions.Rfc2898DeriveBytesCtorDiagId, UrlFormat = Obsoletions.SharedUrlFormat)]
public Rfc2898DeriveBytes(byte[] password, byte[] salt, int iterations)
: this(password, salt, iterations, HashAlgorithmName.SHA1)
{
}

[Obsolete(Obsoletions.Rfc2898DeriveBytesCtorMessage, DiagnosticId = Obsoletions.Rfc2898DeriveBytesCtorDiagId, UrlFormat = Obsoletions.SharedUrlFormat)]
public Rfc2898DeriveBytes(byte[] password, byte[] salt, int iterations, HashAlgorithmName hashAlgorithm)
: this(password, salt, iterations, hashAlgorithm, clearPassword: false)
{
}

[Obsolete(Obsoletions.Rfc2898OutdatedCtorMessage, DiagnosticId = Obsoletions.Rfc2898OutdatedCtorDiagId, UrlFormat = Obsoletions.SharedUrlFormat)]
[Obsolete(Obsoletions.Rfc2898DeriveBytesCtorMessage, DiagnosticId = Obsoletions.Rfc2898DeriveBytesCtorDiagId, UrlFormat = Obsoletions.SharedUrlFormat)]
public Rfc2898DeriveBytes(string password, byte[] salt)
: this(password, salt, 1000)
{
}

[Obsolete(Obsoletions.Rfc2898OutdatedCtorMessage, DiagnosticId = Obsoletions.Rfc2898OutdatedCtorDiagId, UrlFormat = Obsoletions.SharedUrlFormat)]
[Obsolete(Obsoletions.Rfc2898DeriveBytesCtorMessage, DiagnosticId = Obsoletions.Rfc2898DeriveBytesCtorDiagId, UrlFormat = Obsoletions.SharedUrlFormat)]
public Rfc2898DeriveBytes(string password, byte[] salt, int iterations)
: this(password, salt, iterations, HashAlgorithmName.SHA1)
{
}

[Obsolete(Obsoletions.Rfc2898DeriveBytesCtorMessage, DiagnosticId = Obsoletions.Rfc2898DeriveBytesCtorDiagId, UrlFormat = Obsoletions.SharedUrlFormat)]
public Rfc2898DeriveBytes(string password, byte[] salt, int iterations, HashAlgorithmName hashAlgorithm)
: this(
Encoding.UTF8.GetBytes(password ?? throw new ArgumentNullException(nameof(password))),
Expand All @@ -62,18 +64,19 @@ public Rfc2898DeriveBytes(string password, byte[] salt, int iterations, HashAlgo
{
}

[Obsolete(Obsoletions.Rfc2898OutdatedCtorMessage, DiagnosticId = Obsoletions.Rfc2898OutdatedCtorDiagId, UrlFormat = Obsoletions.SharedUrlFormat)]
[Obsolete(Obsoletions.Rfc2898DeriveBytesCtorMessage, DiagnosticId = Obsoletions.Rfc2898DeriveBytesCtorDiagId, UrlFormat = Obsoletions.SharedUrlFormat)]
public Rfc2898DeriveBytes(string password, int saltSize)
: this(password, saltSize, 1000)
{
}

[Obsolete(Obsoletions.Rfc2898OutdatedCtorMessage, DiagnosticId = Obsoletions.Rfc2898OutdatedCtorDiagId, UrlFormat = Obsoletions.SharedUrlFormat)]
[Obsolete(Obsoletions.Rfc2898DeriveBytesCtorMessage, DiagnosticId = Obsoletions.Rfc2898DeriveBytesCtorDiagId, UrlFormat = Obsoletions.SharedUrlFormat)]
public Rfc2898DeriveBytes(string password, int saltSize, int iterations)
: this(password, saltSize, iterations, HashAlgorithmName.SHA1)
{
}

[Obsolete(Obsoletions.Rfc2898DeriveBytesCtorMessage, DiagnosticId = Obsoletions.Rfc2898DeriveBytesCtorDiagId, UrlFormat = Obsoletions.SharedUrlFormat)]
public Rfc2898DeriveBytes(string password, int saltSize, int iterations, HashAlgorithmName hashAlgorithm)
{
ArgumentOutOfRangeException.ThrowIfNegative(saltSize);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,9 @@ public static void Pbkdf2_PasswordBytes_Compare(
HashAlgorithmName hashAlgorithmName = new HashAlgorithmName(hashAlgorithm);
byte[] key1;

#pragma warning disable SYSLIB0060 // The constructors on Rfc2898DeriveBytes are obsolete.
using (Rfc2898DeriveBytes instanceKdf = new Rfc2898DeriveBytes(password, salt, iterations, hashAlgorithmName))
#pragma warning restore SYSLIB0060
{
key1 = instanceKdf.GetBytes(length);
}
Expand Down Expand Up @@ -253,7 +255,9 @@ public static void Pbkdf2_PasswordString_Compare(
HashAlgorithmName hashAlgorithmName = new HashAlgorithmName(hashAlgorithm);
byte[] key1;

#pragma warning disable SYSLIB0060 // The constructors on Rfc2898DeriveBytes are obsolete.
using (Rfc2898DeriveBytes instanceKdf = new Rfc2898DeriveBytes(password, salt, iterations, hashAlgorithmName))
#pragma warning restore SYSLIB0060
{
key1 = instanceKdf.GetBytes(length);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
using Test.Cryptography;
using Xunit;

#pragma warning disable SYSLIB0060 // Rfc2898DeriveBytes constructors are obsolete.

namespace System.Security.Cryptography
{
public class Rfc2898Tests
Expand Down Expand Up @@ -119,9 +121,7 @@ public static void Ctor_SaltCopied()
[Fact]
public static void Ctor_DefaultIterations()
{
#pragma warning disable SYSLIB0041 // Rfc2898DeriveBytes insecure constructor defaults
using (var deriveBytes = new Rfc2898DeriveBytes(TestPassword, s_testSalt))
#pragma warning restore SYSLIB0041
{
Assert.Equal(DefaultIterationCount, deriveBytes.IterationCount);
}
Expand Down Expand Up @@ -373,13 +373,11 @@ public static void CheckHashAlgorithmValue(HashAlgorithmName hashAlgorithm)
[Fact]
public static void CryptDeriveKey_NotSupported()
{
#pragma warning disable SYSLIB0041 // Rfc2898DeriveBytes insecure constructor defaults
#pragma warning disable SYSLIB0033 // Rfc2898DeriveBytes.CryptDeriveKey is obsolete
using (var deriveBytes = new Rfc2898DeriveBytes(TestPassword, s_testSalt))
{
#pragma warning disable SYSLIB0033 // Rfc2898DeriveBytes.CryptDeriveKey is obsolete
Assert.Throws<PlatformNotSupportedException>(() => deriveBytes.CryptDeriveKey("RC2", "SHA1", 128, new byte[8]));
#pragma warning restore SYSLIB0033
#pragma warning restore SYSLIB0041
}
}

Expand Down

0 comments on commit 6ad67d1

Please sign in to comment.