# Encrypt - AES128 CBC(with iv) example code
화면 요청 에서 부터 시작한 암호화 복호화!!
대략적인 test code를 확인하려면 아래 링크에서 확인 가능 합니다.
# 환경
# tool: STS 4.13.0
# version: 2.7.3-SNAPSHOT
# java: 11
# type: MAVEN
# view: THYMELEAF
# jQuery: 3.6.0
# 페이지
# PROPERTIES FILE
## CRYPTO
crypto.aes.algorithm = AES/CBC/PKCS5Padding
crypto.aes.iv = ENC(a4FahIzQQNWuhPMun12NSicmzNULaZ4RO1IhtzQixAo=)
crypto.aes128.key = ENC(ASyujlUDkqjrnCQBRK+vpdVYUZOr0dTqG6mFGmlthpE=)
crypto.aes256.key = ENC(zDZ8Qg97908xPP0K7NQ32Ku9JYTb+ur+6Oc+R6gLgKpt0EsOJb5huipD7hjuYkaq)
# Configuration
@Configuration
public class CryptoConfig {
public final static String DEFAULT_CHAR_SET = "UTF-8";
@Value("${crypto.aes.algorithm}")
private String aesAlgorithm;
@Value("${crypto.aes.iv}")
private String aesIv;
@Value("${crypto.aes128.key}")
private String aes128SecretKey;
@Bean("aes128Encryptor")
public Cipher aes128Encryptor() {
try {
SecretKeySpec secretKey = new SecretKeySpec(aes128SecretKey.getBytes(DEFAULT_CHAR_SET), "AES");
IvParameterSpec secretIv = new IvParameterSpec(aesIv.getBytes(DEFAULT_CHAR_SET));
Cipher cipher = Cipher.getInstance(aesAlgorithm);
cipher.init(Cipher.ENCRYPT_MODE, secretKey, secretIv);
return cipher;
} catch (InvalidKeyException | InvalidAlgorithmParameterException | NoSuchAlgorithmException | NoSuchPaddingException| UnsupportedEncodingException e) {
e.printStackTrace();
}
return null;
}
@Bean("aes128Decryptor")
public Cipher aes128Decryptor() {
try {
SecretKeySpec secretKey = new SecretKeySpec(aes128SecretKey.getBytes(DEFAULT_CHAR_SET), "AES");
IvParameterSpec secretIv = new IvParameterSpec(aesIv.getBytes(DEFAULT_CHAR_SET));
Cipher cipher = Cipher.getInstance(aesAlgorithm);
cipher.init(Cipher.DECRYPT_MODE, secretKey, secretIv);
return cipher;
} catch (InvalidKeyException | InvalidAlgorithmParameterException | NoSuchAlgorithmException | NoSuchPaddingException| UnsupportedEncodingException e) {
e.printStackTrace();
}
return null;
}
}
# Service
@Service
public class EncryptService {
@Autowired
private Cipher aes128Encryptor;
@Autowired
private Cipher aes128Decryptor;
/**
* AES 128 CBC WITH IV ENCRYPT
*/
public String encryptAes128(String decryptStr, String charSet) {
String encryptStr = "";
try {
byte[] encryptBytes = aes128Encryptor.doFinal(decryptStr.getBytes(charSet));
encryptStr = Base64.getEncoder().encodeToString(encryptBytes);
} catch (Exception e) {
e.printStackTrace();
}
return encryptStr;
}
/**
* AES 128 CBC WITH IV DECRYPT
*/
public String decryptAes128(String encryptStr, String charSet) {
String decryptStr = "";
try {
byte[] encryptBytes = Base64.getDecoder().decode(encryptStr);
byte[] decryptBytes = aes128Decryptor.doFinal(encryptBytes);
decryptStr = new String(decryptBytes, charSet);
} catch (Exception e) {
e.printStackTrace();
}
return decryptStr;
}
}
# Controller
@Slf4j
@Controller
@RequestMapping("/test/encrypt")
public class TestEncryptController {
@Autowired
private EncryptService encryptService;
@PostMapping("/aes/{num}/{type}")
@ResponseBody
public Map<String, String> aes(@PathVariable String num, @PathVariable String type, @RequestParam String before) {
log.debug("[PARAMETER] {}", before);
String after = "";
if(StringUtils.isNotEmpty(before)) {
if("256".equals(num) && "enc".equals(type)) {
after = encryptService.encryptAes256(before, CryptoConfig.DEFAULT_CHAR_SET);
} else if("256".equals(num) && "dec".equals(type)) {
after = encryptService.decryptAes256(before, CryptoConfig.DEFAULT_CHAR_SET);
} else if("128".equals(num) && "enc".equals(type)) {
after = encryptService.encryptAes128(before, CryptoConfig.DEFAULT_CHAR_SET);
} else if("128".equals(num) && "dec".equals(type)) {
after = encryptService.decryptAes128(before, CryptoConfig.DEFAULT_CHAR_SET);
}
}
Map<String, String> response = new HashMap<String, String>();
response.put("before", before);
response.put("after", after);
return response;
}
}
# HTML
<div>
<h3>AES Encrypt/Decrypt</h3>
<input type="text" id="encrypt" placeholder="Encrypt Text" style="display: inline;"/>
<input type="button" onclick="test.crypto('256', 'enc')" value="ENCRYPT256" style="display: inline;"/>
<input type="button" onclick="test.crypto('128', 'enc')" value="ENCRYPT128" style="display: inline;"/>
<br>
<input type="text" id="decrypt" placeholder="Decrypt Text" style="display: inline;"/>
<input type="button" onclick="test.crypto('256', 'dec')" value="DECRYPT256" style="display: inline;"/>
<input type="button" onclick="test.crypto('128', 'dec')" value="DECRYPT128" style="display: inline;"/>
<br>
</div>
# javascript (jQuery)
const test = {
crypto: function(num, type) {
const input = {
before: (type === 'enc') ? $('#encrypt').val() : $('#decrypt').val()
}
AjaxUtils.sendPost(`/test/encrypt/aes/${num}/${type}`, input,
function(result) {
console.log("result:", result.before);
console.log("result:", result.after);
}
);
},
}
const AjaxUtils = {
sendPost: function(url, input, cbSuccess) {
$.ajax(url, {
// options
method : "POST",
data : input,
dataType : "json",
// success
}).done(function(output, _, _) {// 1:data, 2:textStatus, 3:jqXHR
cbSuccess(output);
})
}
}
# LOG
// ENCRYPT128 Click!!
// Controller
// request: ["128","enc","TEST CODE"]
[PARAMETER] TEST CODE
// response: {"before":"TEST CODE","after":"KocYFcSNxooeTIpCIEdg8Q=="}
// JAVASCRIPT
result: TEST CODE
result: KocYFcSNxooeTIpCIEdg8Q==
// DECRYPT128 Click!!
// Controller
// request: ["128","dec","KocYFcSNxooeTIpCIEdg8Q=="]
[PARAMETER] TEST CODE
// response: {"before":"KocYFcSNxooeTIpCIEdg8Q==","after":"TEST CODE"}
// JAVASCRIPT
result: KocYFcSNxooeTIpCIEdg8Q==
result: TEST CODE
# 마치며.
- https://hjho95.tistory.com/25 에 있는 내용을 보게 되면
- 블로그 본문 테스트 코드 처럼 iv 값을 고정된 값으로 사용하면 문제가 될 수 있다는 내용이 인용되어 있다.
- 블로그 본문은 aes128 의 cbc 타입으로만 작성하였는데 링크 걸린 블로그 내용엔 aes128/256, ecb, cbc 타입으로 테스트 코드를 작성해 두었다.
# 암복호화 시리즈
https://hjho95.tistory.com/25 Encrypt - AES128/256 ECB and CBC(with random iv) 테스트 코드
https://hjho95.tistory.com/26 Encrypt - AES128 CBC(with iv) example code
https://hjho95.tistory.com/27 Encrypt - SHA256(with salt) MessageDigest example code
# 암복호화 시리즈 참조 페이지
aes example: https://aesencryption.net/
cbc vs ecb: https://yoda.wiki/wiki/Block_cipher_mode_of_operation
sha example: http://wiki.hash.kr/index.php/SHA256#cite_note-8
'스프링 부트' 카테고리의 다른 글
[SpringBoot] 필터를 이용하여 요청 로그 남기기! (CommonsRequestLoggingFilter) (0) | 2022.10.22 |
---|---|
[SpringBoot] Encrypt - SHA256(with salt) MessageDigest example code (2) | 2022.10.03 |
[SpringBoot] Encrypt - AES128/256 ECB and CBC(with random iv) 테스트 코드 (2) | 2022.10.03 |
[SpringBoot] jdk 1.8 > jdk 11 로 변경하기 (2) | 2022.09.12 |
[SpringBoot] ajax - POST방식으로 PUT, PATCH, DELETE 사용하기! (HiddenHttpMethodFilter) (0) | 2022.08.15 |