Force PowerShell to use TLS 1.2

Force PowerShell to use TLS 1.2

Recently I’ve begun to move the Chocolatey packages I maintain from manual to automatic updating. Going through each package I came across an issue with Yubico Authenticator while retrieving the downloads page using Invoke-WebRequest yubico-authenticator-ps-error

This caught me by surprise as I was retrieving other Yubico website pages, such as developers.yubico.com, without issue.

I decided to look at the SSL / TLS protocols for the pages using SSL Labs SSL online test and found the following:

developers.yubico.com

yubico-developers-tls

yubico.com

yubico-tls

Comparison of Supported TLS Protocols

We are obviously dealing with two different websites here and not pages on a single website. One is yubico.com and the other is developers.yubico.com. Each site has different SSL / TLS protocols that it will accept:

  • developers.yubico.com - will accept TLS 1.0 through to TLS 1.2;
  • yubico.com - will only accept TLS 1.2;

PowerShell and SSL / TLS

By default PowerShell will use TLS 1.0 when using Invoke-WebRequest. This is why it cannot establish a secure session with yubico.com as that site doesn’t ’talk’ TLS 1.0 only TLS 1.2. So we have to force PowerShell to use TLS 1.2:

# Force PowerShell to use TLS 1.2
# you should be able to miss the 'System.' and just use 'Net.'
PS> [Net.ServicePointManager]::SecurityProtocol = 
        [Net.SecurityProtocolType]::Tls12


# Query yubico.com site
PS> Invoke-WebRequest "https://www.yubico.com/support/knowledge-base/categories/articles/yubico-authenticator-download/"

We now get the site data returned as we’d expect.

Which TLS versions does PowerShell support?

The versions of TLS that we can use is already defined for us in the Net.SecurityProtocolType enum:

# Get the BaseType of Net.SecurityProtocolType
PS> [Net.SecurityProtocolType]

IsPublic IsSerial Name                               BaseType
-------- -------- ----                               --------
True     True     SecurityProtocolType               System.Enum

# Get the PowerShell supported TLS versions
PS> [enum]::GetNames([Net.SecurityProtocolType])

SystemDefault
Ssl3
Tls
Tls11
Tls12


# Force PowerShell to use TLS 1.1
PS> [System.Net.ServicePointManager]::SecurityProtocol = 
        [System.Net.SecurityProtocolType]::Tls11


# Force PowerShell to use it's default of TLS 1.0
PS> [System.Net.ServicePointManager]::SecurityProtocol = 
        [System.Net.SecurityProtocolType]::Tls

So we can force PowerShell to use TLS 1.0 (Tls), TLS 1.1 (Tls11) or TLS 1.2 (Tls12) but not TLS 1.3 as there is no definition for that. Trying to force it results in:

# Force PowerShell ti use TLS 1.3
$> [Net.ServicePointManager]::SecurityProtocol = 
        [Net.SecurityProtocolType]::Tls13

Exception setting "SecurityProtocol": "Cannot convert null to 
type "System.Net.SecurityProtocolType" due to enumeration values
that are not valid. Specify one of the following enumeration
values and try again. The possible enumeration values are 
"SystemDefault,Ssl3,Tls,Tls11,Tls12"."

TLS 1.2 is the last version that PowerShell supports.