Copy public enum HMACWrapper {
HMAC_512("HMac-SHA512"), //please note that this is the spec for the BC provider
HMAC_256("HMac-SHA256");
private final String algorithm;
private HMACWrapper(final String algorithm) {
this.algorithm = algorithm;
}
public Mac createHMAC(final SecretKey key) {
try {
Mac e = Mac.getInstance(this.algorithm, "BC");
SecretKeySpec secret = new SecretKeySpec(key.getKey().getEncoded(), this.algorithm);
e.init(secret);
return e;
} catch (NoSuchProviderException | InvalidKeyException | NoSuchAlgorithmException e) {
//handle them
}
}
public byte[] hmac(byte[] message, SecretKey key) {
Mac mac = this.createHMAC(key);
return mac.doFinal(message);
}
public boolean verify(byte[] messageWithHMAC, SecretKey key) {
Mac mac = this.createHMAC(key);
byte[] checksum = extractChecksum(messageWithHMAC, mac.getMacLength());
byte[] message = extractMessage(messageWithHMAC, mac.getMacLength());
byte[] calculatedChecksum = this.hmac(message, key);
int diff = checksum.length ^ calculatedChecksum.length;
for (int i = 0; i < checksum.length && i < calculatedChecksum.length; ++i) {
diff |= checksum[i] ^ calculatedChecksum[i];
}
return diff == 0;
}
public byte[] extractMessage(byte[] messageWithHMAC) {
Mac hmac = this.createHMAC(SecretKey.newKey());
return extractMessage(messageWithHMAC, hmac.getMacLength());
}
private static byte[] extractMessage(byte[] body, int checksumLength) {
if (body.length >= checksumLength) {
byte[] message = new byte[body.length - checksumLength];
System.arraycopy(body, 0, message, 0, message.length);
return message;
} else {
return new byte[0];
}
}
private static byte[] extractChecksum(byte[] body, int checksumLength) {
if (body.length >= checksumLength) {
byte[] checksum = new byte[checksumLength];
System.arraycopy(body, body.length - checksumLength, checksum, 0, checksumLength);
return checksum;
} else {
return new byte[0];
}
}
static {
Security.addProvider(new BouncyCastleProvider());
}
}