【问题标题】:Azure PowerShell - Extract PEM from SSL certificateAzure PowerShell - 从 SSL 证书中提取 PEM
【发布时间】:2019-02-28 18:01:32
【问题描述】:

我在 Azure 下有一个使用 SSL 绑定证书(已通过 Azure 门户生成)的 WebApp。 我想使用 Azure Powershell 检索此 SSL 证书的公钥(PEM 文件)。我已经设法使用 mycertificate.GetPublicKeyString() 函数在 C# 后台提取公钥,但我不知道如何在 PowerShell 下实现。 你有什么想法吗?

非常感谢。

【问题讨论】:

    标签: azure ssl public-key


    【解决方案1】:

    我写了一个脚本来做这件事;除了它提取私钥。成功的关键是以 Pkcs8 格式导出您的公钥。如果您改用 GetRSAPublicKey,这应该会引导您导出公钥 PEM。

    <#
        FileName: pfx-2-pem.ps1
        Author: rashadrivera.com
        Description: This PowerShell script converts a PFX file into PEM format for use in WebPack's
                     Dev Server configurations.  This script is an alternative to using the common
                     OpenSSL, open-source tool; which is an untrusted, unmaintained, security risk.
    #>
    
    param (
    
        [Parameter(Mandatory=$true, HelpMessage="Path to your PFX file")]
        [string] $pfxPath,
    
        [Parameter(Mandatory=$false, HelpMessage="Optional PFX password")]
        [string] $pfxPassword,
    
        [Parameter(Mandatory=$false, HelpMessage="File path for certificate PEM export")]
        [string] $certFile = ".\your.cer.as.pem",
    
        [Parameter(Mandatory=$false, HelpMessage="Path to your private-key PEM export")]
        [string] $pvkFile = ".\your.private-key.as.pem"
    )
    
    $IMPORT_PFX_EXPORT_OPTIONS = [System.Security.Cryptography.X509Certificates.X509KeyStorageFlags]::Exportable
    $HAS_PASSWORD = -Not([System.String]::IsNullOrEmpty($pfxPassword))
    
    function Main() {
    
        [System.IO.Directory]::SetCurrentDirectory($(Get-Location))
    
        _validateParameters
    
        if (-NOT($HAS_PASSWORD)) {
            # Ensure NULL instead of empty or white-space string
            $pfxPassword = $null
        }
    
        $pfxAsCertificate = [System.Security.Cryptography.X509Certificates.X509Certificate2]::new($pfxPath, $pfxPassword, $IMPORT_PFX_EXPORT_OPTIONS)
    
        _exportCertPEM $pfxAsCertificate $certFile
        _exportPrivateKeyPEM $pfxAsCertificate $pvkFile
    }
    
    function _exportCertPEM([System.Security.Cryptography.X509Certificates.X509Certificate2]$pfx, [System.String] $outputPath) {
    
        $base64CertText = [System.Convert]::ToBase64String($pfx.RawData, "InsertLineBreaks")
    
        $out = New-Object String[] -ArgumentList 3
    
        $out[0] = "-----BEGIN CERTIFICATE-----"
        $out[1] = $base64CertText
        $out[2] = "-----END CERTIFICATE-----"
    
        [System.IO.File]::WriteAllLines($outputPath, $out)
    }
    
    function _exportPrivateKeyPEM([System.Security.Cryptography.X509Certificates.X509Certificate2]$pfx, [System.String] $outputPath) {
    
        $key = _extractCngKeyFromCert $pfx
    
        $base64CertText = [System.Convert]::ToBase64String($key.Export([System.Security.Cryptography.CngKeyBlobFormat]::Pkcs8PrivateBlob), "InsertLineBreaks");
    
        $out = New-Object String[] -ArgumentList 3
    
        $out[0] = "-----BEGIN PRIVATE KEY-----"
        $out[1] = $base64CertText
        $out[2] = "-----END PRIVATE KEY-----"
    
        [System.IO.File]::WriteAllLines($outputPath,$out)
    }
    
    function _extractCngKeyFromCert([System.Security.Cryptography.X509Certificates.X509Certificate2]$pfx) {
    
        $algorithmAsOidString = $pfx.GetKeyAlgorithm()
        $algorithmAsOid = [System.Security.Cryptography.Oid]::new($algorithmAsOidString)
    
        if ($algorithmAsOid.FriendlyName -eq "RSA") {
    
            $rsa = [System.Security.Cryptography.X509Certificates.RSACertificateExtensions]::GetRSAPrivateKey($pfx)
            $rsaCng = ([System.Security.Cryptography.RSACng]$rsa)
            return $rsaCng.Key
        } elseif ($algorithmAsOid.FriendlyName -eq "ECC") {
    
            $ecDsa = [System.Security.Cryptography.X509Certificates.ECDsaCertificateExtensions]::GetECDsaPrivateKey($pfx)
            $ecDsaCng = ([System.Security.Cryptography.ECDsaCng]$ecDsa)
            return $ecDsaCng.Key
        } else {
    
            throw "Certificate algorithm of '$algorithmAsOid.FriendlyName' is not supported"
        }
    }
    
    function _validateFilePathString($path) {
    
        try {
    
            [System.IO.FileInfo]::new($path) > $null
        } catch {
    
            throw "File path '$path' is invalid: $PSItem.Exception.Message"
        }
    }
    
    function _validateParameters() {
    
        if (-Not([System.IO.File]::Exists($pfxPath))) {
    
            throw "PFX file '$pfx' was not found"
        }
        try {
    
            if ($HAS_PASSWORD) {
    
                [System.Security.Cryptography.X509Certificates.X509Certificate2]::new($pfxPath, $pfxPassword, $IMPORT_PFX_EXPORT_OPTIONS) > $null
            } else {
    
                [System.Security.Cryptography.X509Certificates.X509Certificate2]::new($pfxPath, $null, $IMPORT_PFX_EXPORT_OPTIONS) > $null
            }
        } catch {
    
            if ($hasPassword) {
    
                throw "Source path of '$sourcePath' is not an X509 certificate file or the password specified is incorrect.  Error: `r`n$PSItem.Exception.Message"
            } else {
    
                throw "Source path of '$sourcePath' is not an X509 certificate file OR a password is required. Error: `r`n$PSItem.Exception.Message"
            }
        }
        _validateFilePathString($certFile)
        _validateFilePathString($pvkFile)
    }
    
    Main
    

    【讨论】:

    • 推测的方法是:(1)为您的证书提取CNGKey; (2) 使用Export(Pkcs8) 导出方式和格式,绝对重要; (3) 使用带有换行符的 Convert.ToBase64String 来获取您的私钥的文本; (4) 用 BEGIN/END PUBLIC KEY 行包装您的密钥文本
    【解决方案2】:

    我找到了这篇文章:

    https://blogs.msdn.microsoft.com/appserviceteam/2017/02/24/creating-a-local-pfx-copy-of-app-service-certificate/

    在 $pfxCertObject 上,您可以调用:$pfxCertObject.GetPublicKeyString(),它会为您提供十六进制模式的公钥。

    使用https://holtstrom.com/michael/tools/hextopem.php,您可以将其转换为 PEM 格式。

    希望这会有所帮助。

    【讨论】:

      【解决方案3】:

      您可以使用 Get-PfxCertificate 从 PKCS#12 存档 (.pfx/.p12) 中提取公共证书

      $pfx = Get-PfxCertificate -FilePath C:\archive.pfx
      $pem = [Convert]::ToBase64String($pfx.GetRawCertData())
      

      【讨论】:

      • 谢谢。但我没有 pfx 文件,证书存储在 Azure 中,因为它是直接使用 Azure 生成的。所以它在资源组中。
      • @Gizmo 你可以用 PowerShell 导出它,并以同样的方式获取公钥
      猜你喜欢
      • 2015-05-16
      • 2022-10-19
      • 2015-07-08
      • 2016-06-02
      • 1970-01-01
      • 1970-01-01
      • 2014-02-13
      • 2017-03-31
      相关资源
      最近更新 更多