Take the 2-minute tour ×
Information Security Stack Exchange is a question and answer site for Information security professionals. It's 100% free, no registration required.

So in Windows, when you make a call to the Data Protection API, you can specify some bytes as "entropy".

To me, this sounds like salt. In PBKDF2, the salt is can, and in fact needs to be stored as plain text. It does not compromise the security of the algorithm, it's part of the implementation of it.

Does the "entropy" you pass to the DPAPI serve the same function? I've read that all it does is make your key application-specific, to an extent, in that if the logged in user read out the keys stored with DPAPI, they couldn't decrypt your encrypted data without the entropy. Of course, the entropy would have to be stored as plain text (or else you end up with an infinite regress).

So, is it OK to store the entropy as plain text (maybe hardcode it)?

Thanks to dr jimbob:

The entropy parameter "is optional entropy provided by the application that will be added to the key derivation [...] By default, DPAPI already uses different entropy for each blob, so in practice adding additional entropy does not [bold added] improve encryption security. According to the documentation, its purpose is to allow applications relying on DPAPI to mitigate the risk of having their secrets stolen by another application. In our test, we found that only GTalk used the conditional entropy, with its value is stored in a registry key and therefore not a real hurdle for the attacker."

share|improve this question
    
I think you'll find "entropy" in this context is more like a seed than a salt. (Differentiating seed and salt is probably grounds for another question <g> ) –  gowenfawr Sep 18 '12 at 21:27
    
If someone doesn't know the entropy, can they still decrypt a value encrypted using DPAPI? –  John Sep 18 '12 at 21:37

2 Answers 2

up vote 2 down vote accepted

From browsing: http://msdn.microsoft.com/en-us/library/ms229741.aspx

The entropy provides a 16 byte (128 bit) initialization vector, not a cryptographic salt.

You generally do not need to keep your IV secret [1], you just have to be careful not to reuse the same IV (which won't happen if it was randomly generated as there are 2128 possible values).

The purpose of the initialization vector is to initially randomize your message before encrypting (typically just the first block).

Compare Electronic CodeBook (ECB) which has no need for an IV and Cipher-Block Chaining which needs one.

Let's say you have some encryption function encrypted_block = Encrypt(block, key) which will take a block of data of fixed size (say 128 bits), a secret encrypt key and return an encrypted block of data, that can be decrypted with block = Decrypt(encrypted_block, key). So if you encrypt a 10 kB file with a 128-bit block size, then you have 640 blocks to encrypt. If two blocks are identical in the original (say its an image with little entropy), then the encrypted blocks at the end will end up identical and patterns can often be discerned. So ECB basically just splits a file into blocks and applies the encryption function to each block individually (without relying on the output of previous blocks).

Now let's look a scheme like CBC which uses an initialization vector (IV). The first block is encrypted by encrypted_block_0 = Encrypt(block_0 ^ IV, key), where ^ is the XOR (bitwise exclusive or operator). The next block is encrypted with encrypted_block_1 = Encrypt(block_1 ^ encrypted_block_0, key); that is you use the result of the encryption of the previous block to 'randomize' the current block prior to feeding into your encryption function. Now if they didn't use an initialization vector for the first block, one could deduce things by observing the first couple blocks. E.g., if you had two encrypted files both with the same initialization vector and saw that the first 10 blocks were identical, you would learn that the first 10 blocks of the plaintext files are identical and you get extra information. Not that merely knowing the IV in the plaintext doesn't help you at all, as it is inside a complicated non-linear Encrypt function that you can't reverse without knowing the secret key.

EDIT: Actually, I think I was wrong to assume that the 16 bytes are used as initialization vector in DPAPI; here'a reverse engineering of microsoft's secret DPAPI: http://cdn.ly.tl/publications/Recovering-Windows-Secrets-and-EFS-Certi%EF%AC%81cates-Of%EF%AC%82ine.pdf

share|improve this answer
    
If someone doesn't know the entropy, can they still decrypt a value encrypted using DPAPI? –  John Sep 18 '12 at 21:13
    
Hmm ok. It looks like it wouldn't be a good idea for me to hardcode the entropy in my application, then. I'll just let DPAPI do it's thing. –  John Sep 18 '12 at 21:42
    
From the paper you cited: "According to the documentation, its purpose is to allow applications relying on DPAPI to mitigate the risk of having their secrets stolen by another application. In our test, we found that only GTalk used the conditional entropy, with its value is stored in a registry key and therefore not a real hurdle for the attacker." So it does do what I thought, but it really doesn't add any security. I'm going to leave it out in my implementation. Thank you for your research! –  John Sep 18 '12 at 21:56

The MSDN documentation does a pretty good job of explaining it:

A small drawback to using the logon password is that all applications running under the same user can access any protected data that they know about. Of course, because applications must store their own protected data, gaining access to the data could be somewhat difficult for other applications, but certainly not impossible.

Basically, if someone discovers some protected data (e.g. an encrypted connection string stored in the registry), a simple application running in the context of the of the user could trivially use DPAPI to decrypt the protected data.

To counteract this, DPAPI allows an application to use an additional secret when protecting data. This additional secret is then required to unprotect the data.

Technically, this "secret" should be called secondary entropy. It is secondary because, while it doesn't strengthen the key used to encrypt the data, it does increase the difficulty of one application, running under the same user, to compromise another application's encryption key. Applications should be careful about how they use and store this entropy. If it is simply saved to a file unprotected, then adversaries could access the entropy and use it to unprotect an application's data.

Clearly storing the entropy in plaintext in the same location as the protected data completely defeats the purpose.

The parameter is further explained as follows:

Internal Protect Function

pOptionalEntropy
Pointer to a DATA_BLOB containing additional entropy used to protect the data. The cbData member holds the length of the pbData member's byte string that contains the optional entropy. The DATA_BLOB used in the protection call must also be used in the unprotection call. This is the application specific "secret" mentioned earlier.
This parameter is optional and can be NULL.

Internal Unprotect Function

pOptionalEntropy
Pointer to a DATA_BLOB containing additional entropy used when the data was protected. The cbData member holds the length of the pbData member's byte string that contains the optional entropy. This is the application specific "secret" mentioned earlier.
This parameter is optional and can be NULL. However, if the optional entropy was used in the protection call, that same entropy must be used in the unprotection call.

Therefore you would be able to increase protection against other applications (or even the user) by using the entropy parameter, and making it a little difficult to discover the entropy value.

So, is it OK to store the entropy as plain text (maybe hardcode it)?

Plaintext is probably fine, provided the location is difficult to find or access. Putting it in the same location as the protected data is somewhat pointless.

You won't be able to get "perfect security" against an attack that already has user access and sufficient time and resources. But there are a few little things you can do to slow them down:

  • If you hard-code the entropy value in the application, it can be found in the binary. But this is more difficult to do.
  • If you apply a simple transformation (such as XOR) to the entropy value before using it, your application would need to be decompiled or the source-code otherwise compromised in order for an attacker to know what to do.
  • You could store your entropy value remotely. This means an attacker would need to know where to find it. And need appropriate other credentials to access it. (Of course said other credentials would also need to be accessible to the application, which is why "perfect security" in this scenario is not possible.)
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.