简体   繁体   English

如何使用PowerShell从网站下载SSL证书?

[英]How to download the SSL certificate from a website using PowerShell?

I want to download the SSL certificate from, say https://www.outlook.com , using PowerShell. 我想使用PowerShell从https://www.outlook.com下载SSL证书。 Is it possible? 可能吗? Could someone help me? 有人能帮助我吗?

To share more knowledge :-) 分享更多知识:-)

$webRequest = [Net.WebRequest]::Create("https://www.outlook.com")
try { $webRequest.GetResponse() } catch {}
$cert = $webRequest.ServicePoint.Certificate
$bytes = $cert.Export([Security.Cryptography.X509Certificates.X509ContentType]::Cert)
set-content -value $bytes -encoding byte -path "$pwd\Outlook.Com.cer"

My co-worker Michael J. Lyons shared this with me. 我的同事Michael J. Lyons和我分享了这个。

You should be able to get the public key by using the ServicePoint property on the HttpWebRequest object. 您应该能够通过使用HttpWebRequest对象上的ServicePoint属性来获取公钥。 This necessary information will be populated once we have made a http request to the site in question. 一旦我们向相关网站发出http请求,就会填充这些必要的信息。

If the request is made to a site which has an untrusted certificate the GetResponse method will throw an exception, However, the ServicePoint will still contain the Certificate so we want to ensure we ignore WebException if the status is a trust failure. 如果请求发送到具有不受信任证书的站点,则GetResponse方法将引发异常,但是, ServicePoint仍将包含Certificate因此我们希望确保在状态为信任失败时忽略WebException

So something like the following should work: 所以类似下面这样的东西应该有效:

function Get-PublicKey
{
    [OutputType([byte[]])]
    PARAM (
        [Uri]$Uri
    )

    if (-Not ($uri.Scheme -eq "https"))
    {
        Write-Error "You can only get keys for https addresses"
        return
    }

    $request = [System.Net.HttpWebRequest]::Create($uri)

    try
    {
        #Make the request but ignore (dispose it) the response, since we only care about the service point
        $request.GetResponse().Dispose()
    }
    catch [System.Net.WebException]
    {
        if ($_.Exception.Status -eq [System.Net.WebExceptionStatus]::TrustFailure)
        {
            #We ignore trust failures, since we only want the certificate, and the service point is still populated at this point
        }
        else
        {
            #Let other exceptions bubble up, or write-error the exception and return from this method
            throw
        }
    }

    #The ServicePoint object should now contain the Certificate for the site.
    $servicePoint = $request.ServicePoint
    $key = $servicePoint.Certificate.GetPublicKey()
    Write-Output $key
}

Get-PublicKey -Uri "https://www.bing.com"
Get-PublicKey -Uri "https://www.facebook.com"

If you want to call the method many times and some might have the same address, you might want to improve the function by using the ServicePointManager.FindServicePoint(System.Uri) method, since it will return a cached version if a request has already been made to that site. 如果要多次调用该方法,并且某些方法可能具有相同的地址,则可能需要使用ServicePointManager.FindServicePoint(System.Uri)方法来改进该函数,因为如果请求已经过,它将返回缓存版本制作到该网站。 So you could check if the service point has been populated with information. 因此,您可以检查服务点是否已填充信息。 If it hasn't, make the web request. 如果没有,请发出Web请求。 If it has, just use the already existing information, saving yourself an http request. 如果有,只需使用已有的信息,为自己保存一个http请求。

From http://poshcode.org/2521 : 来自http://poshcode.org/2521

