mirror of
				https://github.com/datahub-project/datahub.git
				synced 2025-11-04 12:51:23 +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;
 | 
						|
  }
 | 
						|
}
 |