使用根 CA 签名者生成自签名证书

2024-02-19

场景:我正在使用 PowerShellWindows Server 2012r2生成根证书并希望使用它在动态生成(和销毁)的开发/测试环境中签署新创建的中间证书和 Web 证书。这些脚本是远程部署的,目的是尽可能保持纯 PowerShell。在 Windows 10/2016 中,生成根证书后相对容易:

$Cert = New-SelfSignedCertificate -Signer $Root -Subject "CN=$Subject"

我已经使用 COM 生成了根证书X509Enrollment.CX509CertificateRequestCertificate and Security.Cryptography.X509Certificates.X509Certificate2在我已经有一段时间的混蛋PS中,主要是因为我需要确保主题和用法设置得非常具体。我不太确定如何使用它来签署没有上述内容的标准证书(我之前使用过)。

有一些在 C# 中使用 Bouncy Castle(见下文)的示例,我可以将其绑定到 PowerShell,但是随后我需要在动态开发/测试环境中额外部署它,并且我希望能够在 Powershell 中执行此操作(通过 COM如果需要的话)具有最少的依赖性。

  • C# 即时生成自签名证书 https://stackoverflow.com/questions/22230745/generate-self-signed-certificate-on-the-fly
  • 如何在 Powershell 中使用 Bouncy Castle http://blog.differentpla.net/blog/2013/04/17/how-do-i-use-bouncy-castle-from-powershell

在我的例子中,避免 makecert 和 openssl 的最终解决方案是使用 Powershell 和 BouncyCastle。我从以下位置分叉了 PSBouncyCastle 存储库PS充气城堡 https://github.com/rlipscombe/PSBouncyCastle由 RLipscombe 推出,并推送了 1.8.1 Bouncy Castle。我的分叉版本是我用于脚本的版本,分叉位于分叉:PSBouncyCastle.New https://github.com/LimpingNinja/PSBouncyCastle.New.

然后我用了StackOverflow:C# 动态生成证书 https://stackoverflow.com/questions/22230745/generate-self-signed-certificate-on-the-fly作为编写下面的 powershell 的灵感,我将把它添加到我的 GitHub 并发表评论,我会尽快修改它:

Import-Module -Name PSBouncyCastle.New

