JAVA와 C# 간에 RSA와 AES로 비밀통신 해보기(SSL)

JAVA와 C# 간에 RSA와 AES로 비밀통신을 하는 코드와 개념을 간단히 정리해 둔다.

RSA

비대칭 암호화 알고리즘으로써, 암호화키와 복호화키가 존재 한다.

일반적으로 암호화 키는 공개키, 복호화키는 개인키라 하지만, 반대로도 사용할 수 있다. 

반대로 사용하는 대표적인 경우가 CA가 발급한 인증서를 검증할 때 사용한다.

주의 사항

메시지의 길이는 암호키 길이와 같아야 하는데, 기본적으로 PKCS1Padding 을 사용하게 되므로, 11바이트의 해더가 붙는다. 

예를 들어 암호키 사이즈가 512bits 라면, 512/8-11로 53bytes의 메시지 길이 제한이 생긴다.


AES

대칭 암호화 알고리즘으로, 암호화키와 복호화키가 동일하다.

대칭키 중 복호화 시키기는 어렵지만 속도가 빨라 많이 사용한다.


비밀 통신

RSA나 AES를 단독으로 사용해 비밀통신을 하기는 어렵다.

RSA는 메시지 제한이 있기도 하지만, 512bits 기준으로 AES 보다 약 5배 가량은 느렸다.

AES는 대칭키라, 키교환 과정에서 해커가 가로채는 문제가 있다.

RSA와 AES를 혼합해 비밀 통신을 해야 한다

비밀 통신 시작

A와 B가 비밀통신한다고 가정

1. A는 RSA 공개키를 B에게 줌

2. B는 AES키를 생성해 A의 공개키로 암호화 시켜 A에게 보냄

3. A는 받은 암호화된 메시지를 A의 개인키로 풀어 AES키를 획득

4. 그 이후 통신은 AES키로 암호화 시켜 전달한다.

이 과정속에서 해커가 메시지를 가로채서 해독하기는 어렵겠지만, 

B가 해커라면, 비밀통신하는 의미가 없어진다.

B가 그 B가 맞는지 입증할 수 있어야 한다. 

일반적인 B입증 방법

1. 제 3의 인증기관(CA)이 필요하다. 

   인증서 비용이 매년 발생하게 된다.(물론 무료도 있다.)

   B는 사전에 B의 공개키+서버 주소등을 CA에 주고, 

   CA는 B가 준 정보를 CA의 개인키로 암호화시킨 인증서로 만들어 B에게 준다.

2. A는 CA의 공개키를 갖고 있어야 하며, 

   B에게서 받은 인증서를 CA 공개키로 복호화하여 서버 주소와 B의 공개키를 얻어낼 수 있다면, 

   B가 입증되는 것이다. 

3. A는 AES키를 생성해 B의 공개키로 암호화하여 전송

4. B는 B의 개인키로 A의 메시지를 복호화하여 AES키 획득 

5. 이후 통신부터는 AES로 암호/복호화 한다.


좀더 간단한 B입증 방법

1. B의 공개키를 A가 미리 알고있다.

   A가 사용할 클라이언트를 B가 배포한다면 가능하겠지.

2. A는 AES키를 B의 공개키로 암호화 시켜 B에게 전달

3. B는 B의 개인키로 해독하여 AES키 획득

4. 이후 통신은 AES로 암호화


일반적 또는 간단한 입증방법 모두 해커가 A또는 B 혹은 둘 다를 가장한다고 해도, 

진짜 B의 개인키를 모르기 때문에, A의 AES 암호키를 얻을 수 없다.

하지만, A가 사용하는 클라이언트가 이미 감염된 상태라면, 소용없다.


사실 클라이언트가 이미 감염된 상태라면, 암호화 방법으로도 막을 수 없거나, 힘들 꺼다.

이래서 공식 사이트에서 클라이언트를 받거나, 정품 클라이언트를 사용해야 한다.

하지만, ISP(인터넷 서비스 제공자)까지 감염되었다면, 이마저도 안되겠지...


C#과 JAVA 간 호환되는 RSA와 AES 코드

이 코드는 C#과 JAVA 간에 호환되는 코드를 정리하여, 잘 호환되는지 테스트 한 것에 불과하다.
위에서 언급 했던 비밀통신을 구현하는데 사용하거나, 호환되는 코드를 찾는 이에게 도움이 되길...
이 코드를 정리하고 테스트하는데 좀 힘들긴 했다.