Decrypt Xml file with asymmetric key windows forms and windows service

僤鯓⒐⒋嵵緔 提交于 2019-12-11 18:04:17

问题


I'm developping a winforms application using .NET3.5 (C#). And for the protection of the application, I used an Xml file, whitch should should be crypted using an asymmetric key.

Now, My application has two part, the windows forms part, and the windows service part (who check the authenticity of the application). So, my file will be crypted/decrypted by the two parts. And this is where the problem appear. When the win forms part try to decrypt the file already creapted by the service, an exception occur (Incorrect Data). Here's my code:

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

回答1:


You've indicated that the accounts that the service and client run under are different, which explains why it's not working - unless you specify otherwise, the keys are created in the user's own key store, to which the other user does not have access.

You need instead to create the key in the machine store, and to grant the other user(s) access to it (since by default even when created in the machine store, the security applied to the key only permits access to the user that created it).

You're also permitting the decryption to create a new key if one does not exist (which results in your "Bad Data" exception, rather than the probably more useful "Keyset does not exist").

I would suggest amending the encryption method as follows:

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

And the decryption method:

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


来源:https://stackoverflow.com/questions/11260031/decrypt-xml-file-with-asymmetric-key-windows-forms-and-windows-service

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!