본문 바로가기

일상

자바 8에서 AES-256이 갑자기 안 될 때 (JCE 정책 파일과 8u161 경계)

반응형

JDK를 갈아 끼웠더니 암호화가 깨지는 이유와, 예전 서버에서만 되던 진짜 원인을 찾는 방법입니다.


32비트 JDK로 돌던 서비스를 64비트로 옮기는 김에 같은 버전끼리 맞춰 놓았는데, 기동은 되는데 로그인만 하면 암호화 쪽에서 예외가 떨어졌습니다.

버전도 같고 설정도 같은데 예전 것에서는 되고 새 것에서는 안 되니 한참을 헤맸는데, 원인은 소스도 설정도 아니고 JDK 안에 들어 있는 정책 파일 두 개였습니다.

누군가 몇 년 전에 그 파일을 바꿔 놓았고, 그 사실이 어디에도 적혀 있지 않아서 JDK를 새로 깔면 그대로 재현되는 함정이 되어 있었습니다.


- 자바 8은 버전에 따라 AES-256 사용 가능 여부가 갈린다

- 경계는 8u161 이고, 그 이전이면 정책 파일을 직접 갈아 끼워야 한다

- 갈아 끼울 파일은 local_policy.jarUS_export_policy.jar 두 개

- 기존 서버에서만 되던 이유는 누가 이미 바꿔 놓았기 때문이다

- JDK 교체 작업에서는 원본과 파일 단위로 비교하는 절차가 있어야 한다


1. 증상은 암호화가 아니라 키 길이에서 난다

예외 메시지는 보통 java.security.InvalidKeyException: Illegal key size 형태로 떨어지는데, 암호 알고리즘 자체가 없다는 게 아니라 키 길이가 허용치를 넘었다는 뜻입니다.

AES 자체는 128비트든 256비트든 표준에 다 들어 있고 구현도 JDK 안에 있어서, 코드를 아무리 봐도 이상한 데가 안 보입니다.

막힌 건 구현이 아니라 정책이라, 소스를 뒤지는 방향으로 가면 시간을 그대로 버리게 됩니다.



2. 자바에는 암호 강도 제한이 따로 있었다

과거 미국 수출 규제 때문에 JDK는 기본적으로 제한된 강도(limited strength) 로 배포됐고, 그래서 AES 키는 128비트까지만 허용됐습니다.

그 이상을 쓰려면 JCE Unlimited Strength Jurisdiction Policy Files 라는 걸 따로 받아서 JDK 안의 정책 파일을 덮어써야 했는데, 규제가 완화되면서 이 절차는 결국 없어졌습니다.

없어진 시점이 중요한데, 자바 8 기준으로 8u161 부터 무제한 강도가 기본값이 됐습니다.


- 8u161 이상 : 기본이 무제한이라 아무것도 안 해도 AES-256 이 된다

- 8u161 미만 : 기본이 제한이라 정책 파일을 직접 교체해야 한다


버전 확인은 java -version 한 줄이면 되고, 1.8.0_141 처럼 뒷자리가 161보다 작으면 이 함정에 걸리는 구간입니다.


3. 정책 파일은 두 개이고 위치가 정해져 있다

교체 대상은 아래 두 개인데, 한 개만 바꾸면 동작하지 않습니다.


- local_policy.jar

- US_export_policy.jar


위치는 JDK 안의 jre/lib/security/ 이고, JRE 를 따로 설치했다면 그쪽에도 같은 경로가 있습니다.

서버에 JDK 와 JRE 가 둘 다 깔려 있는 경우 실제로 서비스가 물고 있는 쪽을 바꿔야 하는데, 여기서 자주 헛짚습니다.



4. 예전 서버에서만 되던 이유

같은 버전인데 한쪽만 되는 상황이면 답은 하나로 좁혀지는데, 누군가 그 서버의 정책 파일을 이미 갈아 끼워 놓은 것입니다.

몇 년 전 담당자가 조치해 놓고 인수인계 문서에는 남기지 않았고, 그 뒤로 아무도 JDK 를 건드리지 않아서 문제가 드러나지 않았습니다.

그러다 JDK 를 새로 설치하는 순간 정책 파일이 원본으로 돌아가면서 몇 년 만에 같은 증상이 다시 나온 겁니다.

이런 건 소스에도 설정에도 흔적이 없어서, 서버를 옮기거나 런타임을 바꿀 때만 튀어나옵니다.


5. 커스터마이징을 찾아내는 방법

정책 파일 하나를 찾았다고 끝이 아니고, 다른 파일도 손댔을 수 있다고 봐야 합니다.

가장 확실한 방법은 같은 버전 JDK 를 새로 받아서 파일 단위로 전부 비교하는 것이고, 체크섬을 뜨면 몇 분이면 끝납니다.


- 같은 버전 JDK 원본을 별도 경로에 푼다

- 운영 중인 JDK 와 파일별 해시를 비교한다

- 차이 나는 파일만 추려서 왜 다른지 확인한다



실제로 해 보니 다른 파일은 전부 원본과 같았고 정책 파일 두 개만 달랐는데, 다른 게 없다는 사실을 확인해 둔 것 자체가 다음 작업의 근거가 됐습니다.

이 확인을 안 해 두면 나중에 다른 문제가 터졌을 때 또 같은 의심을 처음부터 반복하게 됩니다.


6. 정리

증상은 암호화 오류인데 원인은 소스 밖에 있고, 그것도 런타임 안에 들어 있는 파일이라 평소에는 보이지 않는 종류의 문제입니다.

정리하면 이렇습니다.


- Illegal key size 는 구현이 아니라 정책 문제

- 자바 8은 8u161 을 경계로 기본값이 갈린다

- 그 이전 버전이면 정책 파일 두 개를 함께 교체해야 한다

- 특정 서버에서만 되는 기능은 누가 손댄 흔적을 의심한다

- 런타임 교체 작업에는 원본 대조 절차를 넣어 두는 게 안전하다


버전을 올리는 게 가장 깔끔한 해결이지만 운영 중인 서비스라 그게 어려울 때가 많고, 그럴 때는 최소한 어떤 파일이 왜 바뀌어 있는지 기록으로 남겨 두면 다음 사람이 같은 자리에서 헤매지 않습니다.

여기까지 자바 8의 JCE 정책 파일에 대해서 작성해봤습니다. 여기까지 읽어주셔서 감사합니다!

반응형