인터넷 서비스에서는 대칭키와 공개키를 이용한 암호화를 다양하게 활용하고 있는데 대표적으로 TLS(Transport Layer Security)라고 불리는 암호 규약이 대표적이며 쉽게 예를 들면 웹 브라우징 시에 사용되는 보안 계층을 말한다.
TLS는 기존의 SSL(Secure Sockets Layer)가 표준화되면서 바뀐 이름이며 우리가 인터넷에서 익숙하게 접하는 HTTPS 프로토콜에서 이를 활용하고 있다.
구분목적
Public Key |
누구에게나 공개될 수 있음 / 메세지를 보내는 발신자는 공개키를 통해 정보를 암호화 |
Private Key |
수신자는 비밀키를 암호화된 메세지를 복호화 하는데 사용/ 외부에 노출되지 않도록 안전하게 보관해야 함 |
-
순서
-
1. Client 단에서 RSA를 비동기 호출하여 Public Key 와 Private Key를 생성한다. => RSA init()실행
-
2. 생성된 Public key로 암호화를 진행한다.
-
var rsa = new RSAKey();
rsa.setPublic(result.data.RSAModulus,result.data.RSAExponent);
newPassword = rsa.encrypt(newPassword);
-
3. 암호화된 정보를 Server단으로 전송하여 Server단에서 복호화를 진행한다. => decryptRsa() 실행
-
이때 session에 넣어두었던 PrivateKey를 꺼내 복호화한다.
-
4. 복호화 완료
1). RSASercureUtil.java
-
RSA 암호화 모듈을 만들어놓는다.
-
RSA Public Key는 2개의 Integer, 즉 “Modulus” 와 “Exponent”로 불리는 2개의 Integer로 구성되어 있다.
-
initRsa를 호출하여 Private Key를 Session 정보에 담는다. / 공개키는 return;
public class RSASecureUtil {
private static String RSA_WEB_KEY = "RSA_KEY"; // 개인키 session key
private static String RSA_INSTANCE = "RSA"; // rsa transformation
/**
* rsa 복호화
*
* @param privateKey
* @param securedValue
* @return
* @throws Exception
*/
public static String decryptRsa(HttpServletRequest req,String securedValue) throws Exception {
HttpSession session = req.getSession();
PrivateKey privateKey = (PrivateKey) session.getAttribute(RSASecureUtil.RSA_WEB_KEY);
Cipher cipher = Cipher.getInstance(RSASecureUtil.RSA_INSTANCE);
byte[] encryptedBytes = hexToByteArray(securedValue);
cipher.init(Cipher.DECRYPT_MODE, privateKey);
byte[] decryptedBytes = cipher.doFinal(encryptedBytes);
String decryptedValue = new String(decryptedBytes, "utf-8"); // 문자 인코딩 주의.
return decryptedValue;
}
/**
* 16진 문자열을 byte 배열로 변환한다.
*
* @param hex
* @return
*/
public static byte[] hexToByteArray(String hex) {
if (hex == null || hex.length() % 2 != 0) { return new byte[] {}; }
byte[] bytes = new byte[hex.length() / 2];
for (int i = 0; i < hex.length(); i += 2) {
byte value = (byte) Integer.parseInt(hex.substring(i, i + 2), 16);
bytes[(int) Math.floor(i / 2)] = value;
}
return bytes;
}
/**
* rsa 공개키, 개인키 생성
*
* @param request
*/
public static HashMap<String,Object> initRsa(HttpServletRequest request) {
HttpSession session = request.getSession();
HashMap<String,Object> resultMap = new HashMap<String,Object>();
KeyPairGenerator generator;
try {
generator = KeyPairGenerator.getInstance(RSASecureUtil.RSA_INSTANCE);
generator.initialize(1024);
KeyPair keyPair = generator.genKeyPair();
KeyFactory keyFactory = KeyFactory.getInstance(RSASecureUtil.RSA_INSTANCE);
PublicKey publicKey = keyPair.getPublic();
PrivateKey privateKey = keyPair.getPrivate();
session.setAttribute(RSASecureUtil.RSA_WEB_KEY, privateKey); // session에 RSA 개인키를 세션에 저장
RSAPublicKeySpec publicSpec = (RSAPublicKeySpec) keyFactory.getKeySpec(publicKey, RSAPublicKeySpec.class);
String publicKeyModulus = publicSpec.getModulus().toString(16);
String publicKeyExponent = publicSpec.getPublicExponent().toString(16);
HashMap<String,String> data = new HashMap<String,String>();
data.put("RSAModulus", publicKeyModulus);
data.put("RSAExponent", publicKeyExponent);
resultMap.put("result", Constant.XHR_REQUEST_SUCCESS);
resultMap.put("data",data);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
resultMap.put("result", Constant.XHR_REQUEST_FAIL);
}
return resultMap;
}
/**
* rsa 세션에서 개인키 파기
* @param request
*/
public static void destroyRsa(HttpServletRequest request) {
HttpSession session = request.getSession();
PrivateKey key = (PrivateKey) session.getAttribute(RSASecureUtil.RSA_WEB_KEY);
if (key != null) { // 기존 key 파기
session.removeAttribute(RSASecureUtil.RSA_WEB_KEY);
}
}
}
2).javascript.js
$.ajax({
type : "GET"
,url : "/rsaKey"
,data : null
,dataType : "json"
// ,async : true
,success : function(result, status, xhr) {
if(result.result === XHR_REQUEST_SUCCESS){
// rsaKey요청 성공 시
if(!isNull(newPassword) || !isNull(newPasswordCheck)){
var rsa = new RSAKey();
rsa.setPublic(result.data.RSAModulus,result.data.RSAExponent);
newPassword = rsa.encrypt(newPassword);
} else {}
'Spring-JSP' 카테고리의 다른 글
[Spring-JSP] 파일업로드 처리 / 파일(단,다중) + 추가정보 @ModelAttribute (0) | 2021.01.29 |
---|---|
[Spring-JSP]문자열 출력시 공백 및 줄바꿈 적용 (0) | 2021.01.22 |
[Spring-JSP] AES-256 암호화 (0) | 2020.11.17 |
[Spring-JSP] SHA-256 / SHA-512 암호화 (0) | 2020.11.17 |
Paging Module - Java + javascript (0) | 2020.11.14 |