java.lang.security.audit.crypto.gcm-nonce-reuse.gcm-nonce-reuse
semgrep
Author
221
Download Count*
License
GCM IV/nonce is reused: encryption can be totally useless
Run Locally
Run in CI
Defintion
rules:
- id: gcm-nonce-reuse
metadata:
functional-categories:
- crypto::search::randomness::javax.crypto
cwe:
- "CWE-323: Reusing a Nonce, Key Pair in Encryption"
category: security
source-rule-url: https://www.youtube.com/watch?v=r1awgAl90wM
technology:
- java
owasp:
- A02:2021 - Cryptographic Failures
references:
- https://owasp.org/Top10/A02_2021-Cryptographic_Failures
subcategory:
- vuln
likelihood: MEDIUM
impact: MEDIUM
confidence: HIGH
license: Commons Clause License Condition v1.0[LGPL-2.1-only]
vulnerability_class:
- Cryptographic Issues
languages:
- java
message: "GCM IV/nonce is reused: encryption can be totally useless"
patterns:
- pattern-either:
- pattern: new GCMParameterSpec(..., "...".getBytes(...), ...);
- pattern: byte[] $NONCE = "...".getBytes(...); ... new GCMParameterSpec(...,
$NONCE, ...);
severity: ERROR
Examples
gcm-nonce-reuse.java
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;
public class GcmHardcodedIV
{
public static final int GCM_TAG_LENGTH = 16;
public static final String BAD_IV = "ab0123456789";
//It has not been found how to detect hardcoded byte arrays with semgrep
//todoruleid: gcm-nonce-reuse
public static final byte[] BAD_IV2 = new byte[]{0,1,2,3,4,5,6,7,8,9,10,11};
private static byte[] theIV;
private static SecretKey theKey;
public static void main( String[] args )
{
String clearText = args[0];
System.out.println(clearText);
try {
setKeys();
String cipherText = encrypt(clearText);
System.out.println(cipherText);
String decrypted = decrypt(cipherText);
System.out.println(decrypted);
} catch(Exception e) {
System.out.println(e.getMessage());
}
}
public static String encrypt(String clearText) throws Exception {
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
SecretKeySpec keySpec = new SecretKeySpec(theKey.getEncoded(), "AES");
//ruleid: gcm-nonce-reuse
byte[] theBadIV = BAD_IV.getBytes();
GCMParameterSpec gcmParameterSpec = new GCMParameterSpec(GCM_TAG_LENGTH * 8, theBadIV);
cipher.init(Cipher.ENCRYPT_MODE, keySpec, gcmParameterSpec);
byte[] cipherText = cipher.doFinal(clearText.getBytes());
return Base64.getEncoder().encodeToString(cipherText);
}
public static String decrypt(String cipherText) throws Exception {
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
SecretKeySpec keySpec = new SecretKeySpec(theKey.getEncoded(), "AES");
//Hard to detect that theIV is indeed built from a hardcoded string
//todoruleid: gcm-nonce-reuse
GCMParameterSpec gcmParameterSpec = new GCMParameterSpec(GCM_TAG_LENGTH * 8, theIV);
cipher.init(Cipher.DECRYPT_MODE, keySpec, gcmParameterSpec);
byte[] decoded = Base64.getDecoder().decode(cipherText);
byte[] decryptedText = cipher.doFinal(decoded);
return new String(decryptedText);
}
public static void setKeys() throws Exception {
KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
keyGenerator.init(256);
theIV = BAD_IV.getBytes();
}
}
Short Link: https://sg.run/Dww2