평문을 암호문으로 변환하는 과정
Ex) 평문("123456")
→ 암호화
→ 암호문("aBD#fefa$fae!")
암호문을 평문으로 변환하는 과정
Ex) 암호문("aBD#fefa$fae!!")
→ 복호화
→ 평문("123456")
암호화 후 복호화 불가
Ex) 사용자 비밀번호 - 사용자가 입력한 비밀번호를 암호화 하여 DB에 저장이 될때, 모든 접근자(개발자포함)는 암호화 된 코드를 다시 평문으로 볼 수 없음. 또한, 해킹이 되어도 복호화가 매우 힘듦. (예외 - RainbowTable)
암호화와 복호화 모두 가능
Ex) 사용자 주소, 이메일, 번호 또는 전자서명 같이 재사용성이 있는 정보는 암호화 복호화 모두 이루어져야함.
대칭형(비밀키 암호) : 암호화 할때 사용한 key == 복호화 할때 사용하는 key
주로 데이터 통신 암호화에 많이 쓰임.
비대칭형(공개키 암호) : 암호화 할때 사용한 key != 복호화 할때 사용하는 key
주로 인증에 많이 쓰임.
사용자가 정보를 입력하여 DB로 전달 되기 전에, 입력 값(평문)을 암호문으로 변경 해주는 알고리즘이 있음
알고리즘은 다양함. 그 중 가장 많이 쓰이는 해시함수 알고리즘이 적용된 것만 서술.
단방향 해시 함수 단점
1. 레인보우 테이블 공격
2. 무차별 대입 공격 ( 브루트 포스 )
단방향 해시 함수 보완
1. Key Stretching : 단방향 해쉬값을 계산 한 후 그 해쉬값을 또 해쉬 하고, 또 이를 반복하는 것
2. Salting : 실제 비밀번호 이외에 추가적으로 랜덤 데이터를 더해서 해시값을 계산하는 방법.
SHA(대표적인 해시함수의 시초 since 1993)
MD5
PBKDF2
해시 함수의 컨테이너인 PBKDF2는 솔트를 적용한 후 해시 함수의 반복 횟수를 임의로 선택할 수 있음. PBKDF2는 아주 가볍고 구현하기 쉬우며, SHA와 같이 검증된 해시 함수만을 사용함.(Django 에서 사용)
bcrypt
Salting과 Key Stretching을 구현한 해쉬 함수중 가장 널리 사용되는 것. bcrypt는 처음부터 비밀번호를 단방향 암호화 하기 위해 만들이전 해쉬함수. bcrypt는 보안에 집착하기로 유명한 OpenBSD에서 기본 암호 인증 메커니즘으로 사용되고 있고 미래에 PBKDF2보다 더 경쟁력이 있다고 여겨짐. 입력값을 72 byte로 해야 해서 조금 귀찮음. 하지만 가장 많이 쓰임.
scrypt
scrypt는 상대적으로 최신 알고리즘이며 나머지 둘보다 더 경쟁력 있는 것으로 평가되나, 아직 덜 확산되어 있음. scrypt는 다이제스트(해시 함수라는 수학적인 연산을 통해 생성된 암호화된 메세지)를 생성할 때 메모리 오버헤드를 갖도록 설계되어, 억지 기법 공격(brute-force attack)을 시도할 때 병렬화 처리가 매우 어려움. 따라서 PBKDF2보다 안전하다고 평가되며 미래에 bcrypt에 비해 더 경쟁력이 있다고 여겨짐.
a. AES
현재 가장 보편적으로 쓰이는 암호화 방식은 현 미국 표준 방식. 128~256비트 키를 적용할수 있어 보안성이 뛰어나며 공개된 알고리즘이라 누구나 사용할 수 있음.
a. RSA
공개키 암호시스템의 하나로 암호화뿐만 아니라 전자서명이 가능한 최초의 알고리즘.
주로 적은양의 데이터나 전자서명에 사용. 대칭키인 DES, AES보다 속도가 느리기 때문에 메시지 암호화에는 쓰이지 않고 주로 키를 암호화하는데에 사용
유저의 identification(아이디, 비번) 확인하는 절차
서비스를 누가쓰며, 추적이 가능하도록 하기 위해 필요
앞서 언급했듯이 유저가 로그인에 성공한 후에는 access token이라고 하는 암호화된 유저 정보를 첨부해서 request를 보내게 된다.
유저 로그인
POST /auth HTTP/1.1
Host: localhost:5000
Content-Type: application/json
{
"username": "joe",
"password": "pass"
}
access token
HTTP/1.1 200 OK
Content-Type: application/json
{
"access_token" : "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZGVudGl0eSI6MSwiaWF0IjoxNDQ0OTE3NjQwLCJuYmYiOjE0NDQ5MTc2NDAsImV4cCI6MTQ0NDkxNzk0MH0.KPmI6WSjRjlpzecPvs3q_T3cJQvAgJvaQAPtk1abC_E"
}
그러면 서버에서는 access token을 복호화 해서 해당 유저 정보를 얻게 된다.
예를 들어 access token eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZGVudGl0eSI6MSwiaWF0IjoxNDQ0OTE3NjQwLCJuYmYiOjE0NDQ5MTc2NDAsImV4cCI6MTQ0NDkxNzk0MH0.KPmI6WSjRjlpzecPvs3q_T3cJQvAgJvaQAPtk1abC_E 를 복호화 하면 다음과 같은 정보를 얻는다:
{
user_id = 1
}
복호화해서 얻은 유저 아이디를 통해 해당 유저가 누군지 알 수 있다.
이런 절차의 목적은 해당 유저가 매번 로그인 하지 않도록 하는 것이다.
access token을 생성하는 방법은 여러가지가 있는데, 그 중 가장 널리 사용되는 기술중 하나가 바로 JWT(JSON Web Tokens)이다.
JWT는 말 그대로 유저 정보를 담음 JSON 데이터를 암호화 해서 클라이언트와 서버간에 주고 받는 것이다.
해당 유저가 request에 권한이 있는지 확인하는 절차
Token을 활용해 인가하여 http 특징 중 요청과 응답, stateless 문제를 해결함.
access token을 통해 해당 유저 정보를 얻을 수 있음으로 해당 유저가 가지고 있는 권한(permission)도 확인 할 수 있다
참고
https://sieunlim.tistory.com/16
https://www.zehye.kr/etc/2021/09/15/etc_encryt/
https://st-lab.tistory.com/100