AesDecryptor.java

package cn.home1.oss.lib.common.crypto;

import static java.nio.charset.StandardCharsets.UTF_8;
import static java.util.Arrays.copyOfRange;
import static javax.crypto.Cipher.DECRYPT_MODE;

import lombok.Getter;
import lombok.SneakyThrows;

import java.nio.charset.Charset;
import java.security.Provider;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;

import cn.home1.oss.lib.common.CodecUtils;

/**
 * Created by zhanghaolun on 16/11/17.
 */
public class AesDecryptor implements EncodeDecryptor {

  @Getter
  private final Charset charset;
  private final Provider provider;
  private final AesCbcKey key;

  public AesDecryptor(final Provider provider, final KeyExpression keyExpression) {
    this.charset = UTF_8;
    this.provider = provider;
    this.key = new AesCbcKey(keyExpression);
  }

  @Override
  public String decrypt(final String encryptedAndEncoded) {
    return new String(this.decryptBytes(encryptedAndEncoded), this.charset);
  }

  public byte[] decryptBytes(final String encryptedAndEncoded) {
    final byte[] unencrypted;
    try {
      // 使用BASE64对密文进行解码
      final byte[] decoded = CodecUtils.decodeBase64(encryptedAndEncoded);
      // 解密
      unencrypted = this.decryptCipher().doFinal(decoded);
    } catch (final IllegalBlockSizeException | BadPaddingException | IllegalArgumentException cause) {
      throw new AesException(AesException.AesError.DECRYPT_AES_ERROR, cause);
    }
    try {
      // 去除补位字符
      final byte[] unpad = Pkcs7Encoder.PKCS7_UTF8_BLOCK32.decode(unencrypted);
      return copyOfRange(unpad, 16, unpad.length);
    } catch (final IllegalArgumentException cause) {
      throw new AesException(AesException.AesError.ILLEGAL_BUFFER, cause);
    }
  }

  @SneakyThrows
  Cipher decryptCipher() {
    final Cipher cipher = Cipher.getInstance(CryptoConstants.AES_CBC_NOPADDING, this.provider);// 设置解密模式为AES的CBC模式
    cipher.init(DECRYPT_MODE, this.key.getKeySpec(), this.key.getCbcIv());
    return cipher;
  }
}