โ
Background Knowledge
๐ก Jasypt:
Java Simplified Encryption Java library that provides simple APIs for encryption and decryption of data, including hashing.
โ๏ธ ํด์ฑ์ด๋?
transforming text into charecters using a one-way cryptographic hash function
- one way cryptographic function
- results in hash value/hash code
- irreversable
- MD5, SHA-1, SHA-256
๐ Encryption
- eversible cryptographic process
- encrypts with an algorithm and a key
- AES, DES, RSA
Hash ๐ Encryption ๐ Encoding
https://www.geeksforgeeks.org/encryption-encoding-hashing/
โ๏ธ Salt?
โsaltโ is random data that is used as an additional input to a hash function along with the plain text being hashed
- thanks to salt, we can defend against attacks and add complexity to the hashing process.
- When hashing a password or any other sensitive data, you can provide a salt along with the data.
- The salt is then combined with the data before hashing, resulting in a unique hash for each input even if the original data is the same.
โ๏ธ ์ธ์ฝ๋ฉ?
process of transforming data into a format that is suitable for a particular type of transmission or storage system
- GOAL: make sure data can be represented and transmitted properly
- Base64, hexadecimal, URL encoding
๐ Encryption
- GOAL: protect data, data confidentiality
โ
Bean์ผ๋ก Jasypt ์ํธํ ์ค์
Jasypt build.gradle ์ถ๊ฐ
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| // redis -> java๋ก redis control
implementation 'redis.clients:jedis:5.1.0'
//jasypt
implementation 'com.github.ulisesbocchio:jasypt-spring-boot-starter:3.0.5'
implementation 'javax.xml.bind:jaxb-api:2.3.1'
// validation
implementation 'org.springframework.boot:spring-boot-starter-validation'
//assertions for testJasyptConfig
implementation 'org.assertj:assertj-core:3.19.0'
//test for testJasyptConfig
implementation 'org.junit.jupiter:junit-jupiter-api:5.8.1'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.1'
|
Jasypt Config
- ์๊น ์ด๋ฉ์ผ ๋ณด๋ผ email Address, ์์ฑํ ์ฑ ๋น๋ฐ๋ฒํธ๋ฅผ yaml์์ ์ํธํํด์ ๊ด๋ฆฌํ๊ธฐ ์ํด ํ์ํจ
- Jasypt secret key: ์ด๋ฉ์ผ ์ฃผ์, ์ฑ ๋น๋ฐ๋ฒํธ ๋ฑ์ ์ํธํํ๊ธฐ ์ํด ํ์ํ ๋น๋ฐ๋ฒํธ
- ์ํธํํ๋ ๋ฉ์๋
stringEncryptor
- ์ํธํ ๋น๋ฐ๋ฒํธ
- ์ด๋ค ์๊ณ ๋ฆฌ์ฆ ์ธ๊ฑด์ง
- ๋ฐ๋ณตํ ํด์ฑ ํ์
- salt ์์ฑ ํด๋์ค
- ์ธ์ฝ๋ฉ ๋ฐฉ์
- salt ์์ฑ ํด๋์ค๋ฅผ ์ง์ ํ์ง ์์ผ๋ฉด default๋ก:
RandomSaltGenerator
- ๊ณ ์ ๋ salt ๊ฐ์ ์ฌ์ฉํ๋ ค๋ฉด
StringFixedSaltGenerator
๋ฅผ ์ฌ์ฉํ๋ฉด ๋๋ค - ๋จ ์ด ๊ฒฝ์ฐ ๋ณตํธํ์์๋ ๊ธฐ์กด์ ์ค์ ํ salt ๊ฐ ์ฌ์ฉํด์ผ์ง๋ง ๋ณตํธํ ๊ฐ๋ฅ
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
| import com.ulisesbocchio.jasyptspringboot.annotation.EnableEncryptableProperties;
import org.jasypt.encryption.StringEncryptor;
import org.jasypt.encryption.pbe.PooledPBEStringEncryptor;
import org.jasypt.encryption.pbe.config.SimpleStringPBEConfig;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
@EnableEncryptableProperties
public class JasyptConfig {
@Value(value= "${jasypt.encryptor.password}")
private String PASSWORD_KEY;
@Bean(name= "jasyptStringEncryptor")
public StringEncryptor stringEncryptor(){
PooledPBEStringEncryptor encryptor= new PooledPBEStringEncryptor();
SimpleStringPBEConfig config= new SimpleStringPBEConfig();
config.setPassword(PASSWORD_KEY);
config.setAlgorithm("PBEWithMD5AndDES");
config.setKeyObtentionIterations("1000"); // ๋ฐ๋ณตํ ํด์ฑ ํ์
config.setPoolSize("1"); // ์ํธํ ์ธ์คํด์ค pool
config.setProviderName("SunJCE");
config.setSaltGeneratorClassName("org.jasypt.salt.RandomSaltGenerator"); // salt ์์ฑ ํด๋์ค
config.setStringOutputType("base64"); // ์ธ์ฝ๋ฉ ๋ฐฉ์
encryptor.setConfig(config);
return encryptor;
}
}
|
application.yaml
PBEWithMD5AndDESย encryption ์ ๊ณตํ๋ ์ฌ์ดํธ์์ ์ํธํ
https://devglan.com/onaline-tools/jasypt-online-encryption-decryption
์ํธํํ email Address, ์์ฑํ ์ฑ ๋น๋ฐ๋ฒํธ๋ฅผ ENC()๋ก ๊ฐ์ธ์ ๋ฃ์ด๋
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
data:
redis:
host: localhost
port: 6379
jasypt:
encryptor:
password: ${JASYPT_SECRET_KEY} //ํ๊ฒฝ๋ณ์
bean: jasyptStringEncryptor
email:
address: ENC(์ํธํํด์ ์ฐ๊ธฐ)
app-password: ENC(์ํธํํด์ ์ฐ๊ธฐ)
jwtpassword:
source: ENC(jwtpassword์ํธํํด์ ์ฐ๊ธฐ)
|
์์ฑ๋ yamlํ์ผ์ ๋ค์๊ณผ ๊ฐ์ด ์๊ฒผ์ ๊ฒ์ด๋ค.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
| server: port:8080
spring:
mvc:
pathmatch:
matching-strategy: ant_path_matcher
autoconfigure: exclude:org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
datasource:
username: ENC(dg0o6RGGnI5v2NTvYqiCeA==)
password: ENC(3S04ny0whtz9bZ4PvLkMuIFXmnRB0pjy)
driver-class-name: org.mariadb.jdbc.Driver
# url: jdbc:mariadb://sohan2.c7suy242wrpp.eu-west-1.rds.amazonaws.com:3306/shopping_mall?useUnicode=true&characterEncoding=UTF-8
url: jdbc:mariadb://localhost:3306/BackEndProject_2_verSoh?useUnicode=true&characterEncoding=UTF-8
jpa:
show-sql: true
data:
redis:
host: localhost
port: 6379
jasypt:
encryptor:
password: ${JASYPT_SECRET_KEY}
bean: jasyptStringEncryptor
email:
address: ENC(9FFPzV1CpODhRFqWQPJg6RDj9yuVaV4jnT0FQvc4oE0=)
app-password: ENC(3ViVckG3lnbAeZWKhkWT06ChwI8rfEazJBqXJL5fBak=)
jwtpassword:
source: ENC(/CzryCVnQTpLw20DGA4M7ENiN+eg+PDQ)
logging:
level: debug
|
๐ด TroubleShooting
jwtpassword:
๋ํ ENC()
๋ก ๊ฐ์ธ์ ์ํธํํ๋๋, jwtTokenProvider
์ ๋ฌธ์ ๊ฐ ์๋ค๊ณ error๊ฐ ๋ฐ์ํ๋ค.
์ yaml
์ฒ๋ผ ๋ฐ๊ฟ์ค๊ฑฐ๋ฉด, ๋ง์ฐฌ๊ฐ์ง๋ก jwtTokenProvider
ํ์ผ์์ jwtpassword:
๋ํ ์์ ํด ์ฃผ์ด์ผ ํ๋ค.
yaml
ํ์ผ์ ์ด๋๋ฅผ ๋ณด๋ฉด ๋๋์ง๋ฅผ ์๋ ค์ฃผ์ด์ผ ํจ.
jwtpassword ์ source๋ฅผ ๋ณด๋ ด!
1
2
3
4
5
6
7
8
9
10
11
| @Component
@RequiredArgsConstructor
public class JwtTokenProvider {
private final UserDetailsService userDetailsService;
// @Value("${JWT_SECRET_KEY}") //์์ ์
@Value("${jwtpassword.source}") //์์ ํ
private String secretKey;
private String key;
//JwtTokenProvider methods...
}
|
โ JasyptConfigTest
์์ ์ํธํ
๋๋ JasyptConfigTest
์์ System.out.printlnํด์ ์ํธํํด๋ ๋๋ค.
์ ์ฌ์ดํธ์์ ์ํธํํ์ผ๋ฉด ์ด ํ์ผ ์์ด๋ ๋จ.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
| import org.assertj.core.api.Assertions;
import org.jasypt.encryption.pbe.StandardPBEStringEncryptor;
import org.junit.jupiter.api.Test;
public class JasyptConfigTest {
@Test
void jasypt(){
String url= "db์ฃผ์";
String username= "๋ค์";
String password= "๋น๋ฐ๋ฒํธ";
String encryptUrl= jasyptEncrypt(url);
String encryptUsername= jasyptEncrypt(username);
String encryptPassword= jasyptEncrypt(password);
System.out.println("encryptUrl : " + encryptUrl);
System.out.println("encryptUrl : " + encryptUsername);
System.out.println("encryptPassword : " + encryptPassword);
Assertions.assertThat(url).isEqualTo(jasyptDecrypt(encryptUrl));
}
private String jasyptEncrypt(String input){
String key= "cesarpoo";
StandardPBEStringEncryptor encryptor= new StandardPBEStringEncryptor();
encryptor.setAlgorithm("PBEWithMD5AndDES");
encryptor.setPassword(key);
return encryptor.encrypt(input);
}
private String jasyptDecrypt(String input){
String key= "cesarpoo";
StandardPBEStringEncryptor encryptor= new StandardPBEStringEncryptor();
encryptor.setAlgorithm("PBEWithMD5AndDES");
encryptor.setPassword(key);
return encryptor.decrypt(input);
}
}
|
โ
Run redis server on EC2
Redis server install
์๋ฒ ์์ํ๋ ๋ช
๋ น์ด
1
| sudo systemctl start redis
|
์๋ฒ ์ํ ํ์ธํ๋ ๋ช
๋ น์ด
1
| sudo systemctl status redis
|
redis.conf
- Redis.conf์ ๋ค์ด๊ฐ์
1
| sudo nano /etc/redis/redis.conf
|
- ๋น๋ฐ๋ฒํธ ๋ฐ๊พธ๊ธฐ(์ฐธ๊ณ ์๋ฃ)
- protected-mode ๋ฐ๊พธ๊ธฐ
- ๋ฐฉํ๋ฒฝ ํ์ด์ฃผ๊ธฐ
์๋ฒ ์ฌ์์ ๋ช
๋ น์ด
1
| sudo systemctl restart redis
|
ํฌํธ 6379 ์ด๊ธฐ
redis๋ ๋ณดํต ํฌํธ 6379์์ ์คํ๋๋ค.
1
| sudo netstat -tuln | grep 6379
|
EC2์ ์ฐ๊ฒฐ๋ redis์๋ฒ ์ฐ๊ฒฐ
1
| redis-cli -h -p 6379 -a
|
๐ก ์ฐธ๊ณ
https://wookgu.tistory.com/26
Redis Config??? ํ์๊ฐ ์์๋คโฆโฆ
๐ก ์ฐธ๊ณ
1
2
3
4
5
| https://velog.io/@jinny-l/spring-jasypt-encrypt-yml-and-store-encryption-key-as-environment-variable
-- ํ์์ด ๋ธ๋ก๊ทธ
https://boulder-hippodraco-244.notion.site/Email-Spring-Boot-3-2-52fa5aa2f1154691bd7c2a8fea3d89a6
|