mirror of
https://github.com/datahub-project/datahub.git
synced 2025-07-05 08:07:04 +00:00
144 lines
4.3 KiB
Java
144 lines
4.3 KiB
Java
package security;
|
|
|
|
import java.security.GeneralSecurityException;
|
|
import java.security.InvalidKeyException;
|
|
import java.security.NoSuchAlgorithmException;
|
|
import java.util.Base64;
|
|
import javax.crypto.Mac;
|
|
import javax.crypto.spec.SecretKeySpec;
|
|
import org.apache.commons.codec.digest.HmacAlgorithms;
|
|
|
|
/** Auth Utils Adheres to HSEC requirement for creating application tokens */
|
|
public final class AuthUtil {
|
|
|
|
private static final String HMAC_SHA256_ALGORITHM = HmacAlgorithms.HMAC_SHA_256.toString();
|
|
private static final String DELIIMITER = ":";
|
|
private static final String HEX_CHARS = "0123456789ABCDEF";
|
|
|
|
private AuthUtil() {}
|
|
|
|
/**
|
|
* Generate hash string using the secret HMAC Key
|
|
*
|
|
* @param value value to be hashed
|
|
* @param hmacKey secret HMAC key
|
|
* @return Hashed string using the secret key
|
|
* @throws NoSuchAlgorithmException
|
|
* @throws InvalidKeyException
|
|
*/
|
|
public static String generateHash(String value, byte[] hmacKey)
|
|
throws NoSuchAlgorithmException, InvalidKeyException {
|
|
// Time-stamp at Encryption time
|
|
long tStamp = System.currentTimeMillis();
|
|
String uTValue = new String();
|
|
String cValue;
|
|
String finalEncValue;
|
|
|
|
// Concatenated Values
|
|
uTValue = uTValue.concat(value).concat(":").concat(Long.toString(tStamp));
|
|
cValue = uTValue;
|
|
|
|
// Digest - HMAC-SHA256
|
|
SecretKeySpec signingKey = new SecretKeySpec(hmacKey, HMAC_SHA256_ALGORITHM);
|
|
Mac mac = Mac.getInstance(HMAC_SHA256_ALGORITHM);
|
|
mac.init(signingKey);
|
|
|
|
byte[] rawHmac = mac.doFinal(uTValue.getBytes());
|
|
String hmacString = getHex(rawHmac);
|
|
finalEncValue =
|
|
Base64.getEncoder()
|
|
.encodeToString((cValue.concat(DELIIMITER).concat(hmacString).getBytes()));
|
|
|
|
return finalEncValue;
|
|
}
|
|
|
|
/**
|
|
* Validate the one-way hash string
|
|
*
|
|
* @param hashedValue Hashed value to be validated
|
|
* @param hmacKey HMAC Key used to create the hash
|
|
* @param sessionWindow previously defined session window to validate if the hash is expired
|
|
* @return First element of the hash
|
|
* @throws Exception
|
|
*/
|
|
public static String verifyHash(String hashedValue, byte[] hmacKey, long sessionWindow)
|
|
throws GeneralSecurityException {
|
|
// Username:Timestamp:SignedHMAC(Username:Timestamp)
|
|
String[] decryptedHash = decryptBase64Hash(hashedValue);
|
|
String username = decryptedHash[0];
|
|
String timestamp = decryptedHash[1];
|
|
String signedHMAC = decryptedHash[2];
|
|
long newTStamp = System.currentTimeMillis();
|
|
String newUTValue = username.concat(DELIIMITER).concat(timestamp);
|
|
|
|
// Digest - HMAC-SHA1 Verify
|
|
SecretKeySpec signingKey = new SecretKeySpec(hmacKey, HMAC_SHA256_ALGORITHM);
|
|
Mac mac = Mac.getInstance(HMAC_SHA256_ALGORITHM);
|
|
mac.init(signingKey);
|
|
String rawHmac2 = getHex(mac.doFinal(newUTValue.getBytes()));
|
|
byte[] rawHmac2Bytes = rawHmac2.getBytes();
|
|
|
|
if (!isEqual(rawHmac2Bytes, signedHMAC.getBytes())) {
|
|
throw new GeneralSecurityException("Hash mismatch, tampered session data.");
|
|
}
|
|
|
|
if (newTStamp - Long.parseLong(decryptedHash[1]) >= sessionWindow) {
|
|
throw new GeneralSecurityException("Session expired");
|
|
}
|
|
|
|
return decryptedHash[0];
|
|
}
|
|
|
|
/**
|
|
* Decrypt base64 hash
|
|
*
|
|
* @param value base 64 hash string
|
|
* @return Decrypted base 64 string
|
|
*/
|
|
private static String[] decryptBase64Hash(String value) {
|
|
String decodedBase64 = new String(Base64.getDecoder().decode(value));
|
|
return decodedBase64.split(DELIIMITER);
|
|
}
|
|
|
|
/**
|
|
* Get Hex string from byte array
|
|
*
|
|
* @param raw byte array
|
|
* @return Hex representation of the byte array
|
|
*/
|
|
private static String getHex(byte[] raw) {
|
|
if (raw == null) {
|
|
return null;
|
|
}
|
|
|
|
final StringBuilder hex = new StringBuilder(2 * raw.length);
|
|
|
|
for (final byte b : raw) {
|
|
hex.append(HEX_CHARS.charAt((b & 0xF0) >> 4)).append(HEX_CHARS.charAt((b & 0x0F)));
|
|
}
|
|
|
|
return hex.toString();
|
|
}
|
|
|
|
/**
|
|
* Compares two HMAC byte arrays
|
|
*
|
|
* @param a HMAC byte array 1
|
|
* @param b HMAC byte array 2
|
|
* @return true if the two HMAC are identical
|
|
*/
|
|
private static boolean isEqual(byte[] a, byte[] b) {
|
|
if (a == null || b == null || a.length != b.length) {
|
|
return false;
|
|
}
|
|
|
|
int result = 0;
|
|
|
|
for (int i = 0; i < a.length; i++) {
|
|
result |= a[i] ^ b[i];
|
|
}
|
|
|
|
return result == 0;
|
|
}
|
|
}
|