Извлечь закрытый ключ из файла pfx или хранилища сертификатов БЕЗ использования OpenSSL в Windows

Как следует из названия, я хотел бы экспортировать свой закрытый ключ без использования OpenSSL или любого другого стороннего инструмента. Если мне нужен .cer файл или .pfx файл, я могу легко экспортировать их через MMC или PowerShell pkiclient, но я не могу найти способ получить закрытый ключ.

https://docs.microsoft.com/en-us/powershell/module/pkiclient/export-certificate?view=win10-ps

Используя онлайн-инструмент, например https://www.sslshopper.com/ssl-converter.html это не нормально.

PS Версия:

PS C:\Users\oscar> $PSVersionTable

Name                           Value
----                           -----
PSVersion                      5.1.17134.228
PSEdition                      Desktop
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}
BuildVersion                   10.0.17134.228
CLRVersion                     4.0.30319.42000
WSManStackVersion              3.0
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1

Я могу получить открытый ключ так:

(Get-PfxCertificate -FilePath C:\Users\oscar\Desktop\localhost.pfx).GetPublicKey()

И экспортируйте весь сертификат следующим образом:

(Get-PfxCertificate -FilePath C:\Users\oscar\Desktop\localhost.pfx).GetRawCertData()

Результат от

PS C:\Users\oscar> $mypwd = ConvertTo-SecureString -String "MyPassword" -Force -AsPlainText
PS C:\Users\oscar> $mypfx = Get-PfxData -FilePath C:\Users\oscar\Desktop\localhost.pfx -Password $mypwd
PS C:\Users\oscar> $mypfx

OtherCertificates EndEntityCertificates
----------------- ---------------------
{}                {[Subject]...


PS C:\Users\oscar> $mypfx.EndEntityCertificates

Thumbprint                                Subject
----------                                -------
8ED4971564E35099D6DB490C3756E2AD43AAAAAA  CN=localhost

Протестировал команду от @Brad, но я получил ошибку ниже.

Закрытый ключ НЕ экспортируется в виде обычного текста

certutil -exportPFX -p "myPassword" -privatekey -user my <Certificate Serial Number> C:\localhost.pfx

введите описание изображения здесь

Подобно мастеру экспорта сертификатов в сертификатах MMC, экспорт доступен только в .pfx, если включен ключ.

введите описание изображения здесь


person Ogglas    schedule 22.10.2018    source источник
comment
Вам определенно понадобится .pfx файл, поскольку .cer файлы не хранят закрытые ключи. Какой у тебя $PSVersionTable? Вы можете использовать Get-PfxData -FilePath 'mycertificate.pfx' -Password (ConvertTo-SecureString -Force -AsPlainText -String 'MyClearTextPassword')?   -  person Petru Zaharia    schedule 23.10.2018
comment
@PetruZaharia Да я в курсе, написал это как пример того, что можно экспортировать. :) Обновил вопрос с PSVersion и тем, что я пробовал. Я могу, но не могу экспортировать закрытый ключ.   -  person Ogglas    schedule 23.10.2018


Ответы (7)


У меня была такая же проблема, и я решил ее с помощью модуля PSPKI Powershell из PS Галерея. Хотя я понимаю, что вы ищете решение, которое предпочтительно использует некоторые встроенные функции Windows, установка модуля из PS Gallery может быть приемлемой. По крайней мере, так было в моем случае.

Сначала установите модуль PSPKI (я предполагаю, что репозиторий PSGallery уже настроен):

Install-Module -Name PSPKI

Модуль PSPKI предоставляет командлет Convert-PfxToPem, который преобразует pfx-файл в pem-файл, который содержит сертификат и ключ pirvate в виде текста в кодировке base64:

Convert-PfxToPem -InputFile C:\path\to\pfx\file.pfx -Outputfile C:\path\to\pem\file.pem

Теперь все, что нам нужно сделать, это разделить pem-файл с помощью некоторой магии регулярных выражений. Например, вот так:

(Get-Content C:\path\to\pem\file.pem -Raw) -match "(?ms)(\s*((?<privatekey>-----BEGIN PRIVATE KEY-----.*?-
----END PRIVATE KEY-----)|(?<certificate>-----BEGIN CERTIFICATE-----.*?-----END CERTIFICATE-----))\s*){2}"

$Matches["privatekey"] | Set-Content "C:\path\to\key\file.pem"
$Matches["certificate"] | Set-Content "C:\path\to\certificate\file.pem"
person Christoph Böhme    schedule 03.11.2020
comment
Хороший ответ, но я бы предпочел не использовать стороннюю библиотеку, как вы говорите. Однако, поскольку это пока лучший ответ, я буду отмечать его как принятый, пока не будет лучшей альтернативы. :) - person Ogglas; 03.11.2020
comment
Я добавил сценарий PowerShell, который включает подход .NET к экспорту закрытого ключа в файл PEM Pkcs8. Я также хочу отметить, что PSPKI Convert-PfxToPem очень низкий уровень; использование PInvoke для вызова методов Win32. Поскольку .NET добавила поддержку CNG (Crypto Next Gen), у нас есть все необходимые возможности через пространство имен System.Security.Cryptography. - person RashadRivera; 21.07.2021

