2016-11-07 1 views
0

J'ai un problème avec le certificat du magasin. Dans mon application, l'utilisateur peut utiliser le certificat du fichier ou le certificat du magasin. Après le chargement du certificat, j'utilise un certificat pour les données de signe.Utilisation du certificat du magasin pour RSACryptoServiceProvider

L'utilisation du certificat du fichier est OK, mais je ne peux pas utiliser l'équivalent du magasin.

Code pour signe:

// 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); 
} 

Code pour le certificat de lecture du fichier:

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; 
    } 
} 

Code pour le certificat de lecture du magasin. Après le certificat de chargement du magasin, je suis incapable de signer des données:

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; 
     } 
    } 
} 

Je n'ai aucune expérience dans l'utilisation des certificats. Mais j'ai besoin d'équivalent d'obtenir un certificat du magasin pour la signature.

System.Security.Cryptography.CryptographicException est lancé sur ExportParameters (true). Informations supplémentaires sur Exception: Clé non valide pour une utilisation dans un état spécifié.

Merci.

+0

'Je suis incapable de signer data' - cela ne nous dit pas quelque chose d'utile. Un message d'erreur et un élément de code qui déclenche l'erreur seraient utiles. – Crypt32

+0

Ajout d'informations sur exception: System.Security.Cryptography.CryptographicException est lancé sur ExportParameters (true). Informations supplémentaires sur Exception: La clé n'est pas valide pour une utilisation dans un état spécifié. –

Répondre

0

Je ne comprends pas clairement pourquoi vous essayez d'exporter des paramètres CSP. L'exportation des paramètres CSP dépend des options d'exportation clés et échouera si la clé est non exportable. Au lieu de cela, vous devez utiliser RSACryptoServiceProvider directement sur PrivateKey propriété du X509Certificate2 objet:

// 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

Je reçois System.Security.Cryptography.CryptographicException Informations supplémentaires: Algorithme non valide spécifié. sur byte [] signature = key.SignData (dataToSign, "SHA256"); –

+0

Il semble que CSP utilisé pour stocker la clé ne supporte pas les algorithmes SHA2. – Crypt32

+0

OK, mais que puis-je faire avec ça? C'est le même certificat. –

0

état de fonctionnement est le suivant:

certificat de chargement du magasin:

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(); 
} 

Signer et vérifier les données:

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

Si vous pouvez utiliser .NET 4.6 ceci est beaucoup plus simple, la nouvelle façon d'accéder à des clés privées fonctionne beaucoup plus fiable pour les signatures 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"); 
    } 
}