2012-06-29 31 views
0

我正在開發使用.NET3.5(C#)的Winforms應用程序。爲了保護應用程序,我使用了一個Xml文件,該文件應該使用不對稱密鑰進行加密。解密XML文件與不對稱關鍵窗口窗體和窗口服務

現在,我的應用程序有兩部分,windows窗體部分和windows服務部分(誰檢查應用程序的真實性)。所以,我的文件將被這兩部分加密/解密。這就是問題出現的地方。當勝利表單部分嘗試解密已由服務創建的文件時,會發生異常(不正確的數據)。這裏是我的代碼:

private readonly static string containerName = "ENC_XML_ASY_KEY"; 
private readonly static string keyName = "keyName"; 

public static void EncryptXmlFile(this XmlDocument doc, string elemToEncryptName) 
    { 
     if (doc == null) 
      return; 

     var cspParams = new CspParameters() { KeyContainerName = containerName }; 
     var rsaKey = new RSACryptoServiceProvider(cspParams); 

     var elementToEncrypt = doc.GetElementsByTagName(elemToEncryptName)[0] as XmlElement; 
     if (elementToEncrypt == null) 
      return; 

     // Create a 256 bit Rijndael key. 
     var sessionKey = new RijndaelManaged() { KeySize = 256 }; 

     var eXml = new EncryptedXml(); 
     byte[] encryptedElement = eXml.EncryptData(elementToEncrypt, sessionKey, false); 


     var edElement = new EncryptedData() 
     { 
      Type = EncryptedXml.XmlEncElementUrl, 
      Id = "XmlID", 
      EncryptionMethod = new EncryptionMethod(EncryptedXml.XmlEncAES256Url) 
     }; 

     var ek = new EncryptedKey(); 
     var encryptedKey = EncryptedXml.EncryptKey(sessionKey.Key, rsaKey, false); 

     ek.CipherData = new CipherData(encryptedKey); 
     ek.EncryptionMethod = new EncryptionMethod(EncryptedXml.XmlEncRSA15Url); 
     edElement.KeyInfo.AddClause(new KeyInfoEncryptedKey(ek)); 

     // Create a new KeyInfoName element. 
     var kin = new KeyInfoName() { Value = keyName }; 

     // Add the KeyInfoName element to the encryptedKey object. 
     ek.KeyInfo.AddClause(kin); 
     edElement.CipherData.CipherValue = encryptedElement; 
     EncryptedXml.ReplaceElement(elementToEncrypt, edElement, false); 

    } 

public static void DecryptXmlFile(this XmlDocument doc) 
    { 
     if (doc == null) 
      return; 

     var cspParams = new CspParameters() { KeyContainerName = containerName }; 
     var rsaKey = new RSACryptoServiceProvider(cspParams); 

     var exml = new EncryptedXml(doc); 
     exml.AddKeyNameMapping(keyName, rsaKey); 
     exml.DecryptDocument(); 
    } 

預先感謝您

+0

執行服務和客戶端應用程序運行相同的用戶帳戶? – Iridium

+0

不,但不是用於啓用甚至通過不同機器加密/解密xml文件的非對稱加密?這是我的祕密(該文件可以通過不同的機器進行加密/解密) – SidAhmed

+0

是的,但是您正在創建一個新的密鑰,並將其存儲在用戶的密鑰存儲區中。因此,其他用戶無法訪問該密鑰來執行解密。 – Iridium

回答

1

您曾表示,該服務端和客戶端下運行的賬戶是不同的,這就解釋了爲什麼它不工作 - 除非另行指定,按鍵是在用戶自己的密鑰存儲區中創建的,而其他用戶無權訪問該存儲區。

你需要,而不是建立在計算機存儲的關鍵,授予其他用戶(S)訪問它(因爲在計算機存儲中創建即使在默認情況下,對密鑰只允許安全訪問創建它的用戶)。

如果一個不存在(這會導致您的「錯誤數據」異常,而不是可能更有用的「密鑰集不存在」),您還允許解密創建新密鑰。

我建議修改的加密方法如下:

public static void EncryptXmlFile(this XmlDocument doc, string elemToEncryptName) 
{ 
    if (doc == null) 
     return; 

    var security = new CryptoKeySecurity(); 
    // Give the creating user full access 
    security.AddAccessRule(new CryptoKeyAccessRule(new NTAccount(Environment.UserDomainName, Environment.UserName), CryptoKeyRights.FullControl, AccessControlType.Allow)); 

    // Add read-only access to other users as required 
    security.AddAccessRule(new CryptoKeyAccessRule(new NTAccount("<domain name>", "<user name>"), CryptoKeyRights.GenericRead, AccessControlType.Allow)); 

    // Specify that the key is to be stored in the machine key-store, and apply the security settings created above 
    var cspParams = new CspParameters 
    { 
     KeyContainerName = containerName, 
     Flags = CspProviderFlags.UseMachineKeyStore, 
     CryptoKeySecurity = security 
    }; 
    var rsaKey = new RSACryptoServiceProvider(cspParams); 

    // Remainder of the method here... 

和解密方法:

public static void DecryptXmlFile(this XmlDocument doc) 
{ 
    if (doc == null) 
     return; 

    // Specify that the key is to be loaded from the machine key-store, and not to create a new key if it doesn't exist. 
    var cspParams = new CspParameters 
    { 
     KeyContainerName = containerName, 
     Flags = CspProviderFlags.UseMachineKeyStore | CspProviderFlags.UseExistingKey 
    }; 
    var rsaKey = new RSACryptoServiceProvider(cspParams); 

    // Remainder of the method here... 
+0

謝謝^^,它現在工作正常 – SidAhmed