Если я правильно понимаю, certutil должен сделать это за вас.

certutil -exportPFX -p "ThePasswordToKeyonPFXFile" my [serialNumberOfCert] [fileNameOfPFx]

person Brad    schedule 31.08.2019
comment
Выглядело неплохо, но даже несмотря на то, что помощник сказал Export certificate and private key, я получил сообщение Private key is NOT plain text exportable. Я мог экспортировать только в .pfx. См. Обновленный вопрос для экрана печати. - person Ogglas; 27.08.2020

Ключ, когда его можно экспортировать, можно экспортировать с помощью нескольких API в несколько форматов. Наиболее распространенными будут PKCS # 8 (отраслевой стандарт) и XML (собственно MSFT afaik).

Взгляните на эти ответы:

person Daniel Fisher lennybacon    schedule 15.06.2020
comment
Хороший ответ, но я бы предпочел использовать какую-то встроенную утилиту Windows и не писать свою собственную программу для ее решения. - person Ogglas; 02.09.2020

Попробуйте что-то вроде этого:

$mypwd = ConvertTo-SecureString -String "MyPassword" -Force -AsPlainText
$mypfx = Get-PfxData -FilePath C:\Users\oscar\Desktop\localhost.pfx -Password $mypwd
Export-PfxCertificate -PFXData $mypfx -FilePath C:\Users\oscar\Desktop\localhost.pfx -Password $NewPwd
person Mike Kennedy    schedule 24.06.2020
comment
Export-PfxCertificate - экспортирует сертификат или объект PFXData в файл обмена личной информацией (PFX). Мне нужен только закрытый ключ. docs.microsoft.com/en- нас / powershell / модуль / pkiclient / - person Ogglas; 27.08.2020

Хм. Вы пробовали открыть хранилище сертификатов и таким образом получить закрытый ключ? Вполне уверен, что это будет работать только с сертификатами RSA / DSA.

$store = New-Object System.Security.Cryptography.X509Certificates.X509Store([System.Security.Cryptography.X509Certificates.StoreName]::My,"localmachine")
$store.Open("MaxAllowed")
$cert = $store.Certificates | ?{$_.subject -match "^CN=asdasd"}
$cert.PrivateKey.ToXmlString($false)
$store.Close()

person PowerShellGuy    schedule 23.10.2020
comment
Я получил из этого ценность, но ее нужно изменить. Результат вашего кода: <RSAKeyValue><Modulus>base64 value</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>. Однако с $cert.PrivateKey.ToXmlString(1), а затем преобразовав это с помощью RSA Key Converter - XML ​​в PEM, я получаю закрытый ключ в base64. Однако я не нашел способа сделать это с помощью встроенной утилиты Windows. - person Ogglas; 03.11.2020

На основании того, что упомянул PowerShellGuy.

Это сработает для вас?

# first get your cert, either via pure .NET, or through the PSDrive (Cert:\)

# this is just an example

# get cert from PSDrive
$cert = Get-ChildItem Cert:\LocalMachine\My | where Subject -eq 'CN=MySubject'

# get cert from .NET
$My     = [System.Security.Cryptography.X509Certificates.StoreName]::My
$Store  = [System.Security.Cryptography.X509Certificates.X509Store]::new($My,'localmachine')
$Store.Open([System.Security.Cryptography.X509Certificates.OpenFlags]::MaxAllowed)

$cert   = $Store.Certificates | where Subject -eq 'CN=MySubject'

# get private key
# PKCS8, way #1
$BytesPkcs8 = $cert.PrivateKey.ExportPkcs8PrivateKey()
[System.Convert]::ToBase64String($BytesPkcs8)

# PKCS8, way #2
$Pkcs = [System.Security.Cryptography.CngKeyBlobFormat]::Pkcs8PrivateBlob
$BytesPkcs8 = $cert.PrivateKey.Key.Export($Pkcs)
[System.Convert]::ToBase64String($BytesPkcs8)

# RSA
$BytesRsa = $cert.PrivateKey.ExportRSAPrivateKey()
[System.Convert]::ToBase64String($BytesRsa)

Так эта строка Base64 то, что вы ищете?

person Panos.G    schedule 05.06.2021

Попробуйте этот скрипт, который экспортирует закрытый ключ в формате Pkcs8.

Azure PowerShell - извлечение PEM из SSL-сертификата

person RashadRivera    schedule 21.07.2021