2016-04-19 3 views
2

Я пытаюсь работать с сертификатом X509, который был первоначально импортирован в хранилище ключей CurrentUser на компьютере под управлением Windows 10 с помощью оснастки «Сертификаты» в MMC. Такая же процедура была протестирована на компьютере под управлением Windows 8.1 с таким же результатом..NET Framework x509Certificate2 Class, HasPrivateKey == true && PrivateKey == null?

Используя стандартный модуль PowerShell PKI, я получаю объект X509Certificate2 с помощью Get-Item:

$my_cert = Get-Item Cert:\CurrentUser\My\ADAA82188A17THUMBPRINTXXXXXXXXXXX 

Выход $my_cert | fl * выглядит следующим образом:

PSPath     : Microsoft.PowerShell.Security\Certificate::CurrentUser\My\XXXXXXXXXXXXXXXXXXX 
PSParentPath    : Microsoft.PowerShell.Security\Certificate::CurrentUser\My 
PSChildName    : XXXXXXXXXXXXXXXXXXX 
PSDrive     : Cert 
PSProvider    : Microsoft.PowerShell.Security\Certificate 
PSIsContainer   : False 
EnhancedKeyUsageList  : {Secure Email (1.3.6.1.5.5.7.3.4), IP security user (1.3.6.1.5.5.7.3.7), Encrypting File 
          System (1.3.6.1.4.1.311.10.3.4), Document Signing (1.3.6.1.4.1.311.10.3.12)...} 
DnsNameList    : {My Name} 
SendAsTrustedIssuer  : False 
EnrollmentPolicyEndPoint : Microsoft.CertificateServices.Commands.EnrollmentEndPointProperty 
EnrollmentServerEndPoint : Microsoft.CertificateServices.Commands.EnrollmentEndPointProperty 
PolicyId     : {D52C406F-C279-4BF2-B7C2-EE704290DB3E} 
Archived     : False 
Extensions    : {System.Security.Cryptography.Oid, System.Security.Cryptography.Oid, 
          System.Security.Cryptography.Oid, System.Security.Cryptography.Oid...} 
FriendlyName    : 
IssuerName    : System.Security.Cryptography.X509Certificates.X500DistinguishedName 
NotAfter     : 4/15/2017 2:15:16 PM 
NotBefore    : 4/15/2016 2:15:16 PM 
HasPrivateKey   : True 
PrivateKey    : 
PublicKey    : System.Security.Cryptography.X509Certificates.PublicKey 
RawData     : {56, 130, 19, 252...} 
SerialNumber    : 4F0000002F700000000000000000000000 
SubjectName    : System.Security.Cryptography.X509Certificates.X500DistinguishedName 
SignatureAlgorithm  : System.Security.Cryptography.Oid 
Thumbprint    : XXXXXXXXXXXXXXXXXXX 
Version     : 3 
Handle     : 2241663016272 
Issuer     : CN=Issuing CA, DC=My, DC=Domain, DC=us 
Subject     : [email protected], CN=My Name 

So HasPrivateKey == Правда , но PrivateKey == null. Я пытался выяснить, как получить доступ к закрытому ключу для выполнения шифрования и дешифрования. Примеры, которые я видел в Интернете, похоже, указывают на то, что свойство PrivateKey класса X509Certificate2 должно быть легко доступно, но, видимо, я что-то пропустил.

Здесь я читал похожие вопросы, такие как Empty PrivateKey in x509certificate2, но ни один из них не может решить мою проблему. Я также прочитал Eight tips for working with X.509 certificates in .NET Пол Стовелл, который был очень поучительным, но в конечном счете не помог. Это действительно помогало мне убедиться, что закрытый ключ существует в правильном месте, и, насколько я могу судить, с правильными разрешениями ссылаться на класс X509Certificate2:

C:\Users\My.Name\AppData\Roaming\Microsoft\SystemCertificates\My\Keys 

Имя файла ключа совпадает с Идентификатор ключевого слова в сертификате.

Edit:

Выход certutil -user -store my "Serial Number" является:

Serial Number: 4f000000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 
Issuer: CN=Issuing CA, DC=My, DC=Domain, DC=us 
NotBefore: 4/15/2016 2:15 PM 
NotAfter: 4/15/2017 2:15 PM 
Subject: [email protected], CN=My Name 
Non-root Certificate 
Template: Userv1, User v1 
Cert Hash(sha1): ad ab 82 18 8a 17 4d 75 11 04 48 7c 43 43 d4 05 b9 74 c8 4c 
    Key Container = te-Userv1-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx 
    Unique container name: fcbba1aa0xxxxxxxxxxxxxxxxxxxxxxx_xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx 
    Provider = Microsoft Software Key Storage Provider 
Encryption test passed 
CertUtil: -store command completed successfully. 

Что "ключ" часть информации я здесь отсутствует? Почему не секретный ключ удобно ссылается на объект X509Certificate2? Как я могу получить к нему доступ?

