10

The System.Security.Cryptography namespace has at least 3 different seemingly interchangeable ways to get an object that will perform AES encryption/decryption:

using (var aes = Aes.Create())

or

using (var aes = new AesCryptoServiceProvider())

or

using (var aes = new AesCng())

The first two were introduced in .NET framework version 3.5. The third is much newer; it was introduced in version 4.6.2. One might suspect therefore that it is better than the other 2, but the documentation does not say anywhere that it is recommended to use it in place of the other ones.

The first two each have a code sample. The two samples appear essentially identical.

Which one should I use, and why?

Hammerite
  • 21,755
  • 6
  • 70
  • 91

1 Answers1

8

Aes is an abstract class. I assume that Aes.Create returns a system default. This is probably what you want to use. Let the system decide which ones are available and which ones is best to use.

The others are implementation classes.

  • AesCryptoServiceProvider uses MS CAPI, the older crypto API;
  • AesCng uses the crypto new generation API introduced in Windows Vista;
  • AesManaged implements AES in .NET (not mentioned in your post).

You can also use Aes.Create(string) to choose one of the implementations. If possible I would try and avoid using the implementation classes directly.

Only use the implementation classes if you know that using a specific class is explicitly required or, indeed, if the abstract Aes class is not available.


Note that exposing the crypto implementations in the type system by Microsoft has significant drawbacks; choosing a specific provider may be harder, key based implementation selection may be harder (encryption in hardware) and finally users may be tricked into writing incompatible or inefficient code.

The CipherSpi implementation classes in Java e.g. are hidden from view; these are called from the generic Cipher class.

Maarten Bodewes
  • 90,524
  • 13
  • 150
  • 263
  • 1
    `AesCng` should be used if, and only if, opening a CNG persisted AES key. Otherwise `Aes.Create()` should be used. .NET Core 1.0 removed the ability to use AES via any other means, but then brought the public types back for 2.0 (just for API surface compatibility with .NET Framework) – bartonjs Jan 08 '18 at 17:10
  • 1
    Maarten - Aes.Create() returns an AesCryptoServiceProvider when used in the experimental code running on my development machine. – Hammerite Jan 08 '18 at 17:19
  • @bartonjs I suppose you could use the `Create("AesCng")` constructor for a CNG persisted AES key as well? – Maarten Bodewes Jan 09 '18 at 00:26
  • @Hammerite That makes sense, using fast native code for the actual execution of AES. – Maarten Bodewes Jan 09 '18 at 00:27
  • 1
    @MaartenBodewes Nah, the identifier's way longer than that. (`Aes.Create(typeof(AesCng).GetName())` => `Aes.Create("System.Security.Cryptography.AesCng, System.Core, PublicKeyToken=31bf[etc], [etc]")`). Pretty much anyone using \[Algorithm\].Create(string) has an easier way of doing what they want. – bartonjs Jan 09 '18 at 00:53