2012-02-13 19 views
9

sto cercando la cosa più semplice - crittografare i dati utilizzando la chiave pubblica e decrittografare utilizzando la chiave privata:crittografia e la decrittografia con RSAServiceProvider in C#

X509Certificate2 cert = new X509Certificate2(@"c:\temp\CERT\mycert.pfx", "test1"); 

    RSACryptoServiceProvider privateKey = cert.PrivateKey as RSACryptoServiceProvider; 
    RSACryptoServiceProvider publicKey = cert.PublicKey.Key as RSACryptoServiceProvider; 

    UnicodeEncoding bytConvertor = new UnicodeEncoding(); 
    byte[] plainData = bytConvertor.GetBytes("Sample data"); 

    byte[] enData = publicKey.Encrypt(plainData, true); 
    Console.WriteLine("Encrypted Output: {0}", bytConvertor.GetString(enData)); 

    byte[] deData = privateKey.Decrypt(enData, true); 
    Console.WriteLine("Decrypted Output: {0}", bytConvertor.GetString(deData)); 

Ma la seconda ultima riga privateKey.Decrypt (...) getta la seguente eccezione:

System.Security.Cryptography.CryptographicException è stata gestita
Messaggio = Bad chiave.

Source=mscorlib StackTrace: 
    at System.Security.Cryptography.CryptographicException.ThrowCryptographicException(Int32 hr) 
    at System.Security.Cryptography.RSACryptoServiceProvider.DecryptKey(SafeKeyHandle 
     pKeyContext, Byte[] pbEncryptedKey, Int32 cbEncryptedKey, Boolean 
     fOAEP, ObjectHandleOnStack ohRetDecryptedKey) 
    at System.Security.Cryptography.RSACryptoServiceProvider.Decrypt(Byte[] 
     rgb, Boolean fOAEP) 
    at ConsoleApplication4.Program.Main(String[] args) in `c:\users\kazia\documents\visual studio` 
     `2010\Projects\ConsoleApplication4\Program.cs`:line 44 ... 

InnerException:

Devo mancare qualcosa di ovvio. Qual è il modo standard per utilizzare la crittografia RSA sia in end (pubblico e privato) utilizzando .NET? Qualsiasi aiuto sarebbe apprezzato.

Grazie!

+0

Sembra che l'istanza RSA 'privateKey' non abbia una chiave privata valida. Non so perché. – CodesInChaos

+2

RSA è * molto * lento rispetto ai cifrari simmetrici. Pertanto, si consiglia di crittografare solo una chiave simmetrica generata in modo casuale con RSA e crittografare il messaggio stesso con quella chiave simmetrica. – CodesInChaos

+0

Ciao, c'è una password per il pfx? – Digvijay

risposta

0

trovato la risposta qui:

http://msdn.microsoft.com/en-us/library/ms148409.aspx

grande esempio:

using System; 
using System.Security.Cryptography; 
using System.Security.Cryptography.X509Certificates; 
using System.IO; 
using System.Text; 

// To run this sample use the Certificate Creation Tool (Makecert.exe) to generate a test X.509 certificate and 
// place it in the local user store. 
// To generate an exchange key and make the key exportable run the following command from a Visual Studio command prompt: 

//makecert -r -pe -n "CN=CERT_SIGN_TEST_CERT" -b 01/01/2010 -e 01/01/2012 -sky exchange -ss my 
namespace X509CertEncrypt 
{ 
    class Program 
    { 

     // Path variables for source, encryption, and 
     // decryption folders. Must end with a backslash. 
     private static string encrFolder = @"C:\Encrypt\"; 
     private static string decrFolder = @"C:\Decrypt\"; 
     private static string originalFile = "TestData.txt"; 
     private static string encryptedFile = "TestData.enc"; 

     static void Main(string[] args) 
     { 

      // Create an input file with test data. 
      StreamWriter sw = File.CreateText(originalFile); 
      sw.WriteLine("Test data to be encrypted"); 
      sw.Close(); 

      // Get the certifcate to use to encrypt the key. 
      X509Certificate2 cert = GetCertificateFromStore("CN=CERT_SIGN_TEST_CERT"); 
      if (cert == null) 
      { 
       Console.WriteLine("Certificatge 'CN=CERT_SIGN_TEST_CERT' not found."); 
       Console.ReadLine(); 
      } 


      // Encrypt the file using the public key from the certificate. 
      EncryptFile(originalFile, (RSACryptoServiceProvider)cert.PublicKey.Key); 

      // Decrypt the file using the private key from the certificate. 
      DecryptFile(encryptedFile, (RSACryptoServiceProvider)cert.PrivateKey); 

      //Display the original data and the decrypted data. 
      Console.WriteLine("Original: {0}", File.ReadAllText(originalFile)); 
      Console.WriteLine("Round Trip: {0}", File.ReadAllText(decrFolder + originalFile)); 
      Console.WriteLine("Press the Enter key to exit."); 
      Console.ReadLine(); 
     } 
     private static X509Certificate2 GetCertificateFromStore(string certName) 
     { 

      // Get the certificate store for the current user. 
      X509Store store = new X509Store(StoreLocation.CurrentUser); 
      try 
      { 
       store.Open(OpenFlags.ReadOnly); 

       // Place all certificates in an X509Certificate2Collection object. 
       X509Certificate2Collection certCollection = store.Certificates; 
       // If using a certificate with a trusted root you do not need to FindByTimeValid, instead: 
       // currentCerts.Find(X509FindType.FindBySubjectDistinguishedName, certName, true); 
       X509Certificate2Collection currentCerts = certCollection.Find(X509FindType.FindByTimeValid, DateTime.Now, false); 
       X509Certificate2Collection signingCert = currentCerts.Find(X509FindType.FindBySubjectDistinguishedName, certName, false); 
       if (signingCert.Count == 0) 
        return null; 
       // Return the first certificate in the collection, has the right name and is current. 
       return signingCert[0]; 
      } 
      finally 
      { 
       store.Close(); 
      } 

     } 

     // Encrypt a file using a public key. 
     private static void EncryptFile(string inFile, RSACryptoServiceProvider rsaPublicKey) 
     { 
      using (AesManaged aesManaged = new AesManaged()) 
      { 
       // Create instance of AesManaged for 
       // symetric encryption of the data. 
       aesManaged.KeySize = 256; 
       aesManaged.BlockSize = 128; 
       aesManaged.Mode = CipherMode.CBC; 
       using (ICryptoTransform transform = aesManaged.CreateEncryptor()) 
       { 
        RSAPKCS1KeyExchangeFormatter keyFormatter = new RSAPKCS1KeyExchangeFormatter(rsaPublicKey); 
        byte[] keyEncrypted = keyFormatter.CreateKeyExchange(aesManaged.Key, aesManaged.GetType()); 

        // Create byte arrays to contain 
        // the length values of the key and IV. 
        byte[] LenK = new byte[4]; 
        byte[] LenIV = new byte[4]; 

        int lKey = keyEncrypted.Length; 
        LenK = BitConverter.GetBytes(lKey); 
        int lIV = aesManaged.IV.Length; 
        LenIV = BitConverter.GetBytes(lIV); 

        // Write the following to the FileStream 
        // for the encrypted file (outFs): 
        // - length of the key 
        // - length of the IV 
        // - ecrypted key 
        // - the IV 
        // - the encrypted cipher content 

        int startFileName = inFile.LastIndexOf("\\") + 1; 
        // Change the file's extension to ".enc" 
        string outFile = encrFolder + inFile.Substring(startFileName, inFile.LastIndexOf(".") - startFileName) + ".enc"; 
        Directory.CreateDirectory(encrFolder); 

        using (FileStream outFs = new FileStream(outFile, FileMode.Create)) 
        { 

         outFs.Write(LenK, 0, 4); 
         outFs.Write(LenIV, 0, 4); 
         outFs.Write(keyEncrypted, 0, lKey); 
         outFs.Write(aesManaged.IV, 0, lIV); 

         // Now write the cipher text using 
         // a CryptoStream for encrypting. 
         using (CryptoStream outStreamEncrypted = new CryptoStream(outFs, transform, CryptoStreamMode.Write)) 
         { 

          // By encrypting a chunk at 
          // a time, you can save memory 
          // and accommodate large files. 
          int count = 0; 
          int offset = 0; 

          // blockSizeBytes can be any arbitrary size. 
          int blockSizeBytes = aesManaged.BlockSize/8; 
          byte[] data = new byte[blockSizeBytes]; 
          int bytesRead = 0; 

          using (FileStream inFs = new FileStream(inFile, FileMode.Open)) 
          { 
           do 
           { 
            count = inFs.Read(data, 0, blockSizeBytes); 
            offset += count; 
            outStreamEncrypted.Write(data, 0, count); 
            bytesRead += blockSizeBytes; 
           } 
           while (count > 0); 
           inFs.Close(); 
          } 
          outStreamEncrypted.FlushFinalBlock(); 
          outStreamEncrypted.Close(); 
         } 
         outFs.Close(); 
        } 
       } 
      } 
     } 


     // Decrypt a file using a private key. 
     private static void DecryptFile(string inFile, RSACryptoServiceProvider rsaPrivateKey) 
     { 

      // Create instance of AesManaged for 
      // symetric decryption of the data. 
      using (AesManaged aesManaged = new AesManaged()) 
      { 
       aesManaged.KeySize = 256; 
       aesManaged.BlockSize = 128; 
       aesManaged.Mode = CipherMode.CBC; 

       // Create byte arrays to get the length of 
       // the encrypted key and IV. 
       // These values were stored as 4 bytes each 
       // at the beginning of the encrypted package. 
       byte[] LenK = new byte[4]; 
       byte[] LenIV = new byte[4]; 

       // Consruct the file name for the decrypted file. 
       string outFile = decrFolder + inFile.Substring(0, inFile.LastIndexOf(".")) + ".txt"; 

       // Use FileStream objects to read the encrypted 
       // file (inFs) and save the decrypted file (outFs). 
       using (FileStream inFs = new FileStream(encrFolder + inFile, FileMode.Open)) 
       { 

        inFs.Seek(0, SeekOrigin.Begin); 
        inFs.Seek(0, SeekOrigin.Begin); 
        inFs.Read(LenK, 0, 3); 
        inFs.Seek(4, SeekOrigin.Begin); 
        inFs.Read(LenIV, 0, 3); 

        // Convert the lengths to integer values. 
        int lenK = BitConverter.ToInt32(LenK, 0); 
        int lenIV = BitConverter.ToInt32(LenIV, 0); 

        // Determine the start postition of 
        // the ciphter text (startC) 
        // and its length(lenC). 
        int startC = lenK + lenIV + 8; 
        int lenC = (int)inFs.Length - startC; 

        // Create the byte arrays for 
        // the encrypted AesManaged key, 
        // the IV, and the cipher text. 
        byte[] KeyEncrypted = new byte[lenK]; 
        byte[] IV = new byte[lenIV]; 

        // Extract the key and IV 
        // starting from index 8 
        // after the length values. 
        inFs.Seek(8, SeekOrigin.Begin); 
        inFs.Read(KeyEncrypted, 0, lenK); 
        inFs.Seek(8 + lenK, SeekOrigin.Begin); 
        inFs.Read(IV, 0, lenIV); 
        Directory.CreateDirectory(decrFolder); 
        // Use RSACryptoServiceProvider 
        // to decrypt the AesManaged key. 
        byte[] KeyDecrypted = rsaPrivateKey.Decrypt(KeyEncrypted, false); 

        // Decrypt the key. 
        using (ICryptoTransform transform = aesManaged.CreateDecryptor(KeyDecrypted, IV)) 
        { 

         // Decrypt the cipher text from 
         // from the FileSteam of the encrypted 
         // file (inFs) into the FileStream 
         // for the decrypted file (outFs). 
         using (FileStream outFs = new FileStream(outFile, FileMode.Create)) 
         { 

          int count = 0; 
          int offset = 0; 

          int blockSizeBytes = aesManaged.BlockSize/8; 
          byte[] data = new byte[blockSizeBytes]; 

          // By decrypting a chunk a time, 
          // you can save memory and 
          // accommodate large files. 

          // Start at the beginning 
          // of the cipher text. 
          inFs.Seek(startC, SeekOrigin.Begin); 
          using (CryptoStream outStreamDecrypted = new CryptoStream(outFs, transform, CryptoStreamMode.Write)) 
          { 
           do 
           { 
            count = inFs.Read(data, 0, blockSizeBytes); 
            offset += count; 
            outStreamDecrypted.Write(data, 0, count); 

           } 
           while (count > 0); 

           outStreamDecrypted.FlushFinalBlock(); 
           outStreamDecrypted.Close(); 
          } 
          outFs.Close(); 
         } 
         inFs.Close(); 
        } 

       } 

      } 
     } 

    } 
} 
+0

Ciao kalrashi, grazie per aver segnalato la risposta, ma potresti indicare quale parte del codice contiene la risposta per te? O hai sostituito il codice completo? –

+0

In 'DecryptFile', perché stai cercando il doppio all'inizio? Perché stai leggendo solo 3 byte per la lunghezza anziché 4? potresti evitare una ricerca se leggi 4 byte. – cube45

0

Niente di sbagliato con il codice, l'unica cosa che deve cambiare è il modo in cui è stata generata la coppia di chiavi . Nella risposta:

//makecert -r -pe -n "CN=CERT_SIGN_TEST_CERT" -b 01/01/2010 -e 01/01/2012 -sky exchange -ss my 

La parte rilevante è -Sky scambio, che probabilmente è stato omesso dalla chiamata alla Makecert.exe quando segnalato prima l'errore "Bad tasti" a Decrypt.

Problemi correlati