I asked a question on Code Review Stack Exchange, and received a great summary but was redirected here. Covering the answers of the post, it was noted and suggested that:

  1. Use of plain (CBC) mode. They suggested to use GCM but in my solution I need to avoid adding an additional library. Here are my options, which are for AES in essentially CBC, CTR and ECB.
    Which one would be better to use? Is this too broad a question to ask? What are the benefits to each? If it was credit card data, for example, which is more suitable?
  2. Use of PBKDF2 is outdated, and it was suggested to use Argon2, but here is what I'm using. I am not sure of what to replace this with so as to stay within the constraints of .NET out of the box.

So, taking a credit card, for example, please help me answer these without introducing another library (i.e., BouncyCastle), or if it's absolutely necessary to include another library, please state why .NET's default cryptography is not suitable.

  • 1
    $\begingroup$ Rather than just linking to those pages, it might be helpful to list the relevant options along with the link. $\endgroup$
    – Ella Rose
    Commented Apr 12, 2019 at 18:34

1 Answer 1


without introducing another library

Well, this isn't exactly an ideal situation, but there's still hope. After having browsed the list of available tools there are still some things that can be done, but of course the solution will be less robust and less modern than if one could rely on external libraries.

Which one would be better to use?

This still depends. If you absolutely cannot tolerate ciphertext expansion under any circumstances whatsoever and if you absolutely cannot tolerate using external libraries under any circumstances whatsoever then yes, CBC-mode is your best choice. If you cannot tolerate ciphertext expansion, you want to look into using EME or XTS mode as a fallback, but for the rest of this section I'll assume that ciphertext expansion is acceptable.

Your best choice if you absolutely cannot tolerate using external libraries under any circumstances whatsoever is to use AES-CTR + HMAC-SHA256. You already found the Enum for CTR-Mode, this leads the question to HMAC-SHA256. The optimal way here is to take the entire ciphertext with all associated data (such as routing information and / or salts), run it through HMAC and append (or otherwise pair it with) the resulting authentication tag. Then on decryption reject any incoming messsage that either lacks a tag or has an invalid tag. The key should be derived as described below, but should definitely be independent of the AES key and the CTR IV.

Use of Use of PBKDF2 is outdated, and it was suggested to use Argon, but here is what I'm using. Not sure of what to replace this with within the constraints of .NET out of the box

That's the problem. There is nothing. This is the only situation where falling back to PBKDF2 is acceptable. There are two things to still get somewhat good security out of PBKDF2 and you really want to do both:

  1. Use a non-fixed iteration count. The one really nice thing about PBKDF2 is that its runtime is perfectly linear in its iteration count, so ideally you want to dynamically measure how many iterations per second you can do on your target system and then linearly extrapolate how many you actually want to do. Usually with this you want to target 100ms on something like a server, but the more CPU-time you can spare the better.
  2. Aggregate-Derive-Expand. As pointed out as a "side-note" in the answer on CodeReview.SE the current PBKDF2 parameters lead three separate "chains" of derivation which are easily parallelized by an attacker. Ideally (and this is possible here), one concentrates the keying material into a single string ("aggregate") using eg a straight SHA256 hash (this may get more complicated for more complex keying material structures and properties), then one runs this through the expensive key-derivation function so this function gets called exactly once and thus can be as expensive as possible ("derive"). Finally one gets what TLS calls a "master secret". From this one derives the actual secrets needed like e.g. the AES key, the HMAC key and potentially the CTR IV ("expand"). Ideally one would do this using HKDF, but in this case PBKDF2 with a single iteration also does the trick as would do "label-driven-expansion" where you put the master secret into the key input of an HMAC instance and a label for the key (such as the string "AES key") into the message input.
  • $\begingroup$ I'm going to convince the powers at be to allow the introduction of bouncy castle. The arguments for an external library are getting far too prominent to ignore. $\endgroup$ Commented Apr 14, 2019 at 20:54
  • $\begingroup$ Adventure continued here for all who may benefit: codereview.stackexchange.com/questions/217784/… $\endgroup$ Commented Apr 20, 2019 at 16:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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