-
JSP(사용자 정보 암호화 / 복호화 처리)JSP 2020. 6. 18. 15:03
사용자 정보 암호화 / 복호화 처리
암호화 종류
1. 양방향 암호화
1.1 대칭키 암호화 : 송,수신 평문을 암호화하고 복호화를 진행하면서 암호화시 활용된 보안키값을 복호화하여 평문으로
변경시에도 활용하는것을 의미함.
1.1.1 특징 : 공개키 암호화에비해 암호화/복호화를 통한 송,수신 속도가 빠름.
암호화되어 송신되는 전송 데이타의 길이가 공개키에비해 짧음.
1.1.2 암호화 알고리즘: SEED(KISA 권장), ARIA, DES, MISTY
1.2 공개키 암호화 : 수신 측에서는 암호화 송신을위해 비밀키와 공개키를 생성하고 송신측에게공개키(public)를 제공해 (비대칭키 암호화)송신측에서는 제공된 공개키를 이용해
평문을 암호화해 전송하고, 수신측에서는 비밀키(private)를 활용해 수신 데이타를
평문으로 변경함.
1.2.1 특징 : 암호화 속도가 대칭키 암호화에비해 느림.
1.2.2 암호화 알고리즘 : RSA(KISA 권장), KCDSA, ECC1.3 해쉬 암호화 : 해쉬함수(송신 정보를 작은 데이타[해쉬코드]로 재가공하며, 난수를 활용함.)
를 이용해 암호화한 평문을 송신.
해쉬함수를 이용해 암호화된 데이타는 복호화될수 없음.
수신측에서는 실 수신문 대상의 검증을위한 데이타 지문으로 활용됨.
1.3.1 암호화 알고리즘 : SHA1|2|SHA256(KISA 권장)|SHA512, MD5
2. 단방향 암호화
2. 암호화 알고리즘
MD5(Message Digest Algorithm 5) : 128bit hashcode를 제공하는 단방향(암호화) 알고리즘 기법으로
2006년도 복호화되는 결함이 발견되어 더이상 암호화 알고리즘으로
사용되지 않음.(위변조가 가능함)
Base64Util : 2진 데이터를 64개의 아스키 텍스트로 변환하거나 연변환하는 인코딩 기법으로MD5를 통해 암호화 해싱된값을 문자열로 출력시 활용되며, 원본 해싱값보다 33% 값이 커짐.
송신 대상의 평문을 아스키 코드로 변환하고 2진화데이타로 변환시키고,변환된 2진데이타를 4개의 6bit씩으로 다시 변환처리.
SHA[1|2] (Secure Hash Algorithm) : MD5의 위변조 결함에 대안으로 마련된 단방향 암호화 알고리즘.
한국정보보호협회(KISA의 권유로 SHA1+salt를 권장하고 있음.).
Rainbow Table을 통해 복호화될 가능성이 존재하는 불완전한 알고리즘.
SHA1|SHA2 사용불가. SHA256|SHA512 활용 추천.
AES(Advanced Encryption Standard) : 미 연방 표준 차세대 128bit 암호화 알고리즘으로 암/복호화 가능.
AES(Advanced Encryption Standard) : 미 연방 표준 차세대 128bit 암호화 알고리즘으로 암/복호화 가능.
RSA(MIT의 Ronald Rivest, Adi Shamir, Leconard Adleman 3인에의해 개발된 공개키 암호화 알고리즘)
스탠포드대에서 배포한 javascript 기반 RSA and ECC in JavaScript 라이브러리를 이용한 암호화시 속도비교
www-cs-students.stanford.edu/~tjw/jsbn/)
Chrome FireFox IE Mobile
RSA public, 512 bit, e=3 0ms 1ms 4ms 40ms
RSA public, 512 bit, e=F4 1ms 6ms 20ms 140ms
RSA public, 1024 bit, e=3 1ms 3ms 10ms 90ms
RSA public, 1024 bit, e=F4 2ms 15ms 70ms 180ms
공개키 비밀키 만드는 예제
[CryptoGenerator.java]
package kr.or.ddit.utiles; import java.io.UnsupportedEncodingException; import java.security.InvalidKeyException; import java.security.KeyFactory; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; import java.security.PublicKey; import java.security.spec.InvalidKeySpecException; import java.security.spec.RSAPublicKeySpec; import java.util.HashMap; import java.util.Map; import javax.crypto.BadPaddingException; import javax.crypto.Cipher; import javax.crypto.IllegalBlockSizeException; import javax.crypto.NoSuchPaddingException; import javax.servlet.http.HttpSession; public class CryptoGenerator { // 암, 복호화 : 공개키 + 비밀키 (생성시 동반 생성, 1회 활용하고 폐기) // 반환값 : 공개키(가수부, 지수부 구분) public static Map<String, String> generatePairKey(HttpSession session) { // 공개키 + 비밀키 생성 KeyPairGenerator keyGenerator = null; // 생성된 공개키 + 비밀키 KeyPair keyPair = null; //공개키 PublicKey publicKey = null; //비밀키 PrivateKey privateKey = null; // 공개키 = 가수부 + 지수부 KeyFactory keyFactory = null; Map<String, String> publicKeyMap = new HashMap<String, String>(); try{ keyGenerator = KeyPairGenerator.getInstance("RSA"); // 공개키, 비밀키 생성시 사이즈 설정 : byte 단위 // 사이즈를 결정하는데 반드시 짝수이어야 함 keyGenerator.initialize(2048); //생성된 공개키, 비밀키 취득 keyPair = keyGenerator.generateKeyPair(); //공개키 취득 publicKey = keyPair.getPublic(); //비밀키 취득 privateKey = keyPair.getPrivate(); session.setAttribute("privateKey", privateKey); // 공개키를 가수부와 지수부로 나눠야함 // 공개키(Double Type) : 가수부 + 지수부 => 클라이언트에 제공 // ex) -143.12344556 // float(32bit 단정도 소수) : 부호비트 1bit(양수 0 | 음수 1) + 지수 8bit(소숫점 자리수) + 가수 23bit(실수 표현) // double(64bit 배정도 소수) : 부호비트 1bit(양수 0 | 음수 1) + 지수 11bit(소숫점 자리수) + 가수 52bit(실수 표현) // 공개키가 어떤 알고리즘으로 되어있는지 설정 keyFactory = KeyFactory.getInstance("RSA"); RSAPublicKeySpec publicKeySpec = (RSAPublicKeySpec)keyFactory.getKeySpec(publicKey, RSAPublicKeySpec.class); // 공개키 가수부 String publicModulus = publicKeySpec.getModulus().toString(16); // 공개키 지수부 String publicExponent = publicKeySpec.getPublicExponent().toString(16); publicKeyMap.put("publicModulus", publicModulus); publicKeyMap.put("publicExponent", publicExponent); }catch(NoSuchAlgorithmException e1){ e1.printStackTrace(); }catch(InvalidKeySpecException e2){ e2.printStackTrace(); } return publicKeyMap; } //암호문을 평문으로 복호화 public static String decryptRSA(HttpSession session, String secureValue){ String returnValue = ""; PrivateKey privateKey = (PrivateKey) session.getAttribute("pirvateKey"); try{ // 평문으로 바꿀 때? Cipher cipher = Cipher.getInstance("RSA"); //암호문이 어떤 암호화 방식으로 전달되었는지 cipher.init(Cipher.DECRYPT_MODE, privateKey); // 암호문은 짝수 단위로 바이너리 코드로 존재 // hextoByteArray라는 메소드는 직접 만들어야함 byte[] targetByte = hextoByteArray(secureValue); byte[] beforeString = cipher.doFinal(targetByte); returnValue = new String(beforeString, "UTF-8"); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (NoSuchPaddingException e) { e.printStackTrace(); } catch (InvalidKeyException e) { e.printStackTrace(); } catch (IllegalBlockSizeException e) { e.printStackTrace(); } catch (BadPaddingException e) { e.printStackTrace(); } catch (UnsupportedEncodingException e) { // TODO Auto-generated catch block e.printStackTrace(); } return returnValue; } private static byte[] hextoByteArray(String secureValue) { // 암호문이 null이거나 짝수가 아니면 암호문이 암호화 에러. if(secureValue == null || secureValue.length()%2 != 0){ return new byte[]{}; } byte[] bytes = new byte[secureValue.length()/2]; for(int i = 0; i < secureValue.length(); i+=2){ byte value = (byte)Integer.parseInt(secureValue.substring(i,i+2), 16); bytes[(int)Math.floor(i/2)] = value; } return bytes; } }
jsp에서 사용 예제
필요 js 넣기
www-cs-students.stanford.edu/~tjw/jsbn/
[loginForm.jsp]
<%@page import="java.util.Map"%> <%@page import="kr.or.ddit.utiles.CryptoGenerator"%> <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <% // 요청할 때마다 공개키, 비밀키가 새로 만들어짐 세션에 계속 갱신 Map<String, String> publicKeyMap = CryptoGenerator.generatePairKey(session); //pageContext.setAttribute("publicKeyMap", publicKeyMap); 한거나 마찬가지? %> <c:url var ="loginCheckURL" value="/12/loginCheck.jsp"></c:url> <c:set var="publicKeyMap" value ="<%=publicKeyMap %>"></c:set> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <link rel="stylesheet" href="${pageContext.request.contextPath }/css/admin.css" type="text/css"> <script type='text/javascript' src='http://code.jquery.com/jquery-latest.js'></script> <script type = "text/javascript" src ="${pageContext.request.contextPath}/js/common/validation.js "></script> <script type='text/javascript' src="${pageContext.request.contextPath }/js/common/cookieControl.js"></script> <script type ="text/javascript" src ="${pageContext.request.contextPath }/js/crypto/jsbn.js"></script> <script type ="text/javascript" src ="${pageContext.request.contextPath }/js/crypto/rsa.js"></script> <script type ="text/javascript" src ="${pageContext.request.contextPath }/js/crypto/prng4.js"></script> <script type ="text/javascript" src ="${pageContext.request.contextPath }/js/crypto/rng.js"></script> <title>회원관리 관리자 로그인</title> </head> <!-- 자바스크립트 : RSA 암호화 알고리즘 처리 1. js 라이브러리 http://www-cs-students.stanford.edu/~tjw/jsbn/ jsbn.js, prng4.jg, rng.js, rsa,js 다운로드 2. WebContext 하위에 배치 3. 취득한 js파일 import 우선순위 (순서대로) 3.1 jsbn.js 3.2 rsa.js 3.3 prng4.js 3.4 rng.js --> <body> <table width="770" border="0" align="center" cellpadding="0" cellspacing="0" style="margin: 90px;"> <tr> <td height="150" align="center"><img src="${pageContext.request.contextPath }/image/p_login.gif" /></td> </tr> <tr> <td height="174" style="background: url(${pageContext.request.contextPath }/image/login_bg.jpg); border: 1px solid #e3e3e3;"> <table width="100%" border="0" cellpadding="0" cellspacing="0"> <tr> <td width="260" height="110" align="center" style="border-right: 1px dotted #736357;"> <img src="${pageContext.request.contextPath }/image/logo.jpg" /> </td> <td> <table border="0" align="center" cellpadding="5" cellspacing="0"> <tr> <td><b>아이디</b></td> <td><input type="text" name="mem_id" class="box" tabindex="3" height="18" /></td> <td rowspan="2"> <img src="${pageContext.request.contextPath }/image/login.gif" class="loginBtn"/> </td> </tr> <tr> <td><b>패스워드</b></td> <td><input type="password" name="mem_pass" class="box" tabindex="3" height="18" /></td> </tr> <tr> <td colspan="3" align="right"><a href="">회원가입을 원하세요??</a></td> </tr> </table> </td> </tr> </table> </td> </tr> </table> </body> <script type = "text/javascript"> $(function(){ if('${!empty param.message}'){ alert("${param.message}"); } $('.loginBtn').click(function(){ var mem_id = $('input[name=mem_id]').val(); var mem_pass = $('input[name=mem_pass]').val(); if(!mem_id.validationID()){ alert("아이디를 바르게 입력해주세요"); $('input[name=mem_id]').focus(); return false; } if(!mem_pass.validationPWD()){ alert("비밀번호를 바르게 입력해주세요"); $('input[name=mem_pass]').focus(); return false; } var modulus = '${publicKeyMap["publicModulus"]}'; var exponent = '${publicKeyMap["publicExponent"]}'; var rsaObject = new RSAKey(); rsaObject.setPublic(modulus,exponent); //평문을 암호문으로 바꾸기 var encryptID = rsaObject.encrypt($('input[name_mem_id]').val()); var encryptPWD = rsaObject.encrypt($('input[name_mem_pass]').val()); var $frm = $('<form action="${loginCheckURL}" method="post"></form>'); var $inputID = $('<input type="hidden" value="' +encryptID+ '" name="mem_id" />'); var $inputPWD = $('<input type="hidden" value="' +encryptPWD+ '" name="mem_pass" />'); $frm.append($inputID); $frm.append($inputPWD); $(document.body).append($frm); $frm.submit(); }); }); </script> </html>
'JSP' 카테고리의 다른 글
DBCP(Database Connection Pooling) 속성 (0) 2020.06.22 DCEVM (0) 2020.06.22 JSP(사용자 정의 태그 만들기) (0) 2020.06.17 JSP(expressionLanguage) (0) 2020.06.16 ajax(This XML file does not appear to have any style information associated with it. The document tree is shown below.) 에러 (0) 2020.06.15