Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
f4d3143
Add OWASP-aligned PBKDF2 iteration guidance and password hashing context
jeffhandley Apr 15, 2026
3e12992
Modernize AES encryption snippets and add CBC mode warnings
jeffhandley Apr 15, 2026
457c5df
Replace 1024-bit RSA and PKCS#1 v1.5 with 2048-bit RSA and OAEP
jeffhandley Apr 15, 2026
b70d56b
Add deprecation warnings for legacy crypto algorithms and APIs
jeffhandley Apr 15, 2026
62c2f8e
Fix correctness bugs in crypto code samples
jeffhandley Apr 15, 2026
acfaaeb
Address PR review feedback
jeffhandley Apr 16, 2026
0fbb4be
Revert DPAPI RNG to RNGCryptoServiceProvider for net461 compat
jeffhandley Apr 16, 2026
e440169
Address second round of PR review feedback
jeffhandley Apr 16, 2026
b5e2bbd
Fix RSACryptoServiceProvider obsoletion wording in hardware encryptio…
jeffhandley Apr 16, 2026
a356a6b
Add VB DPAPI project file and re-apply fixes
jeffhandley Apr 16, 2026
a512d7a
Restore hard-coded sample keys with illustration comments
jeffhandley Apr 16, 2026
59997bc
Address reviewer feedback: NIST over OWASP, no algorithm names, no AE…
jeffhandley Apr 16, 2026
a85b170
Address additional reviewer feedback on RSA key sizes and RNG wording
jeffhandley Apr 16, 2026
2309655
Modernize hardware encryption sample: SHA-1 to SHA-256, add disposal
jeffhandley Apr 16, 2026
cc3f5e8
Remove remaining AES-GCM reference and soften algorithm recommendations
jeffhandley Apr 16, 2026
1e65834
Align broader security docs with current NIST guidance
jeffhandley Apr 16, 2026
ea76609
Tighten remaining security compatibility docs
jeffhandley Apr 16, 2026
a812155
Remove remaining AES-GCM recommendations
jeffhandley Apr 16, 2026
2840c50
Fix DPAPI sample analyzer failures
jeffhandley Apr 16, 2026
20355a3
Fix CryptoWalkThru partial reads
jeffhandley Apr 16, 2026
cb76bf4
Apply feedback (top half)
bartonjs Apr 17, 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 @@ -46,7 +46,7 @@ If you're using OpenSSL-backed primitives without any specific intention of usin
* `new ECDsaOpenSsl(...)` -> `ECDsa.Create(...)`
* `new RSAOpenSsl(...)` -> `RSA.Create(...)`

<xref:System.Security.Cryptography.AesCcm?displayProperty=fullName> has no functional equivalent on macOS. Consider using a different cryptographic primitive, such as <xref:System.Security.Cryptography.AesGcm?displayProperty=fullName>, instead.
<xref:System.Security.Cryptography.AesCcm?displayProperty=fullName> has no functional equivalent on macOS.

## Affected APIs

Expand Down
4 changes: 2 additions & 2 deletions docs/core/extensions/sslstream-best-practices.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ Deferring the decision to the OS automatically uses the most recent version of T

## Select cipher suites

`SslStream` allows users to specify which cipher suites can be negotiated by the TLS handshake via the <xref:System.Net.Security.CipherSuitesPolicy> class. As with TLS versions, it's recommended to let the OS decide which are the best cipher suites to negotiate with, and, therefore, it's recommended to avoid using <xref:System.Net.Security.CipherSuitesPolicy>.
`SslStream` allows users to specify which cipher suites can be negotiated by the TLS handshake via the <xref:System.Net.Security.CipherSuitesPolicy> class. As with TLS versions, it's recommended to let the OS decide which are the best cipher suites to negotiate with, and avoid using <xref:System.Net.Security.CipherSuitesPolicy> unless you have a specific interoperability requirement.

> [!NOTE]
> <xref:System.Net.Security.CipherSuitesPolicy> is not supported on Windows and attempts to instantiate it will cause <xref:System.NotSupportedException> to be thrown.
Expand All @@ -37,7 +37,7 @@ There are multiple ways that a server certificate can be passed to <xref:System.

The recommended approach is to use the <xref:System.Net.Security.SslServerAuthenticationOptions.ServerCertificateContext?displayProperty=nameWithType> property. When the certificate is obtained by one of the other two ways, a <xref:System.Net.Security.SslStreamCertificateContext> instance is created internally by the <xref:System.Net.Security.SslStream> implementation. Creating a <xref:System.Net.Security.SslStreamCertificateContext> involves building an <xref:System.Security.Cryptography.X509Certificates.X509Chain> which is a CPU intensive operation. It is more efficient to create a <xref:System.Net.Security.SslStreamCertificateContext> once and reuse it for multiple <xref:System.Net.Security.SslStream> instances.

Reusing <xref:System.Net.Security.SslStreamCertificateContext> instances also enables additional features such us [TLS session resumption](https://datatracker.ietf.org/doc/html/rfc5077) on Linux servers.
Reusing <xref:System.Net.Security.SslStreamCertificateContext> instances also enables additional features such as [TLS session resumption](https://datatracker.ietf.org/doc/html/rfc5077) on Linux servers.

## Custom `X509Certificate` validation

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ Represents a custom binding element that supports channel security using an SSL
sslProtocols="Ssl3|Tls|Tls11|Tls12" />
```

> [!IMPORTANT]
> The syntax shows the full historical enum surface for the `sslProtocols` attribute. For new configurations, don't enable `Ssl3`, `Tls`, or `Tls11`. Prefer OS defaults, or limit the configuration to modern TLS versions supported by your target platform. For more information, see [Transport Layer Security (TLS) best practices with the .NET Framework](../../../network-programming/tls.md).

## Attributes and Elements

The following sections describe attributes, child elements, and parent elements.
Expand All @@ -31,7 +34,7 @@ Represents a custom binding element that supports channel security using an SSL
|Attribute|Description|
|---------------|-----------------|
|requireClientCertificate|A Boolean value that specifies if a client certificate is required for this binding. The default is `false`.|
|sslProtocols|A SslProtocols enum flag value that specifies which SslProtocols are supported. The default is Ssl3&#124;Tls&#124;Tls11&#124;Tls12.|
|sslProtocols|A SslProtocols enum flag value that specifies which SslProtocols are supported. The default is Ssl3&#124;Tls&#124;Tls11&#124;Tls12. This historical default exists for compatibility and isn't recommended for new configurations.|

### Child Elements

Expand Down
8 changes: 4 additions & 4 deletions docs/framework/migration-guide/mitigation-tls-protocols.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,19 @@ ms.assetid: 33f97d13-3022-43da-8b18-cdb5c88df9c2
---
# Mitigation: TLS Protocols

Starting with .NET Framework 4.6, the <xref:System.Net.ServicePointManager?displayProperty=nameWithType> and <xref:System.Net.Security.SslStream?displayProperty=nameWithType> classes are allowed to use one of the following three protocols: Tls1.0, Tls1.1, or Tls 1.2. The SSL3.0 protocol and RC4 cipher are not supported.
Starting with .NET Framework 4.6, the <xref:System.Net.ServicePointManager?displayProperty=nameWithType> and <xref:System.Net.Security.SslStream?displayProperty=nameWithType> classes no longer support the SSL 3.0 protocol or the RC4 cipher.

## Impact

This change affects:

- Any app that uses SSL to talk to an HTTPS server or a socket server using any of the following types: <xref:System.Net.Http.HttpClient>, <xref:System.Net.HttpWebRequest>, <xref:System.Net.FtpWebRequest>, <xref:System.Net.Mail.SmtpClient>, and <xref:System.Net.Security.SslStream>.

- Any server-side app that cannot be upgraded to support Tls1.0, Tls1.1, or Tls 1.2..
- Any server-side app that cannot be upgraded to support modern TLS configurations.

## Mitigation

The recommended mitigation is to upgrade the sever-side app to Tls1.0, Tls1.1, or Tls 1.2. If this is not feasible, or if client apps are broken, the <xref:System.AppContext> class can be used to opt out of this feature in either of two ways:
The recommended mitigation is to upgrade the server-side app to support modern TLS configurations. If that isn't feasible, or if client apps are broken, the <xref:System.AppContext> class can be used to opt out of this feature in either of two ways as a temporary compatibility workaround:

- Programmatically, by using a code snippet like the following:

Expand All @@ -36,7 +36,7 @@ Starting with .NET Framework 4.6, the <xref:System.Net.ServicePointManager?displ
<AppContextSwitchOverrides value="Switch.System.Net.DontEnableSchUseStrongCrypto=true"/>
```

Note, however, that opting out of the default behavior is not recommended, since it makes the application less secure.
Note, however, that opting out of the default behavior is not recommended, since it makes the application less secure.

## See also

Expand Down
20 changes: 10 additions & 10 deletions docs/framework/network-programming/tls.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ helpviewer_keywords:
## What is Transport Layer Security (TLS)?

> [!WARNING]
> TLS 1.0 and 1.1 has been deprecated by [RFC8996](https://datatracker.ietf.org/doc/rfc8996/). This document covers TLS 1.2 and TLS 1.3 only.
> TLS 1.0 and TLS 1.1 have been deprecated by [RFC 8996](https://datatracker.ietf.org/doc/rfc8996/). This document covers TLS 1.2 and TLS 1.3 only.

The Transport Layer Security (TLS) protocol is an industry latest version of the standard designed to help protect the privacy of information communicated over the Internet. [TLS 1.3](https://tools.ietf.org/html/rfc8446) is a standard that provides security improvements over previous versions. This article presents recommendations to secure .NET Framework applications that use the TLS protocol.

Expand Down Expand Up @@ -53,11 +53,11 @@ For more information see [TLS protocol version support in Schannel](/windows/win

## Recommendations

- For TLS 1.3, target .NET Framework 4.8 or later. Check [Audit your code](#audit-your-code-and-make-code-changes) section how to verify your `target framework`.
- For TLS 1.3, target .NET Framework 4.8 or later. Check the [Audit your code](#audit-your-code-and-make-code-changes) section how to verify your `target framework`.
- Do not specify the TLS version explicitly, i.e. don't use the method overloads of `SslStream` that take an explicit `SslProtocols` parameter.
- That way your code will let the OS decide on the TLS version.
- If you must set <xref:System.Net.ServicePointManager.SecurityProtocol?displayProperty=nameWithType>, then set it to <xref:System.Net.SecurityProtocolType.SystemDefault?displayProperty=nameWithType>. That will also use OS default.
- If you must use the method overloads of `SslStream` that take an explicit `SslProtocols` parameter, then pass `SslProtocols.SystemDefault` as argument. That will also use OS default.
- If you must set <xref:System.Net.ServicePointManager.SecurityProtocol?displayProperty=nameWithType>, then set it to <xref:System.Net.SecurityProtocolType.SystemDefault?displayProperty=nameWithType>. That will also use the OS default.
- If you must use the method overloads of `SslStream` that take an explicit `SslProtocols` parameter, then pass `SslProtocols.SystemDefault` as argument. That will also use the OS default.
- Perform a thorough code audit to verify you're not specifying a TLS or SSL version explicitly.

> [!WARNING]
Expand All @@ -70,7 +70,7 @@ When your app lets the OS choose the TLS version:

This article explains how to enable the strongest security available for the version of .NET Framework that your app targets and runs on. When an app explicitly sets a security protocol and version, it opts out of any other alternative, and opts out of .NET Framework and OS default behavior. If you want your app to be able to negotiate a TLS 1.3 connection, explicitly setting to a lower TLS version prevents a TLS 1.3 connection.

If you can't avoid specifying a protocol version explicitly, we strongly recommend that you specify TLS 1.2 or TLS 1.3 (which is `currently considered secure`). For guidance on identifying and removing TLS 1.0 dependencies, download the [Solving the TLS 1.0 Problem](https://www.microsoft.com/download/details.aspx?id=55266) white paper.
If you can't avoid specifying a protocol version explicitly, include only those legacy versions that you absolutely need, and omit modern default versions only when they cause compatibility issues. For guidance on identifying and removing TLS 1.0 dependencies, download the [Solving the TLS 1.0 Problem](https://www.microsoft.com/download/details.aspx?id=55266) white paper.

WCF supports TLS 1.2 as the default in .NET Framework 4.7. Starting with .NET Framework 4.7.1, WCF defaults to the operating system configured version. If an application is explicitly configured with `SslProtocols.None`, WCF uses the operating system default setting when using the NetTcp transport.

Expand Down Expand Up @@ -139,7 +139,7 @@ Because the <xref:System.Net.SecurityProtocolType.SystemDefault?displayProperty=

#### For SslStream

<xref:System.Net.Security.SslStream> defaults to the security protocol and version chosen by the OS. To get the default OS best choice, if possible, don't use the method overloads of <xref:System.Net.Security.SslStream> that take an explicit <xref:System.Security.Authentication.SslProtocols> parameter. Otherwise, pass <xref:System.Security.Authentication.SslProtocols.None?displayProperty=nameWithType>. We recommend that you don't use <xref:System.Security.Authentication.SslProtocols.Default>; setting `SslProtocols.Default` forces the use of SSL 3.0 /TLS 1.0 and prevents TLS 1.2.
<xref:System.Net.Security.SslStream> defaults to the security protocol and version chosen by the OS. To get the default OS best choice, if possible, don't use the method overloads of <xref:System.Net.Security.SslStream> that take an explicit <xref:System.Security.Authentication.SslProtocols> parameter. Otherwise, pass <xref:System.Security.Authentication.SslProtocols.None?displayProperty=nameWithType>. We recommend that you don't use <xref:System.Security.Authentication.SslProtocols.Default>; setting `SslProtocols.Default` forces the use of SSL 3.0 /TLS 1.0 and prevents negotiation of newer versions.

Don't set a value for the <xref:System.Net.ServicePointManager.SecurityProtocol> property (for HTTP networking).

Expand All @@ -160,7 +160,7 @@ If you're targeting 4.7.1, WCF is configured to allow the OS to choose the best
- In your application configuration file.
- **Or**, in your application in the source code.

By default, .NET Framework 4.7 and later versions are configured to use TLS 1.2 and allow connections using TLS 1.1 or TLS 1.0. Configure WCF to allow the OS to choose the best security protocol by configuring your binding to use <xref:System.Security.Authentication.SslProtocols.None?displayProperty=nameWithType>. You can set this on <xref:System.ServiceModel.TcpTransportSecurity.SslProtocols>. `SslProtocols.None` can be accessed from <xref:System.ServiceModel.NetTcpSecurity.Transport>. `NetTcpSecurity.Transport` can be accessed from <xref:System.ServiceModel.NetTcpBinding.Security>.
By default, .NET Framework 4.7 and later versions are configured to use TLS 1.2 and allow connections using TLS 1.1 or TLS 1.0. Don't rely on those older protocols. Configure WCF to allow the OS to choose the best security protocol by configuring your binding to use <xref:System.Security.Authentication.SslProtocols.None?displayProperty=nameWithType>. You can set this on <xref:System.ServiceModel.TcpTransportSecurity.SslProtocols>. `SslProtocols.None` can be accessed from <xref:System.ServiceModel.NetTcpSecurity.Transport>. `NetTcpSecurity.Transport` can be accessed from <xref:System.ServiceModel.NetTcpBinding.Security>.
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.

I'm not certain this is true because IIRC TLS 1.3 says that if both side can talk TLS 1.3 they MUST talk TLS 1.3 and IIRC we did add support for TLS 1.3. Possibly more generic statement will be better here. @bartonjs ideas?

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 recommendation is correct: Set your protocols to None, which SslStream interprets as "no preference, do whatever the OS says". And that's as far of an opinion as this document should have.


If you're using a custom binding:

Expand All @@ -171,7 +171,7 @@ If you're **not** using a custom binding **and** you're setting your WCF binding

#### Using Message Security with certificate credentials

.NET Framework 4.7 and later versions by default use the protocol specified in the <xref:System.Net.ServicePointManager.SecurityProtocol> property. When the [AppContextSwitch](../configure-apps/file-schema/runtime/appcontextswitchoverrides-element.md) `Switch.System.ServiceModel.DisableUsingServicePointManagerSecurityProtocols` is set to `true`, WCF chooses the best protocol, up to TLS 1.0.
.NET Framework 4.7 and later versions by default use the protocol specified in the <xref:System.Net.ServicePointManager.SecurityProtocol> property. When the [AppContextSwitch](../configure-apps/file-schema/runtime/appcontextswitchoverrides-element.md) `Switch.System.ServiceModel.DisableUsingServicePointManagerSecurityProtocols` is set to `true`, WCF chooses the best protocol, up to TLS 1.0. That compatibility path is for legacy scenarios and doesn't satisfy current security guidance.

#### [.NET Framework 4.6.2 and earlier](#tab/462-minus)

Expand All @@ -191,7 +191,7 @@ The switches have the same effect whether you're doing HTTP networking (<xref:Sy

#### Switch.System.Net.DontEnableSchUseStrongCrypto

A value of `false` for `Switch.System.Net.DontEnableSchUseStrongCrypto` causes your app to use strong cryptography. A value of `false` for `DontEnableSchUseStrongCrypto` uses more secure network protocols (TLS 1.2 and TLS 1.1) and blocks protocols that are not secure. For more info, see [The SCH_USE_STRONG_CRYPTO flag](#the-sch_use_strong_crypto-flag). A value of `true` disables strong cryptography for your app. This switch affects only client (outgoing) connections in your application.
A value of `false` for `Switch.System.Net.DontEnableSchUseStrongCrypto` causes your app to use strong cryptography. A value of `false` for `DontEnableSchUseStrongCrypto` uses modern TLS versions, and blocks versions that are not secure. For more info, see [The SCH_USE_STRONG_CRYPTO flag](#the-sch_use_strong_crypto-flag). A value of `true` disables strong cryptography for your app. This switch affects only client (outgoing) connections in your application.

If your app targets .NET Framework 4.6.2 or later versions, this switch defaults to `false`. That's a secure default, which we recommend. If your app runs on .NET Framework 4.6.2, but targets an earlier version, the switch defaults to `true`. In that case, you should explicitly set it to `false`.

Expand All @@ -207,7 +207,7 @@ If your app targets .NET Framework 4.7 or later versions, this switch defaults t

#### Switch.System.ServiceModel.DisableUsingServicePointManagerSecurityProtocols

A value of `false` for `Switch.System.ServiceModel.DisableUsingServicePointManagerSecurityProtocols` causes your application to use the value defined in `ServicePointManager.SecurityProtocols` for message security using certificate credentials. A value of `true` uses the highest protocol available, up to TLS1.0
A value of `false` for `Switch.System.ServiceModel.DisableUsingServicePointManagerSecurityProtocols` causes your application to use the value defined in `ServicePointManager.SecurityProtocols` for message security using certificate credentials. A value of `true` uses the highest protocol available through that legacy compatibility path, which on older systems can still mean TLS 1.0.

For applications targeting .NET Framework 4.7 and later versions, this value defaults to `false`. For applications targeting .NET Framework 4.6.2 and earlier, this value defaults to `true`.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ ms.assetid: 6e4289e6-d1b7-4e82-ab0d-e83e3b6063ed
---
# Using Secure Sockets Layer

The <xref:System.Net> classes use the Secure Sockets Layer (SSL) to encrypt the connection for several network protocols.
The <xref:System.Net> classes use Transport Layer Security (TLS), historically referred to as Secure Sockets Layer (SSL), to encrypt the connection for several network protocols.

For http connections, the <xref:System.Net.WebRequest> and <xref:System.Net.WebResponse> classes use SSL to communicate with web hosts that support SSL. The decision to use SSL is made by the <xref:System.Net.WebRequest> class, based on the URI it is given. If the URI begins with "https:", SSL is used; if the URI begins with "http:", an unencrypted connection is used.

Expand Down
1 change: 1 addition & 0 deletions docs/fundamentals/code-analysis/quality-rules/ca5358.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ These modes are vulnerable to attacks and may cause exposure of sensitive inform
## How to fix violations

- Use only approved modes (<xref:System.Security.Cryptography.CipherMode.CBC?displayProperty=fullName>, <xref:System.Security.Cryptography.CipherMode.CTS?displayProperty=fullName>).
- If you use CBC-based encryption, validate integrity before you decrypt. For more information, see [Timing vulnerabilities with CBC-mode symmetric decryption using padding](../../../standard/security/vulnerabilities-cbc-mode.md).

## When to suppress warnings

Expand Down
2 changes: 1 addition & 1 deletion docs/fundamentals/code-analysis/quality-rules/ca5361.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ Setting `Switch.System.Net.DontEnableSchUseStrongCrypto` to `true` weakens the c

## When to suppress warnings

You can suppress this warning if you need to connect to a legacy service that can't be upgraded to use secure TLS configurations.
You can suppress this warning only if you need to connect to a legacy service that does not support modern TLS versions. Treat that suppression as a temporary compatibility measure.

## Suppress a warning

Expand Down
6 changes: 6 additions & 0 deletions docs/fundamentals/code-analysis/quality-rules/ca5387.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,12 @@ This rule is similar to [CA5388](ca5388.md), but analysis determines that the it

Set the iteration count greater than or equal with 100,000 before calling <xref:System.Security.Cryptography.Rfc2898DeriveBytes.GetBytes*>.

> [!TIP]
> While the analyzer enforces a minimum of 100,000 iterations, this threshold might not keep pace with hardware improvements. [NIST SP 800-132](https://csrc.nist.gov/pubs/sp/800/132/final) recommends selecting an iteration count as high as your environment can tolerate, and increasing it periodically as computing power grows. However, excessively high iteration counts increase CPU cost per authentication attempt, which can be exploited for denial-of-service attacks. Choose a value that balances security with acceptable latency for your application.

> [!TIP]
> Remember that you need to save the iteration count (or a version/scheme identifier that represents it) used to produce the original output so that you can specify the same value again when trying to reproduce the value.

Comment thread
jeffhandley marked this conversation as resolved.
## When to suppress warnings

It's safe to suppress a warning if you need to use a smaller iteration count for compatibility with existing data.
Expand Down
Loading
Loading