Files
codeql/java/ql/test/experimental/library-tests/quantum/jca/Hash.java
2025-10-06 10:46:09 -04:00

314 lines
13 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;
}
}