许多网站提供工具来帮助检查部署到网站的证书是否有效;包括检查是否安装了完整的链,而不仅仅是客户端证书。以下示例:
- https://whatsmychaincert.com
- https://www.sslchecker.com/sslchecker
- https://www.geocerts.com/ssl-checker
- https://www.sslshopper.com/ssl-checker.html
我想通过PowerShell脚本模拟这种检查(注意:目的是检查第三方网站;这样我们就不能访问任何服务器端(,所以想出了以下方法:
Function Get-CertificateChain {
[OutputType([System.Security.Cryptography.X509Certificates.X509ChainElement])]
[CmdletBinding()]
Param (
[Parameter(Mandatory)]
[string]$ComputerName
,
[Parameter()]
[Int32]$Port = 443
,
[Parameter()]
[System.Security.Authentication.SslProtocols]$SslProtocol = [System.Security.Authentication.SslProtocols]::Tls12 # NB: The enum value Default is considered deprecated
,
[Parameter()]
[Switch]$CertificateInfoOnly
)
[System.Net.Sockets.Socket]$socket = [System.Net.Sockets.Socket]::new([System.Net.Sockets.SocketType]::Stream, [System.Net.Sockets.ProtocolType]::Tcp)
$socket.Connect($ComputerName, $Port)
try {
[System.Net.Sockets.NetworkStream]$networkStream = [System.Net.Sockets.NetworkStream]::new($socket, $true)
[System.Net.Security.SslStream]$sslStream = [System.Net.Security.SslStream]::new($networkStream, $true)
$sslStream.AuthenticateAsClient( $ComputerName, $null, $SslProtocol, $false )
[System.Security.Cryptography.X509Certificates.X509Certificate2]$remoteCertificate = [System.Security.Cryptography.X509Certificates.X509Certificate2]($sslStream.RemoteCertificate)
[System.Security.Cryptography.X509Certificates.X509Chain]$chain = [System.Security.Cryptography.X509Certificates.X509Chain]::new()
$chain.Build($remoteCertificate) | Out-Null
Write-Verbose "Chain status length is: $($chain.ChainStatus.Length)" # Gives 0 every time :/
foreach ($chainElement in $chain.ChainElements) {
#[System.Security.Cryptography.X509Certificates.X509ChainElement]
if ($CertificateInfoOnly.IsPresent) {
$chainElement | Select-Object -ExpandProperty Certificate
} else {
$chainElement
}
}
} finally {
$socket.Close()
}
}
然而,即使在缺少完整链的网站上,这也会检索完整链;我想是因为BUILD太有用了,它会获取它能找到的任何丢失的中间证书或根证书。
我在ChainStatus上找到了类似的答案,这似乎是一个更好的解决方案;然而,当我在调用Build之后调用$chain.ChainStatus.Length
时(请参见Write-Verbose
调用(,我会得到0
的结果。
使用.net框架,查看第三方返回的证书链是否有效(即包括在无法自动解决丢失或无序证书链的客户端上(,或者获取实际返回的证书信息的正确方法是什么?
不幸的是,您不能(使用SslStream(。NET将使用本地缓存和网络检索的组合来尝试完成链,并且没有一个地方可以真正阻止它(此外,您通常希望它将根放在顶部,因为通常认为正确的TLS服务器配置是除了根权限之外的整个链(。
由于.NET支持TCP套接字,您可以在.NET中通过自己编写TLS握手代码来实现这一点,然后查看实际情况。。。但我真的不建议这么做。