function Get-WebsiteCertificate {
  [CmdletBinding()]
  param (
    [Parameter(Mandatory=$true)] [System.Uri]
      $Uri,
    [Parameter()] [System.IO.FileInfo]
      $OutputFile,
    [Parameter()] [Switch]
      $UseSystemProxy,  
    [Parameter()] [Switch]
      $UseDefaultCredentials,
    [Parameter()] [Switch]
      $TrustAllCertificates
  )
  try {
    $request = [System.Net.WebRequest]::Create($Uri)
    if ($UseSystemProxy) {
      $request.Proxy = [System.Net.WebRequest]::DefaultWebProxy
    }

    if ($UseSystemProxy -and $UseDefaultCredentials) {
      $request.Proxy.Credentials = [System.Net.CredentialCache]::DefaultNetworkCredentials
    }

    if ($TrustAllCertificates) {
      # Create a compilation environment
      $Provider=New-Object Microsoft.CSharp.CSharpCodeProvider
      $Compiler=$Provider.CreateCompiler()
      $Params=New-Object System.CodeDom.Compiler.CompilerParameters
      $Params.GenerateExecutable=$False
      $Params.GenerateInMemory=$True
      $Params.IncludeDebugInformation=$False
      $Params.ReferencedAssemblies.Add("System.DLL") > $null
      $TASource=@'
        namespace Local.ToolkitExtensions.Net.CertificatePolicy {
          public class TrustAll : System.Net.ICertificatePolicy {
            public TrustAll() { 
            }
            public bool CheckValidationResult(System.Net.ServicePoint sp,
              System.Security.Cryptography.X509Certificates.X509Certificate cert, 
              System.Net.WebRequest req, int problem) {
              return true;
            }
          }
        }
'@ 
      $TAResults=$Provider.CompileAssemblyFromSource($Params,$TASource)
      $TAAssembly=$TAResults.CompiledAssembly

      ## We now create an instance of the TrustAll and attach it to the ServicePointManager
      $TrustAll=$TAAssembly.CreateInstance("Local.ToolkitExtensions.Net.CertificatePolicy.TrustAll")
      [System.Net.ServicePointManager]::CertificatePolicy=$TrustAll
    }

    $response = $request.GetResponse()
    $servicePoint = $request.ServicePoint
    $certificate = $servicePoint.Certificate

    if ($OutputFile) {
      $certBytes = $certificate.Export(
          [System.Security.Cryptography.X509Certificates.X509ContentType]::Cert
        )
      [System.IO.File]::WriteAllBytes( $OutputFile, $certBytes )
      $OutputFile.Refresh()
      return $OutputFile
    } else {
      return $certificate
    }
  } catch {
    Write-Error "Failed to get website certificate. The error was '$_'."
    return $null
  }

  <#
    .SYNOPSIS
      Retrieves the certificate used by a website.

    .DESCRIPTION
      Retrieves the certificate used by a website. Returns either an object or file.

    .PARAMETER  Uri
      The URL of the website. This should start with https.

    .PARAMETER  OutputFile
      Specifies what file to save the certificate as.

    .PARAMETER  UseSystemProxy
      Whether or not to use the system proxy settings.

    .PARAMETER  UseDefaultCredentials
      Whether or not to use the system logon credentials for the proxy.

    .PARAMETER  TrustAllCertificates
      Ignore certificate errors for certificates that are expired, have a mismatched common name or are self signed.

    .EXAMPLE
      PS C:\> Get-WebsiteCertificate "https://www.gmail.com" -UseSystemProxy -UseDefaultCredentials -TrustAllCertificates -OutputFile C:\gmail.cer

    .INPUTS
      Does not accept pipeline input.

    .OUTPUTS
      System.Security.Cryptography.X509Certificates.X509Certificate, System.IO.FileInfo
  #>
}

