Last active
December 3, 2025 00:15
-
-
Save lamw/8fedd19e27ff9276169e1bdd5404ca8c to your computer and use it in GitHub Desktop.
Powershell snippet to help extract the SSL Thumbprint (SHA256) of a remote system
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Function Get-SSLThumbprint256 { | |
| param( | |
| [Parameter( | |
| Position=0, | |
| Mandatory=$true, | |
| ValueFromPipeline=$true, | |
| ValueFromPipelineByPropertyName=$true | |
| )] | |
| [Alias('FullName')] | |
| [String]$URL | |
| ) | |
| # Convert the FQDN/URL to a useable hostname (strips scheme/path) | |
| try { | |
| $Uri = [System.Uri]$URL | |
| } | |
| catch { | |
| Write-Error "Invalid URL provided: $($URL)" | |
| return | |
| } | |
| $Hostname = $Uri.Host | |
| # Use 443 if no port is explicitly specified | |
| $Port = if ($Uri.Port -eq -1) { 443 } else { $Uri.Port } | |
| # 1. Define the Validation Callback | |
| # This delegate tells the SslStream to always accept the certificate, | |
| # bypassing name mismatch and chain errors. | |
| $ValidationCallback = { | |
| param( | |
| [System.Object]$sender, | |
| [System.Security.Cryptography.X509Certificates.X509Certificate]$certificate, | |
| [System.Security.Cryptography.X509Certificates.X509Chain]$chain, | |
| [System.Net.Security.SslPolicyErrors]$sslPolicyErrors | |
| ) | |
| # Always return $true to accept any certificate | |
| $true | |
| } | |
| # 2. Establish a TCP connection | |
| $TcpClient = New-Object System.Net.Sockets.TcpClient | |
| try { | |
| $TcpClient.Connect($Hostname, $Port) | |
| } | |
| catch { | |
| Write-Error "Could not connect to $($Hostname):$($Port). Error: $($_.Exception.Message)" | |
| $TcpClient.Dispose() | |
| return | |
| } | |
| # 3. Establish the SSL stream using the validation callback | |
| # The correct constructor requires the NetworkStream, the leaveInnerStreamOpen boolean ($false), | |
| # and the validation callback delegate. | |
| $SslStream = New-Object System.Net.Security.SslStream($TcpClient.GetStream(), $false, $ValidationCallback) | |
| try { | |
| # Perform the SSL handshake, passing the FQDN for SNI | |
| $SslStream.AuthenticateAsClient($Hostname) | |
| } | |
| catch { | |
| Write-Error "SSL handshake failed for $($Hostname). Error: $($_.Exception.Message)" | |
| $SslStream.Dispose() | |
| $TcpClient.Dispose() | |
| return | |
| } | |
| # 4. Retrieve the certificate object | |
| $Certificate = $SslStream.RemoteCertificate | |
| # Clean up the streams/connections | |
| $SslStream.Dispose() | |
| $TcpClient.Dispose() | |
| if (-not $Certificate) { | |
| Write-Error "Failed to retrieve RemoteCertificate from the SSL stream." | |
| return | |
| } | |
| # 5. Calculate the SHA256 hash (Thumbprint) | |
| $CertHashBytes = $Certificate.GetCertHash([System.Security.Cryptography.HashAlgorithmName]::SHA256) | |
| # 6. Format the output | |
| $SSL_THUMBPRINT = [System.BitConverter]::ToString($CertHashBytes).Replace('-', '') | |
| # Add colons back for the traditional Thumbprint format | |
| return $SSL_THUMBPRINT -replace '(..(?!$))','$1:' | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment