2011-01-28 43 views
1

我們正在嘗試在我們的XP SP2計算機(Win7以後)上爲我們的C#(.net 3.5)應用程序執行此操作。意外的CryptographicException:鍵集不存在AND CryptographicException:訪問被拒絕

在我們的安裝程序(由VS2008創建)中,我們使用AES key和iv加密連接字符串,然後創建RSA key-pair並將它們存儲在MachineKeyStore中。安裝程序將使用RSA public key加密AES密鑰和iv,並使用加密連接字符串存儲加密密鑰和iv。

安裝完成後,我們的應用程序讀取與加密AES密鑰加密的連接字符串和四回,並使用RSA private key(從MachineKeyStore)解密AES密鑰和IV,然後與AES密鑰來解密連接字符串和IV。

安裝程序和我們的應用程序共享constant string,container nameMachineKeyStore

我知道密鑰對的存儲位置,所以我可以監視它以查看密鑰對是否被刪除,更新或創建。

我做了一些測試,發現了一些有趣的事情(意外),但不知道爲什麼它是這樣的。我的用戶帳戶是管理員帳戶。

  1. 安裝程序可以刪除我們的應用程序創建的存儲key-pair並立即創建具有相同容器名稱一個新的;
  2. 安裝程序可以更新由我們的應用程序創建key-pair(不要刪除並重新創建,它被覆蓋,我認爲 - 但根據文檔這不應該發生)
  3. 我們的應用程序無法刪除由創建密鑰對安裝程序:CryptographicException: Keyset does not exist.當密鑰對實際存在時會發生異常; CryptographicException: Keyset does not exist.
  4. 我們的應用程序不能訪問由安裝程序創建的密鑰對, CryptographicException: Access is denied.將在這種情況下發生:當安裝程序創建的密鑰對有
  5. 我們的應用程序不能創建一個新的。安裝程序中的加密適用於AESRSA public key。當應用程序嘗試使用存儲的private key進行解密時,將發生「Access is denied」異常。

我們的代碼如下:

public static void CreateRSAKeyPair(string keyContainerName) 
     { 
      DeleteRSAKeyPair(keyContainerName); 

      CspParameters cspParams = new CspParameters(); 
      cspParams.KeyContainerName = keyContainerName; 
      cspParams.Flags |= CspProviderFlags.UseMachineKeyStore; 

      using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(cspParams)) 
      { 
       rsa.PersistKeyInCsp = false; 
      } 
     } 



public static void DeleteRSAKeyPair(string keyContainerName) 
     { 
      CspParameters cspParams = new CspParameters(); 
      cspParams.KeyContainerName = keyContainerName; 
      cspParams.Flags |= CspProviderFlags.UseMachineKeyStore; 

      using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(cspParams)) 
      { 
       rsa.PersistKeyInCsp = false; 
       try 
       { 
        rsa.Clear(); 
       } 
       catch (CryptographicException ex) 
       { 
        Log.logItem(LogType.Exception, "RSA key clear error, can be ignored", "SecurityMgr::DeleteRSAKeyPair()", "CryptographicException msg=" + ex.ToString()); 
       } 
      } 
     } 

代碼訪問private key解密:

private static byte[] RSADecrypt(byte[] inputData, string keyContainerName) 
     { 
      byte[] resultData = null; 
      try 
      { 
       CspParameters cspParams = new CspParameters(); 
       cspParams.Flags |= CspProviderFlags.UseMachineKeyStore; 
       cspParams.KeyContainerName = keyContainerName; 
       using (RSACryptoServiceProvider rsaProvider = new RSACryptoServiceProvider(cspParams)) 
       { 
        //rsaProvider.PersistKeyInCsp = true; 
        //private key 
        RSAParameters rsaParams = rsaProvider.ExportParameters(true); 
        rsaProvider.ImportParameters(rsaParams); 
        resultData = rsaProvider.Decrypt(inputData, false); 
       } 
      } 
      catch (CryptographicException ex) 
      { 
       string msg = "CryptographicException: keyContainerName=" + keyContainerName + "\nmsg=" + ex.ToString(); 
       Log.logItem(LogType.Exception, "RSA decryption exception", "SecurityMgr::RSADecrypt()", msg); 
      } 
      return resultData; 
     } 

能RSA非對稱加密這樣被使用?

編輯:

這樣做對我們的應用程序中的連接字符串同樣的事情(使用AES和RSA加密)(不涉及安裝程序)工作正常。

回答

2

實際的問題不是很清楚。但是,我在您的代碼中看到一些內容:

  • 您將密鑰對(私有和公共)從提供程序導出到參數中。人們對布爾參數感到困惑。 IT並不意味着它只輸出私鑰。如果將其設置爲true(導出私鑰),則將導出PUBLIC和PRIVATE密鑰。
  • 您從RSA提供程序實例導出的相同密鑰將導入到相同的提供程序中。這沒有任何意義。
  • 刪除ExportParameters和ImportParameters行,它們什麼都不做。如果您在構造函數中指定的容器名稱有效且存在,則您的密鑰應該已經存放在RSA提供程序中。
  • 使用非對稱密碼術,您可以使用PRIVATE密鑰進行加密,因爲您不共享密鑰。然後您使用PUBLIC密鑰解密,因爲另一方(接收方)應該只保留您的PUBLIC密鑰才能解密。如果他們擁有私人密鑰,整個計劃就會受到影響。
+0

對於任何仍在閱讀此內容的人來說,在技術上** ** public ** ** ** private **(使用public加密,使用private解密)稱爲* encryption *,用於加密單個目標誰可以解密它。反過程(** private **> ** public **)被稱爲*簽名*,它驗證源的身份(因爲只有他們可以「加密」它),但公鑰(即任何人)都可以「解密」(驗證)它。只是安全模型中的語義,但重要的區別。 – Katstevens 2016-10-05 02:52:52