3

I want to implement authenticated encryption using C#. There is a dot net class called encryptAndAuthenticate, but it is only supported on windows 8 or later, and I need the code to also work on windows 7. In other words, there is no built-in dot net library to do AES in GMC mode that works on windows 7 or earlier. So it looks like I have to use separate calls to the C# aes and hmac routines. Here is the pseudocode in my head. Am I planning this correctly?

Encryption:

  1. User supplies plaintext.
  2. User supplies password.
  3. CSPRNG generates 256-bit salt.
  4. Slow key derivation function on password and salt produces 640-bit output.
  5. First 256 bits of output becomes AES key.
  6. Next 128 bits of output becomes AES IV.
  7. Last 256 bits of output becomes HMAC-256 key.
  8. AES encrypt CBC mode using (plaintext, AES key, AES IV) to produce ciphertext.
  9. HMAC-SHA256 on IV||ciphertext (using HMAC-256 key) to produce MAC.
  10. Publicly store salt, ciphertext, and MAC.

Decryption:

  1. User retrieves salt, ciphertext, and MAC.
  2. Step 2 from above.
  3. Steps 4-7 from above.
  4. Step 9 from above.
  5. Compare calculated MAC to retrieved MAC.
  6. If different, abort and tell user decryption failed.
  7. If valid, AES decrypt CBC mode using (ciphertext, AES key, AES IV) to produce plaintext.
  8. Display plaintext to user.
Ralph P
  • 543
  • 1
  • 4
  • 10

2 Answers2

3

PBKDF2 alone would be bad for step 4, since the blocks of its output can
trivially be computed independently. ​ If the PBKDF you use can't directly
produce enough output, then you should compose with a fast key-based KDF.


Make sure that

the IV is part of step 9's ciphertext
and
step 5 of decryption is constant-time

.

0

You might want to call out to libsodium instead. It provides password hashing and authenticated encryption built-in, with a very clean API that is easy to use correctly, as long as you remember to choose a fresh nonce every time you encrypt. It will also be faster than AES+HMAC, and uses Argon2 for password hashing, the winner of the Password Hashing Competition.

The API is C, but you can easily P/Invoke, or use the existing bindings. Be warned that the bindings do not throw on auth failure.

Demi
  • 4,853
  • 1
  • 22
  • 40