Files
codeql/java/ql/test/experimental/library-tests/quantum/jca/Hash.java
2025-10-03 13:32:02 -04:00

342 lines
14 KiB
Java

package com.example.crypto.algorithms;
// import org.bouncycastle.crypto.digests.SHA3Digest;
// import org.bouncycastle.crypto.digests.Blake2bDigest;
// import org.bouncycastle.jce.provider.BouncyCastleProvider;
import java.io.FileInputStream;
import java.io.IOException;
import java.security.*;
import java.util.Base64;
import java.util.Properties;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.SecretKeySpec;
import javax.crypto.spec.PBEKeySpec;
/**
* This class demonstrates various hashing, HMAC, and password hashing
* techniques.
*
* SAST/CBOM Classification Notes:
*
* 1. simpleSHA256Hash:
* - Parent Classification: Cryptographic Hash Function.
* - SAST: Uses SHA-256, which is widely regarded as secure.
*
* 2. insecureMD5Hash:
* - Parent Classification: Cryptographic Hash Function.
* - SAST: MD5 is cryptographically broken and should be flagged as insecure.
*
* 3. hashWithBouncyCastleSHA3:
* - Parent Classification: Cryptographic Hash Function (SHA3).
* - SAST: Uses SHA3-256 from BouncyCastle; considered secure.
*
* 4. hashWithBouncyCastleBlake2b:
* - Parent Classification: Cryptographic Hash Function (BLAKE2).
* - SAST: Uses BLAKE2b-512; considered secure if used correctly.
*
* 5. hashAndSign & verifyHashSignature:
* - Parent Classification: Digital Signature (RSA-based).
* - SAST: Uses SHA256withRSA for signing and verification; secure if key
* management is proper.
*
* 6. hashForDataIntegrityCheck:
* - Parent Classification: Data Integrity Check.
* - SAST: Uses SHA-256 to verify integrity; considered secure.
*
* 7. hashWithVariousAlgorithms:
* - Parent Classification: Cryptographic Hash Function.
* - SAST: Iterates through multiple algorithms; insecure algorithms (MD5,
* SHA-1) may be flagged.
*
* 8. hmacWithVariousAlgorithms:
* - Parent Classification: Message Authentication Code (MAC).
* - SAST: Iterates through various HMAC algorithms; HmacSHA1 is considered
* weaker than SHA256 and above.
*
* 9. hashForPasswordStorage:
* - Parent Classification: Password-Based Key Derivation Function (PBKDF).
* - SAST: Uses PBKDF2WithHmacSHA256 with salt and iteration count; considered
* secure,
* though iteration counts should be reviewed against current standards.
*
* 10. hashFromUnknownConfig:
* - Parent Classification: Dynamic Cryptographic Hash Function.
* - SAST: Loading the hash algorithm from an external configuration introduces
* risk of misconfiguration.
*
* 11. insecureHashBasedRNG:
* - Parent Classification: Pseudo-Random Number Generator (PRNG) using hash.
* - SAST: Uses a fixed seed with various hash algorithms; flagged as insecure
* due to predictability.
*/
public class Hash {
// static {
// Security.addProvider(new BouncyCastleProvider());
// }
/**
* Computes a SHA-256 hash of static test data.
*
* CBOM/SAST Classification:
* - Uses SHA-256: Classified as secure.
*/
public void simpleSHA256Hash() throws Exception {
MessageDigest digest = MessageDigest.getInstance("SHA-256");
byte[] hash = digest.digest("Simple Test Data".getBytes());
System.out.println("SHA-256 Hash: " + Base64.getEncoder().encodeToString(hash));
}
/**
* Computes an MD5 hash of static data.
*
* CBOM/SAST Classification:
* - Uses MD5: Classified as insecure.
* - SAST: MD5 is deprecated for cryptographic purposes due to collision
* vulnerabilities.
*/
public void insecureMD5Hash() throws Exception {
MessageDigest md5Digest = MessageDigest.getInstance("MD5");
byte[] hash = md5Digest.digest("Weak Hash Example".getBytes());
System.out.println("MD5 Hash (Insecure): " + Base64.getEncoder().encodeToString(hash));
}
// /**
// * Computes a SHA3-256 hash using BouncyCastle's SHA3Digest.
// *
// * CBOM/SAST Classification:
// * - Uses SHA3-256: Classified as secure.
// * - SAST: BouncyCastle's implementation is considered reliable.
// */
// public void hashWithBouncyCastleSHA3(String input) {
// SHA3Digest digest = new SHA3Digest(256);
// byte[] inputBytes = input.getBytes();
// digest.update(inputBytes, 0, inputBytes.length);
// byte[] hash = new byte[digest.getDigestSize()];
// digest.doFinal(hash, 0);
// System.out.println("SHA3-256 (BC) Hash: " + Base64.getEncoder().encodeToString(hash));
// }
// /**
// * Computes a BLAKE2b-512 hash using BouncyCastle's Blake2bDigest.
// *
// * CBOM/SAST Classification:
// * - Uses BLAKE2b-512: Classified as secure.
// * - SAST: BLAKE2b is modern and fast, considered secure when used correctly.
// */
// public void hashWithBouncyCastleBlake2b(String input) {
// Blake2bDigest digest = new Blake2bDigest(512);
// byte[] inputBytes = input.getBytes();
// digest.update(inputBytes, 0, inputBytes.length);
// byte[] hash = new byte[digest.getDigestSize()];
// digest.doFinal(hash, 0);
// System.out.println("BLAKE2b-512 (BC) Hash: " + Base64.getEncoder().encodeToString(hash));
// }
/**
* Signs the hash of the input using SHA256withRSA.
*
* CBOM/SAST Classification:
* - Digital Signature (RSA): Classified as secure if keys are managed
* correctly.
* - SAST: The combination of SHA256 and RSA is a standard and secure pattern.
*
* @param input The input data to be signed.
* @param privateKey The RSA private key used for signing.
*/
public void hashAndSign(String input, PrivateKey privateKey) throws Exception {
Signature signature = Signature.getInstance("SHA256withRSA");
signature.initSign(privateKey);
signature.update(input.getBytes());
byte[] signedData = signature.sign();
System.out.println("Signed Hash: " + Base64.getEncoder().encodeToString(signedData));
}
/**
* Verifies the signature of the input data.
*
* CBOM/SAST Classification:
* - Digital Signature Verification: Classified as secure when using
* SHA256withRSA.
* - SAST: Should correctly verify that the signed hash matches the input.
*
* @param input The original input data.
* @param signedHash The signed hash to verify.
* @param publicKey The RSA public key corresponding to the private key that
* signed the data.
* @return true if the signature is valid, false otherwise.
*/
public boolean verifyHashSignature(String input, byte[] signedHash, PublicKey publicKey) throws Exception {
Signature signature = Signature.getInstance("SHA256withRSA");
signature.initVerify(publicKey);
signature.update(input.getBytes());
return signature.verify(signedHash);
}
/**
* Computes a SHA-256 hash for data integrity checking and compares it with an
* expected hash.
*
* CBOM/SAST Classification:
* - Data Integrity: Uses SHA-256 for integrity checks, which is secure.
* - SAST: A correct implementation for verifying data has not been tampered
* with.
*
* @param data The input data.
* @param expectedHash The expected Base64-encoded hash.
*/
public void hashForDataIntegrityCheck(String data, String expectedHash) throws Exception {
MessageDigest digest = MessageDigest.getInstance("SHA-256");
byte[] hash = digest.digest(data.getBytes());
String computedHash = Base64.getEncoder().encodeToString(hash);
System.out.println("Computed Hash: " + computedHash);
System.out.println("Validation: " + (computedHash.equals(expectedHash) ? "Pass" : "Fail"));
}
/**
* Computes hashes of the input data using various algorithms.
*
* CBOM/SAST Classification:
* - Cryptographic Hash Functions: Iterates through multiple hash functions.
* - SAST: While many are secure (e.g., SHA-256, SHA-512, SHA3), MD5 and SHA-1
* are insecure
* and should be flagged if used in security-critical contexts.
*
* @param input The input data to hash.
*/
public void hashWithVariousAlgorithms(String input) throws Exception {
String[] algorithms = { "SHA-1", "SHA-224", "SHA-256", "SHA-384", "SHA-512", "SHA3-256", "SHA3-512",
"BLAKE2B-512", "BLAKE2S-256", "MD5" };
for (String algorithm : algorithms) {
MessageDigest digest = MessageDigest.getInstance(algorithm);
byte[] hash = digest.digest(input.getBytes());
System.out.println(algorithm + " Hash: " + Base64.getEncoder().encodeToString(hash));
}
}
/**
* Computes HMACs of the input data using various algorithms.
*
* CBOM/SAST Classification:
* - Message Authentication Code (MAC): Iterates through different HMAC
* algorithms.
* - SAST: HmacSHA256, HmacSHA384, HmacSHA512, HmacSHA3-256, and HmacSHA3-512
* are secure;
* HmacSHA1 is considered less secure and may be flagged.
*
* @param input The input data.
* @param key The secret key used for HMAC computation.
*/
public void hmacWithVariousAlgorithms(String input, byte[] key) throws Exception {
String[] algorithms = { "HmacSHA1", "HmacSHA256", "HmacSHA384", "HmacSHA512", "HmacSHA3-256", "HmacSHA3-512" };
for (String algorithm : algorithms) {
Mac mac = Mac.getInstance(algorithm);
SecretKey secretKey = new SecretKeySpec(key, algorithm);
mac.init(secretKey);
byte[] hmac = mac.doFinal(input.getBytes());
System.out.println(algorithm + " HMAC: " + Base64.getEncoder().encodeToString(hmac));
}
}
/**
* Computes a PBKDF2 hash for password storage.
*
* CBOM/SAST Classification:
* - Password-Based Key Derivation Function (PBKDF): Uses PBKDF2WithHmacSHA256.
* - SAST: Considered secure when using a strong salt and an appropriate
* iteration count.
* Note: The iteration count (10000) should be reviewed against current security
* standards.
*
* @param password The password to hash.
*/
public void hashForPasswordStorage(String password) throws Exception {
byte[] salt = generateSecureSalt(16);
// 10,000 iterations and a 256-bit derived key.
PBEKeySpec spec = new PBEKeySpec(password.toCharArray(), salt, 10000, 256);
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
byte[] hash = factory.generateSecret(spec).getEncoded();
System.out.println("PBKDF2 Hash: " + Base64.getEncoder().encodeToString(hash));
}
/**
* Dynamically loads a hash algorithm from configuration and computes a hash.
*
* CBOM/SAST Classification:
* - Dynamic Cryptographic Hash Selection: Algorithm is loaded from a config
* file.
* - SAST: May be flagged as risky because an insecure or unintended algorithm
* might be chosen.
*/
public void hashFromUnknownConfig() throws Exception {
String algorithm = loadHashAlgorithmFromConfig("config.properties");
MessageDigest digest = MessageDigest.getInstance(algorithm);
byte[] hash = digest.digest("Config-based Hashing".getBytes());
System.out.println("Dynamically Loaded Hash Algorithm (" + algorithm + "): " +
Base64.getEncoder().encodeToString(hash));
}
/**
* Demonstrates an insecure method for generating pseudo-random bytes by using a
* fixed seed with hash algorithms.
*
* CBOM/SAST Classification:
* - Insecure RNG: Uses a fixed seed with various hash algorithms.
* - SAST: This approach is insecure because it produces predictable output and
* should be flagged.
*/
public void insecureHashBasedRNG() throws Exception {
String[] algorithms = { "SHA-256", "SHA-512", "SHA3-256", "SHA3-512" };
for (String algorithm : algorithms) {
MessageDigest digest = MessageDigest.getInstance(algorithm);
byte[] seed = "fixed-seed".getBytes(); // Fixed seed: insecure and predictable.
digest.update(seed);
byte[] pseudoRandomBytes = digest.digest();
System.out.println("Insecure RNG using " + algorithm + ": " +
Base64.getEncoder().encodeToString(pseudoRandomBytes));
}
}
/**
* Loads the hash algorithm from an external configuration file.
*
* CBOM/SAST Classification:
* - Dynamic Configuration: External config loading.
* - SAST: The use of external configuration may introduce risks if the config
* file is compromised.
*
* @param configPath Path to the configuration file.
* @return The hash algorithm to be used (default is SHA-256).
*/
private String loadHashAlgorithmFromConfig(String configPath) {
Properties properties = new Properties();
try (FileInputStream fis = new FileInputStream(configPath)) {
properties.load(fis);
} catch (IOException e) {
e.printStackTrace();
}
return properties.getProperty("hash.algorithm", "SHA-256");
}
/**
* Generates a secure salt using a cryptographically strong random number
* generator.
*
* CBOM/SAST Classification:
* - Secure Salt Generation: Uses SecureRandom.
* - SAST: This is a best-practice approach for generating salts for password
* hashing.
*
* @param length The desired salt length.
* @return A byte array representing the salt.
*/
private byte[] generateSecureSalt(int length) {
byte[] salt = new byte[length];
new SecureRandom().nextBytes(salt);
return salt;
}
}