Getting Started with Google Titan Security Key: A Beginner's Guide
A brief introduction to the Google Titan security key, common authentication use cases, and examples for using the key in app authentication.
Legacy MFA schemes like PIN, SMS/Email OTP, TOTP apps, and mobile push, are vulnerable to phishing attempts and malware. FIDO2-based hardware security keys like Google Titan and YubiKey are probably the only known phishing resistant technologies available today. In this post, we'll do a deep dive into Google Titan security keys, common authentication use cases, and interacting with the devices programmatically during FIDO2 registration and authentication.
What is Google Titan?
Google Titan is a hardware security key, developed by Google, and can be used to authenticate to Google, Google Cloud, and many other services that support FIDO standards. Titan security keys are compatible with the Advanced Protection Program, Google's strongest account security program, originally introduced to safeguard politicians, journalists, activists and others who are at a high risk of targeted online attacks, but now available to everyone. The Titan hardware chip includes firmware to help verify that the keys haven't been tampered with. Google Titan supports authentication protocols like U2F and FIDO2/WebAuthn (CTAP), and ships in USB-A/NFC and USB-C/NFC form factors. While the keys are not officially IP68 rated, they are water, dust and impact resistant, with no batteries or moving parts, making them ideal for long term use.
How is Google Titan Different from YubiKey?
YubiKey is a hardware security key from Yubico, providing strong multi-factor authentication for a wide range of applications and services. YubiKey supports multiple authentication protocols, including U2F, FIDO2/WebAuthn, OpenPGP, OTP, and smart card, and ships in USB A/C, NFC and Lightning form factors. The keys are IP68 rate, crush resistant, with no batteries or moving parts, making them really ideal for long term use. The most popular YubiKeys are USB-A/NFC, USB-C/NFC and USB-C/Lightning.
Just like Google Titan, YubiKey keys also offer cryptographic proof that users are interacting with legitimate services once they have registered their security keys. However, YubiKey has better support for SSH authentication compared to Google Titan. YubiKey can be used to store SSH keys, and work with OpenSSH, PuTTY, and other SSH clients to authenticate SSH servers that support protocols like U2F and FIDO2. Google Titan can also be used, but it only supports the U2F protocol for SSH authentication, limiting the SSH servers it can work with.
Common Authentication Use Cases
Google Titan keys can be used for application or service authentication in a variety of scenarios where secure and strong authentication is required. For example:
- Two-factor authentication (2FA) for web applications.
- Authentication for remote server/application access (see this post).
- Authentication for cloud services like Google Cloud, AWS, and Azure.
- Passwordless authentication, to simplify the authentication process and reduce the risk of password-based attacks like phishing and credential stuffing.
- Developer authentication for code signing.
FIDO2 Registration Flow
Here is a high-level overview of the FIDO2 registration process:
- The user initiates the registration process on their device by selecting the option to register a new security key with a particular service.
- The service (i.e. the relying party) generates a registration request, which includes a unique challenge and some information about the user and service.
- The registration request is sent to the user's device via the browser or another application.
- The user's device uses the FIDO2 client-side API to generate a new public-private key pair and create an attestation object, which includes the public key and other metadata.
- The attestation object is sent back to the service, which verifies the attestation signature and stores the user's public key.
- The service then creates a new user account (if necessary) and associates the user's public key with the account.
- The user is informed that the registration process is complete, and they can now use their security key to authenticate to the service.
Discoverable (Resident) vs Non-Discoverable Keys
FIDO2 hardware security keys can be categorised into discoverable (or resident) and non-discoverable keys. Resident keys are visible to the host operating system and can be used for purposes beyond authentication too, such as storage or encryption. The private keys are generated and stored on the device itself, and cannot be copied or transferred to another device. Non-discoverable keys are hidden from the host and can only be used for authentication. For SSH authentication using non-discoverable keys, a copy of the private key may also be required to be stored in the ~/.ssh
folder of the logged-in user.
When you register the Google Titan security key with a service, the device generates a new public-private key pair and a credential ID, and stores the private key securely on the device. The public key and credential ID are then registered with the service. When you perform a FIDO2 authentication with a service that supports security keys, the service sends a challenge to the device, which signs the challenge using the private key stored on the device and sends the signed response back to the service. The service then verifies the signature using the public key associated with the credential ID.
Set up Your Code Development Environment
For this tutorial, we'll create Python code to interact with the Google Titan security key. Here are the things you need to have in place first:
- Set up a local development environment like VS Code or PyCharm with Python 3.x and the
pip
package manager installed. - Install the Python FIDO2 library using the command
pip install fido2
. - Have a Google Titan key available.
Once you have these components in place, we can use the FIDO2 library to check device information, register credentials, and authenticate to the device.
Get Google Titan Device Information
To get basic device information, connect the Google Titan security key to your workstation, and run the following Python script. Google Titan does not support CTAP2; you'll get an error if you try to retrieve device information using this class.
# Import the necessary modules from fido2 library
from fido2.hid import CtapHidDevice
# Find the first connected FIDO2 device
dev = next(CtapHidDevice.list_devices(), None)
if not dev:
print("No FIDO2 device found.")
exit()
# Get and print device info to the console
print(f"Version: {dev.version}")
print(f"Product Name: {dev.product_name}")
print(f"Serial Number: {dev.serial_number}")
print(f"Device Version: {dev.device_version}")
You can also use the higher-level Fido2Client
class to get device information.
# Import the necessary modules from fido2 library
from fido2.client import Fido2Client, ClientError
from fido2.hid import CtapHidDevice
# Find the first connected FIDO2 device
dev = next(CtapHidDevice.list_devices(), None)
if not dev:
print("No FIDO2 device found.")
exit()
# Set the origin of the relying party that the FIDO2 client will communicate with
origin = 'https://example.com'
try:
# Get and print device info to the console
client = Fido2Client(dev, origin, None)
print(f"Authenticator Attestation GUID: {client.info.aaguid}")
print(f"Versions: {client.info.versions}")
print(f"Firmware Version: {client.info.firmware_version}")
print(f"Options: {client.info.options}")
print(f"Algorithms: {client.info.algorithms}")
print(f"Extensions: {client.info.extensions}")
print(f"Transports: {client.info.transports}")
print(f"Certifications: {client.info.certifications}")
print(f"Max Message Size: {client.info.max_msg_size}")
print(f"Min PIN Length: {client.info.min_pin_length}")
print(f"Force PIN Change: {client.info.force_pin_change}")
print(f"PIN UV Protocols: {client.info.pin_uv_protocols}")
except ClientError as e:
print(f"Error communicating with device: {e}")
Ideally, you should offer a verify
parameter to the Fido2Client
constructer instead of None
. The purpose of this function is to ensure that the relying party ID (rp_id
) is valid and belongs to the expected origin.
def verify(rp_id, origin):
# Perform verification logic here
# Return True if RP ID is valid and belongs to the expected origin, else False
Generate, Register, and Authenticate Credentials
The Python FIDO2 library provides extensive support for the generation, registration, and authentication of credentials (public-private key pairs) against a Google Titan security key. See credentials.py
file under the example
folder of the FIDO2 GitHub repository for the complete source code. The repository also contains sample source code for biometric enrolment, generation of HMAC secrets, and verifying that the credentials are signed by a designated CA.
Generally speaking, if you are developing a server-side application and need to interact with FIDO2 authenticators, you should use Fido2Client
. If you are developing a client-side application in the browser and need to interact with WebAuthn authenticators, you should use WebAuthnClient
.