가장 많이 쓰이는 암호화 방식 중 하나인 해싱. 복호화가 가능한 다른 암호화 방식들과 달리, 해싱은 암호화만 가능하다.
해싱은 해시 함수(Hash Function)를 사용하여 암호화를 진행한다.
동일한 문자열에 동일한 해시 함수를 사용하면 항상 같은 결과값이 나온다는 특징을 가지고 보안상 위협을 줄 수 있다.
함수를 거치기 이전의 값을 알아낼 수 있도록 기록해 놓은 표인 레인보우 테이블라는 것이 있다. 레인보우 테이블에 기록된 값의 경우에는 유출이 되었을 때 해싱을 했더라도 해싱 이전의 값을 알아낼 수 있다.
이때 활용해서 위협을 줄이는 방법인 솔트라는 것이 있다. 소금을 치듯 해싱 이전 값에 이전 값에 임의의 값을 더해 데이터가 유츌되더라도 해싱 이전의 값을 알아내기 더욱 어렵게 만든다.
왜 복호화가 불가능한 암호화 방식을 이용할까?
서버에 비밀번호도 해싱해서 관리자도 모르게 한다. 결국 사용자가 비밀번호를 서버로 전달하면 해싱이 되고 서버에 저장된 비밀번호도 해싱되었기 때문에 둘이 서로 같은지만 보면 된다.
세션 방식과 다르게 서버에 정보를 저장하지 않고 클라이언트측에 사용자의 인증정보를 저장하는 방식이다. 세션 인증이 가지고 있는 한계를 극복하고자 고안되었다.
- 아이디와 패스워드를 서버에 로그인 요청
- 서버에서는 데이터베이스에 인증 정보 검증을 요청한다.
- 유효하면 해당 유저에 대한 토큰을 생성한다.
- 서버는 클라이언트에 토큰을 Authorization 헤더로 전달한다. (Authorization 헤더 말고도 Cookie로 가능)
- 클라이언트에 Token을 저장. (저장 위치는 Local storage, Session Storage, Cookie 등 다양)
- 다른 요청을 할 때 Token을 Autorization 헤더에 Token을 넣어서 요청한다.
- 서버에서는 유요한 토큰인지 검증한다.
- 유효하면 요청에 대한 응답 데이터를 클라이언트에 전송한다.
토큰 기반 인증 구현 시 대표적으로 사용하는 기술.
JWT의 구성은 .으로 3부분으로 구분된다.
Header, Payload, Signature
HTTP Header처럼
Header에는 토큰 자체를 설명하는 데이터. base64 방식으로 인코팅 되어있다. 얼마든지 인코딩할 수 있다. 민감한 정보를 담지 않아야 한다.
HTTP Payload처럼
전달하려는 내용물을 담고 있는 부분. 어떤 정보에 접근 가능하지에 대한 권한, 유저의 이름과 같은 개인정보, 토큰의 발급 시간 및 만료 시간 등의 정보들은 JSON 형태로 담는다.
토큰의 무결성을 확인할 수 있는 부분.
Header와 Payload 데이터를 토대로 서버의 비밀키(암호화에 추가할 salt)와 Header에서 지정한 알고리즘을 사용해서 해싱한다.
데이터를 변조하더라도 토큰을 발급할 때 Secret을 정확하게 모른다면 유요한 Signature을 만들 수 없기 때문에 토큰이 유효성을 보장한다.