암호화를 왜 쓸까?
개인정보와 같은 민감한 내용을 데이터베이스에 저장을 하거나 제공을 해줄 때에 있어서 공격에 취약한 상황에서 바로 노출되지 않도록 하는 역할을 가진다.
특히나 LINE Pay 서비스 특성상 민감한 개인정보를 다루거나 사용하는 일들이 많은데, 이 때 사용되는 암복호화 방식을 학습하기 위해 정리해본다.
단방향 알고리즘 (One-Way Encryption)
Background
평문(Plain Text) 암호화는 가능하지만, 암호문을 평문으로 복호화가 불가능한 알고리즘. 암호화만 가능하기 때문에 단방향 암호화라고 부른다. 이렇게 복호화가 불가능하기 때문에 무결성(Data Integrity: 데이터의 정확성, 일관성, 유효성이 유지) 하다고 말 할 수 있다.
단방향 알고리즘은 Hash 암호화 방식을 사용하는데, 그렇다면 단방향 알고리즘은 언제 사용하는걸까?
복호화가 불가능하기 때문에, 기본적으로 계정의 패스워드를 암호화해서 저장할 때 사용한다고 한다. 즉, 클라이언트가 계정을 생성할 때 단방향 알고리즘으로 패스워드를 암호화해서 암호문(Cipher Text) 을 만들고 이것을 암호문 그대로 데이터에 저장한다.
그렇다면 클라이언트는 로그인은 어떻게 할까? 입력한 패스워드를 동일한 알고리즘으로 암호화 한 후 서버에 저장 된 암호화 된 패스워드 데이터와 비교해서 확인하면 로그인 검증을 할 수 있다.
만약에 클라이언트가 패스워드를 잃어버렸다면? 물론 복호화가 불가능하기 때문에, 패스워드의 실제 평문을 찾을 수는 없다.(찾을 수 있다면 해당 알고리즘은 더이상 사용되면 안되는 알고리즘이다ㅠㅠ) 대신에 우리가 자주 겪어봤던 이메일이나 SMS 본인인증 등을 통해 암호화된 패스워드 자체를 변경해주면 된다.
단방향 알고리즘의 종류
단방향 알고리즘은 여러 해시(Hash) 알고리즘들이 있다.
Hash 함수는 임의의 크기를 가진 데이터를 고정된 데이터의 크기로 변환시키는 함수를 뜻한다. 그렇기 때문에 입력값의 길이가 달라도 출력 값의 길이는 고정되어 있다.
동일한 값이 입력되면 언제나 동일한 Hash 값으로 출력이 되기 때문에, 이를 저장해서 검증하는데 사용이 가능하다. 대표적으로 아래의 알고리즘들이 Hash 함수들이다.
MD5 - Message-Digest algorithm 5 (Deprecated)
메시지 다이제스트(Message Digest)란, 메시지를 해시(Hash)하는 것을 의미한다. 임의의 길이를 가진 메시지를 MD함수에 넣으면 일정한 길이를 가진 데이터를 얻는다.
MD5는 1991년 로널드 라이베스트가 기존 MD4를 대체하기 위해 고안했다고 한다. 1996년에 설계상 결함을 발견했는데, 이 때 부터 SHA-1과 같은 다른 알고리즘을 권장하기 시작했다. 그리고 2004년에는 심각한 결함을 발견하게 되었고, 현재는 절대 사용 되면 안되는 암호화 알고리즘 방식이 되었다. (하지만 파일의 무결성 검사에 유용하게 사용하고 있음)
그렇다면 뭐길래 왜 쓰면 안될까? 일단 쓰면 안되는 이유 보다 먼저 동작 방식을 이해해보자...
- 일단 MD5 Hash 알고리즘은 임의의 길이의 메시지를 입력 받아서 128 비트 짜리 고정 길이의 해시값을 만드는 방식이다. 그렇다면 어떻게 128 비트 짜리 고정 값을 만들까? 아래의 5단계를 거친다고 한다.
- 예시를 들어 데이터 암호화를 위해 "They are deterministic" 라는 문자열을 암호화하는 예제로 설명을 해볼것이다. 공백을 포함해서 22개의 문자로 구성된 문자열이다.
01010100 01101000 01100101 01111001 00100000 01100001 01110010 01100101 00100000 01100100 01100101 01110100 01100101 01110010 01101101 01101001 01101110 01101001 01110011 01110100 01101001 01100011
해당 문자열을 8비트 Binary 데이터로 바꾸면 위와 같이 표현할 수 있다. 이 데이터의 총 크기는 22 X 8 = 176 비트이다. 이 데이터를 가지고 아래의 일련의 과정을 수행해보도록 하자!!!
패딩 비트 추가
- MD5는 512 비트 단위로 알고리즘을 수행하기 때문에 512비트로 나눠지도록 메시지 길이를 만들어줘야한다. 그렇기 때문에 모든 메시지는 512 배수의 비트로 만들어져야 한다. 이 중에 맨 뒤 64비트는 해당 메시지의 길이를 정수로 저장하고 있기 때문에 필수적으로 공간을 가지고 있어야한다. 말로만 설명하면 이해하기 어려우니 케이스별로 설명을 해본다. (그림의 블록 크기는 무시하고 숫자만 봐주세요 ㅠㅠ)
1.a.ii 예시의 padding bit를 예로 들면, 이렇게 맨 앞에 1비트 저장공간에는 "1" 값을 저장하고 나머지 159 비트 저장공간은 0으로 채워준다.
"They are deterministic" 문자열을 위에처럼 8비트 바이너리 데이터로 바꾸는데 성공했다. 그리고 이 데이터를 512 비트 짜리 블록으로 바꿔줘야 하는데, 이 때 우린 계산을 해줘야한다. 우선 블록의 전체 크기는 512 비트이다. 여기서 뒤에 message length를 저장하는 크기인 64비트를 일단 우선적으로 빼줘야 한다. 그렇다면 남는건 448 비트이다. 그리고 padding 비트를 구분 짓는 정수 "1"을 저장하는 1비트도 빼줘야한다. 자 이렇게 우리는 271개의 0이 채워질 패딩 비트의 크기를 알게 되었다. 아래와 같이 512 비트 짜리 블록을 만들 수 있는데, 파란색 부분이 아까 "They are deterministic" 문자열을 8비트 바이너리 데이터로 바꾼 것이고 초록색 밑줄친 부분이 방금 전 계산한 패딩의 크기이다. 보이는 것 처럼 맨 앞에 패딩을 구분짓는 1이 저장된 1비트와 나머지는 모두 0으로 채워진 271개의 비트가 있다. 마지막으로 빨간색으로 된 마지막 8비트는 문자열의 길이인 176(비트)을 2진수로 표현한 값이다. 176 = 10110000 = 128 + 32 + 16 01010100 01101000 01100101 01111001 00100000 01100001 01110010 01100101 00100000 01100100 01100101 01110100 01100101 01110010 01101101 01101001 01101110 01101001 01110011 01110100 01101001 01100011 10000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 10110000 |
- 위 이미지에 맨 뒤에 있는 64비트 메시지 길이를 추가 해준다.
- 패딩 이전 본래 메시지의 길이를 64비트 남겨둔 곳에 저장 해준다.
- 패딩 이전 본래 메시지의 길이를 64비트 남겨둔 곳에 저장 해준다.
- MD5 버퍼의 초기화 = Initialization vectors
- MD5 알고리즘은 최종적으로 128 비트 길이의 해시 값을 출력해줍니다. 그래서 해시값을 계산할 때 A, B, C, D 이름으로 만들어진 32비트 짜리 워드 버퍼 네 개로 이루어진 하나의 128비트 짜리 버퍼를 아래와 같은 상수 값으로 초기화 해서 생성해줍니다.
A | 0x01234567 | 32 bit |
B | 0x89abcdef | 32 bit |
C | 0xfedcba98 | 32 bit |
D | 0x76543210 | 32 bit |