Jay's Developer Note

[Android] MQTT 통신 시 중요사항 - SSL/TLS(HTTPS) 본문

Android

[Android] MQTT 통신 시 중요사항 - SSL/TLS(HTTPS)

Jay(J) 2018. 3. 14. 13:55
728x90

MQTT 통신 시 중요사항(SSL/TLS)

발생원인

간단한 네트워크 통신을 가능케하는 MQTT(Message Queuing Telemetry Transport)를 사용하다가 보안성의 이슈가 생겼다.

그건 TLS(Transport Layer Security)를 사용하여 통신을 하던 도중 클라이언트에서 발생한 뜬금없는 이슈였다.

 

원인는 KeyStore 타입인데, JAVA에서는 SSL 통신 시에 기본적으로 JKS(Java KeyStore)를 사용하게 되는데, 이 JKS 알고리즘이 Android에서는 적용이 안되는 문제다.

 

Android 에서는 JKS 대신 BKS(Bouncycastle KeyStore)를 사용한다.

java.security.KeyStore.getDefaultType() 으로 확인해보면 BKS가 출력되는 것을 확인할 수 있다.

 

BKS 를 쓰는 이유는 Android 에서는 JKS로 통신 시에 HandShaking이 안된다고 한다. 그래서 어쩔 수 없이 BKS로 통신을 한다는 것이다.

 

그래서 서버에서 클라이언트 키를 생성할 시에 BKS 형식으로 키를 만들어야 하며 JKS 형식의 키를 BKS 형식으로 사용하려한다면 당연하게 WrongAlgorithmException 이 발생한다.

그렇다고 JKS 형식의 키를 JKS 형식으로 Android 에서 사용하려한다면 NoSuchAlgorithmException 이 발생하는 것을 볼 수 있다.

해결방법

그렇다면 BKS를 생성해서 써야한다는 것인데, 그 방법에는 2가지가 있다.

 

1. JKS to BKS
2. create BKS

 

구글링을 해보면 JKS to BKS 해주는 사이트들이 있다. 거기에서 사용해도 된다.

근데 난 JKS 형식으로 암호압축 되어 있는 키를 다시 BKS 형식으로 만든다는 게 신뢰가 가지 않아서 2번의 방식을 사용했다.

Linux에서 진행을 했으며, CentOS 7에서 동작했다.

2번을 사용하려면 우선 bouncycastle 홈페이지에서 자신의 JDK의 버전에 맞는 provider jar 파일을 다운로드 받아야한다.(extend 버전 말고 그냥 bcprov-jdk 버전)

 

서버에 jar 파일을 옮기고 이와 같이 BKS 형식의 키를 생성해야 한다.

keytool -importcert -v -trustcacerts -file [서버 인증서 경로] -alias server -keystore /usr/local/src/client.bks[BKS 파일 output 경로] -provider org.bouncycastle.jce.provider.BouncyCastleProvider -providerpath "[다운받은 jar 이름]" -storetype BKS

그러면 client.bks 파일이 생성이 되고 해당 파일을 옮겨서 기존 JKS 방식처럼 진행하면 해결된다.

 

또한 SunX509 형식의 KeyManagerFactory와 TrustManagerFactory는 지원이 안된다.

그래서 각각 getDefaultAlgorithm()을 이용하여 PKIX 형식으로 인스턴스를 생성해야 한다.

728x90