1 package cn.home1.oss.lib.common.crypto;
2
3 import static java.nio.charset.StandardCharsets.UTF_8;
4 import static javax.crypto.Cipher.ENCRYPT_MODE;
5
6 import lombok.Getter;
7 import lombok.SneakyThrows;
8
9 import java.nio.ByteBuffer;
10 import java.nio.charset.Charset;
11 import java.security.Provider;
12
13 import javax.crypto.Cipher;
14
15 import cn.home1.oss.lib.common.CodecUtils;
16
17
18
19
20 public class AesEncryptor implements EncodeEncryptor {
21
22 @Getter
23 private final Charset charset;
24 private final Provider provider;
25 private final AesCbcKey key;
26
27 public AesEncryptor(final Provider provider, final KeyExpression keyExpression) {
28 this.charset = UTF_8;
29 this.provider = provider;
30 this.key = new AesCbcKey(keyExpression);
31 }
32
33 @Override
34 public String encrypt(final String plainText) {
35 return this.encryptBytes(
36 RandomString.RandomStrings.RANDOM_BASE62.generate(this.key.getCbcIvLength()),
37 plainText.getBytes(this.charset)
38 );
39 }
40
41 @Override
42 public String encrypt(final String plainText, final Integer maxAge) {
43 throw new UnsupportedOperationException();
44 }
45
46 public String encryptBytes(final String random, final byte[] plainBytes) {
47 final byte[] randomBytes = random.getBytes(this.charset);
48 final int nopadLength = randomBytes.length + plainBytes.length;
49
50 final byte[] padBytes = Pkcs7Encoder.PKCS7_UTF8_BLOCK32.encode(nopadLength);
51
52
53
54 final ByteBuffer unencrypted = ByteBuffer.allocate(nopadLength + padBytes.length);
55 unencrypted.put(randomBytes);
56 unencrypted.put(plainBytes);
57 unencrypted.put(padBytes);
58 try {
59
60 final byte[] encrypted = this.encryptCipher().doFinal(unencrypted.array());
61
62 return CodecUtils.encodeBase64(encrypted);
63 } catch (final Exception cause) {
64 throw new AesException(AesException.AesError.ENCRYPT_AES_ERROR, cause);
65 } finally {
66 unencrypted.clear();
67 }
68 }
69
70 @SneakyThrows
71 Cipher encryptCipher() {
72 final Cipher cipher = Cipher.getInstance(CryptoConstants.AES_CBC_NOPADDING, this.provider);
73 cipher.init(ENCRYPT_MODE, this.key.getKeySpec(), this.key.getCbcIv());
74 return cipher;
75 }
76 }