Мой экспортируемый закрытый ключ нельзя экспортировать


Примечание. Ответ может быть получен либо на VB.NET, либо на C#. У меня нет предпочтений в отношении этих вопросов и ответов.


Я использую приведенный ниже код на основе Certes и Bouncy Castle для завершения, создания и импорта сертификата TLS Let's Encrypt в мое хранилище CurrentUser. Проблема в том, что, хотя я помечаю закрытый ключ как экспортируемый, он не найден в полученном сертификате.

Как мы видим, возможность экспорта закрытого ключа отключена, хотя в магазине указано, что ключ присутствует.

Я проработал этот пример, и код, кажется, делает почти то же самое, что и мой. Единственное заметное отличие заключается в том, что он загружает 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
Как установить LAMP Stack - Security 5/5 на виртуальную машину Azure Linux VM
Как установить LAMP Stack - Security 5/5 на виртуальную машину Azure Linux VM
В предыдущей статье мы завершили установку базы данных, для тех, кто не знает.
1
0
67
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

После долгого сбора фрагментов из различных источников (слишком много, чтобы их можно было запомнить) я пришел к следующему. Он не включает в себя так много вещей из «Надувного замка», но он работает.

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

Другие вопросы по теме