0

Using the Windows Data Protection API, it is possible to encrypt data in memory, as the following code exemplifies:

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

See the Microsoft reference here: https://msdn.microsoft.com/en-us/library/ms995355.aspx

However, the encypted data in this example is of equal size as the original data. Is there a way to utilize the DPAPI to encrypt data without revealing the file size of the original file? For example, hiding the generated ciphertext at a "random" spot within the key as is possible with one time pads?

Verbal Kint
  • 425
  • 1
  • 3
  • 20
  • Why don't you simply construct your input data as length + data + padding? – Jeroen Mostert Aug 02 '16 at 14:47
  • A possibility certainly, though this would require parsing the data after decryption, when I feel like this should be a common enough concern to already have some implementation – Verbal Kint Aug 02 '16 at 14:55
  • 1
    That depends on the quality of the DPAPI encryption, and how much you care about the possiblity of known plaintext attacks. Another possibility is to generate a key, use that for a proper block encryption (like `AesCryptoServiceProvider`) and protect just the key with DPAPI, so the known length isn't an issue. – Jeroen Mostert Aug 02 '16 at 15:00

1 Answers1

0

If you encrypt data in a DPAPI blob, and then decrypt that blob, you get the exact same data back. This is the whole point of it. If you only look at the encrypted DPAPI blob and the system uses AES (as is the default from Win7 onwards) then anyone can deduce the approximate length of the secret, due to the size of the crypto-data in it being the nearest multiple of the block size to the actual length. E.g if the secret is 17 bytes long, the DPAPI-provider encrypts those bytes followed by 15 bytes with value 0xF to create two blocks for AES to encrypt (And strips those bytes upon decryption). So just seeing the size in the DPAPI-data we can see the secret was say 16-31 bytes long.

If that would be a problem, you would have to wrap your own secret in your own stuffing: create as data to be protected: "length of secret" secret "random stuff", and put that in DPAPI. Anyone could deduce the approximate length of this data (up to 16 bytes) ,but not the length of the actual secret, except for the trivial upperbound, of course. When the legitimate user gets back the decryption of the DPAPI blob, he can deduce the secret from the length field (which should itself have a known fixed length of course). DPAPI ensures that the data is not tampered with (it uses an HMAC) so you trust that data to be correct.

You can also use any byte that you know does not appear in the secret you want to protect and use that as a marker byte for the end of the secret data. E.g. 0x0 if it's a C-string. But adding the length is more failsafe ,I think.

Henno Brandsma
  • 2,116
  • 11
  • 12