使用DPAPI加密而不显示未加密数据的长度?

时间:2016-08-02 12:45:37

标签: c# encryption dpapi

使用Windows Data Protection API,可以加密内存中的数据,如下面的代码所示:

byte[] toEncrypt = UnicodeEncoding.ASCII.GetBytes("ThisIsSomeData16");

Console.WriteLine("Original data: " + UnicodeEncoding.ASCII.GetString(toEncrypt));
Console.WriteLine("Encrypting...");

// Encrypt the data in memory.
EncryptInMemoryData(toEncrypt, MemoryProtectionScope.SameLogon);

Console.WriteLine("Encrypted data: " + UnicodeEncoding.ASCII.GetString(toEncrypt));
Console.WriteLine("Decrypting...");

// Decrypt the data in memory.
DecryptInMemoryData(toEncrypt, MemoryProtectionScope.SameLogon);

Console.WriteLine("Decrypted data: " + UnicodeEncoding.ASCII.GetString(toEncrypt));

请参阅此处的Microsoft参考:https://msdn.microsoft.com/en-us/library/ms995355.aspx

但是,此示例中的加密数据与原始数据的大小相同。有没有办法利用DPAPI加密数据而不泄露原始文件的文件大小?例如,将生成的密文隐藏在密钥内的“随机”位置,尽可能使用一个时间段?

1 个答案:

答案 0 :(得分:0)

如果加密DPAPI blob中的数据,然后解密该blob,则会得到完全相同的数据。这就是它的全部要点。如果您查看加密的DPAPI blob并且系统使用AES(从Win7开始默认),那么由于加密数据的大小,任何人都可以推断出秘密的大致长度它是块大小与实际长度的最接近的倍数。例如,如果密钥长度为17个字节,则DPAPI提供程序将这些字节加密,后跟15个字节,值为0xF,以便为AES加密创建两个块(并在解密时剥离这些字节)。因此,只要看到DPAPI数据中的大小,我们就可以看到这个秘密长达16-31个字节。

如果这是一个问题,你必须将自己的秘密包装在自己的填充物中:创建要保护的数据:"秘密长度"秘密"随机的东西",并把它放在DPAPI中。任何人都可以推断出这个数据的大概长度(最多16个字节),但不是实际秘密的长度,当然除了琐碎的上限之外。当合法用户获回DPAPI blob的解密时,他可以从长度字段中推断出该秘密(当然,该字段本身应具有已知的固定长度)。 DPAPI确保数据不被篡改(它使用HMAC),因此您相信数据是正确的。

您还可以使用您知道的任何字节未出现在要保护的密码中,并将其用作秘密数据末尾的标记字节。例如。 0x0如果它是一个C字符串。但我认为,增加长度更安全。