Skip to content

Latest commit

 

History

History
121 lines (97 loc) · 5.22 KB

File metadata and controls

121 lines (97 loc) · 5.22 KB

FIDO2 Architecture and Data Explanation Report

1. Introduction

FIDO2 (Fast Identity Online 2.0) is a passwordless authentication standard that allows users to log in securely using hardware security keys such as YubiKey.
This system is based on Public Key Cryptography, ensuring the security and integrity of the authentication process.

This report provides a detailed explanation of the FIDO2 architecture, authentication process, and the key data structures used.


2.1 Key Components

The FIDO2 architecture consists of the following key components:

  • Client: The user-side application that interacts with the server and performs authentication via YubiKey.
  • Authenticator: The security device (e.g., YubiKey) that generates keys, processes signing requests, and authenticates the user.
  • Server: Stores user Credential IDs and Public Keys, and verifies authentication requests.
  • Relying Party (RP): The application or website that requests authentication from the Client.

3. FIDO2 Authentication Process

The FIDO2 authentication process consists of two main stages: Registration and Authentication.

3.1 Registration Process

  1. Client sends a registration request to the server.
  2. Server generates a Challenge (random challenge string) and sends it back to the Client.
  3. Client uses YubiKey to generate a Key Pair.
  4. YubiKey generates a unique Credential ID and signs the Challenge using the Private Key.
  5. Client sends the Credential ID and Public Key to the Server.
  6. Server stores the Credential ID and Public Key, completing the registration.

3.2 Authentication Process

  1. Client sends an authentication request to the Server.
  2. Server generates a new Challenge and returns the Credential ID to the Client.
  3. Client retrieves the Credential ID and signs the Challenge using the corresponding Private Key.
  4. Client sends signed_data, authenticator_data, and credential_id to the Server.
  5. Server retrieves the stored Public Key and verifies signed_data.
  6. If signature verification succeeds, authentication is successful.

4. Key Data Structures and Explanation

4.1 Credential ID

  • Purpose: Identifies a specific credential, allowing the server to retrieve the correct Public Key.
  • Characteristics:
    • Generated by YubiKey, uniquely associated with a specific website.
    • Unique and unpredictable, ensuring security.
  • Example:
    986f86c2c61f8f78df847ea84cce8bf58204e319faffcc828263a78e4b27c6d42f4b1059b345d0380ce7a841889b4233a91bd11b5bac229daf77fc3a31e17871
    

4.2 Signed Data

  • Purpose: Signed by YubiKey using the Private Key to authenticate the challenge.
  • Verification Process:
    • The Server retrieves the Public Key using the Credential ID.
    • The Server verifies signed_data using the Public Key.
    • If the signature is valid, it confirms ownership of the Private Key.
  • Example:
    3044022047a0b765665df498ffe0132d07163796fd2b7ea6815054eb0065d93939ed8396
    02200719112b90ce5868df925bffe4491a20ae9994e517d5b4af394b39d8b4081928
    

4.3 Authenticator Data

  • Purpose: Provides additional authentication information, ensuring the request has not been tampered with.
  • Contents:
    • Relying Party Hash (site identifier)
    • Flags (e.g., user presence detection, attestation status)
    • Signature Counter (prevents replay attacks)
  • Example:
    49960de5880e8c687434170f6476605b8fe4aeb9a28632c7995cf3ba831d97630500000009
    

4.4 Challenge

  • Purpose: Prevents replay attacks. The server generates a new challenge for each authentication request.
  • Characteristics:
    • Different for every authentication request.
    • Must be signed by the YubiKey.

4.5 Public Key

  • Example (COSE Key - CBOR Object Signing and Encryption format):
    pQECAzgYIAEhWCDdNfh6giBH2b+1VjQ2UEJBycQmze0jCcKeHl30b10InyJYINnc+d7qECqsoVRv5XC4lMSjddl2NIDoTKYAAcKfQI3/
    

5. Signature Verification Example Code

import base64
import cbor2
from cryptography.hazmat.primitives.asymmetric import ec
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric.utils import decode_dss_signature

# Decode COSE Key (Public Key)
public_key_cose_b64 = "pQECAzgYIAEhWCDdNfh6giBH2b+1VjQ2UEJBycQmze0jCcKeHl30b10InyJYINnc+d7qECqsoVRv5XC4lMSjddl2NIDoTKYAAcKfQI3/"
public_key_cose = base64.b64decode(public_key_cose_b64)
cose_key = cbor2.loads(public_key_cose)

x_coordinate = int.from_bytes(cose_key[-2], "big")
y_coordinate = int.from_bytes(cose_key[-3], "big")

public_numbers = ec.EllipticCurvePublicNumbers(x_coordinate, y_coordinate, ec.SECP256R1())
public_key = public_numbers.public_key()

# Decode signed data
signed_data_hex = "3044022047a0b765665df498ffe0132d07163796fd2b7ea6815054eb0065d93939ed839602200719112b90ce5868df925bffe4491a20ae9994e517d5b4af394b39d8b4081928"
signed_data = bytes.fromhex(signed_data_hex)

# Verify signature
try:
    public_key.verify(signed_data, b"challenge_data", ec.ECDSA(hashes.SHA256()))
    print("✅ Signature verification successful!")
except:
    print("❌ Signature verification failed!")