0

.NET3.5(C#)を使用してwinformsアプリケーションを開発しています。また、アプリケーションを保護するために、Xmlファイルを使用しました。非対称キーを使用して暗号化する必要があります。

現在、私のアプリケーションには、Windowsフォーム部分とWindowsサービス部分(アプリケーションの信頼性をチェックする部分)の2つの部分があります。したがって、私のファイルは2つの部分によって暗号化/復号化されます。そして、これが問題が発生する場所です。Winフォームの一部が、サービスによって既に作成されているファイルを復号化しようとすると、例外が発生します(データが正しくありません)。これが私のコードです:

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

1 に答える 1

1

サービスとクライアントが実行するアカウントが異なることを示しました。これは、サービスが機能しない理由を説明しています。特に指定しない限り、キーは、他のユーザーがアクセスできないユーザー自身のキーストアに作成されます。

代わりに、マシンストアでキーを作成し、他のユーザーにそのキーへのアクセスを許可する必要があります(デフォルトでは、マシンストアで作成された場合でも、キーに適用されるセキュリティは、作成したユーザーへのアクセスのみを許可します)それ)。

また、新しいキーが存在しない場合は、復号化によって新しいキーを作成することを許可しています(これにより、おそらくより有用な「キーセットが存在しません」ではなく、「不正なデータ」例外が発生します)。

暗号化方式を次のように修正することをお勧めします。

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...
于 2012-06-29T13:36:16.287 に答える