我的可导出私钥不可导出

问题描述 投票:0回答:1

注意:答案可以来自 VB.NET 或 C#。我对这个问答没有偏好。


我正在使用下面基于 CertesBouncy Castle 的代码来完成、生成 Let's Encrypt TLS 证书并将其导入到我的 CurrentUser 存储中。问题是,即使我将私钥标记为可导出,但在生成的证书中找不到它。

正如我们所看到的,导出私钥的选项被禁用,即使密钥存储显示它存在。

enter image description here

enter image description here

我已经完成了这个示例,并且代码似乎做了与我的几乎相同的事情。唯一突出的区别是它加载

RsaKeyPairGenerator
来生成新的密钥对。这不适用于我的情况,因为我没有创建自己的证书,并且我已经拥有证书和密钥
Byte
数组。

我的代码是否遗漏了什么或做错了什么?我没有发现它。如何生成和存储私钥可见且可导出的

X509Certificate2
实例?

这是我的代码:


Public Class Tls
  Public Shared Async Function ImportAsync(NewCertificate As X509Certificate2) As Task(Of Result)
    Dim oCollection As X509Certificate2Collection
    Dim oQuery As Func(Of X509Certificate2, Boolean)

    Await Task.CompletedTask

    oQuery = Function(OldCertificate) OldCertificate.Subject = NewCertificate.Subject

    Using oStore As New X509Store(StoreName.My, StoreLocation.CurrentUser)
      oStore.Open(OpenFlags.ReadWrite)
      oCollection = New X509Certificate2Collection(oStore.Certificates.Where(oQuery).ToArray)
      oStore.RemoveRange(oCollection)
      oStore.Add(NewCertificate)
    End Using

    Return Result.Ok
  End Function

  Public Shared Async Function GenerateAsync(Order As IOrderContext, CityCode As String) As Task(Of Result(Of X509Certificate2))
    Dim oCertificateChain As CertificateChain
    Dim oCertificate As X509Certificate2
    Dim oPrivateKey As IKey
    Dim oInfo As CsrInfo

    oInfo = New CsrInfo With {
      .OrganizationUnit = "MyUnit",
      .Organization = "MyOrg",
      .CountryName = "MyCountry",
      .Locality = "MyTown",
      .State = "MyState"
    }

    oPrivateKey = KeyFactory.NewKey(KeyAlgorithm.RS256)
    oCertificateChain = Await Order.Generate(oInfo, oPrivateKey)
    oCertificate = GetSignedCertificate(oCertificateChain.Certificate.ToDer, oPrivateKey.ToDer, CityCode)

    Return oCertificate.ToResult
  End Function

  Private Shared Function GetSignedCertificate(Certificate As Byte(), PrivateKey As Byte(), Password As String) As X509Certificate2
    Dim oUnsignedCertificate As X509.X509Certificate
    Dim oSignedCertificate As X509Certificate2
    Dim oCertificateParser As X509CertificateParser
    Dim oCertificateEntry As X509CertificateEntry
    Dim oPrivateKey As PrivateKeyInfo
    Dim oParameter As AsymmetricKeyParameter
    Dim oKeyEntry As AsymmetricKeyEntry
    Dim oPfxStore As Pkcs12Store
    Dim sSubject As String
    Dim oRandom As SecureRandom
    Dim eFlags As X509KeyStorageFlags

    ' Prepare the private key
    oPrivateKey = PrivateKeyInfo.GetInstance(PrivateKey)
    oParameter = PrivateKeyFactory.CreateKey(oPrivateKey)
    oKeyEntry = New AsymmetricKeyEntry(oParameter)
    oRandom = New SecureRandom
    eFlags = X509KeyStorageFlags.Exportable Or X509KeyStorageFlags.PersistKeySet Or X509KeyStorageFlags.UserKeySet

    ' Convert to PKCS#12 format
    oCertificateParser = New X509CertificateParser
    oUnsignedCertificate = oCertificateParser.ReadCertificate(Certificate)
    oCertificateEntry = New X509CertificateEntry(oUnsignedCertificate)
    sSubject = oUnsignedCertificate.SubjectDN.ToString
    oPfxStore = New Pkcs12Store
    oPfxStore.SetCertificateEntry(sSubject, oCertificateEntry)
    oPfxStore.SetKeyEntry($"{sSubject}_key", oKeyEntry, {oCertificateEntry})

    Using oStream As New MemoryStream
      oPfxStore.Save(oStream, Password.ToCharArray, oRandom)
      oSignedCertificate = New X509Certificate2(oStream.ToArray, Password, eFlags)
    End Using

    Return oSignedCertificate
  End Function
End Class
ssl-certificate bouncycastle public-key-encryption x509certificate2
1个回答
0
投票

经过大量拼凑来自各种不同来源的片段(太多记不清了),我想出了这个。它不包含几乎那么多的 Bouncy Castle 东西,但它确实有效。

Private Shared Function GetSignedCertificate(Certificate As Byte(), PrivateKey As Byte()) As X509Certificate2
  Dim oSecondaryRsa As RSACryptoServiceProvider
  Dim oCertificate As X509Certificate2
  Dim oPrimaryRsa As RSACryptoServiceProvider
  Dim oParameters As CspParameters
  Dim oPrivateKey As PrivateKeyInfo
  Dim oParameter As AsymmetricKeyParameter
  Dim oKeyEntry As AsymmetricKeyEntry
  Dim eFlags As X509KeyStorageFlags

  oPrivateKey = PrivateKeyInfo.GetInstance(PrivateKey)
  oParameter = PrivateKeyFactory.CreateKey(oPrivateKey)
  oKeyEntry = New AsymmetricKeyEntry(oParameter)
  oSecondaryRsa = DotNetUtilities.ToRSA(DirectCast(oKeyEntry.Key, RsaPrivateCrtKeyParameters))

  oParameters = New CspParameters With
  {
    .KeyContainerName = Guid.NewGuid.ToString.ToUpperInvariant,
    .ProviderType = 1,
    .Flags = CspProviderFlags.UseMachineKeyStore
  }

  oPrimaryRsa = New RSACryptoServiceProvider(oParameters)
  oPrimaryRsa.ImportCspBlob(oSecondaryRsa.ExportCspBlob(True))
  oPrimaryRsa.PersistKeyInCsp = True

  eFlags = X509KeyStorageFlags.Exportable Or X509KeyStorageFlags.PersistKeySet Or X509KeyStorageFlags.UserKeySet
  oCertificate = New X509Certificate2(Certificate, String.Empty, eFlags)

  Return oCertificate.CopyWithPrivateKey(oPrimaryRsa)
End Function
© www.soinside.com 2019 - 2024. All rights reserved.