1. 소개
이 섹션은 규범적인 내용이 아닙니다.
이 명세서는 웹 애플리케이션이 강력하고 증명 가능한, 범위 지정된 공개 키 기반 자격 증명을 생성하고 사용할 수 있도록 하는 API를 정의하며, 사용자를 강력하게 인증하는 목적을 가지고 있습니다. 공개 키 자격 증명은 WebAuthn 인증기에 의해 WebAuthn 의존 당사자의 요청에 따라 생성되고 저장되며, 사용자 동의의 대상이 됩니다. 이후 해당 공개 키 자격 증명은 그 오리진에 속하는 의존 당사자만 접근할 수 있습니다. 이 범위 지정은 준수하는 사용자 에이전트와 인증기에 의해 공동으로 강제됩니다. 또한 서로 다른 의존 당사자 간의 프라이버시도 유지됩니다; 한 의존 당사자는 다른 의존 당사자에 범위 지정된 자격 증명의 속성이나 존재 여부조차도 감지할 수 없습니다.
의존 당사자는 사용자와 관련된 두 가지 구별되지만 관련된
절차 동안 Web Authentication API를 사용합니다. 첫
번째는 등록으로, 이 절차에서는 공개 키 자격 증명이
인증기에 생성되어 현재 사용자의 계정에 범위 지정됩니다(계정은 이미 존재할 수도 있고 이때 생성될 수도 있습니다). 두
번째는 인증으로, 이 절차에서는 의존 당사자에게 등록된 사용자의 존재와 동의를 증명하는 인증
어설션이 제시됩니다. 기능적으로, Web Authentication API는 Credential Management API를 확장한 PublicKeyCredential과,
이러한 자격 증명을 navigator.credentials.create()
및 navigator.credentials.get()으로
사용하게 해 주는 인프라로 구성됩니다. 전자는 등록 동안
사용되며, 후자는 인증 동안 사용됩니다.
전반적으로, 준수하는 인증기는 공개 키 자격 증명을 보호하고, 사용자 에이전트와 상호 작용하여 Web Authentication API를 구현합니다. 준수하는 인증기는 (a) 범용 컴퓨팅 장치에서 소프트웨어로 실행되거나, (b) 기기 내 보안 실행 환경, 신뢰할 수 있는 플랫폼 모듈(TPM) 또는 보안 요소(SE) 상에서 동작하거나, (c) 장치 외부에서 구현될 수 있습니다. 장치 내에서 구현되는 인증기를 플랫폼 인증기(platform authenticators)라 부릅니다. 장치 외부에서 구현되는 인증기(예: 로밍 인증기)는 USB, 블루투스 저에너지(BLE), 근거리 무선 통신(NFC)과 같은 전송 수단을 통해 접근할 수 있습니다.
1.1. 명세 로드맵
많은 W3C 명세서가 주로 사용자 에이전트 개발자와 웹 애플리케이션 개발자(즉, "웹 저자")를 대상으로 하지만, Web Authentication의 특성상 이 명세서는 아래에 설명된 바와 같이 여러 대상이 올바르게 사용해야 합니다.
모든 대상은 먼저 § 1.2 사용 사례, § 1.3 샘플 API 사용 시나리오, 및 § 4 용어를 읽어야 하며, 전체 튜토리얼을 위해 [WebAuthnAPIGuide]도 참조해야 합니다. 그 밖에 이 문서의 의도된 주요 대상은 다음과 같습니다.
-
의존 당사자 웹 애플리케이션 개발자 — 특히 로그인 흐름, 계정 복구 흐름, 사용자 계정 데이터베이스 내용 등을 담당하는 사람들.
-
웹 프레임워크 개발자
-
위의 두 대상은 특히 § 7 WebAuthn 의존 당사자 작업을 참조해야 합니다. § 5 Web Authentication API의 도입부가 도움이 될 수 있지만, 해당 섹션은 사용자 에이전트 개발자를 구체적으로 겨냥하고 있음을 이해해야 합니다. 또한 인증기의 증명을 검증하려는 경우 § 6.5 증명 및 § 8 정의된 증명 문장 형식도 관련이 있습니다. 확장을 사용하려면 § 9 WebAuthn 확장과 § 10 정의된 확장이 관심 대상이 될 것입니다. 마지막으로, § 13.4 의존 당사자를 위한 보안 고려사항 및 § 14.6 의존 당사자를 위한 개인정보 고려사항을 읽고 어떤 과제가 애플리케이션과 사용자에 적용되는지 고려해야 합니다.
-
-
사용자 에이전트 개발자
-
운영체제 플랫폼 개발자 — 플랫폼별 인증기 API 설계 및 구현, 플랫폼별 WebAuthn 클라이언트 인스턴스화 등에 책임이 있는 사람들.
-
위의 두 대상은 확장을 지원하려는 경우 § 5 Web Authentication API와 함께 § 9 WebAuthn 확장을 매우 주의 깊게 읽어야 합니다. 또한 § 14.5 클라이언트를 위한 개인정보 고려사항를 주의 깊게 읽어야 합니다.
-
-
인증기 개발자. 이 독자들은 § 6 WebAuthn 인증기 모델, § 8 정의된 증명 문장 형식, § 9 WebAuthn 확장, 및 § 10 정의된 확장을 특히 주의 깊게 볼 것입니다. 또한 § 13.3 인증기를 위한 보안 고려사항 및 § 14.4 인증기를 위한 개인정보 고려사항도 주의 깊게 읽어야 합니다.
Web Authentication 배포의 종단 간 보안을 위해 각 구성 요소—의존 당사자 서버, 클라이언트, 및 인증기—의 역할과 § 13 보안 고려사항 및 § 14 개인정보 고려사항을 모든 대상이 이해하는 것이 중요합니다.
1.2. 사용 사례
아래 사용 사례 시나리오는 두 가지 매우 다른 유형의 인증기와 두 가지 일반적인 배포 유형에서의 자격 증명 사용을 설명하고, 추가 시나리오의 개요도 제공합니다. 추가 시나리오(샘플 코드 포함)는 이후 § 1.3 샘플 API 사용 시나리오에 제시되어 있습니다. 이 예제들은 예시용일 뿐이며, 기능 가용성은 클라이언트 및 인증기 구현에 따라 다를 수 있습니다.
1.2.1. 다중 장치 자격 증명을 사용하는 소비자
이 사용 사례는 소비자 중심의 의존 당사자가 사용자의 장치에 내장된 인증기를 활용하여 다중 장치 자격 증명(일반적으로 동기화된 패스키라고 함)을 사용한 피싱 저항 로그인 제공 방법을 보여줍니다.
1.2.1.1. 등록
-
휴대전화에서:
-
사용자가 브라우저에서 example.com으로 이동하여 기존 계정에 자신이 사용하던 방법(예: 기존 비밀번호 등)으로 로그인하거나 새 계정을 생성합니다.
-
휴대전화가 "example.com에 대한 패스키를 만들겠습니까?"라는 메시지를 표시합니다.
-
사용자가 동의합니다.
-
휴대전화가 이전에 구성된 권한 제스처(PIN, 생체 인식 등)를 요청하며, 사용자가 이를 제공합니다.
-
웹사이트에 "등록이 완료되었습니다."라는 메시지가 표시됩니다.
-
1.2.1.2. 인증
-
노트북 또는 데스크톱에서:
-
사용자가 브라우저에서 example.com으로 이동하여 로그인 절차를 시작합니다.
-
장치에서 다중 장치 자격 증명(일반적으로 동기화된 패스키라고 함)이 사용 가능한 경우:
-
브라우저나 운영체제가 이전에 구성된 권한 제스처(PIN, 생체 인식 등)를 요청합니다; 사용자가 이를 제공합니다.
-
웹 페이지는 선택된 사용자가 로그인되었음을 표시하고, 로그인 후 페이지로 이동합니다.
-
-
동기화된 패스키가 장치에서 이용할 수 없는 경우:
-
브라우저나 운영체제가 전화기나 보안 키와 같은 외부 인증기를 요청합니다.
-
사용자가 이전에 연결한 휴대전화를 선택합니다.
-
-
-
다음으로, 휴대전화에서:
-
사용자가 "example.com에 로그인"이라는 알림이나 알림창을 봅니다.
-
사용자가 이 알림을 선택합니다.
-
사용자에게 example.com의 신원 목록(예: "Mohamed로 로그인 / 张三로 로그인")이 표시됩니다.
-
사용자가 신원을 선택하고 권한 제스처(PIN, 생체 인식 등)를 요청받아 이를 제공합니다.
-
-
이제 노트북으로 돌아가면:
-
웹 페이지는 선택된 사용자가 로그인되었음을 표시하고, 로그인 후 페이지로 이동합니다.
-
1.2.2. 단일 장치 자격 증명을 사용하는 인력
이 사용 사례는 인력 중심의 의존 당사자가 USB 보안 키와 같은 로밍 인증기와 내장 지문 센서와 같은 플랫폼 인증기의 조합을 활용하여 사용자가 다음을 가질 수 있도록 하는 방법을 보여줍니다:
-
새로운 클라이언트 장치(예: 노트북, 데스크톱)에서 인증할 때 사용하거나 플랫폼 인증기가 없는 클라이언트 장치에서 사용하는 "주(primary)" 로밍 인증기,
-
플랫폼 인증기가 있는 클라이언트 장치에서 낮은 마찰로 강력하게 재인증할 수 있는 수단, 또는
-
단일 장치 자격 증명(single-device credentials, 일반적으로 장치 바인딩된 패스키라 함)을 지원하지 않는 패스키 플랫폼 인증기가 있는 클라이언트 장치에서 강력하게 재인증할 수 있는 수단.
1.2.2.1. 등록
이 예에서는 사용자의 고용주가 장치 바인딩된 패스키로 미리 구성된 보안 키를 우편으로 보냅니다.
임시 PIN이 채널 밖(예: RCS 메시지 등)을 통해 사용자에게 전송되었습니다.
1.2.2.2. 인증
-
노트북 또는 데스크톱에서:
-
사용자가 브라우저에서 corp.example.com으로 이동하여 로그인 절차를 시작합니다.
-
브라우저나 운영체제가 사용자에게 보안 키를 요구합니다.
-
사용자가 USB 보안 키를 연결합니다.
-
USB 보안 키는 버튼을 누르라는 신호를 보내며, 사용자가 이를 누릅니다.
-
브라우저나 운영체제가 사용자에게 PIN을 입력하라고 요청합니다.
-
사용자는 제공된 임시 PIN을 입력하고 계속 진행합니다.
-
브라우저나 운영체제가 사용자가 PIN을 변경해야 한다고 알려주고 새 PIN을 요청합니다.
-
사용자가 새 PIN을 입력하고 계속합니다.
-
브라우저나 운영체제가 인증 흐름을 재시작하고 사용자가 PIN을 입력하도록 요청합니다.
-
사용자가 새 PIN을 입력하고 보안 키를 탭합니다.
-
웹 페이지는 선택된 사용자가 로그인되었음을 표시하고, 로그인 후 페이지로 이동합니다.
-
1.2.3. 기타 사용 사례 및 구성
다음과 같은 다양한 추가 사용 사례 및 구성도 가능합니다(예시는 제한되지 않음):
-
사용자가 노트북에서 example.com으로 이동하여 휴대전화에서 자격 증명을 생성하고 등록하도록 안내되는 흐름.
-
사용자가 USB 및/또는 NFC 연결 옵션을 가진 보안 키와 같은 별도의 로밍 인증기를 획득하고, 노트북이나 휴대전화의 브라우저에서 example.com을 로드한 뒤 보안 키에서 자격 증명을 생성하고 등록하도록 안내되는 흐름.
-
의존 당사자가 단일 거래(예: 결제 또는 기타 금융 거래)를 승인하기 위해 사용자에게 권한 제스처를 요청하는 경우.
1.3. 샘플 API 사용 시나리오
이 섹션은 규범적인 내용이 아닙니다.
이 섹션에서는 공개 키 자격 증명의 수명 주기에서 발생하는 몇 가지 이벤트와 이 API를 사용하는 해당 샘플 코드를 살펴봅니다. 이는 예시 흐름이며 API 사용 범위를 제한하지 않습니다.
이전 섹션과 마찬가지로, 이 흐름은 자체 디스플레이가 있는 패스키 로밍 인증기를 사용하는 사용 사례에 초점을 맞춥니다. 이러한 인증기의 예로는 스마트폰이 있습니다. 다른 인증기 유형도 이 API에 의해 지원되며 이는 클라이언트 플랫폼의 구현에 따라 달라집니다. 예를 들어, 이 흐름은 클라이언트 장치에 내장된 인증기의 경우에도 수정 없이 작동합니다. 자체 디스플레이가 없는 인증기(스마트 카드와 유사한)의 경우에도 특정 구현 고려사항이 충족되면 흐름이 작동합니다. 구체적으로, 클라이언트 플랫폼은 인증기가 표시했을 프롬프트를 대신 표시해야 하고, 인증기는 클라이언트 플랫폼이 모든 인증기 자격 증명을 열거할 수 있도록 허용해야 하여 클라이언트가 적절한 프롬프트를 표시할 정보를 가질 수 있어야 합니다.
1.3.1. 등록
이것은 최초 흐름으로, 새 자격 증명이 생성되어 서버에 등록됩니다. 이 흐름에서 WebAuthn 의존 당사자는 플랫폼 인증기(platform authenticators)나 로밍 인증기(roaming authenticators) 중 특정 선호를 갖지 않습니다.
-
사용자가 example.com을 방문하면 스크립트를 제공합니다. 이 시점에서 사용자는 이미 기존 사용자 이름과 비밀번호 또는 추가 인증기 등 의존 당사자가 허용하는 다른 수단으로 로그인했을 수 있으며, 또는 새 계정을 생성하는 중일 수 있습니다.
-
의존 당사자 스크립트가 아래 코드 스니펫을 실행합니다.
-
클라이언트 플랫폼이 인증기를 검색하고 찾습니다.
-
클라이언트가 필요한 경우 페어링 동작을 수행하면서 인증기에 연결합니다.
-
인증기는 사용자에게 생체 인식 또는 다른 권한 제스처를 제공하라는 적절한 UI를 표시합니다.
-
인증기는 클라이언트에 응답을 반환하며, 클라이언트는 다시 의존 당사자 스크립트에 응답을 반환합니다. 사용자가 인증기 선택을 거부하거나 권한 제공을 거부한 경우 적절한 오류가 반환됩니다.
-
새 자격 증명이 생성된 경우,
-
의존 당사자 스크립트는 새로 생성된 자격 증명 공개 키를 서버에 전송하며, 인증기의 출처 및 특성에 관한 증명(attestation)과 같은 추가 정보를 함께 보냅니다.
-
서버는 자격 증명 공개 키를 데이터베이스에 저장하고 이를 사용자 및 증명에서 나타난 인증 특성과 연관시키며, 나중에 사용할 친숙한 이름도 저장합니다.
-
스크립트는 향후 사용자 경험을 개선하기 위해 자격 증명 ID와 같은 데이터를 로컬 스토리지에 저장할 수 있습니다.
-
새 키를 생성하고 등록하는 샘플 코드는 다음과 같습니다:
if ( ! window. PublicKeyCredential) { /* Client not capable. Handle error. */ } var publicKey= { // The challenge is produced by the server; see the Security Considerations challenge: new Uint8Array([ 21 , 31 , 105 /* 29 more random bytes generated by the server */ ]), // Relying Party: rp: { name: "ACME Corporation" }, // User: user: { id: Uint8Array. from ( window. atob( "MIIBkzCCATigAwIBAjCCAZMwggE4oAMCAQIwggGTMII=" ), c=> c. charCodeAt( 0 )), name: "alex.mueller@example.com" , displayName: "Alex Müller" , }, // This Relying Party will accept either an ES256 or RS256 credential, but // prefers an ES256 credential. pubKeyCredParams: [ { type: "public-key" , > alg: - 7 // "ES256" as registered in the IANA COSE Algorithms registry }, { type: "public-key" , > alg: - 257 // Value registered by this specification for "RS256" } ], authenticatorSelection: { // Try to use UV if possible. This is also the default. userVerification: "preferred" }, timeout: 300000 , // 5 minutes excludeCredentials: [ // Don't re-register any authenticator that has one of these credentials { "id" : Uint8Array. from ( window. atob( "ufJWp8YGlibm1Kd9XQBWN1WAw2jy5In2Xhon9HAqcXE=" ), c=> c. charCodeAt( 0 )), "type" : "public-key" }, { "id" : Uint8Array. from ( window. atob( "E/e1dhZc++mIsz4f9hb6NifAzJpF1V4mEtRlIPBiWdY=" ), c=> c. charCodeAt( 0 )), "type" : "public-key" } ], // Make excludeCredentials check backwards compatible with credentials registered with U2F extensions: { "appidExclude" : "https://acme.example.com" } }; // Note: The following call will cause the authenticator to display UI. navigator. credentials. create({ publicKey}) . then( function ( newCredentialInfo) { // Send new credential info to server for verification and registration. }). catch ( function ( err) { // No acceptable authenticator or user refused consent. Handle appropriately. });
1.3.2. 사용자 검증 플랫폼 인증기를 사용한 등록 예시
이 예시는 WebAuthn 의존 당사자가 특히 공개 키 자격 증명을 사용자 검증 플랫폼 인증기으로 생성하는 데 관심이 있을 때의 흐름입니다.
-
사용자가 example.com을 방문하고 로그인 버튼을 클릭하면 login.example.com으로 리디렉션됩니다.
-
사용자가 사용자 이름과 비밀번호로 로그인합니다. 로그인 성공 후 사용자는 다시 example.com으로 리디렉션됩니다.
-
의존 당사자 스크립트가 아래 코드 스니펫을 실행합니다.
-
사용자 에이전트는 사용자 검증 플랫폼 인증기가 사용 가능한지 확인합니다. 사용 불가능하면 이 흐름을 종료합니다.
-
의존 당사자는 사용자에게 함께 자격 증명을 생성할지 묻습니다. 원치 않으면 흐름을 종료합니다.
-
사용자 에이전트 및/또는 운영체제는 적절한 UI를 표시하고 사용자가 사용 가능한 플랫폼 인증기 중 하나를 사용하여 자격 증명을 생성하도록 안내합니다.
-
자격 증명 생성에 성공하면 의존 당사자 스크립트는 새 자격 증명을 서버로 전달합니다.
-
if ( ! window. PublicKeyCredential) { /* Client not capable of the API. Handle error. */ } PublicKeyCredential. isUserVerifyingPlatformAuthenticatorAvailable() . then( function ( uvpaAvailable) { // If there is a user-verifying platform authenticator if ( uvpaAvailable) { // Render some RP-specific UI and get a Promise for a Boolean value return askIfUserWantsToCreateCredential(); } }). then( function ( userSaidYes) { // If there is a user-verifying platform authenticator // AND the user wants to create a credential if ( userSaidYes) { var publicKeyOptions= { /* Public key credential creation options. */ }; return navigator. credentials. create({ "publicKey" : publicKeyOptions}); } }). then( function ( newCredentialInfo) { if ( newCredentialInfo) { // Send new credential info to server for verification and registration. } }). catch ( function ( err) { // Something went wrong. Handle appropriately. });
1.3.3. 인증
이것은 이미 등록된 자격 증명을 가진 사용자가 웹사이트를 방문하여 해당 자격 증명으로 인증하려는 흐름입니다.
-
사용자가 example.com을 방문하면 스크립트를 제공합니다.
-
스크립트는 가능한 한 많은 정보를 제공하여 사용자에 대해 허용 가능한 자격 증명의 선택을 좁히기 위해 클라이언트에게 인증 어설션을 요청합니다. 이 정보는 등록 후 로컬에 저장된 데이터나 사용자에게 사용자 이름을 묻는 등의 다른 수단으로 얻을 수 있습니다.
-
의존 당사자 스크립트가 아래 코드 스니펫 중 하나를 실행합니다.
-
클라이언트 플랫폼이 인증기를 검색하고 찾습니다.
-
클라이언트가 필요한 경우 페어링 동작을 수행하면서 인증기에 연결합니다.
-
인증기는 사용자의 주의가 필요하다는 알림을 표시합니다. 알림을 열면 사용자는 자격 증명을 생성할 때 제공된 계정 정보를 사용하여 허용 가능한 자격 증명의 친숙한 선택 메뉴와, 이러한 키를 요청하는 오리진에 대한 일부 정보를 보게 됩니다.
-
인증기는 사용자로부터 생체 인식 또는 다른 권한 제스처를 얻습니다.
-
인증기는 클라이언트에 응답을 반환하고, 클라이언트는 다시 의존 당사자 스크립트에 응답을 반환합니다. 사용자가 자격 증명 선택을 거부하거나 권한 제공을 거부한 경우 적절한 오류가 반환됩니다.
-
어설션이 성공적으로 생성되어 반환된 경우,
만약 의존 당사자 스크립트가 로컬에 저장된 데이터 등과 같이 자격 증명 목록을 좁히는 힌트를 갖고 있지 않다면, 인증을 수행하는 샘플 코드는 다음과 같을 수 있습니다:
if ( ! window. PublicKeyCredential) { /* Client not capable. Handle error. */ } // credentialId is generated by the authenticator and is an opaque random byte array var credentialId= new Uint8Array([ 183 , 148 , 245 /* more random bytes previously generated by the authenticator */ ]); var options= { // The challenge is produced by the server; see the Security Considerations challenge: new Uint8Array([ 4 , 101 , 15 /* 29 more random bytes generated by the server */ ]), timeout: 300000 , // 5 minutes allowCredentials: [{ type: "public-key" , id: credentialId}] }; navigator. credentials. get({ "publicKey" : options}) . then( function ( assertion) { // Send assertion to server for verification }). catch ( function ( err) { // No acceptable credential or user refused consent. Handle appropriately. });
반면, 의존 당사자 스크립트가 자격 증명 목록을 좁히는 데 도움이 되는 힌트를 가지고 있다면, 다음과 같은 샘플 코드가 될 수 있습니다. 이 샘플은 자격 증명 속성 확장을 사용하는 방법도 보여줍니다.
if ( ! window. PublicKeyCredential) { /* Client not capable. Handle error. */ } var encoder= new TextEncoder(); var acceptableCredential1= { type: "public-key" , id: encoder. encode( "BA44712732CE" ) }; var acceptableCredential2= { type: "public-key" , id: encoder. encode( "BG35122345NF" ) }; var options= { // The challenge is produced by the server; see the Security Considerations challenge: new Uint8Array([ 8 , 18 , 33 /* 29 more random bytes generated by the server */ ]), timeout: 300000 , // 5 minutes allowCredentials: [ acceptableCredential1, acceptableCredential2], extensions: { 'credProps' : true } }; navigator. credentials. get({ "publicKey" : options}) . then( function ( assertion) { // Send assertion to server for verification }). catch ( function ( err) { // No acceptable credential or user refused consent. Handle appropriately. });
1.3.4. 인증 작업 중단
아래 예시는 개발자가 AbortSignal 매개변수를 사용하여 자격 증명 등록 작업을 중단하는 방법을 보여줍니다. 인증 작업에도 유사한 절차가 적용됩니다.
const authAbortController= new AbortController(); const authAbortSignal= authAbortController. signal; authAbortSignal. onabort= function () { // Once the page knows the abort started, inform user it is attempting to abort. } var options= { // A list of options. } navigator. credentials. create({ publicKey: options, signal: authAbortSignal}) . then( function ( attestation) { // Register the user. }). catch ( function ( error) { if ( error== "AbortError" ) { // Inform user the credential hasn't been created. // Let the server know a key hasn't been created. } }); // Assume widget shows up whenever authentication occurs. if ( widget== "disappear" ) { authAbortController. abort(); }
1.3.5. 운영 중지(Decommissioning)
다음은 자격 증명 운영 중지(제거)를 원할 수 있는 가능한 상황들입니다. 이 모든 상황은 서버 측에서 처리되며 여기 지정된 API의 지원을 필요로 하지 않습니다.
-
가능성 #1 — 사용자가 자격 증명을 분실했다고 신고하는 경우.
-
가능성 #2 — 서버가 비활성으로 인해 자격 증명을 등록 해제하는 경우.
-
서버는 유지 관리 활동 중에 데이터베이스에서 자격 증명을 삭제합니다.
-
향후에는 의존 당사자 스크립트가 해당 자격 증명을 허용 목록에 포함시키지 않으며, 해당 자격 증명으로 서명된 어설션은 거부됩니다.
-
-
가능성 #3 — 사용자가 인증기에서 자격 증명을 삭제하는 경우.
-
사용자는 인증기-특유의 방법(예: 기기 설정 UI)을 사용하여 인증기에서 자격 증명을 삭제합니다.
-
이 시점부터 해당 자격 증명은 선택 프롬프트에 나타나지 않으며, 더 이상 해당 자격 증명으로 어설션을 생성할 수 없습니다.
-
나중에 서버가 비활성으로 인해 이 자격 증명을 등록 해제할 수 있습니다.
-
1.4. 플랫폼별 구현 지침
이 명세서는 일반적인 사례에서 Web Authentication을 사용하는 방법을 정의합니다. 특정 플랫폼 지원(예: 앱)과 연계하여 Web Authentication을 사용할 때는 추가 지침과 제한 사항에 대해서는 플랫폼별 문서와 가이드를 참조하는 것이 권장됩니다.
2. 준수
이 명세서는 세 가지 준수 클래스(conformance classes)를 정의합니다. 이들 각 클래스는 해당 클래스의 준수 구성원이 다른 클래스의 비준수 또는 적대적 구성원에 대해 안전하도록 지정되어 있습니다.
2.1. 사용자 에이전트
사용자 에이전트는 준수로 간주되기 위해 § 5 Web Authentication API에 설명된 대로 동작해야 합니다. 준수하는 사용자 에이전트는 이 명세서에 제시된 알고리즘을 원하는 방식으로 구현할 수 있지만, 최종 결과는 명세서의 알고리즘으로 얻을 수 있는 결과와 구별되지 않아야 합니다.
준수하는 사용자 에이전트는 또한 이 명세서의 IDL 단편을 준수하는 구현이어야 하며, 이는 "Web IDL" 명세에 설명되어 있습니다. [WebIDL]
2.1.1. DOMString 유형으로서의 열거형 호환성
열거형 타입은 Web IDL의 다른 부분에서 참조되지 않는데, 이는 명세서와 구현을 업데이트하지 않고 다른 값을 사용하는 것을 금지하게 되기 때문입니다. 이전 호환성을 위해 클라이언트 플랫폼과 의존 당사자는 알려지지 않은 값을 처리해야 합니다.
이 명세서의 열거형은 문서화 및 레지스트리 용도로 존재합니다. 열거형이 다른 곳에 표현될 때는 DOMString으로
타입이 지정됩니다. 예를 들어 transports와
같이.
2.2. 인증기
WebAuthn 인증기는 § 6 WebAuthn 인증기 모델에 정의된 작업을 제공해야 하며, 그 동작은 해당 섹션에 설명된 대로 동작해야 합니다. 이는 인증기가 준수하는 사용자 에이전트에 의해 사용 가능하도록 하기 위한 기능적 및 보안 요건의 집합입니다.
§ 1.2 사용 사례에 설명된 바와 같이, 인증기는 사용자 에이전트의 기반이 되는 운영체제에 구현될 수도 있고, 외부 하드웨어에 또는 둘의 조합으로 구현될 수도 있습니다.
2.2.1. FIDO U2F와의 하위 호환성
인증기가 오직 § 8.6 FIDO U2F 증명 문장 형식만을 지원하는 경우, 사용자 핸들(user handle)을 저장할 메커니즘이 없으므로 반환되는 userHandle은
항상 null이 됩니다.
2.3. WebAuthn 의존 당사자
WebAuthn 의존 당사자는 이 명세서가 제공하는 모든 보안 혜택을 얻기 위해 § 7 WebAuthn 의존 당사자 작업에 설명된 대로 동작해야 합니다. 자세한 논의는 § 13.4.1 WebAuthn 의존 당사자를 위한 보안 혜택을 참조하세요.
2.4. 모든 준수 클래스
위의 준수 클래스 구성원들이 수행하는 모든 CBOR 인코딩은 CBOR 표준에 따라 CTAP2 표준의 정형화된(Canonical) CBOR 인코딩 형식을 사용하여 수행되어야 합니다. 위 준수 클래스의 모든 디코더는 CTAP2 정형화 CBOR 인코딩 형식으로 유효하게 인코딩되지 않은 CBOR을 거부해야 하며, 중복 맵 키가 있는 메시지도 거부하는 것이 권장됩니다.
3. 종속성
이 명세서는 아래 및 참조로 정의된 용어에 나열된 여러 다른 기본 명세들에 의존합니다.
- Base64url encoding
-
용어 Base64url Encoding은 [RFC4648]의 섹션 5에 정의된 URL 및 파일명 안전 문자 집합을 사용하는 base64 인코딩을 가리키며, 모든 꼬리의 '=' 문자는(섹션 3.2에서 허용된 대로) 생략되고 줄바꿈, 공백 또는 기타 추가 문자가 포함되지 않은 것을 의미합니다.
- CBOR
-
이 명세서의 여러 구조(증명 문장 및 확장 등)는 Compact Binary Object Representation(CBOR)의 CTAP2 정형화(Canonical) CBOR 인코딩 형식으로 인코딩됩니다. CBOR 자체는 [RFC8949] 및 [FIDO-CTAP]에 정의되어 있습니다.
- CDDL
-
이 명세서는 모든 CBOR 인코딩 데이터를 기술하기 위해 CBOR Data Definition Language(CDDL)를 사용하며, 이는 [RFC8610]에 정의되어 있습니다.
- COSE
-
CBOR Object Signing and Encryption(COSE) 관련 규격으로는 [RFC9052] 및 [RFC9053]가 있습니다. 또한 IANA COSE Algorithms 레지스트리([IANA-COSE-ALGS-REG])는 원래 [RFC8152]에 의해 설립되었고 이들 규격들에 의해 갱신되어 사용됩니다.
- Credential Management
-
이 문서에 설명된 API는
Credential개념을 정의한 [CREDENTIAL-MANAGEMENT-1]의 확장입니다. - DOM
-
DOMException및 이 명세서에서 사용하는 DOMException 값들은 [DOM4]에 정의되어 있습니다. - ECMAScript
-
%ArrayBuffer%는 [ECMAScript]에 정의되어 있습니다.
- URL
-
domain, host, port, scheme, valid domain 및 valid domain string과 같은 개념들은 [URL]에 정의되어 있습니다.
- Web IDL
-
이 명세서의 많은 인터페이스 정의와 모든 IDL은 [WebIDL]에 의존합니다. 이 업데이트된 Web IDL 표준은 이제 비동기 상호작용을 위한 우선 메커니즘인
Promise에 대한 지원을 추가합니다. - FIDO AppID
-
호출 애플리케이션의 FacetID 결정 및 호출자의 FacetID가 AppID에 대해 권한이 있는지 결정하는 알고리즘(앱ID 확장에서만 사용)은 [FIDO-APPID]에 정의되어 있습니다.
문서 내에서 대문자로만 나타나는 경우(여기와 같이) "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY" 및 "OPTIONAL"과 같은 핵심 단어들은 BCP 14의 규정에 따라 해석됩니다. 자세한 내용은 [RFC2119] 및 [RFC8174]를 참조하세요.
4. 용어
- 증명(Attestation)
-
일반적으로 attestation(증명)은 증언하거나 확인하거나 인증함을 의미합니다. WebAuthn 맥락에서 증명은 인증기와 그것이 생성하는 데이터의 출처에 대한 검증 가능한 증거를 제공하는 데 사용됩니다. 여기에는 자격 증명 ID, 자격 증명 키 쌍, 서명 카운터 등과 같은 항목이 포함됩니다.
증명 문장(attestation statement)은 증명 객체 내에서 등록 절차 동안 제공됩니다. 또한 § 6.5 증명 및 그림 6도 참고하세요. 클라이언트가 증명 문장과 aaguid 부분을 의존 당사자에게 어떻게 전달하는지는 증명 전달 방식에서 설명합니다.
- 증명 인증서(Attestation Certificate)
-
증명 키 쌍에 대한 X.509 인증서로, 인증기가 제조 및 기능을 증명하기 위해 사용합니다. 등록 시점에 인증기는 증명 비밀 키로 생성하여 반환하는 의존 당사자 특정 자격 증명 공개 키(및 추가 데이터)에 서명합니다. 의존 당사자는 증명 인증서에 담긴 증명 공개 키을 사용하여 증명 서명을 검증합니다. 자체 증명(self attestation)의 경우에는 인증기가 별도의 증명 키 쌍이나 증명 인증서를 가지지 않는 점을 참조하세요(self attestation 참조).
- 인증(Authentication)
- 인증 절차(Authentication Ceremony)
-
사용자와 그 사용자의 클라이언트 플랫폼(하나 이상의 인증기를 포함하거나 연결함)이 협력하여 의존 당사자에게 사용자가 이전에 등록한 자격 증명 개인 키를 제어하고 있음을 암호학적으로 증명하는 절차를 말합니다(등록 참조). 여기에는 사용자 존재 확인 또는 사용자 검증이 포함됩니다.
WebAuthn 인증 절차는 § 7.2 인증 어설션 검증에 정의되어 있으며, 의존 당사자가
을navigator.credentials.get()publicKey인수와 함께 호출하여 시작됩니다. 도입부는 § 5 Web Authentication API를 참조하고, 구현 예시는 § 1.3.3 인증을 참조하세요. - 인증
어설션(Authentication Assertion)
- 어설션(Assertion)
-
AuthenticatorAssertionResponse객체는 인증기가 authenticatorGetAssertion 작업의 결과로 반환하는 암호학적으로 서명된 응답입니다.이는 [CREDENTIAL-MANAGEMENT-1] 명세서의 일회용 credentials와 대응됩니다.
- 인증기(Authenticator)
- WebAuthn 인증기
-
하드웨어 또는 소프트웨어로 존재하는 암호학적 엔터티로서, 특정 의존 당사자에 대해 사용자를 등록하고 이후에 등록된 공개 키 자격 증명의 소유를 증명할 수 있으며, 선택적으로 사용자를 검증하여 의존 당사자에게 전달할 수 있습니다. 인증기는 등록 시 및 어설션 시 증명을 통해 자신의 유형 및 보안 특성에 관한 정보를 보고할 수 있습니다.
WebAuthn Authenticator는 로밍 인증기, 클라이언트 장치에 통합된 전용 하드웨어 서브시스템, 또는 클라이언트나 클라이언트 장치의 소프트웨어 구성요소일 수 있습니다. WebAuthn 인증기는 지역적 맥락에서만 동작하도록 제한되지 않으며, 클라이언트 측 하드웨어 외부의 서버에 자격 증명 키 쌍을 생성하거나 저장할 수 있습니다.
일반적으로 인증기는 하나의 사용자만 갖는 것으로 가정됩니다. 여러 자연인이 하나의 인증기에 대한 접근을 공유하는 경우, 해당 자연인들은 그 인증기의 맥락에서는 동일한 사용자로 간주됩니다. 만약 인증기 구현이 분리된 구획에서 다수의 사용자를 지원하면, 각 구획은 다른 사용자의 자격 증명에 접근할 수 없는 단일 사용자로서 별개의 인증기로 간주됩니다.
- 권한 제스처(Authorization Gesture)
-
권한 제스처는 절차의 일부로 사용자가 인증기와 수행하는 물리적 상호작용을 의미하며, 예를 들어 등록 또는 인증과 같은 절차에서 사용됩니다. 이러한 권한 제스처를 수행함으로써 사용자는 사용자 동의를 제공합니다(즉, 절차의 진행을 허가합니다). 이는 인증기가 가능하면 사용자 검증을 포함할 수 있으며, 또는 단순한 사용자 존재 테스트일 수 있습니다.
- 백업됨(Backed Up)
-
공개 키 자격 증명 소스는 생성 인증기 이외의 인증기에서 나타날 수 있도록 어떤 방식으로든 백업될 수 있습니다. 백업은 피어 투 피어 동기화, 클라우드 동기화, 로컬 네트워크 동기화, 수동 내보내기/가져오기 등 여러 메커니즘을 통해 발생할 수 있습니다. 자세한 내용은 § 6.1.3 자격 증명 백업 상태를 참조하세요.
- 백업 허용성(Backup
Eligibility)
- 백업 가능(Backup Eligible)
-
Public Key Credential Source의 생성 시점에 생성 인증기가 해당 공개 키 자격 증명 소스가 백업될 수 있는지 여부를 결정합니다. 백업 허용성은 인증기 데이터의 플래그와 현재 백업 상태에 의해 신호됩니다. 백업 허용성은 자격 증명 속성이며 주어진 공개 키 자격 증명 소스에 대해 영구적입니다. 백업 가능인 공개 키 자격 증명 소스는 다중 장치 자격 증명(multi-device credential)이라 부르며, 백업 불가능한 것은 단일 장치 자격 증명(single-device credential)이라 부릅니다. 자세한 내용은 § 6.1.3 자격 증명 백업 상태를 참조하세요.
- 백업 상태(Backup State)
-
현재 다중 장치 자격 증명의 백업 상태는 현재 관리 인증기(managing authenticator)에 의해 결정됩니다. 백업 상태는 인증기 데이터의 플래그로 신호되며 시간이 지나면서 변경될 수 있습니다. 또한 백업 허용성 및 § 6.1.3 자격 증명 백업 상태를 참조하세요.
- 생체 인증기(Biometric Authenticator)
-
생체 인식(biometric recognition)을 구현하는 모든 인증기를 말합니다.
- 생체 인식(Biometric Recognition)
-
개인의 생물학적·행동적 특징을 기반으로 한 자동 인식입니다([ISOBiometricVocabulary]).
- 바인딩된 자격
증명(Bound credential)
- "Authenticator contains a credential"
- "Credential created on an authenticator"
- "Authenticator contains a credential"
-
공개 키 자격 증명 소스 또는 공개 키 자격 증명은 그 관리 인증기에 바인딩(bound)되어 있다고 합니다. 이는 오직 그 관리 인증기만이 그에 바인딩된 어설션을 생성할 수 있음을 의미합니다.
이를 "관리 인증기(managing authenticator이 contains 바인딩된 자격 증명을 포함한다)" 또는 "바인딩된 자격 증명이 그 관리 인증기에서 생성되었다(created on)"고 표현할 수 있습니다. 다만 서버 측 자격 증명은 인증기 내부의 영구 메모리에 물리적으로 저장되지 않을 수 있으므로, "바인딩된(bound to)"이 기본 용어입니다. 자세한 내용은 § 6.2.2 자격 증명 저장 방식을 참조하세요.
- 절차(Ceremony)
-
절차 개념은 인간 노드와 컴퓨터 노드가 함께 작동하고 사용자 인터페이스, 사람 간 통신, 데이터가 포함된 물리적 객체의 전달을 포함하는 통신 링크를 갖는 네트워크 프로토콜 개념의 확장입니다. 프로토콜에서는 아웃-오브-밴드인 것이 절차에서는 인-밴드일 수 있습니다. 이 명세서에서 등록 및 인증은 절차이며, 권한 제스처는 종종 이러한 절차의 구성 요소입니다.
- 클라이언트(Client)
- WebAuthn 클라이언트
-
여기서는 단순히 클라이언트라고도 합니다. 또한 준수하는 사용자 에이전트도 참조하세요. WebAuthn Client는 일반적으로 사용자 에이전트에 구현된 중개자 역할을 하며, 개념적으로는 Web Authentication API를 하부에서 구현하고
[[Create]](origin, options, sameOriginWithAncestors)및[[DiscoverFromExternalSource]](origin, options, sameOriginWithAncestors)같은 내부 메서드를 구현합니다. 이는 하부의 인증기 연산에 대한 입력을 마샬링하고, 그 결과를 Web Authentication API의 호출자에게 반환하는 역할을 합니다.WebAuthn Client는 WebAuthn Client Device 상에서 실행되며, 이는 서로 구분됩니다.
- 클라이언트 장치(Client
Device)
- WebAuthn 클라이언트 장치
-
WebAuthn Client가 실행되는 하드웨어 장치, 예를 들어 스마트폰, 노트북 또는 데스크톱 컴퓨터와 그 하드웨어에서 실행되는 운영체제를 의미합니다.
WebAuthn Client device와 클라이언트의 구분은 다음과 같습니다:
- 클라이언트 플랫폼(Client Platform)
-
클라이언트 장치와 클라이언트가 함께 클라이언트 플랫폼을 이룹니다. 단일 하드웨어 장치는 서로 다른 운영체제 및/또는 클라이언트를 실행하여 서로 다른 시점에 여러 개의 별개의 클라이언트 플랫폼의 일부가 될 수 있습니다.
- 클라이언트 측(Client-Side)
-
일반적으로 이는 사용자의 클라이언트 플랫폼, 인증기 및 이를 모두 연결하는 모든 요소들의 결합을 의미합니다.
- 클라이언트 측 검색 가능한 공개 키 자격 증명 소스
- 클라이언트 측 검색 가능한 자격 증명
- 검색 가능한 자격 증명(Discoverable Credential)
- 패스키(Passkey)
- [DEPRECATED] 거주 자격 증명(Resident Credential)
- [DEPRECATED] 거주 키(Resident Key)
- 클라이언트 측 검색 가능한 자격 증명
-
참고: 역사적으로, 클라이언트 측 검색 가능한 크리덴셜은 거주(레지던트) 크리덴셜 또는 거주(레지던트) 키로도 알려져 있습니다.
ResidentKey와residentKey라는 용어는 WebAuthn API와 Authenticator Model 모두에서 (예: 딕셔너리 멤버 이름, 알고리즘 변수명, 연산 파라미터 등) 널리 사용되고 있으므로, 이름에resident라는 단어 사용은 하위 호환성을 위해 변경되지 않았습니다. 또한 이곳에서 거주 키(resident key)는 클라이언트 측 검색 가능한 크리덴셜과 동의어로 정의됩니다.클라이언트 측 검색 가능한 공개키 크리덴셜 소스(영어 약칭: 검색 가능한 크리덴셜(Discoverable Credential))는, 검색 가능하며, 인증 절차에서 Relying Party가 어떠한 credential ID도 제공하지 않을 때 사용할 수 있는 public key credential source입니다. 즉, Relying Party가
navigator.credentials.get()호출 시 비어 있는allowCredentials인자를 주는 경우를 뜻합니다. 즉, Relying Party가 반드시 사용자를 먼저 식별할 필요가 없음을 의미합니다.결과적으로, 검색 가능한 크리덴셜 지원 authenticator는 단지 RP ID만 주어져도 검색 가능한 크리덴셜에 대해 assertion signature를 생성할 수 있습니다. 이는 public key credential source가 authenticator 또는 클라이언트 플랫폼에 저장되어 있어야 함을 뜻합니다. 이는 서버 측 공개키 크리덴셜 소스(Server-side Public Key Credential Source)와 대조적이며, 후자는 authenticator에게 RP ID와 credential ID가 모두 제공되어야 하지만 클라이언트 측에 public key credential source를 저장할 필요는 없습니다.
참조: 클라이언트 측 크리덴셜 저장 방식 및 비검색형(non-discoverable) 크리덴셜도 참고하십시오.
참고: 클라이언트 측 검색 가능한 크리덴셜은 인증 절차에서 credential ID가 제공되는 경우(즉,
navigator.credentials.get()호출 시 비어 있지 않은allowCredentials인자와 함께 호출할 때)에도 사용할 수 있습니다. - 준수하는 사용자 에이전트(Conforming User Agent)
-
하부의 클라이언트 장치와 협력하여 Web Authentication API 및 본 명세서에 주어진 알고리즘을 구현하고, 인증기와 의존 당사자 간 통신을 처리하는 사용자 에이전트를 말합니다.
- 자격 증명 ID(Credential ID)
-
확률적으로 고유한 바이트 시퀀스로서 공개 키 자격 증명 소스와 그에 따른 인증 어설션을 식별합니다. 길이는 최대 1023 바이트입니다.
자격 증명 ID는 인증기에 의해 두 가지 형태로 생성됩니다:
-
적어도 16바이트이며 최소 100비트의 엔트로피를 포함하는 경우, 또는
-
공개 키 자격 증명 소스 자체를, 그 안의 Credential ID나 mutable items를 제외한 채로 암호화하여 오직 해당 관리 인증기만 복호화할 수 있게 하는 형태. 이 형태는 인증기를 거의 상태 비저장(state-light)으로 만들 수 있으며, 필요한 상태는 의존 당사자가 저장합니다.
참고: [FIDO-UAF-AUTHNR-CMDS]는 "Security Guidelines"에서 암호화 기법에 대한 지침을 포함합니다.
-
- 자격 증명 키
쌍(Credential Key Pair)
- 자격 증명 개인 키(Credential Private Key)
- 자격 증명 공개 키(Credential Public Key)
- 사용자 공개 키(User Public Key)
- 자격 증명 개인 키(Credential Private Key)
-
자격 증명 키 쌍은 인증기에 의해 생성되며 특정 WebAuthn 의존 당사자에게 범위 지정됩니다. 이는 공개 키 자격 증명의 핵심 요소입니다.
자격 증명 공개 키는 자격 증명 키 쌍의 공개 키 부분입니다. 이 자격 증명 공개 키는 등록 절차 중에 의존 당사자에게 반환됩니다.
자격 증명 개인 키는 자격 증명 키 쌍의 개인 키 부분입니다. 자격 증명 개인 키는 특정 인증기 - 즉 그 관리 인증기에 바인딩되며, 소유자나 인증기 자체에도 노출되어서는 안 됩니다.
자체 증명(self attestation)의 경우에는 자격 증명 키 쌍이 증명 키 쌍으로도 사용된다는 점을 참조하세요(self attestation 참조).
참고: 자격 증명 공개 키는 FIDO UAF의 [UAFProtocol] 및 FIDO U2F의 [FIDO-U2F-Message-Formats]에서 'user public key'로 언급되며, 이 명세서의 일부 관련 부분에서도 동일하게 사용됩니다.
- 자격 증명 속성(Credential Properties)
-
자격 증명 속성은 해당 공개 키 자격 증명 소스의 특징적인 속성으로, 예를 들어 그것이 클라이언트 측 검색 가능한 자격 증명인지 또는 서버 측 자격 증명인지 등을 포함합니다.
- 자격 증명 레코드(Credential Record)
-
§ 7 WebAuthn 의존 당사자 작업에 정의된 알고리즘을 구현하기 위해, 의존 당사자는 등록된 공개 키 자격 증명 소스의 일부 속성을 저장해야 합니다. 자격 증명 레코드 struct는 이러한 속성들의 추상화입니다. 자격 증명 레코드는 등록 절차 동안 생성되며 이후의 인증 절차에서 사용됩니다. 의존 당사자는 필요하거나 사용자가 요청할 때 자격 증명 레코드를 삭제할 수 있습니다.
다음의 항목들은 § 7.1 새 자격 증명 등록 및 § 7.2 인증 어설션 검증의 모든 단계를 구현하기 위해 권장됩니다:
- type
-
해당 공개 키 자격 증명 소스의 type.
- id
- publicKey
-
해당 공개 키 자격 증명 소스의 자격 증명 공개 키.
- signCount
-
해당 공개 키 자격 증명 소스를 사용한 어떤 절차에서든지 반환된 인증기 데이터의 최신 서명 카운터 값입니다.
- transports
-
getTransports()호출 시 해당 공개 키 자격 증명 소스가 등록될 때 반환한 값입니다.참고:
getTransports()이 반환한 값에서 항목을 수정하거나 제거하면 사용자 경험에 부정적 영향을 주거나 해당 자격 증명의 사용을 방해할 수 있습니다. - uvInitialized
-
해당 credential 중 이 공개 키 자격 증명 소스에 대해 UV 플래그가 설정된 적이 있는지를 나타내는 불리언 값입니다.
이 값이
true이면 의존 당사자는 해당 UV 플래그를 인증 절차에서 인증 요소(authentication factor)로 간주할 수 있습니다. 예를 들어 의존 당사자는 uvInitialized가true이고 UV 플래그가 설정되어 있으면 비록 사용자 검증이 요구되지 않았더라도 비밀번호 프롬프트를 건너뛸 수 있습니다.이 값이
false인 경우(이를true로 업데이트할 수 있는 인증 절차를 포함하여), UV 플래그는 authentication factor로 신뢰되어서는 안 됩니다. 이는 공개 키 자격 증명 소스가 처음으로 UV 플래그를 1로 설정했을 때, 아직 의존 당사자와 해당 인증기의 사용자 검증 사이에 신뢰 관계가 확립되지 않았기 때문입니다. 따라서 uvInitialized를false에서true로 업데이트할 때는 WebAuthn의 사용자 검증에 상응하는 추가적인 authentication factor에 의한 승인이 필요할 것을 권장합니다. - backupEligible
-
BE 플래그의 값으로, 해당 공개 키 자격 증명 소스가 생성될 때의 값을 나타냅니다.
- backupState
-
해당 공개 키 자격 증명 소스를 사용하는 어떤 절차에서든지 반환된 인증기 데이터의 BS 플래그의 최신 값을 나타냅니다.
다음의 항목들은 선택사항(OPTIONAL)입니다:
- attestationObject
-
해당 공개 키 자격 증명 소스가 등록될 때의
attestationObject속성 값입니다. 이를 저장하면 의존 당사자가 이후에 자격 증명의 증명 문장을 참조할 수 있게 됩니다. - attestationClientDataJSON
-
해당 공개 키 자격 증명 소스가 등록될 때의
clientDataJSON속성 값입니다. 이를 위의 attestationObject 항목과 함께 저장하면 의존 당사자가 나중에 증명 서명을 재검증할 수 있게 됩니다.
WebAuthn 확장은 확장을 처리하는 데 필요한 추가 항목들을 정의할 수 있습니다. 의존 당사자는 필요에 따라 추가적인 항목을 포함하거나 구현에 필요하지 않은 항목을 생략할 수 있습니다.
자격 증명 레코드에 대한 자격 증명 기술자(credential descriptor)는 다음 내용을 가진
PublicKeyCredentialDescriptor값입니다:type-
해당 type of the credential record.
id-
해당 id of the credential record.
transports-
해당 transports of the credential record.
- 생성 인증기(Generating Authenticator)
-
생성 인증기(Generating Authenticator)는 특정 공개 키 자격 증명 소스의 생성을 초래하는 authenticatorMakeCredential 작업에 관여한 인증기입니다. 생성 인증기는 단일 장치 자격 증명의 경우 해당 자격 증명의 관리 인증기와 동일합니다. 다중 장치 자격 증명의 경우에는 생성 인증기가 현재 특정 인증 작업에 참여하는 관리 인증기와 같을 수도 있고 다를 수도 있습니다.
- 사람이 이해하기 쉬운 식별자(Human Palatability)
-
사람이 기억하고 재현하기 쉬운 식별자는 일반적으로 무작위로 생성된 비트 시퀀스와 달리 일반 사용자들이 기억하고 재현할 수 있도록 의도된 식별자입니다([EduPersonObjectClassSpec] 참조).
- 비검색 가능 자격 증명(Non-Discoverable Credential)
-
이것은 credential로서, 자격 증명 ID를 제공하여
allowCredentials인수를 지정하고navigator.credentials.get()을 호출해야 하는 자격 증명입니다. 이는 서버 측 자격 증명과 관련이 있습니다. - 등록 가능한 오리진 레이블(Registrable Origin Label)
-
도메인의 도메인 레이블 중 첫 번째 레이블로서, 호스트의 등록 가능한 도메인의 첫 번째 레이블입니다. 등록 가능한 도메인이 null이면 null을 반환합니다. 예를 들어
example.co.uk와www.example.de의 등록 가능한 오리진 레이블은 각각example입니다(단,co.uk와de가 퍼블릭 서픽스일 때). - 공개 키 자격 증명(Public Key Credential)
-
일반적으로 크리덴셜(credential)은 한 엔티티가 다른 엔티티에게 본인을 인증하기 위해 제시하는 데이터입니다 [RFC4949]. 공개키 크리덴셜(public key credential)이라는 용어는 다음 중 하나를 의미합니다: 공개키 크리덴셜 소스, attestation이 추가될 수도 있는 크리덴셜 공개키(credential public key)(이는 공개키 크리덴셜 소스와 대응됨), 또는 인증 어서션(authentication assertion). 어떤 의미인지는 일반적으로 문맥에 따라 결정됩니다.
참고: 이는 [RFC4949]의 정의에 대한 의도적 위반입니다. 영어에서 "credential"은 a) 어떤 진술을 증명하기 위해 제시되는 것과 b) 여러 번 사용될 목적으로 만들어진 것을 동시에 의미할 수 있습니다. 공개 키 시스템에서 단일 데이터가 두 가지 요건을 안전하게 만족시키는 것은 불가능합니다. [RFC4949]은 credential을 여러 번 사용될 수 있는 것(공개 키)으로 정의하지만, 이 명세서는 영어 용어의 유연성을 허용합니다. 이 명세서는 관련 데이터를 더 구체적인 용어로 구분합니다:- "Authentication information" (possibly including a private key)
- "Signed value"
- [RFC4949] "credential"
등록 시점에 인증기는 비대칭 키 쌍을 생성하고 해당 의존 당사자로부터의 정보를 공개 키 자격 증명 소스에 저장합니다. 공개 키 부분은 의존 당사자에게 반환되며, 의존 당사자는 이를 활성 사용자 계정에 저장합니다. 이후 해당 의존 당사자는 그 등록된 자격 증명 공개 키를 사용하여 결과적인 인증 어설션을 검증합니다. 이 공개 키 자격 증명은 등록된 RP ID로 식별된 동일한 엔터티에서만 인증에 사용될 수 있습니다.
- 공개 키 자격 증명 소스(Public Key Credential Source)
-
credential source ([CREDENTIAL-MANAGEMENT-1])로서, 인증기가 인증 어설션을 생성하는 데 사용하는 것입니다. 공개 키 자격 증명 소스는 다음과 같은 struct의 항목들으로 구성됩니다:
- type
-
값은
PublicKeyCredentialType이며, 기본값은public-key입니다. - id
- privateKey
-
자격 증명 개인 키입니다.
- rpId
-
이 공개 키 자격 증명 소스가 범위가 지정된 신뢰 당사자 식별자(Relying Party Identifier)입니다. 이는
파라미터와rp.idcreate()동작에 의해 결정됩니다. - userHandle
-
이 공개 키 자격 증명 소스가 생성될 때 연결된 사용자 핸들입니다. 이 항목(item)은 null일 수도 있지만, 검색 가능한 자격 증명(discoverable credentials)의 경우 user handle이 항상 채워져 있어야 합니다.
- otherUI
-
인증자(authenticator)가 UI에 정보를 제공할 때 사용하는 선택적 추가 정보입니다. 예를 들어 사용자의
displayName이 포함될 수 있습니다. otherUI는 mutable item이며, 공개 키 자격 증명 소스에 업데이트 가능성을 저해하지 않도록 묶여서는 안 됩니다.
authenticatorMakeCredential 작업은 공개 키 자격 증명 소스를 특정 관리 인증자(managing authenticator)에 바인딩하여 생성하고, 그 자격 증명 공개키를 반환합니다. 이 공개키는 자격 증명 개인키와 연관되어 있습니다. 신뢰 당사자는 이 자격 증명 공개키를 사용하여 이 공개 키 자격 증명 소스가 만든 인증 어설션을 검증할 수 있습니다.
- 속도 제한(Rate Limiting)
-
속도 제한(일명 스로틀링)은 인증자가 연속된 인증 실패 시도 횟수를 제한함으로써 무차별 대입(brute force) 공격을 방지하기 위해 제어를 구현하는 역할입니다. 제한에 도달하면 인증자는 각 시도가 반복될수록 지연 시간을 기하급수적으로 증가시키거나, 현재 인증 방식을 비활성화하고 사용 가능한 경우 다른 인증 요소(authentication factor)를 표시해야 합니다. 속도 제한은 사용자 검증(user verification)의 일부로 자주 구현됩니다.
- 등록(Registration)
- 등록 절차(Registration Ceremony)
-
절차(ceremony)로, 사용자와 신뢰 당사자, 사용자 클라이언트 플랫폼(하나 이상의 인증자를 포함/연결)이 협력하여 공개 키 자격 증명을 생성하여 사용자 계정에 연결합니다. 이것은 사용자 존재 테스트(test of user presence)나 사용자 검증(user verification)을 반드시 포함합니다. 등록 절차(registration ceremony)가 성공하면 사용자는 인증 절차(authentication ceremony)를 통해 인증할 수 있습니다.
WebAuthn 등록 절차는 § 7.1 새 자격 증명 등록에 정의되어 있으며, 신뢰 당사자가
를navigator.credentials.create()publicKey인자로 호출함으로써 시작됩니다. § 5 Web Authentication API에서 개요, § 1.3.1 등록에서 구현 예시를 참고하세요. - 신뢰 당사자(Relying
Party)
- WebAuthn 신뢰 당사자(WebAuthn Relying Party)
-
웹 애플리케이션의 주체로, Web Authentication API를 이용해 사용자를 등록 및 인증합니다.
신뢰 당사자 구현은 보통 Web Authentication API를 호출하는 클라이언트 측 스크립트와 클라이언트 및 신뢰 당사자 서버 동작 및 기타 애플리케이션 로직을 실행하는 서버 측 구성요소로 이루어집니다. 두 구성요소 간의 통신은 반드시 HTTPS 또는 이에 준하는 전송 보안으로 이루어져야 하며, 그 이외 사항은 본 명세의 범위를 벗어납니다.
참고: 신뢰 당사자 용어는 X.509나 OAuth 등 다른 맥락에서도 자주 쓰입니다. 하지만 한 맥락에서 신뢰 당사자로 동작한다고 해서 다른 맥락에서도 반드시 신뢰 당사자인 것은 아닙니다. 본 명세에서 WebAuthn 신뢰 당사자는 약칭으로 단순히 신뢰 당사자라고도 하며, WebAuthn 맥락의 신뢰 당사자를 명시적으로 지칭합니다. 실제로 WebAuthn 환경은 더 광범위한 맥락(예: OAuth 기반) 안에 내장될 수 있습니다.
- 신뢰 당사자
식별자(Relying Party Identifier)
- RP ID
-
WebAuthn API 맥락에서, 신뢰 당사자 식별자는 유효 도메인 문자열로, 특정 등록 또는 인증 절차가 실행되는 WebAuthn 신뢰 당사자를 식별합니다. 공개 키 자격 증명은 최초 등록시의 같은 주체(RP ID로 구분)에 대해서만 인증에 사용할 수 있습니다.
기본적으로, WebAuthn 동작의 RP ID는 호출자의 origin의 유효 도메인으로 설정됩니다. 이 기본값은 호출자가 제공하는 RP ID 값이 호출자의 origin의 유효 도메인의 등록 가능한 도메인 접미사이거나 동일한 경우에 한해 대체할 수 있습니다. 자세한 내용은 § 5.1.3 새 자격 증명 생성 - PublicKeyCredential의 [[Create]](origin, options, sameOriginWithAncestors) 내부 메서드 및 § 5.1.4 기존 자격 증명을 사용한 어설션 생성을 참고하세요.
RP ID는 호스트의 도메인 이름을 기반으로 합니다. (origin과 달리) 자체적으로 스킴이나 포트를 포함하지 않습니다. 공개 키 자격 증명의 RP ID는 해당 자격 증명의 범위(scope)를 결정합니다. 다시 말해, 해당 공개 키 자격 증명을 사용할 수 있는 origin의 집합을 결정합니다:
-
RP ID는 반드시 origin의 유효 도메인과 같거나, 등록 가능한 도메인 접미사여야 합니다.
-
다음 중 하나가 참이어야 합니다:
예를 들어, origin이
https://login.example.com:1337인 신뢰 당사자의 경우, RP ID로login.example.com(기본),example.com은 가능하지만,m.login.example.com,com은 허용되지 않습니다. 또 다른 예시로http://localhost:8000도 origin이localhost이므로 유효합니다.이는 쿠키 등 널리 배포된 환경 자격 증명(ambient credentials, 예: [RFC6265])의 동작과 맞추기 위함입니다. 여기서의 처리 범위는 document.domain의 setter가 제공하는 "동일 출처"보다 완화되어 있음을 유의하세요.
이러한 origin 값 제한은 WebAuthn 클라이언트에 적용됩니다.
다른 규격에서 WebAuthn 공개 키 자격 증명을 네이티브 모바일 앱 등 Web 플랫폼 이외 환경에서 사용하도록 WebAuthn API와 유사하게 구현하는 경우에는, 호출자를 신뢰 당사자 식별자에 바인딩하는 규칙을 다르게 정의할 수 있습니다. 다만, RP ID 문법은 반드시 유효 도메인 문자열이나 URI([RFC3986] [URL]) 규격을 따라야 합니다.
-
- 서버 측 공개 키 자격 증명 소스(Server-side Public Key Credential
Source)
- 서버 측 자격 증명(Server-side Credential)
- [DEPRECATED] 비상주 자격 증명(Non-Resident Credential)
- 서버 측 자격 증명(Server-side Credential)
-
참고: 서버 측 자격 증명은 과거에는 비상주 자격 증명(non-resident credential)으로 알려졌습니다. 하위 호환성을 위해 WebAuthn API 및 Authenticator Model 구성요소 중 resident 관련 이름은 변경되지 않았습니다.
서버 측 공개 키 자격 증명 소스 또는 약칭으로 서버 측 자격 증명은 공개 키 자격 증명 소스 중에서 오직 신뢰 당사자가
navigator.credentials.get()의allowCredentials인자로 그 자격 증명 ID를 제공할 때에만 인증 절차에서 사용할 수 있습니다. 즉, 신뢰 당사자가 자격 증명의 저장 및 식별 관리를 책임져야 하며, 사용자를 미리 식별해서 자격 증명 ID 목록을 제공할 수 있어야 합니다.클라이언트 측에서 공개 키 자격 증명 소스를 저장하는 것은 서버 측 자격 증명에는 필요하지 않습니다. 반면, 클라이언트 측 검색 가능한 자격 증명(client-side discoverable credential)은 사용자를 미리 식별하지 않고도 자격 증명 ID를
navigator.credentials.get()인자에 제공할 수 있습니다.참고: 서버 측 자격 증명 저장 방식(server-side credential storage modality) 및 비검색 자격 증명(non-discoverable credential)도 참고하세요.
- 사용자 존재 테스트(Test of User Presence)
-
사용자 존재 테스트는 권한 부여 제스처(authorization gesture)의 한 형태이자, 사용자가 인증자와 단순히 접촉(다른 방식도 있음)하는 기술적 절차로, Boolean(참/거짓) 결과를 제공합니다. 이 테스트는 사용자 검증(user verification)에는 해당하지 않습니다. 사용자 존재 테스트는 본질적으로 생체 인식이 불가능하며, 공유 비밀번호나 PIN 등 비밀 입력도 포함하지 않습니다.
- 사용자 계정(User Account)
-
본 명세의 맥락에서 사용자 계정은 일련의 자격 증명 ([CREDENTIAL-MANAGEMENT-1])을 신뢰 당사자 소유의 일부 리소스에 매핑한 것으로, 신뢰 당사자에 의해 관리 및 허가됩니다. 신뢰 당사자는 공개 키 자격 증명에 대해 사용자 핸들을 할당하고, 자격 증명 기록(credential record)을 사용자 계정에 저장함으로써 자격 증명을 사용자 계정과 연결합니다. 이 매핑, 자격 증명 집합, 권한 정보는 시간이 지남에 따라 변할 수 있습니다. 사용자 계정 하나가 여러 자연인(게 사용자)에 의해 접근될 수도 있고, 한 자연인이 여러 사용자 계정에 접근할 수도 있습니다. 이는 사용자/신뢰 당사자 동작에 따라 달라질 수 있습니다.
- 사용자 동의(User Consent)
-
사용자 동의란 사용자가 요청받는 내용에 동의하는 것(예: 안내문을 읽고 이해함)을 의미합니다. 권한 부여 제스처는 절차(ceremony)의 한 부분으로, 사용자 동의(user consent)를 표시하는 데 자주 사용됩니다.
- 사용자 핸들(User Handle)
-
사용자 핸들은 사용자 계정의 식별자로, 신뢰 당사자가
에 지정합니다(등록 때). 검색 가능한 자격 증명(discoverable credentials)은 이 식별자를 저장하고, 인증 절차(authentication ceremonies)에서,user.id에 반드시 반환해야 합니다. (단, 빈response.userHandle인자로 시작한 경우)allowCredentials사용자 핸들의 주요 역할은 이러한 인증 절차에서 사용자 계정을 식별하는 것입니다. 자격 증명 ID도 사용할 수 있지만, 자격 증명 ID는 인증자가 정해 각 자격 증명마다 독립적이고, user handle은 신뢰 당사자가 지정해 같은 자격 증명 집합 모두에 동일하게 할당해야 한다는 점이 다릅니다.
인증자는 RP ID와 사용자 핸들의 쌍을 공개 키 자격 증명 소스에 매핑합니다. 이로 인해 인증자는 하나의 user handle 및 신뢰 당사자별로 최다 하나의 검색 가능한 자격 증명만 저장합니다. 따라서 사용자 핸들은 인증자가 등록 절차(registration ceremony) 중 기존 검색 가능한 자격 증명을 새 것으로 교체해야 하는지 판단하는 데에도 사용됩니다.
사용자 핸들은 최대 64바이트 길이의 불투명한 바이트 시퀀스로, 사용자에게 표시해서는 안 됩니다. 개인정보 식별 정보가 포함되어선 안 되며, § 14.6.1 사용자 핸들 내용 참조.
- 사용자가 존재함(User Present)
-
사용자 존재 테스트가 성공적으로 완료되면 사용자가 "존재한다"고 간주합니다.
- 사용자 검증(User Verification)
-
인증자가 authenticatorMakeCredential 및 authenticatorGetAssertion 동작 호출을 로컬에서 허가하는 기술적 과정입니다. 사용자 검증(user verification)은 다양한 권한 부여 제스처로 유도될 수 있습니다. 예를 들어 터치 후 PIN, 비밀번호 입력, 생체 인식(biometric recognition) 등 (지문 등) ([ISOBiometricVocabulary])이 목적입니다. 이는 개별 사용자의 식별을 구분하려는 의도를 갖습니다. 자세한 내용은 § 6.2.3 인증 요소 능력(Authentication Factor Capability) 참조.
사용자 검증만으로 신뢰 당사자가 사용자 본인을 정확히 식별할 수 있는 것은 아니지만, 똑같은 자격 증명으로 2회 이상 사용자 검증이 수행됐다면 항상 동일 사용자가 해당 과정을 실행했음을 표현합니다. 단, 하나의 인증자를 여러 자연인이 공유하면 논리적 동일 사용자와 실제 자연인이 반드시 일치하진 않습니다.
참고: 자연인 구분은 클라이언트 플랫폼과 인증자의 역량에 크게 달려 있습니다. 예를 들어, 단일 사용자가 쓰는 기기로 설계되었지만, 여러 자연인이 지문을 등록하거나 같은 PIN을 공유할 수 있는 경우라면 여러 계정(user account)에도 접근 가능할 수 있습니다.
참고: authenticatorMakeCredential 및 authenticatorGetAssertion 호출은 인증자에서 관리하는 키 자료의 사용을 의미합니다.
보안을 위해, 사용자 검증 및 자격 증명 개인키 사용은 모두 반드시 인증자가 정의하는 논리(적) 보안 경계 안에서 이루어져야 합니다.
사용자 검증 절차는 무차별 대입 공격에 대한 방어책으로 속도 제한(rate limiting)을 구현할 수 있습니다.
- 사용자 검증됨(User Verified)
5. 웹 인증 API
이 절에서는 공개 키 자격 증명을 생성하고 사용하는 API를 규범적으로 명세합니다. 기본 개념은 자격 증명이 사용자에게 속하고 인증기에 의해 관리되며, WebAuthn 인증기와 WebAuthn Relying Party가 클라이언트 플랫폼을 통해 상호작용한다는 것입니다. Relying Party 스크립트는 (사용자 동의(user’s consent)를 얻어) 브라우저에 Relying Party가 향후 사용할 새 자격 증명을 생성하도록 요청할 수 있습니다. 아래 그림 을 참조하세요.
스크립트는 또한 기존 자격 증명으로 인증 작업을 수행하는 것에 대해 사용자의 허가를 요청할 수 있습니다. 아래 그림 을 참조하세요.
이러한 모든 작업은 인증기에서 수행되며 사용자를 대신해 클라이언트 플랫폼에 의해 중개됩니다. 스크립트가 자격 증명 자체에 접근하는 일은 전혀 없으며, 오직 객체 형태로 된 자격 증명에 대한 정보만 받게 됩니다.
위의 스크립트 인터페이스 외에도, 인증기는 사용자 인터페이스를 구현(MAY)하거나 해당 기능을 구현하는 클라이언트 소프트웨어와 함께 제공될 수 있습니다. 이러한 인터페이스는 예를 들어 인증기를 초기 상태로 재설정하거나 인증기의 현재 상태를 검사하는 데 사용될 수 있습니다. 다시 말해, 이러한 인터페이스는 기록, 저장된 암호, 쿠키 등과 같은 사용자 상태를 관리하기 위해 브라우저가 제공하는 사용자 인터페이스와 유사합니다. 자격 증명 삭제와 같은 인증기 관리 작업은 그러한 사용자 인터페이스의 책임으로 간주되며 스크립트에 노출된 API에서는 의도적으로 제외됩니다.
이 API의 보안 특성은 클라이언트와 인증기가 함께 동작함으로써 제공됩니다. 자격 증명을 보유하고 관리하는 인증기는 모든 작업이 특정 기원(origin)에 범위가 지정되어 있으며, 응답에 기원을 포함시켜 다른 기원에 대해 재생(replay)될 수 없도록 보장합니다. 구체적으로는, § 6.3 Authenticator Operations에 정의된 바와 같이 요청자의 전체 기원이 포함되어 서명되며, 이는 새 자격 증명이 생성될 때 생성되는 attestation object와 WebAuthn 자격 증명이 생성하는 모든 assertion에 포함됩니다.
추가로 사용자 프라이버시를 유지하고 악의적인 Relying Party가 다른 Relying Party에 속한 공개 키 자격 증명의 존재를 탐지하는 것을 방지하기 위해, 각 자격 증명은 범위가 지정되어 Relying Party 식별자 또는 RP ID에 한정됩니다. 이 RP ID는 모든 작업에 대해 클라이언트가 인증기에 제공하며, 인증기는 Relying Party에 의해 생성된 자격 증명이 동일한 RP ID로 요청된 작업에서만 사용될 수 있도록 보장합니다. 이렇게 기원(origin)과 RP ID를 분리하면 단일 Relying Party가 여러 기원을 유지하는 경우에도 API를 사용할 수 있게 됩니다.
클라이언트는 이러한 보안 조치를 돕기 위해 각 작업에 대해 Relying Party의 기원(origin) 및 RP ID를 인증기에 제공합 니다. 이것은 WebAuthn 보안 모델의 핵심 부분이므로, 사용자 에이전트는 이 API를 보안 컨텍스트(secure contexts)에서만 호출자에게 노출합니다. 특히 웹 컨텍스트의 경우, 이는 오류 없이 설정된 보안 전송(예: TLS)을 통해 접근되는 컨텍스트만 포함합니다.
Web Authentication API는 다음 섹션에 제시된 Web IDL 조각들의 합집합으로 정의됩니다. 결합된 IDL 목록은 IDL 색인에 제공됩니다.
5.1. PublicKeyCredential 인터페이스
이 PublicKeyCredential
인터페이스는 Credential
[CREDENTIAL-MANAGEMENT-1]로부터 상속되며, 새 자격 증명이 생성되거나 새 assertion이
요청될 때 호출자에게 반환되는 속성을 포함합니다.
[SecureContext ,Exposed =Window ]interface PublicKeyCredential :Credential { [SameObject ]readonly attribute ArrayBuffer ; [rawId SameObject ]readonly attribute AuthenticatorResponse response ;readonly attribute DOMString ?authenticatorAttachment ;AuthenticationExtensionsClientOutputs ();getClientExtensionResults static Promise <boolean >();isConditionalMediationAvailable PublicKeyCredentialJSON (); };toJSON
id-
이 속성은
Credential로부터 상속되지만,PublicKeyCredential은 Credential의 getter를 재정의하여 객체의[[identifier]]내부 슬롯에 포함된 데이터의 base64url 인코딩을 대신 반환합니다. rawId-
이 속성은
ArrayBuffer형태로[[identifier]]내부 슬롯에 포함된 값을 반환합니다. response, of type AuthenticatorResponse, readonly-
이 속성은 새 공개 키 자격 증명을 생성하거나 인증 어설션을 생성하라는 클라이언트의 요청에 대한 인증기의 응답을 포함합니다. 만약
PublicKeyCredential이create()에 대한 응답으로 생성되었다면, 이 속성의 값은AuthenticatorAttestationResponse가 될 것이고, 그렇지 않다면 이PublicKeyCredential은get()에 대한 응답으로 생성되었으며 이 속성의 값은AuthenticatorAssertionResponse가 됩니다. authenticatorAttachment, of type DOMString, readonly, nullable-
이 속성은 authenticator attachment modality를 보고하며,
navigator.credentials.create()또는navigator.credentials.get()호출이 성공적으로 완료되었을 때 적용된 값을 나타냅니다. 이 속성의 값은AuthenticatorAttachment의 멤버여야 합니다. Relying Parties는 알 수 없는 값을 null로 처리해야 합니다.Note: 만약 등록 절차 또는 인증 절차의 결과로authenticatorAttachment의 값이 "cross-platform"이고 동시에isUserVerifyingPlatformAuthenticatorAvailable가true를 반환한다면, 사용자는 그 절차에서 로밍 인증기를 사용했고 동시에 사용 가능한 플랫폼 인증기가 있다는 뜻입니다. 따라서 Relying Party는 사용자가 사용 가능한 플랫폼 인증기를 등록하도록 유도할 기회를 가집니다. 이는 보다 원활한 사용자 경험을 가능하게 할 수 있습니다.인증기의 attachment modality는 시간이 지남에 따라 변경될 수 있습니다. 예를 들어, 휴대전화는 한 시점에서는 플랫폼 부착(platform attachment)만 지원할 수 있지만 이후 업데이트를 통해 크로스-플랫폼 부착(cross-platform attachment)도 지원하게 될 수 있습니다.
getClientExtensionResults()-
이 연산은
[[clientExtensionsResults]]의 값을 반환합니다. 이 값은 확장의 클라이언트 확장 출력을 생성한 확장 식별자 → 출력 간의 항목들을 포함하는 맵입니다. isConditionalMediationAvailable()-
PublicKeyCredential은 이 메서드를 재정의하여conditional중재가navigator.credentials.get()동안 사용 가능한지를 나타냅니다. WebAuthn Relying Parties는options.을mediationconditional로 설정하기 전에 사용 가능 여부를 확인하는 것이 권장됩니다.이 메서드를 호출하면,
true로 해석되는 경우 conditional 사용자 중재(user mediation)가 사용 가능함을 나타내며 그렇지 않으면false로 해결되는 약속(Promise)이 반환됩니다.이 메서드는 인수를 받지 않으며 불리언 값을 반환하는 약속을 반환합니다.
클라이언트 기능인
conditionalGet은 이 약속이true로 해결되는 것과 동등합니다.Note: 만약 이 메서드가 존재하지 않는다면,
conditional사용자 중재는navigator.credentials.get()에 대해 사용 불가능한 것으로 간주됩니다.Note: 이 메서드는
conditional사용자 중재가navigator.credentials.create()에 대해 사용 가능한지를 나타내지는 않습니다. 이 경우에는conditionalCreate기능을getClientCapabilities()에서 확인해야 합니다. toJSON()-
이 연산은
RegistrationResponseJSON또는AuthenticationResponseJSON를 반환합니다. 이는PublicKeyCredential을 반영하는 JSON 타입 표현으로, Relying Party 서버에 application/json 페이로드로 제출하기에 적합합니다. 클라이언트는 일반적인 방식으로 값을 JSON 타입으로 직렬화할 책임이 있지만, 먼저 모든ArrayBuffer값을DOMString값으로 변환하기 위해 base64url 인코딩을 반드시 수행해야 합니다.RegistrationResponseJSON.clientExtensionResults또는AuthenticationResponseJSON.clientExtensionResults멤버는getClientExtensionResults()의 출력을 설정해야 하며, 이때ArrayBuffer값들은 base64url 인코딩을 사용해DOMString값으로 인코딩되어야 합니다. 이에는 IANA "WebAuthn Extension Identifiers" 레지스트리에 등록되어 있지만 § 9 WebAuthn Extensions에 정의되지 않은 확장으로부터의ArrayBuffer값이 포함될 수 있습니다.AuthenticatorAttestationResponseJSON.transports멤버는getTransports()의 출력을 설정해야 합니다.AuthenticatorAttestationResponseJSON.publicKey멤버는getPublicKey()의 출력을 설정해야 합니다.AuthenticatorAttestationResponseJSON.publicKeyAlgorithm멤버는getPublicKeyAlgorithm()의 출력을 설정해야 합니다.
typedef DOMString ; // The structure of this object will be either // RegistrationResponseJSON or AuthenticationResponseJSONBase64URLString typedef object ;PublicKeyCredentialJSON dictionary {RegistrationResponseJSON required DOMString ;id required Base64URLString ;rawId required AuthenticatorAttestationResponseJSON ;response DOMString ;authenticatorAttachment required AuthenticationExtensionsClientOutputsJSON ;clientExtensionResults required DOMString ; };type dictionary {AuthenticatorAttestationResponseJSON required Base64URLString ;clientDataJSON required Base64URLString ;authenticatorData required sequence <DOMString >; // The publicKey field will be missing if pubKeyCredParams was used to // negotiate a public-key algorithm that the user agent doesn't // understand. (See section “Easily accessing credential data” for a // list of which algorithms user agents must support.) If using such an // algorithm then the public key must be parsed directly from // attestationObject or authenticatorData.transports Base64URLString ;publicKey required COSEAlgorithmIdentifier ; // This value contains copies of some of the fields above. See // section “Easily accessing credential data”.publicKeyAlgorithm required Base64URLString ; };attestationObject dictionary {AuthenticationResponseJSON required DOMString ;id required Base64URLString ;rawId required AuthenticatorAssertionResponseJSON ;response DOMString ;authenticatorAttachment required AuthenticationExtensionsClientOutputsJSON ;clientExtensionResults required DOMString ; };type dictionary {AuthenticatorAssertionResponseJSON required Base64URLString ;clientDataJSON required Base64URLString ;authenticatorData required Base64URLString ;signature Base64URLString ; };userHandle dictionary { };AuthenticationExtensionsClientOutputsJSON
[[type]]-
PublicKeyCredential인터페이스 객체의[[type]]내부 슬롯 값은 문자열 "public-key"입니다.Note: 이는
type속성 getter를 통해 반영됩니다 (Credential로부터 상속됨). [[discovery]]-
PublicKeyCredential인터페이스 객체의[[discovery]]내부 슬롯 값은 "remote"입니다. [[identifier]]-
이 내부 슬롯은 인증기가 선택한 자격 증명 ID를 포함합니다. 자격 증명 ID는 자격 증명을 조회하는 데 사용되며, 동일 유형의 모든 자격 증명과 모든 인증기에서 높은 확률로 전역적으로 유일할 것으로 기대됩니다.
이 API는 이 식별자의 형식을 제약하지 않지만, 그 길이는 1023 바이트를 초과해서는 안 되며 인증기가 키를 고유하게 선택할 수 있을 만큼 충분해야 합니다. 예를 들어, 온보드 저장소가 없는 인증기는 대칭 키로 감싼 자격 증명 개인 키를 포함하는 식별자를 생성할 수 있습니다(해당 대칭 키는 인증기에 내장됨).
[[clientExtensionsResults]]-
이 내부 슬롯은 내부 슬롯로, Relying Party가
navigator.credentials.create()또는navigator.credentials.get()를 호출할 때 요청한 클라이언트 확장 처리 결과를 포함합니다.
PublicKeyCredential의
인터페이스 객체는 Credential의
[[CollectFromCredentialStore]](origin, options, sameOriginWithAncestors) 구현을 상속하며, 자체적으로 [[Create]](origin, options, sameOriginWithAncestors),
[[DiscoverFromExternalSource]](origin, options, sameOriginWithAncestors),
및 [[Store]](credential, sameOriginWithAncestors)의
자체 구현을 정의합니다.
만약 CredentialsContainer의
preventSilentAccess()
메서드를 호출하더라도 PublicKeyCredential
자격 증명에는 영향이 없습니다. 이 자격 증명은 항상 사용자 상호작용을 요구하기 때문입니다.
5.1.1. CredentialCreationOptions 사전 확장
navigator.credentials.create()를
통해 등록을 지원하기 위해, 이 문서는 CredentialCreationOptions
사전을 다음과 같이 확장합니다:
partial dictionary CredentialCreationOptions {PublicKeyCredentialCreationOptions ; };publicKey
5.1.2. CredentialRequestOptions 사전 확장
navigator.credentials.get()를
통해 어설션을 얻는 것을 지원하기 위해, 이 문서는 CredentialRequestOptions
사전을 다음과 같이 확장합니다:
partial dictionary CredentialRequestOptions {PublicKeyCredentialRequestOptions ; };publicKey
5.1.3.
새 자격 증명 만들기 - PublicKeyCredential의 [[Create]](origin, options, sameOriginWithAncestors)
내부 메서드
PublicKeyCredential의
인터페이스 객체에서 구현된 [[Create]](origin, options, sameOriginWithAncestors)
내부 메서드 [CREDENTIAL-MANAGEMENT-1] 덕분에 WebAuthn Relying Party 스크립트는
navigator.credentials.create()
를 호출하여 새로운 공개키 크리덴셜 소스를 요청할 수 있으며, 이 크리덴셜은 바인딩된 인증기와 연결됩니다.
다음과 같이 설정함으로써
options.
을 mediationconditional로
하면,
Relying Parties는 사용자가 이미
자격 증명 생성을 허용한 경우 눈에 띄는 모달 UI 없이 자격 증명을 등록하길 원함을 표시할 수 있습니다.
Relying Party는 이 기능이 사용
가능한지 확인하기 위해 먼저 getClientCapabilities()를
사용하여
client가 conditionalCreate
기능을 지원하는지 확인해야 하며, 그렇지 않으면 사용자에게 눈에 보이는 오류가 발생할 수 있습니다.
클라이언트는
options.
가 mediationconditional로
설정된 경우, 의식적으로 의식적으로 의식을 수행하지 않는 한 requireUserPresence와 requireUserVerification를 모두
FALSE로 설정해야 합니다.
모든 navigator.credentials.create()
작업은 AbortController를
사용하여 중단할 수 있습니다; 자세한 지침은 DOM § 3.3 Using
AbortController and AbortSignal objects in APIs를 참조하세요.
이 내부 메서드는 세 개의 인수를 받습니다:
origin-
이 인수는 호출하는
create()구현에 의해 결정된 relevant settings object의 origin입니다. options-
이 인수는
CredentialCreationOptions객체이며, 그options.멤버는 생성될 public key credential의 원하는 속성을 지정하는publicKeyPublicKeyCredentialCreationOptions객체를 포함합니다. sameOriginWithAncestors-
이 인수는 Boolean 값이며, 호출자의 environment settings object가 조상들과 same-origin인지에 따라
true가 됩니다. 호출자가 교차 출처인 경우에는false입니다.참고: 이 내부 메서드의 호출은 permissions policy에 의해 허용되었음을 나타내며, 이는 [CREDENTIAL-MANAGEMENT-1] 수준에서 평가됩니다. 자세한 내용은 § 5.9 Permissions Policy integration을 참조하세요.
참고: 이 알고리즘은 동기적입니다: Promise의
해결/거절은 navigator.credentials.create()에서
처리됩니다.
이 알고리즘에서 사용되는 모든 BufferSource
객체는 알고리즘이 시작될 때 스냅샷되어야 하며, 동기화 문제를 피하기 위해 구현체는 버퍼 소스가 보유한 바이트의 복사본을 얻는 것을 권장합니다.
이 메서드가 호출되면 사용자 에이전트는 다음 알고리즘을 반드시 실행해야 합니다:
-
단언:
options.가 존재함을 확인합니다.publicKey -
만약 sameOriginWithAncestors가
false이면:-
만약
options.가 존재하고 값이mediationconditional인 경우:-
NotAllowedError"DOMException을 던집니다.
-
-
만약 호출하는
create()구현에 의해 결정된 relevant global object가 transient activation을 가지고 있지 않다면:-
NotAllowedError"DOMException을 던집니다.
-
-
relevant global object의 사용자 활성화를 소비합니다.
-
만약 자격 증명을 생성하는 origin이 사용자가 주소 표시줄에서 보는 최상위 기원의 top-level origin과 다르다면, client는 이 사실을 사용자에게 명확히 알려야 합니다.
-
-
pkOptions를
options.의 값으로 둡니다.publicKey -
만약
pkOptions.이 존재하면, 그 값이 client가 정의한 합리적인 범위 내에 있는지 확인하고, 아니면 가장 가까운 유효값으로 수정합니다. 그 조정된 값으로 타이머 lifetimeTimer를 설정합니다. 만약 존재하지 않으면 client-특정 기본값으로 설정합니다.timeout권장 범위 및 기본값에 대한 지침은 recommended range and default for a WebAuthn ceremony timeout를 참조하세요.
client는 특수한 요구가 있는 사용자를 위해 타임아웃을 정할 때 인지적 지침을 고려해야 합니다.
-
만약
pkOptions.의 길이가 1에서 64 바이트(포함) 사이가 아니면user.idTypeError를 던집니다. -
callerOrigin을
origin으로 둡니다. 만약 callerOrigin이 opaque origin이면 "NotAllowedError"DOMException을 던집니다. -
effectiveDomain을 callerOrigin의 effective domain으로 둡니다. 만약 해당 effective domain이 유효한 domain이 아니면 "
SecurityError"DOMException을 던집니다.참고: effective domain은 호스트를 나타낼 수 있으며, 이는 domain, ipv4 주소, ipv6 주소, opaque host, 또는 empty host 등 다양한 방식으로 표현될 수 있습니다. 여기서는 domain 형식의 호스트만 허용됩니다. 이는 단순화 목적 및 PKI 기반 보안과 함께 IP 주소 식별을 사용하는 데 따른 여러 문제를 고려한 것입니다.
-
- 존재하는 경우
-
만약
pkOptions.가 effectiveDomain의 registrable domain suffix가 아니고 같지도 않다면, 그리고 클라이언트가rp.id- related origin requests를 지원하는 경우
-
-
related origins validation procedure를 callerOrigin과 rpIdRequested 인수로 실행합니다. 결과가
false이면 "SecurityError"DOMException을 던집니다.
- related origin requests를 지원하지 않는 경우
-
"
SecurityError"DOMException을 던집니다.
- 존재하지 않는 경우
참고:
pkOptions.는 호출자의 RP ID를 나타냅니다. RP ID는 호출자가 명시적으로rp.idpkOptions.를 설정하지 않은 한 호출자의 origin의 effective domain으로 기본 설정됩니다.rp.id -
credTypesAndPubKeyAlgs을 새 list로 두고, 이 리스트의 항목들은
PublicKeyCredentialType와COSEAlgorithmIdentifier의 쌍이 되도록 합니다. -
만약
pkOptions.의 크기pubKeyCredParams- 0인 경우
-
다음의
PublicKeyCredentialType와COSEAlgorithmIdentifier쌍을 credTypesAndPubKeyAlgs에 추가합니다:-
public-key와-7("ES256"). -
public-key와-257("RS256").
-
- 0이 아닌 경우
-
각각의 current에 대해
pkOptions.를 반복합니다:pubKeyCredParams-
만약
current.에 이 구현이 지원하지 않는typePublicKeyCredentialType가 포함되어 있으면 계속합니다. -
alg을
current.로 둡니다.alg
만약 credTypesAndPubKeyAlgs가 비어 있으면 "
NotSupportedError"DOMException을 던집니다. -
-
clientExtensions를 새 map으로 하고, authenticatorExtensions를 새 map으로 둡니다.
-
만약
pkOptions.가 존재하면, 각각의 extensionId → clientExtensionInput에 대해:extensions-
만약 extensionId가 이 client platform에서 지원되지 않거나 등록 확장(registration extension)이 아니면 계속합니다.
-
Set clientExtensions[extensionId]을 clientExtensionInput으로 설정합니다.
-
만약 extensionId가 authenticator extension이 아니면 계속합니다.
-
authenticatorExtensionInput을 extensionId의 client extension processing 알고리즘을 clientExtensionInput에 실행하여 얻은 (CBOR) 결과로 둡니다. 만약 알고리즘이 오류를 반환하면 계속합니다.
-
Set authenticatorExtensions[extensionId]을 authenticatorExtensionInput의 base64url 인코딩으로 설정합니다.
-
-
collectedClientData를 새
CollectedClientData인스턴스로 하고 그 필드는 다음과 같습니다:type-
문자열 "webauthn.create".
challenge-
pkOptions.
challenge의 base64url 인코딩. origin-
callerOrigin의 직렬화.
crossOrigin-
이 내부 메서드에 전달된
sameOriginWithAncestors인수의 값의 역값입니다. topOrigin-
만약 이 내부 메서드에 전달된
sameOriginWithAncestors인수가false이면 callerOrigin의 top-level origin의 직렬화이고, 그렇지 않으면undefined입니다.
-
clientDataJSON를 collectedClientData로부터 구성된 JSON-호환 직렬화로 둡니다.
-
clientDataHash를 clientDataJSON로 표현된 직렬화된 클라이언트 데이터의 해시로 둡니다.
-
만약
options.이 존재하고 aborted 상태라면,signaloptions.의 abort reason을 throw 하십시오.signal -
issuedRequests를 새 ordered set으로 둡니다.
-
authenticators는 주어진 순간에 이 client platform에서 현재 사용 가능한 각 authenticator를 식별하는 플랫폼별 핸들들의 집합을 나타내는 값입니다.
참고: 어떤 것이 "사용 가능"한 authenticator인지에 대한 기준은 의도적으로 명시하지 않았습니다; 이는 인증기가 USB로 핫플러그되거나 NFC/Bluetooth로 검색되거나 플랫폼에 내장되는 등 다양한 메커니즘으로 클라이언트가 인식하는 방식을 나타냅니다.
-
만약
options.이 존재하고 값이mediationconditional이면:-
만약 사용자 에이전트가 최근에 인증을 중재하지 않았거나, 그 인증의 기원이 callerOrigin이 아니거나, 사용자가 이 유형의 자격 증명 생성을 동의하지 않으면 "
NotAllowedError"DOMException을 던집니다.어떤 시점에서 사용자 에이전트가 인증 절차가 완료되었다고 믿을지는 사용자 에이전트에 달려 있습니다. 그 인증 절차는 Web Authentication API 이외의 다른 수단으로 수행될 수 있습니다.
-
-
hints값을 고려하여 사용자 인터페이스를 적절히 구성합니다. -
lifetimeTimer를 시작합니다.
-
While
lifetimeTimer가 만료되지 않은 동안, lifetimeTimer와 authenticators의 상태 및 응답에
따라 각 authenticator에 대해 다음 작업을 수행합니다:
- 만약 lifetimeTimer가 만료되면,
-
각각의 authenticator에 대해 issuedRequests에서 authenticatorCancel 연산을 호출하고 제거합니다.
- 만약 사용자가 프로세스를 취소하는 UI 옵션을 사용하면,
-
각각의 authenticator에 대해 issuedRequests에서 authenticatorCancel을 호출하고 제거합니다. 그런 다음 "
NotAllowedError"DOMException을 던집니다. - 만약
options.이 존재하고 중단(aborted) 상태이면,signal -
각 authenticator에 대해 issuedRequests에 있는 항목을 대상으로, authenticatorCancel 작업을 authenticator에 호출하고 제거 authenticator를 issuedRequests에서 합니다. 그런 다음
options.의 중단 사유(abort reason)를 throw합니다.signal - 만약 authenticator가 이 client device에서 사용 가능해지면,
-
참고: 여기에는 lifetimeTimer 시작 시 이미 사용 가능했던 경우도 포함됩니다.
-
이 authenticator는 이제 candidate authenticator가 됩니다.
-
만약
pkOptions.이 존재하면:authenticatorSelection-
만약
pkOptions.가 존재하고 그 값이 이 authenticator의 authenticator attachment modality와 같지 않으면 계속합니다.authenticatorSelection.authenticatorAttachment -
만약
pkOptions.authenticatorSelection.residentKey- 존재하고
required로 설정된 경우 -
만약 authenticator가 client-side discoverable public key credential source를 저장할 수 없으면 계속합니다.
- 존재하고
preferred또는discouraged로 설정된 경우 -
영향 없음.
- 존재하지 않는 경우
-
만약
pkOptions.가authenticatorSelection.requireResidentKeytrue로 설정되어 있고 authenticator가 client-side discoverable public key credential source를 저장할 수 없으면 계속합니다.
- 존재하고
-
만약
pkOptions.이authenticatorSelection.userVerificationrequired로 설정되어 있고 이 authenticator가 user verification을 수행할 수 없으면 계속합니다.
-
-
requireResidentKey를 자격 증명 생성에 대한 유효 상주 키 요구 사항(effective resident key requirement for credential creation) Boolean 값으로 정의한다. 정의 방법은 다음과 같다:
pkOptions.authenticatorSelection.residentKey- 존재하며
required로 설정된 경우 -
requireResidentKey를
true로 한다. - 존재하며
preferred로 설정된 경우 -
만약 authenticator
- 클라이언트 측 자격 증명 저장 방식을 지원하는 경우
-
requireResidentKey를
true로 한다. - 클라이언트 측 자격 증명 저장 방식을 지원하지 않거나, 클라이언트가 인증자의 능력을 판단할 수 없는 경우
-
requireResidentKey를
false로 한다.
- 존재하며
discouraged로 설정된 경우 -
requireResidentKey를
false로 한다. - 존재하지 않는 경우
-
requireResidentKey를
pkOptions.값으로 한다.authenticatorSelection.requireResidentKey
- 존재하며
-
userVerification을 자격 증명 생성에 대한 유효 사용자 검증 요구사항(effective user verification requirement for credential creation) Boolean 값으로 정의한다. 정의는 다음과 같다.
pkOptions.authenticatorSelection.userVerification-
required로 설정된 경우 -
-
options.값이mediationconditional이고, 본 절차에서 사용자 검증(user verification)을 획득할 수 없는 경우,ConstraintErrorDOMException을 throw한다. -
userVerification을
true로 한다.
-
-
preferred로 설정된 경우 -
만약 authenticator
-
discouraged로 설정된 경우 -
userVerification을
false로 한다.
-
-
enterpriseAttestationPossible를 Boolean 값으로 둡니다. 만약
pkOptions.attestation- 설정이
enterprise인 경우 -
만약 사용자 에이전트가
pkOptions.에 대해 enterprise attestation을 지원하기 원하면 enterpriseAttestationPossible를rp.idtrue로 합니다. 그렇지 않으면false로 합니다. - 그 외
-
enterpriseAttestationPossible를
false로 설정합니다.
- 설정이
-
attestationFormats를 문자열 리스트로 두고 초기값은
pkOptions.의 값으로 합니다.attestationFormats -
만약
pkOptions.attestation- 설정이
none인 경우 -
attestationFormats를 단일 요소 리스트 ["none"]로 설정합니다.
- 설정이
-
excludeCredentialDescriptorList를 새 list로 둡니다.
-
각각의 C에 대해
pkOptions.의 credential descriptor:excludeCredentials-
만약
C.가 비어 있지 않고, authenticator가transportsC.에 언급되지 않은 전송 방식으로 연결되어 있다면, 클라이언트는 계속할 수 있습니다.transports참고: 클라이언트가 계속하기로 선택하면,
C.에 있는 전송 힌트가 정확하지 않은 경우 동일한 authenticator에 바인드된 여러 자격 증명이 실수로 등록될 수 있습니다. 예를 들어, 소프트웨어 업그레이드로 연결 옵션이 추가되어 저장된 전송 힌트가 부정확해질 수 있습니다.transports -
그렇지 않으면 Append C를 excludeCredentialDescriptorList에 추가합니다.
-
- authenticator에서 authenticatorMakeCredential 연산을
호출합니다. 인수로는 clientDataHash,
pkOptions.,rppkOptions., requireResidentKey, userVerification, credTypesAndPubKeyAlgs, excludeCredentialDescriptorList, enterpriseAttestationPossible, attestationFormats, 및 authenticatorExtensions.user -
Append authenticator를 issuedRequests에 추가합니다.
-
- 만약 authenticator가 이 client device에서 더 이상 사용 가능하지 않게 되면,
-
Remove authenticator를 issuedRequests에서 제거합니다.
- 만약 어떤 authenticator가 사용자 취소 상태를 반환하면,
-
-
Remove 해당 authenticator를 issuedRequests에서 제거합니다.
-
남아 있는 각 authenticator에 대해 authenticatorCancel을 호출하고 제거합니다.
참고: Authenticators는 "사용자가 전체 작업을 취소했다"는 표시를 반환할 수 있습니다. 사용자 에이전트가 이를 사용자에게 어떻게 나타내는지는 명시되지 않습니다.
-
- 만약 어떤 authenticator가 "
InvalidStateError"에 해당하는 오류 상태를 반환하면, -
-
Remove 해당 authenticator를 issuedRequests에서 제거합니다.
-
남아 있는 각 authenticator에 대해 authenticatorCancel을 호출하고 제거합니다.
-
"
InvalidStateError"DOMException을 던집니다.
참고: 이 오류 상태는 excludeCredentialDescriptorList가 해당 authenticator에 바인드된 자격 증명을 식별하고 사용자가 작업에 동의한 경우에만 인증기가 반환하기 때문에 별도로 처리됩니다. 이 명시적 동의를 고려하면 이 경우가 Relying Party에 대해 구별 가능한 것이 허용됩니다.
-
- 만약 어떤 authenticator가 "
InvalidStateError"이 아닌 오류 상태를 반환하면, -
Remove 해당 authenticator를 issuedRequests에서 제거합니다.
참고: 이 경우는 작업에 대한 사용자 동의를 의미하지 않으므로, 오류에 대한 세부 정보는 잠재적으로 식별 가능한 정보를 유출하지 않기 위해 Relying Party로부터 숨겨집니다. 자세한 내용은 § 14.5.1 Registration Ceremony Privacy를 참조하세요.
- 만약 어떤 authenticator가 성공을 표시하면,
-
-
Remove 해당 authenticator를 issuedRequests에서 제거합니다. 이 인증기는 이제 selected authenticator가 됩니다.
-
credentialCreationData를 다음 항목을 가진 struct으로 둡니다:
-
attestationObjectResult -
성공한 authenticatorMakeCredential 연산으로부터 반환된 바이트입니다.
참고: 이 값은 § 6.5.4 Generating an Attestation Object에서 정의된
attObj입니다. -
clientDataJSONResult -
그 값은 clientDataJSON의 바이트입니다.
-
attestationConveyancePreferenceOption -
그 값은 pkOptions.
attestation의 값입니다. -
clientExtensionResults -
그 값은 각 확장에 대해 client extension processing 알고리즘을 실행하여 생성된 client extension output 항목들을 포함하는
AuthenticationExtensionsClientOutputs객체입니다.
-
-
constructCredentialAlg을 다음과 같은 알고리즘으로 둡니다: 이 알고리즘은 전역 객체 global을 인수로 받고 다음 단계를 수행합니다:
-
만약 credentialCreationData.attestationConveyancePreferenceOption의 값이
none-
잠재적으로 식별 가능한 정보를 비식별 버전으로 대체합니다:
-
만약 aaguid가 16 바이트 0이고, attested credential data 내에서, 그리고
credentialCreationData.attestationObjectResult.fmt이 "packed"이며 "x5c"가 없으면, 이는 self attestation이 사용되고 있음을 의미하므로 추가 조치가 필요 없습니다. -
그렇지 않으면:
-
credentialCreationData.attestationObjectResult.fmt
의 값을 "none"으로 설정하고, credentialCreationData.attestationObjectResult.attStmt
의 값을 빈 CBOR 맵으로 설정합니다. (참조: § 8.7 None Attestation Statement Format 및 § 6.5.4 Generating an Attestation Object).
-
-
indirect-
클라이언트는 더 프라이버시 친화적이거나 검증하기 쉬운 버전(예: Anonymization CA를 사용하는 방식)으로 aaguid와 attestation statement를 대체할 수 있습니다.
direct또는enterprise-
authenticator의 AAGUID와 attestation statement를 변경 없이 Relying Party에게 전달합니다.
-
attestationObject를 새
ArrayBuffer로 만들고, global의 %ArrayBuffer%을 사용하여 credentialCreationData.attestationObjectResult의 바이트를 포함시킵니다. -
id를
attestationObject.authData.attestedCredentialData.credentialId로 둡니다. -
pubKeyCred를 global과 연관된 새
PublicKeyCredential객체로 만들고 그 필드는 다음과 같습니다:[[identifier]]-
id
authenticatorAttachment-
현재 authenticator의 authenticator attachment modality와 일치하는
AuthenticatorAttachment값입니다. response-
global과 연관된 새
AuthenticatorAttestationResponse객체로 그 필드는 다음과 같습니다:clientDataJSON-
global의 %ArrayBuffer%를 사용하여 생성된 새
ArrayBuffer로 credentialCreationData.clientDataJSONResult의 바이트를 포함합니다. attestationObject-
attestationObject
[[transports]]-
사전식(lexicographical) 순서로 정렬된 0개 이상의 고유한
DOMString들의 시퀀스로, 해당 authenticator가 지원하는 것으로 여겨지는 전송 방식들입니다. 이 값들은AuthenticatorTransport의 멤버여야 하지만, client platforms는 알 수 없는 값을 무시해야 합니다.만약 사용자 에이전트가 이 정보를 드러내고 싶지 않으면, 프라이버시를 보존하기 위한 임의의 시퀀스를 대신 반환할 수 있습니다. 이 시퀀스는 여전히 유효해야 합니다(사전식 정렬 및 중복 없음). 예를 들면 빈 시퀀스를 사용할 수 있습니다. 이 경우 Relying Party 동작이 최적이 아닐 수 있습니다.
만약 사용자 에이전트가 전송 정보가 없다면, 이 필드를 빈 시퀀스로 설정하는 것이 권장됩니다.
참고: 특정 authenticator가 지원하는 전송을 사용자 에이전트가 어떻게 발견하는지는 본 명세의 범위를 벗어나지만, attestation certificate, CTAP2와 같은 인증기 프로토콜의 메타데이터, 혹은 플랫폼 인증기에 대한 특수 지식 등에서 정보를 얻을 수 있습니다.
[[clientExtensionsResults]]-
global의 %ArrayBuffer%를 사용하여 생성된 새
ArrayBuffer로 credentialCreationData.clientExtensionResults의 바이트를 포함합니다.
-
pubKeyCred를 반환합니다.
-
-
남아 있는 issuedRequests의 각 authenticator에 대해 authenticatorCancel을 호출하고 제거합니다.
-
constructCredentialAlg를 반환하고 이 알고리즘을 종료합니다.
-
-
"
NotAllowedError"DOMException을 던집니다.
위 과정 동안 사용자 에이전트는 인증기 선택 및 승인 과정을 안내하기 위해 사용자에게 일부 UI를 보여주는 것이 권장됩니다. 만약
options.
가 mediationconditional로
설정되어 있으면, 이전에 사용자 에이전트가 결정한 수단으로 자격 증명 생성이 미리 동의되지 않은 경우를 제외하고 눈에 띄는 모달 UI를 표시해서는 안 됩니다.
5.1.3.1. 생성 요청 예외
이 절은 규범적이지 않습니다.
WebAuthn Relying
Parties는 navigator.credentials.create()
호출에서 여러 예외를 마주칠 수 있습니다.
일부 예외는 발생 원인이 여러 가지일 수 있어, WebAuthn Relying Parties가 WebAuthn 사용 상황을 바탕으로 실제 원인을 추론해야 할 수
있습니다.
참고: 이 명세 외부에서 정의된 것을 포함하여 모든 WebAuthn Extensions의 처리 중 발생할 수 있는 예외는 여기에는 나열되지 않습니다.
다음의 DOMException
예외들이 발생할 수 있습니다:
AbortError-
절차가
AbortController에 의해 취소되었습니다. 자세한 내용은 § 5.6 Abort Operations with AbortSignal 및 § 1.3.4 Aborting Authentication Operations를 참조하세요. ConstraintError-
다음 중 하나입니다:
residentKey가required로 설정되었으나 사용 가능한 인증기가 resident key를 지원하지 않았거나,userVerification이required로 설정되었으나 사용 가능한 인증기가 user verification을 수행할 수 없었던 경우입니다. InvalidStateError-
인증 과정에서 사용된 인증기가 사용자가 동의한 후에
excludeCredentials목록에 있는 항목을 인식했을 때 발생합니다. NotSupportedError-
pubKeyCredParams에 있는 항목 중 어떤 것도type이public-key이 아니었거나, authenticator가pubKeyCredParams에 명시된 서명 알고리즘 중 어느 것도 지원하지 않는 경우입니다. SecurityError-
effective domain이 유효한 domain이 아니거나, 또는
가 effective domain과 같거나 그 등록 가능한 도메인 접미사가 아닌 경우입니다. 후자의 경우, 클라이언트는 related origin requests를 지원하지 않거나 related origins validation procedure가 실패한 것입니다.rp.id NotAllowedError-
사용자가 절차를 취소하는 등 다양한 가능한 원인을 포괄하는 포괄적 오류입니다. 이러한 원인 중 일부는 이 명세 전반에 문서화되어 있으며, 다른 것들은 클라이언트 특유의 원인일 수 있습니다.
다음의 단순 예외(simple exceptions)들도 발생할 수 있습니다:
TypeError-
options인수가 유효한CredentialCreationOptions값이 아니거나,의 값이 비어 있거나 64 바이트보다 긴 경우입니다.user.id
5.1.4. 기존 자격 증명을 사용하여 어설션 생성
WebAuthn Relying
Parties는
navigator.credentials.get({publicKey:..., ...})
를 호출하여 기존의 public
key credential을 검색하고 사용자 동의(user’s consent)를 얻어 사용합니다.
Relying Party 스크립트는 선택적으로 어떤
public key credential sources가 허용되는지에 대한 기준을 지정할 수 있습니다.
client platform은 지정된 기준에
맞는 public key credential sources를 찾아 사용자가 스크립트가 사용하도록 허용할
자격 증명을 선택하도록 안내합니다. 예를 들어 사용자는 프라이버시를 유지하기 위해 전체 상호작용을 거부할 수 있습니다. 사용자가 public key credential
source를 선택하면, 사용자 에이전트는 § 6.3.3 The authenticatorGetAssertion
Operation을 사용하여 Relying Party가 제공한 challenge와 다른 수집된 데이터를 서명해 authentication assertion을
생성하고, 이를 credential로 사용합니다.
navigator.credentials.get()
구현은 [CREDENTIAL-MANAGEMENT-1]에 따라
PublicKeyCredential.
를 호출하여 사용자 중재 없이 사용 가능해야 할 credentials을 수집합니다(대략적으로 이 명세의 authorization gesture). 만약 정확히
하나가 발견되지 않으면,
[[CollectFromCredentialStore]]()PublicKeyCredential.
를 호출하여 사용자가 public key credential source를 선택하도록 합니다.
[[DiscoverFromExternalSource]](origin, options, sameOriginWithAncestors)
이 명세는 어떤 authorization gesture이든 간에 어설션을 생성하려면 필요하므로, PublicKeyCredential
은 [[CollectFromCredentialStore]](origin, options, sameOriginWithAncestors)
의 기본 동작(빈 집합 반환)을 상속합니다. PublicKeyCredential의
[[DiscoverFromExternalSource]](origin, options, sameOriginWithAncestors)
구현은 다음 섹션에서 명세됩니다.
일반적으로 사용자 에이전트는 인증기 선택 및 승인 과정을 사용자에게 안내하기 위해 일부 UI를 표시해야 합니다.
options.
를 mediationconditional
로 설정하면, Relying Parties는 자격
증명이 발견되지 않는 한 눈에 띄는 모달 UI를 표시하지 않도록 요청할 수 있습니다.
Relying Party는 이 기능이 사용 가능한지
확인하기 위해 먼저 isConditionalMediationAvailable()
또는 getClientCapabilities()
를 사용하여 client가 conditionalGet
기능을 지원하는지 확인해야 합니다. 그렇지 않으면 사용자에게 보이는 오류가 발생할 수 있습니다.
모든 navigator.credentials.get()
작업은 AbortController
를 사용하여 중단될 수 있습니다; 자세한 지침은 DOM § 3.3 Using
AbortController and AbortSignal objects in APIs를 참조하세요.
5.1.4.1. PublicKeyCredential의
[[DiscoverFromExternalSource]](origin, options, sameOriginWithAncestors)
내부 메서드
[[DiscoverFromExternalSource]](origin, options, sameOriginWithAncestors)이 internal method는 세 개의 인수를 받습니다:
origin-
이 인수는 호출하는
get()구현에 의해 결정된 relevant settings object의 origin입니다. 즉,CredentialsContainer의 Request aCredential추상 연산에 해당합니다. options-
이 인수는
CredentialRequestOptions객체이며, 그options.멤버는 검색할 public key credential의 원하는 속성을 지정하는publicKeyPublicKeyCredentialRequestOptions객체를 포함합니다. sameOriginWithAncestors-
이 인수는 Boolean 값이며, 호출자의 environment settings object가 조상들과 same-origin인지에 따라
true가 됩니다. 호출자가 교차 출처인 경우에는false입니다.참고: 이 내부 메서드의 호출은 permissions policy에 의해 허용되었음을 나타내며, 이는 [CREDENTIAL-MANAGEMENT-1] 수준에서 평가됩니다. 자세한 내용은 § 5.9 Permissions Policy integration을 참조하세요.
참고: 이 알고리즘은 동기적입니다: Promise
의 해결/거절은 navigator.credentials.get()에서
처리됩니다.
이 알고리즘에서 사용되는 모든 BufferSource
객체는 알고리즘이 시작될 때 스냅샷되어야 하며, 동기화 문제를 피하기 위해 구현체는 버퍼 소스가 보유한 바이트의 복사본을 얻는 것을 권장합니다.
이 메서드가 호출되면 사용자 에이전트는 다음 알고리즘을 반드시 실행해야 합니다:
-
단언:
options.가 존재함을 확인합니다.publicKey -
pkOptions를
options.의 값으로 둡니다.publicKey -
만약
options.가 존재하고 그 값이mediationconditional인 경우:-
credentialIdFilter를
pkOptions.의 값으로 둡니다.allowCredentials -
pkOptions.를 empty로 설정합니다.allowCredentials참고: 이렇게 하면 non-discoverable credentials가
conditional요청 동안 사용되는 것을 방지합니다. -
lifetimeTimer를 무한(infinity) 값으로 설정합니다.
참고: lifetimeTimer가 무한으로 설정되는 이유는 사용자가 문서의 전체 수명 동안
"webauthn"autofill detail token이 지정된input폼 컨트롤을 통해 상호작용할 수 있도록 하기 위함입니다. 예를 들어 사용자가 해당 입력 필드를 클릭하면 사용자 에이전트는 발견된 자격 증명 목록을 렌더링하여 사용자가 선택하도록 하거나 "다른 방법 시도" 옵션을 제공할 수 있습니다.
-
-
그 밖의 경우(else):
-
credentialIdFilter를 빈 list로 둡니다.
-
만약
pkOptions.이 존재하면, 그 값이 client가 정의한 합리적 범위 내에 있는지 확인하고, 아니면 가장 가까운 유효값으로 수정합니다. 그 조정된 값으로 lifetimeTimer를 설정합니다. 만약 존재하지 않으면 client-특정 기본값으로 설정합니다.timeout타임아웃의 합리적 범위 및 기본값에 대한 지침은 recommended range and default for a WebAuthn ceremony timeout를 참조하세요.
사용자 에이전트는 특수한 필요가 있는 사용자를 위해 타임아웃을 정할 때 인지적 지침을 고려해야 합니다.
-
-
callerOrigin을
origin으로 둡니다. 만약 callerOrigin이 opaque origin이면 "NotAllowedError"DOMException을 던집니다. -
effectiveDomain을 callerOrigin의 effective domain으로 둡니다. 만약 해당 effective domain이 유효한 domain이 아니면 "
SecurityError"DOMException을 던집니다.참고: effective domain은 host로 해석될 수 있으며, 이는 domain, ipv4 주소, ipv6 주소, opaque host, 또는 empty host 등 다양한 방식으로 표현될 수 있습니다. 여기서는 domain 형식의 호스트만 허용됩니다. 이는 단순화 목적 및 PKI 기반 보안과 직접 IP 주소 식별을 함께 사용할 때 발생하는 여러 문제를 고려한 것입니다.
-
만약
pkOptions.rpId- 존재하는 경우
-
만약
pkOptions.가 effectiveDomain의 registrable domain suffix가 아니고 같지도 않다면, 그리고 클라이언트가rpId- related origin requests를 지원하는 경우
-
-
rpIdRequested를
pkOptions.의 값으로 둡니다.rpId -
related origins validation procedure를 callerOrigin과 rpIdRequested로 실행합니다. 결과가
false이면 "SecurityError"DOMException을 던집니다.
-
- related origin requests를 지원하지 않는 경우
-
"
SecurityError"DOMException을 던집니다.
- 존재하지 않는 경우
-
pkOptions.를 effectiveDomain으로 설정합니다.rpId
참고: rpId는 호출자의 RP ID를 나타냅니다. RP ID는 호출자가 명시적으로
pkOptions.를 설정하지 않은 경우 호출자의 origin의 effective domain으로 기본 설정됩니다.rpId -
clientExtensions를 새 map으로, authenticatorExtensions를 새 map으로 둡니다.
-
만약
pkOptions.가 존재하면, 각각의 extensionId → clientExtensionInput에 대해:extensions-
만약 extensionId가 이 client platform에서 지원되지 않거나 인증 확장(authentication extension)이 아니면 계속합니다.
-
Set clientExtensions[extensionId]을 clientExtensionInput으로 설정합니다.
-
만약 extensionId가 authenticator extension이 아니면 계속합니다.
-
authenticatorExtensionInput을 extensionId의 client extension processing 알고리즘을 clientExtensionInput에 실행하여 얻은 (CBOR) 결과로 둡니다. 만약 알고리즘이 오류를 반환하면 계속합니다.
-
Set authenticatorExtensions[extensionId]을 base64url 인코딩한 authenticatorExtensionInput으로 설정합니다.
-
-
collectedClientData를 새
CollectedClientData인스턴스로 하고 그 필드는 다음과 같습니다:type-
문자열 "webauthn.get".
challenge-
pkOptions.
challenge의 base64url 인코딩. origin-
callerOrigin의 직렬화.
crossOrigin-
이 내부 메서드에 전달된
sameOriginWithAncestors인수의 값의 역값입니다. topOrigin-
만약 이 내부 메서드에 전달된
sameOriginWithAncestors인수가false이면 callerOrigin의 top-level origin의 직렬화이고, 그렇지 않으면undefined입니다.
-
clientDataJSON를 collectedClientData로부터 구성된 JSON-호환 직렬화로 둡니다.
-
clientDataHash를 clientDataJSON로 표현된 직렬화된 클라이언트 데이터의 해시로 둡니다.
-
만약
options.이 존재하고 중단(aborted) 상태라면,signaloptions.의 중단 사유(abort reason)를 throw 하십시오.signal -
issuedRequests를 새 ordered set으로 둡니다.
-
savedCredentialIds를 새 map으로 둡니다.
-
authenticators는 주어진 순간에 이 client platform에서 현재 사용 가능한 각 authenticator를 식별하는 플랫폼별 핸들들의 집합을 나타내는 값입니다.
참고: 어떤 것이 "사용 가능"한 authenticator인지에 대한 기준은 의도적으로 명시하지 않았습니다; 이는 인증기가 USB로 핫플러그되거나 NFC/Bluetooth로 검색되거나 플랫폼에 내장되는 등 다양한 메커니즘으로 클라이언트가 인식하는 방식을 나타냅니다.
-
silentlyDiscoveredCredentials를 새 map으로 두고, 그 entries는 DiscoverableCredentialMetadata → authenticator의 형태입니다.
-
hints값을 고려하여 사용자 인터페이스를 적절히 구성합니다. -
lifetimeTimer를 시작합니다.
-
While lifetimeTimer가 만료되지 않은 동안, lifetimeTimer와 authenticators의 상태 및 응답에 따라 각 authenticator에 대해 다음 작업을 수행합니다:
- 만약 lifetimeTimer가 만료되면,
-
각각의 authenticator에 대해 issuedRequests에서 authenticatorCancel을 호출하고 제거합니다.
- 만약 사용자가 프로세스를 취소하는 UI 옵션을 사용하면,
-
각각의 authenticator에 대해 issuedRequests에서 authenticatorCancel을 호출하고 제거합니다. 그런 다음 "
NotAllowedError"DOMException을 던집니다. - 만약
options.이 존재하고 중단(aborted) 상태이면,signal -
각 authenticator를 issuedRequests에서 대상으로 하여 authenticatorCancel 작업을 authenticator에 수행하고, 제거 authenticator를 issuedRequests에서 합니다. 그런 다음
options.의 중단 사유를 throw 합니다.signal - 만약
options.이mediationconditional이고 사용자가input또는textarea폼 컨트롤과 상호작용하고 해당 폼 컨트롤의autocomplete속성의 non-autofill credential type이"webauthn"인 경우, -
참고:
"webauthn"autofill detail token은 반드시 "Normal" 또는 "Contact" 형식의 마지막 autofill detail token 바로 뒤에 나타나야 합니다. 예를 들어:-
"username webauthn" -
"current-password webauthn"
-
만약 silentlyDiscoveredCredentials가 비어 있지 않다면(not empty):
-
silentlyDiscoveredCredentials에서 DiscoverableCredentialMetadata을 사용자가 선택하도록 선택적으로 안내합니다. 프롬프트는 각 DiscoverableCredentialMetadata의 otherUI 값(예:
name및displayName)을 표시해야 합니다.사용자가 선택한 경우, credentialMetadata를 선택된 DiscoverableCredentialMetadata로 둡니다.
-
만약 사용자가 credentialMetadata를 선택하면,
-
publicKeyOptions를 pkOptions의 임시 복사본으로 둡니다.
-
authenticator를 silentlyDiscoveredCredentials[credentialMetadata]의 값으로 둡니다.
-
publicKeyOptions.를 단일 항목을 포함하는 list로 설정합니다. 그 단일allowCredentialsPublicKeyCredentialDescriptor항목의id값은 credentialMetadata의 id 값으로 설정하고, 해당 항목의id값은 credentialMetadata의 type으로 설정합니다. -
issuing a credential request to an authenticator 알고리즘을 authenticator, savedCredentialIds, publicKeyOptions, rpId, clientDataHash, 및 authenticatorExtensions를 인수로 실행합니다.
만약 이것이
false를 반환하면 계속합니다. -
Append authenticator를 issuedRequests에 추가합니다.
-
-
-
- 만약
options.이mediationconditional이 아니고, issuedRequests가 비어 있으며,pkOptions.가 비어 있지 않고, 거기서 어떤 authenticator도 사용 가능해지지 않을 것이라면,allowCredentials -
사용자에게 적합한 자격 증명을 찾을 수 없음을 알립니다. 사용자가 대화 상자를 확인하면 "
NotAllowedError"DOMException을 던집니다.참고: 한 가지 방법으로, client platform은 현재
pkOptions.의 각allowCredentialsPublicKeyCredentialDescriptor항목의transports멤버를 검사하여 어떤 authenticator도 더 이상 사용 가능해지지 않을 것임을 판단할 수 있습니다. 예를 들어 모든항목이PublicKeyCredentialDescriptor만을 나열하지만 모든 플랫폼 authenticator를 이미 시도해 보았다면, 요청을 충족할 가능성이 없습니다. 또는 모든 항목이 클라이언트 플랫폼이 지원하지 않는 전송을 나열할 수도 있습니다.internal - 만약 authenticator가 이 client device에서 사용 가능해지면,
-
참고: 여기에는 lifetimeTimer 시작 시 이미 사용 가능했던 경우도 포함됩니다.
-
만약
options.이mediationconditional이고 authenticator가 silentCredentialDiscovery 연산을 지원하면:-
collectedDiscoveredCredentialMetadata를 authenticator에서 silentCredentialDiscovery 연산을 rpId를 인수로 하여 호출한 결과로 둡니다.
-
각각의 credentialMetadata에 대해 collectedDiscoveredCredentialMetadata:
-
-
그렇지 않으면:
-
issuing a credential request to an authenticator 알고리즘을 authenticator, savedCredentialIds, pkOptions, rpId, clientDataHash, 및 authenticatorExtensions를 인수로 실행합니다.
만약 이것이
false를 반환하면 계속합니다.참고: 이 분기는
options.이mediationconditional이고 해당 authenticator가 silentCredentialDiscovery 연산을 지원하지 않아도 conditional user mediation 요청 동안 그런 인증기를 사용하려는 경우에 취해집니다. -
Append authenticator를 issuedRequests에 추가합니다.
-
-
- 만약 authenticator가 이 client device에서 더 이상 사용 가능하지 않게 되면,
-
Remove authenticator를 issuedRequests에서 제거합니다.
- 만약 어떤 authenticator가 사용자 취소 상태를 반환하면,
-
-
Remove 해당 authenticator를 issuedRequests에서 제거합니다.
-
남아 있는 각 authenticator에 대해 authenticatorCancel을 호출하고 제거합니다.
참고: Authenticators는 "사용자가 전체 작업을 취소했다"는 표시를 반환할 수 있습니다. 사용자 에이전트가 이를 사용자에게 어떻게 나타내는지는 명시되지 않습니다.
-
- 만약 어떤 authenticator가 오류 상태를 반환하면,
-
Remove 해당 authenticator를 issuedRequests에서 제거합니다.
- 만약 어떤 authenticator가 성공을 나타내면,
-
-
Remove 해당 authenticator를 issuedRequests에서 제거합니다.
-
assertionCreationData를 다음 항목을 가진 struct으로 둡니다:
-
credentialIdResult -
만약
savedCredentialIds[authenticator]가 존재하면, credentialIdResult의 값을 해당 바이트로 설정합니다. 그렇지 않으면, 성공한 authenticatorGetAssertion 연산에서 반환된 credential ID의 바이트로 설정합니다. -
clientDataJSONResult -
그 값은 clientDataJSON의 바이트입니다.
-
authenticatorDataResult -
그 값은 authenticator data의 바이트로, 해당 authenticator가 반환한 값입니다.
-
signatureResult -
그 값은 authenticator가 반환한 서명 값의 바이트입니다.
-
userHandleResult -
만약 authenticator가 user handle을 반환했다면, userHandleResult의 값을 반환된 user handle의 바이트로 설정합니다. 그렇지 않으면 해당 값을 null로 설정합니다.
-
clientExtensionResults -
그 값은
AuthenticationExtensionsClientOutputs객체로, 각 확장의 extension identifier → client extension output 항목들을 포함합니다. 이러한 항목들은pkOptions.에 있는 각 클라이언트 확장에 대해 그 확장의 client extension processing 알고리즘을 실행하여 생성됩니다.extensions
-
-
만약 credentialIdFilter가 비어 있지 않고(is not empty) credentialIdFilter가 credentialIdResult의 값과 일치하는
id항목을 포함하지 않으면 계속합니다. -
만약 credentialIdFilter가 비어 있고(is empty) userHandleResult가 null이면 계속합니다.
-
settings를 current settings object로 둡니다. global을 settings의 global object로 둡니다.
-
pubKeyCred를 global과 연관된 새
PublicKeyCredential객체로 만들고 그 필드는 다음과 같습니다:[[identifier]]-
global의 %ArrayBuffer%를 사용하여 생성된 새
ArrayBuffer로 assertionCreationData.credentialIdResult의 바이트를 포함합니다. authenticatorAttachment-
해당 authenticator의 현재 authenticator attachment modality에 일치하는
AuthenticatorAttachment값입니다. response-
global과 연관된 새
AuthenticatorAssertionResponse객체로 그 필드는 다음과 같습니다:clientDataJSON-
global의 %ArrayBuffer%를 사용하여 생성된 새
ArrayBuffer로 assertionCreationData.clientDataJSONResult의 바이트를 포함합니다. authenticatorData-
global의 %ArrayBuffer%를 사용하여 생성된 새
ArrayBuffer로 assertionCreationData.authenticatorDataResult의 바이트를 포함합니다. signature-
global의 %ArrayBuffer%를 사용하여 생성된 새
ArrayBuffer로 assertionCreationData.signatureResult의 바이트를 포함합니다. userHandle-
만약
assertionCreationData.userHandleResult가 null이면 이 필드를 null로 설정합니다. 그렇지 않으면, global의 %ArrayBuffer%를 사용하여 생성된 새ArrayBuffer로 assertionCreationData.userHandleResult의 바이트를 포함합니다.
[[clientExtensionsResults]]-
global의 %ArrayBuffer%를 사용하여 생성된 새
ArrayBuffer로 assertionCreationData.clientExtensionResults의 바이트를 포함합니다.
-
남아 있는 각 authenticator에 대해 authenticatorCancel을 호출하고 issuedRequests에서 제거합니다.
-
pubKeyCred를 반환하고 이 알고리즘을 종료합니다.
-
-
"
NotAllowedError"DOMException을 던집니다.
5.1.4.2. 인증기에게 자격 증명 요청 발행
이 [[DiscoverFromExternalSource]](origin, options, sameOriginWithAncestors)의
하위 알고리즘은 주어진 credential을 주어진 authenticator에 요청하기 위해 필요한, UI 문맥에 독립적인 구체적인 단계를 포괄합니다. 이 알고리즘은 [[DiscoverFromExternalSource]](origin, options, sameOriginWithAncestors)에서
현재의 user mediation 유형(예: conditional
mediation 등)에 따라 여러 지점에서 호출됩니다.
이 알고리즘은 다음 인수들을 받습니다:
authenticator-
이 값은 이 client platform에 현재 연결된 authenticator를 식별하는 플랫폼별 핸들입니다.
savedCredentialIds-
이 인수는 map이며, authenticator → credential ID를 포함합니다. 이 알고리즘에서 이 인수는 수정됩니다.
pkOptions-
이 인수는
PublicKeyCredentialRequestOptions객체로, 검색할 public key credential의 원하는 속성을 지정합니다. rpId-
요청의 RP ID입니다.
clientDataHash-
clientDataJSON로 표현된 직렬화된 클라이언트 데이터의 해시입니다.
authenticatorExtensions-
이 인수는 map이며, extension identifiers를 키로 하고 base64url 인코딩된 client extension processing 결과(인증기 확장용)를 값으로 가집니다.
이 알고리즘은 authenticator가 요청을 처리할 수 없다고 client가 판단하면 false를 반환하고, 요청이 성공적으로 발행되면 true를
반환합니다.
인증기에게 자격 증명 요청을 발행하는 단계는 다음과 같습니다:
-
만약
pkOptions.가userVerificationrequired로 설정되어 있고 authenticator가 user verification을 수행할 수 없다면,false를 반환합니다. -
userVerification를 어설션에 대한 유효한 user verification 요구사항인 불리언 값으로 둡니다. 만약
pkOptions.이userVerification- 가
required로 설정된 경우 -
userVerification를
true로 둡니다. - 가
preferred로 설정된 경우 -
만약 해당 authenticator가
- user verification을 수행할 수 있다면
-
userVerification를
true로 둡니다. - user verification을 수행할 수 없다면
-
userVerification를
false로 둡니다.
- 가
discouraged로 설정된 경우 -
userVerification를
false로 둡니다.
- 가
-
만약
pkOptions.allowCredentials- 비어있지 않다면
-
-
allowCredentialDescriptorList를 새 list로 둡니다.
-
client platform별 절차를 실행하여,
pkOptions.에 기술된 어떤 public key credentials이 이 authenticator에 bound되어 있는지를 rpId와 각 항목의allowCredentialsid,type과 대조하여 판단합니다. 그 필터링된 리스트를 allowCredentialDescriptorList로 설정합니다. -
만약 allowCredentialDescriptorList가 비어있다면,
false를 반환합니다. -
distinctTransports를 새 ordered set으로 둡니다.
-
만약 allowCredentialDescriptorList에 정확히 하나의 값이 있으면,
savedCredentialIds[authenticator]를allowCredentialDescriptorList[0].id의 값으로 설정합니다(자세한 내용은 여기와 § 6.3.3 The authenticatorGetAssertion Operation를 참조하세요). -
각각의 자격 증명 디스크립터 C에 대해 각 항목의
C.값을 distinctTransports에 추가합니다(있는 경우).transports참고: 이는 ordered set의 성질에 따라 distinctTransports에 중복 없이 전송 값들만 집계하게 됩니다.
-
만약 distinctTransports가
- 비어있지 않다면
-
클라이언트는 distinctTransports에서 하나의 transport 값을 선택합니다. 이 선택은 해당 authenticator에 적합한 전송 수단에 대한 로컬 구성 지식을 반영할 수 있습니다.
그런 다음, 선택된 transport를 사용하여 authenticator에 대해 authenticatorGetAssertion 연산을 rpId, clientDataHash, allowCredentialDescriptorList, userVerification, 및 authenticatorExtensions를 인수로 호출합니다.
- 비어있다면
-
해당 authenticator에 적합한 전송 수단에 대한 로컬 구성 지식을 사용하여, authenticatorGetAssertion 연산을 authenticator에 대해 rpId, clientDataHash, allowCredentialDescriptorList, userVerification, 및 authenticatorExtensions를 인수로 호출합니다.
-
- 비어 있음
-
해당 authenticator에 적합한 전송 수단에 대한 로컬 구성 지식을 사용하여, authenticatorGetAssertion 연산을 authenticator에 대해 rpId, clientDataHash, userVerification, 및 authenticatorExtensions를 인수로 호출합니다.
참고: 이 경우에는 Relying Party가 허용 가능한 자격 증명 디스크립터 목록을 제공하지 않았으므로, 인증기는 rpId로 식별되는 범위(scope)에 해당하는 어떤 자격 증명이든 사용하도록 요청받는 것입니다.
-
true를 반환합니다.
5.1.4.3. 요청 예외 처리
이 절은 규범적이지 않습니다.
WebAuthn Relying
Parties는 navigator.credentials.get()
호출에서 여러 예외를 만날 수 있습니다. 일부 예외는 발생 원인이 여러 개인 경우가 있어, WebAuthn Relying Parties가 WebAuthn 사용 상황을 바탕으로 실제 원인을 추론해야 할 수
있습니다.
Note: 이 명세 외부에서 정의된 것을 포함하여 모든 WebAuthn Extensions의 처리 중 발생할 수 있는 예외는 여기에는 나열되지 않습니다.
다음의 DOMException
예외들이 발생할 수 있습니다:
AbortError-
절차가
AbortController에 의해 취소되었습니다. 자세한 내용은 § 5.6 Abort Operations with AbortSignal 및 § 1.3.4 Aborting Authentication Operations를 참조하세요. SecurityError-
effective domain이 유효한 domain이 아니거나, 또는
가 effective domain과 같거나 그 등록 가능한 도메인 접미사가 아닌 경우입니다. 후자의 경우, 클라이언트는 related origin requests를 지원하지 않거나 related origins validation procedure가 실패한 것입니다.rp.id NotAllowedError-
사용자가 절차를 취소하는 등 다양한 가능한 원인을 포괄하는 포괄적 오류입니다. 이러한 원인들 중 일부는 이 명세 전반에 문서화되어 있으며, 다른 것들은 클라이언트 특유의 원인일 수 있습니다.
다음의 단순 예외들도 발생할 수 있습니다:
TypeError-
options인수가 유효한CredentialRequestOptions값이 아니었을 경우 발생합니다.
5.1.5. 기존 자격 증명 저장 - PublicKeyCredential의
[[Store]](credential, sameOriginWithAncestors) 내부 메서드
[[Store]](credential, sameOriginWithAncestors)
메서드는 Web Authentication의 PublicKeyCredential
타입에 대해 지원되지 않으므로, [[Store]](credential, sameOriginWithAncestors)
내부 메서드는 항상 오류를 던집니다.
Note: 이 알고리즘은 동기적이며; Promise
의 해결/거절 처리는 navigator.credentials.store()에서
이루어집니다.
이 내부 메서드는 두 개의 인수를 받습니다:
credential-
이 인수는
PublicKeyCredential객체입니다. sameOriginWithAncestors-
이 인수는 Boolean 값으로, 호출자의 environment settings object가 조상들과 same-origin인지에 따라
true가 됩니다.
이 메서드가 호출되면 사용자 에이전트는 다음 알고리즘을 반드시 실행해야 합니다:
-
"
NotSupportedError"DOMException을 던집니다.
5.1.6. User-Verifying Platform Authenticator의 가용성 -
PublicKeyCredential의 isUserVerifyingPlatformAuthenticatorAvailable() 메서드
WebAuthn
Relying Parties는 이 메서드를 사용하여 user-verifying platform authenticator를 사용해 새
자격 증명을 생성할 수 있는지 판단합니다. 호출 시 client는 client
platform별 절차를 사용해 사용 가능한 user-verifying platform authenticators을
검색합니다. 하나라도 발견되면 프라미스는 true로 해결되고, 그렇지 않으면 false로 해결됩니다. 결과에 따라 Relying Party는 사용자에게 자격
증명 생성 유도 등 추가 동작을 취할 수 있습니다.
이 메서드는 인수가 없으며 불리언 값을 반환합니다.
partial interface PublicKeyCredential {static Promise <boolean >(); };isUserVerifyingPlatformAuthenticatorAvailable
Note: 이 메서드를 browsing context에서 호출했을 때 해당 컨텍스트가 Web Authentication API에 대해
"사용 금지(disabled)"로 판단되면(예: allowed to use 알고리즘에 의해), 프라미스는 이름이 "NotAllowedError"인
DOMException으로
거절됩니다. 자세한 내용은 § 5.9 Permissions Policy integration을 참조하세요.
5.1.7.
클라이언트 기능의 가용성 - PublicKeyCredential의 getClientCapabilities()
메서드
WebAuthn
Relying Parties는 이 메서드를 사용하여 일부 워크플로우나 사용자 경험을 제공하기 위한 제한된 클라이언트 기능들의 가용성을 판단할 수 있습니다. 예를 들어,
RP는 클라이언트에서 오직 hybrid
전송만 이용 가능하거나 conditional
mediation이 불가능한 경우에만 표시되는 로그인 버튼을 제공할 수 있습니다(대신 사용자명 필드를 표시하는 대신).
호출 시 client는 client platform별 절차를 사용하여 이러한 기능들의 가용성을 검색합니다.
이 메서드는 인수가 없고, 기능 키를 불리언 값으로 매핑한 레코드를 반환합니다.
partial interface PublicKeyCredential {static Promise <PublicKeyCredentialClientCapabilities >(); };getClientCapabilities typedef record <DOMString ,boolean >;PublicKeyCredentialClientCapabilities
Keys는 PublicKeyCredentialClientCapabilities에서
사전식(오름차순)으로 정렬되어야 합니다.
키 집합은 ClientCapability의
열거값 집합을 포함하는 것이 좋지만, 클라이언트는 필요에 따라 키를 생략할 수 있습니다; 자세한 내용은 § 14.5.4 Disclosing Client Capabilities를 참조하세요.
특정 기능의 값이 true이면 그 기능이 현재 클라이언트에서 지원되는 것으로 알려진 것입니다. 값이 false이면 현재 지원되지 않는 것으로
알려진 것입니다. 어떤 키가 존재하지 않으면 해당 클라이언트 기능의 가용성은 알려지지 않은 것입니다.
키 집합은 또한 클라이언트가 구현한 각 확장에 대해 접두사로 문자열 extension:를 붙인 키를 포함하는
것이 권장됩니다. 해당 구현된 확장에 대한 값은 true여야 합니다. 만약 getClientCapabilities()가 클라이언트에서
지원되지만 어떤 확장이 true로 매핑되지 않았다면, Relying Party는 그 확장에 대한 클라이언트 처리 단계가 수행되지 않을 것이며, 확장이 인증기로 전달되지 않을
수 있다고 가정할 수 있습니다.
확장이 true로 매핑되어 있더라도, 특정 연산에 사용되는 인증기가 그 확장을 지원하지 않을 수 있으므로, Relying Parties는 인증기에서 그 확장의 처리가 수행될 것이라고
가정해서는 안 됩니다.
Note: 이 메서드를 browsing context에서 호출했을 때 해당 컨텍스트가 Web Authentication API에 대해
"사용 금지(disabled)"로 판단되면(예: allowed to use 알고리즘에 의해), 프라미스는 이름이 "NotAllowedError"인
DOMException으로
거절됩니다. 자세한 내용은 § 5.9 Permissions Policy integration을 참조하세요.
5.1.8.
등록 절차 옵션 역직렬화 - PublicKeyCredential의
parseCreationOptionsFromJSON() 메서드
WebAuthn
Relying Parties는 이 메서드를 사용하여 JSON 타입으로 표현된
navigator.credentials.create()의
옵션들을 PublicKeyCredentialCreationOptions로
변환합니다.
호출 시 client는 options
인수를 새롭고 동일한 구조의 PublicKeyCredentialCreationOptions
객체로 변환해야 하며, base64url 인코딩을 사용하여 DOMString
속성들을 디코딩해야 합니다. 이 변환은 client extension inputs에 대해서도 적용되어야 합니다.
AuthenticationExtensionsClientInputsJSON
은 IANA "WebAuthn Extension Identifiers" 레지스트리에 등록된 확장들을 포함할 수 있으나, § 9
WebAuthn Extensions에 정의되지 않은 확장들도 허용될 수 있습니다.
만약 client가 JSON 타입 표현을 파싱하는 중에 문제가 발생하면,
호환되지 않는 값에 대한 설명을 포함한 "EncodingError"
DOMException을
던지고 연산을 종료해야 합니다.
partial interface PublicKeyCredential {static PublicKeyCredentialCreationOptions (parseCreationOptionsFromJSON PublicKeyCredentialCreationOptionsJSON ); };options dictionary {PublicKeyCredentialCreationOptionsJSON required PublicKeyCredentialRpEntity ;rp required PublicKeyCredentialUserEntityJSON ;user required Base64URLString ;challenge required sequence <PublicKeyCredentialParameters >;pubKeyCredParams unsigned long ;timeout sequence <PublicKeyCredentialDescriptorJSON >= [];excludeCredentials AuthenticatorSelectionCriteria ;authenticatorSelection sequence <DOMString >= [];hints DOMString = "none";attestation sequence <DOMString >= [];attestationFormats AuthenticationExtensionsClientInputsJSON ; };extensions dictionary {PublicKeyCredentialUserEntityJSON required Base64URLString ;id required DOMString ;name required DOMString ; };displayName dictionary {PublicKeyCredentialDescriptorJSON required DOMString ;type required Base64URLString ;id sequence <DOMString >; };transports dictionary { };AuthenticationExtensionsClientInputsJSON
5.1.9.
인증 절차 옵션 역직렬화 - PublicKeyCredential의 parseRequestOptionsFromJSON()
메서드들
WebAuthn
Relying Parties는 이 메서드를 사용하여 JSON 타입으로 표현된
navigator.credentials.get()의
옵션들을 PublicKeyCredentialRequestOptions로
변환합니다.
호출 시 client는 options
인수를 새롭고 동일한 구조의 PublicKeyCredentialRequestOptions
객체로 변환해야 하며, base64url 인코딩을 사용해 DOMString
속성들을 디코딩해야 합니다. 이 변환은 client extension inputs에도 적용되어야 합니다.
AuthenticationExtensionsClientInputsJSON
은 IANA "WebAuthn Extension Identifiers" 레지스트리에 등록된 확장들을 포함할 수 있으나, § 9
WebAuthn Extensions에 정의되지 않은 확장들도 허용될 수 있습니다.
만약 client가 JSON 타입 표현을 파싱하는 중 문제를 만나면,
호환되지 않는 값에 대한 설명을 포함한 "EncodingError"
DOMException을
던지고 연산을 종료해야 합니다.
partial interface PublicKeyCredential {static PublicKeyCredentialRequestOptions (parseRequestOptionsFromJSON PublicKeyCredentialRequestOptionsJSON ); };options dictionary {PublicKeyCredentialRequestOptionsJSON required Base64URLString ;challenge unsigned long ;timeout DOMString ;rpId sequence <PublicKeyCredentialDescriptorJSON >= [];allowCredentials DOMString = "preferred";userVerification sequence <DOMString >= [];hints AuthenticationExtensionsClientInputsJSON ; };extensions
5.1.10. 인증기에게 자격 증명 변경 신호 전송 - PublicKeyCredential의 signal methods
partial interface PublicKeyCredential {static Promise <undefined >(signalUnknownCredential UnknownCredentialOptions );options static Promise <undefined >(signalAllAcceptedCredentials AllAcceptedCredentialsOptions );options static Promise <undefined >(signalCurrentUserDetails CurrentUserDetailsOptions ); };options dictionary {UnknownCredentialOptions required DOMString ;rpId required Base64URLString ; };credentialId dictionary {AllAcceptedCredentialsOptions required DOMString ;rpId required Base64URLString ;userId required sequence <Base64URLString >; };allAcceptedCredentialIds dictionary {CurrentUserDetailsOptions required DOMString ;rpId required Base64URLString ;userId required DOMString ;name required DOMString ; };displayName
WebAuthn Relying
Parties는 이러한 signal
methods를 사용하여 authenticators에게 public key credentials의 상태를 알릴 수 있으며, 이를 통해 잘못되었거나 폐기된 자격 증명을
업데이트, 제거 또는 숨기도록 할 수 있습니다. Clients는 인증기가
자신의 credentials map을 업데이트할 수 없거나 요청 시점에 연결되어 있지 않을 수 있으므로 이
기능을 기회에 따라 제공할 수 있습니다. 또한 사용자의 동의 없이 사용자의 자격 증명에 관한 정보를 노출하는 것을 피하기 위해, signal methods는 연산의 성공 여부를 나타내지 않습니다. 성공적으로 해결된
프라미스는 단지 options 객체가 올바르게 구성되었음을 의미할 뿐입니다.
각 signal method는 authenticator actions를 포함합니다. Authenticators는 권고된 대로 하지 않고 자체적으로 authenticator actions에서 벗어날 수 있습니다(예: 사용자의 의사에 반한다고 합리적으로 판단되는 변경을 무시하거나, 일부 변경에 대해 사용자에게 확인을 요청하는 등). 따라서 Authenticator actions는 signal methods를 처리하는 권장 방식으로 제공됩니다.
만약 어떤 authenticator가 특정 authenticator action을 처리할 능력이 없다면, clients는 동등한 효과를 달성하기 위해 [FIDO-CTAP]의
authenticatorCredentialManagement 명령과 같은 기존 인프라를 사용할 수 있습니다.
Note: Signal methods는 의도적으로 authenticators가 authenticator actions를 완료할 때까지 기다리지 않습니다. 이 조치는 요청 시간에 따른 응답 타이밍으로 사용자의 자격 증명 가용성에 관한 정보를 사용자 동의 없이 WebAuthn Relying Parties가 얻는 것을 방지합니다.
5.1.10.1. 비동기 RP ID 검증 알고리즘
비동기 RP ID 검증 알고리즘은 signal methods가 RP IDs를 병렬로 검증할 수 있게 합니다. 이 알고리즘은 DOMString
rpId를 입력으로 받고, 검증이 실패하면 거절되는 프라미스를 반환합니다. 단계는 다음과 같습니다:
-
effectiveDomain을 relevant settings object의 origin의 effective domain으로 둡니다. 만약 effectiveDomain이 유효한 domain이 아니면 "
SecurityError"DOMException로 거절된 프라미스를 반환합니다. -
만약 rpId가 effectiveDomain의 registrable domain suffix이거나 같다면, undefined로 해결된 프라미스를 반환합니다.
-
만약 클라이언트가 related origin requests를 지원하지 않으면 "
SecurityError"DOMException로 거절된 프라미스를 반환합니다. -
p를 새 프라미스로 둡니다.
-
다음 단계들을 병렬로 실행합니다:
-
만약 related origins validation procedure를 callerOrigin과 rpId로 실행한 결과가
true이면, p를 resolve 합니다. -
그렇지 않으면, p를 "
SecurityError"DOMException로 reject 합니다.
-
-
p를 반환합니다.
5.1.10.2. signalUnknownCredential(options)
signalUnknownCredential
메서드는 특정 credential id가
WebAuthn Relying Party에 의해 인식되지 않았음을(예: 사용자가 삭제했음) 알리는 용도입니다. signalAllAcceptedCredentials(options)와
달리, 이 메서드는 전체 수락된 credential
IDs 목록 및 userHandle를 전달할 필요가 없으므로, 인증되지 않은 호출자에게 프라이버시
유출을 피합니다(자세한 내용은 § 14.6.3 Privacy leak via credential IDs
참조).
signalUnknownCredential(options)
호출 시 client는 다음 단계를 실행합니다:
-
만약 base64url 디코딩 결과
options.가 오류이면, "credentialIdTypeError"로 거절된 프라미스를 반환합니다. -
p를 비동기 RP ID 검증 알고리즘을
options.로 실행한 결과로 둡니다.rpId -
프라미스 p가 이행되면, 다음 단계들을 병렬로 실행합니다:
-
현재 이 client platform에서 사용 가능한 모든 authenticator에 대해, unknownCredentialId authenticator action을 options를 입력으로 하여 호출합니다.
-
-
p를 반환합니다.
unknownCredentialId authenticator action은 UnknownCredentialOptions
options를 받아 다음과 같이 동작합니다:
-
각각의 해당 public key credential source credential에 대해, 그 authenticator의 credential map을 순회합니다:
-
만약 credential의 rpId가
options.와 같고, credential의 id가 base64url 디코딩한rpIdoptions.와 같다면, credential을 credentials map에서 제거하거나, 인증기별 절차를 사용해 이후의 authentication ceremonies에서 숨기도록 합니다.credentialId
-
사용자가 WebAuthn Relying Party가 제공하는 UI에서 credential을 삭제합니다. 이후 WebAuthn Relying Party에
로그인하려 시도할 때, 빈 allowCredentials가
제공되면, authenticator UI는
사용자가 이전에 삭제한 자격 증명을 제안할 수 있습니다. 사용자가 그 자격 증명을 선택하고 로그인 시도가 거부된 후, WebAuthn Relying Party는 다음을 실행합니다:
PublicKeyCredential. signalUnknownCredential({ rpId: "example.com" , credentialId: "aabbcc" // 사용자가 방금 시도한 credential id, base64url });
그 후 authenticator는 해당 credential을 삭제하거나 이후 인증 절차에서 숨깁니다.
5.1.10.3. signalAllAcceptedCredentials(options)
특정 사용자의 전체 credential ids 목록을
신호합니다. WebAuthn
Relying Parties는 사용자가 인증된 상태이므로 프라이버시 유출 위험이 없는 경우(자세한 내용은 § 14.6.3 Privacy leak via credential IDs 참조) 이 메서드를 signalUnknownCredential()보다
선호해야 합니다. 전체 목록은 사용자의 public key credentials의 전체 스냅샷을 제공하며, 현재 연결된 인증기에 아직 보고되지 않은 변경 사항을 반영할 수 있습니다.
signalAllAcceptedCredentials(options)
호출 시 client는 다음 단계를 실행합니다:
-
만약 base64url 디코딩 결과
options.가 오류이면, "userIdTypeError"로 거절된 프라미스를 반환합니다. -
각각의 credentialId에 대해
options.:allAcceptedCredentialIds-
만약 base64url 디코딩 결과 credentialId가 오류이면, "
TypeError"로 거절된 프라미스를 반환합니다.
-
-
p를 비동기 RP ID 검증 알고리즘을
options.로 실행한 결과로 둡니다.rpId -
프라미스 p가 이행되면, 다음 단계들을 병렬로 실행합니다:
-
현재 이 client platform에서 사용 가능한 모든 authenticator에 대해, allAcceptedCredentialIds authenticator action을 options를 입력으로 하여 호출합니다.
-
-
p를 반환합니다.
allAcceptedCredentialIds authenticator actions는 AllAcceptedCredentialsOptions
options를 입력으로 받아 다음과 같이 동작합니다:
-
userId를 base64url 디코딩한
options.의 결과로 둡니다.userId -
단언: userId가 오류가 아님을 보장합니다.
-
credential를
credentials map[options.로 둡니다.rpId, userId] -
만약 credential가 존재하지 않으면 이 단계를 중단합니다.
-
만약
options.가 포함하지 않는다면, credential을 credentials map에서 제거하거나 인증기별 절차를 사용해 이후 인증 절차에서 숨깁니다.allAcceptedCredentialIds -
그렇지 않고, 만약 credential이 인증기별 절차로 이미 숨겨져 있다면, 그 조치를 되돌려 credential이 이후의 인증 절차에서 나타나도록 합니다.
사용자는 두 개의 credential ids(credential ids)를 가지고 있으며, 이들이 base64url로 인코딩되면 aa와
bb가 됩니다. 사용자가 credential aa를 WebAuthn Relying Party 제공 UI에서 삭제하면, Relying
Party는 다음을 실행합니다:
PublicKeyCredential. signalAllAcceptedCredentials({ rpId: "example.com" , userId: "aabbcc" , // user handle, base64url. allAcceptedCredentialIds: [ "bb" , ] });
실행 시 인증기(authenticator)가
연결되어 있으면, 해당 인증기는 aa에 해당하는 public key credential을 이후 인증 절차에서 삭제하거나 숨깁니다.
Note: 인증기들은 signalAllAcceptedCredentials(options)가
실행될 때 연결되어 있지 않을 수 있습니다. 따라서 WebAuthn Relying Parties는 예를 들어 매번 로그인 시마다 주기적으로 signalAllAcceptedCredentials(options)를
실행하는 것을 선택할 수 있습니다.
Note: allAcceptedCredentialIds에
포함되지 않은 자격 증명은 제거되거나 숨겨져 복구 불가능할 수 있습니다. Relying parties는 유효한 credential IDs가 목록에서 누락되지 않도록 주의해야 합니다. 만약 실수로
유효한 credential ID가 누락되었다면,
가능한 한 빨리 signalAllAcceptedCredentials(options)에
포함시켜(인증기가 지원하면) 다시 표시되게 해야 합니다.
Authenticators는 가능하면 자격 증명을 영구적으로 삭제하기보다는 일정 기간 숨기는 것을 권장합니다. 이는 Relying Party가 실수로 유효한 credential IDs를 목록에서 누락했을 때 복구에 도움이 됩니다.
5.1.10.4. signalCurrentUserDetails(options)
signalCurrentUserDetails
메서드는 사용자의 현재 name
및 displayName을
신호합니다.
signalCurrentUserDetails(options)
호출 시 client는 다음 단계를 실행합니다:
-
만약 base64url 디코딩 결과
options.가 오류이면, "userIdTypeError"로 거절된 프라미스를 반환합니다. -
p를 비동기 RP ID 검증 알고리즘을
options.로 실행한 결과로 둡니다.rpId -
프라미스 p가 이행되면, 다음 단계들을 병렬로 실행합니다:
-
현재 이 client platform에서 사용 가능한 모든 authenticator에 대해, currentUserDetails authenticator action을 options를 입력으로 하여 호출합니다.
-
-
p를 반환합니다.
currentUserDetails authenticator action은 CurrentUserDetailsOptions
options를 입력으로 받아 다음과 같이 동작합니다:
-
userId를 base64url 디코딩한
options.의 결과로 둡니다.userId -
단언: userId가 오류가 아님을 보장합니다.
-
credential를
credentials map[options.로 둡니다.rpId, userId] -
만약 credential가 존재하지 않으면 이 단계를 중단합니다.
-
credential의 otherUI를
options.및nameoptions.에 맞게 업데이트합니다.displayName
사용자가 WebAuthn Relying Party 제공 UI에서 자신의 이름을 업데이트합니다. Relying Party는 다음을 실행합니다:
PublicKeyCredential. signalCurrentUserDetails({ rpId: "example.com" , userId: "aabbcc" , // user handle, base64url. name: "New user name" , displayName: "New display name" });
그 후 authenticator는 일치하는 자격 증명의 otherUI를 업데이트합니다.
Note: 인증기들은 signalCurrentUserDetails(options)가
실행될 때 연결되어 있지 않을 수 있습니다. 따라서 WebAuthn Relying Parties는 예를 들어 매번 로그인 시마다 주기적으로 signalCurrentUserDetails(options)를
실행하는 것을 선택할 수 있습니다.
5.2.
Authenticator Responses (interface AuthenticatorResponse)
Authenticators는 Relying Party의 요청에 응답할 때
AuthenticatorResponse
인터페이스에서 파생된 객체를 반환합니다:
[SecureContext ,Exposed =Window ]interface AuthenticatorResponse { [SameObject ]readonly attribute ArrayBuffer clientDataJSON ; };
clientDataJSON, of type ArrayBuffer, readonly-
이 속성은 JSON-호환 직렬화된 client data를 포함하며, 그 해시가 클라이언트에 의해
create()또는get()호출에서 인증기로 전달된다는 점에 유의해야 합니다(즉, client data 자체는 인증기로 전송되지 않습니다).
5.2.1. Information About Public Key Credential (interface
AuthenticatorAttestationResponse)
The AuthenticatorAttestationResponse
인터페이스는 새 public
key credential 생성을 위한 클라이언트의 요청에 대한
authenticator의 응답을 나타냅니다. 이
응답은 이후에 자격 증명을 식별하는 데 사용할 수 있는 새 자격 증명에 관한 정보와, 등록 시 WebAuthn Relying Party가 자격 증명의 특성을 평가하는 데 사용할 수 있는 메타데이터를
포함합니다.
[SecureContext ,Exposed =Window ]interface AuthenticatorAttestationResponse :AuthenticatorResponse { [SameObject ]readonly attribute ArrayBuffer attestationObject ;sequence <DOMString >();getTransports ArrayBuffer ();getAuthenticatorData ArrayBuffer ?();getPublicKey COSEAlgorithmIdentifier (); };getPublicKeyAlgorithm
clientDataJSON-
이 속성은
AuthenticatorResponse로부터 상속되며, 인증기를 생성된 자격 증명에 대해 호출하도록 만든 클라이언트에서 전달한 JSON-호환 직렬화된 client data를 포함합니다(자세한 내용은 § 6.5 Attestation 참조). 정확한 JSON 직렬화는 보존되어야 하며, 이는 직렬화된 클라이언트 데이터의 해시가 해당 직렬화에 대해 계산되었기 때문입니다. attestationObject, of type ArrayBuffer, readonly-
이 속성은 attestation object를 포함합니다. 이 객체는 클라이언트에게는 불투명하며, 클라이언트로부터 변조되지 않도록 암호학적으로 보호됩니다. attestation object는 authenticator data와 attestation statement를 모두 포함합니다. 전자는 AAGUID, 고유한 credential ID 및 credential public key를 포함합니다. attestation statement의 내용은 인증기가 사용하는 attestation statement format에 의해 결정됩니다. 또한 Relying Party의 서버가 attestation statement를 검증하고 authenticator data와 JSON-호환 직렬화된 client data를 디코드하여 검증하는 데 필요한 추가 정보를 포함할 수 있습니다. 자세한 내용은 § 6.5 Attestation, § 6.5.4 Generating an Attestation Object, 및 Figure 6를 참조하세요.
getTransports()-
이 연산은
[[transports]]의 값을 반환합니다. getAuthenticatorData()-
이 연산은
attestationObject에 포함된 authenticator data를 반환합니다. 자세한 내용은 § 5.2.1.1 Easily accessing credential data를 참조하세요. getPublicKey()-
이 연산은 새 자격 증명의 DER 형식 SubjectPublicKeyInfo를 반환하거나, 제공할 수 없는 경우 null을 반환합니다. 자세한 내용은 § 5.2.1.1 Easily accessing credential data를 참조하세요.
getPublicKeyAlgorithm()-
이 연산은 새 자격 증명의
COSEAlgorithmIdentifier를 반환합니다. 자세한 내용은 § 5.2.1.1 Easily accessing credential data를 참조하세요. [[transports]]-
이 internal slot은 사전식 순서로 정렬된 0개 이상의 고유한
DOMString의 시퀀스를 포함합니다. 이 값들은 해당 authenticator가 지원하는 것으로 알려진 전송 수단이며, 정보가 없으면 빈 시퀀스가 됩니다. 값은AuthenticatorTransport의 멤버여야 하지만, Relying Parties는 알 수 없는 값도 수락하고 저장해야 합니다.
5.2.1.1. Easily accessing credential data
모든 [[Create]](origin, options, sameOriginWithAncestors)
메서드 사용자는 반환된 credential public key를 구문 분석하여 저장해야 하며, 이는 향후 authentication assertions을 검증하는 데 필요합니다. 그러나 credential
public key는 COSE 형식으로 되어 있어 attestedCredentialData의
credentialPublicKey 멤버 안의 CBOR 구조입니다. 이것은 authenticator data 안에 있고, attestation object에 포함되어 있고, 이
attestation object는 AuthenticatorAttestationResponse의
attestationObject입니다.
Relying Parties는
attestation을 사용하려면 attestationObject를
구문 분석하고 credential public key를 얻어야 합니다. 이는 인증기가 서명한 공개키 복사본이기 때문입니다.
그러나 많은 유효한 WebAuthn 사용 사례에서는 attestation을 필요로 하지 않습니다. 그런 경우 사용자 에이전트가 구문 분석 작업을 수행하고 authenticator
data를 직접 노출하며 credential public key를 더 편리한 형식으로 변환할 수 있습니다.
따라서 getPublicKey()
연산은 credential
public key를 SubjectPublicKeyInfo로 반환합니다. 이 ArrayBuffer는
예를 들어 Java의 java.security.spec.X509EncodedKeySpec, .NET의
System.Security.Cryptography.ECDsa.ImportSubjectPublicKeyInfo, 또는 Go의
crypto/x509.ParsePKIXPublicKey에 전달할 수 있습니다.
getPublicKey()
사용에는 몇 가지 제한이 있습니다: pubKeyCredParams를
사용하여 Relying Party는 인증기와
협상하여 사용자 에이전트가 이해하지 못할 수 있는 공개키 알고리즘을 사용할 수 있습니다. 그러나 그렇게 하는 경우 사용자 에이전트는 결과 COSE 공개키를 SubjectPublicKeyInfo 형식으로 변환할 수 없으며 getPublicKey()의
반환값은 null이 됩니다.
사용자 에이전트는 getPublicKey()에
대해 null이 아닌 값을 반환할 수 있어야 하며, 그 조건은 credential public key의 COSEAlgorithmIdentifier
값이 다음 중 하나일 때입니다:
-
-257 (RS256).
-
-8 (EdDSA), 여기서 crv는 6 (Ed25519)입니다.
SubjectPublicKeyInfo는 COSE 공개키에 포함된 서명 알고리즘(예: 어떤 해시 함수를 사용할지)에 관한 정보를
포함하지 않습니다. 이를 제공하기 위해 getPublicKeyAlgorithm()
은 해당 credential
public key의 COSEAlgorithmIdentifier를
반환합니다.
많은 경우 CBOR을 전혀 파싱할 필요를 제거하기 위해, getAuthenticatorData()
은 attestationObject에서
authenticator data를
반환합니다. authenticator
data는 다른 필드들을 바이너리 형식으로 인코딩하여 포함하지만, 해당 필드들에 접근하기 위한 헬퍼 함수는 제공되지 않습니다. 왜냐하면 Relying Parties는 어설션을 얻을 때 이미 그런 필드를 추출해야 하기
때문입니다. credential creation과 달리 어설션에서의 서명 검증은 항상 수행되어야 하므로, Relying Parties는 서명된 authenticator data에서 필드를 추출해야 하며, 동일한
함수들이 자격 증명 생성 시에도 사용됩니다.
Relying Parties는 이러한 함수들을
사용하기 전에 기능 감지를 수행하여 'getPublicKey' in AuthenticatorAttestationResponse.prototype의 값을 확인해야 합니다.
Note: getPublicKey()
및 getAuthenticatorData()
는 본 명세의 Level 2에서만 추가되었습니다. 이러한 함수들이 존재해야 하는 Relying Parties는 오래된 사용자 에이전트와 상호운용되지 않을 수 있습니다.
5.2.2. Web Authentication Assertion (interface AuthenticatorAssertionResponse)
The AuthenticatorAssertionResponse
인터페이스는 authenticator가
Relying Party의 challenge 및 선택적 자격 증명 목록을 받고 생성한 새로운 authentication assertion에 대한 응답을 나타냅니다. 이 응답은 credential
private key의 보유를 증명하는 암호화 서명과, 선택적으로 특정 거래에 대한 사용자 동의에 대한 증거를 포함합니다.
[SecureContext ,Exposed =Window ]interface AuthenticatorAssertionResponse :AuthenticatorResponse { [SameObject ]readonly attribute ArrayBuffer authenticatorData ; [SameObject ]readonly attribute ArrayBuffer signature ; [SameObject ]readonly attribute ArrayBuffer ?userHandle ; };
clientDataJSON-
이 속성은
AuthenticatorResponse로부터 상속되며, 인증기를 어설션 생성에 사용하도록 만든 클라이언트에서 전달한 JSON-호환 직렬화된 client data를 포함합니다 (자세한 내용은 § 5.8.1 Client Data Used in WebAuthn Signatures (dictionary CollectedClientData) 참조). 정확한 JSON 직렬화는 보존되어야 하며, 직렬화된 클라이언트 데이터의 해시가 해당 직렬화에 대해 계산되었기 때문입니다. authenticatorData, of type ArrayBuffer, readonly-
이 속성은 인증기가 반환한 authenticator data를 포함합니다. 자세한 내용은 § 6.1 Authenticator Data를 참조하세요.
signature, of type ArrayBuffer, readonly-
이 속성은 인증기에서 반환한 원시 서명을 포함합니다. 자세한 내용은 § 6.3.3 The authenticatorGetAssertion Operation을 참조하세요.
userHandle, of type ArrayBuffer, readonly, nullable-
이 속성은 인증기가 반환한 user handle를 포함하거나, 인증기가 user handle을 반환하지 않으면 null을 가집니다. 자세한 내용은 § 6.3.3 The authenticatorGetAssertion Operation을 참조하세요. 만약 authentication ceremony에서 사용된
allowCredentials옵션이 비어있다면, 인증기는 반드시 user handle을 반환해야 하며, 그 외의 경우에는 반환해도 됩니다.
5.3.
Parameters for Credential Generation (dictionary PublicKeyCredentialParameters)
dictionary PublicKeyCredentialParameters {required DOMString type ;required COSEAlgorithmIdentifier alg ; };
type, of type DOMString-
이 멤버는 생성하려는 자격 증명의 유형을 지정합니다. 값은
PublicKeyCredentialType의 멤버여야 하는 것이 권장되지만, client platforms는 알 수 없는 값을 반드시 무시해야 하며, 알 수 없는PublicKeyCredentialParameters항목은 무시되어야 합니다. alg, of type COSEAlgorithmIdentifier-
이 멤버는 새로 생성될 자격 증명에 사용할 암호화 서명 알고리즘을 지정하며, 따라서 생성될 비대칭 키 쌍의 유형(예: RSA 또는 타원곡선)을 결정합니다.
Note: 우리는 여기서 멤버 이름으로 "algorithm"을 풀어 쓰지 않고 "alg"를 사용하는데, 이는 인증기로 전송될 메시지에 직렬화될 때 저대역폭 링크를 통해 전송될 수 있기 때문입니다.
5.4.
Options for Credential Creation (dictionary PublicKeyCredentialCreationOptions)
dictionary PublicKeyCredentialCreationOptions {required PublicKeyCredentialRpEntity rp ;required PublicKeyCredentialUserEntity user ;required BufferSource challenge ;required sequence <PublicKeyCredentialParameters >pubKeyCredParams ;unsigned long timeout ;sequence <PublicKeyCredentialDescriptor >excludeCredentials = [];AuthenticatorSelectionCriteria authenticatorSelection ;sequence <DOMString >hints = [];DOMString attestation = "none";sequence <DOMString >attestationFormats = [];AuthenticationExtensionsClientInputs extensions ; };
rp, of type PublicKeyCredentialRpEntity-
이 멤버는 요청을 담당하는 Relying Party의 이름과 식별자를 포함합니다.
값의
name멤버는 필수입니다. 자세한 내용은 § 5.4.1 Public Key Entity Description (dictionary PublicKeyCredentialEntity)를 참조하세요.값의
id멤버는 자격 증명이 RP ID에 범위(scope)되어야 함을 지정합니다. 생략하면 해당 값은CredentialsContainer객체의 relevant settings object의 origin의 effective domain이 됩니다. 자세한 내용은 § 5.4.2 Relying Party Parameters for Credential Generation (dictionary PublicKeyCredentialRpEntity)를 참조하세요. user, of type PublicKeyCredentialUserEntity-
이 멤버는 등록을 수행하는 사용자 계정의 이름들과 식별자를 포함합니다.
값의
name,displayName및id멤버는 필수입니다.id는 향후 인증 절차에서userHandle로 반환될 수 있으며, 동일한와rp.id를 가진 discoverable credentials를 덮어쓰는 데 사용됩니다.user.idname및displayName는 인증기 및 클라이언트가 향후 인증 절차에서 사용자를 도울 목적으로 사용할 수 있으나, 향후 인증 절차의 결과로 Relying Party에 반환되지는 않습니다.추가 세부 사항은 § 5.4.1 Public Key Entity Description (dictionary PublicKeyCredentialEntity) 및 § 5.4.3 User Account Parameters for Credential Generation (dictionary PublicKeyCredentialUserEntity)를 참조하세요.
challenge, of type BufferSource-
이 멤버는 새로 생성된 자격 증명에 대한 authenticator가 다른 데이터와 함께 서명하는 challenge를 지정합니다. 보안 고려 사항에 대해서는 § 13.4.3 Cryptographic Challenges를 참조하세요.
pubKeyCredParams, of type sequence<PublicKeyCredentialParameters>-
이 멤버는 Relying Party가 지원하는 키 유형과 서명 알고리즘을 우선순위(가장 선호하는 것에서 덜 선호하는 것 순)로 나열합니다. 중복은 허용되나 사실상 무시됩니다. 클라이언트와 인증기는 가능한 한 가장 선호하는 유형으로 자격 증명을 생성하려고 최선을 다합니다. 나열된 유형 중 어느 것도 생성할 수 없으면
create()연산은 실패합니다.다양한 인증기를 지원하려는 Relying Parties는 적어도 다음
COSEAlgorithmIdentifier값을 포함하는 것이 권장됩니다:-
-8 (Ed25519)
-
-7 (ES256)
-
-257 (RS256)
추가 서명 알고리즘은 필요에 따라 포함할 수 있습니다.
-
timeout, of type unsigned long-
이 선택적 멤버는 Relying Party가 호출 완료를 위해 기다릴 의사가 있는 시간(밀리초)을 지정합니다. 이는 힌트로 취급되며, client에 의해 재정의될 수 있습니다.
excludeCredentials, of type sequence<PublicKeyCredentialDescriptor>, defaulting to[]-
Relying Party는 이 선택적 멤버를 사용하여 해당 credentials 중 사용자의 계정(
user.id)에 매핑된 기존 자격 증명을 나열해야 합니다. 이는 새 자격 증명이 이미 해당 자격 증명을 포함하는 인증기에서 생성되지 않도록 하기 위함입니다. 만약 그렇다면 클라이언트는 대신 사용자가 다른 인증기를 사용하도록 안내하거나, 실패할 경우 오류를 반환하도록 요청받습니다. authenticatorSelection, of type AuthenticatorSelectionCriteria-
Relying Party는 이 선택적 멤버를 사용하여 authenticator가 참여하기 위해 반드시 또는 권장해야 하는 기능과 설정을 지정할 수 있습니다. 자세한 내용은 § 5.4.4 Authenticator Selection Criteria (dictionary AuthenticatorSelectionCriteria)를 참조하세요.
hints, of type sequence<DOMString>, defaulting to[]-
이 선택적 멤버는 사용자 에이전트가 사용자와 상호작용할 때 안내하기 위한
PublicKeyCredentialHint의 0개 이상의 요소를 포함합니다. 요소의 타입은DOMString입니다. 자세한 내용은 § 2.1.1 Enumerations as DOMString types를 참조하세요. attestation, of type DOMString, defaulting to"none"-
Relying Party는 이 선택적 멤버를 사용하여 attestation conveyance에 관한 선호를 지정할 수 있습니다. 값은
AttestationConveyancePreference의 멤버여야 하는 것이 권장됩니다. Client platforms는 알 수 없는 값을 무시하고, 해당 멤버가 존재하지 않는 것처럼 처리해야 합니다.기본값은
none입니다. attestationFormats, of type sequence<DOMString>, defaulting to[]-
Relying Party는 이 선택적 멤버를 사용하여 인증기가 사용할 attestation statement 형식에 대한 선호를 지정할 수 있습니다. 값은 IANA "WebAuthn Attestation Statement Format Identifiers" 레지스트리에서 가져온 것이어야 하며, 값들은 가장 선호하는 것에서 덜 선호하는 것 순으로 정렬됩니다. 중복은 허용되지만 사실상 무시됩니다. 이 매개변수는 자문의 성격을 가지며 인증기는 이 매개변수에 열거되지 않은 attestation statement를 사용할 수 있습니다.
기본값은 기본 목록(빈 목록)으로, 선호가 없음을 나타냅니다.
extensions, of type AuthenticationExtensionsClientInputs-
Relying Party는 이 선택적 멤버를 사용하여 클라이언트 및 인증기가 추가 처리를 수행하도록 요청하는 client extension inputs을 제공할 수 있습니다. 예를 들어, Relying Party는 클라이언트가 생성된 credential에 관한 추가 정보를 반환하도록 요청할 수 있습니다.
확장 프레임워크는 § 9 WebAuthn Extensions에 정의되어 있습니다. 일부 확장은 § 10 Defined Extensions에 정의되어 있으니, 최신 등록 확장 목록은 IANA "WebAuthn Extension Identifiers" 레지스트리를 참조하세요.
5.4.1.
공개 키 엔터티 설명 (dictionary PublicKeyCredentialEntity)
PublicKeyCredentialEntity
딕셔너리는 사용자 계정 또는 WebAuthn
Relying Party를 설명하며, 공개 키 자격 증명이 각각 연결되거나 범위 지정된 대상을 의미합니다.
dictionary PublicKeyCredentialEntity {required DOMString name ; };
name, 유형 DOMString-
엔터티의 사용자 친화적 이름입니다. 이 기능은
PublicKeyCredentialEntity가 나타내는 대상에 따라 다릅니다:-
[더 이상 사용되지 않음]
PublicKeyCredentialRpEntity에 의해 상속될 때, Relying Party의 사용자 친화적 식별자로, 오직 표시용입니다. 예: "ACME Corporation", "Wonderful Widgets, Inc." 또는 "ОАО Примертех".이 멤버는 많은 클라이언트가 표시하지 않기 때문에 더 이상 사용되지 않으나, 이전과의 호환성을 위해 필수 속성으로 남아 있습니다. Relying Parties는 안전한 기본값으로 이 값을 RP ID와 동일하게 설정할 수 있습니다.
-
Relying Parties는 [RFC8266] 2.3절에 명시된 Nickname Profile의 PRECIS FreeformClass [RFC8264] 따라
name값 지정 또는 표시 시 엄격한 검증을 수행해야 합니다. -
이 문자열은 언어 및 방향 메타데이터를 포함할 수 있습니다. Relying Parties는 RP ID 이외의 값을 설정할 경우 이를 제공하는 것을 권장합니다. 메타데이터 인코딩 방식은 § 6.4.2 언어 및 방향 인코딩 참고하세요.
-
클라이언트는 [RFC8266] 2.3절의 Nickname Profile 및 [RFC8264] 에 따라,
name값을 사용자에게 표시하거나 authenticatorMakeCredential 작업의 파라미터로 포함하기 전에 검증을 수행해야 합니다.
-
-
PublicKeyCredentialUserEntity에 의해 상속될 때, 사용자 계정의 사용자 친화적 식별자입니다. 이 식별자는 클라이언트가 사용자에게 자격 증명이 연결된 사용자 계정을 이해하도록 도와주는 데 주로 표시됩니다.예시: "alexm", "+14255551234", "alex.mueller@example.com", "alex.mueller@example.com (prod-env)", 또는 "alex.mueller@example.com (ОАО Примертех)" 등.
-
Relying Party는 이 값을 사용자에게 선택하게 할 수 있습니다. 또한 [RFC8265] 3.4.3절의 UsernameCasePreserved Profile 및 [RFC8264]에 따라 값을 설정하거나 표시할 때 검증을 수행해야 합니다.
-
이 문자열은 언어 및 방향 메타데이터를 포함할 수 있습니다. Relying Parties 는 이 정보를 제공하는 것이 좋습니다. 인코딩 방식은 § 6.4.2 언어 및 방향 인코딩 참고.
-
클라이언트는 [RFC8265] 3.4.3절 UsernameCasePreserved Profile 및 [RFC8264] 에 따라,
name값을 사용자에게 표시하거나 authenticatorMakeCredential 작업에 포함하기 전에 검증을 수행해야 합니다.
-
클라이언트, 클라이언트 플랫폼 또는 인증기가
name값 표시 시, 항상 UI 엘리먼트를 사용하여 해당 값의 경계를 명확하게 하고, 다른 요소로 넘침이 발생하지 않도록 해야 합니다 [css-overflow-3].name멤버 값을 저장할 때, § 6.4.1 문자열 잘림에서 설명한 대로 최소 64바이트 이상의 크기 제한을 이용해 잘릴 수 있습니다. -
5.4.2.
자격 증명 생성을 위한 Relying Party 파라미터 (dictionary PublicKeyCredentialRpEntity)
PublicKeyCredentialRpEntity
딕셔너리는 새로운 자격 증명 생성시 추가 Relying
Party 속성을 제공하는 데 사용됩니다.
dictionary PublicKeyCredentialRpEntity :PublicKeyCredentialEntity {DOMString id ; };
id, 유형 DOMString-
Relying Party 엔터티의 고유 식별자로, RP ID를 설정합니다.
5.4.3.
자격 증명 생성을 위한 사용자 계정 파라미터 (dictionary PublicKeyCredentialUserEntity)
PublicKeyCredentialUserEntity
딕셔너리는 새로운 자격 증명 생성시 추가 사용자 계정
속성을 제공하는 데 사용됩니다.
dictionary PublicKeyCredentialUserEntity :PublicKeyCredentialEntity {required BufferSource id ;required DOMString displayName ; };
id, 유형 BufferSource-
사용자 핸들로, 사용자 계정의 식별자입니다. 사용자 핸들은 최대 64바이트 크기의 불투명 바이트 시퀀스이고, 사용자에게 표시되지 않습니다.
안전한 동작을 보장하기 위해, 인증 및 권한 결정은 반드시 이
id멤버를 기반으로 해야 하며,displayName이나name멤버는 사용하지 않아야 합니다. 자세한 내용은 [RFC8266] 6.1절 참고.사용자 핸들에는 사용자에 관한 개인정보(사용자 이름, 이메일 등)가 포함되어서는 안 됩니다; 상세 내용은 § 14.6.1 사용자 핸들 구성 참고. 사용자 핸들은 비어 있을 수 없습니다.
사용자 핸들은 서로 다른 사용자 계정 간에 고정 값이어선 안 되며, 일부 인증기는 항상 탐색 가능한 자격 증명을 생성하므로, 일정한 사용자 핸들은 한 인증기로 두 개 이상의 계정을 사용할 수 없게 합니다.
displayName, 유형 DOMString-
사용자 계정 용 사용자 친화적 이름으로, 오직 표시 용도로만 사용됩니다. Relying Party는 사용자가 직접 선택하도록 해야 하며, 필요 이상으로 선택을 제한해서는 안 됩니다. 적합하거나 사용자 친화적 이름이 없다면, 비어있는 문자열로 설정해야 합니다.
예시: "Alex Müller", "Alex Müller (ACME Co.)" 또는 "田中倫" 등.
-
Relying Parties는 [RFC8266] 2.3절(별명 프로파일) 및 [RFC8264] 에 따라,
displayName값을 빈 문자열이 아닌 경우 지정 또는 표시 시 검증을 수행해야 합니다. -
이 문자열은 언어 및 방향성 메타데이터를 포함할 수 있습니다. Relying Parties는 이 정보 제공을 고려해야 합니다. 인코딩 방식은 § 6.4.2 언어 및 방향 인코딩 참고.
-
클라이언트는 [RFC8266] 2.3절 Nickname Profile 및 [RFC8264] 에 따라
displayName값을 사용자에게 표시하거나 authenticatorMakeCredential 작업의 파라미터에 포함하기 전에 검증을 수행해야 합니다.
클라이언트, 클라이언트 플랫폼 또는 인증기는
displayName값 표시 시 항상 UI 엘리먼트를 사용하여 해당 값의 경계를 명확히 구분하고, 다른 요소로의 오버플로우가 없도록 해야 합니다 [css-overflow-3].displayName멤버 값을 저장할 때, § 6.4.1 문자열 잘림에서 설명한 대로 최소 64바이트 이상의 크기 제한으로 잘릴 수 있습니다. -
5.4.4.
인증기 선택 기준 (dictionary AuthenticatorSelectionCriteria)
WebAuthn Relying
Parties는 AuthenticatorSelectionCriteria
딕셔너리를 사용하여 인증기 속성에 대한 요구사항을 지정할 수 있습니다.
dictionary AuthenticatorSelectionCriteria {DOMString authenticatorAttachment ;DOMString residentKey ;boolean requireResidentKey =false ;DOMString userVerification = "preferred"; };
authenticatorAttachment, 유형 DOMString-
이 멤버가 존재하면, 적격 인증기는 지정된 인증기 연결 방식 (§ 6.2.1 인증기 연결 방식 참고)으로만 필터링됩니다. 존재하지 않으면 어떤 연결 방식이라도 허용됩니다. 값은
AuthenticatorAttachment의 멤버여야 하며, 클라이언트 플랫폼은 알 수 없는 값을 무시하고, 해당 멤버가 존재하지 않는 것처럼 처리해야 합니다.또한
authenticatorAttachment멤버(PublicKeyCredential)에서 어떤 인증기 연결 방식이 사용되었는지 알 수 있습니다. (create()또는get()작업 성공시) residentKey, 유형 DOMString-
Relying Party가 클라이언트 측에서 탐색 가능한 자격 증명 생성을 얼마나 원하는지 지정합니다. 과거 명칭에서 유래된 “resident” 용어를 그대로 사용합니다. 값은
ResidentKeyRequirement의 멤버여야 하며, 클라이언트 플랫폼은 알 수 없는 값은 무시하고 해당 멤버 미존재로 취급해야 합니다. 값이 없으면,requireResidentKey가true인 경우에는required,false또는 미존재인 경우에는discouraged입니다.ResidentKeyRequirement참조 –residentKey값의 의미 및 설명. requireResidentKey, 유형 boolean, 기본값false-
이 멤버는 WebAuthn Level 1부터의 이전 호환을 위해 남아 있으며, 탐색 가능한 자격 증명에 대해 “resident” 용어를 계속 사용합니다. Relying Parties는
residentKey를required로 설정한 경우에만true로 설정해야 합니다. userVerification, 유형 DOMString, 기본값"preferred"-
이 멤버는 Relying Party가
create()작업에서 사용자 검증 에 대해 요구하는 사항을 지정합니다. 값은UserVerificationRequirement의 멤버여야 하며, 클라이언트 플랫폼은 알 수 없는 값을 무시하고 해당 멤버 미존재로 취급해야 합니다.UserVerificationRequirement참조 –userVerification값의 의미 및 설명.
5.4.5. 인증기 연결 방식 열거형 (enum AuthenticatorAttachment)
이 열거형의 값들은 인증기의 연결 방식을 설명합니다. Relying
Parties는 연결 방식 선호도를 navigator.credentials.create()
를 호출하여 자격 증명 생성할 때 지정할 수 있고, 클라이언트는 연결 방식을 등록 또는 등록이나 인증 절차 완료 시 보고합니다.
enum AuthenticatorAttachment {"platform" ,"cross-platform" };
참고: AuthenticatorAttachment
열거형은 의도적으로 참조되지 않습니다. § 2.1.1 DOMString으로서의 열거형 참고.
platform-
이 값은 플랫폼 연결을 의미합니다.
cross-platform-
이 값은 크로스-플랫폼 연결을 의미합니다.
참고: 인증기 연결 방식
선택 옵션은 [[Create]](origin, options, sameOriginWithAncestors)
작업에서만 사용할 수 있습니다. Relying
Party는 예를 들어, 사용자가 로밍 자격 증명으로 다른 클라이언트 디바이스에서 인증하도록 보장하거나,
특정 클라이언트 디바이스에서 더 쉬운 재인증을 위해
플랫폼 자격 증명을 등록할 수
있습니다. [[DiscoverFromExternalSource]](origin, options, sameOriginWithAncestors)
작업에는 연결 방식 선택 옵션이 없습니다. 클라이언트와 사용자는 당시 사용
가능한 자격 증명을 사용하며,
allowCredentials
옵션에 의해 제한됩니다.
5.4.6.
리던트 키 요구사항 열거형 (enum ResidentKeyRequirement)
enum ResidentKeyRequirement {"discouraged" ,"preferred" ,"required" };
참고: ResidentKeyRequirement
열거형은 의도적으로 참조되지 않습니다. § 2.1.1 DOMString으로서의 열거형 참고.
이 열거형의 값들은 클라이언트 측에서 탐색 가능한 자격 증명(이전에는 리던트 자격 증명 또는 리던트 키로 알려짐)에 대해 Relying Party의 요구사항을 설명합니다:
discouraged-
Relying Party는 서버 측 자격 증명 생성을 선호하지만 클라이언트 측에서 탐색 가능한 자격 증명도 허용합니다. 클라이언트 및 인증기는 가능하면 서버 측 자격 증명을 생성해야 합니다.
참고: Relying Party는 생성된 자격 증명이 서버 측 자격 증명임을 강제할 수 없습니다. Credential Properties Extension의
rk속성에 값이 반환되지 않을 수도 있습니다. 이 때문에, 실제로 해당 자격 증명이 서버 측 자격 증명인지 여부를 알지 못해, 동일 사용자 핸들로 두 번째 자격 증명을 만들면 첫 번째 자격 증명이 삭제되는지 알 수 없습니다. preferred-
Relying Party는 클라이언트 측에서 탐색 가능한 자격 증명 생성을 강하게 선호하지만, 서버 측 자격 증명도 허용합니다. 클라이언트와 인증기는 가능하면 탐색 가능한 자격 증명을 생성해야 합니다. 예를 들어, 클라이언트는 사용자 검증 절차 안내를 통해 탐색 가능한 자격 증명을 생성하도록 안내해야 합니다. 이 옵션은
userVerification값보다 우선합니다. required-
Relying Party가 클라이언트 측에서 탐색 가능한 자격 증명을 반드시 요구합니다. 클라이언트는 클라이언트 측에서 탐색 가능한 자격 증명을 생성할 수 없으면 오류를 반환해야 합니다.
참고: Relying Party는 인증기가 클라이언트 측에서
탐색 가능한 자격 증명을 생성했는지 여부를 resident key credential
property (Credential Properties
Extension)로 확인할 수 있습니다.
이는 discouraged
또는 preferred
가
options.
에 사용된 경우, 해당 시점의 인증기가
클라이언트 측 탐색 가능 자격 증명이든 서버 측 자격 증명이든 생성 가능성이 있기 때문입니다.
authenticatorSelection.residentKey
5.4.7.
Attestation Conveyance 선호 열거형 (enum AttestationConveyancePreference)
WebAuthn Relying
Parties는 자격 증명 생성 중 attestation conveyance에 대해 선호를 지정하기 위해 AttestationConveyancePreference를
사용할 수 있습니다.
enum AttestationConveyancePreference {"none" ,"indirect" ,"direct" ,"enterprise" };
참고: AttestationConveyancePreference
열거형은 의도적으로 참조되지 않았으며, § 2.1.1 DOMString 타입의 열거형을 참고하세요.
none-
Relying Party는 인증기 attestation에 관심이 없습니다. 예를 들어, 사용자 동의를 받고 식별 정보를 Relying Party로 전달해야 하는 상황을 피하거나, Attestation CA 또는 Anonymization CA와의 추가 roundtrip을 줄이기 위해 사용할 수 있습니다. 인증기가 self attestation이 아닌 attestation statement를 생성하는 경우, 클라이언트는 해당 값을 None attestation statement로 대체합니다.
이 값이 기본값이며, 알 수 없는 값도 이 값의 동작으로 돌아갑니다.
indirect-
Relying Party는 검증 가능한 attestation statement를 받고자 하지만, 이러한 attestation statement를 어떻게 획득할지에 대해 클라이언트가 결정하도록 허용합니다. 클라이언트는 인증기에서 생성된 attestation statement를 사용자의 프라이버시를 보호하거나, 또는 이기종 생태계에서 Relying Party의 attestation 검증을 돕기 위해 익명화 CA(Anonymization CA)가 생성한 것으로 대체할 수 있습니다.
참고: 이 경우 반드시 Relying Party가 검증 가능한 attestation statement를 얻는다는 보장은 없습니다. 예를 들어, 인증기가 self attestation을 사용하고 클라이언트가 해당 statement를 그대로 전달하는 경우입니다.
direct-
Relying Party는 인증기가 생성한 attestation statement 그 자체를 받길 원합니다.
enterprise-
Relying Party는 비즈니스용 attestation, 즉 인증기를 고유하게 식별하는 정보가 포함될 수 있는 attestation statement를 받길 원합니다. 이는 기업 내에서 등록을 특정 인증기에 연결하고자 하는 통제된 배포용입니다. 사용자 에이전트는 해당 RP ID용으로 사용자 에이전트 혹은 인증기 설정이 허용하지 않는 이상, 이러한 attestation을 제공해서는 안 됩니다.
허용되는 경우, 사용자 에이전트는 인증기에게 비즈니스용 attestation 요청 신호를 보내고(호출 시점), 결과로 나온 AAGUID와 attestation statement를 수정 없이 Relying Party로 전달해야 합니다.
5.5.
인증 생성 옵션 (dictionary PublicKeyCredentialRequestOptions)
PublicKeyCredentialRequestOptions
딕셔너리는 get()
이 인증을 생성하는 데 필요한 데이터를 제공합니다.
challenge
멤버는 반드시 포함되어야 하며, 나머지 멤버는 선택적입니다.
dictionary PublicKeyCredentialRequestOptions {required BufferSource challenge ;unsigned long timeout ;DOMString rpId ;sequence <PublicKeyCredentialDescriptor >allowCredentials = [];DOMString userVerification = "preferred";sequence <DOMString >hints = [];AuthenticationExtensionsClientInputs extensions ; };
challenge, 유형 BufferSource-
이 멤버는 인증기가 authentication assertion을 생성할 때 다른 데이터와 함께 서명하는 챌린지를 지정합니다. 자세한 보안 고려사항은 § 13.4.3 암호화 챌린지를 참고하세요.
timeout, 유형 unsigned long-
이 선택적 멤버는 Relying Party가 호출 완료 대기 가능 시간(밀리초)을 지정합니다. 이 값은 힌트로 취급되며, 클라이언트가 재정의할 수 있습니다.
rpId, 유형 DOMString-
이 선택적 멤버는 Relying Party가 주장하는 RP ID를 지정합니다. 클라이언트는 Relying Party의 origin이 이 RP ID의 scope와 일치하는지 반드시 확인해야 합니다. 인증기는 인증에 사용할 자격 증명의 rpId와 이 RP ID가 정확히 일치하는지도 반드시 확인해야 합니다.
지정하지 않은 경우
CredentialsContainer객체의 relevant settings object의 origin의 effective domain이 값으로 사용됩니다. allowCredentials, 유형 sequence<PublicKeyCredentialDescriptor>, 기본값[]-
이 선택적 멤버는 클라이언트가 이 인증 과정에 적합한 인증기를 찾을 때 사용됩니다. 사용 예시는 두 가지입니다:
-
인증할 사용자 계정이 이미 식별된 경우(예: 사용자가 사용자명을 입력한 경우), Relying Party는 이 멤버를 사용해 해당 사용자 계정의 크리덴셜 기록에 대한 크리덴셜 디스크립터를 나열해야 합니다. 이는 일반적으로 사용자 계정 안의 모든 크리덴셜 기록을 포함해야 합니다.
항목은 가능한 경우
transports도 지정해야 하며, 이는 클라이언트가 상황에 최적화된 사용자 경험을 제공하는 데 도움이 됩니다. 또한, userVerification 요청 시 Relying Party가 직접 리스트를 필터링할 필요는 없으며, 클라이언트가 비적격 자격 증명을 자동으로 무시하게 됩니다. (userVerification이required인 경우.)프라이버시 관련은 § 14.6.3 자격 증명 ID를 통한 프라이버시 유출을 참고하세요.
-
인증할 사용자 계정을 사전에 알 수 없는 경우, Relying Party는 이 값을 비워두거나 아예 지정하지 않을 수 있습니다. 이 경우에는 오직 탐색 가능한 자격 증명만이 인증 과정에서 사용되며, 사용자 계정은 결과
userHandle값으로 식별될 수 있습니다. 만약 사용 가능한 인증기가 한 Relying Party에 대해 두 개 이상의 탐색 가능한 자격 증명을 소유한 경우, 클라이언트 플랫폼 또는 인증기가 이를 사용자에게 나열하여 선택하도록 합니다. (7단계, § 6.3.3 authenticatorGetAssertion 동작 참고)
비워두지 않은 경우, 목록 내 어떤 자격 증명도 사용할 수 없다면 클라이언트는 오류를 반환해야 합니다.
목록은 선호도 순으로 내림차순 정렬되어 있습니다. 즉, 첫 번째 항목이 가장 선호되고, 마지막이 덜 선호됩니다.
-
userVerification, 유형 DOMString, 기본값"preferred"-
이 선택적 멤버는
get()동작에서 Relying Party의 user verification 요구사항을 지정합니다. 값은UserVerificationRequirement의 멤버여야 하며, 클라이언트 플랫폼은 알 수 없는 값을 무시하고 해당 멤버가 없는 것처럼 취급해야 합니다. 적합한 인증기는 오직 이 요구조건을 충족하는 것만 필터링됩니다.UserVerificationRequirement에서userVerification값과 의미를 참고하세요. hints, 유형 sequence<DOMString>, 기본값[]-
이 선택적 멤버는
PublicKeyCredentialHint에서 가져온 하나 이상의 요소로, 사용자 에이전트가 사용자와 상호작용할 때 지침으로 사용됩니다. 값이 나열형에서 유래했지만 실질 타입은DOMString임에 주의. (§ 2.1.1 DOMString 타입의 열거형 참고) extensions, 유형 AuthenticationExtensionsClientInputs-
Relying Party는 이 선택적 멤버로 클라이언트 확장 입력값을 제공해 클라이언트와 인증기에게 추가 처리를 요청할 수 있습니다.
확장 프레임워크는 § 9 WebAuthn 확장에서 정의되어 있습니다. 일부 확장은 § 10 정의된 확장에 서술되어 있습니다. 등록된 최신 WebAuthn 확장 목록은 IANA "WebAuthn Extension Identifiers" 레지스트리 [IANA-WebAuthn-Registries]와 [RFC8809]도 참고하세요.
5.6. AbortSignal을 사용한 연산 중단
개발자는 AbortController
를 활용하여 [[Create]](origin, options, sameOriginWithAncestors)
및 [[DiscoverFromExternalSource]](origin, options, sameOriginWithAncestors)
작업을 제어할 것을 권장합니다.
상세한 사용법은 DOM § 3.3
AbortController와 AbortSignal 객체의 API 통합 부분을 참고하세요.
참고: DOM § 3.3
AbortController와 AbortSignal 객체의 API 통합에 따르면,
웹 플랫폼 API가 AbortController와
연동될 경우,
AbortSignal
이 aborted 될 때 Promise를 즉시 reject 해야 합니다.
[[Create]](origin, options, sameOriginWithAncestors)
및 [[DiscoverFromExternalSource]](origin, options, sameOriginWithAncestors)
메서드는 복잡한 상속과 병렬 구조로 인해,
두 API의 알고리즘은 해당 aborted 속성을 세 곳에서 점검함으로써 이 요건을 충족시킵니다. [[Create]](origin, options, sameOriginWithAncestors)의
경우,
Credential Management
1 § 2.5.4 자격 증명 생성에서 [[Create]](origin, options, sameOriginWithAncestors)
호출 직전,
§ 5.1.3 새 자격 증명 생성 - PublicKeyCredential의 [[Create]](origin, options,
sameOriginWithAncestors) 내부 메서드에서 인증기 세션 시작 직전,
그리고 마지막으로 authenticator 세션 내에서 속성을 확인합니다.
[[DiscoverFromExternalSource]](origin, options, sameOriginWithAncestors)도
동일합니다.
Window
객체의 visibility와 focus 상태는 [[Create]](origin, options, sameOriginWithAncestors)
및 [[DiscoverFromExternalSource]](origin, options, sameOriginWithAncestors)
동작의 진행 여부를 결정합니다.
Document와 연관된 Window
객체가 포커스를 잃으면, 위 작업들은 중단되어야 합니다.
5.7. WebAuthn 확장 입력과 출력
아래 세부 절에서는 WebAuthn 확장 입력과 출력을 전달하는 데 사용되는 데이터 타입을 정의합니다.
참고: 인증기 확장 출력은 인증기 데이터의 일부로 전달됩니다(표 1 참고).
참고: 아래에 정의된 타입인 AuthenticationExtensionsClientInputs
및 AuthenticationExtensionsClientOutputs
는 등록 확장과 인증 확장
모두에 적용됩니다.
이름의 "Authentication..." 부분은 "WebAuthentication..." 의미로 간주해야 합니다.
5.7.1. 인증 확장 클라이언트 입력 (dictionary
AuthenticationExtensionsClientInputs)
dictionary { };AuthenticationExtensionsClientInputs
이 사전은 0개 이상의 WebAuthn 확장에 대한 클라이언트 확장 입력 값을 담고 있습니다.
5.7.2. 인증 확장 클라이언트 출력 (dictionary
AuthenticationExtensionsClientOutputs)
dictionary { };AuthenticationExtensionsClientOutputs
이 사전은 0개 이상의 WebAuthn 확장에 대한 클라이언트 확장 출력 값을 담고 있습니다.
5.7.3. 인증 확장 인증기 입력 (CDDL
type AuthenticationExtensionsAuthenticatorInputs)
AuthenticationExtensionsAuthenticatorInputs = {
* $$extensionInput
} .within { * tstr => any }
CDDL 타입
AuthenticationExtensionsAuthenticatorInputs는 0개 이상의 WebAuthn 확장에 대한 인증기 확장 입력 값을 담고 있는 CBOR 맵을 정의합니다.
확장은 § 9.3 요청 파라미터 확장에 설명된 대로 멤버를 추가할 수 있습니다.
이 타입은 Relying Party에게 노출되지 않지만, 클라이언트와 인증기에서 사용됩니다.
5.7.4. 인증 확장 인증기 출력 (CDDL
type AuthenticationExtensionsAuthenticatorOutputs)
AuthenticationExtensionsAuthenticatorOutputs = {
* $$extensionOutput
} .within { * tstr => any }
CDDL 타입
AuthenticationExtensionsAuthenticatorOutputs는 0개 이상의 WebAuthn 확장에 대한 인증기 확장 출력 값을 담고 있는 CBOR 맵을 정의합니다.
확장은 § 9.3 요청 파라미터 확장에 설명된 대로 멤버를 추가할 수 있습니다.
5.8. 지원 데이터 구조
공개 키 자격 증명 타입은 지원 명세서에서 정의된 특정 데이터 구조를 사용합니다. 다음과 같습니다.
5.8.1.
WebAuthn 서명에 사용되는 클라이언트 데이터 (dictionary CollectedClientData)
클라이언트 데이터는 WebAuthn Relying Party와 클라이언트 양쪽의 맥락적 바인딩을 나타냅니다. 이는 키가 문자열이고, 값은 JSON에서 유효하게 인코딩될 수 있는 어떤 타입이라도 될 수 있는 키-값 매핑입니다. 구조는 아래 Web IDL로 정의됩니다.
참고: CollectedClientData
는 향후 확장될 수 있습니다. 따라서 파싱 시 미지의 키와 키 순서 변경에 대해 유연하게 동작해야 합니다. § 5.8.1.2
제한된 검증 알고리즘도 참고하세요.
dictionary CollectedClientData {required DOMString type ;required DOMString challenge ;required DOMString origin ;boolean crossOrigin ;DOMString topOrigin ; };dictionary {TokenBinding required DOMString status ;DOMString id ; };enum {TokenBindingStatus "present" ,"supported" };
type, 유형 DOMString-
이 멤버는 새로운 자격 증명을 생성할 때 "webauthn.create", 기존 자격 증명에서 인증 정보를 가져올 때는 "webauthn.get" 문자열을 포함합니다. 이 멤버의 목적은 공격자가 한 서명을 다른 서명으로 대체하는 특정 타입의 서명 혼동 공격을 방지하기 위함입니다.
challenge, 유형 DOMString-
이 멤버는 Relying Party 가 제공한 챌린지의 base64url 인코딩 값을 포함합니다. § 13.4.3 암호화 챌린지의 보안 참고도 참고하세요.
origin, 유형 DOMString-
이 멤버는 요청자의 완전히 한정된 origin 문자열을 포함합니다(클라이언트가 인증기에 제공), [RFC6454] 구문에 따라 지정됩니다.
crossOrigin, 유형 boolean-
이 선택적 멤버는 내부 메서드로 전달된
sameOriginWithAncestors인자의 반값을 담고 있습니다. topOrigin, 유형 DOMString-
이 선택적 멤버는 요청자의 완전히 한정된 최상위 origin 값을 포함하며, [RFC6454] 구문으로 지정됩니다. 이 값은 same-origin with its ancestors가 아닌 컨텍스트에서만 설정되며, 즉
crossOrigin이true일 경우에만 값이 있습니다. - [예약됨] tokenBinding
-
이 선택적 멤버는 Token Binding 프로토콜 [TokenBinding] 상태에 대한 정보를 포함합니다. 값이 없으면 클라이언트가 토큰 바인딩을 지원하지 않음을 의미합니다.
참고: Token Binding은 WebAuthn Level 1, 2에는 있었지만 Level 3에서는 사용되지 않을 예정입니다. tokenBinding 필드는 다른 용도로 재사용되지 않도록 예약되어 있습니다.
status, 유형 DOMString-
이 멤버는
TokenBindingStatus의 멤버여야 하지만, 클라이언트 플랫폼은 알 수 없는 값을 무시하고, 해당 tokenBinding 멤버가 없는 것처럼 처리해야 합니다. 알고 있는 값은 다음 두 가지 중 하나입니다.supported-
클라이언트가 토큰 바인딩을 지원하지만 Relying Party와 통신 시 협상되지 않았음을 나타냅니다.
present-
토큰 바인딩이 Relying Party와의 통신 시 사용되었음을 의미합니다. 이 경우
id멤버가 반드시 존재해야 합니다.
참고:
TokenBindingStatus열거형은 의도적으로 참조되지 않았으며, § 2.1.1 DOMString 타입의 열거형 참고. id, 유형 DOMString-
status가present인 경우 이 멤버가 반드시 존재해야 하며, base64url 인코딩 형식의 Token Binding ID여야 합니다(통신에 사용된 값).
참고: Token Binding ID는 클라이언트 플랫폼에 따라 획득 방식이 다릅니다.
CollectedClientData
구조는 클라이언트가 다음 값을 계산할 때 사용합니다:
- 클라이언트 데이터의 JSON 호환 직렬화
-
이는
CollectedClientData사전에 JSON 호환 직렬화 알고리즘을 실행한 결과입니다. - 직렬화된 클라이언트 데이터의 해시
-
이는 클라이언트가 구성한 클라이언트 데이터의 JSON 호환 직렬화에 대해 SHA-256을 이용해 계산한 해시입니다.
5.8.1.1. 직렬화
CollectedClientData
의 직렬화는 JSON 값을 바이트로 직렬화 알고리즘의 부분집합입니다. 즉, CollectedClientData
에 대한 유효한 JSON 인코딩을 산출하며, 또한 전체 JSON 파서를 통합하지 않고 검증자가 구조적으로 사용 가능한 추가 구조도 제공합니다. 검증자에게는 표준 JSON 구문 분석을 권장하지만,
전체 파서가 부담일 때는 아래 보다 제한적인 알고리즘을 사용할 수 있습니다. 이 검증 알고리즘은 base64url 인코딩,
바이트열 덧붙이기(고정 템플릿에 작성하는 식), 조건 분기(입력이 escape 필요 없음이 전제)만 있으면 됩니다.
직렬화 알고리즘은, 최초에는 빈 바이트열에 연속적으로 바이트열을 덧붙여 전체 결과를 완성합니다.
-
result에 빈 바이트열을 할당합니다.
-
0x7b2274797065223a(
{"type":)를 result에 덧붙입니다. -
CCDToString(
type) 을 result에 덧붙입니다. -
0x2c226368616c6c656e6765223a(
,"challenge":)를 result에 덧붙입니다. -
CCDToString(
challenge) 을 result에 덧붙입니다. -
0x2c226f726967696e223a(
,"origin":)를 result에 덧붙입니다. -
CCDToString(
origin) 을 result에 덧붙입니다. -
0x2c2263726f73734f726967696e223a(
,"crossOrigin":)를 result에 덧붙입니다. -
crossOrigin이 없거나false일 경우:-
0x66616c7365(
false)를 result에 덧붙입니다.
-
-
그 외의 경우:
-
0x74727565(
true)를 result에 덧붙입니다.
-
-
topOrigin이 존재할 경우:-
0x2c22746f704f726967696e223a(
,"topOrigin":)를 result에 덧붙입니다. -
CCDToString(
topOrigin) 을 result에 덧붙입니다.
-
-
CollectedClientData의 임시 복사본을 만들고,type,challenge,origin,crossOrigin(존재 시),topOrigin(존재 시)를 삭제합니다. -
임시 복사본에 남은 필드가 없는 경우:
-
0x7d(
})를 result에 덧붙입니다.
-
-
그 외의 경우:
-
임시 복사본에 serialize JSON to bytes를 적용해 바이트열 remainder를 만듭니다.
-
0x2c(
,)를 result에 덧붙입니다. -
remainder에서 선두 바이트를 제거합니다.
-
remainder를 result에 덧붙입니다.
-
-
이 직렬화의 결과는 result의 값입니다.
위 알고리즘에서 사용하는 함수 CCDToString은 다음과 같이 정의됩니다:
-
encoded에 빈 바이트열을 할당합니다.
-
0x22(
")를 encoded에 덧붙입니다. -
주어진 객체에 ToString을 적용해 문자열로 변환합니다.
-
문자열 내 각 코드포인트에 대해, 만약:
- {U+0020, U+0021, U+0023–U+005B, U+005D–U+10FFFF} 범위일 때
-
해당 코드포인트의 UTF-8 바이너리를 encoded에 덧붙입니다.
- U+0022인 경우
-
0x5c22(
\")를 encoded에 덧붙입니다. - U+005C인 경우
-
0x5c5c(\\)를 encoded에 덧붙입니다.
- 기타
-
0x5c75(
\u)와 해당 코드포인트 값을 16진법 4자리 소문자로 인코딩한 것을 encoded에 덧붙입니다.
-
0x22(
")를 encoded에 덧붙입니다. -
이 함수의 결과는 encoded의 값입니다.
5.8.1.2. 제한된 검증 알고리즘
전체 JSON 파서를 도입하기 어렵다면, 인코딩된 CollectedClientData
를 검증하기 위한 아래 알고리즘을 활용할 수 있습니다:
-
알고리즘의 입력값:
-
clientDataJSON:
clientDataJSON(직렬화된CollectedClientData) 바이트열 -
type:
type에 들어갈 기대 문자열 -
challenge:
PublicKeyCredentialRequestOptions혹은PublicKeyCredentialCreationOptions에 사용된 챌린지 바이트열 -
origin: 사용자 에이전트에게 요청을 전달한
origin. -
옵션 topOrigin: (있다면)
topOrigin기대값 -
requireTopOrigin: topOrigin이 정의되어 있고
topOrigin속성이 clientDataJSON에 없으면 검증 실패로 처리할지 여부(boolean).이 항목 덕분에, 이 알고리즘은 requireTopOrigin이
false인 경우 WebAuthn LV2 JSON-compatible 직렬화 알고리즘 과 하위 호환됩니다.
-
-
expected에 빈 바이트열 할당.
-
0x7b2274797065223a(
{"type":)를 expected에 덧붙임. -
CCDToString(type) 를 expected에 덧붙임.
-
0x2c226368616c6c656e6765223a(
,"challenge":)를 expected에 덧붙임. -
challenge에 base64url 인코딩을 적용해 challengeBase64로 저장.
-
CCDToString(challengeBase64) 를 expected에 덧붙임.
-
0x2c226f726967696e223a(
,"origin":)를 expected에 덧붙임. -
CCDToString(origin) 을 expected에 덧붙임.
-
0x2c2263726f73734f726967696e223a(
,"crossOrigin":)를 expected에 덧붙임. -
topOrigin이 정의되어 있다면:
-
0x74727565(
true)를 expected에 덧붙임. -
requireTopOrigin이 true이거나 0x2c22746f704f726967696e223a(
,"topOrigin":)이 clientDataJSON의 expected 길이 위치에서 시작하는 접두사라면…-
0x2c22746f704f726967696e223a(
,"topOrigin":)를 expected에 덧붙임. -
CCDToString(topOrigin)을 expected에 덧붙임.
-
-
-
그 외의 경우 (topOrigin 미정의):
-
0x66616c7365(
false)를 expected에 덧붙임.
-
-
expected가 clientDataJSON의 접두사가 아니라면 검증은 실패.
-
clientDataJSON이 expected보다 길지 않으면 검증 실패.
-
clientDataJSON에서 expected 길이에 해당하는 위치의 바이트 값이:
- 0x7d일 때
-
검증 성공.
- 0x2c일 때
-
검증 성공.
- 그 외
-
검증 실패.
5.8.1.3. 향후 확장
제한된 검증 알고리즘과의 호환성을 유지하기 위하여,
향후 명세 버전에서는 type,
challenge,
origin,
crossOrigin,
또는 topOrigin
를 CollectedClientData
에서 제거해서는 안 됩니다.
또한 직렬화 알고리즘의 해당 필드 직렬화 순서를 바꾸거나, 중간에 새 필드를 끼워넣어도 안 됩니다.
CollectedClientData
에 필드를 추가하는 경우,
제한된 검증 알고리즘이 업데이트되어 위 두 알고리즘에 포함되기 전에는 검증자들이 이 필드를 고려하지 못합니다. 이후
업데이트가 이뤄지면 추가된 필드 역시 앞 문단의 제한사항을 적용받게 되며, 과거 버전의 직렬화에 대해 호환 가능해야 합니다. 즉, 추가된 여섯 번째 키-값 쌍은 이전 버전 에이전트에서는 여섯
번째에 오지 않거나 아예 없을 수도 있음을 검증 알고리즘이 처리해야 합니다.
5.8.2. 자격 증명 유형 열거형(enum PublicKeyCredentialType)
enum PublicKeyCredentialType {"public-key" };
참고: PublicKeyCredentialType
열거형은 의도적으로 참조되지 않았으니, § 2.1.1 DOMString 타입의 열거형을 참고하세요.
현재 하나의 자격 증명 유형만 정의되어 있으며, 바로 "public-key"입니다.
5.8.3.
자격 증명 설명자 (dictionary PublicKeyCredentialDescriptor)
dictionary PublicKeyCredentialDescriptor {required DOMString type ;required BufferSource id ;sequence <DOMString >transports ; };
이 사전은 특정 공개 키 자격
증명을 식별합니다.
이는 create()
에서 동일한 인증기에 중복 자격 증명 생성을
방지하고,
get()
에서 클라이언트가 현재 해당 자격 증명에 접근할 수 있는지 확인하는 데 사용됩니다.
자격 증명 기록의 설명자는 해당 자격 증명 기록의 일부 속성의
부분집합이며,
PublicKeyCredential
객체의 일부 필드를 반영합니다. 이 객체는 create()
와 get()
이 반환하는 객체와도 상응합니다.
type, 유형 DOMString-
이 멤버는 참조하는 공개 키 자격 증명의 타입을 담고 있습니다. 값은
PublicKeyCredentialType의 멤버여야 하지만 클라이언트 플랫폼은 알 수 없는PublicKeyCredentialDescriptor의type을 무시해야 합니다. 단, 모든 요소가 알 수 없는type때문에 무시된다면, 빈allowCredentials과는 의미적으로 다르므로 오류로 처리해야 합니다.이 값은 type 항목 값을 반영해야 하며, 이는 자격 증명 기록이 나타내는 공개 키 자격 증명 소스의 값입니다.
type필드와도 대응합니다. id, 유형 BufferSource-
이 멤버는 참조하는 공개 키 자격 증명의 자격 증명 ID를 담고 있습니다.
이 값은 id 항목 값을 반영해야 하며, 이는 자격 증명 기록이 나타내는 공개 키 자격 증명 소스의 값입니다.
rawId필드와도 대응합니다. transports, 유형 sequence<DOMString>-
이 선택적 멤버는 참조하는 공개 키 자격 증명의 관리 인증기와 클라이언트가 어떻게 통신할지에 대한 힌트입니다. 이 값들은
AuthenticatorTransport의 멤버여야 하지만, 클라이언트 플랫폼은 알 수 없는 값은 무시해야 합니다.이 값은 transports 항목 값을 반영해야 하며, 이는 자격 증명 기록이 나타내는 공개 키 자격 증명 소스의 값입니다.
메소드와도 동일합니다.response.getTransports()PublicKeyCredential구조의create()작업에서 생성됩니다.
5.8.4. 인증기 전송 방식 열거형(enum AuthenticatorTransport)
enum AuthenticatorTransport {"usb" ,"nfc" ,"ble" ,"smart-card" ,"hybrid" ,"internal" };
참고: AuthenticatorTransport
열거형은 의도적으로 참조되지 않았으며, § 2.1.1 DOMString 타입의 열거형을 참고하세요.
getTransports()
를 이용해 알게 됩니다.
usb-
해당 인증기가 탈착 USB를 통해 연결될 수 있음을 나타냅니다.
nfc-
해당 인증기가 근거리 무선 통신(NFC)으로 연결될 수 있음을 나타냅니다.
ble-
해당 인증기가 블루투스 스마트(Bluetooth Low Energy / BLE)로 연결될 수 있음을 나타냅니다.
smart-card-
해당 인증기가 ISO/IEC 7816 스마트카드(접점식)로 연결될 수 있음을 나타냅니다.
hybrid-
해당 인증기가 데이터 전송과 근접 메커니즘을 조합해 연결될 수 있음을 나타냅니다. 예로 스마트폰을 사용해 데스크톱 컴퓨터에서 인증할 때 활용 가능합니다.
internal-
해당 인증기가 클라이언트 디바이스의 특수 전송 방식으로 접근됨을 의미하며, 즉 플랫폼 인증기입니다. 이러한 인증기는 클라이언트 디바이스에서 분리할 수 없습니다.
5.8.5. 암호 알고리즘 식별자 (typedef COSEAlgorithmIdentifier)
typedef long ;COSEAlgorithmIdentifier
COSEAlgorithmIdentifier
값은 암호 알고리즘을 식별하는 숫자입니다.
알고리즘 식별자는 IANA COSE Algorithms registry [IANA-COSE-ALGS-REG]에 등록된
값이어야 하며, 예시로 "ES256"은 -7, "RS256"은 -257 등입니다.
COSE 알고리즘 레지스트리는 COSE 키에서 추가 매개변수로 자유도를 남깁니다. 상호운용성을 위해, 본 명세는 credential public key에 대해 다음을 보증합니다.
-
알고리즘 ES256(-7) 키는 crv 매개변수를 반드시 P-256(1)로 지정하고, 압축 점 형식을 사용해서는 안 됩니다.
-
알고리즘 ES384(-35) 키는 반드시 P-384(2)를 crv 매개변수로 지정하고, 압축 점 형식을 쓰면 안 됩니다.
-
알고리즘 ES512(-36) 키는 반드시 P-521(3)을 crv 매개변수로 지정하고, 압축 점 형식을 허용하지 않습니다.
-
알고리즘 EdDSA(-8) 키는 반드시 Ed25519(6)을 crv 매개변수로 지정해야 합니다. (COSE에서 항상 압축 형태를 사용.)
이러한 제한은 RFC9053의 2.1절 [RFC9053]의 권고와 동일합니다.
참고: 이 알고리즘들을 사용하여 서명 검증을 올바르게 구현하려면 다양한 체크가 필요합니다. 그중 하나는 비압축 타원곡선 점을 처리할 때 해당 점이 실제 곡선 위에 있는지 확인해야 하며, 이는 암호 라이브러리와 기타 코드 사이의 간극으로 인해 누락 위험이 있으니 반드시 확인해야 합니다.
5.8.6.
사용자 검증 요구 열거형(enum UserVerificationRequirement)
enum UserVerificationRequirement {"required" ,"preferred" ,"discouraged" };
WebAuthn Relying Party는 일부 작업에 대해 사용자 검증을 요구할 수 있으며, 이 타입으로 요구 사항을 표현할 수 있습니다.
참고: UserVerificationRequirement
열거형은 의도적으로 참조되지 않았으며, § 2.1.1 DOMString 타입의 열거형을 참고하세요.
required-
Relying Party가 해당 작업에 대해 사용자 검증을 반드시 요구하며, 응답의 UV 플래그가 설정되어 있지 않으면 전체 ceremony가 실패로 간주됩니다. 클라이언트는 사용자 검증을 할 수 없다면 반드시 오류를 반환해야 합니다.
preferred-
Relying Party는 해당 작업에서 가능하다면 사용자 검증을 선호하지만, 응답의 UV 플래그가 설정되어 있지 않아도 작업을 실패로 간주하지 않습니다.
discouraged-
Relying Party는 해당 작업 중 사용자 검증을 사용하고 싶지 않습니다(예: 사용자 플로우에 대한 지장을 최소화하기 위함).
5.8.7.
클라이언트 기능 열거형(enum ClientCapability)
enum ClientCapability {"conditionalCreate" ,"conditionalGet" ,"hybridTransport" ,"passkeyPlatformAuthenticator" ,"userVerifyingPlatformAuthenticator" ,"relatedOrigins" ,"signalAllAcceptedCredentials" ,"signalCurrentUserDetails" ,"signalUnknownCredential" };
이 열거형은 WebAuthn Relying Party가 특정 워크플로우 및 경험을 사용자에게 제공하기 위해 평가할 수 있는 제한적 클라이언트 기능 집합을 정의합니다.
Relying Party는
getClientCapabilities()
메서드를 통해 사용할 수 있는 기능 설명을 얻을 수 있습니다.
참고: ClientCapability
열거형은 의도적으로 참조되지 않았으며, § 2.1.1 DOMString 타입의 열거형을 참고하세요.
conditionalCreate-
WebAuthn 클라이언트가 등록 과정에서
conditional중재를 지원함을 의미합니다.자세한 내용은 § 5.1.3 새 자격 증명 생성 - PublicKeyCredential의 [[Create]](origin, options, sameOriginWithAncestors) 내부 메서드를 참고하세요.
conditionalGet-
WebAuthn 클라이언트가 인증 과정에서
conditional중재를 지원함을 의미합니다.이 기능은
isConditionalMediationAvailable()메서드가true로 평가되는 것과 같습니다.자세한 내용은 § 5.1.4 기존 자격 증명을 사용한 어설션 생성을 참고하세요.
hybridTransport-
WebAuthn 클라이언트가
hybrid전송 방식을 지원함을 의미합니다. passkeyPlatformAuthenticator-
WebAuthn 클라이언트가 패스키 플랫폼 인증기를 로컬 및/또는
hybrid전송을 통해 지원함을 의미합니다. userVerifyingPlatformAuthenticator-
WebAuthn 클라이언트가 사용자 검증 플랫폼 인증기를 지원함을 의미합니다.
relatedOrigins-
WebAuthn 클라이언트가 연관 Origin 요청을 지원함을 의미합니다.
signalAllAcceptedCredentials-
WebAuthn 클라이언트가
signalAllAcceptedCredentials()을 지원함을 의미합니다. signalCurrentUserDetails,-
WebAuthn 클라이언트가
signalCurrentUserDetails()을 지원함을 의미합니다. signalUnknownCredential-
WebAuthn 클라이언트가
signalUnknownCredential()을 지원함을 의미합니다.
5.8.8. User-agent 힌트 열거(enum PublicKeyCredentialHint)
enum PublicKeyCredentialHint {"security-key" ,"client-device" ,"hybrid" , };
Note: PublicKeyCredentialHint
열거형은 의도적으로 참조되지 않음. 자세한 내용은 § 2.1.1
DOMString 타입으로서의 열거형을 참고하십시오.
힌트는 credential의 transports
및 authenticatorAttachment에
포함된 정보와 모순될 수 있습니다. 이 경우 힌트가 우선합니다. (transports
값은 discoverable credentials를 사용할 때는 제공되지 않으므로, 이러한 요청의 일부
측면을 표현하는 유일한 방법으로 힌트가 사용될 수 있습니다.)
security-key-
Relying Party가 사용자가 실제 보안 키로 이 요청을 충족하리라 판단한다는 점을 나타냅니다. 예를 들어, 엔터프라이즈 Relying Party가 직원들에게 보안 키를 배포했으며, 해당 키만을 authenticator로 등록 및 인증에 허용하고자 할 때 이 힌트를 설정할 수 있습니다.
구버전 user agent와의 호환성을 위해, 이 힌트가
PublicKeyCredentialCreationOptions내에서 사용될 경우authenticatorAttachment값을cross-platform으로 지정해야 합니다. client-device-
Relying Party가 사용자가 클라이언트 디바이스에 연결된 플랫폼 인증기로 이 요청을 충족하리라 판단한다는 점을 나타냅니다.
구버전 user agent와의 호환성을 위해, 이 힌트가
PublicKeyCredentialCreationOptions내에서 사용될 경우authenticatorAttachment값을platform으로 지정해야 합니다. hybrid-
Relying Party가 사용자가 스마트폰과 같은 범용 인증기로 이 요청을 충족하리라 판단한다는 점을 나타냅니다. 예를 들어, 소비자 Relying Party가 전용 보안 키를 가진 고객의 비율이 매우 적다고 판단하는 경우입니다. 이 옵션은 또한 로컬 플랫폼 인증기가 UI에 표시되지 않아야 함을 의미합니다.
구버전 user agent와의 호환성을 위해, 이 힌트가
PublicKeyCredentialCreationOptions내에서 사용될 경우authenticatorAttachment값을cross-platform으로 지정해야 합니다.
5.9. Permissions Policy 통합
이 명세는
"publickey-credentials-create"
와
"publickey-credentials-get"
으로 식별되는 두 가지 정책 제어 기능을 정의합니다. 이들의 기본 허용 목록은 모두
'self' 입니다. [Permissions-Policy]
Document의
permissions policy는 해당 문서 내의 모든 콘텐츠가 성공적으로 사용 할 수 있는지, 즉 Web Authentication API
(navigator.credentials.create({publicKey:..., ...})
또는
navigator.credentials.get({publicKey:..., ...}))
를 호출할 수 있는지를 결정합니다.
만약 비활성화되어 있다면, 해당 문서의 콘텐츠는 위의 메서드를 사용할 수 없으며, 시도할 경우 오류를 반환합니다.
Note: [CREDENTIAL-MANAGEMENT-1]에 지정된 알고리즘이 실제 permissions policy 평가를
수행합니다. 이러한 정책 평가는 current settings object에 접근할 수 있을 때 발생해야 하기 때문입니다. [[Create]](origin, options, sameOriginWithAncestors)
와 [[DiscoverFromExternalSource]](origin, options, sameOriginWithAncestors)
내부 메서드는 위와 같이 병렬로 호출되기 때문에 접근할 수 없습니다. CredentialsContainer의
Create a Credential 및 Request a Credential 추상 연산에서 처리됩니다.
5.10. iframe 요소 내에서 Web Authentication 사용하기
Web
Authentication API는 기본적으로 교차 출처
iframe에서
비활성화되어 있습니다.
이 기본 정책을 재정의하고 교차 출처
iframe
에서 Web
Authentication API의 [[Create]](origin, options, sameOriginWithAncestors)
및 [[DiscoverFromExternalSource]](origin, options, sameOriginWithAncestors)
메서드 호출을 허용하려면,
allow
속성을
iframe
요소에 지정하고
publickey-credentials-create
또는
publickey-credentials-get
feature-identifier 토큰을 각각
allow
속성 값에 포함시켜야 합니다.
Relying Party가 WebAuthn API를 임베디드 컨텍스트에서 사용하는 경우 § 13.4.2 임베디드 사용의 가시성 고려사항에서 UI 변조 및 이에 대한 가능한 완화책에 대해 검토해야 합니다.
5.11. 관련 origin 간 Web Authentication 사용하기
기본적으로 Web Authentication은 RP ID가 origin의 effective domain과 같거나, 등록 가능한 도메인 접미사여야 합니다.
이로 인해 여러 국가별 도메인(example.com, example.co.uk, example.sg 등)이나 대체/브랜드 도메인(myexampletravel.com, examplecruises.com 등), 또는 플랫폼 서비스 제공업체를 사용하는 대규모 환경에서 배포가 어려울 수 있습니다.
WebAuthn Relying Parties는 관련 WebAuthn Clients가 여러 origin에 걸쳐 credential을 생성/사용할 수 있도록 선택적으로 허용할 수 있습니다. 이러한 Relying Party는 모든 origin에서 공통된 RP ID를 사용해야 합니다.
JSON 문서는 해당 webauthn well-known URL [RFC8615]에, RP ID에 대해 HTTPS로 반드시 제공되어야 하며, 응답은 아래와 같아야 합니다:
-
콘텐츠 타입은
application/json이어야 합니다. -
최상위 JSON 객체에는
origins라는 키가 반드시 있어야 하며, 값은 하나 이상의 웹 origin 문자열 배열이어야 합니다.
예를 들어, RP ID가 example.com일 때:
{ "origins" : [ "https://example.co.uk" , "https://example.de" , "https://example.sg" , "https://example.net" , "https://exampledelivery.com" , "https://exampledelivery.co.uk" , "https://exampledelivery.de" , "https://exampledelivery.sg" , "https://myexamplerewards.com" , "https://examplecars.com" ] }
WebAuthn Clients가 이 기능을 지원할 경우 최소 다섯 개의 등록 가능한 origin 라벨을 지원해야 합니다. 클라이언트 정책에 따라 상한선을 규정할 수 있습니다.
이 well-known endpoint에 대한 WebAuthn Client의 요청은 credentials 없이, referrer 없이,
https: 스킴으로 해야 합니다. 리디렉트가 발생하면, WebAuthn
Client는 모든 리디렉트가 https: 스킴을 사용할 것을
명확히 요구해야 합니다.
WebAuthn Client가 이 기능을
지원한다면 getClientCapabilities()에 대한 응답에 relatedOrigins
를 반드시 포함해야 합니다.
5.11.1. 관련 origin 검증
관련 origin 검증 절차는 callerOrigin과 rpIdRequested를 인자로 아래와 같이 동작합니다:
-
maxLabels를 클라이언트 정책에서 허용하는 등록 가능한 origin 라벨 최대 수로 합니다.
-
RP ID rpIdRequested에 대해
webauthnwell-known URL [RFC8615] (https://rpIdRequested/.well-known/webauthn)을 credentials 없이, referrer 없이,https:스킴으로 가져옵니다.-
가져오기에 실패하거나 응답의 콘텐츠 타입이
application/json이 아니거나 리디렉트 이후 최종 상태 코드가 200이 아니면, "SecurityError"DOMException을 throw합니다. -
리소스 본문이 올바른 JSON 객체가 아니면, "
SecurityError"DOMException을 throw합니다. -
JSON 객체의 origins 속성이 없거나 문자열 배열이 아니면, "
SecurityError"DOMException을 throw합니다.
-
-
labelsSeen을 새로운 빈 집합(set)으로 생성합니다.
-
각 originItem에 대해 다음을 수행합니다:
-
url을 URL 파서로 originItem을 입력값으로 실행한 결과로 합니다. 실패 시 continue 합니다.
-
domain을 effective domain of url로 합니다. null이면 continue 합니다.
-
label을 등록 가능한 origin 라벨 of domain으로 합니다.
-
label이 비어있거나 null이면 continue 합니다.
-
labelsSeen의 크기가 maxLabels 이상이고 labelsSeen에 label이 없으면 continue 합니다.
-
callerOrigin과 url이 동일 origin인 경우,
true를 반환합니다.
-
-
false를 반환합니다.
6. WebAuthn 인증기 모델
Web Authentication API는 WebAuthn 인증기의 구체적인 추상 동작 모델을 내포하고 있습니다. 본 절에서는 인증기 모델을 설명합니다.
클라이언트 플랫폼은 이 추상 모델을 자유롭게 구현하거나 노출할 수 있습니다. 단, 해당 플랫폼이 지원하는 인증기에서 동작하는 Web Authentication API의 동작은 § 5 Web Authentication API에 명시된 동작과 구별 불가능해야 합니다.
Note: [FIDO-CTAP]은 본 모델의 구체적 실체화 예시이지만, 반환 데이터가 WebAuthn API의 알고리즘에서 기대하는 것과 차이가 있습니다. CTAP2 응답 메시지는 문자열 키 대신 정수 키로 CBOR 맵을 구성합니다. 클라이언트가 이러한 데이터 변환을 담당합니다. [FIDO-CTAP] 명세의 §6. Authenticator API에 CTAP2 정수 키와 WebAuthn 문자열 키 매핑이 명시되어 있습니다.
인증기의 경우, 본 모델은 지원해야 할 논리 연산과 클라이언트 및 WebAuthn Relying Party에 노출해야 할 데이터 형식을 정의합니다. 단, 클라이언트 디바이스와의 통신 방법은 상호운용성에 꼭 필요한 부분이 아니라면 정의하지 않습니다. 예를 들어, USB, NFC 등 전송 방식에 대한 프로토콜은 정의하지 않습니다. 또한, 구체적인 오류 코드 유형이나 반환 방법을 정의하지 않지만, 클라이언트가 요구하는 수준에서 오류 동작을 정의합니다. 따라서, 특정 오류 코드가 본문에 언급되더라도, 구현 상 서로 구별(또는 구별하지 않아도 됨)을 보장해야 합니다.
Relying Party는 필요시 다양한 인증기 특성을 지정하여 credentials 생성이나 assertion 생성 시 인증기 선택에 영향을 줄 수 있습니다. 해당 과정은 자격 증명 생성 옵션 또는 assertion 옵션을 통해 이루어집니다. 이런 옵션은 WebAuthn API의 알고리즘이 마샬링하여 아래 정의된 인증기 연산에 전달됩니다.
이 추상 모델에서 인증기는 키 관리와 암호학적 서명을 담당합니다. 인증기는 WebAuthn 클라이언트에 내장될 수도 있고, 별도의 디바이스에 완전히 분리될 수도 있습니다. 인증기 자체는 종종 고신뢰 하드웨어 모듈(예: TPM)을 포함할 수도 있습니다. 특히 인증기가 WebAuthn 클라이언트에 내장된 경우 이 암호 모듈은 나머지 인증기보다 신뢰도가 더 높을 수 있습니다.
각 인증기는 (rpId, userHandle) 쌍에서 public key credential source로의 credentials map (ordered map)을 저장합니다.
또한 각 인증기는 인증기의 종류(제조사, 모델 등)를 나타내는 128비트 식별자인 Authenticator Attestation Globally Unique Identifier 또는 AAGUID를 가집니다. AAGUID는 제조사가 실질적으로 같은 모든 인증기에서 반드시 동일해야 하며, 다른 종류의 인증기와는 (매우 높은 확률로) 달라야 합니다. 각 인증기 종류의 AAGUID는 무작위로 생성하는 것이 바람직합니다. Relying Party는 인증기의 AAGUID를 통해 인증 수준이나 키 보호 강도 등 속성을 다른 출처 정보를 활용하여 추론할 수 있습니다. Relying Party는 attestation을 요청·검증하지 않고도 인증기 제조사가 누구인지 AAGUID로 추정할 수 있으나, attestation이 없는 한 AAGUID는 증명력이 없습니다.
인증기의 주요 기능은 다양한 컨텍스트 데이터에 바인딩된 WebAuthn 서명을 제공하는 것입니다. 이 데이터들은 서버에서 인증기로 서명 요청이 전달되는 과정 중 스택의 여러 수준에서 관찰·추가됩니다. 서버는 서명 검증 과정에서 해당 바인딩이 예상값과 일치하는지를 확인합니다. 이러한 컨텍스트 바인딩은 Relying Party 또는 클라이언트가 추가하는 클라이언트 데이터와, 인증기가 추가하는 인증기 데이터로 구분됩니다. 인증기는 클라이언트 데이터 전체가 아닌 그 해시값만 서명에 사용하고, 인증기 데이터를 조합해 전체에 서명합니다. (이는 인증기의 대역폭과 처리 요구사항을 최소화하기 위한 것입니다.)
이 설계의 목표는 다음과 같이 요약할 수 있습니다.
-
서명 생성 방식은 클라이언트 디바이스와 인증기 간 연결 대역폭 또는 지연이 매우 제한적인 경우(예: 블루투스 LE, 근거리 무선통신 등)도 지원해야 합니다.
-
인증기가 처리하는 데이터는 작고, 저수준 코드에서도 쉽게 해석할 수 있어야 합니다. 특히 인증기는 JSON과 같은 고수준 인코딩을 직접 파싱할 필요가 없어야 합니다.
-
클라이언트와 인증기 모두 상황에 따라 컨텍스트 바인딩을 자유롭게 추가할 수 있어야 합니다.
-
주요 인코딩 포맷을 재사용하여 도입 및 구현을 용이하게 하는 설계를 지향합니다.
인증기는 암호학적 서명을 두 가지 목적으로 생성합니다:
-
Attestation signature(인증 서명)은 public key credential이 authenticatorMakeCredential로 생성될 때 생성됩니다. 인증 서명은 인증기(그의 AAGUID로 표기)와 자격 증명(credential public key 등)의 특정 특성을 증명합니다. 인증 서명은 필요한 경우 attestation private key로 서명되며, attestation 유형에 따라 키 선택이 달라집니다. Attestation에 대한 자세한 내용은 § 6.5 Attestation을 참고하십시오.
-
Assertion signature(주장 서명)은 authenticatorGetAssertion이 호출될 때 생성됩니다. 이것은 인증기가 사용자가 특정 트랜잭션(예: 로그인, 결제)에 명시적 동의했음을 확언(주장)하는 서명입니다. 즉, assertion signature는 특정 credential private key를 가진 인증기가 해당 트랜잭션을 요청하는 사용자가 그 credential 생성을 동의한 것과 동일인임을 (최선의 노력으로) 보장합니다. 또한 클라이언트 데이터 등 추가 정보를 제공하며, 사용자 동의 방식 및 인증기가 표시한 프롬프트 등도 포함할 수 있습니다. assertion signature의 형식은 아래 Figure 4를 참고하십시오.
WebAuthn signature라는 용어는 인증 서명과 주장 서명 모두를 지칭합니다. 이 서명들의 형식 및 생성 절차는 아래서 명시합니다.
6.1. 인증기 데이터
인증기 데이터 구조는 인증기가 만든 컨텍스트적 바인딩을 인코딩합니다. 이 바인딩은 인증기 자체에서 제어하며, 인증기의 보안 특성에 대한 WebAuthn Relying Party의 평가에 따라 신뢰도가 결정됩니다. 경우에 따라 인증기가 클라이언트에 내장되어 있을 수 있고, 그 바인딩의 신뢰도는 클라이언트 데이터와 다를 바 없을 수 있습니다. 반대로, 인증기가 독립된 고보안 하드웨어와 소프트웨어를 갖춘 장치로, 클라이언트와 안전한 채널로 연결될 수도 있습니다. 두 경우 모두 Relying Party는 같은 형식의 인증기 데이터를 받아, 그 인증기에 대한 지식으로 신뢰 판단을 내립니다.
인증기 데이터는 간결하지만 확장 가능한 인코딩을 가지고 있습니다. 이는 인증기가 단순한 소프트웨어 스택과 낮은 전력 소비 등 매우 제한적인 기능의 장치일 수 있기 때문에 필요합니다. 클라이언트 플랫폼보다 훨씬 단순할 수 있습니다.
인증기 데이터 구조는 37 바이트 이상의 바이트 배열이며, 표 와 같이 구성됩니다.
| 이름 | 길이 (바이트) | 설명 |
|---|---|---|
| rpIdHash | 32 | RP ID의 SHA-256 해시 값. 해당 자격 증명이 스코프되는 RP ID 입니다. |
| flags | 1 |
플래그 (0번 비트가 가장 하위 비트):
|
| signCount | 4 | 서명 카운터, 32비트 부호 없는 빅엔디언 정수. |
| attestedCredentialData | 가변형 (존재하는 경우) | Attested credential data (존재할 때). 자세한 사항은 § 6.5.1 Attested Credential Data를 참고하세요. 길이는 credential ID 및 credential public key의 크기에 따라 달라집니다. |
| extensions | 가변형 (존재하는 경우) | 확장에서 정의한 인증기 데이터. 이는 CBOR [RFC8949] 맵이며, 확장 식별자를 키로, authenticator extension output을 값으로 가지고 있습니다. 자세한 내용은 § 9 WebAuthn Extensions 참고. |
RP ID는 자격 증명 생성 시 클라이언트로부터 수신되며, 어설션이 생성될 때도 다시 전달됩니다. 하지만 아래와 같은 중요한 면에서 클라이언트 데이터와 다룹니다. 첫째, 클라이언트 데이터와 달리, 자격 증명의 RP ID는 연산 사이에 바뀌지 않으며 자격 증명의 수명 동안 동일하게 유지됩니다. 둘째, 인증기는 authenticatorGetAssertion 동작에서, 요청된 자격 증명이 스코프된 RP ID와 클라이언트가 제공한 RP ID가 정확히 일치하는지 확인하여 이것을 검증합니다.
인증기는 다음 절차로 인증기 데이터 구조를 생성합니다:
-
UP 플래그는 인증기가 사용자 존재 판별을 수행한 경우에만 설정되어야 합니다. UV 플래그는 인증기가 사용자 확인을 수행한 경우에만 설정됩니다.
RFU비트는 항상 0으로 설정되어야 합니다.Note: 인증기가 사용자 존재 판별과 사용자 확인을 모두 수행했다면, (예: 하나의 승인 제스처로 함께 수행) UP 플래그와 UV 플래그를 모두 설정합니다.
-
BE 플래그는 해당 자격 증명이 다중 기기 자격 증명일 때만 설정되어야 합니다. 이 값은 등록 의식 후엔 변하지 않아야 합니다. 관련 내용은 § 6.1.3 Credential Backup State 참고.
-
BS 플래그는 자격 증명이 다중 기기 자격 증명이면서, 현재 백업된 상태일 때만 설정되어야 합니다.
자격 증명의 백업 상태가 불확실하거나, 인증기가 백업된 자격 증명에 문제가 있다고 의심하는 경우 BS 플래그는 설정하지 않아야 합니다.
-
Attestation signature의 경우 인증기는 반드시 AT 플래그를 설정하고
attestedCredentialData를 포함해야 합니다. Assertion signature에서는 AT 플래그를 설정하거나attestedCredentialData를 포함해서는 안 됩니다. -
인증기가 확장 데이터를 포함하지 않으면 ED 플래그를 0으로, 확장 데이터가 포함되면 1로 설정해야 합니다.
Attested
credential data의 길이 결정은,
credentialPublicKey가
credentialId
길이 뒤에 어디서 시작하는지 결정하고,
credentialPublicKey의
길이를 구하는 과정이 필요합니다 (자세한 내용은 Section 7 of [RFC9052] 참고).
6.1.1. 서명 카운터 관련 사항
인증기는 서명 카운터 기능을 구현하는 것이
권장됩니다. 이 카운터들은 개념적으로 인증기의 각 자격 증명 단위 또는 인증기 전체에서 저장됩니다. 각 자격 증명의 서명 카운터의 초기 값은 authenticator data의
signCount
값으로 지정됩니다. 서명 카운터는 authenticatorGetAssertion 연산이 성공할 때마다 0 이상의 값만큼 증가하며, 그 이후
값들이 다시 WebAuthn
Relying Party에 authenticator data로 반환됩니다. 서명 카운터의 목적은 Relying Party가 복제된 인증기를 탐지할 수 있도록 돕는 것입니다. 복제
탐지는 보호 조치가 약한 인증기일수록 더 중요합니다.
서명 카운터 기능을 구현하지 않는 인증기의
경우 authenticator
data의
signCount는
항상 0으로 고정됩니다.
Relying Party는 authenticatorGetAssertion 작업의 가장 최근 서명 카운터를 저장합니다. (또는 해당 자격 증명에 대해 아직 authenticatorGetAssertion이 수행된 적이 없다면 authenticatorMakeCredential 연산 결과의 카운터를 저장.) 이후 authenticatorGetAssertion 작업에서 Relying Party는 저장된 서명 카운터 값과 이번 어설션에서 반환된
signCount
값을 비교합니다. 둘 중 하나라도 0이 아니면서 새로운
signCount가
저장된 값 이하일 경우,
인증기가 복제되었거나, 인증기에 문제가 있거나, 어설션이 생성된 순서와 다르게 RP에서 처리되어 경쟁 상태가 발생한 것일 수 있습니다.
서명 카운터 불일치 탐지 시, 현재 연산이 복제 인증기로 수행된 것인지, 원본 인증기에서 수행된 것인지는 알 수 없습니다. Relying Party는 자사 위험 허용치 및 운영 요인을 고려하여 이런 상황을 적절히 처리해야 합니다.
인증기 권장 사항:
-
자격 증명 단위 서명 카운터를 구현해야 합니다. 이는 서명 카운터 값이 여러 Relying Party에서 공유되어 사용자가 상관 식별자로 활용될 위험을 방지합니다. 인증기는 글로벌 서명 카운터 (즉, 인증기 단위 전체)도 구현할 수 있으나, 이것은 사용자의 프라이버시 보호에는 덜 바람직합니다.
-
서명 카운터 값이 실수로 감소하지 않도록 보장해야 합니다 (예: 하드웨어 오류 등으로 인한 하락 방지).
6.1.2. FIDO U2F 서명 형식 호환성
Assertion signature는 인증기 데이터 구조와 클라이언트 데이터 해시를 연결해 서명하는데, 이 형식은 FIDO U2F 인증 서명 형식과 호환됩니다 (자세한 내용은 Section 5.4, [FIDO-U2F-Message-Formats] 참고).
이는 FIDO U2F 인증 응답 메시지에서 서명된 데이터의 처음 37바이트가 유효한 인증기 데이터 구조이고, 나머지 32바이트가 클라이언트 데이터 해시이기 때문입니다. 이 인증기 데이터 구조에서
rpIdHash는
FIDO U2F의 application 파라미터에 해당하며, 모든
flags는
UP을 제외하고
항상 0입니다.
attestedCredentialData와
extensions는
나타나지 않습니다. 따라서 FIDO U2F 인증 서명도 authenticatorGetAssertion 동작이 생성한 일반 assertion
signature와 동일한 검증 절차로 검증할 수 있습니다.
6.1.3. 자격 증명 백업 상태
자격 증명의 백업 가능성과 현재 백업 상태는 BE, BS 플래그로 인증기 데이터에 전달되며, 표 에 명시되어 있습니다.
BE 플래그 값은 authenticatorMakeCredential 동작 중 설정되며, 이후 변경될 수 없습니다.
BS 플래그 값은 공개 키 자격 증명 소스의 상태에 따라 시간이 지남에 따라 변할 수 있습니다. 아래 표 에 유효 조합 및 의미가 정의되어 있습니다.
| BE | BS | 설명 |
|---|---|---|
0
| 0
| 해당 자격 증명은 단일 기기 자격 증명입니다. |
0
| 1
| 이 조합은 허용되지 않습니다. |
1
| 0
| 이 자격 증명은 다중 기기 자격 증명이며, 현재 백업되지 않음 상태입니다. |
1
| 1
| 이 자격 증명은 다중 기기 자격 증명이며, 현재 백업됨 상태입니다. |
Relying Party는 향후 평가를 위해 최신 플래그 값을 사용자 계정과 함께 저장하는 것이 권장됩니다.
아래는 Relying Party가 이러한 플래그를 활용하는 비한정 리스트입니다:
-
추가 인증기 요구:
BE 플래그가
0이면, 해당 자격 증명은 단일 기기 자격 증명이며, 생성 인증기는 이를 백업할 수 없습니다.단일 기기 자격 증명은 단일 장치 분실에 취약합니다. Relying Party는 각 사용자 계정에 추가 인증기 등록 또는 계정 복구 수단이 있도록 해야 합니다. 예를 들어, 사용자가 추가 인증기(예: 이동형 인증기 혹은 다중 기기 인증 가능 인증기)를 설정하도록 안내할 수 있습니다.
-
사용자 패스워드 없는 계정으로 업그레이드:
BS 플래그가
0에서1로 전환되면, 인증기는 해당 자격 증명이 백업되어 단일 장치 분실로부터 보호됨을 알립니다.Relying Party는 사용자가 계정 보안을 강화하고 패스워드를 제거하도록 안내할 수 있습니다.
-
상태 변화 후 추가 인증 요인 요구:
BS 플래그가
1에서0으로 전환되면, 인증기는 해당 자격 증명이 더 이상 백업되지 않으며 단일 장치 분실에 취약함을 알립니다. 이는 사용자가 백업 서비스를 비활성화했거나, 백업 서비스에 문제가 있어 발생할 수 있습니다.이런 전환이 발생할 경우 Relying Party는 사용자가 다른 인증 요인을 검증하도록 안내해야 합니다. 만약 계정에 다른 자격 증명이 없다면, 사용자가 계정 접근권을 잃지 않도록 추가 자격 증명 등록을 안내해야 합니다. 예를 들어, 추가 인증기(이동형 인증기 혹은 다중 기기 지원 인증기)를 설정하도록 안내할 수 있습니다.
6.2. 인증기 분류
많은 사용 사례는 사용된 authenticator의 기능에 따라 달라집니다. 이 절에서는 그러한 기능들, 그중 중요한 조합들, 그리고 그 조합들이 어떤 사용 사례를 가능하게 하는지를 정의합니다.
예를 들면:
-
특정 client device에서 처음 인증할 때에는, 사용자가 그 client device에 아직 platform credential을 가지고 있지 않으므로 일반적으로 roaming authenticator가 필요합니다.
-
같은 client device에서 이후 재인증을 할 때에는, platform authenticator가 별도의 장치를 찾아야 하는 번거로움이 없기 때문에 가장 편리할 가능성이 높습니다.
-
전통적인 사용자 이름과 비밀번호 외의 second-factor 인증의 경우에는 어떤 authenticator라도 사용할 수 있습니다.
-
비밀번호 없는 multi-factor 인증은 authenticator가 user verification을 수행할 수 있어야 하며, 경우에 따라 discoverable credential capable일 필요도 있습니다.
-
노트북은 USB와 Bluetooth를 통해 roaming authenticators에 연결을 지원할 수 있는 반면, 휴대전화는 NFC만 지원할 수 있습니다.
위 예시는 주요 authenticator type 특성을 설명합니다:
-
authenticator가 roaming인지 platform인지, 또는 경우에 따라 둘 다인지 — 즉 authenticator attachment modality. roaming authenticator는 전송 방식 하나 이상을 지원하여 client와 통신할 수 있습니다.
-
인증기가 user verification을 수행할 수 있는지 여부 — 즉 authentication factor capability.
-
인증기가 discoverable credential capable인지 여부 — 즉 credential storage modality.
이 특성들은 서로 독립적이며 이론적으로는 어떤 방식으로든 조합될 수 있지만, 표 는 특별히 주목할 만한 몇몇 authenticator types의 이름과 조합을 나열합니다.
| Authenticator Type | Authenticator Attachment Modality | Credential Storage Modality | Authentication Factor Capability |
|---|---|---|---|
| Second-factor platform authenticator | platform | Either | Single-factor capable |
| User-verifying platform authenticator | platform | Either | Multi-factor capable |
| Second-factor roaming authenticator | cross-platform | Server-side storage | Single-factor capable |
| Passkey roaming authenticator | cross-platform | Client-side storage | Multi-factor capable |
| Passkey platform authenticator | platform (transport
= internal)
or cross-platform (transport
= hybrid)
| Client-side storage | Multi-factor capable |
second-factor platform authenticator는 동일한 client device의 재인증에 편리하며, 새 세션을 시작하거나 기존 세션을 재개할 때 추가적인 보안 계층을 제공하는 데 사용할 수 있습니다. second-factor roaming authenticator는 특정 client device에서 처음 인증하거나, 여러 사용자가 공유하는 client device에서 사용하는 경우에 더 자주 사용될 것입니다.
Passkey platform authenticators와 passkey roaming authenticators는 비밀번호 없는 multi-factor 인증을 가능하게 합니다. credential private key의 소유 증명에 더해, 이러한 인증기들은 일반적으로 PIN 또는 biometric recognition과 같은 두번째 authentication factor로서 user verification을 지원합니다. 따라서 authenticator는 두 종류의 authentication factor로 동작할 수 있어, 비밀번호를 Relying Party와 공유할 필요 없이 multi-factor 인증을 가능하게 합니다. 이러한 인증기들은 또한 discoverable credentials(일명 passkeys)를 지원하므로, 사용자명 입력이 필요 없는 인증 흐름도 지원합니다.
user-verifying platform authenticator 클래스는
주로 passkey platform authenticator 클래스에 의해 대체되었지만,
이 정의는 isUserVerifyingPlatformAuthenticatorAvailable
메서드에서 여전히 사용됩니다.
표 에 명시되지 않은 조합들은 사용 사례가 덜 분명합니다:
-
roaming authenticator가 discoverable credential capable이지만 multi-factor capable이 아닌 경우, 사용자명 없이 single-factor 인증에 사용할 수 있으며, 이 경우 사용자는 user handle과 credential private key의 소유만으로 자동으로 식별됩니다. 이는 일부 상황에서 유용할 수 있지만, authenticator가 도난당할 경우 사용자가 특히 취약해집니다.
-
roaming authenticator가 multi-factor capable이지만 discoverable credential capable이 아닌 경우에는 multi-factor 인증에 사용할 수 있지만, 먼저 사용자를 식별해야 하므로 개인 식별 정보가 유출될 위험이 있습니다; 자세한 내용은 § 14.6.3 크리덴셜 ID를 통한 프라이버시 노출를 참조하십시오.
다음 하위 절들에서는 authenticator attachment modality, credential storage modality 및 authentication factor capability의 측면을 더 자세히 정의합니다.
6.2.1. Authenticator Attachment Modality
Clients는 다양한 방식으로 authenticators와 통신할 수 있습니다. 예를 들어, client는 client device 고유의 API를 사용하여 해당 authenticator와 통신할 수 있습니다. 반면에, client는 Bluetooth와 같은 표준화된 크로스 플랫폼 전송 프로토콜(참조: § 5.8.4 Authenticator Transport Enumeration (enum AuthenticatorTransport))을 사용하여 cross-platform attached authenticators를 검색하고 통신할 수 있습니다. 우리는 authenticators가 client device의 일부인 경우 이를 platform authenticators라고 부르며, 크로스 플랫폼 전송 프로토콜로 접근 가능한 인증기는 roaming authenticators라고 부릅니다.
-
platform authenticator는 client device 고유의 전송을 사용하여 부착되며, 이를 platform attachment라고 합니다. 보통 client device에서 제거할 수 없습니다. public key credential이 platform authenticator에 bound된 경우 이를 platform credential이라고 합니다.
-
roaming authenticator는 크로스 플랫폼 전송을 사용하여 부착되며, 이를 cross-platform attachment라고 합니다. 이 클래스의 인증기는 client devices에서 분리할 수 있고 서로 "로밍"할 수 있습니다. public key credential이 roaming authenticator에 bound된 경우 이를 roaming credential이라고 합니다.
일부 platform authenticators는 상황에 따라 roaming authenticators로 동작할 수도 있습니다. 예를 들어, 모바일 기기에 통합된 platform authenticator는 Bluetooth를 통해 스스로를 roaming authenticator로 제공할 수 있습니다. 이 경우 모바일 기기에서 실행되는 clients는 해당 인증기를 platform authenticator로 인식하는 반면, 다른 clients가 다른 client device에서 동일한 인증기와 Bluetooth로 통신할 때에는 이를 roaming authenticator로 인식하게 됩니다.
platform authenticators의 주요 사용 사례는 특정 client device를 "신뢰된 장치"로 등록하는 것입니다. 즉 client device 자체가 향후 something you have authentication factor로 동작하도록 하는 것입니다. 이렇게 하면 사용자는 향후 authentication 절차에서 roaming authenticator를 찾을 필요가 없으므로 편리합니다(예: 주머니에서 키 고리나 휴대전화를 꺼낼 필요가 없음).
로밍 인증기의 사용 사례에는 다음이 포함됩니다: 새로운 클라이언트 장치에서 처음으로 인증을 할 때, 거의 사용하지 않는 클라이언트 장치에서 사용할 때, 여러 사용자가 공유하는 클라이언트 장치에서 사용할 때, 또는 플랫폼 인증기가 포함되지 않은 클라이언트 장치에서 사용할 때가 있습니다. 또한 정책이나 사용자 선호에 따라 인증기를 사용하는 클라이언트 장치와 분리하여 보관해야 할 때도 해당됩니다. 로밍 인증기는 다른 인증기를 분실한 경우를 대비해 백업 크리덴셜을 보관하는 용도로도 사용할 수 있습니다.
6.2.2. Credential Storage Modality
authenticator는 public key credential source를 두 가지 방식 중 하나로 저장할 수 있습니다:
-
authenticator, client 또는 client device에 내장된 영구 저장소에 저장하는 방식(예: secure element). 이 방식은 client-side discoverable public key credential source의 기술적 요구사항입니다.
-
public key credential source를 암호화(랩핑)하여 오직 이 authenticator만이 복호화(언랩핑)할 수 있게 하고, 그 결과 생성된 암호문을 credential ID로 두는 방법. 이 credential ID는 Relying Party에 의해 저장되며, authenticator에게
allowCredentials옵션으로 반환됩니다(참조:get()). 이를 통해 authenticator가 해당 public key credential source를 복호화하고 사용할 수 있습니다.이 방식은 암호화된 public key credential sources가 Relying Party에 의해 저장되므로, authenticator의 저장 용량이 사실상 무제한이 될 수 있게 합니다 — 하지만 이러한 방식으로 저장된 credential은 Relying Party로부터 먼저 검색되어야만 authenticator가 이를 사용할 수 있습니다.
어떤 저장 전략을 지원하는지에 따라 authenticator의 credential storage modality가 다음과 같이 정의됩니다:
-
authenticator가 client-side credential storage modality를 갖는 경우는 client-side discoverable public key credential sources를 지원할 때입니다. authenticator가 client-side credential storage modality를 가지면, 이를 discoverable credential capable라고도 합니다.
-
authenticator가 server-side credential storage modality를 가지는 경우는 client-side credential storage modality를 갖고 있지 않아, 즉 public key credential sources를 오직 credential ID로서 암호문 형태로만 저장하는 것을 지원할 때입니다.
참고로 discoverable credential capable한 authenticator는 두 가지 저장 전략을
모두 지원할 수 있습니다. 이 경우 authenticator는 자의 재량으로 서로 다른 credentials에 대해 서로 다른 저장 전략을 사용할
수 있지만, 이는 residentKey
및 requireResidentKey
옵션을 포함한 create()의
제약을 따릅니다.
6.2.3. Authentication Factor Capability
인증식(authentication ceremony) 동안 신원을 증명하는 데 사용할 수 있는 세 가지 넓은 범주의 authentication factors가 있습니다: something you have, something you know 및 something you are입니다. 예로는 각각 물리적 키, 비밀번호, 지문 등이 있습니다.
모든 WebAuthn Authenticators는 something you have 범주에 속하지만, authenticator가 user verification을 지원하면 추가로 하나 또는 두 가지 다른 유형의 authentication factor로도 동작할 수 있습니다. 예를 들어, authenticator가 PIN을 검증할 수 있다면, 그 PIN은 something you know이고, biometric authenticator는 something you are을 검증할 수 있습니다. 따라서 authenticator가 user verification을 지원하면, 이를 multi-factor capable라고 합니다. 반대로 authenticator가 multi-factor capable이 아니면 single-factor capable입니다. 단일 multi-factor capable 인증기는 여러 모드의 user verification을 지원할 수 있으므로, 세 가지 종류의 authentication factor를 모두 수행할 수 있습니다.
user verification은 authenticator에서 로컬로 수행되며 Relying Party에 의해 수행되지 않지만, authenticator는 서명된 응답에서 UV flag를 설정하여 user verification이 수행되었는지를 표시합니다. 따라서 Relying Party는 UV flag를 사용하여 등록(registration) 또는 인증식(authentication ceremony)에서 추가적인 authentication factors가 사용되었는지를 확인할 수 있습니다. UV flag의 진위는 다시 authenticator의 attestation statement를 검사하여 평가할 수 있습니다.
6.3. Authenticator Operations
WebAuthn Client는 해당 인증기의 어떠한 작업도 호출하기 위해 반드시 인증기와 연결해야 합니다. 이 연결은 authenticator session을 정의합니다. 인증기는 세션 간의 격리를 유지해야 합니다. 이는 한 번에 하나의 세션만 허용하거나 더 복잡한 세션 관리를 제공함으로써 달성할 수 있습니다.
다음 작업들은 클라이언트가 authenticator session에서 호출할 수 있습니다.
6.3.1. Lookup Credential Source by Credential ID Algorithm
credential id를 조회(looking up)한 결과로서 credential id credentialId를 authenticator authenticator에서 찾는 결과는 다음 알고리즘의 결과입니다:
-
만약 authenticator가 credentialId를 복호화하여 public key credential source credSource로 만들 수 있다면:
-
credSource.id를 credentialId로 설정합니다.
-
credSource를 반환합니다.
-
-
각각(For each) public key credential source credSource에 대하여, 이것이 authenticator의 credentials map에 포함되어 있으면:
-
만약 credSource.id가 credentialId이면, credSource를 반환합니다.
-
-
null을 반환합니다.
6.3.2. The authenticatorMakeCredential Operation
이 작업을 호출하기 전에, 클라이언트는 반드시 authenticatorCancel 작업을 호출하여 authenticator session에서 진행 중인 다른 모든 작업을 중단해야 합니다.
이 작업은 다음 입력 매개변수를 받습니다:
- hash
-
클라이언트가 제공한 직렬화된 client data의 해시.
- rpEntity
- userEntity
-
user account의
PublicKeyCredentialUserEntity, 여기에는 user handle가 포함됩니다. - requireResidentKey
-
credential 생성에 대한 유효한 resident key 요구로, client에 의해 결정되는 Boolean 값입니다.
- requireUserPresence
-
상수 Boolean 값
true또는 FALSE (만약options.가mediationconditional로 설정되고 사용자 에이전트가 이전에 사용자 동의를 수집한 경우). - requireUserVerification
-
credential 생성에 대한 유효한 user verification 요구로, client에 의해 결정되는 Boolean 값입니다.
- credTypesAndPubKeyAlgs
-
PublicKeyCredentialType와 공개키 알고리즘(COSEAlgorithmIdentifier)의 쌍으로 이루어진 시퀀스이며, 이는 Relying Party가 요청한 것입니다. 이 시퀀스는 선호도 순으로 정렬되어 있으며, authenticator는 지원 가능한 가장 선호되는 credential을 만들기 위해 최선을 다합니다. - excludeCredentialDescriptorList
-
선택적(OPTIONAL)으로 제공되는
PublicKeyCredentialDescriptor객체의 목록으로, Relying Party가 이들 중 어떤 것이 인증기에서 알려져 있다면 새 credential을 생성하지 않도록 의도한 것입니다. excludeCredentialDescriptorList는 알려진 credential들의 목록을 포함합니다. - enterpriseAttestationPossible
-
개별 식별 가능한 attestation이 인증기에 의해 반환될 수 있음을 나타내는 Boolean 값.
- attestationFormats
-
Relying Party의 attestation statement 형식 선호도를 가장 선호하는 것부터 덜 선호하는 것 순으로 표현한 문자열 시퀀스입니다. 만약 authenticator가 attestation을 반환하면, 지원하는 가장 선호되는 형식을 사용하려고 최선을 다합니다.
- extensions
-
CBOR map으로, extension identifiers를 키로 하고 해당 authenticator extension inputs을 값으로 가지며, 클라이언트가 Relying Party가 요청한 확장에 기반하여 생성합니다(있다면).
이 작업이 호출되면, authenticator는 다음 절차를 반드시 수행해야 합니다:
-
제공된 모든 매개변수가 문법적으로 올바르고 길이가 적절한지 확인합니다. 그렇지 않으면 "
UnknownError"와 동등한 오류 코드를 반환하고 작업을 종료합니다. -
PublicKeyCredentialType와 credTypesAndPubKeyAlgs에 있는 암호학적 매개변수들의 조합 중 적어도 하나가 지원되는지 확인합니다. 지원되지 않으면 "NotSupportedError"와 동등한 오류 코드를 반환하고 작업을 종료합니다. -
각 descriptor에 대해 excludeCredentialDescriptorList:
-
만약 이 인증기에서 looking up을 수행한 결과
descriptor.가 null이 아니고, 반환된 항목의 item의 RP ID 및 type이idrpEntity.및idexcludeCredentialDescriptorList.와 각각 일치하면, 새 credential 생성에 대한 사용자 동의를 확인하는 authorization gesture을 수집합니다. 이 authorization gesture에는 반드시 test of user presence가 포함되어야 합니다. 사용자가type- 새 credential 생성에 동의하면
-
"
InvalidStateError"와 동등한 오류 코드를 반환하고 작업을 종료합니다. - 새 credential 생성에 동의하지 않으면
-
"
NotAllowedError"와 동등한 오류 코드를 반환하고 작업을 종료합니다.
Note: 이 authorization gesture의 목적은 credential을 생성하는 것이 아니라, 프라이버시상의 이유로
descriptor.가 이 authenticator에 바인딩되어 있다는 사실의 공개를 허용하는 것입니다. 만약 사용자가 동의하면, client와 Relying Party는 이를 감지하고 사용자가 다른 authenticator를 사용하도록 안내할 수 있습니다. 사용자가 동의하지 않으면, authenticator는iddescriptor.가 자신에게 바인딩되어 있다는 사실을 드러내지 않으며, 단순히 사용자가 credential 생성 동의를 거부한 것처럼 응답합니다.id
-
-
만약 requireResidentKey가
true이고 인증기가 client-side discoverable public key credential source를 저장할 수 없다면, "ConstraintError"와 동등한 오류 코드를 반환하고 작업을 종료합니다. -
만약 requireUserVerification가
true이고 인증기가 user verification을 수행할 수 없다면, "ConstraintError"와 동등한 오류 코드를 반환하고 작업을 종료합니다. -
새 credential 생성을 위한 사용자 동의(authorization gesture)을 수집합니다.
이 authorization gesture에 대한 프롬프트는 인증기에 자체 출력 기능이 있다면 인증기가
표시하고, 그렇지 않으면 사용자 에이전트가 표시합니다. 프롬프트는 가능한 경우
rpEntity.,idrpEntity.,nameuserEntity.및nameuserEntity.를 표시해야 합니다.displayName만약 requireUserVerification가
true이면, authorization gesture는 반드시 user verification을 포함해야 합니다.만약 requireUserPresence가
true이면, authorization gesture는 반드시 test of user presence를 포함해야 합니다.사용자가 동의하지 않거나 user verification이 실패하면 "
NotAllowedError"와 동등한 오류 코드를 반환하고 작업을 종료합니다. -
authorization gesture이 완료되어 user consent가 얻어진 후, 새 credential 객체를 생성합니다:
-
(publicKey, privateKey)를 이 인증기가 지원하는
PublicKeyCredentialType과 credTypesAndPubKeyAlgs의 첫 번째 지원 가능한 항목에서 표현된 암호 매개변수의 조합을 사용하여 생성된 새로운 암호 키 쌍으로 둡니다. -
userHandle를
userEntity.로 둡니다.id -
credentialSource를 다음 필드를 가진 새로운 public key credential source로 둡니다:
- type
- privateKey
-
privateKey
- rpId
-
rpEntity.id - userHandle
-
userHandle
- otherUI
-
인증기가 포함하기로 선택한 기타 정보.
-
만약 requireResidentKey가
true이거나 인증기가 client-side discoverable public key credential source 생성을 선택하면:-
credentialId를 새로운 credential id로 둡니다.
-
credentialSource.id를 credentialId로 설정합니다.
-
credentials를 이 인증기의 credentials map으로 둡니다.
-
Set credentials[(
rpEntity., userHandle)]를 credentialSource로 설정합니다.id
-
-
그렇지 않으면:
-
credentialId를 credentialSource를 직렬화하여 이 인증기만 복호화할 수 있도록 암호화한 결과로 둡니다.
-
-
-
새 credential 객체를 생성하는 동안 오류가 발생하면 "
UnknownError"와 동등한 오류 코드를 반환하고 작업을 종료합니다. -
processedExtensions를 authenticator extension processing의 결과로 둡니다(지원되는 각 extension identifier → authenticator extension input에 대해) 및 extensions에서 수행합니다.
-
만약 authenticator가:
- U2F 장치인 경우
-
새 credential에 대한 signature counter 값을 0으로 둡니다. (U2F 장치는 signature counter를 지원할 수 있지만 credential 생성 시 카운터를 반환하지 않습니다. 자세한 내용은 [FIDO-U2F-Message-Formats] 참조.)
- 글로벌 signature counter를 지원하는 경우
-
authenticator data를 생성할 때 글로벌 signature counter의 실제 값을 사용합니다.
- credential별 signature counter를 지원하는 경우
-
카운터를 할당하여 새 credential과 연관시키고 카운터 값을 0으로 초기화합니다.
- signature counter를 지원하지 않는 경우
-
새 credential에 대한 signature counter 값을 항상 0으로 둡니다.
-
attestedCredentialData를 credentialId 및 publicKey를 포함하는 attested credential data 바이트 배열로 둡니다.
-
attestationFormat을 attestationFormats에서 enterpriseAttestationPossible를 고려하여 지원되는 첫 번째 attestation statement format identifier로 둡니다. 만약 attestationFormats에 지원되는 값이 없다면, attestationFormat을 이 인증기가 가장 선호하는 attestation statement format identifier로 둡니다.
-
authenticatorData를 § 6.1 Authenticator Data에 지정된 바이트 배열로 둡니다. 여기에는 attestedCredentialData가
attestedCredentialData로 포함되고, 있으면 processedExtensions가extensions로 포함됩니다. -
새 credential을 위한 attestation object를 § 6.5.4 Generating an Attestation Object에 명시된 절차, attestation statement format attestationFormat 및 값 authenticatorData와 hash를 사용하여 생성합니다. 또한
enterpriseAttestationPossible값을 고려합니다. attestation에 대한 자세한 내용은 § 6.5 Attestation을 참조하십시오.
이 작업이 성공적으로 완료되면, 인증기는 attestation object를 클라이언트에 반환합니다.
6.3.3. authenticatorGetAssertion 작업
이 작업을 호출하기 전에, 클라이언트는 authenticatorCancel 작업을 호출하여 authenticator session 내에서 진행 중인 모든 다른 작업을 중단해야 한다.
이 작업은 다음 입력 매개변수를 가진다:
- rpId
- hash
-
클라이언트가 제공하는 직렬화된 클라이언트 데이터의 해시이다.
- allowCredentialDescriptorList
-
리스트이며,
PublicKeyCredentialDescriptor의 객체들의 OPTIONAL 리스트로 Relying Party가 허용하는 인증 정보를 (클라이언트에 의해 필터링되어 있을 수 있음) 설명한다. 제공되는 경우에 한함. - requireUserPresence
-
불리언 상수 값
true이다. 이는 WebAuthn에서는 필수가 아니더라도 구현에서 사용자 존재 확인을 선택적으로 적용할 수 있도록 하기 위하여 유사-매개변수로 포함되어 있다. - requireUserVerification
-
assertion에 대한 효과적인 사용자 검증 요건을 나타내는 불리언 값으로, 클라이언트가 제공한다.
- extensions
-
클라이언트가 Relying Party가 요청한 확장자에 따라 작성한 CBOR map으로, extension identifier를 그에 상응하는 authenticator extension input에 매핑한다.
이 메소드가 호출되면, authenticator는 다음 절차를 수행해야 한다:
-
제공된 모든 매개변수가 문법적으로 올바르고 길이가 적절한지 확인한다. 그렇지 않으면 "
UnknownError"에 해당하는 오류 코드를 반환하고 작업을 종료한다. -
credentialOptions를 새로운 빈 set으로 생성한다. 이 set에는 공개키 자격 증명 소스가 포함된다.
-
allowCredentialDescriptorList가 제공된 경우, 각 allowCredentialDescriptorList의 descriptor에 대해:
-
credSource를 credential id 찾아보기에 따라 이 인증장치에서
descriptor.로 얻는다.id -
credSource가
null이 아니면, credentialOptions에 추가한다.
-
-
그렇지 않은 경우 (allowCredentialDescriptorList가 제공되지 않았다면), 각 이 인증장치의 credentials map의 key → credSource에 대해, credentialOptions에 추가한다.
-
credentialOptions에서 rpId가 rpId와 일치하지 않는 항목을 모두 제거한다.
-
credentialOptions가 비어있으면, "
NotAllowedError"에 해당하는 오류 코드를 반환하고 작업을 종료한다. -
사용자에게 공개키 자격 증명 소스 selectedCredential을
credentialOptions에서 선택하도록 안내한다.
authorization
gesture를 수집하여 사용자
동의를 획득한다.
authorization
gesture에 대한 안내창은 인증장치에 출력 기능이 있으면 인증장치에서, 그렇지 않으면 사용자 에이전트에서 표시될 수 있다.
만약 requireUserVerification이
true라면, authorization gesture 안에 사용자 검증이 포함되어야 한다.requireUserPresence가
true라면, authorization gesture에 사용자 존재 테스트가 반드시 포함되어야 한다.만약 사용자가 동의하지 않으면 "
NotAllowedError"에 해당하는 오류 코드를 반환하고 작업을 종료한다. -
processedExtensions를 authenticator extension 처리 결과로 한다. 지원하는 extension identifier → authenticator extension input을 각각 extensions에 대해 실행한다.
-
서명 카운터 또는 글로벌 서명 카운터 값을 인증장치의 구현 방식에 따라 양의 값만큼 증가시킨다. 만약 authenticator가 서명 카운터를 구현하지 않는다면, 카운터 값은 0으로 유지된다.
-
authenticatorData를 다음 절차로 생성한 바이트 배열로 한다. § 6.1 Authenticator Data에 명시되어 있으며, processedExtensions가 있다면 그것을
extensions로 포함한다.attestedCredentialData는 포함하지 않는다. -
signature는 assertion signature로,
authenticatorData || hash의 연결에 대해 selectedCredential의 privateKey로 생성한다. 아래 그림 참고. 단순하고 구분 기호 없는 연결(concatenation)은 authenticator data가 자신의 길이를 기술하기 때문에 사용해도 안전하다. 직렬화된 클라이언트 데이터의 해시는 항상 마지막 요소가 된다.assertion signature 생성 과정. -
assertion signature 생성 중 오류가 발생하면 "
UnknownError"에 해당하는 오류 코드를 반환하고 작업을 종료한다. -
사용자 에이전트에 반환:
-
selectedCredential.id — 2개 이상의 인증 정보(즉, allowCredentialDescriptorList)가 제공되었거나, 해당 리스트가 제공되지 않은 경우 반환한다.
참고: allowCredentialDescriptorList에 클라이언트가 정확히 하나의 인증 정보를 제공했고, 성공적으로 사용된 경우 해당 credential ID는 이미 클라이언트가 알고 있으므로 반환하지 않는다. 흔한 경우에 불필요한 바이트 전달을 절감할 수 있다.
-
authenticatorData
-
signature
-
selectedCredential.userHandle
참고: allowCredentialDescriptorList가 제공된 경우, 반환된 userHandle 값은
null일 수 있다. 자세한 내용은 userHandleResult 참고.
-
authenticator가 지정된 Relying Party에 해당하고 지정된 기준에 부합하는 credential을 찾지 못하면 작업을 종료하고 오류를 반환한다.
6.3.4. authenticatorCancel 작업
이 작업은 입력 매개변수가 없으며 반환값도 없다.
클라이언트가 authenticator session에서 이 작업을 호출하면, 해당 인증장치 세션 내에서 현재 진행 중인 authenticatorMakeCredential 또는 authenticatorGetAssertion 작업을 종료시킨다. 인증장치는 취소된 작업에 대해 사용자 입력을 더 이상 요청하거나 받지 않는다. 클라이언트는 취소된 작업에 대해 인증장치로부터의 이후 응답을 무시한다.
authenticator session에서 authenticatorMakeCredential 또는 authenticatorGetAssertion 작업이 진행 중이지 않다면, 이 작업은 무시된다.
6.3.5. silentCredentialDiscovery 작업
이는 인증장치가 conditional
사용자 중재를 지원하도록 하는 OPTIONAL 작업이다.
다음 입력 매개변수를 가진다:
이 작업이 호출되면, authenticator는 다음 절차를 따라야 한다:
-
collectedDiscoverableCredentialMetadata를 새 리스트로 지정한다. 이 리스트의 항목은 다음 DiscoverableCredentialMetadata 구조체이다. 각 구조체의 항목은 다음과 같다:
- type
- id
- rpId
- userHandle
-
사용자 핸들이다.
- otherUI
-
authenticator가 UI에 표시할 기타 정보이다.
-
각 공개키 자격 증명 소스 credSource에 대해 authenticator의 credentials map을 순회한다:
-
credSource가 클라이언트 측 탐색 가능한 자격 증명이 아니면 continue 한다.
-
discoveredCredentialMetadata를 새 DiscoverableCredentialMetadata 구조체로, credSource의 type, id, rpId, userHandle, otherUI를 복사하여 생성한다.
-
discoveredCredentialMetadata를 collectedDiscoverableCredentialMetadata에 추가한다.
-
-
collectedDiscoverableCredentialMetadata를 반환한다.
6.4. 문자열 처리
인증기는 Relying Party가 선택한 임의의
문자열을 저장해야 할 수도 있습니다. 예를 들어, name
과 displayName
은 PublicKeyCredentialUserEntity
안에 있습니다.
이 절에서는 사람이 볼 수도 있는 임의 문자열을 처리할 때 발생할 수 있는 실제 문제점들에 대해 설명합니다.
6.4.1. 문자열 잘림
API의 각 임의 문자열은 인증기가 사용할 수 있는 자원이 제한적일 수 있음을 고려해야 합니다. 잘림(truncation) 처리를 선택할 경우, 문자열 값이 손상되지 않도록 주의해야 합니다.
예를 들어, 유니코드 코드 포인트 기준으로만 잘라내면 그래프림 클러스터가 잘릴 수 있습니다. 이렇게 되면 글리프 전체가 지워지는 대신 잘린 클러스터가 다른 모양의 글리프로 표시될 수 있어 문자열의 의미가 변경될 수도 있습니다. 예를 들어, 그림 은 인코딩이 65바이트인 UTF-8 문자열의 끝을 보여줍니다. 만약 64바이트로 제한한다면 마지막 0x88 바이트가 우선 제거됩니다. 이로 인해 UTF-8 코드 포인트의 일부만 남게 되면, 그 나머지도 제거해야 합니다. 그래도 남은 부분이 그래프림 클러스터의 일부라면, 역시 해당 클러스터 전체가 제거되어야 합니다.
이러한 처리를 담당하는 주체는 주로 클라이언트여야 하며, 인증기가 문자 인코딩 및 유니코드 문자 속성을 이해해야 하는 부담을 덜어주는 것이 바람직합니다. 아래 절에서는 클라이언트와 인증기가 각각 문자열 잘림을 수행할 때의 요구사항을 정의합니다.
6.4.1.1. 클라이언트의 문자열 잘림
WebAuthn 클라이언트가 문자열을 자를 때, Relying Party가 관찰할 수 있는 잘림 동작은 반드시 다음 요구사항을 만족해야 합니다:
지정된 최소 지원 길이보다 크거나 같은 크기 제한을 선택합니다. UTF-8 문자 인코딩에서 문자열의 바이트 길이가 그 제한에 맞도록 잘릴 수 있습니다. 이 잘림은 반드시 UTF-8 코드 포인트 경계를 지켜야 하며, 그래프림 클러스터 경계까지 지키는 것이 바람직합니다 [UAX29]. 잘린 값은 선택한 크기 제한보다 짧을 수 있지만, 반드시 해당 제한을 만족하면서 그래프림 클러스터 경계에서 끝나는 가장 긴 접두사 부분 문자열보다는 짧지 않아야 합니다.
클라이언트는 인증기가 위 요구사항을 충족한다면, 잘림 처리를 인증기에 맡길 수 있습니다. 그렇지 않은 경우 클라이언트가 인증기에 문자열을 전달하기 전 직접 잘림 처리를 해야 합니다.
또한 위 조건 외에, 단순히 바이트 경계에서만 자르면 사용자 에이전트가 알아야 할 문제가 있습니다. 인증기가 [FIDO-CTAP]를 사용하는 경우 인증기로부터 이후에 받는 메시지에서 값을 CBOR 문자열로 표현해야 하므로 유효한 UTF-8이어야 합니다. 따라서 인증기를 다룰 때, 사용자 에이전트는 다음을 권장합니다:
-
인증기로 보내는 문자열이 유효하게 인코딩되어 있는지 확인합니다.
-
문자열을 잘라낸 결과 인코딩이 깨진 경우를 처리합니다. 예를 들어, 끝에 남은 코드 포인트 조각은 삭제하거나 U+FFFD로 대체할 수 있습니다.
6.4.1.2. 인증기의 문자열 잘림
WebAuthn 인증기는 리소스가 제한적인 환경에서 동작할 수 있으므로, 인증기에 대한 요구사항은 클라이언트에 비해 더 완화되어 있습니다.
WebAuthn 인증기가 문자열을 자를 때, 반드시 다음 요구조건을 만족해야 합니다:
지정된 최소 지원 길이보다 크거나 같은 크기 제한을 선택합니다. UTF-8 문자 인코딩에서 문자열의 바이트 길이가 그 제한에 맞도록 잘릴 수 있습니다. 이 잘림은 UTF-8 코드 포인트 경계를 지키는 것이 바람직하며, 그래프림 클러스터 경계를 지킬 수도 있습니다 [UAX29]. 잘린 값은 제한보다 짧을 수 있으나, 해당 제한을 만족하고 그래프림 클러스터 경계에서 끝나는 가장 긴 접두사 부분 문자열보다는 짧지 않아야 합니다.
6.4.2. 언어 및 방향성 인코딩
문자열이 올바른 맥락에서 표시되기 위해서는 언어 및 기준 방향 정보가 필요할 수 있습니다. 이 API의 문자열은 고정기능 인증기에 기록한 뒤 나중에 다른 플랫폼에서 읽어서 표시할 수 있으므로, 문자열 자체에 언어/방향 메타데이터를 인코딩하여 원자적으로 전달되도록 합니다.
문서상 허용된 문자열에 언어/방향 메타데이터를 인코딩하려면, 코드포인트 뒤에 두 개의 시퀀스를 추가합니다:
첫 번째 시퀀스는 언어 태그를 인코딩하며, U+E0001 코드 포인트와 이어진 언어 태그 각 ASCII 값을 U+E0000만큼 올린 코드포인트로 표현합니다. 예를 들어, 언어 태그 “en-US”는 U+E0001, U+E0065, U+E006E, U+E002D, U+E0055, U+E0053이 됩니다.
두 번째 시퀀스는 U+200E(“LEFT-TO-RIGHT MARK”), U+200F(“RIGHT-TO-LEFT MARK”), U+E007F(“CANCEL TAG”) 중 하나의 코드포인트로 이뤄집니다. 앞 두 값은 방향성 표시용이나, 필요한 경우에만 사용해야 합니다(예: RTL 문자열이 LTR-강한 문자로 시작할 때). U+E007F 값은 언어 태그가 끝났음을 나타내는 방향성 중립 마킹입니다.
즉, 문자열 “حبیب الرحمان”은 언어를 인코딩할지에 따라 둘 중 하나의 DOMString 값을 가질 수 있습니다. (이 예에서는 방향이 명확하므로 방향 표시가 필요없음)
-
가공하지 않은 문자열: U+062D, U+0628, U+06CC, U+0628, U+0020, U+0627, U+0644, U+0631, U+062D, U+0645, U+0627, U+0646
-
언어 “ar-SA”로 인코딩: U+062D, U+0628, U+06CC, U+0628, U+0020, U+0627, U+0644, U+0631, U+062D, U+0645, U+0627, U+0646, U+E0001, U+E0061, U+E0072, U+E002D, U+E0053, U+E0041, U+E007F
언어 및 방향 정보가 인코딩될 수 있는 문자열을 사용하는 쪽은 잘림으로 인해 언어 태그가 다른(그러나 여전히 유효한) 언어로 잘릴 수 있음을 인지해야 합니다. 최종 방향성 마커 또는 CANCEL TAG 코드포인트는 잘림되었음을 명확히 나타냅니다.
6.5. Attestation(인증서명)
인증기는 가능하다면 인증서명(attestation) 형태 또한 제공해야 합니다. 인증기가 이런 기능을 제공한다면, 기본 요구사항은 인증기가 각 공개키 자격증명에 대해, 인증서명 문장을 생성할 수 있어야 하며, 그 문장은 WebAuthn Relying Party가 검증할 수 있어야 합니다. 일반적으로 이 인증서명 문장은 attestation private key로 credential public key와 챌린지에 서명하고, attestation public key의 출처 정보를 제공하는 인증서나 유사 데이터를 담습니다. 이를 통해 Relying Party가 신뢰 여부를 판단할 수 있습니다. 그러나, attestation key pair가 없다면, 인증기는 self attestation 또는, credential private key로 no attestation을 할 수도 있습니다. 이러한 모든 정보는 인증기가 새로운 공개키 자격증명을 생성할 때 마다 반환되며, 전체적으로 attestation object라는 형태가 됩니다. attestation object와 authenticator data (이 안에 attested credential data가 들어있음) 그리고 attestation statement의 관계는 아래 그림 에 나와 있습니다.
인증기가 self attestation 또는 no attestation을 하는 경우, Relying Party가 신뢰 여부를 판단할 정보(출처)가 제공되지 않습니다. 이 때 인증기는 Relying Party에 대해 아무런 보장도 하지 않습니다.
packed attestation statement format만을 보여줍니다. 여러
추가 형식은 § 8 Defined Attestation Statement Formats에
정의되어 있습니다.
attestation object의 중요한 구성 요소는 attestation statement입니다. 이는 서명이 된 데이터 오브젝트로 공개키 자격증명 자체 및 이를 생성한 인증기에 대한 진술을 포함합니다. attestation signature는 보통 인증기관의 키로 서명되어 있습니다(단, self attestation의 경우 credential private key로 서명). attestation statement를 바르게 해석하기 위해 Relying Party는 다음 두 측면을 이해해야 합니다:
-
Attestation statement format은 시그니처가 어떻게 표현되는지, 그리고 여러 컨텍스트 바인딩이 인증기에 의해 어떻게 attestation statement에 포함되는지를 정의합니다. 즉, 이 포맷은 문장(statement)의 문법(syntax)를 정의합니다. TPM, Android OS 등 다양한 기존 요소들은 각자 attestation statement format을 정의한 바 있습니다. 본 명세서는 이러한 여러 포맷을 § 6.5.2 Attestation Statement Formats에서 확장 가능하게 지원합니다. 각 포맷은 § 8.1에서 설명하는 문자열 식별자로 구분합니다.
-
Attestation type은 attestation statement의 의미와 신뢰 모델을 정의합니다. 구체적으로, Relying Party가 해당 statement가 암호학적으로 유효함을 검증한 뒤 신뢰를 어떻게 쌓을지 정의합니다. 명세서는 § 6.5.3 Attestation Types에서 여러 attestation type을 지원합니다.
일반적으로 attestation statement format과 attestation type간에 단순 매핑은 없습니다. 예를 들면, "packed" 형식은 § 8.2 Packed Attestation Statement Format에서 설명되어 있으며, 모든 attestation type과 조합될 수 있습니다. 다른 형식과 타입은 보다 제한적일 수 있습니다.
Attestation의 프라이버시, 보안, 운영 특성은 다음에 따라 달라집니다:
-
Attestation type (신뢰 모델 결정),
-
Attestation statement format (표현 및 attestation의 표현 강도를 제한할 수 있음),
-
각 개별 인증기의 특성(구성, 보안 환경 여부 등).
Attestation type 및
attestation statement format은 인증기가 선택하며,
Relying Party는 attestation
및 attestationFormats
파라미터로 요청만 할 수 있습니다.
대부분의 인증기는 소수의 attestation type과 attestation statement format만 지원할 것으로 예상되며, Relying Party는 정책에 따라 수용할 수 있는 attestation type을 결정하게 됩니다. Relying Party는 또한 신뢰하려는 인증기 특징도 사전에 알아야 하며, 예를 들어 FIDO Metadata Service [FIDOMetadataService]가 참고가 될 수 있습니다.
6.5.1. Attested Credential Data
인증된 자격 증명 데이터는 자격 증명에 대한 attestation object를 생성할 때 authenticator data에 추가되는 가변 길이의 바이트 배열입니다. 이 형식은 표 에 나와 있습니다.
| 이름 | 길이 (바이트) | 설명 |
|---|---|---|
| aaguid | 16 | 인증기의 AAGUID |
| credentialIdLength | 2 | credentialId의 바이트 길이 L, 16비트 부호 없는 빅엔디안 정수, 값은 반드시 1023 이하여야 합니다. |
| credentialId | L | 자격 증명 ID |
| credentialPublicKey | 가변 | 자격 증명 공개키가 COSE_Key 포맷으로 인코딩된 값. 구체적인 규격은 RFC9052 7장과 CTAP2 정규 CBOR 인코딩 규칙을 따릅니다. COSE_Key로 인코딩된 공개키에는 "alg" 파라미터가 반드시 포함되어야 하며, 다른 선택적 파라미터는 포함되어선 안 됩니다. "alg" 파라미터에는 반드시 COSEAlgorithmIdentifier
값을 넣어야 합니다.인코딩된 공개키에는 해당 key type과 알고리즘에 따른 추가 필수 파라미터도 반드시 들어가야 합니다(예: "kty", "alg"가 필수, 자세한 내용은 RFC9053 2장 참조). |
6.5.1.1. credentialPublicKey 값을 COSE_Key 포맷으로
인코딩한 예시
이 절에서는 ES256, PS256, RS256 서명 알고리즘에 대한 COSE_Key 인코딩된 타원 곡선 및 RSA 공개키 예시를 제공합니다. 이 예시는 위의 credentialPublicKey 값 규칙을 따르며, 가독성을 위해 CDDL [RFC8610] 형식으로 제시됩니다.
모든 COSE_Key 인코딩 키의 일반 구조는 RFC9052 7장에 명시되어 있습니다. 각 알고리즘별 키 타입은 [RFC9053] 및 기타 규격에 정의되어 있습니다.
아래는 EC2 포맷으로 인코딩된 COSE_Key 타원 곡선 공개키 예시입니다(RFC9053 7.1장
참조).
P-256 곡선(ECDSA w/ SHA-256, ES256 알고리즘) 사용:
{ 1 : 2 , ; kty: EC2 key type 3 : -7 , ; alg: ES256 signature algorithm -1 : 1 , ; crv: P-256 curve -2 : x , ; x좌표, 32바이트 바이트열 ; 예시(16진): 65eda5a12577c2bae829437fe338701a10aaa375e1bb5b5de108de439c08551d -3 : y ; y좌표, 32바이트 바이트열 ; 예시(16진): 1e52ed75701163f7f9e40ddf9f341b3dc9ba860af7e0ca7ca7e9eecd0084d19c }
위 타원 곡선 공개키를 CTAP2 표준 CBOR 인코딩으로 인코딩한 예시(가독성을 위해 공백/줄바꿈 포함):
A5 01 02 03 26 20 01 21 58 20 65eda5a12577c2bae829437fe338701a10aaa375e1bb5b5de108de439c08551d 22 58 20 1e52ed75701163f7f9e40ddf9f341b3dc9ba860af7e0ca7ca7e9eecd0084d19c
아래는 COSE_Key로 인코딩된 2048비트 RSA 공개키 예시입니다([RFC8230] 4장
참조).
PS256 서명 알고리즘(RSASSA-PSS with SHA-256)용:
{ 1 : 3 , ; kty: RSA key type 3 : -37 , ; alg: PS256 -1 : n , ; n: RSA 모듈러스 n, 256바이트 바이트열 ; 예시(중간 생략): DB5F651550...6DC6548ACC3 -2 : e ; e: RSA 퍼블릭 지수 e, 3바이트 바이트열 ; 예시: 010001 }
아래는 위와 동일한 COSE_Key 인코딩 RSA 공개키를 RS256 서명 알고리즘(RSASSA-PKCS1-v1_5 with SHA-256)으로 사용할 때의 예시입니다:
{ 1 : 3 , ; kty: RSA key type 3 : -257 , ; alg: RS256 -1 : n , ; n: RSA 모듈러스 n, 256바이트 바이트열 ; 예시(중간 생략): DB5F651550...6DC6548ACC3 -2 : e ; e: RSA 퍼블릭 지수 e, 3바이트 바이트열 ; 예시: 010001 }
6.5.2. Attestation Statement Formats
위에서 설명한 것처럼, attestation statement format은 authenticator가 컨텍스트 결합 정보에 대해 암호 서명을 표현하는 데이터 형식입니다. 각각의 attestation statement format은 다음 템플릿으로 정의해야 합니다:
-
지원하는 attestation type:
-
문법: 이 형식에서 생성되는 attestation statement의 문법.
확장 포인트$$attStmtType는 § 6.5.4 Attestation Object 생성에 정의되어 있으며, 이에 대해 CDDL [RFC8610]로 정의합니다. -
Signing procedure: 주어진 public key credential을 인증하고, attestation을 위한 authenticator data 구조(해당 attestation의 authenticator data)와 직렬화된 클라이언트 데이터의 해시를 받아, 이 포맷에 맞는 attestation statement를 산출하는 절차입니다.
-
Verification procedure: attestation statement를 검증하는 절차이며,
다음 인풋을 받습니다:-
attStmt: attestation statement 구조체
-
authenticatorData: attestation에서 사용되었다고 주장하는 authenticator data
-
clientDataHash: 직렬화된 클라이언트 데이터의 해시
이 절차는 아래 중 하나를 반환합니다:
-
attestation이 유효하지 않음을 나타내는 오류
-
구현체별 attestation type과 신뢰 경로(trust path)를 나타내는 값. 신뢰 경로는 self attestation이면 비어 있고, 아니면 X.509 인증서 집합임.
-
정의된 attestation statement format의 목록은 § 8 Defined Attestation Statement Formats에 있습니다.
6.5.3. Attestation Type 종류
WebAuthn은 여러 attestation type을 지원하며, 각각의 attestation statement 의미 및 신뢰 모델을 정의합니다.
참고: 본 명세에서는 authenticator가 사용하는 attestation type을 명시적으로 표현하는 데이터 구조를 정의하지
않습니다. Relying Party가 attestation
statement 검증을 할 때
(즉, navigator.credentials.create()
사용 시 attestation
conveyance가 none이
아니고 받은 attestation statement를 검증함)
검증의 일부로 사용된 attestation
type을 결정하게 됩니다.
구체 절차 예시는 § 8 Attestation Statement Formats의 "Verification
procedure" 절, 그리고 § 14.4.1 Attestation Privacy 참조.
이 절에서 정의한 Self, None을 제외한 모든 attestation type은 검증이 끝난 뒤 신뢰 경로를 루트 인증서와
매칭(7.1-23단계, § 7.1 자격
증명 등록)해야 함.
이러한 구분은 Relying Party 정책 내에서
attestation의 허용 여부 판단에 주로 활용됨.
- Basic Attestation (Basic)
-
기본(basic) attestation의 경우 [UAFProtocol], 인증기의 attestation key pair는 인증기 "모델" 단위(즉, 하나의 "배치")로 고유합니다. 따라서 같은(혹은 유사한) 모델의 인증기들은 attestation key pair를 공유합니다. 자세한 내용은 § 14.4.1 Attestation Privacy 참조.
Basic attestation은 batch attestation이라고도 합니다.
- Self Attestation (Self)
-
self attestation 또는 surrogate basic attestation의 경우 [UAFProtocol], 인증기는 별도의 attestation key pair가 없습니다. 대신 credential private key로 attestation signature를 만듭니다. 실질적인 attestation private key 보호가 없는 인증기는 이 유형을 사용합니다.
- Attestation CA (AttCA)
-
이 유형에서는 authenticator가 TPM(Trusted Platform Module) 기반이고, 사용자별 "endorsement key"(EK)를 보유합니다.
이 키로 신뢰받는 별도의 제3자 Attestation CA ([TCG-CMCProfile-AIKCertEnroll], 예전 이름 "Privacy CA")와 안전하게 통신 가능.
인증기는 여러 attestation identity key pair(AIK)를 생성해서 각각에 대해 Attestation CA로부터 AIK 인증서를 발급받을 수 있습니다. 이 방식은 EK(전역식별) 노출을 Attestation CA로 제한할 수 있습니다. 각 authenticator에서 생성된 public key credential마다 개별적으로 AIK를 요청 가능하며, Relying Party에게 attestation certificate로 제공할 수 있습니다.참고: 이 모델은 여러 attestation 인증서를 만들며, 가장 최근에 요청한 것이 "active" 인증서입니다.
- Anonymization CA (AnonCA)
-
이 유형에서는 authenticator가 Anonymization CA를 사용하여 매 자격 증명마다 동적으로 attestation certificate를 발급합니다. 이 덕분에 attestation statement는 Relying Party에게 식별이 불가한 정보만 제공합니다(트래킹 방지).
참고: Attestation statement에 attestation type이 AttCA, AnonCA인 경우 내부 데이터 구조는 Basic type과 같으므로, 실제로는 attestation certificate의 외부적 해석 없이는 구분 불가.
- 검증 정보 없을 때 (None)
-
이 경우 attestation 정보가 없습니다. § 8.7 None Attestation Statement Format도 참고하세요.
6.5.4. Attestation Object 생성
attestation object를 생성하려면(예: 그림 6), 다음 입력이 있어야 함:
- attestationFormat
- authData
-
authenticator data를 담은 바이트 배열.
- hash
authenticator는 반드시 아래 절차를 따라야 합니다:
-
attStmt는 attestationFormat의 signing procedure에 authData, hash를 전달해 생성함.
-
fmt는 attestationFormat의 attestation statement format identifier임.
-
아래 문법에 따라 CBOR 맵으로 attestation object를 반환. 변수는 위 알고리즘으로 채움:
attObj = { authData: bytes, ; 각 $$attStmtType마다 fmt 값과 attStmt 구조 정의 $$attStmtType } .within attStmtTemplate attStmtTemplate = { authData: bytes, fmt: text, attStmt: ( { * tstr => any } ; 각 구체적 attStmtType 별 맵 // [ * any ] ; attStmt가 배열일 수도 있음 ) }
6.5.5. Packed/FIDO U2F Attestation 및 Assertion Signature의 서명 포맷
-
COSEAlgorithmIdentifier -7 (ES256) 및 기타 ECDSA 기반 알고리즘의 경우,
sig값은 [RFC3279] 2.2.3절에서 정의한 ASN.1 DER Ecdsa-Sig-Value로 인코딩되어야 한다.예시: 30 44 ; SEQUENCE (68 Bytes) 02 20 ; INTEGER (32 Bytes) | 3d 46 28 7b 8c 6e 8c 8c 26 1c 1b 88 f2 73 b0 9a | 32 a6 cf 28 09 fd 6e 30 d5 a7 9f 26 37 00 8f 54 02 20 ; INTEGER (32 Bytes) | 4e 72 23 6e a3 90 a9 a1 7b cf 5f 7a 09 d6 3a b2 | 17 6c 92 bb 8e 36 c0 41 98 a2 7b 90 9b 6e 8f 13참고: CTAP1/U2F authenticator는 이미 이 포맷으로 서명을 생성하므로, CTAP2 authenticator도 일관성을 위해 동일 포맷을 사용합니다.
새로 정의되는 attestation format은 ASN.1 인코딩 사용 없이, 내부 구조 없는 고정 길이 바이트 배열 방식으로 서명값을 나타내는 것이 권장됩니다([RFC9053], [RFC8230] 방식).
아래 서명 포맷 정의는 이 요구사항을 만족하며, 명시되지 않은 다른 서명 알고리즘의 동일 구조 도출 예시로 활용할 수 있습니다:
-
COSEAlgorithmIdentifier -257 (RS256)의 경우
sig값은 [RFC8017] 8.2.1절의 RSASSA-PKCS1-v1_5 시그니처 방식을 SHA-256 해시와 함께 사용해 생성해야 하며, 서명 결과는 ASN.1로 래핑되지 않음. -
COSEAlgorithmIdentifier -37 (PS256)의 경우
sig값은 [RFC8017] 8.1.1절의 RSASSA-PSS 시그니처 스킴을 SHA-256 해시와 함께 사용해 생성해야 하며, 서명 결과는 ASN.1로 래핑되지 않음.
7. WebAuthn Relying Party 작업
등록
또는 인증 의식은
WebAuthn
Relying Party가 각각 PublicKeyCredentialCreationOptions
또는 PublicKeyCredentialRequestOptions
객체를 생성함으로써 시작되며, 이는 ceremony를 위한 파라미터를
인코딩한다. Relying Party는 이 단계에서
민감한 정보가 누출되지 않도록 주의해야 한다; 자세한 사항은 § 14.6.2 사용자명 열거를 참조하라.
create()
또는 get()
이(가) 성공적으로 실행되면,
Relying Party의 스크립트는
PublicKeyCredential
내에 클라이언트로부터 AuthenticatorAttestationResponse
또는 AuthenticatorAssertionResponse
구조체를 각각 받게 된다.
이 구조체의 내용을 Relying Party 서버로
전송해야 하며, 이 방법은 본 명세의 범위를 벗어난다.
본 절에서는 Relying Party가 이러한
구조체를 수신했을 때 수행해야 할 작업을 설명한다.
7.1. 새로운 자격 증명 등록하기
등록 의식을 수행하기 위해 Relying Party는 다음과 같이 진행해야 한다:
-
options를 Relying Party의 ceremony 필요에 맞게 구성한 새로운
CredentialCreationOptions구조체로 정한다. pkOptions를options.로 한다.publicKey -
navigator.credentials.create()를 호출하고 options를 인자로 전달한다. credential을 성공적으로 해결된 프라미스의 결과로 설정한다. 프라미스가 거부될 경우, 사용자에게 보이는 오류로 ceremony를 중단하거나 거부된 프라미스의 컨텍스트에서 파악할 수 있는 방식대로 사용자 경험을 안내해야 한다. 예를 들어 프라미스가 "InvalidStateError"와 동등한 오류 코드로 거부될 경우, 사용자에게 다른 인증기 사용을 안내할 수 있다. 다양한 오류 컨텍스트와 그 사유에 대한 자세한 정보는 § 6.3.2 authenticatorMakeCredential 작업을 참고하라. -
response를
credential.로 한다. response가responseAuthenticatorAttestationResponse의 인스턴스가 아니면, 사용자에게 보이는 오류로 ceremony를 중단한다. -
clientExtensionResults를
credential.호출 결과로 한다.getClientExtensionResults() -
JSONtext를
response.의 값을 UTF-8 디코드 처리한 결과로 한다.clientDataJSON참고: UTF-8 디코드의 어떤 구현도 결과가 UTF-8 디코드 알고리즘과 동일하다면 사용 가능하다. 특히, 시작 BOM(Byte Order Mark)이 있다면 제거되어야 한다.
-
자격 증명 생성 중에 수집된 것으로 주장된 클라이언트 데이터 C를, JSONtext에 구현별 JSON 파서를 실행한 결과로 설정한다.
참고: C는 이 알고리즘이 요구하는 대로 C의 구성요소에 참조할 수만 있으면 구현별 자료구조 표현일 수 있다.
-
C.값이typewebauthn.create인지 확인한다. -
C.값이challengepkOptions.의 base64url 인코딩 값과 동일한지 확인한다.challenge -
C.값이 origin 중 Relying Party가 기대하는 값인지 검증한다. 관련 내용은 § 13.4.9 자격 증명의 origin 유효성 검사 참고.origin -
C.이 존재하고 값이crossOrigintrue이면, 이 자격 증명이 Relying Party가 기대하는, 조상과 same-origin이 아닌 iframe 내에서 생성되었는지 검증한다. -
C.이 존재하면:topOrigin-
Relying Party가 기대하는, 조상과 same-origin이 아닌 iframe 내에서 생성된 것인지 검증한다.
-
C.값이 origin 중 Relying Party가 sub-frame으로 두기를 기대하는 페이지 origin과 일치하는지 검증한다. 추가 내용은 § 13.4.9 자격 증명의 origin 유효성 검사 참고.topOrigin
-
-
hash를
response.에 대해 SHA-256 해시를 계산한 결과로 설정한다.clientDataJSON -
attestationObject필드의 CBOR 디코딩을 수행하여 fmt (어테스테이션 형식), 인증기 데이터 authData 및 어테스테이션 서명 attStmt을 획득한다. -
rpIdHash값이 RP ID의 SHA-256 해시와 일치하는지 검사한다. 이 RP ID는 Relying Party가 기대하는 값이어야 한다. -
options.이mediationconditional이 아니면, UP 비트가 authData의flags내에 설정되어 있는지 확인한다. -
이 등록에 대해 Relying Party가 사용자 검증을 요구한다면, UV 비트가 authData의
flags내에 설정되어 있는지 확인한다. -
Relying Party가 자격 증명의 백업 적합성을 사용해 사용자 경험이나 정책을 결정한다면, BE 비트를 authData의
flags에서 확인한다. -
Relying Party가 자격 증명의 백업 상태를 사용해 사용자 경험이나 정책을 결정한다면, BS 비트를 authData의
flags에서 확인한다. -
credential public key의 "alg" 파라미터가 authData 내에 존재하며,
alg속성이pkOptions.에 포함된 항목 중 하나와 일치하는지 확인한다.pubKeyCredParams -
어테스테이션의 형식(fmt)을 지원되는 WebAuthn 어테스테이션 형식 식별자 값들과 USASCII 대/소문자 구분 일치로 확인한다. 현재 등록된 WebAuthn 어테스테이션 형식 식별자 목록은 IANA "WebAuthn Attestation Statement Format Identifiers" 레지스트리 [IANA-WebAuthn-Registries]에서 관리한다. 자세한 내용은 [RFC8809] 참고.
-
attStmt가 올바른 어테스테이션
명세이고, 어테스테이션 서명이 유효한지,
어테스테이션 명세 형식 fmt의 검증 절차를 attStmt,
authData, hash를 넣어 사용하여 검증한다.
참고: 각 어테스테이션 명세 형식은 고유의 검증 절차를 지정한다. 처음 정의된 형식들은 § 8 어테스테이션 명세 형식 정의를, 최신 목록은 [IANA-WebAuthn-Registries]를 참조할 것.
- 검증이 성공하면 해당 어테스테이션 타입 및 fmt에 대해 신뢰할 수
있는 트러스트 앵커(즉, 어테스테이션 루트 인증서) 목록을 신뢰할 수 있는 소스 혹은 정책에서 획득한다. 예를 들어, FIDO 메타데이터 서비스 [FIDOMetadataService]는 해당 정보를 얻는 하나의 방법을 제공하며,
aaguid는attestedCredentialData내에 존재한다. -
검증 절차의 결과를 이용해 어테스테이션 신뢰성을
평가한다(21단계):
-
어테스테이션 없음이 제공된 경우, 어테스테이션 없음이 Relying Party의 정책상 허용되는지 확인한다.
-
셀프 어테스테이션이 사용된 경우, 셀프 어테스테이션이 Relying Party 정책상 허용되는지 확인한다.
-
그 외의 경우, 어테스테이션 트러스트 경로로 반환된 X.509 인증서를 사용해, 어테스테이션 공개키가 허용되는 루트 인증서로 올바르게 체인업되는지, 혹은 그 자체가 허용되는 인증서인지 확인한다. (즉, 22단계에서 얻은 루트 인증서와 동일할 수도 있음).
어테스테이션이 신뢰할 수 없는 것으로 간주되면, Relying Party는 등록 의식을 실패 처리해야 한다.
참고: 그러나 정책상 허용된다면, Relying Party는 자격 증명 ID와 공개키를 등록하되, 해당 자격 증명을 셀프 어테스테이션으로 간주할 수도 있다(§ 6.5.3 어테스테이션 타입 참조). 이 경우 Relying Party는 특정 인증기 모델이 아닌, 공개키 자격 증명이 생성되었다는 것에 대하여 암호학적 증거가 없음을 인정한다. 자세한 내용은 [FIDOSecRef] 및 [UAFProtocol] 참고.
-
-
credentialId가 1023바이트 이하인지 검증한다. 이 크기를 초과하는 자격 증명 ID는 RP가 등록 의식을 실패 처리하게 해야 한다. -
credentialId가 아직 어떤 사용자에게도 등록되지 않았는지 확인한다.credentialId가 이미 알려진 경우, Relying Party는 등록 의식을 실패시켜야 한다.참고: Relying Party가 중복 자격 증명 ID를 거부하는 이유는 다음과 같다: 자격 증명 ID는 충분한 엔트로피를 보장하므로 우연 중복은 매우 희박하다. 그러나, 셀프 어테스테이션이 아닌 경우에는 개인키의 소유를 명확히 증명하는 서명이 포함되지 않는다. 이로 인해 공격자가 사용자의 자격 증명 ID 및 공개키를 획득해 정상 등록을 시도하는 등의 사고를 방지할 수 있다. 피해자의 기존 자격 증명이 대체된다면 피해자가 다음 로그인 때 공격자의 계정으로 로그인될 수 있다.
-
credentialRecord를 다음
내용으로 하는 새로운 자격 증명
기록으로 한다:
- type
-
credential..type - id
-
credential.또는idcredential., 어느 쪽이든 Relying Party가 선호하는 형식을 사용한다.rawId - publicKey
-
자격 증명 공개키는 authData에 존재한다.
- signCount
-
authData.signCount. - uvInitialized
- transports
-
response.호출 결과다.getTransports() - backupEligible
- backupState
새로운 자격 증명 기록에는 다음의 선택적 내용도 포함될 수 있다:
- attestationObject
-
response..attestationObject - attestationClientDataJSON
-
response..clientDataJSON
Relying Party는 필요한 경우 추가 항목도 포함시킬 수 있다. 비규범적 예시로, Relying Party는 사용자가 계정 설정에서 상호작용 시 쉽게 기억할 수 있도록 자격 증명에 "별명"을 지정할 수 있다. 이 별명으로 어느 자격 증명이 어떤 인증기에 바인딩되어 있는지 식별할 수 있다.
-
clientExtensionResults의 클라이언트 확장 출력과
authData 내
extensions의 인증기 확장 출력을 Relying Party 요구대로 처리한다. 각 확장에 따라 처리 방법이 명확히 규정되어 있을 수도 있고, Relying Party가 자유롭게 처리할 수도 있다. Relying Party는 어떤 확장 출력도 무시 가능하다.클라이언트는 추가 인증기 확장이나 클라이언트 확장을 설정하여, 인증기 확장 출력 또는 클라이언트 확장 출력에 Relying Party가
pkOptions.에서 요청하지 않은 값이 등장할 수 있다. 이 경우 Relying Party는 이를 무시하거나 어테스테이션을 거부할 수 있으며, 정책에 따라 결정한다.extensions모든 확장은 클라이언트와 인증기 모두에서 선택사항이므로, Relying Party는 요청한 확장 중 일부 혹은 전부가 미처리되는 경우를 고려해야 한다.
-
위 모든 단계가 성공하면, credentialRecord를 사용자 계정에 저장하고,
pkOptions.를 참조하여 등록 의식을 계속 진행한다. 그렇지 않으면 등록 의식을 실패시킨다.userRelying Party가 이 경우에도 등록 의식을 실패 처리하지 않는다면, Relying Party는 특정 인증기 모델로 생성된 것이라는 암호학적 증거가 공개키 자격 증명에 대해 없다는 사실을 인정하는 것이다. Relying Party는 자격 증명을 어테스테이션 없음으로 간주해도 된다(§ 6.5.3 어테스테이션 타입 참조). 자세한 논의는 [FIDOSecRef]와 [UAFProtocol] 참조.
어테스테이션 객체 검증을 위해서는 위 22단계에서 허용 가능한 트러스트 앵커를 결정하는 신뢰할 수 있는 방법이 Relying Party에 있어야 한다. 또한, 인증서를 사용할 경우 Relying Party는 중간 CA 인증서의 상태 정보에 접근 가능해야 한다. Relying Party는 클라이언트가 어테스테이션 정보에 인증서 체인을 제공하지 않은 경우에도 체인을 구축할 수 있어야 한다.
7.2. 인증 어서션 검증
인증 의식을 수행하기 위해, Relying Party는 다음과 같이 수행해야 한다:
-
options를 Relying Party의 필요에 따라 구성한 새로운
CredentialRequestOptions구조체로 두고, pkOptions를options.로 둔다.publicKey -
navigator.credentials.get()을 호출하고, options를 인자로 전달한다. credential 값을 성공적으로 resolve된 프라미스의 결과로 둔다. 만약 프라미스가 거부되면, 사용자에게 보이는 오류로 의식을 중단하거나, 거부된 프라미스의 컨텍스트에서 알 수 있는 방식으로 사용 경험을 안내해야 한다. 다양한 오류 상황과 그 원인에 대해서는 § 6.3.3 authenticatorGetAssertion 작업을 참고하라. -
response를
credential.값으로 둔다. response가responseAuthenticatorAssertionResponse의 인스턴스가 아니면, 사용자에게 보이는 오류로 의식을 중단한다. -
clientExtensionResults를
credential.호출 결과로 둔다.getClientExtensionResults() -
pkOptions.가 비어 있지 않으면,allowCredentialscredential.가 공개 키 자격 증명 중idpkOptions.에 나열된 것 중 하나를 식별하는지 확인한다.allowCredentials -
인증되는 사용자를 식별하고, credentialRecord를 해당 자격증명 기록으로 둔다:
- 사용자가 인증 의식 시작 전에 예를 들어 사용자명이나 쿠키로 식별된 경우,
-
식별된 사용자 계정이 자격증명 기록을 포함하는지, 이 때 그 id가
credential.와 같은지 검증한다. credentialRecord를 해당 자격증명 기록으로 둔다.rawIdresponse.이 있을 경우, 해당 값이 user handle과 같은지 검증한다.userHandle - 사용자가 인증 의식 시작 전에 식별되지 않은 경우,
-
response.이 존재하는지 검증한다.userHandleresponse.이 가리키는 사용자 계정이 자격증명 기록을 포함하고, 이는 id가userHandlecredential.와 같은지 검증한다. credentialRecord를 해당 자격증명 기록으로 둔다.rawId
-
cData, authData, sig를 각각 response의
clientDataJSON,authenticatorData,signature값으로 둔다. -
JSONtext를 cData에 UTF-8 디코드를 수행한 결과로 둔다.
참고: UTF-8 디코드의 구현은, UTF-8 디코드 알고리즘과 같은 결과를 내면 어떤 구현도 괜찮다. 특히, 앞쪽의 BOM(Byte Order Mark)은 반드시 제거되어야 한다.
-
서명에 사용된 클라이언트 데이터 C를, JSONtext에 구현별 JSON 파서를 돌린 결과로 둔다.
참고: C는 이 알고리즘이 요구하는 대로 C의 구성 요소에 참조만 할 수 있다면, 구현별 자료구조일 수 있다.
-
C.값이typewebauthn.get문자열인지 확인한다. -
C.값이challengepkOptions.의 base64url 인코딩과 같은지 확인한다.challenge -
C.값이 origin 중 Relying Party가 기대하는 값인지 검증한다. 자세한 지침은 § 13.4.9 자격 증명의 origin 유효성 검사 참고.origin -
C.이 존재하고 값이crossOrigintrue이면, Relying Party가 이 자격 증명이 조상과 same-origin이 아닌 iframe 내에서 사용될 것이라 기대하는지 검증한다. -
C.이 있을 경우:topOrigin-
Relying Party가 이 자격 증명을 조상과 same-origin이 아닌 iframe 내에서 사용될 것이라 기대하는지 검증한다.
-
C.값이 origin 중 Relying Party가 sub-framed 페이지로 예상하는 origin과 일치하는지 검증한다. 자세한 지침은 § 13.4.9 자격 증명의 origin 유효성 검사 참고.topOrigin
-
-
authData 안의
rpIdHash값이 RP ID의 SHA-256 해시이며, 이는 Relying Party가 기대하는 값인지 검증한다.참고: appid 확장을 사용할 경우 이 단계에 특별한 로직이 필요하다. 세부사항은 § 10.1.1 FIDO AppID Extension (appid) 참고.
-
이 어서션에 대해 사용자 검증이 필요한지 결정한다. 사용자 검증은
pkOptions.이userVerificationrequired로 지정된 경우에만, 그리고 반드시 필요하도록 해야 한다.만약 사용자 검증이 필요하다면, UV 비트가 authData의
flags내에 설정되어 있는지 확인한다. 필요하지 않다면 UV flag 값은 무시한다. -
BE 비트가 authData의
flags에서 설정되어 있지 않으면, BS 비트가 설정되지 않았는지 확인한다. -
자격 증명의 백업 상태가 Relying Party의 업무 로직이나 정책에서 쓰인다면, currentBe와 currentBs를 각각 BE, BS 비트의 값으로 두고,
credentialRecord.backupEligible및credentialRecord.backupState와 비교한다:-
credentialRecord.backupEligible이 설정돼 있으면, currentBe가 설정돼 있는지 확인한다. -
credentialRecord.backupEligible이 설정돼 있지 않으면, currentBe도 설정돼 있지 않은지 확인한다. -
Relying Party 정책이 있다면 적용한다.
참고: § 6.1.3 자격 증명 백업 상태에 Relying Party가 BS flag를 처리하는 예시가 있다.
-
-
cData에 대해 SHA-256 해시를 계산한 결과를 hash로 둔다.
-
credentialRecord.publicKey를 사용하여, sig가 authData와 hash를 바이너리로 이어붙인 값에 대한 올바른 서명인지 검증한다.참고: 이 검증 단계는 FIDO U2F 인증기가 생성한 서명도 호환된다. § 6.1.2 FIDO U2F 서명 형식 호환성 참고.
-
authData.
signCount가 0이 아니거나credentialRecord.signCount가 0이 아니면, 다음 하위 단계를 실행한다:-
authData.
signCount값이- 크면
credentialRecord.signCount보다: - 서명 카운터가 유효하다.
- 작거나 같으면
credentialRecord.signCount보다: -
이는 인증기가 복제(clone)되었을 수도 있다는 신호이나, 증거는 아니다. 예를 들어 다음과 같은 경우일 수 있다:
-
두 개 이상의 자격 증명 개인키가 존재하며 동시에 사용되는 경우.
-
인증기가 고장난 경우.
-
Relying Party가 인증기에서 생성된 순서와 다른 순서로 어서션 응답을 처리하는 경쟁 조건이 존재하는 경우.
Relying Party는 스스로의 운영 특성에 따라 위험 평가에 이 정보를 반영해야 한다. 이 경우 Relying Party가 아래에서
credentialRecord.signCount를 갱신할지, 인증 의식 authentication ceremony를 실패 처리할지 등은 Relying Party별로 다르다.서명 카운터에 관한 더 자세한 정보는 § 6.1.1 서명 카운터 관련 사항 참고.
-
- 크면
-
-
clientExtensionResults에 있는 클라이언트 확장 출력과, authData 내
extensions에 있는 인증기 확장 출력을 Relying Party가 요구하는 대로 처리한다. 각 확장별로 명확하게 처리 단계가 규정되어 있을 수도 있고, Relying Party가 자유롭게 처리할 수도 있다. Relying Party는 부분 또는 전체 확장 출력을 무시할 수 있다.클라이언트는 추가 인증기 확장 또는 클라이언트 확장을 설정해 인증기 확장 출력 또는 클라이언트 확장 출력에 Relying Party가
pkOptions.에서 요청하지 않은 값이 담기게 할 수 있다. 이때 Relying Party는 해당 확장을 무시하거나 어서션을 거부할 수 있으며, 이 결정은 정책 및 사용 중인 확장에 따라 다르다.extensions모든 확장은 클라이언트와 인증기 모두에서 선택 사항이므로, Relying Party는 요청한 확장 중 일부 또는 전부가 처리되지 않을 수 있음을 대비해야 한다.
-
credentialRecord을(를) 새 상태 값으로 갱신한다:
-
credentialRecord.backupState값을 currentBs 값으로 갱신한다. -
credentialRecord.uvInitialized가false라면, authData 내 UV 비트 값을 반영해 갱신한다. 이 때 이 변경은 WebAuthn 사용자 검증과 동등한 인증 수단 추가 인증을 요구해야 하며, 인증이 안 된다면 이 단계는 건너뛴다.
Relying Party가 본 WebAuthn 인증 의식 단계 외의 추가 보안 검사를 한다면, 위 상태 갱신은 그 추가 검증이 성공적으로 끝난 뒤에 해야 한다.
8. 정의된 어테스테이션 명세 형식
WebAuthn은 플러그인 형태의 어테스테이션 명세 형식을 지원합니다. 이 절에서는 그런 형식들에 대한 초기 목록을 정의합니다.
8.1. 어테스테이션 명세 형식 식별자
어테스테이션 명세 형식은 문자열로 식별되며, 이를 어테스테이션 명세 형식 식별자라고 합니다. 이 식별자는 어테스테이션 명세 형식 작성자가 선택합니다.
어테스테이션 명세 형식 식별자는 [IANA-WebAuthn-Registries]가 관리하는 IANA "WebAuthn Attestation Statement Format Identifiers" 레지스트리에 등록하는 것이 좋으며([RFC8809]), 등록된 모든 어테스테이션 명세 형식 식별자는 서로 고유합니다.
등록되지 않은 어테스테이션 명세 형식 식별자는 고유성을 보장하기 위해, 소문자 역방향 도메인 네이밍(reverse domain-name) 방법을 사용하고 개발자가 등록한 도메인명을 사용해야 합니다. 모든 어테스테이션 명세 형식 식별자는 32 오타이트 이하의 길이어야 하며, 인쇄 가능한 US-ASCII 문자만 사용해야 하고, 역슬래시와 따옴표는 사용할 수 없습니다. 즉, [RFC5234]의 VCHAR이지만 %x22(doublequote) 및 %x5c(backslash)는 제외합니다.
참고: 즉, 도메인명을 기반으로 한 어테스테이션 명세 식별자는 LDH Label만 사용할 수 있습니다. [RFC5890] 참고.
구현에서는 WebAuthn 어테스테이션 명세 형식 식별자 비교 시 대소문자를 구분해야 합니다.
여러 버전이 존재할 수 있는 어테스테이션 명세 형식은 식별자에 버전을 포함하여야 합니다. 실제로, 버전이 다르면 서로 다른 형식으로 취급합니다. 예: packed2는 § 8.2 Packed Attestation Statement Format의 새 버전입니다.
다음 절에서 현재 정의되어 등록되어 있는 어테스테이션 명세 형식들과 그 식별자를 소개합니다. 최신 등록 어테스테이션 명세 형식 식별자 목록은 어테스테이션 명세 형식 식별자로서 IANA "WebAuthn Attestation Statement Format Identifiers" 레지스트리 [IANA-WebAuthn-Registries]에서 관리합니다 ([RFC8809]).
8.2. Packed 어테스테이션 명세 형식
이 형식은 WebAuthn에 최적화된 어테스테이션 명세 형식입니다. 매우 압축적이지만 확장 가능하도록 설계된 인코딩 방식을 사용합니다. 자원이 제한적인 인증기(예: 시큐어 엘리먼트 등)에서도 구현할 수 있습니다.
- 어테스테이션 명세 형식 식별자
-
packed
- 지원 어테스테이션 타입
- 구문
-
Packed Attestation의 구문은 아래 CDDL로 정의됩니다:
$$attStmtType //= ( fmt: "packed", attStmt: packedStmtFormat ) packedStmtFormat = { alg: COSEAlgorithmIdentifier, sig: bytes, x5c: [ attestnCert: bytes, * (caCert: bytes) ] } // { alg: COSEAlgorithmIdentifier sig: bytes, }필드들의 의미는 아래와 같습니다:
- alg
-
COSEAlgorithmIdentifier값으로, 어테스테이션 서명에 사용된 알고리즘 식별자입니다. - sig
-
어테스테이션 서명이 담긴 바이트 문자열입니다.
- x5c
-
이 배열의 요소는 attestnCert와 그 인증서 체인(있을 경우)이며, 각각 X.509 형식으로 인코딩됩니다. 어테스테이션 인증서 attestnCert는 배열 내 첫 번째 요소여야 합니다.
- attestnCert
-
X.509 형식으로 인코딩된 어테스테이션 인증서 값입니다.
- 서명 절차
-
이 어테스테이션 명세 형식의 서명 절차는 어설션 서명 생성 절차와 비슷합니다.
-
authenticatorData를 어테스테이션을 위한 인증기 데이터로, clientDataHash를 직렬화된 클라이언트 데이터의 해시로 둡니다.
-
Basic 또는 AttCA 어테스테이션이 사용될 경우, 인증기는 authenticatorData와 clientDataHash를 연결해 sig를 만들고, 인증기에서 선택한 어테스테이션 개인키로 서명합니다. x5c에는 attestnCert 및 연관 인증서 체인(있을 경우)을 설정합니다. alg는 어테스테이션 개인키의 알고리즘으로 설정합니다.
-
Self 어테스테이션이 사용될 경우, 인증기는 authenticatorData와 clientDataHash를 연결해 sig를 만들고, 자격 증명 개인키로 서명합니다. alg는 자격 증명 개인키의 알고리즘으로 설정하고, 나머지 필드는 생략합니다.
-
- 검증 절차
-
검증 절차 입력값 attStmt, authenticatorData, clientDataHash가 주어지면, 검증 절차 는 아래와 같습니다:
-
attStmt가 위에 정의된 구문대로 올바른 CBOR인지 검증하고, CBOR 디코딩으로 포함된 필드를 추출합니다.
-
x5c가 있을 경우:
-
alg에 지정된 알고리즘을 사용해, attestnCert의 어테스테이션 공개키로 authenticatorData와 clientDataHash를 연결한 값에 대한 sig가 올바른 서명인지 검증합니다.
-
attestnCert가 § 8.2.1 Packed 어테스테이션 명세의 인증서 요구사항을 만족하는지 검증합니다.
-
attestnCert에 OID
1.3.6.1.4.1.45724.1.1.4(id-fido-gen-ce-aaguid) 확장이 있으면, 이 확장의 값이 authenticatorData의aaguid와 일치하는지 검증합니다. -
선택적으로, x5c를 검사하고 외부 정보를 참고해 attStmt가 Basic 또는 AttCA 어테스테이션을 전달하는 것인지 판단할 수 있습니다.
-
성공 시, 구현의사에 맞는 값(예: 어테스테이션 타입 Basic, AttCA 또는 불명확, 그리고 어테스테이션 트러스트 경로 x5c)를 반환합니다.
-
-
x5c가 없으면, Self 어테스테이션이 사용 중입니다.
-
authenticatorData의
credentialPublicKey알고리즘과 alg가 같은지 검증합니다. -
sig가 authenticatorData와 clientDataHash 연결값에 대해 alg로 자격 증명 공개키로 올바르게 서명되었는지 검증합니다.
-
성공 시, 구현의사에 맞는 값(예: 어테스테이션 타입 Self 및 빈 어테스테이션 트러스트 경로)을 반환합니다.
-
-
8.2.1. Packed 어테스테이션 명세의 인증서 요구사항
어테스테이션 인증서에는 다음 필드/확장이 반드시 포함되어야 합니다:
-
버전(Version)은 3으로 설정해야 합니다(ASN.1 INTEGER 값 2로 표시됨).
-
주체(Subject)는 아래와 같이 설정해야 합니다:
- Subject-C
-
인증기 벤더가 설립된 국가의 ISO 3166 코드 (PrintableString)
- Subject-O
-
인증기 벤더의 정식 명칭(UTF8String)
- Subject-OU
-
문자열 “Authenticator Attestation”(UTF8String)
- Subject-CN
-
벤더가 정하는 임의의 UTF8String
-
관련 어테스테이션 루트 인증서가 여러 인증기 모델에 사용되는 경우, Extension OID
1.3.6.1.4.1.45724.1.1.4(id-fido-gen-ce-aaguid)가 반드시 존재해야 하며, 16바이트 OCTET STRING의 AAGUID가 포함되어야 합니다. 이 확장은 critical로 지정하면 안 됩니다.Relying Party는 어테스테이션 루트 인증서가 여러 인증기 모델에 쓰이는지 알지 못할 수 있으므로, 해당 확장이 존재하는지 확인하고, 있으면 어테스테이션 객체에 제시된 AAGUID와 값이 일치하는지 검증하는 것이 좋습니다.
X.509 Extension은 DER 인코딩한 값을 OCTET STRING에 담는 방법으로 인코딩하므로, AAGUID는 두 번 OCTET STRING으로 감싸야 유효합니다.
-
Basic Constraints 확장은 CA 컴포넌트를 반드시
false로 설정해야 합니다.
그 외에, Authority Information Access(AIA) 확장의 id-ad-ocsp 항목, 그리고 CRL Distribution Point 확장([RFC5280])은
선택적입니다. 이는 많은 어테스테이션 인증서의 상태가 인증기 메타데이터 서비스로도 제공되기 때문입니다. 예를 들어, FIDO Metadata Service [FIDOMetadataService] 참고.
특정 인증기 모델의 펌웨어 버전 구분을 위해 Extension OID 1.3.6.1.4.1.45724.1.1.5
(id-fido-gen-ce-fw-version)를 사용할 수 있습니다. 있을 경우, 이 속성 값은 0 이상의 정수(INTEGER)이며, 펌웨어 버전이 올라가면
증가됩니다. 이 확장은 critical로 지정하면 안 됩니다.
예를 들어, 다음은 위 확장 OID와 필드를 포함하는 어테스테이션 인증서입니다:
-----BEGIN CERTIFICATE-----MIIBzTCCAXOgAwIBAgIUYHS3FJEL/JTfFqafuAHvlAS+hDYwCgYIKoZIzj0EAwIw QTELMAkGA1UEBhMCVVMxFDASBgNVBAoMC1dlYkF1dGhuIFdHMRwwGgYDVQQDDBNF eGFtcGxlIEF0dGVzdGF0aW9uMCAXDTI0MDEwMzE3NDUyMVoYDzIwNTAwMTA2MTc0 NTIxWjBBMQswCQYDVQQGEwJVUzEUMBIGA1UECgwLV2ViQXV0aG4gV0cxHDAaBgNV BAMME0V4YW1wbGUgQXR0ZXN0YXRpb24wWTATBgcqhkjOPQIBBggqhkjOPQMBBwNC AATDQN9uaFFH4BKBjthHTM1drpb7gIuPod67qyF6UdL4qah6XUp6tE7Prl+DfQ7P YH9yMOOcci3nr+Q/jOBaWVERo0cwRTAhBgsrBgEEAYLlHAEBBAQSBBDNjDlcJu3u 3mU7AHl9A8o8MBIGCysGAQQBguUcAQEFBAMCASowDAYDVR0TAQH/BAIwADAKBggq hkjOPQQDAgNIADBFAiA3k3aAUVtLhDHLXOgY2kRnK2hrbRgf2EKdTDLJ1Ds/RAIh AOmIblhI3ALCHOaO0IO7YlMpw/lSTvFYv3qwO3m7H8Dc -----END CERTIFICATE-----
위 속성들은 인증서에서 다음과 같이 구조화됩니다:
30 21 -- SEQUENCE
06 0B 2B 06 01 04 01 82 E5 1C 01 01 04 -- OID 1.3.6.1.4.1.45724.1.1.4
04 12 -- OCTET STRING
04 10 -- OCTET STRING
CD 8C 39 5C 26 ED EE DE -- AAGUID cd8c395c-26ed-eede-653b-00797d03ca3c
65 3B 00 79 7D 03 CA 3C
30 12 -- SEQUENCE
06 0B 2B 06 01 04 01 82 E5 1C 01 01 05 -- OID 1.3.6.1.4.1.45724.1.1.5
04 03 -- OCTET STRING
02 01 -- INTEGER
2A -- 펌웨어 버전: 42
8.2.2. 엔터프라이즈 Packed 어테스테이션 명세의 인증서 요구사항
Extension OID 1.3.6.1.4.1.45724.1.1.2 (id-fido-gen-ce-sernum)은 엔터프라이즈 목적의 packed
어테스테이션에서 추가로 포함될 수 있습니다. 있을 경우, 이 확장은 특정 AAGUID에 대해 기기별로 고유한 octet string 값을 포함해야 합니다. 이 값은 공장 초기화(factory
reset) 동안에도 동일하게 유지되어야 하며, 기기와 연관된 다른 일련번호 또는 하드웨어 식별자와는 다를 수도 있습니다. 이 확장은 critical로 지정하면 안 되며, 값은 OCTET
STRING으로 인코딩되어야 하며, 엔터프라이즈가 아닌 어테스테이션에는 포함되지 않아야 합니다.
8.3. TPM 어테스테이션 명세 형식
이 어테스테이션 명세 형식은 일반적으로 암호 엔진으로 신뢰 플랫폼 모듈(TPM)을 사용하는 인증기에서 사용됩니다.
- 어테스테이션 명세 형식 식별자
-
tpm
- 지원 어테스테이션 타입
- 구문
-
TPM 어테스테이션의 구문은 아래와 같습니다:
$$attStmtType // = ( fmt: "tpm", attStmt: tpmStmtFormat ) tpmStmtFormat = { ver: "2.0", ( alg: COSEAlgorithmIdentifier, x5c: [ aikCert: bytes, * (caCert: bytes) ] ) sig: bytes, certInfo: bytes, pubArea: bytes }각 필드의 의미는 다음과 같습니다:
- ver
-
서명이 준수하는 TPM 명세 버전입니다.
- alg
-
COSEAlgorithmIdentifier값으로, 어테스테이션 서명에 사용된 알고리즘 식별자입니다. - x5c
-
X.509 인코딩된 aikCert 및 그 인증서 체인입니다.
- aikCert
-
어테스테이션에 사용되는 AIK 인증서(X.509 인코딩).
- sig
-
어테스테이션 서명 값으로, [TPMv2-Part2] 11.3.4절에 명시된 대로 TPMT_SIGNATURE 구조체입니다.
- certInfo
-
위 서명이 계산된 TPMS_ATTEST 구조체로, [TPMv2-Part2] 10.12.8절 참고.
- pubArea
-
TPM이 자격 증명 공개키를 나타내는 데 사용하는 TPMT_PUBLIC 구조체([TPMv2-Part2] 12.2.4절 참고)입니다.
- 서명 절차
-
authenticatorData를 어테스테이션을 위한 인증기 데이터로, clientDataHash를 직렬화된 클라이언트 데이터의 해시로 둡니다.
authenticatorData와 clientDataHash를 연결하여 attToBeSigned를 만듭니다.
[TPMv2-Part3] 18.2절의 절차에 따라 어테스테이션 개인키를 사용해 서명을 생성합니다. 이때
extraData파라미터에는 attToBeSigned를 "alg"와 대응되는 해시 알고리즘으로 다이제스트한 값을 사용합니다. ("RS256"의 경우 SHA-256.)pubArea 필드는 자격 증명 공개키의 공개 영역(TPMT_PUBLIC 구조체)로, certInfo는 TPMS_ATTEST 구조체, sig는 위 과정에서 얻은 서명 값으로 각각 설정합니다.
참고: TPM의 TPM2_ReadPublic 명령으로 pubArea를 읽으면 TPM2B_PUBLIC 구조체가 반환됩니다. TPM2B_PUBLIC은 2바이트 길이 뒤에 TPMT_PUBLIC가 오므로, pubArea에 넣기 전 이 2바이트는 제거해야 합니다.
- 검증 절차
-
검증 절차 입력값 attStmt, authenticatorData, clientDataHash가 주어졌을 때, 검증 절차는 아래와 같다:
attStmt가 위 구문대로 올바른 CBOR인지 확인하고, CBOR 디코딩으로 포함된 필드를 추출합니다.
pubArea의
parameters와unique가 지정한 공개키가, authenticatorData의credentialPublicKey와 동일한지 검증합니다.attestedCredentialData구조체 내에 존재합니다.authenticatorData와 clientDataHash를 연결해 attToBeSigned를 생성합니다.
certInfo의 무결성을 검증합니다.
-
x5c가 존재하는지 확인합니다.
-
aikCert이 § 8.3.1 TPM 어테스테이션 명세의 인증서 요구사항을 만족하는지 확인합니다.
-
aikCert에 OID
1.3.6.1.4.1.45724.1.1.4(id-fido-gen-ce-aaguid) 확장이 있다면, 해당 확장 값이 authenticatorData의aaguid와 같은지 확인합니다. -
sig가 certInfo에 대해 aikCert의 어테스테이션 공개키, alg 알고리즘으로 올바르게 서명됐는지 확인합니다.
certInfo가 유효한지 검증합니다: 참고: certInfo는 TPMS_ATTEST 구조체입니다.
-
magic값이TPM_GENERATED_VALUE로 설정됐는지 확인합니다. -
type값이TPM_ST_ATTEST_CERTIFY로 설정됐는지 확인합니다. -
extraData가 attToBeSigned에 대해 "alg" 해시 알고리즘으로 계산된 해시인지 확인합니다. -
attested에 [TPMv2-Part2] 10.12.3절 기준으로,name필드가 pubArea의 유효한 Name(이름)인TPMS_CERTIFY_INFO구조체가 있는지 확인합니다. Name 계산은 [TPMv2-Part1] 16절의 nameAlg 규칙에 따라 시행합니다.참고: TPM은 항상
name에 pubArea의 nameAlg와 동일한 nameAlg가 사용된 TPMS_CERTIFY_INFO 구조체를 반환합니다.참고: "표준 어테스테이션 구조체" ([TPMv2-Part1] 31.2절)의
qualifiedSigner,clockInfo,firmwareVersion필드는 무시합니다. aikCert 키 속성에 따라 해당 값들이 가려질 수 있습니다. 유효하다면 위험 엔진의 입력값으로 사용할 수 있습니다. -
모두 성공하면, 구현에 맞는 값(예: 어테스테이션 타입 AttCA 와 어테스테이션 트러스트 경로 x5c)을 반환합니다.
-
8.3.1. TPM 어테스테이션 명세의 인증서 요구사항
TPM 어테스테이션 인증서에는 다음 필드/확장이 반드시 포함되어야 합니다:
-
버전(Version)은 3으로 설정해야 합니다.
-
Subject 필드는 비어 있어야 합니다.
-
Subject Alternative Name 확장은 [TPMv2-EK-Profile] 3.2.9절에 정의된 대로 설정되어야 합니다.
참고: [TPMv2-EK-Profile] 옛 버전에서는 EK 인증서에 TPM 일련번호가 담긴 선택적 속성 HardwareModuleName을 허용했습니다. HardwareModuleName은 어테스테이션 인증서의 Subject Alternative Name에 포함하지 않아야 합니다.
-
Extended Key Usage 확장은 OID
2.23.133.8.3("joint-iso-itu-t(2) internationalorganizations(23) 133 tcg-kp(8) tcg-kp-AIKCertificate(3)")를 반드시 포함해야 합니다. -
Basic Constraints 확장은 CA 컴포넌트를 반드시
false로 설정해야 합니다. -
Authority Information Access(AIA) 확장의
id-ad-ocsp항목과 CRL Distribution Point 확장([RFC5280])은 모두 선택 사항입니다. 많은 어테스테이션 인증서의 상태가 메타데이터 서비스로도 제공되기 때문입니다. 예를 들어, FIDO Metadata Service [FIDOMetadataService] 참고.
8.4. Android Key 어테스테이션 명세 형식
해당 인증기가 Android "N" 이상 플랫폼의 플랫폼 인증기라면, 어테스테이션 명세는 Android 키 어테스테이션에 기반합니다. 이런 경우, 어테스테이션 명세는 보안 운영 환경에서 동작하는 컴포넌트가 생성하지만, 어테스테이션을 위한 인증기 데이터는 이 환경 외부에서 생성됩니다. WebAuthn Relying Party는 어테스테이션에 사용된 것으로 주장되는 인증기 데이터가 어테스테이션 인증서 확장 데이터 필드와 일치하는지 확인해야 합니다.
- 어테스테이션 명세 형식 식별자
-
android-key
- 지원 어테스테이션 타입
- 구문
-
Android key 어테스테이션 명세는 Android 어테스테이션 명세(즉, DER로 인코딩된 X.509 인증서 시퀀스)로 구성됩니다. 자세한 내용은 Android 개발자 문서를 참고하십시오. 구문은 다음과 같이 정의됩니다:
$$attStmtType //= ( fmt: "android-key", attStmt: androidStmtFormat ) androidStmtFormat = { alg: COSEAlgorithmIdentifier, sig: bytes, x5c: [ credCert: bytes, * (caCert: bytes) ] } - 서명 절차
-
authenticatorData를 어테스테이션을 위한 인증기 데이터로, clientDataHash를 직렬화된 클라이언트 데이터의 해시로 둡니다.
Android Key 어테스테이션을 요청할 때
keyStore.getCertificateChain(myKeyUUID)를 호출하고, clientDataHash를 challenge 값으로 제공합니다(예: setAttestationChallenge 사용). x5c는 반환 값을 그대로 사용합니다.인증기는 authenticatorData와 clientDataHash를 연결한 값을 자격 증명 개인키로 서명하여 sig 값을 생성하고, alg는 해당 서명 알고리즘으로 설정합니다.
- 검증 절차
-
검증 절차 입력값 attStmt, authenticatorData, clientDataHash가 주어지면, 검증 절차는 다음과 같습니다:
-
attStmt가 위 정의된 구문에 맞는 유효한 CBOR인지 확인하고, CBOR 디코딩 후 필드를 추출합니다.
-
sig가 authenticatorData와 clientDataHash를 연결해 만든 값에 대해 x5c 첫번째 인증서의 공개키와 alg 알고리즘으로 올바른 서명인지 검증합니다.
-
x5c의 첫 번째 인증서에서 추출한 공개키가, authenticatorData 내
credentialPublicKey와 동일한지 검증합니다. -
어테스테이션 인증서의 확장 데이터의
attestationChallenge필드가 clientDataHash와 동일한지 검증합니다. -
어테스테이션 인증서 확장 데이터의 authorization list에서 아래 항목을 확인합니다:
-
AuthorizationList.allApplications필드는 두 authorization list(softwareEnforced,teeEnforced) 어디에도 없어야 합니다. PublicKeyCredential은 반드시 RP ID 범위여야 합니다. -
이하 조건들은 RP가 신뢰 실행환경(TEE) 키만 허용하려면
teeEnforced리스트만, 그렇지 않으면teeEnforced와softwareEnforced의 합집합을 사용합니다.-
AuthorizationList.origin필드 값이KM_ORIGIN_GENERATED과 일치해야 합니다. -
AuthorizationList.purpose필드 값이KM_PURPOSE_SIGN과 일치해야 합니다.
-
-
-
모두 성공 시, 구현에 따라 어테스테이션 유형 Basic 및 어테스테이션 트러스트 경로 x5c를 반환합니다.
-
8.4.1. Android Key 어테스테이션 명세의 인증서 요구사항
Android Key 어테스테이션 어테스테이션 인증서의 Android key 어테스테이션 인증서 확장 데이터는 OID
1.3.6.1.4.1.11129.2.1.17로 식별되며, 스키마는 Android
개발자 문서에서 정의되어 있습니다.
8.5. Android SafetyNet 어테스테이션 명세 형식
참고: 이 형식은 더 이상 권장되지 않으며, 문서의 이후 버전에서 삭제될 예정입니다.
해당 인증기가 특정 Android 플랫폼의 플랫폼 인증기라면, 어테스테이션 명세는 SafetyNet API에 기반할 수 있습니다. 이 경우 인증기 데이터는 SafetyNet API를 호출하는 측(일반적으로 Android 애플리케이션)의 완전한 제어 하에 있으며, 어테스테이션 명세는 플랫폼 상태 및 호출 애플리케이션의 신원에 대해 일부 진술을 제공합니다. (자세한 내용은 SafetyNet 문서 참고.)
- 어테스테이션 명세 형식 식별자
-
android-safetynet
- 지원 어테스테이션 타입
- 구문
-
Android 어테스테이션 명세의 구문은 다음과 같습니다:
$$attStmtType //= ( fmt: "android-safetynet", attStmt: safetynetStmtFormat ) safetynetStmtFormat = { ver: text, response: bytes }각 필드의 의미는 다음과 같습니다:
- ver
-
SafetyNet API를 제공하는 Google Play Services의 버전번호입니다.
- response
-
SafetyNet API의 getJwsResult() 호출의 UTF-8 인코딩 결과입니다. 이 값은 Compact Serialization 형태의 JWS [RFC7515] 객체입니다(자세한 내용은 SafetyNet 온라인 문서 참고).
- 서명 절차
-
authenticatorData를 어테스테이션을 위한 인증기 데이터로, clientDataHash를 직렬화된 클라이언트 데이터의 해시로 둡니다.
authenticatorData와 clientDataHash를 연결하고, SHA-256 해시를 수행해 나온 결과를 attToBeSigned로 둡니다.
SafetyNet 어테스테이션을 요청할 때 attToBeSigned를 nonce로 제공해야 합니다. response는 SafetyNet이 반환한 응답, ver는 구동 중인 Google Play Services 버전으로 설정합니다.
- 검증 절차
-
검증 절차 입력값 attStmt, authenticatorData, clientDataHash가 주어지면, 검증 절차는 다음과 같습니다:
-
attStmt가 위 구문에 맞는 유효한 CBOR인지, CBOR 디코딩 후 필드를 추출합니다.
-
response 값이 ver 버전을 따르는 올바른 SafetyNet 응답인지 SafetyNet 온라인 문서에 정의된 단계로 검사합니다. (현재 SafetyNet 응답 형식은 하나뿐이며, ver는 향후 지원을 위해 예약됨.)
-
response의 payload에서
nonce속성이 authenticatorData와 clientDataHash를 연결해 SHA-256 한 값을 Base64한 값과 동일한지 검증합니다. -
SafetyNet 응답이 실제로 SafetyNet 서비스에서 발급됐는지 SafetyNet 온라인 문서에 안내된 절차로 확인합니다.
-
모두 성공 시, 구현 의사에 따라 어테스테이션 유형 Basic 및 어테스테이션 트러스트 경로 x5c를 반환합니다.
-
8.6. FIDO U2F 어테스테이션 명세 형식
이 어테스테이션 명세 형식은 [FIDO-U2F-Message-Formats]에 정의된 포맷을 사용하는 FIDO U2F 인증기에서 사용됩니다.
- 어테스테이션 명세 형식 식별자
-
fido-u2f
- 지원 어테스테이션 타입
- 구문
-
FIDO U2F 어테스테이션 명세의 구문은 다음과 같습니다:
$$attStmtType //= ( fmt: "fido-u2f", attStmt: u2fStmtFormat ) u2fStmtFormat = { x5c: [ attestnCert: bytes ], sig: bytes }각 필드의 의미는 다음과 같습니다:
- x5c
-
X.509 형식의 어테스테이션 인증서 한 개가 담긴 배열입니다.
- sig
-
어테스테이션 서명 값입니다. 이 서명은 [FIDO-U2F-Message-Formats]에 정의된 U2F 등록 응답 메시지 원문 전체에 대해 계산됩니다. (인증기로부터 클라이언트가 전송받은 데이터.)
- 서명 절차
-
attested credential의 자격 증명 공개키가 알고리즘 -7("ES256")이 아니면 중지하고 에러를 반환합니다. 그렇지 않으면 authenticatorData를 어테스테이션을 위한 인증기 데이터로, clientDataHash를 직렬화된 클라이언트 데이터의 해시로 둡니다. (SHA-256이 쓰이므로 clientDataHash는 32바이트입니다.)
[FIDO-U2F-Message-Formats] 4.3절(Registration Response Message)에 따라 등록 응답 메시지를 만드는데, application parameter는 해당 자격 증명이 속한 RP ID의 SHA-256 해시, challenge parameter는 clientDataHash, key handle parameter는 해당 자격 증명 ID로 합니다. 해당 메시지의 raw signature 부분(즉, 사용자 공개키, key handle, 인증서 제외)이 sig로, 어테스테이션 공개키의 인증서가 x5c로 설정됩니다.
- 검증 절차
-
검증 절차 입력값 attStmt, authenticatorData, clientDataHash가 주어지면, 검증 절차는 다음과 같습니다:
-
attStmt가 위 구문대로 유효한 CBOR인지 확인한 후, CBOR 디코딩 후 필드를 추출합니다.
-
x5c에 정확히 한 개의 요소가 있는지 확인하고, attCert가 해당 인증서임을 둡니다. certificate public key는 attCert의 공개키입니다. 만약 해당 공개키가 P-256 곡선 상의 타원곡선(EC) 공개키가 아니라면 실패 처리합니다.
-
authenticatorData에서 rpIdHash를, 그리고 authenticatorData.
attestedCredentialData에서 credentialId와 credentialPublicKey를 추출합니다. -
credentialPublicKey(COSE_KEY 형식, RFC9052 7절)을 Raw ANSI X9.62 공개키 형식(FIDO Registry 3.6.2절)으로 변환합니다.
-
x는 credentialPublicKey의 "-2" 키(x 좌표) 값으로, 크기는 32바이트이어야 합니다. 크기가 다르거나 키가 없으면 알고리즘을 실패 처리합니다.
-
y는 credentialPublicKey의 "-3" 키(y 좌표) 값으로, 크기는 32바이트이어야 합니다. 크기가 다르거나 키가 없으면 실패 처리합니다.
-
publicKeyU2F는
0x04 || x || y로 연결한 값입니다.참고: 이것은 ECC 압축되지 않은(UNCOMPRESSED) 공개키 형식입니다.
-
-
verificationData는
0x00 || rpIdHash || clientDataHash || credentialId || publicKeyU2F으로 연결한 값입니다(4.3절 참고). -
sig를 verificationData와 certificate public key로 [SEC1] 4.1.4절의 절차에 따라 SHA-256 해시를 사용해 검증합니다.
-
선택적으로 x5c를 검사하고, 외부 정보를 참고해 attStmt가 Basic 또는 AttCA 어테스테이션인지 확인 가능합니다.
-
모두 성공하면, 구현 의사에 따라 어테스테이션 유형 Basic, AttCA 또는 불명확, 그리고 어테스테이션 트러스트 경로 x5c를 반환합니다.
-
8.7. None 어테스테이션 명세 형식
none 어테스테이션 명세 형식은 WebAuthn Relying Party가 인증기가 제공한 어테스테이션 명세를 받고 싶지 않음을 나타냈을 때, 이를 대체하는 용도로 사용됩니다. 자세한 내용은 § 5.4.7 Attestation Conveyance Preference Enumeration (enum AttestationConveyancePreference)를 참조하십시오.
인증기가 어테스테이션을 지원하지 않으면, 인증기가 직접 이 형식의 어테스테이션 명세를 생성할 수도 있습니다.
- 어테스테이션 명세 형식 식별자
-
none
- 지원 어테스테이션 타입
- 구문
-
none 어테스테이션 명세의 구문은 다음과 같습니다:
$$attStmtType //= ( fmt: "none", attStmt: emptyMap ) emptyMap = {} - 서명 절차
-
위에 정의된 정해진 어테스테이션 명세를 반환합니다.
- 검증 절차
-
구현의사에 맞게 어테스테이션 유형 None과 빈 어테스테이션 트러스트 경로를 반환합니다.
8.8. Apple 익명 어테스테이션 명세 형식
이 어테스테이션 명세 형식은 Apple에서 WebAuthn을 지원하는 특정 Apple 기기에서만 사용됩니다.
- 어테스테이션 명세 형식 식별자
-
apple
- 지원 어테스테이션 타입
- 구문
-
Apple 어테스테이션 명세의 구문은 아래와 같이 정의됩니다:
$$attStmtType //= ( fmt: "apple", attStmt: appleStmtFormat ) appleStmtFormat = { x5c: [ credCert: bytes, * (caCert: bytes) ] }이 필드들의 의미는 다음과 같습니다:
- x5c
-
credCert와 그 이후의 인증서 체인이 X.509 형식으로 각각 들어갑니다.
- credCert
-
어테스테이션에 사용되는 자격 증명 공개키 인증서로, X.509 형식입니다.
- 서명 절차
-
-
authenticatorData를 어테스테이션의 인증기 데이터로 하고, clientDataHash를 직렬화된 클라이언트 데이터의 해시로 둡니다.
-
authenticatorData와 clientDataHash를 연결하여 nonceToHash를 만듭니다.
-
nonceToHash에 SHA-256 해시를 하여 nonce를 생성합니다.
-
Apple 익명 어테스테이션 CA가 자격 증명 공개키에 대한 X.509 인증서를 발급하며, nonce를 OID
1.2.840.113635.100.8.2확장 필드로 인증서에 포함합니다. credCert가 이 인증서입니다. credCert가 어테스테이션 증거가 되며, 포함된 nonce는 해당 어테스테이션이 실시간임을 증명합니다. 또한 nonce는 authenticatorData 및 클라이언트 데이터의 무결성도 보장합니다. -
x5c에 credCert와 인증서 체인들을 넣습니다.
-
- 검증 절차
-
검증 절차 입력(attStmt, authenticatorData, clientDataHash)가 주어지면, 검증 절차는 다음과 같이 진행됩니다:
-
attStmt가 위에서 정의한 구문대로의 유효한 CBOR인지 확인하고, CBOR 디코딩으로 필드를 추출합니다.
-
authenticatorData와 clientDataHash를 연결해 nonceToHash를 만듭니다.
-
nonceToHash에 SHA-256 해시를 하여 nonce를 생성합니다.
-
nonce값이 credCert의 OID
1.2.840.113635.100.8.2확장 필드 값과 동일한지 검증합니다. -
자격 증명 공개키와 credCert의 Subject Public Key 값이 같은지 검증합니다.
-
모두 성공하면 어테스테이션 타입 익명화 CA와 어테스테이션 트러스트 경로 x5c를 나타내는 구현별 값들을 반환합니다.
-
8.9. 복합 어테스테이션 명세 형식
"compound" 어테스테이션 명세 형식은 한 번의 ceremony에서 여러 개의 독립된(자기완결적) 어테스테이션 명세를 전달하는 데 사용됩니다.
- 어테스테이션 명세 형식 식별자
-
compound
- 지원 어테스테이션 타입
-
제한 없음. § 6.5.3 어테스테이션 타입 참고.
- 구문
-
복합 어테스테이션 명세의 구문은 다음과 같이 정의됩니다:
$$attStmtType //= ( fmt: "compound", attStmt: [2* nonCompoundAttStmt] ) nonCompoundAttStmt = { $$attStmtType } .within { fmt: text .ne "compound", * any => any } - 서명 절차
-
해당 없음
- 검증 절차
-
검증 절차 입력값 attStmt, authenticatorData, clientDataHash가 주어지면, 검증 절차는 다음과 같습니다:
-
attStmt 내의 각 subStmt마다 해당 어테스테이션 명세 형식 식별자
subStmt.fmt에 대응하는 검증 절차를 검증 절차 입력값 (subStmt, authenticatorData, clientDataHash)로 평가합니다.하나 이상의 subStmt에 대해 유효성 검증에 실패하면, 이에 대한 처리는 Relying Party 정책에 따릅니다.
-
충분히 많은(이 기준은 Relying Party 정책에 따라 결정됨) 항목이 성공적으로 검증되면, 성공한 검증 절차의 출력 조합을 나타내는 구현별 값을 반환합니다.
-
9. WebAuthn 확장
공개키 자격 증명의 생성, 인증 어서션의 요청 및 생성을 위한 § 5 Web Authentication API에서 정의된 메커니즘은 특정 용례에 맞게 확장할 수 있습니다. 각 용례는 등록 확장 또는 인증 확장을 정의함으로써 지원됩니다.
모든 확장은 클라이언트 확장입니다. 즉, 확장은 클라이언트와의 통신과 처리 과정을 포함합니다. 클라이언트 확장은 다음과 같은 단계와 데이터를 정의합니다:
-
navigator.credentials.create()확장 요청 파라미터와 등록 확장에 대한 응답 값을 정의합니다. -
navigator.credentials.get()확장 요청 파라미터와 인증 확장에 대한 응답 값을 정의합니다. -
클라이언트 확장 처리는 등록 확장과 인증 확장 둘 다에 대해 정의됩니다.
공개키 자격 증명을
생성하거나 인증
어서션을 요청할 때 WebAuthn Relying Party는 여러 확장들의 사용을 요청할 수 있습니다. 각 확장은 클라이언트 또는
WebAuthn
인증기가 지원할 경우 해당 작업 도중 호출됩니다. Relying Party는 get()
호출(인증 확장) 또는 create()
호출(등록 확장)에서 각 확장에 대해 클라이언트 확장 입력을 전송합니다.
클라이언트는 지원하는 각 확장마다 클라이언트 확장 처리를 수행하며, 각
확장별로 확장 식별자와 클라이언트 확장
출력 값을 클라이언트 데이터에 포함해 결과를
보강합니다.
확장에는 인증기 확장도 있습니다. 인증기 확장은 인증기와의 통신 및 처리를 포함한다는 의미입니다. 인증기 확장은 다음 단계를 정의합니다:
-
authenticatorMakeCredential 확장 요청 파라미터와 등록 확장의 응답 값을 정의합니다.
-
authenticatorGetAssertion 확장 요청 파라미터와 인증 확장의 응답 값을 정의합니다.
인증기 확장의 경우, 클라이언트 확장 처리의 일환으로,
클라이언트는 각 확장에 대해 CBOR 인증기 확장 입력 값을 생성(보통
대응하는 클라이언트 확장
입력에서 계산)하여 호출 도중 인증기에 전달합니다(create()
호출 시 등록 확장, get()
호출 시 인증 확장). 이 값들은 CBOR 형식의 이름-값 쌍으로 전달되며, 이름은
확장 식별자, 값은 해당
인증기 확장 입력입니다. 인증기는 지원하는 확장별로 추가 처리를 하고, 각 확장별로 CBOR 인증기 확장 출력을
반환합니다. 인증기 확장 출력은 서명된 인증기 데이터 일부로 반환되므로, 인증기 확장에서는 서명되지 않은
확장 출력도 정의할 수 있습니다(예: 출력 값이 인증기 데이터에 의존적일 때).
클라이언트
확장 처리의 일환으로 인증기 확장에서 인증기 확장 출력 및 서명되지 않은 확장 출력을 활용하여 클라이언트 확장
출력을 생성할 수도 있습니다.
모든 WebAuthn 확장은 클라이언트와 인증기 모두에서 선택사항입니다. 즉, Relying Party가 요청한 확장을 브라우저 또는 OS가 인증기까지 전달하지 않거나, 인증기가 무시할 수 있으며, 어떠한 경우에도 WebAuthn API 처리 과정에서 실패로 간주하지 않습니다. 따라서 Relying Party는 확장을 API 호출에 포함할 때, 일부 또는 전부가 무시될 수 있음을 고려해야 합니다.
모든 WebAuthn 확장은 클라이언트나 인증기가 미지원하더라도 사용자의 보안 및 프라이버시를 침해하지 않도록 정의해야 합니다. 예를 들어, 확장에서 클라이언트 처리가 필요하다면 JSON에서 CBOR로 단순 변환만 해도 인증기에서 의미 없는 값을 생성하게 설계하면, 인증기는 해당 확장을 자동으로 무시합니다. 모든 확장이 선택사항이므로 이로 인해 API 동작상 실패가 발생하지 않습니다.
최신 WebAuthn 확장 목록은 [IANA-WebAuthn-Registries]의 IANA "WebAuthn Extension Identifiers" registry에서 확인 가능합니다.
9.1. 확장 식별자
확장은 확장 저자가 지정하는 문자열인 확장 식별자로 식별됩니다.
확장 식별자는 [IANA-WebAuthn-Registries]의 IANA "WebAuthn Extension Identifiers" registry에 등록하는 것이 좋으며([RFC8809]), 등록된 모든 확장 식별자는 서로 고유합니다.
등록되지 않은 확장 식별자는 전역적으로 고유하도록, 예를 들어 정의 엔티티 이름을 포함(myCompany_extension 등)하는 식으로 지어야 합니다.
모든 확장 식별자는 최대 32 옥타이트 이내, 인쇄 가능한 USASCII 문자만(따옴표, 역슬래시 제외)이어야 하며, [RFC5234]의 VCHAR이지만 %x22/5c 없이 구성되어야 하고, 구현체는 대소문자를 구분해서 비교해야 합니다.
여러 버전이 존재할 수 있는 확장은 식별자에 버전을 포함하도록 해야 합니다. 실제로, 버전이 다르면 각기 다른 확장으로 간주됩니다. 예:
myCompany_extension_01
§ 10 정의된 확장은 추가 확장과 그 식별자를 정의합니다. 최신 목록은 IANA "WebAuthn Extension Identifiers" [IANA-WebAuthn-Registries]에서 확인하십시오.
9.2. 확장 정의 방법
확장 정의에는 반드시 확장 식별자, 클라이언트 확장 입력 인자(이를 get() 또는 create()로 전달), 클라이언트 확장 처리 규칙, 클라이언트 확장 출력 값을 명시해야 합니다. 인증기와 통신하는 인증기 확장인 경우, CBOR 인증기 확장 입력 인자(이를 authenticatorGetAssertion 또는 authenticatorMakeCredential 호출로 전달), 인증기 확장 처리 규칙, CBOR 인증기 확장 출력 값을 지정해야 합니다. 확장은 서명되지 않은 확장 출력도 정의할 수 있습니다.
클라이언트가 처리하는 클라이언트 확장은,
반드시 클라이언트 확장
출력값을 반환해야 하며, 이를 통해 WebAuthn Relying Party가 해당 확장이 클라이언트에서 처리된 것을 인지할 수 있습니다.
마찬가지로 인증기 처리가 필요한 확장은 반드시 인증기 확장 출력을 반환하여, Relying Party가 인증기에서 처리됐음을 인지할 수 있게
해야 합니다. 결과 값이 필요 없는 확장은 true로 된 JSON Boolean 클라이언트 확장 출력으로 정의할 수 있습니다. 인증기
확장도 마찬가지로, 값이 필요 없다면 true(CBOR Boolean)을 반환해야 합니다.
9.3. 확장 요청 파라미터 확장하기
확장은 1~2개의 요청 인자를 정의합니다. 클라이언트 확장 입력은 JSON으로 인코딩될 수 있는 값이며,
WebAuthn
Relying Party에서
get()
또는 create()
호출 시 클라이언트에 전달됩니다.
CBOR 인증기 확장 입력은 클라이언트에서 인증기 확장 처리
도중 인증기로 전달됩니다.
Relying Party는 확장 사용을 요청하면서,
클라이언트 확장 입력을
extensions
옵션에 키-값쌍(확장 식별자-값)으로 포함해 create()
또는 get()
호출 시 이용합니다.
참고: 다른 문서에서는 확장 입력 시 "항상" 확장 식별자가 키가 아니도록 정의한 경우가 있습니다. 위 관례는 신규 확장에 그대로 적용됩니다.
var assertionPromise= navigator. credentials. get({ publicKey: { // Other members omitted for brevity extensions: { // An "entry key" identifying the "webauthnExample_foobar" extension, // whose value is a map with two input parameters: "webauthnExample_foobar" : { foo: 42 , bar: "barfoo" } } } });
확장 정의 시 클라이언트 확장
입력의 유효 값도 명시해야 합니다. 클라이언트는 유효하지 않은 입력의 확장은 무시해야 합니다. 인자 값이 필요 없는 확장은 Boolean 값 true로
요청하도록 정의할 수 있습니다.
클라이언트 처리에만 영향을 주는 확장은 인증기 확장 입력을 정의할 필요가 없습니다. 인증기 처리가 필요한 확장은 클라이언트 확장 입력에서
인증기 확장 입력을 어떻게 계산하는지 정의해야 하며, CDDL 타입
AuthenticationExtensionsAuthenticatorInputs
및
AuthenticationExtensionsAuthenticatorOutputs에서
$$extensionInput과 $$extensionOutput 그룹 소켓에 확장 식별자를 키로 추가해야 합니다. 입력 파라미터가 필요없는
확장(즉, Boolean 클라이언트 확장 입력 true)은 인증기 확장 입력도 Boolean
true(CBOR major type 7, value 21)로 정의됩니다.
아래 예시는 식별자
webauthnExample_foobar인 확장이 unsigned integer 입력을 인증기 확장 입력으로 받고, 1개 이상의 바이트 문자열 배열을 인증기 확장
출력값으로 반환함을 정의합니다:
$$extensionInput //= ( webauthnExample_foobar : uint) $$extensionOutput //= ( webauthnExample_foobar : [ + bytes] )
일부 인증기는 블루투스 저전력, NFC 등 좁은 대역폭 링크를 사용하므로, 확장 설계 시 인증기 인자가 최대한 작도록 권장합니다.
9.4. 클라이언트 확장 처리
확장은 자격 증명 생성 또는 어서션 생성 시 클라이언트에서 추가 처리 요구를 정의할 수 있습니다. 해당 확장의 클라이언트 확장 입력값이 이 처리의 입력값이 됩니다. 클라이언트는 지원하는 클라이언트 확장마다 clientExtensions map에 확장 식별자를 키, 해당 확장 입력값을 값으로 추가합니다.
마찬가지로, 클라이언트
확장 출력은 getClientExtensionResults()
반환값의 딕셔너리로 표현되며, 키는 확장 식별자, 값은 각 확장의 클라이언트 확장 출력입니다.
클라이언트 확장
입력처럼, 클라이언트 확장 출력도 JSON으로 인코딩 가능한 값이어야 합니다.
무시된 확장에 대해서는 어떤 값도 반환하면 안 됩니다.
인증기 처리 확장이 필요한 경우, 클라이언트 확장 입력을 바탕으로 CBOR 인증기 확장 입력을 계산하는 방법과, CBOR 인증기 확장 출력, 그리고 서명되지 않은 확장 출력이 사용될 때, 그것을 클라이언트 확장 출력으로 변환하는 방법도 정의해야 합니다.
9.5. 인증기 확장 처리
처리된 각 인증기 확장의 CBOR 인증기 확장 입력 값은 authenticatorMakeCredential 및 authenticatorGetAssertion 동작의 extensions 파라미터에 포함됩니다. extensions는 CBOR map으로, 키는 확장 식별자이며 값은 해당 인증기 확장 입력입니다.
확장 출력은 인증기 데이터의 extensions 파트에 표현됩니다. 인증기 데이터의 extensions 파트는 CBOR map으로, 키는 확장 식별자이며 값은 해당 인증기 확장 출력입니다.
서명되지 않은 확장 출력은 인증기 데이터와 별개로 표현되며, 인증기가 반환하는 별도 map입니다(키는 동일 확장 식별자를 사용함). 이 map은 서명되지 않은 출력을 사용하는 인증기 확장에만 해당 항목을 포함합니다. 확장에서 인증기 데이터에 대한 서명을 출력하는 경우, 또는 일부 출력이 Relying Party에 전송되지 않아야 할 경우 등에서 유용합니다.
참고: [FIDO-CTAP]에서는
unsignedExtensionOutputs라는 map에 CBOR로 반환됩니다.
각 지원 확장별로, 해당 확장에 대한 인증기 확장 처리 규칙을 적용해 인증기 확장 출력 및 필요시 서명되지 않은 확장 출력을 해당 입력과 추가 입력값에서 계산합니다. 무시된 확장에 대해서는 어떤 값도 반환하면 안 됩니다.
10. 정의된 확장
이 절과 하위 절에서는 IANA "WebAuthn Extension Identifiers" 레지스트리([IANA-WebAuthn-Registries])에 추가로 등록될 확장들을 정의합니다. 이 확장들은 다양한 상호운용성을 목표로 사용자 에이전트에서 구현될 수 있습니다.
10.1. 클라이언트 확장
이 절에서는 오직 클라이언트 확장만을 정의합니다.
10.1.1. FIDO AppID 확장 (appid)
이 확장은 이전에 FIDO U2F JavaScript API [FIDOU2FJavaScriptAPI]로 자격 증명을 등록한 WebAuthn Relying Party가 어서션을 요청할 수 있도록 합니다. FIDO API는 Relying Party에 대해 AppID라는 추가 식별자를 사용하며([FIDO-APPID]), 해당 API로 생성된 자격 증명은 모두 그 식별자로 스코프가 지정됩니다. 이 확장 없이는 AppID가 아닌 RP ID로 스코프를 변경하려면 자격 증명을 재등록해야 했습니다.
appid
확장 입력 외에,
U2F 자격 증명 인증을 허용하려면 Relying
Party 쪽에서 다음 추가 처리가 필요합니다:
-
원하는 U2F 자격 증명들을
allowCredentials옵션에 나열합니다.get()메서드 이용:-
type값을public-key로 설정. -
id값은 원하는 U2F 키 핸들로 설정. U2F 키 핸들은 보통 base64url 인코딩이지만, 실제 전달 시에는 바이너리로 디코드해야 함.
allowCredentials에 WebAuthn 자격 증명 ID와 U2F 키 핸들을 혼합해 사용 가능하며, 이 확장 입력이 WebAuthn의 RP ID 스코프의 자격 증명 사용을 막지는 않습니다. -
이 확장만으로 FIDO 호환 자격 증명을 생성할 수 없습니다. 즉, WebAuthn에서 생성된 자격 증명은 FIDO JS API와 호환되지 않습니다.
참고: appid
값은 Relying Party가
이전에 FIDO API에서 사용한 AppID로 설정해야 하며, WebAuthn RP ID와 변환 값이 다를 수 있습니다. 예를 들어 이전 AppID가 "https://accounts.example.com"이었고, 현재
RP ID가 "example.com"일 수 있음.
- 확장 식별자
-
appid - 적용 용도
- 클라이언트 확장 입력
-
FIDO AppID를 지정하는 DOMString 하나.
partial dictionary AuthenticationExtensionsClientInputs {DOMString ; };appid - 클라이언트 확장 처리
-
-
facetId를 호출자의 origin을 FIDO의 FacetID 결정 알고리즘에 넣어 얻습니다.
-
appId는 확장 입력입니다.
-
facetId와 appId를 FIDO의 FacetID가 해당 AppID에 대해 권한이 있는지 판단하는 알고리즘에 전달합니다. 거부되면
SecurityErrorDOMException를 반환합니다. -
allowCredentialDescriptorList 생성 중에, U2F 인증기가 자격 증명이 부적합하다고 나타내면(
SW_WRONG_DATA반환 등) 클라이언트는 U2F application parameter를 appId의 SHA-256 해시로 다시 시도해야 하며, 이로 유효한 자격 증명을 찾으면 이를 리스트에 반드시 포함해야 합니다. 이 경우 appId가 authenticatorGetAssertion의 rpId 파라미터 대신 사용됩니다. -
output를 Boolean
false로 둡니다. -
assertionCreationData 생성 시, U2F 인증기가 appId의 SHA-256 해시를 U2F application parameter로 사용해 어서션을 만들었다면 output을
true로 둡니다.
-
참고: 실제로는 여러 구현이 위 FacetID/권한검증 알고리즘의 step 4 이후를 생략하며, 대신 step 3에서 호스트 비교를 동일 사이트(same site)까지만 허용합니다.
- 클라이언트 확장 출력
-
output 값을 반환합니다. true면 AppID가 사용됐으므로 어서션 검증 시
rpIdHash는 AppID의 해시, RP ID가 아니여야 함을 Relying Party가 예상해야 합니다.partial dictionary AuthenticationExtensionsClientOutputs {boolean ; };appid - 인증기 확장 입력
-
없음.
- 인증기 확장 처리
-
없음.
- 인증기 확장 출력
-
없음.
10.1.2. FIDO AppID 제외 확장(appidExclude)
이 등록 확장은 WebAuthn Relying Party가 이전 FIDO U2F JavaScript API [FIDOU2FJavaScriptAPI]로 생성된 특정 자격 증명을 포함하는 인증기를 제외하도록 허용합니다.
FIDO U2F JavaScript API에서의 전환 중, Relying Party는 레거시 자격 증명을 이미 등록한 사용자를 다수 보유할 수 있습니다. appid 확장은 로그인 플로우 전환을 원활하게 할 수 있지만, 등록 플로우 전환 시 excludeCredentials 필드는 해당 내용을 WebAuthn 자격 증명으로만 간주하기 때문에 레거시 자격 증명이 있는 인증기를 효과적으로 제외하지 못합니다. 이 확장은 클라이언트 플랫폼이 excludeCredentials 목록을 WebAuthn과 레거시 FIDO 자격 증명 모두로 간주하도록 지시합니다. 참고로, U2F 키 핸들은 일반적으로 base64url 인코딩을 사용하지만, excludeCredentials 내에서 사용할 때는 바이너리로 디코딩해야 합니다.
- 확장 식별자
-
appidExclude - 적용 작업
- 클라이언트 확장 입력
-
FIDO AppID를 지정하는 단일 DOMString 값.
partial dictionary AuthenticationExtensionsClientInputs {DOMString ; };appidExclude - 클라이언트 확장 처리
-
새 자격 증명 생성 시:
-
RP ID를 정한 직후 다음 단계 수행:
-
facetId를 호출자의 origin을 FIDO FacetID 결정 알고리즘에 넣은 결과로 한다.
-
appId를 확장 입력
appidExclude의 값으로 한다. -
facetId, appId를 FIDO FacetID/권한 알고리즘에 전달한다. 거부되면
SecurityErrorDOMException을 반환하고 자격 증명 생성 알고리즘 및 이 절차를 즉시 종료한다.참고: 실제로 여러 구현체는 FacetID/AppID 권한 알고리즘의 4단계 이후를 구현하지 않으며, 대신 3단계에서 호스트 비교를 same site로 완화함.
-
위 조건에 걸리지 않으면 일반 절차대로 진행.
-
-
authenticatorMakeCredential 호출 직전 다음 단계 수행:
-
authenticator가 U2F 프로토콜 [FIDO-U2F-Message-Formats] 지원 시, excludeCredentialDescriptorList 내 각 credential descriptor C에 대해:
-
C가 U2F 자격 증명인지 확인하려면 authenticator에 다음 "5가지 값"으로
U2F_AUTHENTICATE메시지를 전송:- control byte
-
0x07("check-only") - challenge parameter
-
32바이트 랜덤
- application parameter
-
appId의 SHA-256 해시
- key handle length
-
C.의 길이(바이트)id - key handle
-
C., 즉 credential idid
-
authenticator가
message:error:test-of-user-presence-required(즉, 성공)으로 응답하면, 해당 authenticator에 대한 일반 처리 중단 및 플랫폼 구현별로 인증기 사용 불가 표시(UI, 추가 사용자 동의 요청 등, 동의시InvalidStateError처리 가능). 사용자 동의는 control byte만0x03("enforce-user-presence-and-sign")으로 재전송해 응답 무시해도 됨.
-
-
위 절차 없이 일반 처리 지속.
-
-
- 클라이언트 확장 출력
-
Relying Party에 이 확장이 적용되었음을
true값으로 반환합니다.partial dictionary AuthenticationExtensionsClientOutputs {boolean ; };appidExclude - 인증기 확장 입력
-
없음.
- 인증기 확장 처리
-
없음.
- 인증기 확장 출력
-
없음.
10.1.3. 자격 증명 속성 확장(credProps)
이 클라이언트 등록 확장은 클라이언트가 알고 있는 특정 자격 증명 속성을 WebAuthn Relying Party에게 등록 절차 결과로 공개키 자격 증명 소스가 생성될 때 보고할 수 있도록 합니다.
현재, 하나의 자격 증명 속성이 정의되어 있습니다: 클라이언트 측 발견 가능한 자격 증명 속성입니다.
- 확장 식별자
-
credProps - 적용 작업
- 클라이언트 확장 입력
-
Relying Party가 이 확장을 요청함을 나타내기 위해
trueBoolean 값을 입력합니다.partial dictionary AuthenticationExtensionsClientInputs {boolean ; };credProps - 클라이언트 확장 처리
-
authenticatorMakeCredential 연산을 호출할 때 사용된 requireResidentKey 파라미터의 값을
rk로 설정합니다. - 클라이언트 확장 출력
-
Set
clientExtensionResults["를 authenticatorMakeCredential 연산을 호출할 때 사용된 requireResidentKey 파라미터의 값으로 설정합니다.credProps"]["rk"]dictionary {CredentialPropertiesOutput boolean rk ; };partial dictionary AuthenticationExtensionsClientOutputs {CredentialPropertiesOutput ; };credProps rk, of type boolean-
이 선택적 속성은 클라이언트 측 발견 가능한 자격 증명 속성 또는 거주 키 자격 증명 속성이라고도 하며, PublicKeyCredential 이 등록 절차 결과로 클라이언트 측 발견 가능한 자격 증명인지 여부를 나타내는 Boolean 값입니다.
rk값이true면 자격 증명은 발견 가능한 자격 증명입니다.rk값이false면 서버 측 자격 증명입니다.rk속성이 존재하지 않으면 해당 자격 증명이 발견 가능한 자격 증명인지 서버 측 자격 증명인지 알 수 없습니다.참고: 일부 인증기는 클라이언트 플랫폼이 요청하지 않아도 발견 가능한 자격 증명을 생성할 수 있습니다. 이 때문에 클라이언트 플랫폼은
rk값을 충분히 신뢰할 수 없으면 포함하지 않을 수 있습니다. Relying Party는credProps확장이 지원될 경우 클라이언트 플랫폼이rk속성을 채우려 노력함을 가정해야 하며, 속성이 없으면 생성된 자격 증명이 비발견 자격 증명임을 의미함을 참고하십시오.
- 인증기 확장 입력
-
없음.
- 인증기 확장 처리
-
없음.
- 인증기 확장 출력
-
없음.
10.1.4. 의사 난수 함수 확장 (prf)
이 클라이언트 등록 확장 및 인증 확장은
Relying Party가 자격 증명과 연계된 의사 난수 함수(PRF)의 출력을 계산할 수 있게 해줍니다. 이 확장이 제공하는 PRF는 어떤
길이의 BufferSource도
입력으로 받아 32바이트 BufferSource로
매핑합니다.
대표적인 예로, PRF 출력을 대칭키로 사용해 사용자 데이터를 암호화할 수 있습니다. 이렇게 암호화된 데이터는 연관 자격 증명에서 어서션을 얻을 수 있을 때에만 접근이 가능하게 됩니다. 아래 규정에 따라 한 번의 어서션 작업에서 두 입력에 대해 PRF를 계산하면, 어서션 동안 매번 새 랜덤 입력을 선택해서 암호화 키를 주기적으로 교체할 수 있습니다. 입력이 예측 불가능하다면, 사용자 검증까지 만족하고 인증기에 일시적으로 접근할 수 있더라도 올바른 PRF 입력을 모르면 암호화 키를 얻을 수 없습니다.
이 확장은 [FIDO-CTAP]의 hmac-secret 확장 위에 구현되어
있습니다. WebAuthn과 하위 플랫폼 간의 사용 분리를 위해 입력과 출력을 사용자 에이전트만 암호화 가능하게 해야 하므로 별도의 클라이언트 확장입니다. 이 분리는 제공된 PRF 입력에 컨텍스트 문자열과 함께
해싱하는 방식으로 이루어지며, 임의 입력에 대한 PRF 계산을 방지합니다.
hmac-secret 확장은 자격 증명 당 2개의 PRF를 제공합니다: 하나는 사용자 검증이 수행될 때, 나머지 하나는 기타 요청에 사용됩니다. 본 확장은 자격 증명 당 하나의 PRF만 노출하며,
hmac-secret 구현 시 반드시 사용자 검증이 수행되는 경우의 PRF만 노출해야 합니다. 필요하다면 UserVerificationRequirement를
우선합니다.
참고: 이 확장은 인증기가 [FIDO-CTAP]을 사용하지 않아도 Relying Party의 관점에서 동일한 동작을 보장하면 구현될 수 있습니다.
- 확장 식별자
-
prf - 적용 작업
- 클라이언트 확장 입력
-
dictionary {AuthenticationExtensionsPRFValues required BufferSource ;first BufferSource ; };second dictionary {AuthenticationExtensionsPRFInputs AuthenticationExtensionsPRFValues eval ;record <DOMString ,AuthenticationExtensionsPRFValues >evalByCredential ; };partial dictionary AuthenticationExtensionsClientInputs {AuthenticationExtensionsPRFInputs ; };prf eval, of type AuthenticationExtensionsPRFValues-
PRF를 계산할 하나 또는 두 입력입니다. 모든 인증기가 생성 시 PRF 계산을 지원하지 않으므로, 출력이 없을 수 있습니다. 그렇다면 출력을 얻으려면 어서션이 필요합니다.
evalByCredential, of type record<DOMString, AuthenticationExtensionsPRFValues>-
base64url로 인코딩된 자격 증명 ID를 해당 PRF 입력에 매핑합니다.
allowCredentials가 비어 있지 않은 경우 어서션에만 적용됩니다.
- 클라이언트 확장 처리 (등록)
-
-
evalByCredential이 존재하면 이름이 "NotSupportedError"인DOMException을 반환합니다. -
인증기 확장 입력에서
hmac-secret을true로 설정합니다. -
eval값이 있고 향후 [FIDO-CTAP]에서 생성 시 PRF 계산을 허용하면, 아래와 같이hmac-secret입력을 설정합니다: -
인증기 확장 출력의
enabled에hmac-secret의 값을 할당. 없으면enabled값을false로 설정. -
복호화된 PRF 결과(있다면)를
results에 설정합니다.
-
- 클라이언트 확장 처리 (인증)
-
-
evalByCredential이 비어 있지 않은데allowCredentials가 비어 있으면 이름이 "NotSupportedError"인DOMException을 반환합니다. -
evalByCredential의 어떤 key라도 빈 문자열이거나, 유효한 base64url 인코딩이 아니거나,id와 일치하지 않으면 (base64url decode 후) 이름이 "SyntaxError"인DOMException을 반환합니다. -
prf확장 출력을 빈 딕셔너리로 초기화합니다. -
ev를 null로 두고, 매핑되는 PRF 입력을 찾음:
-
evalByCredential이 존재하고 해당 entry의 key가 반환될 credential ID의 base64url 인코딩이면, ev를 그 값으로 한다. -
ev가 null이고,
eval값이 있으면 ev에 해당 값을 할당합니다.
-
-
ev가 null이 아니면:
-
- 인증기 확장 입력 / 처리 / 출력
-
이 확장은 [FIDO-CTAP]의
hmac-secret확장을 사용해서 인증기와 통신합니다. Relying Party를 위한 별도의 인증기 동작은 명시하지 않습니다. - 클라이언트 확장 출력
-
dictionary {AuthenticationExtensionsPRFOutputs boolean enabled ;AuthenticationExtensionsPRFValues results ; };partial dictionary AuthenticationExtensionsClientOutputs {AuthenticationExtensionsPRFOutputs ; };prf enabled, of type boolean-
생성된 자격 증명에 대해 하나 또는 두 PRF가 사용 가능하면
true입니다. 이 값은 등록 중에만 보고되며, 인증의 경우 전달되지 않습니다. results, of type AuthenticationExtensionsPRFValues-
eval또는evalByCredential입력에 대해 계산된 PRF 결과입니다. 등록 동안 출력이 없는 경우도 있습니다.eval의 설명을 참고하세요.일부 상황(예: PRF 출력이 클라이언트 측 키 파생에만 사용되는 경우)에서는
results값을PublicKeyCredential이 원격 서버에 전송될 때(예: § 7 WebAuthn Relying Party Operations) 포함하지 않는 것이 필요할 수 있습니다. 특히RegistrationResponseJSON및AuthenticationResponseJSON이을 통해 반환될 때,PublicKeyCredential.toJSON()results값이 포함될 수 있습니다.
10.1.5. 대용량 blob 저장 확장(largeBlob)
이 클라이언트 등록 확장 및 인증 확장은 Relying Party가 자격 증명에 연관된 불투명 데이터(opaque data)를 저장할 수 있게 해줍니다. 인증기는 소량의 데이터만 저장할 수 있고, 대부분의 Relying Party는 온라인 서비스로서 사용자별로 임의의 상태를 별도로 저장할 수 있으므로, 이 기능은 일부 특수한 경우에만 유용합니다. 예를 들어, Relying Party가 중앙 인증 서비스 대신 인증서 발급 식으로 운용하고 싶은 경우가 해당됩니다.
참고: Relying Party는 저장 공간이 제한된 디바이스에 쓸 때 불투명 데이터가 압축됨을 전제로 별도 압축 없이 데이터를 저장해도 됩니다.
인증서 시스템은 자격 증명의 공개키에 서명해야 하는데, 해당 공개키는 자격 증명 생성 이후에만 알 수 있으므로, 이 확장은 등록 컨텍스트에서 blob 기록 기능을 제공하지 않습니다. 다만, Relying Party가 이후 인증 확장을 쓸 계획이라면 자격 증명 생성 시 등록 확장을 함께 사용하는 것이 좋습니다.
인증서는 대부분의 인증기가 저장할 수 있는 용량에 비해 큰 데이터이므로, 사용자 에이전트는 리소스 할당이 적절하고 오용되지 않도록 사용자에게 알림/확인을 적절히 제공해야 합니다.
참고: 상호운용을 위해 [FIDO-CTAP]을 이용해 인증기에 대용량 blob을 쓰는 사용자 에이전트는 해당 사양에 명시된 자격 증명별 대용량 blob 저장 방식을 따라야 합니다.
참고: 이동형 인증기가 [FIDO-CTAP]을 교차 플랫폼 전송 프로토콜로 사용할 경우 Large Blob
확장은 발견 가능한 자격
증명에만 지원되며,
값이 authenticatorSelection.residentKeypreferred
또는 required
가 아닌 경우 에러가 날 수 있습니다. 하지만 FIDO-CTAP을 사용하지 않는 인증기는 반드시 발견 가능한 자격 증명에만 이 확장을 제한하지는 않을 수 있습니다.
- 확장 식별자
-
largeBlob - 적용 작업
- 클라이언트 확장 입력
-
partial dictionary AuthenticationExtensionsClientInputs {AuthenticationExtensionsLargeBlobInputs ; };largeBlob enum {LargeBlobSupport ,"required" , };"preferred" dictionary {AuthenticationExtensionsLargeBlobInputs DOMString support ;boolean read ;BufferSource write ; };support, of type DOMString-
값은
LargeBlobSupport의 값 중 하나를 취하는 DOMString입니다. (§ 2.1.1 Enumeration as DOMString types 참고) 등록 시에만 유효합니다. read, of type boolean-
이 불리언 값이 있으면 Relying Party가 해당 자격 증명에 이미 저장된 blob을 가져오고 싶음을 나타냅니다. 인증(Assertion) 시에만 유효합니다.
write, of type BufferSource-
해당 자격 증명에 연관해 Relying Party가 저장하고 싶은 불투명 바이트 문자열입니다. 인증(Assertion) 시에만 유효합니다.
- 클라이언트 확장 처리 (등록)
-
-
-
이름이 "
NotSupportedError"인DOMException반환.
-
-
- 클라이언트 확장 처리 (인증)
-
-
support값이 지정되어 있으면:-
이름이 "
NotSupportedError"인DOMException반환.
-
-
-
이름이 "
NotSupportedError"인DOMException반환.
-
-
read값이true면:-
클라이언트 확장 출력
largeBlob을 초기화합니다. -
어떤 인증기라도 성공(즉,
[[DiscoverFromExternalSource]](origin, options, sameOriginWithAncestors)에서)이면 해당 자격 증명에 저장된 largeBlob 데이터를 읽으려고 시도합니다. -
성공 시
blob에 결과값을 설정합니다.참고: 읽기에 실패하면,
largeBlob이AuthenticationExtensionsClientOutputs에는 존재하지만,blob멤버는 존재하지 않습니다.
-
-
write값이 있으면:-
allowCredentials항목이 정확히 하나가 아니면:-
이름이 "
NotSupportedError"인DOMException반환.
-
-
성공 시
written에true를, 아니면false를 설정합니다.
-
-
- 클라이언트 확장 출력
-
partial dictionary AuthenticationExtensionsClientOutputs {AuthenticationExtensionsLargeBlobOutputs ; };largeBlob dictionary {AuthenticationExtensionsLargeBlobOutputs boolean supported ;ArrayBuffer blob ;boolean written ; }; - 인증기 확장 처리
-
이 확장은 대용량 blob을 인증기에 저장/조회하도록 사용자 에이전트가 동작하게 하며, Relying Party를 위한 별도의 인증기 상호작용은 명시하지 않습니다.
10.2. 인증기 확장
이 절에서는 클라이언트 확장이면서 인증기 확장인 확장들을 정의합니다.
이 절은 현재 비어 있습니다.
11. 사용자 에이전트 자동화
사용자 에이전트 자동화 및 웹 애플리케이션 테스트 목적을 위해, 본 문서는 [WebDriver] 확장 명령 여러 가지를 정의합니다.
11.1. WebAuthn WebDriver 확장 기능(Capability)
아래에 정의된 확장 명령의 사용 가능 여부를 광고하기 위해, 새로운 확장 기능(Capability)이 정의됩니다.
| 기능(Capability) | Key | 값 타입(Value Type) | 설명 |
|---|---|---|---|
| 가상 인증기 지원 | "webauthn:virtualAuthenticators"
| boolean | 엔드포인트 노드가 모든 가상 인증기 명령을 지원하는지 나타냄 |
기능을 검증할 때, 다음은 "webauthn:virtualAuthenticators"를
value와 함께 검증하는 확장별 단계입니다:
-
value가 boolean이 아니면, WebDriver 오류를 WebDriver error code invalid argument와 함께 반환합니다. -
그 외에는
deserialized를value로 설정합니다.
기능을 매칭할 때, "webauthn:virtualAuthenticators"와
value의 확장별 매칭 단계는 다음과 같습니다:
11.1.1. 인증기 확장 기능(Capabilities)
또한, 본 명세에서 정의한 모든 인증기 확장(즉, 인증기 확장 처리가 정의된 것)에 대해 확장 기능(Capability)이 개별로 정의됩니다:
| 기능 | Key | 값 타입 | 설명 |
|---|---|---|---|
| 의사난수함수(PRF) 확장 지원 | "webauthn:extension:prf"
| boolean | 엔드포인트 노드 WebAuthn WebDriver 구현이 prf 확장을 지원하는지 나타냄 |
| 대용량 blob 저장 확장 지원 | "webauthn:extension:largeBlob"
| boolean | 엔드포인트 노드 WebAuthn WebDriver 구현이 largeBlob 확장을 지원하는지 나타냄 |
| credBlob 확장 지원 | "webauthn:extension:credBlob"
| boolean | 엔드포인트 노드 WebAuthn WebDriver 구현이 [FIDO-CTAP]에 정의된
credBlob 확장을 지원하는지 나타냄
|
기능을 검증할 때, 인증기 확장 기능 key와 value를
검증하는 확장별 단계는 다음과 같습니다:
-
value가 boolean이 아니면, WebDriver 오류를 WebDriver error code invalid argument와 함께 반환합니다. -
그 외에는
deserialized를value로 설정합니다.
기능 매칭 시, 인증기 확장 기능 key와 value의 확장별
매칭 단계는 다음과 같습니다:
-
value가true이고 엔드포인트 노드 WebAuthn WebDriver 구현이key로 식별되는 인증기 확장을 지원하지 않으면, 매칭은 실패합니다. -
그 외에는 매칭이 성공합니다.
정의된 인증기 확장을 구현하는 User-Agent는 대응하는 인증기 확장 기능도 함께 구현해야 합니다.
11.2. 가상 인증기
이들 WebDriver 확장 명령은 가상 인증기를 생성하고 조작합니다: 인증기 모델의 소프트웨어 구현입니다. 가상 인증기는 가상 인증기 데이터베이스에 저장됩니다. 저장된 각 가상 인증기는 다음 속성들을 가집니다:
- authenticatorId
-
[RFC3986]의 부록 A에 명시된
unreservedproduction에서 최대 48자까지 사용한 널이 아닌 문자열입니다. 가상 인증기를 고유하게 식별합니다. - protocol
-
가상 인증기가 사용하는 프로토콜.
"ctap1/u2f","ctap2","ctap2_1"중 하나입니다. [FIDO-CTAP] - transport
-
모사되는
AuthenticatorTransport값. transport가internal이면 인증기는 플랫폼 연계를, 아니면 교차 플랫폼 연계를 시뮬레이션합니다. - hasResidentKey
-
true로 설정하면, 인증기는 클라이언트 측 발견 가능한 자격 증명을 지원합니다. - hasUserVerification
-
true로 설정하면, 인증기는 사용자 검증을 지원합니다. - isUserConsenting
-
모든 사용자 동의 승인 제스처(authorization gesture), 그리고 확장으로서 사용자 존재 확인의 결과를 좌우합니다.
true면 항상 사용자 동의가 허가되며,false면 거부됩니다. - isUserVerified
-
가상 인증기의 사용자 검증 결과를 결정합니다.
true면 항상 검증이 성공하고,false면 실패합니다.참고: hasUserVerification이
false면 이 속성의 효과는 없습니다. - extensions
-
가상 인증기가 지원하는 확장 식별자들의 문자열 배열입니다.
가상 인증기는 extensions 배열에 포함된 모든 인증기 확장을 필수로 지원해야 하며, 포함돼 있지 않은 확장은 지원하면 안 됩니다.
- defaultBackupEligibility
-
새로 생성되는 모든 공개키 자격 증명 소스에 해당 백업 자격(backup eligibility)의 자격 증명 속성의 기본값을 지정합니다. 가상 인증기에서 authenticatorMakeCredential 수행 시 이 값이 BE authenticator data 플래그로 반영되어야 합니다.
- defaultBackupState
-
새로 생성되는 모든 공개키 자격 증명 소스에 해당 백업 상태의 자격 증명 속성의 기본값을 지정합니다. 가상 인증기에서 authenticatorMakeCredential 수행 시, BS authenticator data 플래그로 반드시 반영되어야 합니다.
11.3. 가상 인증기 추가
가상 인증기 추가 WebDriver 확장 명령은 소프트웨어 가상 인증기를 생성합니다. 정의는 다음과 같습니다:
| HTTP 메서드 | URI 템플릿 |
|---|---|
| POST | /session/{session id}/webauthn/authenticator
|
인증기 설정은 JSON 객체로, 원격 엔드 스텝에 parameters로 전달됩니다. 여기에 아래 key, value 쌍이 포함됩니다:
| Key | 값 타입 | 유효 값 | 기본값 |
|---|---|---|---|
| protocol | string | "ctap1/u2f", "ctap2", "ctap2_1"
| None |
| transport | string | AuthenticatorTransport
값
| None |
| hasResidentKey | boolean | true, false
| false
|
| hasUserVerification | boolean | true, false
| false
|
| isUserConsenting | boolean | true, false
| true
|
| isUserVerified | boolean | true, false
| false
|
| extensions | string array | 확장 식별자 배열 | 빈 배열 |
| defaultBackupEligibility | boolean | true, false
| false
|
| defaultBackupState | boolean | true, false
| false
|
원격 엔드 스텝은 다음과 같습니다:
-
parameters가 JSON 객체(Object)가 아니면, WebDriver 오류를 WebDriver error code invalid argument와 함께 반환합니다.
참고: parameters는 인증기 설정(Authenticator Configuration) 객체입니다.
-
authenticator를 새 가상 인증기로 둡니다.
-
parameters의 각 enumerable 고유 속성(own property)에 대해:
-
key를 해당 속성 이름으로 둡니다.
-
value를 parameters에서 key 속성 가져오기 결과로 둡니다.
-
인증기 설정에 key가 없으면 WebDriver 오류를 WebDriver error code invalid argument와 함께 반환.
-
value가 해당 key의
유효 값(valid values)에 없으면 WebDriver 오류를 WebDriver error code invalid argument와 함께 반환.
-
-
인증기 설정에서 기본값이 정의된 각 속성에 대해:
-
key가 authenticator에 정의된 속성이 아니라면, key를 default로 설정합니다.
-
-
인증기 설정의 각 속성에 대해:
-
key가 authenticator에 정의된 속성이 아니라면, WebDriver 오류를 WebDriver error code invalid argument와 함께 반환.
-
-
authenticator.extensions에 있는 각 extension에 대해:
-
extension이 확장 식별자이면서, 엔드포인트 노드 WebAuthn WebDriver 구현에서 지원하지 않으면, WebDriver 오류를 WebDriver error code unsupported operation과 함께 반환.
-
-
고유한 authenticatorId를 생성합니다.
-
authenticator의
authenticatorId에 authenticatorId 설정. -
authenticator를 가상 인증기 데이터베이스에 저장합니다.
-
성공(success)과 데이터 authenticatorId를 반환합니다.
11.4. 가상 인증기 제거
가상 인증기 제거 WebDriver 확장 명령은 이전에 생성된 가상 인증기를 제거합니다. 정의는 다음과 같습니다:
| HTTP 메서드 | URI 템플릿 |
|---|---|
| DELETE | /session/{session id}/webauthn/authenticator/{authenticatorId}
|
원격 엔드 스텝은 다음과 같습니다:
-
authenticatorId가 가상 인증기 데이터베이스에 저장된 어떤 가상 인증기와도 일치하지 않으면, WebDriver 오류를 WebDriver error code invalid argument와 함께 반환합니다.
-
authenticatorId로 식별되는 가상 인증기를 가상 인증기 데이터베이스에서 제거합니다.
-
성공을 반환합니다.
11.5. 자격 증명 추가
자격 증명 추가 WebDriver 확장 명령은 공개키 자격 증명 소스를 기존 가상 인증기에 주입합니다. 정의는 다음과 같습니다:
| HTTP 메서드 | URI 템플릿 |
|---|---|
| POST | /session/{session id}/webauthn/authenticator/{authenticatorId}/credential
|
자격 증명 파라미터는 JSON 객체이며 원격 엔드 스텝에 parameters로 전달됩니다. 다음 key, value 쌍을 포함합니다:
| Key | 설명 | 값 타입 |
|---|---|---|
| credentialId | Credential ID를 Base64url 인코딩한 값 | string |
| isResidentCredential | true면 클라이언트 측 발견 가능 자격 증명이 생성됨.
false면 서버 측 자격 증명 생성됨.
| boolean |
| rpId | 자격 증명이 스코프되는 Relying Party ID | string |
| privateKey | 개인키 1개만 담긴 비대칭 키 패키지. [RFC5958], Base64url 인코딩 사용. | string |
| userHandle | 자격 증명과 연관된 userHandle을 Base64url 인코딩. 없을 수 있음. | string |
| signCount | 서명 카운터의 초기값 | number |
| largeBlob | 자격 증명별 대용량 blob을 공개키 자격 증명 소스에 연관, Base64url 인코딩. 없을 수 있음. | string |
| backupEligibility | 공개키 자격 증명 소스의 백업 자격 시뮬레이션 값. 지정되지 않으면 가상 인증기의 defaultBackupEligibility 사용. authenticator data의 BE 플래그로 반영되어야 함 | boolean |
| backupState | 공개키 자격 증명 소스의 백업 상태 시뮬레이션 값. 지정되지 않으면 가상 인증기의 defaultBackupState 사용. authenticator data의 BS 플래그로 반영되어야 함 | boolean |
| userName | 해당 자격 증명에 연관된 user의
name.
지정되지 않으면 빈 문자열이 기본.
| string |
| userDisplayName | 해당 자격 증명에 연관된 user의
displayName.
지정되지 않으면 빈 문자열이 기본.
| string |
원격 엔드 스텝은 다음과 같습니다:
-
parameters가 JSON 객체가 아니면, WebDriver 오류를 WebDriver error code invalid argument와 함께 반환.
참고: parameters는 자격 증명 파라미터 객체입니다.
-
credentialId를 parameters의 credentialId 속성 값에 대해 Base64url 디코딩 결과로 둡니다.
-
credentialId가 실패면 WebDriver 오류를 WebDriver error code invalid argument와 함께 반환.
-
isResidentCredential을 parameters의 isResidentCredential 속성 값으로 둡니다.
-
isResidentCredential이 정의되지 않으면 WebDriver 오류를 WebDriver error code invalid argument와 함께 반환.
-
rpId를 parameters의 rpId 속성 값으로 둡니다.
-
rpId가 유효한 RP ID가 아니면, WebDriver 오류를 WebDriver error code invalid argument와 함께 반환.
-
privateKey를 parameters의 privateKey 속성 값에 대해 Base64url 디코딩 결과로 둡니다.
-
privateKey가 실패면 WebDriver 오류를 WebDriver error code invalid argument와 함께 반환.
-
privateKey가 [RFC5958]의 P-256 곡선상 ECDSA 단일 개인키가 포함된 정상 인코딩 키 패키지가 아니면, WebDriver 오류를 WebDriver error code invalid argument와 함께 반환.
-
parameters의 userHandle 속성이 정의된 경우:
-
userHandle을 parameters의 userHandle 속성 값에 대해 Base64url 디코딩 결과로 둡니다.
-
userHandle이 실패면 WebDriver 오류를 WebDriver error code invalid argument와 함께 반환.
-
-
그 외의 경우:
-
isResidentCredential이
true면 WebDriver 오류를 WebDriver error code invalid argument와 함께 반환. -
userHandle을
null로 둡니다.
-
-
authenticatorId가 가상 인증기 데이터베이스에 저장된 어떤 가상 인증기와도 일치하지 않으면, WebDriver 오류를 WebDriver error code invalid argument와 함께 반환.
-
authenticator를 authenticatorId에 해당하는 가상 인증기로 둡니다.
-
isResidentCredential이
true이고 해당 authenticator의 hasResidentKey 값이false면 WebDriver 오류를 WebDriver error code invalid argument와 함께 반환. -
해당 authenticator가 largeBlob 확장을 지원하고 parameters의 largeBlob 속성이 정의되어 있으면:
-
largeBlob을 parameters의 largeBlob 속성 값에 대해 Base64url 디코딩 결과로 둡니다.
-
largeBlob이 실패면 WebDriver 오류를 WebDriver error code invalid argument와 함께 반환.
-
-
그 외의 경우:
-
largeBlob을
null로 둡니다.
-
-
backupEligibility를 parameters의 backupEligibility 속성 값으로 둡니다.
-
backupEligibility가 정의되지 않으면, authenticator의 defaultBackupEligibility 값을 사용합니다.
-
backupState를 parameters의 backupState 속성 값으로 둡니다.
-
backupState가 정의되지 않으면, authenticator의 defaultBackupState 값을 사용합니다.
-
userName을 parameters의 userName 속성으로 둡니다.
-
userName이 정의되지 않으면 빈 문자열로 둡니다.
-
userDisplayName을 parameters의 userDisplayName 속성으로 둡니다.
-
userDisplayName이 정의되지 않으면 빈 문자열로 둡니다.
-
credential을 isResidentCredential이
true면 새 클라이언트 측 발견 가능 공개키 자격 증명 소스로, 아니면 서버 측 공개키 자격 증명 소스로 생성하여 다음 항목을 추가:- type
- id
-
credentialId
- privateKey
-
privateKey
- rpId
-
rpId
- userHandle
-
userHandle
- otherUI
-
userName과 userDisplayName로 구성합니다.
-
credential과 연계된 서명 카운터 counter를 parameters의 signCount 또는 정의되지 않았다면
0으로 설정. -
largeBlob이
null이 아니면, credential에 자격 증명별 대용량 blob으로 설정. -
credential 및 counter를 authenticator의 데이터베이스에 저장합니다.
-
성공을 반환합니다.
11.6. 자격 증명 가져오기(Get Credentials)
자격 증명 가져오기
WebDriver 확장 명령은 가상 인증기에 저장된 모든 공개키 자격 증명 소스마다 하나의
자격 증명 파라미터 객체를
반환합니다.
이는 자격 증명 추가로 저장되었는지,
또는 navigator.credentials.create()
로 저장되었는지와 관계없이 모두 포함합니다. 정의는 다음과 같습니다:
| HTTP 메서드 | URI 템플릿 |
|---|---|
| GET | /session/{session id}/webauthn/authenticator/{authenticatorId}/credentials
|
원격 엔드 스텝은 다음과 같습니다:
-
authenticatorId가 가상 인증기 데이터베이스에 저장된 어떠한 가상 인증기와도 일치하지 않으면, WebDriver 오류를 WebDriver error code invalid argument와 함께 반환합니다.
-
credentialsArray를 빈 배열로 둡니다.
-
authenticatorId로 식별되는 인증기가 관리하는 각 공개키 자격 증명 소스 credential마다, 해당하는 자격 증명 파라미터 Object를 생성해 credentialsArray에 추가합니다.
-
성공과 데이터 credentialsArray를 반환합니다.
11.7. 자격 증명 제거(Remove Credential)
자격 증명 제거 WebDriver 확장 명령은 가상 인증기에 저장된 공개키 자격 증명 소스를 하나 제거합니다. 정의는 다음과 같습니다:
| HTTP 메서드 | URI 템플릿 |
|---|---|
| DELETE | /session/{session id}/webauthn/authenticator/{authenticatorId}/credentials/{credentialId}
|
원격 엔드 스텝은 다음과 같습니다:
-
authenticatorId가 가상 인증기 데이터베이스에 저장된 어떤 가상 인증기와도 일치하지 않으면, WebDriver 오류를 WebDriver error code invalid argument 와 함께 반환합니다.
-
authenticator를 authenticatorId로 식별된 가상 인증기로 둡니다.
-
credentialId가 authenticator가 관리하는 어떤 공개키 자격 증명 소스에도 일치하지 않으면, WebDriver 오류 를 WebDriver error code invalid argument와 함께 반환합니다.
-
authenticator가 관리하는 credentialId로 식별된 공개키 자격 증명 소스를 제거합니다.
-
성공을 반환합니다.
11.8. 모든 자격 증명 제거(Remove All Credentials)
모든 자격 증명 제거 WebDriver 확장 명령은 특정 가상 인증기에 저장된 모든 공개키 자격 증명 소스를 제거합니다. 정의는 다음과 같습니다:
| HTTP 메서드 | URI 템플릿 |
|---|---|
| DELETE | /session/{session id}/webauthn/authenticator/{authenticatorId}/credentials
|
원격 엔드 스텝은 다음과 같습니다:
-
authenticatorId가 가상 인증기 데이터베이스에 저장된 어떤 가상 인증기와도 일치하지 않으면, WebDriver 오류를 WebDriver error code invalid argument와 함께 반환합니다.
-
authenticatorId로 식별된 가상 인증기에서 모든 공개키 자격 증명 소스를 제거합니다.
-
성공을 반환합니다.
11.9. 사용자 검증 상태 설정(Set User Verified)
사용자 검증 상태 설정 확장 명령은 가상 인증기의 isUserVerified 속성을 설정합니다. 정의는 다음과 같습니다:
| HTTP 메서드 | URI 템플릿 |
|---|---|
| POST | /session/{session id}/webauthn/authenticator/{authenticatorId}/uv
|
원격 엔드 스텝은 다음과 같습니다:
-
parameters가 JSON 객체가 아니면, WebDriver 오류를 WebDriver error code invalid argument 와 함께 반환합니다.
-
authenticatorId가 가상 인증기 데이터베이스에 저장된 어떤 가상 인증기와도 일치하지 않으면, WebDriver 오류를 WebDriver error code invalid argument와 함께 반환합니다.
-
parameters에 isUserVerified 속성이 정의되어 있지 않으면 WebDriver 오류를 WebDriver error code invalid argument와 함께 반환합니다.
-
authenticator를 authenticatorId로 식별된 가상 인증기로 둡니다.
-
authenticator의 isUserVerified 속성을 parameters의 isUserVerified 값으로 설정합니다.
-
성공을 반환합니다.
11.10. 자격 증명 속성 설정(Set Credential Properties)
자격 증명 속성 설정 확장 명령은 가상 인증기의 공개키 자격 증명 소스의 backupEligibility와 backupState 자격 증명 속성을 설정할 수 있습니다. 정의는 다음과 같습니다:
| HTTP 메서드 | URI 템플릿 |
|---|---|
| POST | /session/{session id}/webauthn/authenticator/{authenticatorId}/credentials/{credentialId}/props
|
자격 증명 속성 설정 파라미터(Set Credential Properties Parameters)는 JSON 객체로, 원격 엔드 스텝에 parameters로 전달됩니다. 다음 key와 value 쌍을 포함합니다:
| Key | 설명 | 값 타입 |
|---|---|---|
| backupEligibility | 백업 자격(backup eligibility) 자격 증명 속성 | boolean |
| backupState | 백업 상태(backup state) 자격 증명 속성 | boolean |
원격 엔드 스텝은 다음과 같습니다:
-
parameters가 JSON 객체가 아니면, WebDriver 오류를 WebDriver error code invalid argument와 함께 반환합니다.
참고: parameters는 자격 증명 속성 설정 파라미터 객체입니다.
-
authenticatorId가 가상 인증기 데이터베이스에 저장된 어떤 가상 인증기와도 일치하지 않으면, WebDriver 오류를 WebDriver error code invalid argument와 함께 반환합니다.
-
credential을 authenticator가 credentialId로 관리하는 공개키 자격 증명 소스로 둡니다.
-
credential이 비어 있으면 WebDriver 오류 를 WebDriver error code invalid argument와 함께 반환합니다.
-
backupEligibility를 parameters의 backupEligibility 속성 값으로 둡니다.
-
backupEligibility가 정의되어 있으면, credential의 백업 자격 자격 증명 속성을 해당 값으로 설정합니다.
참고: 일반적으로 backupEligibility 속성은 공개키 자격 증명 소스에 대해 영구적입니다. 이 명령은 테스트 및 디버깅 목적으로 속성을 변경할 수 있도록 합니다.
-
backupState를 parameters의 backupState 속성 값으로 둡니다.
-
backupState가 정의되어 있으면 credential의 백업 상태 자격 증명 속성을 해당 값으로 설정합니다.
-
성공을 반환합니다.
12. IANA 고려 사항
12.1. WebAuthn 어테스테이션 명세 식별자 등록 업데이트
이 절에서는 § 8 정의된 어테스테이션 명세에서 정의된 아래 어테스테이션 명세 식별자들을 IANA "WebAuthn Attestation Statement Format Identifiers" 레지스트리 [IANA-WebAuthn-Registries]에 대해 업데이트하며, [RFC8809]에 의해 제정되었고, 최초 [WebAuthn-1]에서 등록된 식별자가 본 명세를 참조하도록 변경합니다.
-
WebAuthn 어테스테이션 명세 식별자: packed
-
설명: "packed" 어테스테이션 명세 형식은 WebAuthn에 최적화된 어테스테이션 형식입니다. 매우 간결하며 확장 가능한 인코딩을 제공합니다. 제한된 리소스(예: 시큐어 엘리먼트)를 가지는 인증기도 구현할 수 있습니다.
-
명세 문서: 본 명세의 § 8.2 Packed Attestation Statement Format
-
WebAuthn 어테스테이션 명세 식별자: tpm
-
설명: TPM 어테스테이션 명세 형식은 packed 명세 형식과 동일한 형식을 반환하지만 rawData, signature 등 계산 방법이 다릅니다.
-
명세 문서: 본 명세의 § 8.3 TPM Attestation Statement Format
-
WebAuthn 어테스테이션 명세 식별자: android-key
-
설명: 안드로이드 "N" 및 이후 버전의 플랫폼 인증기는 이 독자적 하드웨어 어테스테이션을 제공합니다.
-
명세 문서: 본 명세의 § 8.4 Android Key Attestation Statement Format
-
WebAuthn 어테스테이션 명세 식별자: android-safetynet
-
설명: 안드로이드 기반의 플랫폼 인증기는 Android SafetyNet API 기반 어테스테이션 명세를 생성할 수 있습니다.
-
명세 문서: 본 명세의 § 8.5 Android SafetyNet Attestation Statement Format
-
WebAuthn 어테스테이션 명세 식별자: fido-u2f
-
설명: FIDO U2F 인증기에 사용합니다.
-
명세 문서: 본 명세의 § 8.6 FIDO U2F Attestation Statement Format
12.2. WebAuthn 어테스테이션 명세 식별자 신규 등록
이 절에서는 § 8 정의된 어테스테이션 명세에서 새롭게 정의된 어테스테이션 명세 식별자를 IANA "WebAuthn Attestation Statement Format Identifiers" 레지스트리 [IANA-WebAuthn-Registries]에 신규로 등록함을 명시합니다. 이는 [RFC8809]에 의해 제정되었습니다.
-
WebAuthn 어테스테이션 명세 식별자: apple
-
설명: 애플 기기의 플랫폼 인증기에 사용됨
-
명세 문서: 본 명세의 § 8.8 Apple 익명 어테스테이션 명세 형식
-
WebAuthn 어테스테이션 명세 식별자: none
-
설명: WebAuthn Relying Party가 인증기 어테스테이션 정보를 수신 원치 않음을 명시할 때, 인증기 제공 어테스테이션을 이 형식으로 대체함.
-
명세 문서: 본 명세의 § 8.7 None Attestation Statement Format
12.3. WebAuthn 확장 식별자 등록 업데이트
이 절에서는 § 10 정의된 확장에서 정의된 아래 확장 식별자 값을 IANA "WebAuthn Extension Identifiers" 레지스트리 [IANA-WebAuthn-Registries]에 대해 업데이트함을 명시합니다. 이 레지스트리는 [RFC8809]에 의해 제정되었고, 원래는 [WebAuthn-1]에서 등록된 값입니다.
-
WebAuthn 확장 식별자: appid
-
설명: 이 인증 확장은 이전 FIDO JavaScript API로 자격 증명을 등록한 WebAuthn Relying Party가 어서션을 요청할 수 있도록 합니다.
-
명세 문서: 본 명세의 § 10.1.1 FIDO AppID Extension (appid)
12.4. WebAuthn 확장 식별자 신규 등록
이 절에서는 § 10 정의된 확장에서 새롭게 정의된 확장 식별자 값을 IANA "WebAuthn Extension Identifiers" 레지스트리 [IANA-WebAuthn-Registries]에 신규로 등록함을 명시합니다. 본 레지스트리는 [RFC8809]에 의해 제정되었습니다.
-
WebAuthn 확장 식별자: appidExclude
-
설명: 이 등록 확장은 WebAuthn Relying Party가 이전 FIDO U2F JavaScript API [FIDOU2FJavaScriptAPI]로 생성된 특정 자격 증명이 있는 인증기를 제외할 수 있도록 허용합니다.
-
명세 문서: 본 명세의 § 10.1.2 FIDO AppID Exclusion Extension (appidExclude)
-
WebAuthn 확장 식별자: credProps
-
설명: 이 클라이언트 등록 확장은 새로 생성된 자격 증명(credential)의 속성을 클라이언트에서 판별하여 호출한 WebAuthn Relying Party의 웹 애플리케이션에 보고할 수 있게 합니다.
-
명세 문서: 본 명세의 § 10.1.3 Credential Properties Extension (credProps)
-
WebAuthn 확장 식별자: largeBlob
-
설명: 이 클라이언트 등록 확장 및 인증 확장은 Relying Party가 자격 증명에 불투명 데이터를 저장할 수 있도록 허용합니다.
-
명세 문서: 본 명세의 § 10.1.5 Large blob storage extension (largeBlob)
13. 보안 고려사항
이 명세서는 Web API와 암호학적 피어-엔터티 인증 프로토콜을 정의합니다. Web Authentication API는 웹 개발자(즉, "author")가 자신의 등록 및 인증 절차에서 Web Authentication 프로토콜을 활용할 수 있게 합니다. Web Authentication 프로토콜 엔드포인트를 구성하는 엔터티는 사용자 제어 하의 WebAuthn Authenticator들과 WebAuthn Relying Party의 실행 환경에서 호스팅되는 Relying Party의 웹 애플리케이션입니다. 이 모델에서 사용자 에이전트는 WebAuthn Client와 함께 authenticator와 Relying Parties 사이의 중개자 역할을 합니다. 또한, authenticator는 자신의 출처에 관해 attest할 수 있습니다.
현재 이 명세서는 상세한 보안 고려사항을 모두 포함하지는 않습니다. 다만 [FIDOSecRef] 문서는 본 명세에 전반적으로 적용 가능한 보안 분석을 제공합니다. 또한 [FIDOAuthnrSecReqs] 문서 모음은 authenticator의 보안 특성에 관해 유용한 정보를 제공합니다.
이하 소항들은 현재의 Web Authentication-특유 보안 고려사항을 구성합니다. 대상별로 구분되어 있으며; 일반적인 보안 고려사항은 이 섹션의 직접 하위절이고, authenticator, client 및 Relying Party 구현자들을 위한 고려사항은 각각의 하위절로 그룹화되어 있습니다.
13.1. 서명되지 않은 Credential ID
credential ID는 authentication assertion과 함께 서명되지 않은 상태로 전송됩니다. 이는 문제가 되지 않습니다. 만약 authenticator가 잘못된 credential ID를 반환하거나, 공격자가 credential ID를 가로채 조작하더라도, 결과적으로 WebAuthn Relying Party는 반환된 서명된 authenticator data를 검증하기 위한 올바른 credential public key를 조회하지 못하게 되고, 결과 상호작용은 오류로 끝나게 됩니다.
13.2. 클라이언트와 인증기 간 물리적 근접성
WebAuthn의 authenticator 모델에서는 일반적으로 roaming authenticators가 클라이언트와 물리적으로 가깝고 직접 통신한다고 가정합니다. 이러한 배치는 중요한 장점을 제공합니다.
클라이언트와 authenticator 간의 물리적 근접성은 something you have 인증 요소의 핵심 강점입니다. 예를 들어, roaming authenticator가 USB 또는 Bluetooth로만 통신할 수 있다면, 이러한 전송 수단의 제한된 범위는 악의적 행위자가 authenticator와 상호작용하려면 물리적으로 그 범위 내에 있어야 함을 보장합니다. 반면, 원격에서 호출될 수 있는 authenticator의 경우에는 반드시 그렇지 않습니다 — 설령 authenticator가 사용자 존재 확인을 수행하더라도, 사용자가 원격으로 시작된 악성 요청을 승인하도록 속을 수 있습니다.
클라이언트와 authenticator의 직접 통신은 client가 scope 제약을 강제로 적용할 수 있게 합니다. 반면, 클라이언트와 인증기 간 통신이 제3자에 의해 중개된다면, client는 제3자가 범위 제약을 집행하고 authenticator 접근을 제어하도록 신뢰해야 합니다. 이를 실패할 경우 악의적 Relying Party가 다른 Relying Parties용으로 유효한 authentication assertions를 받거나, 악의적 사용자가 다른 사용자의 authentication assertions에 접근할 수 있게 될 수 있습니다.
만약 authenticator가 클라이언트와 물리적으로 가깝지 않아도 되도록 설계하거나, 또는 client와 authenticator가 직접 통신하지 않는 솔루션을 설계한다면, 설계자는 이것이 scope 제약의 집행과 authenticator의 something you have 인증 요소로서의 강도에 어떤 영향을 미치는지 고려해야 합니다.
13.3. 인증기(authenticators)에 대한 보안 고려사항
13.3.1. 어테스테이션 인증서 계층
어테스테이션 인증서를 위한 3계층 구조(예: Attestation Root, Attestation Issuing CA, Attestation Certificate)를 권고합니다. 또한 각 WebAuthn Authenticator 디바이스 라인(모델)마다 별도의 발급 CA를 사용하는 것이 권장됩니다. 이는 특정 인증기 모델 버전의 문제를 격리하는 데 도움이 됩니다.
어테스테이션 루트 인증서가 단일 WebAuthn Authenticator 디바이스 라인(AAGUID)에만 전용되지 않은 경우, attestation 인증서 자체에 AAGUID를 명시하여 authenticator data와 대조 검증할 수 있어야 합니다.
13.3.2. 어테스테이션 인증서 및 CA 유출
어테스테이션 인증서를 발급하는 중간 CA 또는 루트 CA가 유출된 경우, WebAuthn Authenticator의 attestation key pairs 자체는 안전하지만 해당 인증서들은 더 이상 신뢰할 수 없습니다. 만약 제조업체가 자사 authenticator 모델들의 attestation public keys를 기록해 두었다면, 새로운 중간 CA 또는 루트 CA로부터 이 키들을 위한 새로운 attestation certificates를 발급할 수 있습니다. 루트 CA가 변경된다면 WebAuthn Relying Parties는 신뢰하는 루트 인증서를 적절히 업데이트해야 합니다.
발급 CA가 해당 private key가 유출되었다고 판단하면, 해당 WebAuthn Authenticator의 attestation certificate는 발급 CA에 의해 폐기되어야 합니다. 제조업체는 펌웨어 업데이트를 배포하고 이미 제조된 WebAuthn Authenticators에 새로운 attestation private keys와 certificates를 주입해야 할 수 있습니다(이 과정은 본 명세의 범위를 벗어납니다). 제조업체가 이를 수행할 수 없다면, 영향을 받은 WebAuthn Authenticators로부터의 향후 attestation statements를 신뢰할 수 없게 될 수 있습니다.
관련 내용은 Relying Parties에 대한 관련 보안 고려사항인 § 13.4.5 폐기된 어테스테이션 인증서를 참조하세요.
13.4. Relying Parties를 위한 보안 고려사항
13.4.1. WebAuthn Relying Parties에 대한 보안 이점
이 명세서가 WebAuthn Relying Parties에게 제공하는 주요 이점은 다음과 같습니다:
-
사용자와 계정을 광범위하게 호환되며 사용하기 쉬운 다중요소 인증으로 보호할 수 있습니다.
-
Relying Party는 사용자에게 인증기 하드웨어를 제공할 필요가 없습니다. 대신 각 사용자는 적합한 authenticator를 독립적으로 구비하고 동일한 authenticator를 여러 Relying Parties에서 사용할 수 있습니다. Relying Party는 선택적으로 authenticators의 보안 속성에 대한 요구사항을 attestation statements를 검사함으로써 강제할 수 있습니다.
-
Authentication ceremonies는 중간자 공격(man-in-the-middle attacks)에 저항력이 있습니다. 등록 절차에 대해서는 아래 § 13.4.4 어테스테이션 한계를 참조하세요.
-
Relying Party는 PIN, 생체인식 등 다양한 형태의 사용자 검증을 거의 코드 변경 없이 자동으로 지원할 수 있으며, 각 사용자는 선호하는 인증 방식을 자신이 선택한 authenticator로 결정할 수 있습니다.
-
Relying Party는 위의 이점을 얻기 위해 추가 비밀을 저장할 필요가 없습니다.
Conformance 섹션에 명시된 바와 같이, 위의 모든 보안 이점을 얻기 위해 Relying Party는 § 7 WebAuthn Relying Party Operations에 기술된 대로 동작해야 합니다. 다만 한 가지 예외적 사용 사례가 아래 § 13.4.4 어테스테이션 한계에 설명되어 있습니다.
13.4.2. 임베디드 사용 시 가시성 고려사항
간단히 WebAuthn을 임베디드 컨텍스트에서 사용하는 것(예:
iframe
내 사용, § 5.10 iframe 요소 내 Web Authentication 사용 참조)은 사용자를 UI Redressing 공격(일명
"Clickjacking")에 취약하게 만들 수 있습니다. 공격자가 자신의 UI를 Relying Party의 의도된 UI 위에 포개고 사용자가 의도하지 않은 동작을 하도록 속이려 할 수 있습니다. 예를 들어,
공격자가 사용자를 속여 물건을 구매하거나 돈을 이체하게 할 수 있습니다.
비록 WebAuthn-특유 UI는 일반적으로 client platform이 처리하므로 UI Redressing에 취약하지 않지만, 임베디드된 WebAuthn 콘텐츠를 가진 Relying Party는 자신의 콘텐츠 UI가 사용자에게 보이는지를 보장하는 것이
중요합니다. 이를 위해 실험적 수단으로 Intersection Observer v2의
isVisible 속성 상태를 관찰하는 방법이 있습니다. 예를 들어, 임베디드 컨텍스트에서 실행되는 Relying Party 스크립트가 isVisible이
false로 설정되는 것을 감지하면 미리 팝업 창으로 로드하여 콘텐츠가 가려지는 상황을 우회할 수 있습니다.
13.4.3. 암호학적 챌린지
암호학적 프로토콜로서 Web Authentication은 재생 공격(replay attacks)을 피하기 위해 랜덤화된 챌린지에 의존합니다. 따라서 PublicKeyCredentialCreationOptions.challenge와
PublicKeyCredentialRequestOptions.challenge의
값은 반드시 신뢰할 수 있는 환경(예: 서버 측)에서 Relying Parties에 의해 무작위로 생성되어야 하며,
클라이언트의 응답에 포함된 challenge
값은 생성된 값과 일치해야 합니다. 이는 클라이언트의 동작에 의존하지 않는 방식으로 수행되어야 합니다. 예를 들어 Relying Party는 연산이 완료될 때까지 챌린지를 일시적으로 저장해야 합니다.
불일치를 허용하면 프로토콜의 보안이 손상됩니다.
챌린지는 권장 범위 및 기본 WebAuthn 절차 타임아웃의 상한과 유사한 기간 동안 유효해야 합니다.
재생 공격을 방지하기 위해 챌린지는 충분한 엔트로피를 포함해야 합니다. 따라서 챌린지는 최소 16바이트 이상이어야 합니다.
13.4.4. 어테스테이션의 한계
이 절은 규범적이지 않습니다.
새 자격 증명을 등록할 때(registering a new credential), attestation statement가 존재한다면, WebAuthn Relying Party가 다양한 authenticator의 특성에 대해 어느 정도 보증을 도출할 수 있게 해줄 수 있습니다. 예를 들어 authenticator 모델이나 자격 증명 개인키를 어떻게 저장·보호하는지 등에 관하여입니다. 그러나 단지 attestation statement만으로는 Relying Party가 사용자가 의도한 attestation object가 실제로 그 authenticator에서 생성된 것인지, 중간자 공격자에 의해 생성된 것이 아닌지를 확인할 수 있는 수단을 제공하지 않습니다. 예를 들어 공격자는 Relying Party 스크립트에 주입된 악성 코드를 사용할 수 있습니다. 따라서 Relying Party는 TLS 등 관련 기술과 같은 다른 수단에 의존하여 attestation object를 중간자 공격으로부터 보호해야 합니다.
등록 절차가 안전하게 완료되고 authenticator가 credential private key의 기밀성을 유지한다고 가정하면, 그 공개키로 수행되는 이후의 authentication ceremonies는 중간자 공격으로부터 변조에 저항합니다.
위 논의는 모든 attestation
types에 적용됩니다. 어떤 경우에도 중간자 공격자는 PublicKeyCredential
객체(여기에는 attestation statement와 등록될 credential public key가 포함됨)를 대체하고
이후의 authentication assertions을 동일한 Relying Party에 대해 변조할 수 있습니다.
이러한 공격은 탐지 가능할 수 있습니다; 만약 Relying Party가 공격자의 credential public key를 등록했다면, 공격자는 이후의 모든 authentication ceremonies를 그 공격자의 키로 변조해야 하므로 정상이었던 절차들이 실패하면서 공격이 드러날 가능성이 있습니다.
Self Attestation 및 None 이외의 어테스테이션 타입은 이러한 공격의 난이도를 높여 줄 수 있습니다. 왜냐하면 Relying Parties가 사용자에게 인증기 정보(예: 모델 식별)를 표시할 수 있기 때문입니다. 공격자는 사용자의 인증기와 동일 모델의 진짜 authenticator를 사용해야 하거나, 사용자가 Relying Party가 보고하는 인증기 모델이 기대와 다름을 알아차릴 수 있습니다.
참고: 위에서 설명한 모든 변형의 중간자 공격들은 기존의 비밀번호 인증에 대한 중간자 공격보다 공격자가 수행하기 더 어렵습니다.
13.4.5. 폐기된 어테스테이션 인증서
인증서 증명서 검증이 중간 인증 CA 인증서가 폐기되어 실패하고, 신뢰 당사자의 정책이 이러한 상황에서 등록/인증 요청을 거부해야 한다고 요구할 경우, 신뢰 당사자가 동일한 중간 CA로 체인된 인증서 증명서를 사용하여 CA 유출일 이후 등록된 공개 키 자격 증명을 등록 해제(또는 "자체 증명"과 동등한 신뢰 수준으로 표시)하는 것도 권장됩니다. 따라서 신뢰 당사자는 등록 시 중간 인증 CA 인증서를 기억하여, 해당 인증서가 폐기된 후 수행된 등록에 대해 관련된 공개 키 자격 증명을 등록 해제할 수 있도록 하는 것이 권장됩니다.
또한 인증자에 대한 관련 보안 고려 사항은 § 13.3.2 인증서 증명서 및 인증 CA 유출를 참고하세요.
13.4.6. 자격 증명 손실 및 키 이동성
이 명세서는 credential private keys의 백업이나 authenticators 간 공유를 위한 프로토콜을 정의하지 않습니다. 일반적으로 credential private key는 그것을 생성한 authenticator를 떠나지 않는 것으로 기대됩니다. 따라서 인증기를 분실하면 일반적으로 그 인증기에 바인딩된 모든 credentials를 잃게 되며, 사용자가 Relying Party에 등록된 자격 증명을 하나만 가지고 있다면 계정에 접근할 수 없게 될 수 있습니다. 개인키를 백업하거나 공유하는 대신 Web Authentication API는 동일한 사용자에 대해 복수의 credentials를 등록하도록 허용합니다. 예를 들어 사용자는 자주 사용하는 platform credentials을 자주 사용하는 client devices에 등록하고, 새로운 또는 드물게 사용하는 client devices용으로 하나 이상의 roaming credentials를 백업으로 등록할 수 있습니다.
Relying Parties는 사용자에게 동일한 credentials를
동일한 사용자 계정에 복수 등록하도록 허용하고 권장해야
합니다. Relying Parties는
및
excludeCredentials
옵션을 사용하여 서로 다른 credentials가 서로 다른 authenticators에 바인딩되도록 해야 합니다.
user.id
13.4.7. 보호되지 않은 계정 감지
이 절은 규범적이지 않습니다.
이 보안 고려사항은 인증 절차의 첫 단계로 authentication ceremonies를 지원하면서 비-empty한 allowCredentials
인자를 사용하는 Relying Parties에
적용됩니다.
예를 들어 서버-사이드 자격 증명을 첫 단계로 사용하는 인증의 경우가 해당합니다.
이 경우 allowCredentials
인자는 어떤 사용자 계정이 WebAuthn 자격 증명을
등록했는지 여부에 대한 정보를 유출할 위험이 있으며, 이는 계정 보호 강도의 신호가 될 수 있습니다.
예를 들어 공격자가 사용자 이름만 제공하여 인증 절차를 시작할 수 있고, Relying Party가 일부 사용자 계정에 대해 비어 있지 않은 allowCredentials를
응답하고 다른 계정에는 실패 또는 비밀번호 챌린지를 응답한다면,
공격자는 후자의 계정들이 WebAuthn 어설션을 요구하지 않을 가능성이 높다고 결론짓고, 그보다 약할 것으로 보이는 계정들을 집중 공격할 수 있습니다.
이 문제는 § 14.6.2 사용자 이름 열거 및 § 14.6.3 credential ID를 통한 개인정보 유출에서 설명된 문제와 유사하며, 유사한 방식으로 완화할 수 있습니다.
13.4.8. 코드 인젝션 공격
어떤 악성 코드가 origin 내에서 실행되어 scope 내의 Relying Party의 public key credentials에 접근할 수 있게 되면 WebAuthn이 제공하는 모든 보안 보장이 무력화될 수 있습니다. WebAuthn Clients는 WebAuthn API를 secure contexts에서만 노출하므로 기본적인 공격은 완화되지만, Relying Parties는 추가적인 주의를 기울여야 합니다.
코드 인젝션은 여러 경로로 발생할 수 있으며; 이 절은 몇 가지 가능한 시나리오와 완화책을 제시하지만 포괄적인 목록은 아닙니다.
-
악성 코드는 Relying Party가 포함한 제3자 스크립트로 인해 주입될 수 있습니다(의도적이거나 제3자 취약점으로 인한 경우).
따라서 Relying Party는 origins 내에서 포함하는 제3자 스크립트의 양을 제한해야 합니다.
Relying Party는 Content Security Policy [CSP2] 및/또는 당시 이용 가능한 기타 적절한 기술을 사용하여 어떤 스크립트가 자신의 origins에서 실행될 수 있는지를 제한해야 합니다.
-
악성 코드는 자격 증명 scope 규칙에 따라 RP ID의 서브도메인에 호스팅된 사용자 제출 코드에서 발생할 수 있습니다. 예를 들어
usercontent.example.org에 호스팅된 사용자 제출 코드가 credentials를 scope으로 사용할 수 있다면, Relying Party가 assertion 검증시 서브도메인origin을 허용한다면 악성 사용자가 중간자 공격을 수행하여 유효한 authentication assertions를 얻고 피해자를 가장할 수 있습니다.따라서 기본적으로 Relying Party는 assertion 검증 시 서브도메인
origin을 허용해서는 안 됩니다. 만약 Relying Party가 서브도메인origin을 허용해야 한다면, 그 Relying Party는 자신의 scope 내에 있는 허용된 서브도메인에서 신뢰할 수 없는 코드를 제공해서는 안 됩니다.
13.4.9. 자격 증명의 origin 검증
자격 증명 등록(registering a credential) 및 어설션 검증(verifying an assertion) 시에,
Relying Party는 클라이언트 데이터의
origin
멤버를 반드시 검증해야 합니다.
Relying Party는 예상치 못한 origin
값을 수락해서는 안 됩니다. 그렇게 하면 악의적 웹사이트가 유효한 credentials를 획득할 수 있습니다.
WebAuthn 자격 증명의 scope는 그들이 등록된 RP ID 외의 도메인에서
사용되는 것을 방지하지만,
Relying Party의 origin 검증은 결함
있는 authenticator가 자격 증명 scope을 집행하지 못할 경우의 추가 보호층으로 작용합니다.
악성 서브도메인에 대한 논의는 § 13.4.8 코드 인젝션 공격을 참조하세요.
검증은 정확한 문자열 일치 또는 Relying Party의 필요에 따라 다른 방법으로 수행될 수 있습니다. 예를 들어:
-
오직
https://example.org에서만 서비스되는 웹 애플리케이션은origin이 정확히https://example.org인지를 요구해야 합니다.이는 가장 단순한 경우로,
origin이https://뒤에 RP ID가 따라오는 문자열일 것으로 기대되는 경우입니다. -
소수의 도메인에서 서비스되는 웹 애플리케이션은
origin이 허용된 origin 목록의 요소 중 하나와 정확히 일치하도록 요구할 수 있습니다. 예:["https://example.org", "https://login.example.org"]. -
related origin requests를 활용하는 웹 애플리케이션은
origin이 허용된 origin 목록의 요소 중 하나와 정확히 일치하도록 요구할 수 있습니다. 예:["https://example.co.uk", "https://example.de", "https://myexamplerewards.com"]. 이 목록은 일반적으로 RP ID의 well-known URI에 나열된 origin과 일치합니다. § 5.11 관련 origin 간 Web Authentication 사용을 참조하세요. -
자주 변하는 대규모 도메인 집합에서 서비스되는 웹 애플리케이션은
origin을 구조적으로 파싱하여 URL 스킴이https이고 권한(authority)이 RP ID와 같거나 그 서브도메인인지(예: example.org 또는 any subdomain of example.org) 요구할 수 있습니다.참고: RP ID의 어느 서브도메인이든 허용하는 것의 위험성에 관한 논의는 § 13.4.8 코드 인젝션 공격을 참조하세요.
-
네이티브 애플리케이션을 동반하는 웹 애플리케이션은
origin을 운영체제 의존 식별자(네이티브 앱 식별자)로 허용할 수 있습니다. 예:["https://example.org", "example-os:appid:204ffa1a5af110ac483f131a1bef8a841a7adb0d8d135908bbd964ed05d2653b"].
클라이언트 데이터의 topOrigin
멤버를 검증할 때도 유사한 고려사항이 적용됩니다.
topOrigin이
존재할 경우, Relying Party는 그 값이
예상되는지 검증해야 합니다.
이 검증은 정확한 문자열 일치 또는 Relying
Party가 필요로 하는 다른 방법으로 수행될 수 있습니다. 예를 들어:
-
교차 출처
iframe에 포함되는 것을 원치 않는 웹 애플리케이션은topOrigin이 정확히origin과 같도록 요구할 수 있습니다. -
교차 출처
iframe에 포함되기를 허용하는 소수의 도메인이 있는 웹 애플리케이션은topOrigin이 허용된 origin 목록의 요소 중 하나와 정확히 일치하도록 요구할 수 있습니다. 예:["https://example-partner1.org", "https://login.partner2-example.org"]. -
교차 출처
iframe에 많은 도메인에서 포함되기를 허용하는 웹 애플리케이션은topOrigin의 어떤 값도 허용하거나 특정 절차로 주어진topOrigin값이 특정 절차에 의해 허용되는지 동적으로 결정할 수 있습니다.
14. 프라이버시 고려사항
[FIDO-Privacy-Principles]의 프라이버시 원칙은 이 명세에도 적용됩니다.
이 절은 대상별로 나누어져 있습니다.
일반 프라이버시 고려사항은 이 절의 직접 하위 절로, authenticator, client, Relying Party 구현자를 위한 프라이버시 고려사항은 각각 별도의 하위 절로 정리되어 있습니다.
14.1. 탈익명화 방지 대책
이 절은 규범적이지 않습니다.
Web Authentication API의 많은 설계 요소들은 프라이버시 우려에서 비롯되었습니다. 본 명세에서 주로 다루는 우려는 사용자의 개인 신원 보호, 즉 인간 개체의 식별 또는 별도의 신원들을 동일인으로 연결하는 것을 방지하는 것입니다. Web Authentication API는 전역 신원을 사용하거나 제공하지 않지만, 다음과 같은 연관 가능한 식별자들이 사용됩니다:
-
사용자의 credential ID 및 credential public key.
이 정보들은 WebAuthn Relying Party에 의해 등록되어, 해당 사용자가 credential private key를 소유하고 있다는 증명을 위해 사용됩니다. 이 정보들은 client가 authenticator와 통신할 때도 볼 수 있습니다.
-
각 Relying Party에 특화된 신원, 예를 들어 사용자명과 user handle.
각 Relying Party는 시스템 내에서 사용자를 식별하기 위해 이 신원정보를 사용하며, client가 authenticator와 통신할 때도 볼 수 있습니다.
-
사용자의 생체 특성(예: 지문, 얼굴 인식 데이터) [ISOBiometricVocabulary]
이는 authenticator가 user verification을 수행할 때 선택적으로 사용되며, Relying Party에는 공개되지 않습니다. 다만 platform authenticators의 경우, 구현에 따라 client에 보일 수 있습니다.
-
사용자 authenticator의 모델(제품명 등).
이는 attestation statement로 Relying Party에 등록 시 제공되며, client가 authenticator와 통신할 때도 볼 수 있습니다.
-
사용자 authenticator의 식별 정보(예: 일련번호 등).
이는 client가 authenticator와 통신할 수 있게 하기 위해 사용될 수 있으나, Relying Party에는 공개되지 않습니다.
위 정보 중 일부는 Relying Party와 필연적으로 공유되어야 합니다. 이후 절에서는 악의적인 Relying Party가 이러한 정보를 사용하여 사용자의 개인 신원을 파악하지 못하도록 하는 대책을 설명합니다.
14.2. 익명성, 범위 한정, 상호연결 불가 공개키 자격증명
이 절은 규범적이지 않습니다.
Credential ID와 credential public key는 강력한 인증을 위해 WebAuthn Relying Party와 공유되어야 하지만, 이들은 식별성을 최소화하도록 설계되어 있으며 Relying Parties 간에 공유되지 않습니다.
-
Credential ID, credential public key 모두 각각만으로는 의미가 없으며, 오직 credential key pair 자체만을 식별할 뿐입니다.
-
각 공개키 자격증명은 특정 Relying Party에 한정(scope)되어 있으며, client가 그 존재를 다른 Relying Party에 노출하지 않습니다. 그래서 악의적인 Relying Party가 client에게 사용자 신원 정보를 요구할 수 없습니다.
-
client 역시, 공개키 자격증명의 존재를 Relying Party에게 user consent 없이 노출하지 않음을 보장합니다. 자세한 내용은 § 14.5.1 등록 절차 프라이버시와 § 14.5.2 인증 절차 프라이버시에서 다룹니다. 악의적인 Relying Party는 사용자가 이미 등록하고 사용 가능한 공개키 자격증명이 있더라도 몰래 사용자를 식별할 수 없습니다.
-
authenticator는 서로 다른 공개키 자격증명의 credential ID와 credential public key가 동일 사용자에 속한다는 것을 연결하지 않도록 보장합니다. 서로 공모한 Relying Party 두 쌍은 추가 정보(예: 고의로 재사용한 사용자명/이메일 주소) 없이는 사용자를 연관지을 수 없습니다.
-
authenticator는 그 attestation certificate가 단일 인증기나 소규모 인증기를 구별할 만큼 고유하지 않도록 보장합니다. 자세한 내용은 § 14.4.1 인증서 프라이버시에서 다룹니다. 쌍을 이루는 악의적인 Relying Party도 개별 authenticator를 추적해 시스템 간 사용자를 연결할 수 없습니다.
또한 클라이언트 측 검색가능 공개키 자격증명 소스에는 Relying Party가 지정한 user handle을 선택적으로 포함할 수 있습니다. 이 자격증명은 사용자를 식별 및 인증하는 데 둘 다 사용할 수 있습니다. 즉, 프라이버시를 신경 쓰는 Relying Party는 기존 사용자명 없이 user account를 생성할 수 있어 Relying Parties 간 연관 가능성이 더 낮아집니다.
14.3. authenticator-로컬 생체 인식
생체 인증기는 생체 인식을 authenticator 내부에서 수행합니다. 단, platform authenticators의 경우 구현에 따라 생체 데이터가 client에도 노출될 수 있습니다. 생체 데이터는 WebAuthn Relying Party에는 공개되지 않으며, 오직 로컬에서 user verification을 수행하고, 공개키 자격증명 등록 또는 인증에만 사용됩니다. 따라서 악의적인 Relying Party는 생체 데이터로 사용자의 신원을 파악할 수 없으며, Relying Party에서 보안사고가 나더라도 생체 데이터가 다른 Relying Party에서 로그인을 위조하는 데 악용될 위험이 없습니다.
만약 Relying Party가 생체 인식을 요구하면, 생체 인증기가 로컬에서 user verification을 수행하고, 그 결과를 UV 플래그를 서명된 assertion 응답에 설정하여 신호만 보냅니다. 생체 데이터를 Relying Party에 직접 공개하지 않습니다.
14.4. authenticator를 위한 프라이버시 고려사항
14.4.1. 인증서(Attestation) 프라이버시
Attestation
certificate 및 attestation key pair는 사용자를 추적하거나 동일 사용자의 여러 온라인 신원을 연결하는 데 사용될 수
있습니다.
이를 완화하는 방법은 여러 가지가 있으며, 예시로:
-
WebAuthn Authenticator 제조사는 동일한 attestation certificate을 공유하는 배치(batch) 단위로 authenticator를 출하할 수 있습니다(이를 Basic Attestation 또는 batch attestation이라 함). 이렇게 하면, 특정 attestation certificate의 private key가 유출될 때 해당 certificate를 개별적으로 취소하지 못할 위험이 있는 대신 사용자는 익명 처리됩니다.
이 경우 authenticator 제조사는 충분한 익명성이 보장되도록 배치 크기를 충분히 크게 하고 동시에 프라이빗키 유출 시 피해 사용자를 최소화하도록 배치 크기를 최적화해야 합니다.[UAFProtocol]은 충분히 큰 그룹 생성을 위해 동일 attestation certificate을 100,000개 이상 authenticator 장치가 공유할 것을 요구합니다. 이 값이 적절한 배치 크기에 대한 가이드가 될 수 있습니다.
-
WebAuthn Authenticator는 attestation key pair를 credential별로 동적으로 생성하고 이에 대한 certificate를 요청할 수 있습니다(Anonymization CA 접근법). 예를 들어 authenticator는 기본 attestation private key(및 certificate)를 탑재해 출하되며, 클라우드 운영 Anonymization CA와 연동해 credential별로 credential마다 동적으로 attestation key pair와 certificate를 생성할 수 있습니다.
Note: 이 명세 외부의 문서에서는 "Privacy CA"라는 용어가 본 명세에서의 Anonymization CA와 동일한 개념으로 사용되기도 합니다. TCG(Trusted Computing Group)에서는 기존에 "Privacy CA"로 지칭하던 것을 현재 Attestation CA(ACA)라고 부르기 때문에, 본 문서에서는 혼동을 줄이기 위해 "Anonymization CA"라는 용어를 사용합니다.
14.4.2. authenticator에 저장된 개인정보(PII)의 프라이버시
authenticator는 본 명세에 정의되지 않은 추가 정보를 client에 제공할 수 있습니다. 예를 들면 사용자가 인증 절차에 사용할 credential을 선택할 수 있게 하는 풍부한 UI 기능이 그 예입니다. 만약 authenticator가 그렇게 한다면, 성공적인 user verification이 이루어지지 않은 한 개인정보를 노출해서는 안 됩니다. user verification이 동시에 두 명 이상 등록유저에 대해 지원된다면, authenticator는 현재 verified된 사용자 이외엔 개인정보를 노출해서는 안 됩니다. user verification 기능이 없는 authenticator는 어떠한 개인정보도 저장하면 안 됩니다.
이와 관련해, user handle이 id
멤버로 전달되는 PublicKeyCredentialUserEntity의
값은 개인정보로 간주하지 않습니다. 자세한 내용은 § 14.6.1 User Handle 내용을 참고하세요.
이 권고들은 물리적으로 authenticator에 접근할 수 있는 공격자가 등록된 사용자들의 개인정보를 추출하지 못하도록 하기 위함입니다.
14.5. client를 위한 프라이버시 고려사항
14.5.1. 등록 절차 프라이버시
사용자 동의(consent) 없이 사용자가 식별되는 것을
막기 위해, [[Create]](origin, options, sameOriginWithAncestors)
메서드의 구현 시 악의적인 WebAuthn Relying Party가 다음 상황(여기서 "excluded"는 Relying Party가 excludeCredentials에
나열한 credential 중 적어도 하나가 해당 authenticator에 bound되어 있다는 뜻)에 따라 구분할 수 있는 정보가 유출되지 않도록
주의해야 합니다:
-
어떤 authenticator도 없음
-
최소 1개의 authenticator가 있고, 그 중 적어도 하나가 제외됨
위 경우를 구분할 수 있다면, 악의적인 Relying
Party가 어떤 credential이 사용가능한지 탐색하여 사용자를 식별할 수 있는 정보가 유출됩니다. 예를 들어, 제외된 authenticator가 감지되는 즉시 실패
응답을 반환한다면 특히 이 authenticator가 platform authenticator일 때 Relying Party는 사용자가 수동 취소하기 전 절차가 취소됨을 파악할 수 있어,
excludeCredentials
목록 중 최소 1개 credential이 사용 가능하다고 결론지을 수 있습니다.
그러나, 사용자가 식별 가능한 오류가 반환되기 전에 새 credential 생성을 명시적으로 동의했다면 이는 문제가 되지 않습니다. 즉, 사용자가 정보 유출에 동의했으므로 추가 우려가 없습니다.
14.5.2. 인증 절차 프라이버시
사용자 동의 없이 식별을 방지하려면, [[DiscoverFromExternalSource]](origin, options, sameOriginWithAncestors)
메서드를 구현할 때 악의적인 WebAuthn Relying Party가 다음 상황(여기서 "named"란 Relying Party가 allowCredentials에
나열한 credential이 존재함을 뜻함)을 구분할 수 있는 정보가 노출되지 않도록 주의해야 합니다:
-
명명된 credential이 존재하지 않음
-
명명된 credential이 존재하지만 사용자가 사용에 동의하지 않음
위 두 경우가 구분 가능하다면, 악의적인 Relying
Party가 사용가능한 credential을 탐색해 사용자 식별정보를 알 수 있습니다. 예컨대 클라이언트가 authenticator에서 명명된 credential을 찾은 뒤에만 인증 절차 진행/취소 버튼 등을 표시한다면 이 정보로 인해 Relying Party가 절차가 사용자에 의해
취소(타임아웃 아님)되었음을 탐지하고, 따라서 allowCredentials
에 나온 credential 중 1개 이상이 존재함을 추정할 수 있습니다.
이 문제는 명명된 credential 보유 여부와 관계없이 언제든 인증 절차를 취소할 수 있는 버튼 등을 항상 표시하면 완화될 수 있습니다.
14.5.3. 운영체제 계정 간 프라이버시
여러 명이 사용하는 운영체제를 가진 client device에 platform authenticator가 포함되어 있다면, platform authenticator 및 client device는 platform credential의 존재 여부가 해당 자격증명을 만든 운영체제 사용자에게만 노출되도록 해야 합니다.
14.5.4. 클라이언트 기능 공개
getClientCapabilities
메서드는 WebAuthn
Relying Party가 클라이언트 및/또는 사용자의 성공 확률을 높인 등록·인증 경험을 설계할 수 있도록 도와줍니다.
WebAuthn 기능 지원 여부는 지문 채취(핑거프린팅)의 위험이 있으므로, 클라이언트 구현은 정책 및/또는 사용자 동의에 따라 기능 공개를 제한할 수 있습니다.
14.6. Relying Party를 위한 프라이버시 고려사항
14.6.1. user handle 내용
user handle은 § 14.4.2 authenticator에 저장된 개인정보(PII)의 프라이버시에서 개인정보로 간주되지 않으며,
또한 authenticator는 user handle을 user verification
없이 공개할 수 있으므로, Relying
Party는 user handle에 개인정보(이메일 주소, 사용자명 등)를 담아서는 안 됩니다. 해시값 역시, 해시 함수가 salt 값이 Relying Party에만
비공개로 존재할 때만 허용됩니다. 단순 해시는 예측 가능한 값에 대해 방어하지 못합니다.
권장 방법은 user handle을 64바이트 난수로 하고,
이를 user account에 저장하는 것입니다.
14.6.2. 사용자명(Username) 탐색
registration 또는 authentication ceremony 개시 시, WebAuthn Relying Party가 등록 유저에 관한 민감정보를 유출할 위험이 있습니다. 예를 들어, 어떤 Relying Party가 사용자명으로 이메일 주소를 쓰고, 공격자가 "alex.mueller@example.com"으로 인증 절차를 시도했을 때 실패 응답을, "j.doe@example.com"으로 시도하면 성공 응답을 받았다면 공격자는 "j.doe@example.com"이 등록되어 있고 "alex.mueller@example.com"은 등록되어 있지 않음을 알 수 있습니다. 이렇게 하여 Relying Party는 "j.doe@example.com"이 자기 서비스에 계정이 있다는 민감 정보를 유출하는 셈이 됩니다.
아래는 이와 같은 공격에서 민감정보 유출을 예방/완화할 수 있는 Relying Party의 비규범적 조치 예시입니다:
-
-
Relying Party가 자체 사용자명 체계를 쓴다면:
-
registration ceremony에서 구문적으로 이메일인 사용자명의 등록은 거부합니다.
Note: 그 이유는 이미 등록된 사용자명을 재등록하면 Relying Party가 등록 절차를 실패시킬 수밖에 없고, 정보 유출을 완전히 막을 수 없기 때문입니다. 이메일 주소형 사용자명을 막으면, 여러 서비스 간 동일 사용자명 사용이 줄어 그 영향도 줄어듭니다.
-
-
Relying Party가 이메일을 사용자로 쓴다면:
-
registration ceremony에서 이메일 입력 후 사용자의 상호작용을 잠시 중단하고, 예측불가능한 일회용 코드 및 진행 안내가 담긴 이메일을 보냅니다. 발송된 메일 내용이나 이미 등록된 이메일 여부와 무관하게 웹 인터페이스에는 동일 메시지를 출력합니다.
Note: 이 방법은, 예를 들어 국가 ID나 신용카드 번호 등 외부적 의미가 있는 식별자에도 비슷하게 적용될 수 있습니다(예: 등기우편 등 기타 대역외 연락수단이 있는 경우).
-
-
-
-
authentication ceremony 시작 시 해당 사용자명에 맞는 user account가 없다면, 적당한 모의값(서로 그럴듯하게 구성된 값)으로 채운
navigator.credentials.get()및PublicKeyCredentialRequestOptions객체로 절차를 계속합니다.이 방식은
allowCredentials를 통한 정보 유출 완화에도 쓸 수 있습니다. § 13.4.7 미보호 계정 탐지 및 § 14.6.3 Credential ID 프라이버시 유출 참고.Note: 사용자명은 로그인 폼, 세션 쿠키 등 특정 Relying Party별 다양한 방식으로 "제공" 가능합니다.
Note: 모의값들이 실제값과 현저히 다르다면, 공격자가 이를 통해 실제 계정의 존재 여부를 검사할 수 있습니다. 예를 들면 입력값마다 항상 같거나, 같음 사용자명 반복 입력 시 응답값이 매번 다르면 들킬 수 있습니다.
allowCredentials멤버에 사용자명으로부터 결정적으로 도출된 의사난수값을 쓸 수 있습니다. -
AuthenticatorAssertionResponse의 검증 실패 원인이 서명 오류인지 해당 유저·자격증명 미등록 때문인지 구분할 수 없게 만듭니다. -
WebAuthn ceremony 개시 전 사용자명·비밀번호 또는 세션 쿠키 등 1단계 인증을 먼저 거치는 다단계 authentication ceremony를 구성합니다. 이렇게 하면 username enumeration 문제가 WebAuthn 단계 이전으로 이동되어 더 쉽게 완화할 수 있습니다.
-
14.6.3. Credential ID 프라이버시 유출
이 절은 규범적이지 않습니다.
이 프라이버시 고려사항은 비어있지 않은 allowCredentials
인자와 함께 authentication ceremony 1단계를 구현하는 Relying Party에 적용됩니다. 예를 들어 서버측 credential을 첫 1차
인증 단계로 쓰는 경우입니다.
이 경우 allowCredentials
인자를 통해 인증받지 않은 호출자에게 사용자의 credential ID가 노출될 수 있어 개인정보 유출 위험이 있습니다. Credential ID는 여러 Relying Party를 연관짓지 않도록 설계됐으나, credential ID의
길이로 어떤 authenticator가 만들었는지
유추가 가능할 수 있습니다.
한 사용자가 여러 Relying Party에서
동일한 사용자명과 인증기 조합을 사용할 수 있으므로, allowCredentials
내 credential ID 개수와 길이가 전역 식별자가 되어 사용자를 탈익명화할 수도 있습니다.
또한 credential ID를 알면 공격자가 잠시 사용자 인증기에 물리적 접근만 해도 신원 추정 시험이 가능합니다.
이런 정보 유출을 막기 위해 Relying Party는 예를 들어 다음처럼 할 수 있습니다:
-
WebAuthn authentication ceremony 및 credential ID 공개 전 사용자명/비번이나 세션쿠키 인증 등 별도 단계 인증을 수행합니다.
-
클라이언트 검색 가능 credential만 사용해
allowCredentials인자 자체를 생략할 수 있게 합니다.
위 예방조치들이 곤란한 상황, 즉 사용자명만 주어졌을 때 allowCredentials
노출이 필요한 경우 Relying Party는 § 14.6.2 사용자명 탐색과 같이 가상의 credential ID를 반환함으로써 프라이버시 유출을 완화할 수 있습니다.
인증받지 않은 호출자에게 credential id를
노출하지 않기 위해, 해당 credential id가 인식되지 않았음을 신호할 때 WebAuthn Relying Party는 signalUnknownCredential(options)
메서드를 쓰고 signalAllAcceptedCredentials(options)
메서드는 사용하지 않아야 합니다.
15. 접근성 고려 사항
사용자 검증이 가능한 인증자는 로밍이든 플랫폼이든 사용자에게 하나 이상의 사용자 검증 방식을 제공해야 합니다. 예로 지문 인식과 PIN 입력 모두를 제공하는 것입니다. 이렇게 하면 선택한 검증 방식이 어떤 이유로 동작하지 않을 때 다른 사용자 검증 방법으로 대체할 수 있습니다. 또한 로밍 인증자의 경우, 인증자와 플랫폼이 함께 동작하여 PIN 입력과 같은 사용자 검증 방식을 제공할 수 있습니다 [FIDO-CTAP].
Relying Party는 등록 시점에, 사용자가 향후 승인 제스처를 올바르게 수행할 수 있도록 지원 기능을 제공해야 합니다. 예시로 인증자에 이름을 붙이기, 기기와 연결할 사진을 선택하기 또는 자유형 텍스트 지시(예: 스스로 위한 메모 등)를 입력받는 것을 들 수 있습니다.
15.1. 인증 절차 타임아웃 권장 범위
타이밍에 의존하는 인증 절차 예를 들어 등록 과정(참고:
timeout)
또는 인증
과정(참고: timeout)
등은 [WCAG21]의 2.2 충분한 시간 가이드라인을 따라야 합니다. 만약 클라이언트 플랫폼이 Relying
Party가 제공한 타임아웃이 [WCAG21] 가이드라인에 적합하지 않다고 판단하면,
클라이언트 플랫폼은 해당 타임아웃을 조정할 수
있습니다.
WebAuthn 인증 절차 타임아웃 권장 범위 및 기본값은 다음과 같습니다:
-
권장 범위: 300000 밀리초 ~ 600000 밀리초
-
권장 기본값: 300000 밀리초(5분)
16. 테스트 벡터
이 섹션은 규범적이지 않습니다.
이 섹션은 구현 검증에 사용될 수 있는 예시 값(example values)을 나열합니다.
예시는 동일 등록 및 인증 과정 쌍으로 의사코드(pseudocode)로 제시되며, 바이트 문자열 리터럴 및 주석은 CDDL [RFC8610] 표기법을 따릅니다. 예제는 전체 구현을 망라하지 않고 WebAuthn 확장을 포함하지 않습니다.
예제들은 입력에서 출력까지의 흐름을 따르며, 일부 중간 값을 포함할 수 있습니다.
등록 예제에서는 Relying Party가
challenge
입력을 정의하고,
클라이언트는 clientDataJSON
출력을 생성하며 인증자는
attestationObject
출력을 생성합니다.
인증 예제에서는 Relying Party가
challenge
입력을 정의하고,
클라이언트는 clientDataJSON
출력을 생성하며 인증자는
authenticatorData
및 signature
출력을 생성합니다.
그 외 암호학적으로 관련 없는 입력과 출력은 포함하지 않습니다.
인증자 구현자들은
attestationObject,
authenticatorData
및 signature
출력을 자신들의 구현이 비슷한 구조로 만드는지 확인할 수 있습니다. 클라이언트 구현자들은
clientDataJSON
출력 구조가 유사한지 확인할 수 있습니다. Relying
Party
구현자들은 동일 challenge
입력으로 등록 출력을 성공적으로 검증할 수 있고,
동일 challenge
입력과 등록 예제에서 얻은 credential public key, credential ID로 인증 출력을 검증할 수 있는지 체크할 수 있습니다.
모든 예제는 RP ID
example.org와 origin
https://example.org 그리고 해당되는 경우 topOrigin
https://example.com을 사용합니다.
별도 언급이 없다면 예제에는 attestation 없음이 포함되어 있습니다.
모든 랜덤 값은 CDDL에서 'WebAuthn test vectors'로 명시된 기본 입력 키 소재에서 HKDF-SHA-256 [RFC5869]을 사용해 결정적으로 생성됩니다.
ECDSA 서명은 결정론적 nonce [RFC6979]를
사용합니다.
예제의 RSA 키는 p ≥ 1024인 두 개의 가장 작은 메르센 소수 2p - 1 로 구성됩니다.
참고:
-
재현 가능성을 위해 예제에 credential private key 및 attestation private key가 포함되어 있으나, 실제로 이 값들은 클라이언트 또는 Relying Party와 공유되지 않습니다.
참고: CTAP2를 구현하는 인증자는 [FIDO-CTAP] 명세와는 다른 키로 attestation object를 반환합니다. 이 예제들은 WebAuthn Relying Party가 기대하는 attestation object 포맷을 반영하므로 CTAP2에서 출력된 attestation object는 바이트 단위로 동일해지도록 키 변환이 필요할 수 있습니다.
16.1. Attestation 신뢰 루트 인증서
모든 attestation이 포함된 예제는
X.509 DER [RFC5280]로
인코딩된
아래의 attestation_ca_cert 신뢰 루트 인증서를 사용합니다:
attestation_ca_key = h'7809337f05740a96a78eedf9e9280499dcc8f2aa129616049ec1dccfe103eb2a' ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'00', info='Attestation CA', L=32) attestation_ca_serial_number = h'ed7f905d8bd0b414d1784913170a90b6' ; Derived by: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'01', info='Attestation CA', L=16) attestation_ca_cert = h'30820207308201ada003020102021100ed7f905d8bd0b414d1784913170a90b6300a06082a8648ce3d0403023062311e301c06035504030c15576562417574686e207465737420766563746f7273310c300a060355040a0c0357334331253023060355040b0c1c41757468656e74696361746f72204174746573746174696f6e204341310b30090603550406130241413020170d3234303130313030303030305a180f33303234303130313030303030305a3062311e301c06035504030c15576562417574686e207465737420766563746f7273310c300a060355040a0c0357334331253023060355040b0c1c41757468656e74696361746f72204174746573746174696f6e204341310b30090603550406130241413059301306072a8648ce3d020106082a8648ce3d030107034200043269300e5ff7b699015f70cf80a8763bf705bc2e2af0c1b39cff718b7c35880ca30f319078d91b03389a006fdfc8a1dcd84edfa07d30aa13474a248a0dab5baaa3423040300f0603551d130101ff040530030101ff300e0603551d0f0101ff040403020106301d0603551d0e0416041445aff715b0dd786741fee996ebc16547a3931b1e300a06082a8648ce3d04030203480030450220483063b6bb08dcc83da33a02c11d2f42203176893554d138c614a36908724cc8022100f5ef2c912d4500b3e2f5b591d0622491e9f220dfd1f9734ec484bb7e90887663'
16.1.1. ES256 자격 증명(Attestation 없음)
등록:
challenge = h'00c30fb78531c464d2b6771dab8d7b603c01162f2fa486bea70f283ae556e130' ; 파생 방법: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'00', info='none.ES256', L=32) credential_private_key = h'6e68e7a58484a3264f66b77f5d6dc5bc36a47085b615c9727ab334e8c369c2ee' ; 파생 방법: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'01', info='none.ES256', L=32) client_data_gen_flags = h'f9' ; 파생 방법: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'02', info='none.ES256', L=1) ; extra_client_data는 client_data_gen_flags의 0x01 비트가 1일 때만 포함됨 extra_client_data = h'06441e0e375c4c1ad70620302532c4e5' ; 파생 방법: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'03', info='none.ES256', L=16) aaguid = h'8446ccb9ab1db374750b2367ff6f3a1f' ; 파생 방법: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'04', info='none.ES256', L=16) credential_id = h'f91f391db4c9b2fde0ea70189cba3fb63f579ba6122b33ad94ff3ec330084be4' ; 파생 방법: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'05', info='none.ES256', L=32) ; auth_data_UV_BE_BS는 인증자 데이터 플래그의 UV, BE, BS 비트를 결정하나, BS는 BE일 때만 설정됨 auth_data_UV_BE_BS = h'ba' ; 파생 방법: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'06', info='none.ES256', L=1) clientDataJSON = h'7b2274797065223a22776562617574686e2e637265617465222c226368616c6c656e6765223a22414d4d507434557878475453746e63647134313759447742466938767049612d7077386f4f755657345441222c226f726967696e223a2268747470733a2f2f6578616d706c652e6f7267222c2263726f73734f726967696e223a66616c73652c22657874726144617461223a22636c69656e74446174614a534f4e206d617920626520657874656e6465642077697468206164646974696f6e616c206669656c647320696e20746865206675747572652c207375636820617320746869733a20426b5165446a646354427258426941774a544c4535513d3d227d' attestationObject = h'a363666d74646e6f6e656761747453746d74a068617574684461746158a4bfabc37432958b063360d3ad6461c9c4735ae7f8edd46592a5e0f01452b2e4b559000000008446ccb9ab1db374750b2367ff6f3a1f0020f91f391db4c9b2fde0ea70189cba3fb63f579ba6122b33ad94ff3ec330084be4a5010203262001215820afefa16f97ca9b2d23eb86ccb64098d20db90856062eb249c33a9b672f26df61225820930a56b87a2fca66334b03458abf879717c12cc68ed73290af2e2664796b9220'
인증:
challenge = h'39c0e7521417ba54d43e8dc95174f423dee9bf3cd804ff6d65c857c9abf4d408' ; 파생 방법: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'07', info='none.ES256', L=32) client_data_gen_flags = h'4a' ; 파생 방법: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'08', info='none.ES256', L=1) ; extra_client_data는 client_data_gen_flags의 0x01 비트가 1일 때만 포함됨 ; auth_data_UV_BS는 인증자 데이터 플래그의 UV와 BS 비트를 설정하나, BS는 등록 시 BE가 설정되었을 때만 설정됨 auth_data_UV_BS = h'38' ; 파생 방법: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'09', info='none.ES256', L=1) authenticatorData = h'bfabc37432958b063360d3ad6461c9c4735ae7f8edd46592a5e0f01452b2e4b51900000000' clientDataJSON = h'7b2274797065223a22776562617574686e2e676574222c226368616c6c656e6765223a224f63446e55685158756c5455506f334a5558543049393770767a7a59425039745a63685879617630314167222c226f726967696e223a2268747470733a2f2f6578616d706c652e6f7267222c2263726f73734f726967696e223a66616c73657d' signature = h'3046022100f50a4e2e4409249c4a853ba361282f09841df4dd4547a13a87780218deffcd380221008480ac0f0b93538174f575bf11a1dd5d78c6e486013f937295ea13653e331e87'
16.1.2. 자체 Attestation이 포함된 ES256 자격 증명
등록:
challenge = h'7869c2b772d4b58eba9378cf8f29e26cf935aa77df0da89fa99c0bdc0a76f7e5' ; 파생 방법: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'00', info='packed-self.ES256', L=32) credential_private_key = h'b4bbfa5d68e1693b6ef5a19a0e60ef7ee2cbcac81f7fec7006ac3a21e0c5116a' ; 파생 방법: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'01', info='packed-self.ES256', L=32) client_data_gen_flags = h'db' ; 파생 방법: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'02', info='packed-self.ES256', L=1) ; extra_client_data는 client_data_gen_flags의 0x01 비트가 1일 때만 포함됨 extra_client_data = h'53d8535ef284d944643276ffd3160756' ; 파생 방법: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'03', info='packed-self.ES256', L=16) aaguid = h'df850e09db6afbdfab51697791506cfc' ; 파생 방법: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'04', info='packed-self.ES256', L=16) credential_id = h'455ef34e2043a87db3d4afeb39bbcb6cc32df9347c789a865ecdca129cbef58c' ; 파생 방법: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'05', info='packed-self.ES256', L=32) ; auth_data_UV_BE_BS는 인증자 데이터 플래그의 UV, BE, BS 비트를 결정하나, BS는 BE일 때만 설정됨 auth_data_UV_BE_BS = h'fd' ; 파생 방법: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'06', info='packed-self.ES256', L=1) clientDataJSON = h'7b2274797065223a22776562617574686e2e637265617465222c226368616c6c656e6765223a2265476e4374334c55745936366b336a506a796e6962506b31716e666644616966715a774c33417032392d55222c226f726967696e223a2268747470733a2f2f6578616d706c652e6f7267222c2263726f73734f726967696e223a66616c73652c22657874726144617461223a22636c69656e74446174614a534f4e206d617920626520657874656e6465642077697468206164646974696f6e616c206669656c647320696e20746865206675747572652c207375636820617320746869733a205539685458764b453255526b4d6e625f3078594856673d3d227d' attestationObject = h'a363666d74667061636b65646761747453746d74a263616c67266373696758483046022100ae045923ded832b844cae4d5fc864277c0dc114ad713e271af0f0d371bd3ac540221009077a088ed51a673951ad3ba2673d5029bab65b64f4ea67b234321f86fcfac5d68617574684461746158a4bfabc37432958b063360d3ad6461c9c4735ae7f8edd46592a5e0f01452b2e4b55d00000000df850e09db6afbdfab51697791506cfc0020455ef34e2043a87db3d4afeb39bbcb6cc32df9347c789a865ecdca129cbef58ca5010203262001215820eb151c8176b225cc651559fecf07af450fd85802046656b34c18f6cf193843c5225820927b8aa427a2be1b8834d233a2d34f61f13bfd44119c325d5896e183fee484f2'
인증:
challenge = h'4478a10b1352348dd160c1353b0d469b5db19eb91c27f7dfa6fed39fe26af20b' ; 파생 방법: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'07', info='packed-self.ES256', L=32) client_data_gen_flags = h'1f' ; 파생 방법: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'08', info='packed-self.ES256', L=1) ; extra_client_data는 client_data_gen_flags의 0x01 비트가 1일 때만 포함됨 extra_client_data = h'8136f9debcfa121496a265c6ce2982d5' ; 파생 방법: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'09', info='packed-self.ES256', L=16) ; auth_data_UV_BS는 인증자 데이터 플래그의 UV와 BS 비트를 설정하나, BS는 등록 시 BE가 설정되었을 때만 설정됨 auth_data_UV_BS = h'a1' ; 파생 방법: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'0a', info='packed-self.ES256', L=1) authenticatorData = h'bfabc37432958b063360d3ad6461c9c4735ae7f8edd46592a5e0f01452b2e4b50900000000' clientDataJSON = h'7b2274797065223a22776562617574686e2e676574222c226368616c6c656e6765223a225248696843784e534e493352594d45314f7731476d3132786e726b634a5f6666707637546e2d4a71386773222c226f726967696e223a2268747470733a2f2f6578616d706c652e6f7267222c2263726f73734f726967696e223a66616c73652c22657874726144617461223a22636c69656e74446174614a534f4e206d617920626520657874656e6465642077697468206164646974696f6e616c206669656c647320696e20746865206675747572652c207375636820617320746869733a206754623533727a36456853576f6d58477a696d4331513d3d227d' signature = h'3044022076691be76a8618976d9803c4cdc9b97d34a7af37e3bdc894a2bf54f040ffae850220448033a015296ffb09a762efd0d719a55346941e17e91ebf64c60d439d0b9744'
16.1.3. clientDataJSON에 "crossOrigin": true가 포함된 ES256 자격 증명
등록:
challenge = h'3be5aacd03537142472340ab5969f240f1d87716e20b6807ac230655fa4b3b49' ; 파생 방법: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'00', info='none.ES256.crossOrigin', L=32) credential_private_key = h'96c940e769bd9f1237c119f144fa61a4d56af0b3289685ae2bef7fb89620623d' ; 파생 방법: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'01', info='none.ES256.crossOrigin', L=32) client_data_gen_flags = h'71' ; 파생 방법: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'02', info='none.ES256.crossOrigin', L=1) ; extra_client_data는 client_data_gen_flags의 0x01 비트가 1일 때만 포함됨 extra_client_data = h'cd9aae12d0d1f435aaa56e6d0564c5ba' ; 파생 방법: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'03', info='none.ES256.crossOrigin', L=16) aaguid = h'883f4f6014f19c09d87aa38123be48d0' ; 파생 방법: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'04', info='none.ES256.crossOrigin', L=16) credential_id = h'6e1050c0d2ca2f07c755cb2c66a74c64fa43065c18f938354d9915db2bd5ce57' ; 파생 방법: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'05', info='none.ES256.crossOrigin', L=32) ; auth_data_UV_BE_BS는 인증자 데이터 플래그의 UV, BE, BS 비트를 결정하나, BS는 BE일 때만 설정됨 auth_data_UV_BE_BS = h'27' ; 파생 방법: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'06', info='none.ES256.crossOrigin', L=1) clientDataJSON = h'7b2274797065223a22776562617574686e2e637265617465222c226368616c6c656e6765223a224f2d57717a514e5463554a484930437257576e7951504859647862694332674872434d475666704c4f306b222c226f726967696e223a2268747470733a2f2f6578616d706c652e6f7267222c2263726f73734f726967696e223a747275652c22657874726144617461223a22636c69656e74446174614a534f4e206d617920626520657874656e6465642077697468206164646974696f6e616c206669656c647320696e20746865206675747572652c207375636820617320746869733a207a5a71754574445239445771705735744257544675673d3d227d' attestationObject = h'a363666d74646e6f6e656761747453746d74a068617574684461746158a4bfabc37432958b063360d3ad6461c9c4735ae7f8edd46592a5e0f01452b2e4b54500000000883f4f6014f19c09d87aa38123be48d000206e1050c0d2ca2f07c755cb2c66a74c64fa43065c18f938354d9915db2bd5ce57a501020326200121582022200a473f90b11078851550d03b4e44a2279f8c4eca27b3153dedfe03e4e97d225820cbd0be95e746ad6f5a8191be11756e4c0420e72f65b466d39bc56b8b123a9c6e'
인증:
challenge = h'876aa517ba83fdee65fcffdbca4c84eeae5d54f8041a1fc85c991e5bbb273137' ; 파생 방법: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'07', info='none.ES256.crossOrigin', L=32) client_data_gen_flags = h'57' ; 파생 방법: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'08', info='none.ES256.crossOrigin', L=1) ; extra_client_data는 client_data_gen_flags의 0x01 비트가 1일 때만 포함됨 extra_client_data = h'f76a5c4d50f401bcbeab876d9a3e9e7e' ; 파생 방법: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'09', info='none.ES256.crossOrigin', L=16) ; auth_data_UV_BS는 인증자 데이터 플래그의 UV와 BS 비트를 설정하나, BS는 등록 시 BE가 설정되었을 때만 설정됨 auth_data_UV_BS = h'0c' ; 파생 방법: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'0a', info='none.ES256.crossOrigin', L=1) authenticatorData = h'bfabc37432958b063360d3ad6461c9c4735ae7f8edd46592a5e0f01452b2e4b50500000000' clientDataJSON = h'7b2274797065223a22776562617574686e2e676574222c226368616c6c656e6765223a226832716c463771445f65356c5f505f62796b7945377135645650674547685f49584a6b655737736e4d5463222c226f726967696e223a2268747470733a2f2f6578616d706c652e6f7267222c2263726f73734f726967696e223a747275652c22657874726144617461223a22636c69656e74446174614a534f4e206d617920626520657874656e6465642077697468206164646974696f6e616c206669656c647320696e20746865206675747572652c207375636820617320746869733a2039327063545644304162792d713464746d6a366566673d3d227d' signature = h'304402204396b14b216ed47920dc359e46aa0a1d4a912cf9d50f25a58ec236a11db4cf5e02204fdb59ff01656c4b0868e415436a464b0e30e94b02c719b995afaba9c917146b'
16.1.4. clientDataJSON에 "topOrigin"이 포함된 ES256 자격 증명
등록:
challenge = h'4e1f4c6198699e33c14f192153f49d7e0e8e3577d5ac416c5f3adc92a41f27e5' ; 파생 방법: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'00', info='none.ES256.topOrigin', L=32) credential_private_key = h'a2d6de40ab974b80d8c1ef78c6d4300097754f7e016afe7f8ea0ad9798b0d420' ; 파생 방법: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'01', info='none.ES256.topOrigin', L=32) client_data_gen_flags = h'54' ; 파생 방법: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'02', info='none.ES256.topOrigin', L=1) ; extra_client_data는 client_data_gen_flags의 0x01 비트가 1일 때만 포함됨 aaguid = h'97586fd09799a76401c200455099ef2a' ; 파생 방법: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'03', info='none.ES256.topOrigin', L=16) credential_id = h'b8ad59b996047ab18e2ceb57206c362da57458793481f4a8ebf101c7ca7cc0f1' ; 파생 방법: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'04', info='none.ES256.topOrigin', L=32) ; auth_data_UV_BE_BS는 인증자 데이터 플래그의 UV, BE, BS 비트를 결정하나, BS는 BE일 때만 설정됨 auth_data_UV_BE_BS = h'a0' ; 파생 방법: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'05', info='none.ES256.topOrigin', L=1) clientDataJSON = h'7b2274797065223a22776562617574686e2e637265617465222c226368616c6c656e6765223a225468394d595a68706e6a504254786b68555f53646667364f4e58665672454673587a72636b7151664a2d55222c226f726967696e223a2268747470733a2f2f6578616d706c652e6f7267222c2263726f73734f726967696e223a747275652c22746f704f726967696e223a2268747470733a2f2f6578616d706c652e636f6d227d' attestationObject = h'a363666d74646e6f6e656761747453746d74a068617574684461746158a4bfabc37432958b063360d3ad6461c9c4735ae7f8edd46592a5e0f01452b2e4b5410000000097586fd09799a76401c200455099ef2a0020b8ad59b996047ab18e2ceb57206c362da57458793481f4a8ebf101c7ca7cc0f1a5010203262001215820a1c47c1d82da4ebe82cd72207102b380670701993bc35398ae2e5726427fe01d22582086c1080d82987028c7f54ecb1b01185de243b359294a0ed210cd47480f0adc88'
인증:
challenge = h'd54a5c8ca4b62a8e3bb321e3b2bc73856f85a10150db2939ac195739eb1ea066' ; 파생 방법: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'06', info='none.ES256.topOrigin', L=32) client_data_gen_flags = h'77' ; 파생 방법: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'07', info='none.ES256.topOrigin', L=1) ; extra_client_data는 client_data_gen_flags의 0x01 비트가 1일 때만 포함됨 extra_client_data = h'52216824c5514070c0156162e2fc54a5' ; 파생 방법: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'08', info='none.ES256.topOrigin', L=16) ; auth_data_UV_BS는 인증자 데이터 플래그의 UV와 BS 비트를 설정하나, BS는 등록 시 BE가 설정되었을 때만 설정됨 auth_data_UV_BS = h'9f' ; 파생 방법: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'09', info='none.ES256.topOrigin', L=1) authenticatorData = h'bfabc37432958b063360d3ad6461c9c4735ae7f8edd46592a5e0f01452b2e4b50500000000' clientDataJSON = h'7b2274797065223a22776562617574686e2e676574222c226368616c6c656e6765223a22315570636a4b53324b6f34377379486a7372787a68572d466f51465132796b3572426c584f6573656f4759222c226f726967696e223a2268747470733a2f2f6578616d706c652e6f7267222c2263726f73734f726967696e223a747275652c22746f704f726967696e223a2268747470733a2f2f6578616d706c652e636f6d222c22657874726144617461223a22636c69656e74446174614a534f4e206d617920626520657874656e6465642077697468206164646974696f6e616c206669656c647320696e20746865206675747572652c207375636820617320746869733a205569466f4a4d565251484441465746693476785570513d3d227d' signature = h'304402206a19613fa8cfacfc8027272aec5dae3555fea9f983d841581466678d71e6761a02207a9785ba22e48eb18525850357d9dc70795aaad2e6021159c4a4a183146eaa71'
16.1.5. 아주 긴 자격 증명 ID를 가진 ES256 자격 증명
등록:
challenge = h'1113c7265ccf5e65124282fa1d7819a7a14cb8539aa4cdbec7487e5f35d8ec6c' ; 파생 방법: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'00', info='none.ES256.long-credential-id', L=32) credential_private_key = h'6fd2149bb5f1597fe549b138794bde61893b2dc32ca316de65f04808dac211dc' ; 파생 방법: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'01', info='none.ES256.long-credential-id', L=32) client_data_gen_flags = h'90' ; 파생 방법: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'02', info='none.ES256.long-credential-id', L=1) ; extra_client_data는 client_data_gen_flags의 0x01 비트가 1일 때만 포함됨 aaguid = h'8f3360c2cd1b0ac14ffe0795c5d2638e' ; 파생 방법: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'03', info='none.ES256.long-credential-id', L=16) credential_id = h'3a761a4e1674ad6c4305869435c0eee9c286172c229bb91b48b4ada140c0863417031305cce5b4a27a88d7fe728a5f5a627de771b4b40e77f187980c124f9fe832d7136010436a056cce716680587d23187cf1fc2c62ae86fc3e508ee9617ffc74fbc10488ec16ec5e9096328669a898709b655e549738c666c1ae6281dc3b5f733c251d3eefb76ee70a3805ca91bcc18e49c8dc7f63ebcb486ba8c3d6ab52b88ff72c6a5bb47c32f3ee8683a3ddc8abf60870448ec8a21b5bdcb183c7dead870255575a6df96eb1b6a2a1019780cba9e4887b17ff1164bbbcc10eb0d86ed75984cd3fa3419103024507dfd9ce8f92c56af7914cb0bb50b87ba82a312bb7dcd93028dbdcd6adb266979667158335171e3682d37755701edbf9d872846a291d49e57ef09da1ec637f5052ed2aa7407f7e61827468e94b461844f4c67be5fa9c6055a566f8fdfc29d4bf78a9ff275f552cc68ba543fa3962eea36fd1ea8453764577d021d0a181efc1f6100ab2e4110039e21ee16970bda7432b6134492155afc126295b3a2eccd12c66a68e340969e995e3e8c9c476e395cfc21203414110779474f1c9797406637dbe414f132519d3bf0ce4f01734ef0e1a12c3ad604ff15d766b1624db6a5a7ccbff7bc35c9908df94aba277e0af48f04ff3d16381c47e5a37ed3988a67a3b1ecaa926336b33391fff04128f869991c9fabd905b6fe3ceef5f8b630ec1c5d2636d5b1961ad5ca5004170f6f5e482792aad989b0287fe91e5c479403397152f1fa56aa79b156eb47e6c8ea3eb175c34cfb38ad8e772874639b1023d4d01395c94e55831671cc022aa6fa1e02a02c2e4abc776f6960e51f83b71a8c0f207b6a347573977812c9aa5480b0011aa739bd4b76c18c000cc4757cceccb920f007c40c00e37e5ab21476cd9f6054a8fffb55a108f5c706e2cea2049d81fd321ff47d2a5761b0800955ab1d4f4889f55a84e2601c684f17a4ade7453ea49591d0b59c8d9a765052f62219cf6ef4a5dd9539f0617d6ebbebce7c000455475d18449e25c49ef9a1e3efe18c09082ebe2058d7c347defaa92f0664553b805c7d76bbfce5f330aca220ac90a789380fc479ea0d8793205813cca590a912f699ad52f991a1bc0a503c3ec4b2a696719e3c26591a87127f7305cc7e72f4c8e39355ebb06a5b1042990f38710ee7aa612ee4374bb82e878585a70a96c2a6b47f101a4ff154be4fd76a3167577a5cc54d9167c154c69ac35485e44cc898b719e1be3cc9c0fb5624b8f8a0dae10947a41bf848b6c1bb33d1006ec077d7e286e3f2a7b4843716390119449fe2721e81a5ed2333d331c7120765da58fadae73c19d9a8c4509cf8ac1e9d98b799a5274509069739b5823f3fb496663820033426988eefca53e580e0f9e0dfe0992fc2e53a97e053639f98577058f995bdbd41cefdb' ; 파생 방법: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'04', info='none.ES256.long-credential-id', L=1023) ; auth_data_UV_BE_BS는 인증자 데이터 플래그의 UV, BE, BS 비트를 결정하나, BS는 BE일 때만 설정됨 auth_data_UV_BE_BS = h'69' ; 파생 방법: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'05', info='none.ES256.long-credential-id', L=1) clientDataJSON = h'7b2274797065223a22776562617574686e2e637265617465222c226368616c6c656e6765223a22455250484a6c7a50586d5553516f4c364858675a7036464d75464f61704d322d7830682d587a5859374777222c226f726967696e223a2268747470733a2f2f6578616d706c652e6f7267222c2263726f73734f726967696e223a66616c73657d' attestationObject = h'a363666d74646e6f6e656761747453746d74a0686175746844617461590483bfabc37432958b063360d3ad6461c9c4735ae7f8edd46592a5e0f01452b2e4b549000000008f3360c2cd1b0ac14ffe0795c5d2638e03ff3a761a4e1674ad6c4305869435c0eee9c286172c229bb91b48b4ada140c0863417031305cce5b4a27a88d7fe728a5f5a627de771b4b40e77f187980c124f9fe832d7136010436a056cce716680587d23187cf1fc2c62ae86fc3e508ee9617ffc74fbc10488ec16ec5e9096328669a898709b655e549738c666c1ae6281dc3b5f733c251d3eefb76ee70a3805ca91bcc18e49c8dc7f63ebcb486ba8c3d6ab52b88ff72c6a5bb47c32f3ee8683a3ddc8abf60870448ec8a21b5bdcb183c7dead870255575a6df96eb1b6a2a1019780cba9e4887b17ff1164bbbcc10eb0d86ed75984cd3fa3419103024507dfd9ce8f92c56af7914cb0bb50b87ba82a312bb7dcd93028dbdcd6adb266979667158335171e3682d37755701edbf9d872846a291d49e57ef09da1ec637f5052ed2aa7407f7e61827468e94b461844f4c67be5fa9c6055a566f8fdfc29d4bf78a9ff275f552cc68ba543fa3962eea36fd1ea8453764577d021d0a181efc1f6100ab2e4110039e21ee16970bda7432b6134492155afc126295b3a2eccd12c66a68e340969e995e3e8c9c476e395cfc21203414110779474f1c9797406637dbe414f132519d3bf0ce4f01734ef0e1a12c3ad604ff15d766b1624db6a5a7ccbff7bc35c9908df94aba277e0af48f04ff3d16381c47e5a37ed3988a67a3b1ecaa926336b33391fff04128f869991c9fabd905b6fe3ceef5f8b630ec1c5d2636d5b1961ad5ca5004170f6f5e482792aad989b0287fe91e5c479403397152f1fa56aa79b156eb47e6c8ea3eb175c34cfb38ad8e772874639b1023d4d01395c94e55831671cc022aa6fa1e02a02c2e4abc776f6960e51f83b71a8c0f207b6a347573977812c9aa5480b0011aa739bd4b76c18c000cc4757cceccb920f007c40c00e37e5ab21476cd9f6054a8fffb55a108f5c706e2cea2049d81fd321ff47d2a5761b0800955ab1d4f4889f55a84e2601c684f17a4ade7453ea49591d0b59c8d9a765052f62219cf6ef4a5dd9539f0617d6ebbebce7c000455475d18449e25c49ef9a1e3efe18c09082ebe2058d7c347defaa92f0664553b805c7d76bbfce5f330aca220ac90a789380fc479ea0d8793205813cca590a912f699ad52f991a1bc0a503c3ec4b2a696719e3c26591a87127f7305cc7e72f4c8e39355ebb06a5b1042990f38710ee7aa612ee4374bb82e878585a70a96c2a6b47f101a4ff154be4fd76a3167577a5cc54d9167c154c69ac35485e44cc898b719e1be3cc9c0fb5624b8f8a0dae10947a41bf848b6c1bb33d1006ec077d7e286e3f2a7b4843716390119449fe2721e81a5ed2333d331c7120765da58fadae73c19d9a8c4509cf8ac1e9d98b799a5274509069739b5823f3fb496663820033426988eefca53e580e0f9e0dfe0992fc2e53a97e053639f98577058f995bdbd41cefdba50102032620012158203b8176b7504489cc593046d7988abb7905a742de6ac2cdc748a873c663e90cb12258201436d5edc9a75f23999eef9d5950a5c2455514ee1014084720f841a06b828a11'
인증:
challenge = h'ef1deba56dce48f674a447ccf63b9599258ce87648e5c396f2ef0ca1da460e3b' ; 파생 방법: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'06', info='none.ES256.long-credential-id', L=32) client_data_gen_flags = h'80' ; 파생 방법: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'07', info='none.ES256.long-credential-id', L=1) ; extra_client_data는 client_data_gen_flags의 0x01 비트가 1일 때만 포함됨 ; auth_data_UV_BS는 인증자 데이터 플래그의 UV와 BS 비트를 설정하나, BS는 등록 시 BE가 설정되었을 때만 설정됨 auth_data_UV_BS = h'e5' ; 파생 방법: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'08', info='none.ES256.long-credential-id', L=1) authenticatorData = h'bfabc37432958b063360d3ad6461c9c4735ae7f8edd46592a5e0f01452b2e4b50d00000000' clientDataJSON = h'7b2274797065223a22776562617574686e2e676574222c226368616c6c656e6765223a22377833727057334f53505a307045664d396a75566d53574d36485a4935634f573875384d6f647047446a73222c226f726967696e223a2268747470733a2f2f6578616d706c652e6f7267222c2263726f73734f726967696e223a66616c73657d' signature = h'304502203ecef83fb12a0cae7841055f9f87103a99fd14b424194bbf06c4623d3ee6e3fd022100d2ace346db262b1374a6b70faa51f518a42ddca13a4125ce6f5052a75bac9fb6'
16.1.6. ES256 자격 증명을 사용한 Packed Attestation
등록:
challenge = h'c1184a5fddf8045e13dc47f54b61f5a656b666b59018f16d870e9256e9952012' ; 파생 방법: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'00', info='packed.ES256', L=32) credential_private_key = h'36ed7bea2357cefa8c4ec7e134f3312d2e6ca3058519d0bcb4c1424272010432' ; 파생 방법: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'01', info='packed.ES256', L=32) client_data_gen_flags = h'8d' ; 파생 방법: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'02', info='packed.ES256', L=1) ; extra_client_data는 client_data_gen_flags의 0x01 비트가 1일 때만 포함됨 extra_client_data = h'f5af1b3588ca0a05ab05753e7c29756a' ; 파생 방법: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'03', info='packed.ES256', L=16) aaguid = h'876ca4f52071c3e9b25509ef2cdf7ed6' ; 파생 방법: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'04', info='packed.ES256', L=16) credential_id = h'c9a6f5b3462d02873fea0c56862234f99f081728084e511bb7760201a89054a5' ; 파생 방법: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'05', info='packed.ES256', L=32) ; auth_data_UV_BE_BS는 인증자 데이터 플래그의 UV, BE, BS 비트를 결정하나, BS는 BE일 때만 설정됨 auth_data_UV_BE_BS = h'4f' ; 파생 방법: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'06', info='packed.ES256', L=1) attestation_private_key = h'ec2804b222552b4b277d1f58f8c4343c0b0b0db5474eb55365c89d66a2bc96be' ; 파생 방법: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'07', info='packed.ES256', L=32) attestation_cert_serial_number = h'88c220f83c8ef1feafe94deae45faad0' ; 파생 방법: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'08', info='packed.ES256', L=16) clientDataJSON = h'7b2274797065223a22776562617574686e2e637265617465222c226368616c6c656e6765223a227752684b58393334424634543345663153324831706c61325a725751475046746877365356756d56494249222c226f726967696e223a2268747470733a2f2f6578616d706c652e6f7267222c2263726f73734f726967696e223a66616c73652c22657874726144617461223a22636c69656e74446174614a534f4e206d617920626520657874656e6465642077697468206164646974696f6e616c206669656c647320696e20746865206675747572652c207375636820617320746869733a20396138624e596a4b436757724258552d66436c3161673d3d227d' attestationObject = h'a363666d74667061636b65646761747453746d74a363616c67266373696758473045022025fcee945801b94e63d7c029e6f761654cf02e7100d5364a3b90e03daa6276fc022100eabcdf4ce19feb0980e829c3b6137079b18e42f43ce5c3c573b83368794f354c637835638159022530820221308201c8a00302010202110088c220f83c8ef1feafe94deae45faad0300a06082a8648ce3d0403023062311e301c06035504030c15576562417574686e207465737420766563746f7273310c300a060355040a0c0357334331253023060355040b0c1c41757468656e74696361746f72204174746573746174696f6e204341310b30090603550406130241413020170d3234303130313030303030305a180f33303234303130313030303030305a305f311e301c06035504030c15576562417574686e207465737420766563746f7273310c300a060355040a0c0357334331223020060355040b0c1941757468656e74696361746f72204174746573746174696f6e310b30090603550406130241413059301306072a8648ce3d020106082a8648ce3d03010703420004a91ba4389409dd38a428141940ca8feb1ac0d7b4350558104a3777a49322f3798440f378b3398ab2d3bb7bf91322c92eb23556f59ad0a836fec4c7663b0e4dc3a360305e300c0603551d130101ff04023000300e0603551d0f0101ff040403020780301d0603551d0e04160414a589ba72d060842ab11f74fb246bdedab16f9b9b301f0603551d2304183016801445aff715b0dd786741fee996ebc16547a3931b1e300a06082a8648ce3d040302034700304402201726b9d85ecd8a5ed51163722ca3a20886fd9b242a0aa0453d442116075defd502207ef471e530ac87961a88a7f0d0c17b091ffc6b9238d30f79f635b417be5910e768617574684461746158a4bfabc37432958b063360d3ad6461c9c4735ae7f8edd46592a5e0f01452b2e4b54d00000000876ca4f52071c3e9b25509ef2cdf7ed60020c9a6f5b3462d02873fea0c56862234f99f081728084e511bb7760201a89054a5a50102032620012158201cf27f25da591208a4239c2e324f104f585525479a29edeedd830f48e77aeae522582059e4b7da6c0106e206ce390c93ab98a15a5ec3887e57f0cc2bece803b920c423'
인증:
challenge = h'b1106fa46a57bef1781511c0557dc898a03413d5f0f17d244630c194c7e1adb5' ; 파생 방법: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'09', info='packed.ES256', L=32) client_data_gen_flags = h'75' ; 파생 방법: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'0a', info='packed.ES256', L=1) ; extra_client_data는 client_data_gen_flags의 0x01 비트가 1일 때만 포함됨 extra_client_data = h'019330c8cc486c3f3eba0b85369eabf1' ; 파생 방법: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'0b', info='packed.ES256', L=16) ; auth_data_UV_BS는 인증자 데이터 플래그의 UV와 BS 비트를 설정하나, BS는 등록 시 BE가 설정되었을 때만 설정됨 auth_data_UV_BS = h'46' ; 파생 방법: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'0c', info='packed.ES256', L=1) authenticatorData = h'bfabc37432958b063360d3ad6461c9c4735ae7f8edd46592a5e0f01452b2e4b50d00000000' clientDataJSON = h'7b2274797065223a22776562617574686e2e676574222c226368616c6c656e6765223a2273524276704770587676463446524841565833496d4b4130453958773858306b526a44426c4d6668726255222c226f726967696e223a2268747470733a2f2f6578616d706c652e6f7267222c2263726f73734f726967696e223a66616c73652c22657874726144617461223a22636c69656e74446174614a534f4e206d617920626520657874656e6465642077697468206164646974696f6e616c206669656c647320696e20746865206675747572652c207375636820617320746869733a20415a4d77794d78496244382d756775464e70367238513d3d227d' signature = h'30460221009d8d54895393894d37b9fa7bdfbcff05403de3cf0d6443ffb394fa239f101579022100c8871288f19c6c48a3b64c09d39868c12d16ed80ea4c5d8890288975c0272f50'
16.1.7. ES384 자격 증명을 이용한 Packed Attestation
등록:
challenge = h'567b030b3e186bc1d169dd45b79f9e0d86f1fd63474da3eade5bdb8db379a0c3' ; 파생 방법: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'00', info='packed.ES384', L=32) credential_private_key = h'271e37d309c558c0f35222b37abba7500377d68e179e4c74b0cb558551b2e5276b47b90a317ca8ebbe1a12c93c2d5dd9' ; 파생 방법: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'01', info='packed.ES384', L=48) client_data_gen_flags = h'32' ; 파생 방법: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'02', info='packed.ES384', L=1) ; client_data_gen_flags의 0x01 비트가 1일 때에만 extra_client_data가 포함됩니다 aaguid = h'e950dcda3bdae1d087cda380a897848b' ; 파생 방법: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'03', info='packed.ES384', L=16) credential_id = h'953ae2dd9f28b1a1d5802c83e1f65833bb9769a08de82d812bc27c13fc6f06a9' ; 파생 방법: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'04', info='packed.ES384', L=32) ; auth_data_UV_BE_BS는 인증자 데이터 플래그의 UV, BE, BS 비트를 결정하지만, BS는 BE일 때만 설정됩니다 auth_data_UV_BE_BS = h'db' ; 파생 방법: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'05', info='packed.ES384', L=1) attestation_private_key = h'8d979fbb6e49c4eeb5925a2bca0fcdb023d3fb90bcadce8391da9da4ed2aee9a' ; 파생 방법: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'06', info='packed.ES384', L=32) attestation_cert_serial_number = h'3d0a5588bb87ebb1d4cee4a1807c1b7c' ; 파생 방법: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'07', info='packed.ES384', L=16) clientDataJSON = h'7b2274797065223a22776562617574686e2e637265617465222c226368616c6c656e6765223a22566e7344437a3459613848526164314674352d65445962785f574e4854615071336c76626a624e356f4d4d222c226f726967696e223a2268747470733a2f2f6578616d706c652e6f7267222c2263726f73734f726967696e223a66616c73657d' attestationObject = h'a363666d74667061636b65646761747453746d74a363616c67266373696758473045022100c56ecc970b7843833e0f461fde26233f61eb395161d481558c08b9c6ed61675b022029f5e05033705cd0f9b0a07e149468ec308a4f84906409efdceb1da20a7518d6637835638159022530820221308201c7a00302010202103d0a5588bb87ebb1d4cee4a1807c1b7c300a06082a8648ce3d0403023062311e301c06035504030c15576562417574686e207465737420766563746f7273310c300a060355040a0c0357334331253023060355040b0c1c41757468656e74696361746f72204174746573746174696f6e204341310b30090603550406130241413020170d3234303130313030303030305a180f33303234303130313030303030305a305f311e301c06035504030c15576562417574686e207465737420766563746f7273310c300a060355040a0c0357334331223020060355040b0c1941757468656e74696361746f72204174746573746174696f6e310b30090603550406130241413059301306072a8648ce3d020106082a8648ce3d0301070342000417e5cc91d676d370e36aa7de40c25aacb45a3845f13d2932088ece2270b9b431241c219c22d0c256c9438ade00f2c05e62f8ef906b9b997ae9f3c460c2db66f5a360305e300c0603551d130101ff04023000300e0603551d0f0101ff040403020780301d0603551d0e04160414c7c8dd95382a2230e4c0dd3664338fa908169a9c301f0603551d2304183016801445aff715b0dd786741fee996ebc16547a3931b1e300a06082a8648ce3d0403020348003045022054068cc9ae038937b7c468c307edb9c6927ffdeb6a20070c483eb40330f99f10022100cf41953919c3c04693d6b1f42a613753f204e70e85fc6e9b17036170b83596e068617574684461746158c5bfabc37432958b063360d3ad6461c9c4735ae7f8edd46592a5e0f01452b2e4b55900000000e950dcda3bdae1d087cda380a897848b0020953ae2dd9f28b1a1d5802c83e1f65833bb9769a08de82d812bc27c13fc6f06a9a5010203382220022158304866bd8b01da789e9eb806e5eab05ae5a638542296ab057a2f1bbce9b58f8a08b9171390b58a37ac7fffc2c5f45857da2258302a0b024c7f4b72072a1f96bd30a7261aae9571dd39870eb29e55c0941c6b08e89629a1ea1216aa64ce57c2807bf3901a'
인증:
challenge = h'ff41c3d25dbd8966fb61e28ef5e47041e137ed268520412d76202ba0ad2d1453' ; 파생 방법: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'08', info='packed.ES384', L=32) client_data_gen_flags = h'0c' ; 파생 방법: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'09', info='packed.ES384', L=1) ; client_data_gen_flags의 0x01 비트가 1일 때에만 extra_client_data가 포함됩니다 ; auth_data_UV_BS는 인증자 데이터 플래그의 UV, BS 비트를 설정하지만, BS는 등록 때 BE가 설정된 경우에만 적용됩니다 auth_data_UV_BS = h'af' ; 파생 방법: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'0a', info='packed.ES384', L=1) authenticatorData = h'bfabc37432958b063360d3ad6461c9c4735ae7f8edd46592a5e0f01452b2e4b50d00000000' clientDataJSON = h'7b2274797065223a22776562617574686e2e676574222c226368616c6c656e6765223a225f304844306c32396957623759654b4f39655277516545333753614649454574646941726f4b307446464d222c226f726967696e223a2268747470733a2f2f6578616d706c652e6f7267222c2263726f73734f726967696e223a66616c73657d' signature = h'3065023100e4efbb46745ed00e67c4d51ab2bacab2af62ffa8b7c5fecec6d7d9bf2582275034a713a3dd731685eee81adfaf6aa63f0230161655353f07e018a3c2539f8de7c8c4cf88d4c32d2be29fe4e76fa096ecc9458bbfe0895d57129ab324130e6f0692db'
16.1.8. ES512 자격 증명을 이용한 Packed Attestation
등록:
challenge = h'4ee220cd92b07e11451cb4c201c5755bd879848e492a9b12d79135c62764dc2fd28ead4808cafe5ad1de8fa9e08d4a8eeafea4dfb333877b02bc503f475d3b0c1394a7683baaf4f2477829f7b8cf750948985558748c073068396fcfdcd3f245bf2038e6bb38d7532768aad13be8c118f727722e7426139041e9caca503884c5' ; 파생 방법: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'00', info='packed.ES512', L=128) credential_private_key = h'f11120594f6a4944ac3ba59adbbc5b85016895b649f4cc949a610f4b48be47b318850bacb105f747647bba8852b6b8e52a0b3679f1bbbdfe18c99409bcb644fa45' ; 파생 방법: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'01', info='packed.ES512', L=65) client_data_gen_flags = h'6d' ; 파생 방법: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'02', info='packed.ES512', L=1) ; client_data_gen_flags의 0x01 비트가 1일 때에만 extra_client_data가 포함됩니다 extra_client_data = h'a37a958ce2f6b535a6e06c64cc8fd082' ; 파생 방법: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'03', info='packed.ES512', L=16) aaguid = h'39d8ce6a3cf61025775083a738e5c254' ; 파생 방법: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'04', info='packed.ES512', L=16) credential_id = h'd17d5af7e3f37c56622a67c8462c9e1c6336dfccb8b61d359dc47378dba58ce4' ; 파생 방법: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'05', info='packed.ES512', L=32) ; auth_data_UV_BE_BS는 인증자 데이터 플래그의 UV, BE, BS 비트를 결정하지만, BS는 BE일 때만 설정됩니다 auth_data_UV_BE_BS = h'cf' ; 파생 방법: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'06', info='packed.ES512', L=1) attestation_private_key = h'ffbc89d5f75994f52dc5e7538ee269402d26995d40c16fb713473e34fca98be4' ; 파생 방법: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'07', info='packed.ES512', L=32) attestation_cert_serial_number = h'8a128b7ebe52b993835779e6d9b81355' ; 파생 방법: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'08', info='packed.ES512', L=16) clientDataJSON = h'7b2274797065223a22776562617574686e2e637265617465222c226368616c6c656e6765223a22547549677a5a4b7766684646484c544341635631573968356849354a4b707353313545317869646b33435f536a713149434d722d577448656a366e676a55714f3676366b33374d7a683373437646415f5231303744424f5570326737717654795233677039376a5064516c496d465659644977484d47673562385f63305f4a46767941343572733431314d6e614b72524f2d6a424750636e636935304a684f5151656e4b796c4134684d55222c226f726967696e223a2268747470733a2f2f6578616d706c652e6f7267222c2263726f73734f726967696e223a66616c73652c22657874726144617461223a22636c69656e74446174614a534f4e206d617920626520657874656e6465642077697468206164646974696f6e616c206669656c647320696e20746865206675747572652c207375636820617320746869733a206f3371566a4f4c327454576d3447786b7a495f5167673d3d227d' attestationObject = h'a363666d74667061636b65646761747453746d74a363616c67266373696758483046022100c48fcbd826bbc79680802026688d41ab6da8c3a1d22ab6cecf36c8d7695d22500221008767dfe591277e973078d5692c8c35cf9d579792822e7145c96a0ac4515df5b0637835638159022730820223308201c8a0030201020211008a128b7ebe52b993835779e6d9b81355300a06082a8648ce3d0403023062311e301c06035504030c15576562417574686e207465737420766563746f7273310c300a060355040a0c0357334331253023060355040b0c1c41757468656e74696361746f72204174746573746174696f6e204341310b30090603550406130241413020170d3234303130313030303030305a180f33303234303130313030303030305a305f311e301c06035504030c15576562417574686e207465737420766563746f7273310c300a060355040a0c0357334331223020060355040b0c1941757468656e74696361746f72204174746573746174696f6e310b30090603550406130241413059301306072a8648ce3d020106082a8648ce3d03010703420004940b68885291536e2f7c60c05acfb252e7eebcf4304425dd93ab7b1962f20492bf18dc0f12862599e81fb764ac92151f9a78fcbb35d7a26c8c52949b18133c06a360305e300c0603551d130101ff04023000300e0603551d0f0101ff040403020780301d0603551d0e041604143ffad863abcd3dc5717b8a252189f41af97e7f31301f0603551d2304183016801445aff715b0dd786741fee996ebc16547a3931b1e300a06082a8648ce3d0403020349003046022100832c8b64c4f0188bd32e1bec63e13301cdc03165d3ef840d1f3dabb9a5719f83022100add57a9d5bedec98f29222dfc97ea795d055ee13a02a153d02be9ce00aedeb9168617574684461746158e9bfabc37432958b063360d3ad6461c9c4735ae7f8edd46592a5e0f01452b2e4b54d0000000039d8ce6a3cf61025775083a738e5c2540020d17d5af7e3f37c56622a67c8462c9e1c6336dfccb8b61d359dc47378dba58ce4a5010203382320032158420083240a2c3ad21a3dc0a6daa3d8bc05a46d7cd9825ba010ae2a22686c2d6d663d7d5f678987fb1e767542e63dc197ae915e25f8ee284651af29066910a2cc083f50225842017337df47ab5cce5d716ef8caffa97a3012689b1f326ea6c43a1ba9596c72f71f0122390143552b42be772b4c35ffb961220c743b486a601ea4cb6d5412f5b078d3'
인증:
challenge = h'08d3190c6dcb3d4f0cb659a0333bf5ea124ddf36a0cd33d5204b0d7a22a8cc26f2e4f169d200285c77b3fb22e0f1c7f49a87d4be2d25e92d797808ddaaa9b5715efd3a6ada9339d3052a687dbc5d2f8c871b0451e0691f57ad138541b7b72e7aa8933729ec1c664bf2e4dedae1616d08ecefa80a2a53b103663ce5a881048829' ; 파생 방법: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'09', info='packed.ES512', L=128) client_data_gen_flags = h'ac' ; 파생 방법: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'0a', info='packed.ES512', L=1) ; client_data_gen_flags의 0x01 비트가 1일 때에만 extra_client_data가 포함됩니다 ; auth_data_UV_BS는 인증자 데이터 플래그의 UV, BS 비트를 설정하지만, BS는 등록 때 BE가 설정된 경우에만 적용됩니다 auth_data_UV_BS = h'52' ; 파생 방법: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'0b', info='packed.ES512', L=1) authenticatorData = h'bfabc37432958b063360d3ad6461c9c4735ae7f8edd46592a5e0f01452b2e4b51900000000' clientDataJSON = h'7b2274797065223a22776562617574686e2e676574222c226368616c6c656e6765223a22434e4d5a4447334c5055384d746c6d674d7a763136684a4e337a61677a5450564945734e65694b6f7a436279355046703067416f5848657a2d794c67386366306d6f66557669306c3653313565416a6471716d31635637394f6d72616b7a6e544253706f666278644c3479484777525234476b66563630546855473374793536714a4d334b6577635a6b7679354e376134574674434f7a7671416f71553745445a6a7a6c7149454569436b222c226f726967696e223a2268747470733a2f2f6578616d706c652e6f7267222c2263726f73734f726967696e223a66616c73657d' signature = h'3081870242009bda02fe384e77bcb9fb42b07c395b7a53ec9d9616dd0308ab8495c2141c8364c7d16e212a4a4fb8e3987ff6c99eafd64d8484fd28c3fc7968f658a9033d1bb1b802416383e9f3ee20c691b66620299fef36bea2df4d39c92b2ead92f58e7b79ab0d9864d2ebf3b0dcc66ea13234492ccee6e9d421db43c959bcb94c162dc9494136c9f6'
16.1.9. RS256 자격 증명을 이용한 Packed Attestation
등록:
challenge = h'bea8f0770009bd57f2c0df6fea9f743a27e4b61bbe923c862c7aad7a9fc8e4a6' ; 파생 방법: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'00', info='packed.RS256', L=32) ; 가장 작은 두 메르센 소수 2^p - 1 (p >= 1024) private_key_p = 2 ^ 1279 -1 = h'7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff' private_key_q = 2 ^ 2203 -1 = h'07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff' client_data_gen_flags = h'1c' ; 파생 방법: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'01', info='packed.RS256', L=1) ; client_data_gen_flags의 0x01 비트가 1일 때에만 extra_client_data가 포함됩니다 aaguid = h'428f8878298b9862a36ad8c7527bfef2' ; 파생 방법: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'02', info='packed.RS256', L=16) credential_id = h'992a18acc83f67533600c1138a4b4c4bd236de13629cf025ed17cb00b00b74df' ; 파생 방법: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'03', info='packed.RS256', L=32) ; auth_data_UV_BE_BS는 인증자 데이터 플래그의 UV, BE, BS 비트를 결정하지만, BS는 BE일 때만 설정됩니다 auth_data_UV_BE_BS = h'7e' ; 파생 방법: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'04', info='packed.RS256', L=1) attestation_private_key = h'08a1322d5aa5b5b40cd67c2cc30b038e7921d7888c84c342d50d79f0c5fc3464' ; 파생 방법: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'05', info='packed.RS256', L=32) attestation_cert_serial_number = h'1f6fb7a5ece81b45896b983a995da5f3' ; 파생 방법: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'06', info='packed.RS256', L=16) clientDataJSON = h'7b2274797065223a22776562617574686e2e637265617465222c226368616c6c656e6765223a2276716a776477414a76566679774e3976367039304f69666b7468752d6b6a79474c48717465705f49354b59222c226f726967696e223a2268747470733a2f2f6578616d706c652e6f7267222c2263726f73734f726967696e223a66616c73657d' attestationObject = h'a363666d74667061636b65646761747453746d74a363616c672663736967584730450221008b8c5c6ea8c142c032e0be69e1353d44461c5c9109941cdda951b976eb95b6b302204d52f406c19e254b3ff9589bd18070fb055ac8db12fdd0a6734bea9d7168e900637835638159022630820222308201c7a00302010202101f6fb7a5ece81b45896b983a995da5f3300a06082a8648ce3d0403023062311e301c06035504030c15576562417574686e207465737420766563746f7273310c300a060355040a0c0357334331253023060355040b0c1c41757468656e74696361746f72204174746573746174696f6e204341310b30090603550406130241413020170d3234303130313030303030305a180f33303234303130313030303030305a305f311e301c06035504030c15576562417574686e207465737420766563746f7273310c300a060355040a0c0357334331223020060355040b0c1941757468656e74696361746f72204174746573746174696f6e310b30090603550406130241413059301306072a8648ce3d020106082a8648ce3d03010703420004b7b36b7542a11120b443c794d0c99fdc25a06b76586413d81e086163ef6fe147a557afc34e2861d9057d6d465d4705a0310550bdeeb5f35ee35b9425ab859981a360305e300c0603551d130101ff04023000300e0603551d0f0101ff040403020780301d0603551d0e04160414fb37b647bccfb9e54d989eaaacc1633868703fb3301f0603551d2304183016801445aff715b0dd786741fee996ebc16547a3931b1e300a06082a8648ce3d0403020349003046022100b86bc129d92afca7d9869a39f70f139a305b4073a39eb654d81424bed5757d91022100cf9f7c60cab7c4a7d3e7f0020f281a93d4fd0a9f95121b989f56932a68885fba68617574684461746159021bbfabc37432958b063360d3ad6461c9c4735ae7f8edd46592a5e0f01452b2e4b55d00000000428f8878298b9862a36ad8c7527bfef20020992a18acc83f67533600c1138a4b4c4bd236de13629cf025ed17cb00b00b74dfa4010303390100205901b403fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012143010001'
인증:
challenge = h'295f59f5fa8fe62c5aca9e27626c78c8da376ae6d8cd2dd29aebad601e1bc4c5' ; 파생 방법: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'07', info='packed.RS256', L=32) client_data_gen_flags = h'0e' ; 파생 방법: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'08', info='packed.RS256', L=1) ; client_data_gen_flags의 0x01 비트가 1일 때에만 extra_client_data가 포함됩니다 ; auth_data_UV_BS는 인증자 데이터 플래그의 UV, BS 비트를 설정하지만, BS는 등록 때 BE가 설정된 경우에만 적용됩니다 auth_data_UV_BS = h'ba' ; 파생 방법: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'09', info='packed.RS256', L=1) authenticatorData = h'bfabc37432958b063360d3ad6461c9c4735ae7f8edd46592a5e0f01452b2e4b51900000000' clientDataJSON = h'7b2274797065223a22776562617574686e2e676574222c226368616c6c656e6765223a224b56395a39667150356978617970346e596d7834794e6f33617562597a5333536d75757459423462784d55222c226f726967696e223a2268747470733a2f2f6578616d706c652e6f7267222c2263726f73734f726967696e223a66616c73657d' signature = h'01063d52d7c39b4d432fc7063c5d93e582bdcb16889cd71f888d67d880ea730a428498d3bc8e1ee11f2b1ecbe6c292b118c55ffaaddefa8cad0a54dd137c51f1eec673f1bb6c4d1789d6826a222b22d0f585fc901fdc933212e579d199b89d672aa44891333e6a1355536025e82b25590256c3538229b55737083b2f6b9377e49e2472f11952f79fdd0da180b5ffd901b4049a8f081bb40711bef76c62aed943571f2d0575304cb549d68d8892f95086a30f93716aee818f8dc06e96c0d5e0ed4cfa9fd8773d90464b68cf140f7986666ff9c9e3302acd0535d60d769f465e2ab57ef8aabc89fccfef7ba32a64154a8b3d26be2298f470b8cc5377dbe3dfd4b0b45f8f01e63bde6cfc76b62771f9b70aa27cf40152cad93aa5acd784fd4b90f676e2ea828d0bf2400aebbaae4153e5838f537f88b6228346782a93a899be66ec77de45b3efcf311da6321c92e6b0cd11bfe653bf3e98cee8e341f02d67dbb6f9c98d9e8178090cfb5b70fbc6d541599ac794ae2f1d4de1286ec8de8c2daf7b1d15c8438e90d924df5c19045220a4c8438c1b979bbe016cf3d0eeec23c3999d4882cc645b776de930756612cdc6dd398160ff02a6'
16.1.10. Ed25519 자격 증명을 사용한 Packed 증명
등록:
challenge = h'560c73a09ce7a1586d61c1d6e41fef149be523e220fc9f385d38ab23702ebf1b' ; 파생됨: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'00', info='packed.Ed25519', L=32) private_key = h'c87fce9e9cd283d272a2418d9683366f83661e458ad4451f0f1c95cb83b0f0a8' ; 파생됨: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'01', info='packed.Ed25519', L=32) client_data_gen_flags = h'41' ; 파생됨: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'02', info='packed.Ed25519', L=1) ; client_data_gen_flags의 0x01 비트가 1이면 extra_client_data가 포함됩니다 extra_client_data = h'db7587e24b9187edb77933754331e443' ; 파생됨: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'03', info='packed.Ed25519', L=16) aaguid = h'164009ea09faae7c397bc3e2ad0e7ec0' ; 파생됨: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'04', info='packed.Ed25519', L=16) credential_id = h'c6cffa01b7fda368a7e0b29c1384a719820246bca894dd12914708743af0cecd' ; 파생됨: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'05', info='packed.Ed25519', L=32) ; auth_data_UV_BE_BS는 인증기 데이터 플래그의 UV, BE 및 BS 비트를 결정하지만 BS는 BE가 설정된 경우에만 설정됩니다 auth_data_UV_BE_BS = h'e8' ; 파생됨: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'06', info='packed.Ed25519', L=1) attestation_private_key = h'673ee7fd94405de523fd84a088ab082d75b7fceef02a301e2bca0a28537cf243' ; 파생됨: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'07', info='packed.Ed25519', L=32) attestation_cert_serial_number = h'6e391f23f57150dc7a12dad18f2b43ad' ; 파생됨: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'08', info='packed.Ed25519', L=16) clientDataJSON = h'7b2274797065223a22776562617574686e2e637265617465222c226368616c6c656e6765223a225667787a6f4a7a6e6f5668745963485735425f76464a766c492d49675f4a38345854697249334175767873222c226f726967696e223a2268747470733a2f2f6578616d706c652e6f7267222c2263726f73734f726967696e223a66616c73652c22657874726144617461223a22636c69656e74446174614a534f4e206d617920626520657874656e6465642077697468206164646974696f6e616c206669656c647320696e20746865206675747572652c207375636820617320746869733a2032335748346b7552682d323365544e31517a486b51773d3d227d' attestationObject = h'a363666d74667061636b65646761747453746d74a363616c672663736967584730450220730a54d4f76cb1f2b7dd4a5a6eee3374e3c8a60fb3c4daa527c9277e365b64aa0221008b31a04a28cc4148b14c42a916548ee7f430bc7629295b42ee93e5d1aaba8ee6637835638159022530820221308201c7a00302010202106e391f23f57150dc7a12dad18f2b43ad300a06082a8648ce3d0403023062311e301c06035504030c15576562417574686e207465737420766563746f7273310c300a060355040a0c0357334331253023060355040b0c1c41757468656e74696361746f72204174746573746174696f6e204341310b30090603550406130241413020170d3234303130313030303030305a180f33303234303130313030303030305a305f311e301c06035504030c15576562417574686e207465737420766563746f7273310c300a060355040a0c0357334331223020060355040b0c1941757468656e74696361746f72204174746573746174696f6e310b30090603550406130241413059301306072a8648ce3d020106082a8648ce3d03010703420004fb96a581a0b36742a8c45d6ffb5af1ef155524b50339445ec1109874045e0087db77edef91f3dc949927470d84b01627087b72c86b7c9d02e1389cba680ffc36a360305e300c0603551d130101ff04023000300e0603551d0f0101ff040403020780301d0603551d0e04160414ef2ce1a86caba85121130a16e8ce82a75d5a6653301f0603551d2304183016801445aff715b0dd786741fee996ebc16547a3931b1e300a06082a8648ce3d0403020348003045022100ad4fa628cffba5a642a562cbfefe63efecce26d90c80114114d1745383e12f01022028af87ba3b0ff868a34b9458bc6973b27380a328dd87b7436651ffa823280bca6861757468446174615881bfabc37432958b063360d3ad6461c9c4735ae7f8edd46592a5e0f01452b2e4b54900000000164009ea09faae7c397bc3e2ad0e7ec00020c6cffa01b7fda368a7e0b29c1384a719820246bca894dd12914708743af0cecda401010327200621582089f81eba4a1f510cb243ff7fb9e9cf899bf627e49ce1ac3c3eae8adb2a8d7d7b'
인증:
challenge = h'3790da8b2b72ee8ce19761787ad38cbfaa697eb3ca013a1342988756b98785ab' ; 파생됨: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'09', info='packed.Ed25519', L=32) client_data_gen_flags = h'de' ; 파생됨: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'0a', info='packed.Ed25519', L=1) ; client_data_gen_flags의 0x01 비트가 1이면 extra_client_data가 포함됩니다 ; auth_data_UV_BS는 인증기 데이터 플래그의 UV 및 BS 비트를 설정하지만, BS는 등록 시 BE가 설정된 경우에만 설정됩니다 auth_data_UV_BS = h'18' ; 파생됨: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'0b', info='packed.Ed25519', L=1) authenticatorData = h'bfabc37432958b063360d3ad6461c9c4735ae7f8edd46592a5e0f01452b2e4b51900000000' clientDataJSON = h'7b2274797065223a22776562617574686e2e676574222c226368616c6c656e6765223a224e35446169797479376f7a686c32463465744f4d763670706672504b41546f545170694856726d48686173222c226f726967696e223a2268747470733a2f2f6578616d706c652e6f7267222c2263726f73734f726967696e223a66616c73657d' signature = h'4c873571377ac019f257d6bf07249f63ac2487483c51bc511ce0f0e3266c840cb07a09cdc445a2f963d8603a9f0f6cf9ce709d7fc6a96c7c51ea08d33776010c'
16.1.11. ES256 자격 증명을 사용한 TPM 증명
등록:
challenge = h'cfc82cdf1ceee876120aa88f0364f0910193460cfb97a317b2fe090694f9a299' ; 파생됨: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'00', info='tpm.ES256', L=32) credential_private_key = h'80c60805e564f6d33e7abdff9d32e3db09a6219fe378a268d23107191b18e39f' ; 파생됨: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'01', info='tpm.ES256', L=32) client_data_gen_flags = h'84' ; 파생됨: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'02', info='tpm.ES256', L=1) ; client_data_gen_flags의 0x01 비트가 1이면 extra_client_data가 포함됩니다 aaguid = h'4b92a377fc5f6107c4c85c190adbfd99' ; 파생됨: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'03', info='tpm.ES256', L=16) credential_id = h'ec27bec7521c894bbb821105ea3724c90e770cf1fa354157ef18d0f18f78bea9' ; 파생됨: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'04', info='tpm.ES256', L=32) ; auth_data_UV_BE_BS는 인증기 데이터 플래그의 UV, BE 및 BS 비트를 결정하지만 BS는 BE가 설정된 경우에만 설정됩니다 auth_data_UV_BE_BS = h'af' ; 파생됨: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'05', info='tpm.ES256', L=1) attestation_private_key = h'6210f09e0ce7593e851a880a4bdde2d2192afeac46104abce1a890a5a71cf0c6' ; 파생됨: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'06', info='tpm.ES256', L=32) attestation_cert_serial_number = h'311fc42da0ab10c43a9b1bf3a75e34e2' ; 파생됨: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'07', info='tpm.ES256', L=16) clientDataJSON = h'7b2274797065223a22776562617574686e2e637265617465222c226368616c6c656e6765223a227a38677333787a753648595343716950413254776b51475452677a376c364d587376344a427054356f706b222c226f726967696e223a2268747470733a2f2f6578616d706c652e6f7267222c2263726f73734f726967696e223a66616c73657d' attestationObject = h'a363666d746374706d6761747453746d74a663616c67266373696758463044022066e5826a652091030fd444e33c3eca2bc6dc548cf3045013addb38aa6457a21002203f3a5c95c9e707d0e555041bcc8698ee4ebc04e26cc8bae459705471789851766376657263322e30637835638159023a30820236308201dca0030201020210311fc42da0ab10c43a9b1bf3a75e34e2300a06082a8648ce3d0403023062311e301c06035504030c15576562417574686e207465737420766563746f7273310c300a060355040a0c0357334331253023060355040b0c1c41757468656e74696361746f72204174746573746174696f6e204341310b30090603550406130241413020170d3234303130313030303030305a180f33303234303130313030303030305a30003059301306072a8648ce3d020106082a8648ce3d03010703420004c54e3f109094f60d7699b7db5d838569ffd1f3e1c9e897cd9eb40063f9402e3e9937e936cf1fcd5eb743ff443c97ab2edcd7c8e0e6cf6cfd413b8ab19fffa769a381d33081d0300c0603551d130101ff04023000300e0603551d0f0101ff040403020780301d0603551d0e041604145f546cb6973d4981e80fcdc7463859f5879680e4301f0603551d2304183016801445aff715b0dd786741fee996ebc16547a3931b1e30100603551d250409300706056781050803305e0603551d110101ff04543052a450304e314c3014060567810502010c0b69643a30303030303030303014060567810502030c0b69643a3030303030303030301e060567810502020c15576562417574686e207465737420766563746f7273300a06082a8648ce3d0403020348003045022063c9a2797b8066f1db34dd609f1ab6695607e7a98e9ff8090a68853c9a9fc949022100a55831a39f5b8a2aa9a68837829cabf43fea2a5cea4859ae851cac78e6ac3e97677075624172656158560023000b0004000000000010001000030010002041202698c9d9753fb4bb3f27cd09fe6b8afdb76438ee2ae54d7c9dade10d864b0020d8735115cdb330a63ea1d6e43d5000f4bd56f99bce83ee1d73301fc270116d076863657274496e666f5869ff544347801700000020277d0e05579dd013215a62273f7f3a3e7e191ead2654a3036d75a5a3ee37a6b0000000000000000011111111222222223300000000000000000022000b9c42d8aad5939331b9af3711af179f17123178098c9a7d0ca89fcd1fc800f3c7000068617574684461746158a4bfabc37432958b063360d3ad6461c9c4735ae7f8edd46592a5e0f01452b2e4b54d000000004b92a377fc5f6107c4c85c190adbfd990020ec27bec7521c894bbb821105ea3724c90e770cf1fa354157ef18d0f18f78bea9a501020326200121582041202698c9d9753fb4bb3f27cd09fe6b8afdb76438ee2ae54d7c9dade10d864b225820d8735115cdb330a63ea1d6e43d5000f4bd56f99bce83ee1d73301fc270116d07'
인증:
challenge = h'00093b66c21d5b5e89f7a07082118907ea3e502d343b314b8c5a54d62db202fb' ; 파생됨: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'08', info='tpm.ES256', L=32) client_data_gen_flags = h'86' ; 파생됨: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'09', info='tpm.ES256', L=1) ; client_data_gen_flags의 0x01 비트가 1이면 extra_client_data가 포함됩니다 ; auth_data_UV_BS는 인증기 데이터 플래그의 UV와 BS 비트를 설정하지만, BS는 등록 시 BE가 설정된 경우에만 설정됩니다 auth_data_UV_BS = h'87' ; 파생됨: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'0a', info='tpm.ES256', L=1) authenticatorData = h'bfabc37432958b063360d3ad6461c9c4735ae7f8edd46592a5e0f01452b2e4b50d00000000' clientDataJSON = h'7b2274797065223a22776562617574686e2e676574222c226368616c6c656e6765223a2241416b375a7349645731364a393642776768474a422d6f2d554330304f7a464c6a46705531693279417673222c226f726967696e223a2268747470733a2f2f6578616d706c652e6f7267222c2263726f73734f726967696e223a66616c73657d' signature = h'3045022060dc76b1607ec716c6e5eba8d056695ed6bc47b2e3d7a729c34e759e3ab66aa0022100d010a9e8fddcb64c439dfdca628ddb33cf245d567d157d9f66f942601bed9b38'
16.1.12. ES256 자격 증명을 사용한 Android Key 증명
등록:
challenge = h'3de1f0b7365dccde3ff0cbf25e26ffa7baff87ef106c80fc865dc402d9960050' ; 파생됨: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'00', info='android-key.ES256', L=32) credential_private_key = h'd4328d911acb0ebcc42aad29b29ffb55d5bc31d8af7ca9a16703d56c21abc7b4' ; 파생됨: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'01', info='android-key.ES256', L=32) client_data_gen_flags = h'73' ; 파생됨: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'02', info='android-key.ES256', L=1) ; client_data_gen_flags의 0x01 비트가 1이면 extra_client_data가 포함됩니다 extra_client_data = h'555d5c42e476a8b33f6a63dfa07ccbd2' ; 파생됨: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'03', info='android-key.ES256', L=16) aaguid = h'ade9705e1ce7085b899a540d02199bf8' ; 파생됨: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'04', info='android-key.ES256', L=16) credential_id = h'0a4729519788b6ed8a2d772b494e186244d8c798c052960dbc8c10c915176795' ; 파생됨: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'05', info='android-key.ES256', L=32) ; auth_data_UV_BE_BS는 인증기 데이터 플래그의 UV, BE 및 BS 비트를 결정하지만 BS는 BE가 설정된 경우에만 설정됩니다 auth_data_UV_BE_BS = h'1e' ; 파생됨: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'06', info='android-key.ES256', L=1) attestation_cert_serial_number = h'1ff91f76b63f44812f998b250b0286bf' ; 파생됨: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'07', info='android-key.ES256', L=16) clientDataJSON = h'7b2274797065223a22776562617574686e2e637265617465222c226368616c6c656e6765223a2250654877747a5a647a4e345f384d76795869625f7037725f682d385162494438686c334541746d57414641222c226f726967696e223a2268747470733a2f2f6578616d706c652e6f7267222c2263726f73734f726967696e223a66616c73652c22657874726144617461223a22636c69656e74446174614a534f4e206d617920626520657874656e6465642077697468206164646974696f6e616c206669656c647320696e20746865206675747572652c207375636820617320746869733a205656316351755232714c4d5f616d50666f487a4c30673d3d227d' attestationObject = h'a363666d746b616e64726f69642d6b65796761747453746d74a363616c672663736967584630440220592bbc3c4c5f6158b52be1e085c92848986d7844245dfc9512e1a7e9ff7a2cd8022015bdd0852d3bd091e1c22da4211f4ccf0fdf4d912599d1c6630b1f310d3166f5637835638159026d3082026930820210a00302010202101ff91f76b63f44812f998b250b0286bf300a06082a8648ce3d0403023062311e301c06035504030c15576562417574686e207465737420766563746f7273310c300a060355040a0c0357334331253023060355040b0c1c41757468656e74696361746f72204174746573746174696f6e204341310b30090603550406130241413020170d3234303130313030303030305a180f33303234303130313030303030305a305f311e301c06035504030c15576562417574686e207465737420766563746f7273310c300a060355040a0c0357334331223020060355040b0c1941757468656e74696361746f72204174746573746174696f6e310b30090603550406130241413059301306072a8648ce3d020106082a8648ce3d0301070342000499169657036d089a2a9821a7d0063d341f1a4613389359636efab5f3cbf1accfdd91c55543176ea99b644406dd1dd63774b6af65ac759e06ff40b1c8ab02df6ba381a83081a5300c0603551d130101ff04023000300e0603551d0f0101ff040403020780301d0603551d0e041604141ac81e50641e8d1339ab9f7eb25f0cd5aac054b0301f0603551d2304183016801445aff715b0dd786741fee996ebc16547a3931b1e3045060a2b06010401d679020111043730350202012c0201000201000201000420b20e943e3a7544b3a438943b6d5655313a47ef1af34e00ff3261aeb9ed155817040030003000300a06082a8648ce3d040302034700304402206f4609c9ffc946c418cef04c64a0d07bcce78f329b99270b822f2a4d1e3b75330220093c8d18328f36ef157f296393bdc7721dd2bd67438ffeaa42f051a044b7457168617574684461746158a4bfabc37432958b063360d3ad6461c9c4735ae7f8edd46592a5e0f01452b2e4b55d00000000ade9705e1ce7085b899a540d02199bf800200a4729519788b6ed8a2d772b494e186244d8c798c052960dbc8c10c915176795a501020326200121582099169657036d089a2a9821a7d0063d341f1a4613389359636efab5f3cbf1accf225820dd91c55543176ea99b644406dd1dd63774b6af65ac759e06ff40b1c8ab02df6b'
인증:
challenge = h'e4ee05ca9dbced74116540f24ed9adc62aae8507560522844ffa7eea14f7af86' ; 파생됨: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'08', info='android-key.ES256', L=32) client_data_gen_flags = h'43' ; 파생됨: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'09', info='android-key.ES256', L=1) ; client_data_gen_flags의 0x01 비트가 1이면 extra_client_data가 포함됩니다 extra_client_data = h'ab127107eff182bc3230beb5f1dad29c' ; 파생됨: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'0a', info='android-key.ES256', L=16) ; auth_data_UV_BS는 인증기 데이터 플래그의 UV와 BS 비트를 설정하지만, BS는 등록 시 BE가 설정된 경우에만 설정됩니다 auth_data_UV_BS = h'4a' ; 파생됨: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'0b', info='android-key.ES256', L=1) authenticatorData = h'bfabc37432958b063360d3ad6461c9c4735ae7f8edd46592a5e0f01452b2e4b50900000000' clientDataJSON = h'7b2274797065223a22776562617574686e2e676574222c226368616c6c656e6765223a22354f344679703238375851525a55447954746d74786971756851645742534b45545f702d36685433723459222c226f726967696e223a2268747470733a2f2f6578616d706c652e6f7267222c2263726f73734f726967696e223a66616c73652c22657874726144617461223a22636c69656e74446174614a534f4e206d617920626520657874656e6465642077697468206164646974696f6e616c206669656c647320696e20746865206675747572652c207375636820617320746869733a2071784a78422d5f78677277794d4c3631386472536e413d3d227d' signature = h'304502202060107d953b286aa1bf35e3e8c78b383fddab5591b2db17ffb23ed83fe7df20022100a99be0297cb0d9d38aa96f30b760a4e0749dab385acd2a51d0560caae570d225'
16.1.13. ES256 자격 증명을 사용한 Apple 익명 증명
등록:
challenge = h'f7f688213852007775009cf8c096fda89d60b9a9fb5a50dd81dd9898af5a0609' ; 파생됨: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'00', info='apple.ES256', L=32) credential_private_key = h'de987bd9d43eeb44728ce0b14df11209dff931fb56b5b1948de4c0da1144ded0' ; 파생됨: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'01', info='apple.ES256', L=32) client_data_gen_flags = h'5f' ; 파생됨: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'02', info='apple.ES256', L=1) ; client_data_gen_flags의 0x01 비트가 1이면 extra_client_data가 포함됩니다 extra_client_data = h'4e32cf9e939a5d052b14d71b1f6b5364' ; 파생됨: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'03', info='apple.ES256', L=16) aaguid = h'748210a20076616a733b2114336fc384' ; 파생됨: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'04', info='apple.ES256', L=16) credential_id = h'9c4a5886af9283d9be3e9ec55978dedfdce2e3b365cab193ae850c16238fafb8' ; 파생됨: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'05', info='apple.ES256', L=32) ; auth_data_UV_BE_BS는 인증기 데이터 플래그의 UV, BE 및 BS 비트를 결정하지만 BS는 BE가 설정된 경우에만 설정됩니다 auth_data_UV_BE_BS = h'2a' ; 파생됨: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'06', info='apple.ES256', L=1) attestation_cert_serial_number = h'394275613d5310b81a29ce90f48b61c1' ; 파생됨: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'07', info='apple.ES256', L=16) clientDataJSON = h'7b2274797065223a22776562617574686e2e637265617465222c226368616c6c656e6765223a22395f61494954685341486431414a7a34774a6239714a316775616e37576c4464676432596d4b396142676b222c226f726967696e223a2268747470733a2f2f6578616d706c652e6f7267222c2263726f73734f726967696e223a66616c73652c22657874726144617461223a22636c69656e74446174614a534f4e206d617920626520657874656e6465642077697468206164646974696f6e616c206669656c647320696e20746865206675747572652c207375636820617320746869733a20546a4c506e704f6158515572464e6362483274545a413d3d227d' attestationObject = h'a363666d74656170706c656761747453746d74a1637835638159025c30820258308201fea0030201020210394275613d5310b81a29ce90f48b61c1300a06082a8648ce3d0403023062311e301c06035504030c15576562417574686e207465737420766563746f7273310c300a060355040a0c0357334331253023060355040b0c1c41757468656e74696361746f72204174746573746174696f6e204341310b30090603550406130241413020170d3234303130313030303030305a180f33303234303130313030303030305a305f311e301c06035504030c15576562417574686e207465737420766563746f7273310c300a060355040a0c0357334331223020060355040b0c1941757468656e74696361746f72204174746573746174696f6e310b30090603550406130241413059301306072a8648ce3d020106082a8648ce3d030107034200048a3d5b1b4c543a706bf6e4b00afedb3c930b690dd286934fe2911f779cc7761af728e1aa3b0ff66692192daa776b83ddf8e3340d2d9a0eabdfc324eb3e2f136ca38196308193300c0603551d130101ff04023000300e0603551d0f0101ff040403020780301d0603551d0e0416041412f1ce6c0ae39b403bfc9200317bc183a4e4d766301f0603551d2304183016801445aff715b0dd786741fee996ebc16547a3931b1e303306092a864886f76364080204263024a122042097851a1a98b69c0614b26a94b70ec3aa07c061f89dbee23fbee01b6c42d718b0300a06082a8648ce3d040302034800304502207d541a5553f38b93b78b26a9dca58e64a7f8fac15ca206ae3ea32497cda375fb0221009137c6b75e767ec08224b29a7f703db4b745686dcc8a26b66e793688866d064f68617574684461746158a4bfabc37432958b063360d3ad6461c9c4735ae7f8edd46592a5e0f01452b2e4b54900000000748210a20076616a733b2114336fc38400209c4a5886af9283d9be3e9ec55978dedfdce2e3b365cab193ae850c16238fafb8a50102032620012158208a3d5b1b4c543a706bf6e4b00afedb3c930b690dd286934fe2911f779cc7761a225820f728e1aa3b0ff66692192daa776b83ddf8e3340d2d9a0eabdfc324eb3e2f136c'
인증:
challenge = h'd3eb2964641e26fed023403a72dde093b19c4ba9008c3f9dd83fcfd347a66d05' ; 파생됨: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'08', info='apple.ES256', L=32) client_data_gen_flags = h'c2' ; 파생됨: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'09', info='apple.ES256', L=1) ; client_data_gen_flags의 0x01 비트가 1이면 extra_client_data가 포함됩니다 ; auth_data_UV_BS는 인증기 데이터 플래그의 UV와 BS 비트를 설정하지만, BS는 등록 시 BE가 설정된 경우에만 설정됩니다 auth_data_UV_BS = h'e2' ; 파생됨: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'0a', info='apple.ES256', L=1) authenticatorData = h'bfabc37432958b063360d3ad6461c9c4735ae7f8edd46592a5e0f01452b2e4b50900000000' clientDataJSON = h'7b2274797065223a22776562617574686e2e676574222c226368616c6c656e6765223a22302d73705a4751654a76375149304136637433676b37476353366b416a442d6432445f503030656d625155222c226f726967696e223a2268747470733a2f2f6578616d706c652e6f7267222c2263726f73734f726967696e223a66616c73657d' signature = h'3046022100ee35db795ce28044e1f8231d68b3d79a9882f7415aa35c1b5ac74d24251073c8022100dcc65691650a412d0ceef843710c09827acf26c7845bddac07eec95863e7fc4c'
16.1.14. ES256 자격 증명을 사용한 FIDO U2F 증명
등록:
challenge = h'e074372990b9caa507a227dfc67b003780c45325380d1a90c20f81ed7d080c06' ; 파생됨: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'00', info='fido-u2f.ES256', L=32) credential_private_key = h'51bd002938fa10b83683ac2a2032d0a7338c7f65a90228cfd1f61b81ec7288d0' ; 파생됨: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'01', info='fido-u2f.ES256', L=32) client_data_gen_flags = h'00' ; 파생됨: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'02', info='fido-u2f.ES256', L=1) ; client_data_gen_flags의 0x01 비트가 1이면 extra_client_data가 포함됩니다 aaguid = h'afb3c2efc054df425013d5c88e79c3c1' ; 파생됨: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'03', info='fido-u2f.ES256', L=16) credential_id = h'a4ba6e2d2cfec43648d7d25c5ed5659bc18f2b781538527ebd492de03256bdf4' ; 파생됨: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'04', info='fido-u2f.ES256', L=32) attestation_private_key = h'66fda477a2a99d14c5edd7c1041a297ba5f3375108b1d032b79429f42349ce33' ; 파생됨: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'05', info='fido-u2f.ES256', L=32) attestation_cert_serial_number = h'04f66dc6542ea7719dea416d325a2401' ; 파생됨: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'06', info='fido-u2f.ES256', L=16) clientDataJSON = h'7b2274797065223a22776562617574686e2e637265617465222c226368616c6c656e6765223a22344851334b5a4335797155486f696666786e73414e344445557955344452715177672d4237583049444159222c226f726967696e223a2268747470733a2f2f6578616d706c652e6f7267222c2263726f73734f726967696e223a66616c73657d' attestationObject = h'a363666d74686669646f2d7532666761747453746d74a26373696758473045022100f41887a20063bb26867cb9751978accea5b81791a68f4f4dd6ea1fb6a5c086c302204e5e00aa3895777e6608f1f375f95450045da3da57a0e4fd451df35a31d2d98a637835638159022530820221308201c7a003020102021004f66dc6542ea7719dea416d325a2401300a06082a8648ce3d0403023062311e301c06035504030c15576562417574686e207465737420766563746f7273310c300a060355040a0c0357334331253023060355040b0c1c41757468656e74696361746f72204174746573746174696f6e204341310b30090603550406130241413020170d3234303130313030303030305a180f33303234303130313030303030305a305f311e301c06035504030c15576562417574686e207465737420766563746f7273310c300a060355040a0c0357334331223020060355040b0c1941757468656e74696361746f72204174746573746174696f6e310b30090603550406130241413059301306072a8648ce3d020106082a8648ce3d0301070342000456fffa7093dede46aefeefb6e520c7ccc78967636e2f92582ba71455f64e93932dff3be4e0d4ef68e3e3b73aa087e26a0a0a30b02dc2aa2309db4c3a2fc936dea360305e300c0603551d130101ff04023000300e0603551d0f0101ff040403020780301d0603551d0e04160414420822eb1908b5cd3911017fbcad4641c05e05a3301f0603551d2304183016801445aff715b0dd786741fee996ebc16547a3931b1e300a06082a8648ce3d040302034800304502200d0b777f0a0b181ad2830275acc3150fd6092430bcd034fd77beb7bdf8c2d546022100d4864edd95daa3927080855df199f1717299b24a5eecefbd017455a9b934d8f668617574684461746158a4bfabc37432958b063360d3ad6461c9c4735ae7f8edd46592a5e0f01452b2e4b54100000000afb3c2efc054df425013d5c88e79c3c10020a4ba6e2d2cfec43648d7d25c5ed5659bc18f2b781538527ebd492de03256bdf4a5010203262001215820b0d62de6b30f86f0bac7a9016951391c2e31849e2e64661cbd2b13cd7d5508ad225820503b0bda2a357a9a4b34475a28e65b660b4898a9e3e9bbf0820d43494297edd0'
인증:
challenge = h'f90c612981d84f599438de1a500f76926e92cc84bef8e02c6e23553f00485435' ; 파생됨: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'07', info='fido-u2f.ES256', L=32) client_data_gen_flags = h'2c' ; 파생됨: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'08', info='fido-u2f.ES256', L=1) ; client_data_gen_flags의 0x01 비트가 1이면 extra_client_data가 포함됩니다 ; auth_data_UV_BS는 인증기 데이터 플래그의 UV와 BS 비트를 설정하지만, BS는 등록 시 BE가 설정된 경우에만 설정됩니다 auth_data_UV_BS = h'd1' ; 파생됨: HKDF-SHA-256(IKM='WebAuthn test vectors', salt=h'09', info='fido-u2f.ES256', L=1) authenticatorData = h'bfabc37432958b063360d3ad6461c9c4735ae7f8edd46592a5e0f01452b2e4b50100000000' clientDataJSON = h'7b2274797065223a22776562617574686e2e676574222c226368616c6c656e6765223a222d5178684b59485954316d554f4e3461554139326b6d36537a49532d2d4f417362694e5650774249564455222c226f726967696e223a2268747470733a2f2f6578616d706c652e6f7267222c2263726f73734f726967696e223a66616c73657d' signature = h'304402206172459958fea907b7292b92f555034bfd884895f287a76200c1ba287239137002204727b166147e26a21bbc2921d192ebfed569b79438538e5c128b5e28e6926dd7'
16.2. WebAuthn 확장에 대한 테스트 벡터
이 섹션은 WebAuthn 확장의 예시 값을 나열합니다.
16.2.1. 의사 난수 함수 확장 (prf)
이 섹션은 의사 난수 함수(prf) 확장의 예시 값을 나열합니다.
이 prf 확장은 CTAP2의 hmac-secret 확장 [FIDO-CTAP]과 통합되므로,
예시는 두 섹션으로 나뉩니다:
WebAuthn prf 확장의 예시 입력 및 출력(관련: WebAuthn 클라이언트 및 WebAuthn 릴라잉
파티);
그리고 WebAuthn prf 확장과 CTAP2
hmac-secret 확장 간의 매핑 예시(관련: WebAuthn 클라이언트 및 WebAuthn 인증기).
16.2.1.1. 웹 인증 API
다음 예시는 WebAuthn 클라이언트 구현 및 WebAuthn 릴라잉 파티의 prf 확장 사용을 테스트하는 데 사용할 수 있습니다. 예시는 모두를 포괄하지는 않습니다.
-
enabled출력은 등록 절차 동안 항상 존재하며, 인증 절차 동안에는 절대 나타나지 않습니다:// 예시 확장 입력: { prf: {} } // navigator.credentials.create()의 예시 클라이언트 확장 출력: { prf: { enabled: true } } { prf: { enabled: false } } // navigator.credentials.get()의 예시 클라이언트 확장 출력: { prf: {} } -
results출력은 등록 절차 또는 인증 절차 중에eval또는evalByCredential입력이 있을 경우에 나타날 수 있습니다:// 예시 확장 입력: { prf: { eval: { first: new Uint8Array([ 1 , 2 , 3 , 4 ]) } } } // navigator.credentials.create()의 예시 클라이언트 확장 출력: { prf: { enabled: true } } { prf: { enabled: false } } { prf: { enabled: true , results: { first: ArrayBuffer} } } // navigator.credentials.get()의 예시 클라이언트 확장 출력: { prf: {} } { prf: { results: { first: ArrayBuffer} } } -
다음 출력
는 오직results.secondresults출력이 존재하고 선택된 PRF 입력에second입력이 포함된 경우에만 존재합니다:// 예시 확장 입력: { prf: { eval: { first: new Uint8Array([ 1 , 2 , 3 , 4 ]), second: new Uint8Array([ 5 , 6 , 7 , 8 ]), }, evalByCredential: { "e02eZ9lPp0UdkF4vGRO4-NxlhWBkL1FCmsmb1tTfRyE" : { first: new Uint8Array([ 9 , 10 , 11 , 12 ]), } } } } // 자격 증명 "e02eZ9lP..."이 사용된 경우 navigator.credentials.get()의 예시 출력: { prf: { results: { first: ArrayBuffer} } } // 다른 자격 증명이 사용된 경우 navigator.credentials.get()의 예시 출력: { prf: {} } { prf: { results: { first: ArrayBuffer, second: ArrayBuffer} } } -
출력
first및second는 임의의BufferSource유형일 수 있습니다. 동일한first및second입력은 동일한 출력 결과를 만듭니다:// 예시 확장 입력: { prf: { evalByCredential: { "e02eZ9lPp0UdkF4vGRO4-NxlhWBkL1FCmsmb1tTfRyE" : { first: new Uint8Array([ 9 , 10 , 11 , 12 ]), second: new Uint8Array([ 9 , 10 , 11 , 12 ]) } } } } // navigator.credentials.get()의 예시 클라이언트 확장 출력: { prf: { results: { first: new Uint8Array([ 0xc4 , 0x17 , 0x2e , 0x98 , 0x2e , 0x90 , 0x97 , 0xc3 , 0x9a , 0x6c , 0x0c , 0xb7 , 0x20 , 0xcb , 0x37 , 0x5b , 0x92 , 0xe3 , 0xfc , 0xad , 0x15 , 0x4a , 0x63 , 0xe4 , 0x3a , 0x93 , 0xf1 , 0x09 , 0x6b , 0x1e , 0x19 , 0x73 ]), second: new Uint32Array([ 0x982e17c4 , 0xc397902e , 0xb70c6c9a , 0x5b37cb20 , 0xadfce392 , 0xe4634a15 , 0x09f1933a , 0x73191e6b ]), } } }
이 섹션에서 사용된 의사 난수 값들은 다음과 같이 생성되었습니다:
-
"e02eZ9lPp0UdkF4vGRO4-NxlhWBkL1FCmsmb1tTfRyE" = Base64Url(SHA-256(UTF-8("WebAuthn PRF test vectors") || 0x00)) -
h'c4172e982e9097c39a6c0cb720cb375b92e3fcad154a63e43a93f1096b1e1973' = SHA-256(UTF-8("WebAuthn PRF test vectors") || 0x01)
16.2.1.2. CTAP2 hmac-secret 확장
다음 예시는 WebAuthn 클라이언트 구현이 prf 확장을 CTAP2의 [FIDO-CTAP] hmac-secret 확장과 어떻게 연동하는지
테스트하는 데 사용할 수 있습니다.
예시는 CDDL 표기법으로 제공됩니다.
예시는 모두를 포괄하지는 않습니다.
-
다음의 공통 정의들은 이후 모든 예시에 사용됩니다:
; 주어진 입력 매개변수들: platform_key_agreement_private_key = 0x0971bc7fb1be48270adcd3d9a5fc15d5fb0f335b3071ff36a54c007fa6c76514 authenticator_key_agreement_public_key = { 1 : 2 , 3 : -25 , -1 : 1 , -2 : h'a30522c2de402b561965c3cf949a1cab020c6f6ea36fcf7e911ac1a0f1515300' , -3 : h'9961a929abdb2f42e6566771887d41484d889e735e3248518a53112d2b915f00' , } authenticator_cred_random = h'437e065e723a98b2f08f39d8baf7c53ecb3c363c5e5104bdaaf5d5ca2e028154' 예시에서
first및second입력은 각각 예제 내에서prf_eval_first및prf_eval_second로 매핑됩니다.prf_results_first및prf_results_second값은 예시에서 각각 출력및results.first출력으로 매핑됩니다.results.second -
PIN 프로토콜 2를 사용하는 단일 입력 사례:
; Relying Party로부터의 입력: prf_eval_first = h'576562417574686e20505246207465737420766563746f727302' ; 클라이언트가 계산: shared_secret = h'0c63083de8170101d38bcf8bd72309568ddb4550867e23404b35d85712f7c20d8bc911ee23c06034cbc14290b9669bec07739053c5a416e313ef905c79955876' salt1 = h'527413ebb48293772df30f031c5ac4650c7de14bf9498671ae163447b6a772b3' salt_enc = h'437e065e723a98b2f08f39d8baf7c53ebbb2ed3e746b87576fd81f95def5757cad24be18eaef892e97692e684e07da53' ; 인증기가 계산: output1 = h'3c33e07d202c3b029cc21f1722767021bf27d595933b3d2b6a1b9d5dddc77fae' output_enc = h'3bfaa48f7952330d63e35ff8cd5bca48d2a12823828915749287256ab146272f9fb437bf65691243c3f504bd7ea6d5e6' ; 클라이언트가 복호화: prf_results_first = h'3c33e07d202c3b029cc21f1722767021bf27d595933b3d2b6a1b9d5dddc77fae' -
PIN 프로토콜 2를 사용하는 두 입력 사례:
; Relying Party로부터의 입력: prf_eval_first = h'576562417574686e20505246207465737420766563746f727302' prf_eval_second = h'576562417574686e20505246207465737420766563746f727303' ; 클라이언트가 계산: shared_secret = h'0c63083de8170101d38bcf8bd72309568ddb4550867e23404b35d85712f7c20d8bc911ee23c06034cbc14290b9669bec07739053c5a416e313ef905c79955876' salt1 = h'527413ebb48293772df30f031c5ac4650c7de14bf9498671ae163447b6a772b3' salt2 = h'd68ac03329a10ee5e0ec834492bb9a96a0e547baf563bf78ccbe8789b22e776b' salt_enc = h'23dde5e3462daf36559b85c4ac5f9656aa9bfd81c1dc2bf8533c8b9f3882854786b4f500e25b4e3d81f7fc7c742362294d92926c883b3fae1a3673246464bf730446e1fa4698c432a9092477c5dde5e3' ; 인증기가 계산: output1 = h'3c33e07d202c3b029cc21f1722767021bf27d595933b3d2b6a1b9d5dddc77fae' output2 = h'a62a8773b19cda90d7ed4ef72a80a804320dbd3997e2f663805ad1fd3293d50b' output_enc = h'90ee52f739043bc17b3488a74306d7801debb5b61f18662c648a25b5b5678ede482cdaff99a537a44f064fcb10ce6e04dfd27619dc96a0daff8507e499296b1eecf0981f7c8518b277a7a3018f5ec6fb' ; 클라이언트가 복호화: prf_results_first = h'3c33e07d202c3b029cc21f1722767021bf27d595933b3d2b6a1b9d5dddc77fae' prf_results_second = h'a62a8773b19cda90d7ed4ef72a80a804320dbd3997e2f663805ad1fd3293d50b' -
PIN 프로토콜 1을 사용하는 단일 입력 사례:
; Relying Party로부터의 입력: prf_eval_first = h'576562417574686e20505246207465737420766563746f727302' ; 클라이언트가 계산: shared_secret = h'23e5ed7157c25892b77732fb9c8a107e3518800db2af4142f9f4adfacb771d39' salt1 = h'527413ebb48293772df30f031c5ac4650c7de14bf9498671ae163447b6a772b3' salt_enc = h'ab8c878bb05d04700f077ed91845ec9c503c925cb12b327ddbeb4243c397f913' ; 인증기가 계산: output1 = h'3c33e07d202c3b029cc21f1722767021bf27d595933b3d2b6a1b9d5dddc77fae' output_enc = h'15d4e4f3f04109b492b575c1b38c28585b6719cf8d61304215108d939f37ccfb' ; 클라이언트가 복호화: prf_results_first = h'3c33e07d202c3b029cc21f1722767021bf27d595933b3d2b6a1b9d5dddc77fae'
이 섹션에서 사용된 입력 및 의사 난수 값들은 다음과 같이 생성되었습니다:
-
seed = UTF-8("WebAuthn PRF test vectors") -
prf_eval_first = seed || 0x02 -
prf_eval_second = seed || 0x03 -
platform_key_agreement_private_key = SHA-256(seed || 0x04) -
authenticator_key_agreement_public_key = P256-Public-Key(sk)여기서sk = SHA-256(seed || 0x05) -
authenticator_cred_random = SHA-256(seed || 0x06) -
iv(PIN 프로토콜 2의 단일 입력salt_enc에서): 잘라낸SHA-256(seed || 0x07) -
iv(PIN 프로토콜 2의 두 입력salt_enc에서): 잘라낸SHA-256(seed || 0x08) -
iv(PIN 프로토콜 2의 단일 입력output_enc에서): 잘라낸SHA-256(seed || 0x09) -
iv(PIN 프로토콜 2의 두 입력output_enc에서): 잘라낸SHA-256(seed || 0x0a)
17. 감사의 말씀
본 명세의 검토와 기여를 해주신 다음 분들께 감사드립니다: Yuriy Ackermann, James Barclay, Richard Barnes, Dominic Battré, Julien Cayzac, Domenic Denicola, Rahul Ghosh, Brad Hill, Nidhi Jaju, Jing Jin, Wally Jones, Ian Kilpatrick, Axel Nennker, Zack Newman, Yoshikazu Nojima, Kimberly Paulhamus, Adam Powers, Yaron Sheffer, Anne van Kesteren, Johan Verrept, 그리고 Boris Zbarsky.Adam Powers가 전체 등록 및 인증 흐름 다이어그램 (그림 1 및 그림 2)을 제작해주신 데에 감사드립니다.
Anthony Nadalin, John Fontana, 그리고 Richard Barnes 가 Web Authentication Working Group의 공동 의장으로 활동하며 기여해주신 점에 감사드립니다.
Simone Onofri, Philippe Le Hégaret, Wendy Seltzer, Samuel Weiler, 그리고 Harry Halpin 이 W3C 팀 컨택트로서 기여해주신 데에도 감사의 말씀을 전합니다.
18. 변경 이력
이 절은 규범적이지 않습니다.
이 절은 시간이 지남에 따라 이 명세에 이루어진 주요 변경 사항을 요약한 것입니다.
18.1. Web Authentication Level 2 [webauthn-2-20210408] 이후 변경점
18.1.1. 주요 변경
다음 변경 사항들은 Web Authentication API 및 그 동작 방식에 적용되었습니다.
변경 사항:
-
타임아웃 가이드 업데이트: § 15.1 세리머니 타임아웃 권장 범위
-
uvm확장이 더 이상 포함되지 않음; 대신 L2 [webauthn-2-20210408] 참고 -
aaguid는 인증된 자격 증명 데이터에서
attestation선호도가none일 때 0으로 초기화하지 않음: § 5.1.3 새 자격 증명 생성 - PublicKeyCredential의 [[Create]](origin, options, sameOriginWithAncestors) 내부 메서드
폐지 사항:
-
등록 파라미터
: § 5.4.1 공개키 엔터티 설명 (dictionary PublicKeyCredentialEntity)publicKey.rp.name -
tokenBinding이 [RESERVED]로 변경됨.
신규 기능:
-
새로운 JSON (역)직렬화 메서드:
-
크로스-오리진 iframe에서의 생성 작업:
-
생성 시 조건부 중재: § 5.1.3 새 자격 증명 생성 - PublicKeyCredential의 [[Create]](origin, options, sameOriginWithAncestors) 내부 메서드
-
get 시 조건부 중재: § 5.1.4 기존 자격 증명을 사용해 어서션 생성
-
§ 5.1.7 클라이언트 기능 사용 가능성 - PublicKeyCredential의 getClientCapabilities() 메서드
-
열거형
hybrid의 새 값: § 5.8.4 인증기 전송 수단 열거형 (enum AuthenticatorTransport). -
§ 5.1.10 인증기에 자격 증명 변경 신호 전달 - PublicKeyCredential의 signal 메서드
-
새로운 클라이언트 데이터 속성
topOrigin: § 5.8.1 WebAuthn 서명에 사용되는 클라이언트 데이터 (dictionary CollectedClientData)
18.1.2. 편집상 변경
다음 변경 사항들은 문서의 명확성, 가독성, 탐색성 등 향상을 위해 반영되었습니다.
-
§ 1.2 사용 사례가 실제 배포 환경의 발전을 반영하도록 업데이트됨.
-
자격 증명 레코드 개념을 도입하여 릴라잉 파티가 보관해야 할 데이터 및 등록과 인증 세리머니 간의 관계를 형식화함.
-
오류 조건 명확화:
-
§ 6.4 문자열 처리를 클라이언트의 문자열 길이 제한(§ 6.4.1.1 클라이언트에 의한 문자열 절단)과 인증기의 문자열 길이 제한(§ 6.4.1.2 인증기에 의한 문자열 절단)으로 분리하여 책임 소재를 명확히 함.
-
§ 16 테스트 벡터 추가함.
-
규범적 언어를 "참고" 블록 외부로 이동.