1 package cn.home1.oss.lib.common.crypto;
2
3 import static com.google.common.base.Preconditions.checkArgument;
4 import static java.lang.Integer.parseInt;
5
6 import com.google.common.base.Preconditions;
7
8 import lombok.Getter;
9
10 import javax.crypto.spec.IvParameterSpec;
11 import javax.crypto.spec.SecretKeySpec;
12
13 import cn.home1.oss.lib.common.CodecUtils;
14
15
16
17
18 public class AesCbcKey {
19
20 public static final String AES_MODE_CBC = "CBC";
21
22 @Getter
23 private final KeyExpression keyExpression;
24 @Getter
25 private final SecretKeySpec keySpec;
26 @Getter
27 private final IvParameterSpec cbcIv;
28 @Getter
29 private final int cbcIvLength;
30
31 public AesCbcKey(final KeyExpression keyExpression) {
32 this.keyExpression = keyExpression;
33
34 final String spec = keyExpression.getSpec();
35 final int keySize = keySize(spec);
36 final int cbcIvLength = cbcIvLength(spec);
37
38 final String key = keyExpression.getValue();
39 checkArgument(key.endsWith("="), "must ends with '='");
40
41 final byte[] keyBytes = CodecUtils.decodeBase64(key);
42 Preconditions.checkArgument(keyBytes.length * 8 == keySize, AesException.AesError.ILLEGAL_AES_KEY);
43
44 this.keySpec = new SecretKeySpec(keyBytes, CryptoConstants.ALGO_AES);
45
46 this.cbcIv = new IvParameterSpec(keyBytes, 0, cbcIvLength);
47
48 this.cbcIvLength = cbcIvLength;
49 }
50
51 public AesCbcKey(final String keyExpression) {
52 this(new KeyExpression(keyExpression));
53 }
54
55 @Override
56 public String toString() {
57 return this.keyExpression.toString();
58 }
59
60 public static int keySize(final String spec) {
61 return parseInt(spec.split(CryptoConstants.UNDERSCORE)[0].substring(3));
62 }
63
64 public static String keySpec(final int keySize) {
65 return CryptoConstants.ALGO_AES + keySize + CryptoConstants.UNDERSCORE + AES_MODE_CBC + 16;
66 }
67
68 public static int cbcIvLength(final String spec) {
69 return parseInt(spec.substring(spec.indexOf(AES_MODE_CBC) + 3));
70 }
71 }