사전 자격증명
개념

자격증명

gabury1고친 사람 github-actions[bot]

자격증명은 요청을 보낸 쪽이 누구인지, 무엇을 허락받았는지를 상대에게 증명해 줍니다. 로그인할 때 넣는 비밀번호도, 프로그램끼리 주고받는 키와 토큰도 이 일을 합니다. 받는 쪽은 이것을 확인하고 요청을 들여보낼지 정합니다. 그래서 자격증명이 새면 남이 그 주인 행세를 할 수 있습니다.

쉽고 빠른 이해

자격증명은 「내가 그 사람이 맞다」를 보여 주는 증거입니다. 아이디와 비밀번호 한 벌이 그 예입니다.

서버는 요청을 보낸 쪽의 얼굴을 볼 수 없습니다. 증거가 없으면 누구든 남의 이름을 대고 남의 데이터를 가져갈 수 있습니다.

  1. 발급하는 쪽이 주인에게 자격증명을 내줍니다
  2. 주인은 요청할 때 그것을 함께 보냅니다
  3. 받는 쪽은 자기가 아는 값과 맞춰 본 뒤 들여보낼지 정합니다

자격증명을 쓰면 지키는 수고가 따라옵니다. 받는 쪽은 그것을 누가 내밀었는지 가리지 못합니다. 훔친 사람도 주인으로 통합니다. 그래서 자격증명은 숨겨 둡니다. 샌 낌새가 보이면 곧바로 무효로 만듭니다. 그리고 새것을 받습니다.

상세

회사 건물 입구의 보안 요원은 드나드는 직원의 얼굴을 다 외우지 못합니다. 그래서 출입증을 보고 문을 열어 줍니다. 출입증을 대는 사람은 들어갑니다. 못 대는 사람은 문 앞에서 돌아갑니다.

자격증명(credential)은 「나는 누구다」나 「나는 이 일을 해도 된다」는 주장을 뒷받침하려고 상대에게 내미는 증거입니다. 로그인 폼에 넣는 아이디와 비밀번호 한 벌이 그 예입니다. 자격증명은 대개 한 번 쓰고 버리지 않습니다. 같은 것을 여러 번 내밉니다.

이 편에서 주인은 자격증명을 발급받아 쓰는 쪽입니다. 주인은 사람일 수도 있고 프로그램일 수도 있습니다. 검증자는 자격증명을 받아서 확인하는 쪽입니다.

발급자는 자격증명을 만들어 주인에게 내주는 쪽입니다. 발급자와 검증자는 같은 서버일 때가 많습니다.

이 절은 자격증명을 이루는 조각과 증명하는 방법부터 봅니다. 사람과 프로그램이 각각 무엇을 쓰는지도 봅니다. 그다음 자격증명 하나가 발급부터 폐기까지 거치는 단계를 그림으로 따라갑니다. 끝으로 새었을 때의 피해, 권한만 나누는 위임, 자격증명이 필요한 때를 봅니다.

이름을 대는 값과 증명하는 값

자격증명은 대개 두 조각이 한 벌입니다. 한 조각은 「나는 누구다」라고 이름을 댑니다. 아이디나 이메일 주소 같은 식별자가 이 일을 합니다.

식별자만으로는 증명이 안 됩니다. 식별자는 남도 알 수 있는 값이기 때문입니다. 주인만 아는 조각이 같이 있어야 합니다. 비밀번호가 이 조각입니다. 이렇게 주인 말고는 모르게 지켜야 하는 값이 시크릿(secret)입니다.

시크릿을 다루는 방식은 둘로 갈립니다. 비밀번호는 식별자와 함께 검증자에게 건너갑니다. 시크릿이 건너가지 않는 자격증명도 있습니다. 시크릿은 주인 쪽에 남습니다. 그것으로 만든 증거만 건너갑니다. 이쪽은 아래 「프로그램이 쓰는 자격증명」에서 봅니다.

증명하는 세 갈래

상대가 주장하는 신원이 맞는지 확인하는 일을 인증이라고 합니다. 자격증명은 인증에서 내미는 증거입니다.

무엇을 증거로 삼느냐는 세 갈래로 나뉩니다. 이 갈래가 인증 요소입니다.

인증 요소 무엇으로 증명하나 예
아는 것 주인의 머릿속에 있는 값 비밀번호 · 비밀 숫자
가진 것 주인 손에 있는 물건 휴대폰에 뜨는 일회용 코드 · 하드웨어 보안 키
주인 자신 몸의 특징 지문 · 얼굴

요소 하나만 쓰면 그 하나가 새는 순간 뚫립니다. 이를 막으려고 서로 다른 요소를 둘 이상 섞어 요구하기도 합니다. 이것을 다중 인증이라고 합니다. 비밀번호가 새도 공격자 손에 주인의 휴대폰이 없으면 로그인이 막힙니다.

사람이 쓰는 자격증명

사람은 로그인 화면에서 한 번 자격증명을 냅니다. 서버는 확인이 끝나면 로그인 상태를 가리키는 값을 하나 내줍니다. 세션 식별자나 토큰이 그 값입니다.

그 뒤의 요청은 비밀번호 대신 이 값을 싣고 옵니다. 이 값도 발급된 순간부터 자격증명 노릇을 합니다. 이 값을 훔치면 비밀번호를 몰라도 로그인한 사람 행세를 할 수 있습니다.

프로그램이 쓰는 자격증명

프로그램끼리 부를 때는 사람이 끼지 않습니다. 화면에 비밀번호를 칠 사람이 없습니다. 미리 받아 둔 값을 설정에 넣어 두고 요청마다 싣습니다. 백엔드 개발자가 자주 다루는 자격증명이 이쪽입니다.

이쪽 자격증명 가운데 인증서와 SSH(Secure Shell, 원격 접속 프로토콜) 키는 짝을 이루는 키 두 개를 씁니다. 하나는 주인만 갖는 개인 키입니다. 다른 하나는 누구에게 줘도 되는 공개 키입니다.

두 키는 서명으로 이어집니다. 서명은 개인 키로만 만들 수 있는 증거값입니다. 주인이 개인 키로 서명을 만들어 보내면, 검증자는 짝이 되는 공개 키로 그 서명이 맞는지 확인합니다. 검증자는 공개 키만 가지고도 상대가 개인 키를 가졌는지 알 수 있습니다.

공개 키만 받아서는 그 키가 누구의 것인지 알 수 없습니다. 그래서 공개 키와 주인의 신원을 한 문서에 적습니다. 믿을 만한 기관이 그 문서에 서명해 보증합니다. 이 문서가 인증서입니다.

인증서에 서명하는 기관은 인증 기관입니다. 검증자는 이 기관을 믿기 때문에, 기관이 서명한 인증서에 적힌 신원도 믿습니다.

아래 표는 프로그램이 흔히 쓰는 자격증명 넷을 생김새와 확인 방법으로 가릅니다.

종류 생김새 검증자가 확인하는 것
API(Application Programming Interface) 키 서비스가 발급한 긴 무작위 문자열 자기가 발급한 키 목록에 있나
액세스 토큰 권한을 내주는 서버가 발급한 문자열. 범위와 수명이 정해져 있다 토큰에 정해진 범위와 수명 안의 요청인가
인증서와 개인 키 인증 기관이 서명한 문서 한 장과, 주인만 가진 짝 키 신뢰하는 인증 기관이 서명했나 · 개인 키로 만든 서명이 맞나
SSH 키 SSH 서버에 들어갈 때 쓰는 공개 키와 개인 키 한 쌍 미리 등록해 둔 공개 키와 짝이 맞나

넷은 무엇이 네트워크를 건너가느냐로 두 무리로 갈립니다. API 키와 액세스 토큰은 값 자체가 요청에 실립니다. 인증서와 SSH 키는 개인 키가 네트워크로 아예 넘어가지 않습니다. 그 키로 만든 서명만 건너갑니다.

아래 그림은 인증서 쪽에서 무엇이 남고 무엇이 건너가는지 보입니다. SSH 키는 인증서 대신 검증자에게 미리 등록해 둔 공개 키를 씁니다.

sequenceDiagram
    participant 주인
    participant 검증자
    Note over 주인: 개인 키는 여기 남는다
    주인->>검증자: 개인 키로 만든 서명과 인증서를 보낸다
    Note over 검증자: 인증서에서 공개 키를 얻는다
    Note over 검증자: 그 공개 키로 서명을 확인한다

자격증명이 거치는 단계

자격증명 하나는 만들어진 뒤 여러 손을 거칩니다. 발급 → 보관 → 요청에 실어 보냄 → 확인 → 폐기 순서입니다. 아래 그림은 그 순서를 발급자 · 주인 · 검증자 셋 사이의 왕복으로 보입니다.

sequenceDiagram
    participant 발급자
    participant 주인
    participant 검증자
    발급자->>주인: 자격증명을 발급한다
    Note over 주인: 남이 못 보게 보관한다
    주인->>검증자: 요청에 자격증명을 싣는다
    Note over 검증자: 알고 있는 값과 맞춰 본다
    검증자-->>주인: 맞으면 요청을 처리한다
    발급자->>검증자: 폐기한 자격증명을 알린다
    Note over 검증자: 폐기된 값은 거절한다

발급자는 자격증명을 만들어 주인에게 줍니다. 주인은 남이 못 보게 보관했다가 요청마다 싣습니다. 검증자는 자기가 아는 값과 맞춰 보고 들여보낼지 정합니다.

더는 통하면 안 되는 자격증명은 발급자가 폐기합니다. 발급자는 폐기한 것을 검증자에게 알립니다. 검증자는 폐기된 값이 들어오면 거절합니다.

검증자가 쥔 「아는 값」은 자격증명과 꼭 같은 값이 아닙니다. 비밀번호라면 원문 대신 되돌리기 어려운 값으로 바꿔 저장합니다. 공개 키 방식이라면 공개 키만 가지고 있습니다. 단계마다 무엇을 지키는지는 운영 절이 다룹니다.

새었을 때의 피해

검증자는 자격증명이 맞는지만 확인합니다. 그것을 내민 쪽이 진짜 주인인지는 알 수 없습니다. 그래서 자격증명을 손에 넣은 공격자는 대개 그 주인 행세를 할 수 있습니다.

새는 길은 인증 요소마다 다릅니다.

인증 요소 새는 길
아는 것 공격자가 비밀번호를 짐작해 맞힌다 · 입력하는 손을 엿본다 · 적어 둔 메모를 찾는다 · 키 입력을 가로채는 악성 프로그램을 심는다 · 검증자의 비밀번호 저장소를 털어 오프라인에서 대입해 본다
가진 것 잃어버리거나 도둑맞는다 · 주인의 컴퓨터에 들어온 공격자가 소프트웨어로 된 인증 도구를 복사한다 · 다른 통로로 보낸 일회용 코드를 중간에서 가로챈다
주인 자신 공격자가 지문 사본으로 복제품을 만든다 · 검증자가 남을 주인으로 잘못 맞춘다

주인이 속아서 스스로 시크릿을 넘기기도 합니다. 가짜 로그인 화면으로 비밀번호를 받아 내는 공격을 피싱이라고 합니다.

여러 서비스에 같은 비밀번호를 쓰면 한 곳에서 샌 값으로 다른 곳에 들어갈 수 있습니다. 샌 비밀번호 목록을 가지고 여러 서비스에 차례로 넣어 보는 공격이 크리덴셜 스터핑입니다. 크리덴셜은 자격증명의 영어 이름 credential 을 소리 나는 대로 적은 말입니다.

자격증명을 넘기지 않고 권한만 나누기

사용자가 다른 서비스에게 자기 계정의 일부를 쓰게 하고 싶을 때가 있습니다. 사진 인화 서비스가 사진 공유 서비스에 올려 둔 내 사진을 읽어 가는 경우가 그렇습니다. 가장 단순한 길은 인화 서비스에 내 비밀번호를 알려 주는 것입니다.

이 길에는 문제가 여럿입니다.

문제 무슨 일이 생기나
저장 인화 서비스가 비밀번호를 나중에 또 쓰려고 저장해야 한다. 대개 평문이다
범위 비밀번호를 받은 쪽은 사진만이 아니라 계정의 모든 일을 할 수 있다
끊기 인화 서비스 하나만 끊으려 해도 비밀번호를 바꿔야 한다. 그러면 비밀번호를 알려 준 다른 서비스도 전부 끊긴다
유출 인화 서비스 하나가 털리면 비밀번호와, 그 비밀번호로 지키던 데이터가 함께 샌다

확인된 상대에게 무엇을 해도 되는지 정하는 일을 인가라고 합니다. 인증이 「누구인가」를 가린다면, 인가는 「무엇을 해도 되나」를 가립니다.

내 권한 일부를 남에게 맡기는 일은 위임입니다. OAuth 2.0 이 이런 위임을 정한 규격입니다. OAuth 2.0 은 비밀번호를 넘기는 대신 다른 자격증명을 따로 발급합니다.

이 일에는 넷이 나옵니다. 사진을 가진 사용자는 자원 소유자입니다. 사진을 보관하는 사진 공유 서비스는 자원 서버입니다. 사진을 읽어 가려는 쪽은 인화 서비스입니다.

넷째는 토큰을 내주는 인가 서버입니다. 사진 공유 서비스가 믿는 서버입니다. 인가 서버는 자원 소유자의 허락을 받고 나서 인화 서비스에 액세스 토큰을 내줍니다. 액세스 토큰은 허락된 범위와 수명이 정해진 문자열입니다.

sequenceDiagram
    participant 소유자 as 자원 소유자
    participant 인화 as 인화 서비스
    participant 인가 as 인가 서버
    participant 자원 as 자원 서버
    소유자->>인가: 직접 로그인하고 허락한다
    Note over 소유자,인가: 비밀번호는 이 둘 사이에서만 오간다
    인가->>인화: 액세스 토큰을 내준다
    인화->>자원: 토큰을 싣고 사진을 청한다
    자원-->>인화: 사진을 돌려준다

자원 소유자는 인가 서버에 직접 로그인합니다. 비밀번호는 인화 서비스에 넘어가지 않습니다. 인화 서비스는 토큰만 쥡니다. 이 편의 말로는 인화 서비스가 토큰의 주인입니다.

자원 소유자가 한 번 내준 이 허락을 인가 그랜트라고 합니다. 이렇게 받은 토큰은 누구인지보다 무엇을 허락받았는지를 증명합니다. 자격증명은 인증에도 쓰이고 인가에도 쓰입니다.

언제 필요한가

요청을 보낸 쪽이 누구인지에 따라 결과가 달라지는 곳이면 자격증명이 필요합니다. 앞 소절의 사진 공유 서비스에 올린 사진을 읽어 가는 요청이 그렇습니다. 누가 청하느냐에 따라 사진을 내줄지가 갈립니다.

누가 보내도 같은 답을 주는 공개 정보라면 자격증명 없이 엽니다. 공개 문서 페이지나, 서비스가 살아 있는지 묻는 상태 확인 주소가 그 예입니다.

배경

서버는 요청을 보낸 상대를 볼 수 없습니다. 요청은 네트워크를 건너온 바이트일 뿐입니다. 누구든 남의 아이디를 적어 보낼 수 있습니다. 상대가 내세운 신원이 맞는지 가리려면 그 주장을 뒷받침할 무언가가 요청에 함께 실려 와야 합니다.

사람 사이에서는 물건이 이 일을 해 왔습니다. 경찰 배지 · 운전면허증 · 여권이 그렇습니다. 영어로는 이런 물건이 credentials 입니다. 신원이나 권한 주장을 뒷받침하는 증거라는 뜻입니다.

이런 증거는 대개 여러 번 씁니다. 한 번 쓰는 데 드는 시간에 비해 수명이 깁니다. 들고 있는 사람은 보여 주기만 하면 됩니다.

인터넷 보안은 이 낱말을 빌려 왔습니다. 그런데 기계가 하는 인증은 대개 여러 단계를 거칩니다. 데이터도 여러 개 씁니다. 그 가운데 어느 것을 자격증명이라고 불러야 할지가 바로 드러나지 않을 수 있습니다. 이 갈림은 이견 절이 다룹니다.

예시

아래 넷은 각 소절이 다루는 공식 문서에 실린 예시 값을 바꾸지 않고 옮긴 것입니다. 앞의 셋은 식별자와 시크릿이 한 벌로 적혀 있습니다. 마지막 하나는 검증자 쪽 파일에 공개 키만 있습니다.

예시와 운영 절의 괄호 속 대문자 낱말은 표준 문서가 요구의 세기를 적는 말입니다. 뜻은 아래와 같습니다.

낱말 세기
MUST · SHALL 반드시 한다
MUST NOT · SHALL NOT 반드시 하지 않는다
SHOULD 되도록 한다. 까닭이 있으면 안 해도 된다
SHOULD NOT · NOT RECOMMENDED 되도록 하지 않는다
MAY · OPTIONAL 해도 되고 안 해도 된다

OAuth 2.0 클라이언트 자격증명

OAuth 2.0 에서 인가 서버에 토큰을 청하는 프로그램은 클라이언트입니다. 클라이언트는 비밀을 지킬 수 있느냐로 갈립니다. 클라이언트 비밀을 안전하게 지킬 수 있으면 기밀 클라이언트입니다. 지킬 수 없으면 공개 클라이언트입니다.

기밀 클라이언트는 대개 클라이언트 자격증명 한 벌을 발급받거나 인가 서버와 함께 정해 둡니다. 비밀번호일 수도 있고 공개 키·개인 키 한 쌍일 수도 있습니다. 아래는 클라이언트 식별자와 클라이언트 비밀번호를 쓰는 요청입니다. 클라이언트가 자기 자격증명만 내밀고 액세스 토큰을 청합니다.

http
POST /token HTTP/1.1
Host: server.example.com
Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
Content-Type: application/x-www-form-urlencoded

grant_type=client_credentials

Authorization: Basic 뒤의 값 하나에 클라이언트 식별자와 비밀번호가 함께 들어 있습니다. HTTP(HyperText Transfer Protocol) 기본 인증은 식별자를 사용자 이름 칸에, 비밀번호를 비밀번호 칸에 넣습니다. 두 값을 콜론으로 이은 뒤 Base64 로 인코딩해 한 값으로 싣습니다.

인가 서버는 이 요청에서 반드시 클라이언트를 인증합니다(MUST). 인증을 통과한 클라이언트는 액세스 토큰을 받습니다. 그 토큰이 다음 요청부터 쓰일 새 자격증명입니다.

리프레시 토큰은 새 액세스 토큰을 받아 오는 데 쓰는 자격증명입니다. 아래는 리프레시 토큰으로 액세스 토큰을 새로 받는 요청입니다. 이번에는 클라이언트 식별자와 비밀번호를 헤더 대신 본문에 실었습니다. 인가 서버에 따라 이 방식을 받아 주기도 합니다(MAY).

http
POST /token HTTP/1.1
Host: server.example.com
Content-Type: application/x-www-form-urlencoded

grant_type=refresh_token&refresh_token=tGzv3JOkF0XG5Qx2TlKWIA
&client_id=s6BhdRkqt3&client_secret=7Fjfp0ZBr1KtDRbnfVdmIw

이 요청에는 자격증명이 둘 실립니다. refresh_token 은 새 액세스 토큰을 청하는 근거입니다. client_id 와 client_secret 은 클라이언트 자신의 식별자와 시크릿입니다.

본문에 싣는 방식에는 규칙이 붙습니다. 아래 표의 TLS(Transport Layer Security, 전송 계층 보안)는 통신 구간을 암호화하는 규격입니다.

규칙 세기
식별자와 비밀번호를 본문에 싣는 방식은 권하지 않는다 NOT RECOMMENDED
기본 인증이나 다른 비밀번호 기반 HTTP 인증 방식을 못 쓰는 클라이언트만 이 방식을 쓴다 SHOULD
두 값은 본문에만 싣는다. 요청 주소에는 넣지 않는다 MUST NOT
비밀번호로 인증하는 요청에는 인가 서버가 TLS 를 요구한다 MUST

AWS 공유 자격증명 파일

AWS(Amazon Web Services)의 SDK(Software Development Kit, 소프트웨어 개발 도구 모음)와 도구에 인증과 설정을 알려 주는 가장 흔한 방법은 공유 설정 파일과 공유 자격증명 파일입니다. 「공유」는 한 사용자의 로컬 환경에서 도는 모든 프로그램과 SDK 에 그 값이 함께 적용된다는 뜻입니다. 아래는 자격증명 파일 한 벌입니다.

ini
[default]
aws_access_key_id=AKIAIOSFODNN7EXAMPLE
aws_secret_access_key=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
aws_session_token=IQoJb3JpZ2luX2IQoJb3JpZ2luX2IQoJb3JpZ2luX2IQoJb3JpZ2luX2IQoJb3JpZVERYLONGSTRINGEXAMPLE

[default] 는 프로필 이름입니다. aws_access_key_id 가 식별자, aws_secret_access_key 가 시크릿입니다. 셋째 줄 aws_session_token 도 비밀로 다루는 값입니다. 자격증명 파일에는 비밀로 다루는 이 세 설정만 들어갈 수 있습니다.

세 값은 공유 설정 파일에 둘 수도 있습니다. 그래도 AWS 는 따로 떼어 자격증명 파일에 두라고 권합니다. 그러면 필요할 때 파일마다 접근 권한을 다르게 줄 수 있습니다. 두 파일은 모두 평문입니다.

git credential

git 은 원격 저장소에 쓸 사용자 이름과 비밀번호를 찾아 주는 git credential 명령을 둡니다. 이 명령은 키=값 형식의 줄을 주고받습니다. git 은 이 줄 묶음을 자격증명 설명(credential description)이라 합니다.

아래는 https://example.com/foo.git 에 쓸 비밀번호를 찾는 설명입니다. 이 설명을 표준 입력으로 넣습니다. 끝에는 빈 줄을 하나 둡니다. 그 빈 줄이 입력이 끝났다고 git 에 알립니다.

protocol=https
host=example.com
path=foo.git

git credential fill 을 돌리면 출력에 사용자 이름과 비밀번호가 붙어 나옵니다.

protocol=https
host=example.com
username=bob
password=secr3t

protocol 과 host 두 줄은 어느 서버에 쓸 자격증명인지 찾는 열쇠입니다. username 과 password 두 줄이 자격증명 자체입니다.

출력은 대개 입력에 준 줄을 되풀이합니다. 다만 git 이 설명을 고쳐 내보내기도 합니다. 프로토콜이 HTTP(S) 이면서 credential.useHttpPath 설정이 false 면 path 줄을 지우는 것이 그 예입니다.

이 비밀번호로 접속해 받아들여지면, git credential 을 부른 프로그램이 approve 동작으로 git 에 알립니다. 그러면 git 은 다음에도 이 자격증명을 다시 씁니다. 거절당하면 reject 동작으로 알립니다. 그러면 git 은 다음에 새 비밀번호를 묻습니다.

OpenSSH authorized_keys

OpenSSH 의 공개 키 인증에서는 사용자가 키 한 쌍을 만듭니다. 서버는 공개 키를 압니다. 개인 키는 사용자만 압니다. 서버는 들어와도 되는 공개 키를 파일에 한 줄씩 적어 둡니다. 그 파일의 기본 위치는 계정의 ~/.ssh/authorized_keys 입니다.

# Comments are allowed at start of line. Blank lines are allowed.
# Plain key, no restrictions
ssh-rsa ...
# Forced command, disable PTY and all forwarding
restrict,command="dump /home" ssh-rsa ...

한 줄은 옵션 · 키 종류 · base64 로 적은 키 · 주석 순서로 칸을 띄어 씁니다. 옵션 칸은 없어도 됩니다.

위 파일의 첫 키는 아무 제한이 없습니다. 둘째 키는 restrict 로 가상 터미널과 모든 포워딩을 막습니다. 그리고 command 로 정한 명령 하나만 돌게 묶습니다.

로그인할 때 클라이언트는 자기가 개인 키를 쓸 수 있다는 것을 증명합니다. 서버는 그에 맞는 공개 키가 그 계정에 허락돼 있는지 봅니다. 검증자 쪽 파일에는 공개 키만 있습니다. 개인 키는 서버로 건너가지 않습니다.

이견

자격증명의 알맹이는 어디서나 같습니다. 주장을 뒷받침해 상대에게 내미는 증거입니다. 갈리는 것은 그 이름을 어느 데이터에 붙이느냐입니다. 같은 비밀번호를 두고 한 문서는 자격증명이라 부릅니다. 다른 문서는 다른 이름으로 부릅니다.

인터넷 보안 용어집의 좁은 뜻

IETF(Internet Engineering Task Force, 국제 인터넷 표준화 기구)가 낸 인터넷 보안 용어집 RFC 4949(Request for Comments, 의견 요청 문서)는 자격증명을 데이터 객체로 정의합니다. 이 객체는 식별자 하나와 인증 정보 한 단위가 서로 짝이라는 사실을 담습니다. 옮겨 다닐 수 있어야 합니다. 시스템에 들어오려는 쪽이 신원을 확인받을 때 내밀 수 있어야 합니다.

인증 정보는 이 용어집이 따로 쓰는 이름입니다. 개인 키가 그 예입니다. 개인 키는 사용자의 식별자에 일정 기간 묶여, 그동안 여러 번의 인증에 쓰입니다.

이 정의의 예로 용어집은 X.509 공개 키 인증서를 듭니다. X.509 는 인증서 형식을 정한 표준입니다. 식별자와 접근 권한의 짝을 담은 것은 권한 자격증명이라 부릅니다. 예는 신원 대신 권한을 담는 X.509 속성 인증서입니다.

RFC 4949 는 이 정의로 공개 키 로그인을 따져 봅니다. 이 과정에는 데이터가 적어도 셋 쓰입니다. 개인 키 · 그 개인 키로 서명한 값 · 사용자의 공개 키 인증서입니다.

데이터 자격증명인가 까닭
개인 키 아니다 건네지도 내밀지도 않는다. 이름은 「인증 정보」다
서명한 값 아니다 한 번 쓰고 마는 값이다. 오래가지 않는다
공개 키 인증서 그렇다 필요한 쪽에 언제든 건네고 내밀 수 있다

같은 용어집은 넓은 정의 「주장한 신원을 세우려고 건네는 데이터」를 쓰지 않기를 권합니다(SHOULD NOT). 이 권고가 걸리는 쪽은 RFC 처럼 IETF 의 표준 절차에서 나오는 문서입니다. 까닭은 인증 한 번에 여러 데이터가 오갈 수 있다는 것입니다. 그 전부가 자격증명은 아닙니다.

미국 정부 쪽 정의 「인증 거래에서 검증자에게 내밀 때 확인(verify)받는 객체」도 같은 문서들에 쓰지 않기를 권합니다(SHOULD NOT). 개념을 헷갈리게 섞는다는 까닭입니다. 이 용어집의 말로는 확인(verify)받는 것은 신원입니다. 자격증명은 유효성 검사(validate)를 받습니다. 이 편이 「검증자가 자격증명을 확인한다」고 쓴 말은 이 둘을 한데 묶은 것입니다.

미국 정부 신원 지침의 묶음 기록

NIST(National Institute of Standards and Technology, 미국 국립표준기술연구소)는 디지털 신원 지침 SP 800-63(Special Publication, 특별 간행물)을 냅니다. 지금 판은 개정 4판입니다. 개정 4판은 개정 3판(SP 800-63-3)을 대체합니다.

이 지침은 인증수단(authenticator)이라는 말을 따로 씁니다. 먼저 가입자는 서비스에 등록을 마친 사용자입니다. 인증수단은 가입자가 가지고 통제하는 것입니다. 가입자는 이것으로 신원을 확인받습니다.

이 지침에서 자격증명은 신원을 식별자를 거쳐 인증수단 하나 이상에 권위 있게 묶어 두는 객체나 자료구조입니다. 다른 속성을 더 묶을 수도 있습니다. 인증수단의 예로는 암호 모듈과 비밀번호를 듭니다. 이 뜻에서 비밀번호는 자격증명이 아니라 인증수단입니다.

자격증명은 자격증명 서비스 제공자가 발급하고 보관하고 관리합니다. 자격증명 서비스 제공자는 믿을 만한 기관입니다. 신청자의 신원을 확인하는 일과 인증수단을 가입자 계정에 등록하는 일을 맡습니다.

가입자 쪽에는 자격증명에 담긴 정보의 사본이 있을 수 있습니다. 그 사본은 대개 디지털 인증서입니다. 짝이 되는 개인 키와 함께 인증수단 안에 들어 있는 일이 많습니다.

위임 규격의 넓은 뜻

OAuth 2.0 을 정한 RFC 6749 는 비밀 값 자체를 자격증명이라고 부릅니다. 자원 소유자의 비밀번호 자격증명을 「곧 사용자 이름과 비밀번호」라고 적습니다. 클라이언트 자격증명의 예로는 비밀번호와 공개 키·개인 키 한 쌍을 듭니다. RFC 4949 가 인증 정보라 부른 개인 키도 이 쓰임에서는 자격증명 묶음에 듭니다.

인가 서버가 내주는 액세스 토큰도 같은 문서가 「위임 전용 자격증명」이라고 부릅니다. 자원 소유자의 자격증명과 다른 한 벌의 자격증명이라는 뜻입니다.

검증 가능한 자격증명

W3C(World Wide Web Consortium, 월드 와이드 웹 컨소시엄)의 검증 가능한 자격증명 데이터 모델 2.0 은 또 다른 데이터를 가리킵니다. 자격증명은 발급자가 만든 주장 하나 이상의 묶음입니다. 주장(claim)은 어떤 대상에 대해 내세운 말입니다. 한 자격증명 안의 주장들이 서로 다른 대상에 관한 것이어도 됩니다.

이 묶음이 두 성질을 갖추면 검증 가능한 자격증명이라 부릅니다. 하나는 누가 변조하면 흔적이 드러난다는 것입니다. 다른 하나는 누가 만들었는지를 암호 기법으로 확인할 수 있다는 것입니다. 이 문서는 자기 정의가 NIST 의 정의와 다르다고 직접 밝힙니다.

개발 도구의 쓰임

AWS 의 공유 자격증명 파일은 액세스 키 식별자 · 비밀 액세스 키 · 세션 토큰 셋을 담습니다. 파일 이름부터 credentials 입니다. AWS IAM(Identity and Access Management) 문서는 액세스 키를 「장기 자격증명」이라고 부릅니다. git 의 git credential 문서는 로그인 이름과 비밀번호를 「자격증명 그 자체」라고 부릅니다. 둘 다 OAuth 2.0 과 같은 넓은 쪽 쓰임입니다.

누가 자격증명이라 부르는 것 비밀번호 · 개인 키는
IETF · RFC 4949 식별자와 인증 정보의 짝을 담아 옮겨 다니는 데이터 객체. 예: 공개 키 인증서 개인 키는 「인증 정보」
NIST · SP 800-63 개정 4판 신원을 인증수단에 묶는 객체나 자료구조. 자격증명 서비스 제공자가 발급·보관·관리 비밀번호는 「인증수단」
OAuth 2.0 · RFC 6749 사용자 이름과 비밀번호 · 클라이언트 비밀번호나 키 한 쌍 · 액세스 토큰 그 자체가 자격증명
W3C · 검증 가능한 자격증명 2.0 발급자가 만든 주장의 묶음 정의에 나오지 않는다
AWS · git 문서 액세스 키 식별자와 비밀 키 · 사용자 이름과 비밀번호 그 자체가 자격증명

이 편의 상세와 운영은 넓은 쪽 쓰임을 따릅니다. 비밀번호와 키도 자격증명이라 부릅니다.

운영

자격증명을 굴릴 때 아픈 곳은 다섯입니다. 검증자의 비밀번호 저장, 바꾸는 때, 파일과 코드에 적힌 값, 폐기, 수명과 범위입니다.

검증자의 비밀번호 저장

비밀번호를 받는 검증자는 원문을 저장하지 않습니다. 오프라인 공격에 버티는 형태로 저장해야 합니다(SHALL). 솔트를 섞어 알맞은 비밀번호 해싱 스킴으로 해시해야 합니다(SHALL).

솔트는 비밀번호마다 따로 고르는 값입니다. 계정 여럿이 같은 해시값을 갖지 않게 합니다.

비밀번호 해싱 스킴은 비밀번호 · 솔트 · 비용 인자를 받아 해시를 냅니다. 비용 인자는 해시 한 번에 드는 계산량을 정하는 값입니다. 해시 파일을 훔친 공격자가 비밀번호를 하나 짐작해 볼 때마다 드는 비용을 키웁니다.

항목 요구
솔트 길이 32비트 이상 (SHALL). 저장된 해시끼리 솔트가 겹치지 않게 고른다
함께 저장할 값 솔트와 해시값 (SHALL) · 쓴 해싱 스킴과 비용 인자 (SHOULD). 뒤의 둘은 새 알고리즘으로 옮겨 갈 때 쓴다
비용 인자 검증자 성능을 해치지 않는 선에서 되도록 높게 (SHOULD) · 컴퓨터 성능이 오르는 만큼 시간이 지나며 올린다 (SHOULD)
한 번 더 감싸기 검증자만 아는 비밀 키로 키 있는 해시나 암호화를 한 번 더 (SHOULD) · 그 키는 해시와 따로 저장 (SHALL) · 하드웨어 보안 모듈 같은 하드웨어 보호 영역에 둔다 (SHOULD)
비밀번호를 받는 통로 승인된 암호화와 인증된 보호 채널 (SHALL)

바꾸는 때

검증자와 자격증명 서비스 제공자는 가입자에게 비밀번호를 정해진 주기마다 바꾸라고 요구하지 않습니다(SHALL NOT). 대신 비밀번호가 침해됐다는 증거가 있으면 검증자가 반드시 바꾸게 합니다(SHALL). 이 두 요구는 사람이 고르고 외우는 비밀번호에 걸립니다.

프로그램이 쓰는 키에는 다른 권고가 있습니다. AWS IAM 은 액세스 키 같은 장기 자격증명을 써야 한다면 필요할 때 갱신하라고 권합니다. 직원이 회사를 떠날 때가 그 예입니다. 키를 마지막으로 쓴 때를 보여 주는 정보를 보고 키를 갱신하거나 지우라고도 권합니다.

장기 키를 아예 안 만드는 길도 있습니다. AWS 의 컴퓨팅 서비스 위에서 도는 프로그램에는 IAM 역할의 임시 자격증명이 전달됩니다. SDK 로 짠 프로그램은 이 임시 자격증명을 찾아 씁니다. 그래서 장기 자격증명을 프로그램마다 나눠 줄 필요가 없습니다. AWS IAM 은 되도록 장기 자격증명 대신 임시 자격증명에 기대라고 권합니다.

파일과 코드에 적힌 자격증명

설정 파일이나 소스 코드에 적은 자격증명은 커밋과 함께 저장소 이력에 남습니다. GitHub 의 시크릿 스캐닝은 저장소 모든 브랜치의 git 이력 전체를 훑어 코드에 박힌 자격증명을 찾습니다. API 키 · 비밀번호 · 토큰이 대상입니다. 찾으면 그 저장소의 Security and quality 탭에 경고를 띄웁니다.

경고를 받으면 그 자격증명을 곧바로 갈아 끼웁니다. git 이력에서 값을 지울 수도 있습니다. 다만 시간이 많이 듭니다. 이미 폐기했다면 대개 할 필요가 없습니다.

코드 밖 파일로 옮겨도 그 파일이 평문일 수 있습니다. 앞의 AWS 자격증명 파일이 그렇습니다. 대신 비밀 값만 따로 모은 파일이라 그 파일에만 접근 권한을 따로 줄 수 있습니다.

폐기

OAuth 2.0 토큰은 폐기 요청 하나로 무효로 만듭니다. 클라이언트는 폐기할 토큰을 token 에 싣습니다. 자기 클라이언트 자격증명도 함께 실어 인증합니다. 어떤 종류의 토큰인지 token_type_hint 에 힌트로 실을 수도 있습니다(MAY). 인가 서버가 토큰을 찾는 일을 돕는 값입니다.

http
POST /revoke HTTP/1.1
Host: server.example.com
Content-Type: application/x-www-form-urlencoded
Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW

token=45ghiukldjahdnhzdauz&token_type_hint=refresh_token

기밀 클라이언트라면 인가 서버는 먼저 그 클라이언트 자격증명을 확인합니다. 이어서 그 토큰이 이 클라이언트에게 발급된 것인지 봅니다. 통과하면 토큰을 곧바로 무효로 만듭니다. 폐기된 토큰은 다시 쓸 수 없습니다.

다만 서버가 여럿이면 폐기 소식이 일부 서버에 늦게 닿을 수 있습니다.

리프레시 토큰을 폐기할 때, 인가 서버가 액세스 토큰 폐기를 지원하면 같은 인가 그랜트에서 나온 액세스 토큰도 되도록 무효로 만듭니다(SHOULD). 클라이언트는 토큰이 언제든 예고 없이 무효가 될 수 있다고 보고 대비해야 합니다.

수명과 범위

새는 것을 다 막지는 못합니다. 샌 토큰으로 할 수 있는 일을 미리 줄여 둡니다.

