Security Resources

⌘K
  1. Home
  2. Security Resources
  3. Secure Code Explain
  4. Use of Weak Cryptographic Algorithms

Use of Weak Cryptographic Algorithms

Here is an example of Java code that is vulnerable to weak cryptography:

🥺 Vulnerable Code

// Vulnerable: MD5 for passwords and AES-ECB for stored card data
MessageDigest md = MessageDigest.getInstance("MD5");
String passwordHash = Hex.encodeHexString(
        md.digest(password.getBytes(StandardCharsets.UTF_8)));

Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(HARDCODED_KEY, "AES"));
byte[] encrypted = cipher.doFinal(cardNumber.getBytes(StandardCharsets.UTF_8));

MD5 is fast and unsalted here, so a commodity GPU tries billions of candidates per second against the whole dump and identical passwords produce identical hashes. ECB encrypts every block independently, which means repeated plaintext produces repeated ciphertext and the structure of the data leaks straight through. Neither construction has any integrity protection, so ciphertext can be reordered or spliced without detection.

😎 Secure Code

Here is a version of the same code that is secured against weak cryptography:

// Passwords: a memory-hard KDF with a per-user salt handled by the library
Argon2 argon2 = Argon2Factory.create(Argon2Factory.Argon2Types.ARGON2id);
String passwordHash = argon2.hash(3, 65536, 2, password.toCharArray());  // t=3, 64 MiB, p=2

// Stored data: authenticated encryption with a unique 96-bit nonce
byte[] nonce = new byte[12];
SecureRandom.getInstanceStrong().nextBytes(nonce);

Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
cipher.init(Cipher.ENCRYPT_MODE, keyFromKms(), new GCMParameterSpec(128, nonce));
cipher.updateAAD(userId.getBytes(StandardCharsets.UTF_8));
byte[] encrypted = cipher.doFinal(cardNumber.getBytes(StandardCharsets.UTF_8));

Argon2id costs memory as well as time, which is what makes offline cracking expensive; bcrypt or scrypt with sane parameters are fine alternatives. AES-GCM gives confidentiality and integrity in one pass, the nonce is random and never reused with the same key, and the additional authenticated data binds the ciphertext to the record it belongs to so rows cannot be swapped. Keys come from a KMS and are rotated - never a constant in the source tree.