Skip to content

Commit 92095de

Browse files
committed
fix crypto package
1 parent ef4e44e commit 92095de

File tree

21 files changed

+480
-254
lines changed

21 files changed

+480
-254
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package com.codingapi.springboot.security.crypto;
2+
3+
import com.codingapi.springboot.framework.crypto.AES;
4+
import lombok.SneakyThrows;
5+
import org.springframework.util.Base64Utils;
6+
7+
import java.nio.charset.StandardCharsets;
8+
9+
public class MyAES {
10+
11+
private final static MyAES instance = new MyAES();
12+
13+
private AES aes;
14+
15+
private MyAES() {
16+
}
17+
18+
void init(AES aes) {
19+
this.aes = aes;
20+
}
21+
22+
public static MyAES getInstance() {
23+
return instance;
24+
}
25+
26+
@SneakyThrows
27+
public String encode(String input) {
28+
return Base64Utils.encodeToString(aes.encrypt(input.getBytes(StandardCharsets.UTF_8)));
29+
}
30+
31+
@SneakyThrows
32+
public String decode(String input) {
33+
return new String(aes.decrypt(Base64Utils.decodeFromString(input)),StandardCharsets.UTF_8);
34+
}
35+
36+
@SneakyThrows
37+
public byte[] encode(byte[] input) {
38+
return aes.encrypt(input);
39+
}
40+
41+
@SneakyThrows
42+
public byte[] decode(byte[] input){
43+
return aes.decrypt(input);
44+
}
45+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package com.codingapi.springboot.security.crypto;
2+
3+
import com.codingapi.springboot.framework.crypto.AES;
4+
import com.codingapi.springboot.security.properties.SecurityJwtProperties;
5+
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
6+
import org.springframework.context.annotation.Bean;
7+
import org.springframework.context.annotation.Configuration;
8+
import org.springframework.util.Base64Utils;
9+
10+
@Configuration
11+
public class MyCryptoConfiguration {
12+
13+
@Bean
14+
@ConditionalOnMissingBean
15+
public AES aes(SecurityJwtProperties properties) throws Exception {
16+
AES aes = new AES(Base64Utils.decodeFromString(properties.getAseKey()), Base64Utils.decodeFromString(properties.getAseIv()));
17+
MyAES.getInstance().init(aes);
18+
return aes;
19+
}
20+
21+
}

springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/filter/MyAuthenticationFilter.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ protected void doFilterInternal(HttpServletRequest request, HttpServletResponse
4343

4444
Token token = jwt.parser(sign);
4545
if (token.canRestToken()) {
46-
Token newSign = jwt.create(token.getUsername(), token.getDecodePassword(), token.getAuthorities());
46+
Token newSign = jwt.create(token.getUsername(), token.getDecodeIv(), token.getAuthorities());
4747
log.info("reset token ");
4848
response.setHeader(TOKEN_KEY, newSign.getToken());
4949
}

springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/jwt/Jwt.java

+2-3
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
import io.jsonwebtoken.Jwts;
88
import io.jsonwebtoken.security.Keys;
99

10-
import java.io.IOException;
1110
import java.nio.charset.StandardCharsets;
1211
import java.security.Key;
1312
import java.util.List;
@@ -24,8 +23,8 @@ public Jwt(String secretKey, int jwtTime, int jwtRestTime) {
2423
this.jwtRestTime = jwtRestTime;
2524
}
2625

27-
public Token create(String username, String password, List<String> authorities) throws IOException {
28-
Token token = new Token(username, password, authorities, jwtTime, jwtRestTime);
26+
public Token create(String username, String iv, List<String> authorities){
27+
Token token = new Token(username, iv, authorities, jwtTime, jwtRestTime);
2928
String jwt = Jwts.builder().setSubject(token.toJson()).signWith(key).compact();
3029
token.setToken(jwt);
3130
return token;

springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/jwt/Token.java

+9-10
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
11
package com.codingapi.springboot.security.jwt;
22

3-
import com.codingapi.springboot.framework.crypto.AESUtils;
43
import com.codingapi.springboot.framework.serializable.JsonSerializable;
4+
import com.codingapi.springboot.security.crypto.MyAES;
55
import com.codingapi.springboot.security.exception.TokenExpiredException;
66
import lombok.Getter;
77
import lombok.Setter;
88
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
99
import org.springframework.security.core.authority.SimpleGrantedAuthority;
1010

1111
import java.beans.Transient;
12-
import java.io.IOException;
1312
import java.util.ArrayList;
1413
import java.util.Collection;
1514
import java.util.List;
@@ -19,7 +18,7 @@
1918
public class Token implements JsonSerializable {
2019

2120
private String username;
22-
private String certificate;
21+
private String iv;
2322
private String token;
2423
private List<String> authorities;
2524
private long expireTime;
@@ -29,9 +28,9 @@ public class Token implements JsonSerializable {
2928
public Token() {
3029
}
3130

32-
public Token(String username, String certificate, List<String> authorities, int expireValue, int remindValue) throws IOException {
31+
public Token(String username, String iv, List<String> authorities, int expireValue, int remindValue){
3332
this.username = username;
34-
this.certificate = AESUtils.getInstance().encode(certificate);
33+
this.iv = MyAES.getInstance().encode(iv);
3534
this.authorities = authorities;
3635
this.expireTime = System.currentTimeMillis() + expireValue;
3736
this.remindTime = System.currentTimeMillis() + remindValue;
@@ -49,13 +48,13 @@ public boolean isExpire() {
4948
}
5049

5150

52-
public String getCertificate() {
53-
return certificate;
51+
public String getIv() {
52+
return iv;
5453
}
5554

5655
@Transient
57-
public String getDecodePassword() throws IOException {
58-
return AESUtils.getInstance().decode(certificate);
56+
public String getDecodeIv(){
57+
return MyAES.getInstance().decode(iv);
5958
}
6059

6160
public boolean canRestToken() {
@@ -69,7 +68,7 @@ public UsernamePasswordAuthenticationToken getAuthenticationToken() {
6968
for (String authority : authorities) {
7069
simpleGrantedAuthorities.add(new SimpleGrantedAuthority(authority));
7170
}
72-
return new UsernamePasswordAuthenticationToken(this, certificate, simpleGrantedAuthorities);
71+
return new UsernamePasswordAuthenticationToken(this, iv, simpleGrantedAuthorities);
7372
}
7473

7574

springboot-starter-security-jwt/src/main/java/com/codingapi/springboot/security/properties/SecurityJwtProperties.java

+12-1
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,24 @@
77
@Getter
88
public class SecurityJwtProperties {
99

10-
1110
/**
1211
* JWT密钥
1312
* 需大于32位的字符串
1413
*/
1514
private String jwtSecretKey = "codingapi.security.jwt.secretkey";
1615

16+
17+
/**
18+
* aes key
19+
*/
20+
private String aseKey = "QUNEWCQlXiYqJCNYQ1phc0FDRFgkJV4mKiQjWENaYXM=";
21+
22+
/**
23+
* aes iv
24+
*/
25+
private String aseIv = "QUNYRkdIQEVEUyNYQ1phcw==";
26+
27+
1728
/**
1829
* JWT 有效时间(毫秒)
1930
* 15分钟有效期 1000*60*15=900000
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
22
com.codingapi.springboot.security.configurer.WebSecurityConfigurer,\
3+
com.codingapi.springboot.security.crypto.MyCryptoConfiguration,\
34
com.codingapi.springboot.security.AutoConfiguration
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package com.codingapi.springboot.security.jwt;
2+
3+
import com.codingapi.springboot.security.exception.TokenExpiredException;
4+
import org.junit.jupiter.api.Test;
5+
import org.springframework.beans.factory.annotation.Autowired;
6+
import org.springframework.boot.test.context.SpringBootTest;
7+
8+
import java.util.Collections;
9+
import java.util.List;
10+
11+
import static org.junit.jupiter.api.Assertions.*;
12+
13+
@SpringBootTest
14+
class TokenTest {
15+
16+
@Autowired
17+
private Jwt jwt;
18+
19+
@Test
20+
void verify() throws TokenExpiredException {
21+
String username = "admin";
22+
String iv = "123456";
23+
List<String> authorities = Collections.singletonList("ADMIN");
24+
25+
Token token =jwt.create(username,iv,authorities);
26+
token.verify();
27+
28+
Token data = jwt.parser(token.getToken());
29+
assertEquals(data.getDecodeIv(),iv);
30+
}
31+
}
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,9 @@
11
package com.codingapi.springboot.framework;
22

3-
import com.codingapi.springboot.framework.crypto.AES;
4-
import com.codingapi.springboot.framework.properties.BootProperties;
5-
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
6-
import org.springframework.boot.context.properties.ConfigurationProperties;
7-
import org.springframework.context.annotation.Bean;
83
import org.springframework.context.annotation.Configuration;
94

105
@Configuration
116
public class AutoConfiguration {
127

138

14-
@Bean
15-
@ConfigurationProperties(prefix = "codingapi.boot")
16-
public BootProperties bootProperties() {
17-
return new BootProperties();
18-
}
19-
20-
@Bean
21-
@ConditionalOnMissingBean
22-
public AES aes(BootProperties properties) {
23-
return new AES(properties.getAseKey(), properties.getAseIv());
24-
}
25-
269
}
Original file line numberDiff line numberDiff line change
@@ -1,63 +1,110 @@
11
package com.codingapi.springboot.framework.crypto;
22

3-
import org.apache.commons.crypto.stream.CryptoInputStream;
4-
import org.apache.commons.crypto.stream.CryptoOutputStream;
5-
import org.apache.commons.io.IOUtils;
6-
import org.springframework.util.Base64Utils;
3+
import org.bouncycastle.jce.provider.BouncyCastleProvider;
74

5+
import javax.crypto.Cipher;
6+
import javax.crypto.KeyGenerator;
7+
import javax.crypto.SecretKey;
88
import javax.crypto.spec.IvParameterSpec;
99
import javax.crypto.spec.SecretKeySpec;
10-
import java.io.ByteArrayInputStream;
11-
import java.io.ByteArrayOutputStream;
1210
import java.io.IOException;
13-
import java.io.InputStream;
1411
import java.nio.charset.StandardCharsets;
15-
import java.util.Properties;
12+
import java.security.AlgorithmParameters;
13+
import java.security.Key;
14+
import java.security.Security;
15+
import java.util.Random;
1616

1717
public class AES {
1818

19-
private final SecretKeySpec key;
20-
private final IvParameterSpec iv;
21-
private final Properties properties;
22-
private final String transform;
19+
public static final String KEY_ALGORITHM = "AES";
2320

24-
public AES(String transform, byte[] keys, byte[] iv) {
25-
this.key = new SecretKeySpec(keys, "AES");
26-
this.iv = new IvParameterSpec(iv);
27-
this.properties = new Properties();
28-
this.transform = transform;
29-
AESUtils.getInstance().init(this);
21+
public static final String CIPHER_ALGORITHM = "AES/CBC/PKCS7Padding";
22+
23+
private final Key key;
24+
private final AlgorithmParameters iv;
25+
private final String algorithm;
26+
27+
public AES(String algorithm,Key key,AlgorithmParameters iv){
28+
Security.addProvider(new BouncyCastleProvider());
29+
this.algorithm = algorithm;
30+
this.key = key;
31+
this.iv = iv;
32+
}
33+
34+
public AES(String algorithm, int generateKeySize) throws Exception {
35+
Security.addProvider(new BouncyCastleProvider());
36+
this.algorithm = algorithm;
37+
this.key = generateKey(generateKeySize);
38+
this.iv = generateIV(randomIv());
39+
}
40+
41+
public AES(String algorithm, byte[] keys, byte[] ivs) throws Exception{
42+
Security.addProvider(new BouncyCastleProvider());
43+
this.algorithm = algorithm;
44+
this.key = convertToKey(keys);
45+
this.iv = generateIV(ivs);
46+
}
47+
48+
public AES() throws Exception {
49+
this(CIPHER_ALGORITHM,256);
50+
}
51+
52+
53+
public AES(int generateKeySize) throws Exception {
54+
this(CIPHER_ALGORITHM,generateKeySize);
55+
}
56+
57+
public AES(byte[] keys, byte[] ivs) throws Exception{
58+
this(CIPHER_ALGORITHM,keys,ivs);
59+
}
60+
61+
public AES(String key, String iv) throws Exception{
62+
this(CIPHER_ALGORITHM,key.getBytes(StandardCharsets.UTF_8),iv.getBytes(StandardCharsets.UTF_8));
3063
}
3164

65+
private byte[] randomIv(){
66+
Random random = new Random();
67+
byte[] bytes = new byte[16];
68+
random.nextBytes(bytes);
69+
return bytes;
70+
}
3271

33-
public AES(String key, String iv) {
34-
this("AES/CBC/PKCS5Padding", key.getBytes(StandardCharsets.UTF_8), iv.getBytes(StandardCharsets.UTF_8));
72+
private SecretKey generateKey(int keySize) throws Exception {
73+
KeyGenerator keyGenerator = KeyGenerator.getInstance(KEY_ALGORITHM);
74+
keyGenerator.init(keySize);
75+
return keyGenerator.generateKey();
3576
}
3677

3778

38-
public String encode(String input) throws IOException {
39-
return Base64Utils.encodeToString(encode(input.getBytes(StandardCharsets.UTF_8)));
79+
private AlgorithmParameters generateIV(byte[] ivs) throws Exception {
80+
AlgorithmParameters params = AlgorithmParameters.getInstance(KEY_ALGORITHM);
81+
params.init(new IvParameterSpec(ivs));
82+
return params;
4083
}
4184

42-
public String decode(String input) throws IOException {
43-
return new String(decode(Base64Utils.decodeFromString(input)), StandardCharsets.UTF_8);
85+
private Key convertToKey(byte[] keyBytes){
86+
return new SecretKeySpec(keyBytes, KEY_ALGORITHM);
4487
}
4588

89+
public byte[] getKey(){
90+
return key.getEncoded();
91+
}
4692

47-
public byte[] encode(byte[] input) throws IOException {
48-
final ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
49-
try (CryptoOutputStream cos = new CryptoOutputStream(transform, properties, outputStream, key, iv)) {
50-
cos.write(input);
51-
cos.flush();
52-
}
53-
return outputStream.toByteArray();
93+
public byte[] getIv() throws IOException {
94+
return iv.getEncoded();
5495
}
5596

56-
public byte[] decode(byte[] input) throws IOException {
57-
final InputStream inputStream = new ByteArrayInputStream(input);
58-
try (CryptoInputStream cis = new CryptoInputStream(transform, properties, inputStream, key, iv)) {
59-
return IOUtils.toByteArray(cis);
60-
}
97+
public byte[] encrypt(byte[] data) throws Exception {
98+
Cipher cipher = Cipher.getInstance(algorithm);
99+
cipher.init(Cipher.ENCRYPT_MODE, key, iv);
100+
return cipher.doFinal(data);
101+
}
102+
103+
104+
public byte[] decrypt(byte[] encryptedData) throws Exception {
105+
Cipher cipher = Cipher.getInstance(algorithm);
106+
cipher.init(Cipher.DECRYPT_MODE, key, iv);
107+
return cipher.doFinal(encryptedData);
61108
}
62109

63110
}

0 commit comments

Comments
 (0)