Don't use DES/3DES/RC2 weak cipher algorithms

Rule ND3102 Security

Since 2005 the NIST no longer considers DES and 3DES cipher algorithms secure (3DES was fully withdrawn at the end of 2023). RC2 shares the 64-bit block size that makes them vulnerable to the Sweet32 birthday attack. Rijndael / RijndaelManaged are obsolete in .NET (SYSLIB0022): they only add non-standard block sizes to AES and are not FIPS validated. Sources: https://www.nist.gov/news-events/news/2005/06/nist-withdraws-outdated-data-encryption-standard https://sweet32.info/

This is CWE-327 Use of a Broken or Risky Cryptographic Algorithm.

Flagged Code
static byte[] Encrypt(byte[] plain, byte[] key, byte[] iv) {
   using var cipher = TripleDES.Create();                       // flagged: 3DES
   cipher.Key = key;
   cipher.IV = iv;
   using var encryptor = cipher.CreateEncryptor();
   return encryptor.TransformFinalBlock(plain, 0, plain.Length);
}
Fixed Code
static byte[] Encrypt(byte[] plain, byte[] key, byte[] iv) {
   using var cipher = Aes.Create();                             // AES (or AesGcm)
   cipher.Key = key;
   cipher.IV = iv;
   using var encryptor = cipher.CreateEncryptor();
   return encryptor.TransformFinalBlock(plain, 0, plain.Length);
}

How to fix

Use AES via System.Security.Cryptography.Aes.Create() (or the authenticated AesGcm which also detects tampering). Suppress issues when DES/3DES/RC2 is kept for legacy data compatibility.

CQLinq source

This rule is written in CQLinq, C# LINQ over the NDepend code model. It ships with every new NDepend project: you can read it, adapt it, or use it as a starting point for your own custom rules.

// <Name>Don't use DES/3DES/RC2 weak cipher algorithms</Name>
// <Id>ND3102:DontUseDES3DESWeakCipherAlgorithms</Id>
warnif count > 0

// Third-party members are part of the code model only when the application uses them.
let weakCipherTypes = ThirdParty.Types.WithFullNameIn(
  "System.Security.Cryptography.DES",
  "System.Security.Cryptography.DESCryptoServiceProvider",
  "System.Security.Cryptography.TripleDES",
  "System.Security.Cryptography.TripleDESCryptoServiceProvider",
  "System.Security.Cryptography.TripleDESCng",
  "System.Security.Cryptography.RC2",
  "System.Security.Cryptography.RC2CryptoServiceProvider",
  // Rijndael is obsolete (SYSLIB0022): AES with non-standard block sizes, not FIPS validated
  "System.Security.Cryptography.Rijndael",
  "System.Security.Cryptography.RijndaelManaged")

// Constructors and factories: new DESCryptoServiceProvider(), TripleDES.Create(), RC2.Create("RC2")
let weakCipherMembers = weakCipherTypes.ChildMethods()
   .Where(m => m.IsConstructor || (m.IsStatic && m.SimpleName == "Create"))
   .ToHashSetEx()

where weakCipherMembers.Any()

from m in Application.Methods.UsingAny(weakCipherMembers)
let weakCipherMembersUsed = m.MethodsCalled.Intersect(weakCipherMembers).ToArray()
let onlyRijndael = weakCipherMembersUsed.All(mc => mc.ParentType.SimpleName.StartsWith("Rijndael"))
select new {
  m,
  weakCipherMembersUsed,
  Debt = 1.ToHours().ToDebt(),
  Severity = onlyRijndael ? Severity.Medium : Severity.High
}

//<Expl>
// The *{0}* uses the weak or obsolete cipher algorithm(s) *{1}*.
// Use *System.Security.Cryptography.Aes* instead.
//</Expl>

//<Desc>
// Since 2005 the NIST no longer considers DES and 3DES cipher algorithms
// secure (3DES was fully withdrawn at the end of 2023). RC2 shares the
// 64-bit block size that makes them vulnerable to the *Sweet32* birthday
// attack. *Rijndael* / *RijndaelManaged* are obsolete in .NET (SYSLIB0022):
// they only add non-standard block sizes to AES and are not FIPS validated.
// Sources:
// https://www.nist.gov/news-events/news/2005/06/nist-withdraws-outdated-data-encryption-standard
// https://sweet32.info/
//
// This is CWE-327 *Use of a Broken or Risky Cryptographic Algorithm*.
//
// **Flagged Code**
// ```csharp
// static byte[] Encrypt(byte[] plain, byte[] key, byte[] iv) {
//    using var cipher = TripleDES.Create();                       // flagged: 3DES
//    cipher.Key = key;
//    cipher.IV = iv;
//    using var encryptor = cipher.CreateEncryptor();
//    return encryptor.TransformFinalBlock(plain, 0, plain.Length);
// }
// ```
//
// **Fixed Code**
// ```csharp
// static byte[] Encrypt(byte[] plain, byte[] key, byte[] iv) {
//    using var cipher = Aes.Create();                             // AES (or AesGcm)
//    cipher.Key = key;
//    cipher.IV = iv;
//    using var encryptor = cipher.CreateEncryptor();
//    return encryptor.TransformFinalBlock(plain, 0, plain.Length);
// }
// ```
//</Desc>

//<HowToFix>
// Use AES via *System.Security.Cryptography.Aes.Create()* (or the
// authenticated *AesGcm* which also detects tampering).
// Suppress issues when DES/3DES/RC2 is kept for legacy data compatibility.
//</HowToFix>

Security: all 39 items