Spring-JSP

[Spring-JSP] RSA 암호화

Jeong Jeon
반응형

인터넷 서비스에서는 대칭키와 공개키를 이용한 암호화를 다양하게 활용하고 있는데 대표적으로 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 {}
반응형