2016-11-07 3 views
0

У меня проблема с сертификатом из магазина. В моем приложении пользователь может использовать сертификат из файла или сертификата из магазина. После загрузки сертификата я использую сертификат для данных знака.Использование сертификата из магазина для RSACryptoServiceProvider

Использование сертификата из файла в порядке, но я не могу использовать эквивалент из хранилища.

Код для знака:

// Sign data 
using (RSACryptoServiceProvider csp = new RSACryptoServiceProvider()) 
{ 
    byte[] dataToSign = Encoding.UTF8.GetBytes(plainText); 
    csp.ImportParameters(((RSACryptoServiceProvider)_certPopl.PrivateKey).ExportParameters(true)); 
    byte[] signature = csp.SignData(dataToSign, "SHA256"); 
    // Verify signature 
    if (!csp.VerifyData(dataToSign, "SHA256", signature)) 
     throw new Exception("Nepodařilo se vytvořit platný podpisový kód poplatníka."); 
    PKP = Convert.ToBase64String(signature); 
} 

Код сертификата для чтения из файла:

X509Certificate2Collection certStore = new X509Certificate2Collection(); 
certStore.Import(fileName, password, X509KeyStorageFlags.Exportable); 
foreach (X509Certificate2 cert in certStore) 
{ 
    // Find the first certificate with a private key 
    if (cert.HasPrivateKey) 
    { 
     _certPopl = cert; 
     break; 
    } 
} 

Код сертификата для чтения из магазина. После загрузки сертификата из магазина я не могу подписать данные:

public void LoadCertificate(string certificateName, DateTime notAfter, string password) 
{ 
    var store = new X509Store(StoreName.My, StoreLocation.CurrentUser); 
    store.Open(OpenFlags.MaxAllowed); 
    foreach (var certificate in store.Certificates) 
    { 
     if (certificate.FriendlyName.Equals(certificateName) && certificate.NotAfter.Equals(notAfter)) 
     { 
      //X509Certificate2Collection certStore = new X509Certificate2Collection(); 
      //certStore.Import(certificate.Export(X509ContentType.SerializedCert), password, X509KeyStorageFlags.Exportable); 
      //_certPopl = certStore[0]; 

      X509Certificate2Collection certStore = new X509Certificate2Collection(); 
      certStore.Import(certificate.GetRawCertData()); 
      foreach (X509Certificate2 cert in certStore) 
      { 
       // Find the first certificate with a private key 
       if (cert.HasPrivateKey) 
       { 
        _certPopl = cert; 
        break; 
       } 
      } 

      break; 
     } 
    } 
} 

У меня нет опыта работы с сертификатами. Но мне нужен эквивалент получения сертификата из магазина для подписания.

System.Security.Cryptography.CryptographicException выбрано ExportParameters (true). Дополнительная информация об исключении: Ключ не действует для использования в указанном состоянии.

Спасибо.

+0

'Я не могу подписать data' - это не говорит нам ничего полезного. Сообщение об ошибке и фрагмент кода, который вызывает ошибку, будет полезен. – Crypt32

+0

Добавлена ​​информация об исключении: System.Security.Cryptography.CryptographicException выбрано ExportParameters (true). Дополнительная информация об исключении: ключ не действителен для использования в указанном состоянии. –

ответ

0

Я не понимаю, почему вы пытаетесь экспортировать параметры CSP. Экспорт параметров CSP зависит от параметров экспорта ключей и не работает, если ключ не экспортируется. Вместо этого, вы должны использовать RSACryptoServiceProvider непосредственно на PrivateKey свойстве X509Certificate2 объекта:

// assuming, you have X509Certificate2 object with existing private key in _certPol variable 
// retrieve private key 
var key = _certPol.PrivateKey as RSACryptoServiceProvider; 
// check if it is legacy RSA, otherwise return. 
if (key == null) { return; } 
byte[] dataToSign = Encoding.UTF8.GetBytes(plainText); 
// sign data 
byte[] signature = key.SignData(dataToSign, "SHA256"); 
// Verify signature 
if (!key.VerifyData(dataToSign, "SHA256", signature)) 
    throw new Exception("Nepodařilo se vytvořit platný podpisový kód poplatníka."); 
... 
+0

Я получаю System.Security.Cryptography.CryptographicException Дополнительная информация: Указан неверный алгоритм. on byte [] signature = key.SignData (dataToSign, «SHA256»); –

+0

Похоже, что CSP, используемый для хранения ключа, не поддерживает алгоритмы SHA2. – Crypt32

+0

Хорошо, но что я могу сделать с этим? Это тот же сертификат. –

0

Рабочее состояние является:

Загрузка сертификата из магазина:

var store = new X509Store(StoreName.My, StoreLocation.CurrentUser); 
try 
{ 
    store.Open(OpenFlags.ReadOnly); 
    foreach (var certificate in store.Certificates) 
    { 
     if (certificate.FriendlyName.Equals(certificateName) && certificate.NotAfter.Equals(notAfter)) 
     { 
      _certPopl = certificate; 
      break; 
     } 
    } 
} 
finally 
{ 
    store.Close(); 
} 

Войти и проверить данные:

byte[] dataToSign = Encoding.UTF8.GetBytes(plainText); 
var privKey = (RSACryptoServiceProvider)_certPopl.PrivateKey; 
// Force use of the Enhanced RSA and AES Cryptographic Provider with openssl-generated SHA256 keys 
var enhCsp = new RSACryptoServiceProvider().CspKeyContainerInfo; 
var cspparams = new CspParameters(enhCsp.ProviderType, enhCsp.ProviderName, privKey.CspKeyContainerInfo.KeyContainerName); 
privKey = new RSACryptoServiceProvider(cspparams); 
byte[] signature = privKey.SignData(dataToSign, "SHA256"); 
// Verify signature 
if (!privKey.VerifyData(dataToSign, "SHA256", signature)) 
    throw new Exception("Nepodařilo se vytvořit platný podpisový kód poplatníka."); 
0

Если вы можете использовать .NET 4.6 это намного проще, новый способ доступа к закрытым ключам работает более надежно для SHA-2 подписи:

using (RSA rsa = cert.GetRSAPrivateKey()) 
{ 
    if (rsa == null) 
    { 
     throw new Exception("Wasn't an RSA key, or no private key was present"); 
    } 

    bool isValid = rsa.VerifyData(
     Encoding.UTF8.GetBytes(plainText), 
     signature, 
     HashAlgorithmName.SHA256, 
     RSASignaturePadding.Pkcs1); 

    if (!isValid) 
    { 
     throw new Exception("VerifyData failed"); 
    } 
} 
Смежные вопросы