(예전에 본인이 다른 블로그 및 카페에서 작성했었던 게시글을 옮겨온것입니다.)

 

Jasypt 라이브러리를 이용하여 스프링부트 DB연결정보 암호화 하는 방법에 대해서 살짝 적어볼까합니다.

오래전에 일일코딩에서 어느 분이 스프링에 xml 설정 기반으로 암호화 하는 방법에 대해서 다루시기는 하였는데,

요즘엔 스프링부트도 현업에서도 많이 쓰고 있어서 스프링부트에 적용하는 방법도 알아봅시다.

(사실 알고보면 별차이 없을수도..)

현재 스텝2 수업에서 진행하고 있는 스프링부트 프로젝트 예제로 진행하겠습니다.

(이 프로젝트로 진행하겠습니다~)

application.properties 파일을 열어보면 DB 연결설정 정보가 있는데요.

요즘엔 워낙 보안이 중요시되기 때문에 DB 연결 설정이나 기타 주요한 정보가 노출될 것을 감안해서 암호화해서 저장을 하는 경우가 많더라구요. 외부에 노출되면 안되는 주요 정보 같은 것들을 암호화하지 않고 저렇게 평문으로 작성해놓으면(개발하는 동안에는 상관없지만 실제 운영에 적용시에!!) 보안상에 문제가 발생할 여지가 있구요.

웹 취약점 검사에서 지적사항으로 나오는 경우들이 있습니다.(제가 얼마전에 그러한 지적을 받았음...)

password만 암호화하는 곳도 있고, url, username, password 전부 암호화를 하는 플젝도 있는데요. 여기서는 간단하게 password 만 암호화해보도록 하겠습니다.

우선 관련 라이브러리를 받아야하기에 maven repository 로 이동합니다. 구글에서 검색하시면 바로 나옵니다.

들어가서 메인 페이지 상단에 jasypt 로 검색합니다.

검색 결과에 여러 항목이 조회가 될텐데 저희는 스프링부트에 적용할거니 Jasypt Spring Boot Starter 를 클릭해서 안으로 들어갑니다.

본인의 스프링부트 및 자바 버전과 호환되는 버전을 선택해야하는데요.

저는 일단은 가장 최신 버전을 선택하겠습니다.

본인의 프로젝트가 maven인지 gradle인지 확인하신후 맞게 복사하여 주세요. 저는 gradle을 복사하였습니다.

복사한 내용을 프로젝트의 build.gradle 안에서 dependencies 에 붙여넣기 하였습니다.

(maven이신분은 pom.xml 에 추가해주시면 되겠죠)

저장 후에 Refresh Gradle Project 를 진행해줍니다. 그리고 관련 jar 파일이 추가되었는지 확인해줍니다.

정상적으로 추가가 된 것을 확인하였으면 이제 db password 를 암호화하도록 하겠습니다.

암호화를 하는 방법은 일반적으로 두 가지가 있습니다.

1. jasypt bin파일을 통째로 다운로드받아서 그 안에 bat 파일을 실행하는 방법(리눅스의 경우에는 sh파일을 실행)

2. 이클립스에서 암호화하는 클래스 작성해서 실행시키는 방법.

저희는 아무래도 command보다는 이클립스가 익숙하므로 두 번째 방법을 선택하겠습니다.

만약, 1번 방법으로 진행하겠다면 https://github.com/jasypt/jasypt --> jasypt 소스가 올라가있는 깃허브로 들어가서 jasypt-dist 폴더를 받으시면 되구요. 자세한 설명은 jasypt 공식홈페이지 중 여기를 http://www.jasypt.org/cli.html 참고하면 됩니다.

그럼 프로젝트내에 class 파일을 하나 만들겠습니다. 암호화 결과만 확인하고 다시 삭제할거라서 임의의 경로에 아무 클래스명으로 하나 만들면 됩니다. 그리고 클래스 구현부는 다음과 같이 코딩해줍니다.

어떠한 알고리즘을 사용할지 먼저 설정을 해줘야하는데 저희는 MD5 암호화를 사용할거라서 PBEWithMD5AndDES 라고 입력을 해줍니다. 이 이외에도 지원하는 암호화 알고리즘이 많이 있는데(MD2, SHA, SHA-256 등) 이 부분은 jasypt 홈페이지를 참고하시면 자세히 알 수 있습니다.

그리고 저는 패스워드를 hanqJava로 설정했는데요. 패스워드는 임의로 정하면 되지만, 이 패스워드는 나중에 암호화된 값을 다시 복호화할때 적용해야할 필수 Key이기 때문에 절대 잊어버리시면 안됩니다.

그리고 sysout을 통해서 암호화 된 결과를 출력해보았습니다.

메인 메서드를 실행해보니 콘솔에 다음과 같이 찍히네요.

똑같은 문자 root를 암호화했는데 출력할때마다 암호화 결과가 매번 달라지네요?

이것은 saltGenerator를 지정하지 않으면 디폴트로 random salt가 사용되기 때문인데요. 매번 암호화 결과가 달라지기 때문에 random 설정이 어찌보면 보안상 더 안전할 수도 있을 것 같습니다.

만약, 랜덤하게 하고 싶지 않다면

이 문장을 추가한후에 다시 실행해보시면 됩니다.(매개변수 "fixedSalt"는 제가 임의로 넣은거고 꼭 저렇게 안넣으셔도 됩니다.)

단, 만약 저처럼 콘솔에 오류가 뜬다면

스프링부트 버전과 라이브러리 버전이 맞지 않기때문에 발생하는 현상으로 이 경우에는 jasypt 버전을 바꾸어줍니다. 그래서 저는 버전을 2.1.1 에서 2.1.0 으로 내렸습니다.

jasypt 라이브러리가 스프링 및 스프링부트, jre 버전에 워낙 민감한(?) 라이브러리인지라 정상적으로 코딩한것 같은데 오류가 난다면 버전 지원 문제일 확률이 큽니다. 그럴 경우 한 단계, 두 단계 낮은 구버전으로 내리시면 됩니다.

Refesh Gradle Project를 해주고 다시 실행해주니 콘솔에 정상적으로 찍힙니다.

이번에는 매번 동일한 결과가 출력되네요.

단, 암호화시에 고정 salt를 지정해준 경우 나중에 복호화할때도 똑같이 설정을 해줘야 합니다.

저는 위 문장은 다시 삭제하고 default 설정인 random salt로 다시 생성하여서 사용하겠습니다.

암호화된 값을 복사해서 application.properties의 password 입력란에 넣어줍니다. 값을 넣을때는 암호화된것이라는 알려주기 위해서 ENC()로 감싸줍니다. 나중에 복호화를 진행할 때, ENC()로 감싸준것만 복호화가 진행되기 때문입니다.

저는 암호화된 값이 IFEL2T6xpUtTlz5g8EnUYw== 이므로 위와같이 적어줬습니다.

암호화 결과는 얻었으므로 아까 만든 JasyptEnc 클래스 파일은 다시 삭제해줘도 무방합니다.

(단, 암호화에 사용한 key는 기억하고 있어야겠죠)

이제 스프링부트 실행시 복호화를 하기 위한 설정을 진행합니다.

jasypt 환경설정을 해줄 클래스 파일을 만듭니다. 저는 common 아래에 만들었습니다.

여기서 SimpleStringPBEConfig를 사용할경우에 password, algorithm, poolSize는 반드시 넣어줘야 하는 필수 항목입니다. PoolSize를 설정하지 않고 톰캣을 실행하였더니 0보다 큰 값을 입력하라고 오류가 뜨더라구요. 다른 항목들은 설정하지 않아도 연동에는 문제가 없었습니다.

만약, 아까 암호화시 saltGenerator를 랜덤이 아닌 고정으로 지정하였다면 아래처럼 한 줄 더 추가해주면 될 것 같습니다.

그리고 application.properties 에 아래와 같이 세 줄 추가해줍니다.

bean 값은 위의 클래스 파일에서 지정해준 bean name을 적어주면 되구요.

prefix와 suffix는 안적어줘도 되기는 할텐데 혹시 복호화시에 오류가 나는 경우에는 추가해주시면 됩니다.

만약, properties 파일이 아닌 yml 파일에 설정을 한다면 아래와 같이 적어주면 되겠지요.

설정이 완료되었으면 스프링부트 앱을 실행시켜서 정상적으로 톰캣에 올라가는지, 디비 데이터를 조회오는지 확인하면 됩니다.

제 STS에서는 콘솔에도 별다른 오류가 찍히지 않았으며, 레프트 메뉴 클릭시에도 정상적으로 디비 데이터가 조회되는 것을 확인할 수가 있습니다.

db password를 암호화해서 실제 프로젝트 구동시에 복호화를 해서 db가 정상적으로 연결하는것을 확인해보았는데요!!

그런데 저희는 암호화, 복호화에 사용되었던 키를 소스상에 그냥 하드코딩으로 넣었는데요.

중요한 키 정보를 자바 소스상에 직접 넣는것은 차후 수정도 불편하고, 보안상 좋은 방법은 아닌것 같으니, 따로 properties 파일로 분리해보도록 하겠습니다.

게시글 내용이 길어질것 같아서 이후 내용은 새로운 게시글로 작성해서 이어서 올리겠습니다...!

+ Recent posts