2016-08-02 59 views
0

使用Windows数据保护API,可以如下面的代码示例了内存中的数据进行加密,:使用DPAPI加密而不泄露未加密数据的长度?

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

然而,在这个例子中encypted数据与原始数据大小相同。有没有办法利用DPAPI来加密数据而不会泄露原始文件的文件大小?例如,将密钥生成的密文隐藏在密钥中的“随机”位置,尽可能使用一次性密码?

+0

为什么不简单地将输入数据构造为length + data + padding? –

+0

当然,虽然这需要在解密后解析数据,但我觉得这应该是一个常见的问题,已经有一些实现 –

+1

这取决于DPAPI加密的质量,以及您对可能性的关心程度已知的明文攻击。另一种可能性是生成一个密钥,将其用于适当的块加密(如'AesCryptoServiceProvider'),并使用DPAPI保护密钥,所以已知长度不是问题。 –

回答

0

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

如果这将是一个问题,您将不得不将自己的秘密包装在自己的填充中:创建为要保护的数据:“秘密长度”秘密“随机内容”,并将其放入DPAPI中。任何人都可以推断出这些数据的大致长度(最多16字节),但不是实际秘密的长度,当然,除了小数点以上的数字外。当合法用户取回DPAPI blob的解密时,他可以从长度字段中推导出秘密(当然它本身具有已知的固定长度)。 DPAPI确保数据不会被篡改(它使用HMAC),因此您相信该数据是正确的。

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