从/向Windows应用商店应用中的文件读取/写入加密和经过身份验证的数据

时间:2014-06-11 10:52:22

标签: c# encryption windows-runtime cryptography windows-store-apps

我想在Windows Metro应用程序中加密文件的内容。有问题的文件存储在设备中本地(LocalState文件夹),并包含一个我不希望用户能够(轻松)修改的长字符串。应用程序很可能使用对称密钥加密和解密文件。

这提供的保护可供讨论,因为应用程序可以被破解以获得密钥。不过,这对我来说是可以接受的,只要用户不能直接修改/伪造文件。我相信经过身份验证的加密是这样做的方式,但我对这个主题的了解并不是很好。

我花了很长时间尝试使用Windows Metro API加密字符串,使用 SymmetricKeyAlgorithmProvider EncryptedAndAuthenticatedData 类。然而,使用示例(来自Microsoft或互联网)似乎很少,并且几乎总是进行简单加密(未经过身份验证)或经过身份验证而无需保存数据。例如,示例here仅连续加密和解密数据。事实上,有些例子每次都会生成一个随机密钥,我相信我无法做到。

我有类似的东西:

private EncryptedAndAuthenticatedData authenticatedEncryption(string strMsg, string strKey)
{
    SymmetricKeyAlgorithmProvider objAlgProv = SymmetricKeyAlgorithmProvider.OpenAlgorithm(SymmetricAlgorithmNames.AesGcm);
    IBuffer buffMsg = CryptographicBuffer.ConvertStringToBinary(strMsg, BinaryStringEncoding.Utf8);
    IBuffer buffKey = CryptographicBuffer.ConvertStringToBinary(strKey, BinaryStringEncoding.Utf8);
    IBuffer buffNonce = CryptographicBuffer.CreateFromByteArray(new byte[]{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 });
    CryptographicKey key = objAlgProv.CreateSymmetricKey(buffKey);
    EncryptedAndAuthenticatedData objEncrypted = CryptographicEngine.EncryptAndAuthenticate(key, buffMsg, buffNonce, null);
    return objEncrypted;
}

正如你所看到的,我甚至使用恒定的随机数,这当然不理想,但我找不到另一种方法。我不知道这种方法可能存在其他问题。

使用这种加密方法后,我尝试使用 DataContractSerializer 序列化 EncryptedAndAuthenticatedData 对象,但没有成功(该类的对象无法序列化),以及我发现无法从 AuthenticationTag EncryptedData 属性构建EncryptedAndAuthenticatedData对象(假设我可以将其写入文件)。

这就意味着我还没有找到正确加密和验证字符串的方法,更不用说将结果保存到文件以便以后能够读取和解密(我有另一种方法用于经过身份验证的解密,它以相同的方式使用key和nonce。)

您是否知道我是否以及如何使用Windows Metro提供的课程?还有更好的方法吗?

1 个答案:

答案 0 :(得分:2)

所以我认为您可以使用更简单的方法:DataProtectionProvider

DataProtectionProvideris是Microsoft提供的一个类,它使用从机器标识,用户标识和软件包标识的组合派生的密钥对给定的byte arrayStream进行对称加密。它使用简单,应该很容易提供很好的保护。

示例文档提供了一个简单示例:

public async Task<IBuffer> SampleProtectAsync(
    String strMsg,
    String strDescriptor,
    BinaryStringEncoding encoding)
{
    // Create a DataProtectionProvider object for the specified descriptor.
    DataProtectionProvider Provider = new DataProtectionProvider(strDescriptor);

    // Encode the plaintext input message to a buffer.
    encoding = BinaryStringEncoding.Utf8;
    IBuffer buffMsg = CryptographicBuffer.ConvertStringToBinary(strMsg, encoding);

    // Encrypt the message.
    IBuffer buffProtected = await Provider.ProtectAsync(buffMsg);

    // Execution of the SampleProtectAsync function resumes here
    // after the awaited task (Provider.ProtectAsync) completes.
    return buffProtected;
}

public async Task<String> SampleUnprotectData(
    IBuffer buffProtected,
    BinaryStringEncoding encoding)
{
    // Create a DataProtectionProvider object.
    DataProtectionProvider Provider = new DataProtectionProvider();

    // Decrypt the protected message specified on input.
    IBuffer buffUnprotected = await Provider.UnprotectAsync(buffProtected);

    // Execution of the SampleUnprotectData method resumes here
    // after the awaited task (Provider.UnprotectAsync) completes
    // Convert the unprotected message from an IBuffer object to a string.
    String strClearText = CryptographicBuffer.ConvertBinaryToString(encoding, buffUnprotected);

    // Return the plaintext string.
    return strClearText;
}

在这种情况下,strDescriptor描述了您希望能够访问加密内容的用户。如果是计算机上的任何人,则值为"LOCAL=machine"。如果它只是给定用户,则值为"LOCAL=user"

如果您使用的是MVC或MVVM,则可以轻松地将其添加到LocalStorageController之类的内容中,以便在您的应用程序离开应用程序之前自动加密/解密所有本地存储。

希望这有助于编码!