+0

Попробуйте '$ my_cert.get_PrivateKey()'. имеет он вызывает любое исключение? – PetSerAl

+0

@PetSerAl, я получаю исключение - «Неверный тип провайдера указан». –

ответ

4

Это может указывать на одно из следующих действий:

1) закрытый ключ хранится в поставщике хранения ключей (а не поставщиком услуг устаревших криптографических), который плохо поддерживается .NET и не поддерживается PrivateKey свойством X509Certificate2 класс на всех. Вы можете проверить это, выполнив следующую команду:

certutil -user -store my "<CertSerialNumber>" 

2) отсутствует закрытый ключ.

HasPrivateKey Недвижимость не обязательно отражает фактическое изображение и может True для несуществующих ключей или False для существующих ключей. Запустите команду certutil, чтобы убедиться, что ключ представлен.

В случае, если закрытый ключ представлен, но привязки сломаны, вы можете попытаться восстановить привязки, выполнив следующую команду:

certutil -user -repairstore my "<CertSerialNumber>" 
+0

Я добавил вывод CertUtil к своему первоначальному сообщению. Похоже, вы правы - закрытый ключ хранится хранилище ключей Провайдер (KSP). Сейчас я ищу хорошие примеры работы с ключами KSP и CNG. Знаете ли вы о каких-либо? –

+0

Что именно вам нужно? – Crypt32

+0

Думаю, мне ничего не нужно. Я просто искал ярлык для понимания на примерах, но мне удалось взломать его вместе ... Спасибо за вашу помощь в этом! –

3

Вашего Certutil информация показывает Provider = Microsoft Software Key Storage Provider что означает, что закрытый ключ хранящийся под Windows CNG, вместо Windows CryptoAPI (CAPI).

.NET 4.6 добавлен метод GetRSAPrivateKey (расширение), чтобы облегчить изменение в противном случае, если свойство PrivateKey возвращает то, что не было RSACryptoServiceProvider (или DSACryptoServiceProvider). Если у вас есть доступ к этому методу (я не уверен, какая версия Framework PowerShell использует), тогда это решит вашу проблему.

Две вещей, чтобы быть в курсе, хотя:

  1. GetRSAPrivateKey возвращает уникальный Одноразовый объект каждый раз. Вы должны поместить его в оператор using/вручную вызвать Dispose, когда закончите с ним (в отличие от cert.PrivateKey, который не является уникальным, поэтому не следует удалять).
  2. Знаки/проверки // методы шифрования/дешифрования переместились в базовый класс RSA (albiet с несколько разными, более перспективными сигнатурами).
2

Я решил проблему.

По какой-то причине .NET framework не может импортировать секретные ключи из файлов, однако он может импортироваться из встроенного хранилища окон, это связано с тем, что метод PrivateKey поддерживает только ключи RSA и DSA для Microsoft Spec: прочитайте примечания в разделе «Примечания».

В любом случае, чтобы получить PrivateKey объект, чтобы вернуть ключ информации, Вам нужно сделать следующее:

1) Импорт файла P12 в Windows, хранилище ключей, дважды щелкнув по нему. 2) Выберите "Импорт", когда будет предложено в "Current User" 3) Убедитесь, что выбран "Make Key экспортируемый",

, если эта опция не доступна, то ваш сертификат не имеет собственной ключ

. 4) Выберите «Автоматически поместить в магазин»

5) Напишите следующий код для получения сертификата:

Dim CertDataInfo As System.Security.Cryptography.X509Certificates.X509Certificate2 
Dim Store As New System.Security.Cryptography.X509Certificates.X509Store("MY", Security.Cryptography.X509Certificates.StoreLocation.CurrentUser) 

Store.Open(Security.Cryptography.X509Certificates.OpenFlags.ReadOnly) 
Console.writeline (Store.Certificates.Count) 

For I = 0 To Store.Certificates.Count - 1 
If Store.Certificates.Item(I).FriendlyName = "Heider Sati's Cert(48F57XTHVE)" Then 
    CertDataInfo = Store.Certificates.Item(I) 
End If 

Console.writeline ("Cert: " & Store.Certificates.Item(I).FriendlyName) 

Next 
Store.Close() 

If CertDataInfo.PrivateKey Is Nothing Then 
MsgBox("NULL") 
Else 
MsgBox("YES") 
End If 

6) Выполнить код, если вы получаете ДА, то закрытый ключ не NULL (или НИЧЕГО), и это то, что вы ищете.

Если вы загружаете тот же сертификат непосредственно из файла, закрытый ключ всегда будет НИЧЕГО/НУЛЛ, но HasPrivateKey скажет ДА, что означает (я знаю, что есть ключ, но все же я не знаю как понять его. Когда вы импортировать его в хранилище Windows, то Windows, это перевести его в .NET-совместимый формат.

Я надеюсь, что это помогает.