ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • TIL.60 인증 & 인가 (Hash/Hashing)
    TIL 2020. 12. 7. 15:01
    728x90

    인증과 인가는 API에서 가장 자주 구현되는 가운데 하나이다.

    먼저 로그인 절차부터 차근차근 알아보자.

     

    로그인 절차 

    1. 유저 아이디와 비번 생성
    2. 유저 비번 암호화 해서 DB에 저장.
    3. 유저 로그인 -> 아이디와 비밀번호 입력
    4. 유저가 입력한 비밀번호 암호화 한후 암호화되서 DB에 저정된 유저 비밀번호와 비교.
    5. 일치하면 로그인 성공
    6. 로그인 성공하면 access token을 클라이언트에게 전송.
    7. 유저는 로그인 성공후 다음부터는 access token을 첨부해서 request를 서버에 전송함으로서 매번 로그인 해도 되지 않도록 한다.

     

    유저 비밀번호 암호화

    • 유저의 비밀번호는 절대 비밀번호 그대로 DB에 저장 하지 않는다.

      • DB가 해킹을 당하면 유저의 비밀번호도 그대로 노출 된다.
      • 외부 해킹이 아니더라도 내부 개발자나 인력이 유저들의 비밀번호를 볼 수 있다.
    • 유저의 비밀번호는 꼭 암호화 해서 저장 해야 한다.

      • 그럼으로 DB가 해킹을 당해도 비밀번호가 그대로 노출되지 않으며
      • 내부 인력도 비밀번호를 알 수가 없음.
    • 비밀번호 암호에는 단방향 해쉬 함수(one-way hash function)가 일반적으로 쓰인다.

      • 단방향 해시 함수는 원본 메시지를 변환하여 암호화된 메시지인 다이제스트(digest)를 생성한다. 원본 메시지를 알면 암호화된 메시지를 구하기는 쉽지만 암호화된 메시지로는 원본 메시지를 구할 수 없어서 단방향성(one-way) 이라고 한다.
      • 예를 들어, "test password"를 hash256이라는 해쉬 함수를 사용하면 0b47c69b1033498d5f33f5f7d97bb6a3126134751629f4d0185c115db44c094e 값이 나온다.
      • 만일 "test password2"를 hash256 해쉬 함수를 사용하면 d34b32af5c7bc7f54153e2fdddf251550e7011e846b465e64207e8ccda4c1aeb 값이 나온다. 실제 비밀번호는 비슷하지만 해쉬 함수 값은 완전히 틀린것을 볼 수 있다. 이러한 효과를 avalance라고 하는데 비밀번호 해쉬 값을 해킹을 어렵게 만드는 하나의 요소이다.
        In [21]: import hashlib
    
        In [22]: m = hashlib.sha256()
    
        In [23]: m.update(b"test password")
    
        In [24]: m.hexdigest()
        Out[24]: '0b47c69b1033498d5f33f5f7d97bb6a3126134751629f4d0185c115db44c094e'
    
        In [25]: m = hashlib.sha256()
    
        In [26]: m.update(b"test password2")
    
        In [27]: m.hexdigest()
        Out[27]: 'd34b32af5c7bc7f54153e2fdddf251550e7011e846b465e64207e8ccda4c1aeb'

    인증(Authentication)

    Authentication은 유저의 identification을 확인하는 절차

    먼저 인증을 하기 위해선 아이디와 비번을 생성할 수 있는 기능이 필요하다

    간단히 말해서 , 인증은 회원가입과 로그인을 말한다

     

    개발자로서의 인증이란

    우리 서비스를 누가 쓰는지? 어떻게 사용하는지? 추적이 가능하도록 하기 위해 필요하다

    이러한 추적으로 인해 쌓인 데이터는 서비스 및 사용자 피드백 의견 등으로 사용이 가능할 것이며

    이는 개발을 하는데 당연히 신경써야하는 부분 중 하나이다.

     

    인증에서 중요한 정보라 하면 당연, 아이디, 이메일 주소 , 비밀번호 등 사용자의 데이터가 가장 중요한 정보이며

    이 중 비밀번호가 제일 중요한 요소이며 데이터베이스에 저장하면서

    백엔드 개발자라 할지라도 유저의 비밀번호를 알 수 없게 끔해야한다.

     

    비밀번호를 관리해야하는 이유

    1. 법규상의 규제 -> 법으로 제정되어있다.

    2. 개인정보를 보호하기 위해 반드시 필수 관리 대상이다.

     

    비밀번호는 어떻게 관리해야 하는가?

    1. 데이터베이스에 저장 시 개인정보를 해싱을 사용하여 복원할 수 없도록 저장한다.(복호화 불가능)

    - >해싱하여 복원 할수 없도록 --> 저장한 백엔드 개발자조차 알지 못하도록 해야한다.

     

    2. 통신 시 개인정보를 주고받을때 SSL을 적용하여 암호화(HTTPS)

    (SSL 이라는 인증서를 이용해 암호화한 상태로 주고받음)

    자물쇠 모양이 있는지 확인!

    HTTP 와 HTTPS 차이 찾아보자

    SSL 인증서가 무엇인지 찾아보자


    * 해시 (Hash) 란?

    1. 해시란 데이터를 관리/유지 하기 위한 자료구조이다.

    원래의 해시 함수 목적은 메시지 인증과 무결성 체크가 목적이었다.

    하지만 해시 함수는 입력 값의 길이에 상관 없이 고정된 길이의 해시값(다이제스트)를 출력하는데

    입력 값이 조금만 바뀌더라도 전혀 다른 해시값이 출력되므로 이를 이용해 암호화에 많이 사용되고 있다.

     

    2. 해시는 리소스를 포기하고 속도를 끌어올리는거에 포커스가 맞춰져 있다.

    리스트나 인트와 같이 빠르게 검색하고 데이터베이스 테이블에서 원하는 정보를 빨리 찾을때 용이하다.

    (빠르게 검색하고 금방금방 찾아내기 위해 만들어낸 자료형 중의 하나!로 이해하자)

    원래는 암호화를 위해 만들어지진 않았으나 단방향 해쉬의 특징을 이용해 암호화에 적용하여 사용하게 되었다.

     

    아래 이미지와 같이

    데이터를 특정 조건, 규칙 등의 해시함수를 의해 분류가 되고

    분류된 데이터를 특정 조건, 규칙에 의해 데이터베이스 테이블 (해시 테이블)에 데이터를 집어넣게되는 과정

    전체를 해싱이라 한다.

     

    해시-해시테이블-해싱 5분만에 이해하기 - Gunny - YouTube

     


    단방향 해시(One-way-hash)란?

    위에서 언급한 비밀번호를 암호화하는데 사용되는 단방향 해시란 무엇일까?

    input -> output (O)

    input <- output (X)

    output으로 input으로 돌아올수 없는 특징을 가지고 있다.  -> 암호화는 가능하지만 복호화는 불가능하다

    따라서 원본을 알 수 없음으로 패스워드는 단방향 해시함수를 사용하여 암호화해줄 필요가 있다.

     

    또한 단방향 해쉬에서는 SHA-256 알고리즘 함수가 주로 사용한다.


    * SHA-256

    SHA(Secure Hash Algorithm, 안전한 해시 알고리즘) 함수들은 서로 관련된 암호학적 해시 함수들의 모음이다.

    이들 함수 미국 국가안보국(NSA)이 1993년에 처음으로 설계했으며 미국 국가 표준으로 지정되었다. SHA 함수군에 속하는 최초의 함수는 공식적으로 SHA라고 불리지만, 나중에 설계된 함수들과 구별하기 위하여 SHA-0이라고도 불린다. 2년 후 SHA-0의 변형인 SHA-1이 발표되었으며, 그 후에 4종류의 변형,

     SHA-224, SHA-256, SHA-384, SHA-512가 더 발표되었다. 이들을 통칭해서 SHA-2라고 하기도 한다.


    단방향 해쉬의 문제점

    1. 인식 가능성

    해시 함수의 특징은 입력 값의 길이에 상관없이 고정된 길이의 해시값(다이제스트)가 출력되는데,

    메시지가 같으면 다이제스트도 같으므로 다른 사용자와 패스워드가 같으면 다이제스트도 같아 

    한꺼번에 정보가 누출될 가능성있다.

    (어떤 사용자가 1234를 입력하든 같은 output이 나오는 단점

    사람들이 많이 사용하는 비밀번호의 경우 무작위로 찍어서 얻어 걸리는 경우가 있다.)

     

    2. 속도

    해시는 기본적으로 데이터/관리를 위한 자료구조 형식으로 위의 언급한 특징으로 인해 암호화에 사용되고 있다

    해시는 리소스(자원)을 포기하고 속도를 올린 특징을 가지고 있어 데이터에 빠르게 접근 할 수 있는 (장점)이 있지만

    처리 속도가 빠르기 때문에 무차별 대입공격인 (Brut force attack)을 당할 수 있다고 한다.

     

    이러한 단점을 보완하기 위해 나온것이 Salting 과 Key Stretching 이다.

    Salting 

    패스워드에 임의의 문자열인 salt를 추가하여 Digest를 생성하는데 salt는 최소 128bit 정도는 되어야 안전하다

    해시함수(Hash Function)의 문제점과 해결 (tistory.com)

    이제 데이터 정보를 빼와 Digest를 알아도 패스워드 일치 여부를 알기가 매우 어려워 지게 된다

    Salting 과 Keystreching을 이용해 무차별 대입공격인 (Brut force attack)을 막을 수 있다

    KeyStretching

    단방향 해쉬 값을 계산한 후 그 해쉬값을 또 해쉬하고 또 해쉬하고 이를 반복하는 것을 말한다.

    즉, salt로 생성된 Digest를 입력값으로 하여 새로운 Digest를 만들고 새로운 Digest를 입력값으로 또다시 새로운 Digest를 만드는 과정을 반복한다.

    Salting 과 Keystreching을 이용해 무차별 대입공격인 (Brut force attack)을 막을 수 있다

     

    이처럼 Salting 과 Keystreching으로 구성된 암호화 시스템은 구현하는 것이 아닌

    이미 검증된 암호화 시스템을 사용하는것이 안전하다.

    • PBKDF2 : 가장 많이 사용되며 Django에서 기본으로 사용 중이다. ISO-27001의 보안 규정을 준수하고 있다.
    • bcrypt : 애초부터 패스워드 저장을 목적으로 설계되어 매우 강력한 패스워드 다이제스트를 생성하는 시스템을 쉽게 구현할 수 있다. 관련된 라이브러리도 언어별로 쉽게 찾을 수 있다.
    • scrypt : 위 두 개보다 진보된 시스템이다. 만약 구현하려는 시스템이 매우 민감한 정보를 다루고, 보안 시스템을 구현하는 데 많은 비용을 투자할 수 있다면 사용한다.

    bcrypt

    Salting & KeyStretching 이용한 매우 강력한 Password Digest를 쉽게 구현할 수 있는 대표적 라이브러리

    해쉬 결과값에 salting값과 해시값 및 반복함수를 같이 보관하기 때문에 비밀번호 해싱을 적용하는데 있어

    DB설계를 복잡하게 할 필요가 없다.

    매우 강력한 Password Digest를 쉽게 구현할 수 있는 라이브러리이다.

    bcrypt 구조


    인가(Authorization)

    Authorization은 유저가 요청하는 request를 실행할 수 있는 권한이 있는 유저인가를 확인하는 절차이다.

    예를 들어, 해당 유저는 고객 정보를 볼 수 있는 있지만 수정 할 수는 없다 등

    Authroization도 JWT를 통해서 구현 될 수 있다.

    access token을 통해 해당 유저 정보를 얻을 수 있음으로

    해당 유저가 가지고 있는 권한(permission)도 확인 할 수 있다.

     

    사용자가 서버에 로그인하면 해당 사용자가 맞는가를 확인하는 과정 통틀어 인가라고 한다.

    ('가' -> 허락하다의 의미이다.)

     

    이는 아래와 같은 HTTP의 특징때문에 필요하다

    1. 요청/응답으로 이루어져있다는거

    2. stateless 한 성질(http 통신의 기본 특징)


    JWT(JSON Web Tokens)

    • 앞서 언급했듯이 유저가 로그인에 성공한 후에는 access token이라고 하는 암호화된 유저 정보를 첨부해서 request를 보내게 된다.
    • 그러면 서버에서는 access token복호화 해서 해당 유저 정보를 얻게 된다.
    • 복호화해서 얻은 유저 아이디를 통해 해당 유저가 누군지 알 수 있다.
    • 이런 절차의 목적은 해당 유저가 매번 로그인 해도 되지 않도록 하는 것이다.
    • access token을 생성하는 방법은 여러가지가 있는데, 그 중 가장 널리 사용되는 기술중 하가 바로 JWT(JSON Web Tokens)이다.
    • JWT는 말 그대로 유저 정보를 담음 JSON 데이터를 암호화 해서 클라이언트와 서버간에 주고 받는 것이다.

    JWT 구조

    Header (헤더)

    Header => Metadata 가 들어감

    토큰의 타입과 어떤 알고리즘으로 암호화가 되어있는지에 대한 정보를 담고 있어야 한다. 

    나는 HS256이라는 알고리즘으로 저장된 JWT야! 라고 알려주는것과 같다.



    Payload(내용)

    토큰은 티켓과 같은 의미이다.

    토큰에는 뭐가 담겨 있을까

    payload 내용 안에는 클라이언트와 서버간의 협의한에 사용하는 비공개 유저정보가 들어간다.

    서버만 딱 알아들을 수 있는 내용 + 만료기간(만료기간이 끝나면 로그인이 풀리는 이유 중 하나)


    Signature(서명)

    JWT 가 원본 그대로라는 것을 확인할때 사용하는 부분이다.

    프론트엔드가 JWT를 백엔드 API 서버로 전송하면 서버에서 전송받은 JWT의 서명부분을 복호화하여

    서버에서 생성한 JWT가 맞는지 확인한다.

    서명부분이 진짜 암호화를 해서 들어가는 부분이다.(중요정보)

    이러한 작업은 마치 넷플릭스 가입 유저가 넷플릭스에서 발행한 토큰을 가지고

    왓챠 서비스를 사용하러 들어가는 것으로 예를 들수있다.

    각 업체별로 JWT의 서명부분을 다르게 사용하는 이유이기도 하다

    또한 여기서 주의할 점은 헤더와 내용에는 단순히 인코딩된 정보(type 변환)로 되어있어

    누구나 원본을 볼 수 있으므로 개인정보를 이곳에 저장하여 통신하는 것은 멍청한 짓이다.

     

    * 복호화 (암호된걸 풀어서 우리 데이터가 맞는지 확인하기 위함)

     

     

    사용자가 로그인을 완료하며 백엔드 서버에서는 프론트 서버단으로 응답과 함께 토큰을 생성하여 전달해준다.

    그럼 프론트서버는 사용자의 요청에 의한 응답으로 전달받은 토큰이 부여된 데이터를 전송하여

    새로고침 및 페이지 이동 시, 이미 로그인을 해있다는 징표(?)로서 토큰을 사용해 통신을 주고받으며

    정해진 만료시간 내에서 추가 로그인 없이 서비스를 이용할 수 있다.

    (보통 이렇게 전달된 토큰은 사용자의 브라우저 (로컬, 세션 스토리지 등)에 저장된다.

    이러한 토큰을 JSON WEB TOKEN 이라는 일명 JWT라고 한다.

     

    즉, 토큰은 인가를 완료하였다는 것을 증빙하는 용도로 사용된다.

    로그인하면 토큰을 준다는 외운다는 의미로 이해하자

     


    정리

     

    인증 - > 회원가입하고 로그인까지가 다 인증

    Salting - 비밀번호에 랜덤한 문자열을 추가하는것

    KeyStretching - 솔팅을 여러번 반복하는 것 (붙히고 돌리고 붙히고 돌리고..)

    bcrypt - 솔팅과 키스트레칭을 일일이 할 수 없음으로 이용하는 라이브러리

    인가 - 로그인을 한 사람이 추가적인 서비스를 이용할 때 

    로그인을 해서 얻어낸 사실을 다음 (세션 ID, 토큰 등등) 인가는 로그인하고 나서의 일

    JWT = 인증 인가를 하기 위한 증명 장치 , 암호화된 유저정보를 담고 있는 장치 (웹에서 토크는 모두 JWT임)

    클라이언트가 서버에 요청을 보낼때만 필요한것 -> 토큰은 request 헤더안에 들어간다.

    백엔드에서는 이러한 json 형식의 데이터를 response body에 담아 보내준다.

    728x90

    'TIL' 카테고리의 다른 글

    TIL. 62 회원가입, 로그인 _ HTTP 통신  (0) 2020.12.09
    TIL.61 Bcrypt, Pyjwt (암호화)  (0) 2020.12.08
    TIL.56 SPA_UX 및 개발자  (0) 2020.12.04
    TIL.49 How the web works?  (0) 2020.11.27
    TIL.48 HTTP  (0) 2020.11.26
Designed by Tistory.