2014-03-06 3 views

답변

7

HttpWebRequest 개체의 ServicePoint 속성을 사용하여 공개 키를 가져올 수 있어야합니다. 이 필수 정보는 문제의 사이트에 대해 http 요청을 한 후에 채워집니다. 요청이하는 GetResponse 메서드는 예외가 발생합니다 신뢰할 수없는 인증서가있는 사이트로했을 경우

은, 그러나, ServicePoint는 여전히 Certificate 그래서 우리는 상태가 신뢰 실패하면 우리가 WebException을 무시 보장 할 포함됩니다.

그래서 다음과 같이 작동합니다 :

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" 

당신이 방법을 여러 번 호출 할과 같은 주소를 가질 수있는 몇 가지, 당신은 ServicePointManager.FindServicePoint(System.Uri) 방법을 사용하여 기능을 개선 할 수 있습니다 경우, 이후 해당 사이트에 대한 요청이 이미 있으면 캐시 된 버전을 반환합니다. 따라서 서비스 지점에 정보가 입력되었는지 확인할 수 있습니다. 그렇지 않은 경우 웹 요청을하십시오. 있다면, 이미 존재하는 정보를 사용하여 http 요청을 저장하십시오.

+0

놀라운 설명. 시간 내 주셔서 감사합니다 :-) – RafaMarrara

1

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 
     [email protected]' 
     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." 
    } 
} 

내가 성공적으로이 같은 이러한 기능을 사용 :

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

시간 내 주셔서 감사합니다 :-) – RafaMarrara

14

더 많은 지식을 공유하기 위해

$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" 

내 동료 마이클 J. :-) 리용은이 사실을 나에게 알렸다.

+0

Nit : Powershell은 문자열을 행복하게 열거 형 멤버로 변환하므로'$ cert.Export ("Cert")'는 유효합니다. – zneak

관련 문제