View Javadoc
1   package cn.home1.oss.lib.common.crypto;
2   
3   import static java.nio.charset.StandardCharsets.UTF_8;
4   import static java.util.Arrays.copyOfRange;
5   import static javax.crypto.Cipher.DECRYPT_MODE;
6   
7   import lombok.Getter;
8   import lombok.SneakyThrows;
9   
10  import java.nio.charset.Charset;
11  import java.security.Provider;
12  
13  import javax.crypto.BadPaddingException;
14  import javax.crypto.Cipher;
15  import javax.crypto.IllegalBlockSizeException;
16  
17  import cn.home1.oss.lib.common.CodecUtils;
18  
19  /**
20   * Created by zhanghaolun on 16/11/17.
21   */
22  public class AesDecryptor implements EncodeDecryptor {
23  
24    @Getter
25    private final Charset charset;
26    private final Provider provider;
27    private final AesCbcKey key;
28  
29    public AesDecryptor(final Provider provider, final KeyExpression keyExpression) {
30      this.charset = UTF_8;
31      this.provider = provider;
32      this.key = new AesCbcKey(keyExpression);
33    }
34  
35    @Override
36    public String decrypt(final String encryptedAndEncoded) {
37      return new String(this.decryptBytes(encryptedAndEncoded), this.charset);
38    }
39  
40    public byte[] decryptBytes(final String encryptedAndEncoded) {
41      final byte[] unencrypted;
42      try {
43        // 使用BASE64对密文进行解码
44        final byte[] decoded = CodecUtils.decodeBase64(encryptedAndEncoded);
45        // 解密
46        unencrypted = this.decryptCipher().doFinal(decoded);
47      } catch (final IllegalBlockSizeException | BadPaddingException | IllegalArgumentException cause) {
48        throw new AesException(AesException.AesError.DECRYPT_AES_ERROR, cause);
49      }
50      try {
51        // 去除补位字符
52        final byte[] unpad = Pkcs7Encoder.PKCS7_UTF8_BLOCK32.decode(unencrypted);
53        return copyOfRange(unpad, 16, unpad.length);
54      } catch (final IllegalArgumentException cause) {
55        throw new AesException(AesException.AesError.ILLEGAL_BUFFER, cause);
56      }
57    }
58  
59    @SneakyThrows
60    Cipher decryptCipher() {
61      final Cipher cipher = Cipher.getInstance(CryptoConstants.AES_CBC_NOPADDING, this.provider);// 设置解密模式为AES的CBC模式
62      cipher.init(DECRYPT_MODE, this.key.getKeySpec(), this.key.getCbcIv());
63      return cipher;
64    }
65  }