mirror of
				https://github.com/datahub-project/datahub.git
				synced 2025-10-31 18:59: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;
 | |
|   }
 | |
| }
 | 
