Skip to content

Instantly share code, notes, and snippets.

@IISResetMe
Last active June 14, 2024 20:31
Show Gist options
  • Save IISResetMe/66ab3f0ced4eb406f21bf354cfe7ad45 to your computer and use it in GitHub Desktop.
Save IISResetMe/66ab3f0ced4eb406f21bf354cfe7ad45 to your computer and use it in GitHub Desktop.
using namespace System.Net.Sockets
using namespace System.Net.Security
using namespace System.Security.Cryptography.X509Certificates
function ConvertFrom-X509Certificate {
param(
[Parameter(ValueFromPipeline)]
[X509Certificate2]$Certificate
)
process {
@(
'-----BEGIN CERTIFICATE-----'
[Convert]::ToBase64String(
$Certificate.Export([X509ContentType]::Cert),
[Base64FormattingOptions]::InsertLineBreaks
)
'-----END CERTIFICATE-----'
) -join [Environment]::NewLine
}
}
function Get-RemoteCertificate {
param(
[Alias('CN')]
[Parameter(Mandatory = $true, Position = 0)]
[string]$ComputerName,
[Parameter(Position = 1)]
[UInt16]$Port = 443,
[ValidateSet('Base64', 'X509Certificate')]
[string]$As = 'X509Certificate'
)
$tcpClient = [TcpClient]::new($ComputerName, $Port)
try {
$tlsClient = [SslStream]::new($tcpClient.GetStream())
$tlsClient.AuthenticateAsClient($ComputerName)
if ($As -eq 'Base64') {
return $tlsClient.RemoteCertificate |ConvertFrom-X509Certificate
}
return $tlsClient.RemoteCertificate -as [X509Certificate2]
}
finally {
if ($tlsClient -is [IDisposable]) {
$tlsClient.Dispose()
}
$tcpClient.Dispose()
}
}
@lkeersmaekers
Copy link

Just what I needed but I've added a [switch]$Insecure = $false to the parameters and changed to $tlsClient = [SslStream]::new($tcpClient.GetStream(), $false, {$Insecure}) to be able to get certificate information when the certificate is invalid.

@MertSenel
Copy link

thanks you @IISResetMe this is something I was looking for.

@jwarwick-bry
Copy link

Also I found that if the server requires client auth certs, even though you should be able to preview the server certs, this library doesn't provide for that. So I added a optional client auth, too.
[string]$ClientAuth

        #annoyingly (and probably protocol-unnecessarily):  Error retrieving property '$RemoteCertificate': $This operation is only allowed using a successfully authenticated context.
        if ($ClientCert -AND $ClientCert.length -gt 5) {
            $pfxPath = $ClientCert
			$varCached = get-variable -scope script -name 'pfxPassword' -ErrorAction SilentlyContinue
            if (-NOT $varCached) { 
				$script:pfxPassword = Read-Host -Prompt "Enter the password for the client SSL cert PFX file" -AsSecureString 
			}
            $pfxCert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2($pfxPath, $pfxPassword)
            $sslOptions = [System.Net.Security.SslClientAuthenticationOptions]::new()
            $sslOptions.TargetHost = $ComputerName
            $sslOptions.ClientCertificates = [System.Security.Cryptography.X509Certificates.X509CertificateCollection]::new()
            $sslOptions.ClientCertificates.Add($pfxCert)
            $sslOptions.EnabledSslProtocols = [System.Security.Authentication.SslProtocols]::Tls12
            $tlsClient.AuthenticateAsClient($sslOptions)
        }else {
            $tlsClient.AuthenticateAsClient($ComputerName)
        }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment