336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

프로젝트 보안취약점 지적사항 중에 로그인화면에서 로그인 시도 시 비밀번호가 평문으로 전달되면 안된다는 것이 있었다. 아래의 문서를 찾아 적용하였고 정리해둔다.

 

 

javascript - java 간 RSA 를 이용해서 암호화 복호화 하기

 

1) javascript encrypt library 다운로드

 

RSA and ECC in JavaScript 링크 OR

biginteger javascript.zip
0.01MB

- jsbn.js, prng4.js, rng.js, rsa.js

 

 

2) JSP

 

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>

<%

    String ctxPath = (String) request.getContextPath();

%>

<!DOCTYPE html>

<html>

<head>

<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

<title>Login</title>

<script type="text/javascript" src="<%=ctxPath %>/script/jquery/jquery-1.11.0.min.js"></script>

<!-- 순서에 유의 -->

<script type="text/javascript" src="<%=ctxPath %>/script/RSA/rsa.js"></script>

<script type="text/javascript" src="<%=ctxPath %>/script/RSA/jsbn.js"></script>

<script type="text/javascript" src="<%=ctxPath %>/script/RSA/prng4.js"></script>

<script type="text/javascript" src="<%=ctxPath %>/script/RSA/rng.js"></script>

 

<script type="text/javascript">    

    function login(){

        var id = $("#USER_ID_TEXT");

        var pw = $("#USER_PW_TEXT");

    

        if(id.val() == ""){

            alert("아이디를 입력 해주세요.");

            id.focus();

            return false;

        }

        

        if(pw.val() == ""){

            alert("비밀번호를 입력 해주세요.");

            pw.focus();

            return false;

        }

        

        // rsa 암호화

        var rsa = new RSAKey();

        rsa.setPublic($('#RSAModulus').val(),$('#RSAExponent').val());

        

        $("#USER_ID").val(rsa.encrypt(id.val()));

        $("#USER_PW").val(rsa.encrypt(pw.val()));

        

        id.val("");

        pw.val("");

 

        return true;

    }

</script>

</head>

<body>

    <form name="frm" method="post" action="<%=ctxPath%>/login.do" onsubmit="return login()">

        <input type="hidden" id="RSAModulus" value="${RSAModulus}"/>

        <input type="hidden" id="RSAExponent" value="${RSAExponent}"/>    

        <input type="text" placeholder="아이디" id="USER_ID_TEXT" name="USER_ID_TEXT" />

        <input type="password" placeholder="비밀번호" id="USER_PW_TEXT" name="USER_PW_TEXT" />

        <input type="hidden" id="USER_ID" name="USER_ID">

        <input type="hidden" id="USER_PW" name="USER_PW">

        <input type="submit" value="로그인" />

    </form>

</body>

</html>

 

 

3) JAVA

 

import java.security.KeyFactory;

import java.security.KeyPair;

import java.security.KeyPairGenerator;

import java.security.PrivateKey;

import java.security.PublicKey;

import java.security.spec.RSAPublicKeySpec;

 

import javax.crypto.Cipher;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import javax.servlet.http.HttpSession;

 

import org.springframework.stereotype.Controller;

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.servlet.ModelAndView;

 

@Controller("loginController")

public class LoginController {

 

    private static String RSA_WEB_KEY = "_RSA_WEB_Key_"; // 개인키 session key

    private static String RSA_INSTANCE = "RSA"; // rsa transformation

 

    // 로그인 폼 호출

    @RequestMapping("/loginForm.do")

    public ModelAndView loginForm(HttpServletRequest request, HttpServletResponse response) throws Exception {

 

        // RSA 키 생성

        initRsa(request);

 

        ModelAndView mav = new ModelAndView();

        mav.setViewName("loginForm");

        return mav;

    }

 

    // 로그인

    @RequestMapping("/login.do")

    public ModelAndView login(HttpServletRequest request, HttpServletResponse response) throws Exception {

 

        String userId = (String) request.getParameter("USER_ID");

        String userPw = (String) request.getParameter("USER_PW");

 

        HttpSession session = request.getSession();

        PrivateKey privateKey = (PrivateKey) session.getAttribute(LoginController.RSA_WEB_KEY);

 

        // 복호화

        userId = decryptRsa(privateKey, userId);

        userPw = decryptRsa(privateKey, userPw);

 

        // 개인키 삭제

        session.removeAttribute(LoginController.RSA_WEB_KEY);

 

        // 로그인 처리

        /*

          

         ...  

           

         */

 

        ModelAndView mav = new ModelAndView();

        mav.setViewName("index");

        return mav;

    }

 

    /**

     * 복호화

     * 

     * @param privateKey

     * @param securedValue

     * @return

     * @throws Exception

     */

    private String decryptRsa(PrivateKey privateKey, String securedValue) throws Exception {

        Cipher cipher = Cipher.getInstance(LoginController.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 void initRsa(HttpServletRequest request) {

        HttpSession session = request.getSession();

 

        KeyPairGenerator generator;

        try {

            generator = KeyPairGenerator.getInstance(LoginController.RSA_INSTANCE);

            generator.initialize(1024);

 

            KeyPair keyPair = generator.genKeyPair();

            KeyFactory keyFactory = KeyFactory.getInstance(LoginController.RSA_INSTANCE);

            PublicKey publicKey = keyPair.getPublic();

            PrivateKey privateKey = keyPair.getPrivate();

 

            session.setAttribute(LoginController.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);

 

            request.setAttribute("RSAModulus", publicKeyModulus); // rsa modulus 를 request 에 추가

            request.setAttribute("RSAExponent", publicKeyExponent); // rsa exponent 를 request 에 추가

        } catch (Exception e) {

            // TODO Auto-generated catch block

            e.printStackTrace();

        }

    }

}

 

참고 : https://cofs.tistory.com/297

'-- JSP, SPRING' 카테고리의 다른 글

한 서버에 여러 버전 JDK 사용  (0) 2021.04.13
SPRING CSRF 구현  (0) 2020.04.08
자바 특수문자 사용방법  (0) 2018.03.15
synchronized에 대해서  (0) 2017.08.03
@PostConstruct, @PreDestroy 어노테이션  (0) 2017.07.07
posted by 어린왕자악꿍