Skip to main content

AES + RSA Encryption(암호화 연구)

· 10 min read
Alex Han
Software Engineer

Untitled

배경(기존)

AES-256 FUI using CBC mode

이전 회사에서는 암호화 방식은 AES-256-CBC 방식을 사용하고 있고 사용자를 판별하기 위한 토큰 암호화에만 이를 사용했습니다.

암호화에 대해 잘 모르고 있었기 때문에 단순히 key, iv 값을 통해 암호화 전문(string)을 생성하고 key, iv 값을 통해 복호화 전문(string)을 만들어 사용했습니다.

기존의 암호화 사용방식은 아래와 같았습니다.

  1. 암호화 로직을 꼬는 방식
    1. 암호화 하는 방식
      1. 랜덤으로 AES 암호화 키 세트 생성.
      2. a의 키 세트를 서버의 환경 변수를 통해 암호화.
      3. 평문을 a에서 생성한 암호화 키 세트를 통해 암호화(token 생성).
      4. 데이터베이스에 b에서 암호화된 암호화 키 세트와 c를 통해 암호화 된 token 저장.
    2. 암호화 푸는 방식
      1. 데이터베이스에서 2-b 암호화된 암호화 키 세트를 가져와 서버의 환경변수를 통해 암호화를 풀어줌.
      2. a의 암호화 키 세트를 통해 2-c token 암호를 풀어 고객을 찾아내는 방식.

원래 있었던 평문을 암호화하고 암호화 문을 평문화하는 2가지 모듈에 로직을 약간 넣어 혹시 모를 키 유출에 대비하려고 했었습니다.

그러던 중 외부 금융권 회사(보안 중요)와 협업을 하게 됐는데, 그 회사에서는 암호화 키 노출에 대해 민감히 반응했고 암호화 방식 하나만이 아닌 다른 암호화 방식도 추가해 도입하길 원했습니다.

고객사의 요청 사항은 아래와 같았습니다.

비대칭 암호화를 통해 대칭키를 암호화해 주고 받고 통신 시 암호화해서 주고 받았으면 하는데 이 때 서로 다른 암호화 방식 2개(AES, RSA)를 사용했으면 한다는 것이었습니다.

AES 암호화 방식도 겨우 쓰고 있었기에 무슨 소리인지 알지 못했고 검색을 통해 AES 암호화 방식이 대칭키이고 RSA 암호화 방식이 비대칭키인 것을 알게 됐습니다.

AES 암호화는 암호화를 하거나 풀 때 동일한 키를 통해 암복호화를 진행하기 때문에 대칭키고 RSA 암호화는 public key, private key 중 하나로 암호화 하면 다른 하나로 복호화하는 방식이기에 비대칭키인 것으로 이해했습니다.

결론적으로 고객사의 니즈를 정확히 파악하다가 결국 간단한 프로세스를 만들어 냈습니다.

  1. 데이터를 주고 받을 시 AES로 암호화 하여 주고 받습니다.
  2. RSA로 AES 암호화 키를 암호화해 주고 받아 AES 암호화 키 유출을 막습니다.

RSA + AES 암호화 구성

위의 프로세스를 구성하기 위해서는 RSA 암호화 모듈, AES 암호화 모듈, 교체 주기에 따라 암호화 키들을 생성 업데이트 하는 모듈이 필요했고 아래와 같이 설계할 수 있었습니다.

RSA+AES 암호화 빙식 프로세스 RSA+AES 암호화 빙식 프로세스

역할

  1. RSA 암호화 모듈
    1. RSA 암호화 키 세트 랜덤 생성
    2. RSA encode
    3. RSA decode
  2. AES 암호화 모듈
    1. AES 암호화 키 세트 랜덤 생성
    2. AES encode
    3. AES decode
  3. AES 교체 주기마다 AES 암호화 모듈에 요청해 데이터베이스에 교체해주는 모듈
  4. RSA 교체 주기마다 RSA 암호화 모듈에 요청해 데이터베이스에 교체해주는 모듈

과정

  1. RSA 암호화 모듈을 통해 저장해둔 rsa public key와 AES 암호화 키세트를 고객사에 제공(api)
  2. 고객사는 AES 암호화 모듈로 랜덤하게 생성한 AES 키세트를 이용해 body를 암호화.
  3. AES 암호화 키 세트를 rsa public key를 이용해 RSA 암호화.
  4. RSA 암호화 된 AES 암호화 키 세트와 AES를 통해 암호화 된 body를 서버로 전송
  5. 서버에서 저장해 둔 rsa private key를 통해 AES 암호화 키 세트를 복호화.
  6. 복호화한 AES 암호화 키 세트를 통해 암호화 된 body를 복호화.
  7. 반환 시는 고객은 이미 랜덤하게 생성한 rsa 암호화 이전 AES 암호화 키를 가지고 있기 때문에 6번에서 복호화한 AES 암호화 키를 그대로 사용해 암호화 해 body로 전송하면 됩니다.

프로세스를 통한 이점

  1. 매 요청 마다 AES 암호화 키를 랜덤하게 생성 보안에 좋음.
  2. RSA 암호화 키를 주기적으로 교체하고 고객사도 이 정보를 주기적으로 받아 처리해 보안에 좋음.
  3. 고객사와 서비스 서버 간에 랜덤하게 생성한 후 rsa public key를 통해 암호화한 AES 암호화 키 세트를 요청 시 주는 것 외에 키를 주고 받지 않아 보안에 좋음.
  4. 암호를 풀 수 있는 rsa private key는 db server 에만 존재해 통신 시 보안이 DB 서버의 보안과 같이 높아짐.
  5. 고객사의 요청을 충족시켜줌

로직 변경

모든 걸 api를 통해 처리하고 자동화하려던 위의 프로세스 설계는 고객사 측의 기존 니즈와 다르고 완전하지 못한 설계였기에 좀 더 보완이 필요했고 고객사에서 원하는 방향대로 아래와 같이 로직을 다시 변경했습니다.

  1. 고객사에서 사용할 언어에 맞게 암호화 모듈을 제공하고 이를 통해 rsa 암호화 키를 생성 후 우리에게 rsa_public_key를 메일로 제공합니다.
  2. 해당 키를 저장하고 고객사에서 요청 시 랜덤으로 aes_key를 생성하고 저장해 둔 rsa_public_key를 encode 해 고객사에 api를 통해 전달합니다.
  3. 고객사에서는 해당 키를 encoded_aes_key를 decode 해 저장하고 우리와 통신 시 aes_key로 https body 를 encode 해 우리 서비스에 요청합니다.
  4. 고객에 요청에 의해 랜덤하게 생성한 aes_key를 저장해둔 것을 이용해 body를 decode하고 서비스 로직 실행 완료 후 다시 encode해 고객에게 반환합니다.
  5. 언제든 rsa_key 또는 aes_key 업데이트는 고객사의 요청에 따라 교체할 수 있게 합니다.

초기 설계한 로직에서 이미 기능들은 모두 만들었기 때문에 해당 로직을 구현하는데 어려움은 없었고 고객사의 니즈를 제대로 충족할 수 있었습니다.

결론

암호화 방식에 대해서 좀 더 공부해 볼 수 있는 동기부여가 되는 시간이었고 그 동안 잘못 사용하고 있던 것들을 바로 잡을 수 있었습니다. 또한 여러 암호화 방식을 이용해 보안을 더 강화하는 재밌는 로직에 대해서도 알 수 있는 흥미로웠고 배울 수 있는 시간이었습니다.