function New-SelfSignedCertificate {
  [CmdletBinding()]
  param (
    [string]$SubjectName,
    [string]$FriendlyName = "New Certificate",
    [object]$Issuer,
    [bool]$IsCA = $false,
    [int]$KeyStrength = 2048,
    [int]$ValidYears = 2,
    [hashtable]$EKU = @{}
  )

  # Needed generators
  $random = New-SecureRandom
  $certificateGenerator = New-CertificateGenerator

  if($Issuer -ne $null -and $Issuer.HasPrivateKey -eq $true)
  {
    $IssuerName = $Issuer.IssuerName.Name
    $IssuerPrivateKey = $Issuer.PrivateKey
  }
  # Create and set a random certificate serial number
  $serial = New-SerialNumber -Random $random
  $certificateGenerator.SetSerialNumber($serial)

  # The signature algorithm
  $certificateGenerator.SetSignatureAlgorithm('SHA256WithRSA')

  # Basic Constraints - certificate is allowed to be used as intermediate.
  # Powershell requires either a $null or reassignment or it will return this from the function
  $certificateGenerator = Add-BasicConstraints -isCertificateAuthority $IsCA -certificateGenerator $certificateGenerator

  # Key Usage
  if($EKU.Count -gt 0) 
  {
    $certificateGenerator = $certificateGenerator | Add-ExtendedKeyUsage @EKU
  }
  # Create and set the Issuer and Subject name
  $subjectDN = New-X509Name -Name ($SubjectName)
  if($Issuer -ne $null) {
    $IssuerDN = New-X509Name -Name ($IssuerName)
  }
  else 
  {
    $IssuerDN = New-X509Name -Name ($SubjectName)
  }  
  $certificateGenerator.SetSubjectDN($subjectDN)
  $certificateGenerator.SetIssuerDN($IssuerDN)

  # Authority Key and Subject Identifier
  if($Issuer -ne $null)
  {
    $IssuerKeyPair = ConvertTo-BouncyCastleKeyPair -PrivateKey $IssuerPrivateKey
    $IssuerSerial = [Org.BouncyCastle.Math.BigInteger]$Issuer.GetSerialNumber()
    $authorityKeyIdentifier = New-AuthorityKeyIdentifier -name $Issuer.IssuerName.Name -publicKey $IssuerKeyPair.Public -serialNumber $IssuerSerial
    $certificateGenerator = Add-AuthorityKeyIdentifier -certificateGenerator $certificateGenerator -authorityKeyIdentifier $authorityKeyIdentifier
  }

  # Validity range of the certificate
  [DateTime]$notBefore = (Get-Date).AddDays(-1)
  if($ValidYears -gt 0) {
    [DateTime]$notAfter = $notBefore.AddYears($ValidYears)
  }
  $certificateGenerator.SetNotBefore($notBefore)
  $certificateGenerator.SetNotAfter($notAfter)


  # Subject public key ~and private
  $subjectKeyPair = New-KeyPair -Strength $keyStrength -Random $random
  if($IssuerPrivateKey -ne $null)
  {
    $IssuerKeyPair = [Org.BouncyCastle.Security.DotNetUtilities]::GetKeyPair($IssuerPrivateKey)
  }
  else 
  {
    $IssuerKeyPair = $subjectKeyPair
  }
  $certificateGenerator.SetPublicKey($subjectKeyPair.Public)

  # Create the Certificate
  $IssuerKeyPair = $subjectKeyPair
  $certificate = $certificateGenerator.Generate($IssuerKeyPair.Private, $random)
  # At this point you have the certificate and need to convert it and export, I return the private key for signing the next cert
  $pfxCertificate = ConvertFrom-BouncyCastleCertificate -certificate $certificate -subjectKeyPair $subjectKeyPair -friendlyName $FriendlyName
  return $pfxCertificate
}

此 powershell 的一些用法示例如下:

生成根CA

$TestRootCA = New-SelfSignedCertificate -subjectName "CN=TestRootCA" -IsCA $true
Export-Certificate -Certificate $test -OutputFile "TestRootCA.pfx" -X509ContentType Pfx

生成标准自签名

$TestSS = New-SelfSignedCertificate -subjectName "CN=TestLocal"
Export-Certificate -Certificate $TestSS -OutputFile "TestLocal.pfx" -X509ContentType Pfx

生成证书,使用根证书签名

$TestRootCA = New-SelfSignedCertificate -subjectName "CN=TestRootCA" -IsCA $true
$TestSigned = New-SelfSignedCertificate -subjectName "CN=TestSignedByRoot" -issuer $TestRootCA

Export-Certificate -Certificate $test -OutputFile "TestRootCA.pfx" -X509ContentType Pfx
Export-Certificate -Certificate $test -OutputFile "TestRootCA.pfx" -X509ContentType Pfx

生成具有特定用途的自签名

$TestServerCert = New-SelfSignedCertificate -subjectName "CN=TestServerCert" -EKU @{ "ServerAuthentication" = $true }

请注意,-EKU 参数通过 splatting 接受,这样做是为了确保添加到 Add-ExtendedKeyUsage 的任何内容都有效传递。它接受以下证书用法:

  • 电子签名
  • 不可否认性
  • 密钥加密
  • 数据加密
  • 关键协议
  • 密钥证书签名
  • CrlSign
  • 仅加密
  • 仅破译

这符合我的需求,并且似乎适用于我们用于动态环境的所有 Windows 平台。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用根 CA 签名者生成自签名证书 的相关文章

随机推荐