function Import-Certificate {
<#
    .SYNOPSIS
        Imports certificate in specified certificate store.

    .DESCRIPTION
        Imports certificate in specified certificate store.

    .PARAMETER  CertFile
        The certificate file to be imported.

    .PARAMETER  StoreNames
        The certificate store(s) in which the certificate should be imported.

    .PARAMETER  LocalMachine
        Using the local machine certificate store to import the certificate

    .PARAMETER  CurrentUser
        Using the current user certificate store to import the certificate

    .PARAMETER  CertPassword
        The password which may be used to protect the certificate file

    .EXAMPLE
        PS C:\> Import-Certificate C:\Temp\myCert.cer

        Imports certificate file myCert.cer into the current users personal store

    .EXAMPLE
        PS C:\> Import-Certificate -CertFile C:\Temp\myCert.cer -StoreNames my

        Imports certificate file myCert.cer into the current users personal store

    .EXAMPLE
        PS C:\> Import-Certificate -Cert $certificate -StoreNames my -StoreType LocalMachine

        Imports the certificate stored in $certificate into the local machines personal store 

    .EXAMPLE
        PS C:\> Import-Certificate -Cert $certificate -SN my -ST Machine

        Imports the certificate stored in $certificate into the local machines personal store using alias names

    .EXAMPLE
        PS C:\> ls cert:\currentUser\TrustedPublisher | Import-Certificate -ST Machine -SN TrustedPublisher

        Copies the certificates found in current users TrustedPublishers store to local machines TrustedPublisher using alias  

    .INPUTS
        System.String|System.Security.Cryptography.X509Certificates.X509Certificate2, System.String, System.String

    .OUTPUTS
        NA

    .NOTES
        NAME:      Import-Certificate
        AUTHOR:    Patrick Sczepanksi (Original anti121)
        VERSION:   20110502
        #Requires -Version 2.0
    .LINK
        http://poshcode.org/2643
        http://poshcode.org/1937 (Link to original script)

#>

    [CmdletBinding()]
    param
    (
        [Parameter(ValueFromPipeline=$true,Mandatory=$true, Position=0, ParameterSetName="CertFile")]
        [System.IO.FileInfo]
        $CertFile,

        [Parameter(ValueFromPipeline=$true,Mandatory=$true, Position=0, ParameterSetName="Cert")]
        [System.Security.Cryptography.X509Certificates.X509Certificate2]
        $Cert,

        [Parameter(Position=1)]
        [Alias("SN")]
        [string[]] $StoreNames = "My",

        [Parameter(Position=2)]
        [Alias("Type","ST")]
        [ValidateSet("LocalMachine","Machine","CurrentUser","User")]
        [string]$StoreType = "CurrentUser",

        [Parameter(Position=3)]
        [Alias("Password","PW")]
        [string] $CertPassword
    )

    begin
    {
        [void][System.Reflection.Assembly]::LoadWithPartialName("System.Security")
    }

    process 
    {
        switch ($pscmdlet.ParameterSetName) {
            "CertFile" {
                try {
                    $Cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2 $($CertFile.FullName),$CertPassword
                }
                catch {   
                    Write-Error ("Error reading '$CertFile': $_ .") -ErrorAction:Continue
                }
            }
            "Cert" {

            }
            default {
                Write-Error "Missing parameter:`nYou need to specify either a certificate or a certificate file name."
            }
        }

        switch -regex ($storeType) {
            "Machine$" { $StoreScope = "LocalMachine" }
            "User$"  { $StoreScope = "CurrentUser" }
        } 

        if ( $Cert ) {
            $StoreNames | ForEach-Object {
                $StoreName = $_
                Write-Verbose " [Import-Certificate] :: $($Cert.Subject) ($($Cert.Thumbprint))"
                Write-Verbose " [Import-Certificate] :: Import into cert:\$StoreScope\$StoreName"

                if (Test-Path "cert:\$StoreScope\$StoreName") {
                    try
                    {
                        $store = New-Object System.Security.Cryptography.X509Certificates.X509Store $StoreName, $StoreScope
                        $store.Open([System.Security.Cryptography.X509Certificates.OpenFlags]::ReadWrite)
                        $store.Add($Cert)
                        if ( $CertFile ) {
                            Write-Verbose " [Import-Certificate] :: Successfully added '$CertFile' to 'cert:\$StoreScope\$StoreName'."
                        } else {
                            Write-Verbose " [Import-Certificate] :: Successfully added '$($Cert.Subject) ($($Cert.Thumbprint))' to 'cert:\$StoreScope\$StoreName'."
                        }
                    }
                    catch
                    {
                        Write-Error ("Error adding '$($Cert.Subject) ($($Cert.Thumbprint))' to 'cert:\$StoreScope\$StoreName': $_ .") -ErrorAction:Continue
                    }
                    if ( $store ) {
                        $store.Close()
                    }
                } 
                else {
                    Write-Warning "Certificate store '$StoreName' does not exist. Skipping..."
                }
            }
        } else {
            Write-Warning "No certificates found."
        }
    }

    end { 
        Write-Host "Finished importing certificates." 
    }
}

I successfully used these functions like this: 我成功地使用了这样的函数:

##Import self-signed certificate
Get-WebsiteCertificate $baseUrl local.cer -trust | Out-Null
Import-Certificate -certfile local.cer -SN Root  | Out-Null

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何使用PowerShell将SSL证书添加到azure网站? - How to add an SSL certificate to an azure website using powershell? 如何在 PowerShell 中检索 IIS 网站的 SSL 证书 - How to retrieve SSL certificate of an IIS website in PowerShell 如何使用 powershell 从 Azure keyvault in.cer 格式下载证书? - how to download certificate from Azure keyvault in .cer format using powershell? 绑定后将SSL证书分配给网站-Powershell - Assign SSL Certificate to Website After Binding - Powershell 在Powershell中使用SendKeys从网站下载文件 - Download file from website using SendKeys in Powershell 如何从使用 PowerShell 自签名的 web 服务器下载证书? - How do I download the certificate from a web server that is self signed using PowerShell? 无法使用 powershell 从章鱼库访问 ssl 证书作为 X509Certificate2 对象 - Unable to access ssl certificate from octopus library as X509Certificate2 object using powershell PowerShell 6. *使用SSL证书和UBUNTU进行远程处理 - PowerShell 6.* Remoting using SSL certificate and UBUNTU Powershell - 使用共享证书添加SSL绑定 - Powershell - Add SSL binding using shared certificate 如何使用 PowerShell 或 Windows 命令行从网站下载图像文件? - How to download an image file from a website using PowerShell or from Windows command line?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM