프로젝트를 하나 진행하는데.. 소켓 데이터 암호화가 필요한 시점이 왔었다. Node.js 에 npm 모듈로 socket.io 를 올린 서버와, socket.io 라이브러리를 사용하는 안드로이드 어플리케이션. 둘 사이에 JSON 데이터를 socket.io를 통해 주고 받는다. 이 데이터가 암호화되지 않은 평문이라면, 아마 와이어샤크 등으로 쉽게 모든 개인 정보가 보여졌을 것이다.
처음엔 공개 키 암호화 방식으로 RSA 암호화만을 사용하려고 했었다. 아주 강력한 암호화 방식. RSA Key Pair(공개 키, 비밀 키 한 쌍)을 생성하고, 공개 키로 암호화한 건 비밀 키로만 복호화할 수 있는 방식이다. 하지만, RSA 암호화 방식은 적은 양의 데이터(평문 데이터 245byte 이하)만 암호화가 가능하다고 해, JSON 암호화에는 부적절했다. JSON 은 키 하나와 값 하나만 들어가더라도, 문자열로 { "key":"value" } 가 되어 너무 길어진다. 그리고, RSA 암호화는 그 알고리즘이 복잡하여 Key Pair 생성 시간이 상대적으로 너무 오래 걸려 성능 상으로도 부적절했다.
그래서 알아보니, AES 암호화를 같이 곁들여 사용하는 게 일반적이라고 한다. AES 암호화는 대칭 키 알고리즘이다. 하나의 비밀 키를 만들어, 그 비밀 키로 암호화 및 복호화를 하는 방식이다. AES 암호화는 미국 정부에서 DES 를 대체해 사용할 만큼 강력하지만, 알고리즘은 간단하여 성능상으로도 큰 문제가 없다. 무엇보다, 평문 데이터의 길이에 상관이 없이 암호화가 가능하다.
어떻게 RSA와 AES를 적절히 볶아 쓰는가?
간단했다. AES 는 대칭 키 하나를 가지고 암호화와 복호화 둘 다 해버린다. RSA 는 공개 키로 암호화 하고, 비밀 키로 복호화한다. 그렇다면, 서버에서 RSA Key Pair 를 만들고, RSA 공개 키를 클라이언트에 알리고 난 뒤 클라이언트는 AES를 통해 평문 데이터를 암호화하고, RSA 공개 키를 통해 AES 대칭 키를 암호화 해 서버로 보내면 된다. 받은 서버는 RSA 비밀 키로 암호화된 AES 대칭 키를 복호화한 뒤, 그 AES 대칭 키로 AES 암호화 된 평문 데이터를 복호화하면 될 것이다.
조금(?) 복잡해 보이는데, 이렇게들 쓴다더라
그래서 이렇게 적용하도록 했고, 얼추 적용은 시켰다. 근데 이 암호화 관련 예제 소스가 영어로 구글링하면 나오긴 하는데 Node.js와 안드로이드 사이 한 번에 작동하는 코드를 찾기 힘들어 직접 올린다
RSA 2048bit 키와 AES 256bit 키이다.
Node.js 에선 npm 모듈 패키지로 node-rsa 를 추가 설치했다.
RSA encryption example for Node.js using node-rsa
AES encryption example for Node.js
RSA encryption example for Android
AES encryption example for Android
공통적으로, 이들 소스 코드 내 모든 encrypt 와 decrypt 함수(메소드)들은 모두 Base64 인코딩을 기준으로 한다.
여담으로... 보통 웹 상 로그인에 적용하지는 않는다. 웹에선 암호화는 SSL 이하 잡 으로 취급하는 분위기. 웹에선 SSL이 최고인 듯
'Programming > Language Tip' 카테고리의 다른 글
안드로이드 - 서비스와 액티비티간 통신 (0) | 2017.05.08 |
---|---|
안드로이드 - MVC 패턴 개념, 안드로이드에서 MVC 패턴의 미묘함 (3) | 2017.03.11 |
안드로이드 - 외부 스레드에서 UI 스레드로 (0) | 2017.03.11 |
안드로이드, 자바 - 러너블 (Runnable) (0) | 2017.03.11 |