발신자에 묶인 토큰은 정해진 발신자만 쓸 수 있는 토큰입니다. 그 발신자가 어떤 비밀을 안다는 것을 보여야 받아들여집니다. 훔치거나 샌 토큰을 남이 함부로 못 쓰게 막으려는 장치입니다.

토큰을 발신자에 묶는 방식으로는 상호 TLS 와 DPoP(Demonstrating Proof of Possession, 소유 증명 시연)가 있습니다. 두 방식 모두 토큰을 특정 클라이언트에 암호 기법으로 묶습니다. 상호 TLS 는 TLS 연결에서 서버만이 아니라 클라이언트도 인증서를 내미는 방식입니다.

조치 줄이는 피해 세기
액세스 토큰의 권한을 그 용도에 필요한 최소로 샌 토큰으로 할 수 있는 일의 범위 SHOULD
액세스 토큰을 받아 줄 자원 서버를 하나나 몇 개로 묶기 샌 토큰이 통하는 서버 SHOULD
액세스 토큰을 발신자에 묶기 훔친 토큰을 남이 내미는 것 SHOULD
한동안 안 쓴 리프레시 토큰을 만료 잊힌 토큰이 계속 통하는 기간 SHOULD

리프레시 토큰은 더 단단히 묶습니다. 리프레시 토큰 로테이션은 인가 서버가 액세스 토큰을 새로 내줄 때마다 리프레시 토큰도 새로 내주는 방식입니다. 앞의 리프레시 토큰은 무효가 됩니다.

공개 클라이언트의 리프레시 토큰은 발신자에 묶거나 로테이션을 써야 합니다(MUST). 공개 클라이언트는 예시 절에서 본 대로 클라이언트 비밀을 안전하게 지킬 수 없는 클라이언트입니다.

로테이션을 쓰면 인가 서버가 침해를 알아챌 수 있습니다. 토큰이 새어 공격자와 정상 클라이언트가 둘 다 쓰면, 둘 중 하나는 무효가 된 토큰을 내밀게 됩니다. 인가 서버는 그것으로 침해를 알아챕니다.

sequenceDiagram
    participant 클라이언트
    participant 공격자
    participant 서버 as 인가 서버
    서버->>클라이언트: 리프레시 토큰 1 발급
    Note over 공격자: 토큰 1 을 훔친다
    클라이언트->>서버: 토큰 1 로 갱신을 청한다
    서버-->>클라이언트: 새 액세스 토큰과 토큰 2
    Note over 서버: 토큰 1 은 무효가 된다
    공격자->>서버: 토큰 1 로 갱신을 청한다
    Note over 서버: 무효 토큰이 왔다 · 침해로 본다
    Note over 서버: 살아 있는 토큰 2 를 폐기한다

인가 서버는 무효 토큰을 누가 내밀었는지 가리지 못합니다. 그래서 살아 있는 리프레시 토큰을 폐기합니다. 공격은 거기서 멈춥니다. 정상 클라이언트는 그 대가로 인가 그랜트를 새로 받아야 합니다.

인가 서버는 비밀번호가 바뀌거나 사용자가 인가 서버에서 로그아웃하면 리프레시 토큰을 자동으로 폐기해도 됩니다(MAY).

관련 항목

자격증명으로 치르는 확인 절차

인증 · 인가 · 인증과 인가 · 다중 인증 · 인증 요소 · 신원 증명 · 싱글 사인온 · HTTP 인증 · HTTP 기본 인증

자격증명의 하위 종류

비밀번호 · API 키 · 액세스 토큰 · 리프레시 토큰 · 세션 · 쿠키 · 인증서 · X.509 · 속성 인증서 · 클라이언트 인증서 · 개인 키 · SSH 키 · 보안 키 · 패스키 · 일회용 비밀번호 · JWT · 임시 자격증명 · 클라이언트 시크릿

자격증명을 발급하고 확인하는 역할

검증자 · 자원 소유자 · 자격증명 서비스 제공자 · 인증 기관 · 인가 서버 · 자원 서버 · 신뢰 당사자 · 가입자 · 기밀 클라이언트 · 공개 클라이언트

자격증명을 보관하고 지키는 방법

비밀번호 해싱 · 해시 함수 · 솔트 · 비용 인자 · 하드웨어 보안 모듈 · 시크릿 관리 · 환경 변수 · 키 관리 · 키 로테이션 · 최소 권한 · TLS · 상호 TLS · DPoP · 토큰 폐기 · 리프레시 토큰 로테이션 · 시크릿 스캐닝 · 공개 키

자격증명을 노리는 공격

자격증명 유출 · 피싱 · 크리덴셜 스터핑 · 무차별 대입 공격 · 사전 공격 · 키로거 · 사회 공학 · 세션 하이재킹 · 중간자 공격 · 재전송 공격

자격증명 대신 권한을 넘기는 위임 표준

OAuth 2.0 · OpenID Connect · SAML · 클라이언트 자격증명 그랜트 · 인가 그랜트 · 위임

자격증명을 정의하는 표준·문서

RFC 4949 · SP 800-63 · RFC 6749 · RFC 7009 · RFC 9700 · 검증 가능한 자격증명 · RFC 2119

자격증명을 저마다 다르게 정의하는 기구와 그 용어

IETF · NIST · W3C · 인증수단 · 인증 정보 · 디지털 신원 · 신원 제공자 · 클레임

자격증명을 담아 쓰는 개발 도구

git-credential · authorized_keys · OpenSSH · AWS IAM · AWS · GitHub

다른 이름: credential · credentials · 자격 증명 · 크리덴셜