com.groupbyinc.common.security.AesDecryption Maven / Gradle / Ivy
package com.groupbyinc.common.security;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.StringUtils;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.Mac;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.Provider;
import java.security.Security;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.KeySpec;
import static com.groupbyinc.common.security.AesEncryption.CLIENT_KEY_HASHING_ITERATIONS;
import static com.groupbyinc.common.security.AesUtil.geEncryptSalt;
import static com.groupbyinc.common.security.AesUtil.getMessageAuthenticationCodeSalt;
import static java.nio.charset.StandardCharsets.UTF_8;
public class AesDecryption {
private SecretKey encryptionKey;
private Cipher cipher;
private SecretKey macKey;
private Mac hmac;
public AesDecryption(String clientKey, String customerId)
throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException {
this(clientKey, customerId, new BouncyCastleProvider());
}
public AesDecryption(String clientKey, String customerId, Provider provider) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException {
Security.addProvider(provider);
cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
KeySpec spec = new PBEKeySpec(clientKey.toCharArray(), geEncryptSalt(customerId).getBytes(StandardCharsets.UTF_8), CLIENT_KEY_HASHING_ITERATIONS, 128);
KeySpec macSpec = new PBEKeySpec(clientKey.toCharArray(), getMessageAuthenticationCodeSalt(customerId).getBytes(StandardCharsets.UTF_8), CLIENT_KEY_HASHING_ITERATIONS, 160);
encryptionKey = new SecretKeySpec(factory.generateSecret(spec)
.getEncoded(), "AES");
macKey = new SecretKeySpec(factory.generateSecret(macSpec)
.getEncoded(), "HmacSHA256");
hmac = Mac.getInstance("HmacSHA256");
hmac.init(macKey);
}
public String decrypt(AesContent aesContent) throws InvalidAlgorithmParameterException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
if (aesContent == null) {
throw new IllegalStateException("cannot decrypt null AesContent");
} else if (StringUtils.isBlank(aesContent.getCipherText()) || StringUtils.isBlank(aesContent.getInitialValue()) || StringUtils.isBlank(aesContent.getMessageAuthenticationCode())) {
throw new IllegalStateException("cipher text, IV and messageAuthenticationCode must be provided");
}
byte[] ivBytes = Base64.decodeBase64(aesContent.getInitialValue()
.getBytes(UTF_8));
byte[] cipherTextBytes = Base64.decodeBase64(aesContent.getCipherText()
.getBytes(UTF_8));
byte[] macBytes = Base64.decodeBase64(aesContent.getMessageAuthenticationCode()
.getBytes(UTF_8));
if (!validateMac(ivBytes, cipherTextBytes, macBytes)) {
throw new IllegalStateException("MAC does not match");
}
IvParameterSpec iv = new IvParameterSpec(ivBytes);
cipher.init(Cipher.DECRYPT_MODE, encryptionKey, iv);
byte[] original = cipher.doFinal(cipherTextBytes);
return new String(original, UTF_8);
}
public boolean validateMac(AesContent aesContent) {
if (aesContent == null) {
throw new IllegalStateException("cannot decrypt null AesContent");
} else if (StringUtils.isBlank(aesContent.getCipherText()) || StringUtils.isBlank(aesContent.getInitialValue()) || StringUtils.isBlank(aesContent.getMessageAuthenticationCode())) {
throw new IllegalStateException("cipher text, IV and messageAuthenticationCode must be provided");
}
byte[] ivBytes = Base64.decodeBase64(aesContent.getInitialValue()
.getBytes(UTF_8));
byte[] cipherTextBytes = Base64.decodeBase64(aesContent.getCipherText()
.getBytes(UTF_8));
byte[] macBytes = Base64.decodeBase64(aesContent.getMessageAuthenticationCode()
.getBytes(UTF_8));
return validateMac(ivBytes, cipherTextBytes, macBytes);
}
private boolean validateMac(byte[] ivBytes, byte[] cipherTextBytes, byte[] macBytes) {
byte[] ciperTextAndIv = new byte[cipherTextBytes.length + ivBytes.length];
System.arraycopy(cipherTextBytes, 0, ciperTextAndIv, 0, cipherTextBytes.length);
System.arraycopy(ivBytes, 0, ciperTextAndIv, cipherTextBytes.length, ivBytes.length);
byte[] mac = hmac.doFinal(ciperTextAndIv);
return MessageDigest.isEqual(mac, macBytes);
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy