Product: SonarQube Community (self-hosted)
sonar-java version: sonar-java 8.28.0.43176 on SonarQube Community Build 26.4.0.121862
Java source level: 21 (javac 21, source/target 17)
Rule
java:S3329 — Cipher IVs must be unpredictable
Description
S3329 inconsistently handles Cipher.DECRYPT_MODE depending on whether it is passed directly to cipher.init(...) or through a local variable. Both forms are semantically identical, but the rule appears to rely on syntactic matching and fails to perform trivial constant propagation.
Reproducer
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.GeneralSecurityException;
public class CipherDecryptExample {
private static final byte[] KEY_BYTES = new byte[16];
private static final byte[] IV_BYTES = new byte[16];
// BEFORE — no S3329 raised
public byte[] decryptA(byte[] ct) throws GeneralSecurityException {
SecretKeySpec ks = new SecretKeySpec(KEY_BYTES, "AES");
IvParameterSpec iv = new IvParameterSpec(IV_BYTES);
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, ks, iv); // not flagged
return cipher.doFinal(ct);
}
// AFTER — S3329 raised on cipher.init(...)
public byte[] decryptB(byte[] ct) throws GeneralSecurityException {
SecretKeySpec ks = new SecretKeySpec(KEY_BYTES, "AES");
IvParameterSpec iv = new IvParameterSpec(IV_BYTES);
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
int opMode = Cipher.DECRYPT_MODE;
cipher.init(opMode, ks, iv); // flagged: S3329
return cipher.doFinal(ct);
}
}