# Table of Contents - [YubiKey Manager (ykman) CLI User Guide — YubiKey Manager (ykman) CLI Guide documentation](#yubikey-manager-ykman-cli-user-guide-yubikey-manager-ykman-cli-guide-documentation) - [Introduction — YubiKey Manager (ykman) CLI Guide documentation](#introduction-yubikey-manager-ykman-cli-guide-documentation) - [Installation — YubiKey Manager (ykman) CLI Guide documentation](#installation-yubikey-manager-ykman-cli-guide-documentation) - [Using the YubiKey Manager GUI — YubiKey Manager (ykman) CLI Guide documentation](#using-the-yubikey-manager-gui-yubikey-manager-ykman-cli-guide-documentation) - [Hidden Commands — YubiKey Manager (ykman) CLI Guide documentation](#hidden-commands-yubikey-manager-ykman-cli-guide-documentation) - [OpenPGP Commands — YubiKey Manager (ykman) CLI Guide documentation](#openpgp-commands-yubikey-manager-ykman-cli-guide-documentation) - [FIDO Commands — YubiKey Manager (ykman) CLI Guide documentation](#fido-commands-yubikey-manager-ykman-cli-guide-documentation) - [OATH Commands — YubiKey Manager (ykman) CLI Guide documentation](#oath-commands-yubikey-manager-ykman-cli-guide-documentation) - [Using the ykman CLI — YubiKey Manager (ykman) CLI Guide documentation](#using-the-ykman-cli-yubikey-manager-ykman-cli-guide-documentation) - [Base Commands — YubiKey Manager (ykman) CLI Guide documentation](#base-commands-yubikey-manager-ykman-cli-guide-documentation) - [OTP Commands — YubiKey Manager (ykman) CLI Guide documentation](#otp-commands-yubikey-manager-ykman-cli-guide-documentation) - [HSMauth Commands — YubiKey Manager (ykman) CLI Guide documentation](#hsmauth-commands-yubikey-manager-ykman-cli-guide-documentation) - [PIV Commands — YubiKey Manager (ykman) CLI Guide documentation](#piv-commands-yubikey-manager-ykman-cli-guide-documentation) - [Copyright — YubiKey Manager (ykman) CLI Guide documentation](#copyright-yubikey-manager-ykman-cli-guide-documentation) - [APDUs ](#apdus-) - [YubiHSM 2 User Guide — YubiHSM 2 User Guide documentation](#yubihsm-2-user-guide-yubihsm-2-user-guide-documentation) - [.NET YubiKey SDK: User's Manual ](#-net-yubikey-sdk-user-s-manual-) - [.NET YubiKey SDK ](#-net-yubikey-sdk-) - [.NET YubiKey SDK: YubiKey API reference ](#-net-yubikey-sdk-yubikey-api-reference-) - [.NET YubiKey SDK: Core API reference ](#-net-yubikey-sdk-core-api-reference-) - [What is a YubiKey? ](#what-is-a-yubikey-) - [How to install the SDK ](#how-to-install-the-sdk-) - [Running .NET SDK applications on Linux ](#running-net-sdk-applications-on-linux-) - [Threads ](#threads-) - [The KeyCollector's touch notification ](#the-keycollector-s-touch-notification-) - [Delegates (callbacks) in the SDK ](#delegates-callbacks-in-the-sdk-) - [The KeyCollector and alternatives ](#the-keycollector-and-alternatives-) - [Handling Sensitive Data (PINs, Passwords, and Keys) ](#handling-sensitive-data-pins-passwords-and-keys-) - [Making a connection ](#making-a-connection-) - [Unknown](#unknown) - [Providing alternate cryptographic implementations ](#providing-alternate-cryptographic-implementations-) - [Physical interfaces ](#physical-interfaces-) - [Unknown](#unknown) - [Configure slot ](#configure-slot-) - [How to retrieve a slot's status ](#how-to-retrieve-a-slot-s-status-) - [How to swap slot configurations ](#how-to-swap-slot-configurations-) - [Swap slot configurations ](#swap-slot-configurations-) - [Program NDEF ](#program-ndef-) - [Update slot ](#update-slot-) - [Unknown](#unknown) - [OTP application concepts ](#otp-application-concepts-) - [Update scan-code map ](#update-scan-code-map-) - [Get serial number ](#get-serial-number-) - [Get device information ](#get-device-information-) - [How to read NDEF information ](#how-to-read-ndef-information-) - [How to delete a slot's configuration ](#how-to-delete-a-slot-s-configuration-) - [Challenge-response ](#challenge-response-) - [Query FIPs mode ](#query-fips-mode-) - [Read status ](#read-status-) - [Read NDEF payload (NFC only) ](#read-ndef-payload-nfc-only-) - [How to back up credentials ](#how-to-back-up-credentials-) - [Configuration concepts ](#configuration-concepts-) - [OATH-HOTP ](#oath-hotp-) - [OATH credentials overview ](#oath-credentials-overview-) - [Protecting the OATH application with a password ](#protecting-the-oath-application-with-a-password-) - [URI string format ](#uri-string-format-) - [OATH commands and APDUs ](#oath-commands-and-apdus-) - [Building a certificate request for a PIV private key ](#building-a-certificate-request-for-a-piv-private-key-) - [PIV attestation statements ](#piv-attestation-statements-) - [Maximum certificate sizes ](#maximum-certificate-sizes-) - [ECDSA signatures ](#ecdsa-signatures-) - [Elliptic Curve Diffie-Hellman key agreement ](#elliptic-curve-diffie-hellman-key-agreement-) - [Public key handling ](#public-key-handling-) - [Overview of the SDK ](#overview-of-the-sdk-) - [YubiKey-host device communication ](#yubikey-host-device-communication-) - [Static passwords ](#static-passwords-) - [Yubico OTP ](#yubico-otp-) - [Private key handling ](#private-key-handling-) - [ ](#-) - [Keeping track of PIV slot contents ](#keeping-track-of-piv-slot-contents-) - [ ](#-) - [ ](#-) - [Secure Channel Protocol (SCP) ](#secure-channel-protocol-scp-) - [ ](#-) - [ ](#-) - [OATH session APIs ](#oath-session-apis-) - [ ](#-) - [ ](#-) - [ ](#-) - [ ](#-) - [Device notifications ](#device-notifications-) - [PIV access control ](#piv-access-control-) - [ ](#-) - [PIV PIN, touch and bio policies ](#piv-pin-touch-and-bio-policies-) - [ ](#-) - [Building a basic authenticator ](#building-a-basic-authenticator-) - [How to update slot settings ](#how-to-update-slot-settings-) - [Modified hexadecimal encoding (ModHex) ](#modified-hexadecimal-encoding-modhex-) - [How to configure NDEF to use a slot to generate an OTP ](#how-to-configure-ndef-to-use-a-slot-to-generate-an-otp-) - [ ](#-) - [ ](#-) - [ ](#-) - [ ](#-) - [ ](#-) - [ ](#-) - [ ](#-) - [ ](#-) - [How FIDO U2F works ](#how-fido-u2f-works-) - [Maintaining compatibility ](#maintaining-compatibility-) - [Challenge-response ](#challenge-response-) - [FIDO U2F and FIPS ](#fido-u2f-and-fips-) - [ ](#-) - [ ](#-) - [Security Domain certificate management ](#security-domain-certificate-management-) - [ ](#-) - [ ](#-) - [ ](#-) - [OATH overview ](#oath-overview-) - [The FIDO U2F PIN ](#the-fido-u2f-pin-) - [Security Domain device information ](#security-domain-device-information-) - [Security Domain common tasks ](#security-domain-common-tasks-) - [Security Domain key management ](#security-domain-key-management-) - [How to set, modify, remove, and use slot access codes ](#how-to-set-modify-remove-and-use-slot-access-codes-) - [ ](#-) - [ ](#-) - [ ](#-) - [ ](#-) - [ ](#-) - [ ](#-) - [How to program a slot with an OATH HOTP credential ](#how-to-program-a-slot-with-an-oath-hotp-credential-) - [ ](#-) - [ ](#-) - [How to send a challenge to a YubiKey and receive a response code ](#how-to-send-a-challenge-to-a-yubikey-and-receive-a-response-code-) - [Slots ](#slots-) - [PIV PIN-only mode ](#piv-pin-only-mode-) - [How FIDO2 works ](#how-fido2-works-) - [How to program a slot with a Yubico OTP credential ](#how-to-program-a-slot-with-a-yubico-otp-credential-) - [The PIV PIN, PUK, and management key ](#the-piv-pin-puk-and-management-key-) - [How to program a slot with a challenge-response credential ](#how-to-program-a-slot-with-a-challenge-response-credential-) - [NDEF overview ](#ndef-overview-) - [FIDO2 touch and fingerprint notification ](#fido2-touch-and-fingerprint-notification-) - [OTP commands and APDUs ](#otp-commands-and-apdus-) - [CTAP2 PIN/UV authentication protocols ](#ctap2-pin-uv-authentication-protocols-) - [ ](#-) - [The minimum PIN length ](#the-minimum-pin-length-) - [The SDK's "automatic" AuthToken logic ](#the-sdk-s-automatic-authtoken-logic-) - [YubiKey Bio Multi-protocol Edition considerations and quirks ](#yubikey-bio-multi-protocol-edition-considerations-and-quirks-) - [FIDO2 HMAC secret ("hmac-secret" extension) ](#fido2-hmac-secret-hmac-secret-extension-) - [ ](#-) - [ ](#-) - [ ](#-) - [ ](#-) - [ ](#-) - [ ](#-) - [ ](#-) - [Migrating from SmartCard.NET to the SDK ](#migrating-from-smartcard-net-to-the-sdk-) - [PIN complexity policy ](#pin-complexity-policy-) - [FIDO2 Blobs ](#fido2-blobs-) - [ ](#-) - [ ](#-) - [ ](#-) - [ ](#-) - [ ](#-) - [ ](#-) - [ ](#-) - [The FIDO2 PIN ](#the-fido2-pin-) - [FIDO2 Authenticator Configuration ](#fido2-authenticator-configuration-) - [ ](#-) - [PIV GET and PUT DATA ](#piv-get-and-put-data-) - [Credential ](#credential-) - [OTP application how-to guides ](#otp-application-how-to-guides-) - [FIDO2 Authentication (PIN and Fingerprint) ](#fido2-authentication-pin-and-fingerprint-) - [TLV ](#tlv-) - [FIDO U2F Reset ](#fido-u2f-reset-) - [PIV slots ](#piv-slots-) - [YubiHSM Auth session APIs ](#yubihsm-auth-session-apis-) - [Interacting with a YubiHSM 2 ](#interacting-with-a-yubihsm-2-) - [FIDO2 credential blobs ("credBlob" extension) ](#fido2-credential-blobs-credblob-extension-) - [ ](#-) - [YubiHSM Auth commands ](#yubihsm-auth-commands-) - [Add credential ](#add-credential-) - [Attacks on RSA decryption and mitigation ](#attacks-on-rsa-decryption-and-mitigation-) - [FIDO2 Bio Enrollment (and related operations) ](#fido2-bio-enrollment-and-related-operations-) - [FIDO2 Reset ](#fido2-reset-) - [How to program a slot with a static password ](#how-to-program-a-slot-with-a-static-password-) - [Get application version ](#get-application-version-) - [Reset application ](#reset-application-) - [List credentials ](#list-credentials-) - [Get management key retries ](#get-management-key-retries-) - [Delete credential ](#delete-credential-) - [Get AES-128 session keys ](#get-aes-128-session-keys-) - [Change management key ](#change-management-key-) - [FIDO2 large blobs ("largeBlobs" option) ](#fido2-large-blobs-largeblobs-option-) - [FIDO2 Credentials ](#fido2-credentials-) - [Commands ](#commands-) - [PIV data objects ](#piv-data-objects-) - [How authentication is achieved: AuthTokens, permissions, PIN/UV, and AuthParams ](#how-authentication-is-achieved-authtokens-permissions-pin-uv-and-authparams-) - [FIDO2 credential management ](#fido2-credential-management-) - [What's new in the SDK? ](#what-s-new-in-the-sdk-) - [Yubico Product Documentation — Yubico Product Documentation documentation](#yubico-product-documentation-yubico-product-documentation-documentation) - [FIDO U2F commands ](#fido-u2f-commands-) - [FIDO2 commands ](#fido2-commands-) - [PIV commands ](#piv-commands-) - [Unknown](#unknown) - [Unknown](#unknown) - [Unknown](#unknown) - [Unknown](#unknown) - [FIDO U2F overview ](#fido-u2f-overview-) - [FIDO2 overview ](#fido2-overview-) - [YubiHSM Auth overview ](#yubihsm-auth-overview-) - [PIV overview ](#piv-overview-) - [Unknown](#unknown) - [Introduction — YubiHSM 2 User Guide documentation](#introduction-yubihsm-2-user-guide-documentation) - [Core Concepts — YubiHSM 2 User Guide documentation](#core-concepts-yubihsm-2-user-guide-documentation) - [Security Domain overview ](#security-domain-overview-) - [Getting Started — YubiHSM 2 User Guide documentation](#getting-started-yubihsm-2-user-guide-documentation) - [Set FIPS Mode — YubiHSM 2 User Guide documentation](#set-fips-mode-yubihsm-2-user-guide-documentation) - [Set up KSP on Windows — YubiHSM 2 User Guide documentation](#set-up-ksp-on-windows-yubihsm-2-user-guide-documentation) - [YubiHSM 2 References — YubiHSM 2 User Guide documentation](#yubihsm-2-references-yubihsm-2-user-guide-documentation) - [YubiHSM 2 Management Tasks — YubiHSM 2 User Guide documentation](#yubihsm-2-management-tasks-yubihsm-2-user-guide-documentation) - [Backup and Restore with YubiHSM Backup Keys — YubiHSM 2 User Guide documentation](#backup-and-restore-with-yubihsm-backup-keys-yubihsm-2-user-guide-documentation) - [Glossary — YubiHSM 2 User Guide documentation](#glossary-yubihsm-2-user-guide-documentation) - [YubiHSM Algorithms — YubiHSM 2 User Guide documentation](#yubihsm-algorithms-yubihsm-2-user-guide-documentation) - [Copyright — YubiHSM 2 User Guide documentation](#copyright-yubihsm-2-user-guide-documentation) - [Reset YubiHSM to Factory Settings — YubiHSM 2 User Guide documentation](#reset-yubihsm-to-factory-settings-yubihsm-2-user-guide-documentation) - [YubiHSM 2 SDK Tools And Libraries — YubiHSM 2 User Guide documentation](#yubihsm-2-sdk-tools-and-libraries-yubihsm-2-user-guide-documentation) - [Third Party Integration Deployment Guides — YubiHSM 2 User Guide documentation](#third-party-integration-deployment-guides-yubihsm-2-user-guide-documentation) - [Deploy for EJBCA — YubiHSM 2 User Guide documentation](#deploy-for-ejbca-yubihsm-2-user-guide-documentation) - [Deploy for OpenSSL with libp11 — YubiHSM 2 User Guide documentation](#deploy-for-openssl-with-libp11-yubihsm-2-user-guide-documentation) - [Deploy for OpenSC pkcs11-tool — YubiHSM 2 User Guide documentation](#deploy-for-opensc-pkcs11-tool-yubihsm-2-user-guide-documentation) - [Deploy for OpenSSL with engine_pkcs11 and yubihsm_pkcs11 — YubiHSM 2 User Guide documentation](#deploy-for-openssl-with-engine-pkcs11-and-yubihsm-pkcs11-yubihsm-2-user-guide-documentation) - [Deploy for OpenSSL on Windows — YubiHSM 2 User Guide documentation](#deploy-for-openssl-on-windows-yubihsm-2-user-guide-documentation) - [Deploy for Signing Java Code — YubiHSM 2 User Guide documentation](#deploy-for-signing-java-code-yubihsm-2-user-guide-documentation) - [Deploy for Microsoft Host Guardian Service (HGS) — YubiHSM 2 User Guide documentation](#deploy-for-microsoft-host-guardian-service-hgs-yubihsm-2-user-guide-documentation) - [Deploy for Active Directory Certificate Services CA — YubiHSM 2 User Guide documentation](#deploy-for-active-directory-certificate-services-ca-yubihsm-2-user-guide-documentation) - [Deploy for Microsoft SQL Server — YubiHSM 2 User Guide documentation](#deploy-for-microsoft-sql-server-yubihsm-2-user-guide-documentation) - [Unknown](#unknown) - [OTP application overview ](#otp-application-overview-) - [Deploy for OpenSSH Certificates for Host Login — YubiHSM 2 User Guide documentation](#deploy-for-openssh-certificates-for-host-login-yubihsm-2-user-guide-documentation) - [YubiHSM Command Reference — YubiHSM 2 User Guide documentation](#yubihsm-command-reference-yubihsm-2-user-guide-documentation) - [YubiKey FIPS 4 Series Technical Manual — YubiKey FIPS 4 Series Technical Manual documentation](#yubikey-fips-4-series-technical-manual-yubikey-fips-4-series-technical-manual-documentation) - [Yubico OID Reference Guide — Yubico OID Reference Guide documentation](#yubico-oid-reference-guide-yubico-oid-reference-guide-documentation) - [Yubico Best Practices — Best Practices documentation](#yubico-best-practices-best-practices-documentation) - [YubiKey Technical Manual — YubiKey Technical Manual documentation](#yubikey-technical-manual-yubikey-technical-manual-documentation) - [YubiEnterprise Services — YubiEnterprise Services documentation](#yubienterprise-services-yubienterprise-services-documentation) - [Class AuthenticatorInfo ](#class-authenticatorinfo-) - [Yubico FIDO Pre-reg with Okta — Yubico FIDO Pre-reg with Okta documentation](#yubico-fido-pre-reg-with-okta-yubico-fido-pre-reg-with-okta-documentation) - [Class YubiKeyCompatSwitches ](#class-yubikeycompatswitches-) - [Class CommandApdu ](#class-commandapdu-) - [Class GetMetadataCommand ](#class-getmetadatacommand-) - [Class DeviceResetResponse ](#class-deviceresetresponse-) - [Class GetSerialNumberResponse ](#class-getserialnumberresponse-) - [Unknown](#unknown) - [Class SetPinCommand ](#class-setpincommand-) - [Class EnumerateRpsBeginCommand ](#class-enumeraterpsbegincommand-) - [Class PivDataObject ](#class-pivdataobject-) - [Class DeleteCredentialCommand ](#class-deletecredentialcommand-) - [Class GetApplicationVersionCommand ](#class-getapplicationversioncommand-) - [Enum YubiKeyCapabilities ](#enum-yubikeycapabilities-) - [Class EnumerateCredentialsBeginCommand ](#class-enumeratecredentialsbegincommand-) - [Class PivSlot ](#class-pivslot-) - [Class ConfigureSlotCommand ](#class-configureslotcommand-) - [Class GetBioMetadataCommand ](#class-getbiometadatacommand-) - [Class GetKeyAgreementResponse ](#class-getkeyagreementresponse-) - [Class UpdateUserInfoCommand ](#class-updateuserinfocommand-) - [Enum FormFactor ](#enum-formfactor-) - [Class PinProtectedData ](#class-pinprotecteddata-) - [Enum PinUvAuthTokenPermissions ](#enum-pinuvauthtokenpermissions-) - [Enum PinUvAuthProtocol ](#enum-pinuvauthprotocol-) - [Class GetBioMetadataResponse ](#class-getbiometadataresponse-) - [Class CredentialUserInfo ](#class-credentialuserinfo-) - [Enum DeviceFlags ](#enum-deviceflags-) - [YubiKey Minidriver User Guide — YubiKey Smart Card Minidriver User Guide documentation](#yubikey-minidriver-user-guide-yubikey-smart-card-minidriver-user-guide-documentation) - [Class CoseEcPublicKey ](#class-coseecpublickey-) - [Class UserEntity ](#class-userentity-) - [Class VerifyPinCommand ](#class-verifypincommand-) - [Class SetDeviceInfoCommand ](#class-setdeviceinfocommand-) - [Class VerifyPinResponse ](#class-verifypinresponse-) - [Class SetDeviceInfoResponse ](#class-setdeviceinforesponse-) - [Class VerifyUvCommand ](#class-verifyuvcommand-) - [Class PinUvAuthProtocolBase ](#class-pinuvauthprotocolbase-) - [Class SetDeviceInfoBaseCommand ](#class-setdeviceinfobasecommand-) - [Class VerifyTemporaryPinCommand ](#class-verifytemporarypincommand-) - [Class VerifyUvResponse ](#class-verifyuvresponse-) - [Class SetLegacyDeviceConfigCommand ](#class-setlegacydeviceconfigcommand-) - [Class ChangePinCommand ](#class-changepincommand-) - [Class ChangePinResponse ](#class-changepinresponse-) - [Class SetLegacyDeviceConfigResponse ](#class-setlegacydeviceconfigresponse-) - [Class VerifyTemporaryPinResponse ](#class-verifytemporarypinresponse-) - [Class GetPinTokenCommand ](#class-getpintokencommand-) - [Unknown](#unknown) - [Class SetLegacyDeviceConfigBase ](#class-setlegacydeviceconfigbase-) - [Class GetPinUvAuthTokenResponse ](#class-getpinuvauthtokenresponse-) - [Class GetProtocolVersionCommand ](#class-getprotocolversioncommand-) - [Class InitializeAuthenticateManagementKeyCommand ](#class-initializeauthenticatemanagementkeycommand-) - [Class InitializeAuthenticateManagementKeyResponse ](#class-initializeauthenticatemanagementkeyresponse-) - [Class GetProtocolVersionResponse ](#class-getprotocolversionresponse-) - [Class SetPinResponse ](#class-setpinresponse-) - [Class VerifyFipsModeCommand ](#class-verifyfipsmodecommand-) - [Class CompleteAuthenticateManagementKeyCommand ](#class-completeauthenticatemanagementkeycommand-) - [Class MakeCredentialResponse ](#class-makecredentialresponse-) - [Class VerifyFipsModeResponse ](#class-verifyfipsmoderesponse-) - [Class MakeCredentialData ](#class-makecredentialdata-) - [Class SetPinRetriesCommand ](#class-setpinretriescommand-) - [Class SetPinCommand ](#class-setpincommand-) - [Class SetPinRetriesResponse ](#class-setpinretriesresponse-) - [Class CompleteAuthenticateManagementKeyResponse ](#class-completeauthenticatemanagementkeyresponse-) - [Class SetPinResponse ](#class-setpinresponse-) - [Class GetAssertionResponse ](#class-getassertionresponse-) - [Class ChangeReferenceDataResponse ](#class-changereferencedataresponse-) - [Class GetCredentialMetadataResponse ](#class-getcredentialmetadataresponse-) - [Class VerifyPinCommand ](#class-verifypincommand-) - [Unknown](#unknown) - [Class VerifyPinResponse ](#class-verifypinresponse-) - [Class SetManagementKeyCommand ](#class-setmanagementkeycommand-) - [Class ChangeManagementKeyResponse ](#class-changemanagementkeyresponse-) - [Class SerializedLargeBlobArray ](#class-serializedlargeblobarray-) - [Class KeyHistory ](#class-keyhistory-) - [Class GetPagedDeviceInfoResponse ](#class-getpageddeviceinforesponse-) - [Class GetMetadataResponse ](#class-getmetadataresponse-) - [Class DeleteCredentialCommand ](#class-deletecredentialcommand-) - [Class GetAssertionData ](#class-getassertiondata-) - [Class DeleteKeyCommand ](#class-deletekeycommand-) - [Class GetKeyAgreementCommand ](#class-getkeyagreementcommand-) - [Class GetPinUvAuthTokenUsingUvCommand ](#class-getpinuvauthtokenusinguvcommand-) - [Interface IYubiKeyResponseWithData ](#interface-iyubikeyresponsewithdata-tdata-) - [Class AdminData ](#class-admindata-) - [Class SetManagementKeyResponse ](#class-setmanagementkeyresponse-) - [Class EnumerateRpsBeginResponse ](#class-enumeraterpsbeginresponse-) - [Class RelyingParty ](#class-relyingparty-) - [Class EnumerateRpsGetNextResponse ](#class-enumeraterpsgetnextresponse-) - [Class ResetRetryCommand ](#class-resetretrycommand-) - [Class RegisterCommand ](#class-registercommand-) - [Yubico PIV Tool User Guide — YubiKey PIV Tool User Guide documentation](#yubico-piv-tool-user-guide-yubikey-piv-tool-user-guide-documentation) - [Class ResetRetryResponse ](#class-resetretryresponse-) - [Class GetLargeBlobResponse ](#class-getlargeblobresponse-) - [Class RegisterResponse ](#class-registerresponse-) - [Class AuthenticateResponse ](#class-authenticateresponse-) - [Class AuthenticateCommand ](#class-authenticatecommand-) - [Class SetLargeBlobResponse ](#class-setlargeblobresponse-) - [Class ImportAsymmetricKeyResponse ](#class-importasymmetrickeyresponse-) - [Class GenerateKeyPairResponse ](#class-generatekeypairresponse-) - [Class AuthenticateDecryptCommand ](#class-authenticatedecryptcommand-) - [Class AuthenticateDecryptResponse ](#class-authenticatedecryptresponse-) - [Class AuthenticateKeyAgreeResponse ](#class-authenticatekeyagreeresponse-) - [Class AuthenticateKeyAgreeCommand ](#class-authenticatekeyagreecommand-) - [Class AuthenticateSignCommand ](#class-authenticatesigncommand-) - [Class CreateAttestationStatementCommand ](#class-createattestationstatementcommand-) - [Class AuthenticateSignResponse ](#class-authenticatesignresponse-) - [Class CreateAttestationStatementResponse ](#class-createattestationstatementresponse-) - [Class PutDataResponse ](#class-putdataresponse-) - [Class PutDataCommand ](#class-putdatacommand-) - [Class ResetPivCommand ](#class-resetpivcommand-) - [Class BioEnrollSampleResult ](#class-bioenrollsampleresult-) - [Class ResetPivResponse ](#class-resetpivresponse-) - [Interface IYubiKeyResponse ](#interface-iyubikeyresponse-) - [Enum CryptographicKeyType ](#enum-cryptographickeytype-) - [Class RsaFormat ](#class-rsaformat-) - [Class ResetResponse ](#class-resetresponse-) - [Class VersionResponse ](#class-versionresponse-) - [Class ChangeManagementKeyCommand ](#class-changemanagementkeycommand-) - [Yubico Authenticator User Guide — Yubico Authenticator User Guide documentation](#yubico-authenticator-user-guide-yubico-authenticator-user-guide-documentation) - [Class CardCapabilityContainer ](#class-cardcapabilitycontainer-) - [Class GetLargeBlobCommand ](#class-getlargeblobcommand-) - [Class GetPagedDeviceInfoCommand ](#class-getpageddeviceinfocommand-) - [Class GetInfoResponse ](#class-getinforesponse-) - [Class GetNextAssertionCommand ](#class-getnextassertioncommand-) - [Class ListCredentialsResponse ](#class-listcredentialsresponse-) - [Class DeleteCredentialResponse ](#class-deletecredentialresponse-) - [Class ResetApplicationResponse ](#class-resetapplicationresponse-) - [Class GetApplicationVersionResponse ](#class-getapplicationversionresponse-) - [Class EnumerateCredentialsGetNextCommand ](#class-enumeratecredentialsgetnextcommand-) - [Class MoveKeyCommand ](#class-movekeycommand-) - [Class GetAes128SessionKeysResponse ](#class-getaes128sessionkeysresponse-) - [Class GetManagementKeyRetriesResponse ](#class-getmanagementkeyretriesresponse-) - [Class GetPinUvAuthTokenUsingPinCommand ](#class-getpinuvauthtokenusingpincommand-) - [Enum ResponseStatus ](#enum-responsestatus-) - [Class GetAes128SessionKeysCommand ](#class-getaes128sessionkeyscommand-) - [Class ResetApplicationCommand ](#class-resetapplicationcommand-) --- # YubiKey Manager (ykman) CLI User Guide — YubiKey Manager (ykman) CLI Guide documentation * [](https://docs.yubico.com/software/yubikey/tools/ykman/index.html#) * YubiKey Manager (ykman) CLI User Guide * [View page source](https://docs.yubico.com/software/yubikey/tools/ykman/_sources/index.rst.txt) * * * YubiKey Manager (ykman) CLI User Guide[](https://docs.yubico.com/software/yubikey/tools/ykman/index.html#yubikey-manager-ykman-cli-user-guide "Permalink to this heading") ============================================================================================================================================================================ * [Introduction](https://docs.yubico.com/software/yubikey/tools/ykman/intro.html) * [Features](https://docs.yubico.com/software/yubikey/tools/ykman/intro.html#features) * [Navigating this Guide](https://docs.yubico.com/software/yubikey/tools/ykman/intro.html#navigating-this-guide) * [Troubleshooting](https://docs.yubico.com/software/yubikey/tools/ykman/intro.html#troubleshooting) * [Installation](https://docs.yubico.com/software/yubikey/tools/ykman/Install_ykman.html) * [Download YubiKey Manager and ykman Installers](https://docs.yubico.com/software/yubikey/tools/ykman/Install_ykman.html#download-yubikey-manager-and-ykman-installers) * [OS-independent Installation](https://docs.yubico.com/software/yubikey/tools/ykman/Install_ykman.html#os-independent-installation) * [Windows Installation](https://docs.yubico.com/software/yubikey/tools/ykman/Install_ykman.html#windows-installation) * [MacOS](https://docs.yubico.com/software/yubikey/tools/ykman/Install_ykman.html#macos) * [MacOS Installation](https://docs.yubico.com/software/yubikey/tools/ykman/Install_ykman.html#macos-installation) * [Linux Installation](https://docs.yubico.com/software/yubikey/tools/ykman/Install_ykman.html#linux-installation) * [Developers](https://docs.yubico.com/software/yubikey/tools/ykman/Install_ykman.html#developers) * [Using the YubiKey Manager GUI](https://docs.yubico.com/software/yubikey/tools/ykman/Using_the_ykman_GUI.html) * [Launch YubiKey Manager GUI on Windows](https://docs.yubico.com/software/yubikey/tools/ykman/Using_the_ykman_GUI.html#launch-yubikey-manager-gui-on-windows) * [Launch YubiKey Manager GUI on MacOS](https://docs.yubico.com/software/yubikey/tools/ykman/Using_the_ykman_GUI.html#launch-yubikey-manager-gui-on-macos) * [YubiKey Manager GUI Version](https://docs.yubico.com/software/yubikey/tools/ykman/Using_the_ykman_GUI.html#yubikey-manager-gui-version) * [View YubiKey Firmware Version](https://docs.yubico.com/software/yubikey/tools/ykman/Using_the_ykman_GUI.html#view-yubikey-firmware-version) * [Managing Applications](https://docs.yubico.com/software/yubikey/tools/ykman/Using_the_ykman_GUI.html#managing-applications) * [Configure YubiKey Slot on YubiKey](https://docs.yubico.com/software/yubikey/tools/ykman/Using_the_ykman_GUI.html#configure-yubikey-slot-on-yubikey) * [Resetting FIDO2 Function](https://docs.yubico.com/software/yubikey/tools/ykman/Using_the_ykman_GUI.html#resetting-fido2-function) * [Using the ykman CLI](https://docs.yubico.com/software/yubikey/tools/ykman/Using_the_ykman_CLI.html) * [Locate ykman CLI Installation Path](https://docs.yubico.com/software/yubikey/tools/ykman/Using_the_ykman_CLI.html#locate-ykman-cli-installation-path) * [ykman CLI Version](https://docs.yubico.com/software/yubikey/tools/ykman/Using_the_ykman_CLI.html#ykman-cli-version) * [Launch ykman CLI on Windows](https://docs.yubico.com/software/yubikey/tools/ykman/Using_the_ykman_CLI.html#launch-ykman-cli-on-windows) * [Launch ykman CLI on macOS](https://docs.yubico.com/software/yubikey/tools/ykman/Using_the_ykman_CLI.html#launch-ykman-cli-on-macos) * [Launch Issues](https://docs.yubico.com/software/yubikey/tools/ykman/Using_the_ykman_CLI.html#launch-issues) * [Base Commands](https://docs.yubico.com/software/yubikey/tools/ykman/Base_Commands.html) * [ykman \[OPTIONS\] COMMAND \[ARGS\]…](https://docs.yubico.com/software/yubikey/tools/ykman/Base_Commands.html#ykman-options-command-args) * [ykman config \[OPTIONS\] COMMAND \[ARGS\]…](https://docs.yubico.com/software/yubikey/tools/ykman/Base_Commands.html#ykman-config-options-command-args) * [ykman config mode \[OPTIONS\] MODE](https://docs.yubico.com/software/yubikey/tools/ykman/Base_Commands.html#ykman-config-mode-options-mode) * [ykman config nfc \[OPTIONS\]](https://docs.yubico.com/software/yubikey/tools/ykman/Base_Commands.html#ykman-config-nfc-options) * [ykman config reset \[OPTIONS\]](https://docs.yubico.com/software/yubikey/tools/ykman/Base_Commands.html#ykman-config-reset-options) * [ykman config set-lock-code \[OPTIONS\]](https://docs.yubico.com/software/yubikey/tools/ykman/Base_Commands.html#ykman-config-set-lock-code-options) * [ykman config usb \[OPTIONS\]](https://docs.yubico.com/software/yubikey/tools/ykman/Base_Commands.html#ykman-config-usb-options) * [ykman info \[OPTIONS\]](https://docs.yubico.com/software/yubikey/tools/ykman/Base_Commands.html#ykman-info-options) * [ykman list \[OPTIONS\]](https://docs.yubico.com/software/yubikey/tools/ykman/Base_Commands.html#ykman-list-options) * [ykman script \[OPTIONS\] FILE \[ARGUMENTS\]](https://docs.yubico.com/software/yubikey/tools/ykman/Base_Commands.html#ykman-script-options-file-arguments) * [Acronyms](https://docs.yubico.com/software/yubikey/tools/ykman/Base_Commands.html#acronyms) * [FIDO Commands](https://docs.yubico.com/software/yubikey/tools/ykman/FIDO_Commands.html) * [ykman fido \[OPTIONS\] COMMAND \[ARGS\]…](https://docs.yubico.com/software/yubikey/tools/ykman/FIDO_Commands.html#ykman-fido-options-command-args) * [ykman fido access \[OPTIONS\] COMMAND \[ARGS\]…](https://docs.yubico.com/software/yubikey/tools/ykman/FIDO_Commands.html#ykman-fido-access-options-command-args) * [ykman fido access change-pin \[OPTIONS\]](https://docs.yubico.com/software/yubikey/tools/ykman/FIDO_Commands.html#ykman-fido-access-change-pin-options) * [ykman fido access force-change \[OPTIONS\]](https://docs.yubico.com/software/yubikey/tools/ykman/FIDO_Commands.html#ykman-fido-access-force-change-options) * [ykman fido access set-min-length \[OPTIONS\] LENGTH](https://docs.yubico.com/software/yubikey/tools/ykman/FIDO_Commands.html#ykman-fido-access-set-min-length-options-length) * [ykman fido access unlock \[OPTIONS\] (Deprecated)](https://docs.yubico.com/software/yubikey/tools/ykman/FIDO_Commands.html#ykman-fido-access-unlock-options-deprecated) * [ykman fido access verify-pin \[OPTIONS\]](https://docs.yubico.com/software/yubikey/tools/ykman/FIDO_Commands.html#ykman-fido-access-verify-pin-options) * [ykman fido config \[OPTIONS\] COMMAND \[ARGS\]…](https://docs.yubico.com/software/yubikey/tools/ykman/FIDO_Commands.html#ykman-fido-config-options-command-args) * [ykman fido config enable-ep-attestation \[OPTIONS\]](https://docs.yubico.com/software/yubikey/tools/ykman/FIDO_Commands.html#ykman-fido-config-enable-ep-attestation-options) * [ykman fido config toggle-always-uv \[OPTIONS\]](https://docs.yubico.com/software/yubikey/tools/ykman/FIDO_Commands.html#ykman-fido-config-toggle-always-uv-options) * [ykman fido credentials \[OPTIONS\] COMMAND \[ARGS\]…](https://docs.yubico.com/software/yubikey/tools/ykman/FIDO_Commands.html#ykman-fido-credentials-options-command-args) * [ykman fido credentials delete \[OPTIONS\] CREDENTIAL\_ID](https://docs.yubico.com/software/yubikey/tools/ykman/FIDO_Commands.html#ykman-fido-credentials-delete-options-credential-id) * [ykman fido credentials list \[OPTIONS\]](https://docs.yubico.com/software/yubikey/tools/ykman/FIDO_Commands.html#ykman-fido-credentials-list-options) * [ykman fido fingerprints \[OPTIONS\] COMMAND \[ARGS\]…](https://docs.yubico.com/software/yubikey/tools/ykman/FIDO_Commands.html#ykman-fido-fingerprints-options-command-args) * [ykman fido fingerprints add \[OPTIONS\] NAME](https://docs.yubico.com/software/yubikey/tools/ykman/FIDO_Commands.html#ykman-fido-fingerprints-add-options-name) * [ykman fido fingerprints delete \[OPTIONS\] ID](https://docs.yubico.com/software/yubikey/tools/ykman/FIDO_Commands.html#ykman-fido-fingerprints-delete-options-id) * [ykman fido fingerprints list \[OPTIONS\]](https://docs.yubico.com/software/yubikey/tools/ykman/FIDO_Commands.html#ykman-fido-fingerprints-list-options) * [ykman fido fingerprints rename \[OPTIONS\] ID NAME](https://docs.yubico.com/software/yubikey/tools/ykman/FIDO_Commands.html#ykman-fido-fingerprints-rename-options-id-name) * [ykman fido info](https://docs.yubico.com/software/yubikey/tools/ykman/FIDO_Commands.html#ykman-fido-info) * [ykman fido reset \[OPTIONS\]](https://docs.yubico.com/software/yubikey/tools/ykman/FIDO_Commands.html#ykman-fido-reset-options) * [Hidden Commands](https://docs.yubico.com/software/yubikey/tools/ykman/Hidden_Commands.html) * [ykman apdu \[OPTIONS\] \[APDU\]](https://docs.yubico.com/software/yubikey/tools/ykman/Hidden_Commands.html#ykman-apdu-options-apdu) * [ykman sd \[OPTIONS\] COMMAND \[ARGS\]](https://docs.yubico.com/software/yubikey/tools/ykman/Hidden_Commands.html#ykman-sd-options-command-args) * [ykman sd info \[OPTIONS\]](https://docs.yubico.com/software/yubikey/tools/ykman/Hidden_Commands.html#ykman-sd-info-options) * [ykman sd keys \[OPTIONS\] COMMAND \[ARGS\]](https://docs.yubico.com/software/yubikey/tools/ykman/Hidden_Commands.html#ykman-sd-keys-options-command-args) * [ykman sd keys delete \[OPTIONS\] KID KVN](https://docs.yubico.com/software/yubikey/tools/ykman/Hidden_Commands.html#ykman-sd-keys-delete-options-kid-kvn) * [ykman sd keys export \[OPTIONS\] KID KVN OUTPUT](https://docs.yubico.com/software/yubikey/tools/ykman/Hidden_Commands.html#ykman-sd-keys-export-options-kid-kvn-output) * [ykman sd keys generate \[OPTIONS\] KID KVN PUBLIC-KEY](https://docs.yubico.com/software/yubikey/tools/ykman/Hidden_Commands.html#ykman-sd-keys-generate-options-kid-kvn-public-key) * [ykman sd keys import \[OPTIONS\] KID KVN INPUT](https://docs.yubico.com/software/yubikey/tools/ykman/Hidden_Commands.html#ykman-sd-keys-import-options-kid-kvn-input) * [ykman sd keys set-allowlist \[OPTIONS\] KID KVN \[SERIALS\]](https://docs.yubico.com/software/yubikey/tools/ykman/Hidden_Commands.html#ykman-sd-keys-set-allowlist-options-kid-kvn-serials) * [ykman sd reset \[OPTIONS\]](https://docs.yubico.com/software/yubikey/tools/ykman/Hidden_Commands.html#ykman-sd-reset-options) * [HSMauth Commands](https://docs.yubico.com/software/yubikey/tools/ykman/HSMauth_Commands.html) * [Enable or Disable YubiHSM Auth on a YubiKey](https://docs.yubico.com/software/yubikey/tools/ykman/HSMauth_Commands.html#enable-or-disable-yubihsm-auth-on-a-yubikey) * [ykman hsmauth \[OPTIONS\] COMMAND \[ARGS\]…](https://docs.yubico.com/software/yubikey/tools/ykman/HSMauth_Commands.html#ykman-hsmauth-options-command-args) * [ykman hsmauth access \[OPTIONS\] COMMAND \[ARGS\]…](https://docs.yubico.com/software/yubikey/tools/ykman/HSMauth_Commands.html#ykman-hsmauth-access-options-command-args) * [ykman hsmauth access change-management-password](https://docs.yubico.com/software/yubikey/tools/ykman/HSMauth_Commands.html#ykman-hsmauth-access-change-management-password) * [ykman hsmauth credentials \[OPTIONS\] COMMAND \[ARGS\]…](https://docs.yubico.com/software/yubikey/tools/ykman/HSMauth_Commands.html#ykman-hsmauth-credentials-options-command-args) * [ykman hsmauth credentials delete \[OPTIONS\] LABEL](https://docs.yubico.com/software/yubikey/tools/ykman/HSMauth_Commands.html#ykman-hsmauth-credentials-delete-options-label) * [ykman hsmauth credentials derive \[OPTIONS\] LABEL](https://docs.yubico.com/software/yubikey/tools/ykman/HSMauth_Commands.html#ykman-hsmauth-credentials-derive-options-label) * [ykman hsmauth credentials export \[OPTIONS\] LABEL PUBLIC-KEY](https://docs.yubico.com/software/yubikey/tools/ykman/HSMauth_Commands.html#ykman-hsmauth-credentials-export-options-label-public-key) * [ykman hsmauth credentials generate \[OPTIONS\] LABEL](https://docs.yubico.com/software/yubikey/tools/ykman/HSMauth_Commands.html#ykman-hsmauth-credentials-generate-options-label) * [ykman hsmauth credentials import \[OPTIONS\] LABEL PRIVATE-KEY](https://docs.yubico.com/software/yubikey/tools/ykman/HSMauth_Commands.html#ykman-hsmauth-credentials-import-options-label-private-key) * [ykman hsmauth credentials list \[OPTIONS\]](https://docs.yubico.com/software/yubikey/tools/ykman/HSMauth_Commands.html#ykman-hsmauth-credentials-list-options) * [ykman hsmauth credentials symmetric \[OPTIONS\] LABEL](https://docs.yubico.com/software/yubikey/tools/ykman/HSMauth_Commands.html#ykman-hsmauth-credentials-symmetric-options-label) * [ykman hsmauth info \[OPTIONS\]](https://docs.yubico.com/software/yubikey/tools/ykman/HSMauth_Commands.html#ykman-hsmauth-info-options) * [ykman hsmauth reset \[OPTIONS\]](https://docs.yubico.com/software/yubikey/tools/ykman/HSMauth_Commands.html#ykman-hsmauth-reset-options) * [OATH Commands](https://docs.yubico.com/software/yubikey/tools/ykman/OATH_Commands.html) * [ykman oath \[OPTIONS\] COMMAND \[ARGS\]…](https://docs.yubico.com/software/yubikey/tools/ykman/OATH_Commands.html#ykman-oath-options-command-args) * [ykman oath access \[OPTIONS\] COMMAND \[ARGS\]…](https://docs.yubico.com/software/yubikey/tools/ykman/OATH_Commands.html#ykman-oath-access-options-command-args) * [ykman oath access change \[OPTIONS\]](https://docs.yubico.com/software/yubikey/tools/ykman/OATH_Commands.html#ykman-oath-access-change-options) * [ykman oath access forget \[OPTIONS\]](https://docs.yubico.com/software/yubikey/tools/ykman/OATH_Commands.html#ykman-oath-access-forget-options) * [ykman oath access remember \[OPTIONS\]](https://docs.yubico.com/software/yubikey/tools/ykman/OATH_Commands.html#ykman-oath-access-remember-options) * [ykman oath accounts \[OPTIONS\] COMMAND \[ARGS\]…](https://docs.yubico.com/software/yubikey/tools/ykman/OATH_Commands.html#ykman-oath-accounts-options-command-args) * [ykman oath accounts add \[OPTIONS\] NAME \[SECRET\]](https://docs.yubico.com/software/yubikey/tools/ykman/OATH_Commands.html#ykman-oath-accounts-add-options-name-secret) * [ykman oath accounts code \[OPTIONS\] \[QUERY\]](https://docs.yubico.com/software/yubikey/tools/ykman/OATH_Commands.html#ykman-oath-accounts-code-options-query) * [ykman oath accounts delete \[OPTIONS\] QUERY](https://docs.yubico.com/software/yubikey/tools/ykman/OATH_Commands.html#ykman-oath-accounts-delete-options-query) * [ykman oath accounts list \[OPTIONS\]](https://docs.yubico.com/software/yubikey/tools/ykman/OATH_Commands.html#ykman-oath-accounts-list-options) * [ykman oath accounts rename \[OPTIONS\] QUERY NAME](https://docs.yubico.com/software/yubikey/tools/ykman/OATH_Commands.html#ykman-oath-accounts-rename-options-query-name) * [ykman oath accounts uri \[OPTIONS\] URI](https://docs.yubico.com/software/yubikey/tools/ykman/OATH_Commands.html#ykman-oath-accounts-uri-options-uri) * [ykman oath info \[OPTIONS\]](https://docs.yubico.com/software/yubikey/tools/ykman/OATH_Commands.html#ykman-oath-info-options) * [ykman oath reset \[OPTIONS\]](https://docs.yubico.com/software/yubikey/tools/ykman/OATH_Commands.html#ykman-oath-reset-options) * [OpenPGP Commands](https://docs.yubico.com/software/yubikey/tools/ykman/OpenPGP_Commands.html) * [ykman openpgp \[OPTIONS\] COMMAND \[ARGS\]…](https://docs.yubico.com/software/yubikey/tools/ykman/OpenPGP_Commands.html#ykman-openpgp-options-command-args) * [ykman openpgp access \[OPTIONS\] COMMAND \[ARGS\]…](https://docs.yubico.com/software/yubikey/tools/ykman/OpenPGP_Commands.html#ykman-openpgp-access-options-command-args) * [ykman openpgp access change-admin-pin \[OPTIONS\]](https://docs.yubico.com/software/yubikey/tools/ykman/OpenPGP_Commands.html#ykman-openpgp-access-change-admin-pin-options) * [ykman openpgp access change-pin \[OPTIONS\]](https://docs.yubico.com/software/yubikey/tools/ykman/OpenPGP_Commands.html#ykman-openpgp-access-change-pin-options) * [ykman openpgp access change-reset-code \[OPTIONS\]](https://docs.yubico.com/software/yubikey/tools/ykman/OpenPGP_Commands.html#ykman-openpgp-access-change-reset-code-options) * [ykman openpgp access set-retries \[OPTIONS\] PIN-RETRIES RESET-CODE-RETRIES ADMIN-PIN-RETRIES](https://docs.yubico.com/software/yubikey/tools/ykman/OpenPGP_Commands.html#ykman-openpgp-access-set-retries-options-pin-retries-reset-code-retries-admin-pin-retries) * [ykman openpgp access set-signature-policy \[OPTIONS\] POLICY](https://docs.yubico.com/software/yubikey/tools/ykman/OpenPGP_Commands.html#ykman-openpgp-access-set-signature-policy-options-policy) * [ykman openpgp access unblock-pin \[OPTIONS\]](https://docs.yubico.com/software/yubikey/tools/ykman/OpenPGP_Commands.html#ykman-openpgp-access-unblock-pin-options) * [ykman openpgp certificates \[OPTIONS\] COMMAND \[ARGS\]…](https://docs.yubico.com/software/yubikey/tools/ykman/OpenPGP_Commands.html#ykman-openpgp-certificates-options-command-args) * [ykman openpgp certificates delete \[OPTIONS\] KEY](https://docs.yubico.com/software/yubikey/tools/ykman/OpenPGP_Commands.html#ykman-openpgp-certificates-delete-options-key) * [ykman openpgp certificates export \[OPTIONS\] KEY CERTIFICATE](https://docs.yubico.com/software/yubikey/tools/ykman/OpenPGP_Commands.html#ykman-openpgp-certificates-export-options-key-certificate) * [ykman openpgp certificates import \[OPTIONS\] KEY CERTIFICATE](https://docs.yubico.com/software/yubikey/tools/ykman/OpenPGP_Commands.html#ykman-openpgp-certificates-import-options-key-certificate) * [ykman openpgp info \[OPTIONS\]](https://docs.yubico.com/software/yubikey/tools/ykman/OpenPGP_Commands.html#ykman-openpgp-info-options) * [ykman openpgp keys \[OPTIONS\] COMMAND \[ARGS\]…](https://docs.yubico.com/software/yubikey/tools/ykman/OpenPGP_Commands.html#ykman-openpgp-keys-options-command-args) * [ykman openpgp keys attest \[OPTIONS\] KEY CERTIFICATE](https://docs.yubico.com/software/yubikey/tools/ykman/OpenPGP_Commands.html#ykman-openpgp-keys-attest-options-key-certificate) * [ykman openpgp keys import \[OPTIONS\] KEY PRIVATE-KEY](https://docs.yubico.com/software/yubikey/tools/ykman/OpenPGP_Commands.html#ykman-openpgp-keys-import-options-key-private-key) * [ykman openpgp keys info \[OPTIONS\] KEY](https://docs.yubico.com/software/yubikey/tools/ykman/OpenPGP_Commands.html#ykman-openpgp-keys-info-options-key) * [ykman openpgp keys set-touch \[OPTIONS\] KEY POLICY](https://docs.yubico.com/software/yubikey/tools/ykman/OpenPGP_Commands.html#ykman-openpgp-keys-set-touch-options-key-policy) * [ykman openpgp reset \[OPTIONS\]](https://docs.yubico.com/software/yubikey/tools/ykman/OpenPGP_Commands.html#ykman-openpgp-reset-options) * [OTP Commands](https://docs.yubico.com/software/yubikey/tools/ykman/OTP_Commands.html) * [ykman otp \[OPTIONS\] COMMAND \[ARGS\]…](https://docs.yubico.com/software/yubikey/tools/ykman/OTP_Commands.html#ykman-otp-options-command-args) * [ykman otp calculate \[OPTIONS\] {1|2} \[CHALLENGE\]](https://docs.yubico.com/software/yubikey/tools/ykman/OTP_Commands.html#ykman-otp-calculate-options-1-2-challenge) * [ykman otp chalresp \[OPTIONS\] {1|2} \[KEY\]](https://docs.yubico.com/software/yubikey/tools/ykman/OTP_Commands.html#ykman-otp-chalresp-options-1-2-key) * [ykman otp delete \[OPTIONS\] {1|2}](https://docs.yubico.com/software/yubikey/tools/ykman/OTP_Commands.html#ykman-otp-delete-options-1-2) * [ykman otp hotp \[OPTIONS\] {1|2} \[KEY\]](https://docs.yubico.com/software/yubikey/tools/ykman/OTP_Commands.html#ykman-otp-hotp-options-1-2-key) * [ykman otp info \[OPTIONS\]](https://docs.yubico.com/software/yubikey/tools/ykman/OTP_Commands.html#ykman-otp-info-options) * [ykman otp ndef \[OPTIONS\] {1|2}](https://docs.yubico.com/software/yubikey/tools/ykman/OTP_Commands.html#ykman-otp-ndef-options-1-2) * [ykman otp settings \[OPTIONS\] {1|2}](https://docs.yubico.com/software/yubikey/tools/ykman/OTP_Commands.html#ykman-otp-settings-options-1-2) * [ykman otp static \[OPTIONS\] {1|2} \[PASSWORD\]](https://docs.yubico.com/software/yubikey/tools/ykman/OTP_Commands.html#ykman-otp-static-options-1-2-password) * [ykman otp swap \[OPTIONS\]](https://docs.yubico.com/software/yubikey/tools/ykman/OTP_Commands.html#ykman-otp-swap-options) * [ykman otp yubiotp \[OPTIONS\] {1|2}](https://docs.yubico.com/software/yubikey/tools/ykman/OTP_Commands.html#ykman-otp-yubiotp-options-1-2) * [PIV Commands](https://docs.yubico.com/software/yubikey/tools/ykman/PIV_Commands.html) * [ykman piv \[OPTIONS\] COMMAND \[ARGS\]…](https://docs.yubico.com/software/yubikey/tools/ykman/PIV_Commands.html#ykman-piv-options-command-args) * [ykman piv access \[OPTIONS\] COMMAND \[ARGS\]…](https://docs.yubico.com/software/yubikey/tools/ykman/PIV_Commands.html#ykman-piv-access-options-command-args) * [ykman piv access change-management-key \[OPTIONS\]](https://docs.yubico.com/software/yubikey/tools/ykman/PIV_Commands.html#ykman-piv-access-change-management-key-options) * [ykman piv access change-pin \[OPTIONS\]](https://docs.yubico.com/software/yubikey/tools/ykman/PIV_Commands.html#ykman-piv-access-change-pin-options) * [ykman piv access change-puk \[OPTIONS\]](https://docs.yubico.com/software/yubikey/tools/ykman/PIV_Commands.html#ykman-piv-access-change-puk-options) * [ykman piv access set-retries \[OPTIONS\] PIN-RETRIES PUK-RETRIES](https://docs.yubico.com/software/yubikey/tools/ykman/PIV_Commands.html#ykman-piv-access-set-retries-options-pin-retries-puk-retries) * [ykman piv access unblock-pin \[OPTIONS\]](https://docs.yubico.com/software/yubikey/tools/ykman/PIV_Commands.html#ykman-piv-access-unblock-pin-options) * [ykman piv certificates \[OPTIONS\] COMMAND \[ARGS\]…](https://docs.yubico.com/software/yubikey/tools/ykman/PIV_Commands.html#ykman-piv-certificates-options-command-args) * [ykman piv certificates delete \[OPTIONS\] SLOT](https://docs.yubico.com/software/yubikey/tools/ykman/PIV_Commands.html#ykman-piv-certificates-delete-options-slot) * [ykman piv certificates export \[OPTIONS\] SLOT CERTIFICATE](https://docs.yubico.com/software/yubikey/tools/ykman/PIV_Commands.html#ykman-piv-certificates-export-options-slot-certificate) * [ykman piv certificates generate \[OPTIONS\] SLOT PUBLIC-KEY](https://docs.yubico.com/software/yubikey/tools/ykman/PIV_Commands.html#ykman-piv-certificates-generate-options-slot-public-key) * [ykman piv certificates import \[OPTIONS\] SLOT CERTIFICATE](https://docs.yubico.com/software/yubikey/tools/ykman/PIV_Commands.html#ykman-piv-certificates-import-options-slot-certificate) * [ykman piv certificates request \[OPTIONS\] SLOT PUBLIC-KEY CSR](https://docs.yubico.com/software/yubikey/tools/ykman/PIV_Commands.html#ykman-piv-certificates-request-options-slot-public-key-csr) * [ykman piv info \[OPTIONS\]](https://docs.yubico.com/software/yubikey/tools/ykman/PIV_Commands.html#ykman-piv-info-options) * [ykman piv keys \[OPTIONS\] COMMAND \[ARGS\]…](https://docs.yubico.com/software/yubikey/tools/ykman/PIV_Commands.html#ykman-piv-keys-options-command-args) * [ykman piv keys attest \[OPTIONS\] SLOT CERTIFICATE](https://docs.yubico.com/software/yubikey/tools/ykman/PIV_Commands.html#ykman-piv-keys-attest-options-slot-certificate) * [ykman piv keys delete \[OPTIONS\] SLOT](https://docs.yubico.com/software/yubikey/tools/ykman/PIV_Commands.html#ykman-piv-keys-delete-options-slot) * [ykman piv keys export \[OPTIONS\] SLOT PUBLIC-KEY](https://docs.yubico.com/software/yubikey/tools/ykman/PIV_Commands.html#ykman-piv-keys-export-options-slot-public-key) * [ykman piv keys generate \[OPTIONS\] SLOT PUBLIC-KEY](https://docs.yubico.com/software/yubikey/tools/ykman/PIV_Commands.html#ykman-piv-keys-generate-options-slot-public-key) * [ykman piv keys import \[OPTIONS\] SLOT PRIVATE-KEY](https://docs.yubico.com/software/yubikey/tools/ykman/PIV_Commands.html#ykman-piv-keys-import-options-slot-private-key) * [ykman piv keys info \[OPTIONS\] SLOT](https://docs.yubico.com/software/yubikey/tools/ykman/PIV_Commands.html#ykman-piv-keys-info-options-slot) * [ykman piv keys move \[OPTIONS\] SOURCE DEST](https://docs.yubico.com/software/yubikey/tools/ykman/PIV_Commands.html#ykman-piv-keys-move-options-source-dest) * [ykman piv objects \[OPTIONS\] COMMAND \[ARGS\]…](https://docs.yubico.com/software/yubikey/tools/ykman/PIV_Commands.html#ykman-piv-objects-options-command-args) * [ykman piv objects export \[OPTIONS\] OBJECT OUTPUT](https://docs.yubico.com/software/yubikey/tools/ykman/PIV_Commands.html#ykman-piv-objects-export-options-object-output) * [ykman piv objects generate \[OPTIONS\] OBJECT](https://docs.yubico.com/software/yubikey/tools/ykman/PIV_Commands.html#ykman-piv-objects-generate-options-object) * [ykman piv objects import \[OPTIONS\] OBJECT DATA](https://docs.yubico.com/software/yubikey/tools/ykman/PIV_Commands.html#ykman-piv-objects-import-options-object-data) * [ykman piv reset \[OPTIONS\]](https://docs.yubico.com/software/yubikey/tools/ykman/PIV_Commands.html#ykman-piv-reset-options) * [Copyright](https://docs.yubico.com/software/yubikey/tools/ykman/copyright.html) * [Trademarks](https://docs.yubico.com/software/yubikey/tools/ykman/copyright.html#trademarks) * [Disclaimer](https://docs.yubico.com/software/yubikey/tools/ykman/copyright.html#disclaimer) * [Contact Information](https://docs.yubico.com/software/yubikey/tools/ykman/copyright.html#contact-information) * [Getting Help](https://docs.yubico.com/software/yubikey/tools/ykman/copyright.html#getting-help) * [Feedback](https://docs.yubico.com/software/yubikey/tools/ykman/copyright.html#feedback) * [Document Updated](https://docs.yubico.com/software/yubikey/tools/ykman/copyright.html#document-updated) [Cookies](https://www.yubico.com/support/terms-conditions/cookie-notice/) | [Privacy Policy](https://www.yubico.com/support/terms-conditions/privacy-notice/) --- # Introduction — YubiKey Manager (ykman) CLI Guide documentation * [](https://docs.yubico.com/software/yubikey/tools/ykman/index.html) * Introduction * [View page source](https://docs.yubico.com/software/yubikey/tools/ykman/_sources/intro.rst.txt) * * * Introduction[](https://docs.yubico.com/software/yubikey/tools/ykman/intro.html#introduction "Permalink to this heading") ========================================================================================================================== Yubico’s **ykman** CLI (command line interface) is an advanced cross-platform tool for managing and configuring YubiKeys. Interacting with ykman involves sending text-based commands through a terminal or command prompt. ykman uses Python 3.9 (or later) and supports features of the latest YubiKey firmware (5.7+). The **YubiKey Manager** GUI (graphical user interface) application is the visual interface version of YubiKey Manager. Interacting with the GUI involves clicking through intuitive screens and buttons of a desktop application. While the GUI application and CLI tool share some YubiKey configuration abilities, the CLI provides more options, advanced configuration abilities, and up-to-date features. Important End-of-Life (EOL) for the YubiKey Manager GUI was announced on February 19, 2025 and will commence on February 19, 2026. The YubiKey Manager GUI will not be supported by Yubico following the EOL date. For more details, see Yubico’s [End-of-Life policy](https://www.yubico.com/support/terms-conditions/yubico-end-of-life-policy/) and the [End-of-Life Products page](https://www.yubico.com/support/terms-conditions/yubico-end-of-life-policy/eol-products/) . For an alternative to the YubiKey Manager GUI, see the [Yubico Authenticator](https://www.yubico.com/products/yubico-authenticator/) application. Yubico Authenticator supports the latest YubiKey features and is available for desktop and mobile devices. Features[](https://docs.yubico.com/software/yubikey/tools/ykman/intro.html#features "Permalink to this heading") ------------------------------------------------------------------------------------------------------------------ The ykman CLI is the premier tool for advanced management and configuration of all YubiKey applications (FIDO2, FIDO U2F, PIV, Yubico OTP, YubiHSM Auth, OpenPGP, OATH, Security Domain). Capabilities include: * Importing and managing PIV certificates * Running scripts * Resetting YubiKey applications to their factory default states * Displaying YubiKey information, including the serial number and firmware version * Configuring a YubiKey’s Secure Channel Protocol keys (SCP03 and SCP11) * Enabling and disabling USB and NFC interfaces * Configuring an OTP application slot * Managing a YubiKey’s configuration lock code * Creating a FIDO2 PIN * Executing [APDU](https://docs.yubico.com/yesdk/users-manual/yubikey-reference/apdu.html) (application protocol data unit) commands. Navigating this Guide[](https://docs.yubico.com/software/yubikey/tools/ykman/intro.html#navigating-this-guide "Permalink to this heading") -------------------------------------------------------------------------------------------------------------------------------------------- This guide contains the instructions for using both the ykman CLI tool and the YubiKey Manager GUI. The majority of this guide describes the ykman CLI commands, which are organized by YubiKey application. General YubiKey commands are listed in [Base Commands](https://docs.yubico.com/software/yubikey/tools/ykman/Base_Commands.html#base-commands-label) . For YubiKey Manager GUI tasks, see the chapter on [Using the YubiKey Manager GUI](https://docs.yubico.com/software/yubikey/tools/ykman/Using_the_ykman_GUI.html#gui-label) . Troubleshooting[](https://docs.yubico.com/software/yubikey/tools/ykman/intro.html#troubleshooting "Permalink to this heading") -------------------------------------------------------------------------------------------------------------------------------- If you attempt to use a CLI/GUI command and it fails, the cause could be due to one of the following factors: * The CLI/GUI you are using is not the latest version * Your YubiKey model does not support the feature * Your YubiKey’s firmware does not include the feature To verify if your CLI/GUI version supports a particular feature, check the release notes: * [ykman CLI Release Notes](https://developers.yubico.com/yubikey-manager/Release_Notes.html) * [YubiKey Manager GUI Release Notes](https://developers.yubico.com/yubikey-manager-qt/Release_Notes.html) To check your YubiKey’s model and firmware version, use the `ykman info` command with the ykman CLI tool or visit the [Home](https://docs.yubico.com/software/yubikey/tools/authenticator/auth-guide/settings.html#the-home-page-yubikey-at-a-glance) (desktop, Android) or [Configuration](https://docs.yubico.com/software/yubikey/tools/authenticator/auth-guide/settings.html#yubikey-overview) (iOS, iPadOS) page in Yubico Authenticator. Note Yubico periodically updates the firmware to take advantage of features and capabilities introduced into the ecosystem. YubiKeys are programmed in Yubico’s facilities with the latest available firmware and once programmed cannot be updated to another version. The firmware cannot be altered or removed from a YubiKey. * * * Click for [Yubico Support](http://yubi.co/support) . [Cookies](https://www.yubico.com/support/terms-conditions/cookie-notice/) | [Privacy Policy](https://www.yubico.com/support/terms-conditions/privacy-notice/) --- # Installation — YubiKey Manager (ykman) CLI Guide documentation * [](https://docs.yubico.com/software/yubikey/tools/ykman/index.html) * Installation * [View page source](https://docs.yubico.com/software/yubikey/tools/ykman/_sources/Install_ykman.rst.txt) * * * Installation[](https://docs.yubico.com/software/yubikey/tools/ykman/Install_ykman.html#installation "Permalink to this heading") ================================================================================================================================== Important End-of-Life (EOL) for the YubiKey Manager GUI was announced on February 19, 2025 and will commence on February 19, 2026. The YubiKey Manager GUI will not be supported by Yubico following the EOL date. For more details, see Yubico’s [End-of-Life policy](https://www.yubico.com/support/terms-conditions/yubico-end-of-life-policy/) and the [End-of-Life Products page](https://www.yubico.com/support/terms-conditions/yubico-end-of-life-policy/eol-products/) . For an alternative to the YubiKey Manager GUI, see the [Yubico Authenticator](https://www.yubico.com/products/yubico-authenticator/) application. Yubico Authenticator supports the latest YubiKey features and is available for desktop and mobile devices. Both YubiKey Manager (the GUI) and ykman (the CLI) can be installed on **Windows**, **macOS**, and **Linux** systems. The GUI is bundled with an old version of the CLI. Each has its own installer for each OS platform. Unfortunately, on developers.yubico.com both the GUI and the CLI are frequently referred to as “YubiKey Manager”. In this guide we try to make the distinction by calling the GUI “YubiKey Manager” and the CLI “ykman”. Download YubiKey Manager and ykman Installers[](https://docs.yubico.com/software/yubikey/tools/ykman/Install_ykman.html#download-yubikey-manager-and-ykman-installers "Permalink to this heading") ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- * Download the **YubiKey Manager GUI** installers from: [yubikey-manager-qt Releases](https://developers.yubico.com/yubikey-manager-qt/Releases/) . Note that the URL and filenames include `qt` - this identifies it as the YubiKey Manager GUI installer. > Important > > The installer for the YubiKey Manager GUI bundles together the GUI with the ykman CLI. **However, the ykman CLI that is bundled with the YubiKey Manager GUI is not the most recent version.** For the latest ykman CLI, download the tool separately. * Download **YubiKey Manager (ykman) CLI installer** from: [yubikey-manager Releases](https://developers.yubico.com/yubikey-manager/Releases/) . Note that download site refers to the ykman CLI version as yubiKey-manager. Note Additional installation packages may be available from third parties. ### YubiKey Manager Versions and Installer files[](https://docs.yubico.com/software/yubikey/tools/ykman/Install_ykman.html#yubikey-manager-versions-and-installer-files "Permalink to this heading") The table lists the latest installers released. See the download pages for previous versions. For GUI releases see, [yubikey-manager-qt Releases](https://developers.yubico.com/yubikey-manager-qt/Releases/) . Notice there is a `-qt` in all the GUI version installer filenames. For CLI releases see, [yubikey-manager Releases](https://developers.yubico.com/yubikey-manager/Releases/) . | | | | | | --- | --- | --- | --- |**ykman (CLI) Installers**[](https://docs.yubico.com/software/yubikey/tools/ykman/Install_ykman.html#id4 "Permalink to this table") | Version | Installer | OS | Release Date | | --- | --- | --- | --- | | 5.7.0 | yubikey\_manager-5.7.0.tar.gz | Ubuntu | 2025-05-26 | | 5.7.0 | yubikey-manager-5.7.0-mac.pkg | macOS | 2025-05-26 | | 5.7.0 | yubikey-manager-5.7.0-win64.msi | Windows 64 bit | 2025-05-26 | | | | | | | --- | --- | --- | --- |**YubiKey Manager (GUI) Installers**[](https://docs.yubico.com/software/yubikey/tools/ykman/Install_ykman.html#id5 "Permalink to this table") | Version | Installer | OS | Release Date | | --- | --- | --- | --- | | 1.2.6 | yubikey-manager-qt-1.2.6-win32.exe | Windows 32 bit | 2024-04-04 | | 1.2.6 | yubikey-manager-qt-1.2.6-win64.exe | Windows 64 bit | 2024-04-04 | | 1.2.5 | yubikey-manager-qt-1.2.5.tar.gz | Linux - Ubuntu | 2023-02-03 | | 1.2.5 | yubikey-manager-qt-1.2.5-linux.AppImage | Linus\_AppImage | 2023-02-03 | | 1.2.5 | yubikey-manager-qt-1.2.5-mac.pkg | macOS | 2023-02-03 | OS-independent Installation[](https://docs.yubico.com/software/yubikey/tools/ykman/Install_ykman.html#os-independent-installation "Permalink to this heading") ---------------------------------------------------------------------------------------------------------------------------------------------------------------- ykman (CLI version) can be installed independently of platform by using `pip` (or equivalent). This installation method uses the Python package manager, which might be useful for people who are using the libraries that come with ykman for writing Python software. See the [YubiKey Manager CLI for Python](https://developers.yubico.com/yubikey-manager/) . Note PIP (or equivalent) must first be installed on the target system. For the latest ykman version: `pip install --user yubikey-manager` For the YubiKey Manager GUI version (which has an outdated ykman CLI): `pip install --user yubikey-manager-qt-` ### Command Prompt[](https://docs.yubico.com/software/yubikey/tools/ykman/Install_ykman.html#command-prompt "Permalink to this heading") To install YubiKey Manager (the GUI and the (old) CLI) on Windows from Command Prompt (CMD): 1. Press the Windows key and type: `cmd` 2. Select **Run as administrator** 3. Select **Yes** when prompted to run the app in elevated mode 4. Change directory (`cd`) to where ykman was downloaded 5. Type (paste) the following: `yubikey-manager-qt-1.2.3.win64.exe` and press **Enter**. Replace the filename, with the actual the filename that includes the version information. For example: `yubikey-manager-1.2.3.win64.exe`. Then press **Enter**. \`\`pip install --user yubikey-manager-\`\` Note The YubiKey Manager installers with the `-qt` in the filename are for the GUI version. The installers without the `-qt` in the filename are for ykman, the CLI. Windows Installation[](https://docs.yubico.com/software/yubikey/tools/ykman/Install_ykman.html#windows-installation "Permalink to this heading") -------------------------------------------------------------------------------------------------------------------------------------------------- Install the YubiKey Manager GUI and the YubiKey Manager CLI separately. ### Install YubiKey Manager GUI[](https://docs.yubico.com/software/yubikey/tools/ykman/Install_ykman.html#install-yubikey-manager-gui "Permalink to this heading") When installing from the `.exe` package (see below), installation can be made to run silently (i.e., without user interaction) by adding `/S` to the install command. 1. Download the installer. See [Download YubiKey Manager and ykman Installers](https://docs.yubico.com/software/yubikey/tools/ykman/Install_ykman.html#download-label) . 2. Open a command terminal and change to your downloads directory. C:\\Users\\ \> cd Downloads C:\\Users\\\\Downloads \> 3. Confirm the installer is downloaded. Enter directory command, `dir`. View the response for the installer. For example, `yubikey-manager-qt-1.2.6-win32.exe`. 4. Enter the installation command. The example includes designating the installation path using the `/D` option. C:\\Users\\\\Downloads \>.\\yubikey-manager-qt-1.2.6-win32.exe /D "C:\\Program Files\\Yubico\\YubiKey Manager 5. Complete the YubiKey Manager Setup wizard. 1. In the Welcome screen, click **Next**. 2. In the Choose Install Location screen, click **Next** to select the default. Optionally, click Browse to select a different location, then click **Next**. 3. In the Choose Start Menu Folder screen, click **Install**. Optionally, select a different folder and choose to create shortcuts, then click **Install**. 4. If a pop-up asks, Do you want to allow this app to make changes to your device?, click **Yes**. 5. Wait while the YubiKey Manager GUI is installed. In the Installing screen, a progress bar shows the status. 6. In the Completing YubiKey Manager Setup screen, click **Finish**. Optionally, deselect the Run YubiKey Manager. The YubiKey Manager icon is added to the Start menu panel. 6. Optionally, right-click the YubiKey Manager icon in the Start menu panel and select, **Pin to Start** or **Pin to taskbar**. ### Install YubiKey Manager (ykman) CLI[](https://docs.yubico.com/software/yubikey/tools/ykman/Install_ykman.html#install-yubikey-manager-ykman-cli "Permalink to this heading") 1. Download the installer. See [Download YubiKey Manager and ykman Installers](https://docs.yubico.com/software/yubikey/tools/ykman/Install_ykman.html#download-label) . 2. Open a File Explorer and browse to the Downloads folder. 3. Double-click the installer for the latest version. For example, `yubikey-manager-5.4.0-win64.msi`. Note The filename includes `yubikey-manager`, because ykman is the CLI version of the YubiKey Manager. 4. Complete the YubiKey Manager (ykman) CLI Setup wizard. 1. In the Welcome screen, click **Next**. 2. In the Destination Folder screen, click **Next** to select the default. Optionally, click Change to select a different location, then click **Next**. 3. In the Ready to install YubiKey Manager (ykman) CLI screen, click **Install**. 4. If a pop-up asks, Do you want to allow this app to make changes to your device?, click **Yes**. 5. Wait while the ykman CLI is installed. In the Installing screen, a progress bar shows the status. 6. In the Completed the YubiKey Manager (ykman) CLI Setup Wizard screen, click **Finish**. 5. Optionally, from the command prompt, change to the installation directory and confirm the ykman CLI is listed. If running from a mapped drive, you might need to add `/D `. This ensures YubiKey Manager (ykman) is installed in the correct drive. C:\\Program Files> dir Volume in drive C Volume Serial Number is Directory of C:\\Program Files 05/31/2024 03:22 PM . 02/27/2024 09:29 PM Common Files 05/24/2024 01:30 PM Google 05/31/2024 03:41 PM Internet Explorer 05/07/2022 01:00 AM WindowsPowerShell 05/31/2024 03:22 PM Yubico 0 File(s) 0 bytes 14 Dir(s) 238,592,212,992 bytes free MacOS[](https://docs.yubico.com/software/yubikey/tools/ykman/Install_ykman.html#macos "Permalink to this heading") -------------------------------------------------------------------------------------------------------------------- ### Uninstaller[](https://docs.yubico.com/software/yubikey/tools/ykman/Install_ykman.html#uninstaller "Permalink to this heading") Once installed, the application uninstaller, `ykman-uninstall.exe`, is located in the ykman install directory. Running the uninstaller starts the uninstall process. The `/S` silent install option described above works with the uninstaller. MacOS Installation[](https://docs.yubico.com/software/yubikey/tools/ykman/Install_ykman.html#macos-installation "Permalink to this heading") ---------------------------------------------------------------------------------------------------------------------------------------------- Install the YubiKey Manager GUI and the YubiKey Manager CLI separately. The installers for both the GUI and CLI versions are macOS packages. ### Install YubiKey Manager GUI[](https://docs.yubico.com/software/yubikey/tools/ykman/Install_ykman.html#id3 "Permalink to this heading") 1. Download the installer. See [Download YubiKey Manager and ykman Installers](https://docs.yubico.com/software/yubikey/tools/ykman/Install_ykman.html#download-label) . 2. Open a Finder and browse to the Downloads folder. 3. Double-click the installer. For example, `yubikey-manager-qt-1.2.5-mac.pkg`. Note the `-qt` indicates it is the YubiKey Manager GUI installer. 4. Complete the YubiKey Manager installer wizard. 1. In the Introduction screen, click **Continue**. The Destination Select screen is skipped and defaults are applied. 2. In the Installation Type screen, click **Install**. 3. If a pop-up ask to allow the installation, enter your password or use Touch ID and click **Install Software**. 4. Wait while the YubiKey Manager is installed. In the Installation screen, a progress bar shows the status. 5. In the Summary screen, click **Close**. 6. Optionally, open Launchpad and locate the YubiKey Manager icon. ### Install ykman CLI Using Homebrew[](https://docs.yubico.com/software/yubikey/tools/ykman/Install_ykman.html#install-ykman-cli-using-homebrew "Permalink to this heading") From the Mac’s terminal run the `brew` command below. For Homebrew documentation and installation, see [https://brew.sh](https://brew.sh/) . This is the preferred install method for the CLI as it also enables native `ykman` command functionality without the need to change directories. Use this method to upgrade the version of ykman CLI. The command identifies older versions of components including ykman and automatically upgrades them. brew install ykman ### Install ykman CLI Using Package Installer[](https://docs.yubico.com/software/yubikey/tools/ykman/Install_ykman.html#install-ykman-cli-using-package-installer "Permalink to this heading") 1. Download the installer. See [Download YubiKey Manager and ykman Installers](https://docs.yubico.com/software/yubikey/tools/ykman/Install_ykman.html#download-label) . 2. Open a Finder and browse to the Downloads folder. 3. Double-click the installer for the newest version. For example, `yubikey-manager-5.4.0-mac.pkg`. Note there is no `-qt` in the filename. This indicates it is the YubiKey Manager CLI installer. 4. Complete the yubiKey-manager installer wizard. 1. In the Introduction screen, click **Continue**. The Destination Select screen is skipped and defaults are applied. 2. In the Installation Type screen, click **Install**. 3. If a pop-up ask to allow the installation, enter your password or use Touch ID and click **Install Software**. 4. Wait while the YubiKey Manager (ykman) CLI is installed. In the Installation screen, a progress bar shows the status. 5. In the Summary screen, click **Close**. 6. Optionally, open a terminal and run the ykman help command. ~ % ykman \-h Usage: ykman \[OPTIONS\] COMMAND \[ARGS\]... Configure your YubiKey via the command line. Examples: List connected YubiKeys, only output serial number: $ ykman list \--serials Show information about YubiKey with serial number 123456: $ ykman \--device 123456 info . . . Linux Installation[](https://docs.yubico.com/software/yubikey/tools/ykman/Install_ykman.html#linux-installation "Permalink to this heading") ---------------------------------------------------------------------------------------------------------------------------------------------- On Linux platforms you need to have `pcscd` installed and running to communicate with a YubiKey over the Smart Card interface. Additionally, you might need to set permissions for your user to access YubiKeys via the HID interfaces. Some of the libraries used by ykman have C-extensions, and might require additional dependencies to build, such as `swig` and potentially `PCSC lite`. ### Third Party Linux Distributions[](https://docs.yubico.com/software/yubikey/tools/ykman/Install_ykman.html#third-party-linux-distributions "Permalink to this heading") Yubico provides packages for Ubuntu in the yubico/stable PPA. Note For Linux amd64 ONLY and other architectures such as ARM, use the general `pip` instructions above. If you are using packages from one of the several Linux distributions’ third party repositories, follow the installation steps from the Linux distribution. For example: sudo apt-add-repository ppa:yubico/stable sudo apt update sudo apt install yubikey-manager See also the Yubico Support Knowledge Base article [Installing Yubico Software on Linux](https://support.yubico.com/hc/en-us/articles/360016649039-Installing-Yubico-Software-on-Linux) . Developers[](https://docs.yubico.com/software/yubikey/tools/ykman/Install_ykman.html#developers "Permalink to this heading") ------------------------------------------------------------------------------------------------------------------------------ For more information, see the ykman CLI page on [developers.yubico.com](https://developers.yubico.com/yubikey-manager/) . For APDUs, see the [APDU page in the .NET YubiKey SDK User’s Manual](https://docs.yubico.com/yesdk/users-manual/yubikey-reference/apdu.html) . * * * Click for [Yubico Support](http://yubi.co/support) . [Cookies](https://www.yubico.com/support/terms-conditions/cookie-notice/) | [Privacy Policy](https://www.yubico.com/support/terms-conditions/privacy-notice/) --- # Using the YubiKey Manager GUI — YubiKey Manager (ykman) CLI Guide documentation * [](https://docs.yubico.com/software/yubikey/tools/ykman/index.html) * Using the YubiKey Manager GUI * [View page source](https://docs.yubico.com/software/yubikey/tools/ykman/_sources/Using_the_ykman_GUI.rst.txt) * * * Using the YubiKey Manager GUI[](https://docs.yubico.com/software/yubikey/tools/ykman/Using_the_ykman_GUI.html#using-the-yubikey-manager-gui "Permalink to this heading") ========================================================================================================================================================================== Important End-of-Life (EOL) for the YubiKey Manager GUI was announced on February 19, 2025 and will commence on February 19, 2026. The YubiKey Manager GUI will not be supported by Yubico following the EOL date. For more details, see Yubico’s [End-of-Life policy](https://www.yubico.com/support/terms-conditions/yubico-end-of-life-policy/) and the [End-of-Life Products page](https://www.yubico.com/support/terms-conditions/yubico-end-of-life-policy/eol-products/) . For an alternative to the YubiKey Manager GUI, see the [Yubico Authenticator](https://www.yubico.com/products/yubico-authenticator/) application. Yubico Authenticator supports the latest YubiKey features and is available for desktop and mobile devices. Launch YubiKey Manager GUI on Windows[](https://docs.yubico.com/software/yubikey/tools/ykman/Using_the_ykman_GUI.html#launch-yubikey-manager-gui-on-windows "Permalink to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ ### Windows Launch using Graphical Interface[](https://docs.yubico.com/software/yubikey/tools/ykman/Using_the_ykman_GUI.html#windows-launch-using-graphical-interface "Permalink to this heading") 1. Open the Start menu panel, locate and click the YubiKey Manager GUI app. 2. Optionally, right-click the YubiKey Manager GUI icon and select, **Pin to Start** or **Pin to taskbar**. [![_images/gui-win-yb-icon-taskbar.png](https://docs.yubico.com/software/yubikey/tools/ykman/_images/gui-win-yb-icon-taskbar.png)](https://docs.yubico.com/software/yubikey/tools/ykman/_images/gui-win-yb-icon-taskbar.png) ### Windows Launch using Windows Command Line[](https://docs.yubico.com/software/yubikey/tools/ykman/Using_the_ykman_GUI.html#windows-launch-using-windows-command-line "Permalink to this heading") To launch from the command line 64 bit system: > C:\\\>"C:\\Program Files\\Yubico\\YubiKey Manager\\ykman-gui.exe" To launch from the command line 32 bit system: > C:\\\>"C:\\Program Files (x86)\\Yubico\\YubiKey Manager\\ykman-gui.exe" ### Debug Logging Mode[](https://docs.yubico.com/software/yubikey/tools/ykman/Using_the_ykman_GUI.html#debug-logging-mode "Permalink to this heading") To launch `ykman` with **debug logging** enabled, add the following to the execution command: \--log\-level DEBUG \--log\-file %USERPROFILE%\\Desktop\\ykman\-log.txt For example: C:\\\>"C:\\Program Files (x86)\\Yubico\\YubiKey Manager\\ykman-gui.exe" \--log\-level DEBUG \--log\-file %USERPROFILE%\\Desktop\\ ykman\-log.txt Launch YubiKey Manager GUI on MacOS[](https://docs.yubico.com/software/yubikey/tools/ykman/Using_the_ykman_GUI.html#launch-yubikey-manager-gui-on-macos "Permalink to this heading") -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 1. Open Launchpad, locate and click the YubiKey Manager GUI icon. 2. Optionally, right-click the YubiKey Manager GUI icon in the task bar and select **Options > Keep in Dock**. [![_images/gui-installed-start-yb-icon.png](https://docs.yubico.com/software/yubikey/tools/ykman/_images/gui-installed-start-yb-icon.png)](https://docs.yubico.com/software/yubikey/tools/ykman/_images/gui-installed-start-yb-icon.png) YubiKey Manager GUI Version[](https://docs.yubico.com/software/yubikey/tools/ykman/Using_the_ykman_GUI.html#yubikey-manager-gui-version "Permalink to this heading") ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- To identify the version of the YubiKey Manager GUI on either Windows or MacOS: 1. Launch the YubiKey Manager GUI. 2. Click About in the upper right corner of the GUI. The version is displayed in a popup box. [![_images/about-version-mac-gui.png](https://docs.yubico.com/software/yubikey/tools/ykman/_images/about-version-mac-gui.png)](https://docs.yubico.com/software/yubikey/tools/ykman/_images/about-version-mac-gui.png) View YubiKey Firmware Version[](https://docs.yubico.com/software/yubikey/tools/ykman/Using_the_ykman_GUI.html#view-yubikey-firmware-version "Permalink to this heading") -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- To identify the version of the YubiKey on either Windows or MacOS: 1. Launch the **YubiKey Manager**, GUI version. 2. At the YubiKey Manager GUI prompt, insert your YubiKey and touch. [![_images/gui-home-insert-ybkey.png](https://docs.yubico.com/software/yubikey/tools/ykman/_images/gui-home-insert-ybkey.png)](https://docs.yubico.com/software/yubikey/tools/ykman/_images/gui-home-insert-ybkey.png) If your YubiKey is already connected, the YubiKey Manager GUI Home tab is displayed. Note that the tool only reads a single YubiKey at a time, so if you have multiple keys connected, it might not be evident which one YubiKey Manager GUI is identifying. 3. View the listed YubiKey firmware version. When your YubiKey credential is accepted YubiKey Manager GUI opens the **Home** tab and lists the accepted YubiKey firmware: * YubiKey series (e.g., YubiKey 5) * Firmware (e.g., 5.4.X) * Images of the various form factors within that series. [![_images/gui-home-ybkey-accepted.png](https://docs.yubico.com/software/yubikey/tools/ykman/_images/gui-home-ybkey-accepted.png)](https://docs.yubico.com/software/yubikey/tools/ykman/_images/gui-home-ybkey-accepted.png) Managing Applications[](https://docs.yubico.com/software/yubikey/tools/ykman/Using_the_ykman_GUI.html#managing-applications "Permalink to this heading") ---------------------------------------------------------------------------------------------------------------------------------------------------------- YubiKey Manager GUI can be used to check which applications are enabled on which interface and to enable or disable each application on each physical interface. ### View Available Interfaces[](https://docs.yubico.com/software/yubikey/tools/ykman/Using_the_ykman_GUI.html#view-available-interfaces "Permalink to this heading") The **Interfaces** tab displays your key’s form factor (for example, USB), and the interfaces it has. Use the **Interfaces** tab to configure what is available on that key. For example, you can disable the interfaces/applications by deselecting the respective checkboxes. ### View YubiKey Enabled Applications[](https://docs.yubico.com/software/yubikey/tools/ykman/Using_the_ykman_GUI.html#view-yubikey-enabled-applications "Permalink to this heading") 1. Launch the **YubiKey Manager**, GUI version. 2. Insert the YubiKey whose applications you want to manage. 3. View available applications. Select the **Applications** tab. [![_images/gui-apps-menu.png](https://docs.yubico.com/software/yubikey/tools/ykman/_images/gui-apps-menu.png)](https://docs.yubico.com/software/yubikey/tools/ykman/_images/gui-apps-menu.png) ### Enable and Disable Applications[](https://docs.yubico.com/software/yubikey/tools/ykman/Using_the_ykman_GUI.html#enable-and-disable-applications "Permalink to this heading") 1. Launch the **YubiKey Manager**, GUI version. 2. Insert the YubiKey whose applications you want to manage. 3. View available applications. Select the **Interfaces** tab. A checkbox with a tick is shown next to each enabled applications. 4. Enable to disable applications for the YubiKey. 1. Select the checkbox to enable an application. 2. Unselect the checkbox to disable an application. 3. Click **Save Interfaces**. [![_images/gui-interfaces-options.png](https://docs.yubico.com/software/yubikey/tools/ykman/_images/gui-interfaces-options.png)](https://docs.yubico.com/software/yubikey/tools/ykman/_images/gui-interfaces-options.png) Note For the YubiKey 5Ci, any modifications made to the applications over the USB interface also apply to the applications over Lightning®. ### Locking[](https://docs.yubico.com/software/yubikey/tools/ykman/Using_the_ykman_GUI.html#locking "Permalink to this heading") Once the desired applications have been selected, a lock code can be set to prevent changes to the set of enabled applications. This is done using the ykman CLI `ykman config set-lock-code`. The lock code is 16 bytes presented as 32 hex characters. For more information, see [ykman config set-lock-code \[OPTIONS\]](https://docs.yubico.com/software/yubikey/tools/ykman/Base_Commands.html#set-lock-code-label) . Configure YubiKey Slot on YubiKey[](https://docs.yubico.com/software/yubikey/tools/ykman/Using_the_ykman_GUI.html#configure-yubikey-slot-on-yubikey "Permalink to this heading") ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 1. Launch the **YubiKey Manager**, GUI version. 2. Insert the YubiKey whose applications you want to manage. 3. Select application to configure. 1. Select the **Applications** tab. 2. Select from the displayed list of applications. 4. Select the YubiKey slot to configure. Click the slot **Configure** button. [![_images/gui-app-otp-options.png](https://docs.yubico.com/software/yubikey/tools/ykman/_images/gui-app-otp-options.png)](https://docs.yubico.com/software/yubikey/tools/ykman/_images/gui-app-otp-options.png) 5. Complete the configuration options. These are specific to each application type. Resetting FIDO2 Function[](https://docs.yubico.com/software/yubikey/tools/ykman/Using_the_ykman_GUI.html#resetting-fido2-function "Permalink to this heading") ---------------------------------------------------------------------------------------------------------------------------------------------------------------- Resetting the key is not the same as unblocking it. Because resetting the FIDO2 function returns the key to its beginning state when it has no PIN, you must set a new PIN and enroll the key again after resetting it. > 1. Remove your YubiKey if it is still connected to your machine, then launch ykman and insert your key. > > [![_images/ykman-5.4.3.png](https://docs.yubico.com/software/yubikey/tools/ykman/_images/ykman-5.4.3.png)](https://docs.yubico.com/software/yubikey/tools/ykman/_images/ykman-5.4.3.png) > > 2. Click on the word **Applications** at the top of that tab. A list of menu options appears. The specific options depend on the key. > > [![_images/ykman-applications-options-list.png](https://docs.yubico.com/software/yubikey/tools/ykman/_images/ykman-applications-options-list.png)](https://docs.yubico.com/software/yubikey/tools/ykman/_images/ykman-applications-options-list.png) > > 3. Select **FIDO2**. The FIDO2 page appears. > > [![_images/ykman-FIDO2-page.png](https://docs.yubico.com/software/yubikey/tools/ykman/_images/ykman-FIDO2-page.png)](https://docs.yubico.com/software/yubikey/tools/ykman/_images/ykman-FIDO2-page.png) > > 4. Click the **Reset FIDO** button. The Reset FIDO confirmation popup appears. > > [![_images/ykman-reset-fido-confirmation.png](https://docs.yubico.com/software/yubikey/tools/ykman/_images/ykman-reset-fido-confirmation.png)](https://docs.yubico.com/software/yubikey/tools/ykman/_images/ykman-reset-fido-confirmation.png) > > 5. Click **Yes**. Everything on the key is removed: the PIN (if set) is deleted. The **Remove and re-insert your YubiKey!** prompt appears. > > [![_images/ykman-remove-and-reinsert-yubikey.png](https://docs.yubico.com/software/yubikey/tools/ykman/_images/ykman-remove-and-reinsert-yubikey.png)](https://docs.yubico.com/software/yubikey/tools/ykman/_images/ykman-remove-and-reinsert-yubikey.png) > > 6. Remove and re-insert your YubiKey. The **Touch your YubiKey** prompt appears, and the green LED flashes. > > [![_images/ykman-touch-your-yubikey.png](https://docs.yubico.com/software/yubikey/tools/ykman/_images/ykman-touch-your-yubikey.png)](https://docs.yubico.com/software/yubikey/tools/ykman/_images/ykman-touch-your-yubikey.png) > > 7. Touch your YubiKey. The message “FIDO applications have been reset” appears at the bottom of the **Applications** page. > > 8. Remove the key in preparation for re-enrolling it. > * * * Click for [Yubico Support](http://yubi.co/support) . [Cookies](https://www.yubico.com/support/terms-conditions/cookie-notice/) | [Privacy Policy](https://www.yubico.com/support/terms-conditions/privacy-notice/) --- # Hidden Commands — YubiKey Manager (ykman) CLI Guide documentation * [](https://docs.yubico.com/software/yubikey/tools/ykman/index.html) * Hidden Commands * [View page source](https://docs.yubico.com/software/yubikey/tools/ykman/_sources/Hidden_Commands.rst.txt) * * * Hidden Commands[](https://docs.yubico.com/software/yubikey/tools/ykman/Hidden_Commands.html#hidden-commands "Permalink to this heading") ========================================================================================================================================== The commands described here are listed when you run the command, `ykman --full-help`. ykman apdu \[OPTIONS\] \[APDU\][](https://docs.yubico.com/software/yubikey/tools/ykman/Hidden_Commands.html#ykman-apdu-options-apdu "Permalink to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------------------ Execute arbitrary Application Protocol Data Unit (APDUs). Provide APDUs as a hex encoded, space-separated list using the following syntax: `[CLA]INS[P1P2][:DATA][/LE][=EXPECTED_SW]` If not provided CLA, P1 and P2 are all set to zero. Setting EXPECTED\_SW causes the command to check the response SW and fail if it differs. “=” can be used as shorthand for “=9000” (SW=OK). ### Examples[](https://docs.yubico.com/software/yubikey/tools/ykman/Hidden_Commands.html#examples "Permalink to this heading") Select the OATH application, send a LIST instruction (`0xA1`), and make sure we get `sw=9000` (these are equivalent): $ ykman apdu a40400:a000000527210101=9000 a1=9000 or $ ykman apdu -a oath a1= Factory reset the OATH application: $ ykman apdu -a oath 04dead or $ ykman apdu a40400:a000000527210101 04dead or (using full-apdu mode) $ ykman apdu -s 00a4040008a000000527210101 -s 0004dead Get 8 random bytes from the OpenPGP application: $ ykman apdu -a openpgp 84/08= ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/Hidden_Commands.html#options "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | | `-a, --app [otp\|management\|`

`openpgp\|oath\|piv\|fido\|`

`hsmauth\|secure-domain]` | Select application. | | `-s, --send-apdu TEXT` | Provide full APDUs. | | `--short` | Force usage of short APDUs. | | `-x, --no-pretty` | Print only the hex output of a response. | ykman sd \[OPTIONS\] COMMAND \[ARGS\][](https://docs.yubico.com/software/yubikey/tools/ykman/Hidden_Commands.html#ykman-sd-options-command-args "Permalink to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ Manage the Security Domain (SD) application, which holds keys for Secure Copy Protocol (SCP). ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/Hidden_Commands.html#id1 "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | ### Commands[](https://docs.yubico.com/software/yubikey/tools/ykman/Hidden_Commands.html#commands "Permalink to this heading") | Commmand | Description | | --- | --- | | `info` | List keys in the Security Domain of the YubiKey. | | `keys` | Manage SCP keys. | | `reset` | Reset all Security Domain data. | ykman sd info \[OPTIONS\][](https://docs.yubico.com/software/yubikey/tools/ykman/Hidden_Commands.html#ykman-sd-info-options "Permalink to this heading") ---------------------------------------------------------------------------------------------------------------------------------------------------------- List keys in the Security Domain of the YubiKey. ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/Hidden_Commands.html#id2 "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | ykman sd keys \[OPTIONS\] COMMAND \[ARGS\][](https://docs.yubico.com/software/yubikey/tools/ykman/Hidden_Commands.html#ykman-sd-keys-options-command-args "Permalink to this heading") ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Manage SCP keys. ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/Hidden_Commands.html#id3 "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | ### Commands[](https://docs.yubico.com/software/yubikey/tools/ykman/Hidden_Commands.html#id4 "Permalink to this heading") | Commmand | Description | | --- | --- | | `delete` | Delete a key or keyset. | | `export` | Export certificate chain for a key. | | `generate` | Generate an asymmetric key pair. | | `import` | Import a key or certificate. | | `set-allowlist` | Set an allowlist of certificate serial numbers for a key. | ykman sd keys delete \[OPTIONS\] KID KVN[](https://docs.yubico.com/software/yubikey/tools/ykman/Hidden_Commands.html#ykman-sd-keys-delete-options-kid-kvn "Permalink to this heading") ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Deletes the key or keyset with the given Key ID (KID) and Key Version Number (KVN). Set either KID or KVN to `0` to use it as a wildcard and delete all keys matching the specific KID or KVN. ### Arguments[](https://docs.yubico.com/software/yubikey/tools/ykman/Hidden_Commands.html#arguments "Permalink to this heading") | Argument | Description | | --- | --- | | `KID KVN` | Key reference for the key to delete. | ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/Hidden_Commands.html#id5 "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | | \`\` -f, –force\`\` | Confirm the action without prompting. | ykman sd keys export \[OPTIONS\] KID KVN OUTPUT[](https://docs.yubico.com/software/yubikey/tools/ykman/Hidden_Commands.html#ykman-sd-keys-export-options-kid-kvn-output "Permalink to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ Export certificate chain for a key. ### Arguments[](https://docs.yubico.com/software/yubikey/tools/ykman/Hidden_Commands.html#id6 "Permalink to this heading") | Argument | Description | | --- | --- | | `KID KVN` | Key reference for the certificate chain

to output. | | `OUTPUT` | File to write the certificate chain to,

Use ‘-’ to use stdout. | ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/Hidden_Commands.html#id7 "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | ykman sd keys generate \[OPTIONS\] KID KVN PUBLIC-KEY[](https://docs.yubico.com/software/yubikey/tools/ykman/Hidden_Commands.html#ykman-sd-keys-generate-options-kid-kvn-public-key "Permalink to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ Generate an asymmetric key pair. The private key is generated on the YubiKey, and written to one of the slots. ### Arguments[](https://docs.yubico.com/software/yubikey/tools/ykman/Hidden_Commands.html#id8 "Permalink to this heading") | Argument | Description | | --- | --- | | `KID KVN` | Key reference for the new key. | | `PUBLIC-KEY` | File containing the generated public key

Use ‘-’ to use stdout. | ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/Hidden_Commands.html#id9 "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | | `-r, --replace-kvn INTEGER` | Replace an existing key of the same type,

the same KID. | ykman sd keys import \[OPTIONS\] KID KVN INPUT[](https://docs.yubico.com/software/yubikey/tools/ykman/Hidden_Commands.html#ykman-sd-keys-import-options-kid-kvn-input "Permalink to this heading") ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Import a key or certificate. `KID 0x01` expects the input to be a “:”-separated triple of K-ENC:K-MAC:K-DEK. `KID 0x11, 0x13, 0x15` expect the input to be a file containing a private key and (optionally) a certificate chain. `KID 0x10, 0x20-0x2F` expect the file to contain a CA-KLOC certificate. ### Arguments[](https://docs.yubico.com/software/yubikey/tools/ykman/Hidden_Commands.html#id10 "Permalink to this heading") | Argument | Description | | --- | --- | | `KID KVN` | Key reference for the new key. | | `INPUT` | SCP03 keyset, or input file.

Use ‘-’ to use stdout. | ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/Hidden_Commands.html#id11 "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | | `-p, --password TEXT` | Password used to decrypt the file,

if needed. | | `-r, --replace-kvn INTEGER` | Replace an existing key of the same type,

the same KID. | ykman sd keys set-allowlist \[OPTIONS\] KID KVN \[SERIALS\][](https://docs.yubico.com/software/yubikey/tools/ykman/Hidden_Commands.html#ykman-sd-keys-set-allowlist-options-kid-kvn-serials "Permalink to this heading") -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Set an allowlist of certificate serial numbers for a key. Each certificate in the chain used when authenticating an SCP11a/c session is checked and rejected if their serial number is not in this `allowlist`. ### Arguments[](https://docs.yubico.com/software/yubikey/tools/ykman/Hidden_Commands.html#id12 "Permalink to this heading") | Argument | Description | | --- | --- | | `KID KVN` | Key reference for the allowlist to set. | | `SERIALS` | Serial numbers of certificates to allow. Separate serial numbers using a space. | ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/Hidden_Commands.html#id13 "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | ykman sd reset \[OPTIONS\][](https://docs.yubico.com/software/yubikey/tools/ykman/Hidden_Commands.html#ykman-sd-reset-options "Permalink to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------------ Reset all Security Domain data. This action wipes all keys and restore factory settings for the Security Domain on the YubiKey. ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/Hidden_Commands.html#id14 "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | | `-f, --force` | Confirm the action without prompting. | [Cookies](https://www.yubico.com/support/terms-conditions/cookie-notice/) | [Privacy Policy](https://www.yubico.com/support/terms-conditions/privacy-notice/) --- # OpenPGP Commands — YubiKey Manager (ykman) CLI Guide documentation * [](https://docs.yubico.com/software/yubikey/tools/ykman/index.html) * OpenPGP Commands * [View page source](https://docs.yubico.com/software/yubikey/tools/ykman/_sources/OpenPGP_Commands.rst.txt) * * * OpenPGP Commands[](https://docs.yubico.com/software/yubikey/tools/ykman/OpenPGP_Commands.html#openpgp-commands "Permalink to this heading") ============================================================================================================================================= Acronyms and their definitions are listed at the bottom of the [Base Commands](https://docs.yubico.com/software/yubikey/tools/ykman/Base_Commands.html#base-commands-label) page. ykman openpgp \[OPTIONS\] COMMAND \[ARGS\]…[](https://docs.yubico.com/software/yubikey/tools/ykman/OpenPGP_Commands.html#ykman-openpgp-options-command-args "Permalink to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ Manage OpenPGP application. ### Examples[](https://docs.yubico.com/software/yubikey/tools/ykman/OpenPGP_Commands.html#examples "Permalink to this heading") **Set the retries** for PIN, Reset Code and Admin PIN to 10: $ ykman openpgp access set-retries 10 10 10 **Require touch** to use the authentication key: $ ykman openpgp keys set-touch aut on ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/OpenPGP_Commands.html#options "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | ### Commands[](https://docs.yubico.com/software/yubikey/tools/ykman/OpenPGP_Commands.html#commands "Permalink to this heading") | Command | Description | | --- | --- | | `access` | Manage PIN, Reset Code, and Admin PIN. | | `certificates` | Manage certificates. | | `info` | Display general status of the OpenPGP application. | | `keys` | Manage private keys. | | `reset` | Reset all OpenPGP data. | ykman openpgp access \[OPTIONS\] COMMAND \[ARGS\]…[](https://docs.yubico.com/software/yubikey/tools/ykman/OpenPGP_Commands.html#ykman-openpgp-access-options-command-args "Permalink to this heading") -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Manage PIN, Reset Code, and Admin PIN. ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/OpenPGP_Commands.html#id1 "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | ### Commands[](https://docs.yubico.com/software/yubikey/tools/ykman/OpenPGP_Commands.html#id2 "Permalink to this heading") | Command | Description | | --- | --- | | `change-admin-pin` | Change the Admin PIN. | | `change-pin` | Change the User PIN. | | `change-reset-code` | Change the Reset Code. | | `set-retries` | Set the number of retry attempts for the user. | | `set-signature-policy` | Set the Signature PIN policy. | | `unblock-pin` | Unblock the PIN using Reset Code or Admin PIN. | ykman openpgp access change-admin-pin \[OPTIONS\][](https://docs.yubico.com/software/yubikey/tools/ykman/OpenPGP_Commands.html#ykman-openpgp-access-change-admin-pin-options "Permalink to this heading") ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Change the Admin PIN. The Admin PIN has a minimum length of 8, and supports any type of alphanumeric characters. ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/OpenPGP_Commands.html#id3 "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | | `-a, --admin-pin TEXT` | Current Admin PIN. | | `-n, --new-admin-pin TEXT` | New Admin PIN. | ykman openpgp access change-pin \[OPTIONS\][](https://docs.yubico.com/software/yubikey/tools/ykman/OpenPGP_Commands.html#ykman-openpgp-access-change-pin-options "Permalink to this heading") ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Change the User PIN. The PIN has a minimum length of 6, and supports any type of alphanumeric characters. PIN minimum length for YubiKey FIPS 5.7.+ when not using Key Derivation Function (KDF) is 8. ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/OpenPGP_Commands.html#id4 "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | | `-n, --new-pin TEXT` | A new PIN. | | `-P, --pin TEXT` | Current PIN code. | ykman openpgp access change-reset-code \[OPTIONS\][](https://docs.yubico.com/software/yubikey/tools/ykman/OpenPGP_Commands.html#ykman-openpgp-access-change-reset-code-options "Permalink to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Change the Reset Code. The Reset Code has a minimum length of 6, and supports any type of alphanumeric characters. ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/OpenPGP_Commands.html#id5 "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | | `-a, --admin-pin TEXT` | Admin PIN. | | `-r, --reset-code TEXT` | A new Reset Code. | ykman openpgp access set-retries \[OPTIONS\] PIN-RETRIES RESET-CODE-RETRIES ADMIN-PIN-RETRIES[](https://docs.yubico.com/software/yubikey/tools/ykman/OpenPGP_Commands.html#ykman-openpgp-access-set-retries-options-pin-retries-reset-code-retries-admin-pin-retries "Permalink to this heading") --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Set the number of retry attempts for the user PIN, Reset Code, and Admin PIN. ### Arguments[](https://docs.yubico.com/software/yubikey/tools/ykman/OpenPGP_Commands.html#arguments "Permalink to this heading") | Argument | Description | | --- | --- | | `PIN-RETRIES` | Set number of retries for PIN attempts. | | `RESET-CODE-RETRIES` | Set number of retries for Reset Code attempts. | | `ADMIN-PIN-RETRIES` | Set number of retries for Admin PIN attempts. | ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/OpenPGP_Commands.html#id6 "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | | `-a, --admin-pin TEXT` | Admin PIN for OpenPGP. | | `-f, --force` | Confirm the action without prompting. | ykman openpgp access set-signature-policy \[OPTIONS\] POLICY[](https://docs.yubico.com/software/yubikey/tools/ykman/OpenPGP_Commands.html#ykman-openpgp-access-set-signature-policy-options-policy "Permalink to this heading") --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Set the Signature PIN policy. The Signature PIN policy is used to control whether the PIN is always required when using the Signature key, or if it is required only once per session. ### Arguments[](https://docs.yubico.com/software/yubikey/tools/ykman/OpenPGP_Commands.html#id7 "Permalink to this heading") | Argument | Description | | --- | --- | | `POLICY` | Signature PIN policy to set (always, once). | ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/OpenPGP_Commands.html#id8 "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | | `-a, --admin-pin TEXT` | Admin PIN for OpenPGP. | ykman openpgp access unblock-pin \[OPTIONS\][](https://docs.yubico.com/software/yubikey/tools/ykman/OpenPGP_Commands.html#ykman-openpgp-access-unblock-pin-options "Permalink to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Unblock the PIN, using Reset Code or Admin PIN. If the PIN is lost or blocked you can reset it to a new value using the Reset Code. Alternatively, the Admin PIN can be used with the `-a, --admin-pin` option, instead of the Reset Code. The new PIN has a minimum length of 6, and supports any type of alphanumeric characters. ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/OpenPGP_Commands.html#id9 "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | | `-a, --admin-pin TEXT` | Admin PIN. Use `-` as a value to

prompt for input. | | `-n, --new-pin TEXT` | A new PIN. | | `-r, --reset-code TEXT` | Reset Code. | ykman openpgp certificates \[OPTIONS\] COMMAND \[ARGS\]…[](https://docs.yubico.com/software/yubikey/tools/ykman/OpenPGP_Commands.html#ykman-openpgp-certificates-options-command-args "Permalink to this heading") -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Manage certificates. ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/OpenPGP_Commands.html#id10 "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | ### Commands[](https://docs.yubico.com/software/yubikey/tools/ykman/OpenPGP_Commands.html#id11 "Permalink to this heading") | Command | Description | | --- | --- | | `delete` | Delete an OpenPGP certificate. | | `export` | Export an OpenPGP certificate. | | `import` | Import an OpenPGP certificate. | ykman openpgp certificates delete \[OPTIONS\] KEY[](https://docs.yubico.com/software/yubikey/tools/ykman/OpenPGP_Commands.html#ykman-openpgp-certificates-delete-options-key "Permalink to this heading") ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Delete an OpenPGP certificate. ### Arguments[](https://docs.yubico.com/software/yubikey/tools/ykman/OpenPGP_Commands.html#id12 "Permalink to this heading") | Argument | Description | | --- | --- | | `KEY` | Key slot to delete certificate from `sig`, `enc`,

`aut`, or `att`. | ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/OpenPGP_Commands.html#id13 "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | | `-a, --admin-pin TEXT` | Admin PIN for OpenPGP. | ykman openpgp certificates export \[OPTIONS\] KEY CERTIFICATE[](https://docs.yubico.com/software/yubikey/tools/ykman/OpenPGP_Commands.html#ykman-openpgp-certificates-export-options-key-certificate "Permalink to this heading") ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Export an OpenPGP certificate. ### Arguments[](https://docs.yubico.com/software/yubikey/tools/ykman/OpenPGP_Commands.html#id14 "Permalink to this heading") | Argument | Description | | --- | --- | | `CERTIFICATE` | File to write certificate to. Use `-` to use

`stdout`. | | `KEY` | Key slot to read from (`sig`, `enc`, `aut`,

or `att`). | ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/OpenPGP_Commands.html#id15 "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | | `-F, --format [PEM\|DER]` | Encoding format. Default: `PEM` | ykman openpgp certificates import \[OPTIONS\] KEY CERTIFICATE[](https://docs.yubico.com/software/yubikey/tools/ykman/OpenPGP_Commands.html#ykman-openpgp-certificates-import-options-key-certificate "Permalink to this heading") ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Import an OpenPGP certificate. ### Arguments[](https://docs.yubico.com/software/yubikey/tools/ykman/OpenPGP_Commands.html#id16 "Permalink to this heading") | Argument | Description | | --- | --- | | `CERTIFICATE` | File containing the certificate. Use `-` to

use `stdin`. | | `KEY` | Key slot to import certificate to (`sig`, `enc`,

`aut`, or `att`). | ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/OpenPGP_Commands.html#id17 "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | | `-a, --admin-pin TEXT` | Admin PIN for OpenPGP. | ykman openpgp info \[OPTIONS\][](https://docs.yubico.com/software/yubikey/tools/ykman/OpenPGP_Commands.html#ykman-openpgp-info-options "Permalink to this heading") --------------------------------------------------------------------------------------------------------------------------------------------------------------------- Display status of OpenPGP application. ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/OpenPGP_Commands.html#id18 "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | ykman openpgp keys \[OPTIONS\] COMMAND \[ARGS\]…[](https://docs.yubico.com/software/yubikey/tools/ykman/OpenPGP_Commands.html#ykman-openpgp-keys-options-command-args "Permalink to this heading") ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Manage private keys. ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/OpenPGP_Commands.html#id19 "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | ### Commands[](https://docs.yubico.com/software/yubikey/tools/ykman/OpenPGP_Commands.html#id20 "Permalink to this heading") | Command | Description | | --- | --- | | `attest` | Generate an attestation certificate for a key. | | `import` | Import a private key for OpoenPGP attestation. | | `info` | Show metadata about a private key. | | `set-touch` | Set touch policy for OpenPGP keys. | ykman openpgp keys attest \[OPTIONS\] KEY CERTIFICATE[](https://docs.yubico.com/software/yubikey/tools/ykman/OpenPGP_Commands.html#ykman-openpgp-keys-attest-options-key-certificate "Permalink to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Generate an attestation certificate for a key. Attestation is used to show that an asymmetric key was generated on the YubiKey and therefore does not exist outside the device. ### Arguments[](https://docs.yubico.com/software/yubikey/tools/ykman/OpenPGP_Commands.html#id21 "Permalink to this heading") | Argument | Description | | --- | --- | | `KEY` | Key slot to attest (`sig`, `enc`, `aut`). | | `CERTIFICATE` | File to write attestation certificate to. Use `-`

to use `stdout`. | ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/OpenPGP_Commands.html#id22 "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | | `-F, --format [PEM\|DER]` | Encoding format. Default: `PEM` | | `-P, --pin TEXT` | PIN code. | ykman openpgp keys import \[OPTIONS\] KEY PRIVATE-KEY[](https://docs.yubico.com/software/yubikey/tools/ykman/OpenPGP_Commands.html#ykman-openpgp-keys-import-options-key-private-key "Permalink to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Import a private key for OpenPGP attestation. The attestation key is by default pre-generated during production with a Yubico-issued key and certificate. Warning This private key cannot be recovered once overwritten! ### Arguments[](https://docs.yubico.com/software/yubikey/tools/ykman/OpenPGP_Commands.html#id23 "Permalink to this heading") | Argument | Description | | --- | --- | | `KEY` | Key slot to import to. Only `att` is supported. | | `PRIVATE-KEY` | File containing the private key. Use `-` to

use `stdin`. | ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/OpenPGP_Commands.html#id24 "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | | `-a, --admin-pin TEXT` | Admin PIN for OpenPGP. | ykman openpgp keys info \[OPTIONS\] KEY[](https://docs.yubico.com/software/yubikey/tools/ykman/OpenPGP_Commands.html#ykman-openpgp-keys-info-options-key "Permalink to this heading") --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Shows metadata about a private key. This shows what type of key is stored in a specific slot, whether it was imported into the YubiKey, or generated on-chip, and what the Touch policy is for using the key. ### Arguments[](https://docs.yubico.com/software/yubikey/tools/ykman/OpenPGP_Commands.html#id25 "Permalink to this heading") | Argument | Description | | --- | --- | | `KEY` | Key slot to set (`sig`, `dec`, `enc`, `aut`). | ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/OpenPGP_Commands.html#id26 "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | ykman openpgp keys set-touch \[OPTIONS\] KEY POLICY[](https://docs.yubico.com/software/yubikey/tools/ykman/OpenPGP_Commands.html#ykman-openpgp-keys-set-touch-options-key-policy "Permalink to this heading") --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Set touch policy for OpenPGP keys. The touch policy is used to require user interaction for all operations using the private key on the YubiKey. The touch policy is set individually for each key slot. To see the current touch policy, run: $ ykman openpgp info Warning Setting the touch policy of the attestation key to “fixed” cannot be undone without replacing the attestation private key. ### Arguments[](https://docs.yubico.com/software/yubikey/tools/ykman/OpenPGP_Commands.html#id27 "Permalink to this heading") | Argument | Description | | --- | --- | | `KEY` | Key slot to set (`sig`, `enc`, `aut` or `att`). | | `POLICY` | Touch policy to set (`on`, `off`, `fixed`, `cached` or `cached-fixed`). | ### Touch Policies[](https://docs.yubico.com/software/yubikey/tools/ykman/OpenPGP_Commands.html#touch-policies "Permalink to this heading") | Policy | Description | | --- | --- | | `Cached` | Touch required, cached for 15s after use. | | `Cached-Fixed` | Touch required, cached for 15s after use, cannot be

disabled without deleting the private key. | | `Fixed` | Touch required, cannot be disabled without deleting

the private key. | | `Off` | No touch required. (Default) | | `On` | Touch required. | ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/OpenPGP_Commands.html#id28 "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | | `-a, --admin-pin TEXT` | Admin PIN for OpenPGP. | | `-f, --force` | Confirm the action without prompting. | ykman openpgp reset \[OPTIONS\][](https://docs.yubico.com/software/yubikey/tools/ykman/OpenPGP_Commands.html#ykman-openpgp-reset-options "Permalink to this heading") ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- Reset OpenPGP application. This action wipes all OpenPGP data, and sets all PINs to their default values. The attestation key and certificate are not reset. ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/OpenPGP_Commands.html#id29 "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | | `-f, --force` | Confirm the action without prompting. | * * * Click for [Yubico Support](http://yubi.co/support) . [Cookies](https://www.yubico.com/support/terms-conditions/cookie-notice/) | [Privacy Policy](https://www.yubico.com/support/terms-conditions/privacy-notice/) --- # FIDO Commands — YubiKey Manager (ykman) CLI Guide documentation * [](https://docs.yubico.com/software/yubikey/tools/ykman/index.html) * FIDO Commands * [View page source](https://docs.yubico.com/software/yubikey/tools/ykman/_sources/FIDO_Commands.rst.txt) * * * FIDO Commands[](https://docs.yubico.com/software/yubikey/tools/ykman/FIDO_Commands.html#fido-commands "Permalink to this heading") ==================================================================================================================================== On Windows, FIDO operations are privileged. Therefore you must run Command Prompt or PowerShell as administrator in order to be able to run commands that begin with `ykman fido`. Acronyms and their definitions are listed at the bottom of the [Base Commands](https://docs.yubico.com/software/yubikey/tools/ykman/Base_Commands.html#base-commands-label) page. ykman fido \[OPTIONS\] COMMAND \[ARGS\]…[](https://docs.yubico.com/software/yubikey/tools/ykman/FIDO_Commands.html#ykman-fido-options-command-args "Permalink to this heading") --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Manage FIDO applications. ### Examples[](https://docs.yubico.com/software/yubikey/tools/ykman/FIDO_Commands.html#examples "Permalink to this heading") * Reset the FIDO (FIDO2 and U2F) applications: $ ykman fido reset * Change the FIDO2 PIN from 123456 to 654321: $ ykman fido access change-pin --pin 123456 --new-pin 654321 ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/FIDO_Commands.html#options "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | ### Commands[](https://docs.yubico.com/software/yubikey/tools/ykman/FIDO_Commands.html#commands "Permalink to this heading") | Command | Description | | --- | --- | | `access` | Manage the PIN for FIDO. | | `config` | Manage FIDO configuration. | | `credentials` | Manage discoverable (resident) credentials. | | `fingerprints` | Manage fingerprints. | | `info` | Display status of FIDO2 application. | | `reset` | Reset all FIDO applications. | ykman fido access \[OPTIONS\] COMMAND \[ARGS\]…[](https://docs.yubico.com/software/yubikey/tools/ykman/FIDO_Commands.html#ykman-fido-access-options-command-args "Permalink to this heading") ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Manage the PIN for FIDO. ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/FIDO_Commands.html#id1 "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | ### Commands[](https://docs.yubico.com/software/yubikey/tools/ykman/FIDO_Commands.html#id2 "Permalink to this heading") | Command | Description | | --- | --- | | `change-pin` | Set or change the PIN code. | | `force-change` | Force the PIN to be changed to a new value before use.

Command introduced in ykman (CLI) version 5.3.0. | | `set-min-length` | Set the minimum length allowed for PIN.

Command introduced in ykman (CLI) version 5.3.0. | | `verify-pin` | Verify the FIDO PIN against a YubiKey. | ykman fido access change-pin \[OPTIONS\][](https://docs.yubico.com/software/yubikey/tools/ykman/FIDO_Commands.html#ykman-fido-access-change-pin-options "Permalink to this heading") -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Set or change the PIN code. The FIDO2 PIN must be at least 4 characters, and supports any type of alphanumeric characters. Some YubiKeys can be configured to require a longer PIN. On YubiKey FIPS (4 Series), a PIN can be set for FIDO U2F. That PIN must be at least 6 characters. ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/FIDO_Commands.html#id3 "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | | `-n, --new-pin TEXT` | A new PIN. | | `-P, --pin TEXT` | Current PIN code. | | `-u, --u2f` | Set FIDO U2F PIN instead of FIDO2 PIN.

Applies to YubiKey FIPS only. | ykman fido access force-change \[OPTIONS\][](https://docs.yubico.com/software/yubikey/tools/ykman/FIDO_Commands.html#ykman-fido-access-force-change-options "Permalink to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ Force the PIN to be changed to a new value before use. ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/FIDO_Commands.html#id4 "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | | `-P, --pin TEXT` | PIN code. | ykman fido access set-min-length \[OPTIONS\] LENGTH[](https://docs.yubico.com/software/yubikey/tools/ykman/FIDO_Commands.html#ykman-fido-access-set-min-length-options-length "Permalink to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ Set the minimum length allowed for the PIN. Use the `--rp` option to specify which Relying Part (RPs) are allowed to request this information. ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/FIDO_Commands.html#id5 "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | | `-P, --pin TEXT` | PIN code. | | `-R, --rp-id TEXT` | RP ID to allow. | ykman fido access unlock \[OPTIONS\] (Deprecated)[](https://docs.yubico.com/software/yubikey/tools/ykman/FIDO_Commands.html#ykman-fido-access-unlock-options-deprecated "Permalink to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ **Yubico replaced the \`\`unlock\`\` command with the \`\`verify-pin\`\` command.** Verify U2F PIN for YubiKey FIPS. Unlock the YubiKey FIPS and allow U2F registration. ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/FIDO_Commands.html#id6 "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | | `-P, --pin TEXT` | Current PIN code. | ykman fido access verify-pin \[OPTIONS\][](https://docs.yubico.com/software/yubikey/tools/ykman/FIDO_Commands.html#ykman-fido-access-verify-pin-options "Permalink to this heading") -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Verify the FIDO PIN against a YubiKey. For YubiKeys supporting FIDO2 this resets the `retries` counter of the PIN. For YubiKey FIPS (4 Series) this unlocks the session, allowing U2F registration. ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/FIDO_Commands.html#id7 "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | | `-P, --pin TEXT` | Current PIN code. | ykman fido config \[OPTIONS\] COMMAND \[ARGS\]…[](https://docs.yubico.com/software/yubikey/tools/ykman/FIDO_Commands.html#ykman-fido-config-options-command-args "Permalink to this heading") ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Manage FIDO configuration. ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/FIDO_Commands.html#id8 "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | ### Commands[](https://docs.yubico.com/software/yubikey/tools/ykman/FIDO_Commands.html#id9 "Permalink to this heading") | Command | Description | | --- | --- | | `enable-ep-attestation` | Enables Enterprise Attestation for

Authenticators pre-configured to support it.

Command introduced in ykman (CLI) v5.3.0. | | `toggle-always-uv` | Toggles the state of Always Require User

Verification.

Command introduced in ykman (CLI) v5.3.0. | ykman fido config enable-ep-attestation \[OPTIONS\][](https://docs.yubico.com/software/yubikey/tools/ykman/FIDO_Commands.html#ykman-fido-config-enable-ep-attestation-options "Permalink to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ Enables Enterprise Attestation for Authenticators pre-configured to support it. ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/FIDO_Commands.html#id10 "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | | `-P, --pin TEXT` | PIN code. | ykman fido config toggle-always-uv \[OPTIONS\][](https://docs.yubico.com/software/yubikey/tools/ykman/FIDO_Commands.html#ykman-fido-config-toggle-always-uv-options "Permalink to this heading") -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Toggles the state of Always Require User Verification. ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/FIDO_Commands.html#id11 "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | | `-P, --pin TEXT` | PIN code. | ykman fido credentials \[OPTIONS\] COMMAND \[ARGS\]…[](https://docs.yubico.com/software/yubikey/tools/ykman/FIDO_Commands.html#ykman-fido-credentials-options-command-args "Permalink to this heading") --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Manage discoverable (resident) credentials. This command lets you manage credentials stored on your YubiKey. Credential management is only available when a FIDO PIN is set on the YubiKey. Note Managing credentials requires having a PIN. Set a PIN before trying to manage credentials. ### Examples[](https://docs.yubico.com/software/yubikey/tools/ykman/FIDO_Commands.html#id12 "Permalink to this heading") * List stored credentials (providing PIN via argument): $ ykman fido credentials list --pin 123456 * Delete a credential by user name (PIN is prompted for): $ ykman fido credentials delete example\_user ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/FIDO_Commands.html#id13 "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | ### Commands[](https://docs.yubico.com/software/yubikey/tools/ykman/FIDO_Commands.html#id14 "Permalink to this heading") | Command | Description | | --- | --- | | `delete` | Delete a resident credential. | | `list` | List resident credentials. | ykman fido credentials delete \[OPTIONS\] CREDENTIAL\_ID[](https://docs.yubico.com/software/yubikey/tools/ykman/FIDO_Commands.html#ykman-fido-credentials-delete-options-credential-id "Permalink to this heading") --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Delete a credential. List stored credential IDs using the `list` subcommand. ### Arguments[](https://docs.yubico.com/software/yubikey/tools/ykman/FIDO_Commands.html#arguments "Permalink to this heading") | Argument | Description | | --- | --- | | `CREDENTIAL_ID` | A unique substring match of a Credential ID. | ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/FIDO_Commands.html#id15 "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | | `-f, --force` | Confirm deletion without prompting. | | `-P, --pin TEXT` | PIN code. | ykman fido credentials list \[OPTIONS\][](https://docs.yubico.com/software/yubikey/tools/ykman/FIDO_Commands.html#ykman-fido-credentials-list-options "Permalink to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ List credentials. Shows a list of credentials stored on the YubiKey. The `--csv` flag returns more complete information about each credential, in CSV (comma separated values) format. ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/FIDO_Commands.html#id16 "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | | `-c, --csv` | Returns full credential information in CSV format. | | `-P, --pin TEXT` | PIN code. | ykman fido fingerprints \[OPTIONS\] COMMAND \[ARGS\]…[](https://docs.yubico.com/software/yubikey/tools/ykman/FIDO_Commands.html#ykman-fido-fingerprints-options-command-args "Permalink to this heading") ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Manage fingerprints. Requires a YubiKey with fingerprint sensor. Fingerprint management is available only when a FIDO PIN is set on the YubiKey. ### Examples[](https://docs.yubico.com/software/yubikey/tools/ykman/FIDO_Commands.html#id17 "Permalink to this heading") * Register a new fingerprint (providing PIN via argument): $ ykman fido fingerprints add "Left thumb" --pin 123456 * List already stored fingerprints (providing PIN via argument): $ ykman fido fingerprints list --pin 123456 * Delete a stored fingerprint with ID “f691” (PIN is prompted for): $ ykman fido fingerprints delete f691 ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/FIDO_Commands.html#id18 "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | ### Commands[](https://docs.yubico.com/software/yubikey/tools/ykman/FIDO_Commands.html#id19 "Permalink to this heading") | Command | Description | | --- | --- | | `add` | Add a new fingerprint. | | `delete` | Delete a fingerprint. | | `list` | List registered fingerprint. | | `rename` | Set the label for a fingerprint. | ykman fido fingerprints add \[OPTIONS\] NAME[](https://docs.yubico.com/software/yubikey/tools/ykman/FIDO_Commands.html#ykman-fido-fingerprints-add-options-name "Permalink to this heading") ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Add a new fingerprint. ### Arguments[](https://docs.yubico.com/software/yubikey/tools/ykman/FIDO_Commands.html#id20 "Permalink to this heading") | Argument | Description | | --- | --- | | `NAME` | Short readable name for the fingerprint.

For example, “Left thumb”. | ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/FIDO_Commands.html#id21 "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | | `-P, --pin TEXT` | PIN code. | ykman fido fingerprints delete \[OPTIONS\] ID[](https://docs.yubico.com/software/yubikey/tools/ykman/FIDO_Commands.html#ykman-fido-fingerprints-delete-options-id "Permalink to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ Delete a fingerprint. Delete a fingerprint from the YubiKey by its ID. To view the YuibiKey ID, run the `ykman fido fingerprints list` command. ### Arguments[](https://docs.yubico.com/software/yubikey/tools/ykman/FIDO_Commands.html#id22 "Permalink to this heading") | Argument | Description | | --- | --- | | `ID` | To see the ID run the `fingerprints list` subcommand. | ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/FIDO_Commands.html#id23 "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | | `-f, --force` | Confirm deletion without prompting. | | `-P, --pin TEXT` | PIN code. | ykman fido fingerprints list \[OPTIONS\][](https://docs.yubico.com/software/yubikey/tools/ykman/FIDO_Commands.html#ykman-fido-fingerprints-list-options "Permalink to this heading") -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- List registered fingerprint. Lists fingerprints by ID and (if available) label. ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/FIDO_Commands.html#id24 "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | | `-P, --pin TEXT` | PIN code. | ykman fido fingerprints rename \[OPTIONS\] ID NAME[](https://docs.yubico.com/software/yubikey/tools/ykman/FIDO_Commands.html#ykman-fido-fingerprints-rename-options-id-name "Permalink to this heading") ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Set the label for a fingerprint. ### Arguments[](https://docs.yubico.com/software/yubikey/tools/ykman/FIDO_Commands.html#id25 "Permalink to this heading") | Argument | Description | | --- | --- | | `ID` | The ID of the fingerprint to rename.

See `fingerprints list`. | | `NAME` | Short readable name for the fingerprint.

For example, “Left thumb”. | ### Options:[](https://docs.yubico.com/software/yubikey/tools/ykman/FIDO_Commands.html#id26 "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | | `-P, --pin TEXT` | PIN code. | ykman fido info[](https://docs.yubico.com/software/yubikey/tools/ykman/FIDO_Commands.html#ykman-fido-info "Permalink to this heading") ---------------------------------------------------------------------------------------------------------------------------------------- Display general status of the FIDO2 application. ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/FIDO_Commands.html#id27 "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | ykman fido reset \[OPTIONS\][](https://docs.yubico.com/software/yubikey/tools/ykman/FIDO_Commands.html#ykman-fido-reset-options "Permalink to this heading") -------------------------------------------------------------------------------------------------------------------------------------------------------------- Reset all FIDO applications. This action wipes all FIDO credentials on the YubiKey, including FIDO U2F credentials, and removes the PIN code. The reset is triggered immediately after the YubiKey is inserted, and it requires that the YubiKey be touched. ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/FIDO_Commands.html#id28 "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | | `-f, --force` | Confirm the action without prompting. | * * * Click for [Yubico Support](http://yubi.co/support) . [Cookies](https://www.yubico.com/support/terms-conditions/cookie-notice/) | [Privacy Policy](https://www.yubico.com/support/terms-conditions/privacy-notice/) --- # OATH Commands — YubiKey Manager (ykman) CLI Guide documentation * [](https://docs.yubico.com/software/yubikey/tools/ykman/index.html) * OATH Commands * [View page source](https://docs.yubico.com/software/yubikey/tools/ykman/_sources/OATH_Commands.rst.txt) * * * OATH Commands[](https://docs.yubico.com/software/yubikey/tools/ykman/OATH_Commands.html#oath-commands "Permalink to this heading") ==================================================================================================================================== Acronyms and their definitions are listed at the bottom of the [Base Commands](https://docs.yubico.com/software/yubikey/tools/ykman/Base_Commands.html#base-commands-label) page. ykman oath \[OPTIONS\] COMMAND \[ARGS\]…[](https://docs.yubico.com/software/yubikey/tools/ykman/OATH_Commands.html#ykman-oath-options-command-args "Permalink to this heading") --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Manage OATH application. ### Examples[](https://docs.yubico.com/software/yubikey/tools/ykman/OATH_Commands.html#examples "Permalink to this heading") * Generate codes for accounts starting with `yubi`: $ ykman oath accounts code yubi * Add an account that requires touch, the secret key `f5up4ub3dw`, and the name `yubico`: $ ykman oath accounts add yubico f5up4ub3dw --touch * Set a password for the OATH application: $ ykman oath access change-password ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/OATH_Commands.html#options "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | ### Commands[](https://docs.yubico.com/software/yubikey/tools/ykman/OATH_Commands.html#commands "Permalink to this heading") | Command | Description | | --- | --- | | `access` | Manage password protection for OATH. | | `accounts` | Manage and use OATH accounts. | | `info` | Display general status of OATH application. | | `reset` | Reset all OATH data. | ykman oath access \[OPTIONS\] COMMAND \[ARGS\]…[](https://docs.yubico.com/software/yubikey/tools/ykman/OATH_Commands.html#ykman-oath-access-options-command-args "Permalink to this heading") ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Manage password protection for OATH. ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/OATH_Commands.html#id1 "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | ### Commands[](https://docs.yubico.com/software/yubikey/tools/ykman/OATH_Commands.html#id2 "Permalink to this heading") | Command | Description | | --- | --- | | `change` | Change the password used to protect OATH accounts. | | `forget` | Remove a stored password from this computer. | | `remember` | Store YubiKeys passwords on this computer to avoid

having to enter it on each use. | ykman oath access change \[OPTIONS\][](https://docs.yubico.com/software/yubikey/tools/ykman/OATH_Commands.html#ykman-oath-access-change-options "Permalink to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ Change the password used to protect OATH accounts. Allows you to set or change a password that is required to access the OATH accounts stored on the YubiKey. ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/OATH_Commands.html#id3 "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | | `-c, --clear` | Clear the current password. | | `-n, --new-password TEXT` | Provide a new password as an argument. | | `-p, --password TEXT` | Provide a password to unlock the YubiKey. | | `-r, --remember` | Remember the password on this machine. | ykman oath access forget \[OPTIONS\][](https://docs.yubico.com/software/yubikey/tools/ykman/OATH_Commands.html#ykman-oath-access-forget-options "Permalink to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ Remove a stored password from this computer. ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/OATH_Commands.html#id4 "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | | `-a, --all` | Remove all stored passwords. | ykman oath access remember \[OPTIONS\][](https://docs.yubico.com/software/yubikey/tools/ykman/OATH_Commands.html#ykman-oath-access-remember-options "Permalink to this heading") ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Store the YubiKey password on this computer to avoid entering it on each use. ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/OATH_Commands.html#id5 "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | | `-p, --password TEXT` | Provide a password to unlock the YubiKey. | ykman oath accounts \[OPTIONS\] COMMAND \[ARGS\]…[](https://docs.yubico.com/software/yubikey/tools/ykman/OATH_Commands.html#ykman-oath-accounts-options-command-args "Permalink to this heading") --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Manage and use OATH accounts. ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/OATH_Commands.html#id6 "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | ### Commands[](https://docs.yubico.com/software/yubikey/tools/ykman/OATH_Commands.html#id7 "Permalink to this heading") | Command | Description | | --- | --- | | `add` | Add a new account. | | `code` | Generate codes. | | `delete` | Delete an account. | | `list` | List all accounts. | | `rename` | Rename an account. Requires YubiKey 5.3 or later. | | `uri` | Add a new account from an `otpauth://` URI. | ykman oath accounts add \[OPTIONS\] NAME \[SECRET\][](https://docs.yubico.com/software/yubikey/tools/ykman/OATH_Commands.html#ykman-oath-accounts-add-options-name-secret "Permalink to this heading") -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Add a new OATH account to the YubiKey. ### Arguments[](https://docs.yubico.com/software/yubikey/tools/ykman/OATH_Commands.html#arguments "Permalink to this heading") | Argument | Description | | --- | --- | | `NAME` | Human readable name for this account, such as username or

email address. | | `SECRET` | Optional. Base32-encoded secret/key value provided by

the server. | ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/OATH_Commands.html#id8 "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | | `-a, --algorithm`

`[SHA1\|SHA256\|SHA512]` | Algorithm to use for code

generation. Default: SHA1 | | `-c, --counter INTEGER` | Initial counter value for HOTP accounts. | | `-d, --digits [6\|7\|8]` | Number of digits in generated code.

Default: 6 | | `-f, --force` | Confirm the action without prompting. | | `-i, --issuer TEXT` | Optional. Issuer of the account. | | `o, --oath-type [HOTP\|TOTP]` | Time-based (TOTP) or counter-based

(HOTP) account. Default: TOTP | | `-p, --password TEXT` | Provide a password to unlock the

YubiKey. | | `-P, --period INTEGER` | Number of seconds a TOTP code is

valid. Default: 30 | | `-r, --remember` | Remember the password on this machine. | | `-t, --touch` | Require touch on YubiKey to generate

code. | ykman oath accounts code \[OPTIONS\] \[QUERY\][](https://docs.yubico.com/software/yubikey/tools/ykman/OATH_Commands.html#ykman-oath-accounts-code-options-query "Permalink to this heading") ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Generate codes from OATH accounts stored on the YubiKey. Accounts of type HOTP or those that require touch, also require a single match to be triggered. ### Arguments[](https://docs.yubico.com/software/yubikey/tools/ykman/OATH_Commands.html#id9 "Permalink to this heading") | Argument | Description | | --- | --- | | `QUERY` | Provide a query string to match one or more specific accounts. | ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/OATH_Commands.html#id10 "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | | `-H, --show-hidden` | Include hidden accounts. | | `-p, --password TEXT` | Provide a password to unlock the YubiKey. | | `-r, --remember` | Remember the password on this machine. | | `-s, --single` | Ensure only a single match, and output only

the code. | ykman oath accounts delete \[OPTIONS\] QUERY[](https://docs.yubico.com/software/yubikey/tools/ykman/OATH_Commands.html#ykman-oath-accounts-delete-options-query "Permalink to this heading") ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Delete an account from the YubiKey. ### Arguments[](https://docs.yubico.com/software/yubikey/tools/ykman/OATH_Commands.html#id11 "Permalink to this heading") | Argument | Description | | --- | --- | | `QUERY` | Provide a query string to match a single account, as shown

in [ykman oath accounts list](https://docs.yubico.com/software/yubikey/tools/ykman/OATH_Commands.html#ac-list)
. | ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/OATH_Commands.html#id12 "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | | `-f, --force` | Confirm deletion without prompting | | `-p, --password TEXT` | Provide a password to unlock the YubiKey. | | `-r, --remember` | Remember the password on this machine. | ykman oath accounts list \[OPTIONS\][](https://docs.yubico.com/software/yubikey/tools/ykman/OATH_Commands.html#ykman-oath-accounts-list-options "Permalink to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ List all accounts stored on the YubiKey. ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/OATH_Commands.html#id13 "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | | `-H, --show-hidden` | Include hidden accounts. | | `-o, --oath-type` | Display the OATH type. | | `-p, --password TEXT` | Provide a password to unlock the YubiKey. | | `-P, --period` | Display the period. | | `-r, --remember` | Remember the password on this machine. | ykman oath accounts rename \[OPTIONS\] QUERY NAME[](https://docs.yubico.com/software/yubikey/tools/ykman/OATH_Commands.html#ykman-oath-accounts-rename-options-query-name "Permalink to this heading") -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Rename an account. Requires YubiKey 5.3 or later. ### Arguments[](https://docs.yubico.com/software/yubikey/tools/ykman/OATH_Commands.html#id14 "Permalink to this heading") | Argument | Description | | --- | --- | | `QUERY` | A query to match a single account, as shown in

[ykman oath accounts list](https://docs.yubico.com/software/yubikey/tools/ykman/OATH_Commands.html#ac-list)
. | | `NAME` | The name of the account. Use format `:`

to specify the issuer. | ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/OATH_Commands.html#id15 "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | | `-f, --force` | Confirm rename without prompting. | | `-p, --password TEXT` | Provide a password to unlock the YubiKey. | | `-r, --remember` | Remember the password on this machine. | ykman oath accounts uri \[OPTIONS\] URI[](https://docs.yubico.com/software/yubikey/tools/ykman/OATH_Commands.html#ykman-oath-accounts-uri-options-uri "Permalink to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ Add a new account from an `otpauth://` URI. Use a URI to add a new account to the YubiKey. ### Arguments[](https://docs.yubico.com/software/yubikey/tools/ykman/OATH_Commands.html#id16 "Permalink to this heading") | Argument | Description | | --- | --- | | `URI` | Specify URI path for account. | ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/OATH_Commands.html#id17 "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | | `-f, --force` | Confirm the action without prompting. | | `-p, --password TEXT` | Provide a password to unlock the YubiKey. | | `-r, --remember` | Remember the password on this machine. | | `-t, --touch` | Require touch on YubiKey to generate code. | ykman oath info \[OPTIONS\][](https://docs.yubico.com/software/yubikey/tools/ykman/OATH_Commands.html#ykman-oath-info-options "Permalink to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------------ Display status of OATH application. ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/OATH_Commands.html#id18 "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | ykman oath reset \[OPTIONS\][](https://docs.yubico.com/software/yubikey/tools/ykman/OATH_Commands.html#ykman-oath-reset-options "Permalink to this heading") -------------------------------------------------------------------------------------------------------------------------------------------------------------- Reset all OATH data. This action deletes all accounts and restores factory settings for the OATH application on the YubiKey. ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/OATH_Commands.html#id19 "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | | `-f, --force` | Confirm the action without prompting. | * * * Click for [Yubico Support](http://yubi.co/support) . [Cookies](https://www.yubico.com/support/terms-conditions/cookie-notice/) | [Privacy Policy](https://www.yubico.com/support/terms-conditions/privacy-notice/) --- # Using the ykman CLI — YubiKey Manager (ykman) CLI Guide documentation * [](https://docs.yubico.com/software/yubikey/tools/ykman/index.html) * Using the ykman CLI * [View page source](https://docs.yubico.com/software/yubikey/tools/ykman/_sources/Using_the_ykman_CLI.rst.txt) * * * Using the ykman CLI[](https://docs.yubico.com/software/yubikey/tools/ykman/Using_the_ykman_CLI.html#using-the-ykman-cli "Permalink to this heading") ====================================================================================================================================================== The ykman CLI can be used to configure all aspects of the YubiKey. This section covers the options for accessing and launching ykman CLI. Note ykman CLI is also called YubiKey Manager (CLI) and is separate from the YubiKey Manager GUI. The term YubiKey Manager is listed here as a literal to displayed text. Locate ykman CLI Installation Path[](https://docs.yubico.com/software/yubikey/tools/ykman/Using_the_ykman_CLI.html#locate-ykman-cli-installation-path "Permalink to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ The examples in this guide reference the default installation path. If you choose a different installation path, update the command to point to the path you used. To locate the ykman executable: 1. Open a command line (Windows) or a terminal (MacOS). These commands work on both Windows and MacOS. The examples show a Windows prompt `>`. The MacOS prompt is `%`. 2. Identify the ykman installation path: On Windows: \> where ykman \> Program Files\\Yubico\\YubiKey Manager CLI\\ykman.exe \> Python311\\Scripts\\ykman.exe On MacOS: % where ykman /opt/homebrew/bin/ykman /opt/homebrew/bin/ykman /usr/local/bin/ykman ykman CLI Version[](https://docs.yubico.com/software/yubikey/tools/ykman/Using_the_ykman_CLI.html#ykman-cli-version "Permalink to this heading") -------------------------------------------------------------------------------------------------------------------------------------------------- Run the version command. If needed, change to the ykman directory. See [Locate ykman CLI Installation Path](https://docs.yubico.com/software/yubikey/tools/ykman/Using_the_ykman_CLI.html#ykman-install-path-label) . On Windows: > \> ykman \-v > YubiKey Manager (ykman) version: 5.4.0 On macOS % ykman \-v YubiKey Manager (ykman) version: 5.4.0 Launch ykman CLI on Windows[](https://docs.yubico.com/software/yubikey/tools/ykman/Using_the_ykman_CLI.html#launch-ykman-cli-on-windows "Permalink to this heading") ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- Run `ykman` commands from the command prompt. You do not need to specifically set PATH variables for ykman. Launch the ykman CLI through the command line, select and run the command using one of the options listed below. ### 64-bit Systems[](https://docs.yubico.com/software/yubikey/tools/ykman/Using_the_ykman_CLI.html#bit-systems "Permalink to this heading") > C:\\\>"C:\\Program Files\\Yubico\\YubiKey Manager CLI\\ykman.exe " ### 32-bit Systems[](https://docs.yubico.com/software/yubikey/tools/ykman/Using_the_ykman_CLI.html#id1 "Permalink to this heading") > C:\\\>"C:\\Program Files (x86)\\Yubico\\YubiKey Manager CLI\\ykman.exe " ### Debug Logging Mode[](https://docs.yubico.com/software/yubikey/tools/ykman/Using_the_ykman_CLI.html#debug-logging-mode "Permalink to this heading") To launch `ykman` with **debug logging** enabled, add the following to the execution command: \--log\-level DEBUG \--log\-file %USERPROFILE%\\Desktop\\ykman\-log.txt **Example**: C:\\\>"C:\\Program Files (x86)\\Yubico\\YubiKey Manager\\ykman-gui.exe" \--log\-level DEBUG \--log\-file %USERPROFILE%\\Desktop\\ ykman\-log.txt Launch ykman CLI on macOS[](https://docs.yubico.com/software/yubikey/tools/ykman/Using_the_ykman_CLI.html#launch-ykman-cli-on-macos "Permalink to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------------------ From the Mac Terminal application, run the listed commands as needed. If you have installed `ykman` using Homebrew, as referenced in the [Installation](https://docs.yubico.com/software/yubikey/tools/ykman/Install_ykman.html#ykman-install-label) , you do not need to change directories to run `ykman` commands in Mac’s terminal. The ykman CLI runs native commands natively. ### Launch ykman CLI Mode[](https://docs.yubico.com/software/yubikey/tools/ykman/Using_the_ykman_CLI.html#launch-ykman-cli-mode "Permalink to this heading") From the command line: > % ykman ### Launch ykman Debug Log Mode[](https://docs.yubico.com/software/yubikey/tools/ykman/Using_the_ykman_CLI.html#launch-ykman-debug-log-mode "Permalink to this heading") To run `ykman` with **debug logging** (to a file) enabled, add the following to the run command: \--log\-level DEBUG \--log\-file /Users//Desktop/ykman.txt Launch Issues[](https://docs.yubico.com/software/yubikey/tools/ykman/Using_the_ykman_CLI.html#launch-issues "Permalink to this heading") ------------------------------------------------------------------------------------------------------------------------------------------ ### PATH Issue[](https://docs.yubico.com/software/yubikey/tools/ykman/Using_the_ykman_CLI.html#path-issue "Permalink to this heading") If ykman did not start as expected, there might be a PATH issue. Run the command: \> ykman \-v If you do not see the version you are expecting, you might have a PATH issue. Set the PATH variables to point to the correct version or run the ykman launch command from the ykman installation directory. ### Change Directory on MacOS[](https://docs.yubico.com/software/yubikey/tools/ykman/Using_the_ykman_CLI.html#change-directory-on-macos "Permalink to this heading") Change directory to the location of the ykman executables. On macOS you must escape the “space” in the filename “YubiKey Manager.app” by putting in a backslash before the space, or you must enclose the filename in double quotes. Examples of both are given below: % cd /Applications/YubiKey\\ Manager.app/Contents/MacOS/ % cd "/Applications/YubiKey Manager.app/Contents/MacOS/" * * * Click for [Yubico Support](http://yubi.co/support) . [Cookies](https://www.yubico.com/support/terms-conditions/cookie-notice/) | [Privacy Policy](https://www.yubico.com/support/terms-conditions/privacy-notice/) --- # Base Commands — YubiKey Manager (ykman) CLI Guide documentation * [](https://docs.yubico.com/software/yubikey/tools/ykman/index.html) * Base Commands * [View page source](https://docs.yubico.com/software/yubikey/tools/ykman/_sources/Base_Commands.rst.txt) * * * Base Commands[](https://docs.yubico.com/software/yubikey/tools/ykman/Base_Commands.html#base-commands "Permalink to this heading") ==================================================================================================================================== The base commands are those that do not apply to any specific protocol. However, they do apply to the different connection methods such as USB and NFC. See the bottom of this page for acronyms and their definitions. ykman \[OPTIONS\] COMMAND \[ARGS\]…[](https://docs.yubico.com/software/yubikey/tools/ykman/Base_Commands.html#ykman-options-command-args "Permalink to this heading") ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- Configure your YubiKey via the command line. ### Examples[](https://docs.yubico.com/software/yubikey/tools/ykman/Base_Commands.html#examples "Permalink to this heading") * List connected YubiKeys, only output serial number: `$ ykman list --serials` * Show information about the YubiKey with serial number 0123456: `$ ykman --device 0123456 info` ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/Base_Commands.html#options "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | | `-c, --scp-sd KID KVN` | Specify which key the YubiKey is

using to authenticate.

Option added in ykman version 5.7.1 | | `-d, --device SERIAL` | Specify YubiKey to interact with by

serial number. | | `--diagnose` | Show diagnostics information for

troubleshooting. | | `--full-help` | Show `--help`, including hidden

commands, and exit. | | `--log-file FILE` | Write logs to a given FILE instead of

printing to stderr.

Requires `--log-level`. | | `-l, --log-level [error\|`

`warning\|info\|debug\|traffic]` | Enable logging at given verbosity

level. | | `-o, --scp-oce KID KVN` | Specify which key the OCE is using

to authenticate.

Option added in ykman version 5.7.1 | | `-p, --scp-password PASSWORD` | Specify a password required to access

the `--scp` file, if needed.

Option added in ykman version 5.5 | | `-r, --reader NAME` | Specify a YubiKey by smart card

reader. Cannot be used with

`--device` or `list`. | | `-s, --scp CRED` | Specify private key and certificate

chain for secure messaging. Can be

used multiple times to provide key

and certificates in multiple files,

(private key, certificates in

leaf-last order), or SCP03 keys in

hex separated by colon (:)

`K-ENC:K-MAC[:K-DEK]`

Option added in ykman version 5.5 | | `-t, --scp-ca FILENAME` | Specify the CA to use to verify the

SCP11 card key (CA-KLCC)

Option added in ykman version 5.5 | | `-v, --version` | Show version information about the

app \[ykman\]. | ### Commands[](https://docs.yubico.com/software/yubikey/tools/ykman/Base_Commands.html#commands "Permalink to this heading") | Command | Description | | --- | --- | | `apdu` | Execute arbitrary APDUs (hidden command) | | `config` | Configure the YubiKey. Enable/Disable applications. | | `fido` | Manage the [FIDO applications](https://docs.yubico.com/software/yubikey/tools/ykman/FIDO_Commands.html)
. | | `hsmauth` | Manage the [YubiHSM Auth application](https://docs.yubico.com/software/yubikey/tools/ykman/HSMauth_Commands.html) | | `info` | Show general information. | | `list` | List connected YubiKeys. | | `oath` | Manage the [OATH Application](https://docs.yubico.com/software/yubikey/tools/ykman/OATH_Commands.html)
. | | `openpgp` | Manage the [OpenPGP Application](https://docs.yubico.com/software/yubikey/tools/ykman/OpenPGP_Commands.html)
. | | `otp` | Manage the [OTP Application](https://docs.yubico.com/software/yubikey/tools/ykman/OTP_Commands.html)
. | | `piv` | Manage the [PIV Application](https://docs.yubico.com/software/yubikey/tools/ykman/PIV_Commands.html)
. | | `script` | Run a Python script. | | `sd` | Manage the Security Domain application, which holds keys

for SCP. (hidden command) | ykman config \[OPTIONS\] COMMAND \[ARGS\]…[](https://docs.yubico.com/software/yubikey/tools/ykman/Base_Commands.html#ykman-config-options-command-args "Permalink to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Configure the YubiKey, enable or disable applications. The applications can be enabled and disabled independently over different transports (USB and NFC). The configuration can also be protected by a lock code. ### Examples[](https://docs.yubico.com/software/yubikey/tools/ykman/Base_Commands.html#id1 "Permalink to this heading") * Disable PIV over NFC: $ ykman config nfc --disable PIV * Enable all applications over USB: $ ykman config usb --enable-all * Generate and set a random application lock code: $ ykman config set-lock-code --generate ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/Base_Commands.html#id2 "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | ### Commands[](https://docs.yubico.com/software/yubikey/tools/ykman/Base_Commands.html#id3 "Permalink to this heading") | Commmand | Description | | --- | --- | | `mode` | Manage connection modes (USB interfaces). | | `nfc` | Enable or disable applications over NFC. | | `reset` | Reset all YubiKey data. | | `set-lock-code` | Set or change the configuration lock code. | | `usb` | Enable or disable applications over USB. | ykman config mode \[OPTIONS\] MODE[](https://docs.yubico.com/software/yubikey/tools/ykman/Base_Commands.html#ykman-config-mode-options-mode "Permalink to this heading") -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Manage connection modes (USB Interfaces). This command is generally used with YubiKeys prior to the 5 series. Use `ykman config usb` for more granular control on YubiKey 5 and later. Get the current connection mode of the YubiKey, or set it to `MODE`. ### Examples[](https://docs.yubico.com/software/yubikey/tools/ykman/Base_Commands.html#id4 "Permalink to this heading") * Set the OTP and FIDO mode: $ ykman config mode OTP+FIDO * Set the CCID only mode and use touch to eject the smart card: $ ykman config mode CCID --touch-eject ### Arguments[](https://docs.yubico.com/software/yubikey/tools/ykman/Base_Commands.html#arguments "Permalink to this heading") | Argument | Description | | --- | --- | | `MODE` | `MODE` can be a string, such as `OTP+FIDO+CCID`, or a

shortened form: `o+f+c`. It can also be a mode number. | ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/Base_Commands.html#id5 "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | | `--autoeject-timeout SECONDS` | When set, the smartcard automatically

ejects after the given time. Implies

`--touch-eject` (CCID mode only). | | `--chalresp-timeout SECONDS` | Sets the timeout when waiting for touch

for challenge response. | | `-f, --force` | Confirm the action without prompting. | | `--touch-eject` | When set, the button toggles the state

the smartcard between ejected and

inserted (CCID mode only). | ykman config nfc \[OPTIONS\][](https://docs.yubico.com/software/yubikey/tools/ykman/Base_Commands.html#ykman-config-nfc-options "Permalink to this heading") -------------------------------------------------------------------------------------------------------------------------------------------------------------- Enable or disable applications over NFC. ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/Base_Commands.html#id6 "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | | `-a, --enable-all` | Enable all applications. | | `-d, --disable [OTP\|U2F\|FIDO2\|`

`OATH\|PIV\|OPENPGP\|HSMAUTH]` | Disable applications. | | `-D, --disable-all` | Disable all applications. | | `-e, --enable [OTP\|U2F\|FIDO2\|`

`OATH\|PIV\|OPENPGP\|HSMAUTH]` | Enable applications. | | `-f, --force` | Confirm the action without prompting. | | `-l, --list` | List enabled applications. | | `-L, --lock-code HEX` | Current application configuration

lock code. | | `-R, --restrict` | Disable NFC for transport.

Re-enable Restricted NFC mode.

Available for YubiKeys with

firmware version 5.7 and later. | ykman config reset \[OPTIONS\][](https://docs.yubico.com/software/yubikey/tools/ykman/Base_Commands.html#ykman-config-reset-options "Permalink to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------------------ Reset all YubiKey data. This command is only used with the YubiKey Bio Multi-protocol Edition. This action wipes all data and restores factory settings for all applications on the YubiKey. ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/Base_Commands.html#id7 "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | | `-f, --force` | Confirm the action without prompting. | ykman config set-lock-code \[OPTIONS\][](https://docs.yubico.com/software/yubikey/tools/ykman/Base_Commands.html#ykman-config-set-lock-code-options "Permalink to this heading") ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Set or change the configuration lock code. The configuration lock code only applies to the management application. A lock code may be used to protect the application configuration. The lock code must be a 32 characters (16 bytes) hex value. Once this code is set, if the user attempts to toggle the on/off state of any of the applications on the key, they are prompted for the configuration lock code. It is only toggling that triggers this; no such prompt appears if a user adds or removes an OATH-TOTP credential, for example. This command was introduced with firmware version 5.0. ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/Base_Commands.html#id8 "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | | `-c, --clear` | Clear the lock code. | | `-f, --force` | Confirm the action without prompting. | | `-g, --generate` | Generate a random lock code. Cannot use

with `--new-lock-code`. | | `-l, --lock-code HEX` | Current lock code. | | `-n, --new-lock-code HEX` | New lock code. Cannot use with `--generate` | ykman config usb \[OPTIONS\][](https://docs.yubico.com/software/yubikey/tools/ykman/Base_Commands.html#ykman-config-usb-options "Permalink to this heading") -------------------------------------------------------------------------------------------------------------------------------------------------------------- Enable or disable applications over USB. ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/Base_Commands.html#id9 "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | | `-a, --enable-all` | Enable all applications. | | `--autoeject-timeout SECONDS` | When set the smartcard automatically

ejects after the specified time.

Used with `--touch-eject`. | | `--chalresp-timeout SECONDS` | Sets the timeout when waiting for

touch response to the challenge-

response from the OTP application. | | `-d, --disable [OTP\|U2F\|FIDO2\|`

`OATH\|PIV\|OPENPGP\|HSMAUTH]` | Disable applications. | | `-e, --enable [OTP\|U2F\|FIDO2\|`

`OATH\|PIV\|OPENPGP\|HSMAUTH]` | Enable applications. | | `-f, --force` | Confirm the action without prompting. | | `-l, --list` | List enabled applications. | | `-L, --lock-code HEX` | Current application configuration

lock code. | | `--no-touch-eject` | Disable touch eject (CCID only). | | `--touch-eject` | When set, the button toggles the

state of the smartcard between

ejected and inserted (CCID only). | ykman info \[OPTIONS\][](https://docs.yubico.com/software/yubikey/tools/ykman/Base_Commands.html#ykman-info-options "Permalink to this heading") -------------------------------------------------------------------------------------------------------------------------------------------------- Show general information. Displays information about the connected YubiKey such as serial number, firmware version, capabilities, etc. ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/Base_Commands.html#id10 "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | | `-c, --check-fips` | Check if YubiKey is in FIPS-approved mode.

Available on YubiKey 4 FIPS only. | ### FIPS-Approved Mode[](https://docs.yubico.com/software/yubikey/tools/ykman/Base_Commands.html#fips-approved-mode "Permalink to this heading") NIST classified the YubiKey 5 Series FIPS as “composite authenticators”. As such, no device in that series can be taken out of the FIPS-approved mode after initialization without zeroizing the function. This means that once the YubiKey is correctly configured, it remains in the correct configuration. This is what renders the `--check-fips` command unnecessary for YubiKey 5 FIPS Series keys. As long as the crypto officer ensures that the YubiKey 5 Series FIPS devices are correctly configured at initialization, they remain in FIPS-approved mode. ### Example[](https://docs.yubico.com/software/yubikey/tools/ykman/Base_Commands.html#example "Permalink to this heading") $ ./ykman info Device type: YubiKey 5Ci FIPS Serial number: 31234067 Firmware version: 5.7.3 Form factor: Keychain (USB-C, Lightning) Enabled USB interfaces: OTP, FIDO, CCID PIN complexity is enforced Applications Yubico OTP Enabled FIDO U2F Not available FIDO2 Enabled OATH Enabled PIV Enabled OpenPGP Enabled YubiHSM Auth Enabled FIPS approved applications FIDO2: False OATH: False PIV: False OpenPGP: False YubiHSM Auth: False ykman list \[OPTIONS\][](https://docs.yubico.com/software/yubikey/tools/ykman/Base_Commands.html#ykman-list-options "Permalink to this heading") -------------------------------------------------------------------------------------------------------------------------------------------------- List connected YubiKeys. ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/Base_Commands.html#id11 "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | | `-r, --readers` | List available smart card readers. | | `-s, --serials` | Output only serial numbers of the connected YubiKeys,

one per line. Devices without serial numbers are not

listed. | ykman script \[OPTIONS\] FILE \[ARGUMENTS\][](https://docs.yubico.com/software/yubikey/tools/ykman/Base_Commands.html#ykman-script-options-file-arguments "Permalink to this heading") ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Run a Python script. Warning Never run a script without fully understanding what it does! Scripts are very powerful, and have the power to harm to both your YubiKey and your computer. ONLY run scripts that you fully trust! Arguments can be passed to the script by adding them after the end of the command. These are accessible inside the script as `sys.argv`, with the script name as the initial value. For more information on scripting, see [sys.argv in the Python.org documentation](https://docs.python.org/3/library/sys.html#sys.argv) . ### Examples[](https://docs.yubico.com/software/yubikey/tools/ykman/Base_Commands.html#id12 "Permalink to this heading") Run the file `myscript.py`, passing arguments `123456` and `indata.csv`: $ ykman script myscript.py 123456 indata.csv ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/Base_Commands.html#id13 "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | | `-f, --force` | Confirm the action without prompting. | | `-s, --site-dir DIR` | Specify additional path(s) from which to

load Python modules. | Acronyms[](https://docs.yubico.com/software/yubikey/tools/ykman/Base_Commands.html#acronyms "Permalink to this heading") -------------------------------------------------------------------------------------------------------------------------- | | | | --- | --- | | [3DES](https://en.wikipedia.org/wiki/Triple_DES)
: | Triple Data Encryption Algorithm | | [AES](https://en.wikipedia.org/wiki/Advanced_Encryption_Standard)
: | Advanced Encryption Standard | | CCC: | Card Capability Container | | [CCID](https://en.wikipedia.org/wiki/CCID_(protocol))
: | Chip card interface device, a USB protocol for a smartcard. | | CHUID: | Card Holder Unique ID | | CN: | Common name | | CSR: | Certificate Signing Request | | [ECC](https://en.wikipedia.org/wiki/Elliptic-curve_cryptography)
: | Elliptic curve cryptography | | [FIDO](https://en.wikipedia.org/wiki/FIDO_Alliance)
: | Fast Identity Online | | [FIPS](https://en.wikipedia.org/wiki/Federal_Information_Processing_Standards)
: | Federal Information Processing Standards (US government) covering codes and encryption standards. | | [HMAC](https://en.wikipedia.org/wiki/HMAC)
: | Hash-based message authentication code | | HOTP: | HMAC-based One-Time Password algorithm | | [OATH](https://en.wikipedia.org/wiki/OAuth)
: | The Initiative for Open Authentication is an organization that specifies two open authentication standards, TOTP and HOTP | | OTP: | One-Time Password | | PUK: | PIN Unlock Key | | `stdin`: | standard input - usually keyboard or CLI instructions | | `stdout`: | standard output - usually print to screen | | TOTP: | Time-based One-Time Password algorithm | | [X.509](https://en.wikipedia.org/wiki/X.509)
: | The standard defining the format of a [public key certificate](https://en.wikipedia.org/wiki/Public_key_certificate) | * * * Click for [Yubico Support](http://yubi.co/support) . [Cookies](https://www.yubico.com/support/terms-conditions/cookie-notice/) | [Privacy Policy](https://www.yubico.com/support/terms-conditions/privacy-notice/) --- # OTP Commands — YubiKey Manager (ykman) CLI Guide documentation * [](https://docs.yubico.com/software/yubikey/tools/ykman/index.html) * OTP Commands * [View page source](https://docs.yubico.com/software/yubikey/tools/ykman/_sources/OTP_Commands.rst.txt) * * * OTP Commands[](https://docs.yubico.com/software/yubikey/tools/ykman/OTP_Commands.html#otp-commands "Permalink to this heading") ================================================================================================================================= Acronyms and their definitions are listed at the bottom of the [Base Commands](https://docs.yubico.com/software/yubikey/tools/ykman/Base_Commands.html#base-commands-label) page. ykman otp \[OPTIONS\] COMMAND \[ARGS\]…[](https://docs.yubico.com/software/yubikey/tools/ykman/OTP_Commands.html#ykman-otp-options-command-args "Permalink to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ Manage YubiOTP application. The YubiKey provides two keyboard-based slots that can each be configured with a credential. Several credential types are supported. A slot configuration can be write-protected with an access code. This prevents the configuration from being overwritten without the access code being provided. Note Mode-switching the YubiKey is not possible when a slot is configured with an access code. To provide an access code to commands which require it, use the `--access-code` option. This option must be given directly after the `otp` command and before any sub-command. ### Examples[](https://docs.yubico.com/software/yubikey/tools/ykman/OTP_Commands.html#examples "Permalink to this heading") **Swap the configurations** between the two slots: $ ykman otp swap Program a **random challenge-response** credential to slot 2: $ ykman otp chalresp --generate 2 Program a Yubico **OTP credential** to slot 1, using the serial as public ID: $ ykman otp yubiotp 1 --serial-public-id Program a random 38 character **static password** to slot 2: $ ykman otp static --generate 2 --length 38 **Remove** a currently set access code from slot 2: $ ykman otp --access-code 0123456789ab settings 2 --delete-access-code ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/OTP_Commands.html#options "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | | `--access-code HEX` | A 6-byte access code. Enter `-` to prompt for

input. | ### Commands[](https://docs.yubico.com/software/yubikey/tools/ykman/OTP_Commands.html#commands "Permalink to this heading") | Command | Description | | --- | --- | | `calculate` | Perform a challenge-response operation. | | `chalresp` | Program a challenge-response credential. | | `delete` | Deletes the configuration stored in a slot. | | `hotp` | Program an HMAC-SHA1 OATH-HOTP credential. | | `info` | Display general status of the YubiKey OTP slots. | | `ndef` | Configure a slot to be used over NDEF (NFC). | | `settings` | Update the settings for a slot. | | `static` | Configure a static password. | | `swap` | Swaps the two slot configurations. | | `yubiotp` | Program a Yubico OTP credential. | ykman otp calculate \[OPTIONS\] {1|2} \[CHALLENGE\][](https://docs.yubico.com/software/yubikey/tools/ykman/OTP_Commands.html#ykman-otp-calculate-options-1-2-challenge "Permalink to this heading") ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Perform a challenge-response operation to a YubiKey slot. Send a challenge (in hex) to a YubiKey slot with a challenge-response credential and read the response. Supports output as an OATH-TOTP code. ### Arguments[](https://docs.yubico.com/software/yubikey/tools/ykman/OTP_Commands.html#arguments "Permalink to this heading") | Argument | Description | | --- | --- | | `CHALLENGE` | Challenge default is hex. For base32, use `--totp`

setting. | | `1, 2` | Select the slot for the action. | ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/OTP_Commands.html#id1 "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | | `-d, --digits [6\|8]` | Number of digits in generated TOTP code. Ignored

unless `--totp` is set. Default: `6` | | `-T, --totp` | Generate a TOTP code, use the current time if

challenge is omitted. | ykman otp chalresp \[OPTIONS\] {1|2} \[KEY\][](https://docs.yubico.com/software/yubikey/tools/ykman/OTP_Commands.html#ykman-otp-chalresp-options-1-2-key "Permalink to this heading") --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Program a challenge-response credential to a YubiKey slot 1 or 2. ### Arguments[](https://docs.yubico.com/software/yubikey/tools/ykman/OTP_Commands.html#id2 "Permalink to this heading") | Argument | Description | | --- | --- | | `KEY` | Provide key in hex. For base32, use `--totp` setting.

If `KEY` is not specified, an interactive prompt asks

for it. | | `1, 2` | Select the slot for the action. | ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/OTP_Commands.html#id3 "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | | `-f, --force` | Confirm the action without prompting. | | `-g, --generate` | Generate a random secret key. Cannot be used with

`KEY` argument. | | `-t, --touch` | Require touch on the YubiKey to generate a response. | | `-T, --totp` | Use a base32 encoded key for TOTP credentials.

Optionally, can be padded. | ykman otp delete \[OPTIONS\] {1|2}[](https://docs.yubico.com/software/yubikey/tools/ykman/OTP_Commands.html#ykman-otp-delete-options-1-2 "Permalink to this heading") ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- Deletes the configuration for the YubiKey in the specified slot, 1 or 2. ### Arguments[](https://docs.yubico.com/software/yubikey/tools/ykman/OTP_Commands.html#id4 "Permalink to this heading") | Argument | Description | | --- | --- | | `1, 2` | Select the slot for the action. | ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/OTP_Commands.html#id5 "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | | `-f, --force` | Confirm the action without prompting. | ykman otp hotp \[OPTIONS\] {1|2} \[KEY\][](https://docs.yubico.com/software/yubikey/tools/ykman/OTP_Commands.html#ykman-otp-hotp-options-1-2-key "Permalink to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Program an HMAC-SHA1 OATH-HOTP credential for YubiKey in slot 1 or 2. The YubiKey can be configured to output an OATH Token Identifier as a prefix to the OTP itself, which consists of OMP+TT+MUI. Using the `--identifier` option to specify: * OMP+TT as 4 characters * MUI as 8 characters * full OMP+TT+MUI as 12 characters. If `--identifier` is omitted, the default values are: * OMP+TT - `ubhe` * MUI - the YubiKey serial number ### Arguments[](https://docs.yubico.com/software/yubikey/tools/ykman/OTP_Commands.html#id6 "Permalink to this heading") | Argument | Description | | --- | --- | | `KEY` | A key given in hex.

If `KEY` is not specified, an interactive prompt asks

for it. | | `1, 2` | Select the slot for the action. | ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/OTP_Commands.html#id7 "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | | `-d, --digits [6\|8]` | Number of digits in generated code.

Default: `6` | | `-c, --counter INTEGER` | Initial counter value. | | `-f, --force` | Confirm the action without prompting. | | `-i, --identifier TEXT` | Token identifier. | | `--no-enter` | Do not send an **Enter** keystroke after

outputting the code. | ykman otp info \[OPTIONS\][](https://docs.yubico.com/software/yubikey/tools/ykman/OTP_Commands.html#ykman-otp-info-options "Permalink to this heading") --------------------------------------------------------------------------------------------------------------------------------------------------------- Display general status of YubiKey OPT slots. ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/OTP_Commands.html#id8 "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | ykman otp ndef \[OPTIONS\] {1|2}[](https://docs.yubico.com/software/yubikey/tools/ykman/OTP_Commands.html#ykman-otp-ndef-options-1-2 "Permalink to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------------------- Configure slot 1 or 2 to be used over NDEF (NFC). If `--prefix` is not specified, default values are used, based on type: * URI - “[https://my.yubico.com/yk](https://my.yubico.com/yk) /#” * TEXT - an empty string ### Arguments[](https://docs.yubico.com/software/yubikey/tools/ykman/OTP_Commands.html#id9 "Permalink to this heading") | Argument | Description | | --- | --- | | `1, 2` | Select the slot for the action. | ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/OTP_Commands.html#id10 "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | | `-p, --prefix TEXT` | Added before the NDEF payload.

Typically a URI. | | `-t, --ndef-type [TEXT\|URI]` | NDEF payload type Default: URI | ykman otp settings \[OPTIONS\] {1|2}[](https://docs.yubico.com/software/yubikey/tools/ykman/OTP_Commands.html#ykman-otp-settings-options-1-2 "Permalink to this heading") --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Update the settings for YubiKey in slot 1 or 2. Change the settings for a slot without changing the stored secret. All settings not specified are written with default values. ### Arguments[](https://docs.yubico.com/software/yubikey/tools/ykman/OTP_Commands.html#id11 "Permalink to this heading") | Argument | Description | | --- | --- | | `1, 2` | Select the slot for the action. | ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/OTP_Commands.html#id12 "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | | `-A, --new-access-code HEX` | Set a new 6-byte access code for

the slot.

Use `-` as value to prompt for input. | | `--delete-access-code` | Remove access code from the slot. | | `--enter / --no-enter` | Send **Enter** keystroke after

slot output. Default: `enter` | | `-f, --force` | Confirm the action without prompting. | | `-p, --pacing [0\|20\|40\|60]` | Throttle output speed by adding a delay

(in ms) between characters emitted.

Default: `0` | | `--use-numeric-keypad` | Use scan codes for numeric keypad when

sending digits. Helps with some

keyboard layouts. Default: `False` | ykman otp static \[OPTIONS\] {1|2} \[PASSWORD\][](https://docs.yubico.com/software/yubikey/tools/ykman/OTP_Commands.html#ykman-otp-static-options-1-2-password "Permalink to this heading") --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Configure a static password for YubiKey in slot 1 or 2. To avoid problems with different keyboard layouts, the following characters (upper and lower case) are allowed by default: > `c b d e f g h i j k l n r t u v` Use the `--keyboard-layout` option to allow more characters based on preferred keyboard layout. ### Arguments[](https://docs.yubico.com/software/yubikey/tools/ykman/OTP_Commands.html#id13 "Permalink to this heading") | Argument | Description | | --- | --- | | `PASSWORD` | Specify if required. | | `1, 2` | Select the slot for the action. | ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/OTP_Commands.html#id14 "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | | `-f, --force` | Confirm the action without prompting. | | `-g, --generate` | Generate a random password. | | `-k, --keyboard-layout`

`[MODHEX\|US\|UK\|DE\|FR\|`

`IT\|BEPO\|NORMAN]` | Keyboard layout to use for the static

password. Default: `MODHEX` | | `-l, --length LENGTH` | Length of generated password.

Default: 38;1<=x<=38 | | `--no-enter` | Do not send an **Enter** keystroke after

outputting the password. | ykman otp swap \[OPTIONS\][](https://docs.yubico.com/software/yubikey/tools/ykman/OTP_Commands.html#ykman-otp-swap-options "Permalink to this heading") --------------------------------------------------------------------------------------------------------------------------------------------------------- Swaps the two slot configurations. ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/OTP_Commands.html#id15 "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | | `-f, --force` | Confirm the action without prompting. | ykman otp yubiotp \[OPTIONS\] {1|2}[](https://docs.yubico.com/software/yubikey/tools/ykman/OTP_Commands.html#ykman-otp-yubiotp-options-1-2 "Permalink to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Program a Yubico OTP credential for YubiKey in slot 1 or 2. ### Arguments[](https://docs.yubico.com/software/yubikey/tools/ykman/OTP_Commands.html#id16 "Permalink to this heading") | Argument | Description | | --- | --- | | `1, 2` | Select the slot for the action. | ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/OTP_Commands.html#id17 "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | | `-f, --force` | Confirm the action without prompting. | | `-k, --key HEX` | 16-byte secret key. | | `-g, --generate-private-id` | Generate a random private ID. Cannot

be used with `--private-id`. | | `-G, --generate-key` | Generate a random secret key. Cannot

be used with `--key`. | | `--no-enter` | Do not send an **Enter** keystroke

after emitting the OTP. | | `-O, --config-output FILENAME` | Output configuration to a file

Existing files are appended. | | `-P, --public-id MODHEX` | Public identifier prefix. | | `-p, --private-id HEX` | 6-byte private identifier. | | `-S, --serial-public-id` | Use YubiKey serial number as public

ID. Cannot be used with

`--public-id`. | | `-u, --upload` | Upload credential to YubiCloud. This

opens a browser. Cannot be used with

`--force`. | * * * Click for [Yubico Support](http://yubi.co/support) . [Cookies](https://www.yubico.com/support/terms-conditions/cookie-notice/) | [Privacy Policy](https://www.yubico.com/support/terms-conditions/privacy-notice/) --- # HSMauth Commands — YubiKey Manager (ykman) CLI Guide documentation * [](https://docs.yubico.com/software/yubikey/tools/ykman/index.html) * HSMauth Commands * [View page source](https://docs.yubico.com/software/yubikey/tools/ykman/_sources/HSMauth_Commands.rst.txt) * * * HSMauth Commands[](https://docs.yubico.com/software/yubikey/tools/ykman/HSMauth_Commands.html#hsmauth-commands "Permalink to this heading") ============================================================================================================================================= For a description of YubiHSM Auth, see the _YubiKey 5 Series Technical Manual_, [Protocols and Applications > YubiHSM Auth](https://docs.yubico.com/hardware/yubikey/yk-tech-manual/yk5-apps.html#yubihsm-auth) chapter. This chapter describes the `ykman hsmauth` commands, not the `yubishm` commands. For YubiHSM installation, configuration, and `yubihsm` commands see the [YubiHSM 2 User Guide](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/index.html) . Enable or Disable YubiHSM Auth on a YubiKey[](https://docs.yubico.com/software/yubikey/tools/ykman/HSMauth_Commands.html#enable-or-disable-yubihsm-auth-on-a-yubikey "Permalink to this heading") --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- This section includes the expected output and testing methods. YubiHSM Auth is available as of firmware version 5.4.X and is disabled by default. **Enable** YubiHSM Auth by running: ykman config usb \--enable HSMAUTH YubiHSM Auth successfully enabled. **Test enablement** by connecting to the YubiHSM with YubiHSM-Shell: yubihsm\> session ykopen 1 "default key" "my secret" Session authenticated to YubiHSM2. **Disable** YubiHSM Auth by running: ykman config usb \--disable HSMAUTH YubiHSM Auth successfully disabled. **Test disablement** by connecting to the YubiHSM with YubiHSM-Shell: yubihsm\> session ykopen 1 "default key" "my secret" No access to the YubiKey application YubiHSM Auth. ykman hsmauth \[OPTIONS\] COMMAND \[ARGS\]…[](https://docs.yubico.com/software/yubikey/tools/ykman/HSMauth_Commands.html#ykman-hsmauth-options-command-args "Permalink to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ Manage the YubiHSM Auth application. ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/HSMauth_Commands.html#options "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | ### Commands[](https://docs.yubico.com/software/yubikey/tools/ykman/HSMauth_Commands.html#commands "Permalink to this heading") | Command | Description | | --- | --- | | `access` | Manage Management Key for YubiHSM Auth. | | `credentials` | Manage YubiHSM Auth credentials. | | `info` | Display general status of the YubiHSM Auth application. | | `reset` | Reset all YubiHSM Auth data. | ykman hsmauth access \[OPTIONS\] COMMAND \[ARGS\]…[](https://docs.yubico.com/software/yubikey/tools/ykman/HSMauth_Commands.html#ykman-hsmauth-access-options-command-args "Permalink to this heading") -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Manage the management key for YubiHSM Auth. ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/HSMauth_Commands.html#id1 "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | ### Commands[](https://docs.yubico.com/software/yubikey/tools/ykman/HSMauth_Commands.html#id2 "Permalink to this heading") | Command | Description | | --- | --- | | `change-management-password` | Change the management password. | ykman hsmauth access change-management-password[](https://docs.yubico.com/software/yubikey/tools/ykman/HSMauth_Commands.html#ykman-hsmauth-access-change-management-password "Permalink to this heading") ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Change the management password. Allows you to change the management password. This is required to add and delete YubiHSM Auth credentials stored on the YubiKey. `ykman hsmauth access change-management-password` supersedes `ykman hsmauth access change-management-key`, in ykman version 5.5. ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/HSMauth_Commands.html#id3 "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | | `-m, --management-password`

`TEXT` | Current management password.

Default: b’x00x00x00x00x00x00x00

x00x00x00x00x00x00x00x00x00’ | | `-n, --new-management-password`

`TEXT` | Specify the new management password. | ykman hsmauth credentials \[OPTIONS\] COMMAND \[ARGS\]…[](https://docs.yubico.com/software/yubikey/tools/ykman/HSMauth_Commands.html#ykman-hsmauth-credentials-options-command-args "Permalink to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ Manage YubiHSM Auth credentials. ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/HSMauth_Commands.html#id4 "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | ### Commands[](https://docs.yubico.com/software/yubikey/tools/ykman/HSMauth_Commands.html#id5 "Permalink to this heading") | Command | Description | | --- | --- | | `delete` | Delete a credential. | | `derive` | Import a symmetric credential derived from a password. | | `export` | Export the public key corresponding to an asymmetric credential. | | `generate` | Generate an asymmetric credential. | | `import` | Import an asymmetric credential. | | `list` | List all credentials. | | `symmetric` | Import a symmetric credential. | ykman hsmauth credentials delete \[OPTIONS\] LABEL[](https://docs.yubico.com/software/yubikey/tools/ykman/HSMauth_Commands.html#ykman-hsmauth-credentials-delete-options-label "Permalink to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Delete a credential. This deletes a YubiHSM Auth credential from the YubiKey. ### Arguments[](https://docs.yubico.com/software/yubikey/tools/ykman/HSMauth_Commands.html#arguments "Permalink to this heading") | Argument | Description | | --- | --- | | `LABEL` | A label to match a single credential, as shown in

`credential list`. | ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/HSMauth_Commands.html#id6 "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | | `-m, --management-password,`

`--management-key TEXT` | The management password. | | `-f, --force` | Confirm the action without prompting. | ykman hsmauth credentials derive \[OPTIONS\] LABEL[](https://docs.yubico.com/software/yubikey/tools/ykman/HSMauth_Commands.html#ykman-hsmauth-credentials-derive-options-label "Permalink to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Import a symmetric credential derived from a password. This imports a symmetric YubiHSM Auth credential by deriving ENC and MAC keys from a password. ### Arguments[](https://docs.yubico.com/software/yubikey/tools/ykman/HSMauth_Commands.html#id7 "Permalink to this heading") | Argument | Description | | --- | --- | | `LABEL` | A label for the YubiHSM Auth credential. | ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/HSMauth_Commands.html#id8 "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | | `-d, --derivation-password`

`TEXT` | Derivation password for ENC and MAC keys. | | `-c, --credential-password`

`TEXT` | Password to protect credential. | | `-m, --management-password,`

`--management-key TEXT` | The management password. | | `-t, --touch` | Requires touch on YubiKey to access

credential. | ykman hsmauth credentials export \[OPTIONS\] LABEL PUBLIC-KEY[](https://docs.yubico.com/software/yubikey/tools/ykman/HSMauth_Commands.html#ykman-hsmauth-credentials-export-options-label-public-key "Permalink to this heading") ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Export the public key corresponding to an asymmetric credential. This exports the long-term public key corresponding to the asymmetric YubiHSM Auth credential stored on the YubiKey. ### Arguments[](https://docs.yubico.com/software/yubikey/tools/ykman/HSMauth_Commands.html#id9 "Permalink to this heading") | Argument | Description | | --- | --- | | `LABEL` | A label for the YubiHSM Auth credential. | | `PUBLIC-KEY` | File to write the public key to.

Use `-` to use `stdout`. | ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/HSMauth_Commands.html#id10 "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | | `-F, --format [PEM\|DER]` | Encoding format. Default: PEM | ykman hsmauth credentials generate \[OPTIONS\] LABEL[](https://docs.yubico.com/software/yubikey/tools/ykman/HSMauth_Commands.html#ykman-hsmauth-credentials-generate-options-label "Permalink to this heading") ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Generate an asymmetric credential. This generates an asymmetric YubiHSM Auth credential (private key) on the YubiKey. ### Arguments[](https://docs.yubico.com/software/yubikey/tools/ykman/HSMauth_Commands.html#id11 "Permalink to this heading") | Argument | Description | | --- | --- | | `LABEL` | A label for the YubiHSM Auth credential. | ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/HSMauth_Commands.html#id12 "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | | `-c, --credential-password TEXT` | Password to protect credential. | | `-m, --management-password,`

`--management-key TEXT` | The management password. | | `-t, --touch` | Requires touch on YubiKey to access credential. | ykman hsmauth credentials import \[OPTIONS\] LABEL PRIVATE-KEY[](https://docs.yubico.com/software/yubikey/tools/ykman/HSMauth_Commands.html#ykman-hsmauth-credentials-import-options-label-private-key "Permalink to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Import an asymmetric credential. This imports a private key as an asymmetric YubiHSM Auth credential to the YubiKey. ### Arguments[](https://docs.yubico.com/software/yubikey/tools/ykman/HSMauth_Commands.html#id13 "Permalink to this heading") | Argument | Description | | --- | --- | | `LABEL` | A label for the YubiHSM Auth credential. | | `PRIVATE-KEY` | File containing the private key.

Use `-` to use `stdin`. | ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/HSMauth_Commands.html#id14 "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | | `-c, --credential-password TEXT` | Password to protect credential. | | `-m, --management-password,`

`--management-key TEXT` | The management password. | | `-p, --password TEXT` | Password used to decrypt the private

key. | | `-t, --touch` | Requires touch on YubiKey to access

credential. | ykman hsmauth credentials list \[OPTIONS\][](https://docs.yubico.com/software/yubikey/tools/ykman/HSMauth_Commands.html#ykman-hsmauth-credentials-list-options "Permalink to this heading") --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- List all credentials stored on the YubiKey. ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/HSMauth_Commands.html#id15 "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | ykman hsmauth credentials symmetric \[OPTIONS\] LABEL[](https://docs.yubico.com/software/yubikey/tools/ykman/HSMauth_Commands.html#ykman-hsmauth-credentials-symmetric-options-label "Permalink to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Import a symmetric credential. This imports an ENC and MAC key as a symmetric YubiHSM Auth credential on the YubiKey. ### Arguments[](https://docs.yubico.com/software/yubikey/tools/ykman/HSMauth_Commands.html#id16 "Permalink to this heading") | Argument | Description | | --- | --- | | `LABEL` | A label for the YubiHSM Auth credential. | ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/HSMauth_Commands.html#id17 "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | | `-c, --credential-password TEXT` | Password to protect credential. | | `-E, --enc-key TEXT` | The ENC key. | | `-g, --generate` | Generate a random encryption and MAC

key. | | `-m, --management-password,`

`--management-key TEXT` | The management password. | | `-M, --mac-key TEXT` | The MAC key. | | `-t, --touch` | Requires touch on YubiKey to access credential. | ykman hsmauth info \[OPTIONS\][](https://docs.yubico.com/software/yubikey/tools/ykman/HSMauth_Commands.html#ykman-hsmauth-info-options "Permalink to this heading") --------------------------------------------------------------------------------------------------------------------------------------------------------------------- Display general status of the YubiHSM Auth application. ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/HSMauth_Commands.html#id18 "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | ykman hsmauth reset \[OPTIONS\][](https://docs.yubico.com/software/yubikey/tools/ykman/HSMauth_Commands.html#ykman-hsmauth-reset-options "Permalink to this heading") ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- Reset all YubiHSM Auth data. This action wipes all data and restores factory setting for the YubiHSM Auth application on the YubiKey. ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/HSMauth_Commands.html#id19 "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | | `-f, --force` | Confirm the action without prompting. | [Cookies](https://www.yubico.com/support/terms-conditions/cookie-notice/) | [Privacy Policy](https://www.yubico.com/support/terms-conditions/privacy-notice/) --- # PIV Commands — YubiKey Manager (ykman) CLI Guide documentation * [](https://docs.yubico.com/software/yubikey/tools/ykman/index.html) * PIV Commands * [View page source](https://docs.yubico.com/software/yubikey/tools/ykman/_sources/PIV_Commands.rst.txt) * * * PIV Commands[](https://docs.yubico.com/software/yubikey/tools/ykman/PIV_Commands.html#piv-commands "Permalink to this heading") ================================================================================================================================= Acronyms and their definitions are listed at the bottom of the [Base Commands](https://docs.yubico.com/software/yubikey/tools/ykman/Base_Commands.html#base-commands-label) page. ykman piv \[OPTIONS\] COMMAND \[ARGS\]…[](https://docs.yubico.com/software/yubikey/tools/ykman/PIV_Commands.html#ykman-piv-options-command-args "Permalink to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ Manage the PIV Application. ### Examples[](https://docs.yubico.com/software/yubikey/tools/ykman/PIV_Commands.html#examples "Permalink to this heading") **Generate** an ECC P-256 private key and a self-signed certificate in slot 9a: $ ykman piv keys generate --algorithm ECCP256 9a pubkey.pem $ ykman piv certificates generate --subject "CN=yubico" 9a pubkey.pem **Change the PIN** from 123456 to 654321: $ ykman piv access change-pin --pin 123456 --new-pin 654321 **Reset all PIV data** and restore default settings: $ ykman piv reset ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/PIV_Commands.html#options "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | ### Commands[](https://docs.yubico.com/software/yubikey/tools/ykman/PIV_Commands.html#commands "Permalink to this heading") | Command | Description | | --- | --- | | `access` | Manage PIN, PUK, and Management Key. | | `certificates` | Manage certificates. | | `info` | Display general status of the PIV application. | | `keys` | Manage private keys. | | `objects` | Manage PIV data objects. | | `reset` | Reset all PIV data. | ykman piv access \[OPTIONS\] COMMAND \[ARGS\]…[](https://docs.yubico.com/software/yubikey/tools/ykman/PIV_Commands.html#ykman-piv-access-options-command-args "Permalink to this heading") -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Manage PIN, PUK, and Management Key. ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/PIV_Commands.html#id1 "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | ### Commands[](https://docs.yubico.com/software/yubikey/tools/ykman/PIV_Commands.html#id2 "Permalink to this heading") | Command | Description | | --- | --- | | `change-management-key` | Change the management key. | | `change-pin` | Change the PIN code. | | `change-puk` | Change the PUK code. | | `set-retries` | Set the number of PIN and PUK retry attempts. | | `unblock-pin` | Unblock the PIN (using the PUK). | ykman piv access change-management-key \[OPTIONS\][](https://docs.yubico.com/software/yubikey/tools/ykman/PIV_Commands.html#ykman-piv-access-change-management-key-options "Permalink to this heading") --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Change the management key. Management functionality is guarded by a management key. This key is required for administrative tasks, such as generating key pairs. A random key may be generated and stored on the YubiKey, protected by PIN. Note With the release of the 5.7 YubiKey firmware version, Advanced Encryption Standard 192 bit (AES-192) is the default **security type** for the PIV management key. Triple Data Encryption Standard (TDES or 3DES) is the default security type for YubiKey firmware versions older than 5.7. The default **value** is the same for all firmware versions, regardless of the security type. For this value as well as the default PIN and PUK codes, see the [“General Information” section of “Yubico PIV Tool” on our developer site](https://developers.yubico.com/yubico-piv-tool/YubiKey_PIV_introduction.html#:~:text=General%20information,key%20(9B)%20is%20010203040506070801020304050607080102030405060708) . ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/PIV_Commands.html#id3 "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | | `-a, --algorithm [TDES\|`

`AES128\|AES192\|AES256]` | Management key algorithm.

Default v5.7: `AES-192`

Default pre-v.5.7: `TDES` | | `-f, --force` | Confirm the action without prompting. | | `-g, --generate` | Generate a random management key.

Implied by `--protect` unless

`--new-management-key` is also

given. Cannot be used with

`--new-management-key`. | | `-m, --management-key TEXT` | Current management key. TEXT=identifier. | | `-n, --new-management-key TEXT` | Set a new management key. TEXT=identifier. | | `-p, --protect` | Store new management key on the

YubiKey, protected by PIN. A random

key is used if no key is provided. | | `-P, --pin TEXT` | PIN code. | | `-t, --touch` | Require touch on YubiKey when

prompted for management key. | ykman piv access change-pin \[OPTIONS\][](https://docs.yubico.com/software/yubikey/tools/ykman/PIV_Commands.html#ykman-piv-access-change-pin-options "Permalink to this heading") ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Change the PIN code. The PIN must be between 6 and 8 alphanumeric characters. For cross-platform compatibility, numeric PINs are recommended. ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/PIV_Commands.html#id4 "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | | `-n, --new-pin TEXT` | Set a new PIN. | | `-P, --pin TEXT` | Current PIN code. | ykman piv access change-puk \[OPTIONS\][](https://docs.yubico.com/software/yubikey/tools/ykman/PIV_Commands.html#ykman-piv-access-change-puk-options "Permalink to this heading") ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Change the PUK code. If the PIN is lost or blocked it can be reset using a PUK. The PUK must be between 6 and 8 bytes long and can be any type of alphanumeric character. ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/PIV_Commands.html#id5 "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | | `-n, --new-puk TEXT` | Set a new PUK code. | | `-p, --puk TEXT` | Current PUK code. | ykman piv access set-retries \[OPTIONS\] PIN-RETRIES PUK-RETRIES[](https://docs.yubico.com/software/yubikey/tools/ykman/PIV_Commands.html#ykman-piv-access-set-retries-options-pin-retries-puk-retries "Permalink to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Set the number of PIN and PUK retry attempts. Note This resets the PIN and PUK to their factory defaults. ### Arguments[](https://docs.yubico.com/software/yubikey/tools/ykman/PIV_Commands.html#arguments "Permalink to this heading") | Argument | Description | | --- | --- | | `PIN-RETRIES` | Set number of retries for PIN attempts. | | `PUK-RETRIES` | Set number of retries for PUK attempts. | ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/PIV_Commands.html#id6 "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | | `-f, --force` | Confirm the action without prompting. | | `-m, --management-key TEXT` | The management key. TEXT=identifier. | | `-P, --pin TEXT` | PIN code. | ykman piv access unblock-pin \[OPTIONS\][](https://docs.yubico.com/software/yubikey/tools/ykman/PIV_Commands.html#ykman-piv-access-unblock-pin-options "Permalink to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Unblock the PIN, using PUK. ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/PIV_Commands.html#id7 "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | | `-n, --new-pin NEW-PIN` | Set a new PIN code. | | `-p, --puk TEXT` | Current PUK code. | ykman piv certificates \[OPTIONS\] COMMAND \[ARGS\]…[](https://docs.yubico.com/software/yubikey/tools/ykman/PIV_Commands.html#ykman-piv-certificates-options-command-args "Permalink to this heading") -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Manage certificates. ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/PIV_Commands.html#id8 "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | ### Commands[](https://docs.yubico.com/software/yubikey/tools/ykman/PIV_Commands.html#id9 "Permalink to this heading") | Option | Description | | --- | --- | | `delete` | Delete a certificate. | | `export` | Export an X.509 certificate. | | `generate` | Generate a self-signed X.509 certificate. | | `import` | Import an X.509 certificate. | | `request` | Generate a Certificate Signing Request (CSR). | ykman piv certificates delete \[OPTIONS\] SLOT[](https://docs.yubico.com/software/yubikey/tools/ykman/PIV_Commands.html#ykman-piv-certificates-delete-options-slot "Permalink to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Delete a certificate from a PIV slot on the YubiKey. ### Arguments[](https://docs.yubico.com/software/yubikey/tools/ykman/PIV_Commands.html#id10 "Permalink to this heading") | Argument | Description | | --- | --- | | `SLOT` | PIV slot of the certificate. | ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/PIV_Commands.html#id11 "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | | `-m, --management-key TEXT` | The management key. TEXT=identifier. | | `-P, --pin TEXT` | PIN code. | ykman piv certificates export \[OPTIONS\] SLOT CERTIFICATE[](https://docs.yubico.com/software/yubikey/tools/ykman/PIV_Commands.html#ykman-piv-certificates-export-options-slot-certificate "Permalink to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Export an X.509 certificate. Reads a certificate from one of the PIV slots on the YubiKey. ### Arguments[](https://docs.yubico.com/software/yubikey/tools/ykman/PIV_Commands.html#id12 "Permalink to this heading") | Argument | Description | | --- | --- | | `SLOT` | PIV slot of the certificate. | | `CERTIFICATE` | File to write certificate to. Use `-` to

use `stdout`. | ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/PIV_Commands.html#id13 "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | | `-F, --format [PEM\|DER]` | Encoding format. Default: `PEM` | ykman piv certificates generate \[OPTIONS\] SLOT PUBLIC-KEY[](https://docs.yubico.com/software/yubikey/tools/ykman/PIV_Commands.html#ykman-piv-certificates-generate-options-slot-public-key "Permalink to this heading") --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Generate a self-signed X.509 certificate. A self-signed certificate is generated and written to one of the slots on the YubiKey. A private key must already be present in the corresponding key slot. ### Arguments[](https://docs.yubico.com/software/yubikey/tools/ykman/PIV_Commands.html#id14 "Permalink to this heading") | Argument | Description | | --- | --- | | `SLOT` | PIV slot of the certificate. | | `PUBLIC-KEY` | File containing a public key. Use `-` to use

`stdin`. | ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/PIV_Commands.html#id15 "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | | `-a, --hash-algorithm`

`[SHA256\|SHA384\|SHA512]` | Hash algorithm. Default: SHA256

SHA1 deprecated in v5.5. | | `-d, --valid-days INTEGER` | Number of days until the certificate

expires. Default: `365` | | `-m, --management-key TEXT` | The management key. TEXT=identifier. | | `-P, --pin TEXT` | PIN code. | | `-s, --subject TEXT` | Required. Subject for the certificate,

as an RFC 4514 string. | ykman piv certificates import \[OPTIONS\] SLOT CERTIFICATE[](https://docs.yubico.com/software/yubikey/tools/ykman/PIV_Commands.html#ykman-piv-certificates-import-options-slot-certificate "Permalink to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Import an X.509 certificate. Write a certificate to one of the PIV slots on the YubiKey. ### Arguments[](https://docs.yubico.com/software/yubikey/tools/ykman/PIV_Commands.html#id16 "Permalink to this heading") | Argument | Description | | --- | --- | | `SLOT` | PIV slot of the certificate. | | `CERTIFICATE` | File containing the certificate. Use `-` to

use `stdin`. | ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/PIV_Commands.html#id17 "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | | `-c, --compress` | Compresses the certificate before storing. | | `-m, --management-key TEXT` | The management key. TEXT=identifier. | | `-p, --password TEXT` | A password might be needed to decrypt

the data. | | `-P, --pin TEXT` | PIN code. | | `-v, --verify` | Verify that the certificate matches the

private key in the slot. | ykman piv certificates request \[OPTIONS\] SLOT PUBLIC-KEY CSR[](https://docs.yubico.com/software/yubikey/tools/ykman/PIV_Commands.html#ykman-piv-certificates-request-options-slot-public-key-csr "Permalink to this heading") --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Generate a Certificate Signing Request (CSR). A private key must already be present in the corresponding key slot. ### Arguments[](https://docs.yubico.com/software/yubikey/tools/ykman/PIV_Commands.html#id18 "Permalink to this heading") | Argument | Description | | --- | --- | | `CSR` | File to write CSR to. Use `-` to use `stdout`. | | `PUBLIC-KEY` | File containing a public key. Use `-` to use

`stdin`. | | `SLOT` | PIV slot of the certificate. | ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/PIV_Commands.html#id19 "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | | `-a, --hash-algorithm`

`[SHA256\|SHA384\|SHA512]` | Hash algorithm. Default: SHA256

SHA1 deprecated in v5.5. | | `-P, --pin TEXT` | PIN code. | | `-s, --subject TEXT` | Required. Subject for the requested

certificate, as an RFC 4514 string. | ykman piv info \[OPTIONS\][](https://docs.yubico.com/software/yubikey/tools/ykman/PIV_Commands.html#ykman-piv-info-options "Permalink to this heading") --------------------------------------------------------------------------------------------------------------------------------------------------------- Display general status of PIV application. ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/PIV_Commands.html#id20 "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | ykman piv keys \[OPTIONS\] COMMAND \[ARGS\]…[](https://docs.yubico.com/software/yubikey/tools/ykman/PIV_Commands.html#ykman-piv-keys-options-command-args "Permalink to this heading") ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Manage private keys. ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/PIV_Commands.html#id21 "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | ### Commands[](https://docs.yubico.com/software/yubikey/tools/ykman/PIV_Commands.html#id22 "Permalink to this heading") | Command | Description | | --- | --- | | `attest` | Generate an attestation certificate for a key pair. | | `delete` | Delete a key. | | `export` | Export a public key corresponding to a stored private key. | | `generate` | Generate an asymmetric key pair. | | `import` | Import a private key from file. | | `info` | Show metadata about a private key. | | `move` | Moves a key. | ykman piv keys attest \[OPTIONS\] SLOT CERTIFICATE[](https://docs.yubico.com/software/yubikey/tools/ykman/PIV_Commands.html#ykman-piv-keys-attest-options-slot-certificate "Permalink to this heading") --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Generate an attestation certificate for a key pair. Attestation is used to show that an asymmetric key was generated on the YubiKey and therefore does not exist outside the device. ### Arguments[](https://docs.yubico.com/software/yubikey/tools/ykman/PIV_Commands.html#id23 "Permalink to this heading") | Argument | Description | | --- | --- | | `CERTIFICATE` | File to write attestation certificate to. Use `-`

to use `stdout`. | | `SLOT` | PIV slot of the private key. | ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/PIV_Commands.html#id24 "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | | `-F, --format [PEM\|DER]` | Encoding format. Default: `PEM` | ykman piv keys delete \[OPTIONS\] SLOT[](https://docs.yubico.com/software/yubikey/tools/ykman/PIV_Commands.html#ykman-piv-keys-delete-options-slot "Permalink to this heading") --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Delete a key from a PIV slot on the YubiKey. ### Arguments[](https://docs.yubico.com/software/yubikey/tools/ykman/PIV_Commands.html#id25 "Permalink to this heading") | Argument | Description | | --- | --- | | `SLOT` | PIV slot of the key. | ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/PIV_Commands.html#id26 "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | | `-m, --management-key TEXT` | The management key. TEXT=identifier. | | `-P, --pin TEXT` | PIN code. | ykman piv keys export \[OPTIONS\] SLOT PUBLIC-KEY[](https://docs.yubico.com/software/yubikey/tools/ykman/PIV_Commands.html#ykman-piv-keys-export-options-slot-public-key "Permalink to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Export a public key corresponding to a stored private key. This command uses several different mechanisms for exporting the public key corresponding to a stored private key, which might fail. If a certificate is stored in the slot it is assumed to contain the correct public key. If this is not the case, the wrong public key is returned. Use the `--verify` flag to verify that the public key being returned matches the private key, by using the slot to create and verify a signature. This might require the PIN be provided. ### Arguments[](https://docs.yubico.com/software/yubikey/tools/ykman/PIV_Commands.html#id27 "Permalink to this heading") | Argument | Description | | --- | --- | | `PUBLIC-KEY` | File containing the generated public key. Use `-`

to use `stdout`. | | `SLOT` | PIV slot of the private key. | ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/PIV_Commands.html#id28 "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | | `-F, --format [PEM\|DER]` | Encoding format. Default: `PEM` | | `-P, --pin TEXT` | PIN code. Used with `--verify`. | | `-v, --verify` | Verify that the public key matches the

private key in the slot. | ykman piv keys generate \[OPTIONS\] SLOT PUBLIC-KEY[](https://docs.yubico.com/software/yubikey/tools/ykman/PIV_Commands.html#ykman-piv-keys-generate-options-slot-public-key "Permalink to this heading") ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Generate an asymmetric key pair. The private key is generated on the YubiKey and written to one of the slots. ### Arguments[](https://docs.yubico.com/software/yubikey/tools/ykman/PIV_Commands.html#id29 "Permalink to this heading") | Argument | Description | | --- | --- | | `PUBLIC-KEY` | File containing the generated public key. Use `-`

to use `stdout`. | | `SLOT` | PIV slot of the private key. | ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/PIV_Commands.html#id30 "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | | `-a, --algorithm [RSA1024`

`\|RSA2048\|RSA3072\|RSA4096`

`ECCP256\|ECCP384\|ED25519`

`X25519]` | Algorithm to use in key generation.

Default: `RSA2048` | | `-F, --format [PEM\|DER]` | Encoding format. Default: `PEM` | | `-m, --management-key TEXT` | The management key. TEXT=identifier. | | `-P, --pin TEXT` | PIN code. | | `--pin-policy [DEFAULT`

`\|NEVER\|ONCE\|ALWAYS`

`\|MATCH-ONCE\|MATCH-ALWAYS]` | PIN policy for slot. | | `--touch-policy [DEFAULT`

`\|NEVER\|ALWAYS\|CACHED]` | Touch policy for slot. | ykman piv keys import \[OPTIONS\] SLOT PRIVATE-KEY[](https://docs.yubico.com/software/yubikey/tools/ykman/PIV_Commands.html#ykman-piv-keys-import-options-slot-private-key "Permalink to this heading") --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Import a private key from file. Write a private key to one of the PIV slots on the YubiKey. ### Arguments[](https://docs.yubico.com/software/yubikey/tools/ykman/PIV_Commands.html#id31 "Permalink to this heading") | Argument | Description | | --- | --- | | `PRIVATE-KEY` | File containing the private key. Use `-` to use

`stdin`. | | `SLOT` | PIV slot of the private key. | ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/PIV_Commands.html#id32 "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | | `-m, --management-key TEXT` | The management key. TEXT=identifier. | | `--pin-policy [DEFAULT\|NEVER`

`ONCE\|ALWAYS\|MATCH-ONCE`

`MATCH-ALWAYS]` | PIN policy for slot. | | `-p, --password TEXT` | Password used to decrypt the private

key. | | `-P, --pin TEXT` | PIN code. | | `--touch-policy [DEFAULT\|`

`NEVER\|ALWAYS\|CACHED]` | Touch policy for slot. | ykman piv keys info \[OPTIONS\] SLOT[](https://docs.yubico.com/software/yubikey/tools/ykman/PIV_Commands.html#ykman-piv-keys-info-options-slot "Permalink to this heading") ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Show metadata about a private key. This shows: * what type of key is stored in a specific slot * whether the key was imported into the YubiKey or generated on-chip * the PIN and Touch policies for using the key ### Arguments[](https://docs.yubico.com/software/yubikey/tools/ykman/PIV_Commands.html#id33 "Permalink to this heading") | Argument | Description | | --- | --- | | `SLOT` | PIV slot of the private key. | ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/PIV_Commands.html#id34 "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | ykman piv keys move \[OPTIONS\] SOURCE DEST[](https://docs.yubico.com/software/yubikey/tools/ykman/PIV_Commands.html#ykman-piv-keys-move-options-source-dest "Permalink to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Moves a key from one PIV slot into another. ### Arguments[](https://docs.yubico.com/software/yubikey/tools/ykman/PIV_Commands.html#id35 "Permalink to this heading") | Argument | Description | | --- | --- | | `SOURCE` | PIV slot of the key to move. | | `DEST` | PIV slot to move the key into. | ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/PIV_Commands.html#id36 "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | | `-m, --management-key TEXT` | The management key. TEXT=identifier. | | `-P, --pin TEXT` | PIN code. | ykman piv objects \[OPTIONS\] COMMAND \[ARGS\]…[](https://docs.yubico.com/software/yubikey/tools/ykman/PIV_Commands.html#ykman-piv-objects-options-command-args "Permalink to this heading") ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Manage PIV data objects. ### Examples[](https://docs.yubico.com/software/yubikey/tools/ykman/PIV_Commands.html#id37 "Permalink to this heading") **Write** the contents of a file to data object with ID: `abc123` $ ykman piv objects import abc123 myfile.txt **Read** into a file, the contents of the data object with ID: `abc123` $ ykman piv objects export abc123 myfile.txt **Generate** a random value for CHUID: $ ykman piv objects generate chuid ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/PIV_Commands.html#id38 "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | ### Commands[](https://docs.yubico.com/software/yubikey/tools/ykman/PIV_Commands.html#id39 "Permalink to this heading") | Command | Description | | --- | --- | | `export` | Export an arbitrary PIV data object. | | `generate` | Generate and write data for a supported data object. | | `import` | Write an arbitrary PIV object. | ykman piv objects export \[OPTIONS\] OBJECT OUTPUT[](https://docs.yubico.com/software/yubikey/tools/ykman/PIV_Commands.html#ykman-piv-objects-export-options-object-output "Permalink to this heading") --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Export an arbitrary PIV data object. ### Arguments[](https://docs.yubico.com/software/yubikey/tools/ykman/PIV_Commands.html#id40 "Permalink to this heading") | Argument | Description | | --- | --- | | `OBJECT` | Name of PIV data object or ID in HEX. | | `OUTPUT` | File to write object to. Use `-` to use `stdout`. | ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/PIV_Commands.html#id41 "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | | `-P, --pin TEXT` | PIN code. | ykman piv objects generate \[OPTIONS\] OBJECT[](https://docs.yubico.com/software/yubikey/tools/ykman/PIV_Commands.html#ykman-piv-objects-generate-options-object "Permalink to this heading") ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Generate and write data for a supported data object. ### Arguments[](https://docs.yubico.com/software/yubikey/tools/ykman/PIV_Commands.html#id42 "Permalink to this heading") | Argument | Description | | --- | --- | | `OBJECT` | Name of PIV data object or ID in HEX.

Supported data objects are:

`CHUID` (Card Holder Unique ID)

`CCC` (Card Capability Container) | ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/PIV_Commands.html#id43 "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | | `-m, --management-key TEXT` | The management key. TEXT=identifier. | | `-P, --pin TEXT` | PIN code. | ykman piv objects import \[OPTIONS\] OBJECT DATA[](https://docs.yubico.com/software/yubikey/tools/ykman/PIV_Commands.html#ykman-piv-objects-import-options-object-data "Permalink to this heading") ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Write an arbitrary PIV object. Write a PIV object by providing the object ID. Yubico writable PIV objects are available in the range 5f0000 - 5fffff. ### Arguments[](https://docs.yubico.com/software/yubikey/tools/ykman/PIV_Commands.html#id44 "Permalink to this heading") | Argument | Description | | --- | --- | | `DATA` | File containing the data to be written. Use `-` to

use `stdin`. | | `OBJECT` | Name of PIV data object or ID in HEX. | ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/PIV_Commands.html#id45 "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | | `-m, --management-key TEXT` | The management key. TEXT = identifier. | | `-P, --pin TEXT` | PIN code. | ykman piv reset \[OPTIONS\][](https://docs.yubico.com/software/yubikey/tools/ykman/PIV_Commands.html#ykman-piv-reset-options "Permalink to this heading") ----------------------------------------------------------------------------------------------------------------------------------------------------------- Reset all PIV data. This action wipes all data and restores factory settings for the PIV application on your YubiKey. This option is not available in ykman CLI version 5.4.0. ### Options[](https://docs.yubico.com/software/yubikey/tools/ykman/PIV_Commands.html#id46 "Permalink to this heading") | Option | Description | | --- | --- | | `-h, --help` | Show this message and exit. | | `-f, --force` | Confirm the action without prompting. | * * * Click for [Yubico Support](http://yubi.co/support) . [Cookies](https://www.yubico.com/support/terms-conditions/cookie-notice/) | [Privacy Policy](https://www.yubico.com/support/terms-conditions/privacy-notice/) --- # Copyright — YubiKey Manager (ykman) CLI Guide documentation * [](https://docs.yubico.com/software/yubikey/tools/ykman/index.html) * Copyright * [View page source](https://docs.yubico.com/software/yubikey/tools/ykman/_sources/copyright.rst.txt) * * * Copyright[](https://docs.yubico.com/software/yubikey/tools/ykman/copyright.html#copyright "Permalink to this heading") ======================================================================================================================== © 2021-2025 Yubico AB. All rights reserved. Trademarks[](https://docs.yubico.com/software/yubikey/tools/ykman/copyright.html#trademarks "Permalink to this heading") -------------------------------------------------------------------------------------------------------------------------- Yubico and YubiKey are registered trademarks of Yubico AB. All other trademarks are the property of their respective owners. Disclaimer[](https://docs.yubico.com/software/yubikey/tools/ykman/copyright.html#disclaimer "Permalink to this heading") -------------------------------------------------------------------------------------------------------------------------- The contents of this document are subject to revision without notice due to continued progress in methodology, design, and manufacturing. Yubico shall have no liability for any error or damages of any kind resulting from the use of this document. The Yubico Software referenced in this document is licensed to you under the terms and conditions accompanying the software or as otherwise agreed between you or the company that you are representing. Contact Information[](https://docs.yubico.com/software/yubikey/tools/ykman/copyright.html#contact-information "Permalink to this heading") -------------------------------------------------------------------------------------------------------------------------------------------- Yubico AB Gävlegatan 22 113 30 Stockholm Sweden Getting Help[](https://docs.yubico.com/software/yubikey/tools/ykman/copyright.html#getting-help "Permalink to this heading") ------------------------------------------------------------------------------------------------------------------------------ Documentation is continuously updated on [https://docs.yubico.com/](https://docs.yubico.com/) (this site). Additional support resources are available in the Yubico Knowledge Base. Click the links to: * [Submit a support request](http://yubi.co/support) * [Contact our sales team](https://www.yubico.com/support/contact/) Feedback[](https://docs.yubico.com/software/yubikey/tools/ykman/copyright.html#feedback "Permalink to this heading") ---------------------------------------------------------------------------------------------------------------------- Yubico values and welcomes your feedback. If you think you may have discovered a flaw in our product, please submit a support request at [https://support.yubico.com/hc/en-us](https://support.yubico.com/hc/en-us) and provide as much detail as you can. Document Updated[](https://docs.yubico.com/software/yubikey/tools/ykman/copyright.html#document-updated "Permalink to this heading") -------------------------------------------------------------------------------------------------------------------------------------- 2025-07-17 23:27:54 UTC [Cookies](https://www.yubico.com/support/terms-conditions/cookie-notice/) | [Privacy Policy](https://www.yubico.com/support/terms-conditions/privacy-notice/) --- # APDUs ##### Table of Contents APDUs ===== An Application Protocol Data Unit (APDU) is simply a byte array that contains information following the ISO 7816 standard. There are two kinds of APDU: * Command * Response The application running on the host machine (in PIV, that is "Off-Card") sends a Command APDU, and the YubiKey returns a response APDU. Here is an example of a command APDU, and its and response. command APDU: 00 87 03 9B 04 7C 02 80 00 response APDU: 7C 0A 80 08 3D 12 D6 71 F7 32 75 0D 90 00 Command APDU[](https://docs.yubico.com/yesdk/users-manual/yubikey-reference/apdu.html#command-apdu) ---------------------------------------------------------------------------------------------------- There are up to seven elements in a command APDU. All command APDUs must have the first four, but it is legal to have the first four, five, six, or seven elements. #### Table 1.1: Possible command APDU elements[](https://docs.yubico.com/yesdk/users-manual/yubikey-reference/apdu.html#table-11-possible-command-apdu-elements) | Class | Instruction | Param 1 | Param 2 | Length of Data | Data | Max Length of Response Data | | --- | --- | --- | --- | --- | --- | --- | | CLA | INS | P1 | P2 | Lc | Data | Le | | CLA | INS | P1 | P2 | Lc | Data | (absent) | | CLA | INS | P1 | P2 | Lc | (absent) | (absent) | | CLA | INS | P1 | P2 | (absent) | (absent) | (absent) | For example, with the command APDU `00 87 03 9B 04 7C 02 80 00`, these are the elements. #### Table 1.2: Example command APDU elements[](https://docs.yubico.com/yesdk/users-manual/yubikey-reference/apdu.html#table-12-example-command-apdu-elements) | CLA | INS | P1 | P2 | Lc | Data | Le | | --- | --- | --- | --- | --- | --- | --- | | 00 | 87 | 03 | 9B | 04 | 7C 02 80 00 | (absent) | When building command APDUs in the SDK, the `Le` value will always be absent. The `Le` value is the maximum number of bytes in the data response. However, we will not specify that. Rather, we will let the YubiKey return as many bytes as it will, and check the length in each command class. For example, when getting the version, we expect the return data to contain three bytes. We could set `Le` to 3. If so, then the class that actually sends the APDU (a `Connection` class) could check the length of the return data for an appropriate length. It could throw an exception or return an error. However, we will instead make that check in the class that processes the specific command. In that way, if there is an error, the exception or error return can be generated by the class that knows what the command really is and create a more specific error message. Response APDU[](https://docs.yubico.com/yesdk/users-manual/yubikey-reference/apdu.html#response-apdu) ------------------------------------------------------------------------------------------------------ A response APDU consists of up to three elements. #### Table 2.1: Possible response APDU elements[](https://docs.yubico.com/yesdk/users-manual/yubikey-reference/apdu.html#table-21-possible-response-apdu-elements) | Data | Status Word 1 | Status Word 2 | | --- | --- | --- | | Return Data | SW1 | SW2 | | (absent) | SW1 | SW2 | The last two bytes make up the status word, which is the error or success code. A response might contain data and the status word, or just the status word. For example, with the response APDU `7C 0A 80 08 3D 12 D6 71 F7 32 75 0D 90 00`, these are the elements. #### Table 2.2: Example response APDU elements[](https://docs.yubico.com/yesdk/users-manual/yubikey-reference/apdu.html#table-22-example-response-apdu-elements) | Data | SW1 | SW2 | | --- | --- | --- | | 7C 0A 80 08 3D 12 D6 71 F7 32 75 0D | 90 | 00 | Note that if there is an error, the response APDU will be two bytes only: SW1 and SW2. For example, the two-byte response of `6A 81` means "Card is blocked or command not supported". #### Table 2.3: Response APDU indicating error[](https://docs.yubico.com/yesdk/users-manual/yubikey-reference/apdu.html#table-23-response-apdu-indicating-error) | Data | SW1 | SW2 | | --- | --- | --- | | (absent) | 6A | 81 | It is also possible to have a successful response APDU of only two bytes (no data). For example, suppose a command APDU requests the YubiKey set the number of PIN retries to five (instead of the default three). If the YubiKey successfully sets the retry count, there is no data to be returned, simply the status word, `90 00`, indicating success. #### Table 2.4: Response APDU indicating success with no data[](https://docs.yubico.com/yesdk/users-manual/yubikey-reference/apdu.html#table-24-response-apdu-indicating-success-with-no-data) | Data | SW1 | SW2 | | --- | --- | --- | | (absent) | 90 | 00 | Chaining[](https://docs.yubico.com/yesdk/users-manual/yubikey-reference/apdu.html#chaining) -------------------------------------------------------------------------------------------- There is a limit to the length of an APDU. For a command APDU, the limit is 260, and for a response APDU it is 258. If the amount of data to send would cause the APDU to exceed the limit, then it must be sent in more the one call. ### Command APDU chaining[](https://docs.yubico.com/yesdk/users-manual/yubikey-reference/apdu.html#command-apdu-chaining) For a command APDU, chaining generally means setting the CLA to `10 | CLA` (OR 0x10 with the CLA) for the APDUs which do not contain all the data. That is, use the normal CLA value, but just set the `0x10` bit. This indicates that there will be one or more command APDUs following, each with more data. Each of the following command APDUs will be the same as the first, just with more data. Then, for the last APDU (it holds the last of the data), set the CLA to be the regular value (no `0x10` bit). For example, suppose you were sending the PIV command "Sign" for a 2048-bit RSA key. Here's what the command APDU would be. | CLA | INS | P1 | P2 | Lc | Data | Le | | --- | --- | --- | --- | --- | --- | --- | | 00 | 87 | 07 | 9c | _data len_ | 7c _L1_ 82 _L2_ 81 _L3_ __ | absent | The Data is made up of these elements. | 7C | L1 | 82 | L2 | 81 | L3 | Encoded Data | | --- | --- | --- | --- | --- | --- | --- | | tag (auth template) | length (DER) | tag (response) | length (DER) | tag (challenge) | length (DER) | PKCS 1 v1.5 or PSS | The actual data we will send will be the following. | 7C | L1 | 82 | L2 | 81 | L3 | Encoded Data | | --- | --- | --- | --- | --- | --- | --- | | | decimal 262 | | 00 (this is not a response) | | decimal 256 | PKCS 1 v1.5 | | 7c | 82 01 06 | 82 | 00 | 81 | 82 01 00 | 00 01 FF FF ... FF 00 __ | | 1 byte | 3 | 1 | 1 | 1 | 3 | 256 | There will be 268 bytes of data to send. The APDU's field _Lc_ is one byte only, so the maximum value it can represent is 255. So break the data into two commands. #### First command APDU[](https://docs.yubico.com/yesdk/users-manual/yubikey-reference/apdu.html#first-command-apdu) | CLA | INS | P1 | P2 | Lc | Data | Le | | --- | --- | --- | --- | --- | --- | --- | | 10 | 87 | 07 | 9c | d6 | 7c 82 01 06 82 00 81 82 01 00 00 01 ff ff ... ff | absent | | 0x10 set, more data in following APDU | | | | Lc is 214, number of bytes in APDU's data | 214 bytes | | #### Second command APDU[](https://docs.yubico.com/yesdk/users-manual/yubikey-reference/apdu.html#second-command-apdu) | CLA | INS | P1 | P2 | Lc | Data | Le | | --- | --- | --- | --- | --- | --- | --- | | 00 | 87 | 07 | 9c | 34 | ff ff ff 00 30 2f ... 1F | absent | | 0x10 NOT set, last of the data in this APDU | | | | Lc is 52, number of bytes in APDU's data | 52 bytes, the rest of the data | | For both calls, the CLA, INS, P1, and P2 values are the same (except for the `0x10` bit in the CLA of the first call). The data is simply broken up. Notice that the data in the first APDU contains some TLV constructions. But those tags are not in the second APDU's data. The second APDU simply continues with the data. ### Response APDU chaining[](https://docs.yubico.com/yesdk/users-manual/yubikey-reference/apdu.html#response-apdu-chaining) If the YubiKey needs to return more than 256 bytes of data, it will need to break it up into multiple response APDUs. The response APDU will contain up to 256 bytes of data, followed by SW1 and SW2. If SW1 is `61`, then SW2 contains the number of bytes that still need to be returned. The application running on the host (off-card) will receive the data, and when getting to the status word, will see that there are more bytes waiting to be transferred. At that point, the application needs to send a new command APDU: GET RESPONSE (`00 c0 00 00`). For example, suppose the application wanted a copy of the attestation certificate. The process would look something like this. command APDU: 00 cb 3f ff 05 5c 03 5f ff 01 response APDU: 53 82 02 f5 ... 61 ff command APDU: 00 c0 00 00 response APDU: a9 e9 c1 5b ... 61 f9 command APDU: 00 c0 00 00 response APDU: 28 42 e5 8d ... 90 00 The first command APDU is GET DATA and the data it is requesting is the attestation cert. The first response APDU starts sending the cert. SW1 is `61`, meaning there's more data, and SW2 is `ff` meaning there is at least 255 bytes of data still to transfer. So the application sends the GET RESPONSE APDU. The YubiKey returns more data (simply picking up where it left off), and SW1 of `61` (more data still) and SW2 of `f9` (only 249 bytes left). The application sends GET RESPONSE again. This time the response is 249 bytes of data and SW1, SW2 of 90 00, meaning success, so there's no more data. [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/yubikey-reference/apdu.md/#L1) Previous [Physical interfaces](https://docs.yubico.com/yesdk/users-manual/yubikey-reference/transports/overview.html) Next [OTP application](https://docs.yubico.com/yesdk/users-manual/application-otp/application-concepts-overview.html) --- # YubiHSM 2 User Guide — YubiHSM 2 User Guide documentation * [](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/index.html#) * YubiHSM 2 User Guide * [View page source](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/_sources/index.rst.txt) * * * YubiHSM 2 User Guide[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/index.html#yubihsm-2-user-guide "Permalink to this heading") ================================================================================================================================================= Contents * [Introduction](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-introduction.html) * [Operating System Requirements](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-introduction.html#operating-system-requirements) * [Physical Characteristics](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-introduction.html#physical-characteristics) * [YubiHSM 2 Cryptographic Specifications](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-introduction.html#yubihsm-2-cryptographic-specifications) * [FIPS certified](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-introduction.html#fips-certified) * [Performance](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-introduction.html#performance) * [Management](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-introduction.html#management) * [Core Concepts](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-core-concepts.html) * [Objects](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-core-concepts.html#objects) * [Capabilities](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-core-concepts.html#capabilities) * [Domains](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-core-concepts.html#domains) * [Label](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-core-concepts.html#label) * [Object ID](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-core-concepts.html#object-id) * [Origin](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-core-concepts.html#origin) * [Sequence](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-core-concepts.html#sequence) * [Options](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-core-concepts.html#options) * [Attestation](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-core-concepts.html#attestation) * [Logs and Error Codes](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-core-concepts.html#logs-and-error-codes) * [Effective Capabilities (Tying It All Together)](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-core-concepts.html#effective-capabilities-tying-it-all-together) * [YubiHSM 2 SDK Tools And Libraries](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-sdk-tools-libraries.html) * [YubiHSM 2 SDK Downloads](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-sdk-tools-libraries.html#yubihsm-2-sdk-downloads) * [YubiHSM 2 Communication](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-sdk-tools-libraries.html#yubihsm-2-communication) * [YubiHSM 2 Setup Tool](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-sdk-tools-libraries.html#yubihsm-2-setup-tool) * [YubiHSM 2 Shell](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-sdk-tools-libraries.html#yubihsm-2-shell) * [YubiHSM 2 Connector](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-sdk-tools-libraries.html#hsm2-connector-label) * [YubiHSM 2 Auth](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-sdk-tools-libraries.html#yubihsm-2-auth) * [YubiHSM 2 Wrap](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-sdk-tools-libraries.html#yubihsm-2-wrap) * [YubiHSM 2 Key Storage Provider (KSP)](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-sdk-tools-libraries.html#yubihsm-2-key-storage-provider-ksp) * [PKCS#11](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-sdk-tools-libraries.html#pkcs-11) * [Libyubihsm](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-sdk-tools-libraries.html#hsm2-libyubishm-label) * [Python Library](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-sdk-tools-libraries.html#python-library) * [Getting Started](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-quick-start.html) * [Set Up the YubiHSM 2 Environment](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-quick-start.html#set-up-the-yubihsm-2-environment) * [Connect to the YubiHSM 2](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-quick-start.html#connect-to-the-yubihsm-2) * [Initial Provisioning and Deployment for HMAC, PKCS11, or RSA](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-quick-start.html#initial-provisioning-and-deployment-for-hmac-pkcs11-or-rsa) * [Add a New Authentication Key](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-quick-start.html#add-a-new-authentication-key) * [Generate an Asymmetric Key Object for Signing](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-quick-start.html#generate-an-asymmetric-key-object-for-signing) * [Export an Asymmetric Key Under Wrap](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-quick-start.html#export-an-asymmetric-key-under-wrap) * [YubiHSM 2 Management Tasks](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-index-tools.html) * [Set FIPS Mode](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-fips-support-guide.html) * [Set up KSP on Windows](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-configure-software-windows.html) * [Backup and Restore with YubiHSM Backup Keys](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-backup-restore.html) * [Reset YubiHSM to Factory Settings](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-reset-to-factory.html) * [Third Party Integration Deployment Guides](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-index-third-party.html) * [Deploy for OpenSSH Certificates for Host Login](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-openssh-certs-host-login.html) * [Deploy for OpenSC pkcs11-tool](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-opensc-pkcs11.html) * [Deploy for OpenSSL with libp11](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-openssl-libp11.html) * [Deploy for OpenSSL with engine\_pkcs11 and yubihsm\_pkcs11](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-openssl-yubihsm2.html) * [Deploy for Signing Java Code](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-java-code-signing.html) * [Deploy for OpenSSL on Windows](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-openssl-windows-guide.html) * [Deploy for Active Directory Certificate Services CA](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-adcs-deploy.html) * [Deploy for Microsoft Host Guardian Service (HGS)](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-ms-host-guardian-service-guide.html) * [Deploy for Microsoft SQL Server](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-ms-sql-server-deploy-guide.html) * [Deploy for EJBCA](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-ejbca-guide.html) * [YubiHSM 2 References](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-index-references.html) * [YubiHSM Algorithms](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-algorithms.html) * [YubiHSM Command Reference](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-cmd-reference.html) * [Glossary](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-glossary.html) * [Copyright](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/copyright.html) [Cookies](https://www.yubico.com/support/terms-conditions/cookie-notice/) | [Privacy Policy](https://www.yubico.com/support/terms-conditions/privacy-notice/) --- # .NET YubiKey SDK: User's Manual ##### Table of Contents .NET YubiKey SDK: User's Manual =============================== This manual gives general information about the SDK and how to use it. After reading about a topic, you can get programming details from the [API Documentation](https://docs.yubico.com/yesdk/yubikey-api/index.html) section. [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/intro.md/#L1) --- # .NET YubiKey SDK .NET YubiKey SDK ================ The SDK allows you to integrate the YubiKey and its applications into your .NET-based application or library. SDK documentation ----------------- The documentation for the .NET YubiKey SDK is split into two main sections: * A [user's manual](https://docs.yubico.com/yesdk/users-manual/intro.html) that describes the concepts that you will encounter while working with the SDK and the YubiKey. It provides a general outline of how to use the SDK. Tutorials and walk-throughs can be found here as well. * [API Documentation](https://docs.yubico.com/yesdk/yubikey-api/index.html) is where detailed descriptions of the classes and interfaces of the SDK reside. Supported platforms ------------------- Modern .NET supports more than just Microsoft Windows, and so do we. Support for macOS is built in, and has been tested on both Intel and Apple Silicon (i.e. M1) platforms. (Apple Silicon is supported through Rosetta 2.) We also support common Linux distributions such as Debian, Ubuntu, RHEL, and CentOS. Other distros may still work, but they have not been tested by the SDK team. Future distribution and platform support will be driven by customer interest. This SDK targets .NET Standard 2.0, allowing for a wide reach of .NET platforms. See [this page](https://docs.microsoft.com/en-us/dotnet/standard/net-standard) for more information on what .NET implementations support .NET Standard 2.0. Note that while this SDK may build with Xamarin and Mono, only the Windows and macOS operating systems are supported at this time. Additionally, while .NET Framework 4.6.x is listed as implementing Standard 2.0, this is not entirely true. The SDK relies on certain cryptographic functionality that is defined in the standard but not actually implemented in Framework 4.6.x. Supported YubiKey applications ------------------------------ The YubiKey is a versatile security key that supports numerous standards and protocols. This SDK offers full support for integrating with Yubico OTP, along with the OATH, PIV, and FIDO U2F standards. ### OTP Yubico OTP is a simple yet strong authentication mechanism that is supported by all YubiKeys out of the box. Yubico OTP can be used as the second factor in a 2-factor authentication scheme or on its own, providing 1-factor authentication. Read more about OTP [here](https://docs.yubico.com/yesdk/users-manual/application-otp/otp-overview.html) . ### OATH The Initiative for Open Authentication (OATH) is an organization that specifies two open one-time password standards: HMAC OTP (HOTP), and the more familiar Time-based OTP (TOTP). Read more about OATH [here](https://docs.yubico.com/yesdk/users-manual/application-oath/oath-overview.html) . ### PIV Personal Identity Verification (PIV), or FIPS 201, is a US government standard. It enables RSA signing and encryption, along with ECC signing and key agreement operations using a private key stored on a smart card (such as the YubiKey 5). PIV is primarily used for non-web applications. It has built-in support under Windows and can be used on macOS as well. Read more about PIV [here](https://docs.yubico.com/yesdk/users-manual/application-piv/piv-overview.html) . ### FIDO U2F U2F is an open authentication standard that enables keychain devices, mobile phones and other devices to securely access any number of web-based services - instantly and with no drivers or client software needed. U2F was created by Google and Yubico, with contribution from NXP, and is today hosted by the open-authentication industry consortium [FIDO Alliance](https://fidoalliance.org/) . The technical specifications were launched in late 2014, including native support in Google Accounts and Chrome, and have since resulted in a thriving ecosystem of hardware, software and service providers. Read more about FIDO U2F [here](https://docs.yubico.com/yesdk/users-manual/application-u2f/fido-u2f-overview.html) . ### FIDO2 FIDO2 is the "second generation" of the FIDO open authentication standard. It is similar to U2F in that implementations allow instant secure access to web-based services, with no drivers or client software needed. FIDO2 was created by the [FIDO Alliance](https://fidoalliance.org/) -- a consortium of dozens of tech and other companies as well as government organizations from around the world -- along with the [W3C](https://www.w3.org/) (World Wide Web Consortium). The technical specifications for FIDO2 were launched in 2018. Today, many [browsers and mobile platforms support FIDO2](https://support.yubico.com/hc/en-us/articles/360016615020-Operating-system-and-web-browser-support-for-FIDO2-and-U2F) . Read more about FIDO2 [here](https://docs.yubico.com/yesdk/users-manual/application-fido2/fido2-overview.html) . ### YubiHSM Auth YubiHSM Auth is a YubiKey CCID application that stores the long-lived credentials used to establish secure sessions with a YubiHSM 2. The secure session protocol is based on Secure Channel Protocol (SCP). YubiHSM Auth is supported by YubiKey firmware version 5.4.3. YubiHSM Auth uses hardware to protect these long-lived credentials. In addition to providing robust security for the YubiHSM Auth application itself, this hardware protection subsequently increases the security of the default password-based solution for YubiHSM 2's authentication. Read more about YubiHSM Auth [here](https://docs.yubico.com/yesdk/users-manual/application-yubihsm-auth/yubihsm-auth-overview.html) . ### Security Domain The Security Domain is a special application on the YubiKey responsible for managing secure communication channels and cryptographic keys. It implements protocols defined by [Global Platform Consortium](https://globalplatform.org/) that provide confidentiality and integrity for commands sent between host applications and the YubiKey. Read more about Security Domain [here](https://docs.yubico.com/yesdk/users-manual/application-security-domain/security-domain-overview.html) . [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/index.md/#L1) --- # .NET YubiKey SDK: YubiKey API reference ##### Table of Contents .NET YubiKey SDK: YubiKey API reference ======================================= This section of the documentation contains the specific information about each class in the Yubico.YubiKey library. For a high-level overview and discussions of the concepts and operations of the YubiKey and this SDK, visit the [User's Manual](https://docs.yubico.com/yesdk/users-manual/intro.html) . [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/yubikey-api/index.md/#L1) --- # .NET YubiKey SDK: Core API reference ##### Table of Contents .NET YubiKey SDK: Core API reference ==================================== This section of the documentation contains the specific information about each class in the Yubico.Core library. For a high-level overview and discussions of the concepts and operations of the YubiKey and this SDK, visit the [User's Manual](https://docs.yubico.com/yesdk/users-manual/intro.html) . [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/core-api/index.md/#L1) --- # What is a YubiKey? ##### Table of Contents What is a YubiKey? ================== The YubiKey is a multi-application, multi-protocol personal security device aimed at protecting an individual's online identity. YubiKeys currently support the following: * One-time password generation * Yubico OTP * OATH-HOTP * OATH-TOTP * Smart cards * Personal Identity Verification (PIV) card * OpenPGP card * YubiHSM Auth * FIDO / WebAuthn * FIDO Universal 2nd Factor (U2F) * FIDO2 The YubiKey 5 Series -------------------- The YubiKey 5 Series security keys offer strong authentication with support for multiple protocols, including FIDO2, which is a new standard that enables the replacement of password-based authentication. The YubiKey strengthens security by replacing passwords with strong hardware-based authentication using public key cryptography. ### What's new in the YubiKey? #### FIDO2 All devices in the YubiKey 5 Series support FIDO2 / WebAuthn, enabling secure passwordless authentication on websites and applications that support the protocol. #### NFC The YubiKey 5 NFC brings NFC capabilities to the YubiKey 5 Series. All of the applications, including FIDO2, are available over NFC, expanding the options for quick tap-n-go authentication across desktops, laptops, and mobile devices. This makes the YubiKey 5 NFC an ideal upgrade for the YubiKey NEO. #### Easier identification The YubiKey 5 Series devices can report their form factor via the new management application. They can additionally report whether or not they support applications over the NFC interface. This enables easier, programmatic identification of the physical attributes of the YubiKey. [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/getting-started/what-is-a-yubikey.md/#L1) --- # How to install the SDK ##### Table of Contents How to install the SDK ====================== Installing the .NET YubiKey SDK can be done using the NuGet package manager. Supported versions of .NET -------------------------- The YubiKey SDK targets .NET Standard 2.0 for wide compatibility. .NET Standard is not an implementation of .NET, but instead describes the minimum set of requirements for an implementation. You can read more about .NET Standard and what it means [here](https://docs.microsoft.com/en-us/dotnet/standard/net-standard) . Targeting 2.0 means that this SDK can be used by: * **.NET 5.0** or newer * **.NET Core 2.0** or newer * **.NET Framework 4.6.1** or newer * **Mono 5.4** or newer * **UWP 10.0.16299** or newer * **Xamarin.Mac 8.0** While the Xamarin.iOS and Xamarin.Android frameworks are technically supported by .NET Standard 2.0, this SDK does not currently support the iOS or Android platforms. Adding the NuGet package reference ---------------------------------- The official SDK releases can be found on the NuGet package manager under the [Yubico organization](https://www.nuget.org/profiles/Yubico) . The package to install is called [Yubico.YubiKey](https://www.nuget.org/packages/Yubico.YubiKey/) . ### Using Visual Studio Adding the SDK to your project using Visual Studio can be done in a few steps: 1. With your solution open, right click on the project you wish to add the dependency to in the solution explorer tool window. 2. Make sure the package source, located in the top right of the NuGet Package Manager window, is set to `nuget.org`. 3. Click on the `Browse` tab and search for `Yubico.YubiKey`. 4. Click on the `Install` button. NuGet will display a list of the SDK's dependencies. Click `Accept`. NuGet will then display the license information for the project and dependencies. Read and accept the license agreements to continue. Now your project is ready to use the YubiKey SDK! Start by adding using Yubico.YubiKey; to the top of your source file to get started. ##### Note In order to install a pre-release version of the SDK, you need to make sure the "Include Prerelease" checkbox is checked in the NuGet Package Manager window. ### Using the dotnet CLI You can add the SDK to your project using the `dotnet` command line tool. Use the [`add package` command](https://docs.microsoft.com/en-us/dotnet/core/tools/dotnet-add-package) . The package name for the SDK is `Yubico.YubiKey`. Use the following example invocation as reference: dotnet add package Yubico.YubiKey ##### Note In order to install a pre-release version of the SDK, include the `--prerelease` parameter. ### Editing your project manually This section assumes the project file format is the "SDK-style" seen in .NET Core and .NET 5+ projects. Open the `*.csproj` file for your project in your favorite text editor. You should see something like the following: Exe net5.0 Insert a new `ItemGroup` tag pair after the property group, or use an existing group that contains other package references. Add a `PackageReference` tag with an `Include` attribute set to the name of the SDK package: `Yubico.YubiKey`. Add a `Version` attribute and enter the latest version number of the SDK found on NuGet. Your project file should now look something like: Exe net5.0 [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/getting-started/how-to-install.md/#L1) --- # Running .NET SDK applications on Linux ##### Table of Contents Running .NET SDK applications on Linux ====================================== Some special steps may be required to run applications that depend on the .NET SDK on Linux. Distributions ------------- ### Officially supported A distribution is officially supported after our team has run through our acceptance tests on that distro. This is not the exhaustive suite of tests for the SDK, but it's enough to give us confidence that the platform-specific device discovery and communication logic are working properly. Any abnormalities observed should be reported to our [GitHub repo](https://github.com/Yubico/Yubico.NET.SDK/issues) . At this time, the SDK has been tested to work on the following Linux distributions: * Debian * Ubuntu * CentOS * RedHat Enterprise Linux (RHEL) ### Other distros There are plenty of popular distros that are _not_ on this list. Though not officially supported, there is a high likelihood that the SDK will still work on these distros. The instructions below will likely be identical or very similar to what you will need to do to get started with your distribution of choice. Dependencies ------------ The .NET SDK depends on two main components for device communication: udev and pcsc-lite. ### PCSC-lite PCSC-lite (referred to as PCSC for the remainder of this document) is a library used to communicate with smart card readers and smart cards. Much of the YubiKey functionality is exposed to an operating system as a smart card, so PCSC is likely critical for your user to have installed. If you are planning to develop against the OATH, PIV, or OpenPGP YubiKey applications, or you want to communicate with the YubiKey over NFC, you will certainly need to have PCSC installed on the computer running your application. PCSC can be installed in the following way: # For APT based distros (e.g. Debian, Ubuntu): sudo apt install pcscd # For YUM based distros (e.g. RedHat, CentOS): sudo yum install pcsc-lite ### UDev UDev is a common Linux device manager available on most distributions. It is used to discover PnP devices, from displays and sound cards to mice and keyboards. In the case of the .NET SDK, UDev is used to discover the two HID devices exposed by the YubiKey. UDev should typically already be installed on your system. If it is not, that may mean that your Linux distro uses an alternate device management system. Swapping your current device manager with UDev is likely not a viable option and is not recommended. If you are running a distro that is not running UDev and you are interested in using this SDK, please open an issue on our [GitHub repo](https://github.com/Yubico/Yubico.NET.SDK/issues) . If there is broad interest, we will evaluate adding support to our roadmap. #### Making sure the SDK can find UDev As of SDK 1.4.0, the SDK P/Invokes UDev's shared library `libudev.so`. This library can have multiple names (usually including a version number, e.g. `libudev.so.1`), so we target the lowest common denominator name: `libudev`. As of .NET 7, the .NET library resolver is not capable of automatically resolving the full path / name of this dependency. As such, it will likely be required that you create a symbolic link from your shared library directory, typically `/usr/lib`, to the real location of libudev. For example: # On Debian and Ubuntu, libraries are usually stored in an x86_64 subdirectory: sudo ln -s /usr/lib/linux-x86_64/libudev.so.1 /usr/lib/libudev.so # On CentOS and RHEL, libraries are usually stored in a lib64 subdirectory: sudo ln -s /usr/lib64/libudev.so.1 /usr/lib/libudev.so Note that the exact file name and location may change based on your distribution and the version of libudev installed. ### .NET and OpenSSL / libcrypto Some distributions, like Ubuntu, have started to phase out older versions of OpenSSL, making OpenSSL 3.x its default. Older .NET versions such as .NET Core 3.1 do not support this and require older versions of OpenSSL. Be aware that .NET itself may have dependencies like this, and the choice of framework version may have further impact for your application's stated dependencies. Although the SDK supports any .NET implementation of .NET Standard 2.0, it is recommended that .NET 6.x be your minimum target. This is a long-term support release of .NET and has the needed support for the newer versions of OpenSSL. It also includes quite a few general improvements to the Linux experience. [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/getting-started/running-on-linux.md/#L1) --- # Threads ##### Table of Contents Threads ======= The YubiKey is effectively single-threaded. Although there really is no concept of a thread on a YubiKey, it is best to think of all operations on the YubiKey happening in the same thread. Suppose you have a multithreaded application. Now suppose you make a connection to a YubiKey in one of those threads, and then make another connection in a separate thread. You will not get two connections operating independently. Any call to the YubiKey in one thread will affect the internal state, which will affect any call from the other thread. Because of this, the SDK is built to be run in a single thread. You should write your code accordingly. Either make sure all interactions with the YubiKey are handled by one thread only, or use locks to guarantee only one thread at a time calls to the YubiKey. [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/sdk-programming-guide/threads.md/#L1) --- # The KeyCollector's touch notification ##### Table of Contents The KeyCollector's touch notification ===================================== Normally, the KeyCollector is used to collect PINs, keys, or other secret values. However, it is also used to notify the caller that an operation requires touch or a fingerprint in order to complete. For example, suppose your code is calling the SDK in order to make a FIDO2 credential on a YubiKey. The SDK will call on the YubiKey to perform the `MakeCredentialCommand`. That command will be able to complete the task only if user touches the gold contact at the right time. But when exactly is the user supposed to touch the contact? You could write your code to guess when touch is needed, which might work. However, if you supply a KeyCollector, the SDK will notify your application (which can then notify the user) exactly when it is needed. What the SDK does ----------------- When the SDK needs the user to touch the YubiKey's contact, it will call the KeyCollector delegate with the `KeyEntryRequest.TouchRequest`. var keyEntryData = new KeyEntryData() { Request = KeyEntryRequest.TouchRequest }; _ = KeyCollector(keyEntryData); The return from the KeyCollector is a boolean. A `false` return indicates the SDK should cancel the operation. However, this call is informative only, there is no cancelling. Hence, the SDK will ignore the return value. The SDK will make the KeyCollector call on a new thread, which allows work on the main communication thread between the SDK and YubiKey to proceed without interruption. Later on, when the operation has completed (the user touched the contact), timed out (the user did not touch the contact in time), or there was an error, the SDK will call the KeyCollector again, this time with the `KeyEntryRequest.Release`. This call to release will be on the same thread as the call to request touch. What your KeyCollector should do -------------------------------- When the SDK calls your KeyCollector delegate with the touch request, it needs to do two things: notify the user that touch is needed and return to the SDK "immediately". "Immediately" means your code should not wait for an indeterminate operation to complete before returning. An example of an indeterminate operation is waiting for a user to click an "OK" button; it might happen quickly, it might not happen for several seconds, it is possible it doesn't happen for days or even ever. You might accomplish this by writing the touch notification to the command line (e.g. `Console.WriteLine`), launching a modeless notification window, or launching a modal notification window on a new thread (e.g. `Task` class). In all three of these possibilities, your code will make calls that perform an operation for which the caller (the SDK) does not need to wait. This call to the KeyCollector notifies your code that user interaction with the YubiKey is needed. It is possible to write a KeyCollector that requires further user interaction as well. For example, you could write a KeyCollector that launches a window with a message indicating the YubiKey needs touch, plus an "OK" button (or similar). That is, there are two acts of user interaction here: touch the YubiKey's contact and click the "OK' button. The window is not closed until the button is clicked. However, because the touch notification is informative only, your KeyCollector most likely should not require further user interaction. Hence, your best option is likely a modeless notification window, such as Example 2 below. When the YubiKey's operation is complete (either timeout, error, or the user did indeed touch, and it executed successfully), the SDK calls your KeyCollector with the Release request. You will have the opportunity to close any windows or perform any other cleanup necessary. ### Example 1: Console public class SampleKeyCollector { . . . public bool Fido2SampleKeyCollectorDelegate(KeyEntryData keyEntryData) { . . . switch (keyEntryData.Request) { case KeyEntryRequest.TouchRequest: // This call does not wait for any other action (such as user interaction) // to return. It writes to the console and returns "immediately". Console.WriteLine("Touch the YubiKey's contact to complete the operation.\n"); return true; case KeyEntryRequest.Release: // There's no cleanup necessary with a call to Console.WriteLine. return true; } } . . . } ### Example 2: Modeless window In this example, the KeyCollector will launch a window, which will remain until its `Visible` property is set to `false`. That happens when the SDK calls with `Release`. The procedure can be described as follows: * The SDK discovers that touch is needed. * The SDK creates a new thread (call it thread T) and calls the KeyCollector on this thread with the request `TouchRequest`. * The KeyCollector launches a window with a message. This call returns "immediately" to the KeyCollector. * The KeyCollector in turn returns "immediately" to the SDK. * When the operation completes (most likely the user touched the YubiKey's contact), the SDK, on Thread T, calls the KeyCollector with the request `Release`. * The KeyCollector takes down the window and returns. * Thread T ends. This is what it looks like from the user's perspective: * A window appears indicating they need to touch the YubiKey's contact. * They touch the contact. * The Window disappears. using System.Windows.Forms; // This class contains fields of Form and Label, which implement // IDisposable, which means it is likely your KeyCollector will also need // to implement IDisposable, and in your Dispose, call the Form and Label // Dispose methods. public class SampleKeyCollector : IDisposable { private Form _form; private Label _label; private bool _disposed; . . . public bool Fido2SampleKeyCollectorDelegate(KeyEntryData keyEntryData) { . . . switch (keyEntryData.Request) { case KeyEntryRequest.TouchRequest: _form = new Form { Text = "User Action Required", MaximizeBox = false, MinimizeBox = false, ControlBox = false, StartPosition = FormStartPosition.CenterScreen }; _label = new Label { Text = "Touch the YubiKey's contact to complete the operation.", AutoSize = true }; _form.Controls.Add(_label); // This call launches the window with the title "User Action Required" // and the message in the client area "Touch the YubiKey's contact ...". // It is modeless so does not wait for any other action (such as user // interaction) to return. It simply launches the window and returns, // just as a call to Console.WriteLine does. Hence, it will return to // the SDK "immediately". The window will remain visible until it is // closed. _form.Show(); _label.Refresh(); return true; case KeyEntryRequest.Release: // This will be called on the same thread as the TouchRequest was made. // Now that we know the YubiKey has completed its operation, we can // close the window. if (!(_label is null)) { _label.Visible = false; _label.Dispose(); _label = null; } if (!(_form is null)) { _form.Visible = false; _form.Dispose(); _form = null; } return true; } } . . . } In this example, a window is built using the `Form` class and launched using the `Show` method. By launching using the `Show` method, it is a modeless window. It is possible to launch it as a modal window (requiring user interaction) by calling the `ShowDialog` method. [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/sdk-programming-guide/key-collector-touch.md/#L1) --- # Delegates (callbacks) in the SDK ##### Table of Contents Delegates (callbacks) in the SDK ================================ There are a number of places in the SDK where the developer must supply a `delegate`, the C# version of a `callback`. This page discusses what they are, and how to write your own. A callback ---------- A callback is simply a function you provide the SDK. In turn, the SDK will call that function when it needs to do some work that only your application can do. The easiest way to illustrate this is with an example: the PIN collector. Suppose you are building a PIV application, and want to sign some data. That operation requires the PIN to be verified (it is possible to turn off the PIN requirement, but for now, let's just look at the case where the PIN is required). In order to verify the PIN, the SDK, of course, needs the PIN. How should that be provided? While it is possible to simply require the caller enter the PIN as a byte array, the SDK requests a PIN-collecting function. In this way, when the SDK needs the PIN, it will call this function, use the PIN it collects, then release it. Following this pattern, the PIN appears in memory the least amount of time (see the User's Manual entry on [sensitive data](https://docs.yubico.com/yesdk/users-manual/sdk-programming-guide/sensitive-data.html) ). The SDK does not have a PIN-collecting class or method. That's because how your application collects the PIN is up to you. Maybe you collect it at the command line, maybe you launch a new Window, or have a "sub-window" of the main window. Maybe you collect it once at the beginning and simply keep it in a buffer somewhere (not recommended). When the sign operation needs the PIN, it will call a PIN-collecting function. But because there is no such method in the SDK, it will be your responsibility to provide one. Read [this article about the `KeyCollector`](https://docs.yubico.com/yesdk/users-manual/sdk-programming-guide/key-collector.html) for details on this delegate. [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/sdk-programming-guide/delegates-in-sdk.md/#L1) --- # The KeyCollector and alternatives ##### Table of Contents The `KeyCollector` and alternatives =================================== ##### Note The sample code contains sample key collectors. One sample key collector can be found at `Yubico.YubiKey/examples/PivSampleCode/KeyCollector`. It collects PINs and keys from the command line. See also the section below, [Building a KeyCollector](https://docs.yubico.com/yesdk/users-manual/sdk-programming-guide/key-collector.html#building-a-keycollector) . In the SDK, there is the concept of a `KeyCollector`. This is a user-supplied [delegate](https://docs.yubico.com/yesdk/users-manual/sdk-programming-guide/delegates-in-sdk.html) , a callback method the SDK calls when it needs a PIN, password, key, or some other secret value in order to complete verification or authentication. ##### Note The key collector is also used to notify the caller that touch or a fingerprint is needed. See the [article on the KeyCollector and touch](https://docs.yubico.com/yesdk/users-manual/sdk-programming-guide/key-collector-touch.html) for a more detailed description of how to handle touch notifications. For example, with the PIV application, you can make a call to sign data. That requires the PIN to be verified in order to execute. using (var pivSession = new PivSession(yubiKey)) { pivSession.KeyCollector = CallerSuppliedKeyCollector; byte[] signature = pivSession.Sign(PivSlot.Authentication, dataToSign); } The SDK's `Sign` method will determine it needs the PIN, so it will make a call to `CallerSuppliedKeyCollector`, requesting the PIN. That method will do what it needs to get the PIN from the end user, such as creating a new Window with a PIN box or writing/reading from the command line. The `KeyCollector` returns the PIN and the SDK verifies it. The data can now be signed. It is also possible to call the `VerifyPin` method directly. using (var pivSession = new PivSession(yubiKey)) { pivSession.KeyCollector = SomeKeyCollector; pivSession.VerifyPin(); } As with the `Sign` method, the `VerifyPin` will call on the `KeyCollector` to retrieve the PIN. Normally, an application would never call the `VerifyPin` method because there's no need. The SDK will automatically make the necessary calls to verify a PIN when it needs the PIN to be verified, and simply won't verify if it does not need it. Once a PIN has been verified in a session, generally, there is no need to verify it again in that session (there are exceptions [discussed below](https://docs.yubico.com/yesdk/users-manual/sdk-programming-guide/key-collector.html#called-if-needed-more-than-once) ). For example, suppose you want to create two signatures. using (var pivSession = new PivSession(yubiKey)) { pivSession.KeyCollector = SomeKeyCollector; byte[] signature1 = pivSession.Sign(PivSlot.Authentication, dataToSign1); byte[] signature2 = pivSession.Sign(PivSlot.Authentication, dataToSign2); } using (var pivSession = new PivSession(yubiKey)) { pivSession.KeyCollector = SomeKeyCollector; pivSession.VerifyPin(); byte[] signature1 = pivSession.Sign(PivSlot.Authentication, dataToSign1); byte[] signature2 = pivSession.Sign(PivSlot.Authentication, dataToSign2); } In the first session above, the first call to `Sign` will, "under the covers", make a call to verify the PIN. For the second call to `Sign`, there is no need, the PIN has already been verified. In the second session above, the PIN has been verified by the call to `VerifyPin`, so both calls to `Sign` will execute without calling the `VerifyPin` method under the covers. Verification and authentication without the `KeyCollector` ========================================================== The SDK contains methods to verify and authenticate where the secret value is provided by the caller, rather than the `KeyCollector`. For example, with PIV, there are these methods. bool TryVerifyPin(ReadOnlyMemory pin, out int? retriesRemaining); bool TryChangePin(ReadOnlyMemory currentPin, ReadOnlyMemory newPin, out int? retriesRemaining); bool TryChangePuk(ReadOnlyMemory currentPuk, ReadOnlyMemory newPuk, out int? retriesRemaining); bool TryResetPin(ReadOnlyMemory puk, ReadOnlyMemory newPin, out int? retriesRemaining); bool TryChangePinAndPukRetryCounts( ReadOnlyMemory managementKey, ReadOnlyMemory pin, byte newRetryCountPin, byte newRetryCountPuk, out int? retriesRemaining); bool TryAuthenticateManagementKey(ReadOnlyMemory managementKey, bool mutualAuthentication = true); bool TryChangeManagementKey( ReadOnlyMemory currentKey, ReadOnlyMemory newKey, PivTouchPolicy touchPolicy = PivTouchPolicy.Default) There is no need to build a `KeyCollector`. You simply verify the PIN and authenticate the management key each session. The case for a `KeyCollector` ============================= If you want to use the caller-supplied verify and authenticate methods, you are still going to need to collect the PIN, password, or key. That is, your application most likely contains a "Key Collector" component already. For example, you have code to collect the PIN from the user, otherwise where did the PIN come from? Because you probably already have code to collect the PIN/Password/Key, it is likely not going to be difficult to extend it to fit within the SDK's `KeyCollector` framework. Furthermore, there are advantages to using the `KeyCollector`. The SDK manages PIN, password, and key requirements --------------------------------------------------- With PIV, for example, some operations require the PIN, other operations require the management key, and still other operations that require both. With a `KeyCollector`, you do not need to make sure your code is written to fulfill the correct verify/auth logic. The SDK takes care of that for you. Collected only if needed ------------------------ The SDK will only ask for a secret to be collected if it is needed. This reduces the exposure to attack. See the User's Manual article on [sensitive data](https://docs.yubico.com/yesdk/users-manual/sdk-programming-guide/sensitive-data.html) . One alternative is for your app to manage the logic of when each secret is needed. Another alternative is to simply use the caller-supplied secret verification methods at the beginning of each session. Generally, once a secret has been verified in a session, there is no need to verify it again. Hence, just make sure each secret is authenticated in each session and there is no futher management needed. For example, with PIV, you could do this. using (var pivSession = new PivSession(yubiKey)) { bool isAuth = pivSession.TryAuthenticateManagementKey(mgmtKey); bool isVerified = pivSession.TryVerifyPin(pin); . . . } One downside to this is that you will be authenticating a secret even when it is not needed. If your application will be doing something that needs the PIN, but it won't be doing anything that needs the management key, you will be requiring the user to provide the management key anyway, making them perform some task that is not needed. In addition, it increases the exposure to attack. Another downside is that there are rare cases when a PIN might be needed more than once. These exceptions are [discussed below](https://docs.yubico.com/yesdk/users-manual/sdk-programming-guide/key-collector.html#called-if-needed-more-than-once) . The SDK manages retries ----------------------- Suppose your application creates a PIV session and you will be doing something that requires PIN verification. You collect the PIN from the user and call the following. using (var pivSession = new PivSession(yubiKey)) { bool isVerified = pivSession.TryVerifyPin(pin, out int? retriesRemaining); } Suppose the return is `false`. Maybe the user typed `Paris167, but the PIN is really` Paris16\` Now what? How about the following? using (var pivSession = new PivSession(yubiKey)) { ReadOnlyMemory pin = CollectPin(); while (!pivSession.TryVerifyPin(pin, out int? retriesRemaining)) { if (!CollectPin(someMessage, retriesRemaining, out ReadOnlyMemory pin)) { throw OperationCanceledException(message); } } } Much of this logic is already handled by the SDK. You can call the following. using (var pivSession = new PivSession(yubiKey)) { pivSession.KeyCollector = SomeKeyCollector; // false is returned if the user cancels. bool isVerified = pivSession.TryVerifyPin(); // An exception is thrown if the user cancels. pivSession.VerifyPin(); } In these cases the SDK will handle the retries. It will call the `KeyCollector` until the correct PIN is entered, the delegate returns canceled, or the retry count goes to zero. The `KeyCollector` you provide will have to decide how to present the retry count to the user and offer a way to cancel. But any solution will need to do that. The SDK tells the `KeyCollector` to `Release` --------------------------------------------- Once the secret has been authenticated, it is a good idea to overwrite sensitive data. With a `KeyCollector` you write that code once. The SDK will call the `KeyCollector` with `KeyEntryRequest.Release`, indicating that the SDK no longer needs the collected value. The `KeyCollector` knows it can now overwrite any data and release any other resources. If you don't use the `KeyCollector`, you will have to write the release code every time. For example, here is a possibility. using (var pivSession = new PivSession(yubiKey)) { var pinData = new Memory(new byte[8]); try { int pinLength = CollectPin(pinData); while (!pivSession.TryVerifyPin(pinData.Slice(0, pinLength, out int? retriesRemaining)) { pinLength = CollectPin(someMessage, retriesRemaining, pinData)) if (pinLength == 0) { throw OperationCanceledException(message); } } } finally { CryptographicOperations.ZeroMemory(pinData.Span); } } Called "just in time" --------------------- The SDK will not request a secret until it is needed. That means you don't need to collect it and have it waiting around in memory, just in case it is needed. Of course, you can collect it at the beginning of a session, authenticate it, and release it. But that has its own [problems](https://docs.yubico.com/yesdk/users-manual/sdk-programming-guide/key-collector.html#collected-only-if-needed) . Called if needed more than once ------------------------------- There are rare cases where authentication of a secret is needed more than once per session. In such a case, using a `KeyCollector` will be the most convenient. For example, with PIV, it is possible to generate or load a private key with the PIN policy "Always". This means the PIN must be verified each time it is used, even if the PIN has already been verified in the session. Under the covers, the [Verify command](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#verify) must be the only command executed before the [Sign command](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#authenticate-sign) . If using the `KeyCollector`, the SDK will make sure that happens. Without it, you will be required to manage it. Might be needed for PIV PIN-only mode ------------------------------------- Many applications will set a YubiKey to [PIN-only](https://docs.yubico.com/yesdk/users-manual/application-piv/pin-only.html) . This means that PIV operations that require management key authentication will be able to execute with the caller supplying onl the PIN. If a YubiKey is set to the PIN-only mode of `PinDerived`, the SDK will require a `KeyCollector` to obtain the PIN. Note that Yubico recommends applications NOT use `PinDerived`. It is provided only for backwards compatibility. You should only use `PinProtected`. If a YubiKey is set for `PinProtected`, it will generally be possible to use the YubiKey without a `KeyCollector`. However, there are odd cases where a YubiKey can be set for `PinProtected` and a `KeyCollector` is needed to obtain the PIN. Building a KeyCollector ======================= At a minimum, your key collector will be a single method with this signature. public bool KeyCollectingFunction(KeyEntryData keyEntryData); The return is a `boolean`, if it was able to collect the value or values requested, return `true`. If not, return `false`. Almost always, a `false` means the user canceled the operation. It's certainly possible to write a "standalone" method (e.g. a static method in a static class), but more likely, your key collector will be a class. using Yubico.YubiKey; public class MyKeyCollector { // fields and properties // Create a new KeyCollector object that pops up a window. // This window will be a child of the parentWindow and will // have boxes for entering the PINs and keys, along with OK // and Cancel buttons. public MyKeyCollector(Handle parentWindow) { } // Create a new KeyCollector object that pops up a window. // This window will be a standalone window, no parent. It // will have boxes for entering the PINs and keys, along // with OK and Cancel buttons. public MyKeyCollector() { } // This is the method passed to the Yubico SDK as the // KeyCollector delegate. public bool KeyCollectorDelegate(KeyEntryData keyEntryData) { } } Using this class would look something like this. var keyCollectorObject = new MyKeyCollector(parentWindow); . . . using (var pivSession = new PivSession(yubiKey)) { pivSession.KeyCollector = keyCollectorObject.KeyCollectorDelegate; . . . } There's a good chance you already have some class that is a key collector. It might not be called "key collector", but it is likely you already have a class built to collect PINs, passwords or other such user-supplied secrets. If so, you will possibly need to simply add a method that fulfills the SDK's delegate requirement. The KeyCollector delegate ------------------------- Your method, at its foundation, will be something like this. public bool KeyCollectorDelegate(KeyEntryData keyEntryData) { switch (keyEntryData.Request) { default: return false; case KeyEntryRequest.Release: // Do release work. case KeyEntryRequest.VerifyPivPin: // Collect a PIN to be used to verify a PIV session. case KeyEntryRequest.ChangePivPin: // Collect two PINs, the current and a new one, to be used // to change the PIV PIN. case KeyEntryRequest.ChangePivPuk: // Collect two PUKs, the current and a new one, to be used // to change the PIV PUK. case KeyEntryRequest.ResetPivPinWithPuk: // Collect the PUK and a new PIN to be used to recover the // PIV PIN. case KeyEntryRequest.AuthenticatePivManagementKey: // Collect a management key to be used to authenticate a // PIV session. case KeyEntryRequest.ChangePivManagementKey: // Collect two management keys, the current and a new one, // to be used to change the PIV management key. } } When the SDK calls your key collector, it will pass an enum parameter indicating what is requested. Your code will now know what it has to present to the user. Will it be a message saying, "Enter the PIV PIN"? Or a message saying, "Enter the current PIV PIN and a new PIN, in order to change the PIN"? There are at least eight enum values indicating what the SDK needs the key collector to collect (and probably more in the future as more features are added to the SDK). Your key collector does not have to support all of them. If you build a key collector that only verifies or changes a PIV PIN, then your switch statement only needs to support those values (and Release). The value indicating the request is the `KeyEntryData.Request` property. There is more information in the `KeyEntryData` object. public sealed class KeyEntryData { public KeyEntryRequest Request { get; set; } public bool IsRetry { get; set; } public int? RetriesRemaining { get; set; } } Suppose the `Request` is `KeyEntryRequest.VerifyPivPin`. Your code now knows that the SDK wants you to collect the PIV PIN. But your code can also look at the `IsRetry` property. If that is `true`, your code now knows that a PIN had already been collected, but it was incorrect. Maybe you want to present a message to the user, "The previous PIN attempt failed. Do you want to try again?" Furthermore, you can look at the `RetriesRemaining` property. You can let the user know how many retries they have before the PIN is blocked. Enter the PIV PIN The previous PIN attempt failed. You have 4 attempts remaining before the PIN is blocked. PIN:_______________ OK CANCEL If the caller decides to cancel, your key collector delegate can return `false`. Once your code has collected the PIN, it must return it. That is done using the `SubmitValue` and `SubmitValues` methods inside the `KeyEntryData`. Just as the `KeyEntryData` has information letting you know all about what is being requested, it contains methods that allow you to return the values collected. If you are to return one value (e.g. a PIV PIN for verification), then return that value using `KeyEntryData.SubmitValue`. If you are to return two values (e.g. a current and a new PIV PIN), return them using `KeyEntryData.SubmitValues`. using System.Security.Cryptography; using Yubico.YubiKey; public class MyKeyCollector { private byte[] _currentValue = new byte[MaxValueLength] private int _currentLength; public Memory CurrentValue = new Memory(_currentValue); public bool SampleKeyCollectorDelegate(KeyEntryData keyEntryData) { if (keyEntryData is null) { return false; } switch (keyEntryData.Request) { case KeyEntryRequest.Release: CryptographicOperations.ZeroMemory(CurrentValue.Span) break; case KeyEntryRequest.VerifyPivPin: // The CollectValue method will collect the PIN and store // it in the CurrentValue property. isCollected = CollectValue( "PIN", keyEntryData.IsRetry, keyEntryData.RetriesRemaining); if (isCollected) { keyEntryData.SubmitValue(CurrentValue.Slice(0, _currentLength).Span); } break; } return isCollected; } } ### Release One possible value of `KeyEntryRequest` is `Release`. This is how the SDK tells the delegate that it has used the PIN (or key or whatever was requested), and your code can release any resources. At this point, the delegate will likely overwrite sensitive data, close handles, and so on. Your `KeyCollector` delegate MUST NOT throw an exception when the request is `Release`. Most `KeyCollector` delegates will likely be written to never throw an exception in any situation (just return `false` if something goes wrong), but it is vitally important that it never throw an exception when the request is `Release`. The `Release` is called from inside a `finally` block, and it is a bad idea to throw exceptions from inside `finally`. [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/sdk-programming-guide/key-collector.md/#L1) --- # Handling Sensitive Data (PINs, Passwords, and Keys) ##### Table of Contents Handling Sensitive Data (PINs, Passwords, and Keys) =================================================== Introduction ------------ This guide addresses the challenges of handling sensitive data like PINs, passwords, and keys in C# applications, particularly when using the SDK. While no method provides absolute security, these practices can significantly reduce the risk of data leakage. Potential Risks --------------- * Clear-text sensitive data in memory: If an attacker gains access to the program's memory, they could potentially read sensitive information. * Data persistence after memory release: Sensitive data may remain in memory even after it's no longer needed, increasing the risk of exposure. * Unintended copies due to memory management: C#'s memory management might create copies of data in memory, spreading sensitive information to multiple locations. * Exposure through memory swapping: When the operating system swaps memory to disk, sensitive data could be written to non-volatile storage. **Note:** If an attacker has access to running program memory, the system is already compromised. These measures mitigate risks but don't provide absolute security. Best Practices -------------- 1. **Use Byte Arrays over Strings**: Prefer `byte[]` over strings for sensitive data. Byte arrays allow direct memory manipulation and can be securely overwritten. Strings in C# are immutable, meaning any operation on a string creates a new string object, potentially leaving copies of sensitive data in memory. 2. **Overwrite Buffers**: Use [`CryptographicOperations.ZeroMemory()`](https://learn.microsoft.com/en-us/dotnet/api/system.security.cryptography.cryptographicoperations.zeromemory) to clear data after use. Simply setting a reference to null doesn't clear the actual data from memory. Overwriting ensures the sensitive data is actually removed. 3. **Minimize Data Lifespan**: Collect sensitive data just before use and clear immediately after. The longer sensitive data remains in memory, the higher the risk of exposure. Minimizing its lifespan reduces this risk. 4. **Control Buffer Sizes**: Pre-allocate maximum-sized buffers to avoid resizing risks. Resizing operations can create copies of data in memory. By pre-allocating the maximum size, you avoid these copies and maintain better control over where your sensitive data resides. 5. **Pin Memory**: Use techniques like [`stackalloc`](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/stackalloc) , [`GC.AllocateArray()`](https://learn.microsoft.com/en-us/dotnet/api/system.gc.allocatearray) , [`fixed` statement](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/statements/fixed) , or [`GCHandle.Alloc()`](https://learn.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.gchandle.alloc) to prevent unintended copies. These techniques prevent the garbage collector from moving your sensitive data around in memory, reducing the risk of leaving copies in various memory locations. ### Avoid Using: * **Strings**: Cannot be securely wiped without risking runtime crashes. Strings are immutable and internally optimized by the runtime, making it impossible to guarantee that all copies of the string have been securely erased. * **SecureString**: No longer recommended by Microsoft for new development. SecureString was designed to mitigate some risks, but its implementation is platform-specific and doesn't provide significant advantages over properly managed byte arrays. Implementation Examples ----------------------- ### Buffer Management private const int MaxPinLength = 8; var pin = new byte[MaxPinLength]; public void CollectPin(byte[] pin) { // Implementation to safely collect PIN // This method should handle the PIN input and store it directly in the provided byte array // It should also ensure that no more than MaxPinLength bytes are written } ### Secure Usage Pattern var managementKey = new byte[ManagementKeySize]; try { CollectManagementKey(managementKey); AuthenticateManagementKey(managementKey); CryptographicOperations.ZeroMemory(managementKey); // Continue with operation } finally { CryptographicOperations.ZeroMemory(managementKey); } This pattern ensures that the management key is cleared from memory even if an exception occurs during the authentication process. Conclusion ---------- While these practices significantly reduce risks, they don't guarantee complete security. Always consider the specific security requirements of your application and the potential threats in your environment. Regular security audits and staying updated with the latest security best practices are crucial in maintaining the security of sensitive data handling in your applications. [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/sdk-programming-guide/sensitive-data.md/#L1) --- # Making a connection ##### Table of Contents Making a connection =================== Before your application can call on the YubiKey to perform operations, it must connect to the appropriate device. There are generally two steps: 1: Find all YubiKeys available on the host machine and choose the one to use. and either 2a: Create an instance of one of the "Session" classes (e.g. `PivSession`). or 2b: Make a connection to that device through one of the YubiKey applications. The vast majority of applications will use the "Session" classes. Anything you can do with a connection (2b) you can do with a "Session" object (2a). However, early releases of the SDK do not have "Session" classes for every application yet. It is possible you want to perform some operation for which there is no "Session" class yet, or maybe there is some reason you do not want to create a session. If so, there is another way to make a connection. The class representing the hardware. ------------------------------------ Each YubiKey available on the host machine can be represented by an instance of `IYubiKeyDevice`. Because there can be more than one YubiKey available at any one time, you will need to obtain a list. Use the [YubiKeyDevice](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.YubiKeyDevice.html) class. ##### Important The enumeration methods are "best effort", which means they will attempt to return a set of `IYubiKeyDevice` objects even if errors are encountered with some devices. Therefore the number of `IYubiKeyDevice` objects returned by the enumeration methods may not equal the number of YubiKeys attached to the host machine. Complicating this is the fact that each physical YubiKey can look like one or more separate devices to the host machine. The enumeration method will do its best to find all of these devices, and match them back together using their serial number. If they can't be matched, they will be returned as separate `IYubiKeyDevice` objects. // Chooses the first YubiKey found on the computer. IYubiKeyDevice? SampleChooseYubiKey() { IEnumerable list = YubiKeyDevice.FindAll(); return list.First(); } You can also find only those YubiKeys that support a particular transport protocol (e.g. smart card for PIV), or you want to find only those YubiKeys inserted into a USB port (as opposed to NFC). // Chooses the first USB-based YubiKey that exposes Smart Card functionality. IYubiKeyDevice? SampleChooseYubiKey() { IEnumerable list = YubiKeyDevice.FindByTransport(Transport.UsbSmartCard); return list.First(); } Now you can cycle through the list, obtaining information about each YubiKey to help decide which to use. IYubiKeyDevice? SampleChooseYubiKey() { IEnumerable list = YubiKeyDevice.FindByTransport(Transport.UsbSmartCard); foreach (IYubiKeyDevice currentYubiKey in list) { if (currentYubiKey.FirmwareVersion.Major < 5) { continue; } return currentYubiKey; } return null; } Choosing the YubiKey application -------------------------------- Now that you have an object representing the YubiKey hardware, you need to obtain an object representing the YubiKey application you want to access. Remember, there are six possible applications: * OTP * FIDO * FIDO2 * PIV * OpenPgpCard * OATH ##### Note Developers working with the SDK on macOS must enable input monitoring in order to interact with a YubiKey's OTP application. The YubiKey acts as a keyboard, and the SDK needs to be able to "monitor" it in order to interact with it. To enable input monitoring, open **System Preferences** and go to **Security & Privacy**. Scroll down and click on \* _Input Monitoring_\*. Check the box next to the application that needs to monitor YubiKeys via the SDK, such as Visual Studio. You may need to click the lock icon in the bottom left corner and enter your Mac user password in order to make changes. ![Input monitoring settings](https://docs.yubico.com/yesdk/images/input-monitoring.png "Input monitoring settings in macOS") If you are building a macOS application, your users must also go through these same steps to enable input monitoring. Additionally, developers must add the following entitlements to their Entitlements.plist file (Entitlements.plist is created automatically when you create a new macOS application project in Visual Studio): * `com.apple.security.smartcard` * `com.apple.security.device.usb` ### 2a: Session To connect to the YubiKey application, you can use a `Session` class. For example, to make a connection to PIV: IYubiKeyDevice? yubiKeyToUse = SampleChooseYubiKey(); if (yubiKeyToUse is null) { // handle case where no YubiKey was found. } using var pivSession = new PivSession(yubiKeyToUse); The `PivSession` class has methods you can call to perform PIV operations, such as generating a key pair. ### 2b: Connection Get an instance of `IYubiKeyConnection`: IYubiKeyDevice? yubiKeyToUse = SampleChooseYubiKey(); if (yubiKeyToUse is null) { // handle case where no YubiKey was found. } IYubiKeyConnection connection = yubiKeyToUse.Connect(YubiKeyApplication.Piv); You can now use this "Connection" object to perform PIV commands. Note that with this connection, all you can do is perform commands, you cannot perform any of the operations in the "Session" object. Furthermore, a "Session" object has a field public IYubiKeyConnection Connection { get; } This means that when you get a "Session" object, you get a "Connection" object as well. That is, you can make calls to the commands directly even if you build a "Session" object. So for most applications, there is no reason not to get a "Session" object. Nonetheless, if you find for any reason you do not want to create a "Session" object, yet still want to call YubiKey commands, this connection is available. Note that early releases of the SDK do not have "Session" classes for all applications. This would mean that the only way to get some functionality is through this "Connection" object. Only one application -------------------- The YubiKey can operate only one application at a time. For example, if you connect to the device through PIV, do not try to connect through FIDO until all the PIV operations are done. Do not try to connect to the YubiKey through multiple threads. Visit the [Threads](https://docs.yubico.com/yesdk/users-manual/sdk-programming-guide/threads.html) page in the User's Manual for more information on multiple threads. [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/sdk-programming-guide/making-a-connection.md/#L1) --- # Unknown YubiKey FIPS 4 Series Technical Manual Yubico Oct 29, 2025 CONTENTS 1 YubiKey FIPS 4 Series1 1.1 Why FIPS? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 1.2 Do You Require FIPS Keys? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 1.3 Compatible Devices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 2 YubiKey FIPS 4 Series Overview3 2.1 YubiKey FIPS (4 Series) Devices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 2.2 YubiKey FIPS Sub-Modules . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 3 FIPS (4 Series) Deployment Considerations5 3.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 3.2 Deployment in a FIPS-Compliant Environment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 3.3 Registration and Enrollment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 3.4 Authentication . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 3.5 Identifying FIPS YubiKeys . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 4 Deploying YubiKey FIPS (4 Series) in FIPS-Approved Mode11 4.1 One Time Password (OTP) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 5 Copyright23 5.1 Trademarks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 5.2 Disclaimer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 5.3 Contact Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 5.4 Getting Help . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24 5.5 Feedback . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24 5.6 Document Updated . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24 i ii CHAPTER ONE YUBIKEY FIPS 4 SERIES 1.1 Why FIPS? Federal Information Processing Standards (FIPS) are developed by the United States government for use in computer systems to establish requirements such as ensuring computer security and interoperability. The National Institute of Standards and Technology (NIST) and the Canadian Centre for Cyber Security (CCCS) run the NIST Cryptographic Module Validation Program (CMVP) as a collaborative effort. FIPS certification demonstrates that a product has gone through a rigorous audit process and adheres to a security standard that can be measured and quantified. Many government organizations and government contractors are required to use FIPS-approved products, as are highly- regulated industries in general. Other countries also recognize FIPS 140-2. For the US government, the default is that FIPS isrequired. 1.2 Do You Require FIPS Keys? If you do not have a security auditor, and/or the auditor does not have a compliance requirement, you probably do not need FIPS. The standard line of YubiKeys offers the same security, algorithms and functionality. The standard line also evolves at a much more rapid pace because it does not need to go through an exhaustive validation process, which commonly takes a year or more. Yubico can release standard firmware with new features, enhancements, etc. at any time, whereas FIPS-certified products must go through the FIPS validation process every time there is a change. 1.3 Compatible Devices Before proceeding, make sure your YubiKeys are from the (4) FIPS Series, not the 5 FIPS Series. If you’re not sure how to tell, look forv5in the laser-markings on the keys themselves. Keys with this marking belong to the 5 FIPS Series; keys without it are from the (4) FIPS Series. See below images for clarification. 1 YubiKey FIPS 4 Series Technical Manual The YubiKey (4) FIPS Series, to which this article applies. The YubiKey 5 FIPS Series. If you determine you have YubiKey 5 FIPS Series keys, please refer to YubiKey Technical Manual instead. 2Chapter 1. YubiKey FIPS 4 Series CHAPTER TWO YUBIKEY FIPS 4 SERIES OVERVIEW The YubiKey FIPS (4 Series) are hardware authentication devices manufactured by Yubico which support one-time passwords, public-key encryption and authentication, and the Universal 2nd Factor (U2F) protocols developed by the FIDO Alliance, with Yubico as a primary contributor and thought leader. The cryptographic functionality of the YubiKey FIPS (4 Series) devices are powered by the FIPS 140-2 certified Yu- biKey 4 cryptographic module, a single-chip cryptographic processor with a non-extractable key store that handles all of the cryptographic operations. The YubiKey 4 cryptographic module is FIPS 140-2 certified (Overall Level 2, Physical Security Level 3). 2.1 YubiKey FIPS (4 Series) Devices The YubiKey 4 cryptographic module is a secure element that supports multiple protocols designed to be embedded in USB security tokens. The module can generate, store, and perform cryptographic operations for sensitive data and can be utilized via an external touch-button for Test of User Presence in addition to PIN for smart card authentication. The module implements five major functions - Yubico One Time Password (OTP), FIDO Universal 2nd Factor (U2F), PIV-compatible smart card, OpenPGP smart card and OATH OTP authentication. 2.1.1 YubiKey 4 Cryptographic Module, FIPS 140-2 Certificate #: 3517 https://csrc.nist.gov/Projects/Cryptographic-Module-Validation-Program/Certificate/3517 Table 1:YubiKey FIPS (4 Series) devices covered by this Certificate Product NameDescription YubiKey FIPS (4 Series)Keychain form factor with USB-A connector YubiKey Nano FIPS (4 Series)Nano form factor with USB-A connector YubiKey C FIPS (4 Series)Keychain form factor with USB-C connector YubiKey C Nano FIPS (4 Series)Nano form factor with USB-C connector All of the models in the YubiKey FIPS (4 Series) provide a USB 2.0 interface, regardless of the form factor or the USB connector. The YubiKey presents itself as a USB composite device in addition to each individual USB interface. The YubiKey USB PID is described in the YubiKey USB ID Values guide. 3 YubiKey FIPS 4 Series Technical Manual 2.2 YubiKey FIPS Sub-Modules The YubiKey FIPS Series device features are implemented in five sub-modules. Table 2:YubiKey FIPS 4 features by sub-module Sub-ModuleKey Features One Time Password (OTP) 2 Slots for OTP configurations Supported protocols - Yubico OTP - OATH-HOTP - Challenge/Response HMAC-SHA1 - Static password OATH 32 for OATH credentials Supported protocols - OATH-TOTP - OATH-HOTP Supported Algorithms - HMAC-SHA1 - HMAC-SHA256 PIV-compatible 24 slots for private keys Support Key algorithms - RSA 2048 - ECC P256 - ECC P384 OpenPGP Card PGP Smart Card V2.0 Supported Algorithms - RSA 2048 - RSA 3072 - RSA 4096 (imported only) FIDO U2F FIDO U2F 4Chapter 2. YubiKey FIPS 4 Series Overview CHAPTER THREE FIPS (4 SERIES) DEPLOYMENT CONSIDERATIONS 3.1 Introduction Deploying the YubiKey FIPS (Federal Information Processing Standard) Series offers organizations the option of using any of the multiple protocols on the YubiKey for strong authentication. Because not all issues can be resolved by a single authentication protocol, the YubiKey FIPS Series includes PIV, OATH, YubiOTP, and FIDO U2F protocols to address a wide range of scenarios. The FIPS guidelines and requirements are designed to ensure that in a secured environment, only devices in the FIPS-approved mode are able to authenticate. To meet FIPS requirements, corporate IT staff need to work closely with their compliance department to develop and implement strong processes. The FIPS- mandated Crypto Officer role must be incorporated into online services user registration steps that meet the needs of the organization’s security and business processes. 3.1.1 Audience This document is intended for IT administrators, Crypto Officers, and compliance officers deploying FIPS Series Yu- biKeys in a FIPS-compliant environment. It sets out the deployment options available to individual end users and to organization admins. The document provides guidance on the key decisions to be made when deploying YubiKeys in a FIPS-compliant environment. This document does not list the steps for technical implementation; instead, it provides links to the appropriate deployment guides. For more detailed information pertaining to FIPS YubiKeys, please review the YubiKey FIPS Series Technical Manual. 3.2 Deployment in a FIPS-Compliant Environment Yubico’s YubiKey FIPS series presents the first multiprotocol FIPS 140-2 validated security keys. These YubiKeys meet the cryptographic requirements of the NIST (National Institute of Standards and Technology) FIPS 140-2 specifications. These keys enable strong authentication and thus greater security across multiple sites and services. To take advantage of all the protocols on the YubiKey FIPS series, it is important to understand how they fit within a FIPS-compliant envi- ronment. To be FIPS-compliant, an organization first defines its operational processes and then applies the technology so as to align with those processes. A FIPS compliant environment requires that the role of granting permission be distinct and separate from the role of using those permissions. In order to maintain that separation, FIPS mandates that a Crypto Officer perform all registration and enrollment activities for a user. 5 YubiKey FIPS 4 Series Technical Manual 3.2.1 FIPS-Approved Mode Default Setting Many organizations choose to buy YubiKey FIPS series because the hardware has been certified to enable them to achieve compliance and meet the highest levels of authentication assurance (physical level 3). Tooling and deployment approaches often differ; for example, some customers may require a default U2F sub-module Admin PIN to prevent unauthorized U2F registration, while others may not. Since each customer deployment differs, FIPS mode is not enabled by default on FIPS Series YubiKeys. In a FIPS mode of operation, every sub-module (OTP, OATH, OpenPGP, PIV and U2F) of a FIPS YubiKey must be individually placed in FIPS mode so that the capability to load or generate authentication secrets requires a PIN. Some sub-modules, such as the U2F sub-module, do not ship with a pre-defined PIN. The organization implementing FIPS YubiKeys must therefore supply the PIN as part of their initialization process. By contrast, other submodules like the YubiKey FIPS PIV are always in a FIPS-approved mode, since the Management Key, PIN and PUK are never undefined. The YubiKey FIPS Series Technical Manual provides guidance on configuring each sub-module. Yubico can provide custom configuration to improve the process. Please work with your sales representative if your organization has custom configuration needs. Note:Resetting the U2F sub-module of the YubiKey permanently invalidates FIPS compliance for the YubiKey overall since FIPS mode for the U2F sub-module cannot be enabled after the reset. Resetting the U2F sub-module should be limited to the decommissioning process only. The OpenPGP and PIV sub-modules on the FIPS YubiKey come with authentication codes set by default for ele- vated permissions, and are considered to be in a FIPS-compatible mode out of the box. To be considered to be in the FIPS-compatible mode, the OTP, OATH and U2F sub-modules must have their elevated permissions protected with authentication codes during the initialization process. It is important to note that setting the Admin PIN on the U2F sub-module will prevent registration of new U2F sites without the PIN being provided, but it is not required for authen- tication. Once the OATH Admin PIN is set, the OATH sub-module will require it to be provided to display the OATH codes stored within, and/or add new ones. The table below lists the sub-modules, their respective FIPS mode defaults, and their respective Crypto Officer roles. 6Chapter 3. FIPS (4 Series) Deployment Considerations YubiKey FIPS 4 Series Technical Manual Table 1:FIPS mode crypto officer roles Sub-ModuleDefault FIPS ModeCrypto Officer Role PIVSet Manage Management key, Register new Credential(s), define PIN retries OpenPGPSet Manage Admin password, Register new Credential(s), define PIN retries OATHNot Set Set Authorization Password, Register new Credential(s) OTPNot Set Set Admin PIN, Register new Credential(s) U2FNot Set Set Admin PIN, Register new Credential(s) 3.3 Registration and Enrollment It is important to note that once a key is in FIPS mode, the Crypto Officer must unlock the sub-module before registration can occur. For customers who are familiar with self-service registration flows, the introduction of the Crypto Officer role needs to be clearly communicated within the organization. If your organization needs to access a number of sites that do not require FIPS keys, then the case can be made for providing users with both a FIPS key and a non-FIPS key. This way end users can register themselves to sites without involving the Crypto Officer and thereby reduce operational overhead. For registration on the YubiKey FIPS series, there are a couple of approaches. The options listed below range from less restrictive to more restrictive. Work with your compliance team to determine the option that best meets your needs. 3.3. Registration and Enrollment7 YubiKey FIPS 4 Series Technical Manual 3.3.1 Option 1 - Enable FIPS-Approved Mode After Registration In this option, the end user is able to register the YubiKey with services. Once the end user completes their registrations, the Crypto Officer sets the sub-module’s Admin PIN or passwords and locks the YubiKey. No further registrations can be performed unless the Crypto Officer unlocks the particular sub-module on the particular key. Enable FIPS-approve mode After registration 3.3.2 Option 2 - Enable FIPS-Approved Mode Prior to Registration In this option, the YubiKey is in FIPS-approved mode from the beginning. The Crypto Officer locks the sub-modules and registers the YubiKey with the various relying parties that the user needs to access. Once the Admin PIN and/or password is set, if registration to new sites/services is required, the Crypto Officer needs to unlock the sub-module. Depending on the service, in order to properly bind the key to the user’s account, the Crypto Officer might need to have the user log into the site on a secured enrollment station prior to registering the YubiKey. Once all services are registered, the Crypto Officer will lock any unlocked sub-modules and return the key to the user who should then validate that access was set up properly. 8Chapter 3. FIPS (4 Series) Deployment Considerations YubiKey FIPS 4 Series Technical Manual Enable FIPS-approve mode Before registration For both Option 1 and Option 2, after the initial registration, if the user wants to register their device to a new service, they would engage the Crypto Officer to unlock the YubiKey and register the YubiKey to the new service. Neither option is in itself preferable over the other; the preferred approach is determined by your needs. It is important to consult your compliance team before making a decision on which option is appropriate for your organization. 3.4 Authentication Authentication for most of the protocols functions the same whether the YubiKey is in FIPS-approved mode or not. The Crypto Officer is only involved in the registration process. If the key is in FIPS-approved mode, it only needs to be unlocked for registration. It is not used for authentication. Note:The OATH sub-module requires the Crypto Officer to be involved with the authentication process: the OATH sub-module must be unlocked by the Crypto Officer. Work with your compliance team to determine the option that best meets your needs for OATH-based authentication. 3.5 Identifying FIPS YubiKeys The FIPS YubiKeys have “FIPS” printed on the back of the keys for easy identification. The YubiKey Manager Com- mand Line Interface (CLI) tool can also be used to identify FIPS keys. Using the command “ykman fido info”, you can identify the FIPS key and see if FIPS mode is enabled. The YubiKey manager CLI can be downloaded for Win- dows, Linux, and macOS at https://www.yubico.com/products/services-software/download/yubikey-manager/. Spe- cific FIPS command instructions can be found in the YubiKey FIPS (4 Series) Technical Manual. The FIDO U2F attestation certificate identifies the security key as an official Yubico product. Attestation is only evaluated during a registration flow and not during authentication. Furthermore, attestation can only identify YubiKey capabilities and not whether FIPS mode is enabled. The attestation certificate has limited device model information. Due to privacy concerns, the default settings for FIPS YubiKeys have no FIPS-related information. For these reasons, registering a YubiKey with a Crypto Officer becomes more important. Visit the Yubico developer U2F attestation site 3.4. Authentication9 YubiKey FIPS 4 Series Technical Manual for more information. Yubico can provide custom programming to meet customer attestation needs while maintaining compliance with the FIDO U2F standard. Please contact your Yubico representative for more information. 10Chapter 3. FIPS (4 Series) Deployment Considerations CHAPTER FOUR DEPLOYING YUBIKEY FIPS (4 SERIES) IN FIPS-APPROVED MODE When using a YubiKey FIPS (4 Series) device as an authenticator in a FIPS environment, all of the sub-modules must be in a FIPS-approved mode of operation for the YubiKey FIPS (4 Series) device as a whole to be considered as operating in a FIPS-approved mode. By default, not all of the sub-modules on the YubiKey FIPS (4 Series) device are in a FIPS mode of operation. The Crypto Officer deploying the YubiKey FIPS Series (4 Series) device in a secured environment must define and supervise an initialization and delivery process which ensures that each sub-module on the YubiKey FIPS (4 Series) device is in a FIPS-approved mode of operation before being deployed to the user. The sub-modules on the YubiKey FIPS (4 Series) device must be configured in a FIPS-approved mode; this can be done using the YubiKey Manager Command Line Interface (CLI) available in the downloads for Windows and macOS at https://www.yubico.com/support/download/yubikey-manager/. The PIV and OpenPGP sub-modules have their respective credentials set to default values, and as such are already in a FIPS-approved mode. The OTP, OATH and U2F sub-modules must all have their respective credentials set to be in a FIPS mode. The YubiKey Manager can verify the YubiKey FIPS (4 Series) device is in a FIPS-approved mode of operation with the command: ykman info However, it is highly recommended that all of the credentials across all of the sub-modules are changed from the default values before the YubiKey FIPS (4 Series) device is deployed to the end user. 11 YubiKey FIPS 4 Series Technical Manual Table 1:Credentials and allowed values Sub-moduleCredentialAllowed ValuesCredential owner One Time Password (OTP) Access Code: OTP Slot 1 6 byte access codesCrypto Officer Access Code: OTP Slot 2 6 byte access codesCrypto Officer OATHAuthentication Key 14-64 byte HMAC SHA1/SHA256 key Crypto Officer PIV Smart CardManagement Key3-key TDES keyCrypto Officer PUK6-8 byte PINCrypto Officer PIN6-8 byte PINAuthenticated User OpenPGP Smart Card Admin Password (PW3) 8 to 127 byte PINCrypto Officer Reset Code (RC, Optional) 8 to 127 byte PINCrypto Officer User Password (PW1) 6 to 127 byte PINAuthenticated User U2FPIN6 to 32 byte PINCrypto Officer 4.1 One Time Password (OTP) The YubiKey FIPS OTP sub-module supports 2 independent OTP configurations, known as OTP slots. The OTP slots can be configured to output an OTP created with the Yubico OTP or OATH-HOTP algorithm, a HMAC-SHA1 hashed response to a provided challenge or a static password. The OTP slot 1’s output is triggered via a short touch (1~3 seconds) on the gold contact and the OTP slot 2’s is triggered via a long touch (+3 seconds). A 6 byte access code can be set on slot 1 and slot 2 independently. Once set, the OTP slot’s access code is required when modifying, overwriting or deleting the configuration on the respective OTP slot. By default, the YubiKey is shipped without any access code. 12Chapter 4. Deploying YubiKey FIPS (4 Series) in FIPS-Approved Mode YubiKey FIPS 4 Series Technical Manual 4.1.1 Placing the OTP Sub-Module in FIPS-Approved Mode Each OTP slot must be locked down with a Access Code for the YubiKey FIPS OTP sub-module to be in a FIPS- approved mode of operation. By default, no Access Codes are set for either slot. An Access Code must be applied to either OTP slot either when writing a new configuration or by updating the config- uration in an OTP slot where one is already present. An Access Code cannot be set to an empty OTP slot. To secure an unused OTP slot, a blank OTP configuration with an Access Code must be used. YubiKey FIPS (4 Series) devices must either be deployed with the OTP slots already set with an Access Code, or with a OTP application or service which configures the Access Code on both slots on enrollment. The OTP slot Access codes must be archived in a manner which only allows the Crypto Officer access to them, as the Access Codes are used when resetting the OTP Sub-module. The Crypto Officer can set an Access code to the OTP slots using the YubiKey Manager Command Line Interface (CLI) available at: https://www.yubico.com/products/services-software/download/yubikey-manager/ To apply an Access Code to a new configuration using the YubiKey Manager CLI, include the flag --access-code=in the OTP configuration string. The command must be of the format: ykman otp --access-code= \[OTP configuration\] Where - •is the Access Code to be set. The Access Code must be a hexadecimal string exactly 12 char- acters in length (6 bytes). •\[OTP configuration\]is the configuration being loaded. For full details on setting an OTP configuration using the YubiKey Manager CLI, see the YubiKey Manager documen- tation. To fill a blank OTP configuration with an access code, use the command: ykman otp --access-code=\\ chalresp 000000000000000000000000000000 Where - •is the Access Code to be set. •is either1or2(without quotes) depending on if the OTP configuration is being applied to OTP slot 1 or OTP slot 2. To apply an Access Code to an existing configuration using the YubiKey Manager CLI, use the command: ykman otp --access-code= settings Where - •is the Access Code to be set. •is the OTP slot with the existing configuration to be secured. 4.1. One Time Password (OTP)13 YubiKey FIPS 4 Series Technical Manual 4.1.2 Verifying the OTP Sub-Module is in FIPS-Approved Mode To verify the YubiKey FIPS OTP sub-module has access codes set for both OTP slots and is in a FIPS-approved mode, use the command: ykman otp info 4.1.3 Recommended OTP Settings YubiKey FIPS OTP sub-module will satisfy the security recommendation if the sub-module is operating in the FIPS- approved mode. 4.1.4 Resetting the OTP Sub-Module To reset the YubiKey FIPS OTP sub-module, both OTP Slot 1 and OTP Slot 2 must be independently have their loaded configuration and encryption keys deleted. This process cannot be reversed and the OTP configurations or secrets cannot be recovered or restored. Resetting the OTP slots will remove the access code as part of the configurations for either OTP slot. To delete the configuration in an OTP slot, use the command: ykman otp --access-code= delete Where - •is slot being deleted. •is the access code for that slot. The Access Code must be provided for deleting the slots, which should be recorded and accessible by the Crypto Officer. This command must be run for both slots to reset the YubiKey FIPS OTP sub-module. 4.1.5 User Entered Data The YubiKey FIPS OTP sub-module will only accept user data in specific formats and lengths, dependent on the OTP configuration. The user supplied data is used to generate the OTPs supplied by the sub-module. YubiOTP The YubiOTP configuration will accept data in the following formats and lengths: •Public ID- 1-16 byte modhex string, default 6 bytes (12 characters) •Private ID- 6 byte hexadecimal string •AES key- 16 byte hexadecimal string The generated OTP codes contain the characters of the Public ID as entered, followed by a 32 character string generated as a hash of the Private ID with counter, time stamp and randomly generated data, encrypted with the provided AES key. 14Chapter 4. Deploying YubiKey FIPS (4 Series) in FIPS-Approved Mode YubiKey FIPS 4 Series Technical Manual OATH-HOTP The OATH-HOTP configuration will accept data in the following formats and lengths: •Token Identifier- Optional 6 byte string composed of either modhex or numeric characters (12 characters). •Moving factor seed- 8 byte decimal value •Secret key- 20 byte hexadecimal string The generated OTP codes contain the characters of the Token Identifier as entered if included, followed by a 6 or 8 digit numeric string generated as a truncated hash of the Secret key with the counter. Challenge-Response The Challenge-Response configuration will accept data in the following formats and lengths: •Secret key- 20 byte hexadecimal string The generated responses consist of a 40 character hexadecimal string generated as a HMAC-SHA1 hash of the supplied challenge and the Secret key. Static Password The Static Password configuration will accept data in the following formats and lengths: •Password- A string of up to 38 characters as defined by the keyboard scan code ID. The generated Static Password codes contain the characters as programed, provided that the host system is using the same keyboard layout as the system the password was programmed on. 4.1.6 OATH The YubiKey FIPS OATH sub-module supports up to 32 OATH credentials, either OATH-HOTP or OATH-TOTP, as defined in the OATH Specification. The Yubico Authenticator is used to add or remove credentials, retrieve generated codes and optionally set an authentication key in the YubiKey FIPS OATH sub-module. •A 14 - 64 byte Authentication keycan be set on the OATH sub-module. Once set, the Authentication Key is required when adding, deleting and generating OATH credentials. Placing the OATH Sub-Module in FIPS-Approved Mode Access to the YubiKey FIPS OATH sub-module must be protected with an Authentication Key for the sub-module to be in a FIPS-approved mode of operation. By default, no Authentication Key is set. The Crypto Officer can set Authentication Key using the YubiKey Manager Command Line Interface (CLI) available at https://www.yubico.com/products/services-software/download/yubikey-manager/. To set an Authentication Key using the YubiKey Manager CLI, use the command: ykman oath set-password -n Whereis the Authentication Key to be set. The Authentication Key must be an alphanumeric string between 14 and 64 characters in length. 4.1. One Time Password (OTP)15 YubiKey FIPS 4 Series Technical Manual Verifying the OATH Sub-Module is in FIPS-Approved Mode Use the YubiKey Manager CLI to verify the YubiKey FIPS OATH sub-module is protected with an Authentication Key and in a FIPS-Approved mode. This can be done with the command: ykman oath info Recommended OATH Settings YubiKey FIPS OATH sub-module will satisfy the security recommendation if the sub-module is operating in the FIPS- approved mode. Resetting the OATH Sub-Module The YubiKey FIPS OATH sub-module can be reset using the YubiKey Manager CLI. To reset the YubiKey FIPS OATH sub-module, use the command: ykman oath reset Resetting the YubiKey FIPS OATH sub-module will remove all loaded OATH credentials, after which they cannot be recovered or restored, as well as the Authentication Key. User Entered Data The YubiKey FIPS OATH sub-module will only accept user data in specific formats and lengths, dependant on the OTP configuration. The user supplied data is used to generate the OATH OTPs supplied by the sub-module, as well as identify each loaded credential. The OATH configuration will accept data in the following formats and lengths: •Name- 64 byte character string composed of alphanumeric characters. •Secret key- 20 byte base32 string The Name can be displayed, along with a 6 or 8 digit numeric string generated as a truncated hash of the Secret key with the timestamp or counter, depending on the algorithm used. 4.1.7 PIV Smart Card The YubiKey FIPS PIV sub-module implements a PIV compatible standard as defined in the NIST SP 800-73-4 publi- cation. Access to functions on the YubiKey FIPS PIV sub-module are restricted by the Management Key, the PIN and the PUK. The Management key is used for: •Importing or generating asymmetric key pairs •Importing x.509 certificates and associated information •Setting the retry counters for PIN (also requires PIN) and PUK The PIN is used to: •Perform cryptographic operations using private keys •Changing the PIN 16Chapter 4. Deploying YubiKey FIPS (4 Series) in FIPS-Approved Mode YubiKey FIPS 4 Series Technical Manual The PUK is used to: •Unblock and set a new PIN for a blocked PIN •Change the PUK The YubiKey FIPS PIV sub-module has the default values: •Management Key (010203040506070801020304050607080102030405060708) •PIN (123456) •PUK (12345678) Placing the PIV Sub-Module in FIPS-Approved Mode By default the YubiKey FIPS PIV sub-module in the FIPS-Approved mode of operation. To change the default Man- agement Key, PIN and PUK, follow the guidance in section 2.3.4 (Recommended PIV Settings) below to secure the sub-module. Verifying the PIV Sub-Module is in FIPS-Approved Mode The YubiKey FIPS PIV sub-module is always in a FIPS-Approved Mode as the Management Key, PIN and PUK are never undefined. Recommended PIV Settings YubiKey FIPS (4 Series) devices should be deployed using a credential management tool like Microsoft ADCS with YubiKey mini-driver or 3rd party. The credential management tool will replace the default values by automatically setting a random value for the management key and PUK, and allow the end user to define the PIN. If the YubiKey FIPS PIV sub-module is not being managed with a credential management tool, the Management Key, PIN and PUK must be changed by the Crypto Officer. To do so, the YubiKey Manager Command Line Interface (CLI) available at https://www.yubico.com/products/services-software/download/yubikey-manager/ can be used. To change the Management Key, use the command: ykman piv change-management-key\\ -m010203040506070801020304050607080102030405060708\\ -n Whereis the new management key. To change the PIN, use the command: ykman piv change-pin -P123456 -n Whereis the new PIN. To change the PUK, use the command: ykman piv change-puk -p12345678 -n Whereis the new PUK. 4.1. One Time Password (OTP)17 YubiKey FIPS 4 Series Technical Manual Resetting the PIV Sub-Module The YubiKey FIPS PIV sub-module can only be reset if both the PIN and the PUK are blocked due to failed authentica- tion attempts exceeding their retry counters. Once the PIN and PUK are blocked, the YubiKey FIPS PIV sub-module can be reset using the YubiKey Manager CLI with the command: ykman piv reset Once reset, all data within the YubiKey FIPS PIV sub-module (keys, certificates and information in other data objects) will be removed and cannot be recovered. The only exception is the attestation certificate, which will persist. Resetting the YubiKey FIPS PIV sub-module will restore the Management Key, PIN and PUK to the default values. User Entered Data The YubiKey FIPS PIV sub-module can be configured to hold up to 12 user uploaded x509 certificates in DER format with a maximum size of 3052 bytes each, along with associated user Data Objects. It also has 15260 bytes available for storing Certificate Chain Certificates (root and intermediate certificates). The YubiKey FIPS PIV sub-module will accept data in the formats defined by NIST in Special Publication 800-73-4. 4.1.8 OpenPGP Smart Card The YubiKey FIPS OpenPGP sub-module implements the OpenPGP card 2.0 specification. The functions on the OpenPGP sub-module are secured with User Password (PW1), Admin Password (PW3) and optionally the Reset Code (RC). The Admin Password (PW3) is used for: •Importing or generating asymmetric key pairs •Reading from or writing to admin data objects •Unblocking the User Password (PW1) •Setting the Reset Code (RC) •Setting the retry counters for PW1 and PW3 The User Password (PW1) is used for: •Performing cryptographic operations using private keys •Reading from or writing to user data objects The Reset Code (RC) is used for: •Unblocking the User Password (PW1) The YubiKey FIPS OpenPGP sub-module has default values: •User Password (PW1) (123456) •Admin Password (PW3) (12345678) •The Reset Code (RC) is optional and does not have a default value. 18Chapter 4. Deploying YubiKey FIPS (4 Series) in FIPS-Approved Mode YubiKey FIPS 4 Series Technical Manual Placing the OpenPGP Sub-Module in FIPS-Approved Mode By default, the YubiKey FIPS OpenPGP sub-module is in the FIPS-Approved mode of operation. To change the default User Password, Admin Password or set a Reset Code, follow the recommended OpenPGP settings to secure the sub- module. Verifying the OpenPGP Sub-Module is in FIPS-Approved Mode The YubiKey FIPS OpenPGP sub-module is always in a FIPS-Approved Mode as the Admin Password and User Pass- word are never undefined. Recommended OpenPGP Settings YubiKey FIPS (4 Series) devices should be deployed using an OpenPGP application, such as GPG4Win, on Windows for OpenPGP card management. The User Password (PW1) and Admin Password (PW3) must be changed from the default values. For more details on the process to change the User Password (PW1) and Admin Password (PW3) or to set a Reset Code (RC), refer to the GnuPG man pages. Resetting the OpenPGP Sub-Module The YubiKey FIPS OpenPGP sub-module can be reset at any time. YubiKey FIPS OpenPGP sub-module can be reset using the YubiKey Manager CLI with the command: ykman openpgp reset Once reset, all data within the YubiKey FIPS OpenPGP sub-module (keys and information in data objects) will be removed and cannot be recovered. Resetting the YubiKey FIPS OpenPGP sub-module will restore the Admin Password and User Password to the default values, and will remove the Reset Code if set previously. User Entered Data The YubiKey FIPS OpenPGP sub-module can be configured to hold a single OpenPGP RSA key with 3 subkeys, imported by the user. The user supplied data is used to provide associated information about the stored PGP key. The OpenPGP configuration will accept data in the following formats and lengths: •Key- One RSA key, up to 4096 bits (limited to 2048 on the FIPS series devices), also including the following data objects: –Name - 255 character UTF-8 string –Email - 255 character UTF-8 RFC2822 mail name-addr string –Comment - 255 character UTF-8 string –Language - 2 to 8 byte string as defined by ISO 639 –Sex - 1 byte string as defined by ISO 5218 •Authentication key- One RSA sub-key, up to 4096 bits (limited to 2048 on the FIPS series devices) •Encryption key- One RSA sub-key, up to 4096 bits (limited to 2048 on the FIPS series devices) •Signing key- One RSA sub-key, up to 4096 bits (limited to 2048 on the FIPS series devices) 4.1. One Time Password (OTP)19 YubiKey FIPS 4 Series Technical Manual The listed data objects can be displayed when accessing the OpenPGP Applet, and are included in the OpenPGP public key when generated and exported. 4.1.9 U2F The YubiKey FIPS U2F sub-module supports the FIDO U2F standard as defined by the FIDO Alliance U2F Specifi- cation. In addition to the functionality detailed by the FIDO U2F specification, the YubiKey FIPS U2F sub-module allows setting an Admin PIN. Note:When set, the Admin PIN is required to register the U2F sub-module to new FIDO U2F services or accounts. Authentication to those services afterwards does not require the Admin PIN to be supplied. Placing the U2F Sub-Module in FIPS-Approved Mode For the YubiKey FIPS U2F sub-module to be in a FIPS-approved mode of operation, an Admin PIN must be set. By default, no Admin PIN is set. Further, if the YubiKey FIPS U2F sub-module has been reset, it cannot be set into a FIPS-approved mode of operation, even with the Admin PIN set. To set or change the Admin PIN, the YubiKey Manager Command Line Interface (CLI) must be used. To set an Admin PIN using the YubiKey Manager CLI, use the command: ykman fido set-pin --u2f -n Whereis the Admin PIN to be set. The Admin PIN must be a alphanumeric string between 6 and 32 characters long. To register a FIPS YubiKey locked with an Admin PIN, the YubiKey must first be unlocked on the host computer where the U2F registration will occur. Once unlocked, the FIPS YubiKey will allow U2F registrations until power-cycled, at which point the Admin PIN must be provided again. To unlock the U2F registration function, use the YubiKey Manager CLI with the command: ykman fido unlock -P Verifying the U2F Sub-Module is in FIPS-Approved Mode Use the YubiKey Manager CLI to verify the YubiKey FIPS U2F sub-module is in a FIPS-Approved mode. This can be done with the command: ykman fido info If the Admin PIN is set and the YubiKey FIPS U2F sub-module has not been reset previously, then the command will indicate the U2F sub-module is in the FIPS-approved mode. 20Chapter 4. Deploying YubiKey FIPS (4 Series) in FIPS-Approved Mode YubiKey FIPS 4 Series Technical Manual Recommended U2F Settings YubiKey FIPS U2F sub-module will satisfy the security recommendation if the sub-module is operating in the FIPS- approved mode. Warning:The FIDO U2F Standard does not support the user entering a U2F Admin PIN at registration currently. Resetting the U2F Sub-Module The YubiKey FIPS U2F sub-module can be reset using the YubiKey Manager CLI. To reset the YubiKey FIPS U2F sub-module, use the command: ykman fido reset Resetting the YubiKey FIPS U2F sub-module will regenerate the U2F key wrapping key and thus disabling all the U2F credentials associated with the device. The device cannot be used to authenticate to previously registered U2F services or accounts. During the reset process, the U2F attestation certificate will be overwritten with a hard-coded, self-signed attestation certificate. Warning:Resetting the YubiKey FIPS U2F sub-module will prevent the sub-module to be set to the approved FIPS mode of operation afterwards. This in turn will prevent the YubiKey FIPS (4 Series) device from being set into the FIPS-approved mode overall, and it can no longer be deployed as a FIPS authenticator. Further, some U2F sites or services may not support the replacement self-signed attestation key due to requiring an attestation certificate with an verified chain to a trusted root. For U2F sites or services where this is a requirement, the reset YubiKey FIPS U2F sub-module will not be able to register or authenticate to them. User Entered Data The YubiKey FIPS U2F sub-module does not accept any user data which can be extracted. All keys and associated data are generated internally and only exposed to the associated service being authenticated. U2F Attestation The YubiKey FIPS U2F sub-module contains an attestation certificate as part of the U2F specifications. The U2F Attes- tation certificate for FIPS series devices with firmware 4.4.5 and above includes an Object Identifier (OID) indicating that the hardware has been FIPS 140-2 certified. The OID value for FIPS Series YubiKeys will be1.3.6.1.4.1. 41482.12. This OID may be used during U2F registration to confirm the YubiKey being registered is a valid FIPS device by having the relying party include an attestation signature as part of the registration, then checking for this string. 4.1. One Time Password (OTP)21 YubiKey FIPS 4 Series Technical Manual 22Chapter 4. Deploying YubiKey FIPS (4 Series) in FIPS-Approved Mode CHAPTER FIVE COPYRIGHT ©2021-2025 Yubico AB. All rights reserved. 5.1 Trademarks Yubico and YubiKey are registered trademarks of Yubico AB. All other trademarks are the property of their respective owners. 5.2 Disclaimer The contents of this document are subject to revision without notice due to continued progress in methodology, design, and manufacturing. Yubico shall have no liability for any error or damages of any kind resulting from the use of this document. The Yubico Software referenced in this document is licensed to you under the terms and conditions accompanying the software or as otherwise agreed between you or the company that you are representing. 5.3 Contact Information Yubico AB Gävlegatan 22 113 30 Stockholm Sweden 23 YubiKey FIPS 4 Series Technical Manual 5.4 Getting Help Documentation is continuously updated on https://docs.yubico.com/ (this site). Additional support resources are avail- able in the Yubico Knowledge Base. More options for getting touch with us are available on the Contact out Support team of Yubico’s website. 5.5 Feedback Yubico values and welcomes your feedback. If you think you may have discovered a flaw in our product, please submit a support request at https://www.yubico.com/support/contact/ and provide as much detail as you can. 5.6 Document Updated 2025-10-29 22:07:46 UTC 24Chapter 5. Copyright --- # Providing alternate cryptographic implementations ##### Table of Contents Providing alternate cryptographic implementations ================================================= During the course of operations, the SDK will need to perform cryptographic operations such as random number generation, HMAC, AES, Triple-DES, or more. When that happens, the SDK will use the default cryptography in the .NET environment, unless you provide an alternative. This page describes how to provide an alternative. This does not replace the crypto on the YubiKey ----------------------------------------------- First of all, this has nothing to do with the cryptography performed on the YubiKey itself. When the YubiKey needs to perform some cryptographic operation (such as signing, random number generation, or so on), it will perform the crypto it has, either in the chip or the firmware. You cannot get the YubiKey to use alternate implementations. Instead, this is about the times the SDK needs to perform cryptography in order to communicate with the YubiKey. For example, in order to authenticate the PIV management key, the YubiKey will perform some Triple-DES operations (as specified by the PIV standard). The off-board application will also need to perform complementary Triple-DES operations. The off-board application will simply call on the SDK to perform the necessary actions, including the Triple-DES operations. It is not necessary to provide alternate implementations -------------------------------------------------------- If you do not provide alternate crypto, the SDK will work. It will simply use the default cryptography found in .NET (see `System.Security.Cryptography`). This is a completely acceptable choice for most applications. Why provide alternate implementations? -------------------------------------- Even though it is not necessary to provide crypto (i.e. doing nothing will work), some developers will still use alternate implementations. They might do so because they have access to a hardware random number generator or a hardware accelarator, or their product must use a FIPS-certified crypto library. Some developers trust only their own implementations. For those developers who want to replace the default crypto the SDK uses, then read on. For developers who are happy to let the SDK use the default .NET implementations, it is fine to skip this page. CryptoProviders class --------------------- Whenever the SDK needs to perform some crypto operation it calls on the [CryptoProviders](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Cryptography.html) static class. That class has a number of properties that are actually delegates (function pointers). These functions build the objects the SDK will use to perform the crypto. Therefore, to replace the default implementations: * Create a class that can perform the algorithm in question * Write a function that can build the object (factory method) * Load that function into the `CryptoProviders` class. The class you build must be a subclass of a specific .NET class, and the function must have the specific signature specified in the `CryptoProviders` class. Why does the SDK use a delegate that builds an object (a factory method), rather than loading an actual object itself? There are two main reasons. First, an object contains state, which can include keys or plaintext. Each time the SDK needs to perform any crypto, it will build an object, use it, and then immediately dispose it so any sensitive data can be overwritten as soon as possible. If an object were to be loaded, rather than a factory method, it would be much more difficult to guarantee every secret inside the object were overwritten after using it. Second, the default crypto is from the `System.Security.Cryptography` namespace, and all the classes that will be used implement `IDisposable`. Any replacement object will need to be a subclass and hence must also implement `IDisposable`. Because any object the SDK will use is disposable, then the rules of ownership must be followed. That is, ownership of the objects must be firmly established so that objects are not disposed before they might be used. By building, and owning, new objects each time, the SDK will avoid any ownership problems. ### Example: How the SDK uses the CryptographyProviders class for random number generation Look at the `CryptoProviders` class. There is a property for the random number generator. public static class CryptographyProviders { public static Func RngCreator { get; set; } } Suppose the SDK is performing an operation that needs random numbers. Here's what it will do. using System.Security.Cryptography; . . . using RandomNumberGenerator randomObject = CryptographyProviders.RngCreator() { randomObject.GetBytes(buffer); } ### Example alternate implementation: RandomNumberGenerator The SDK is built with the `RngCreator` property set to a function that will build and return the default RNG. To change to a new RNG, set the `RngCreator` property to your function (even though this is a static class, it is possible to set the properties). Your function must have the following signature. System.Security.Cryptography.RandomNumberGenerator CreateAlternateRng(); #### The RandomNumberGenerator class .NET defines a public abstract class `System.Security.Cryptography.RandomNumberGenerator`. The SDK will expect to build an instance of this class and use it. In fact, the `RngCreator` function loaded by the SDK will build an object using the `RandomNumberGenerator.Create` method. // Creates an instance of the default implementation of a cryptographic random number // generator that can be used to generate random data. public static System.Security.Cryptography.RandomNumberGenerator Create(); The SDK's `RngCreator` function is simply one line of code: return RandomNumberGenerator.Create(); #### The alternate Your replacement starts with a class that is a subclass of RandomNumberGenerator. public class AlternateRandom : System.Security.Cryptography.RandomNumberGenerator { } Once you have a class that fulfills the requirements, you now build a function that can create an instance of that class. This might be a static method inside the class itself, or it might be in another class. It might look something like this. public static RandomNumberGenerator CreateAlternateRng() { return new AlternateRandom(); } #### Set the RngCreator property in CryptographyProviders All you need to do is set the `RngCreator` property. After setting it to the new function, every time the SDK creates a new `RandomNumberGenerator`, it will be calling your method. CryptographyProviders.RngCreator = AlternateRandom.CreateAlternateRng; You will likely do this at the beginning of your program, such as in the `main`. #### Possible extra information Suppose your implementation needs some information to instantiate. For example, it might need a handle to a hardware device or a handle to a FIPS library. That is, the constructor is actually public AlternateRandom(SomeHandleType handle) { } Your function that builds it would normally look like this. public static RandomNumberGenerator CreateAlternateRng(SomeHandleType handle) { return new AlternateRandom(handle); } However, the function you provide to the SDK must be a method that has no input arguments. There are a couple ways around this. First, you could create a new handle each time. public static RandomNumberGenerator CreateAlternateRng() { SomeHandleType handle = SomeClass.BuildHwHandle(); return new AlternateRandom(handle); } It is possible you do not want to create a new handle every time, and besides, you might need more information to build the handle, such as a hardware path. A second way is to have your `RandomNumberGenerator` class hold the information, create an instance of that class, and pass an instance method as the delegate. using System.Security.Cryptography; public static AlternateRandom { public SomeHandleType Handle { get; set; } public AlternateRandom(SomeHandleType handle) { Handle = handle; } public RandomNumberGenerator CreateAlternateRng() { return this; } } At the beginning of your program, you would do something like this. var handle = new SomeHandleType(info); var alternateRandom = new AlternateRandom(handle); CryptographyProviders.RngCreator = alternateRandom.CreateAlternateRng; [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/sdk-programming-guide/alternate-crypto.md/#L1) --- # Physical interfaces ##### Table of Contents Physical interfaces =================== Physical interfaces are the ways that a computer, phone, or other device can connect with the YubiKey in order to communicate with it. USB Transports -------------- All of the models in the YubiKey 5 Series provide a USB 2.0 interface, regardless of the form factor of the USB connector. The YubiKey is a composite USB device. When plugged into a computer with its default settings, the YubiKey will present three separate USB transports: * A Human Interface Device (HID) Keyboard * A HID FIDO device * A smart card reader with smart card attached Each device serves one or more applications on the YubiKey, with the smart card interface being the most versatile. Below is a list of applications available on the YubiKey 5 and which USB transport they are available on: | Application | HID Keyboard | Smart Card | HID FIDO | | --- | --- | --- | --- | | Management | Partial \[1\] | Yes | Partial \[1\] | | OTP | Yes | Partial \[2\] | No | | OATH | No | Yes | No | | PIV | No | Yes | No | | OpenPGP | No | Yes | No | | FIDO U2F | No | No \[3\] | Yes | | FIDO2 | No | No | Yes | \[1\]: The GetDeviceInfo and SetDeviceInfo commands are available over all transports. \[2\]: OTP was available over Smart Card in the YubiKey NEO. Most OTP operations are now blocked over smart card. \[3\]: The FIDO U2F was available over smart card in the YubiKey NEO. The USB product ID (PID) and product string will change depending on which of the USB interfaces are enabled as described in the table below. Yubico's vendor ID (VID) is `0x1050`. | USB interfaces | PID | Product string | | --- | --- | --- | | OTP | 0x0401 | YubiKey OTP | | FIDO | 0x0402 | YubiKey FIDO | | CCID | 0x0404 | YubiKey CCID | | OTP, FIDO | 0x0403 | YubiKey OTP+FIDO | | OTP, CCID | 0x0405 | YubiKey OTP+CCID | | FIDO, CCID | 0x0406 | YubiKey FIDO+CCID | | OTP, FIDO, CCID | 0x0407 | YubiKey OTP+FIDO+CCID | An interface is enabled so long as there is a single application enabled which uses that interface. For example, the OTP (HID Keyboard) is enabled when the OTP application is enabled over USB. The HID FIDO interface is enabled when either the U2F or FIDO2 applications are enabled over USB. The CCID (smart card) interface is enabled when the PIV, OATH, or OpenPGP applications are enabled over USB. OTP interface output is sent as a series of keystrokes from a virtual HID keyboard. This allows for OTP to be used in any environment which can accept standard keyboard input. For more information on the HID Keyboard transport, see the [OTP application documentation](https://docs.yubico.com/yesdk/users-manual/application-otp/hid.html) . The FIDO interface has a HID usage page set to `0xF1D0`. ### Linux support #### HID keyboard The SDK's HID operations on Linux make use of "libudev", "libc", and "hidraw". Make sure they are available on the device. The shared libraries "libudev" and "libc" must in one of the paths the SDK will search (see the .NET documentation for the `DllImportSearchPath` enum; the SDK uses the value `SafeDirectories`). One directory the SDK searches is `/usr/lib`. If the SDK cannot find some needed library, it will likely be easiest to simply create a symbolic link. For example: $ cd /usr/lib $ sudo ln -s /usr/lib/x86_64-linux-gnu/libudev.so libudev.so **udev**: The udev library is part of Linux and will probably already be installed on the device. It is commonly found in a directory such as /usr/lib/x86_64-linux-gnu/libudev.so If so, there is likely nothing you will need to do. If the SDK cannot find `libudev.so`, make sure it is on the device (e.g. `$ find /usr -name libudev.so`). If it is, maybe it is not in a standard location and you need to make a symbolic link. **libc**: The SDK expects a libc library named `libc.so.6` to be in the shared library search path. If it is not, you will likely make a symbolic link in `/usr/lib`. $ cd /usr/lib $ sudo ln -s /usr/lib/x86_64-linux-gnu/libc.so.6 libc.so.6 **hidraw**: The hidraw library is a driver that provides an interface to USB devices. This driver should be part of the Linux kernel and there should be nothing you need to do. #### Smart card In order to use the SDK to contact a YubiKey on a Linux device, you need to install the "pcsclite" library. This is an Open Source implementation of PC/SC (personal computers/ smart card), a specification for integrating smart cards into computer environments. If it is not already installed on your Linux device, you will likely run a command such as: $ apt-get install libpcsclite1 **Arch Linux**: If on Arch Linux, you need to install both `pcsclite` and `ccid`: sudo pacman -S pcsclite ccid Optionally, you can also install `pcsc-tools`, which provides additional tools for troubleshooting smart card connectivity: sudo pacman -S pcsc-tools Once package installation is complete, start the pcsc daemon: sudo systemctl enable --now pcscd.socket sudo systemctl start --now pcscd.socket For more information on working with smart cards on Arch Linux, see the [Arch Linux documentation](https://wiki.archlinux.org/title/Smartcards) . NFC --- In addition to USB, the YubiKey 5 NFC keys also provide an NFC wireless interface for additional convenience. Unlike the YubiKey NEO, the YubiKey 5 NFC does not support RFID tags, such as MIFARE Classic and MIFARE DESFire. The URI used by the NDEF tag has been updated to a new format; an example of the new format is provided below. The `` value will be replaced with the OTP generated by the YubiKey. https://my.yubico.com/yk/# For operations that require a touch, all touch requests within the first 15 seconds of the operation will succeed. After a period of inactivity, a YubiKey placed on a desktop NFC reader may power down to help prevent unintended access to the device. To regain connectivity with an NFC reader, remove the YubiKey from the reader and reposition it on the reader. Some NFC readers may power cycle the YubiKey and, in doing so, prevent the device from powering down. [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/yubikey-reference/transports/overview.md/#L1) --- # Unknown Yubico OID Reference Guide Yubico Jan 31, 2025 CONTENTS 1 Yubico Object ID (OID) Arc1 2 OID Product Arc3 2.1 Base Prefix . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 2.2 Yubico OID Allocation Arc Values . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 2.3 Sample OID with Product Type . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 3 YubiHSM OIDs5 3.1 Attestation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 3.2 Certificate Extensions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 3.2.1 Pre-loaded certificates . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6 3.2.2 Intermediates . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6 3.3 Sample OID with Product Type . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6 4 FIDO Product OID Arc7 4.1 Base Prefix . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 4.2 FIDO2 and U2F Arc Values . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 4.2.1 FIDO Device Type . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 4.2.2 FIDO Attributes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8 4.2.3 FIDO Enterprise Attestation Attributes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8 4.3 Sample OID with U2F Type . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8 5 PIV Attestation OID Arc9 5.1 Base Prefix . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 5.2 Implementation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 5.3 PIV OID Attestation Certificate Arc Values . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 5.4 Sample OID with PIV Type . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 6 OpenPGP Attestation OID Arc13 6.1 Base Prefix . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 6.2 OpenPGP Arc Values . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 6.3 Sample OID with OpenPGP Type . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 7 LDAP Extensions OID Arc17 7.1 Base Prefix . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 7.2 LDAP Arc Values . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 7.2.1 LDAP Class . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 7.2.2 LDAP Attributes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18 7.3 Sample OID with LDAP Type . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18 8 FIPS Certificates OID Arc19 i 8.1 Base Prefix . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 8.2 FIPS Arc Values . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 8.3 Sample OID with LDAP Type . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20 9 Copyright21 9.1 Trademarks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 9.2 Disclaimer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 9.3 Contact Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 9.4 Document Updated . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22 ii CHAPTER ONE YUBICO OBJECT ID (OID) ARC The arc from Yubico’s OID is described in this guide. Object IDentifiers (OIDs) are a standardized method for naming objects, concepts, or persistent nameable things. The arc defines the subtree from Yubico’s OID. Each node (the number between each dot) in the OID, identifies the controlling authority for that node. Yubico’s private enterprise OID is: 1.3.6.1.4.1.41482 Where - 1.3.6.1.4.1- identifies the authorities:iso.identified-organization.dod.internet. private.enterprise 41482- identifies Yubico The Yubico OID including the arc, has the format:1.3.6.1.4.1.41482.xx.xx. Where xx.xx- are numbers that assigns a Yubico product type and attributes that are relevant to the product type. This can include physical type, certificate extensions, class, or other attribute. Also, depending upon the product type, the second node is not always used. 1 Yubico OID Reference Guide 2Chapter 1. Yubico Object ID (OID) Arc CHAPTER TWO OID PRODUCT ARC 2.1 Base Prefix The values in the table are added to the Yubico OID to identify the Yubico product type. 1.3.6.1.4.1.41482 For the Form Factor OID, it matches the values for form factors listed in the Configuration Reference. 2.2 Yubico OID Allocation Arc Values Within that arc, Yubico has a number of allocations. For each Sub-tree identified, additional OIDs are included to provide relevant details. For attribute subtree values of the products, see their respective chapters. NumberDescription 1U2F Device Type Sub-tree 2U2F Device Identifier 3PIV attestation Sub-tree 4YubiCrypt attestation Sub-tree 5OpenPGP attestation 6Yk Quorum attestation Sub-tree 10LDAP Classes 11LDAP Attributes 12FIPS 13FIDO Attributes Sub-tree 2.3 Sample OID with Product Type 1.3.6.1.4.1.41482.13This represents an OID containted in an Attestation certificate for FIDO by Yubico. Within this certificate, each OID will include details specific to the FIDO credential and attestation certificate. 3 Yubico OID Reference Guide 4Chapter 2. OID Product Arc CHAPTER THREE YUBIHSM OIDS When generating attestation certificates for keys, the YubiHSM will include OIDs listing specific information regarding the attested key. 3.1 Attestation Asymmetric keys in the YubiHSM can be attested by another Asymmetric key. The attestation process creates a new x509 certificate for the attested key. The device comes pre-loaded with an attestation key and certificate referenced by ID0. It is possible to use your own key and certificate for attestation, these then have to have the same ID and the key has to have the sign-attestation-certificateCapability set. Details: •Public key is copied from the attested key •Serial is a random 16 byte integer •Issuer is the subject of the attesting certificate •Dates is copied from the attesting certificate •Subject is the string “YubiHSM Attestation id 0x” with the attested ID appended •If the attesting key is RSA the signature is SHA256-PKCS#1v1.5 •If the attesting key is EC the signature is ECDSA-SHA256 3.2 Certificate Extensions Some certificate extensions are added in the generated certificate and the pre-loaded certificate: 5 Yubico OID Reference Guide OIDDescriptionData Type 1.3.6.1.4.1.41482.4.1Firmware versionOctet String 1.3.6.1.4.1.41482.4.2Serial numberInteger 1.3.6.1.4.1.41482.4.3OriginBit String 1.3.6.1.4.1.41482.4.4DomainsBit String 1.3.6.1.4.1.41482.4.5CapabiltiesBit String 1.3.6.1.4.1.41482.4.6Object IDInteger 1.3.6.1.4.1.41482.4.9LabelUtf8String 1.3.6.1.4.1.41482.4.10FIPS Integer value6 1.3.6.1.4.1.41482.4.12FIPS-approved Boolean TRUEif enabled FALSEotherwise See: •Origins •Domains •Capabilities •Object ID •Label •FIPS 3.2.1 Pre-loaded certificates The pre-loaded certificate can be fetched as an opaque object with ID 0. This will in turn be signed by an intermediate CA which is signed by a Yubico root CA. 3.2.2 Intermediates E45DA5F361B091B30D8F2C6FA040DB6FEF57918E.pem 3.3 Sample OID with Product Type 1.3.6.1.4.1.41482.13 6Chapter 3. YubiHSM OIDs CHAPTER FOUR FIDO PRODUCT OID ARC FIDO protocols, including FIDO2/WebAuthn and U2F, support the generation of attestation certificates for generated credentials. These credentials include OIDs listing details about the YubiKey itself. These OIDs are unique to Yubico FIDO Authentication devices, and may not be present on attestation certificates generated by non-Yubico hardware. 4.1 Base Prefix The values in the table are added to the Yubico OID to identify the Yubico product type. 1.3.6.1.4.1.41482 4.2 FIDO2 and U2F Arc Values When we change the physical appearance of devices or functional capabilities, this list will be expanded. 4.2.1 FIDO Device Type NumberDescription 1YubiKey U2F PlayStore devices (NXP-based) and Security Key Series (Infineon-based) 2YubiKey NEO (NXP-based) 3YubiKey Plus (Infineon-based) 4YubiKey Edge (Infineon-based) 5YubiKey 4 USB (Infineon-based) \[2015-11-03\] 6YubiKey NFC Preview (Infineon-based) \[2018-04-12\] 7YubiKey 5 \[2018-09-14\] 8YubiKey 5 Ci Lightning preview \[2019-02-08\] 9YubiKey Bio 7 Yubico OID Reference Guide 4.2.2 FIDO Attributes Full prefix1.3.6.1.4.1.41482.13 NumberDescriptionEncoding 1Firmware version Octet string (3 bytes), Major, Minor, Patch, like: 040300 for 4.3.0 2CSPN certificationValue marking which cert is relevant For CSPN OID, this entry is only present if the device has achieved CSPN certification. 4.2.3 FIDO Enterprise Attestation Attributes The FIDO Enterprise Attestation certificate includes the OIDs listed above with the addition of the FIDO Enterprise Attestation specific OIDs. The OIDs listed below are owned and maintained by the FIDO Alliance. Full prefix1.3.6.1.4.1.45724 NumberDescriptionEncoding 1.1.2Serial numberSerial number for enterprise attestation For the Serial Number OID (1.3.6.1.4.1.45724.1.1.2), this entry is only present on the Enterprise Attestation certificate, and is otherwise not included. 4.3 Sample OID with U2F Type Example for a YubiKey NEO: •version 1:1.3.6.1.4.1.41482.1.2 •version 2:1.3.6.1.4.1.41482.2: 1.3.6.1.4.1.41482.1.2 Example for Yubikey 4 FIPS: •version 2:1.3.6.1.4.1.41482.2: 1.3.6.1.4.1.41482.1.5 1.3.6.1.4.1.41482.12 8Chapter 4. FIDO Product OID Arc CHAPTER FIVE PIV ATTESTATION OID ARC The attestation feature added to the PIV module in YubiKey 4.3 and 5. For actual commands to work with the attestation feature, see the yubico-piv-tool documentation. The concept of attestation is used to show that a certain asymmetric key has been generated on device and not imported. Typically this would be used before creating a certificate. 5.1 Base Prefix The values in the table are added to the Yubico OID to identify the Yubico product type. 1.3.6.1.4.1.41482 5.2 Implementation Attestation is implemented by creating a X.509 certificate for the key that is to be attested, this is only done if the key has been generated on device. This certificate should be used for the purpose of verifying that the key was generated in device. Additional information included in the Attestation Certificate can be used to provide information about the device the attested key was generated on. Some features of the generated certificate: •Serial will be a random 16 byte integer •Issuer will be the subject of the attesting certificate •Dates will be copied from the attesting certificate •Subject will be the string “YubiKey PIV Attestation ” with the attested slot appended •If the attesting key is RSA the signature will be SHA256-PKCS#1v1.5 •If the attesting key is EC the signature will be ECDSA-SHA256 The YubiKey comes with a pre-loaded attestation certificate signed by a Yubico PIV CA. This can be overwritten by loading a new key and certificate to slot f9. After the Yubico key is overwritten it can not be brought back. The attestation key and certificate will not be cleared out by a reset of the device. Note:If you have a YubiKey Preview device, the attestation certificate will instead be signed by our Yubico PIV Preview CA 9 Yubico OID Reference Guide Note:The root cert for the Yubico PIV CA was updated on September 24, 2018. The prior PEM can be found here. YubiKey 4 Series manufactured prior to mid-2017 and some manufactured in 2018 were signed with Yubico’s U2F Attestation CA. For more information on support added to the current root certificate, see PIV Attestation Verification Fails with OpenSSL 1.1.0. 5.3 PIV OID Attestation Certificate Arc Values The PIV Attestation certificates issued by Yubico have additional OIDs, used as certificate extensions. NumberDescription 1Attestation data and signature 2Attestation certificate 3Firmware version 4Applet version 5Serial number Batch start 6Serial number Batch end 7Serial number (specific) 8Usage policy 9Form factor 10FIPS 11CSPN 5.4 Sample OID with PIV Type Extensions in the generated certificate. 10Chapter 5. PIV Attestation OID Arc Yubico OID Reference Guide CertificateDescription 1.3.6.1.4.1.41482.3.3 Firmware version, encoded as 3 bytes, like: 040300 for 4.3.0 1.3.6.1.4.1.41482.3.7 Serial number of the YubiKey, encoded as an integer. 1.3.6.1.4.1.41482.3.8 Two bytes, the first encoding pin policy and the second touch policy - Pin policy: 01 - never, 02 - once per session, 03 - always - Touch policy: 01 - never, 02 - always, 03 - cached for 15s 1.3.6.1.4.1.41482.3.9 Formfactor, encoded as one byte - USB-A Keychain: 01 (81 for FIPS Devices) - USB-A Nano: 02 (82 for FIPS Devices) - USB-C Keychain: 03 (83 for FIPS Devices) - USB-C Nano: 04 (84 for FIPS Devices) - Lightning and USB-C: 05 (85 for FIPS Devices) 1.3.6.1.4.1.41482.3.10 FIPS Certified YubiKey 1.3.6.1.4.1.41482.3.11 CSPN Certified YubiKey 5.4. Sample OID with PIV Type11 Yubico OID Reference Guide 12Chapter 5. PIV Attestation OID Arc CHAPTER SIX OPENPGP ATTESTATION OID ARC This document describes the OIDs present in the attestation certificates added to the OpenPGP module in YubiKey 5.2. For generating attestation certificates, you can use YubiKey Manager CLI (ykman) version 3.1.0 or higher. The concept of attestation is to cryptographically certify that a certain asymmetric key has been generated on device, and not imported. This can be used to prove that no other copies of the asymmetric key exist. Yubico OIDs within the generated attestation certificate include contextual information about the device and key attested to. 6.1 Base Prefix The values in the table are added to the Yubico OID to identify the Yubico product type. 1.3.6.1.4.1.41482 13 Yubico OID Reference Guide 6.2 OpenPGP Arc Values NumberDescriptionEncoding 1Cardholder NameUTF8 String 2Whether generated on device Integer (0 == imported, 1 == generated) 3Firmware version Octet string (3 bytes), Major, Minor, Patch, like: 040300 for 4.3.0 4 Fingerprint of the attested key (TAG C7/C8/C9) Octet string, 20 bytes 5 Generation date of the key (TAG CE/CF/D0) Octet string, 4 bytes 6 If the attested key is a SIG key, the current value of the Signature Counter Integer 7Serial number of the deviceInteger 8 User Interaction Flag (UIF) if supported (TAG D6/D7/D8) Octet string (1 byte), 00 - disabled, 01 - enabled, 02 - permanently enabled 9Form factor Octet string (1 byte) 00 - not specified, 01 - USB A Keychain, 02 - USB A Nano, 03 - USB C Keychain, 04 USB C Nano, 05 Lightning 10FIPS 11CSPN 14Chapter 6. OpenPGP Attestation OID Arc Yubico OID Reference Guide 6.3 Sample OID with OpenPGP Type Full prefix1.3.6.1.4.1.41482.5 Extensions in the generated certificate: 6.3. Sample OID with OpenPGP Type15 Yubico OID Reference Guide OIDTypeDescription 1.3.6.1.4.1.41482.5.1UTF-8 StringCardholder name 1.3.6.1.4.1.41482.5.2Integer Attested key’s source - 0x00: imported (not permitted) - 0x01: generated on device 1.3.6.1.4.1.41482.5.3Octet String (3) YubiKey version number ex: 050303 = 5.3.3 1.3.6.1.4.1.41482.5.4Octet String (20)Attested key’s fingerprint 1.3.6.1.4.1.41482.5.5Octet String (4)Attested key’s generation date 1.3.6.1.4.1.41482.5.6Integer Attested key’s signature counter (if applicable) 1.3.6.1.4.1.41482.5.7Integer YubiKey’s serial number 1.3.6.1.4.1.41482.5.8Octet String (1) User Interaction Flag (UIF) - 0x00: touch disabled - 0x01: touch enabled - 0x02: touch permanent - 0x03: touch cached - 0x04: touch permanent, cached 1.3.6.1.4.1.41482.5.9Octet String (1) Form Factor - 0x00: Unspecified - 0x01: USB-A Keychain - 0x02: USB-A Nano - 0x03: USB-C Keychain - 0x04: USB-C Nano - 0x05: USB-C/Lightning Keychain 1.3.6.1.4.1.41482.5.10Octet String (1)FIPS Certified YubiKey 1.3.6.1.4.1.41482.5.11Octet String (1)CSPN Certified YubiKey 16Chapter 6. OpenPGP Attestation OID Arc CHAPTER SEVEN LDAP EXTENSIONS OID ARC 7.1 Base Prefix The values in the table are added to the Yubico OID to identify the Yubico product type. 1.3.6.1.4.1.41482 7.2 LDAP Arc Values 7.2.1 LDAP Class Used for declaring Yubico specific class objects for schema extensions for LDAP servers IDFull NumberName 11.3.6.1.4.1.41482.10.1yubicoAttributes 21.3.6.1.4.1.41482.10.2 31.3.6.1.4.1.41482.10.3 17 Yubico OID Reference Guide 7.2.2 LDAP Attributes Used for declaring Yubico specific schema extensions for LDAP servers IDFull NumberNameDescription 11.3.6.1.4.1.41482.11.1yubicoYubiOTP TokenID:SEED: Counter:Metadata 21.3.6.1.4.1.41482.11.2yubicoHOTP TokenID:SEED:Counter: Metadata 31.3.6.1.4.1.41482.11.3yubicoTOTP TokenID:SEED:Counter: Metadata 41.3.6.1.4.1.41482.11.4yubicoU2F TokenID:KeyHandle: Counter:Metadata 51.3.6.1.4.1.41482.11.5yubicoPublicKeysTo- kenID:PublicKey:Metadata 7.3 Sample OID with LDAP Type 18Chapter 7. LDAP Extensions OID Arc CHAPTER EIGHT FIPS CERTIFICATES OID ARC The PIV Attestation certificates generated on the device will include OIDs with additional information about the Yu- biKey the certificate was generated on. For FIPS devices, there will also be an additional OID to indicate the YubiKey was FIPS certified. For all other devices, this OID entry will not be present. 8.1 Base Prefix The values in the certificates are added to the Yubico OID to identify the Yubico product type. 1.3.6.1.4.1.41482 8.2 FIPS Arc Values FIPS is marked with the OID1.3.6.1.4.1.41482.12and a value marking what FIPS certificate the device belongs to: 1: YubiKey Standard and YubiKey Nano Certificate #2267, validation date 10/14/2014 https://csrc.nist.gov/Projects/ cryptographic-module-validation-program/Certificate/2267 2: YubiKey (4) FIPS Certificate #3204, validation date 6/21/2018 - 4/30/2019 (revoked but no keys programmed with this) https://csrc.nist.gov/Projects/cryptographic-module-validation-program/Certificate/3204 3:YubiKey (4) FIPS Certificate #3517, validation date 9/3/2019 https://csrc.nist.gov/Projects/ Cryptographic-Module-Validation-Program/Certificate/3517 4: YubiKey 5 FIPS Certificate #3907 (Level 1), validation date 4/22/2021 https://csrc.nist.gov/projects/ cryptographic-module-validation-program/certificate/3907 5: YubiKey 5 FIPS Certificate #3914 (Level 2), validation date 05/03/2021 https://csrc.nist.gov/projects/ cryptographic-module-validation-program/certificate/3914 6:YubiHSM 2 Certificate #3916, validation date 05/03/2021 https://csrc.nist.gov/projects/ cryptographic-module-validation-program/certificate/3916 7: YubiKey 5 FIPS Certificate #3914 (Level 2) update, validation date 08/19/2021 https://csrc.nist.gov/projects/ cryptographic-module-validation-program/certificate/3914 8: YubiKey 5 FIPS Certificate #XXXX (Level 2), validation date TBD. YubiKey with firmware ver- sion 5.7.4 submitted to CMVP for FIPS 140-3 validation on 11/19/2024. https://csrc.nist.gov/Projects/ cryptographic-module-validation-program/Modules-In-Process/Modules-In-Process-List 19 Yubico OID Reference Guide 8.3 Sample OID with LDAP Type FIPS is marked with the OID1.3.6.1.4.1.41482.12 20Chapter 8. FIPS Certificates OID Arc CHAPTER NINE COPYRIGHT ©2024-2025 Yubico AB. All rights reserved. 9.1 Trademarks Yubico and YubiKey are registered trademarks of Yubico AB. All other trademarks are the property of their respective owners. 9.2 Disclaimer The contents of this document are subject to revision without notice due to continued progress in methodology, design, and manufacturing. Yubico shall have no liability for any error or damages of any kind resulting from the use of this document. Yubico Software referenced in this document is licensed to you under the terms and conditions accompanying the software or as otherwise agreed between you or the company that you are representing. 9.3 Contact Information Yubico AB Gävlegatan 22 113 30 Stockholm Sweden More options for getting touch with us are available on the Contact page of Yubico’s website. 21 Yubico OID Reference Guide 9.4 Document Updated 2025-01-31 19:20:40 UTC 22Chapter 9. Copyright --- # Configure slot ##### Table of Contents Configure slot ============== Commits a configuration to one of two programmable slots. Slot 1 corresponds to the "short press" of the YubiKey button, and Slot 2 the "long press". Available --------- Short press (slot 1): YubiKey firmware 1.x and later Long press (slot 2): YubiKey firmware 2.0 and later Note: Access over USB (CCID) disabled after YubiKey firmware 5.x Command APDU info ----------------- | CLA | INS | P1 | P2 | Lc | Data | | --- | --- | --- | --- | --- | --- | | 0x00 | 0x01 | (See below) | 0x00 | 52 | (see below) | ### P1: Slot P1 determines which slot to program. It can have one of the following values: | Option | Value | | --- | --- | | Short press (Slot 1) | 0x01 | | Long press (Slot 2) | 0x03 | ### Data: Configuration structure The data field contains a standard configuration structure. | Field | Size | Description | | --- | --- | --- | | Fixed Data | 16 | Fixed data in binary form. | | UID | 6 | Fixed UID part of the ticket. | | AES Key | 16 | AES key | | Access Code | 6 | Access code to re-program the slot | | EXT Flags | 1 | Extended flags | | TKT Flags | 1 | Ticket configuration flags | | CFG Flags | 1 | General configuration flags | | Reserved | 2 | Must be zero | | CRC | 2 | CRC16 value of all the fields | TBD page will go into more detail on how to construct a valid configuration. Response APDU info ------------------ | Lr | Data | SW1 | SW1 | | --- | --- | --- | --- | | 0x06 | [Status structure](https://docs.yubico.com/yesdk/users-manual/application-otp/otp-commands.html#status-structure) | 0x90 | 0x00 | Examples -------- $ opensc-tool.exe -c default -r 1 -s 00:a4:04:00:08:a0:00:00:05:27:20:01:01 -s 00:01:01:00:34:de:ad:be:ef: de:ad:be:ef:de:ad:be:ef:de:ad:be:ef:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00: 00:00:00:00:00:10:20:20:a0:00:00:2a:ac Sending: 00 A4 04 00 08 A0 00 00 05 27 20 01 01 Received (SW1=0x90, SW2=0x00): 05 03 01 04 05 00 ...... Sending: 00 01 01 00 34 DE AD BE EF DE AD BE EF DE AD BE EF DE AD BE EF 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 10 20 20 A0 00 00 2A AC Received (SW1=0x90, SW2=0x00): 05 03 01 05 05 00 ...... [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-otp/commands-configure-slot.md/#L1) --- # How to retrieve a slot's status ##### Table of Contents How to retrieve a slot's status =============================== When you construct an [OtpSession](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.OtpSession.html) object, you can retrieve the general status of both OTP application [slots](https://docs.yubico.com/yesdk/users-manual/application-otp/slots.html) . Slot status will tell you if the slot: * is configured * requires touch To output slot status to the console, do the following: using (OtpSession otp = new OtpSession(yKey)) { Output(Slot.ShortPress, otp.IsShortPressConfigured, otp.ShortPressRequiresTouch); Output(Slot.LongPress, otp.IsLongPressConfigured, otp.LongPressRequiresTouch); } void Output(Slot slot, bool configured, bool touchRequired) { Console.WriteLine($"Slot {slot} Configured: {configured}"); if (configured) { Console.WriteLine($"Slot {slot} Requires Touch: {touchRequired}"); } } [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-otp/how-to-retrieve-slot-status.md/#L1) --- # How to swap slot configurations ##### Table of Contents How to swap slot configurations =============================== Because swapping [slot](https://docs.yubico.com/yesdk/users-manual/application-otp/slots.html) settings requires zero configuration, this operation is not designed as a Fluent Builder operation. It’s as simple as calling the [SwapSlots](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.OtpSession.html#Yubico_YubiKey_Otp_OtpSession_SwapSlots) method: using (OtpSession otp = new OtpSession(yKey)) { otp.SwapSlots(); } ##### Note This method will fail if at least one of the slots is not currently configured. Also, if one or both of the slots is protected with an access code, this method will fail. [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-otp/how-to-swap-slot-configs.md/#L1) --- # Swap slot configurations ##### Table of Contents Swap slot configurations ======================== Swaps the configurations in the short and long press slots. Available --------- YubiKey firmware 2.3.2 and later Command APDU info ----------------- | CLA | INS | P1 | P2 | Lc | Data | | --- | --- | --- | --- | --- | --- | | 0x00 | 0x01 | 0x06 | 0x00 | (absent) | (absent) | Response APDU info ------------------ | Lr | Data | SW1 | SW1 | | --- | --- | --- | --- | | 0x06 | [Status structure](https://docs.yubico.com/yesdk/users-manual/application-otp/otp-commands.html#status-structure) | 0x90 | 0x00 | Examples -------- $ opensc-tool.exe -c default -r 1 -s 00:a4:04:00:08:a0:00:00:05:27:20:01:01 -s 00:01:06:00 Sending: 00 A4 04 00 08 A0 00 00 05 27 20 01 01 Received (SW1=0x90, SW2=0x00): 05 03 01 02 05 00 ...... Sending: 00 01 06 00 Received (SW1=0x90, SW2=0x00): 05 03 01 03 05 00 ...... [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-otp/commands-swap-slots.md/#L1) --- # Program NDEF ##### Table of Contents Program NDEF ============ Sets the static payload for the NFC data exchange (NDEF) used by NFC enabled keys. Available --------- YubiKey firmware 3.x, and 5.x and later Command APDU info ----------------- | CLA | INS | P1 | P2 | Lc | Data | | --- | --- | --- | --- | --- | --- | | 0x00 | 0x01 | (See below) | 0x00 | (Varies) | (See below) | ### P1: Slot P1 determines which slot to program. It can have one of the following values: | Option | Value | | --- | --- | | NDEF Slot 1 (Primary) | 0x08 | | NDEF Slot 2 | 0x09 | ### Data: NDEF configuration structure | Field | Size | Description | | --- | --- | --- | | Length | 1 | Number of valid bytes in the data field. | | Type | 1 | Leave this set to `55` | | Data | 54 | The NDEF payload. It does not need to fill the entire buffer. | | Access Code | 6 | The current access code for the slot, if any. | Response APDU info ------------------ | Lr | Data | SW1 | SW1 | | --- | --- | --- | --- | | 0x06 | [Status structure](https://docs.yubico.com/yesdk/users-manual/application-otp/otp-commands.html#status-structure) | 0x90 | 0x00 | Examples -------- TODO [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-otp/commands-program-ndef.md/#L1) --- # Update slot ##### Table of Contents Update slot =========== Updates the flags for a given configuration slot if the slot configuration allows for it. The slot must either have the "Allow Update" flag set, or be marked as "Dormant". Available --------- YubiKey firmware 2.3 and later Command APDU info ----------------- | CLA | INS | P1 | P2 | Lc | Data | | --- | --- | --- | --- | --- | --- | | 0x00 | 0x01 | (See below) | 0x00 | 52 | (see below) | ### P1: Slot P1 determines which slot to program. It can have one of the following values: | Option | Value | | --- | --- | | Short press (Slot 1) | 0x04 | | Long press (Slot 2) | 0x05 | ### Data: Configuration structure The data field contains a standard configuration structure. | Field | Size | Description | | --- | --- | --- | | Fixed Data | 16 | Do not set this field. | | UID | 6 | Do not set this field. | | AES Key | 16 | Do not set this field. | | Access Code | 6 | Do not set this field. | | EXT Flags | 1 | Extended flags | | TKT Flags | 1 | Ticket configuration flags | | CFG Flags | 2 | General configuration flags | | Reserved | 2 | Must be zero | | CRC | 2 | CRC16 value of all the fields | The only changes that are allowed are the setting of the following flags: * Ticket Flags: Tab First, Append Tab 1, Append Tab 2, Append Delay 1, Append Delay 2, Append Carriage Return * Config Flags: Pacing 10ms, Pacing 20ms * Extended Flags: Serial Number Visibility (Button, USB, API), Use Numeric Keypad, Fast Trigger, Allow Update, Dormant, Invert LED Response APDU info ------------------ | Lr | Data | SW1 | SW1 | | --- | --- | --- | --- | | 0x06 | [Status structure](https://docs.yubico.com/yesdk/users-manual/application-otp/otp-commands.html#status-structure) | 0x90 | 0x00 | Examples -------- TODO [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-otp/commands-update-slot.md/#L1) --- # Unknown Best Practices Yubico Jun 23, 2025 CONTENTS 1 Introduction1 1.1 Audiences . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 1.2 Passkeys & FIDO2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 1.3 FIDO metadata & attestation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 1.4 Updates . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 2 Attestation and Authenticator Metadata3 2.1 Intended audience . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 2.2 Background . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 2.3 AAGUIDs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 2.4 FIDO Metadata Service (MDS) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 3 Passkey Frequently Asked Questions5 3.1 Intended audience . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 3.2 What is a passkey? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 3.3 Is ‘passkey’ the new name for FIDO and WebAuthn credentials? . . . . . . . . . . . . . . . . . . . . 5 3.4 Why is the term passkey in the news a lot recently? . . . . . . . . . . . . . . . . . . . . . . . . . . . 6 3.5 How are passkeys different from YubiKeys? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6 3.6 What terms will Yubico use to talk about passkeys? . . . . . . . . . . . . . . . . . . . . . . . . . . . 6 3.7 What are the security tradeoffs between copyable and device-bound passkeys? . . . . . . . . . . . . 7 3.8 How can organizations tell what type of passkeys are used to authenticate to their services? . . . . . . 7 3.9 What is Yubico’s overall guidance about passkeys? . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 3.10 Can passkeys replace a password as well as another authentication factor? . . . . . . . . . . . . . . . 8 4 Passkey Best Practices for Service Providers9 4.1 Intended audience . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 4.2 Plan for user experience challenges . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 4.3 Consider how users will recover from the loss of an authenticator . . . . . . . . . . . . . . . . . . . 10 4.4 Decide when to use discoverable credentials . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 4.5 Decide when to request attestation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 4.6 Consider approaches for detecting passkey support in the browser or platform . . . . . . . . . . . . . 11 4.7 Be cautious about requiring optional WebAuthn features . . . . . . . . . . . . . . . . . . . . . . . . 12 5 Authenticator Enforcement Best Practices for Identity Providers13 5.1 Intended audience . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 5.2 Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 5.3 MDS Management . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 5.4 Customer-centric enforcement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 5.4.1 Do not override customer authenticator selection . . . . . . . . . . . . . . . . . . . . . . . 14 5.4.2 Allow custom metadata . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 i 5.5 Use cases . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 5.5.1 Non-certified devices with MDS metadata . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 5.5.1.1 Authenticator verification and testing . . . . . . . . . . . . . . . . . . . . . . . . . 15 5.5.1.2 Vulnerability remediation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 5.5.2 Customer-provided metadata . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 5.5.2.1 Custom authenticators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 5.5.2.2 Certified devices not listed in MDS . . . . . . . . . . . . . . . . . . . . . . . . . . 16 5.6 Considerations for authenticator selection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 5.6.1 Security vetting and assessment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 5.6.2 Additional considerations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 5.7 IdP implementation recommendations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 5.7.1 Lifecycle and MDS updates . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 5.7.2 Logging and API access . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 5.7.3 Known incompatible devices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 6 Glossary19 7 Copyright21 7.1 Trademarks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 7.2 Disclaimer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 7.3 Contact Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 7.4 Document Updated . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22 Index23 ii CHAPTER ONE INTRODUCTION This collection of guides is intended to help service providers, organizations and individuals make good decisions about supporting, requiring, and using the protocols that the YubiKey supports. It includes frequently asked questions, best practices, and reference architectures. 1.1 Audiences This collection of guides is made up of a variety of different kinds of articles, from conceptual articles that lay a foundation for understanding how a technology works to FAQs and prescriptive best practices guidance. While we expect readers to be familiar with thekindof article they’re reading, there’s a lot of content in this Best Practices book that may seem inconsistent or even conflicting if the intended audience isn’t made very clear. We’ve made sure to label each article with its intended audiences and, when applicable, a short discussion ofwhythe guidance applies to each of them. We have identified four main audiences: •Service Providers (individual or customer identity) •Identity Providers (organization or workforce identity) •Organizations •Individuals The main difference for what these audiences require generally comes down to what part of the authentication design and authenticator selection processes they have control over. Service providers typically only control the design of the service or relying party, but they may be able to encourage use of a specific authenticator (by providing free authenticators to customers). They usually lack the authority to require a specific authenticator or even a specific authentication method. Individuals, on the other hand, typically only control the authenticator they use for personal use and what services they use it with. Identity providers and organizations tend to have closer coordination, and together control all aspects of authentication, from the authenticator selection to the relying party or service configuration, and can enforce those decisions with either technology or policy controls. Organizations may even build their own relying parties for authentication - in which case they’ll act as the identity provider as well. While there are some exceptions to these situations in the form of laws or regulations around certain industries or types of services, those exceptions tend to make the decision making process easier by removing some choice. Not all types of guidance will be applicable to all audiences, and in some cases (like thePasskey Frequently Asked Questions), guidance may be applicable to all audiences. 1 Best Practices 1.2 Passkeys & FIDO2 Before the introduction of synced passkeys, the choices for modern phishing-resistant authentication were limited to two options: use a FIDO2 hardware security key or a platform authenticator (such as Windows Hello for Business or Touch ID for the Mac). Nowadays, there is a much broader spectrum of authenticator choice, and with it, a more challenging set of decisions to make. For all audiences: •Passkey Frequently Asked Questions For Service Providers: •Passkey Best Practices for Service Providers 1.3 FIDO metadata & attestation The FIDO specifications allow for various levels of privacy regarding individual FIDO authenticators. This guidance discusses the tradeoffs made between privacy and compliance for passkeys and contains specific recommendations for Identity providers processing attestation metadata and for organizations navigating the attestation ecosystem. Concepts: •Attestation and Authenticator Metadata For identity providers: •Authenticator Enforcement Best Practices for Identity Providers 1.4 Updates This is a living document. The computer security landscape is constantly evolving. Changes in regulations, security needs, threat actor behavior, and the technology itself all have the potential to change how the YubiKey and the protocols it supports are best used. This document will be updated periodically and represents the current consensus within Yubico. Specific recommendations may change from time to time. Consider bookmarking this documentation and returning to it periodically to ensure you’re still following the most up-to-date guidance. 2Chapter 1. Introduction CHAPTER TWO ATTESTATION AND AUTHENTICATOR METADATA 2.1 Intended audience This conceptual article will be of most interest to organizations that need to ensure that their workforce is using a strong authenticator and identity providers looking to provide that assurance to organizations via their products. 2.2 Background Organizations may want to limit the use of FIDO authenticators to specific makes and models to ensure the devices users authenticate with meet their security and compliance needs. In order to facilitate this, the FIDO specification provides a mechanism calledattestation. Attestation uses data supplied by device manufacturers and validated and aggregated by the FIDO Alliance to verify cryptographic signatures generated during FIDO authenticator registration. 2.3 AAGUIDs Identity providers (IdPs) use an authenticator’sAAGUIDto look up a certificate chain that can be used to validate the attestation statement’s signature. IdPs may also use the AAGUID to look up other information about an authenticator, such as the features it supports, or the presence of specific 3rd party certifications, or even an icon to display to help a user to determine where their passkey is stored. 1 This information is collectively known as theauthenticator metadata. 2.4 FIDO Metadata Service (MDS) In order to facilitate IdPs’ use ofauthenticator metadata, the FIDO Alliance hosts the FIDO Metadata Service (MDS), which is updated as vendors produce new authenticators with differentAAGUIDsand as authenticators achieve FIDO and 3rd party certifications. TheMDSprevents IdPs from having to hard code AAGUID and certificate chain informa- tion. TheMDSis a single large document which is over 5 megabytes in size at the time of writing. The bandwidth and compute requirements to obtain and process it make it unsuitable for checking during every new authenticator regis- tration. IdPs should download and ingest a new MDS document into their systems periodically, out of band from the authenticator registration process. The FIDO Alliance recommends that the MDS is downloaded and ingested monthly. 2 However, in 2024, the MDS averaged between one and two updatesper week. Identity providers may want to download and process the MDS more frequently to support the rapid changes in the FIDO authenticator ecosystem. 1 FIDO Metadata Statement standard 2 “How often should I be fetching MDS3 blob?” at https://fidoalliance.org/metadata/ 3 Best Practices The MDS is not exhaustive. There is no requirement to list an authenticator in the MDS, even if it has received a FIDO Alliance certification. There are a number of reasons why device manufacturers or customers may not want the metadata for their authenticators published, but ultimately customers must have the option of privacy, even if they are using an authenticator that has been customized for them by a device manufacturer. 3 Synced passkey providers aren’t even eligible for listing in the MDS because, with some exceptions, they are not currently capable of producing attestations. More information about the MDS can be found at the FIDO Alliance Metadata Service page: https://fidoalliance.org/ metadata/ 3 See theUse Casessection in the “Authenticator Enforcement Best Practices for Identity Providers” chapter of this guide for more detail. 4Chapter 2. Attestation and Authenticator Metadata CHAPTER THREE PASSKEY FREQUENTLY ASKED QUESTIONS 3.1 Intended audience This FAQ is for everyone because passkeys are for everyone. Whether you’re looking to understand what passkeys mean to you as an individual or for your organization, you consume identity information (relying parties) or produce it (identity providers), or you just want to log on to your favorite web site, this FAQ will help you understand what passkeys are and some of the terms used to describe them. 3.2 What is a passkey? Passkeys are like passwords, but better. They’re better because they aren’t created insecurely by humans, and because they use public key cryptography to create much more secure experiences. But passkeys aren’t a new thing. It’s just a new name starting to be used for WebAuthn/FIDO2 credentials that en- able fully passwordless experiences. These types of credentials are also called discoverable credentials, or sometimes resident credentials. We like the new term and will use it, because it helps people understand they’re a password replacement with a simple term. “Passkey” is much more understandable by most people than “discoverable WebAuthn/FIDO credential.” The first public mention of the term passkey to a wide audience was by Apple at a WWDC2021 talk where they introduced a “Passkeys in iCloud Keychain” technology preview to developers. Passkeys refer only to WebAuthn/FIDO credentials. This does not include the many other keys and protocols, such as PIV, OTP, or OpenPGP Card, that are available in the YubiKey 5 Series. 3.3 Is ‘passkey’ the new name for FIDO and WebAuthn credentials? Passkey is a term that the industry is rallying around for FIDO credentials that can fully replace, rather than only augment, passwords. These are called resident or discoverable credentials in the specs. We think “passkey” is a better term than “discoverable WebAuthn/fido credential,” because it evokes its ability to replace passwords in an accessible way. Passkeys in YubiKeys have been supported since discoverable credentials were added in the WebAuthn/FIDO standards around 2018. However, it’s important to note that passkeys in YubiKeys are not copyable, meaning the passkey is bound to the YubiKey. See below question: “How are passkeys different from YubiKeys?” for additional information. 5 Best Practices 3.4 Why is the term passkey in the news a lot recently? Some Platform/OS vendors started shipping support for fully passwordless experiences using external authenticators like YubiKeys (and also using the security-focused hardware built into their devices, such as TPMs) as early as 2019. Since early 2023, many Platform/OS vendors and service providers have added support passkeys. Password managers have also added support for storing a using passkeys. Expect to see a lot more about passkeys from platform vendors such as Apple, Google, and Microsoft, as well as from external authenticator vendors such as Yubico, in the news as the implementations evolve. 3.5 How are passkeys different from YubiKeys? Yubikeys cancontainpasskeys. YubiKeys have had the ability to create these passwordless-enabled FIDO2 credentials (passkeys) since the YubiKey 5 Series became available in mid-2018. Currently, YubiKeys can store a maximum of 100 passkeys. They’re different because copyable passkeys aren’t stored on dedicated hardware and will be automatically synced using the credentials for the underlying cloud account, whereas passkeys in YubiKeys are bound to the YubiKey’s physical hardware where they can’t be copied under normal circumstances. 3.6 What terms will Yubico use to talk about passkeys? We like the term passkey and plan to use it. Because many things are being talked about at the same time, we will try to use terminology consistently to make the differences or similarities clear depending on the situation. This is still a work in progress across the industry, and we will adapt as things change. The first differentiator between different types of passkeys is whether they can be copied or synchronized. These copyable passkeys are often called “multi-device,” “syncable,” “backup enabled,” “shareable,” or similar terms. We prefer to use “copyable” because it clearly describes what can be done with the credential, but it does not imply any goodness or badness and does not use overloaded or confusing terms. We prefer to use “device-bound” to describe passkeys that can’t be copied under normal circumstances, because it aligns with the terminology the rest of the industry is using to describe passkeys. Device-bound passkeys are tied to a specific device and can’t be copied or synchronized under normal circumstances. Once you know a passkey is device-bound, the next step is describing what kind of device it’s bound to. Some device- bound passkeys are bound to general purpose computing devices like a smartphone, a laptop, or even a desktop com- puter. A passkey stored on a YubiKey, on the other hand, is device-bound to a portable, purpose-built security device: a security key. Some of these terms are easily confused with the WebAuthn/FIDO concept of an authentication device’s “attachment”, which can have the values “platform” or “cross-platform.” These terms describe how the authenticator device is attached to the system and provide a way for a web site to tell a browser where to look for a passkey, but they don’t reveal anything about the passkey itself. 6Chapter 3. Passkey Frequently Asked Questions Best Practices 3.7 What are the security tradeoffs between copyable and device- bound passkeys? Device-bound passkeys on portable, purpose-built security devices like YubiKeys are the “gold standard” for modern, phishing-resistant authentication and security. They are very easy to reason about and build systems around; no device, no access. However, for consumers registering credentials to many sites, managing multiple authenticators so you have an up-to-date backup can present challenges. Copyable passkeys can make it easier to recover an account in the event of a lost device (as long as the user can obtain another device that works with the cloud syncing service they used). Using that copyable credential proves that there was access to a device which was logged into the user’s cloud account. This can be a useful additional signal, but it does not provide the same level of security as a device-bound passkey. 3.8 How can organizations tell what type of passkeys are used to au- thenticate to their services? Security keys like the YubiKey are capable of providing attestation information during registration. Services that pro- cess and store attestation information can determine information about the manufacturer, capabilities, and certifications of the security key that created a passkey. This information can help service providers detect counterfeit devices or pro- vide guidance to users about how their passkey is stored. For more detailed information about how to handle attestation, see the Yubico Passkey Workshop’s section on attestation. 3.9 What is Yubico’s overall guidance about passkeys? •We hope that a consumer focused push about passkeys will entice more services to enable support for WebAu- thn/FIDO. •Copyable passkeys offer roughly the same security as “Sign-in with Google/Apple,” plus an additional key sync password. •Today, banks, enterprises, and those wanting or needing high security do not rely solely on the security of cloud accounts provided by Sign-in with Google/Apple via federated login protocols like SAML, OpenID Connect, or OAuth. Even if copyable passkeys are used to provide that association instead, the security provided will still be insufficient for high security needs. •The multitude of high security use cases faced by many organizations need more protocols than just FIDO. These organizations need the security guarantees and cryptographic attestations provided by hardware backed credentials to know their systems are safe and to be able to prove it. •Attestation is also the only way to achieve high confidence that a given credential is device-bound and stored on purpose-built hardware. •Services should continue to request, store, and use attestation information to make risk decisions based on the type of credential that is used. Our guidance on attestation is provided in more detail on our developer site. •More use of WebAuthn/FIDO hopefully means that eventually fewer people will use and fewer services will have to deal with creating and securing dangerous username and password-based systems. We are happy that the standards we co-created and have worked on improving for years are seeing even wider adoption, and we are hopeful that these motions will continue to reduce harm and advance our mission to make the internet safer for all. For more specific passkey guidance for service providers, seePasskey Best Practices for Service Providers. 3.7. What are the security tradeoffs between copyable and device-bound passkeys?7 Best Practices 3.10 Can passkeys replace a password as well as another authenti- cation factor? Absolutely, yes! Passkeys have been described as a “password replacement”, which is true, but it frequently misses that passkeys can also replace the push notification, MFA code, or SMS notification that are often used to bolster password security. Passkeys combine two authentication factors. The first is alwayssomething you have, which is the passkey itself. The second may be one of: •Something you know, which is a PIN, or a device passcode. •Something you are, measured by a biometric sensor like a fingerprint sensor or FaceID. The combination of these factors, as well as the phishing-resistant nature of FIDO2/WebAuthn, make passkeys more secure than passwords combined with traditional MFA. 8Chapter 3. Passkey Frequently Asked Questions CHAPTER FOUR PASSKEY BEST PRACTICES FOR SERVICE PROVIDERS 4.1 Intended audience This documentation is intended for developers that are implementing passkey support for service providers - web sites and services (relying parties) - using a bring-your-own authenticator model. Service providers likely won’t have any control over what authenticator a user prefers, and if the user’s preferred authenticator isn’t available for use, they may choose not to use passkeys at all. It’s even possible they’ll start using a competitor’s product thatdoesallow them to use the authenticator of their choice - for convenience, security, or even privacy reasons - so it is paramount to make sure the passkey component is done right and empowers users to make choices. Just as any MFA is more secure than no MFA, any phishing-resistant MFA is more secure than non-phishing resistant MFA. It follows that anything which prevents a user from using their authenticator of choice to store their passkey is likely to make a site or service less secure - as long as people can opt-out of passkeys entirely. Developers that are building a solution for employees, contractors, or perhaps VIP clients that need to protect their accounts in a specific way for risk management or compliance reasons should be more selective about passkey authen- ticator use. This guidance is not intended to replace guidance for situations where the developer’s organization can choose the authenticator. To find out more about how to support passkeys for employees, contractors, and VIP clients, visit Yubico’s glossary page for passkeys. The goal of this documentation is to guide developers down the path of making the best decisions for their end users, ensuring that they don’t unnecessarily restrict the type of authenticator or how it’s used. The WebAuthn standard, upon which passkeys are based, is very permissive by default and will allow a wide range of authenticators. In short - this document is to ensure that developers don’t do extra work only to aggravate end users. 4.2 Plan for user experience challenges It’s important to acknowledge that the user experience for passkeys can be very inconsistent between browsers and platforms. Different messages and user interfaces can cause confusion and may tempt developers to restrict choices to tailor the experience for users. Unfortunately, with the rapid development of passkeys and seemingly constant change to the user interface offered by platforms and browsers, providing tailored experiences can be very demanding for developers and are likely to be undercut by future changes to platforms and browsers. To help address this, Yubico’s Passkey Workshop is continually updated to include sample strategies for providing additional guidance to end users and will continue to be updated as new developments in the passkey ecosystem unfold. 9 Best Practices 4.3 Consider how users will recover from the loss of an authenticator Because passkeys are very secure, the normal methods for creating a “backup” don’t apply. Unlike passwords or TOTP seeds, you can’t simply keep a copy of the information in a safe place. Some authenticators provide passkey recoverability by syncing them between devices or accessing them via a cloud service, but these synced passkeys are in turn vulnerable to loss of access to the cloud service that houses them. As of November 2023, no passkey providers support importing and exporting passkeys as a form of backup, although some do support sharing passkeys with other users of the same passkey provider. It’s essential for services to support the registration of multiple passkeys to ensure that users can recover their account themselves if they lose an authenticator or lose access to a passkey provider. In addition to simply allowing multiple passkeys on separate authenticators, indicating which passkeys are synced or backup eligible in the user interface will help users determine if they will be able to recover a passkey if they lose or damage a particular device. Moreover, always give end users an opportunity to label a passkey when it is created, and advise them that this label is to help them determine which authenticator or passkey provider holds the passkey (such as a description of the authenticator type, model or its appearance). Lastly, be sure to give users a way to delete individual entries, as this will enable users to remove passkeys for lost devices or even to revoke synced or shared passkeys if they so choose. Implementing device attestation may also help users understand where their passkeys are stored, as long as the authen- ticator supports attestation (more on this below). While synced passkeys will ensure self-service account recovery for most users in most situations, they are not a silver bullet, and you must plan for how you will handle account recovery for users that are unable to access their authenticators where their passkeys reside. 4.4 Decide when to use discoverable credentials Discoverable Credentials (previously known as resident credentials) allow a web browser or platform to enumerate the credentials available in an authenticator for a specific web site or domain and display them to the end user in order to make logging in easier. They are especially convenient for logon flows where the user doesn’t even need to enter their username, as it can be determined from the discoverable credential itself. While the official FIDO2 definition of a passkey is a “discoverable FIDO2 credential”, in practice, discoverability hasn’t been a strict requirement in most passkey implementations. For instance, both Google and Apple support saving a non-discoverable FIDO2 credential in their respective passkey ecosystems. Discoverable credentials have two main drawbacks. The first is privacy related, and the second is related to hardware FIDO2 authenticators with limited discoverable credential storage. These drawbacks may make discoverable creden- tials undesirable for certain services. Additionally, discoverable credentials, as the name implies, can be enumerated by the web browser or operating system if an attacker can unlock the associated authenticator. Conversely, non-discoverable credentials don’t leave any record behind if they’re stored on a FIDO2 security key, even if the authenticator can be unlocked. While this may not be a consideration for most users, for some users with increased privacy requirements, this may mean the difference between being able to use a web service safely or not. Another important aspect to note is that hardware authenticators have limited discoverable credential storage. For example, if a user is attempting to use a YubiKey 5, they will have only a maximum of 25 credentials that can be made discoverable. While it’s unlikely for the average user to hit this limit, it is still possible that users may have filled up all of the discoverable credential slots on their authenticator. Users may have a privacy or technical need for a non-discoverable credential, therefore it is important to always provide a way for the user to initiate a login via username, and perform registrations with discoverable credentials set topreferred. This will allow a graceful fallback for authenticators that have already exhausted their discoverable credential storage. 10Chapter 4. Passkey Best Practices for Service Providers Best Practices Services that handle potentially sensitive informationshouldoptionally provide a method for specifically requesting a non-discoverable credential, to accommodate users with elevated privacy needs. For an example of how to handle both discoverable and non-discoverable credentials, see the Yubico Passkey Workshop. 4.5 Decide when to request attestation Attestation is the only way to achieve high confidence that a given credential is device-bound, and the only way to reliably determine the type of passkey being used. Services that want to be able to provide better information to users about the passkeys that are being used, or need to be able to use information about the passkey to make risk-based decisions about passkey use, should request attestation information during registration. Only device-bound passkeys can provide meaningful attestation, and users always have the option of declining to supply the attestation information. Detailed guidance on implementing attestation is provided in more detail in the Yubico Passkey Workshop’s section on attestation. 4.6 Consider approaches for detecting passkey support in the browser or platform Websites may want to attempt to detect whether or not a browser or platform can use passkeys before showing specific user interface elements, or altering the logon flow for users depending on the level of passkey support. While support for passkeys in general can be inferred from support for WebAuthn, there are no simple, reliable ways to determine whether browsers or platforms can support a specific type of authenticator, or support specific capabilities, like user verification or discoverable credentials. The following code snippet can be used to detect WebAuthn support in the browser, but it does not indicate that user verification, discoverable credentials, or any specific type of authenticator is available. navigator.credentials && navigator.credentials.create && navigator.credentials.get && window.PublicKeyCredential TheisUserVerifyingPlatformAuthenticatorAvailable()static method of thePublicKeyCredentialinter- face is unfortunately only occasionally helpful in determining if a browser has access to a platform authenticator, and it behaves differently on Windows and MacOS. User agent fingerprinting may also be used to determine what sort of browser-based support is available, but it may not reliably indicate platform support. User agents can also be set by the browser, limiting the usefulness of user agent strings for determining passkey support. The best practice for determining whether a platform supports passkeys is to first check whether it supports WebAuthn credentials via the code snippet above, and if it does, give the user an option to register a credential. Once you know for sure (through use) that a specific device supports passkeys, consider setting a cookie so that you don’tneedto do any detection on the next visit. 4.5. Decide when to request attestation11 Best Practices 4.7 Be cautious about requiring optional WebAuthn features Sometimes, the behavior that an authenticator will exhibit changes based on how it’s configured or due to a configuration change on a browser or platform. Maybe an authenticator has run out of storage, or a user hasn’t configured a PIN. It’s important to understand that the arguments passed to the WebAuthn API’s don’t always mean a credential will be created or asserted with those settings - they mean a platform willtryto perform an action on an authenticator with those settings. The only way to determine how a credential has been created or used is to evaluate the data that is returned as part of the WebAuthn call, compare that with your requirements, and inform the end user of the implications of the way their authenticator has processed the WebAuthn request. For examples, seeConsider how users will recover from the loss of an authenticatorandDecide when to use discoverable credentials 12Chapter 4. Passkey Best Practices for Service Providers CHAPTER FIVE AUTHENTICATOR ENFORCEMENT BEST PRACTICES FOR IDENTITY PROVIDERS 5.1 Intended audience This documentation is intended for identity providers and organizations who would like to limit authenticator selection for self-service FIDO authenticator enrollment within a bring-your-own authenticator model. Service providers likely won’t have any control over which authenticator a user prefers, but identity providers that facil- itate access to a specific organization will likely need to accommodate organization preferences or hard requirements for specific authenticator models. This document will outline the steps that identity providers can take to allow customers to limit end user authenticator choice while still providing the flexibility required to support custom authenticators, preview devices, technology pilots, and vulnerability remediation. 5.2 Overview Organizations may wish to limit FIDO authenticator use to specific makes and models to meet their security and compliance requirements. The FIDO specification supports this through a mechanism called attestation, which uses manufacturer-supplied data, aggregated in the FIDO Alliance’s Metadata Service (MDS) 1 , to verify cryptographic signatures during authenticator registration. Identity Providers use an authenticator’sAAGUIDto identify which public keys from the MDS can validate attestation signatures. IdPs may also use the MDS to retrieve additional information, such as supported features, FIDO Alliance 2 or third-party certifications. For a conceptual overview of how attestation and the FIDO Metadata Service work together, seeAttestation and Au- thenticator Metadata 1 FIDO Metadata Overview https://fidoalliance.org/metadata/ 2 FIDO Certification Levels https://fidoalliance.org/certification/authenticator-certification-levels/ 13 Best Practices 5.3 MDS Management TheMDSis a large document Page 13, 1 , making it unsuitable for real-time validation during every new user registration. Instead, the FIDO Alliance recommends that IdPs download and ingest updated MDS blobs at least once per month 3 . This ensures access to the latest device information, certifications, and security features. However, the MDS is not com- prehensive. Even certified authenticators are not required to be listed. This omission may reflect privacy preferences of manufacturers or customers, particularly when devices are customized. 5.4 Customer-centric enforcement 5.4.1 Do not override customer authenticator selection While it is appropriate to offer default minimum requirements for authenticator selection, customers must always have the final say in which authenticators are approved for use in their environment. IdPs should avoid rigidly enforcing any default minimum requirements they impose. Rigidly enforcing default minimum authenticator requirements may: •Prevent customers from testing emerging features or newly developed devices. •Delay deployment of devices needed to address vulnerabilities. Instead, IdPs should warn customers when their selected authenticators do not meet default criteria, but still allow their use. This provides flexibility for organizations to align device selection with their threat models and risk tolerances. 5.4.2 Allow custom metadata Because the MDS does not include every authenticator model, IdPs must support customers’ ability to add manufacturer-provided metadata to allow enforcement for such devices. At a minimum, this includes: •The device’s AAGUID •A list of valid trust anchors for attestation Note:An authenticator’s absence from the MDS does not imply insecurity. Privacy is often the primary reason for non-listing. Examples of custom metadata needs include: •Custom AAGUIDs: Large organizations may request custom identifiers from manufacturers without disclosing this publicly. •Co-development projects: Devices under joint development may be used internally before public release or cer- tification. Because custom metadata is sensitive, IdPs must maintain robust audit logs for its addition or removal and notify customers of any conflicts between custom and official MDS entries. 3 “How often should I be fetching MDS3 blob?” at https://fidoalliance.org/metadata/ 14Chapter 5. Authenticator Enforcement Best Practices for Identity Providers Best Practices 5.5 Use cases New AAGUIDs are issued when an authenticator’s functionality or metadata changes 5 . These identifiers enable fine- grained control during enforcement, even for devices that are uncertified. Organizations may encounter legitimate use cases more frequently now that FIDO adoption has accelerated than they ever have before. This section groups related use cases into two broad classes: devices which are not certified but are listed in the MDS and devices which are not listed in the MDS but may or may not be certified. 5.5.1 Non-certified devices with MDS metadata These are authenticators for which manufacturers have published metadata in the MDS but have not yet completed certification. Examples include: •Preview units sent for evaluation •Production devices released before certification Preview devices may never be certified due to cost or timing constraints. While production models are usually certified eventually, this is not guaranteed. Organizations may also supply their own metadata to support these devices, but they should weigh the added risk from using non-FIDO-managed data. 5.5.1.1 Authenticator verification and testing Customers may wish to evaluate uncertified authenticators for: •Compatibility testing •Assessment of emerging technologies •Feature development with vendors Allowing AAGUIDs to be added for testing purposes reduces operational friction. It enables testing without requiring the deactivation of attestation enforcement, thus maintaining security boundaries. 5.5.1.2 Vulnerability remediation Vendors may assign new AAGUIDs to firmware versions that fix vulnerabilities. These updates may precede certifica- tion. If the threat from the vulnerability is greater than the risk of uncertified usage, temporarily allowing non-certified AAGUIDs can mitigate risk. Once certified, no configuration changes are needed. 5.5.2 Customer-provided metadata 5.5.2.1 Custom authenticators Some organizations use devices that are not listed in the MDS. This may be due to privacy concerns or specialized requirements. Customers should have the ability to: •Add specific AAGUIDs •Provide custom metadata While these devices carry added risk, customers are responsible for evaluating and accepting that risk. 5 Yubico Support “Best practices for managing AAGUID changes” https://support.yubico.com/hc/en-us/articles/ 17779217014812-Best-practices-for-managing-AAGUID-changes 5.5. Use cases15 Best Practices 5.5.2.2 Certified devices not listed in MDS Some certified devices are intentionally excluded from the MDS. IdPs should support enforcement for such devices by allowing customers to manage metadata manually. 5.6 Considerations for authenticator selection 5.6.1 Security vetting and assessment Non-certified authenticators Organizations should evaluate uncertified devices using internal testing, documentation reviews, and compensating controls. Review the FIDO Alliance’s Level 1 certification requirements to establish baseline expectations. Custom metadata Custom metadata introduces potential security gaps. Most metadata elements (such as supported algorithms) can be validated using the FIDO GetInfo command via tools like libfido2 4 . However, attestation root certificates must be independently validated. Errors can result in failed authentications or vulnerability to spoofed devices. Allowing customers to validate that the selected attestation root certificate(s) are valid for the AAGUID in the custom metadata can be achieved by evaluating an attestation statement. Non-attestable AAGUIDs AAGUIDs that lack associated root certificates cannot be attested. In such cases, malicious actors could potentially spoof device identities. Mitigate this risk with compensating controls. Implementing compensating controls When using uncertified or non-attestable authenticators, apply additional safeguards such as: •Behavioral analytics •Risk-based authentication •IdP-specific usage policies 5.6.2 Additional considerations •Establish a robust firmware vulnerability disclosure process •Regularly review custom metadata for continued relevance •Deprecate or remove custom AAGUIDs once they appear in the MDS with appropriate certifications •Validate AAGUID entries periodically •Prepare migration plans for deprecating unauthorized devices •Monitor for shifting security standards or new threats 4 Yubico libfido2 on Github https://github.com/Yubico/libfido2/ 16Chapter 5. Authenticator Enforcement Best Practices for Identity Providers Best Practices 5.7 IdP implementation recommendations 5.7.1 Lifecycle and MDS updates To ensure continued enforcement and alignment with FIDO guidance, IdPs should: •Download and cache the FIDO MDS blob at least monthly, as per FIDO Alliance recommendations Page 13, 1 –Consider downloading and processing the FIDO MDS blob more frequently, to support the rapidly evolving FIDO authenticator ecosystem. –Display the current MDS version in use and the time/date of the last update •Define clear rules for metadata precedence (MDS vs. custom) –Alert customers to conflicts between metadata provided by the MDS and by custom entries –Indicate the metadata source (MDS or custom) in user interface when displaying metadata. •Support root certificate uploads for custom AAGUIDs –Warn administrators of the risks associated with using AAGUIDs missing attestation root certificate infor- mation –Detect and warn administrators of custom AAGUIDs with malformed or un-parsable attestation root cer- tificate information 5.7.2 Logging and API access Managing AAGUIDs and certificates is prone to human error. IdPs should support secure workflows by implementing: 1. Read-only API •Provide authenticated access to AAGUID and metadata listings •Support certificate validation through the API 2. Writable API •Enable automated metadata updates via secure, authenticated endpoints •Accommodate regulatory and procurement workflows 3. Change logging •Record all metadata changes in detail •Use SIEM-compatible formats for logs 5.7.3 Known incompatible devices Some IdPs, such as Entra, require device support for specific features like hmac-secret. Metadata overrides might allow unsupported devices unless properly restricted. IdPs should: •Display UI indicators for known incompatible devices •Prevent customers from uploading unsupported device metadata 5.7. IdP implementation recommendations17 Best Practices 18Chapter 5. Authenticator Enforcement Best Practices for Identity Providers CHAPTER SIX GLOSSARY AAGUID An Authenticator Attestation Global Unique Identifier (AAGUID) is a 128-bit identifier representing make and model for a group of FIDO2 authenticators that share the sameauthenticator metadata. The AAGUID allows a service provider to determine which attestation root certificate chain to treat as trusted for a specific attestation statement, without revealing information that can be used to track an individual authenticator. AAGUIDs are typically written out as a 32-character hexadecimal string, sometimes with dashes after the 8th, 12th, 16th and 20th digits. For example, the AAGUID for the YubiKey 5 NFC is d7781e5d-e353-46aa-afe2-3ca49f13332a. Authenticator Metadata Authenticator metadata is information about authenticator which helps relying parties or identity providers sup- port authenticators with different capabilities, manufactured by different vendors. This information includes the AAGUID, a certificate chain that can be used to validate attestation statements, and information about how the authenticator can be connected (USB, NFC or Bluetooth) as well as what extensions are supported. MDS FIDO Metadata Service (MDS) is a service provided by the FIDO Alliance that defines a uniform, vendor- agnostic method for looking up FIDOauthenticator metadataby itsAAGUID. Additional information about the FIDO Metadata Service can be found at the FIDO Alliance: https://fidoalliance.org/metadata/ 19 Best Practices 20Chapter 6. Glossary CHAPTER SEVEN COPYRIGHT ©2024-2025 Yubico AB. All rights reserved. 7.1 Trademarks Yubico and YubiKey are registered trademarks of Yubico AB. All other trademarks are the property of their respective owners. 7.2 Disclaimer The contents of this document are subject to revision without notice due to continued progress in methodology, design, and manufacturing. Yubico shall have no liability for any error or damages of any kind resulting from the use of this document. Yubico Software referenced in this document is licensed to you under the terms and conditions accompanying the software or as otherwise agreed between you or the company that you are representing. 7.3 Contact Information Yubico AB Gävlegatan 22 113 30 Stockholm Sweden More options for getting touch with us are available on the Contact page of Yubico’s website. 21 Best Practices 7.4 Document Updated 2025-06-23 15:07:10 UTC 22Chapter 7. Copyright INDEX A AAGUID,19 Authenticator Metadata,19 M MDS,19 23 --- # OTP application concepts ##### Table of Contents OTP application concepts ======================== The goal of this section is to cover the critical properties of the OTP application that apply to most or all of the [configurations](https://docs.yubico.com/yesdk/users-manual/application-otp/configuration-concepts-overview.html) . These properties include the following: * [Slots](https://docs.yubico.com/yesdk/users-manual/application-otp/slots.html) Slots are the foundation of the OTP application; each slot can be programmed with one configuration. This article covers slot properties and activation with each configuration type. * [YubiKey-host communication](https://docs.yubico.com/yesdk/users-manual/application-otp/hid.html) Let's say you have programmed a slot with a Yubico OTP configuration. When you activate that slot, the key generates an OTP. But how is that OTP communicated to a host device during authentication? This article covers the HID protocol, which the YubiKey uses when connected to a host over USB or Lightning, as well as the NDEF protocol, which the YubiKey uses to communicate wirelessley over NFC. * [ModHex (modified hexadecimal encoding)](https://docs.yubico.com/yesdk/users-manual/application-otp/modhex.html) When a Yubico OTP or OATH HOTP is generated, the encrypted passcode is a byte string, but when these passwords are sent to a host, they appear as a character string on screen. ModHex is an encoding scheme developed by Yubico to translate the raw bits of OTPs/HOTPs into ASCII/UTF characters in a manner that ensures correct communication and interpretation, regardless of the communication protocol used by the YubiKey or the host's keyboard language configuration. This article covers what's included in the ModHex character set, how it works, and why it's important, as well as how ModHex can be used when configuring static passwords. [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-otp/application-concepts-overview.md/#L1) --- # Update scan-code map ##### Table of Contents Update scan-code map ==================== Updates the scan-codes (or keyboard presses) that the YubiKey will use when typing out one-time passwords. Available --------- YubiKey firmware 3.0 and later. Command APDU info ----------------- | CLA | INS | P1 | P2 | Lc | Data | | --- | --- | --- | --- | --- | --- | | 0x00 | 0x01 | 0x12 | 0x00 | 0x2D | (see below) | The data field is a simple 45-byte array that holds keyboard scan-codes for use during OTP keyboard operations. The default set of characters is: > "cbdefghijklnrtuvCBDEFGHIJKLNRTUV0123456789!\\t\\r" This is represented by the following array of bytes: 0x06, 0x05, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, // c-i 0x0d, 0x0e, 0x0f, 0x11, 0x15, 0x17, 0x18, 0x19, // j-v 0x86, 0x85, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, // C-I 0x8d, 0x8e, 0x8f, 0x91, 0x95, 0x97, 0x98, 0x99, // J-V 0x27, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, // 0-7 0x25, 0x26, // 8-9 0x9e, 0x2b, 0x28 // !, \t, \r Response APDU info ------------------ | Lr | Data | SW1 | SW1 | | --- | --- | --- | --- | | 0x06 | [Status structure](https://docs.yubico.com/yesdk/users-manual/application-otp/otp-commands.html#status-structure) | 0x90 | 0x00 | Examples -------- Reprogram the YubiKey with the default scan-code map: $ opensc-tool.exe -c default -r 1 -s 00:a4:04:00:08:a0:00:00:05:27:20:01:01 -s 00:01:12:00:2D:06:05:07:08:09:0A:0 B:0C:0D:0E:0F:11:15:17:18:19:86:85:87:88:89:8A:8B:8C:8D:8E:8F:91:95:97:98:99:27:1E:1F:20:21:22:23:24:25:26:9E:2B:28 Sending: 00 A4 04 00 08 A0 00 00 05 27 20 01 01 Received (SW1=0x90, SW2=0x00): 05 03 01 03 05 00 ...... Sending: 00 01 12 00 2D 06 05 07 08 09 0A 0B 0C 0D 0E 0F 11 15 17 18 19 86 85 87 88 89 8A 8B 8C 8D 8E 8F 91 95 97 98 99 27 1E 1F 20 21 22 23 24 25 26 9E 2B 28 Received (SW1=0x90, SW2=0x00): 05 03 01 04 05 00 ...... [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-otp/commands-update-scan-code-map.md/#L1) --- # Get serial number ##### Table of Contents Get serial number ================= Reads the serial number of the YubiKey if it is allowed by the configuration. Note that certain keys, such as the Security Key by Yubico, do not have serial numbers. Available --------- YubiKey firmware 1.2 and later. Command APDU info ----------------- | CLA | INS | P1 | P2 | Lc | Data | | --- | --- | --- | --- | --- | --- | | 0x00 | 0x01 | 0x10 | 0x00 | (absent) | (absent) | Response APDU info ------------------ | Lr | Data | SW1 | SW1 | | --- | --- | --- | --- | | 0x04 | Serial Number | 0x90 | 0x00 | Examples -------- $ opensc-tool.exe -c default -r 1 -s 00:a4:04:00:08:a0:00:00:05:27:20:01:01 -s 00:01:10:00 Sending: 00 A4 04 00 08 A0 00 00 05 27 20 01 01 Received (SW1=0x90, SW2=0x00): 04 03 07 03 07 00 06 0F 00 00 .......... Sending: 00 01 10 00 Received (SW1=0x90, SW2=0x00): 00 6B 95 6A .k.j // Serial Number: 7050602 [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-otp/commands-get-serial.md/#L1) --- # Get device information ##### Table of Contents Get device information ====================== Reads configuration and metadata information about the YubiKey. Similar commands exist in other applications. The Command APDU may be different, however the data in the Response APDU will be of identical format. Available --------- YubiKey firmware 4.1 and later. Command APDU info ----------------- | CLA | INS | P1 | P2 | Lc | Data | | --- | --- | --- | --- | --- | --- | | 0x00 | 0x01 | 0x13 | 0x00 | (absent) | (absent) | Response APDU info ------------------ | Lr | Data | SW1 | SW2 | | --- | --- | --- | --- | | (Varies) | (See Below) | 0x90 | 0x00 | The device information is encoded in Tag-Length-Value (TLV) format. The following table describes the possible entries (tags). | Name | Value | Description | | --- | --- | --- | | Available capabilities (USB) | 0x01 | USB Applications and capabilities that are available for use on this YubiKey. | | Serial number | 0x02 | Returns the serial number of the YubiKey (if present and visible). | | Enabled capabilities (USB) | 0x03 | Applications that are currently enabled over USB on this YubiKey. | | Form factor | 0x04 | Specifies the form factor of the YubiKey (USB-A, USB-C, Nano, etc.) | | Firmware version | 0x05 | The Major.Minor.Patch version number of the firmware running on the YubiKey. | | Auto-eject timeout | 0x06 | Timeout in (ms?) before the YubiKey automatically "ejects" itself. | | Challenge-response timeout | 0x07 | The period of time (in seconds) after which the OTP challenge-response command should timeout. | | Device flags | 0x08 | Device flags that can control device-global behavior. | | Configuration lock | 0x0A | Indicates whether or not the YubiKey's configuration has been locked by the user. | | Available capabilities (NFC) | 0x0D | NFC Applications and capabilities that are available for use on this YubiKey. | | Enabled capabilities (NFC) | 0x0E | Applications that are currently enabled over USB on this YubiKey. | Examples -------- YubiKey 4.3.7 $ opensc-tool.exe -c default -r 1 -s 00:a4:04:00:08:a0:00:00:05:27:20:01:01 -s 00:01:13:00 Sending: 00 A4 04 00 08 A0 00 00 05 27 20 01 01 Received (SW1=0x90, SW2=0x00): 04 03 07 03 07 00 06 0F 00 00 .......... Sending: 00 01 13 00 Received (SW1=0x90, SW2=0x00): 0C 01 01 FF 02 04 00 6B 95 6A 03 01 3F .......k.j..? 0C // Overall bytes 01 01 FF // Available capabilities (USB), length = 1, All capabilities available 02 04 00 6B 95 6A // Serial number, length = 4, value = 7060602 03 01 3F // Enabled capabilities (USB), length = 1, All capabilities enabled YubiKey 5.2.3 $ opensc-tool.exe -c default -r 0 -s 00:a4:04:00:08:a0:00:00:05:27:20:01:01 -s 00:01:13:00 Sending: 00 A4 04 00 08 A0 00 00 05 27 20 01 01 Received (SW1=0x90, SW2=0x00): AF 5C 62 50 C3 A8 .\bP.. Sending: 00 01 13 00 Received (SW1=0x90, SW2=0x00): 2E 01 02 02 3F 03 02 00 3C 02 04 00 A8 57 9B 04 ....?...<....W.. 01 01 05 03 05 02 03 06 02 00 0A 07 01 0F 08 01 ................ 80 0D 02 02 3F 0E 02 02 3B 0A 01 00 0F 01 00 ....?...;...... 2B // Overall bytes 01 02 02 3F // Available capabilities (USB), length = 2, All capabilities 03 02 00 3C // Enabled capabilities (USB), length = 2, U2F and CCID unused 02 04 00 AB 57 9B // Serial number, length = 4, value = 11229083 04 01 01 // Form factor, length = 1, 5A Keychain 05 03 05 02 03 // Firmware version, length = 3, value = 5.2.3 06 02 00 0A // Auto eject timeout, length = 2, value = 40,960 07 01 0F // Challenge response timeout, length = 1, value = 15 08 01 80 // Device flags, length = 1, Touch eject enabled 0D 02 02 3F // Available capabilities (NFC), length = 2 0E 02 02 3B // Enabled capabilities (NFC), length = 2 0A 01 00 // Configuration log, length = 1, Unlocked [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-otp/commands-get-device-info.md/#L1) --- # How to read NDEF information ##### Table of Contents How to read NDEF information ============================ In [How to configure NDEF to use a slot to generate an OTP](https://docs.yubico.com/yesdk/users-manual/application-otp/how-to-configure-ndef.html) , we discussed how to configure [NDEF](https://docs.yubico.com/yesdk/users-manual/application-otp/ndef.html) functionality with OTP application [slots](https://docs.yubico.com/yesdk/users-manual/application-otp/slots.html) . Reading NDEF information from the YubiKey requires more thought. In its initial version, the SDK does not support device notifications. This means you can’t set code to be run automatically when the YubiKey is presented to an NFC reader; you must present the YubiKey to the NFC reader and _then_ execute the [ReadNdefTag()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.OtpSession.html#Yubico_YubiKey_Otp_OtpSession_ReadNdefTag) command. It is possible to simulate “tap and go” functionality by polling reads. However, this presents some reliability challenges. Currently, the most reliable way to read the NDEF tag is to prompt the user to touch the NFC reader with the YubiKey and then run the command while they are in contact. ReadNdefTag example ------------------- The following sample code reads the configuration set in the previous [article](https://docs.yubico.com/yesdk/users-manual/application-otp/how-to-configure-ndef.html) : using (OtpSession otp = new OtpSession(yKey)) { NdefDataReader reader = otp.ReadNdefTag(); object output = reader.Type == NdefDataType.Uri ? reader.ToUri() : reader.ToText(); Console.WriteLine($"NDEF Output: [{output}]"); } When executed against the factory NDEF configuration of a YubiKey, the output will look similar to the following: `NDEF Output: [https://my.yubico.com/yk/#cccccctcvhvdhuvhvhubcjgucrticnhichbgcnguevgf]` [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-otp/how-to-read-ndef-information.md/#L1) --- # How to delete a slot's configuration ##### Table of Contents How to delete a slot's configuration ==================================== Deleting a [slot's](https://docs.yubico.com/yesdk/users-manual/application-otp/slots.html) configuration removes all credentials, associated counters (if any), slot settings, etc. To delete a slot's configuration, you must use one of two methods: * [DeleteSlot()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.OtpSession.html#Yubico_YubiKey_Otp_OtpSession_DeleteSlot_Yubico_YubiKey_Otp_Slot_) : for slots that are not configured with an access code. * [DeleteSlotConfiguration()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.OtpSession.html#Yubico_YubiKey_Otp_OtpSession_DeleteSlotConfiguration_Yubico_YubiKey_Otp_Slot_) : for slots that are configured with an access code. ##### Note These methods will fail if the slot you are attempting to delete is not configured. Examples -------- Before running any of the code provided below, make sure you have already connected to a particular YubiKey on your host device via the [YubiKeyDevice](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.YubiKeyDevice.html) class. To select the first available YubiKey connected to your host, use: IEnumerable yubiKeyList = YubiKeyDevice.FindAll(); var yubiKey = yubiKeyList.First(); ### Deleting a slot configuration when an access code is not present To delete a slot configuration that is not protected with an access code, use [DeleteSlot()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.OtpSession.html#Yubico_YubiKey_Otp_OtpSession_DeleteSlot_Yubico_YubiKey_Otp_Slot_) . You cannot chain other methods to `DeleteSlot()`, including `Execute()`. When calling `DeleteSlot()`, just provide the slot field (in this example, `Slot.LongPress`). using (OtpSession otp = new OtpSession(yubiKey)) { otp.DeleteSlot(Slot.LongPress); } ### Deleting a slot configuration when an access code is present To delete a slot configuration that is protected with an access code, you must call [DeleteSlotConfiguration](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.OtpSession.html#Yubico_YubiKey_Otp_OtpSession_DeleteSlotConfiguration_Yubico_YubiKey_Otp_Slot_) and provide the current access code with [UseCurrentAccessCode()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.OperationBase-1.html#Yubico_YubiKey_Otp_Operations_OperationBase_1_UseCurrentAccessCode_Yubico_YubiKey_Otp_SlotAccessCode_) . You cannot set a new access code during this operation--calling [SetNewAccessCode()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.OperationBase-1.html#Yubico_YubiKey_Otp_Operations_OperationBase_1_SetNewAccessCode_Yubico_YubiKey_Otp_SlotAccessCode_) will succeed, but the operation will not be applied. Unlike `DeleteSlot()`, `DeleteSlotConfiguration()` requires `Execute()` for the operation to apply the changes. using (OtpSession otp = new OtpSession(yubiKey)) { ReadOnlyMemory currentAccessCodeBytes = new byte[SlotAccessCode.MaxAccessCodeLength] { 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, }; SlotAccessCode currentAccessCode = new SlotAccessCode(currentAccessCodeBytes); otp.DeleteSlotConfiguration(Slot.LongPress) .UseCurrentAccessCode(currentAccessCode) .Execute(); } [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-otp/how-to-delete-a-slot-configuration.md/#L1) --- # Challenge-response ##### Table of Contents Challenge-response ================== Perform a challenge-response style operation using either YubicoOTP or HMAC-SHA1 against a configured YubiKey slot. Available --------- YubiKey firmware 2.2 and later. Command APDU info ----------------- | CLA | INS | P1 | P2 | Lc | Data | | --- | --- | --- | --- | --- | --- | | 0x00 | 0x01 | (See below) | 0x00 | (varies) | Challenge data | ### P1: Slot P1 indicates both the type of challenge-response algorithm and the slot in which to use. | Option | Value | | --- | --- | | YubicoOTP (Short) | 0x20 | | YubicoOTP (Long) | 0x28 | | HMAC-SHA1 (Short) | 0x30 | | HMAC-SHA1 (Long) | 0x38 | ### Data: Challenge A string of bytes no greater than 64-bytes in length. Response APDU info ------------------ | Lr | Data | SW1 | SW1 | | --- | --- | --- | --- | | 0x10 or 0x14 | Response data | 0x90 | 0x00 | If the YubicoOTP algorithm was used, a 16-byte response will be given. HMAC-SHA1 will return a 20-byte response. Examples -------- TODO [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-otp/commands-challenge-response.md/#L1) --- # Query FIPs mode ##### Table of Contents Query FIPs mode =============== Determines whether or not the device is loaded with FIPS capable firmware, as well as if the key is currently in a FIPS compliant state. Available --------- YubiKey firmware 4.4.x. Command APDU info ----------------- | CLA | INS | P1 | P2 | Lc | Data | | --- | --- | --- | --- | --- | --- | | 0x00 | 0x01 | 0x14 | 0x00 | (absent) | (absent) | Response APDU info ------------------ If a FIPS key: | Lr | Data | SW1 | SW2 | | --- | --- | --- | --- | | 0x01 | 0 = not FIPS compliant, 1 = FIPS compliant | 0x90 | 0x00 | Just because a key may be branded FIPS or have FIPS capable firmware loaded, does not mean that the YubiKey is FIPS compliant. Configurations on the key need to be locked or otherwise protected in order to claim compliant behavior. If not a FIPS key: | Lr | Data | SW1 | SW2 | | --- | --- | --- | --- | | (absent) | (absent) | 0x6B | 0x00 | 0x6B00 is "SW\_WRONG\_P1P2", which in this context simply means that the query command is not present. This behavior can be assumed to mean that the key does not support FIPS mode, and that it does not have FIPS capable firmware. Examples -------- YubiKey 5.2.4 (via NFC) $ opensc-tool.exe -c default -r 0 -s 00:a4:04:00:08:a0:00:00:05:27:20:01:01 -s 00:01:14:00 Sending: 00 A4 04 00 08 A0 00 00 05 27 20 01 01 Received (SW1=0x90, SW2=0x00): A0 A2 7B 13 F8 80 ..{... Sending: 00 01 14 00 Received (SW1=0x6B, SW2=0x00) YubiKey FIPS 4.4.5 $ opensc-tool.exe -c default -r 1 -s 00:a4:04:00:08:a0:00:00:05:27:20:01:01 -s 00:01:14:00 Sending: 00 A4 04 00 08 A0 00 00 05 27 20 01 01 Received (SW1=0x90, SW2=0x00): 04 04 05 01 05 00 06 0F 00 00 .......... Sending: 00 01 14 00 Received (SW1=0x90, SW2=0x00): 00 . [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-otp/commands-query-fips-mode.md/#L1) --- # Read status ##### Table of Contents Read status =========== Read the YubiKey's OTP status structure. Available --------- YubiKey firmware 3.x and later Command APDU info ----------------- | CLA | INS | P1 | P2 | Lc | Data | | --- | --- | --- | --- | --- | --- | | 0x00 | 0x03 | 0x00 | 0x00 | (absent) | (absent) | Response APDU info ------------------ | Lr | Data | SW1 | SW1 | | --- | --- | --- | --- | | 0x06 | [Status structure](https://docs.yubico.com/yesdk/users-manual/application-otp/otp-commands.html#status-structure) | 0x90 | 0x00 | Examples -------- $ opensc-tool.exe -c default -r 0 -s 00:a4:04:00:08:a0:00:00:05:27:20:01:01 -s 00:03:00:00 Sending: 00 A4 04 00 08 A0 00 00 05 27 20 01 01 Received (SW1=0x90, SW2=0x00): 04 03 07 03 07 00 06 0F 00 00 .......... Sending: 00 03 00 00 Received (SW1=0x90, SW2=0x00): 04 03 07 03 07 00 ...... [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-otp/commands-read-status.md/#L1) --- # Read NDEF payload (NFC only) ##### Table of Contents Read NDEF payload (NFC only) ============================ Accessing NDEF requires selecting the NDEF application over NFC. Though conceptually still part of the OTP application, NDEF has its own application ID and is processed separately. NDEF AID: `0xD2, 0x76, 0x00, 0x00, 0x85, 0x01, 0x01` Available --------- YubiKey firmware 3.x and 5.x Command APDU info ----------------- | Command Sequence | CLA | INS | P1 | P2 | Lc | Data | Le | | --- | --- | --- | --- | --- | --- | --- | --- | | 1 (Select File) | 0x00 | 0xA4 | 0x00 | 0x0C | 0x02 | 0xE1 0x04 | (absent) | | 2 (Read Data) | 0x00 | 0xB0 | 0x00 | 0x00 | (absent) | (absent) | 0x00 | Response APDU info ------------------ Only the "Read Data" APDU returns data: | Lr | Data | SW1 | SW2 | | --- | --- | --- | --- | | (varies) | (see below) | 0x90 | 0x00 | The response data is an NFC Data Exchange Format (NDEF) record as defined by the NFC Forum's technical specification of the same name. It is as follows: | Field | Size | Description | | --- | --- | --- | | Tag | 1 | Always `0` | | Length | 1 | Length of the NDEF record | | NDEF Header | 1 | Always `0xD1`: Message Begin+End, Short Record, Type Name Format = NFC Forum well known | | Length of record type | 1 | Always `1` | | Payload Length | 1 | | | Type | 1 | NFC Forum global type "U" | | Payload | (varies) | The actual NDEF message. Of length "payload length" bytes. | Examples -------- $ opensc-tool.exe -c default -r 0 -s 00:A4:04:00:07:D2:76:00:00:85:01:01 -s 00:A4:00:0C:02:E1:04 -s 00:B0:00:00:00 Sending: 00 A4 04 00 07 D2 76 00 00 85 01 01 Received (SW1=0x90, SW2=0x00) Sending: 00 A4 00 0C 02 E1 04 Received (SW1=0x90, SW2=0x00) Sending: 00 B0 00 00 00 Received (SW1=0x90, SW2=0x00): 00 43 D1 01 3F 55 04 6D 79 2E 79 75 62 69 63 6F .C..?U.my.yubico 2E 63 6F 6D 2F 79 6B 2F 23 63 63 63 63 63 63 6E .com/yk/#ccccccn 65 75 68 74 66 64 6E 76 6C 75 6E 68 6C 67 66 72 euhtfdnvlunhlgfr 6A 62 6E 65 65 62 76 6E 67 64 67 6C 6C 67 76 64 jbneebvngdgllgvd 64 65 72 65 62 dereb [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-otp/commands-read-ndef.md/#L1) --- # How to back up credentials ##### Table of Contents How to back up credentials ========================== Secrets on a YubiKey are, by design, write-only objects. This means that the shared secrets stored in the YubiKey can only be written into, and not read out, of the device. If a credential is to be copied, it must be known beforehand and either written down or copied before programming the YubiKey. It is not possible to create an exact copy of a YubiKey. It is possible to duplicate the credentials stored on the YubiKey if that credential was first generated outside of the YubiKey. When you add a credential, be sure you copy the shared secret key for that credential and store it in a safe place. The best ways to back up credentials are: * Add credentials at the same time to multiple YubiKeys if you have them. * Or save a copy of the QR code (capture the screen) or make a copy of the shared secret key and place them in secure storage until needed again. Otherwise, if you add credentials to one YubiKey and then later decide to buy another YubiKey for a backup, you must log into every account and go through the setup process again. To get a new credential for each account, delete the original credentials from the original YubiKey, and then add the new credentials to both YubiKeys. [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-oath/oath-backup-credentials.md/#L1) --- # Configuration concepts ##### Table of Contents Configuration concepts ====================== The articles in this section cover the four OTP application configurations, as well as the [NDEF (NFC Data Exchange Format) tag](https://docs.yubico.com/yesdk/users-manual/application-otp/ndef.html) : * [Yubico OTP](https://docs.yubico.com/yesdk/users-manual/application-otp/yubico-otp.html) * [Initiative for Open Authentication HMAC-based OTP (OATH HOTP)](https://docs.yubico.com/yesdk/users-manual/application-otp/hotp.html) * [Static password](https://docs.yubico.com/yesdk/users-manual/application-otp/static-password.html) * [Challenge-response (using the HMAC-SHA1 or Yubico OTP algorithms)](https://docs.yubico.com/yesdk/users-manual/application-otp/challenge-response.html) The purpose of these articles is to convey the following information: * what each configuration is and how it works * YubiKey nuances related to each configuration * an overview of the SDK functionality in each area * intended applications and limitations of each configuration These articles build on the topics discussed in the [OTP application concepts section](https://docs.yubico.com/yesdk/users-manual/application-otp/application-concepts-overview.html) . You may find it helpful to refer back to that section as you develop an understanding of the configurations. [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-otp/configuration-concepts-overview.md/#L1) --- # OATH-HOTP ##### Table of Contents OATH-HOTP ========= OATH HOTPs (Initiative for Open Authentication HMAC-based one-time passwords) are 6 or 8 digit unique passcodes that are used as the second factor during two-factor authentication. When an OTP application [slot](https://docs.yubico.com/yesdk/users-manual/application-otp/slots.html) on a YubiKey is configured for OATH HOTP, activating the slot (by touching the YubiKey while plugged into a host device over USB or scanning an NFC-enabled key with an [NFC](https://docs.yubico.com/yesdk/users-manual/application-otp/ndef.html) reader) will cause the generation of an HOTP. An HOTP looks like the following: 154916 In order to verify the authenticity of HOTPs, a validation server is needed. When an application receives an HOTP during a login attempt, it must send the HOTP to the server, which assesses whether the HOTP is valid and then reports the result to the application. The SDK provides the [functionality](https://docs.yubico.com/yesdk/users-manual/application-otp/hotp.html#sdk-functionality) to configure an OTP application slot with an HOTP and control how HOTPs are communicated from a YubiKey to a host device. You may have noticed that the YubiKey also has an [OATH application](https://docs.yubico.com/yesdk/users-manual/application-oath/oath-overview.html) , and the SDK provides the ability to configure the OATH application with both HOTPs and TOTPs (time-based OTPs). So why include OATH functionality in the OTP application if an OATH application exists? Early versions of the YubiKey (YubiKey 1 and 2) only had the OTP application. Providing SDK functionality for OATH within the OTP application is therefore a form of legacy support. **For the average SDK user, we recommend using the OATH application instead of the OTP application for any OATH functionality needs.** OATH HOTP components and algorithm ---------------------------------- OATH HOTPs are much simpler than [Yubico OTPs](https://docs.yubico.com/yesdk/users-manual/application-otp/yubico-otp.html) . To generate an HOTP, the YubiKey uses the following elements: * A counter (4 bytes) * A unique secret key (20 bytes) ##### Note At 4 bytes, the counter can be incremented up to 4,294,967,295 times (if the counter starts at 0). This means that even if you were to authenticate 1,000 times every day, it would take 11,767 years before the slot would need to be reconfigured with a new OATH HOTP credential. This is in contrast to the usage counter of Yubico OTPs, which, at 2 bytes in size, can only be incremented 65,535 times before reconfiguration is needed. The HOTP is the product of encrypting the counter with the secret key via the HOTP algorithm as described in [RFC-4226](https://www.ietf.org/rfc/rfc4226.txt) . Both the YubiKey and the validation server store copies of the counter and secret key. OATH HOTP generation and authentication with the YubiKey -------------------------------------------------------- When a slot that is configured for OATH HOTP is activated, the YubiKey’s counter is incremented by 1, and the HOTP is generated by encrypting the counter value with the secret key, both of which are stored in write-only memory on the YubiKey. To authenticate a user, the HOTP has to be sent to and verified by a validation server. This server stores copies of the configuration’s counter and unique secret key. When an HOTP is sent for verification, the server’s counter value is incremented by 1, and the validation server uses its copies of the secret key and counter to compute the HOTP using the same algorithm. If the YubiKey-generated HOTP matches the server-generated HOTP, the user is authenticated. If the HOTPs do not match, the validation server will compute additional HOTPs by incrementing the counter and encrypting it with the secret key. This counter incrementation is referred to as the “look-ahead” window. The look-ahead window is used to help keep the counters of the YubiKey and the validation server in sync. If the YubiKey generates an HOTP but does not send it to the validation server for verification, any subsequent HOTPs generated by the YubiKey will be flagged as invalid by the validation server because the counters are out of sync, and, therefore, the HOTP generated by the server will not match the YubiKey’s HOTP. The size of the look-ahead window is set by the validation server. If the counter used in the YubiKey-generated HOTP falls outside of the look-ahead window, authentication will fail, and the OATH configuration on the YubiKey will need to be reset, with the new secret key and counter shared with the validation server. OATH validation servers ----------------------- At this time, Yubico does not provide a reference architecture for a self-hosted OATH HOTP validation server. It is up to the developer to either set up a self-hosted OATH validation server or utilize a commercial product. OATH HOTP security ------------------ Unlike OATH TOTPs, which are only valid for a finite amount of time after being generated, HOTPs can be used indefinitely as long as their counter is equal to or higher than the counter stored on the validation server (and the counter is within the look-ahead window). Therefore, any HOTPs generated outside of the login process pose a security risk–a hacker could steal these credentials and use them to break into the accompanying account (until a new HOTP is generated and sent for verification). To protect against this scenario, we recommend that you provide a facility to “burn” HOTPs. Burning refers to the process of generating and submitting an HOTP for verification with the goal of simply updating the validation server's counter. Also, if your application and validation server allow it, we recommend using the 8-digit HOTP over the 6-digit HOTP. The two additional digits provide a 100-fold increase in security. ##### Note Given 10 options per digit (the numbers 0 through 9), there are 10^6 = 1,000,000 possible combinations for a 6-digit HOTP and 10^8 = 100,000,000 possible combinations for an 8-digit HOTP. SDK functionality ----------------- The SDK's OATH HOTP functionality within the OTP application is rooted in the [ConfigureHotp()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.OtpSession.html#Yubico_YubiKey_Otp_OtpSession_ConfigureHotp_Yubico_YubiKey_Otp_Slot_) method. This method allows you to configure one of the OTP application slots with an OATH HOTP. After configuration, that slot will generate an HOTP every time it is activated. With ConfigureHotp(), you have the ability to provide your own secret key and initial counter value via [UseKey()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.ConfigureHotp.html#Yubico_YubiKey_Otp_Operations_ConfigureHotp_UseKey_System_ReadOnlyMemory_System_Byte__) and [UseInitialMovingFactor()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.ConfigureHotp.html#Yubico_YubiKey_Otp_Operations_ConfigureHotp_UseInitialMovingFactor_System_Int32_) or randomly generate the key with [GenerateKey()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.ConfigureHotp.html#Yubico_YubiKey_Otp_Operations_ConfigureHotp_GenerateKey_System_Memory_System_Byte__) . ##### Note Generated credentials will need to be shared with the validation server before they are cleared from memory. There is no way to extract credentials from the YubiKey after configuration. By default, an OTP application slot configured for HOTP will generate 6-digit HOTPs. If you would like to generate 8-digit HOTPs, you must call the [Use8Digits()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.ConfigureHotp.html#Yubico_YubiKey_Otp_Operations_ConfigureHotp_Use8Digits_System_Boolean_) method. The YubiKey also allows you to control how the HOTP is sent to a host, depending on the intended use case. You can set a time delay between characters of the HOTP as they are sent to a host device with [Use10msPacing()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.ConfigureHotp.html#Yubico_YubiKey_Otp_Operations_ConfigureHotp_Use10msPacing_System_Boolean_) and [Use20msPacing()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.ConfigureHotp.html#Yubico_YubiKey_Otp_Operations_ConfigureHotp_Use20msPacing_System_Boolean_) . Similarly, you can add a 500ms delay after sending the HOTP with [AppendDelayToOtp()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.ConfigureHotp.html#Yubico_YubiKey_Otp_Operations_ConfigureHotp_AppendDelayToOtp_System_Boolean_) . You can also add additional keystrokes as needed for your intended application with [SendTabFirst()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.ConfigureHotp.html#Yubico_YubiKey_Otp_Operations_ConfigureHotp_SendTabFirst_System_Boolean_) (sends a tab before the HOTP characters) and [AppendCarriageReturn()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.ConfigureHotp.html#Yubico_YubiKey_Otp_Operations_ConfigureHotp_AppendCarriageReturn_System_Boolean_) ( sends an **Enter** key after the HOTP has been sent to a device). For a full list of the methods in the ConfigureHotp class, please see the [API documentation](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.ConfigureHotp.html) . For an example of how to use ConfigureHotp(), please see [How to program a slot with an OATH HOTP credential](https://docs.yubico.com/yesdk/users-manual/application-otp/how-to-program-an-hotp-credential.html) . [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-otp/hotp.md/#L1) --- # OATH credentials overview ##### Table of Contents OATH credentials overview ========================= An OATH credential can be a TOTP (Time-based One-time Password) or a HOTP (HMAC-based One-time Password). The credential has a set of parameters. ### Common parameters for TOTP and HOTP credentials: | Name | Description | | --- | --- | | Issuer | The issuer parameter is an optional string value indicating the provider or service this account is associated with. | | Account Name | The account name is a string that usually is the user's email address. | | Type | Indicates the type of the credential as either HOTP or TOTP. | | Algorithm | The hash algorithm used by the credential. | | Secret | The secret parameter is an arbitrary key value encoded in Base32 according to RFC 3548. | | Digits | The number of digits in a one-time password (OTP). | | Requires Touch | The credential requires the user to touch the key to generate a one-time password (OTP). | | Name | Only get property which serves as the unique identifier for the credential. | The Name is created from Period, Issue and Account Name with the following format: "period/issuer:account" If the credential is TOTP with the default period (30 seconds) or the credential's type is HOTP, then the format will be: "issuer:account" If Issuer is not specified, the format will be: "period/account" Or just an Account Name for TOTP with default period (30 seconds) or HOTP credentials: "account" ### Specific to HOTP credential: HOTP is an event based one-time password algorithm. The moving factor (event) is represented here by the counter parameter. The server and user calculate the OTP by applying a hashing and truncating operation to the secret key and the counter. The server compares the OTP it calculated against the one provided by the user. Both sides then increment the counters. The counters have to be kept in sync between the server and the user. If a user opens the authenticator app to generate an OTP but ends up not using it, the counter on the user side will become out of sync with the server. One way to handle this is a resynchronisation mechanism in which the server tries a couple of future counter values to see if it finds a matching OTP and synchronise the counter accordingly. | Name | Description | | --- | --- | | Counter | The initial counter value. The moving factor is incremented each time based on the counter. | | Period | 0 (Undefined) | Period should be ignored/undefined as this is only applicable to time-based credentials. The validity for HOTP code is set to DateTimeOffset.MaxValue because HOTP code is not time based. ### Specific to TOTP credentials: TOTP is an event based one-time password algorithm. The moving factor (event) is time-based rather than counter-based. | Name | Description | | --- | --- | | Period | The validity period in seconds for TOTP code. It can be 15, 30 or 60 seconds. | The validity for TOTP code is set to DateTimeOffset.Now + credential period (15, 30, or 60 seconds). Also, it is " rounded" to the nearest 15, 30, or 60 seconds. For example, it will start at 1:14:30 and not 1:14:34 if the timestep is 30 seconds. OTP code parameters: -------------------- | Name | Description | | --- | --- | | Value | The generated one-time password. | | Valid From | The timestamp that was used to generate code. | | Valid Until | The timestamp when the code becomes invalid. | Create credentials ------------------ There two ways of creating credentials: 1. Using a URI string. When you enable two-factor authentication on websites, they usually show you a QR code and ask you to scan and launch an authenticator app. QR codes are used in scanning secrets to generate one-time passwords. Secrets may be encoded in QR codes as a URI with the following format: otpauth://TYPE/LABEL?PARAMETERS You can create a credential from the string received from the QR reader or manually from the server. For example: A TOTP credential for user john@example.com, for use with a service provided by ACME Co, might look like the following: var credential = Credential.ParseUri( new Uri("otpauth://totp/ACME%20Co:john@example.com?secret=5JRIUNLTT3URLTR7CLZOTM4P2GFGB3RY&issuer=ACME%20Co&algorithm=SHA1&digits=6&period=30")); Read more about [URI strings](https://docs.yubico.com/yesdk/users-manual/application-oath/uri-string-format.html) . The URI specification [RFC 3986](https://datatracker.ietf.org/doc/html/rfc3986) . 2. Specifying each parameter If you are unable to capture the QR code and use a URI string, you can manually create the credential by adding the account information. The Issuer is recommended, but not required. // create TOTP credential var credential = new Credential { Issuer = "Yubico", AccountName = "test@yubico.com", Type = Totp, Period = 30, Digits = 6, Secret = "HXDMVJECJJWSRB3HWIZR4IFUGFTMXBOZ", RequireTouch = false } // create HOTP credential var credential = new Credential { Issuer = "Yubico", AccountName = "test@yubico.com", Type = Hotp, Digits = 6, Counter = 0, Secret = "HXDMVJECJJWSRB3HWIZR4IFUGFTMXBOZ", RequireTouch = false } [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-oath/oath-credentials.md/#L1) --- # Protecting the OATH application with a password ##### Table of Contents Protecting the OATH application with a password =============================================== For greater security, you can protect the OATH application on the YubiKey with a password. If a password is set, the user will first need to verify the password to unlock the application and perform OATH operations. The exception is resetting the application. The password is not required for that. Setting the password -------------------- To set a password for the OATH application on a YubiKey, you will call the `SetPassword()` method from your instance of `OathSession`. The password you use can be any string of bytes. However, most applications will choose to encode a user-supplied string using UTF-8. The `SetPassword()` method will use those bytes along with a device ID supplied by the YubiKey to apply many rounds of a key-derivation function called [PBKDF2](https://en.wikipedia.org/wiki/PBKDF2) , ensuring an extra level of security against brute-force attacks. Then, the first 16 bytes (128-bits) of the output from that operation are used as the hash value for the password. The secret then will be stored on the YubiKey. Use this method in OathSession class to set the password: oathSession.SetPassword(); Verifying the password ---------------------- Mutual authentication is performed to unlock the OATH application protected with the password. The challenge for this comes from the YubiKey. The response is computed by performing the correct HMAC function of that challenge with the secret, which is a user-supplied password and deviceID put through 1,000 rounds of PBKDF2. A new random challenge is then sent to the application, together with the calculated response. The application will then respond with a similar calculation that the host software can verify. Use this method in OathSession class to verify the password: oathSession.VerifyPassword(); Removing the authentication --------------------------- The authentication can be removed after the current password is successfully verified. Use this method in OathSession class to unset the password: oathSession.UnsetPassword(); Read more about [OathSession](https://docs.yubico.com/yesdk/users-manual/application-oath/oath-session.html) methods. Setting password in Yubico Authenticator App -------------------------------------------- Yubico Authenticator enables you to protect your YubiKey with a password. If the OATH application on the Yubikey is protected with the password, you will be prompted to type this password each time you insert the YubiKey into a USB port or connect over NFC. When using the Yubico Authenticator App with the OATH application on the YubiKey, you will configure it to use the password configured on the YubiKey. It will perform the same algorithmic processes on the password to set and verify the password. Once configured with the password, it can be configured to save the calculated secret on the device to negate the need to enter the password each time the OATH application is used. If so configured, the calculated secret will be stored in the one of the following locations: * Keychain (iOS devices) * Android Keystore (on Android devices) * In ~/.ykman/oath.json on Linux/macOS * In %UserProfile%.ykman\\oath.json (Windows) Note: The Yubico Authenticator App has the ability to protect the secret with FaceID or TouchID, which means you would be prompted to authenticate with one of those methods when using the credential. [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-oath/oath-password.md/#L1) --- # URI string format ##### Table of Contents URI string format ================= otpauth://TYPE/LABEL?PARAMETERS Scheme ------ Each URI begins with a scheme name that refers to a specification for assigning identifiers within that scheme. | The scheme name | | --- | | otpauth | This scheme name is used by Authenticator apps to generate one-time passcodes using OATH. The otpauth:// URI scheme was originally formalised by Google. Most authenticator apps register a handler for otpauth:// so the camera app knows how to prompt the user to launch the authenticator app when it’s scanned. Type ---- | Valid types | | --- | | hotp | | totp | The type is needed to distinguish whether the credential will be used for counter-based HOTP or for time-based TOTP. Read more about the difference between the two types of [OATH credentials](https://docs.yubico.com/yesdk/users-manual/application-oath/oath-credentials.html) . Label ----- The label is used to identify which account a credential is associated with. It also serves as the unique identifier for the credential itself. The label is created from: | Name | Description | | --- | --- | | Issuer | An optional string value indicating the provider or service this account is associated with. | | Account Name | A URI-encoded string that usually is the user's email address. | It is formatted as "Issuer:Account" when both parameters are present. It is formatted as "Account" when there is no Issuer. The label prevents collisions between different accounts with different providers that might be identified using the same account name, e.g. the user's email address. The issuer and account name should be separated by a literal or url-encoded colon, and optional spaces may precede the account name. Neither issuer nor account name may themselves contain a colon. According to [RFC 5234](https://www.rfc-editor.org/rfc/rfc5234.txt) a valid label might look like: Example:alice@gmail.com ACME%20Co:john.doe@email.com Parameters ---------- ### Secret The secret is provided by the website to the user in the QR code, both sides need to retain this secret key for one-time password generation. The secret parameter is an arbitrary credential value encoded in Base32 according to [RFC 3548](https://datatracker.ietf.org/doc/html/rfc3548) . The padding specified in [RFC 3548 section 2.2](https://datatracker.ietf.org/doc/html/rfc3548#section-2.2) is not required and should be omitted. There is Base32 helper class in the Yubico.Core library. ### Issuer The issuer parameter is an optional string value indicating the provider or service the credential is associated with. It is URL-encoded according to [RFC 3986](https://datatracker.ietf.org/doc/html/rfc3986) . Valid values corresponding to the label examples above would be: issuer=Example issuer=ACME%20Co The issuer parameter is recommended, but it can be absent. Also, the issuer parameter and issuer string in label should be equal. ### Algorithm The hash algorithm used by the credential. It is optional. | Valid algorithm | | --- | | SHA1 (Default) | | SHA256 | | SHA512 | ### Digits The number of digits in a one-time password (OTP). | Valid number of digits | | --- | | 6 | | 7 | | 8 | ### Counter The counter is only used if the type is HOTP. The counter parameter is required when provisioning HOTP credentials. It will set the initial counter value. ### Period Period is only used if the type is TOTP. The period parameter defines a validity period in seconds for the TOTP code. | Valid period in seconds | | --- | | 15 | | 30 (Default) | | 60 | Examples -------- ### Without parameters otpauth://totp/Example:alice@google.com?secret=JBSWY3DPEHPK3PXP&issuer=Example Try this live [authenticator demo](https://rootprojects.org/authenticator/) with the source code [here](https://git.coolaj86.com/coolaj86/browser-authenticator.js) . Note that this specific demo and code is not affiliated with Yubico. The URI specification [RFC 3986](https://datatracker.ietf.org/doc/html/rfc3986) . [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-oath/uri-string-format.md/#L1) --- # OATH commands and APDUs ##### Table of Contents OATH commands and APDUs ======================= For each possible OATH command, there will be a class that knows how to build the command [APDU](https://docs.yubico.com/yesdk/users-manual/yubikey-reference/apdu.html) and parse the data in the response APDU. Each class will know what information is needed from the caller for that command. General Definitions ------------------- The OATH application is used to manage and use OATH credentials with YubiKey NEO, YubiKey 4, or YubiKey 5. It can be accessed over USB (when the CCID transport is enabled) or over NFC, using ISO 7816-4 commands. ### Commands Commands marked as Require Auth require a successful VALIDATE command to be performed before they are available, if a validation code is set. | Name | Code | Require Auth | | --- | --- | --- | | PUT | 0x01 | Y | | DELETE | 0x02 | Y | | SET CODE | 0x03 | Y | | RESET | 0x04 | N | | LIST | 0xa1 | Y | | CALCULATE | 0xa2 | Y | | VALIDATE | 0xa3 | N | | CALCULATE ALL | 0xa4 | Y | | SEND REMAINING | 0xa5 | Y | ### Algorithms | Name | Code | | --- | --- | | HMAC-SHA1 | 0x01 | | HMAC-SHA256 | 0x02 | | HMAC-SHA512 | 0x03 | Note: HMAC-SHA512 requires YubiKey 4.3.1 or later. ### Types | Name | Code | | --- | --- | | HOTP | 0x01 | | TOTP | 0x02 | ### Properties | Name | Code | Description | | --- | --- | --- | | Only increasing | 0x01 | Enforces that a challenge is always higher than the previous | | Require touch | 0x02 | Require button press to generate OATH codes | Note: Require touch requires YubiKey 4.2.4 or later. List credentials ---------------- Lists configured credentials. ### Command APDU info | CLA | INS | P1 | P2 | Lc | Data | | --- | --- | --- | --- | --- | --- | | 0x00 | 0xa1 | 0x00 | 0x00 | (absent) | (absent) | ### Response APDU info Response will be a continual list of objects looking like: | Data | SW1 | SW2 | | --- | --- | --- | | (See below) | (See below) | (See below) | #### Data | Name | Code | | --- | --- | | Name list tag | 0x72 | | Name length | Length of name + 1 | | Algorithm | High 4 bits is type, low 4 bits is algorithm | | Name data | Name | #### Response Status | Name | SW1 | SW2 | | --- | --- | --- | | Success | 0x90 | 0x00 | | More data available | 0x61 | 0xxx | | Auth required | 0x69 | 0x82 | | Generic error | 0x65 | 0x81 | ### Examples opensc-tool -c default -s 00:a4:04:00:07:a0:00:00:05:27:21:01 -s 00:a1:00:00 Using reader with a card: Yubico YubiKey OTP+FIDO+CCID 0 Sending: 00 A4 04 00 07 A0 00 00 05 27 21 01 Received (SW1=0x90, SW2=0x00): 79 03 05 02 04 71 08 4B B7 A7 FA D7 AF 40 1B y....q.K.....@. Sending: 00 A1 00 00 Received (SW1=0x90, SW2=0x00): 72 1B 21 4D 69 63 72 6F 73 6F 66 74 3A 74 65 73 r.!Microsoft:tes 74 40 6F 75 74 6C 6F 6F 6B 2E 63 6F 6D 72 16 12 t@outlook.comr.. 47 6F 6F 67 6C 65 3A 74 65 73 74 40 67 6D 61 69 Google:test@gmai 6C 2E 63 6F 6D l.com Put credential -------------- Adds a new (or overwrites) OATH credential. ### Command APDU info | CLA | INS | P1 | P2 | Lc | Data | | --- | --- | --- | --- | --- | --- | | 0x00 | 0x01 | 0x00 | 0x00 | Length of Data | (See below) | #### Data | Name | Code | | --- | --- | | Name tag | 0x71 | | Name length | Length of name data, max 64 bytes | | Name data | Name | | Key tag | 0x73 | | Key length | Length of key data + 2 | | Key algorithm | High 4 bits is type, low 4 bits is algorithm | | Digits | Number of digits in OATH code | | Key data | Key (Secret) | | Property tag(o) | 0x78 | | Property(o) | Property byte | | IMF tag(o) | 0x7a (only valid for HOTP) | | IMF length(o) | Length of imf data, always 4 bytes | | IMF data(o) | Imf | Notes: * Name data is typically presented as "period/issuer:account", but the "period/" and "issuer:" are optional under certain configurations. * Minimal length of the Key data (secret) is 14 bytes, if the length is less then pad with 0s. * Key (secret) is arbitary key value encoded in Base32 according to RFC 3548. * Imf data is a Counter, which counts the number of iterations for HOTP. ### Response APDU info | Data | SW1 | SW2 | | --- | --- | --- | | (absent) | (See below) | (See below) | #### Response Status | Name | SW1 | SW2 | | --- | --- | --- | | Success | 0x90 | 0x00 | | No space | 0x6a | 0x84 | | Auth required | 0x69 | 0x82 | | Wrong syntax | 0x6a | 0x80 | ### Examples opensc-tool -c default -s 00:a4:04:00:07:a0:00:00:05:27:21;01 -s 00:01:00:00:30:71:1A:4D:69:63:72:6F:73:6F:66:74:3A:74:65:73:74:40:6F:75:74:6C:6F:6F:6B:2E:63:6F:6D:73:10:21:06:9C:00:00:00:00:00:00:00:00:00:00:00:00:00: 78:02 Using reader with a card: Yubico YubiKey OTP+FIDO+CCID 0 Sending: 00 A4 04 00 07 A0 00 00 05 27 21 01 Received (SW1=0x90, SW2=0x00): 79 03 05 02 04 71 08 4B B7 A7 FA D7 AF 40 1B y....q.K.....@. Sending: 00 01 00 00 // instruction = 01 30 // overoll data length 71 // Name tag 1A // Name length 4D 69 63 72 6F 73 6F 66 74 3A 74 65 73 // Name data presented as 74 40 6F 75 74 6C 6F 6F 6B 2E 63 6F 6D // issuer:account 73 // Key (secret) tag 10 // Key length + 2 21 // totp (type) + sha1 (algorithm) 06 // number of dighits 9C 00 00 00 00 00 00 00 00 00 00 00 00 00 // Key (secret) data 78 // Property tag 02 // Require touch property Received (SW1=0x90, SW2=0x00) Rename credential ----------------- Renames an existing OATH credential on the YubiKey. ### Command APDU info | CLA | INS | P1 | P2 | Lc | Data | | --- | --- | --- | --- | --- | --- | | 0x00 | 0x05 | 0x00 | 0x00 | Length of Data | (See below) | #### Data | Name | Code | | --- | --- | | Name tag | 0x71 | | Name length | Length of name data, max 64 bytes | | Name data | The current credential's name | | Name tag | 0x71 | | Name length | Length of name data, max 64 bytes | | Name data | The new credential's name | Notes: * This command is only available on YubiKeys with firmware version 5.3.0 and later. * Name data is presented as `period/issuer:account`, but the "period/" and "issuer:" are optional under certain configurations. * The new issuer can be an empty string. ### Response APDU info | Data | SW1 | SW2 | | --- | --- | --- | | (absent) | (See below) | (See below) | #### Response Status | Name | SW1 | SW2 | | --- | --- | --- | | Success | 0x90 | 0x00 | | No such object | 0x69 | 0x84 | | Auth required | 0x69 | 0x82 | | Wrong syntax | 0x6a | 0x80 | ### Examples opensc-tool -c default -s 00:a4:04:00:07:a0:00:00:05:27:21;01 -s 00:01:00:00:30:71:1A:4D:69:63:72:6F:73:6F:66:74:3A:74:65:73:74:40:6F:75:74:6C:6F:6F:6B:2E:63:6F:6D:73:10:21:06:9C:00:00:00:00:00:00:00:00:00:00:00:00:00: 78:02 Using reader with a card: Yubico YubiKey OTP+FIDO+CCID 0 Sending: 00 A4 04 00 07 A0 00 00 05 27 21 01 Received (SW1=0x90, SW2=0x00): 79 03 05 02 04 71 08 4B B7 A7 FA D7 AF 40 1B y....q.K.....@. Sending: 00 05 00 00 // instruction = 01 30 // overoll data length 71 // Name tag 1A // The current name length 4D 69 63 72 6F 73 6F 66 74 3A 74 65 73 // The current name data 74 74 40 6F 75 74 6C 6F 6F 6B 2E 63 6F 6D // presented as issuer:account 71 // Name tag 14 // The new name length 6F 66 74 3A 74 65 73 74 40 6F 75 74 // The new name data 6B 2E 63 6F 6D 6C 6F 6F // presented as issuer:account Received (SW1=0x90, SW2=0x00) Delete credential ----------------- Deletes an existing credential. ### Command APDU info | CLA | INS | P1 | P2 | Lc | Data | | --- | --- | --- | --- | --- | --- | | 0x00 | 0x02 | 0x00 | 0x00 | (Length of Data) | (See below) | #### Data | Name | Code | | --- | --- | | Name tag | 0x71 | | Name length | Length of name | | Name data | Name | ### Response APDU info | Data | SW1 | SW2 | | --- | --- | --- | | (absent) | (See below) | (See below) | #### Response Status | Name | SW1 | SW2 | | --- | --- | --- | | Success | 0x90 | 0x00 | | No such object | 0x69 | 0x84 | | Auth required | 0x69 | 0x82 | | Wrong syntax | 0x6a | 0x80 | ### Examples opensc-tool -c default -s 00:a4:04:00:07:a0:00:00:05:27:21:01 -s 00:02:00:00:1C:71:1A:4D:69:63:72:6F:73:6F:66:74:3A:74:65:73:74:40:6F:75:74:6C:6F:6F:6B:2E:63:6F:6D Using reader with a card: Yubico YubiKey OTP+FIDO+CCID 0 Sending: 00 A4 04 00 07 A0 00 00 05 27 21 01 Received (SW1=0x90, SW2=0x00): 79 03 05 02 04 71 08 4B B7 A7 FA D7 AF 40 1B y....q.K.....@. Sending: 00 02 00 00 1C 71 1A 4D 69 63 72 6F 73 6F 66 74 3A 74 65 73 74 40 6F 75 74 6C 6F 6F 6B 2E 63 6F 6D Received (SW1=0x90, SW2=0x00) Reset ----- Resets the application to just-installed state. ### Command APDU info | CLA | INS | P1 | P2 | Lc | Data | | --- | --- | --- | --- | --- | --- | | 0x00 | 0x04 | 0xde | 0xad | (absent) | (absent) | ### Response APDU info | Data | SW1 | SW2 | | --- | --- | --- | | (absent) | 0x90 | 0x00 | ### Examples opensc-tool -c default -s 00:a4:04:00:07:a0:00:00:05:27:21:01 -s 00:04:DE:AD Using reader with a card: Yubico YubiKey OTP+FIDO+CCID 0 Sending: 00 A4 04 00 07 A0 00 00 05 27 21 01 Received (SW1=0x90, SW2=0x00): 79 03 05 02 04 71 08 4B B7 A7 FA D7 AF 40 1B y....q.K.....@. Sending: 00 04 DE AD Received (SW1=0x90, SW2=0x00) Set Password ------------ Configures Authentication. If length 0 is sent, authentication is removed. The key to be set is expected to be a user-supplied UTF-8 encoded password passed through 1000 rounds of PBKDF2 with the ID from select used as salt. 16 bytes of that are used. When configuring authentication you are required to send an 8 byte challenge and one authentication-response with that key, in order to confirm that the application and the host software can calculate the same response for that key. ### Command APDU info | CLA | INS | P1 | P2 | Lc | Data | | --- | --- | --- | --- | --- | --- | | 0x00 | 0x03 | 0x00 | 0x00 | Length of Data | (See below) | #### Data | Name | Code | | --- | --- | | Key tag | 0x73 | | Key length | Length of key data + 2 | | Key algorithm | Algorithm | | Key data | Key (Secret) | | Challenge tag | 0x74 | | Challenge length | Length of challenge data | | Challenge data | Challenge | | Response tag | 0x75 | | Response length | Length of response data | | Response data | Response | ### Response APDU info | Data | SW1 | SW2 | | --- | --- | --- | | (absent) | (See below) | (See below) | #### Response Status | Name | SW1 | SW2 | | --- | --- | --- | | Success | 0x90 | 0x00 | | Response doesn’t match | 0x69 | 0x84 | | Auth required | 0x69 | 0x82 | | Wrong syntax | 0x6a | 0x80 | ### Examples opensc-tool -c default -s 00:a4:04:00:07:a0:00:00:05:27:21:01 -s 00:03:00:00:33:73:11:01:78:0E:45:A0:06:52:CC:B0:8C:4B:DA:CD:DA:CA:51:34:74:08:F1:03:DA:89:58:E4:40:85:75:14:01:1E:E1:FF:2A:98:2D:4D:CC:CD:8E:B3:3A:12:E4:88:7E:F5:E0:0C Using reader with a card: Yubico YubiKey OTP+FIDO+CCID 0 Sending: 00 A4 04 00 07 A0 00 00 05 27 21 01 Received (SW1=0x90, SW2=0x00): 79 03 05 02 04 71 08 91 B8 DA 1C 23 45 F2 6B y....q.....#E.k Sending: 00 03 00 00 33 73 11 01 78 0E 45 A0 06 52 CC B0 8C 4B DA CD DA CA 51 34 74 08 F1 03 DA 89 58 E4 40 85 75 14 01 1E E1 FF 2A 98 2D 4D CC CD 8E B3 3A 12 E4 88 7E F5 E0 0C Received (SW1=0x90, SW2=0x00) Validate -------- Validates authentication (mutually). The challenge for this comes from the SELECT command. The response if computed by performing the correct HMAC function of that challenge with the correct key. A new challenge is then sent to the application, together with the response. The application will then respond with a similar calculation that the host software can verify. ### Command APDU info | CLA | INS | P1 | P2 | Lc | Data | | --- | --- | --- | --- | --- | --- | | 0x00 | 0xa3 | 0x00 | 0x00 | Length of Data | (See below) | #### Data | Name | Code | | --- | --- | | Response tag | 0x75 | | Response length | Length of response data | | Response data | Response | | Challenge tag | 0x74 | | Challenge length | Length of challenge data | | Challenge data | Challenge | ### Response APDU info Response will be a continual list of objects looking like: | Data | SW1 | SW2 | | --- | --- | --- | | (See below) | (See below) | (See below) | #### Data | Name | Code | | --- | --- | | Response tag | 0x75 | | Response length | Length of response data | | Response data | Response | #### Response Status | Name | SW1 | SW2 | | --- | --- | --- | | Success | 0x90 | 0x00 | | Auth not enabled | 0x69 | 0x84 | | Wrong syntax | 0x6a | 0x80 | | Generic error | 0x65 | 0x81 | Calculate --------- Performs CALCULATE for one named credential. Gets an OTP (one-time password) value generated on a YubiKey. ### Command APDU info | CLA | INS | P1 | P2 | Lc | Data | | --- | --- | --- | --- | --- | --- | | 0x00 | 0xa2 | 0x00 | (See below) | Length of Data | (See below) | #### P2 | Name | Code | | --- | --- | | Full response | 0x00 | | Truncated response | 0x01 | #### Data | Name | Code | | --- | --- | | Name tag | 0x71 | | Name length | Length of name data | | Name data | Name | | Challenge tag | 0x74 | | Challenge length | Length of challenge data | | Challenge data | Challenge | ### Response APDU info The first 4 bytes of the response data is an OTP (one-time password) value. | Data | SW1 | SW2 | | --- | --- | --- | | (See below) | (See below) | (See below) | #### Data | Name | Code | | --- | --- | | Response tag | 0x75 - full; 0x76 - truncated | | Response length | Length of response data + 1 | | Digits | Number of digits in the OATH code | | Response data | Response | #### Response Status | Name | SW1 | SW2 | | --- | --- | --- | | Success | 0x90 | 0x00 | | No such object | 0x69 | 0x84 | | Auth required | 0x69 | 0x82 | | Wrong syntax | 0x6a | 0x80 | | Generic error | 0x65 | 0x81 | opensc-tool -c default -s 00:A4:04:00:07:A0:00:00:05:27:21:01 -s 00:A2:00:00:26:71:1A:4D:69:63:72:6F:73:6F:66:74:3A:74:65:73:74:40:6F:75:74:6C:6F:6F:6B:2E:63:6F:6D:74:08:F1:03:DA:89:58:E4:40:85 Using reader with a card: Yubico YubiKey OTP+FIDO+CCID 0 Sending: 00 A4 04 00 07 A0 00 00 05 27 21 01 Received (SW1=0x90, SW2=0x00): 79 03 05 02 04 71 08 91 B8 DA 1C 23 45 F2 6B y....q.....#E.k Sending: 00 A2 00 00 26 71 1A 4D 69 63 72 6F 73 6F 66 74 3A 74 65 73 74 40 6F 75 74 6C 6F 6F 6B 2E 63 6F 6D 74 08 F1 03 DA 89 58 E4 40 85 Received (SW1=0x90, SW2=0x00): 75 15 06 8A 9B 0D F3 D7 18 43 96 40 A6 58 6F 89 u........C.@.Xo. D4 03 1D C4 C4 9F 6C ......l Calculate All ------------- Calculates OTPs (one-time passwords) for all available credentials. Returns name + response for TOTP credentials and just name for HOTP credentials to avoid overloading the HOTP counters. Note: HOTP credentials, credentials requiring touch and credentials with non default period should be recalculated separetely if needed by using CALCULATE command. ### Command APDU info | CLA | INS | P1 | P2 | Lc | Data | | --- | --- | --- | --- | --- | --- | | 0x00 | 0xa4 | 0x00 | (See below) | Length of Data | (See below) | #### P2 | Name | Code | | --- | --- | | Full response | 0x00 | | Truncated response | 0x01 | #### Data | Name | Code | | --- | --- | | Challenge tag | 0x74 | | Challenge length | Length of challenge data | | Challenge data | Challenge | ### Response APDU info For HOTP the response tag is 0x77 (No response). For credentials requiring touch the response tag is 0x7c (No response). The first 4 bytes of the response data is an OTP (one-time password) value. The response will be a list of the following objects: | Data | SW1 | SW2 | | --- | --- | --- | | (See below) | (See below) | (See below) | #### Data | Name | Code | | --- | --- | | Name tag | 0x71 | | Name length | Length of name data | | Name data | Name | | Response tag | 0x77 - for HOTP; 0x7c - for touch; 0x75 - full; 0x76 - truncated | | Response length | Length of response data + 1 | | Digits | Number of digits in the OATH code | | Response data | Response | #### Response Status | Name | SW1 | SW2 | | --- | --- | --- | | Success | 0x90 | 0x00 | | More data available | 0x61 | 0xXX | | Auth required | 0x69 | 0x82 | | Wrong syntax | 0x6a | 0x80 | | Generic error | 0x65 | 0x81 | opensc-tool -c default -s 00:A4:04:00:07:A0:00:00:05:27:21:01 -s 00:A4:00:00:0A:74:08:F1:03:DA:89:58:E4:40:85 Using reader with a card: Yubico YubiKey OTP+FIDO+CCID 0 Sending: 00 A4 04 00 07 A0 00 00 05 27 21 01 Received (SW1=0x90, SW2=0x00): 79 03 05 02 04 71 08 91 B8 DA 1C 23 45 F2 6B y....q.....#E.k Sending: 00 A4 00 00 0A 74 08 F1 03 DA 89 58 E4 40 85 Received (SW1=0x90, SW2=0x00): 71 1A 4D 69 63 72 6F 73 6F 66 74 3A 74 65 73 74 q.Microsoft:test 40 6F 75 74 6C 6F 6F 6B 2E 63 6F 6D 75 15 06 8A @outlook.comu... 9B 0D F3 D7 18 43 96 40 A6 58 6F 89 D4 03 1D C4 .....C.@.Xo..... C4 9F 6C 71 15 41 70 70 6C 65 3A 74 65 73 74 40 ..lq.Apple:test@ 69 63 6C 6F 75 64 2E 63 6F 6D 77 01 06 icloud.comw.. [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-oath/oath-commands.md/#L1) --- # Building a certificate request for a PIV private key ##### Table of Contents Building a certificate request for a PIV private key ==================================================== You have generated a key pair in, or imported a private key into, a PIV slot. Now you need a certificate. To obtain a certificate, you start by building a certificate request and sending it to a Certificate Authority (CA). The CA will build a cert and return it to you. This document describes how to build a cert request using a key in a YubiKey PIV slot. Note that there is also some sample code that demonstrates this. Find it in .../Yubico.YubiKey/examples/PivSampleCode/CertificateOperations Start with the file SampleCertificateOperations.cs and the method GetCertRequest .NET Base Class Libraries ------------------------- This document describes how to create a cert request using System.Security.Cryptography.X509Certificates.CertificateRequest This is not the only way to create a cert request. There are commercial products available with certificate APIs. However, for this documentation (and the SDK sample code), only classes available in the .NET BCL are examined. The `CertificateRequest` constructor ------------------------------------ To build a cert request, start by building a `CertificateRequest` object. To do so, use the constructor. There are several, but let's look at this one. CertificateRequest( string subjectName, System.Security.Cryptography.RSA publicKey, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.RSASignaturePadding paddingScheme); ### Subject name A certificate is a binding between a name and a public key. So your cert request will need to let the CA know what name and public key are to be in the certificate. There are two ways to provide the subject name, as a `string` and as an instance of `System.Security.Cryptography.X509Certificates.X500DistinguishedName`. The purpose of this document is to describe how to build a cert request when the private key is on a YubiKey. Hence, we will not describe how to build names, either by using the `string` class or the `X500DistinguishedName` class. For this document, we're simply going to use the string string sampleName = "C=US,ST=CA,L=Palo Alto,O=Fake,CN=Fake Cert"; If you want to learn more about building a subject name, either by using a `string` or an [`X500DistinguishedName`](https://docs.microsoft.com/en-us/dotnet/api/system.security.cryptography.x509certificates.x500distinguishedname?view=net-5.0) , see the .NET documentation. ### Public key When you generate a key pair on the YubiKey, a `PivPublicKey` is returned. The `CertificateRequest` class needs that public key as an instance of the `RSA` class. The `PivSampleCode.KeyConverter` class demonstrates how to get an `RSA` object from a `PivPublicKey`. Your code might look something like this. PivRsaPublicKey rsaPublic = pivSession.GenerateKeyPair(...); var rsaParams = new RSAParameters(); rsaParams.Modulus = rsaPublic.Modulus.ToArray(); rsaParams.Exponent = rsaPublic.PublicExponent.ToArray(); RSA rsaPublicKeyObject = RSA.Create(rsaParams); An `RSA` object can contain a public key only or both public and private keys. Later on, we're going to sign the cert request using the private key partner to the public key loaded in this step. Normally, that private key would need to be loaded into this `RSA` object as well, because that's the object the cert request code would use to sign the request. But the private key partner in this case is on the YubiKey and is not allowed to leave the device. We can't load it into this `RSA` object. But we will still be able to sign. How to do so will be described later. ### `HashAlgorithm` To sign using RSA is to encrypt the hash of the data to sign. That is, RSA does not operate directly on the data to sign, but rather the hash (message digest) of the data. So we need to specify which hash algorithm the cert request code should use. Your best choices are the following. HashAlgorithmName.SHA256 HashAlgorithmName.SHA384 HashAlgorithmName.SHA512 There are other algorithms available: `MD5` and `SHA1`. However, researchers have found weaknesses in them, so cryptographers universally recommend not using them any more. Use them only for legacy systems. Which algorithm should you use? Your application might be required to use a particular digest based on a standard or protocol. If not, then you might choose SHA-256 simply because it is the most widely used digest algorithm in RSA signatures. It is the one that will likely have no interoperability issues. Because a longer digest does add some security in digital signatures, you might choose to use the SHA-384 with 1024-bit keys. If you try to use SHA-512, the operation will likely fail because there is not enough space in a 1024-bit block (128 bytes, the size of the signature) to contain a padded, 64-byte digest. If the RSA key is 2048 bits, you can use SHA-512. Note that there is an algorithm SHA-224, but the .NET BCL do not support it. ### `PaddingScheme` Every standard that deals with RSA signatures requires the digest to be padded. There are two available in the .NET BCL. RSASignaturePadding.Pkcs1 RSASignaturePadding.Pss PSS is recommended over PKCS #1. It is possible to encounter a legacy system that requires PKCS #1 and does not support PSS. However, if that is not the case, it is better to use PSS. An RSA signature is the encrypted digest. However, for security reasons, the actual data to encrypt should be the same size as (or very close to the size of) the key itself. For example, if the RSA key is 1024 bits (128 bytes), then the data to sign should also be a 128-byte block. A SHA-256 digest is only 32 bytes. Hence, to create a block to encrypt, add pad bytes. The padding scheme used should be a standard one so that the verifier can know which bytes are pad and which are the digest. Both padding schemes supported in the .NET BCL require a minimum amount of padding. In other words, a particular digest algorithm/padding scheme/key size might not be compatible because the digest is very long and not many pad bytes are needed to complete a block. That is why it is possible you will not be able to use SHA-512 with a 1024-bit key. Extensions ---------- Now that you have the `CertificateRequest` object built, it is possible to add extensions. To learn how to do that, see the .NET BCL documentation. `CreateSigningRequest` ---------------------- When the `CertificateRequest` object has all the information you want, call the appropriate `CreateSigningRequest` method. The `CreateSigningRequest` method that takes no arguments will sign the request using the private key inside the `RSA` object passed to the constructor. In this case, that object has no private key, so we'll need to use public byte[] CreateSigningRequest ( System.Security.Cryptography.X509Certificates.X509SignatureGenerator signatureGenerator); We will build an `X509SignatureGenerator`, which is an object that knows how to sign. The sample code contains an example of one that uses a YubiKey to sign. See .../Yubico.YubiKey/examples/PivSampleCode/CertificateOperations YubiKeySignatureGenerator.cs The `CreateSigningRequest` method will do much of the work to build up the cert request, but will call on our `SignatureGenerator` to do work it can't. ### `X509SignatureGenerator` This is an abstract class. We need to build a subclass that implements the specified methods: BuildPublicKey GetSignatureAlgorithmIdentifier SignData We will pass an instance of our class to the `CreateSigningRequest` method. Start with a "scaffold" class. public sealed class YubiKeySignatureGenerator : X509SignatureGenerator { public YubiKeySignatureGenerator() { } protected override PublicKey BuildPublicKey() { } public override byte[] GetSignatureAlgorithmIdentifier(HashAlgorithmName hashAlgorithm) { } public override byte[] SignData(byte[] data, HashAlgorithmName hashAlgorithm) { } } #### `BuildPublicKey` When we first built the `CertificateRequest` object, we supplied the public key in the `RSA` argument. It would seem that if the object (and the `CreateSigningRequest` method) has access to the public key there should be no need for our `SignatureGenerator` to be able to provide it. But nonetheless, we need to build this method. Fortunately, the `X509SignatureGenerator` base class (the abstract class from which we derive the class we are currently constructing) contains code that can be used to accomplish this. Call this `static` method // Use the RSA object and padding scheme we created for the CertificateRequest // constructor. X509SignatureGenerator defaultGenerator = X509SignatureGenerator.CreateForRSA( rsaPublicKeyObject, RSASignaturePadding.Pss); You now have an `X509SignatureGenerator` object. This happens to be the default. It is what the `CreateSigningRequest()` (no arg version of this method) would use. However, this object was built using an `RSA` object that contained no private key. So it won't be able to sign. But it will be able to build a `PublicKey`. We can update our class to take advantage of this object. public sealed class YubiKeySignatureGenerator : X509SignatureGenerator { private readonly X509SignatureGenerator _defaultGenerator; private readonly RSASignaturePaddingMode _paddingMode; // Use the RSA object and padding scheme we created for the CertificateRequest // constructor. public YubiKeySignatureGenerator(RSA rsaPublicKeyObject, RSASignaturePadding paddingScheme) { _defaultGenerator = X509SignatureGenerator.CreateForRSA(rsaPublicKeyObject, paddingScheme); _paddingMode = paddingScheme.Mode; } protected override PublicKey BuildPublicKey() { return _defaultGenerator.PublicKey; } public override byte[] GetSignatureAlgorithmIdentifier(HashAlgorithmName hashAlgorithm) { } public override byte[] SignData(byte[] data, HashAlgorithmName hashAlgorithm) { } } #### `GetSignatureAlgorithmIdentifier` The point of this method is to return the DER encoding of the algorithm ID of the algorithm that will be used to sign. The algID is part of the finished cert request. Once again, the `CertificateRequest` object (and the `CreateSigningRequest` method) has access to the `RSA` public key, the `HashAlgorithm`, and `RSASignaturePadding`. It would seem that the object has everything it needs to build the "algID". But nonetheless, we need to build this method. Fortunately, the `_defaultGenerator` we built earlier can build the algID for us. public sealed class YubiKeySignatureGenerator : X509SignatureGenerator { . . . public override byte[] GetSignatureAlgorithmIdentifier(HashAlgorithmName hashAlgorithm) { return _defaultGenerator.GetSignatureAlgorithmIdentifier(hashAlgorithm); } public override byte[] SignData(byte[] data, HashAlgorithmName hashAlgorithm) { } } #### `SignData` This is the method we will build that calls on the YubiKey to sign the data. The `CertificateRequest` object is going to pass to our method the data to sign and the hash algorithm it is expected to use. That means we need to digest the data using the specified algorithm, then create a signature using that digest result. We need to pad the digest as well. In order to sign using a YubiKey, we need a `PivSession` and we need to know in which slot the private key we're using resides. private readonly PivSession _pivSession; private readonly byte _slotNumber; private readonly int _keySizeBits; private readonly X509SignatureGenerator _defaultGenerator; private readonly RSASignaturePaddingMode _paddingMode; public YubiKeySignatureGenerator( PivSession pivSession, byte slotNumber, RSA rsaPublicKeyObject, RSASignaturePadding paddingScheme) { _pivSession = pivSession; _slotNumber = slotNumber; _keySizeBits = rsaPublicKeyObject.KeySize; _defaultGenerator = X509SignatureGenerator.CreateForRSA(rsaPublicKeyObject, paddingScheme); _paddingMode = paddingScheme.Mode; } protected override PublicKey BuildPublicKey() { return _defaultGenerator.PublicKey; } public override byte[] GetSignatureAlgorithmIdentifier(HashAlgorithmName hashAlgorithm) { return _defaultGenerator.GetSignatureAlgorithmIdentifier(hashAlgorithm); } public override byte[] SignData(byte[] data, HashAlgorithmName hashAlgorithm) { byte[] dataToSign = DigestData(data, hashAlgorithm); dataToSign = PadRsa(dataToSign, hashAlgorithm); return _pivSession.Sign(_slotNumber, dataToSign); } private byte[] DigestData(byte[] dataToDigest, HashAlgorithmName hashAlgorithm) { using HashAlgorithm digester = hashAlgorithm.Name switch { "SHA1" => CryptographyProviders.Sha1Creator(), "SHA256" => CryptographyProviders.Sha256Creator(), "SHA384" => CryptographyProviders.Sha384Creator(), "SHA512" => CryptographyProviders.Sha512Creator(), _ => throw new ArgumentException(), }; byte[] digest = new byte[digester.HashSize / 8]; _ = digester.TransformFinalBlock(data, 0, data.Length); Array.Copy(digester.Hash, 0, digest, 0, digest.Length); return digest; } private byte[] PadRsa(byte[] digest, HashAlgorithmName hashAlgorithm) { int digestAlgorithm = hashAlgorithm.Name switch { "SHA1" => RsaFormat.Sha1, "SHA256" => RsaFormat.Sha256, "SHA384" => RsaFormat.Sha384, "SHA512" => RsaFormat.Sha512, _ => 0, }; if (_rsaPadding.Mode == RSASignaturePaddingMode.Pkcs1) { return RsaFormat.FormatPkcs1Sign(digest, digestAlgorithm, _keySizeBits); } return RsaFormat.FormatPkcs1Pss(digest, digestAlgorithm, _keySizeBits); } ECC --- It is possible you will want to build a cert request for an ECC key pair. In that case, you will need a `SignatureGenerator` that can sign using ECC. To do so, you will need to build an ECC default `SignatureGenerator`, there are restrictions on the size of the digest (it must match the key size), and there is no padding. The sample code demonstrates how to build a `SignatureGenerator` that can sign using either RSA or ECC. [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-piv/cert-request.md/#L1) --- # PIV attestation statements ##### Table of Contents PIV attestation statements ========================== Attestation was added as a feature in version 4.3 of the YubiKey, so will not be available on earlier models. It is possible to create an attestation statement for some of the keys generated on a YubiKey. Such a statement simply offers evidence that a private key was generated on a YubiKey. It does not say anything about who owns the YubiKey, or who signed some data using the private key, only that the key is from a YubiKey. ##### Note In version 1.0.0 of the SDK, it was not possible to create an attestation statement for keys in slots 82 - 95 (retired key slots). Beginning with version 1.0.1 of the SDK it is possible to create an attestation statement for the keys in those slots. This attestation statement is provided in the form of an X.509 certificate. What this certificate attests (or asserts, affirms) is that "the private key partner to the public key in this certificate was generated on a YubiKey." Note that any private key generated on the YubiKey, using the PIV application, is not allowed to leave the device. In addition, the YubiKey will not create an attestation statement for an imported key. Hence, it is possible to verify that a private key operation was performed (or will be performed) by the YubiKey and only the YubiKey. If the YubiKey is version 5.0 or later, then the attestation statement also contains the YubiKey's serial number. That means anyone examining the certificate can be confident that not only was the private key generated by a YubiKey, but a specific YubiKey. Uses ---- Generally, a certificate binds a name with a public key. That allows verifiers to tie private key operations to a specific entity. For example, if a public key verifies a digital signature, and that public key is certified by a certificate (and the certificate verifies, see chaining below), then the signature is said to belong to the name on the certificate. However, an attestation statement does not tie a name to public key, it ties a process to a public key. The cert has a name, such as "YubiKey PIV Attestation 9A", but that is the name on all attestation statements of all YubiKeys, when the slot attested is 9A. It is not the name of the owner of the public key, but rather the name associated with the process used to generate the public key. How is that useful? Some applications want correspondents to create signatures for authentication or authorization purposes. But they want to know whether the private key used to sign is a software key or a hardware key. A hardware key is much more secure, and with an attestation statement, the application can have more confidence that the key has not been stolen because someone used a weak password or left a monitor unattended. Hardware keys are not completely secure, after all someone can steal your YubiKey. But it is much harder to mount a remote attack on someone using a YubiKey. The attacker must have access to the physical device. And if the attacker does indeed steal your YubiKey, they must enter your PIN to create a signature (assuming you did not turn off the PIN requirement for signing). Because the PIN and PUK block after too many wrong values are entered, it is likely a brute force attack will fail. Chaining -------- Someone verifying your attestation statement will need to know that the certificate you provide is indeed valid. To verify that cert, verify its contents and signature. The public key used to verify a cert's signature comes from the certificate issuer, also known as the Certificate Authority (CA). You will find that public key in the CA's cert. To verify that you do indeed have the correct CA cert, verify using its issuer's public key, found in the CA's issuer's certificate. And so on. This process ends at a root cert. This is a certificate you obtain outside the normal certificate distribution system. Your application will likely have some sort of cert store with trusted root certs. These trusted certs are those that you obtained in a trusted manner, and believe them to be valid. Most trusted certs are "baked into" software distributions. For example, web browsers come with various root certs already loaded. If you trust the software and its distribution, you trust those root certs. Most software packages that use root certs allow you to add new roots. The process of verifying a certificate by using the cert of the issuer, and verifying the issuer's cert by using the cert of the issuer's issuer, and so on until reaching a root cert, is known as chaining. Root Cert | | [CA Cert] (There may or may not be a CA cert between the Root and Attestation Cert) | | Attestation Cert (Slot F9) (from PivSession.GetAttestationCertificate) | | Attestation Statement (created using PivSession.CreateAttestationStatement) (a cert) To obtain the YubiKey CA and root certs, visit the [Yubico Developer's PIV Attestation website](https://developers.yubico.com/PIV/Introduction/PIV_attestation.html) . Using the appropriate cert from this location, you can verify an attestation statement built by a YubiKey. Terminology ----------- Start with the private key in an attestable slot (9A, 9C, 9D, 9E, and 82 - 95). This key has a partner public key. On every YubiKey (since version 4.3) is an attestation key and certificate. These are in slot F9. When an attestation statement is built, the private key in the attestable slot is the "attested key". A new certificate is created. This new certificate is called the attestation statement. * Slot 9A, 9C, 9D, 9E, 82 - 95: * public and private key pair * private key is the attested key * attestation statement: * an X.509 certificate * subject key is the public key partner to the attested key * signed by the attestation key * chains to the attestation cert * Slot F9: * public and private key pair * private key is the attestation key * attestation certificate: * an X.509 certificate * subject key is the public key partner to private key in F9 * chains to a root Replacing the attestation key and cert -------------------------------------- It is possible to replace the attestation key and cert that is loaded onto the YubiKey at manufacture. However, this is something very few users will want to do. If you are wondering whether you might like to replace the attestation key and cert, it is almost a certainty that you should not. But there are companies who have wanted the attestation statement to chain up to their own root instead of a one from Yubico. Hence, the YubiKey allows for it. Note that if you replace the Yubico key and cert, there is no way to recover these original values, they will be gone for good. So use this method with caution. The replacement key must be either RSA-2048, RSA-3072, RSA-4096, ECC-P256, or ECC-P384, and there are some restrictions on the certificate. YubiKeys before version 5 did allow 1024-bit RSA keys as attestation keys, but to make your application work for all YubiKeys, you should never use a 1024-bit RSA key as an attestation key. There are two ways to replace the key: generate a new attestation key or import a key. First, you will almost certainly NOT want to generate the attestation key. If you generate a new key, you will get a public key at the time the key is generated and will have to build a certificate for that public key, then import the certificate. That attestation key will only work for the YubiKey on which it was generated. Generally, the same attestation key and cert is loaded onto many YubiKeys. It is much more efficient to get one attestation certificate for thousands of YubiKeys than to get thousands of attestation certificates. If you have a private key and certificate outside the YubiKey, you can import both. However, note that the attestation certificate must be built with these restrictions: * It must be X.509 version 2 or 3 * The encoded validity dates must be less than 66 bytes * The encoded `SubjectName` must be less than 1029 bytes * The total length of the certificate must be fewer than 3052 bytes The first restriction -- the certificate cannot be version 1 -- might be the most troublesome. Very few CAs build version 1 certificates these days, so is is likely there will be no issue. However, there is one thing to think about. It is possible the certificate building software the CA uses might build version 1 certificates by default. For example, the OpenSSL command line tool can build certificates. However, it does not allow you to pick the version number. It will build a version 1 certificate unless the cert to build will contain one or more extensions. That is, if the certificate to build will contain no extensions, the OpenSSL software will produce a version 1 certificate. If the cert will contain at least one extension, the OpenSSL software will create a version 3 cert. The OpenSSL command line tool currently does not support building version 2 certificates. Hence, to make sure you build a version 3 certificate using the OpenSSL command line tool, build it with at least one extension. For example, here is a command that builds a certificate from a cert request and the cert it builds will contain the `BasicConstraints` extension. $ openssl x509 -req -in certRequest.pem -days 3640 -CA rootcert.pem -CAkey rootkey.pem -extfile basic.txt -CAserial rootcert.srl -out cert.pem where basic.txt contains the BasicConstraints extension: (the following are the contents of the file basic.txt) basicConstraints=critical,CA:true,pathlen:1 For the second restriction, if the certificate is a valid X.509 version 3 certificate, the validity dates will be less than 64 bytes, so that should not be a problem. For the third, most names in certificates are less than 128 bytes, so specifying the name for your attestation cert to be less than 1029 bytes should be easy. Nonetheless, keep an eye on the length of the name. Note that the encoded `SubjectName` refers to the DER encoding of SEQUENCE OF RelativeDistinguishedName If you look inside the DER encoding of a certificate, you will find a `SubjectName`. If you pull out that name as an individual entity, it will look something like this. 30 68 31 0b 30 09 06 03 55 04 06 13 02 55 53 31 0b 30 09 06 03 55 04 08 0c 02 43 41 31 12 30 10 06 03 55 04 07 0c 09 50 61 6c 6f 20 41 6c 74 6f 31 19 30 17 06 03 55 04 0a 0c 10 46 61 6b 65 20 41 74 74 65 73 74 61 74 69 6f 6e 31 1d 30 1b 06 03 55 04 03 0c 14 46 61 6b 65 20 41 74 74 65 73 74 61 74 69 6f 6e 20 32 35 36 This is a TLV (tag-length-value) with a tag of `30`, a length of `68` (decimal 104) and a value of `31 0b ... 36`. The length in the TLV is the value's length. The total length is `6a` (decimal 106): the length of the value plus the length of the tag (one) plus the length of the length octets (also one). For a `SubjectName` to be invalid for an attestation cert, it would look something like this. 30 82 04 01 31 0b 30 09 06 03 55 04 06 13 02 55 53 31 0b 30 . . . 65 20 41 74 74 65 73 74 61 74 69 6f 6e 20 32 35 36 In this case, the tag is `30`, the length is `04 01` (decimal 1025) (the 82 indicates that the following two bytes make up the length), and there are 1025 bytes that make up the value. The total length of this `SubjectName` is `0405` (decimal 1029): the value's length plus the length of the tag (one) plus the length of the length octets (three). ### Checking the key and cert. Due to space and compute limitations, the YubiKey itself does not verify the inputs before loading them. That means it is possible to load bad key/cert combinations. For example, it is possible to load a cert that contains a subject key that is not the partner to the private key. In that case, the YubiKey will create attestation statements that do not verify or do not chain to a root. In other cases, the YubiKey might simply return an error when requested to build an attestation statement. Hence, you must be certain the key and cert you load are correct, and you should thoroughly test the attestation statements before deployment. There is a method in the `PivSession` class to replace the attestation key and cert. public void ReplaceAttestationKeyAndCertificate(PivPrivateKey privateKey, X509Certificate2 certificate) If you use this method to replace the key and cert, it will check the certificate to make sure it meets the requirement. If not, the method will throw an exception. However, this method will not verify the cert itself, nor will it verify the validity dates. It will also NOT verify that the public key represented in the cert is indeed the partner to the private key specified. If you want to make sure they match, you will need to write your own code. The following code is one way to make this check. It uses standard C# classes. If you have access to a secure multi-precision arithmetic library (often called `BigNum` or `BigInteger`), there is a more efficient technique. However, the standard C# `BigInteger` class is not one you should use with sensitive data, so we present this technique. using System.Security.Cryptography; using System.Security.Cryptography.X509Certificates; private static bool IsMatchingKeyAndCert(PivPrivateKey privateKey, X509Certificate2 certificate) { if (privateKey.Algorithm == PivAlgorithm.Rsa2048) { return IsMatchingKeyAndCertRsa((PivRsaPrivateKey)privateKey, (RSA)certificate.PublicKey.Key); } return IsMatchingKeyAndCertEcc((PivEccPrivateKey)privateKey, (byte[])certificate.PublicKey.EncodedKeyValue); } private static bool IsMatchingKeyAndCertRsa(PivRsaPrivateKey privateKey, RSA publicKey) { bool returnValue = isValidCert; // In order to build a System.Security.Cryptography.RSA object // that contains the private key, we must provide all possible // components: modulus, public exponent, private exponent, CRT // info. // We have everything needed from the publicKey (an RSA object) // and privateKey (a PivRsaPrivateKey object) except for the // private exponent. If you have the CRT info, you don't need the // private exponent, so the PivRsaPrivateKey class doesn't keep // it (and the YubiKey itself does not keep it). // But in order to build the RSA private key-containing object we // need to obtain the private exponent. Except we don't really. // Although the object will not build itself without that // component, once it's built, the object ignores it. So we can // supply anything as the private exponent, the object will // build, and it will operate correctly anyway. That's why we're // using an arbitrary private exponent. RSAParameters publicParams = publicKey.ExportParameters(false); byte[] fakeExponent = new byte[publicParams.Modulus.Length]; byte[] modCopy = new byte[publicParams.Modulus.Length]; byte[] expCopy = new byte[publicParams.Exponent.Length]; Array.Copy(publicParams.Modulus, modCopy, publicParams.Modulus.Length); Array.Copy(publicParams.Exponent, expCopy, publicParams.Exponent.Length); // To determine if the public key in the cert is the partner to // the private key, encrypt arbitrary data using that public key, // then decrypt it using the private key. If that works, they are // partners. Use PKCS 1 padding so we don't have to involve any // digest algorithms. byte[] dataToEncrypt = new byte[16]; using RandomNumberGenerator randomObject = RandomNumberGenerator.Create(); randomObject.GetBytes(fakeExponent); fakeExponent[0] &= 0x7F; fakeExponent[^1] |= 1; randomObject.GetBytes(dataToEncrypt); var rsaParams = new RSAParameters(); try { rsaParams.D = fakeExponent; rsaParams.DP = privateKey.ExponentP.ToArray(); rsaParams.DQ = privateKey.ExponentQ.ToArray(); rsaParams.InverseQ = privateKey.Coefficient.ToArray(); rsaParams.P = privateKey.PrimeP.ToArray(); rsaParams.Q = privateKey.PrimeQ.ToArray(); rsaParams.Modulus = modCopy; rsaParams.Exponent = expCopy; using var rsaObject = RSA.Create(); rsaObject.ImportParameters(rsaParams); byte[] encryptedData = rsaObject.Encrypt(dataToEncrypt, RSAEncryptionPadding.Pkcs1); byte[] decryptedData = rsaObject.Decrypt(encryptedData, RSAEncryptionPadding.Pkcs1); return MemoryExtensions.SequenceEqual(dataToEncrypt, decryptedData); } finally { CryptographicOperations.ZeroMemory(rsaParams.P); CryptographicOperations.ZeroMemory(rsaParams.Q); CryptographicOperations.ZeroMemory(rsaParams.DP); CryptographicOperations.ZeroMemory(rsaParams.DQ); CryptographicOperations.ZeroMemory(rsaParams.InverseQ); CryptographicOperations.ZeroMemory(rsaParams.D); } } private static bool IsMatchingKeyAndCertEcc(PivEccPrivateKey privateKey, byte[] publicKey) { bool returnValue = false; ECCurve eccCurve = privateKey.Algorithm == PivAlgorithm.EccP256 ? ECCurve.CreateFromValue("1.2.840.10045.3.1.7") : ECCurve.CreateFromValue("1.3.132.0.34"); var eccParams = new ECParameters { Curve = (ECCurve)eccCurve }; try { int coordLength = (publicKey.Length - 1) / 2; byte[] xCoord = new byte[coordLength]; byte[] yCoord = new byte[coordLength]; Array.Copy(publicKey, 1, xCoord, 0, coordLength); Array.Copy(publicKey, 1 + coordLength, yCoord, 0, coordLength); eccParams.Q.X = xCoord; eccParams.Q.Y = yCoord; eccParams.D = privateKey.PrivateValue.ToArray(); // To determine if the public key in the cert is the partner // to the private key, sign random data using that private // key, then verify it using the public key. If that works, // they are partners. Use the SignHash method so we don't // have to involve any digest algorithms. using var eccObject = ECDsa.Create(eccParams); byte[] dataToSign = new byte[coordLength]; using RandomNumberGenerator randomObject = RandomNumberGenerator.Create(); randomObject.GetBytes(dataToSign); byte[] signature = eccObject.SignHash(dataToSign); return eccObject.VerifyHash(dataToSign, signature); } finally { CryptographicOperations.ZeroMemory(eccParams.D); } } [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-piv/attestation.md/#L1) --- # Maximum certificate sizes ##### Table of Contents Maximum certificate sizes ========================= It is possible to store up to 24 private key/certificate pairs in the PIV slots. However, there are space limitations. In the real world, certificates are generally less than 1,000 bytes. Some large certs are over 1,000 bytes, but rarely over 2,000. It is unlikely that you will run into limitations on the YubiKey. Nonetheless, these are the space limitations for certs in the PIV application on the YubiKey. Maximum size for a single certificate ------------------------------------- | YubiKey Version | Maximum Size in Bytes | | --- | --- | | before 4.0 (e.g. NEO) | 2025 | | 4.x | 3052 | | 4.x FIPS | 3052 | | 5.x | 3052 | | 5.x FIPS | 3052 | Total space available for certificates -------------------------------------- Although a YubiKey 5.x will allow a 3052-byte cert in one of the slots, it will not be able to store 24 certs that big. A NEO (pre-4.0), only has four slots, and will be able to hold four certs of the maximum length. | YubiKey Version | Maximum Total Cert
Space Available | Number of Certs
at Size | Number of Certs
at Maximum Size | | --- | --- | --- | --- | | before 4.0 (e.g. NEO) | 8100 | 4 certs at 2025 bytes | 4 certs at 2025 bytes | | 4.x | about 49,800 | 24 certs at 2075 bytes | 16 certs at 3052 bytes | | 4.x FIPS | about 49,800 | 24 certs at 2075 bytes | 16 certs at 3052 bytes | | 5.x | about 50,000 | 24 certs at 2084 bytes | 16 certs at 3052 bytes | | 5.x FIPS | about 49,890 | 24 certs at 2079 bytes | 16 certs at 3052 bytes | Note that that total amount of storage on a YubiKey (for certs, for PUT DATA objects, etc.) is about 51,000 bytes. Hence, if a YubiKey is loaded with 49,000 bytes of certs, then there will be very little space left for anything else. Summary ------- On a 5.x YubiKey, it is possible to store a 3,052-byte cert in a slot. If a cert is bigger than 3,052 bytes, the YubiKey will reject it and the SDK will throw an exception. It is certainly possible to store several 3,052-byte certs on a 5.x YubiKey, but once the total size limit is reached, the YubiKey won't be able to store any more, even if some of the slots are empty. However, because a real world application will probably not use certs bigger than 2,000 bytes, it is not likely it will ever run into a total space limitation and will be able to store up to 24 certs. [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-piv/cert-size.md/#L1) --- # ECDSA signatures ##### Table of Contents ECDSA signatures ================ A common misconception is that DSA and ECDSA, when generating the actual signature, will perform an encryption operation. However, that is not the case. The DSA or ECDSA signing operation will mathematically "combine" the digest of the data to sign with the private key and a random value to generate two values, commonly called `r` and `s`. There are mathematical operations that can then combine the digest of the signed data along with the public key and the `s` value to generate `r` again. That is, if using the digest, public key, and `s` in a particular way produces `r`, the signature verifies. If not, the signature does not verify. Back in the 1990s, the first DSA standards were specifying how the algorithm operated but also how to present the signature. Someone verifying a DSA signature must know how the signer has organized the `r` and `s`. There were generally two ways to do so. (1) Concatenation r || s where r and s are the same length, prepend 00 bytes if necessary For example, e91a49c5147db1a9aaf244f05a434d6486931d2d00526db078b05edecbcd1eb4a208f3ae1617ae82 |<--- r --->||<--- s --->| (2) DER/BER encoding of SEQUENCE { r INTEGER, s INTEGER } For example, DER: 30 2c 02 15 00 e9 1a 49 c5 14 7d b1 a9 aa f2 44 f0 5a 43 4d 64 86 93 1d 2d 02 13 52 6d b0 78 b0 5e de cb cd 1e b4 a2 08 f3 ae 16 17 ae 82 BER: 30 2e 02 15 00 e9 1a 49 c5 14 7d b1 a9 aa f2 44 f0 5a 43 4d 64 86 93 1d 2d 02 15 00 00 52 6d b0 78 b0 5e de cb cd 1e b4 a2 08 f3 ae 16 17 ae 82 Note that the DER encoding is variable length, some signatures can be longer, some shorter depending on the values. But it is possible to build a BER encoding that is a fixed length for each key size. Virtually all standards chose to require the DER/BER encoding format. For example, if you want to follow the PKCS 10 and X.509 standards for cert requests and certificates (RFCs 2986 and 5280), you will build and read DSA and ECDSA signatures as the BER encoding. .NET Base Class Libraries (BCL) ------------------------------- The way to build and verify ECDSA signatures in the BCL is with the `ECDsa` class. For example, to create a signature, load the private key and call `SignData`. var eccCurve = ECCurve.CreateFromValue("1.2.840.10045.3.1.7"); var eccParams = new ECParameters { Curve = (ECCurve)eccCurve }; eccParams.Q.X = publicPointXCoord; eccParams.Q.Y = publicPointYCoord; eccParams.D = privateValue; using var ecdsaObject = ECDsa.Create(eccParams); byte[] signature = ecdsaObject.SignData(dataToSign, HashAlgorithmName.SHA256); The `SignData` method will use the specified hash algorithm to digest the input `dataToSign` and create an ECDSA signature using that digest along with the private key and a random value. There is another method, `SignHash` that will create the signature from the digest you provide. The result of the signing operation is a byte array. But which format of signature is it? The BCL does not document the format of the resulting signature, so you will have to execute the method and examine the result to find out. It turns out this method produces the concatenation of `r` and `s`, not the DER/BER encoding standards specify. Is it possible to get the BER/DER encoding? Yes and no. There is a method that allows you to specify the format of the signature. byte[] signature = ecdsaObject.SignData( dataToSign, HashAlgorithmName.SHA256, DSASignatureFormat.Rfc3279DerSequence); Note that this will produce the DER encoding, so its length is variable. However, there is a problem with this method, namely it was not introduced until .NET 5.0. That means if you are using, for example, .NET Standard 2.0 (as the .NET YubiKey SDK does), then this method is not available. Similarly, there are methods (`VerifyData` and `VerifyHash`) to verify signatures. The YubiKey ECDSA signature --------------------------- When you call on the YubiKey to sign data using ECDSA, the result will be the DER encoding. Converting the signature ------------------------ If you have a signature in DER/BER form and need to use the BCL to verify, but are not using .NET 5.0, you will need to convert to the concatentation that the `ECDsa` class needs. Similarly, if you build a signature using the BCL and you need to send it in the DER/BER format, you will need to convert. The PIV sample code contains a class that can perform the conversion. See `Yubico.YubiKey/examples/PivSampleCode/Converters/DsaSignatureConverter.cs`. [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-piv/ecdsa-signatures.md/#L1) --- # Elliptic Curve Diffie-Hellman key agreement ##### Table of Contents Elliptic Curve Diffie-Hellman key agreement =========================================== If a slot contains an ECC key (PivAlgorithm.EccP256, PivAlgorithm.EccP384), there are two operations it can perform: signing (ECDSA) and key agreement (EC Diffie-Hellman, or ECDH). An ECDH operation does not encrypt data. Rather, it generates a shared secret. Here is a description of "classical" ECDH. * Two correspondents agree to an EC parameter set. * Phase 1: Each correspondent generates a private and public value. * The correspondents send each other the public values. * Phase 2: Each correspondent uses their own private value with the other correspondent's public value to generate a secret. * If the two use the same parameters, they will generate the same secret. The value each correspondent generates is a point on the curve. The ECDH algorithm is defined as using the x-coordinate of that resulting point. The correspondents can now use this "shared secret" as a key, or as the foundation of a key derivation operation. They share a key. Or we can say they agree on a key, hence the term "Key Agree". Generally they will use the key to encrypt bulk data in a message or conversation. An eavesdropper can see the parameters and public values, but without at least one of the private values, cannot compute the shared secret. This is similar to the RSA digital envelope. In that system, a sender generates a session key, encrypts it using the recipient's public key, and encrypts the bulk data with the session key. The recipient uses their private key to decrypt the session key, then uses the session key to decrypt the bulk data. Note that the RSA algorithm can be used for encryption and signing, but cannot be used for key agreement. ECC can be used for signing and key agreement. It is possible to use ECC for encryption as well. It is generally called ECES (Elliptic Curve Encryption Scheme) or EC ElGamal. However, the .NET Base Class Libraries (BCL) and the YubiKey do not support EC encryption. "Perfect Forward Secrecy" ------------------------- One of the strengths of Diffie-Hellman in general (EC and the original formulation based on large prime numbers) is that it is possible to use different public and private values each time an operation is performed. That means if an attacker is able to break one message, session key, or even a private key, it does not help in breaking other messages. In other words, each message must be attacked independently. This is known as "perfect forward secrecy". In contrast, if an attacker breaks one RSA private key, all digitial envelope messages, old and new, that used or will use that key are compromised. Perfect forward secrecy only applies if different public and private values are used each time. Man-in-the-middle attack ------------------------ One of the easiest ways to attack DH is to intercept messages between two participants. Suppose Alice wants to communicate with Bob, and the two decide to use ECDH with a particular parameter set. But suppose Eve is able to intercept all of Bob's incoming and outgoing messages. When Alice sends her public value, Eve intercepts and keeps it for herself. Eve passes on to Bob her own public value. When Bob sends his public value, Eve intercepts, keeps that public value, and sends her own public value to Alice. Alice will use her private value and Eve's public value to derive a session key. Call this Key-AE. Eve will use her private value and Alice's public value to derive Key-AE. Similarly, Bob will derive Key-BE. Eve will aso be able to derive Key-BE. When Alice sends a message to Bob encrypted with Key-AE, Eve will intercept, decrypt it, store it, encrypt the recovered message using Key-BE, then send this newly encrypted message to Bob. Bob will be able to decrypt using Key-BE. Neither Bob nor Alice know that they are communicating with Eve. To prevent this attack, we need to use certificates. Key agreement with public and private keys ------------------------------------------ In classical ECDH, each party generates a public and private value. However, it is possible to extract a public value from an EC public key and the private value from the partner EC private key. That is, you can generate an EC key pair, then use the keys to perform the Key Agreement operation. Generating the key pair is equivalent to Phase 1. Combining your private key with the correspondent's public key is Phase 2. This means that in order to perform Phase 2, the software (or YubiKey) will need to extract the public and private values from the keys, then perform classical ECDH. Now that we have keys, we can build certificates. Alice and Bob generate key pairs and obtain certificates. Instead of exchanging public values, they exchange certificates. If Eve intercepts Alice's certificate and sends her own certificate to Bob, he will reject it because the name on that certificate is not Alice. Or if Eve builds a new cert with Alice's name, Bob will still be able to reject it because it does not chain to one of his trusted roots. Back to perfect forward secrecy ------------------------------- Suppose you build a system where each participant has a key pair and a certificate, and you use these certs each time someone sends a message. For example, if Alice and Bob want to communicate, each will always use their private key and the public key found in the other party's cert. In this case, each message between Alice and Bob will use the same public and private values, and hence derive the same session key. A message between Alice and Carlos will be encrypted using a key derived from Alice's and Carlos's key pairs, so it will be different from the key used by Alice and Bob. But each message between Alice and Carlos will use the same session key. If an attacker is able to break Alice's private key, all communication between Alice and Bob, and in fact between Alice and anyone else, is compromised. This is not perfect forward secrecy. Hence, to use ECDH with keys while retaining pefect forward secrecy, each participant must generate a new key pair each message. This is not an easy task. It is much easier to obtain a certificate for a particular public key, and have each sender use that certificate to extract a public key. And then each sender can use their private key, and send to the recipient their certificate. In order to have forward perfect secrecty and avoid the man-in-the-middle attack, it seems that each time anyone wants to send someone else a message, they must generate a new key pair and obtain a new cert. And then the sender must contact the recipient and request that they generate a new key pair and obtain a new certificate. Only then can someone start a new session. Solution: signatures -------------------- The solution is not to create a new certificate for each ECDH public key, but rather to sign messages containing the public value. Alice has a key pair with a certificate. Let's say her key pair is ECC. Because she will be using it to sign, let's call this her ECDSA key. When she wants to communicate with Bob, she performs this modified classical DH. * Phase 1: Alice generates a new EC key pair. * She sends this newly generated ECDH public key to Bob, this message signed using her ECDSA private key. The message also contains her cert. * Bob gets this message and verifies it using Alice's cert (chaining to a trusted root). * Phase 1: Bob generates a new EC key pair. * Bob sends to Alice his public value, signed using his public key (it can be RSA). The message contains his cert. * Alice gets this message and verifies it using Bob's cert (chaining to a trusted root). * Phase 2: Both Alice and Bob have the necessary elements to each derive the session key. If Eve intercepts a message and forwards her own public value, it will be rejected if it is not signed. If she signs it using her own private key, then it will not verify or will not chain to the trusted root, and will be rejected. Conclusion ---------- What this all means is that to use ECDH with protections against the man-in-the-middle attack, you must combine it with certificates. To easily achieve perfect forward secrecy, you should sign the messages that contain the public values (as opposed to obtaining a certificate for every message). Incidentally, this is one of the reasons many systems require multiple keys and certs. That is, a standard will often specify that each participant create a signing key and cert and a separate encryption key and cert. If a signing key is broken, an attacker can impersonate a participant in the future, but still cannot read any older messages. [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-piv/key-agreement.md/#L1) --- # Public key handling ##### Table of Contents Public key handling =================== The Yubico .NET SDK provides type-safe public key classes implementing `IPublicKey` for working with keys generated on or imported to YubiKeys. Supported key types ------------------- * **RSA keys**: 1024, 2048, 3072, 4096-bit * **EC keys**: NIST P-256, P-384 curves * **Curve25519 keys**: Ed25519 (signing), X25519 (key agreement) Public key formats ------------------ One of the unfortunate problems of public key cryptography is the myriad ways to represent public keys. Part of this is due to the fact that different algorithms have different elements. For example, an RSA public key consists of two integers: modulus and public exponent. On the other hand, an "Fp" Elliptic Curve (EC) private key consists of the following elements: | EC public key component | EC public key subcomponent | | --- | --- | | curve | prime | | | order | | | coefficients (a, b, c) | | | base point (x, y) | | public point | x coordinate | | | y coordinate | Standard curves (such as NIST P-256) can be represented by an object identifier (OID) and public point (x,y). There is more than one standard that defines how to represent public keys. The most common definitions are `SubjectPublicKeyInfo` from X.509 (the certificate standard used by the vast majority of applications) and PEM (Privacy-Enhanced Mail). PEM ([RFC 7468](https://tools.ietf.org/html/rfc7468) ) was created to describe how to use public key cryptography to build secure email, but it has elements that turned out to be useful to cryptography in general, including its representation of keys. Fortunately, there is some overlap. The vast majority of applications will use the `SubjectPublicKeyInfo` or the PEM "PUBLIC KEY" (which wraps a `SubjectPublicKeyInfo`). `SubjectPublicKeyInfo` is popular because it contains algorithm information in addition to the actual key data. That is, a public key in this format contains an `AlgorithmIdentifier` specifying the algorithm and any parameters as well as the key data specific to that algorithm. There are C# classes that will build or parse these structures, although it will still require some work on your part. This page will show how to export public keys in `SubjectPublicKeyInfo` and PEM formats from public key objects generated by the YubiKey, as well as building public key objects a YubiKey can read from `SubjectPublicKeyInfo` and PEM. Factory methods --------------- PIV defines its own format of encoding public keys. However, the SDK's PIV application APIs that work with public keys require them to be instances of the `PublicKey` class. Hence, your application will need to be able to "convert" between `SubjectPublicKeyInfo` and `PublicKey`. ### RSA public keys // From SubjectPublicKeyInfo format byte[] spkiBytes = // your SubjectPublicKeyInfo bytes RSAPublicKey rsaKey = RSAPublicKey.CreateFromSubjectPublicKeyInfo(spkiBytes); // From RSA parameters using var rsa = RSA.Create(2048); RSAParameters parameters = rsa.ExportParameters(false); // public only RSAPublicKey rsaKey = RSAPublicKey.CreateFromParameters(parameters); ### EC public keys // From SubjectPublicKeyInfo format byte[] spkiBytes = // your SubjectPublicKeyInfo bytes ECPublicKey ecKey = ECPublicKey.CreateFromSubjectPublicKeyInfo(spkiBytes); // From EC parameters using var ecdsa = ECDsa.Create(ECCurve.NamedCurves.nistP256); ECParameters parameters = ecdsa.ExportParameters(false); // public only ECPublicKey ecKey = ECPublicKey.CreateFromParameters(parameters); // From public point (0x04 || X-coordinate || Y-coordinate) ReadOnlyMemory publicPoint = [/* your uncompressed EC point */] ECPublicKey ecKey = ECPublicKey.CreateFromValue(publicPoint, KeyType.ECP256); ### Curve25519 public keys // From SubjectPublicKeyInfo format byte[] spkiBytes = // your SubjectPublicKeyInfo bytes Curve25519PublicKey curve25519Key = Curve25519PublicKey.CreateFromSubjectPublicKeyInfo(spkiBytes); // From public point bytes ReadOnlyMemory publicPoint = [/* your uncompressed EC point */]; Curve25519PublicKey ed25519Key = Curve25519PublicKey.CreateFromValue(publicPoint, KeyType.Ed25519); Curve25519PublicKey x25519Key = Curve25519PublicKey.CreateFromValue(publicPoint, KeyType.X25519); Generating key pairs -------------------- When you generate a new key pair in a YubiKey's PIV application, you are given the public key, which is returned as an instance of the `PublicKey` class. From this class, you can obtain important information about the key, including `KeyDefinition` and `KeyType`. Depending on the specific class, `Parameters` (EC and RSA) and `PublicPoint` (EC and Curve25519) are also included. using var pivSession = new PivSession(yubiKey); pivSession.KeyCollector = yourKeyCollector; pivSession.AuthenticateManagementKey(); // Generate returns the public key IPublicKey publicKey = pivSession.GenerateKeyPair( PivSlot.Authentication, KeyType.Ed25519, PivPinPolicy.Once, PivTouchPolicy.Never); // Type-check for specific key properties if (publicKey is Curve25519PublicKey ed25519Key) { Console.WriteLine("Generated public key: " + ed25519Key.PublicPoint); } Exporting public keys --------------------- // Export to SubjectPublicKeyInfo format (standard) byte[] spkiBytes = publicKey.ExportSubjectPublicKeyInfo(); // Access key-specific properties if (publicKey is RSAPublicKey rsaKey) { RSAParameters rsaParams = rsaKey.Parameters; byte[] modulus = rsaParams.Modulus; byte[] exponent = rsaParams.Exponent; } if (publicKey is ECPublicKey ecKey) { ECParameters ecParams = ecKey.Parameters; ReadOnlyMemory publicPoint = ecKey.PublicPoint; // 0x04 || X || Y format byte[] xCoord = ecParams.Q.X; byte[] yCoord = ecParams.Q.Y; } if (publicKey is Curve25519PublicKey curve25519Key) { ReadOnlyMemory publicPoint = curve25519Key.PublicPoint; } PEM format conversion --------------------- // Export to PEM format byte[] spkiBytes = publicKey.ExportSubjectPublicKeyInfo(); string pemKey = "-----BEGIN PUBLIC KEY-----\n" + Convert.ToBase64String(spkiBytes, Base64FormattingOptions.InsertLineBreaks) + "\n-----END PUBLIC KEY-----"; // Import from PEM format string pemData = // your PEM PUBLIC KEY string base64Data = pemData .Replace("-----BEGIN PUBLIC KEY-----\n", "") .Replace("\n-----END PUBLIC KEY-----", ""); byte[] spkiBytes = Convert.FromBase64String(base64Data); IPublicKey publicKey = RSAPublicKey.CreateFromSubjectPublicKeyInfo(spkiBytes); // or ECPublicKey, etc. ##### Note When importing a public key in PEM format, there are a number of possible header and footer combinations, including the following: -----BEGIN PUBLIC KEY----- -----END PUBLIC KEY----- -----BEGIN RSA PUBLIC KEY----- -----END RSA PUBLIC KEY----- -----BEGIN EC PUBLIC KEY----- -----END EC PUBLIC KEY----- ### Determining the algorithm when importing a public key in PEM format If you have a byte array that contains the `SubjectPublicKeyInfo`, and you want to build a `PublicKey`, you will need to first determine the public key algorithm. Once you know the algorithm, you can use the appropriate C# class to read the encoded data (for example, `RSAPublicKey`, `ECPublicKey`, or `Curve25519PublicKey` ). The algorithm is specified in the key data itself. However, the .NET Base Class Library does not have a class that can parse `SubjectPublicKeyInfo` and build the appropriate object. The only methods that can read this encoding are in classes for the specific algorithms. That is, the RSA class can read `SubjectPublicKeyInfo` only if the input data is an RSA key, the ECDsa class can read it only if the input data is an ECC key, etc. One possible workaround would be to supply the encoded key to the RSA class and if it works, we have an RSA key. If it does not work, give the encoded key to the ECDsa class. However, if the RSA class gets an encoded key that is not RSA, it throws an exception, and using exceptions to determine code flow is not best practice. To determine the algorithm of an imported key, we need to open up the encoding and read the object identifier (OID) of the `AlgorithmIdentifier`. And to find the OID, we need to decode the DER encoding of `SubjectPublicKeyInfo`. `SubjectPublicKeyInfo` is defined as: SubjectPublicKeyInfo ::= SEQUENCE { algorithm AlgorithmIdentifier, subjectPublicKey BIT STRING } AlgorithmIdentifier ::= SEQUENCE { algorithm OBJECT IDENTIFIER, parameter ANY DEFINED BY algorithm OPTIONAL } This means that the DER encoding will look something like the following: 30 len // The len octets might be one, two, or three bytes long. 30 len 06 len OID bytes etc. To get to the OID, we need to read the first `30 len`, then the second `30 len`, then the `06 len`. Error handling -------------- Factory methods validate input and may throw exceptions: try { var publicKey = ECPublicKey.CreateFromValue(publicPoint, KeyType.ECP256); } catch (ArgumentException ex) { // Handle invalid parameters, key type mismatches, or malformed data } catch (CryptographicException ex) { // Handle invalid key format or cryptographic validation failures } References ---------- * [RFC 5280](https://tools.ietf.org/html/rfc5280) - SubjectPublicKeyInfo format * [RFC 7468](https://tools.ietf.org/html/rfc7468) - PEM encoding * [RFC 7748](https://tools.ietf.org/html/rfc7748) - Curve25519 and Curve448 * [SDK PIV integration tests](https://github.com/Yubico/Yubico.NET.SDK/tree/HEAD/Yubico.YubiKey/tests/integration/Yubico/YubiKey/Piv) * SDK unit tests for additional usage examples: * [Curve25519PublicKeyTests](https://github.com/Yubico/Yubico.NET.SDK/blob/HEAD/Yubico.YubiKey/tests/unit/Yubico/YubiKey/Cryptography/Curve25519PublicKeyTests.cs) * [ECPublicKeyTests](https://github.com/Yubico/Yubico.NET.SDK/blob/HEAD/Yubico.YubiKey/tests/unit/Yubico/YubiKey/Cryptography/ECPublicKeyTests.cs) * [RSAPublicKeyTests](https://github.com/Yubico/Yubico.NET.SDK/blob/HEAD/Yubico.YubiKey/tests/unit/Yubico/YubiKey/Cryptography/RSAPublicKeyTests.cs) [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-piv/public-keys.md/#L1) --- # Overview of the SDK ##### Table of Contents Overview of the SDK =================== The YubiKey SDK for Desktop is a collection of libraries, samples, and documentation that target the .NET ecosystem. It supports the macOS and Windows operating systems and is capable of speaking to USB and NFC based YubiKeys. Use the NuGet package manager to install the SDK into your project. You can learn more about this process on the [how to install the SDK](https://docs.yubico.com/yesdk/users-manual/getting-started/how-to-install.html) page. Supported platforms ------------------- Modern .NET supports more than just Microsoft Windows, and so do we. Support for macOS is built in, and has been tested on both Intel and Apple Silicon (i.e. M1) platforms. (Apple Silicon is supported through Rosetta 2.) We also support common Linux distributions such as Debian, Ubuntu, RHEL, and CentOS. Other distros may still work, but they have not been tested by the SDK team. Future distribution and platform support will be driven by customer interest. This SDK targets .NET Standard 2.0, allowing for a wide reach of .NET platforms. See [this page](https://docs.microsoft.com/en-us/dotnet/standard/net-standard) for more information on what .NET implementations support .NET Standard 2.0. Note that while this SDK may build with Xamarin and Mono, only the Windows and macOS operating systems are supported at this time. Additionally, while .NET Framework 4.6.x is listed as implementing Standard 2.0, this is not entirely true. The SDK relies on certain cryptographic functionality that is defined in the standard but not actually implemented in Framework 4.6.x. | Platform | Architecture | Version | | --- | --- | --- | | macOS | x64, arm64 | Catalina, Big Sur | | Windows | x86, x64, arm64 | Windows 10, Windows 11 | | Linux | x64, arm64 | Debian, Ubuntu, RHEL, CentOS | Supported YubiKey applications ------------------------------ The YubiKey is a versatile security key that supports numerous standards and protocols. This SDK offers full support for integrating with Yubico OTP, along with the OATH, PIV, and FIDO U2F standards. ### OTP Yubico OTP is a simple yet strong authentication mechanism that is supported by all YubiKeys out of the box. Yubico OTP can be used as the second factor in a 2-factor authentication scheme or on its own, providing 1-factor authentication. Read more about OTP [here](https://docs.yubico.com/yesdk/users-manual/application-otp/otp-overview.html) . ### OATH The Initiative for Open Authentication (OATH) is an organization that specifies two open one-time password standards: HMAC OTP (HOTP) and the more familiar Time-based OTP (TOTP). Read more about OATH [here](https://docs.yubico.com/yesdk/users-manual/application-oath/oath-overview.html) . ### PIV Personal Identity Verification (PIV), or FIPS 201, is a US government standard. It enables RSA signing and encryption, along with ECC signing and key agreement operations using a private key stored on a smart card (such as the YubiKey 5). PIV is primarily used for non-web applications. It has built-in support under Windows and can be used on macOS as well. Read more about PIV [here](https://docs.yubico.com/yesdk/users-manual/application-piv/piv-overview.html) . ### FIDO U2F U2F is an open authentication standard that enables keychain devices, mobile phones and other devices to securely access any number of web-based services - instantly and with no drivers or client software needed. U2F was created by Google and Yubico, with contribution from NXP, and is today hosted by the open-authentication industry consortium [FIDO Alliance](https://fidoalliance.org/) . The technical specifications were launched in late 2014, including native support in Google Accounts and Chrome, and have since resulted in a thriving ecosystem of hardware, software and service providers. Read more about FIDO U2F [here](https://docs.yubico.com/yesdk/users-manual/application-u2f/fido-u2f-overview.html) . ### FIDO2 FIDO2 is the "second generation" of the FIDO open authentication standard. It is similar to U2F in that implementations allow instant secure access to web-based services, with no drivers or client software needed. FIDO2 was created by the [FIDO Alliance](https://fidoalliance.org/) -- a consortium of dozens of tech and other companies as well as government organizations from around the world -- along with the [W3C](https://www.w3.org/) (World Wide Web Consortium). The technical specifications for FIDO2 were launched in 2018. Today, many [browsers and mobile platforms support FIDO2](https://support.yubico.com/hc/en-us/articles/360016615020-Operating-system-and-web-browser-support-for-FIDO2-and-U2F) . Read more about FIDO2 [here](https://docs.yubico.com/yesdk/users-manual/application-fido2/fido2-overview.html) . ### YubiHSM Auth YubiHSM Auth is a YubiKey CCID application that stores the long-lived credentials used to establish secure sessions with a YubiHSM 2. The secure session protocol is based on Secure Channel Protocol 3 (SCP03). YubiHSM Auth is supported by YubiKey firmware version 5.4.3. YubiHSM Auth uses hardware to protect these long-lived credentials. In addition to providing robust security for the YubiHSM Auth application itself, this hardware protection subsequently increases the security of the default password-based solution for YubiHSM 2's authentication. Read more about YubiHSM Auth [here.](https://docs.yubico.com/yesdk/users-manual/application-yubihsm-auth/yubihsm-auth-overview.html) SDK components -------------- The YubiKey SDK is comprised of two managed assemblies: * **Yubico.YubiKey** is the primary assembly that contains all of the classes and types needed for interacting with the YubiKey. * **Yubico.Core** is a common library used by Yubico's .NET offerings and serves as a platform abstraction layer (PAL). All interaction with operating-system specific functionality is contained within this library. It also contains useful utility classes that can be used for encoding and decoding different kinds of data, such as Base32, Tag-Length-Value (TLV), and ModHex. * **Yubico.NativeShims** is an internal _unmanaged library_ that provides a stable Application Binary Interface (ABI) to the P/Invoke Foreign Function Interface (FFI) in Yubico.Core. All components of the SDK are built to the .NET Standard 2.0 specification. This means that either .NET Framework, .NET Core, or Mono can be used as the underlying runtime, so long as the runtime version implements .NET Standard 2.0 or higher. ![Layer diagram of SDK](https://docs.yubico.com/yesdk/images/sdk_layers_diagram.png "Layers of the SDK") The SDK takes as few dependencies as possible. Most of the functionality is built directly on top of the .NET base class libraries or on top of the platform native APIs (called through P/Invoke). ### Yubico.YubiKey Yubico.YubiKey is where concepts like a YubiKey take shape. This assembly builds on top of Yubico.Core’s platform abstractions for USB and NFC to create a model for what a YubiKey looks like. The Yubico.YubiKey assembly can be broken down into three main areas: YubiKey device definitions, low-level commands, and application libraries. #### YubiKey definition Developing against the .NET YubiKey SDK, one should only ever have to talk about a YubiKey in the abstract. A minimal interface for what defines the lowest common denominator (including Security Keys) should be all that is required, agnostic to the physical transport on which it was discovered. In practice, the SDK will need to be aware of and implement three different kinds of YubiKeys: USB, NFC, and EAP. The decision to slice implementations at this level is due to the disparate nature in which communication is performed over each transport. USB must be aware of multiple interfaces (Keyboard, CCID, HID FIDO), whereas NFC and EAP only have one. NFC has to deal with potentially high failure and retry rates, while the others may not. Additionally, the way a YubiKey is discovered over each transport is different. On USB, a combination of Vendor ID and Product ID is used. NFC, the ATR is used. EAP, the vendor protocol. #### Command APIs Communication with a YubiKey, regardless of physical or logical transport, essentially boils down to an APDU. If CCID / ISO7816 is not being used, then the alternate command (say, a HID frame) can usually be derived from the APDU. The fundamental part of the Yubico.YubiKey assembly will be a near 1:1 mapping between a "command" class and a YubiKey command or APDU. These classes will essentially be a developer-friendly, parameterized method for constructing raw APDUs to send to the YubiKey. While exposed by the public API surface, it is not expected that external developers would choose to program applications at this layer. The low-level command definitions are to support Yubico internal applications, as well as the final higher-level APIs described in the next section. One important concept to note: these command classes are essentially free-standing. They can be used with or without the presence of a YubiKey. When instantiated, a developer has the ability to serialize the command into a byte stream that can be stored or sent to a YubiKey via alternate means. Additionally, if a command expects a response, a response class will be present which will be capable of deserializing a byte stream into a strongly typed, parsed representation of the response. #### Session APIs The session APIs round out the YubiKey SDK. They represent the connection to an application session on the YubiKey. From this session, you can interact with the application in an intuitive and high level way. These APIs are the ones that most developers will want to interact with when developing software for the YubiKey. Many operations are either a single method call, or employ a set of easy to use helper classes to construct the necessary input. For example, if you want to use the PIV smart card functionality and generate a keypair using the YubiKey, you could write code like the following: using System.Linq; using Yubico.YubiKey; // Necessary for the YubiKey definition using Yubico.YubiKey.Piv; // Use the PIV functionality of the SDK public static class Program { public static void Main() { // The SDK may return zero, one, or more YubiKeys. If there // was more than one, let's simply use the first. IYubiKeyDevice yubiKey = YubiKeyDevice.FindAll().First(); // Open a sesion to the PIV application on the YubiKey that // we selected in the previous step. using (PivSession piv = new PivSession(yubiKey)) { // Generate a public-private keypair var publicKey = piv.GenerateKeyPair( PivSlot.CardAuthentication, PivAlgorithm.Rsa2048); } } } With a single (wrapped) line, you are able to generate a 2048-bit RSA keypair in the Card Authentication slot. Many of the YubiKey operations are able to be reduced to a single line of code line this. Look for the [OtpSession](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.OtpSession.html) , [OathSession](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Oath.OathSession.html) , and [PivSession](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.PivSession.html) classes to get started. ### Yubico.Core The Yubico.Core library contains a set of utility classes that are not specific to a particular Yubico product. It also contains all of the platform abstraction logic required for other .NET-based Yubico libraries to run across different platforms and operating systems. For most consumers of the SDK, this library will automatically be included when you reference the `Yubico.YubiKey` NuGet package. [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/getting-started/overview-of-sdk.md/#L1) --- # YubiKey-host device communication ##### Table of Contents YubiKey-host device communication ================================= YubiKeys can, depending on their components, communicate with host devices over USB, NFC, and/or Lightning interfaces. USB communication ----------------- In order for the OTP application on the YubiKey to submit passwords ([Yubico OTPs](https://docs.yubico.com/yesdk/users-manual/application-otp/yubico-otp.html) , [OATH HOTPs](https://docs.yubico.com/yesdk/users-manual/application-otp/hotp.html) , and [static passwords](https://docs.yubico.com/yesdk/users-manual/application-otp/static-password.html) ) through a host device over USB, it must utilize the [USB HID (Human Interface Device)](https://www.usb.org/hid) communication protocol. The HID standard allows compliant hosts and USB peripherals, like keyboards and mice, to communicate without the need for specialized drivers. The YubiKey essentially emulates a HID keyboard; each key on a keyboard is represented by a HID [usage ID](https://www.usb.org/sites/default/files/documents/hut1_12v2.pdf#page=53) (in decimal and hexadecimal), which is collected into a HID usage report (sometimes referred to as a message). The YubiKey generates these usage reports to simulate keystrokes, and the usage reports are decoded by the host into the characters of a password. ### HID reports A HID report consists of eight bytes: the first byte represents a set of modifier key flags, the second byte is unused, and the final six bytes represent keys that are currently being pressed, sorted in the order they were pressed. With HID, modifier key flags (e.g. the left-shift button) are used to, you guessed it, modify the keys included in the final six bytes of the HID report. If modifier key flags are not included in the report, the keys will be sent in their default format (letter keys are lowercase by default). The following tables represent the bytes of a HID report and the bits in the modifier key flags byte: HID Report BytesModifier Key Flags | Byte | Description | | --- | --- | | 0 | Modifier Key Flags | | 1 | Reserved Byte | | 2 | Keypress #1 | | 3 | Keypress #2 | | 4 | Keypress #3 | | 5 | Keypress #4 | | 6 | Keypress #5 | | 7 | Keypress #6 |      | Bit | Description | | --- | --- | | 0 | Left \[Ctrl\] | | 1 | Left \[Shift\] | | 2 | Left \[Alt\] | | 3 | Left GUI\* | | 4 | Right \[Ctrl\] | | 5 | Right \[Shift\] | | 6 | Right \[Alt\] | | 7 | Right GUI\* | \* On Windows systems, this is the Windows key. To send an uppercase "A" to a host device, the YubiKey must send the following usage report: | Byte | Value | Description | | --- | --- | --- | | 0 | 0x02 | The left shift (modifier key flag bit 1) is pressed. | | 1 | 0x00 | (reserved) | | 2 | 0xe1 | Usage ID for the left shift key. | | 3 | 0x04 | Usage ID for the "A" key. | | 4 - 7 | 0x00 | Unused bytes (no more keys pressed). | ### HID keyboard layout challenges A major challenge is that HID usage IDs correspond to physical locations on a keyboard, not the characters themselves. For example, on an English language keyboard, the top row of keys spells QWERTY, and on a German language keyboard, those same keys spell QWERTZ. However, the "Y" key on the English keyboard and the "Z" key on the German keyboard are represented by the same HID usage ID of 28 (0x1c). Therefore, when [programming a YubiKey slot with a static password](https://docs.yubico.com/yesdk/users-manual/application-otp/how-to-program-a-static-password.html) , the SDK must be told which [keyboard layout](https://docs.yubico.com/yesdk/core-api/Yubico.Core.Devices.Hid.KeyboardLayout.html) the host device is configured with in order to send the correct HID usage IDs for your static password characters. ##### Note You can configure your keyboard layout in Windows regardless of the actual keyboard you have. When specifying a keyboard layout, you must be absolutely sure that every host device your key is plugged into be set to the same keyboard layout. Going back to our example, if you program your YubiKey using an English layout, and someone plugs the key into a computer configured with a German layout, then all of the “Y” characters in your static password will be interpreted as “Z”. But what should you do if you can't guarantee that the host device's keyboard layout will always be the same? And where does this leave Yubico OTPs and OATH HOTPs, which are generated by algorithms instead of manually configured by a user? To address these challenges, Yubico invented ModHex (modified hexadecimal), which is both a keyboard layout configuration and an encoding scheme. For more details, see the article on [ModHex](https://docs.yubico.com/yesdk/users-manual/application-otp/modhex.html) . Lightning communication ----------------------- The Apple Lightning connector on the YubiKey 5Ci uses the iAP communication protocol (iPod Accessory Protocol). However, iAP also has support for HID through a tunneling mechanism, which allows the OTP application on the YubiKey to send and receive HID messages when connected over Lightning. NFC communication ----------------- NFC-enabled YubiKeys communicate with host devices through close (wireless) contact with a host's NFC-reader via the [NDEF](https://docs.yubico.com/yesdk/users-manual/application-otp/ndef.html) (NFC Data Exchange Format) protocol. Unlike HID communication, where passwords are sent as bytes that represent HID usage reports, NDEF sends text. When a YubiKey is scanned by an NFC reader, the key emits a URL containing the web address of an OTP validation server followed by the OTP. ##### Note NFC is only compatible with Yubico OTPs and OATH HOTPs--static passwords can only be communicated through HID usage reports. [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-otp/hid.md/#L1) --- # Static passwords ##### Table of Contents Static passwords ================ The OTP application [slots](https://docs.yubico.com/yesdk/users-manual/application-otp/slots.html) on the YubiKey are capable of storing static passwords in place of other configurations. As the name implies, a static password is an unchanging string of characters, much like the passwords you create for various online accounts. When a slot containing a static password is touch-activated, the password characters are sent to the host device as keyboard input (more specifically, as [USB HID reports](https://docs.yubico.com/yesdk/users-manual/application-otp/hid.html) ). ##### Note Because static password characters are stored on the YubiKey as their corresponding HID usage IDs, sometimes referred to as "scan codes," they can only be communicated correctly when the YubiKey is connected to a host device over USB or Lightning. In this case, a host device will translate the HID usage IDs to characters according to the HID communication protocol. NFC-enabled YubiKeys use the [NDEF](https://docs.yubico.com/yesdk/users-manual/application-otp/ndef.html) communication protocol to submit passwords wirelessly to host devices as ASCII/UTF characters. Because NDEF expects input (the password) to already be in ASCII/UTF characters, it will send the HID usage IDs to the host device as-is, and the host will not translate them from HID to ASCII/UTF. As you can imagine, static passwords are not as secure as other configurations, such as [Yuibco OTPs](https://docs.yubico.com/yesdk/users-manual/application-otp/yubico-otp.html) , but their length and complexity still make them resistant to guessing. For this reason, we do NOT recommend using static passwords unless they are required for use with legacy systems for which other configurations would not be compatible. Static password configuration ----------------------------- Static passwords can be either randomly generated or manually set by a developer. Both options require configuration via the API's [ConfigureStaticPassword()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.OtpSession.html#Yubico_YubiKey_Otp_OtpSession_ConfigureStaticPassword_Yubico_YubiKey_Otp_Slot_) method. Please see [How to program a slot with a static password](https://docs.yubico.com/yesdk/users-manual/application-otp/how-to-program-a-static-password.html) for examples. ##### Note Each OTP application slot may store one generated or user-defined password. If you try to configure a slot with both, you will receive a `System.InvalidOperationException`. ### Generate a password The [GeneratePassword()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.ConfigureStaticPassword.html#Yubico_YubiKey_Otp_Operations_ConfigureStaticPassword_GeneratePassword_System_Memory_System_Char__) method allows you to generate a random password of a specified length (up to 38 characters) when configuring a slot with `ConfigureStaticPassword()`. If desired, the SDK can generate passwords using the [ModHex](https://docs.yubico.com/yesdk/users-manual/application-otp/modhex.html) character set, meaning that each character of the static password will be one of the 16 ModHex characters. This ensures that the generated password will be interpreted correctly by host devices, regardless of which keyboard layout they are configured with (e.g. English, German, etc). ##### Note `GeneratePassword()` can be configured to use any keyboard layout (e.g. US English) in the [KeyboardLayout](https://docs.yubico.com/yesdk/core-api/Yubico.Core.Devices.Hid.KeyboardLayout.html) class. ### Set a password The [SetPassword()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.ConfigureStaticPassword.html#Yubico_YubiKey_Otp_Operations_ConfigureStaticPassword_SetPassword_System_ReadOnlyMemory_System_Char__) method allows you to set the static password to anything of your choosing (up to 38 characters in length). Any key may be used as part of the password (including uppercase letters or other modified characters). However, you must specify the host device's [keyboard layout](https://docs.yubico.com/yesdk/core-api/Yubico.Core.Devices.Hid.KeyboardLayout.html) , as that determines which HID usage IDs will be stored on the YubiKey (HID usage IDs for some characters can vary across different keyboard layouts). If your password contains characters that are not present in your chosen keyboard layout, a `System.InvalidOperationException` will be thrown. [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-otp/static-password.md/#L1) --- # Yubico OTP ##### Table of Contents Yubico OTP ========== A Yubico OTP (one-time password) is a unique 44-character string that is generated by the YubiKey when it is touched ( while plugged into a host device over [USB or Lightning](https://docs.yubico.com/yesdk/users-manual/application-otp/hid.html) ) or scanned by an [NFC reader](https://docs.yubico.com/yesdk/users-manual/application-otp/ndef.html) . ##### Note More specifically, the OTP is generated when an OTP application [slot](https://docs.yubico.com/yesdk/users-manual/application-otp/slots.html) that is configured for Yubico OTP is activated. If a YubiKey is connected to a host over USB or Lightning, slot activation occurs when the key is touched, and the duration of touch determines which slot is activated. If a YubiKey is scanned by an NFC reader, the slot that is pointed to by the OTP application's [NDEF tag](https://docs.yubico.com/yesdk/users-manual/application-otp/how-to-configure-ndef.html) will activate. The OTP is made up of various YubiKey device fields and encrypted with a unique 128-bit AES (Advanced Encryption Standard) key. Yubico OTPs look similar to the following: ccccccjlkgjlevtdernkbbnrrvhcvdbljgchbgbdbvgk You'll notice that the example OTP above only includes a subset of Latin alphabet characters. This is because Yubico OTPs are only represented by the 16 [ModHex](https://docs.yubico.com/yesdk/users-manual/application-otp/modhex.html) characters. When YubiKeys are connected to a host device over USB or Lightning, OTPs are communicated to the host via the HID communication protocol. The YubiKey acts like a keyboard, with the characters of the OTP being sent to the host as key presses. ModHex allows Yubico OTPs to be intrepreted correctly by hosts, regardless of the host's keyboard language configuration. For more information on how this works and why it's important, please see the articles on [HID communication](https://docs.yubico.com/yesdk/users-manual/application-otp/hid.html) and [ModHex](https://docs.yubico.com/yesdk/users-manual/application-otp/modhex.html) . Yubico OTPs can be used for user authentication in single-factor and two-factor authentication scenarios. In order to authenticate a user with a Yubico OTP, the OTP must be checked to confirm that it is both associated with the user account in question _and_ valid. Verifying OTPs is the job of the validation server, which stores the YubiKey's AES key and uses it to decrypt and validate OTPs. Off-the-shelf YubiKeys are preconfigured with a Yubico OTP in the short-press slot (for NFC-enabled YubiKeys, the NDEF tag is also pointed to the short-press slot). The OTP secrets are uploaded to Yubico's validation server (YubiCloud) at the time of manufacturing, which enables out-of-the-box OTP validation functionality over USB/Lightning and NFC. If you have an off-the-shelf YubiKey and would like to demo the two-factor OTP authentication experience, check out the [Yubico Playground](https://demo.yubico.com/) . ##### Note If you reconfigure the short-press slot of an off-the-shelf key, you will not be able to revert back to the original Yubico OTP configuration that was set up during manufacturing. OTP secrets cannot be extracted from the device. The .NET SDK provides developers with the resources to build Yubico OTP configuration functionality into their applications. More specifically, the API includes functions that allow you to configure either slot with a Yubico OTP and customize how the OTP is sent to host devices. Components of a Yubico OTP -------------------------- Yubico OTPs are 44 [ModHex](https://docs.yubico.com/yesdk/users-manual/application-otp/modhex.html) characters long. The first 12 characters (6 bytes of binary data) represent the key's public ID--this remains constant across all OTPs generated by a single Yubico OTP configuration. The public ID is typically the first thing that is checked when an OTP is submitted. If the OTP's public ID doesn't match the ID that is registered with a user's account, the OTP will be rejected. ##### Note Public IDs must be unique to a single Yubico OTP configuration. You may not register the same public ID with different [private IDs](https://docs.yubico.com/yesdk/users-manual/application-otp/yubico-otp.html#private-id) and AES keys with the same [validation server](https://docs.yubico.com/yesdk/users-manual/application-otp/yubico-otp.html#authentication-with-a-yubico-otp) . Off-the-shelf YubiKeys are preconfigured with Yubico OTPs that have public IDs that start with "cccc". The SDK provides the option to explicitly set the public ID to something of your choice or to use a ModHex representation of the YubiKey's serial number as the public ID. See the [SDK functionality](https://docs.yubico.com/yesdk/users-manual/application-otp/yubico-otp.html#sdk-functionality) section below for more information. The final 32 characters of the OTP represent the unique 128-bit passcode. The passcode is generated by concatenating various YubiKey fields into a 128-bit long string and encrypting the string with the YubiKey configuration's unique 128-bit AES key. These fields include the following: * private ID (48 bits) * session usage counter (8 bits) * usage counter (16 bits) * timestamp (24 bits) * random number (16 bits) * checksum (16 bits) ### Private ID The private ID is a 6-byte/48-bit field that is unique to the Yubico OTP configuration. The validation server's key storage module (KSM) stores the configuration's AES key and private ID pair. When an OTP is decrypted by the KSM, the private ID field in the OTP is compared to the private ID in the KSM. If they do not match, the OTP is rejected. When a Yubico OTP application slot is configured for a Yubico OTP, the private ID can be set to a specific value or generated randomly. See the [SDK functionality](https://docs.yubico.com/yesdk/users-manual/application-otp/yubico-otp.html#sdk-functionality) section below for more information on how to do this with the SDK. ### Session usage counter The session usage counter is used to keep track of how many OTPs have been generated during a single "session" (i.e. a continuous period of time where the key has been powered on). When the YubiKey is powered up (either through a physical connection to a host or by coming into contact with an NFC reader), the session usage counter (1 byte/8 bits) is initiated to zero. When a new OTP is generated while the key is still powered on, this field is incremented by one. If this field wraps from 0xff to 0, the [usage counter](https://docs.yubico.com/yesdk/users-manual/application-otp/yubico-otp.html#usage-counter) is automatically incremented. The session usage counter is stored in little-endian format (least significant byte first). If two OTPs are generated during the same session, the second OTP received by the validation server should have a higher session usage counter than the previous OTP. If not, the second OTP will be rejected. Each OTP application slot has its own session usage counter. This means that if you configure both slots with a Yubico OTP, their session usage will be tracked separately. For example, if you were to generate an OTP from the short-press slot, the session usage counter for that slot would increment by 1, but the long-press slot's session usage counter would not change. ### Usage counter The usage counter (2 bytes/16 bits) keeps track of how many times the YubiKey has been powered on. It is non-volatile, meaning its value is preserved even when the YubiKey is powered off. The first time the YubiKey is used after a power-up, this value is incremented by 1, and the session usage counter is reset to zero. If a validation server receives an OTP that has a lower usage counter than the previously recorded counter, the OTP will be rejected. This field has a usable range of 1 – 0x7fff. When this counter reaches 0x7fff, it stops. However, this does not render the YubiKey useless; the OTP application slot can simply be reconfigured with new Yubico OTP secrets (which need to be shared with the validation server). Every time a slot is reconfigured, the usage counter will be reset. Each OTP application slot has its own usage counter. The usage counter is also stored in little-endian format. ### Timestamp The timestamp is a 3-byte/24-bit field incremented at a rate of approximately 8 Hz. After powering on, the key's internal random number generator sets the timestamp to a random value. Therefore, the timestamp does not reflect the current time. However, it can be used by the validation server to check how much time has elapsed between two OTPs received during a single session. For example, if one password is supposed to have been generated just a few seconds after the previous one, the timestamps should reflect that. But what if the timestamps show that the "first" one was generated four days after the "second" one? That is a red flag indicating the possibility of a replay attack. The [YubiCloud](https://docs.yubico.com/yesdk/users-manual/application-otp/yubico-otp.html#yubicloud) validation server does not use the timestamp to validate OTPs. If you are [self-hosting](https://docs.yubico.com/yesdk/users-manual/application-otp/yubico-otp.html#self-hosted-validation-servers) your own validation server, you may elect to use the timestamp if you wish. The timestamp wraps from 0xffffff to 0 without any further action. If the timestamp is used by a self-hosted validation server, this condition must be taken into account. Given an 8 Hz rate, the timestamp will wrap approximately every 24 days (given the key is continuously powered on). The field is stored in little-endian format. ### Random number The random number is a 2-byte/16-bit field that is generated by the key's random number generator for each OTP. The goal of the random number is to help guarantee that the OTP's binary ciphertext is always unique and to ensure that the OTP block size is 128 bits. This field is also stored in little-endian format. ##### Note The 128-bit AES encryption key that Yubico OTPs use requires a 128-bit block size (the block is the data being encrypted). So in a sense, the random number functions as padding that brings the block size to the necessary 128-bits. ### Checksum Once all other OTP fields have been set, a 2-byte/16-bit ISO 13239 one's complement checksum is computed over the binary passcode data from the private ID to the random number and added to the end of the OTP string (in little-endian format). This checksum allows the validation server to confirm that an OTP was decrypted properly during authentication. To verify decryption, the validation server calculates another checksum over all bytes of the OTP, including the original checksum field. If decryption was successful, this will give a fixed residual of 0xf0b8. If a different residual is computed by the validation server, the OTP will be rejected. Yubico OTP generation --------------------- Now that we've covered the Yubico OTP components, let's look at the typical OTP generation process: 1. The YubiKey is plugged into a host device over USB/Lightning or comes into contact with a host's NFC reader. 2. The key is powered on. 3. The session usage counter is reset to 0, and the usage counter is incremented by 1. 4. The key's random number generator initializes the timestamp to a random value and begins incrementing it at a rate of 8 Hz. 5. A [slot](https://docs.yubico.com/yesdk/users-manual/application-otp/slots.html) containing a Yubico OTP configuration is activated, prompting OTP generation. 6. The key collects the public ID, private ID, current session usage counter, current usage counter, and current timestamp. 7. The key generates the random number. 8. The key computes the checksum over all OTP passcode fields (private ID through random number). 9. The private ID, session usage counter, usage counter, timestamp, random number, and checksum are concatenated into a 128-bit string and encrypted by the 128-bit AES encryption key. 10. If the key is connected to a host over [USB/Lightning](https://docs.yubico.com/yesdk/users-manual/application-otp/hid.html) , the key translates the bits of the full OTP ( public ID + encrypted passcode) to the HID usage IDs of the ModHex characters that represent those bits. These HID usage IDs are collected into HID usage reports. If the key is in contact with an NFC reader, the key translates the bits of the OTP to the binary UTF codes of the ModHex characters that represent those bits. The OTP (as UTF codes) is added to an [NDEF message](https://docs.yubico.com/yesdk/users-manual/application-otp/ndef.html) as a text string or URI, depending on the key's NDEF tag configuration. 11. The key sends the OTP to the host (through HID usage reports or an NDEF message). 12. After an OTP is generated, the session usage counter is incremented by 1. Authentication with a Yubico OTP -------------------------------- In order to validate Yubico OTPs, a central validation server is needed. Validation servers store the OTP configuration secrets (private ID and AES key) and keep track of the usage counter and session usage counter from previous valid OTPs. When a Yubico OTP is submitted during the user authentication process, the OTP is routed to the validation server by your application, which uses the appropriate AES key to decrypt the OTP. After decrypting, the private ID, usage counter, and session usage counter are used to check the OTP's validity. When a key's OTP application slot is configured with a Yubico OTP, the OTP secrets must be shared with the validation server _and_ the configuration's public ID must be registered with a user account of an application the user wishes to authenticate to. It is up to the application developer to correctly handle OTP account registration and communication with the validation server. ### YubiCloud Yubico provides a network of validation servers around the world known collectively as [YubiCloud](https://www.yubico.com/products/yubicloud/) . During manufacturing, YubiKeys are configured with a Yubico OTP (in the short-press slot), and the OTP secrets are uploaded to YubiCloud. This enables out-of-the-box OTP authentication. To test authentication with YubiCloud, submit a Yubico OTP from your YubiKey [here](https://demo.yubico.com/otp/verify) . To integrate YubiCloud validation into your application, you must add calls to YubiCloud to verify OTPs. To get started, get a [YubiCloud API key](https://upgrade.yubico.com/getapikey/) . ##### Note Check [status.yubico.com](https://status.yubico.com/) for YubiCloud service updates. ### Self-hosted validation servers Yubico strongly recommends using YubiCloud. If for some reason YubiCloud is not suitable for your application, you may host your own validation server. Validation servers are composed of two major components: * verification server * key storage module (KSM) The KSM stores OTP secrets (AES keys and private IDs) and performs OTP decryption. The verification server validates decrypted OTPs. Yubico provides a [reference architecture](https://developers.yubico.com/Software_Projects/Yubico_OTP/YubiCloud_Validation_Servers/) for the [validation server](https://github.com/YubicoLabs/yubikey-val) and [KSM](https://github.com/YubicoLabs/yubikey-ksm) in the YubicoLabs GitHub repository. Please note that these architectures have been deprecated and are no longer supported. At this time, Yubico does not offer an on-premises service. If you are interested in hosting your own validation server to use within your company, please reach out to customer support. Yubico has the ability to manufacture company-specific keys with a different public ID prefix (off-the-shelf YubiKeys use the "cccc" prefix). These keys can be pre-configured with Yubico OTPs, and the secrets will be provided to you for uploading to your self-hosted server. ### Step-by-step OTP authentication process Once a YubiKey's private ID and AES key have been shared with a validation server _and_ the key has been registered with a user account of an application that uses that particular validation server, OTP authentication works as follows: 1. For two-factor authentication, the user enters their username and password on the login screen of the application. 2. The user is prompted to insert their YubiKey into their device or scan their NFC-enabled key with their host device's NFC reader. If the key is physically connected to the host, the green LED of the YubiKey will begin to flash. 3. For a key connected over USB/Lightning, the user must touch the YubiKey to generate and submit an OTP. If the key was scanned by an NFC reader, an OTP is generated automatically. After the OTP is generated, the key sends it to the host via the appropriate communication protocol (HID for USB/Lightning connections or NDEF for NFC). ##### Note For specifics about OTP generation, please see the [previous section](https://docs.yubico.com/yesdk/users-manual/application-otp/yubico-otp.html#yubico-otp-generation) . 4. The YubiKey's public ID is checked by the application to verify that it is associated with the user account. 5. The application sends the OTP to the validation server. 6. The OTP is received by the validation server and passed to the Key Storage Module (KSM). 7. The KSM uses the public ID to locate the corresponding OTP secrets. 8. The KSM uses the AES key to decrypt the OTP. 9. The KSM calculates a checksum over all bytes of the OTP, including the original checksum field. If decryption was successful, this will give a fixed residual of 0xf0b8. If a different residual is computed, the OTP is rejected. 10. The KSM checks that the private ID of the OTP matches the private ID in the KSM. If they do not match, the OTP is rejected. 11. If decryption was successful and the private ID is correct, the KSM passes the validity of the OTP and the usage counters back to the validation server. 12. The validation server checks the session usage counter and usage counter against those from the last valid OTP from that YubiKey. If the usage counter is lower than the previously recorded usage counter, the OTP is rejected. If it is the same as the previous counter, the session usage counter must be higher than the previous session usage counter for the OTP to be valid, otherwise the OTP is rejected. If the usage counter is higher than the previous usage counter, the OTP is accepted as valid. 13. The validation server reports the OTP validity to the application. 14. If the OTP is valid and its public ID is registered with the user account, the user is logged in to the application. Yubico OTP security ------------------- The security of Yubico OTPs relies on three major areas: * the cryptographic strength of the OTP * the write-only properties of YubiKey OTP configuration data * the integrity of the validation server ### Cryptographic strength Yubico OTPs use a 128-bit AES encryption key. This means that there are 2^128 or 3.4028237e+38 possible key combinations. Trying to guess the correct key through a brute-force attack with the world's current computational power would take billions of years. For more information on the Advanced Encryption Standard (AES), please see the [2001 specification](https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.197.pdf) . ### YubiKey properties YubiKey configuration data is write-only. This means that an OTP slot may be reconfigured with a new AES key and private ID, but the current configuration (as well as any previous configurations) may not be extracted from the device. ### Validation server integrity The validation server is responsible for storing secrets (the AES keys and private IDs) as well as keeping track of the usage counter and session usage counter for each key-ID pair. If the server isn't tracking the usage counter and session usage counter properly, this leaves the door open for attackers to find and use previously generated OTPs. Similarly, OTPs emitted outside the login process present a security vulnerability. Until a subsequent OTP is sent to a validation server for authentication, these "unused" OTPs may be stolen and submitted for verification by an attacker. To protect against this scenario, we recommend regularly "burning" OTPs, meaning that you generate and submit an OTP for verification with the goal of simply updating the server's usage counter/session usage counter. If you use YubiCloud, you can do this through the [demo webpage](https://demo.yubico.com/otp/verify) . Companies that use self-hosted validation servers should provide a similar facility to burn OTPs. SDK functionality ----------------- The SDK's Yubico OTP functionality is rooted in the [ConfigureYubicoOtp](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.OtpSession.html#Yubico_YubiKey_Otp_OtpSession_ConfigureYubicoOtp_Yubico_YubiKey_Otp_Slot_) method. This method allows you to configure one of the OTP application slots with a Yubico OTP. After configuration, that slot will generate a Yubico OTP every time it is activated. With ConfigureYubicoOtp, you have the ability to provide your own AES key and private ID via [UseKey()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.ConfigureYubicoOtp.html#Yubico_YubiKey_Otp_Operations_ConfigureYubicoOtp_UseKey_System_Memory_System_Byte__) and [UsePrivateId()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.ConfigureYubicoOtp.html#Yubico_YubiKey_Otp_Operations_ConfigureYubicoOtp_UsePrivateId_System_ReadOnlyMemory_System_Byte__) or randomly generate those credentials via [GenerateKey()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.ConfigureYubicoOtp.html#Yubico_YubiKey_Otp_Operations_ConfigureYubicoOtp_GenerateKey_System_Memory_System_Byte__) and [GeneratePrivateId()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.ConfigureYubicoOtp.html#Yubico_YubiKey_Otp_Operations_ConfigureYubicoOtp_GeneratePrivateId_System_Memory_System_Byte__) . Similarly, you may set the public ID to an explicit value of your choosing with [UsePublicId()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.ConfigureYubicoOtp.html#Yubico_YubiKey_Otp_Operations_ConfigureYubicoOtp_UsePublicId_System_ReadOnlyMemory_System_Byte__) or use your YubiKey's serial number as the public ID with [UseSerialNumberAsPublicId()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.ConfigureYubicoOtp.html#Yubico_YubiKey_Otp_Operations_ConfigureYubicoOtp_UseSerialNumberAsPublicId_System_Nullable_System_Memory_System_Byte___) . ##### Note Generated credentials will need to be shared with the validation server before they are cleared from memory. There is no way to extract credentials from the YubiKey after configuration. If using YubiCloud, you can upload secrets using [this form](https://upload.yubico.com/) . Note that credentials will need to be converted from bytes to ASCII characters before they can be submitted through the key upload form. If your private ID and/or public ID has already been registered with YubiCloud, you will need to redo the configuration with new credentials. Therefore, you may only configure a slot with the key's serial number as the public ID (via UseSerialNumberAsPublicId()) once if you are uploading those configuration secrets to YubiCloud. The YubiKey also allows you to control how the OTP is sent to a host, depending on the intended use case. You can set a time delay between characters of the OTP as they are sent to a host device with [Use10msPacing()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.ConfigureYubicoOtp.html#Yubico_YubiKey_Otp_Operations_ConfigureYubicoOtp_Use10msPacing_System_Boolean_) and [Use20msPacing()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.ConfigureYubicoOtp.html#Yubico_YubiKey_Otp_Operations_ConfigureYubicoOtp_Use20msPacing_System_Boolean_) . Similarly, you can add a 500ms delay after sending the fixed part of the OTP (the 12-character public ID of the key) and/or the 32-character unique passcode of the OTP with [AppendDelayToFixed()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.ConfigureYubicoOtp.html#Yubico_YubiKey_Otp_Operations_ConfigureYubicoOtp_AppendDelayToFixed_System_Boolean_) and [AppendDelayToOtp()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.ConfigureYubicoOtp.html#Yubico_YubiKey_Otp_Operations_ConfigureYubicoOtp_AppendDelayToOtp_System_Boolean_) , respectively. You can also add additional keystrokes as needed for your intended application with [SendTabFirst()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.ConfigureYubicoOtp.html#Yubico_YubiKey_Otp_Operations_ConfigureYubicoOtp_SendTabFirst_System_Boolean_) (sends a tab before the OTP characters), [AppendTabToFixed()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.ConfigureYubicoOtp.html#Yubico_YubiKey_Otp_Operations_ConfigureYubicoOtp_AppendTabToFixed_System_Boolean_) ( sends a tab after the public ID of the OTP), and [AppendCarriageReturn()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.ConfigureYubicoOtp.html#Yubico_YubiKey_Otp_Operations_ConfigureYubicoOtp_AppendCarriageReturn_System_Boolean_) ( sends an **Enter** key after the full OTP has been sent to a device). For a full list of the methods in the ConfigureYubicoOtp class, please see the [API documentation](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.ConfigureYubicoOtp.html) . For an example of how to use ConfigureYubicoOtp(), please see [How to program a slot with a Yubico OTP credential](https://docs.yubico.com/yesdk/users-manual/application-otp/how-to-program-a-yubico-otp-credential.html) . [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-otp/yubico-otp.md/#L1) --- # Private key handling ##### Table of Contents Private key handling ==================== The Yubico .NET SDK supports importing and exporting private keys in standard formats using type-safe factory methods. All private key classes implement `IPrivateKey` and provide secure memory handling. Supported key types ------------------- * **RSA keys**: 1024, 2048, 3072, 4096-bit * **EC keys**: NIST P-256, P-384 curves * **Curve25519 keys**: Ed25519 (signing), X25519 (key agreement) Private key formats ------------------- One of the unfortunate problems of public key cryptography is the myriad ways to represent private keys. Part of this is due to the fact that different algorithms have different elements. For example, an RSA private key can consist of three, five, or eight integers: | 3-integer RSA key | 5-integer RSA key | 8-integer RSA key | | --- | --- | --- | | modulus | prime P | modulus | | public exponent | prime Q | public exponent | | private exponent | exponent P | private exponent | | | exponent Q | prime P | | | coefficient | prime Q | | | | exponent P | | | | exponent Q | | | | coefficient | On the other hand, an "Fp" Elliptic Curve (EC) private key consists of the following elements: | EC private key component | EC private key subcomponent | | --- | --- | | curve | prime | | | order | | | coefficients (a, b, c) | | | base point (x, y) | | public point | x coordinate | | | y coordinate | | private value | | Standard curves (such as NIST P-256) can be represented by an object identifier (OID), public point (x,y), and a private value. In some cases, just the OID and private value are needed as the public point can be computed from the curve parameters and private value. There is more than one standard that defines how to represent private keys. The most common definitions are `PrivateKeyInfo` from PKCS #8 (Public Key Cryptography Standard #8) and PEM (Privacy-Enhanced Mail). PKCS #8 is now an internet standard ([RFC 5208](https://tools.ietf.org/html/rfc5208) ). PEM ([RFC 7468](https://tools.ietf.org/html/rfc7468) ) was created to describe how to use public key cryptography to build secure email, but it has elements that turned out to be useful to cryptography in general, including its representation of keys. Fortunately, there is some overlap. The vast majority of applications will use the PKCS #8 `PrivateKeyInfo` or the PEM "PRIVATE KEY" (which wraps a `PrivateKeyInfo`). `PrivateKeyInfo` is popular because it contains algorithm information in addition to the actual key data. That is, a private key in this format contains an `AlgorithmIdentifier` specifying the algorithm and any parameters as well as the key data specific to that algorithm. There are C# classes that will build or parse these structures, although it will still require some work on your part. This page will show how to build a private key object the YubiKey can read from `PrivateKeyInfo` and PEM formats. Note that a YubiKey will never return a private key, so there will be no need to convert from a YubiKey-formatted private key to a PrivateKeyInfo or PEM format. Factory methods --------------- PIV does not define its own format of encoding private keys, but Yubico has defined an encoding that is very similar to the PIV public key format. However, the SDK's PIV application APIs that work with private keys require them to be instances of the `PrivateKey` class. Hence, when importing a private key into a YubiKey, your application will need to be able to "convert" from `PrivateKeyInfo` or PEM to `PrivateKey`. ### RSA private keys // From PKCS#8 PrivateKeyInfo format byte[] pkcs8Bytes = // your PKCS#8 encoded key RSAPrivateKey rsaKey = RSAPrivateKey.CreateFromPkcs8(pkcs8Bytes); // From RSA parameters using var rsa = RSA.Create(2048); RSAParameters parameters = rsa.ExportParameters(true); RSAPrivateKey rsaKey = RSAPrivateKey.CreateFromParameters(parameters); // From CRT parameters only var crtParameters = new RSAParameters { P = // prime P, Q = // prime Q, DP = // exponent P, DQ = // exponent Q, InverseQ = // coefficient }; RSAPrivateKey rsaKey = RSAPrivateKey.CreateFromParameters(crtParameters); ### EC private keys // From PKCS#8 PrivateKeyInfo format byte[] pkcs8Bytes = // your PKCS#8 encoded key ECPrivateKey ecKey = ECPrivateKey.CreateFromPkcs8(pkcs8Bytes); // From EC parameters using var ecdsa = ECDsa.Create(ECCurve.NamedCurves.nistP256); ECParameters parameters = ecdsa.ExportParameters(true); ECPrivateKey ecKey = ECPrivateKey.CreateFromParameters(parameters); // From private scalar value ReadOnlyMemory privateValue = // your private scalar ECPrivateKey ecKey = ECPrivateKey.CreateFromValue(privateValue, KeyType.ECP256); ### Curve25519 private keys // From PKCS#8 PrivateKeyInfo format byte[] pkcs8Bytes = // your PKCS#8 encoded key Curve25519PrivateKey ed25519Key = Curve25519PrivateKey.CreateFromPkcs8(pkcs8Bytes); // From private key bytes ReadOnlyMemory privateKeyBytes = // your 32-byte private key Curve25519PrivateKey ed25519Key = Curve25519PrivateKey.CreateFromValue(privateKeyBytes, KeyType.Ed25519); Curve25519PrivateKey x25519Key = Curve25519PrivateKey.CreateFromValue(privateKeyBytes, KeyType.X25519); Importing to YubiKey -------------------- using var pivSession = new PivSession(yubiKey); pivSession.KeyCollector = yourKeyCollector; pivSession.AuthenticateManagementKey(); // Import any IPrivateKey implementation pivSession.ImportPrivateKey( PivSlot.Authentication, privateKey, PivPinPolicy.Once, PivTouchPolicy.Never); Exporting private keys ---------------------- // Export to PKCS#8 format byte[] pkcs8Bytes = rsaKey.ExportPkcs8PrivateKey(); byte[] pkcs8Bytes = ecKey.ExportPkcs8PrivateKey(); // Access key-specific properties RSAParameters rsaParams = rsaKey.Parameters; ECParameters ecParams = ecKey.Parameters; ReadOnlyMemory curve25519Bytes = curve25519Key.PrivateKey; PEM format conversion --------------------- // Export to PEM format byte[] pkcs8Bytes = privateKey.ExportPkcs8PrivateKey(); string pemKey = "-----BEGIN PRIVATE KEY-----\n" + Convert.ToBase64String(pkcs8Bytes, Base64FormattingOptions.InsertLineBreaks) + "\n-----END PRIVATE KEY-----"; // Import from PEM format string pemData = // your PEM PRIVATE KEY string base64Data = pemData .Replace("-----BEGIN PRIVATE KEY-----\n", "") .Replace("\n-----END PRIVATE KEY-----", ""); byte[] pkcs8Bytes = Convert.FromBase64String(base64Data); IPrivateKey privateKey = RSAPrivateKey.CreateFromPkcs8(pkcs8Bytes); // or ECPrivateKey, etc. ##### Note When importing a private key in PEM format, there are a number of possible header and footer combinations, including the following: -----BEGIN PRIVATE KEY----- -----END PRIVATE KEY----- -----BEGIN RSA PRIVATE KEY----- -----END RSA PRIVATE KEY----- -----BEGIN EC PRIVATE KEY----- -----END EC PRIVATE KEY----- ### Determining the algorithm when importing a private key in PEM format To build a PrivateKey when importing from PEM, you will need to first determine the private key algorithm. Once you know the algorithm, you can use the appropriate C# class to read the encoded data (for example, `RSAPrivateKey`, `ECPrivateKey`, or `Curve25519PrivateKey` ). The algorithm is specified in the key data itself. However, the .NET Base Class Library does not have a class that can parse `PrivateKeyInfo` and build the appropriate object. The only methods that can read this encoding are in classes for the specific algorithms. That is, the RSA class can read `PrivateKeyInfo` only if the input data is an RSA key, the ECDsa class can read it only if the input data is an ECC key, etc. One possible workaround would be to supply the encoded key to the RSA class and if it works, we have an RSA key. If it does not work, give the encoded key to the ECDsa class. However, if the RSA class gets an encoded key that is not RSA, it throws an exception, and using exceptions to determine code flow is not best practice. To determine the algorithm of an imported key, we need to open up the encoding and read the object identifier (OID) of the `AlgorithmIdentifier`. And to find the OID, we need to decode the DER encoding of `PrivateKeyInfo`. `PrivateKeyInfo` is defined as: PrivateKeyInfo ::= SEQUENCE { version Version, privateKeyAlgorithm AlgorithmIdentifier, privateKey PrivateKey, attributes [0] IMPLICIT Attributes OPTIONAL } Version ::= INTEGER AlgorithmIdentifier ::= SEQUENCE { algorithm OBJECT IDENTIFIER, parameter ANY DEFINED BY algorithm OPTIONAL } This means that the DER encoding will look something like the following: 30 len // The len octets might be one, two, or three bytes long. 02 01 00 30 len 06 len OID bytes etc. In this example, to get to the OID, we need to read the first `30 len`, then the INTEGER, then the second `30 len`, then the `06 len`. Secure memory handling ---------------------- All private key classes implement secure cleanup and disposal patterns: // Using disposable pattern (recommended) using (var privateKey = RSAPrivateKey.CreateFromPkcs8(pkcs8Bytes)) { // Use the private key pivSession.ImportPrivateKey(PivSlot.Authentication, privateKey, PivPinPolicy.Once, PivTouchPolicy.Never); } // Sensitive data automatically cleared // Explicit cleanup ECPrivateKey privateKey = null; try { privateKey = ECPrivateKey.CreateFromPkcs8(pkcs8Bytes); // Use the private key } finally { privateKey?.Clear(); // Securely zero sensitive data } Error handling -------------- Factory methods validate input and may throw exceptions: try { var privateKey = Curve25519PrivateKey.CreateFromValue(keyBytes, KeyType.X25519); } catch (CryptographicException ex) { // Handle invalid key format or bit clamping violations } catch (ArgumentException ex) { // Handle invalid parameters or key type mismatches } References ---------- * [RFC 5208](https://tools.ietf.org/html/rfc5208) - PKCS#8 Private Key format * [RFC 7748](https://tools.ietf.org/html/rfc7748) - Curve25519 and Curve448 * [RFC 7468](https://tools.ietf.org/html/rfc7468) - PEM encoding * [SDK PIV integration tests](https://github.com/Yubico/Yubico.NET.SDK/tree/HEAD/Yubico.YubiKey/tests/integration/Yubico/YubiKey/Piv) * SDK unit tests for additional usage examples * [Curve25519PrivateKeyTests](https://github.com/Yubico/Yubico.NET.SDK/blob/HEAD/Yubico.YubiKey/tests/unit/Yubico/YubiKey/Cryptography/Curve25519PrivateKeyTests.cs) * [ECPrivateKeyTests](https://github.com/Yubico/Yubico.NET.SDK/blob/HEAD/Yubico.YubiKey/tests/unit/Yubico/YubiKey/Cryptography/ECPrivateKeyTests.cs) * [RSAPrivateKeyTests](https://github.com/Yubico/Yubico.NET.SDK/blob/HEAD/Yubico.YubiKey/tests/unit/Yubico/YubiKey/Cryptography/RSAPrivateKeyTests.cs) [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-piv/private-keys.md/#L1) --- # ##### Table of Contents Create attestation statement ---------------------------- ### Command APDU Info | CLA | INS | P1 | P2 | Lc | Data | Le | | --- | --- | --- | --- | --- | --- | --- | | 00 | F9 | _slot number_ | 00 | (absent) | (absent) | (absent) | The slot number can be one of the following (hex values): `9A, 9C, 9D, 9E, 82, 93, 84, 85, 86, 87, 88, 89, 8A, 8B, 8C, 8D, 8E, 8F, 90, 91, 92, 93, 94, 95`. ### Response APDU Info Total Length: _variable + 2_ Data Length: _variable_ | Data | SW1 | SW2 | | --- | --- | --- | | _certificate_ | 90 | 00 | Note that the certificate will be returned over multiple commands. Each return command will be able to return up to 256 bytes. To get more bytes of a return, call the GET RESPONSE APDU. ### Examples $ opensc-tool -c default -s 00:a4:04:00:09:a0:00:00:03:08:00:00:10:00 -s 00:f9:9c:00 -s 00:c0:00:00 -s 00:c0:00:00 -s 00:c0:00:00 Using reader with a card: Yubico YubiKey OTP+FIDO+CCID 0 Sending: 00 A4 04 00 09 A0 00 00 03 08 00 00 10 00 Received (SW1=0x90, SW2=0x00): 61 11 4F 06 00 00 10 00 01 00 79 07 4F 05 A0 00 00 03 08 Sending: 00 F9 9C 00 Received (SW1=0x90, SW2=0x00): 30 82 03 20 30 82 02 08 A0 03 02 01 02 02 10 01 48 79 0D CE 69 34 3C BD 08 C3 CB 14 EC B9 50 30 0D 06 09 2A 86 48 86 F7 0D 01 01 0B 05 00 30 21 31 1F 30 1D 06 03 55 04 03 0C 16 59 75 62 69 63 6F 20 50 49 56 20 41 74 74 65 73 74 61 74 69 6F 6E 30 20 17 0D 31 36 30 33 31 34 30 30 30 30 30 30 5A 18 0F 32 30 35 32 30 34 31 37 30 30 30 30 30 30 5A 30 25 31 23 30 21 06 03 55 04 03 0C 1A 59 75 62 69 4B 65 79 20 50 49 56 20 41 74 74 65 73 74 61 74 69 6F 6E 20 39 63 30 82 01 22 30 0D 06 09 2A 86 48 86 F7 0D 01 01 01 05 00 03 82 01 0F 00 30 82 01 0A 02 82 01 01 00 CE D2 15 EF 4E B8 57 BE 7E 7A 33 5C 6E 3A 51 C8 51 52 82 4F CE EA E1 DA B4 0D 7C 55 8D 4A 90 3A 5E 4B 88 2C 4D EB 4C 48 5D 4D E7 18 F3 48 1B 22 4A 33 AF 93 08 5C 97 1C 01 1A 8F 76 5F 6E 96 E9 48 CA 8C 91 3C Sending: 00 C0 00 00 Received (SW1=0x90, SW2=0x00): 3A 2B 84 C0 0B 64 8B 4B 74 48 BC 8E 8A 94 E7 92 DB 2D 6C FF 5D 75 BF 16 A3 13 F3 55 5C F2 B4 31 34 02 0A 32 DE 5F 37 C4 21 F7 71 0B 01 31 D8 8B 75 3D A2 44 FD C5 DE 26 6C C4 9E 58 36 60 20 C5 0B 57 F9 9C B3 9A 7E F8 D6 87 21 CE A7 17 69 46 40 96 4B F4 21 DE 3F FC 02 D8 49 04 07 94 64 A7 2A 92 57 52 C7 BC D8 F8 56 D9 30 7F 4E 5C 52 9D FD 55 A7 51 BB 8F B0 D0 CD CE 99 8B AD EB 62 E3 40 79 1D 72 BA 58 8C F7 F9 DB CE 1C BD D9 13 30 0A 59 66 97 15 4B 7F 59 25 82 DC 7E 91 FD 22 23 43 F0 B7 73 0F C3 00 65 14 82 A0 B2 E5 56 CD 7A F7 74 4B 41 70 D1 1C CD 0B AD 19 02 03 01 00 01 A3 4E 30 4C 30 11 06 0A 2B 06 01 04 01 82 C4 0A 03 03 04 03 05 02 04 30 14 06 0A 2B 06 01 04 01 82 C4 0A 03 07 04 06 02 04 00 AE 17 FB 30 10 06 0A 2B 06 01 04 01 82 C4 0A 03 08 04 02 03 01 30 Sending: 00 C0 00 00 Received (SW1=0x90, SW2=0x00): 0F 06 0A 2B 06 01 04 01 82 C4 0A 03 09 04 01 01 30 0D 06 09 2A 86 48 86 F7 0D 01 01 0B 05 00 03 82 01 01 00 3F F9 48 2D 26 DB 57 D6 86 76 00 81 0C CB 65 FF D0 5E 31 97 82 F0 97 9F EA 3D D4 0D 14 24 37 92 5D E6 B2 A7 5D 71 73 5B D4 87 40 8D 0A E4 A4 A5 F9 D4 56 D7 98 FE B8 47 9A 52 CD 21 BC A7 6D 09 97 71 DC CF D0 D0 0D 9A 2B 32 13 2A 50 49 92 EC 14 7C 68 C4 97 C4 E1 E5 41 C3 38 CC 6D 85 0C FD BD C2 28 4D 53 B0 E2 45 7A 14 B5 1D 62 80 F4 FE 0C 87 50 F0 47 38 33 1C 39 EA 40 DF 1B 94 E7 FC 87 06 CA A3 D7 35 A6 4A 14 FC B0 88 8E E1 13 EB 06 97 AE 1F 4F 8E B7 DE 93 30 55 02 02 CB 22 DE 5F DE 3B 12 83 03 93 FE 33 E4 11 C4 B5 EC AE D6 57 9A 13 5A 15 F8 4F 75 55 72 F6 E9 29 E1 CA 9B A6 22 FC 0E E0 54 A4 F2 DD 23 80 CC 04 F1 E0 DC 28 72 02 7F 6C 14 E1 E1 69 13 4C 3A Sending: 00 C0 00 00 Received (SW1=0x90, SW2=0x00): F5 F8 57 04 B9 4C 6B CD D8 9C D1 65 1C 20 E9 0C B7 7B DA E4 0E 55 FE B5 5A 11 61 D5 A8 BF 72 36 ED 40 21 47 [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-piv/apdu/attest.md/#L1) --- # Keeping track of PIV slot contents ##### Table of Contents Keeping track of PIV slot contents ================================== For details about [PIV slots, see the User's Manual entry](https://docs.yubico.com/yesdk/users-manual/application-piv/slots.html) . Upon manufacture, the only PIV slots that contain anything are * 80 - PIN * 81 - PUK * 9B - Management Key * F9 - Attestation The programs that use the PIV application will fill the contents of the other slots with keys and certificates. How does a program keep track of the slots? Which slot contains a key? What is the algorithm and size? What is its PIN and touch policy? Was it generated or imported? What is its associated public key? Prior to version 5.3 -------------------- For YubiKeys with version numbers before 5.3, all this information is up to the program to manage. That is, the program that calls on an "older" YubiKey to perform PIV operations must keep a record somehow of which slots have keys, what algorithm (and size) each of the keys is, and what the PIN and touch policies are. Furthermore, for keys generated on the older YubiKey, the only way to get the public key is during generation. That is, the YubiKey generation operation returns the public key, however, that is the only time the older YubiKey will return that public key. There is no function to call to retrieve a public key from a slot at any other time. For these older YubiKeys, it is the program's responsibility to capture the public key at generation time, store it somewhere to be accessible, and create a cert request (or self-signed cert). It is then the program's responsibility to obtain a cert and load it into the appropriate slot. Of course, if there is a cert loaded into a slot, then it is possible to get that cert out. A program can retrieve the public key out of the cert, and obtain the algorithm and key size. However, a cert will not specify the PIN and touch policies. 5.3 and later ------------- Beginning with YubiKey version 5.3, it is possible to obtain "metadata" about a slot. For a private key, this data includes the algorithm and key size, the public key, the PIN and touch policies, and whether the key was generated or imported. The generation operation will return the public key as before, but now there is a function to call to retrieve the public key at any time. See the documentation for the [PivSession.GetMetadata](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.PivSession.html#Yubico_YubiKey_Piv_PivSession_GetMetadata_) method, and the [Get Metadata](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#get-metadata) command. Sample code ----------- There is some sample code demonstrating how to use the SDK to perform PIV operations. Part of that sample code is a class that keeps slot contents. That code might help you as you design your application. [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-piv/keeping-track.md/#L1) --- # ##### Table of Contents Authenticate: decrypt --------------------- ### Command APDU Info | CLA | INS | P1 | P2 | Lc | Data | Le | | --- | --- | --- | --- | --- | --- | --- | | 00 | 87 | _algorithm_ | _slot number_ | _data len_ | _encoded data to decrypt_ | (absent) | The _algorithm_ is either `06` (RSA-1024), `07` (RSA-2048), `05` (RSA 3072), or `16` (RSA 4096). Note that it is not possible to decrypt using ECC. The _slot number_ can be the number of any slot that holds a private key, other than `F9`. That is, the slot number can be any PIV slot other than `80`, `81`, `9B`, or `F9`. The attestation key, `F9`, will sign a certificate it creates, but cannot decrypt or perform key agreement. The _encoded data_ is 7C len1 82 00 81 len2 where len1 and len2 are lengths in DER format, and is the same size as the key. Notice that in the encoded data, the tags for RSA, `7C`, `82`, `81` are the same as the tags when signing. The RSA signing and decrypting operations are mathematically identical. ### Response APDU Info #### Response APDU for AUTHENTICATE:DECRYPT (success) Total Length: _variable + 2_ Data Length: _variable_ | Data | SW1 | SW2 | | --- | --- | --- | | 7C _len1_ 82 _len2 _ | 90 | 00 | The decrypted data will not be decoded. That is, it will still be in the form of PKCS 1 v1.5 (`00 02 pad 00 plaintext`) or OAEP. Note that the response might be returned over multiple commands. Each return command will be able to return up to 256 bytes. To get more bytes of a return, call the GET RESPONSE APDU. #### Response APDU for AUTHENTICATE:DECRYPT (wrong or no PIN, or no touch) Total Length: 2 Data Length: 0 | Data | SW1 | SW2 | | --- | --- | --- | | (no data) | 69 | 82 | If the key was generated or imported with a PIN policy other than "Never", and the command was sent without first verifying the PIN or the wrong PIN was entered, then this response will be returned. In addition, if the key's touch policy is not "Never", and after submitting the command the YubiKey was not touched within the time limit, this response will be returned. ### Examples opensc-tool -c default -s 00:a4:04:00:09:a0:00:00:03:08:00:00:10:00 -s 00:20:00:80:08:31:32:33:34:35:36:ff:ff -s 00:87:06:9d:88:7c:81:85:82:00:81:81:80: 06:84:ef:45:b9:0c:4e:2b:0e:cd:c1:83:23:21:1b:bc: d7:b0:3a:d7:6e:39:cd:48:2e:3d:8c:cc:50:ea:e2:3b: 70:a1:81:3c:e6:f8:06:88:72:3f:07:ff:18:a3:11:93: 0a:d1:ae:16:69:2c:ad:73:ba:a7:aa:a2:ce:58:00:32: d7:2f:4f:92:48:92:96:54:2c:1d:a8:71:59:38:2b:4e: 54:95:8a:ca:5c:fd:a7:09:d9:7c:c8:c6:a9:e9:20:ba: 3d:05:f7:b9:d4:5e:68:5a:19:a5:f5:82:67:fc:b1:5f: 7f:cf:50:2b:32:cf:ed:b9:4c:ae:a5:8e:e5:f6:3e:33 Using reader with a card: Yubico YubiKey FIDO+CCID 0 Sending: 00 A4 04 00 09 A0 00 00 03 08 00 00 10 00 Received (SW1=0x90, SW2=0x00): 61 11 4F 06 00 00 10 00 01 00 79 07 4F 05 A0 00 00 03 08 Sending: 00 20 00 80 08 31 32 33 34 35 36 FF FF Received (SW1=0x90, SW2=0x00) Sending: 00 87 06 9D 88 7C 81 85 82 00 81 81 80 06 84 EF 45 B9 0C 4E 2B 0E CD C1 83 23 21 1B BC D7 B0 3A D7 6E 39 CD 48 2E 3D 8C CC 50 EA E2 3B 70 A1 81 3C E6 F8 06 88 72 3F 07 FF 18 A3 11 93 0A D1 AE 16 69 2C AD 73 BA A7 AA A2 CE 58 00 32 D7 2F 4F 92 48 92 96 54 2C 1D A8 71 59 38 2B 4E 54 95 8A CA 5C FD A7 09 D9 7C C8 C6 A9 E9 20 BA 3D 05 F7 B9 D4 5E 68 5A 19 A5 F5 82 67 FC B1 5F 7F CF 50 2B 32 CF ED B9 4C AE A5 8E E5 F6 3E 33 Received (SW1=0x90, SW2=0x00): 7C 81 83 82 81 80 12 72 21 EB 3C C7 96 28 91 CD BC 23 C9 74 D4 E0 51 EA 76 59 04 80 78 1A F0 E0 18 F1 4E C2 1E 1E 36 DA FE 88 39 C0 68 3E 46 BD 34 90 F5 29 7E DD E6 C1 C2 A1 EE 0A 37 A8 C5 C6 C2 22 88 86 D4 C7 21 AE 93 7C 57 3A 44 93 78 7D 1F 5D 67 E5 F3 44 42 B6 4E D6 80 5B C9 8F 51 15 1A 9A 74 15 8D B4 5B 5C EC 70 D0 9A 73 C8 0F 7B F4 62 12 6F FD 1F 71 8A 8A F0 20 A6 44 AF 91 13 A6 0E 0C 1B 44 89 [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-piv/apdu/auth-decrypt.md/#L1) --- # ##### Table of Contents Authenticate: key agreement --------------------------- ### Command APDU Info | CLA | INS | P1 | P2 | Lc | Data | Le | | --- | --- | --- | --- | --- | --- | --- | | 00 | 87 | _algorithm_ | _slot number_ | _data len_ | _other party's public key_ | (absent) | The _algorithm_ is either `11` (ECC-P256) or `14` (ECC-P384). Note that is is not possible to perform key agreement using RSA. The _slot number_ can be the number of any slot that holds a private key, other than `F9`. That is, the slot number can be any PIV slot other than `80`, `81`, `9B`, or `F9`. The attestation key, `F9`, will sign a certificate it creates, but cannot decrypt or perform key agreement. The _other party's public key_ is encoded as follows 7C len1 82 00 85 len2 where len1 and len2 are lengths in DER format, and is the other party's public key encoded with both x- and y-coordinates: 04 Each coordinate is the size as the key, prepended with 00 bytes if necessary. For ECC, the tags for signing (ECDSA) are `7C`, `82`, `81`, but the tags for ECDH are `7C`, `82`, `85`. That last tag is how the YubiKey will know to perform ECDH as opposed to ECDSA. ### Response APDU Info #### Response APDU for AUTHENTICATE:KEY AGREE (success) Total Length: _variable + 2_ Data Length: _variable_ | Data | SW1 | SW2 | | --- | --- | --- | | 7C _len1_ 82 _len2 _ | 90 | 00 | The shared secret will be the same size as the key, and will be the raw data, no further formatting. Note that the response might be returned over multiple commands. Each return command will be able to return up to 256 bytes. To get more bytes of a return, call the GET RESPONSE APDU. #### Response APDU for AUTHENTICATE:KEY AGREE (wrong or no PIN, or no touch) Total Length: 2 Data Length: 0 | Data | SW1 | SW2 | | --- | --- | --- | | (no data) | 69 | 82 | If the key was generated or imported with a PIN policy other than "Never", and the command was sent without first verifying the PIN or the wrong PIN was entered, then this response will be returned. In addition, if the key's touch policy is not "Never", and after submitting the command the YubiKey was not touched within the time limit, this response will be returned. ### Examples $ opensc-tool -c default -s 00:a4:04:00:09:a0:00:00:03:08:00:00:10:00 -s 00:20:00:80:08:31:32:33:34:35:36:ff:ff -s 00:87:11:90:47:7c:45:82:00:85:41: 04:65:2D:C5:8C:DC:1F:09:11:50:DB:91:F5:F5:8C:A5:32: A5:09:75:E2:34:20:79:09:10:C7:0F:E3:A3:AB:86:DC: EA:9C:70:9F:56:06:3B:CD:22:47:F7:D7:D5:7C:92:5C: 8F:CF:F2:A2:A8:9A:E2:86:00:CA:9A:C1:5E:2A:10:D2 Using reader with a card: Yubico YubiKey FIDO+CCID 0 Sending: 00 A4 04 00 09 A0 00 00 03 08 00 00 10 00 Received (SW1=0x90, SW2=0x00): 61 11 4F 06 00 00 10 00 01 00 79 07 4F 05 A0 00 00 03 08 Sending: 00 20 00 80 08 31 32 33 34 35 36 FF FF Received (SW1=0x90, SW2=0x00) Sending: 00 87 11 90 47 7C 45 82 00 85 41 04 65 2D C5 8C DC 1F 09 11 50 DB 91 F5 F5 8C A5 32 A5 09 75 E2 34 20 79 09 10 C7 0F E3 A3 AB 86 DC EA 9C 70 9F 56 06 3B CD 22 47 F7 D7 D5 7C 92 5C 8F CF F2 A2 A8 9A E2 86 00 CA 9A C1 5E 2A 10 D2 Received (SW1=0x90, SW2=0x00): 7C 22 82 20 71 64 DC 80 F1 6A EE 96 98 AE 13 CE 84 62 C9 C4 1B 52 BA C3 E7 0C E3 13 79 F5 31 FE 5A 96 1C 1A [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-piv/apdu/auth-key-agree.md/#L1) --- # Secure Channel Protocol (SCP) ##### Table of Contents Secure Channel Protocol (SCP) ============================= Commands sent to the YubiKey, or responses from the YubiKey, may contain sensitive data that should not leak to or be tampered with by other applications on the host machine. While the operating system provides some protection through memory space isolation and permissioned access, YubiKeys support additional layers of protection through Secure Channel Protocols (SCP). These protocols, defined by [GlobalPlatform](https://globalplatform.org/) , provide confidentiality and integrity of communication between the host and YubiKey. This standard prescribes methods to encrypt and authenticate smart card (CCID) messages. That is, APDUs and responses are encrypted and contain checksums. If executed properly, the only entities that can see the contents of the messages (and verify their correctness) will be the YubiKey itself and authorized applications. The YubiKey supports two main variants of SCP: * **SCP03** - A symmetric key protocol using AES-128 for encryption and authentication * **SCP11** - An asymmetric protocol using elliptic curve cryptography (ECC) and X.509-certificates Protocol overview ----------------- ### SCP03 (symmetric) SCP03 provides a secure channel using shared secret keys. It is simpler to implement but requires secure key distribution. Think of SCP03 as wrapping commands and responses in an encrypted envelope that only trusted parties can open. Key characteristics: * Uses AES-128 symmetric keys * Three keys per set: encryption, MAC, and data encryption * Supported on YubiKey 5 Series with firmware 5.3+ ### SCP11 (asymmetric) SCP11 uses public key cryptography for authentication and key agreement. It provides stronger security guarantees and simpler key management, but with more complex implementation. SCP11 comes in three variants: * **SCP11a** - Mutual authentication between YubiKey and host * **SCP11b** - YubiKey authenticates to host only * **SCP11c** - Mutual authentication with additional features, such as offline scripting usage (See [GlobalPlatform SCP11 Specification Annex B](https://globalplatform.org/specs-library/secure-channel-protocol-11-amendment-f/) ) Key characteristics: * Uses NIST P-256 elliptic curve * Certificate-based authentication * Supported on YubiKey 5 Series with firmware 5.7.2+ When to use secure channels --------------------------- Secure channels are particularly valuable when: * Communicating with YubiKeys over networks or untrusted channels (e.g. NFC) * Managing YubiKeys remotely through card management systems * Ensuring end-to-end security beyond transport encryption For example, if you tunnel YubiKey commands over the Internet, you might use TLS for transport security and add SCP as an additional layer of defense. Security considerations ----------------------- SCP03 relies entirely on symmetric cryptography, making key distribution a critical security concern. Most YubiKeys ship with default SCP03 keys that are publicly known - using these provides no additional security over cleartext communication. SCP11, being asymmetric, simplifies key management but requires proper certificate handling and validation. Each variant (a/b/c) offers different security properties suitable for different use cases. It is possible to manufacture YubiKeys with custom non-default SCP key sets (this requires a custom order - contact your Yubico sales representative for details). The following sections detail how to implement both protocols, manage keys and certificates, and integrate secure channels with various YubiKey applications. Using secure channels with YubiKey applications ----------------------------------------------- The SDK provides a consistent way to use secure channels across different YubiKey applications. You can enable secure channel communication by providing SCP key parameters when creating application sessions. ### Common pattern Each application session (PIV, OATH, OTP, YubiHSM Auth) accepts an optional `ScpKeyParameters` parameter. This can be either `Scp03KeyParameters` or `Scp11KeyParameters` depending on which protocol you want to use. // Using SCP03 using var scp03Params = Scp03KeyParameters.DefaultKey; // For testing only using var pivSession = new PivSession(yubiKeyDevice, scp03Params); // Using SCP11b using var sdSession = new SecurityDomainSession(yubiKeyDevice, scp03Params); // Create SCP11b key parameters from public key on YubiKey var keyVersionNumber = 0x1; // Example kvn var keyId = ScpKeyIds.SCP11B; var keyReference = KeyReference.Create(keyId, keyVersionNumber); // Get certificate from YubiKey var certificates = sdSession.GetCertificates(keyReference); // Verify the Yubikey's certificate chain against a trusted root using your implementation CertificateChainVerifier.Verify(certificateList) // Use the verified leaf certificate to construct ECPublicKeyParameters var publicKey = certificates.Last().GetECDsaPublicKey(); var scp11Params = new Scp11KeyParameters(keyReference, new ECPublicKeyParameters(publicKey)); // Use SCP11b parameters to open connection using (var pivSession = new PivSession(yubiKeyDevice, scp11Params)) { // All PivSession-commands are now automatically protected by SCP11 session.GenerateKeyPair(PivSlot.Retired12, PivAlgorithm.EccP256, PivPinPolicy.Always); // Protected by SCP11 } ### Application examples #### PIV with secure channel // Using SCP03 StaticKeys scp03Keys = RetrieveScp03KeySet(); // Your static keys using Scp03KeyParameters scp03Params = Scp03KeyParameters.FromStaticKeys(scp03Keys); using (var pivSession = new PivSession(yubiKeyDevice, scp03params)) { // All PivSession-commands are now automatically protected by SCP03 } // Using SCP11b var keyReference = KeyReference.Create(ScpKeyIds.Scp11B, kvn); using (var pivSession = new PivSession(yubiKeyDevice, scp11Params)) { // All PivSession-commands are now automatically protected by SCP11 } #### OATH with secure channel // Using SCP03 StaticKeys scp03Keys = RetrieveScp03KeySet(); // Your static keys using Scp03KeyParamaters scp03Params = Scp03KeyParameters.FromStaticKeys(scp03Keys); using (var oathSession = new OathSession(yubiKeyDevice, scp03params)) { // All oathSession-commands are now automatically protected by SCP03 } // Using SCP11b var keyReference = KeyReference.Create(ScpKeyIds.Scp11B, kvn); using (var oathSession = new OathSession(yubiKeyDevice, scp11Params)) { // All OathSession-commands are now automatically protected by SCP11 } #### OTP with secure channel // Using SCP03 StaticKeys scp03Keys = RetrieveScp03KeySet(); // Your static keys using Scp03KeyParamaters scp03Params = Scp03KeyParameters.FromStaticKeys(scp03Keys); using (var otpSession = new OtpSession(yubiKeyDevice, scp03params)) { // All otpSession-commands are now automatically protected by SCP03 } // Using SCP11b var keyReference = KeyReference.Create(ScpKeyIds.Scp11B, kvn); using (var otpSession = new OtpSession(yubiKeyDevice, scp11Params)) { // All OtpSession-commands are now automatically protected by SCP11 } #### YubiHSM Auth with secure channel // Using SCP03 StaticKeys scp03Keys = RetrieveScp03KeySet(); // Your static keys using Scp03KeyParamaters scp03Params = Scp03KeyParameters.FromStaticKeys(scp03Keys); using (var yubiHsmSession = new YubiHsmAuthSession(yubiKeyDevice, scp03params)) { // All YubiHsmSession-commands are now automatically protected by SCP03 } // Using SCP11b var keyReference = KeyReference.Create(ScpKeyIds.Scp11B, kvn); using (var yubiHsmSession = new YubiHsmSession(yubiKeyDevice, scp11Params)) { // All yubiHsmSession-commands are now automatically protected by SCP11 } ### Direct connection If you need lower-level control, you can establish secure connections directly using [`Connect`](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.IYubiKeyDevice.html#Yubico_YubiKey_IYubiKeyDevice_Connect_) : // Using application ID using var connection = yubiKeyDevice.Connect( applicationId, // byte array for ISO7816 applicationId Scp03KeyParameters.DefaultKey); // Using YubiKeyApplication enum using var connection = yubiKeyDevice.Connect( YubiKeyApplication.Piv, scp11Parameters); // Try pattern if (yubiKeyDevice.TryConnect( YubiKeyApplication.Oath, scpParameters, out var connection)) { using (connection) { // Use connection } } ### Security Domain management The [`SecurityDomainSession`](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Scp.SecurityDomainSession.html) class provides methods to manage SCP configurations: using var session = new SecurityDomainSession(yubiKeyDevice, Scp03KeyParameters.DefaultKey); // Get information about installed keys var keyInfo = session.GetKeyInformation(); // Store certificates for SCP11 session.StoreCertificates(keyReference, certificates); // Manage allowed certificate serials session.StoreAllowlist(keyReference, allowedSerials); // Import private key session.PutKey(keyReference, privateKeyParameters) // Import public key session.PutKey(keyReference, publicKeyParameters) // Reset to factory defaults session.Reset(); ##### Note Using `DefaultKey` in production code provides no security. Always use proper key management in production environments. The next sections will detail specific key management and protocol details for both SCP03 and SCP11. SCP03 (symmetric key protocol) ------------------------------ ### Static keys structure SCP03 relies on a set of shared, secret, symmetric cryptographic keys. Each key set consists of three 16-byte AES-128 keys encapsulated in the [`StaticKeys`](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Scp.StaticKeys.html) class: * Channel encryption key (Key-ENC) * Channel MAC key (Key-MAC) * Data encryption key (Key-DEK) These keys are encapsulated in a `StaticKeys` class and provided to the SDK via `Scp03KeyParameters`: var staticKeys = new StaticKeys(keyDataMac, keyDataEnc, keyDataDek); var scp03Params = new Scp03KeyParameters(ScpKeyIds.Scp03, 0x01, staticKeys); ### Key sets on the YubiKey A YubiKey can contain up to three SCP03 key sets. Each set is identified by a Key Version Number (KVN): slot 1: ENC MAC DEK (KVN=1) slot 2: ENC MAC DEK (KVN=2) slot 3: ENC MAC DEK (KVN=3) Standard YubiKeys are manufactured with a default key set (KVN=0xFF): slot 1: ENC(default) MAC(default) DEK(default) slot 2: --empty-- slot 3: --empty-- ##### Important The default keys are publicly known (0x40 41 42 ... 4F) and provide no security. You should replace them in production environments. ### Managing key sets Use `SecurityDomainSession` to manage SCP03 key sets: // Replace default keys using var session = new SecurityDomainSession(yubiKeyDevice, Scp03KeyParameters.DefaultKey); var newKeys = new StaticKeys(newKeyDataMac, newKeyDataEnc, newKeyDataDek); var newKeyParams = new Scp03KeyParameters(ScpKeyIds.Scp03, 0x01, newKeys); session.PutKey(newKeyParams.KeyReference, newKeyParams.StaticKeys); // Add another key set using var session = new SecurityDomainSession(yubiKeyDevice, existingKeyParams); var keyRef = KeyReference.Create(ScpKeyIds.Scp03, 0x02); // KVN=2 session.PutKey(keyRef, additionalKeys); // Delete a key set session.DeleteKey(keyRef, false); // Reset to factory defaults (restore default keys) session.Reset(); ### Key set rules 1. **Key Version Numbers (KVN):** * Default key set: KVN=0xFF * Accepted values are between 1 and 0x7F 2. **Key Id's (KID)** * Default value: 1 * Accepted values are between 1 and 3 3. **Default Key Replacement:** * When adding first custom key set, default keys are always removed * Cannot retain default keys alongside custom keys 4. **Multiple Key Sets:** * After default keys are replaced, can have 1-3 custom key sets * Each must have unique KVN * Can add/remove without affecting other sets ### Example: complete key management flow // Start with default keys var defaultScp03Params = Scp03KeyParameters.DefaultKey; var firstKvn = 0x1; var keyRef1 = KeyReference.Create(ScpKeyIds.Scp03, firstKvn); using (var session = new SecurityDomainSession(yubiKeyDevice, defaultScp03Params)) { // Add first custom key set (removes default) session.PutKey(keyRef1, newKeys); } // Now authenticate with new keys var newScp03Params = new Scp03KeyParameters(keyRef1, newKeys); using (var session = new SecurityDomainSession(yubiKeyDevice, newScp03Params)) { // Add second key set var secondKvn = 0x2; var keyRef2 = KeyReference.Create(ScpKeyIds.Scp03, secondKvn); session.PutKey(keyRef2, customKeys2); // Check current key information var keyInfo = session.GetKeyInformation(); } ### Key management responsibilities You should: * Track which keys are loaded on each YubiKey * Track KVNs in use * Know if a YubiKey has custom keys from manufacturing * Handle key rotation The YubiKey provides no metadata about installed keys beyond what's available through `GetKeyInformation()`. ##### Note Always use proper key management in production. Never store sensitive keys in source code or configuration files. SCP11 (asymmetric key protocol) ------------------------------- SCP11 uses asymmetric cryptography based on elliptic curves (NIST P-256) for authentication and key agreement. Compared to SCP03, it uses certificates instead of pre-shared keys, providing greater flexibility in cases where the two entities setting up the secure channel are not deployed in strict pairs. The secure channel can be embedded into complex use cases, such as: * Installation of payment credentials on wearables * Production systems * Remote provisioning of cell phone subscriptions Detailed information about SCP11 can be found in [GlobalPlatform Card Technology, Secure Channel Protocol '11' Card Specification v2.3 – Amendment F, Chapter 2](https://globalplatform.org/specs-library/secure-channel-protocol-11-amendment-f/) It comes in three variants, each offering different security properties: ### SCP11 variants * **SCP11a**: Full mutual authentication between host and YubiKey using certificates * Basic mutual authentication * Uses both static and ephemeral key pairs * Requires certificate chain and off-card entity (OCE) verification * Supports authorization rules in OCE certificates * Suitable for direct host-to-YubiKey communication * **SCP11b**: YubiKey authenticates to host only * Simplest variant, no mutual authentication * Uses both static and ephemeral key pairs * Suitable when host authentication isn't required * **SCP11c**: Enhanced mutual authentication with additional features * Uses both static and ephemeral key pairs * Supports offline scripting mode: * Can precompute personalization scripts for groups of cards * Scripts can be deployed via online services or companion apps * Cryptographic operations remain on secure OCE server * Supports authorization rules in OCE certificates ### Key benefits of SCP11 over SCP03 SCP11 provides several advantages over SCP03: * Uses certificates instead of pre-shared keys for authentication * More flexible deployment - doesn't require strict pairing of entities * Supports ECC for key establishment with AES-128 * Better suited for complex deployment scenarios ### Key parameters Unlike SCP03's static keys, SCP11 uses `Scp11KeyParameters` which can contain: * Public/private key pairs * Certificates * Key references * Off-card entity (OCE) information // SCP11b basic parameters var keyReference = KeyReference.Create(ScpKeyIds.Scp11B, 0x1); var scp11Params = new Scp11KeyParameters( keyReference, new ECPublicKeyParameters(publicKey)); // SCP11a/c with full certificate chain var scp11Params = new Scp11KeyParameters( keyReference, // Key reference for this connection pkSdEcka, // Public key for key agreement oceKeyReference, // Off-card entity reference skOceEcka, // Private key for key agreement certificateChain); // Certificate chain for authentication ### Key management Use `SecurityDomainSession` to manage SCP11 keys and certificates: using var session = new SecurityDomainSession(yubiKeyDevice, Scp03KeyParameters.DefaultKey); // Generate new EC key pair var keyReference = KeyReference.Create(ScpKeyIds.Scp11B, 0x3); var publicKey = session.GenerateEcKey(keyReference); // Import existing key pair var privateKey = new ECPrivateKeyParameters(ecdsa); session.PutKey(keyReference, privateKey); // Store certificates session.StoreCertificates(keyReference, certificates); // Manage certificate serial number allowlist var serials = new List { "7F4971B0AD51F84C9DA9928B2D5FEF5E16B2920A", // Examples "6B90028800909F9FFCD641346933242748FBE9AD" }; session.StoreAllowlist(oceKeyReference, serials); ### SCP11b example Simplest variant, where YubiKey authenticates to host: // Get certificates stored on YubiKey var keyReference = KeyReference.Create(ScpKeyIds.Scp11B, 0x1); IReadOnlyCollection certificateList; using (var session = new SecurityDomainSession(yubiKeyDevice)) { certificateList = session.GetCertificates(keyReference); } // Verify the certificate chain against a trusted root using your implementation CertificateChainVerifier.Verify(certificateList) // Create parameters using leaf certificate which has now been verified var leaf = certificateList.Last(); var ecDsaPublicKey = leaf.PublicKey.GetECDsaPublicKey()!.ExportParameters(false); var keyParams = new Scp11KeyParameters( keyReference, new ECPublicKeyParameters(ecDsaPublicKey)); // Use with any application using var pivSession = new PivSession(yubiKeyDevice, keyParams); ### SCP11a example Full mutual authentication requires more setup: // Start with default SCP03 connection using var session = new SecurityDomainSession(yubiKeyDevice, Scp03KeyParameters.DefaultKey); const byte kvn = 0x03; var keyRef = KeyReference.Create(ScpKeyIds.Scp11A, kvn); // Generate new key pair on YubiKey var newPublicKey = session.GenerateEcKey(keyRef); // Setup off-card entity (OCE) var oceRef = KeyReference.Create(OceKid, kvn); var ocePublicKey = new ECPublicKeyParameters(oceCerts.Ca.PublicKey.GetECDsaPublicKey()); session.PutKey(oceRef, ocePublicKey); // Store CA identifier var ski = GetSubjectKeyIdentifier(oceCerts.Ca); session.StoreCaIssuer(oceRef, ski); // Create SCP11a parameters var scp11Params = new Scp11KeyParameters( keyRef, new ECPublicKeyParameters(newPublicKey.Parameters), oceRef, new ECPrivateKeyParameters(privateKey), certChain); // Use the secure connection using var session = new SecurityDomainSession(yubiKeyDevice, scp11Params); ### Security considerations 1. **Certificate Management:** * Proper certificate validation is crucial * Consider using certificate allowlists * Manage certificate chains carefully 2. **Key Generation:** * Can generate keys on YubiKey or import existing * YubiKey-generated keys never leave the device * Imported keys must be properly protected 3. **Protocol Selection:** * SCP11b: Simplest variant, no mutual authentication * SCP11a: Better security through mutual authentication * SCP11c: Additional features over SCP11a 4. **Certificate Allowlists:** * Restrict which certificates can authenticate * Update lists as certificates change * Can be used as a part of a certificate revocation strategy ### Checking SCP support // Check firmware version for SCP11 support if (yubiKeyDevice.HasFeature(YubiKeyFeature.Scp11)) { // Device supports SCP11 } // Get information about installed keys using var session = new SecurityDomainSession(yubiKeyDevice); var keyInfo = session.GetKeyInformation(); // Get supported CA identifiers var caIds = session.GetSupportedCaIdentifiers(true, true); ##### Note SCP11 requires firmware version 5.7.2 or later. Earlier firmware versions only support SCP03. Additional documentation ======================== * [Global Platform Consortium](https://globalplatform.org/) * [GlobalPlatform SCP11 Specification](https://globalplatform.org/specs-library/secure-channel-protocol-11-amendment-f/) [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/sdk-programming-guide/secure-channel-protocol.md/#L1) --- # ##### Table of Contents Generate asymmetric key pair ---------------------------- ### Command APDU Info | CLA | INS | P1 | P2 | Lc | Data | Le | | --- | --- | --- | --- | --- | --- | --- | | 00 | 47 | 00 | _Slot number_ | _data len_ | \[AC __ 80 01 __\]
\[AA 01 __\]
\[AB 01 __\] | (absent) | The slot number can be one of the following (hex values): 9A, 9C, 9D, 9E, 82, 93, 84, 85, 86, 87, 88, 89, 8A, 8B, 8C, 8D, 8E, 8F, 90, 91, 92, 93, 94, 95 F9 Note that SP 800-73-4 declares that another possible value for the slot number is `04`. However, the YubiKey does not support that slot. The value for the "remaining bytes" field must be equal to the number of bytes that come after it. For example, if three bytes come after the "remaining bytes" field, the field's value must be 03. There are six choices for "alg" (algorithm and size): RSA-1024 (06), RSA-2048 (07), RSA 3072 (05), RSA 4096 (16), ECC-P-256 (11), and ECC-P-384 (14). Both the PIN policy and touch policy are optional. If either or both are not given, they will be default. The default for PIN is "once" and touch is "never". The value for the PIN policy in the APDU is either "never" (01), "once" (02), or "always" (03). The value for the touch policy in the APDU is either "never" (01), "always" (02) or "cached" (03). An APDU to generate an ECC-P256 key pair with a PIN policy of "once" and a touch policy of "always" would be the following: 00 47 00 9C 0B AC 09 80 01 11 AA 01 02 AB 01 02 An APDU to generate an RSA-2048 key pair with PIN and touch policies of "default" would be the following: 00 47 00 9D 05 AC 03 80 01 07 ### Response APDU Info: Management Key Authentication Missing Total Length: 2 Data Length: 0 | Data | SW1 | SW2 | | --- | --- | --- | | (no data) | 69 | 82 | ### Response APDU Info: Success Total Length: _variable + 2_ Data Length: _variable_ | Data | SW1 | SW2 | | --- | --- | --- | | _public key_ | 90 | 00 | The public key is in the form of a set of TLVs. If the key is ECC, there is one TLV, where the value (the V) is the public point. If the key is RSA, there are two TLVs, where the first value is the modulus and the second is the public exponent. ECC: 86 || length || 04 || public point 86 41 04 C4 17 7F 2B 96 8F 9C 00 0C 4F 3D 2B 88 B0 AB 5B 0C 3B 19 42 63 20 8C A1 2F EE 1C B4 D8 81 96 9F D8 C8 D0 8D D1 BB 66 58 00 26 7D 05 34 A8 A3 30 D1 59 DE 66 01 0E 3F 21 13 29 C5 98 56 07 B5 26 Note that the 04 is the first byte in the standard way to represent an ECC point. The 04 means that both the x- and y-coordinates follow. This is the only format the YubiKey supports. The other two are 02 and 03, indicating a compressed point, only the x-coordinate is given and the reader must compute the y-coordinate. There are two possible y-coordinates for each x, and the 02 or 03 indicates which to use. 04 x-coordinate: C4 17 7F 2B 96 8F 9C 00 0C 4F 3D 2B 88 B0 AB 5B 0C 3B 19 42 63 20 8C A1 2F EE 1C B4 D8 81 96 9F y-coordinate: D8 C8 D0 8D D1 BB 66 58 00 26 7D 05 34 A8 A3 30 D1 59 DE 66 01 0E 3F 21 13 29 C5 98 56 07 B5 26 RSA: 81 || length || modulus || 82 || length || public exponent 81 82 01 00 F1 50 BE FB B0 9C AD FE F8 0A 3D 10 8C 36 92 DC 34 B7 09 86 42 C9 CD 00 55 D1 A4 A0 40 61 5A 2A 8A B4 7D AC A1 34 A2 2F 0A 36 D2 34 B7 D8 72 58 20 D6 04 66 80 7A 7A 0A D1 03 32 A2 D0 C9 92 7E 59 B8 63 F8 FD A3 0F D0 F1 A1 48 50 DF 82 DC 4F 9F 7C 18 02 29 35 72 DD 10 54 80 12 68 89 8F 05 CA A0 EB D4 F0 82 85 B8 67 AD F3 F7 86 2E D3 6E C8 E0 46 C4 6C 67 57 53 47 C7 38 84 AC F4 F4 44 81 AB DB 64 EE 53 B5 35 AE 92 FF 8E FE 00 A7 A8 B2 86 3B 66 DB 8E A7 07 FF 13 28 49 E5 9B D1 C8 D2 2C F9 84 D5 8A FF 00 3E 88 FB C1 E1 F8 37 8E 9D DB 5D 45 61 1B 29 29 A5 B7 C3 E7 38 E9 1A 15 F3 58 DD CA E2 E1 3D 86 BA BC 63 E2 CD A4 75 3A F9 9C D8 23 0F D8 18 59 F8 12 29 62 AB DC BE A5 01 C5 28 C3 E8 A1 65 CF 39 30 66 18 6A E5 AD FA EC 48 CC E7 BA 8B F7 56 6B DD 7B 56 2A 3B E7 E9 82 03 01 00 01 ### Examples $ opensc-tool -c default -s 00:a4:04:00:09:a0:00:00:03:08:00:00:10:00 -s 00:47:00:9c:0b:ac:09:80:01:06:aa:01:02:ab:01:02 Using reader with a card: Yubico YubiKey OTP+FIDO+CCID 0 Sending: 00 A4 04 00 09 A0 00 00 03 08 00 00 10 00 Received (SW1=0x90, SW2=0x00): 61 11 4F 06 00 00 10 00 01 00 79 07 4F 05 A0 00 00 03 08 Sending: 00 47 00 9C 0B AC 09 80 01 06 AA 01 02 AB 01 02 Received (SW1=0x69, SW2=0x82) [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-piv/apdu/generate-pair.md/#L1) --- # ##### Table of Contents Authenticate: management key single authentication ---------------------------------------------------- ### Command APDU Info (First Call) | CLA | INS | P1 | P2 | Lc | Data | Le | | --- | --- | --- | --- | --- | --- | --- | | 00 | 87 | xx | 9B | 04 | 7C 02 81 00 | (absent) | Note that the standard specifies that P1 holds the "Algorithm reference". That means the value should be 03 for Triple-DES, 08 for AES-128, 0A for AES-192, or 0C for AES-256. The value in P2 is 9B, the slot for the management key. ### Response APDU Info (First Response) Total Length: 14 Data Length: 12 | Data | SW1 | SW2 | | --- | --- | --- | | 7C 0A 81 08 <_Client Authentication Challenge (8 bytes)_\> | 90 | 00 | ### Command APDU Info (Second Call) | CLA | INS | P1 | P2 | Lc | Data | Le | | --- | --- | --- | --- | --- | --- | --- | | 00 | 87 | xx | 9B | 0C | 7C 0A 82 08 <_Client Authentication Response (8 bytes)_\> | (absent) | ### Response APDU Info (Second Response) Total Length: 2 Data Length: 0 | Data | SW1 | SW2 | | --- | --- | --- | | (absent) | 90 | 00 | #### Second Response APDU: Key Not Authenticated Total Length: 2 Data Length: 0 | Data | SW1 | SW2 | | --- | --- | --- | | (absent) | 69 | 82 | The error code `69 82` means "Security status not satisfied". That is, the response to the challenge was incorrect (probably used the wrong management key). ### Examples $ opensc-tool -c default -s 00:a4:04:00:09:a0:00:00:03:08:00:00:10:00 -s 00:87:00:9b:04:7c:02:81:00 -s 00:87:00:9b:0C:7c:0A:82:08:83:50:d1:81:4c:72:ba:09 Using reader with a card: Yubico YubiKey FIDO+CCID 0 Sending: 00 A4 04 00 09 A0 00 00 03 08 00 00 10 00 Received (SW1=0x90, SW2=0x00): 61 11 4F 06 00 00 10 00 01 00 79 07 4F 05 A0 00 00 03 08 Sending: 00 87 00 9B 04 7C 02 81 00 Received (SW1=0x90, SW2=0x00): 7C 0A 81 08 D4 BD 9B 1D A5 D2 6C DA Sending: 00 87 00 9B 0C 7C 0A 82 08 83 50 D1 81 4C 72 BA 09 Received (SW1=0x69, SW2=0x82) Authenticate: management key mutual authentication ---------------------------------------------------- ### Command APDU Info (First Call) | CLA | INS | P1 | P2 | Lc | Data | Le | | --- | --- | --- | --- | --- | --- | --- | | 00 | 87 | xx | 9B | 04 | 7C 02 80 00 | (absent) | Note that the difference between this APDU and the single authentication APDU is the third data byte (the byte at index 2). In single authentication it is 81, in mutual authentication it is 80. ### Response APDU Info (First Response) Total Length: 14 Data Length: 12 | Data | SW1 | SW2 | | --- | --- | --- | | 7C 0A 80 08 <_Client Authentication Challenge (8 bytes)_\> | 90 | 00 | ### Command APDU Info (Second Call) | CLA | INS | P1 | P2 | Lc | Data | Le | | --- | --- | --- | --- | --- | --- | --- | | 00 | 87 | xx | 9B | 18 | 7C 16 80 08 <_Client Authentication Response (8 bytes)_\> 81 08 <\*YubiKey Authentication | | | Challenge (8 bytes)\*> 82 00 | (absent) | | | | | | ### Response APDU Info (Second Response) Total Length: 14 Data Length: 12 | Data | SW1 | SW2 | | --- | --- | --- | | 7C 0A 82 08 <_YubiKey Authentication Response (8 bytes)_\> | 90 | 00 | #### Second Response APDU: Key Not Authenticated Total Length: 2 Data Length: 0 | Data | SW1 | SW2 | | --- | --- | --- | | (absent) | 69 | 82 | The error code `69 82` means "Security status not satisfied". That is, the response to the challenge was incorrect (probably used the wrong management key). ### Examples $ opensc-tool -c default -s 00:a4:04:00:09:a0:00:00:03:08:00:00:10:00 -s 00:87:00:9b:04:7c:02:80:00 -s 00:87:00:9b:18:7c:16:80:08:83:50:d1:81:4c:72:ba:09:81:08:11:22:33:44:55:66:77:88:82:00 Using reader with a card: Yubico YubiKey FIDO+CCID 0 Sending: 00 A4 04 00 09 A0 00 00 03 08 00 00 10 00 Received (SW1=0x90, SW2=0x00): 61 11 4F 06 00 00 10 00 01 00 79 07 4F 05 A0 00 00 03 08 Sending: 00 87 00 9B 04 7C 02 80 00 Received (SW1=0x90, SW2=0x00): 7C 0A 80 08 61 E2 04 AE 33 5B 32 58 Sending: 00 87 00 9B 18 7C 16 80 08 83 50 D1 81 4C 72 BA 09 81 08 11 22 33 44 55 66 77 88 82 00 Received (SW1=0x69, SW2=0x82) [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-piv/apdu/auth-mgmt.md/#L1) --- # OATH session APIs ##### Table of Contents OATH session APIs ================= The high level OATH session APIs provide a simpler way to work with the OATH application on the YubiKey. The OATH session API is a layer built on the lower level command API. Session APIs will help perform OATH scenarios in a shorter amount of development time and without getting involved with each command's details. General Definitions ------------------- The OATH application is used to manage and use OATH credentials with the YubiKey NEO, YubiKey 4, or YubiKey 5. It can be accessed over USB (when the CCID transport is enabled) or over NFC. ### IYubiKeyDevice There is an IYubiKeyDevice interface that represents the YubiKey chosen. // use the first YubiKey found var yubiKeyToUse = YubiKeyDevice.FindAll().First(); ### Credential The `Credential` class represents a single OATH credential. The credential can be a TOTP (Time-based One-time Password) or a HOTP (HMAC-based One-time Password). var credentialTotp = new Credential { Issuer = "Yubico", AccountName = "test@yubico.com", Type = Totp, Period = 30, Algorithm = Sha1, Digits = 6, Secret = "test", RequireTouch = true }; var credentialHotp = new Credential { Issuer = "Yubico", AccountName = "test@yubico.com", Type = Hotp, Algorithm = Sha256, Digits = 8, Counter = 10, Secret = "test", RequireTouch = true }; ### Code The `Code` class represents the credential’s OTP code generated on the YubiKey. The YubiKey supports Open Authentication (OATH) standards for generating one-time password (OTP) codes. The YubiKey-generated passcode can be used as one of the authentication options in two-factor or multi-factor authentication. var credentialTotp = new Credential { Issuer = "Yubico", AccountName = "test@yubico.com", Type = Totp, Period = 30 }; Code otpCode = oathSession.CalculateCredential(credentialTotp); // otpCode will look like: Value = "799357", ValidFrom = DateTimeOffset.Now; ValidUntil = DateTimeOffset.MaxValue; // HOTP credential. // or ValidUntil = DateTimeOffset.Now + Period // TOTP credential period (15, 30, 60 seconds) Read more about [credentials](https://docs.yubico.com/yesdk/users-manual/application-oath/oath-credentials.html) . OathSession ----------- The `OathSession` class contains methods to perform high-level operations and scenarios. Once you have chosen the YubiKey, you have an object: an instance of the IYubiKeyDevice interface representing the actual hardware. To perform OATH operations, create an instance of an OathSession class and pass the YubiKey object. This will connect to the OATH application on the chosen YubiKey: var oathSession = new OathSession(yubiKeyToUse); This class implements [IDisposable](https://docs.microsoft.com/en-us/dotnet/api/system.idisposable) so that we can close out a session. If the OATH application on the chosen YubiKey is protected with a password, the user will need to verify the password first to unlock the application in order to perform any OATH operations except resetting the application. Each method except ResetApplication() will call the KeyCollector delegate to manage authentication if the ResponseStatus returns AuthenticationRequired. So, the delegate will be called every time when a password is needed in order to unlock the OATH application. KeyCollector delegate --------------------- This delegate will be called every time when a password is needed in order to unlock the OATH application. The delegate provided will read the KeyEntryData which contains the information needed to determine what to collect and methods to submit what was collected. The delegate will return true for success or false for "cancel." A cancel will usually happen when the user has clicked a "Cancel" button. The SDK will call the KeyCollector with a Request of Release when the process completes. Methods ------- ### Get credentials The GetCredentials() method gets all configured credentials on the YubiKey. IList credentials = oathSession.GetCredentials(); // Use LINQ to filter credentials by credential's type List filteredCredentials = oathSession.GetCredentials().Where(credential => credential.Type == CredentialType.Totp).ToList(); ### Get OTPs The CalculateAllCredentials() method calculates OTP (one-time passwords) values for all configured credentials on the YubiKey except HOTP credentials and TOTP credentials requiring touch. The OTPs need to be calculated because the YubiKey doesn't have an internal clock. The system time is used and passed to the YubiKey. IDictionary credentialCodes = oathSession.CalculateAllCredentials(); Also, there is the CalculateCredential() method which gets a single OTP value for a specific credential on the YubiKey. This can be used for HOTP credentials and when the RequireTouch property is set for a credential, so you just need to request to recalculate one credential. var credentialTotp = new Credential { Issuer = "Yubico", AccountName = "test@yubico.com", Type = Totp, Period = 30 }; // Pass Credential object. Code otpCode = oathSession.CalculateCredential(Credential); // Or // Pass Issuer, AccountName, Type and Period of the credential you want to calculate. Code otpCode = oathSession.CalculateCredential( "Yubico", "test@yubico.com", CredentialType.Totp, CredentialPeriod.Period30); ### Add credential The AddCredential() method adds a new credential or overwrites the existing one on the YubiKey. The existing credential will be overwritten if the same Issuer and Account Name is used when adding a new credential. It applies to TOTP with a default period (30sec) and HOTP credentials. For example, suppose you have a HOTP credential stored on the YubiKey, and you try to add a TOTP credential with a default period and the same Issuer and Account name. In that case, the credential will be overwritten. The behavior would also be the same if the TOTP credential was added first, and the HOTP credential was second. However, this won't apply to TOTP credentials with non-default periods 15sec or 60sec; they will be added separately. A YubiKey is an embedded device, and storage is a scarce resource. Due to this constraint, the maximum number of credentials that can be added to a YubiKey is 32. Also, the same reason applies to the 64 character restriction for the credential's name (issuer + account name). Note that credentials on the YubiKeys with a firmware version 5.3.0 or older cannot be renamed once they have been added; they can only be viewed or deleted. If you want to change anything about the credential, including the name of the credential, you must delete the existing credential, and create a new credential with the settings and the name that you want. var credentialTotp = new Credential { Issuer = "Yubico", AccountName = "test@yubico.com", Type = Totp, Period = 30, Secret = "test", Digits = 6 }; // Pass Credential object. oathSession.AddCredential(credentialTotp); // Or // Pass the string that you received from QR reader or retrieved from the server. This method will return the credential parsed from the URI string. Credential credential = oathSession.AddCredential( "otpauth://totp/ACME%20Co:test@example.com?secret=HXDMVJECJJWSRB3HWIZR4IFUGFTMXBOZ&issuer=ACME%20Co&algorithm=SHA1&digits=6&period=30"); Read more about [credentials](https://docs.yubico.com/yesdk/users-manual/application-oath/oath-credentials.html) and [URI strings](https://docs.yubico.com/yesdk/users-manual/application-oath/uri-string-format.html) . Remove credential ----------------- The RemoveCredential() method removes an existing credential from the YubiKey. var credentialTotp = new Credential { Issuer = "Yubico", AccountName = "test@yubico.com", Type = Totp, Period = 60, Secret = "test", Digits = 8 }; // Pass Credential object. oathSession.RemoveCredential(credentialTotp); // Or // Pass Issuer, AccountName, Type and Period of the credential you want to remove. Credential credential = oathSession.RemoveCredential( "Yubico", "test@yubico.com", CredentialType.Totp, CredentialPeriod.Period60); // Or, pass just the Issuer and AccountName if the credential is a TOTP type with a default period. Credential credential = oathSession.RemoveCredential( "Yubico", "test@yubico.com"); Rename credential ----------------- The RenameCredential() method renames an existing credential on the YubiKey by setting new issuer and account names. This is only available on the YubiKeys with a firmware version 5.3.0 or later. var credentialTotp = new Credential { Issuer = "Yubico", AccountName = "test@yubico.com", Type = Totp, Period = 60, Secret = "test", Digits = 8 }; // Pass Credential object and the new Issuer and AccountName. oathSession.RenameCredential(credentialTotp, "Test", "example@test.com"); // Or // Pass Issuer, AccountName, Type and Period of the credential you want to rename, as well as the new Issuer and AccountName. Credential credential = RemoveCredential( "Yubico", "test@yubico.com", "Test", "example@test.com", CredentialType.Totp, CredentialPeriod.Period60); // Pass just the current and new Issuer and AccountName if the credential has TOTP type and default period. Credential credential = RemoveCredential( "Yubico", "test@yubico.com", "Test", "example@test.com"); Reset OATH ---------- The ResetApplication() method resets the YubiKey's OATH application back to a factory default state. This will remove the password if one set and delete all OATH credentials stored on the YubiKey. oathSession.ResetApplication(); Set password ------------ The SetPassword() method sets or changes the password for the OATH application. Suppose the password was previously configured on the YubiKey. In that case, this method will prompt for the current password to verify, as well as a new password to change to using the KeyCollector callback. If a password is not configured, this method will collect only a new password to set. The password can be any string of bytes. However, most applications will choose to encode a user supplied string using UTF-8. The password is passed through 1,000 rounds of PBKDF2 with a salt value supplied by the YubiKey, ensuring an extra level of security against brute force attacks. oathSession.SetPassword(); Verify password --------------- The VerifyPassword() method attempts to proactively verify the current password. Note that the the SDK will automatically call the KeyCollector delegate when the password is required. Sometimes an application may want to choose when the password is gathered. This may help with implementing a specific user experience that may otherwise be impossible if you relied on the default KeyCollector behavior. The method performs mutual authentication with the YubiKey using the password collected by the key collector. oathSession.VerifyPassword(); Unset password -------------- The UnsetPassword() method attempts to remove the current password. This method prompts for the current password to verify first and then removes the authentication. oathSession.UnsetPassword(); Read more about [OathPassword](https://docs.yubico.com/yesdk/users-manual/application-oath/oath-password.html) implementation on the YubiKey. [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-oath/oath-session.md/#L1) --- # ##### Table of Contents Get bio metadata ---------------- ### Command APDU Info | CLA | INS | P1 | P2 | Lc | Data | Le | | --- | --- | --- | --- | --- | --- | --- | | 00 | F7 | 00 | 96 | (absent) | (absent) | (absent) | ### Response APDU Info Total Length: _9_ + 2 Data Length: _9_ | Data | SW1 | SW2 | | --- | --- | --- | | _bio metadata as set of TLV_ | 90 | 00 | The data consists of a set of TLVs. The possible valid tags (T of TLV) are listed in the table below. The length (L of TLV) is one. The values (V of TLV) are dependent on the tags, described in the table below. #### Table 1: List of Metadata Elements | Tag | Name | Meaning | Data | | --- | --- | --- | --- | | 07 | IsConfigured | state of biometric verification configuration
(ie. fingerprints are enrolled) | 01 (configured)
00 (not configured) | | 06 | RetriesRemaining | indicates how many biometric match retries are left | 00-03
(when IsConfigured is 01, value 00 indicates that biometric verification is blocked) | | 08 | HasTemporaryPin | indicates if a temporary PIN has been generated in the YubiKey | 01 (generated)
00 (not generated) | [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-piv/apdu/bio-metadata.md/#L1) --- # ##### Table of Contents Get data -------- ### Command APDU Info | CLA | INS | P1 | P2 | Lc | Data | Le | | --- | --- | --- | --- | --- | --- | --- | | 00 | CB | 3F | FF | 3, 4, or 5 | _TLV with T of 5C and V of data object tag_ | (absent) | Note that there are other standards and applications that use the GET DATA APDU, and they sometimes use different values for INS, P1, and P2. They sometimes use the same values as possible input, but describe options in different cases. However, the PIV standard specifies only this combination of INS, P1, and P2. ### Response APDU info: success Total Length: _variable + 2_ Data Length: _variable_ | Data | SW1 | SW2 | | --- | --- | --- | | _data object_ | 90 | 00 | The data object will be a TLV with a tag of `7E` or `53`. If the Get Data command requested "Discovery" (data tag of `7E`), then the TLV will be `73 L V`. Otherwise it will be `53 L V`. ### Response APDU info: data object not found Total Length: _2_ Data Length: _0_ | Data | SW1 | SW2 | | --- | --- | --- | | (no data) | 6A | 82 | ### Response APDU info: security status not satisfied Total Length: _2_ Data Length: _0_ | Data | SW1 | SW2 | | --- | --- | --- | | (no data) | 69 | 82 | ### Examples This gets the CHUID $ opensc-tool -c default -s 00:a4:04:00:09:a0:00:00:03:08:00:00:10:00 -s 00:cb:3f:ff:05:5c:03:5f:c1:02 Using reader with a card: Yubico YubiKey OTP+FIDO+CCID 0 Sending: 00 A4 04 00 09 A0 00 00 03 08 00 00 10 00 Received (SW1=0x90, SW2=0x00): 61 11 4F 06 00 00 10 00 01 00 79 07 4F 05 A0 00 00 03 08 Sending: 00 CB 3F FF 05 5C 03 5F C1 02 Received (SW1=0x90, SW2=0x00): 53 3B 30 19 D4 E7 39 DA 73 9C ED 39 CE 73 9D 83 68 58 21 08 42 10 84 21 38 42 10 C3 F5 34 10 AD 64 BE AC 16 11 4A 56 93 A2 9D 58 3B 74 CB 44 35 08 32 30 33 30 30 31 30 31 3E 00 FE 00 53 3B 30 19 D4 E7 39 DA 73 9C ED 39 CE 73 9D 83 68 58 21 08 42 10 84 21 38 42 10 C3 F5 34 10 AD 64 BE AC 16 11 4A 56 93 A2 9D 58 3B 74 CB 44 35 08 32 30 33 30 30 31 30 31 3E 00 FE 00 [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-piv/apdu/get-data.md/#L1) --- # ##### Table of Contents Authenticate: sign ------------------ ### Command APDU Info | CLA | INS | P1 | P2 | Lc | Data | Le | | --- | --- | --- | --- | --- | --- | --- | | 00 | 87 | _algorithm_ | _slot number_ | _data len_ | _encoded digest of data to sign_ | (absent) | The _algorithm_ is either `06` (RSA-1024), `07` (RSA-2048), `05` (RSA 3072), `16` (RSA 4096), `11` (ECC-P256), or `14` (ECC-P384). The _slot number_ can be the number of any slot that holds a private key, other than `F9`. That is, the slot number can be any PIV slot other than `80`, `81`, `9B`, or `F9`. The attestation key, `F9`, will sign a certificate it creates, so it can sign. It simply cannot sign arbitrary data, only attestation statements. The _encoded digest_ is 7C len1 82 00 81 len2 where len1 and len2 are lengths in DER format, and is the digest of the data to sign. With RSA, the digest is encoded using either PKCS 1 v 1.5 padding, or PKCS 1 PSS. For example, if using PKCS 1 v 1.5 padding, the encoded digest is built as follows. formatted digest = 00 01 FF FF ... FF 00 With a 2048-bit RSA key, the data to pass to the command is 7c 82 01 06 82 00 81 82 01 00 ^ ^ ^ ^ |<-- 256 bytes -->| | | | | | | ---------- len2 ---------- len1 If the data for the APDU is too long for one call (256 bytes), then there will be two calls (a chain). For ECC, there is one format: 7C len1 82 00 81 len2 where len1 and len2 are lengths in DER format, and is the digest of the data to sign. If the key is EccP256, the digest must be 256 bits (32 bytes) or shorter. You will generally use SHA-256. 7C 24 82 00 81 20 <32-byte digest> If the key is EccP384, the digest must be 384 bits (48 bytes) or shorter. You will generally use SHA-384. 7C 34 82 00 81 30 <48-byte digest> ### Response APDU Info #### Response APDU for AUTHENTICATE:SIGN (success) Total Length: _variable + 2_ Data Length: _variable_ | Data | SW1 | SW2 | | --- | --- | --- | | 7C _len1_ 82 _len2 _ | 90 | 00 | Note that the signature might be returned over multiple commands. Each return command will be able to return up to 256 bytes. To get more bytes of a return, call the GET RESPONSE APDU. The signature is returned encoded as follows, 7C len1 82 len2 For example, with RSA-2048, the signature will be 7C 82 01 04 82 82 01 00 <256-byte signature> With ECC-P256, the signature will be 7C 48 82 46 <70-byte signature> An ECC signature is ECDSA, which is the DER encoding of SEQUENCE { r INTEGER, s INTEGER } Both r and s are the same size as the key, so will be 32 bytes long. It is possible that the encoding will be up to 33 bytes, and it can be shorter. For example, 30 44 02 20 <32-byte r> 02 20 <32-byte s> #### Response APDU for AUTHENTICATE:SIGN (wrong or no PIN, or no touch) Total Length: 2 Data Length: 0 | Data | SW1 | SW2 | | --- | --- | --- | | (no data) | 69 | 82 | If the key was generated or imported with a PIN policy other than "Never", and the command was sent without first verifying the PIN or the wrong PIN was entered, then the following response will be returned. In addition, if the key's touch policy is not "Never", and after sumbitting the command the YubiKey was not touched within the time limit, this response will be returned. ### Examples $ opensc-tool -c default -s 00:a4:04:00:09:a0:00:00:03:08:00:00:10:00 -s 00:20:00:80:08:31:32:33:34:35:36:ff:ff -s 10:87:07:9c:d9:7c:82:01:06:82:00:81:82:01:00: 00:01:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff: ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff: ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff: ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff: ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff: ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff: ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff: ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff: ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff: ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff: ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff: ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff: ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:00 -s 00:87:07:9c:31: 30:2f:30:0b:06:09:60:86:48:01:65:03:04:02:01:04: 20:00:01:02:03:04:05:06:07:08:09:0a:0b:0c:0d:0e: 0f:10:11:12:13:14:15:16:17:18:19:1a:1b:1c:1d:1e: 1f -s 00:c0:00:00 -s 00:c0:00:00 Using reader with a card: Yubico YubiKey OTP+FIDO+CCID 0 Sending: 00 A4 04 00 09 A0 00 00 03 08 00 00 10 00 Received (SW1=0x90, SW2=0x00): 61 11 4F 06 00 00 10 00 01 00 79 07 4F 05 A0 00 a.O.......y.O... 00 03 08 ... Sending: 00 20 00 80 08 31 32 33 34 35 36 FF FF Received (SW1=0x90, SW2=0x00) Sending: 10 87 07 9C D9 7C 82 01 06 82 00 81 82 01 00 00 01 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 00 Received (SW1=0x90, SW2=0x00) Sending: 00 87 07 9C 31 30 2F 30 0B 06 09 60 86 48 01 65 03 04 02 01 04 20 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F Received (SW1=0x90, SW2=0x00): 7C 82 01 04 82 82 01 00 AF 71 DA 5B 16 AA 7D 15 50 8A 6A 57 3C 78 86 BB F7 53 29 E0 C4 9C F8 C8 D5 37 D4 D4 E5 3F 9D DE 11 17 B4 11 EE 45 D4 1E B9 75 92 55 34 E6 2B 1F 8A 49 20 48 AD E4 D0 F4 2C DC F5 80 B7 25 49 83 B3 43 14 0F 31 E7 E1 F0 B4 F8 75 C1 B7 9E F9 6A 2D BC 3A F8 2F 84 4D FC 42 27 21 F1 23 13 50 EA 96 05 47 7C BF 0C 97 46 6B 1D A6 5F 80 B9 7B 89 8A F4 8C C3 4B 9F AB 91 29 BB C3 70 7A 9C 99 E6 48 33 90 B5 49 97 AD D0 6B 0B 36 10 A9 B2 FC CA D7 8C EC 30 6D 50 CB BE 57 D7 63 3E C1 A9 80 7F E6 37 FA 51 D8 8C 0B 22 70 95 1B 7A EA 5C E3 43 D7 09 77 54 C4 39 40 F5 B1 A5 BE D7 0C 96 FC 74 41 93 4A 27 C7 07 CE 2F 3A FD C1 FB F8 D3 06 B9 02 D0 16 C7 21 46 38 74 2F 50 1E CF 95 A9 B6 39 74 AC 15 7B E8 23 81 53 F0 AC 15 9F 12 DE 6C DB C5 F2 F0 01 7E 42 31 0E Sending: 00 C0 00 00 Received (SW1=0x90, SW2=0x00): 67 13 97 38 84 CD A5 D1 Sending: 00 C0 00 00 Received (SW1=0x6A, SW2=0x80) [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-piv/apdu/auth-sign.md/#L1) --- # ##### Table of Contents Get metadata ------------ ### Command APDU Info | CLA | INS | P1 | P2 | Lc | Data | Le | | --- | --- | --- | --- | --- | --- | --- | | 00 | F7 | 00 | _slot number_ | (absent) | (absent) | (absent) | ### Response APDU Info Total Length: _variable + 2_ Data Length: _variable_ | Data | SW1 | SW2 | | --- | --- | --- | | _metadata as set of TLV_ | 90 | 00 | The data consists of a set of TLVs. The possible valid tags (T of TLV) are listed in the table below. The length (L of TLV) is one, two, or three bytes, using the DER encoding rules. The values (V of TLV) are dependent on the tags, described in the table below. #### Table 1: List of Metadata Elements | Tag | Name | Meaning | Data | Slots | | --- | --- | --- | --- | --- | | 01 | Algorithm | Algorithm/Type of the key | ff (PIN or PUK), 03 (Triple DES), 08 (AES-128),
0A (AES-192), 0C (AES-256),
06 (RSA-1024), 07 (RSA-2048),
05 (RSA 3072), 16 (RSA 4096)
11 (ECC-P256), or 14 (ECC-P384) | all slots | | 02 | Policy | PIN and touch policy | PIN: 0 (Default), 1 (Never),
2 (Once), 3 (Always)
Touch: 0 (Default), 1 (Never),
2 (Always), 3 (Cached) | 9a, 9b, 9c, 9d, 9e, f9, 82 - 95 | | 03 | Origin | Imported or generated | 1 (generated), 2 (imported) | 9a, 9c, 9d, 9e, f9, 82 - 95 | | 04 | Public | Pub key partner to the pri key | DER encoding of public key | 9a, 9c, 9d, 9e, f9, 82 - 95 | | 05 | Default | Whether PIN/PUK/Mgmt Key has default value | 01 (default) 00 (not default) | 80, 81, 9b | | 06 | Retries | Number of Retries left | Two bytes, the retry count and remaining count | 80, 81 | Another way to look at what is returned is the following table that lists which data elements are returned for each slot. #### Table 2: List of PIV Slots and the Metadata Elements Returned | Slot Number (hex) | Key | Data Returned (tags) | | --- | --- | --- | | 80 | PIN | 01, 05, 06 | | 81 | PUK | 01, 05, 06 | | 9B | Management | 01, 02, 05 | | 82, 83, ..., 95 (20 slots) | Retired Keys | 01, 02, 03, 04 | | 9A | Authentication | 01, 02, 03, 04 | | 9C | Signing | 01, 02, 03, 04 | | 9D | Key Management | 01, 02, 03, 04 | | 9E | Card Authentication | 01, 02, 03, 04 | | F9 | Attestation | 01, 02, 03, 04 | The length of a TLV follows the DER encoding rules (values in hex). 00 to 7F lengths of 0 to 127 81 80 to 81 FF lengths of 128 to 255 82 01 00 to 82 ff ff lengths of 256 to 65,535 Note that the DER encoding rules allow lengths of `83 xx xx xx` and more, but any info returned by this command will not be longer than 65,535 bytes. ### Examples Get Metadata on a public/private key pair, in this case, the PIV Authentication key in slot 9A. It's ECC. $ opensc-tool -c default -s 00:a4:04:00:09:a0:00:00:03:08:00:00:10:00 -s 00:f7:00:9a Using reader with a card: Yubico YubiKey OTP+FIDO+CCID 0 Sending: 00 A4 04 00 09 A0 00 00 03 08 00 00 10 00 Received (SW1=0x90, SW2=0x00): 61 11 4F 06 00 00 10 00 01 00 79 07 4F 05 A0 00 00 03 08 Sending: 00 F7 00 9A Received (SW1=0x90, SW2=0x00): 01 01 11 02 02 02 01 03 01 01 04 43 86 41 04 C4 17 7F 2B 96 8F 9C 00 0C 4F 3D 2B 88 B0 AB 5B 0C 3B 19 42 63 20 8C A1 2F EE 1C B4 D8 81 96 9F D8 C8 D0 8D D1 BB 66 58 00 26 7D 05 34 A8 A3 30 D1 59 DE 66 01 0E 3F 21 13 29 C5 98 56 07 B5 26 Look at the data as a sequence of TL V 01 01 11 02 02 02 01 03 01 01 04 43 86 41 04 C4 17 7F 2B 96 8F 9C 00 0C 4F 3D 2B 88 B0 AB 5B 0C 3B 19 42 63 20 8C A1 2F EE 1C B4 D8 81 96 9F D8 C8 D0 8D D1 BB 66 58 00 26 7D 05 34 A8 A3 30 D1 59 DE 66 01 0E 3F 21 13 29 C5 98 56 07 B5 26 Get Metadata on a public/private key pair, in this case, the Digital Signature key in slot 9C. It's RSA. $ opensc-tool -c default -s 00:a4:04:00:09:a0:00:00:03:08:00:00:10:00 -s 00:f7:00:9c -s 00:c0:00:00 Using reader with a card: Yubico YubiKey OTP+FIDO+CCID 0 Sending: 00 A4 04 00 09 A0 00 00 03 08 00 00 10 00 Received (SW1=0x90, SW2=0x00): 61 11 4F 06 00 00 10 00 01 00 79 07 4F 05 A0 00 00 03 08 Sending: 00 F7 00 9C Received (SW1=0x90, SW2=0x00): 01 01 07 02 02 03 01 03 01 01 04 82 01 09 81 82 01 00 F1 50 BE FB B0 9C AD FE F8 0A 3D 10 8C 36 92 DC 34 B7 09 86 42 C9 CD 00 55 D1 A4 A0 40 61 5A 2A 8A B4 7D AC A1 34 A2 2F 0A 36 D2 34 B7 D8 72 58 20 D6 04 66 80 7A 7A 0A D1 03 32 A2 D0 C9 92 7E 59 B8 63 F8 FD A3 0F D0 F1 A1 48 50 DF 82 DC 4F 9F 7C 18 02 29 35 72 DD 10 54 80 12 68 89 8F 05 CA A0 EB D4 F0 82 85 B8 67 AD F3 F7 86 2E D3 6E C8 E0 46 C4 6C 67 57 53 47 C7 38 84 AC F4 F4 44 81 AB DB 64 EE 53 B5 35 AE 92 FF 8E FE 00 A7 A8 B2 86 3B 66 DB 8E A7 07 FF 13 28 49 E5 9B D1 C8 D2 2C F9 84 D5 8A FF 00 3E 88 FB C1 E1 F8 37 8E 9D DB 5D 45 61 1B 29 29 A5 B7 C3 E7 38 E9 1A 15 F3 58 DD CA E2 E1 3D 86 BA BC 63 E2 CD A4 75 3A F9 9C D8 23 0F D8 18 59 F8 12 29 62 AB DC BE A5 01 C5 28 C3 E8 A1 65 CF 39 30 66 18 6A E5 Sending: 00 C0 00 00 Received (SW1=0x90, SW2=0x00): AD FA EC 48 CC E7 BA 8B F7 56 6B DD 7B 56 2A 3B E7 E9 82 03 01 00 01 01 01 07 02 02 03 01 03 01 01 04 82 01 09 81 82 01 00 F1 50 BE FB B0 9C AD FE F8 0A 3D 10 8C 36 92 DC 34 B7 09 86 42 C9 CD 00 55 D1 A4 A0 40 61 5A 2A 8A B4 7D AC A1 34 A2 2F 0A 36 D2 34 B7 D8 72 58 20 D6 04 66 80 7A 7A 0A D1 03 32 A2 D0 C9 92 7E 59 B8 63 F8 FD A3 0F D0 F1 A1 48 50 DF 82 DC 4F 9F 7C 18 02 29 35 72 DD 10 54 80 12 68 89 8F 05 CA A0 EB D4 F0 82 85 B8 67 AD F3 F7 86 2E D3 6E C8 E0 46 C4 6C 67 57 53 47 C7 38 84 AC F4 F4 44 81 AB DB 64 EE 53 B5 35 AE 92 FF 8E FE 00 A7 A8 B2 86 3B 66 DB 8E A7 07 FF 13 28 49 E5 9B D1 C8 D2 2C F9 84 D5 8A FF 00 3E 88 FB C1 E1 F8 37 8E 9D DB 5D 45 61 1B 29 29 A5 B7 C3 E7 38 E9 1A 15 F3 58 DD CA E2 E1 3D 86 BA BC 63 E2 CD A4 75 3A F9 9C D8 23 0F D8 18 59 F8 12 29 62 AB DC BE A5 01 C5 28 C3 E8 A1 65 CF 39 30 66 18 6A E5 AD FA EC 48 CC E7 BA 8B F7 56 6B DD 7B 56 2A 3B E7 E9 82 03 01 00 01 Get Metadata on the Management Key. $ opensc-tool -c default -s 00:a4:04:00:09:a0:00:00:03:08:00:00:10:00 -s 00:f7:00:9b Using reader with a card: Yubico YubiKey OTP+FIDO+CCID 0 Sending: 00 A4 04 00 09 A0 00 00 03 08 00 00 10 00 Received (SW1=0x90, SW2=0x00): 61 11 4F 06 00 00 10 00 01 00 79 07 4F 05 A0 00 00 03 08 Sending: 00 F7 00 9B Received (SW1=0x90, SW2=0x00): 01 01 03 02 02 00 01 05 01 00 01 01 03 02 02 00 01 05 01 00 Get Metadata on the PIN. $ opensc-tool -c default -s 00:a4:04:00:09:a0:00:00:03:08:00:00:10:00 -s 00:f7:00:80 Using reader with a card: Yubico YubiKey OTP+FIDO+CCID 0 Sending: 00 A4 04 00 09 A0 00 00 03 08 00 00 10 00 Received (SW1=0x90, SW2=0x00): 61 11 4F 06 00 00 10 00 01 00 79 07 4F 05 A0 00 00 03 08 Sending: 00 F7 00 80 Received (SW1=0x90, SW2=0x00): 01 01 FF 05 01 01 06 02 05 05 01 01 FF 05 01 01 06 02 05 05 Get Metadata on the PUK. $ opensc-tool -c default -s 00:a4:04:00:09:a0:00:00:03:08:00:00:10:00 -s 00:f7:00:81 Using reader with a card: Yubico YubiKey OTP+FIDO+CCID 0 Sending: 00 A4 04 00 09 A0 00 00 03 08 00 00 10 00 Received (SW1=0x90, SW2=0x00): 61 11 4F 06 00 00 10 00 01 00 79 07 4F 05 A0 00 00 03 08 Sending: 00 F7 00 81 Received (SW1=0x90, SW2=0x00): 01 01 FF 05 01 01 06 02 05 05 01 01 FF 05 01 01 06 02 05 05 Get Metadata on the Attestation Key. $ opensc-tool -c default -s 00:a4:04:00:09:a0:00:00:03:08:00:00:10:00 -s 00:f7:00:f9 Using reader with a card: Yubico YubiKey OTP+FIDO+CCID 0 Sending: 00 A4 04 00 09 A0 00 00 03 08 00 00 10 00 Received (SW1=0x90, SW2=0x00): 61 11 4F 06 00 00 10 00 01 00 79 07 4F 05 A0 00 00 03 08 Sending: 00 F7 00 F9 Received (SW1=0x90, SW2=0x00): 01 01 07 02 02 02 01 03 01 02 04 82 01 09 81 82 01 00 AC 45 96 66 97 9F 96 FF D9 04 4F 24 5D 5D 4F 99 3C D3 21 A5 FD 2A 63 FC 2B ED 8F 58 EF A7 C2 E3 79 68 94 0D 53 30 23 EC 6C A6 65 B7 E3 CB C6 27 BE 72 92 B0 38 D4 7D E1 54 86 BF 75 07 16 F8 07 E4 7E A3 6B AB DF D6 9D E1 C7 7B A9 E9 D1 3E 97 8C 3E A0 57 C9 07 30 58 E4 9B AC 78 69 A1 6B 71 7C F0 78 9B C3 7F 4A C1 CB 40 BD 94 7F F4 19 36 BB 41 CC 35 CD 2E DB B1 97 A8 B0 05 9C E7 00 2D BF 35 C2 2A E4 92 91 F3 FC 86 C4 D1 B4 58 3C 46 51 5F BF 94 D4 F0 7E E7 4A 1B 85 F1 A3 3A EC B5 1C 0E 86 90 5F 22 09 F1 A5 C8 6B BB 36 5A 63 80 F5 DE 46 E7 51 D8 F0 21 85 73 80 08 01 14 A7 3B B9 5F 80 15 15 A1 E7 7E 53 4D F3 9E 5B BA 7B B6 3C 1F B6 85 18 A8 99 0A 29 47 06 95 C8 94 78 04 06 B8 D0 65 76 15 5D 5E 8D 03 10 98 CE 54 Sending: 00 C0 00 00 Received (SW1=0x90, SW2=0x00): D8 2F E6 EE DA 47 8E BB E1 59 2E D3 B8 DD 16 1B 9A 71 82 03 01 00 01 01 01 07 02 02 02 01 03 01 02 04 82 01 09 81 82 01 00 AC 45 96 66 97 9F 96 FF D9 04 4F 24 5D 5D 4F 99 3C D3 21 A5 FD 2A 63 FC 2B ED 8F 58 EF A7 C2 E3 79 68 94 0D 53 30 23 EC 6C A6 65 B7 E3 CB C6 27 BE 72 92 B0 38 D4 7D E1 54 86 BF 75 07 16 F8 07 E4 7E A3 6B AB DF D6 9D E1 C7 7B A9 E9 D1 3E 97 8C 3E A0 57 C9 07 30 58 E4 9B AC 78 69 A1 6B 71 7C F0 78 9B C3 7F 4A C1 CB 40 BD 94 7F F4 19 36 BB 41 CC 35 CD 2E DB B1 97 A8 B0 05 9C E7 00 2D BF 35 C2 2A E4 92 91 F3 FC 86 C4 D1 B4 58 3C 46 51 5F BF 94 D4 F0 7E E7 4A 1B 85 F1 A3 3A EC B5 1C 0E 86 90 5F 22 09 F1 A5 C8 6B BB 36 5A 63 80 F5 DE 46 E7 51 D8 F0 21 85 73 80 08 01 14 A7 3B B9 5F 80 15 15 A1 E7 7E 53 4D F3 9E 5B BA 7B B6 3C 1F B6 85 18 A8 99 0A 29 47 06 95 C8 94 78 04 06 B8 D0 65 76 15 5D 5E 8D 03 10 98 CE 54 D8 2F E6 EE DA 47 8E BB E1 59 2E D3 B8 DD 16 1B 9A 71 82 03 01 00 01 [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-piv/apdu/metadata.md/#L1) --- # Device notifications ##### Table of Contents Device notifications ==================== A YubiKey is a device that can be added or removed to a computer at any time. To give the best experience to end users, applications should be aware of when a change like this occurs, and have this reflected in their UI as soon as possible. One possible way to achieve this would be to continually call [YubiKeyDevice.FindAll](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.YubiKeyDevice.html#Yubico_YubiKey_YubiKeyDevice_FindAll) in a loop, and look for changes from one iteration to the next. This is called "polling". While this can certainly work, it is not ideal for several reasons. First, it is resulting in calls to the SDK and to the computer that may not be necessary. Since you don't know when a change will occur, you must continually ask the computer for its state. Second, as part of enumerating keys, the SDK must talk to the key to gather basic information such as serial number and firmware version. Since a YubiKey is single threaded and potentially stateful, this could be a disruptive action to an existing key that is in the middle of performing an action. A better approach would be to use the [YubiKeyDeviceListener](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.YubiKeyDeviceListener.html) class that was added to the SDK in version 1.2.0. This class exposes two events: Arrived and Removed. As the names suggest, these events will trigger when a YubiKey is added or removed from the computer, respectively. For more general information about the C# event mechanism and how to use them, please refer to the official documentation for [C# Events](https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/events/) . YubiKeyDeviceListener --------------------- ### Usage YubiKeyDeviceListener is a singleton class. This means that you do not need to worry about constructing it. You can get at the single instance through the [Instance](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.YubiKeyDeviceListener.html#Yubico_YubiKey_YubiKeyDeviceListener_Instance) static property. Once you have obtained the instance to the listener class, you can subscribe (or unsubscribe) to its events using the `+=` (or `-=`) operator. These events expect a delegate or method that follow the standard event handler signature, that is, a method that takes two parameters: an `object` that represents the sender of the event, and [YubiKeyDeviceEventArgs](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.YubiKeyDeviceEventArgs.html) that represents the event payload. `YubiKeyDeviceEventArgs` exposes a property called `Device`. This is the `YubiKeyDevice` that caused the event to be raised. The device property will be populated for both arrival and removal events, even if the actual device is not physically present. The following code snippet shows how you can subscribe to events in your application: var listener = YubiKeyDeviceListener.Instance; listener.Arrived += (s, e) => { Console.WriteLine($"YubiKey arrived!: {e.Device}"); }; listener.Removed += (s, e) => { Console.WriteLine($"YubiKey removed!: {e.Device}"); }; ### Implementation The device listener was implemented with two primary design goals in mind: 1. **One YubiKey = One Event.** Since a YubiKey can expose up to three child devices while plugged in via USB, a naive implementation of events would raise up to three events per key. This was considered unacceptable, as the SDK already does its best to mask this detail from application developers. Since enumeration exposes a single logical YubiKey, so should the events. 2. **Minimize disruption to YubiKeys that are already present.** In order to represent the YubiKey as an SDK object, the SDK must first ask the YubiKey to describe itself. This involves sending a command over each of the available interfaces to the key. If sent to a YubiKey that was already present and engaged in a stateful operation, this command could disrupt that key and cause the other active thread to start failing unexpectedly. The implementation of events in the SDK avoids this by only communicating with keys that the SDK has never seen before. [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/sdk-programming-guide/device-notifications.md/#L1) --- # PIV access control ##### Table of Contents PIV access control ================== There are some PIV commands or operations that require management key authentication or PIN verification to execute. Furthermore, the auth/verification will be valid only during a session. Which commands and operations require which access control element? How does one write code to perform the auth/verification? PIV Session ----------- First of all, if you use the [PivSession](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.PivSession.html) class, all you really need to do is provide a [`KeyCollector` delegate](https://docs.yubico.com/yesdk/users-manual/sdk-programming-guide/delegates-in-sdk.html) . The `PivSession` object will determine when a management key is necessary, and when a PIN (or PUK) is necessary. It will then call on the `KeyCollector` loaded to obtain the appropriate element, and perform the auth/verification. For example, suppose you have some code to generate a key pair. using (var pivSession = new PivSession(yubiKeyToUse)) { pivSession.KeyCollector = SomeKeyCollector; PivPublicKey publicKey = pivSession.GenerateKeyPair( PivSlot.Authentication, PivAlgorithm.EccP256, PivPinPolicy.Once, PivTouchPolicy.Once); } When this is run, the `GenerateKeyPair` code will know that it needs management key authentication only (no PIN or PUK). It will determine if the management key has been authenticated or not in the current session. If it has already been authenticated, the `GenerateKeyPair` method will not call for the management key to be authenticated again. If not, it will call the `KeyCollector`, requesting the management key. Once it has the management key, it will make the appropriate calls to authenticate. Later on, suppose you have this code. using (var pivSession = new PivSession(yubiKeyToUse)) { pivSession.KeyCollector = SomeKeyCollector; byte[] signature = pivSession.Sign(PivSlot.Authentication, digestData); } Is the PIN required? The management key? The `PivSession` object will know that the PIN is required and determine if the PIN has been verified in the session or not. If not, it will call the `KeyCollector`, requesting the PIN, then make the appropriate calls to verify. It is possible the private key in question was generated with the PIN policy set to `Never`. In that case, the `Sign` method will determine that no PIN is required and simply perform the signing operation. Note that it is possible on older YubiKeys for a PIN policy to be `Never`, and the method still requests the PIN. This happens when the touch policy is `Always` or `Cached` and the user does not touch. With a `KeyCollector`, there is no need to worry about management key authentication, or PIN/PUK verification. However, it is still possible to directly call methods to perform these operations. See [PivSession.AuthenticateManagementKey](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.PivSession.html#Yubico_YubiKey_Piv_PivSession_TryAuthenticateManagementKey_) , [PivSession.TryVerifyPin](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.PivSession.html#Yubico_YubiKey_Piv_PivSession_TryVerifyPin_) , and [PivSession.TryResetPin](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.PivSession.html#Yubico_YubiKey_Piv_PivSession_TryResetPin_) . If you want to auth/verify without a `KeyCollector`, you must call the commands directly. How to do so is described in the next section. Authenticating with commands ---------------------------- If you are not familiar with the APDU, visit [this page](https://docs.yubico.com/yesdk/users-manual/yubikey-reference/apdu.html) first. Some PIV commands require a PIN (Personal Identification Number), PUK (PIN Unblocking Key), management key, or maybe even two of those elements in combination. That is, access to some commands is controlled by authenitication by PIN, PUK, or management key. For example: * To generate a key pair, the caller must authenticate the management key. * To sign using a private key, the caller must authenticate the PIN. * To set the PIN retry count, the caller must authenticate both the management key and the PIN. How does one provide this authentication? There are two ways to verify the PIN: * Supply the PIN or PUK as part of the command * Verify the PIN using the [Verify PIN](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#verify) command, and all commands executed in the current session that need the PIN verified will work. Note that how you verify the PIN is not your choice. Some commands include the PIN and/or PUK in the command data, and others do not. If the command data includes the PIN or PUK, you must supply the PIN or PUK with the command. You cannot rely on a previous verification command to authenticate. Similarly, some commands are defined as not including the PIN in the data, so you must verify first. For example, the [Change Reference Data](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#change-reference-data) command can change the PIN. To do so, the command must contain the current PIN and the new PIN. Even if the [Verify PIN](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#verify) command had been successfully executed earlier in the session, this command requires the current PIN. Similarly, the [Key Agreement](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#authenticate-key-agreement) command requires the PIN in order to perform the operation (as long as the private key was generated or installed with the PIN policy set to something other than "Never"). In order for it to work, the PIN must have been successfully verified earlier in the session using the [Verify PIN](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#verify) command. Even if the Change Reference Data command had been successfully executed earlier in the session, the Verify PIN command still must be successfully completed in order to perform the Key Agreement operation. There is only one way to authenticate the management key: * Authenticate using the [Authenticate: management key](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#authenticate-management-key) commands (there are two, both of which need to be successful for the management key to be authenticated), and all commands executed in the current session that need the management key authenticated will work. What is a session? That is, how do you know your code is operating in the same session for which the PIN or management key was authenticated? If it is operating in the same session, the code does not need to call the Verify or Authenticate commands again. But you also want to know when a session ends, so you can know when it is necessary to verify or authenticate. If you create a `PivSession`, then when that object goes out of scope, the session will be closed. If you don't use a `PivSession`, then a session is closed whenever a YubiKey is disconnected, or another YubiKey application is launched (e.g., your application creates a new session for OTP). The safest thing to do is use the `PivSession` with the `using` keyword. using (var pivSession = new PivSession(yubiKeyToUse)) { pivSession.KeyCollector = SomeKeyCollector; . . . } In this way, there is less of a chance you leave a session accidentally open. Part of the command ------------------- The [Reset retry](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#reset-retry-recover-the-pin) command is an example of this method of authenticating. This command resets the PIN using the PUK. You supply the PUK and the new PIN. The command's data includes both the PIN and PUK. | CLA | INS | P1 | P2 | Lc | Data | Le | | --- | --- | --- | --- | --- | --- | --- | | 00 | 2C | 00 | 80 | 10 | _current PUK and new PIN_ | (absent) | 00 2C 00 80 10 31 32 33 34 35 36 37 38 31 32 33 34 35 36 37 ff |<------- PUK ------->|<------- PIN ------->| The YubiKey will authenticate the PUK as part of the command Verify the PIN using a separate command --------------------------------------- The [Get Data](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#get-data) command retrieves various elements out of a YubiKey. For some elements, the PIN is required. In those cases, the Get Data command will not work unless the PIN had been verified earlier in the session. Use the [Verify PIN](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#verify) command. Once you verify the PIN once in a session, the YubiKey will be able to perform all PIV commands in that session that require PIN authorization. [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-piv/access-control.md/#L1) --- # ##### Table of Contents Put data -------- ### Command APDU Info | CLA | INS | P1 | P2 | Lc | Data | Le | | --- | --- | --- | --- | --- | --- | --- | | 00 | DB | 3F | FF | _data length_ | _data element tag followed by data to put_ | (absent) | ### Response APDU info: success Total Length: 2 Data Length: 0 | Data | SW1 | SW2 | | --- | --- | --- | | (no data) | 90 | 00 | ### Response APDU info: security status not satisfied Total Length: _2_ Data Length: _0_ | Data | SW1 | SW2 | | --- | --- | --- | | (no data) | 69 | 82 | ### Examples To be added [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-piv/apdu/put-data.md/#L1) --- # PIV PIN, touch and bio policies ##### Table of Contents PIV PIN, touch and bio policies =============================== Suppose you want to use one of the PIV keys to sign or decrypt. The application running on your host device will call one or more commands to perform the operation. Do you need to enter the PIN to perform the operation? Do you need to touch the YubiKey? Suppose you want to to generate a new key pair, you need to authenticate the management key to perform that operation. But do you need to touch the YubiKey as well? What about fingerprints? This article answers those questions. Related articles ---------------- [PIV commands access control](https://docs.yubico.com/yesdk/users-manual/application-piv/access-control.html) [The PIV PIN, PUK, and management key](https://docs.yubico.com/yesdk/users-manual/application-piv/pin-puk-mgmt-key.html) What are the possible policies? ------------------------------- #### PIN policies * Never: the PIN is never needed * Always: the PIN needed for every use * Once: the PIN is needed once per session #### Touch policies * Never: a touch is never needed * Always: a touch is needed for every use * Cached: a touch is not needed if the YubiKey had been touched in the last 15 seconds, otherwise a touch is needed (Only available for YubiKey versions 4.3 and greater) #### Biometric policies For **YubiKey Bio** versions 5.7 and greater, there are two more possible policies * Match Once: A biometric or PIN verification is required for each session * Match Always: A biometric or PIN verification is required on every object access ##### Warning It is important to point out that setting the PIN policy to "never" reduces security dramatically. This feature was added only because of customer demand for convenience. Yubico recommends setting the PIN policy to "always" or "once". Note that if you do not specify a PIN or touch policy, there is a default. What the default is will be described below. Note also that with management keys there is only a touch policy. The PIN is never needed to perform a management key operation (with the exception of [Set PIN Retries](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#set-pin-retries) , but in this case the PIN is needed becasue that is a command related to the PIN itself). Older YubiKeys (prior to YubiKey 4) ----------------------------------- The ability to use PIN and touch policies other than the default was not available prior to YubiKey 4. What this means is that when using a PIV key in a YubiKey, there was a default policy only and no way to generate or import a key to use a different policy. Default policy -------------- The default policies are programmed into the YubiKey upon manufacture. All YubiKeys, before version 4 and after, are programmed with the same default policies. In the future, there could be a YubiKey with a different default policy. But for now, the default PIN and touch policies are the following. * Slot 9C PIN policy: Always (the PIN is required before each private key operation) * PIN policy: Once (the PIN is required once per session to use a private key to sign, decrypt, or perform key agreement) * Touch policy: Never (touch is never required to use any PIV key, private or management) > Note: > > The default PIN policy for slot 9C is different from the default for the other slots. This is from the PIV standard. So remember that if you generate a key in slot 9C and set the PIN policy to default, the actual PIN policy will be Always. It is a good idea to simply always specify the PIN policy you want, Never or Once, rather than Default. > Note: > > Touch is not a part of the PIV standard. That is why the first YubiKeys that supported PIV did not have the option of touch when using a PIV key. This non-standard ability to require touch was added to YubiKey in version 4 to augment security. Changing the policy: management key (slot 9B) --------------------------------------------- If you want a touch policy different from the default for the management key, use the [Set Management Key command](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#set-management-key) . This will set the actual key value as well as the touch policy. With this command you can enter the current key along with a different touch policy to change the policy only, or enter the same touch policy with a new key to change the key only, or change both key and policy. Setting keys to a non-default policy (all slots other than 80, 81, 9B, F9) -------------------------------------------------------------------------- If you want a policy different from the default for a private key, you must specify that policy when the key is [generated](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#generate-asymmetric) or [imported](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#import-asymmetric) . Once the key is on the YubiKey there is no way to change the policy. Note that you can specify different policies for keys in different slots (if the YubiKey has the option of setting policies). For example, you can generate a new key in slot 9A that has a PIN policy of "always", while a key imported into slot 86 has a PIN policy of "once". > It is important to point out that setting the PIN policy to "never" reduces security dramatically. This feature was added only because of customer demand for convenience. Yubico recommends setting the PIN policy to "always" or "once". Examples -------- ### Management key You have a new YubiKey and one of the first things you do is change the management key from the default. You call the [Set Management Key command](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#set-management-key) and provide the new key data and specify the touch policy. Suppose you set the policy to "always". Now whenever you call the [Authenticate management key](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#authenticate-management-key) command, the authentication won't be complete until the YubiKey has been touched. ### Private key Suppose you generate a new key pair for slot 9C using the [Generate asymmetric key pair](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#generate-asymmetric) command. You set the PIN policy to never and the touch policy to always. Now when you call the [Authenticate: sign](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#authenticate-sign) command, you won't need to combine it with [PIN verification](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#verify) to make it work, but the YubiKey won't complete the signing process until the YubiKey has been touched. Suppose you generate a new key pair for slot 9D. You set the PIN policy to once, and the touch policy to never. Now when you first decrypt using that key in a session, you will need to authenticate the PIN, but won't need to touch. The next time you decrypt in the session, you will not need the PIN nor touch. [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-piv/pin-touch-policies.md/#L1) --- # ##### Table of Contents Import asymmetric key pair -------------------------- ### Command APDU Info | CLA | INS | P1 | P2 | Lc | Data | Le | | --- | --- | --- | --- | --- | --- | --- | | 00 | FE | _algorithm_ | _slot number_ | _data len_ | _set of TLV containing key elements_
\[AA 01 __\]
\[AB 01 __\] | (absent) | The slot number can be one of the following (hex values): 9A, 9C, 9D, 9E, 82, 93, 84, 85, 86, 87, 88, 89, 8A, 8B, 8C, 8D, 8E, 8F, 90, 91, 92, 93, 94, 95 F9 There are six choices for "alg" (algorithm and size): RSA-1024 (06), RSA-2048 (07), RSA 3072 (05), RSA 4096 (16), ECC-P-256 (11), and ECC-P-384 (14). The key data to load is a set of TLV constructions. The L (length) is DER encoding format. The V is the integer in canonical form. If the key is an RSA private key, there are five elements. If it is an ECC key, there is one element. #### Table 3: List of Private Key Tags | Algorithm | Key Element | Tag | | --- | --- | --- | | RSA | prime _P_ | 01 | | RSA | prime _Q_ | 02 | | RSA | prime _p_ exponent _dP_ | 03 | | RSA | prime _q_ exponent _dQ_ | 04 | | RSA | CRT coefficient _QInv_ | 05 | | ECC | private value _s_ | 06 | ### Response APDU Info: Management Key Authentication Missing Total Length: 2 Data Length: 0 | Data | SW1 | SW2 | | --- | --- | --- | | (no data) | 69 | 82 | ### Response APDU Info: Success Total Length: 2 Data Length: 0 | Data | SW1 | SW2 | | --- | --- | --- | | (no data) | 90 | 00 | ### Examples To be added [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-piv/apdu/import-asym.md/#L1) --- # Building a basic authenticator ##### Table of Contents Building a basic authenticator ============================== The most popular use case for the OATH applications is to utilize it by building a time-based OTP authenticator app. Below are some basic steps in order to implement one. 1. Find the connected Yubikey: IEnumerable keys = YubiKeyDevice.FindByTransport(Transport.UsbSmartCard); var yubiKeyToUse = keys.First(); 2. Create an OathSession object: var oathSession = new OathSession(yubiKeyToUse); This will connect to the OATH application on the chosen YubiKey. 3. Get all configured credentials from the YubiKey IList credentials = oathSession.GetCredentials(); You would probably want to find if there any HOTP credentials and credentials that require touch to generate OTPs. This way you don't show the values for those credentials until it is requested by tapping "Generate code" button, for example. Also, you will need to track TOTP credentials that have non-default periods, like 15 and 60 seconds. 4. Calculate the credentials and show OTPs IDictionary credentialCodes = oathSession.CalculateAllCredentials(); When HOTP credentials or credentials that require touch are requested, calculate them by using CalculateCredential() method: Code otpCode = CalculateCredential(Credential); Also, any credentials with a non-default period should be recalculated in their respective interval. 5. Add new credentials. The best way to add credential it is by implementing a QR code scanner and reading an URI string from the QR code. // Pass the string that received from QR reader or manually from server. It will return credential parsed from URI string. Credential credential = _oathSession.AddCredential( "otpauth://totp/ACME%20Co:test@example.com?secret=HXDMVJECJJWSRB3HWIZR4IFUGFTMXBOZ&issuer=ACME%20Co&algorithm=SHA1&digits=6&period=30"); Read more about [credentials](https://docs.yubico.com/yesdk/users-manual/application-oath/oath-credentials.html) and [URI strings](https://docs.yubico.com/yesdk/users-manual/application-oath/uri-string-format.html) . 6. Remove and Rename credentials if needed. var credentialTotp = new Credential { Issuer = "Yubico", AccountName = "test@yubico.com", Type = Totp, Period = 60, Secret = "test", Digits = 8 }; // Pass credential to rename as well as the new Issuer and AccountName. oathSession.RenameCredential(credentialTotp, "Test", "example@test.com"); var credentialTotp = new Credential { Issuer = "Yubico", AccountName = "test@yubico.com", Type = Totp, Period = 60, Secret = "test", Digits = 8 }; // Pass credential to remove. oathSession.RemoveCredential(credentialTotp); Read more about [OathSession](https://docs.yubico.com/yesdk/users-manual/application-oath/oath-session.html) methods and [OathPassword](https://docs.yubico.com/yesdk/users-manual/application-oath/oath-password.html) implementation on the YubiKey. [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-oath/oath-use-case.md/#L1) --- # How to update slot settings ##### Table of Contents How to update slot settings =========================== Some [slot](https://docs.yubico.com/yesdk/users-manual/application-otp/slots.html) settings can be updated via [UpdateSlot](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.UpdateSlot.html) without completely reconfiguring an OTP application slot. These settings involve behaviors not related to encryption or other sensitive information. The slot settings that can be updated include the following: | Settings | | | --- | --- | | [`SetAllowUpdate()`](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.UpdateSlot.html#Yubico_YubiKey_Otp_Operations_UpdateSlot_SetAllowUpdate_) | [`SetAppendDelayToFixed()`](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.UpdateSlot.html#Yubico_YubiKey_Otp_Operations_UpdateSlot_SetAppendDelayToFixed_) | | [`SetSerialNumberApiVisible()`](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.UpdateSlot.html#Yubico_YubiKey_Otp_Operations_UpdateSlot_SetSerialNumberApiVisible_) | [`SetUse10msPacing()`](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.UpdateSlot.html#Yubico_YubiKey_Otp_Operations_UpdateSlot_SetUse10msPacing_) | | [`SetUseNumericKeypad()`](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.UpdateSlot.html#Yubico_YubiKey_Otp_Operations_UpdateSlot_SetUseNumericKeypad_) | [`SetUse20msPacing()`](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.UpdateSlot.html#Yubico_YubiKey_Otp_Operations_UpdateSlot_SetUse20msPacing_) | | [`SetAppendTabToOtp()`](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.UpdateSlot.html#Yubico_YubiKey_Otp_Operations_UpdateSlot_SetAppendTabToOtp_) | [`SetInvertLed()`](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.UpdateSlot.html#Yubico_YubiKey_Otp_Operations_UpdateSlot_SetInvertLed_) | | [`SetAppendCarriageReturn()`](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.UpdateSlot.html#Yubico_YubiKey_Otp_Operations_UpdateSlot_SetAppendCarriageReturn_) | [`SetSerialNumberUsbVisible()`](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.UpdateSlot.html#Yubico_YubiKey_Otp_Operations_UpdateSlot_SetSerialNumberUsbVisible_) | | [`SetSendTabFirst()`](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.UpdateSlot.html#Yubico_YubiKey_Otp_Operations_UpdateSlot_SetSendTabFirst_) | [`SetAppendTabToFixed()`](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.UpdateSlot.html#Yubico_YubiKey_Otp_Operations_UpdateSlot_SetAppendTabToFixed_) | | [`SetFastTrigger()`](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.UpdateSlot.html#Yubico_YubiKey_Otp_Operations_UpdateSlot_SetFastTrigger_) | [`SetAppendDelayToOtp()`](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.UpdateSlot.html#Yubico_YubiKey_Otp_Operations_UpdateSlot_SetAppendDelayToOtp_) | | [`SetSerialNumberButtonVisible()`](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.UpdateSlot.html#Yubico_YubiKey_Otp_Operations_UpdateSlot_SetSerialNumberButtonVisible_) | [`ProtectLongPressSlot()`](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.UpdateSlot.html#Yubico_YubiKey_Otp_Operations_UpdateSlot_ProtectLongPressSlot_) | | [`SetDormant()`](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.UpdateSlot.html#Yubico_YubiKey_Otp_Operations_UpdateSlot_SetDormant_) | | There is no way to retrieve the settings of an OTP slot configuration. Therefore, when you use `UpdateSlot`, you’re resetting every updatable setting. For example, if you intend to add a carriage return to the slot configuration and only call `SetAppendCarriageReturn()`, all other settings will revert to their default states. ##### Note If you call `UpdateSlot` and turn on/off serial number visibility on the USB device descriptor ( via `SetSerialNumberUsbVisible()`), you must reboot the YubiKey before the changes will take effect. This is most easily accomplished by unplugging the key and plugging it back in. UpdateSlot example ------------------ The following is an example of how to update the settings of a slot with `UpdateSlot`. We’ll assume that the boolean variables are set elsewhere. using (OtpSession otp = new OtpSession(_yubiKey)) { otp.UpdateSlot(_slot) .UseCurrentAccessCode(_currentAccessCode) .SetNewAccessCode(_newAccessCode) .SetDormant(_dormant) .SetFastTrigger(_fastTrigger) .SetInvertLed(_invertLed) .SetSerialNumberApiVisible(_serialApi) .SetSerialNumberButtonVisible(_serialButton) .SetSerialNumberUsbVisible(_serialUsb) .SetUseNumericKeypad(_numericKeypad) .SetSendTabFirst(_sendTabFirst) .SetAppendTabToFixed(_appendTabToFixed) .SetAppendTabToOtp(_appendTabToOtp) .SetAppendDelayToFixed(_appendDelayToFixed) .SetAppendDelayToOtp(_appendDelayToOtp) .SetAppendCarriageReturn(!_noEnter) .SetUse10msPacing(_use10msPacing) .SetUse20msPacing(_use20msPacing) .SetAllowUpdate(_allowUpdate) .ProtectLongPressSlot(_protectLongPressSlot) .Execute(); } Slot reconfiguration and access codes ------------------------------------- If a slot is protected by an access code and you wish to reconfigure slot settings, you must provide that access code with `UseCurrentAccessCode()` during the `UpdateSlot()` operation. Otherwise, the operation will fail and throw the following exception: `System.InvalidOperationException has been thrown. YubiKey Operation Failed. [Warning, state of non-volatile memory is unchanged.]` For more information on slot access codes, please see [How to set, reset, remove, and use slot access codes](https://docs.yubico.com/yesdk/users-manual/application-otp/how-to-slot-access-codes.html) . [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-otp/how-to-update-slot-settings.md/#L1) --- # Modified hexadecimal encoding (ModHex) ##### Table of Contents Modified hexadecimal encoding (ModHex) ====================================== As detailed in the section on [USB device communication](https://docs.yubico.com/yesdk/users-manual/application-otp/hid.html#usb-communication) via the [HID (Human Interface Device)](https://www.usb.org/hid) communication protocol, in order to submit a password ([Yubico OTP](https://docs.yubico.com/yesdk/users-manual/application-otp/yubico-otp.html) , [OATH-HOTP](https://docs.yubico.com/yesdk/users-manual/application-otp/hotp.html) , or [static password](https://docs.yubico.com/yesdk/users-manual/application-otp/static-password.html) ) from the YubiKey to a host device over USB (or Lightning), the characters of the password must be sent as HID usage IDs so they can be handled as keyboard input by the host device. Unfortunately, these usage IDs represent physical locations on a keyboard, not the keys themselves. This can become a problem when sending HID usage IDs to host devices that are configured with different keyboard layouts. For example, on an English language keyboard, the top row of keys spells QWERTY, and on a German language keyboard, those same keys spell QWERTZ. However, the "Y" key on the English keyboard and the "Z" key on the German keyboard are represented by the same HID usage ID of 28 (0x1c). If the YubiKey sends the letter "Y" to a host device as part of a password, and it assumes the host device is configured with the English keyboard layout when it is actually configured with the German layout, the usage ID will be incorrectly interpreted as a "Z" by the host device. An incorrect password will then be sent for authentication, which will fail. To address this and other discrepancies between HID usage IDs of characters across different keyboard layouts, Yubico invented the ModHex (modified hexadecimal) encoding scheme. ModHex only uses characters that are located in the same place on virtually all Latin alphabet keyboards: b, c, d, e, f, g, h, i, j, k, l, n, r, t, u, and v. Because there are exactly sixteen characters in this layout, it can be used to relay binary data as a modified hexadecimal code. | ModHex Letter: | c | b | d | e | f | g | h | i | j | k | l | n | r | t | u | v | | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | | Hexadecimal: | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | a | b | c | d | e | f | | Decimal: | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | | Binary: | 0000 | 0001 | 0010 | 0011 | 0100 | 0101 | 0110 | 0111 | 1000 | 1001 | 1010 | 1011 | 1100 | 1101 | 1110 | 1111 | For Yubico OTPs and OATH-HOTPs, the ciphertext generated post-password encryption is binary. So, instead of encoding each 8-bit chunk of ciphertext (e.g. 0110 0011) as an [ASCII character](https://theasciicode.com.ar/) (ASCII includes all letters of the alphabet), each 4-bit chunk of ciphertext (e.g. 1011) can be encoded as one of the 16 ModHex characters. To send the password to a host device over USB/Lightning, the ModHex characters are then translated into their corresponding HID usage IDs so they can be handled by the host device as keyboard input. Yubico OTPs use ModHex encoding by default. OATH-HOTPs can be configured so that the \[first byte\](xref: Yubico.YubiKey.Otp.OtpSettings`1.OathFixedModhex1%28System.Boolean%29), [first two bytes](xref:Yubico.YubiKey.Otp.OtpSettings` 1.UseOathFixedModhex2%28System.Boolean%29), or [all bytes](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.OtpSettings-1.html#Yubico_YubiKey_Otp_OtpSettings_1_UseOathFixedModhex_System_Boolean_) of the token identifier use ModHex encoding. ModHex as a static password keyboard layout ------------------------------------------- When [configuring an OTP application slot with a static password](https://docs.yubico.com/yesdk/users-manual/application-otp/how-to-program-a-static-password.html) , you have two options: 1. [Generate](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.ConfigureStaticPassword.html#Yubico_YubiKey_Otp_Operations_ConfigureStaticPassword_GeneratePassword_System_Memory_System_Char__) a random password of a specified length to be used as the static password. 2. [Set](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.ConfigureStaticPassword.html#Yubico_YubiKey_Otp_Operations_ConfigureStaticPassword_SetPassword_System_ReadOnlyMemory_System_Char__) the static password to something of your choosing. For static passwords, the [keyboard layout](https://docs.yubico.com/yesdk/core-api/Yubico.Core.Devices.Hid.KeyboardLayout.html) determines which HID usage IDs are used to represent the password characters. For example, if the keyboard layout is set to English, the SDK will use the HID usage IDs corresponding to the location of the password characters on an English keyboard. Additionally, for generated passwords, the keyboard layout determines which characters are used during generation (e.g. if the keyboard layout is set to English, the password will only contain characters that are included on the English keyboard). For set passwords, the keyboard layout acts as a filter; if the user-defined password contains characters that are not found in the keyboard layout, a `System.InvalidOperationException` will be thrown. For both types of static passwords, the keyboard layout is set to ModHex by default. This means that generated passwords will only contain ModHex characters, and a `System.InvalidOperationException` will be thrown for set passwords that contain non-ModHex characters. If you can’t be certain which keyboard layout will be configured on all devices that the YubiKey will be used with, you will want to create a password that only contains ModHex characters. As a best practice, we recommend explicitly setting the keyboard layout to ModHex even though it is the default layout. ModHex character casing ----------------------- ModHex characters, like standard hexadecimal characters, are case-insensitive. This means that uppercase and lowercase versions of the ModHex characters have the same decimal and binary representations. For example, ModHex "c" and "C" both represent decimal "0" and binary "0000". This is unlike ASCII characters, where uppercase and lowercase versions of a character have different decimal and binary representations. For passwords that must be decrypted, like Yubico OTPs, the ModHex characters of the password are simply a representation of the binary ciphertext. By representing the ciphertext as characters, the YubiKey can easily communicate the ciphertext to a host device by pretending the characters are keyboard input, which a host device receives through HID usage reports. When a validation server receives the OTP as ModHex characters, it converts them back to their binary forms before decrypting. For example, the OTPs "cbd" and "CbD" will both be converted to "0000 0001 0010". In practice, Yubico OTPs only contain lowercase ModHex characters. Although uppercase ModHex characters would still be interpreted correctly by a validation server, the YubiKey would have to do extra work to communicate uppercase characters to a host device. In order to send an uppercase character via a HID usage report, the modifier key flag has to be activated to show that a **Shift** key is being pressed with the character key. The YubiKey simply omits this unnecessary step. When it comes to static passwords, however, ModHex characters behave more like ASCII characters. Static passwords do not represent binary ciphertext; they are meant to be interpreted as-is. If the system that is validating static passwords is case-sensitive, then it does matter whether the static password contains uppercase or lowercase ModHex characters. If a case-sensitive system expects a password to be "cbd," then sending "CbD" will not authenticate a user. ModHex encoding example ----------------------- The Yubico OTP is 44 ModHex characters in length. The first 12 characters of a Yubico OTP string represent the public ID of the YubiKey that generated the OTP--this ID remains constant across all OTPs generated by that individual key. The last 32 characters of the string is the unique passcode, which is generated and encrypted by the YubiKey. The unencrypted passcode consists of a 128-bit long string of fields unique to the key, including the key's private ID ( 48 bits), a usage counter (16 bits), the timestamp (24 bits), a session usage counter (8 bits), a random number (16 bits), and a checksum (16 bits). This 128-bit string is encrypted with a 128-bit AES key, resulting in a 128-bit encrypted binary string (the ciphertext). For this example, let's say we touched our YubiKey, activating the short-press slot, which happens to be configured to generate a Yubico OTP. The YubiKey encrypts the 128-bit string of our key's unique fields with our secret AES key, resulting in the following binary ciphertext: 0000 0000 0000 0000 0101 1000 1100 0101 0111 0011 0000 0110 0010 1100 1011 0111 0011 1110 0110 1010 0100 0001 1101 0111 1111 0010 0011 0100 0111 1110 0010 1000 0010 0100 0000 1001 1000 0100 0010 0110 1110 0100 0011 0010 Because ModHex is base 16, each 4-bit chunk of the encrypted binary string can be represented by one of the 16 ModHex characters. ##### Note Remember, a bit can represent two unique states (0 or 1), so a string of four bits can represent sixteen unique states (2 x 2 x 2 x 2 = 2^4 = 16). Thus, the 128-bit encrypted binary string can be represented by 32 ModHex characters (128 / 4 = 32). Therefore, our binary ciphertext above will be represented by the following 44-character ModHex string: ccccgjrgiechdrnieuhlfbtivdefiudjdfckjfdhufed This 44-character string includes the 12-character public ID (ccccgjrgiech) and the 32-character encrypted passcode ( drnieuhlfbtivdefiudjdfckjfdhufed). To send this 44-character OTP to a host device over USB/lightning, the YubiKey will send the characters' HID usage IDs via a series of HID usage reports. The host device receives these usage reports and converts them into characters. If your cursor is inside an area that accepts text input, you will see the OTP (in ModHex characters) appear on your screen. When the OTP (as a character string) is sent to a validation server through the host device, it must be converted from ModHex characters back to binary before it can be decrypted. For our example, this means that our OTP will be converted from ccccgjrgiechdrnieuhlfbtivdefiudjdfckjfdhufed back to the binary string shown above. [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-otp/modhex.md/#L1) --- # How to configure NDEF to use a slot to generate an OTP ##### Table of Contents How to configure NDEF to use a slot to generate an OTP ====================================================== The [NDEF](https://docs.yubico.com/yesdk/users-manual/application-otp/ndef.html) (NFC Data Exchange Format) configuration for the OTP application is a special case. The NDEF configuration is always active. If you present the YubiKey to an NFC reader and issue an NDEF read command, the YubiKey will always emit something. When you configure NDEF functionality, you are setting two things: some text and which OTP configuration [slot](https://docs.yubico.com/yesdk/users-manual/application-otp/slots.html) to use to generate a challenge. The text can be either a URI or just static text. Unlike other configuration operations that take a slot identifier, configuring NDEF does not alter the configuration of the OTP application slot. It only sets which slot to activate after sending the text. In its default state, the YubiKey has NDEF configured to emit [https://my.yubico.com/yk/#](https://my.yubico.com/yk/#) and then activate slot 1 ( the [short press](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Slot.html#Yubico_YubiKey_Otp_Slot_ShortPress) slot), which is configured for Yubico OTP. The result looks something like this: [https://my.yubico.com/yk/#vvccccnnjfhbtdgbflcbfcegkkdvttldvlcvvfinvvdu](https://my.yubico.com/yk/#vvccccnnjfhbtdgbflcbfcegkkdvttldvlcvvfinvvdu) . ##### Note YubiKey NEOs use a different URL: [https://my.yubico.com/neo/?](https://my.yubico.com/neo/?) . The most likely use case for this is to configure the YubiKey with a specific Yubico OTP credential and a URL to a validation server. NDEF should only be configured to work with a [Yubico OTP](https://docs.yubico.com/yesdk/users-manual/application-otp/yubico-otp.html) or [HOTP](https://docs.yubico.com/yesdk/users-manual/application-otp/hotp.html) slot. Nothing will prevent you from configuring NDEF to use a slot with any other configuration, but it will not emit anything useful. For example, if a slot is configured for [challenge-response](https://docs.yubico.com/yesdk/users-manual/application-otp/challenge-response.html) , presenting the YubiKey to an NFC reader and issuing a NDEF read command will result in the static text or URI with nothing after. If a slot is configured with a [static password](https://docs.yubico.com/yesdk/users-manual/application-otp/static-password.html) , the password will come through NDEF as the raw [HID](https://docs.yubico.com/yesdk/users-manual/application-otp/hid.html) bytes, which are not recognizable as characters. (Static passwords need to be communicated through a USB port using HID messages.) ConfigureNdef example --------------------- In this example, we will configure the [long-press](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Slot.html#Yubico_YubiKey_Otp_Slot_LongPress) slot to emit an HOTP token, and we will configure NDEF to emit an identifier for an example user. To execute the code below, the YubiKey needs to either be inserted into a USB port or be on an NFC reader when the command is run. using (OtpSession otp = new OtpSession(yKey)) { otp.ConfigureHotp(Slot.LongPress) .UseInitialMovingFactor(4096) .Use8Digits() .UseKey(_key) .Execute(); otp.ConfigureNdef(Slot.LongPress) .AsText("AgentSmith:") .Execute(); } After configuring NDEF with the code above, if you [read](https://docs.yubico.com/yesdk/users-manual/application-otp/how-to-read-ndef-information.html) the YubiKey with an NFC reader, the result will look something like `AgentSmith:00901250`. Next steps ---------- After configuring a slot with NDEF, learn [how to read from the NDEF tag](https://docs.yubico.com/yesdk/users-manual/application-otp/how-to-read-ndef-information.html) . [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-otp/how-to-configure-ndef.md/#L1) --- # ##### Table of Contents Set management key ------------------ ### Command APDU Info | CLA | INS | P1 | P2 | Lc | Data | Le | | --- | --- | --- | --- | --- | --- | --- | | 00 | FF | FF | _touch policy_ | 1B | _new key data_ | (absent) | The touch policy is either `FF` (no touch required) or `FE` (touch required) or `FD` for cached. The new key data is formatted as follows 03 9B 18 <24 binary bytes> 03 means Triple-DES 9B indicates slot 9B (where the management key resides) 18 is the length (0x18 = decimal 24) ### Response APDU Info #### Response APDU for SET MANAGEMENT KEY (success) Total Length: 2 Data Length: 0 | Data | SW1 | SW2 | | --- | --- | --- | | (no data) | 90 | 00 | #### Response APDU for SET MANAGEMENT KEY (authentication failed) Total Length: 2 Data Length: 0 | Data | SW1 | SW2 | | --- | --- | --- | | (no data) | 69 | 82 | ### Examples $ opensc-tool -c default -s 00:a4:04:00:09:a0:00:00:03:08:00:00:10:00 -s 00:FF:FF:FF:1B:03:9B:18:01:02:03:04:05:06:07:08: 08:07:06:05:04:03:02:01: 08:07:06:05:04:03:02:01 Using reader with a card: Yubico YubiKey OTP+FIDO+CCID 0 Sending: 00 A4 04 00 09 A0 00 00 03 08 00 00 10 00 Received (SW1=0x90, SW2=0x00): 61 11 4F 06 00 00 10 00 01 00 79 07 4F 05 A0 00 00 03 08 Sending: 00 FF FF FF 1B 03 9B 18 01 02 03 04 05 06 07 08 08 07 06 05 04 03 02 01 08 07 06 05 04 03 02 01 Received (SW1=0x69, SW2=0x82) [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-piv/apdu/set-mgmt-key.md/#L1) --- # ##### Table of Contents Get the serial number --------------------- ### Command APDU Info | CLA | INS | P1 | P2 | Lc | Data | Le | | --- | --- | --- | --- | --- | --- | --- | | 00 | F8 | 00 | 00 | (absent) | (absent) | (absent) | ### Response APDU Info Total Length: 6 Data Length: 4 | Data | SW1 | SW2 | | --- | --- | --- | | _big endian bytes of the 32-bit serial number_ | 90 | 00 | ### Examples $ opensc-tool -c default -s 00:a4:04:00:09:a0:00:00:03:08:00:00:10:00 -s 00:f8:00:00 Using reader with a card: Yubico YubiKey OTP+FIDO+CCID 0 Sending: 00 A4 04 00 09 A0 00 00 03 08 00 00 10 00 Received (SW1=0x90, SW2=0x00): 61 11 4F 06 00 00 10 00 01 00 79 07 4F 05 A0 00 00 03 08 Sending: 00 F8 00 00 Received (SW1=0x90, SW2=0x00): 00 AE 17 CB In this case, the serial number is 0x00AE17CB = decimal 11409355 [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-piv/apdu/serial.md/#L1) --- # ##### Table of Contents Reset the PIV application ------------------------- Available for all YubiKeys with the PIV application except for YubiKey Bio Multi-protocol Edition (MPE) keys. For YubiKey Bio MPE, use the [device-wide reset](https://docs.yubico.com/yesdk/users-manual/sdk-programming-guide/bio-mpe.html#resetting-a-yubikey-bio-mpe) instead. ### Command APDU Info | CLA | INS | P1 | P2 | Lc | Data | Le | | --- | --- | --- | --- | --- | --- | --- | | 00 | FB | 00 | 00 | (absent) | (absent) | (absent) | ### Response APDU Info #### Response APDU for RESET PIV (success) Total Length: 2 Data Length: 0 | Data | SW1 | SW2 | | --- | --- | --- | | (no data) | 90 | 00 | #### Response APDU for RESET PIV (did not reset, PIN or PUK not blocked) Total Length: 2 Data Length: 0 | Data | SW1 | SW2 | | --- | --- | --- | | (no data) | 69 | 85 | Examples -------- $ opensc-tool -c default -s 00:a4:04:00:09:a0:00:00:03:08:00:00:10:00 -s 00:fb:00:00 Using reader with a card: Yubico YubiKey OTP+FIDO+CCID 0 Sending: 00 A4 04 00 09 A0 00 00 03 08 00 00 10 00 Received (SW1=0x90, SW2=0x00): 61 11 4F 06 00 00 10 00 01 00 79 07 4F 05 A0 00 00 03 08 Sending: 00 FB 00 00 Received (SW1=0x90, SW2=0x00) [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-piv/apdu/reset-piv.md/#L1) --- # ##### Table of Contents Set PIN retries --------------- ### Command APDU Info | CLA | INS | P1 | P2 | Lc | Data | Le | | --- | --- | --- | --- | --- | --- | --- | | 00 | FA | _PIN retries_ | _PUK retries_ | (absent) | (absent) | (absent) | ### Response APDU Info #### Response APDU for SET PIN RETRIES (success) Total Length: 2 Data Length: 0 | Data | SW1 | SW2 | | --- | --- | --- | | (no data) | 90 | 00 | #### Response APDU for SET PIN RETRIES (authentication failed) Total Length: 2 Data Length: 0 | Data | SW1 | SW2 | | --- | --- | --- | | (no data) | 69 | 82 | ### Examples $ opensc-tool -c default -s 00:a4:04:00:09:a0:00:00:03:08:00:00:10:00 -s 00:fa:05:05 Using reader with a card: Yubico YubiKey OTP+FIDO+CCID 0 Sending: 00 A4 04 00 09 A0 00 00 03 08 00 00 10 00 Received (SW1=0x90, SW2=0x00): 61 11 4F 06 00 00 10 00 01 00 79 07 4F 05 A0 00 00 03 08 Sending: 00 FA 05 05 Received (SW1=0x69, SW2=0x82) [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-piv/apdu/set-pin-retries.md/#L1) --- # ##### Table of Contents Get the firmware version number ------------------------------- ### Command APDU info | CLA | INS | P1 | P2 | Lc | Data | Le | | --- | --- | --- | --- | --- | --- | --- | | 00 | FD | 00 | 00 | (absent) | (absent) | (absent) | ### Response APDU info Total Length: 5 Data Length: 3 | Data | SW1 | SW2 | | --- | --- | --- | | _major, minor, patch_ | 90 | 00 | ### Opensc-tool Example $ opensc-tool -c default -s 00:a4:04:00:09:a0:00:00:03:08:00:00:10:00 -s 00:fd:00:00 Using reader with a card: Yubico YubiKey OTP+FIDO+CCID 0 Sending: 00 A4 04 00 09 A0 00 00 03 08 00 00 10 00 Received (SW1=0x90, SW2=0x00): 61 11 4F 06 00 00 10 00 01 00 79 07 4F 05 A0 00 00 03 08 Sending: 00 FD 00 00 Received (SW1=0x90, SW2=0x00): 05 02 04 In this case, the version number is 5.2.4 [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-piv/apdu/version.md/#L1) --- # ##### Table of Contents Verify temporary PIN -------------------- ### Command APDU info | CLA | INS | P1 | P2 | Lc | Data | Le | | --- | --- | --- | --- | --- | --- | --- | | 00 | 20 | 00 | 96 | 12 | 01 10 _temporary PIN_ | (absent) | ### Response APDU info #### Response APDU for VERIFY (success) Total Length: 2 Data Length: 0 | Data | SW1 | SW2 | | --- | --- | --- | | (no data) | 90 | 00 | #### Response APDU for VERIFY (Invalid temporary PIN) Total Length: 2 Data Length: 0 | Data | SW1 | SW2 | | --- | --- | --- | | (no data) | 63 | C0 | If the temporary PIN is incorrect, then the error is `63 C0`. The temporary PIN in invalidated in the YubiKey and a new one needs to be obtained. [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-piv/apdu/verify-temporary-pin.md/#L1) --- # ##### Table of Contents Verify PIN ---------- ### Command APDU info | CLA | INS | P1 | P2 | Lc | Data | Le | | --- | --- | --- | --- | --- | --- | --- | | 00 | 20 | 00 | 80 | 08 | _PIN_ | (absent) | ### Response APDU info #### Response APDU for VERIFY (success) Total Length: 2 Data Length: 0 | Data | SW1 | SW2 | | --- | --- | --- | | (no data) | 90 | 00 | #### Response APDU for VERIFY (Invalid PIN) Total Length: 2 Data Length: 0 | Data | SW1 | SW2 | | --- | --- | --- | | (no data) | 63 | C4 | If the PIN entered is incorrect, then the error is `63 CX` where _X_ is the number of retries remaining. In the above, there are 4 retries remaining. #### Response APDU for VERIFY (PIN Blocked) Total Length: 2 Data Length: 0 | Data | SW1 | SW2 | | --- | --- | --- | | (no data) | 69 | 83 | Whe the YubiKey returns this Status Word, it is not saying the PIN is incorrect. It is simply reporting that there are no retries remaining and the PIN is blocked. Maybe the PIN supplied is correct, maybe not. However, because the PIN has been blocked, authentication was denied. ### Examples $ opensc-tool -c default -s 00:a4:04:00:09:a0:00:00:03:08:00:00:10:00 -s 00:20:00:80:08:31:32:33:34:35:36:ff:ff Using reader with a card: Yubico YubiKey OTP+FIDO+CCID 0 Sending: 00 A4 04 00 09 A0 00 00 03 08 00 00 10 00 Received (SW1=0x90, SW2=0x00): 61 11 4F 06 00 00 10 00 01 00 79 07 4F 05 A0 00 00 03 08 Sending: 00 20 00 80 08 31 32 33 34 35 36 FF FF Received (SW1=0x90, SW2=0x00) [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-piv/apdu/verify.md/#L1) --- # ##### Table of Contents Change reference data --------------------- ### Command APDU Info | CLA | INS | P1 | P2 | Lc | Data | Le | | --- | --- | --- | --- | --- | --- | --- | | 00 | 24 | 00 | 80 | 10 | _current PIN and new PIN_ | (absent) | | 00 | 24 | 00 | 81 | 10 | _current PUK and new PUK_ | (absent) | Which element to change is given in the P2 field of the APDU and the current and new data (old and new PIN or PUK) are given in the data field. The data is simply the two values concatenated. Both the PIN and the PUK are allowed to be 6 to 8 characters. If one is less than 8, it will be padded with 0xff to reach 8 characters/bytes in length. For example, the default PIN is "123456", but on the device, it is represented as `31 32 33 34 34 36 FF FF`. The PIN can be composed of any ASCII character, but PUK composition depends on the key's firmware. For YubiKeys with firmware versions prior to 5.7, the key will accept any value in the `0x00` - `0xFF` range for the PUK. For YubiKeys with firmware version 5.7 and above, the key will only accept values in the `0x00` - `0x7F` range (not including the padding). The data is therefore 16 bytes, current value (possibly padded) followed by the new value (possibly padded). ##### Note YubiKey Bio Multi-protocol Edition (MPE) keys [do not have a PUK](https://docs.yubico.com/yesdk/users-manual/sdk-programming-guide/bio-mpe.html) . ### Response APDU Info #### Response APDU for CHANGE REFERENCE DATA (success) Total Length: 2 Data Length: 0 | Data | SW1 | SW2 | | --- | --- | --- | | (no data) | 90 | 00 | #### Response APDU for CHANGE REFERENCE DATA (invalid current PIN or PUK) Total Length: 2 Data Length: 0 | Data | SW1 | SW2 | | --- | --- | --- | | (no data) | 63 | C2 | If the PIN entered is incorrect, then the error is `63 CX` where _X_ is the number of retries remaining. In the above, there are 2 retries remaining. #### Response APDU for CHANGE REFERENCE DATA (PIN or PUK Blocked) Total Length: 2 Data Length: 0 | Data | SW1 | SW2 | | --- | --- | --- | | (no data) | 69 | 83 | The PIN or PUK entered might or might not be correct, however, authentication was denied because the number of retries have been exhausted. #### Response APDU for CHANGE REFERENCE DATA (PIN or PUK failed length and/or complexity requirements) Total Length: 2 Data Length: 0 | Data | SW1 | SW2 | | --- | --- | --- | | (no data) | 69 | 85 | The new PIN or PUK did not meet the specified length requirements, an invalid character/byte was used, and/or the PIN/PUK violated the key's [PIN complexity policy](https://docs.yubico.com/yesdk/users-manual/sdk-programming-guide/pin-complexity-policy.html) . #### Response APDU for CHANGE REFERENCE DATA (input data failed the length requirement) Total Length: 2 Data Length: 0 | Data | SW1 | SW2 | | --- | --- | --- | | (no data) | 6a | 80 | The total data length did not match the 16-byte requirement. #### Response APDU for CHANGE REFERENCE DATA (invalid P1 and/or P2) Total Length: 2 Data Length: 0 | Data | SW1 | SW2 | | --- | --- | --- | | (no data) | 6a | 88 | The P1 or P2 parameter was not valid given the instruction code. ### Examples $ opensc-tool -c default -s 00:a4:04:00:09:a0:00:00:03:08:00:00:10:00 -s 00:24:00:80:10:31:32:33:34:35:36:ff:ff:36:35:34:33:32:31:ff:ff Using reader with a card: Yubico YubiKey OTP+FIDO+CCID 0 Sending: 00 A4 04 00 09 A0 00 00 03 08 00 00 10 00 Received (SW1=0x90, SW2=0x00): 61 11 4F 06 00 00 10 00 01 00 79 07 4F 05 A0 00 00 03 08 Sending: 00 24 00 80 10 31 32 33 34 35 36 FF FF 36 35 34 33 32 31 FF FF Received (SW1=0x90, SW2=0x00) $ opensc-tool -c default -s 00:a4:04:00:09:a0:00:00:03:08:00:00:10:00 -s 00:24:00:81:10:31:32:33:34:35:36:37:38:38:37:36:35:34:33:32:31 Using reader with a card: Yubico YubiKey OTP+FIDO+CCID 0 Sending: 00 A4 04 00 09 A0 00 00 03 08 00 00 10 00 Received (SW1=0x90, SW2=0x00): 61 11 4F 06 00 00 10 00 01 00 79 07 4F 05 A0 00 00 03 08 Sending: 00 24 00 81 10 31 32 33 34 35 36 37 38 38 37 36 35 34 33 32 31 Received (SW1=0x90, SW2=0x00) [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-piv/apdu/change-ref.md/#L1) --- # How FIDO U2F works ##### Table of Contents How FIDO U2F works ================== At its foundation, there are two FIDO U2F operations: * Registration * Authentication First, the user registers the YubiKey and ties it to a particular account. Second, when logging on, the user makes sure the appropriate YubiKey is inserted. During login, the YubiKey, browser, and authentication server will communicate and perform the steps necessary to authenticate. The user will likely need to tap the YubiKey in order to complete authentication. This article describes what is happening "under the covers" during registration and authentication. The entities involved --------------------- There are three components in FIDO U2F * The authenticator (YubiKey) * The client (a browser, platform component, or application) * The relying party (verifies the authentication process) FIDO U2F can only work when using clients that already have support. For example, suppose you have an online account with a bank and you have added FIDO U2F support. Now you try to log into that account using a Vivaldi or Puffin browser on MacOS. That might not work because it is possible those browsers do not support FIDO U2F. You can log in using Safari or Chrome, because they do have support. The client is, of course, the "medium" through which the authenticator and relying party communicate. However, the client also plays a role in verifying that the relying party is correct, not a fake or attacker. Registration ------------ The goal of registration is for the authenticator to provide a public key and a handle to the partner private key to the relying party. This key and handle are to be associated with an account. Also associated with the account is a counter. The relying party will initialize the stored counter to zero. Next, the client provides "origin data" to the authenticator. This is data the authenticator will use during authentication. If the origin data during authentication does not match the origin data from registration, then the authenticator will return an error. Finally, the relying party provides an "AppId" to the authenticator. See [this description](https://developers.yubico.com/U2F/App_ID.html) for more details on AppIds. For now, an AppId is a list of trusted facets, where we can think of a facet as a description of a FIDO U2F "entry point". This could be the the URL of the login page, among other things. Generally, an authentication server will have a database of accounts, each entry containing a username and password info (not the password itself, but information that can be used to verify the password). With FIDO U2F, each entry will also contain a public key, a private key handle, and a counter. First, let's look at the flow diagram describing U2F registration. ![U2F registration](https://docs.yubico.com/yesdk/images/u2f-registration.png) ### Step 0 The user has logged in to an account and is now adding U2F, or this is happening during account registration. ### Step 1 The relying party sends to the client a random value, called the challenge. The relying party also sends the "AppId". Although it can be more complicated, think of the AppId as either a single URL or else a set of URLs. The client will look at who it is actually connected to (called the "origin") and see if that URL is on the list. If not, there is a mismatch and the connection is dropped. ### Step 2 The client builds a message containing the digest of the origin and the digest of the challenge data. The origin is who the client is actually connected to, and the challenge data includes the challenge, of course, but also the origin (again), and possibly some TLS information. This information is sent to the authenticator (Yubikey). Note that the terminology can change, even inside the standard. There's the origin, which is something the client creates. It creates a string that includes the protocol, hostname, and port of the actual connection. Next is the "application identifier" or "appId". It is the value the relying party sends to the client. It will presumably be the same as the origin. Then there is a "facet ID", which is a single "entry point" to the relying party. Some relying parties can have multiple facets (e.g. one for web, one for iOS, and one for Android). The client will be able to compare the origin it computes with the facet ID or app ID the relying party sends. Finally, there is the digest of the origin, computed by the client. It is sometimes called the "appIdHash", or "origin data", or the "application parameter". For example, one part of the U2F standard uses the term "hash of the origin". However, the part of the standard that specifies how messages are formatted uses the term "application parameter". The following is the message sent by the client to the YubiKey, initiating registration. challenge parameter || application parameter The "challenge parameter" is also known as "client data hash". The client computes the SHA-256 digest of the challenge, origin, and other information. The "application parameter" is also known as "hash of the origin", or "appIdHash", or "origin data". The client computes the SHA-256 digest of the origin it computed. For example, in hex A76CF9A4BDA5D0596D56612E71CDD954C38168954541522F7DCD9433666BA0F008D71B87CC11BF231245CC8C0A1B653FB5A47C2D9D66A8B94154AAB26C2FF670 The challenge data is A76CF9A4BDA5D0596D56612E71CDD954C38168954541522F7DCD9433666BA0F0 The origin data is 08D71B87CC11BF231245CC8C0A1B653FB5A47C2D9D66A8B94154AAB26C2FF670 ### Step 3 The authenticator generates a new ECC key pair (using a standard EC parameter set specified by the FIDO U2F specifications). If the authenticator wants, it can use the information in the origin data as input to the key pair generation process. In fact, the Yubikey performs HMAC on the origin data, using an HMAC key derived from the [FIDO U2F master key](https://docs.yubico.com/yesdk/users-manual/application-u2f/how-u2f-works.html#fido-master-key) to generate the key pair. Note that the master key is in the secure element and never leaves the YubiKey. The authenticator generates a different key pair for each site with which it registers. The private key is never to leave the device in the clear. In order to find the appropriate private key later, the authenticator creates a handle. This can be anything that the authenticator wants, just so long as it is a way for the device to recall that specific private key when needed. For example, it could be a number, whereby a device numbers all its keys starting with 1. When presented with a handle, retrieve the key associated with that number. Whatever the handle, it must somehow contain the origin data. With the Yubikey, the handle is the key itself, along with the origin data, encrypted using an AES key derived from the [FIDO U2F master key](https://docs.yubico.com/yesdk/users-manual/application-u2f/how-u2f-works.html#fido-master-key) . Later on, when presented with the handle, the Yubikey decrypts it and has the private key and correct origin data. Someone outside can see the handle, and know that it contains the private key itself. So all they have to do is decrypt it. But they don't know the key-encrypting-key, so they must perform a brute-force attack, which would take trillions of years. The authenticator now creates a message (sent to the client) containing the public key, the private key handle, and an [attestation cert](https://docs.yubico.com/yesdk/users-manual/application-u2f/how-u2f-works.html#attestation) , then signs it using the attestation private key. marker byte || public key || key handle || attestation cert || signature For example, in hex 05 045827...A4 86149D...7B 308202D8...19 30440220...2C pub key | handle | cert | signature | For a deeper discussion of attestation, see [the section below](https://docs.yubico.com/yesdk/users-manual/application-u2f/how-u2f-works.html#attestation) . ### Step 4 The client forwards the authenticator's message to the relying party, which verifies the signature and attestation cert. It now knows that the private key partner to the public key in the message was indeed generated by a YubiKey. The relying party stores the public key, private key handle, and an initial counter of zero in the user's database entry. Authentication -------------- The goal of authentication is for the authenticator to send, to the relying party, a value that proves the authenticator is the one registered to the specified user. In addition, the authenticator, working with the client, can verify the current origin (who the client is actually connected to) is the correct one. First, let's look at the flow diagram describing U2F registration. ![U2F registration](https://docs.yubico.com/yesdk/images/u2f-authentication.png) ### Step 1 The relying party sends a random challenge (a new one each time), the AppId, and the private key handle to the code running on the client. This login code now calls on the client's U2F Javascript API for authentication. ### Step 2 The client builds the origin data, then sends it along with the challenge, and key handle to the authenticator. control byte || challenge parameter || application parameter || key handle For example, in hex 03 50F2A8...37 08D71B...70 86149D...7B | challenge |origin data| handle | The challenge parameter is not the same one from registration. It is the digest of a new challenge, along with much of the same data used during registration. The origin data (application parameter) is the same from registration. The handle is the same from registration. ### Step 3 The authenticator uses the origin data and key handle from the client to find and retrieve the appropriate key. If it determines that the origin data provided during authentication does not match the origin data from registration, or more likely, it simply cannot find a key associated with the key handle and origin data, it will return an error. If the origin data matches, the authenticator increments its counter and signs the challenge parameter, application parameter (origin data), counter, and a byte indicating whether the user tapped the YubiKey. The counter and signature are sent to the client. The YubiKey has a single counter for all U2F sites (explicitly allowed by the standard), so the initial counter for a new registration might be 0, or it might be greater than zero. ### Step 4 The client sends the counter, challenge, and signature to the relying party, which verifies the signature using the public key (likely stored in the username/password database). It also verifies that the counter is greater than the last authentication. Why This Works -------------- We want a system that verifies the user, and gives the user confidence that they are logging into the actual site. How does this system accomplish that? First, let's look at how this proves to the relying party that the user does indeed have access to the authenticator. Next, we'll look at how the user can have confidence that they are indeed logging into the intended site. ### Validating the User First of all, the U2F authentication only verifies that the authenticator was used. If an attacker steals a user's Yubikey, they can use it and the relying party has no way of knowing that the correct user is not on the other end. Of course, the attacker must also have the user's password. Hence the "2" of U2F, indicating a second factor authentication. Once the relying party has the user's public key, they can verify any signature. Only the Yubikey can create valid signatures that the user's public key will verify, so that the relying party knows that the user's Yubikey created that signature. To break the system, the attacker would have to break ECC (compute the private key based on a public key and/or some set of signatures), or break the Yubikey (obtain the master key off the secure element). Another attack would be "replay". Collect a valid signature and in another session, pass it off as a new one. But signatures are based on the challenge (the smart relying party will make sure that is different every single session) and the counter. So an old signature won't be valid anymore. ### Validating the relying party One of the most important reasons for using this form of two-factor authentication is to thwart the "man-in-the-middle" attack. Here's how that usually works with a username/password system. The attacker uses a phishing email to get you to click on a link. You click and up pops your browser showing a site that looks just like a legitimate login page. But it's not, it is the attacker's site. When you enter your username and password, the bad site simply passes that information on to the real site. If it is correct, the attacker now has opened your account. They pass the opened pages on to you. You perform the operation and log out. The attacker has not done any processing, it simply takes any information you entered and passes it on to the real website, and takes any returned information and passes it on to you. They see everything, so they have your username and password and all the information in the pages you opened. Now look at the target site with U2F. Suppose you click on the link in a phishing email. You see the login page. You enter your username and password, which the bad site passes on to the real one. However, now the real site needs the U2F authentication. It sends the auth message (step 1) to the bad site, which passes it on to you. But when it is passing it on to you, it is passing it on to the client, the browser. The client computes the origin data, which in this case is the bad site. The client sends the challenge, key handle, and origin data to the authenticator, which can see the mismatch between the current origin data and what is in the key handle. It will return an error and the client can drop the connection. The bad site collected your username and password, but could not log in to your account. They now need to steal your Yubikey to break into your account. Note that the U2F standard specifies that the key pair is generated using the origin data and "...the U2F device encodes the requesting origin into the Key Handle." Because the key handle includes the origin data, it will be possible for the authenticator to see the mismatch between the origin data and the key handle. The YubiKey builds a key handle by encrypting the private key and origin data using the [FIDO U2F master key](https://docs.yubico.com/yesdk/users-manual/application-u2f/how-u2f-works.html#fido-master-key) . This means the attacker will not be able to build an alternate key handle. And even if the attacker is able to somehow get the authenticator to compute a signature, the relying party will not authenticate it. That's because the data to sign includes the origin data. The relying party will try to verify the signature using the challenge along with its origin data. However, the authenticator built the signature using the challenge and the atacker's origin data. Incidentally, it would probably be a good idea to collect the username, then perform U2F, and only after that was successful collect the password. FIDO master key --------------- A YubiKey is manufactured with a FIDO master key. Each YubiKey has a different master key. It resides in the secure element so never leaves the device. It is possible to reset the FIDO U2F application on a YubiKey, and when that happens, the old master key is replaced with a newly-generated value. In this case, all old credentials are lost. During FIDO U2F operations, the YubiKey will use the master key to generate the key pair and encrypt the private key. It does this by using the master key as a starting point and deriving values from it. That is, the input is the master key and other data (such as a descriptor indicating the use case, or origin data), and the output is the actual key to use. In this way, only one key is saved in the secure element, yet there can be many different secure keys. Attestation ----------- During registration, the YubiKey will send the public key and partner private key handle to the relying party (via the client). At this point, the relying party wants to know that the public key came from a YubiKey, and not a software implementation. This is proven using attestation. Each YubiKey contains a FIDO U2F attestation private key and cert installed during manufacture. The private key is loaded into the secure element and cannot leave the device. The same private key and cert are installed on thousands of YubiKeys. The registration information the YubiKey sends to the relying party includes the public key and handle, of course, but it also includes the attestation cert and a signature. The YubiKey will create data to sign that includes the digest of the origin, the client data hash (the digest of a JSON structure containing the challenge, origin data, and other information) along with the public key and key handle. This data is signed using the attestation private key. This signature is an attestation statement. An entity verifying the signature can see there is a binding between the relying party (represented by the origin and client data), this registration (represented by the challenge), and the YubiKey (represented by the public key). The relying party knows that the signature was created by the YubiKey's attestation private key because it verifies using the attestation cert. To verify the signature, the relying party extracts the public key from the cert and performs normal verification. It then verifies the cert by chaining to a root. Any relying party that wants to support U2F will obtain root certs for all the devices it is willing to support. Root Cert | | Attestation Cert (Sent in the registration response message) | | Attestation Statement (the signature in the resgistration response message) It is possible to create an attestation statement for the FIDO U2F private keys generated on a YubiKey. Such a statement simply offers evidence that a private key was generated on a YubiKey. It does not say anything about who owns the YubiKey, or who signed some data using the private key, only that the key is from a YubiKey. Note that any private key generated on the YubiKey, using the FIDO U2F application, is not allowed to leave the device in the clear. Hence, it is possible to verify that a private key operation was performed (or will be performed) by the YubiKey and only the YubiKey. See also [this page](https://developers.yubico.com/U2F/Attestation_and_Metadata/) for information on U2F attestation. To verify the attestation cert, use the root certificate. You can find Yubico's U2F root [here](https://developers.yubico.com/U2F/yubico-u2f-ca-certs.txt) . [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-u2f/how-u2f-works.md/#L1) --- # Maintaining compatibility ##### Table of Contents Maintaining compatibility ========================= This article describes the various decisions that the SDK makes in order to maintain application and source compatibility across our versions. App-compat strategy for this SDK -------------------------------- The .NET SDK strives to maintain both source and behavioral compatibility across its releases. **Source compatibility** is the promise that your source code should continue to compile as-is when you update your application to the latest version of the SDK. This promise extends to "minor" (feature) and "patch" (bug-fix) releases of the SDK. Additionally, we only make this guarantee for the `Yubico.YubiKey` and the `Yubico.Core` assemblies. Since `Yubico.NativeShims` is meant to be purely for internal use, we _do not_ make any guarantees here. **Behavioral compatibility** is the promise that your application will behave exactly the same after you have upgraded the YubiKey SDK version. Maintaining this guarantee is far more difficult and is sometimes simply not possible. However, we will continue to do our best to maintain behavioral stability across releases. If a behavioral change is necessitated, such as fixing a bug, we may choose to simply fix the issue. This is far more likely to occur if the bug prevented the feature from ever working in the first place and no workaround was present. If the change is more nuanced than that, or it is changing behavior for some other reason, we have a separate mechanism that we've started using so that these behavior changes may be managed through an opt-in or opt-out decision. There are two exceptions to these promises: 1. Sometimes a breaking change is unavoidable. Perhaps a new YubiKey feature was released that is simply impossible to express with the existing shape of the API. Or a bug was discovered, and it simply must be addressed. In these cases, we will do everything in our power to first mark the affected types or members with the `ObsoleteAttribute` so that you are alerted the fact that there's an issue with the old usage. The attribute will contain text that will result in a usage warning when you recompile. This text will be included in the warning message and will point you to the new API that should be used instead. The old API will remain for several minor releases before we consider it safe to remove entirely. A major release would remove all obsolete APIs in one go. 2. You will note that the promise is only made for minor and patch releases. For example, upgrading feature releases (i.e. `1.9.1` to `1.10.0`) or upgrading patch releases (i.e. `1.9.0` to `1.9.1`) have this guarantee. What has been omitted here is "major" releases (i.e. `1.10.0` to `2.0.0`). Major version releases are our chance to make broader changes that address design-level issues. It should be expected that there will be source level breaking changes when a major version is released. Our SDK does _not_ make any promises around **Application Binary Interface (ABI)** stability. This expectation is generally far less common in the .NET ecosystem to begin with, however there are two very important implications here: 1. You _must_ recompile your code against a new version of our SDK. Simply replacing our assemblies with a newer version is **not** supported and could result in undefined behavior and bugs in your application's behavior. 2. If an enumeration does not have an explicitly defined value, you should assume that the underlying value may change. While these changes should not result in any changes to behavior (assuming you've recompiled) it does mean that these values should not be serialized and stored across versions. If you need to persist these values for whatever reason, it is strongly recommended you create your own stable values to map to, or use another mechanism that does not depend on the specific compiler-generated enumeration value. Managing behavior changes through app-compat switches ----------------------------------------------------- Sometimes it's unavoidable that the SDK must make a behavior breaking change. For example: a bug has been addressed that causes subtle behavior changes that have existed for many releases. Or perhaps an optimization has been made that may result in different timings that could have an effect on UI applications. In these cases, we've introduced a new mechanism for adjusting these behaviors through the use of app-compat switches. These switches use the [`AppContext.SetSwitch`](https://learn.microsoft.com/en-us/dotnet/api/system.appcontext.setswitch) mechanism exposed by the .NET Base Class Library. Whether a behavior change is opt-in or opt-out will be decided on a case-by-case basis. Generally, if we view the change to be a net positive and have a low risk of observable changes to an application, we will make the change opt-out. That means, you will get the new behavior by default. Only if the change causes your application problems should you consider setting the switch to disable that behavior. For more observable or impactful changes, or changes that would benefit a smaller subset of consumers, we will make the change opt-in. That is, the existing behaviors will be maintained, and your application must explicitly call `SetSwitch` with a value of `true`. This decision is clearly very subjective. Any time a behavior change is made, there is a high likelihood that at least one consumer will be adversely affected no matter which behavior we choose. That's why we've introduced these switches in the first place. There will always be a case where someone will need to override out decision. This is your mechanism to do so. All of our compatibility switch names are defined in two central classes: * [YubiKeyCompatSwitches](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.YubiKeyCompatSwitches.html) - This class holds all the compatibility switches that affect the behaviors of the `Yubico.YubiKey` assembly. * [CoreCompatSwitches](https://docs.yubico.com/yesdk/core-api/Yubico.Core.CoreCompatSwitches.html) - This class holds all the compatibility switches that affect the `Yubico.Core` assembly. `Yubico.Core` serves as our platform abstraction layer, so switches here may only impact a certain operating system or a certain downstream dependency. While not YubiKey specific, it may affect things like enumeration and eventing of YubiKeys. Each flag will have a clear explanation of what behavior it affects, what the default is, and what the impact of overriding the default should be. Use these constants as the value for the `switchName` parameter of `AppContext.SetSwitch`. [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/sdk-programming-guide/appcompat.md/#L1) --- # Challenge-response ##### Table of Contents Challenge-response ================== The other OTP application configurations ([Yubico OTP](https://docs.yubico.com/yesdk/users-manual/application-otp/yubico-otp.html) , [OATH HOTP](https://docs.yubico.com/yesdk/users-manual/application-otp/hotp.html) , and [static password](https://docs.yubico.com/yesdk/users-manual/application-otp/static-password.html) ) require the user to activate the configured [slot](https://docs.yubico.com/yesdk/users-manual/application-otp/slots.html) (by touching the YubiKey or scanning it with an [NFC reader](https://docs.yubico.com/yesdk/users-manual/application-otp/ndef.html) ) in order to generate and transmit the password from the YubiKey to a host device. Challenge-response, on the other hand, begins with a “challenge” that a host sends to the YubiKey. The YubiKey receives the challenge as a byte array and “responds” by encrypting or digesting (hashing) the challenge with a stored secret key and sending the response back to the host for authentication. Challenge-response is flexible. It can be used in single and multi-factor authentication for logging into applications or devices, and validation can take place on a host device itself or on a validation server on an internal or external network. The SDK supports all of these scenarios. To implement challenge-response authentication with a .NET application, the following must occur: * A slot on the YubiKey must be [configured](https://docs.yubico.com/yesdk/users-manual/application-otp/challenge-response.html#sdk-functionality) with a secret key and encryption/hashing algorithm. * The application must be able to [send challenges to and receive responses](https://docs.yubico.com/yesdk/users-manual/application-otp/challenge-response.html#sdk-functionality) from a YubiKey. * A copy of the secret key must be shared with the validating party. * The validating party must be able to validate responses and pass the result back to the application. ##### Important All YubiKey-host communication for challenge-response is done via the [HID communication protocol](https://docs.yubico.com/yesdk/users-manual/application-otp/hid.html) . Therefore, challenge-response authentication will only work when a YubiKey is physically plugged into a host over USB or Lightning. Challenges and responses cannot be communicated wirelessly with NFC. Supported challenge-response algorithms --------------------------------------- The .NET SDK and the YubiKey support the following algorithms for challenge-response: * [Yubico OTP](https://docs.yubico.com/yesdk/users-manual/application-otp/yubico-otp.html) (encryption) * HMAC-SHA1 as defined in [RFC2104](https://datatracker.ietf.org/doc/html/rfc2104) (hashing) For Yubico OTP challenge-response, an application will send the YubiKey a 6-byte challenge. The YubiKey will then create a 16-byte string by concatenating the challenge with 10 bytes of unique device fields. For Yubico OTP challenge-response, these 10 bytes of additional data are not important—they are merely added as padding so that the challenge may then be encrypted with a 16-byte key using the AES encryption algorithm (AES requires that data be encrypted in blocks of the same size as the encryption key). The resulting Yubico OTP (as a byte array) becomes the response. For HMAC-SHA1 challenge-response, an application will send the YubiKey a challenge of up to 64 bytes in size, which will be digested (hashed) with a 20-byte secret key, resulting in a 20-byte response (the HMAC-SHA1 hash value). Responses can be received by an application as a byte array or a 6-10 digit numeric code. With HMAC-SHA1, the challenge can be either an application-specified byte array or the current Unix time. ##### Note Hashing/digesting is a one-way operation, meaning that once a block of data is hashed, it cannot be converted back into its original form. Encryption, on the other hand, is a two-way operation. When a block of data is encrypted, it can be decrypted back into its original form. This is an important distinction because the validating party will have to respond differently to Yubico OTP responses (encrypted) and HMAC-SHA1 responses (hashed). For Yubico OTP, the validating party will have to decrypt the response and compare the result with the original challenge. For HMAC-SHA1, the validating party will have to perform the same hashing operation with the original challenge and compare the result to the response received from the YubiKey. Challenge initiation and authentication --------------------------------------- The challenge-response process works as follows: 1. The YubiKey is connected to the host. 2. The application on the host sends a challenge to a specific slot of the YubiKey via the SDK. 3. The YubiKey receives the challenge and encrypts/digests it with the secret key and encryption/hashing algorithm that the slot was configured with. 4. The YubiKey sends the response back to the host, and the application receives it as a raw byte array, a string object of numeric digits, or an integer (as configured with the SDK). 5. The application sends the response to the validating party. For Yubico OTP challenge-response, the response must be decrypted using the YubiKey’s unique secret key. For HMAC-SHA1 challenge-response, the validating party must digest the challenge with the secret key and the HMAC-SHA1 algorithm. 6. For Yubico OTP, if the decrypted response matches the original challenge that was sent to the YubiKey, authentication was successful, and the user is logged in. (For Yubico OTP challenge-response, the 6-byte challenge must match the first 6 bytes of the decrypted response—the other bytes are ignored.) For HMAC-SHA1, if the response matches the validating party's digested challenge, authentication was successful, and the user is logged in. SDK functionality ----------------- The SDK’s challenge-response functionality centers around the following two methods: * [CalculateChallengeResponse()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.OtpSession.html#Yubico_YubiKey_Otp_OtpSession_CalculateChallengeResponse_Yubico_YubiKey_Otp_Slot_) * [ConfigureChallengeResponse()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.OtpSession.html#Yubico_YubiKey_Otp_OtpSession_ConfigureChallengeResponse_Yubico_YubiKey_Otp_Slot_) `ConfigureChallengeResponse()` allows you to configure an OTP application slot on a YubiKey to receive a challenge from a host and process it based on a specific algorithm and secret key. `CalculateChallengeResponse()` allows a host to send a challenge to a YubiKey and then receive its response. ### ConfigureChallengeResponse() When calling `ConfigureChallengeResponse()`, you must set the secret key for the slot, which can be generated randomly via [GenerateKey()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.ConfigureChallengeResponse.html#Yubico_YubiKey_Otp_Operations_ConfigureChallengeResponse_GenerateKey_System_Memory_System_Byte__) or set explicitly with [UseKey()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.ConfigureChallengeResponse.html#Yubico_YubiKey_Otp_Operations_ConfigureChallengeResponse_UseKey_System_ReadOnlyMemory_System_Byte__) . If you choose to generate a key, that key must be shared with the validating party before being cleared from memory. Secrets cannot be extracted from the YubiKey once configured. You must also set the algorithm that will be used to respond to challenges by calling either [UseHmacSha1()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.ConfigureChallengeResponse.html#Yubico_YubiKey_Otp_Operations_ConfigureChallengeResponse_UseHmacSha1) or [UseYubiOtp()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.ConfigureChallengeResponse.html#Yubico_YubiKey_Otp_Operations_ConfigureChallengeResponse_UseYubiOtp) . For example, if you call `UseHmacSha1()`, the YubiKey will digest challenges it receives with the secret key via the HMAC-SHA1 algorithm. ##### Note It’s important that the size of your secret key matches the size that is expected for the algorithm you chose ([16 bytes](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.ConfigureChallengeResponse.html#Yubico_YubiKey_Otp_Operations_ConfigureChallengeResponse_YubiOtpKeySize) for Yubico OTP and [20 bytes](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.ConfigureChallengeResponse.html#Yubico_YubiKey_Otp_Operations_ConfigureChallengeResponse_HmacSha1KeySize) for HMAC-SHA1). The SDK will throw an exception if the key length is incorrect for the chosen algorithm. The `ConfigureChallengeResponse` class also provides optional methods for requiring users to touch the YubiKey to initiate the challenge-response operation ([UseButton()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.ConfigureChallengeResponse.html#Yubico_YubiKey_Otp_Operations_ConfigureChallengeResponse_UseButton_System_Boolean_) ) or enabling the key to process HMAC-SHA1 challenges of less than 64 bytes ([UseSmallChallenge()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.ConfigureChallengeResponse.html#Yubico_YubiKey_Otp_Operations_ConfigureChallengeResponse_UseSmallChallenge_System_Boolean_) ). ##### Note `UseSmallChallenge()` is included for compatibility with legacy systems whose implementations break data sets into multiple blocks, which often results in the last element being smaller than 64 bytes. For a full list of the methods in the `ConfigureChallengeResponse` class, see the [API documentation](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.ConfigureChallengeResponse.html) . For an example of how to use `ConfigureChallengeResponse()`, see [How to program a slot with a challenge-response credential](https://docs.yubico.com/yesdk/users-manual/application-otp/how-to-program-a-challenge-response-credential.html) . ### CalculateChallengeResponse() In order for a host to send a challenge to a YubiKey and receive a response, an application on the host must call `CalculateChallengeResponse()`. With this method, you can: * send a Yubico OTP or HMAC-SHA1 challenge to the YubiKey as an application-specified byte array with [UseChallenge()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.CalculateChallengeResponse.html#Yubico_YubiKey_Otp_Operations_CalculateChallengeResponse_UseChallenge_System_Byte___) . Alternatively, the current Unix time can be sent as a challenge with [UseTotp()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.CalculateChallengeResponse.html#Yubico_YubiKey_Otp_Operations_CalculateChallengeResponse_UseTotp) for HMAC-SHA1 challenge-response. * send a message to the user to notify them to touch the YubiKey to initiate the challenge-response operation with [UseTouchNotifier()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.CalculateChallengeResponse.html#Yubico_YubiKey_Otp_Operations_CalculateChallengeResponse_UseTouchNotifier_System_Action_) . This is only needed if the YubiKey slot was configured to require the button touch with `UseButton()`. * receive the response from the YubiKey. The response can be received as a string object of 6-10 numeric digits via [GetCode()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.CalculateChallengeResponse.html#Yubico_YubiKey_Otp_Operations_CalculateChallengeResponse_GetCode_System_Int32_) (HMAC-SHA1), as a byte array via [GetDataBytes()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.CalculateChallengeResponse.html#Yubico_YubiKey_Otp_Operations_CalculateChallengeResponse_GetDataBytes) (Yubico OTP, HMAC-SHA1), or as a single 10-digit, 32-bit integer via [GetDataInt()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.CalculateChallengeResponse.html#Yubico_YubiKey_Otp_Operations_CalculateChallengeResponse_GetDataInt) (HMAC-SHA1). In addition, the time period for time-based challenges sent with `UseTotp()` (i.e. how long a TOTP response is valid for) can be set via [WithPeriod()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.CalculateChallengeResponse.html#Yubico_YubiKey_Otp_Operations_CalculateChallengeResponse_WithPeriod_System_Int32_) . The default period is 30 seconds. Time-based challenges can only be used with keys configured for HMAC-SHA1 challenge-response. The SDK will throw an exception if you call both `UseTotp()` and `UseChallenge()`. ##### Note The size of the challenge sent to the YubiKey with `UseChallenge()` must align with the slot's configuration. If the slot is configured to perform Yubico OTP, the challenge must be [6 bytes](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.CalculateChallengeResponse.html#Yubico_YubiKey_Otp_Operations_CalculateChallengeResponse_YubicoOtpChallengeSize) long. If the slot is configured for HMAC-SHA1, the challenge must be [64 bytes](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.CalculateChallengeResponse.html#Yubico_YubiKey_Otp_Operations_CalculateChallengeResponse_MaxHmacChallengeSize) long. However, if the slot has been configured with `UseSmallChallenge()`, a challenge smaller than 64 bytes is acceptable. The SDK will throw an exception if the challenge size does not match the YubiKey slot's configuration. For a full list of the methods in the `CalculateChallengeResponse` class, see the [API documentation](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.CalculateChallengeResponse.html) . For an example of how to use `CalculateChallengeResponse()`, see [How to calculate a response code for a challenge-response credential](https://docs.yubico.com/yesdk/users-manual/application-otp/how-to-calculate-a-challenge-response-code.html) . [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-otp/challenge-response.md/#L1) --- # FIDO U2F and FIPS ##### Table of Contents FIDO U2F and FIPS ================= There are FIPS versions of YubiKey. These can be used by applications that require FIPS certification or the use of FIPS-certified products. However, there are some complexities to using a YubiKey for FIDO U2F in a FIPS environment. First of all, in order to be FIPS-compliant, a product can use only FIPS-specified algorithms in FIPS-certified products. Because FIPS does not mention FIDO U2F, it would seem that it is not possible to use U2F in a FIPS-compliant way. However, NIST (the National Institute of Standards and Technology, the government agency that oversees FIPS) has allowed U2F to be used in FIPS-compliant applications if the YubiKey's U2F application requires a PIN. The U2F standard does not say anything about setting a PIN on the application. The standard does not expect a PIN would be required to use U2F, only touch. However, because the U2F standard does not forbid the use of PINs, it is possible to configure an application to require one. YubiKey 4 FIPS series --------------------- Only version 4 FIPS series YubiKeys can be used for FIDO U2F in a FIPS environment. The U2F application of all other YubiKey models cannot be FIPS-compliant. This includes the version 5 FIPS series YubiKeys. Even though it is a FIPS-certified device, its FIDO U2F application is not FIPS-compliant. Note that a version 5 FIPS series YubiKey supports FIDO2 and that can be FIPS-compliant. You can determine programmatically whether a given YubiKey is a 4 FIPS Series key with the [GetDeviceInfoCommand](https://docs.yubico.com/yesdk/users-manual/application-u2f/u2f-commands.html#get-device-info) . var getDeviceInfoCmd = new GetDeviceInfoCommand(); GetDeviceInfoResponse getDeviceInfoRsp = connection.SendCommand(getDeviceInfoCmd); YubiKeyDeviceInfo deviceInfo = getDeviceInfoRsp.GetData(); if (deviceInfo.IsFipsSeries && (deviceInfo.FirmwareVersion.Major == 4)) { // This is a version 4 FIPS YubiKey. } FIPS mode --------- Even though a version 4 FIPS YubiKey is a FIPS-certified device, the FIDO U2F application is not itself FIPS-compliant until it is set with a PIN. During manufacturing, YubiKeys are not configured with a U2F PIN. Therefore, a YubiKey's U2F application is not in FIPS mode by default. After setting the PIN, the YubiKey's U2F application is in FIPS mode. You can programmatically determine if a YubiKey is in FIPS mode or not with [VerifyFipsModeCommand](https://docs.yubico.com/yesdk/users-manual/application-u2f/u2f-commands.html#verify-fips-mode) . var getDeviceInfoCmd = new GetDeviceInfoCommand(); GetDeviceInfoResponse getDeviceInfoRsp = connection.SendCommand(getDeviceInfoCmd); YubiKeyDeviceInfo deviceInfo = getDeviceInfoRsp.GetData(); // Is this YubiKey 4 FIPS series? if (deviceInfo.IsFipsSeries && (deviceInfo.FirmwareVersion.Major == 4)) { // If it is YubiKey 4 FIPS series, we can get the FIPS mode. var vfyFipsModeCmd = new VerifyFipsModeCommand(); VerifyFipsModeResponse vfyFipsModeRsp = connection.SendCommand(vfyFipsModeCmd); if (vfyFipsMode.GetData()) { // If the return from GetData is true, then this is // YubiKey 4 FIPS series in FIPS mode. // If the return is false, then the YubiKey is version 4 // FIPS series, but it is not in FIPS mode. } // Note that if the YubiKey is not version 4 FIPS series, the // VerifyFipsModeCommand is undefined. A call to VerifyFipsModeResponse.GetData // will result in an exception. } ### Setting FIPS mode To put the U2F application of a YubiKey 4 FIPS Series key into FIPS mode, you must set the U2F PIN. Call [U2fSession.SetPin](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.U2f.U2fSession.html#Yubico_YubiKey_U2f_U2fSession_SetPin_) , which obtains the PIN from the `KeyCollector`, or the [U2fSession.TrySetPin](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.U2f.U2fSession.html#Yubico_YubiKey_U2f_U2fSession_TrySetPin_) method that takes in the PIN (no `KeyCollector`). // This is the ASCII PIN "123456". byte[] newPin = new byte[] { 0x31, 0x32, 0x33, 0x34, 0x35, 0x36 }; using (var u2fSession = new U2fSession(yubiKey)) { if (!u2fSession.TrySetPin(newPin)) { // If this fails, call some error handling code. } } The U2F PIN can be any binary data from 6 to 32 bytes long. It will likely be input by the end user at the keyboard, which would make it similar to a normal password. Once you set the PIN, the YubiKey will be in FIPS mode and the `VerifyFipsModeCommand` will return true. Retries ------- If a caller wants to verify or change a PIN, the current PIN must be entered. If a wrong value is provided, the PIN won't be verified or changed and the caller can try again. However, there are limits to how many times a wrong value can be entered. If an incorrect PIN is entered three times in a row, the U2F application is blocked. The only way to unblock it is to reset it. It is important to know that after resetting, the YubiKey can no longer be put into FIPS mode. Note that with the FIDO2 application on the YubiKey 5 FIPS series, the PIN retry count is eight. However, that is FIDO2 on YubiKey 5. The total retry count fo the U2F application on YubiKey 4 FIPS series is three. If the correct PIN is verified before the U2F application is blocked, the retries remaining count returns to three. Unfortunately in the version 4 FIPS series YubiKey, it is not possible to know how many U2F PIN retries are remaining. That is, if the wrong PIN has been entered, the SDK will return to the caller indicating that the wrong PIN was entered, but will not be able to report the number of retries remaining. Removing the PIN ---------------- Once a PIN is set on the U2F application, it is not possible to remove it. That is, if you call `U2fSession.TrySetPin` (or the SetPin command) with an "Empty" PIN, the YubiKey will not reset the PIN, instead it will return an error. The SDK will throw an exception. The only way to remove a U2F PIN is to reset the key's U2F application. A reset generally restores the application to its original factory settings. However, with YubiKey 4 FIPS series, the reset also deletes the attestation key and cert (they are replaced with a "reset" key and cert) and the U2F application will no longer be able to be set to FIPS mode. At this point, if you try to set the PIN, the YubiKey will set the PIN, but it will not be in FIPS mode. The YubiKey will still be able to register new U2F credentials, but they will not be "FIPS" credentials. Note also that when you reset the U2F application, the master secret is changed, so all previous U2F registrations will be lost. Summary ------- What this all means is that if you have a version 4 FIPS series YubiKey, * upon manufacture the U2F application is not in FIPS mode * to put it into FIPS mode, set the PIN * it is possible to change the PIN * once it is in FIPS mode with a PIN, it is not possible to remove the PIN or take it out of FIPS mode, except by resetting the entire application * upon reset, all registrations using that YubiKey will be lost * once the U2F application has been reset, it is no longer in FIPS mode and can no longer be put into FIPS mode [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-u2f/fips-mode.md/#L1) --- # ##### Table of Contents Reset retry (recover the PIN) ----------------------------- Available for all YubiKeys with the PIV application except for YubiKey Bio Multi-protocol Edition (MPE) keys, which [do not have a PUK](https://docs.yubico.com/yesdk/users-manual/sdk-programming-guide/bio-mpe.html) . ### Command APDU Info | CLA | INS | P1 | P2 | Lc | Data | Le | | --- | --- | --- | --- | --- | --- | --- | | 00 | 2C | 00 | 80 | 10 | _current PUK and new PIN_ | (absent) | The data will be 16 bytes long. The PUK is given in the first 8 bytes of the data, and the new PIN is the next 8 bytes. If the PUK or new PIN is not 8 bytes, it is padded with FF bytes. ### Response APDU Info #### Response APDU for RESET RETRY (success) Total Length: 2 Data Length: 0 | Data | SW1 | SW2 | | --- | --- | --- | | (no data) | 90 | 00 | #### Response APDU for RESET RETRY (Invalid PUK) Total Length: 2 Data Length: 0 | Data | SW1 | SW2 | | --- | --- | --- | | (no data) | 63 | C4 | If the PUK entered is incorrect, then the error is `63 CX` where _X_ is the number of retries remaining. In the above, there are 4 retries remaining. #### Response APDU for RESET RETRY (PUK blocked) Total Length: 2 Data Length: 0 | Data | SW1 | SW2 | | --- | --- | --- | | (no data) | 69 | 83 | The PUK entered might or might not be correct, however, authentication was denied because the number of retries have been exhausted. ### Examples $ opensc-tool -c default -s 00:a4:04:00:09:a0:00:00:03:08:00:00:10:00 -s 00:2C:00:80:10:31:32:33:34:35:36:37:38:31:32:33:34:35:36:37:ff Using reader with a card: Yubico YubiKey OTP+FIDO+CCID 0 Sending: 00 A4 04 00 09 A0 00 00 03 08 00 00 10 00 Received (SW1=0x90, SW2=0x00): 61 11 4F 06 00 00 10 00 01 00 79 07 4F 05 A0 00 00 03 08 Sending: 00 2C 00 80 10 31 32 33 34 35 36 37 38 31 32 33 34 35 36 37 FF Received (SW1=0x90, SW2=0x00) [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-piv/apdu/reset-retry.md/#L1) --- # ##### Table of Contents Verify UV --------- ### Command APDU info | CLA | INS | P1 | P2 | Lc | Data | Le | | --- | --- | --- | --- | --- | --- | --- | | 00 | 20 | 00 | 96 | _variable_ | _variable_ | (absent) | The data bytes vary depending on the intended operation: * none - check the biometric state * 02 00 - request a temporary PIN * 03 00 - perform biometric verification ### Response APDU info #### Response APDU for VERIFY (success) Total Length: 2 Data Length: 0 | Data | SW1 | SW2 | | --- | --- | --- | | (no data) | 90 | 00 | #### Response APDU for VERIFY (success with temporary PIN) Total Length: 18 Data Length: 16 | Data | SW1 | SW2 | | --- | --- | --- | | temporary PIN | 90 | 00 | #### Response APDU for VERIFY (Invalid biometric match) Total Length: 2 Data Length: 0 | Data | SW1 | SW2 | | --- | --- | --- | | (no data) | 63 | C0 - C2 | If the biometric match failed, the error is `63 CX` where _X_ is the number of retries remaining. When no retries remain, biometric verification becomes blocked, and the error returned is `0x6983` (`AuthenticationMethodBlocked`). To proceed in this situation, the [PIV PIN verification](https://docs.yubico.com/yesdk/users-manual/application-piv/apdu/verify.html) must be used. [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-piv/apdu/verify-uv.md/#L1) --- # Security Domain certificate management ##### Table of Contents Security Domain certificate management ====================================== The Security Domain manages X.509 certificates primarily for SCP11 protocol operations. These certificates are used for authentication and establishing secure channels. For detailed information about certificate usage in secure channels, see the [Secure Channel Protocol (SCP)](https://docs.yubico.com/yesdk/users-manual/sdk-programming-guide/secure-channel-protocol.html) documentation. Certificate operations ---------------------- ### Storing certificates Certificates are stored in chains associated with specific key references. A typical certificate chain includes: * Root CA certificate * Intermediate certificates (optional) * Leaf (end-entity) certificate // Store certificate chain var certificates = new List { rootCert, intermediateCert, leafCert }; session.StoreCertificates(keyReference, certificates); ### CA configuration For SCP11a and SCP11c, you need to configure the Certificate Authority (CA) information: // Store CA issuer information using Subject Key Identifier (SKI) byte[] subjectKeyIdentifier = GetSkiFromCertificate(caCert); session.StoreCaIssuer(keyReference, subjectKeyIdentifier); ### Retrieving certificates // Get all certificates for a key reference var certificates = session.GetCertificates(keyReference); // Get leaf certificate (last in chain) var leafCert = certificates.Last(); // Get supported CA identifiers var caIds = session.GetSupportedCaIdentifiers( kloc: true, // Key Loading OCE Certificate klcc: true // Key Loading Card Certificate ); Access control -------------- ### Certificate allowlists Use of the allowlist will create strong binding to one or multiple OCE(s) Control which certificates can be used for authentication by maintaining an allowlist of serial numbers: // Store allowlist of certificate serial numbers var allowedSerials = new List { "7F4971B0AD51F84C9DA9928B2D5FEF5E16B2920A", "6B90028800909F9FFCD641346933242748FBE9AD" }; session.StoreAllowlist(keyReference, allowedSerials); // Clear allowlist (allows any valid certificate) session.ClearAllowList(keyReference); Certificate management by SCP11 variant --------------------------------------- Different SCP11 variants have different certificate requirements: ### SCP11a * Full certificate chain required * OCE (Off-Card Entity) certificates needed * Supports authorization rules in certificates * Used for mutual authentication Example setup: // Setup with full chain for SCP11a using var session = new SecurityDomainSession(yubiKeyDevice, scp03Params); var keyRef = KeyReference.Create(ScpKeyIds.Scp11A, kvn); // Store certificates session.StoreCertificates(keyRef, certificates); // Configure OCE var oceRef = KeyReference.Create(OceKid, kvn); session.StoreCaIssuer(oceRef, skiBytes); ### SCP11b * No mutual authentication * Suitable when host authentication isn't required Example setup: // Basic SCP11b setup using var session = new SecurityDomainSession(yubiKeyDevice, scp03Params); var keyRef = KeyReference.Create(ScpKeyIds.Scp11B, kvn); // Only store device certificate session.StoreCertificates(keyRef, new[] { deviceCert }); ### SCP11c * Mutual authentication * Similar to SCP11a but with additional features such as offline scripting usage (See [GlobalPlatform SCP11 Specification Annex B](https://globalplatform.org/specs-library/secure-channel-protocol-11-amendment-f/) ) Security considerations ----------------------- 1. **Certificate Validation** * Verify certificate chains completely 2. **Access Control** * Consider using allowlists in production environments * Regularly review and update allowlists ##### Important Most certificate operations require an authenticated session. Operations are typically only available when using SCP11a or SCP11c variants. Common tasks ------------ ### Initial certificate setup 1. Generate or obtain required certificates 2. Store certificate chain on YubiKey 3. Configure CA information if needed 4. Optionally, set up an allowlist // Example of complete setup using var session = new SecurityDomainSession(yubiKeyDevice, Scp03KeyParameters.DefaultKey); var keyRef = KeyReference.Create(ScpKeyIds.Scp11A, kvn); // Store full chain session.StoreCertificates(keyRef, certificateChain); // Configure CA var oceRef = KeyReference.Create(OceKid, kvn); session.StoreCaIssuer(oceRef, GetSkiFromCertificate(caCert)); // Set up allowlist session.StoreAllowlist(keyRef, allowedSerials); ### Certificate rotation using var session = new SecurityDomainSession(yubiKeyDevice, scpParams); // Store new certificates session.StoreCertificates(keyRef, newCertificateChain); // Update allowlist if needed session.StoreAllowlist(keyRef, newAllowedSerials); ### Troubleshooting 1. **Certificate Loading Issues** * Verify certificate format (X.509 v3) * Check certificate chain order * Validate key references 2. **Authentication Problems** * Verify certificates * Check allowlist configuration ##### Note For additional details on secure channel establishment and certificate usage, refer to the [Secure Channel Protocol (SCP)](https://docs.yubico.com/yesdk/users-manual/sdk-programming-guide/secure-channel-protocol.html) documentation. [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-security-domain/security-domain-certificates.md/#L1) --- # ##### Table of Contents Get device info --------------- ### Inner command APDU info | CLA | INS | P1 | P2 | Lc | Data | Le | | --- | --- | --- | --- | --- | --- | --- | | 00 | C2 | 00 | 00 | (absent) | (absent) | (absent) | ### Response APDU info Total Length: 49 Data Length: 47 | Data | SW1 | SW2 | | --- | --- | --- | | _data_ | 90 | 00 | The data is a byte array with the first byte the length and the following bytes a series of TLVs. See [this section](https://docs.yubico.com/yesdk/users-manual/application-u2f/u2f-commands.html#deviceinfooutput) for more information on the data output and its encoding. [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-u2f/apdu/get-device-info.md/#L1) --- # ##### Table of Contents Echo ---- ### Inner command APDU info | CLA | INS | P1 | P2 | Lc | Data | Le | | --- | --- | --- | --- | --- | --- | --- | | 00 | 40 | 00 | 00 | _data len_ | _data_ | (absent) | ### Response APDU info Total Length: _variable + 2_ Data Length: _variable_ | Data | SW1 | SW2 | | --- | --- | --- | | _data_ | 90 | 00 | [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-u2f/apdu/echo-cmd.md/#L1) --- # ##### Table of Contents Set device info --------------- ### Full command APDU info | CLA | INS | P1 | P2 | Lc | Data | Le | | --- | --- | --- | --- | --- | --- | --- | | 00 | C3 | 00 | 00 | _data length_ | _encoded device info_ | (absent) | The data is encoded as length 01 02 --optional value 03 02 --optional value 04 01 --optional value 05 03 --optional value 06 02 --optional value 07 01 --optional value 08 01 --optional value 0d 02 --optional value 0e 02 --optional value 0a 01 --optional value 0b 01 --optional value See this [table](https://docs.yubico.com/yesdk/users-manual/application-u2f/u2f-commands.html#deviceinfoelements) for information on each of the tags. There is a difference between that table and the data provided for Set Device Info, namely the lock code. The lock code is 16 binary bytes. If there is no lock code, and the caller wants to set one, provide it in the data under the tag `0A`. For example, From no lock code to lock code 0A 10 9A 30 B5 86 27 F1 1D 99 40 7C 4E 14 03 BD 82 17 If there is a lock code already set, provide it under the tag `0B`. 0B 10 9A 30 B5 86 27 F1 1D 99 40 7C 4E 14 03 BD 82 17 To change the lock code, provide the current code under the `0B` tag and the new lock code under the `0A` tag. 0B 10 9A 30 B5 86 27 F1 1D 99 40 7C 4E 14 03 BD 82 17 0A 10 71 08 B4 96 AC 38 64 F2 81 D0 48 55 B2 EA 07 73 To remove the lock code (set the YubiKey so that a lock code is no longer needed), set the new lock code to all `00` bytes. 0B 10 71 08 B4 96 AC 38 64 F2 81 D0 48 55 B2 EA 07 73 0A 10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ### Response APDU info #### Response APDU for successful setting the device info Total Length: 2 Data Length: 0 | Data | SW1 | SW2 | | --- | --- | --- | | (no data) | 90 | 00 | #### Response APDU for incorrect lock code provided If there is a lock code set, but the Set command is sent with no lock code (nothing under the 0B tag), or with an incorrect lock code, this is the return. Total Length: 2 Data Length: 0 | Data | SW1 | SW2 | | --- | --- | --- | | (no data) | 6F | 00 | #### Response APDU when sent to YubiKeys before version 5 Total Length: 2 Data Length: 0 | Data | SW1 | SW2 | | --- | --- | --- | | (no data) | 69 | 00 | [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-u2f/apdu/set-device-info.md/#L1) --- # OATH overview ##### Table of Contents OATH overview ============= The YubiKey supports the Initiative for Open Authentication (OATH) standards for generating one-time password (OTP) codes. Using this application, a YubiKey can be configured with multiple OTP credentials in a manner similar to that found in software authenticators. Unlike a software only solution, the credentials are stored in the YubiKey itself and can roam between your devices. Simply plug the YubiKey into a device that has YubiKey OATH-enabled software, and your credentials will be there. The YubiKey-generated one-time passcodes can be used as one of the authentication options in your application's two-factor or multi-factor authentication workflow. A 6 or 8 digit passcode is not strong enough to stand on its own; it is often used to augment the user's primary credentials. OTP code -------- An OTP is similar to a password, however it can only be used once. It is often used in combination with a regular password as an additional authentication mechanism providing extra security. The OTP code is generated using two inputs: a shared secret and a moving factor. The secret is a static value that is created when you establish a new credential. It is only communicated once, and is stored on both the authenticator (the YubiKey) and the authentication server. The moving factor changes each time a new OTP is requested. The way the moving factor is generated and agreed upon is different for HOTP and TOTP credentials. ### HOTP Credential HOTP stands for HMAC-based One-time Password algorithm (HOTP). The algorithm is specified in [RFC 4226](https://datatracker.ietf.org/doc/html/rfc4226) . It is an event-based OTP where the moving factor is based on a counter. Each time the HOTP is requested and validated, the moving factor is incremented based on a counter. The code that is generated is valid until you actively request another one and the authentication server validates it. The OTP generator and the server are synchronized each time the code is validated, and the user gains access. ### TOTP Credential TOTP stands for Time-based One-time Password (TOTP). The algorithm is specified in [RFC 6238](https://datatracker.ietf.org/doc/html/rfc6238) . The moving factor in a TOTP is time-based rather than counter-based. The amount of time in which each password is valid is called a timestep. The default timestep is 30 seconds, but it can also be 15 or 60 seconds. If you have not used your password within that window, it will no longer be valid, and you will need to request a new one to gain access to your application. ### HOTP vs. TOTP HOTP credentials do not have an expiration period. TOTP improves HOTP by using the current time as the moving factor. TOTP credentials have the advantage of being valid for a limited time period — the timestep. So if the generated code is not used within a certain period of seconds, it expires and can not be used for login. TOTP credentials tend to be more secure because they're only valid for a certain period of time, which adds a certain layer of security. The fact of adding an extra factor that needs to be met increases the security of the code. TOTPs are considered an evolved form of HOTPs— they imply more security because of having an extra factor to meet the algorithm conditions. Since HOTP doesn’t have the time-based limitation, it’s a little more user-friendly but may be more susceptible to brute force attacks. That’s because of a potentially longer window in which the HOTP is valid. Also, HOTP can have a synchronization problem. The HOTP counter is incremented each time the button is tapped, while the server counter is incremented only when a password is successfully validated. For this reason, HOTP validating servers accept a range of OTPs. Specifically, they will accept an OTP generated by a counter within a set number of increments from the previous counter value stored on the server. This range is the validation window. If the token counter is outside of the window allowed by the server, the validation fails, and the token must be re-synchronized. The larger the window - the greater the chance of an adversary guessing one of the accepted OTPs through a brute-force attack. The HOTP algorithm is practical and sound. The possible brute force attack can be prevented by careful implementation of countermeasures in the validation server. However, given TOTP's advantages over the HOTP protocol, TOTP should be favored whenever possible. Use OATH with the YubiKey ------------------------- When using OATH with a YubiKey, the shared secrets are stored and processed in the YubiKey’s secure element. This has two advantages over software-only solutions: 1. Security The secrets always stay within the YubiKey. A phone can get stolen, sold, infected by malware, have its storage read by a connected computer, etc. 2. Accessibility You can display OATH codes on more than one phone or computer. If your phone runs out of battery, you can get a code using a friend’s phone or your computer. OATH functionality ------------------ All OATH operations can be divided into three groups with related types of functionality: | Common | | --- | | Connect to OATH application | | Reset OATH application | | Managing Authentication | | --- | | Set password | | Validate password | | Remove password | | Managing Credentials | | --- | | Get all configured credentials on the YubiKey | | Calculate OTPs for all configured credentials | | Calculate OTP for specific credential | | Add (or overwrite) credential | | Remove credential | | Rename credential | Next Steps ---------- Read more about [credentials](https://docs.yubico.com/yesdk/users-manual/application-oath/oath-credentials.html) . To build an application that utilizes an OATH functionality, the developer can use the SDK. [Make the connection](https://docs.yubico.com/yesdk/users-manual/sdk-programming-guide/making-a-connection.html) , create a [OathSession](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Oath.OathSession.html) , then call appropriate methods. The OathSession methods are based on lower level [commands](https://docs.yubico.com/yesdk/users-manual/application-oath/oath-commands.html) . Read more about [OATH Session](https://docs.yubico.com/yesdk/users-manual/application-oath/oath-session.html) and the main [OATH use case](https://docs.yubico.com/yesdk/users-manual/application-oath/oath-use-case.html) . Sample code is also available demonstrating how to use the SDK to perform OATH operations. [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-oath/oath-overview.md/#L1) --- # The FIDO U2F PIN ##### Table of Contents The FIDO U2F PIN ================ Both the FIDO U2F and FIDO2 standards specify that a device have a "test of user presence" in order to perform registration and authentication operations. During the test, "the user touches a button (or sensor of some kind) to 'activate' the U2F device". With the YubiKey, there is the option to also require a PIN in order to use the U2F application. However, this option is available only for YubiKey 4 FIPS Series keys. If you try to set a PIN for the U2F application on a non-FIPS YubiKey 4 Series key, a YubiKey 5 Series key (FIPS or non-FIPS), or a Security Key Series key, it will not work. However, with YubiKey 5 Series (FIPS and non-FIPS) and Security Key Series keys, it is possible to set a PIN on the _FIDO2_ application. YubiKey 4 Series keys do not have a FIDO2 application. | YubiKey | U2F Available | FIDO2 Available | U2F PIN | FIDO2 PIN | | --- | --- | --- | --- | --- | | 4 | yes | no | no | \- | | 4 FIPS | yes | no | yes | \- | | 5 | yes | yes | no | yes | | 5 FIPS | yes | yes | no | yes | | Security Key | yes | yes | no | yes | To learn more about how the U2F PIN is used with YubiKey 4 FIPS Series keys, see [FIDO U2F and FIPS](https://docs.yubico.com/yesdk/users-manual/application-u2f/fips-mode.html) . [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-u2f/u2f-pin.md/#L1) --- # Security Domain device information ##### Table of Contents Security Domain device information ================================== The Security Domain provides access to various device information and configuration data. This document covers device information retrieval and generic data operations. For protocol details, see the [Secure Channel Protocol (SCP)](https://docs.yubico.com/yesdk/users-manual/sdk-programming-guide/secure-channel-protocol.html) documentation. Card recognition data --------------------- The card recognition data provides information about the YubiKey's capabilities and configuration according to GlobalPlatform Card Specification v2.3.1 §H.2. ### Retrieving card data using var session = new SecurityDomainSession(yubiKeyDevice); // Get card recognition data (TLV encoded) var cardData = session.GetCardRecognitionData(); ### Card data structure The card recognition data follows this TLV structure: | Tag | Description | | --- | --- | | 0x66 | Card Data template | | 0x73 | Card Recognition Data | | ... | Card-specific data elements | Generic data operations ----------------------- The Security Domain supports general-purpose data retrieval and storage using TLV (Tag-Length-Value) formatting. ### Retrieving data // Get data for a specific tag var data = session.GetData(tag); // Get data with additional parameters var data = session.GetData(tag, additionalData); ### Storing data // Store TLV-formatted data byte[] tlvData = PrepareTlvData(); session.StoreData(tlvData); ### Common data tags | Tag | Description | Access Level | | --- | --- | --- | | 0x66 | Card Data | Read-only | | 0x73 | Card Recognition | Read-only | | 0xE0 | Key Information | Read-only | | 0xBF21 | Certificate Store | Read/Write | | 0xFF33 | KLOC Identifiers | Read/Write | | 0xFF34 | KLCC Identifiers | Read/Write | Device configuration -------------------- ### Checking capabilities // Check SCP11 support if (yubiKeyDevice.HasFeature(YubiKeyFeature.Scp11)) { // Device supports SCP11 } // Get installed key information var keyInfo = session.GetKeyInformation(); // Get supported CA identifiers var caIds = session.GetSupportedCaIdentifiers( kloc: true, klcc: true ); ### Device status information 1. **Key Status** var keyInfo = session.GetKeyInformation(); foreach (var entry in keyInfo) { var keyRef = entry.Key; var components = entry.Value; // Check key type and components bool isScp03 = keyRef.Id == ScpKeyIds.Scp03; bool hasAllComponents = components.Count == 3; // For SCP03 } 2. **Certificate Status** // Check certificate configuration foreach (var key in keyInfo.Keys) { try { var certs = session.GetCertificates(key); // Analyze certificate chain AnalyzeCertificateChain(certs); } catch (Exception ex) { // Handle missing certificates } } Data management --------------- ### TLV data handling 1. **Reading TLV Data** var tlvData = session.GetData(tag); var tlvReader = new TlvReader(tlvData); // Parse TLV structure while (tlvReader.HasData) { var tag = tlvReader.PeekTag(); var value = tlvReader.ReadValue(); ProcessTlvData(tag, value); } 2. **Writing TLV Data** using var ms = new MemoryStream(); using var writer = new BinaryWriter(ms); // Build TLV structure writer.Write((byte)tag); writer.Write((byte)length); writer.Write(value); session.StoreData(ms.ToArray()); ### Data organization The Security Domain organizes data hierarchically: Root ├── Card Data (0x66) │ └── Card Recognition (0x73) ├── Key Information (0xE0) │ ├── Key References │ └── Key Components ├── Certificate Store (0xBF21) │ ├── Certificate Chains │ └── CA Information └── Device Configuration ├── KLOC Data (0xFF33) └── KLCC Data (0xFF34) Maintenance operations ---------------------- ### Data validation // Validate stored data public void ValidateDeviceConfiguration() { // Check card data var cardData = session.GetCardRecognitionData(); ValidateCardData(cardData); // Check key information var keyInfo = session.GetKeyInformation(); ValidateKeyConfiguration(keyInfo); // Check certificate store foreach (var key in keyInfo.Keys) { ValidateCertificateConfiguration(key); } } ### Data cleanup // Remove unused data public void CleanupDeviceData() { // Clear unused certificates foreach (var key in keyInfo.Keys) { if (IsKeyExpired(key)) { session.DeleteKey(key); } } // Clear obsolete allowlists foreach (var key in keyInfo.Keys) { if (IsAllowlistObsolete(key)) { session.ClearAllowList(key); } } } [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-security-domain/security-domain-device.md/#L1) --- # Security Domain common tasks ##### Table of Contents Security Domain common tasks ============================ This document covers common operational tasks and workflows for managing the Security Domain. For detailed information about secure channels, see the [Secure Channel Protocol (SCP)](https://docs.yubico.com/yesdk/users-manual/sdk-programming-guide/secure-channel-protocol.html) documentation. Setting up a new YubiKey ------------------------ ### 1\. Initial state assessment Check the current configuration of your YubiKey: using var session = new SecurityDomainSession(yubiKeyDevice); var keyInfo = session.GetKeyInformation(); var hasDefaultKeys = keyInfo.Any(k => k.Key.VersionNumber == 0xFF); ### 2\. Replacing default SCP03 keys Always replace default keys in production environments: // Start with default keys using var defaultSession = new SecurityDomainSession( yubiKeyDevice, Scp03KeyParameters.DefaultKey); // Generate or obtain your secure keys var newKeys = new StaticKeys(newMacKey, newEncKey, newDekKey); var keyRef = KeyReference.Create(ScpKeyIds.Scp03, keyVersionNumber); defaultSession.PutKey(keyRef, newKeys); ##### Warning Default keys provide no security. Replace them before deploying to production. Setting up SCP11 ---------------- ### 1\. Generate initial keys Start with an authenticated SCP03 session: // Use SCP03 session to set up SCP11 using var session = new SecurityDomainSession(yubiKeyDevice, scp03Params); // Generate SCP11b key pair var keyRef = KeyReference.Create(ScpKeyIds.Scp11B, keyVersionNumber); var publicKey = session.GenerateEcKey(keyRef); ### 2\. Configure certificate chain // Store certificates session.StoreCertificates(keyRef, certificateChain); // Configure CA for SCP11a/c var oceSubjectKeyIdentifier = GetSkiFromCertificate(oceCertCa); var caRef = KeyReference.Create(OceKid, kvn); session.StoreCaIssuer(caRef, oceSubjectKeyIdentifier); ### 3\. Set up access control (Optional) // Configure certificate allowlist var allowedSerials = GetAllowedCertificateSerials(); session.StoreAllowlist(keyRef, allowedSerials); Key management tasks -------------------- ### Rotating SCP03 keys // Authenticate with current keys using var session = new SecurityDomainSession(yubiKeyDevice, currentScp03Params); // Replace with new keys var newKeyRef = KeyReference.Create(ScpKeyIds.Scp03, newKvn); session.PutKey(newKeyRef, newStaticKeys, kvnToReplace); ### Rotating SCP11 keys using var session = new SecurityDomainSession(yubiKeyDevice, scpParams); // Generate new key pair var newKeyRef = KeyReference.Create(ScpKeyIds.Scp11B, newKvn); var newPublicKey = session.GenerateEcKey(newKeyRef, kvnToReplace); // Will be replaced Recovery operations ------------------- ### Status check using var session = new SecurityDomainSession(yubiKeyDevice); // Get key information var keyInfo = session.GetKeyInformation(); var activeKeys = keyInfo.Select(k => k.Key).ToList(); // Check certificates foreach (var key in activeKeys) { try { var certs = session.GetCertificates(key); Console.WriteLine($"Key {key} has {certs.Count} certificates"); } catch { Console.WriteLine($"No certificates for key {key}"); } } ### Factory reset // Warning: This removes all custom keys in the Security Domain using var session = new SecurityDomainSession(yubiKeyDevice); session.Reset(); ##### Important Resetting removes all custom keys and certificates. Have a recovery plan ready. Integration with other applications ----------------------------------- ### PIV with secure channel // Using SCP03 using var pivSession = new PivSession(yubiKeyDevice, scp03Params); pivSession.GenerateKeyPair(...); // Protected by SCP03 // Using SCP11 using var pivSession = new PivSession(yubiKeyDevice, scp11Params); pivSession.GenerateKeyPair(...); // Protected by SCP11 ### OATH with secure channel // Using SCP03 using var oathSession = new OathSession(yubiKeyDevice, scp03Params); oathSession.PutCredential(...); // Protected by SCP03 // Using SCP11 using var oathSession = new OathSession(yubiKeyDevice, scp11Params); oathSession.PutCredential(...); // Protected by SCP11 Production deployment tasks --------------------------- ### Initial provisioning 1. **Prepare Keys and Certificates** var scp03Keys = GenerateSecureKeys(); var (privateKey, publicKey, certificates) = GenerateScp11Credentials(); 2. **Configure YubiKey for SCP11B** using var session = new SecurityDomainSession(yubiKeyDevice, Scp03KeyParameters.DefaultKey); // Replace SCP03 keys var scp03Ref = KeyReference.Create(ScpKeyIds.Scp03, keyVersionNumber); session.PutKey(scp03Ref, scp03Keys); // Set up SCP11 var scp11Ref = KeyReference.Create(ScpKeyIds.Scp11B, keyVersionNumber); var scp11Public = session.GenerateEcKey(scp11Ref); session.StoreCertificates(scp11Ref, certificates); 3. **Validate Configuration** // Test new keys using var verifySession = new SecurityDomainSession( yubiKeyDevice, new Scp03KeyParameters(scp03Ref, scp03Keys)); var keyInfo = verifySession.GetKeyInformation(); // Verify expected keys are present ### Regular maintenance 1. **Monitor Key Status** // Check key information var keyInfo = session.GetKeyInformation(); foreach (var key in keyInfo) { // Log key status and plan rotation if needed LogKeyStatus(key); } 2. **Certificate Management** // Check certificate expiration var certificates = session.GetCertificates(keyRef); foreach (var cert in certificates) { if (cert.NotAfter < DateTime.Now.AddMonths(3)) { // Plan certificate renewal PlanCertificateRenewal(cert); } } [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-security-domain/security-domain-tasks.md/#L1) --- # Security Domain key management ##### Table of Contents Security Domain key management ============================== The Security Domain supports management of both symmetric (SCP03) and asymmetric (SCP11) keys. This document describes the key types, their usage, and management operations. For protocol details and secure channel implementation, see the [Secure Channel Protocol (SCP)](https://docs.yubico.com/yesdk/users-manual/sdk-programming-guide/secure-channel-protocol.html) documentation. Key types --------- The Security Domain manages two main types of keys: * **SCP03 Keys**: Symmetric AES-128 keys used for secure messaging * **SCP11 Keys**: Asymmetric NIST P-256 keys and X.509-certificates used for authentication and key agreement SCP03 key management -------------------- Each SCP03 key set consists of three AES-128 keys that work together to secure communications: | Key Type | Key ID (KID) | Purpose | | --- | --- | --- | | Key-ENC | 0x1 | Channel encryption key for securing messages | | Key-MAC | 0x2 | Channel MAC key for message authentication | | Key-DEK | 0x3 | Data encryption key for sensitive data | ### Managing SCP03 keys // Put a new SCP03 key set var kvn = 0x01; var keyRef = KeyReference.Create(ScpKeyIds.Scp03, kvn); var staticKeys = new StaticKeys(keyDataMac, keyDataEnc, keyDataDek); session.PutKey(keyRef, staticKeys); // Replace existing keys var newKeys = new StaticKeys(newMacKey, newEncKey, newDekKey); session.PutKey(keyRef, newKeys, kvnToReplace); ### Key Version Numbers (KVN) SCP03 key sets are identified by Key Version Numbers: * Default key set: KVN=0xFF (publicly known, no security) * Each YubiKey can store up to three custom SCP03 key sets ##### Note When adding the first custom key set, the default keys are automatically removed. SCP11 key management -------------------- SCP11 uses NIST P-256 elliptic curve cryptography. Keys can be: * Generated on the YubiKey * Imported from external sources ### Generating keys // Generate new EC key pair var keyRef = KeyReference.Create(ScpKeyIds.Scp11B, keyVersionNumber); var publicKey = session.GenerateEcKey(keyRef); ### Importing keys // Import existing private key var privateKey = new ECPrivateKeyParameters(ecdsa); session.PutKey(keyRef, privateKey); // Import public key var publicKey = new ECPublicKeyParameters(ecdsaPublic); session.PutKey(keyRef, publicKey); Key management operations ------------------------- ### Querying key information // Get information about installed keys var keyInfo = session.GetKeyInformation(); foreach (var entry in keyInfo) { var keyRef = entry.Key; // KeyReference containing ID and Version var components = entry.Value; // Dictionary of key components Console.WriteLine($"Key {keyRef.Id:X2}:{keyRef.VersionNumber:X2}"); } ### Deleting keys Keys can be deleted individually or reset to factory defaults: // Delete specific key session.DeleteKey(keyRef); // Reset all keys to factory defaults session.Reset(); ##### Warning Resetting removes all custom keys and restores factory defaults (within the Security Domain). Ensure you have backups before resetting. Key rotation ------------ Here are some simple key rotation procedures: ### SCP03 key rotation // Authenticate with current keys using var session = new SecurityDomainSession(yubiKeyDevice, scpParams); // Replace with new keys var newKeyRef = KeyReference.Create(ScpKeyIds.Scp03, keyVersionNumber); session.PutKey(newKeyRef, newStaticKeys, kvnToReplace); ### SCP11 key rotation using var session = new SecurityDomainSession(yubiKeyDevice, scpParams); // Generate new key pair var newKeyRef = KeyReference.Create(ScpKeyIds.Scp11B, keyVersionNumber); var newPublicKey = session.GenerateEcKey(newKeyRef, kvnToReplace); Security considerations ----------------------- 1. **Key Protection** * Use unique keys per device when possible * Consider using SCP11 for mutual authentication 2. **Key Version Management** * Track which keys are loaded on each YubiKey * Track KVNs in use 3. **Default Keys** * Default SCP03 keys provide no security * Replace default keys in production environments * Cannot retain default keys alongside custom keys ##### Important The YubiKey provides no metadata about installed keys beyond what's available through `GetKeyInformation()`. Your application must track additional key management details. [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-security-domain/security-domain-keys.md/#L1) --- # How to set, modify, remove, and use slot access codes ##### Table of Contents How to set, modify, remove, and use slot access codes ===================================================== The YubiKey's OTP application [slots](https://docs.yubico.com/yesdk/users-manual/application-otp/slots.html) can be protected by a six-byte access code. Once a slot is configured with an access code, that slot cannot be reconfigured in any way unless the correct access code is provided during the reconfiguration operation. Attempting to perform a slot configuration operation without providing the correct access code will result in the following exception: `System.InvalidOperationException has been thrown.` `YubiKey Operation Failed. [Warning, state of non-volatile memory is unchanged.]` Slot access code properties --------------------------- Access codes can only be set, modified, or removed during one of the following slot configuration operations: * [ConfigureYubicoOtp()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.OtpSession.html#Yubico_YubiKey_Otp_OtpSession_ConfigureYubicoOtp_Yubico_YubiKey_Otp_Slot_) * [ConfigureHotp()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.OtpSession.html#Yubico_YubiKey_Otp_OtpSession_ConfigureHotp_Yubico_YubiKey_Otp_Slot_) * [ConfigureChallengeResponse()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.OtpSession.html#Yubico_YubiKey_Otp_OtpSession_ConfigureChallengeResponse_Yubico_YubiKey_Otp_Slot_) * [ConfigureStaticPassword()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.OtpSession.html#Yubico_YubiKey_Otp_OtpSession_ConfigureStaticPassword_Yubico_YubiKey_Otp_Slot_) * [UpdateSlot()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.OtpSession.html#Yubico_YubiKey_Otp_OtpSession_UpdateSlot_Yubico_YubiKey_Otp_Slot_) Of these options, the **only** method that allows you to configure a slot access code without changing the slot's current cryptographic credential is `UpdateSlot()`. However, calling `UpdateSlot()` will revert a number of other slot settings (such as `SetAppendCarriageReturn()`) to their default states unless otherwise specified during the operation. See [How to update slot settings](https://docs.yubico.com/yesdk/users-manual/application-otp/how-to-update-slot-settings.html) for more information. ##### Note If a slot is configured with an access code, calling [ConfigureNdef()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.OtpSession.html#Yubico_YubiKey_Otp_OtpSession_ConfigureNdef_Yubico_YubiKey_Otp_Slot_) will fail, even if the correct access code is provided during the operation. Similarly, if a slot is not configured with an access code, you cannot set one when calling `ConfigureNdef()`. Access codes must be exactly six bytes ([MaxAccessCodeLength](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.SlotAccessCode.html#Yubico_YubiKey_Otp_SlotAccessCode_MaxAccessCodeLength) ). The [SlotAccessCode](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.SlotAccessCode.html) container class pads the code with zeros (0x00) if less than six bytes are provided and throws an exception if more than six bytes are provided. If a slot is configured with an access code, that code must be specified during any reconfiguration operation. In addition, if you don’t resupply the same (or any) code as a "new" access code, an access code will not be carried over to the new slot configuration, and the slot will no longer be protected after reconfiguration. If a slot is protected by an access code, deleting the slot's configuration requires the use of the compatible [DeleteSlotConfiguration](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.OtpSession.html#Yubico_YubiKey_Otp_OtpSession_DeleteSlotConfiguration_Yubico_YubiKey_Otp_Slot_) method. Example code ------------ Before running any of the code provided below, make sure you have already connected to a particular YubiKey on your host device via the [YubiKeyDevice](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.YubiKeyDevice.html) class. To select the first available YubiKey connected to your host, use: IEnumerable yubiKeyList = YubiKeyDevice.FindAll(); var yubiKey = yubiKeyList.First(); ### Example: set a slot access code To set a slot's access code when no access code is present, call [SetNewAccessCode()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.OperationBase-1.html#Yubico_YubiKey_Otp_Operations_OperationBase_1_SetNewAccessCode_Yubico_YubiKey_Otp_SlotAccessCode_) during a slot configuration operation, and provide the access code as a `SlotAccessCode` object. Prior to the configuration operation, initialize the `SlotAccessCode` object by passing it the access code in `ReadOnlyMemory` form. In this example, we are setting a new access code while configuring the long press slot with a new HOTP credential. using (OtpSession otp = new OtpSession(yubiKey)) { // example HOTP key ReadOnlyMemory hmacKey = new byte[ConfigureHotp.HmacKeySize] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; // example slot access code ReadOnlyMemory accessCodeBytes = new byte[SlotAccessCode.MaxAccessCodeLength] { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, }; SlotAccessCode accessCode = new SlotAccessCode(accessCodeBytes); otp.ConfigureHotp(Slot.LongPress) .UseKey(hmacKey) .SetNewAccessCode(accessCode) .Execute(); } ### Example: modify a slot access code To modify a slot's access code, you must provide the current access code with [UseCurrentAccessCode()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.OperationBase-1.html#Yubico_YubiKey_Otp_Operations_OperationBase_1_UseCurrentAccessCode_Yubico_YubiKey_Otp_SlotAccessCode_) followed by the new access code with `SetNewAccessCode()` during a slot configuration operation. In this example, we are reconfiguring the long press slot with a new access code via the `UpdateSlot()` method. `UpdateSlot()` will not modify the slot's cryptographic configuration. However, it will revert a number of other slot settings (such as `SetAppendCarriageReturn()`) to their default states unless otherwise specified during the operation. using (OtpSession otp = new OtpSession(yubiKey)) { // Example current slot access code. ReadOnlyMemory currentAccessCodeBytes = new byte[SlotAccessCode.MaxAccessCodeLength] { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, }; SlotAccessCode currentAccessCode = new SlotAccessCode(currentAccessCodeBytes); // Example new slot access code. ReadOnlyMemory newAccessCodeBytes = new byte[SlotAccessCode.MaxAccessCodeLength] { 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, }; SlotAccessCode newAccessCode = new SlotAccessCode(newAccessCodeBytes); otp.UpdateSlot(Slot.LongPress) .UseCurrentAccessCode(currentAccessCode) .SetNewAccessCode(newAccessCode) .Execute(); } ### Example: remove a slot access code If you want to remove a slot's access code during a configuration operation, you can either: * provide a new access code of all zeros with `SetNewAccessCode()`, or * skip the `SetNewAccessCode()` call entirely ##### Note A 6-byte access code of zeros (0x00) is the factory default state for each OTP slot. Once the access code is removed, you do not need to call `UseCurrentAccessCode()` with subsequent configuration operations. In this example, we are effectively removing the access code from the long press slot by providing a new code of all zeros during the `UpdateSlot()` operation. `UpdateSlot()` will not modify the slot's cryptographic configuration. However, it will revert a number of other slot settings (such as `SetAppendCarriageReturn()`) to their default states unless otherwise specified during the operation. using (OtpSession otp = new OtpSession(yubiKey)) { // Example current access code. ReadOnlyMemory currentAccessCodeBytes = new byte[SlotAccessCode.MaxAccessCodeLength] { 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, }; SlotAccessCode currentAccessCode = new SlotAccessCode(currentAccessCodeBytes); // New access code of all zeros. ReadOnlyMemory newAccessCodeBytes = new byte[SlotAccessCode.MaxAccessCodeLength] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; SlotAccessCode newAccessCode = new SlotAccessCode(newAccessCodeBytes); otp.UpdateSlot(Slot.LongPress) .UseCurrentAccessCode(currentAccessCode) .SetNewAccessCode(newAccessCode) .Execute(); } ### Example: provide a slot access code during a configuration operation Once a slot has been configured with an access code, you must provide that access code with `UseCurrentAccessCode()` when performing a configuration operation on that slot. To retain the access code, you must also call `SetNewAccessCode()` and provide the same access code. If you do not call `SetNewAccessCode()`, the access code will be removed. ##### Note If a slot does not have an access code, providing any 6-byte code with `UseCurrentAccessCode()` during a configuration operation will succeed. In this example, we are reconfiguring an access code-protected long press slot with a new Yubico OTP credential. The access code is carried over to the new slot configuration by the `SetNewAccessCode(currentAccessCode)` call. using (OtpSession otp = new OtpSession(yubiKey)) { // Example current access code. ReadOnlyMemory currentAccessCodeBytes = new byte[SlotAccessCode.MaxAccessCodeLength] { 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, }; SlotAccessCode currentAccessCode = new SlotAccessCode(currentAccessCodeBytes); Memory privateId = new byte[ConfigureYubicoOtp.PrivateIdentifierSize]; Memory aesKey = new byte[ConfigureYubicoOtp.KeySize]; otp.ConfigureYubicoOtp(Slot.LongPress) .UseCurrentAccessCode(currentAccessCode) .SetNewAccessCode(currentAccessCode) .UseSerialNumberAsPublicId() .GeneratePrivateId(privateId) .GenerateKey(aesKey) .Execute(); } ### Example: deleting a slot configuration when an access code is present To delete a slot configuration that is protected with an access code, you must call [DeleteSlotConfiguration](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.OtpSession.html#Yubico_YubiKey_Otp_OtpSession_DeleteSlotConfiguration_Yubico_YubiKey_Otp_Slot_) and provide the current access code with `UseCurrentAccessCode()`. You cannot set a new access code during this operation. The `DeleteSlotConfiguration` operation will still succeed if you call `SetNewAccessCode()`, but the new access code will not be applied. using (OtpSession otp = new OtpSession(yubiKey)) { // Example current access code. ReadOnlyMemory currentAccessCodeBytes = new byte[SlotAccessCode.MaxAccessCodeLength] { 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, }; SlotAccessCode currentAccessCode = new SlotAccessCode(currentAccessCodeBytes); otp.DeleteSlotConfiguration(Slot.LongPress) .UseCurrentAccessCode(currentAccessCode) .Execute(); } ##### Note To delete a slot configuration that is not protected with an access code, use [DeleteSlot()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.OtpSession.html#Yubico_YubiKey_Otp_OtpSession_DeleteSlot_Yubico_YubiKey_Otp_Slot_) . [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-otp/how-to-slot-access-codes.md/#L1) --- # ##### Table of Contents Get protocol version -------------------- ### Inner command APDU info | CLA | INS | P1 | P2 | Lc | Data | Le | | --- | --- | --- | --- | --- | --- | --- | | 00 | 03 | 00 | 00 | (absent) | (absent) | (absent) | ### Response APDU info Total Length: _variable + 2_ Data Length: _variable_ | Data | SW1 | SW2 | | --- | --- | --- | | _data_ | 90 | 00 | The data is a byte array, where each byte is an ASCII character. Together they form a string describing the version. This is not NULL-terminated. For example, the return data can be the following six bytes. 0x55 32 46 5F 56 32 These are the ASCII values for "U2F\_V2" [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-u2f/apdu/get-protocol-version.md/#L1) --- # ##### Table of Contents Set legacy device config ------------------------ ### Full command APDU info | CLA | INS | P1 | P2 | Lc | Data | Le | | --- | --- | --- | --- | --- | --- | --- | | 00 | 40 | 00 | 00 | _data length_ | _encoded device info_ | (absent) | The data is encoded as four bytes byte[0] is the touch eject value along with the interfaces byte[1] is the challenge-response timeout byte[2] and byte[3] make up the auto eject timeout (little endian) byte[0] = 0x80 | interfaces if touch eject is true byte[0] = 0x00 | interfaces if touch eject is false the interfaces are 0x00 OTP 0x01 CCID 0x02 OTP | CCID 0x03 U2F 0x04 OTP | U2F 0x05 CCID | U2F 0x06 All (OTP | CCID | U2F) byte[3] and byte[4] make up the auto eject timeout it is little endian decimal 300 is 0x2C 01 decimal 555 is 0xFF 00 ### Response APDU info #### Response APDU for successful setting the device info Total Length: 2 Data Length: 0 | Data | SW1 | SW2 | | --- | --- | --- | | (no data) | 90 | 00 | #### Response APDU when sent to YubiKeys version 5 and later Total Length: 2 Data Length: 0 | Data | SW1 | SW2 | | --- | --- | --- | | (no data) | 69 | 00 | [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-u2f/apdu/set-legacy-device-config.md/#L1) --- # ##### Table of Contents Set the PIN to a new value -------------------------- ### Inner command APDU info | CLA | INS | P1 | P2 | Lc | Data | Le | | --- | --- | --- | --- | --- | --- | --- | | 00 | 44 | 00 | 00 | _data len_ | _data_ | (absent) | The data is encoded as new PIN length (one byte) || current PIN || new PIN If there is no current PIN, then the data will be encoded as new PIN length (one byte) || new PIN ### Response APDU info #### Response APDU for successful setting the new PIN Total Length: 2 Data Length: 0 | Data | SW1 | SW2 | | --- | --- | --- | | (no data) | 90 | 00 | #### Response APDU for current PIN incorrect Total Length: 2 Data Length: 0 | Data | SW1 | SW2 | | --- | --- | --- | | (no data) | 63 | C0 | #### Response APDU for blocked PIN Total Length: 2 Data Length: 0 | Data | SW1 | SW2 | | --- | --- | --- | | (no data) | 69 | 83 | #### Response APDU for new PIN invalid length Total Length: 2 Data Length: 0 | Data | SW1 | SW2 | | --- | --- | --- | | (no data) | 67 | 00 | #### Response APDU for PIN not supported If you try to set a U2F PIN on a non-FIPS YubiKey, a version 5 YubiKey (FIPS or non-FIPS), or a Security Key Series YubiKey, this is the response. Total Length: 2 Data Length: 0 | Data | SW1 | SW2 | | --- | --- | --- | | (no data) | 6D | 00 | [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-u2f/apdu/set-pin.md/#L1) --- # ##### Table of Contents Verify the PIN -------------- ### Inner command APDU info | CLA | INS | P1 | P2 | Lc | Data | Le | | --- | --- | --- | --- | --- | --- | --- | | 00 | 43 | 00 | 00 | _data len_ | _data_ | (absent) | The data is the PIN itself, there is no further encoding. ### Response APDU info #### Response APDU for successfully verifying PIN Total Length: 2 Data Length: 0 | Data | SW1 | SW2 | | --- | --- | --- | | (no data) | 90 | 00 | #### Response APDU for an incorrect PIN Total Length: 2 Data Length: 0 | Data | SW1 | SW2 | | --- | --- | --- | | (no data) | 63 | C0 | [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-u2f/apdu/verify-pin.md/#L1) --- # ##### Table of Contents Authenticate the YubiKey to a relying party ------------------------------------------- ### Inner command APDU info | CLA | INS | P1 | P2 | Lc | Data | Le | | --- | --- | --- | --- | --- | --- | --- | | 00 | 02 | _control byte_ | 00 | _length_ | _data_ | (absent) | The control byte is either `03` (enforce user presence), `07` (check only), or `08` (don't enforce user presence). The data is challenge parameter || application parameter || key handle length || key handle Where the challenge parameter is the client data hash and the application parameter is the hash of the origin data. Each is a SHA-256 message digest so each is 32 byte long. The key handle length is one byte. ### Response APDU info #### Response APDU for successful authentication Total Length: 2 Data Length: 0 | Data | SW1 | SW2 | | --- | --- | --- | | _encoded response_ | 90 | 00 | where the encoded response is user presence || counter || signature #### Response APDU for user presence required Total Length: 2 Data Length: 0 | Data | SW1 | SW2 | | --- | --- | --- | | (no data) | 69 | 85 | #### Response APDU for invalid key handle Total Length: 2 Data Length: 0 | Data | SW1 | SW2 | | --- | --- | --- | | (no data) | 6A | 80 | #### Response APDU for incorrect data length. Total Length: 2 Data Length: 0 | Data | SW1 | SW2 | | --- | --- | --- | | (no data) | 67 | 00 | [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-u2f/apdu/authenticate.md/#L1) --- # ##### Table of Contents Verify FIPS mode ---------------- ### Inner command APDU info | CLA | INS | P1 | P2 | Lc | Data | Le | | --- | --- | --- | --- | --- | --- | --- | | 00 | 46 | 00 | 00 | (absent) | (absent) | (absent) | ### Response APDU info #### Response APDU for FIPS mode (true) Total Length: 2 Data Length: 0 | Data | SW1 | SW2 | | --- | --- | --- | | (no data) | 90 | 00 | #### Response APDU for not FIPS mode (false) Total Length: 2 Data Length: 0 | Data | SW1 | SW2 | | --- | --- | --- | | (no data) | 6A | 81 | #### Response APDU for a device that cannot be set to FIPS mode Total Length: 2 Data Length: 0 | Data | SW1 | SW2 | | --- | --- | --- | | (no data) | 6D | 00 | [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-u2f/apdu/verify-fips.md/#L1) --- # How to program a slot with an OATH HOTP credential ##### Table of Contents How to program a slot with an OATH HOTP credential ================================================== To configure a [slot](https://docs.yubico.com/yesdk/users-manual/application-otp/slots.html) with an [OATH HOTP credential](https://docs.yubico.com/yesdk/users-manual/application-otp/hotp.html) , you will use a [ConfigureHotp](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.ConfigureHotp.html) instance. It is instantiated by calling the factory method of the same name ([ConfigureHotp()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.OtpSession.html#Yubico_YubiKey_Otp_OtpSession_ConfigureHotp_Yubico_YubiKey_Otp_Slot_) ) on your [OtpSession](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.OtpSession.html) instance. The properties of the HOTP credential you wish to set are specified by calling their respective methods on your `ConfigureHotp` instance. ConfigureHotp example --------------------- Before running any of the code provided below, make sure you have already connected to a particular YubiKey on your host device via the [YubiKeyDevice](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.YubiKeyDevice.html) class. To select the first available YubiKey connected to your host, use: IEnumerable yubiKeyList = YubiKeyDevice.FindAll(); var yubiKey = yubiKeyList.First(); ### Configure a slot with a provided secret key or a randomly generated key When calling `ConfigureHotp()`, you must either provide a secret key for the credential with [UseKey()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.ConfigureHotp.html#Yubico_YubiKey_Otp_Operations_ConfigureHotp_UseKey_System_ReadOnlyMemory_System_Byte__) or generate one randomly with [GenerateKey()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.ConfigureHotp.html#Yubico_YubiKey_Otp_Operations_ConfigureHotp_GenerateKey_System_Memory_System_Byte__) . The keys must be equal to the length of [HmacKeySize](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.ConfigureHotp.html#Yubico_YubiKey_Otp_Operations_ConfigureHotp_HmacKeySize) (20 bytes). To configure the [LongPress](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Slot.html#Yubico_YubiKey_Otp_Slot_LongPress) slot with an HOTP using a provided secret key ( which contains all 0s in this example), use: using (OtpSession otp = new OtpSession(yubiKey)) { ReadOnlyMemory hmacKey = new byte[ConfigureHotp.HmacKeySize] {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; otp.ConfigureHotp(Slot.LongPress) .UseKey(hmacKey) .Execute(); } To configure the `LongPress` slot with an HOTP using a randomly generated secret key, use: using (OtpSession otp = new OtpSession(yubiKey)) { Memory hmacKey = new byte[ConfigureHotp.HmacKeySize]; otp.ConfigureHotp(Slot.LongPress) .GenerateKey(hmacKey) .Execute(); } The API does not own the object where secrets are stored. Therefore, you must still provide the place to put the generated information (which is `hmacKey` in this example). Once you have done what is needed with the data, clear the memory where it is located. ### Set the initial moving factor and/or generate 8-digit HOTPs You may optionally set the initial moving factor (the counter) with [UseInitialMovingFactor()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.ConfigureHotp.html#Yubico_YubiKey_Otp_Operations_ConfigureHotp_UseInitialMovingFactor_System_Int32_) . If you do not call this method, the counter will be set to 0 by default. ##### Note `UseInitialMovingFactor()` must be given an integer between 0 and 0xffff0 (1,048,560) that is divisible by 0x10 ( 16), otherwise an exception will be thrown. `ConfigureHotp()` will configure a slot to generate 6-digit HOTPs by default. If you would like to generate 8-digit HOTPs, you must call [Use8Digits()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.ConfigureHotp.html#Yubico_YubiKey_Otp_Operations_ConfigureHotp_Use8Digits_System_Boolean_) during configuration. To set the initial moving factor to 16 and generate 8-digit HOTPs (with a randomly generated secret key), run the following: using (OtpSession otp = new OtpSession(yubiKey)) { Memory hmacKey = new byte[ConfigureHotp.HmacKeySize]; otp.ConfigureHotp(Slot.LongPress) .UseInitialMovingFactor(16) .GenerateKey(hmacKey) .Use8Digits() .Execute(); } Slot reconfiguration and access codes ------------------------------------- If a slot is protected by an access code and you wish to reconfigure it with an OATH HOTP credential, you must provide that access code with `UseCurrentAccessCode()` during the `ConfigureHotp()` operation. Otherwise, the operation will fail and throw the following exception: `System.InvalidOperationException has been thrown. YubiKey Operation Failed. [Warning, state of non-volatile memory is unchanged.]` For more information on slot access codes, please see [How to set, reset, remove, and use slot access codes](https://docs.yubico.com/yesdk/users-manual/application-otp/how-to-slot-access-codes.html) . Additional settings ------------------- The following additional (optional) settings can be applied during configuration: * [AppendCarriageReturn()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.ConfigureHotp.html#Yubico_YubiKey_Otp_Operations_ConfigureHotp_AppendCarriageReturn_System_Boolean_) * [AppendDelayToFixed()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.ConfigureHotp.html#Yubico_YubiKey_Otp_Operations_ConfigureHotp_AppendDelayToFixed_System_Boolean_) * [AppendDelayToOtp()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.ConfigureHotp.html#Yubico_YubiKey_Otp_Operations_ConfigureHotp_AppendDelayToOtp_System_Boolean_) * [AppendTabToFixed()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.ConfigureHotp.html#Yubico_YubiKey_Otp_Operations_ConfigureHotp_AppendTabToFixed_System_Boolean_) * [SendReferenceString()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.ConfigureHotp.html#Yubico_YubiKey_Otp_Operations_ConfigureHotp_SendReferenceString_System_Boolean_) * [SendTabFirst()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.ConfigureHotp.html#Yubico_YubiKey_Otp_Operations_ConfigureHotp_SendTabFirst_System_Boolean_) * [SetAllowUpdate()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.ConfigureHotp.html#Yubico_YubiKey_Otp_Operations_ConfigureHotp_SetAllowUpdate_System_Boolean_) * [Use10msPacing()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.ConfigureHotp.html#Yubico_YubiKey_Otp_Operations_ConfigureHotp_Use10msPacing_System_Boolean_) * [Use20msPacing()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.ConfigureHotp.html#Yubico_YubiKey_Otp_Operations_ConfigureHotp_Use20msPacing_System_Boolean_) * [UseFastTrigger()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.ConfigureHotp.html#Yubico_YubiKey_Otp_Operations_ConfigureHotp_UseFastTrigger_System_Boolean_) * [UseNumericKeypad()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.ConfigureHotp.html#Yubico_YubiKey_Otp_Operations_ConfigureHotp_UseNumericKeypad_System_Boolean_) The OATH HOTP does not have a fixed part, but you can still use `AppendDelayToFixed()` and `AppendTabToFixed()`. These will simply add a delay or send a tab prior to the HOTP, respectively. With the exception of `SendReferenceString()`, these settings can also be toggled after HOTP configuration by calling [UpdateSlot()](https://docs.yubico.com/yesdk/users-manual/application-otp/how-to-update-slot-settings.html) . ##### Note If you call `SetAllowUpdate(false)` during the inital configuration, you will not be able to update these settings with `UpdateSlot()` (the SDK will throw an exception). This can only be undone by reconfiguring the slot with `ConfigureHotp()`. It is not necessary to call `SetAllowUpdate(true)` during configuration because updates are allowed by default. [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-otp/how-to-program-an-hotp-credential.md/#L1) --- # ##### Table of Contents Register the YubiKey with a relying party ----------------------------------------- ### Inner command APDU info | CLA | INS | P1 | P2 | Lc | Data | Le | | --- | --- | --- | --- | --- | --- | --- | | 00 | 01 | 00 | 00 | 64 | _data_ | (absent) | The data is challenge parameter || application parameter Where the challenge parameter is the client data hash and the application parameter is the hash of the origin data. Each is a SHA-256 message digest so each is 32 byte long. ### Response APDU info #### Response APDU for successful registration Total Length: 2 Data Length: 0 | Data | SW1 | SW2 | | --- | --- | --- | | _encoded response_ | 90 | 00 | where the encoded response is 05 || public key || key handle length || key handle || cert || signature) #### Response APDU for PIN required Total Length: 2 Data Length: 0 | Data | SW1 | SW2 | | --- | --- | --- | | (no data) | 63 | C0 | #### Response APDU for blocked PIN Total Length: 2 Data Length: 0 | Data | SW1 | SW2 | | --- | --- | --- | | (no data) | 69 | 83 | #### Response APDU for touch required Total Length: 2 Data Length: 0 | Data | SW1 | SW2 | | --- | --- | --- | | (no data) | 69 | 85 | #### Response APDU for incorrect data length Total Length: 2 Data Length: 0 | Data | SW1 | SW2 | | --- | --- | --- | | (no data) | 67 | 00 | [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-u2f/apdu/register.md/#L1) --- # ##### Table of Contents Reset the FIDO U2F application ------------------------------ ### Inner command APDU info | CLA | INS | P1 | P2 | Lc | Data | Le | | --- | --- | --- | --- | --- | --- | --- | | 00 | 45 | 00 | 00 | (absent) | (absent) | (absent) | ### Response APDU info #### Response APDU for a successful reset Total Length: 2 Data Length: 0 | Data | SW1 | SW2 | | --- | --- | --- | | (no data) | 90 | 00 | #### Response APDU when the YubiKey is not reset Total Length: 2 Data Length: 0 | Data | SW1 | SW2 | | --- | --- | --- | | (no data) | 69 | 86 | [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-u2f/apdu/reset.md/#L1) --- # How to send a challenge to a YubiKey and receive a response code ##### Table of Contents How to send a challenge to a YubiKey and receive a response code ================================================================ Once a YubiKey's [slot](https://docs.yubico.com/yesdk/users-manual/application-otp/slots.html) has been [programmed with a challenge-response credential](https://docs.yubico.com/yesdk/users-manual/application-otp/how-to-program-a-challenge-response-credential.html) , you can send a [challenge](https://docs.yubico.com/yesdk/users-manual/application-otp/challenge-response.html) to that key and receive its response via a [CalculateChallengeResponse](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.CalculateChallengeResponse.html) instance. It is instantiated by calling the factory method of the same name on your [OtpSession](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.OtpSession.html) instance. You can send two types of challenges to a YubiKey: * an application-specified byte array (Yubico OTP and HMAC-SHA1) * the current Unix time (HMAC-SHA1 configurations only) The challenge type and size must align with the type of credential that the YubiKey was programmed with, otherwise an exception will be thrown. For HMAC-SHA1 challenge-response, the YubiKey will digest the challenge with the HMAC-SHA1 credential that it was programmed with. The resulting hash value can then be compared to the hash value produced by the validation server via the HMAC-SHA1 algorithm. For Yubico OTP challenge-response, the YubiKey will encrypt the challenge using its Yubico OTP credential, producing a Yubico OTP (as a byte array). This OTP can then be decrypted by the validation server with the credential's secret key. Response types -------------- The response from a YubiKey can be received via one of three methods: 1. [GetCode()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.CalculateChallengeResponse.html#Yubico_YubiKey_Otp_Operations_CalculateChallengeResponse_GetCode_System_Int32_) : returns a string object containing [six](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.CalculateChallengeResponse.html#Yubico_YubiKey_Otp_Operations_CalculateChallengeResponse_MinOtpDigits) to [ten](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.CalculateChallengeResponse.html#Yubico_YubiKey_Otp_Operations_CalculateChallengeResponse_MaxOtpDigits) numeric digits. A 6-digit code will be returned by default unless a larger number is specified when calling this method (for example, `GetCode(8)`). 2. [GetDataBytes()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.CalculateChallengeResponse.html#Yubico_YubiKey_Otp_Operations_CalculateChallengeResponse_GetDataBytes) : returns a byte array. 3. [GetDataInt()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.CalculateChallengeResponse.html#Yubico_YubiKey_Otp_Operations_CalculateChallengeResponse_GetDataInt) : returns a single 10-digit, 32-bit integer. The integer returned will represent the same code as `GetCode(10)`. Any of these response methods can be used for HMAC-SHA1 challenges. However, `GetDataBytes()` is the only compatible method for Yubico OTP challenges. Touch ----- An important consideration when calculating a challenge-response code is that you must handle the possibility that the key was programmed to require the user to touch the YubiKey button in order to execute a challenge-response operation. Although your program doesn’t have to process the button-touch, you do need to alert the user to touch the button. This is handled by calling the [UseTouchNotifier()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.CalculateChallengeResponse.html#Yubico_YubiKey_Otp_Operations_CalculateChallengeResponse_UseTouchNotifier_System_Action_) method, which takes an Action delegate as a parameter. When the YubiKey requires a touch, the SDK spawns your handler as a Task. There are two important considerations: 1. Your handler executes on a different thread. This means that you should not try to access the YubiKey from that thread — the handler is strictly for alerting the user. If you have a GUI app, it must marshal itself to the proper thread. 2. Your handler is executed asynchronously. The SDK does not wait for your handler to execute, and it doesn’t care when or if it completes. Settings and quirks ------------------- Regardless of the challenge type, you must call [UseYubiOtp()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.CalculateChallengeResponse.html#Yubico_YubiKey_Otp_Operations_CalculateChallengeResponse_UseYubiOtp_System_Boolean_) when sending a challenge with `CalculateChallengeResponse()` Specifically, call `UseYubiOtp(false)` for HMAC-SHA1 challenges or `UseYubiOtp(true)` for Yubico OTP challenges. There is no default setting; an exception will occur if you do not call `UseYubiOtp()`. For Yubico OTP challenge-response, the challenge must be 6 bytes long ([YubicoOtpChallengeSize](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.CalculateChallengeResponse.html#Yubico_YubiKey_Otp_Operations_CalculateChallengeResponse_YubicoOtpChallengeSize) ). For HMAC SHA-1 challenge-response, the application-specified challenge must be 64 bytes long ([MaxHmacChallengeSize](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.CalculateChallengeResponse.html#Yubico_YubiKey_Otp_Operations_CalculateChallengeResponse_MaxHmacChallengeSize) ) unless the YubiKey was previously configured with [UseSmallChallenge()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.ConfigureChallengeResponse.html#Yubico_YubiKey_Otp_Operations_ConfigureChallengeResponse_UseSmallChallenge_System_Boolean_) . Additionally, for time-based HMAC-SHA1 challenges sent with [UseTotp()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.CalculateChallengeResponse.html#Yubico_YubiKey_Otp_Operations_CalculateChallengeResponse_UseTotp) , you can set the time period that the response is valid for via [WithPeriod()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.CalculateChallengeResponse.html#Yubico_YubiKey_Otp_Operations_CalculateChallengeResponse_WithPeriod_System_Int32_) (the default is 30 seconds). CalculateChallengeResponse() examples ------------------------------------- Before running any of the code provided below, make sure you have already connected to a particular YubiKey on your host device via the [YubiKeyDevice](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.YubiKeyDevice.html) class. To select the first available YubiKey connected to your host, use: IEnumerable yubiKeyList = YubiKeyDevice.FindAll(); var yubiKey = yubiKeyList.First(); ### HMAC-SHA1 challenge-response example In this example, we send an HMAC-SHA1 challenge (`hmacChal`) to the short press slot of the YubiKey with [UseChallenge()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.CalculateChallengeResponse.html#Yubico_YubiKey_Otp_Operations_CalculateChallengeResponse_UseChallenge_System_Byte___) and get the response as a string object containing eight numeric digits via `GetCode()`. In addition, we use [UseTouchNotifier()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.CalculateChallengeResponse.html#Yubico_YubiKey_Otp_Operations_CalculateChallengeResponse_UseTouchNotifier_System_Action_) to tell the user to touch the YubiKey through a message printed to the console. The YubiKey's short press slot must be configured with an HMAC-SHA1 credential for this operation to succeed. using (OtpSession otp = new OtpSession(yubiKey)) { // The challenge, hmacChal, was set elsewhere. string result = otp.CalculateChallengeResponse(Slot.ShortPress) .UseChallenge(hmacChal) .UseYubiOtp(false) .UseTouchNotifier(() => Console.WriteLine("Touch the key.")) .GetCode(8); } ### Yubico OTP challenge-response example In this example, we send a Yubico OTP challenge (`yOtpChal`) to the key with `UseChallenge()` and get the response as a byte array via `GetDataBytes()`. This byte array is then converted to a string of [ModHex](https://docs.yubico.com/yesdk/users-manual/application-otp/modhex.html) characters via [ModHex.EncodeBytes()](https://docs.yubico.com/yesdk/core-api/Yubico.Core.Buffers.ModHex.html#Yubico_Core_Buffers_ModHex_EncodeBytes_System_ReadOnlySpan_System_Byte__System_Span_System_Char__) . The YubiKey's short press slot must be configured with a Yubico OTP credential for this operation to succeed. using (OtpSession otp = new OtpSession(yubiKey)) { // The challenge, yOtpChal, was set elsewhere. ReadOnlyMemory resp = otp.CalculateChallengeResponse(Slot.ShortPress) .UseChallenge(yOtpChal) .UseYubiOtp(true) .UseTouchNotifier(() => Console.WriteLine("Touch the key.")) .GetDataBytes(); string result = ModHex.EncodeBytes(resp.Span); } ### Time-based HMAC-SHA1 challenge-response example In this final example, we send a time-based challenge to the long press slot of the key with [UseTotp()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.CalculateChallengeResponse.html#Yubico_YubiKey_Otp_Operations_CalculateChallengeResponse_UseTotp) and get the response from the YubiKey as a single 32-bit integer via `GetDataInt()`. The YubiKey's long press slot must be configured with an HMAC-SHA1 credential for this operation to succeed. using (OtpSession otp = new OtpSession(yubiKey)) { int result = otp.CalculateChallengeResponse(Slot.LongPress) .UseTotp() .UseYubiOtp(false) .UseTouchNotifier(() => Console.WriteLine("Touch the key.")) .GetDataInt(); } [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-otp/how-to-calculate-a-challenge-response-code.md/#L1) --- # Slots ##### Table of Contents Slots ===== The OTP application on the YubiKey contains two configurable slots: the "long press" slot and the "short press" slot. Each slot may be programmed with one of the following configurations: * [Yubico OTP](https://docs.yubico.com/yesdk/users-manual/application-otp/yubico-otp.html) * [Initiative for Open Authentication HMAC-based OTP (OATH HOTP)](https://docs.yubico.com/yesdk/users-manual/application-otp/hotp.html) * [Static password](https://docs.yubico.com/yesdk/users-manual/application-otp/static-password.html) * [Challenge-response (using the HMAC-SHA1 or Yubico OTP algorithms)](https://docs.yubico.com/yesdk/users-manual/application-otp/challenge-response.html) Slot activation --------------- The slots are activated during authentication. Activation results in the generation and/or submission of a password or challenge-response code from the YubiKey to the authenticating party through the use of a [virtual keyboard](https://docs.yubico.com/yesdk/users-manual/application-otp/hid.html) (Yubico OTP, OATH HOTP, static password) or an API call (challenge-response). Only one slot may be activated at a time. Slots configured with a Yubico OTP, OATH HOTP, or static password are activated by touching the YubiKey. The duration of touch determines which slot is used. The first slot ([ShortPress](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Slot.html#Yubico_YubiKey_Otp_Slot_ShortPress) slot) is activated when the YubiKey is touched for 1 - 2.5 seconds. The second slot ([LongPress](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Slot.html#Yubico_YubiKey_Otp_Slot_LongPress) slot) is activated when the YubiKey is touched for 3 - 5 seconds. Challenge-response authentication is automatically initiated via an API call. However, challenge-response configurations can be programmed to require a user to touch the YubiKey in order to validate user presence. In this case, the cryptographic operation will be blocked until the YubiKey is touched (the duration of touch does not matter). If touch is not required, the cryptographic operation will proceed automatically. NFC-compatible YubiKeys also contain an [NDEF](https://docs.yubico.com/yesdk/users-manual/application-otp/ndef.html) tag that can be configured to point to one of the slots. When the YubiKey is scanned by an NFC reader, the slot that is pointed to by the NDEF tag will activate, causing the generation of an OTP. ##### Note NDEF tags only work with Yubico OTPs and OATH HOTPs. Slot properties --------------- The OTP application slots have the following properties: * Each slot may only be programmed with one configuration. * Only one slot may be activated at a time. * Slots can be [pointed to by an NDEF tag](https://docs.yubico.com/yesdk/users-manual/application-otp/how-to-configure-ndef.html) . * No data is shared between slots. * Slots can be protected from reconfiguration with an [access code](https://docs.yubico.com/yesdk/users-manual/application-otp/how-to-slot-access-codes.html) . * Slot configurations can be [deleted](https://docs.yubico.com/yesdk/users-manual/application-otp/how-to-delete-a-slot-configuration.html) . * Slot states can be [retrieved](https://docs.yubico.com/yesdk/users-manual/application-otp/how-to-retrieve-slot-status.html) . * Slot configurations can be [swapped](https://docs.yubico.com/yesdk/users-manual/application-otp/how-to-swap-slot-configs.html) . * Slot settings that aren't related to encryption can be [updated](https://docs.yubico.com/yesdk/users-manual/application-otp/how-to-update-slot-settings.html) without performing complete slot reconfiguration. [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-otp/slots.md/#L1) --- # PIV PIN-only mode ##### Table of Contents PIV PIN-only mode ================= There are a number of PIV operations that require management key authentication in order to execute, such as generating a key pair or importing a certificate (complete list [here](https://docs.yubico.com/yesdk/users-manual/application-piv/pin-puk-mgmt-key.html#operations-that-require-the-management-key) ). This is a requirement specified by the PIV standard. However, the management key is a Triple-DES key, which is 24 binary bytes, or (beginning with YubiKey 5.4.2) an AES key, which can be 16, 24, or 32 binary bytes. While it is easy for someone to enter a six to eight character PIN using a keyboard, how does one enter 16, 24, or 32 binary bytes? Can anyone remember that many binary bytes? And how does one enter them using a keyboard? As characters `'2' '9' 'A' ' 7' '0' 'B'` for `0x29 A7 0B` and so on? To help address these concerns, developers that build applications that use the PIV capabilities of a YubiKey can determine how the management key is managed. One possibility is to configure a YubiKey to be PIN-only. This means that any operation that requires the management key will only require the PIN. For example, normally to generate a new key pair, the application must supply the management key. But for a YubiKey configured for PIN-only, it is possible to generate a key pair with only the PIN provided. Note that this does not remove the management key, it simply means the SDK will be able to authenticate the management key if the PIN is correctly verified. The management key is still required, but now the user no longer needs to supply it. Note also that this is for the PIV PIN only. This has no effect on PINs or passwords of any other YubiKey application (OATH, FIDO, OpenPGP) While this improves usability, there is a tradeoff. When the SDK sets a YubiKey to PIN-only, it blocks the PUK as well (this is discussed below). This means it becomes much more likely a YubiKey becomes unusable if a PIN is forgotten. If you use the PIN-only feature, make sure everyone is aware that recovering from a lost PIN is likely impossible. In addition, this adds another way a YubiKey's PIV application can become unusable. This is discussed below in the section [Failures and recovery](https://docs.yubico.com/yesdk/users-manual/application-piv/pin-only.html#failures-and-recovery) . Management key authentication ----------------------------- When we say the management key must be authenticated in order to execute some operations, we mean that the management key must be authenticated in the same session. For example, suppose you want to import two certificates. using (var pivSession = new PivSession(yubiKey)) { pivSession.KeyCollector = SomeKeyCollector; pivSession.ImportCertificate(PivSlot.Authentication, someCert); pivSession.ImportCertificate(PivSlot.KeyManagement, anotherCert); } During the first call to `Import`, the SDK will call on the `KeyCollector` to return the management key. It will be authenticated and the certificate imported. The second time the `Import` is called, there is no need to collect and authenticate the management key, the first auth was good for the entire session. You could call Authenticate yourself. using (var pivSession = new PivSession(yubiKey)) { pivSession.KeyCollector = SomeKeyCollector; pivSession.AuthenticateManagementKey(); pivSession.ImportCertificate(PivSlot.Authentication, someCert); pivSession.ImportCertificate(PivSlot.KeyManagement, anotherCert); } During the first call to `Import`, there will be no need to collect and authenticate the management key, it is running in a session in which the management key has already been authenticated. As we will see below, there is a way to authenticate a management key in a session without collecting it from the KeyCollector or requiring the user to enter it. Only the PIN is required. In this way, any operation can be performed with only the PIN supplied during the session. PIN-only modes -------------- There are two PIN-only modes: PIN-protected and PIN-derived. Which should you use? PIN-protected. There is a section below listing the ways PIN-protected is the superior mode. Then why is PIN-derived offered? Backwards compatibility. This is a feature offered several years ago. It is possible that there are YubiKeys in use today that are set to PIN-derived and the SDK will support them. ### PIN-protected In this mode, the SDK stores the management key in the PRINTED data object. For background, see the User's Manual entries on [Data Objects](https://docs.yubico.com/yesdk/users-manual/application-piv/piv-objects.html) and [GET and PUT DATA](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#get-data) . In this mode, there is also information stored in ADMIN DATA. It is simply a bit indicating whether the YubiKey is configured for PIN-protected or not. If the SDK encounters an operation that requires management key authentication, it will collect the management key from the PRINTED data object and authenticate. That operation and any subsequent operation that requires management key authentication will work during that session. PIN verification is needed in order to retrieve the data from the PRINTED data object. That means the SDK can retrieve the management key only if the PIN has been verified. In this way the YubiKey can be PIN-only. Because the management key is stored in a data object that is protected by the PIN, we say this mode is PIN-protected. ### PIN-derived ##### Warning You should not use PIN-derived mode. This feature is provided only for backwards compatibility. In this mode, the SDK will generate a random salt. Then it will derive a management key from the PIN and salt. It will store the salt in the ADMIN DATA object. If management key authentication is needed, the SDK collects the ADMIN DATA and the PIN. It can then derive the management key and authenticate. Note that in this mode, if a PIN has already been verified, the SDK will need to retrieve the PIN again in order to derive the management key. This is because in normal PIN verification, the PIN is collected and verified, but not saved. If an application calls one of the Change PIN methods, the SDK will update the management key. However, if some other application has overwritten the contents of ADMIN DATA and/or PRINTED, the SDK will not be able to perform an update. It is a good idea to call the [PivSession.TryRecoverPinOnlyMode](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.PivSession.html#Yubico_YubiKey_Piv_PivSession_TryRecoverPinOnlyMode_) . method before changing the PIN. See the section below ["Failures and recovery"](https://docs.yubico.com/yesdk/users-manual/application-piv/pin-only.html#failures-and-recovery) for more information on possible failures and how to recover. ### PUK blocked The SDK code that implements these modes will also block the PUK. The reason is so that it is harder for a malicious administrator to take over a YubiKey. Generally the PIN and management key are owned by the end user, the YubiKey's owner. An administrator owns the PUK and can reset the PIN if the user forgets it. The malicious administrator can change the PIN and do damage, but without the management key the damage is limited. If a YubiKey is PIN-only and the PUK is not blocked, then the PUK's owner can change the PIN without knowing the PIN and therefore have control over the management key as well. This person now has complete control of the YubiKey. By blocking the PUK only the YubiKey's owner has control of the management key. This reduces usability because it means recovering from a lost PIN is virtually impossible. This is the tradeoff for improving usability with respect to the management key. Configure a YubiKey for PIN-only -------------------------------- A YubiKey must first be configured for PIN-only. With the SDK, call [PivSession.SetPinOnlyMode](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.PivSession.html#Yubico_YubiKey_Piv_PivSession_SetPinOnlyMode_) . That call requires you to specify the mode, `PinProtected`, `PinDerived`, or both. using (var pivSession = new PivSession(yubiKey)) { pivSession.KeyCollector = SomeKeyCollector; pivSession.SetPinOnlyMode(PivPinOnlyMode.PinProtected); } Remember, it is not a good idea to set a YubiKey to PIN-derived, either alone or with PIN-protected. That is, unless you have an older YubiKey that works with an older application that supports only PIN-derived, you should not set a YubiKey to either `PinDerived` or `PinDerived | PinProtected`. In order to set a YubiKey to PIN-only the management key must be authenticated. This is necessary even if it has already been authenticated. The `SetPinOnlyMode` method will try to authenticate using the default management key. If that works, there will be no call to the `KeyCollector` to retrieve the management key, the user will not have to enter it somehow. If the default key does not work, then the method will call the `KeyCollector`. It is also necessary to verify the PIN. If it has already been verified and the mode to set is `PinProtected`, the method won't collect the PIN again. But if the mode is `PinDerived` (or both), whether the PIN has been verified or not, this method will call on the `KeyCollector` to retrieve the PIN. If the mode is PIN-protected, and the current management key is the default, this method will generate a new random key, change the management key to this new value, and store it in PRINTED. If the management key is not the default, this method will collect the current key, it won't change it, and it will store it in PRINTED. If the mode is PIN-derived, this method will change the management key, whether it is the default or not. ### The management key's algorithm Even though the YubiKey is PIN-only, there still is a management key, it is either stored in PRINTED or derived from the PIN. Before version 5.4.2 of the YubiKey, a management key was Triple-DES. Beginning with 5.4.2, though, it is possible to use either a Triple-DES or an AES management key. For a YubiKey before 5.4.2, to set it PIN-only will mean the management key will be Triple-DES. But if the YubiKey is 5.4.2 or later, if you set it to PIN-only, you can specify the management key's algorithm as well. Suppose you specify the algorithm to be AES-128. If PIN-protected, the SDK will possibly generate a new, 16-byte, random key, change the management key to this new value, then store it in PRINTED. If PIN-derived, the SDK will generate a salt, derive a 16-byte value from that salt and the PIN, change the management key to this new value, then store the salt in ADMIN DATA. If you want to set a YubiKey to PIN-only, and want to use AES if possible, but Tiple-DES otherwise, then you will likely use code that looks something like this. using (var pivSession = new PivSession(yubiKey)) { pivSession.KeyCollector = SomeKeyCollector; PivAlgorithm mgmtKeyAlgorithm = yubiKey.HasFeature(YubiKeyFeature.PivAesManagementKey) ? PivAlgorithm.Aes128 : PivAlgorithm.TripleDes; pivSession.SetPinOnlyMode(PivPinOnlyMode.PinProtected, mgmtKeyAlgorithm); } Authenticating the management key in subsequent sessions -------------------------------------------------------- Once a YubiKey has been configured to PIN-only, the SDK will be able to authenticate the management key using the PIN only in each new `PivSession`. For example, using (var pivSession = new PivSession(yubiKey)) { pivSession.KeyCollector = SomeKeyCollector; pivSession.ImportCertificate(PivSlot.Authentication, someCert); } The `ImportCertificate` method requires management key authentication in order to execute. Under the covers it will call the `PivSession.AuthenticateManagementKey` method. That method will determine that the YubiKey is PIN-only, will request the PIN, obtain the management key, and authenticate. While the `KeyCollector` must obtain the PIN, it will not request the user supply the management key. Note that if a YubiKey is set for PIN-derived, each time the management key is authenticated, PIN entry is required. That is, even if the PIN has already been verified, in order to authenticate the management key, the PIN must be entered again. ADMIN DATA ---------- One of the many PIV data objects on the YubiKey is known as ADMIN DATA. See also the documentation on [GET DATA and PUT DATA](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#getvendordatatable) and [YubiKey-specific data](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#getvendordatatable) . This is where information about PIN-only is stored. It contains a field that indicates whether a YubiKey is configured for PIN-protected or not. It also contains a field that holds a salt. If there is no salt there, the YubiKey is not configured for PIN-derived. If there is a salt, then the YubiKey's management key is PIN-derived. Getting the PIN-only mode ------------------------- If you want to know to which mode a YubiKey is configured, call [PivSession.GetPinOnlyMode](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.PivSession.html#Yubico_YubiKey_Piv_PivSession_GetPinOnlyMode_) . This method looks at ADMIN DATA to determine the mode. It will return an enum ([PivPinOnlyMode](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.PivPinOnlyMode.html) ) indicating the mode. If it returns `PivPinOnlyMode.None`, then the YubiKey is not set to PIN-only. If the mode is `PivPinOnlyMode.PinProtected`, then the YubiKey has already been configured to PIN-protected. The enum is a bit field, so it is possible to get `PinProtected | PinDerived`, because it is possible to set a YubiKey to both PIN-protected and PIN-derived. It is also possible to get the value `PinProtectedUnavailable | PinDerivedUnavailable`. This means that it is not possible to set this YubiKey to PIN-only because some other application has written incompatible data to the storage locations. This might not be accurate, however, because the `GetPinOnlyMode` method returns a value based on the contents of ADMIN DATA only, it never looks inside PRINTED. The next section discusses failures, including `Unavailable`, and how to recover. Failures and recovery --------------------- The PIN-only system will break down if some application overwrites the contents of ADMIN DATA and/or PRINTED. It has been documented that one should never write data to these objects, and alternative storage locations are provided. It is very unlikely that any application will write to either of these objects, but it is possible. This section outlines what can go wrong and how to recover. First of all, the SDK is written to generally try something, and if that doesn't work, try something else. For example, when authenticating a management key, the code will check to see if the YubiKey is PIN-only. If it is not, the SDK will perform regular authentication. Or if the YubiKey has data indicating it is PIN-only, the SDK will try to authenticate using PIN-only, but if that does not work, it will again fall back and perform regular authentication. If nothing works, the SDK will throw an exception, or in the case of `TryAuthenticateManagementKey`, return `false`. This generally happens if one application sets a YubiKey to PIN-only, and another application overwrites the information in ADMIN DATA and/or PRINTED. If this happens, it is possible an application will no longer be able to perform PIV operations that require management key authentication, such as generating a key pair or importing a certificate, because the management key is lost. However, it is also possible that recovery from some of these failures is achievable, using the method [PivSession.TryRecoverPinOnlyMode](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.PivSession.html#Yubico_YubiKey_Piv_PivSession_TryRecoverPinOnlyMode_) . ### ADMIN DATA contents The data in ADMIN DATA is supposed to be encoded as follows. 53 len 80 L1 81 01 (optional) --bit field, PUK blocked, Mgmt Key stored in protected data-- 82 L2 (optional) --salt, 16 bytes-- 83 L3 (optional) --time the PIN was last updated-- Suppose some application stores some other information in there and it looks like this. 53 len A1 len --something-- If the mode was PIN-derived, then the salt has been lost and there is no way to recover. However, suppose the YubiKey had been configured for PIN-protected. The management key might still be in PRINTED, and it will be possible to recover. ### PRINTED contents If a YubiKey is configured for PIN-protected, then the contents of PRINTED will be 53 1C 88 1A 89 18 <24 bytes> If someone overwrites those contents, the management key is lost. In this case, you can call `GetPinOnlyMode`, and it might return `PinProtected`, yet authenticating the management key fails because the SDK cannot find the key data. The SDK will call on the `KeyCollector` to retrieve the key. ### The Recover method If you believe a YubiKey is configured for PIN-only, but `GetPinOnlyMode` returns `Unavailable` or the SDK is unable to authenticate the management key, call `TryRecoverPinOnlyMode`. This will read the contents of ADMIN DATA and PRINTED, and try to determine if it is still possible to authenticate using one of the PIN-only techniques. If so, it will authenticate the management key using that technique. The return of this method is the enum `PivPinOnlyMode`. This will report the result of the recovery effort. First of all, if you call the `Recover` method for a YubiKey that has not been configured for PIN-only, the return will likely be `None`. There is nothing to recover and the management key will not be authenticated. Or if the YubiKey has been configured for PIN-only and ADMIN DATA and PRINTED have not been overwritten, they contain the appropriate data, then the method will authenticate the management key and return the mode or modes. If recovery is needed, and if this method is able to recover, it will also overwrite the contents of ADMIN DATA and/or PRINTED. This means that your call will overwrite some other application's data. That is, some other application wrote that data to one or both of the data objects for a reason and is possibly dependent on the information currently in there. The `Recover` method will, if it is able to recover, remove that data and the other application will experience failures. Note that in order to set the objects ADMIN DATA and PRINTED, the management key must be authenticated. If the data in the two storage locations is such that the method just can't recover, it will not be able to set them and they will remain unchanged. This method will try to authenticate using the PIN-only methods, and if they fail, it will try the default management key, and if that fails, it will try to collect the management key using the `KeyCollector`. If it is able to authenticate using the default or the collected key, it will clear the contents of ADMIN DATA and PRINTED. To know the result of the recovery process, check the return value. * `None`: One possibility is that no data was found in ADMIN DATA and PRINTED. * `None`: Another possibility is that invalid data was found in ADMIN DATA and/or PRINTED, the management key was authenticated using the default key or the `KeyCollector`, and the storage locations were cleared of any data. * `PinProtected`: The method was able to find the management key in PRINTED and authenticate. ADMIN DATA is now set with the correct information (there will be no salt). * `PinDerived`: it was able to authenticate the management key using a value derived from the PIN and salt. PRINTED is now empty, ADMIN DATA indicates the YubiKey is PIN-derived (with the correct sale) but not PIN-protected. * `PinProtected | PinDerived`: The method was able to find the management key in PRINTED and authenticate. The ADMIN DATA contained a salt and the key derived was the same one found in PRINTED. Both are set with the correct information. * `PinProtectedUnavailable`: ADMIN DATA had indicated the YubiKey was PIN-protected but not PIN-derived. The data in PRINTED was incorrect, the management key is not authenticated. The data in ADMIN DATA and PRINTED was not changed. * `PinDerivedUnavailable`: ADMIN DATA had indicated the YubiKey was PIN-derived, but the key derived from the PIN and salt did not authenticate. There was no data in PRINTED. The method could not authenticate using the default key or the `KeyCollector`. The contents were not changed. * `PinProtectedUnavailable | PinDerivedUnavailable`: The information in both was incorrect, the management key was not authenticated, the contents were not changed. PIN-protected vs. PIN-derived ----------------------------- If you want to set a YubiKey to PIN-only and need to decide which mode to use, here are the reasons you will want to use PIN-protected. 1. PIN-protected is more secure 2. PIN-protected does not require entering the PIN as much (greater usability) There is only one reason to use PIN-derived. 1. The application calling on the SDK must be compatible with another existing application that can recognize only PIN-derived The SDK will be able to determine if an existing YubiKey is set to PIN-derived and automatically use it. That is, there is no need to set new YubiKeys to PIN-derived just because older YubiKeys exist set for this mode. Furthermore, it is possible to reset a YubiKey to PIN-protected if it is currently set to PIN-derived. Your application that calls on the SDK can check the mode of each YubiKey it encounters ([PivSession.GetPinOnlyMode](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.PivSession.html#Yubico_YubiKey_Piv_PivSession_GetPinOnlyMode_) ) and reset to PIN-protected mode only. [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-piv/pin-only.md/#L1) --- # How FIDO2 works ##### Table of Contents How FIDO2 works =============== At its foundation, FIDO2 is very similar to U2F. However, there are differences. For example: * In FIDO2 the messages between entities are much more complex with more information * In FIDO2 the PIN is encrypted before transmitting it to the authenticator * FIDO2 has mechanisms for biometric authenticators (e.g. "on-board" fingerprint readers) As with U2F, there are two main operations in FIDO2: * Make a credential (registration) * Get an assertion (authenticate) First, the user registers the YubiKey and ties it to a particular account. Second, when logging on, the user makes sure the appropriate YubiKey is inserted. During login, the YubiKey, browser, and authentication server will communicate and perform the steps necessary to authenticate. The user will likely need to tap the YubiKey in order to complete authentication. The entities involved --------------------- There are three components in FIDO2 * The authenticator (YubiKey) * The client (a browser, platform component, or application) * The relying party (verifies the authentication process) FIDO2 can only work when using clients that already have support. For example, suppose you have an online account with a bank which has added FIDO2 support. Now you try to log into that account using a Vivaldi browser on MacOS. That might not work because it is possible that browser does not support FIDO2. You can log in using Safari or Chrome, because they do have support. The client is, of course, the "medium" through which the authenticator and relying party communicate. However, the client also plays a role in verifying that the relying party is correct, not a fake or attacker. Make a credential ----------------- The goal of registration is for the authenticator to provide a public key to the relying party. This key is to be associated with an account. The client provides relying party data (RpIdHash) to the authenticator. This is data the authenticator will use during authentication. Later on, if the RpIdHash provided during authentication does not match the RpIdHash from registration, then the authenticator will return an error. In order to register, the relying party supplies a challenge, which the authenticator signs. That signature (an attestation statement), along with a certificate verifying the private key used (attestation certificate), is sent to the relying party. The relying party can verify the signature using the public key (verifying that the sender does indeed have access to the private key) and then verify the public key using the attestation certificate (which should chain to a known root). Generally, an authentication server will have a database of accounts, each entry containing a username and password info (not the password itself, but information that can be used to verify the password). With FIDO2, each entry will also contain a public key as well. Get assertion ------------- The goal of authentication is for the authenticator to send, to the relying party, a value that proves the authenticator is the one registered to the specified user. In addition, the authenticator, working with the client, can verify the current relying party (who the client is actually connected to) is the correct one. The relying party sends a challenge to the client. The client bundles this challenge with the relying party data (RpIdHash), and sends it to the authenticator. The authenticator looks in its storage for the private key associated with the specified relying party. If there is none, it cannot create an assertion, so returns an error. This happens when the client is connected to an attacker's site. If there is an entry for the given relying party, the authenticator will sign the challenge (and other data), and return this signature. The client passes the signture on to the relying party, which can verify the signature using the public key associated with the account. More details ------------ See the [FIDO2 Credentials](https://docs.yubico.com/yesdk/users-manual/application-fido2/fido2-credentials.html) doc for more details. [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-fido2/how-fido2-works.md/#L1) --- # How to program a slot with a Yubico OTP credential ##### Table of Contents How to program a slot with a Yubico OTP credential ================================================== To program a [slot](https://docs.yubico.com/yesdk/users-manual/application-otp/slots.html) with a [Yubico OTP](https://docs.yubico.com/yesdk/users-manual/application-otp/yubico-otp.html) credential, you will use a [ConfigureYubicoOtp](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.ConfigureYubicoOtp.html) instance. It is instantiated by calling the factory method of the same name on your [OtpSession](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.OtpSession.html) instance. First, a clarification of terms is needed. “Yubico OTP” is both an OTP credential type and a [challenge-response](https://docs.yubico.com/yesdk/users-manual/application-otp/challenge-response.html) algorithm. In this context, we are referring to the credential type. A Yubico OTP credential is touch-activated. When you touch the YubiKey, it will emit a binary challenge using [ModHex](https://docs.yubico.com/yesdk/users-manual/application-otp/modhex.html) characters. A Yubico OTP credential contains the following three parts, which must be set during instantiation: * Public ID The public ID is a prefix that is prepended to the actual challenge; it is not used to generate the challenge. The serial number of the YubiKey is often used to generate this ID. * Private ID The private ID is a six-byte value that is used as part of the algorithm to create a challenge and as a way to validate identity. * Key The key is a 16-byte AES key that is used as the primary secret for the credential. ConfigureYubicoOtp example -------------------------- You can configure the [ShortPress](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Slot.html#Yubico_YubiKey_Otp_Slot_ShortPress) slot of your YubiKey with a Yubico OTP credential as follows: using (OtpSession otp = new OtpSession(yKey)) { // privateId and aesKey are Memory references. otp.ConfigureYubicoOtp(Slot.ShortPress) .UseSerialNumberAsPublicId() .UsePrivateId(privateId) .UseKey(aesKey) .Execute(); } In this example, we’re configuring a Yubico OTP credential using the serial number of the YubiKey to generate the public ID and supplying an existing private ID and AES key. You can also generate a new private ID and AES key to use instead: using (OtpSession otp = new OtpSession(yKey)) { Memory privateId = new byte[ConfigureYubicoOtp.PrivateIdentifierSize]; Memory aesKey = new byte[ConfigureYubicoOtp.KeySize]; otp.ConfigureYubicoOtp(Slot.ShortPress) .UseSerialNumberAsPublicId() .GeneratePrivateId(privateId) .GenerateKey(aesKey) .Execute(); // Do whatever is needed with privateId and aesKey, and clear them. } The API does not own the object where secrets are stored. Because of this, you must still provide the place to put the generated information. Once you have done what is needed with the data, you should clear the memory where it is located. Slot reconfiguration and access codes ------------------------------------- If a slot is protected by an access code and you wish to reconfigure it with a Yubico OTP credential, you must provide that access code with `UseCurrentAccessCode()` during the `ConfigureYubicoOtp()` operation. Otherwise, the operation will fail and throw the following exception: `System.InvalidOperationException has been thrown. YubiKey Operation Failed. [Warning, state of non-volatile memory is unchanged.]` For more information on slot access codes, please see [How to set, reset, remove, and use slot access codes](https://docs.yubico.com/yesdk/users-manual/application-otp/how-to-slot-access-codes.html) . [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-otp/how-to-program-a-yubico-otp-credential.md/#L1) --- # The PIV PIN, PUK, and management key ##### Table of Contents The PIV PIN, PUK, and management key ==================================== Per the standard, there are three keys/secret values in PIV (Personal Identity Verification): * PIN (Personal Identification Number) * PUK (PIN Unblocking Key) * Management key The main purpose of the PIN is to authenticate the user for signing and decrypting, although there are other operations that need it as well. The standard specifies that it is a 6- to 8-byte value, each of the bytes an ASCII number ('0' to '9', which in ASCII is `0x30` to `0x39`). The YubiKey allows the PIN to be any ASCII character: numbers, letters (upper- and lower-case), and even non-alphanumeric characters such as !, %, or # (among others). The PUK is used to unblock the PIN (see the section below on [blocking](https://docs.yubico.com/yesdk/users-manual/application-piv/pin-puk-mgmt-key.html#blocking) ). The standard specifies that the PUK is to be an 8-byte value, with each of the bytes any binary value from `0x00` to `0xFF`. The YubiKey, however, will accept a PUK of 6 to 8 characters. For YubiKeys with firmware versions prior to 5.7, the key will accept any value in the `0x00` - `0xFF` range in the PUK. For YubiKeys with firmware version 5.7 and above, the key will only accept values in the `0x00` - `0x7F` range. Values from `0x80` - `0xFF` will be considered invalid by the key, and any attempt to change the PUK to a byte array containing one of these values will fail. These restrictions are due to the YubiKey's PUK length requirements: for firmware versions prior to 5.7, the YubiKey simply requires a PUK length of 6-8 bytes, but for firmware version 5.7 and above, that requirement has changed to 6-8 _Unicode code points_ in length. This is an important change because the byte representation (UTF-8 encoding) of a single code point can be 1-4 bytes in length, which means that a 6-byte PUK may be less than 6 code points. In order to accommodate keys of varying firmware versions, the SDK maintains a 6-8 byte length requirement when calling [PivSession.TryChangePuk](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.PivSession.html#Yubico_YubiKey_Piv_PivSession_TryChangePuk) or [Piv.Commands.ChangeReferenceDataCommand](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.Commands.ChangeReferenceDataCommand.html) . However, keys with firmware 5.7 and above will only accept values that represent single-byte code points, hence the restricted range of `0x00` - `0x7F` (the range of `0x80` - `0xFF` represents code points of two bytes in length). For additional information on Unicode, UTF-8, and the SDK, see the [FIDO2 documentation](https://docs.yubico.com/yesdk/users-manual/application-fido2/fido2-pin.html) . ##### Note If your application uses the keyboard to insert the PUK, you might limit the user to ASCII characters, regardless of a key's firmware version. The management key is used to authenticate the entity allowed to perform many YubiKey management operations, such as generating a key pair. On YubiKeys before version 5.4.2, it is a Triple-DES key, which means it is 24 bytes long. Beginning with 5.4.2, the management key can be an AES key, either 128, 192, or 256 bits (16, 24, or 32 bytes). The management key is binary (each byte is a value from 0x00 to 0xFF). If it is a Triple-DES key, the key data is 192 bits long, but because of the "parity bits", only 168 bits supply the key's strength. In addition, because of certain attacks on Triple-DES, the actual effective bit strength of a key is 112. The YubiKey is manufactured with the following default PIN, PUK, and management key values: * PIN: "123456" * PUK: "12345678" * Management Key: "010203040506070801020304050607080102030405060708" Note that the PIV standard specifies these default values. And while the management key value is consistent across YubiKeys, the management key _algorithm_ depends on a key's firmware version. For firmware 5.6 and earlier, the default management key algorithm is Triple-DES; for firmware 5.7 and later, the default algorithm is AES-192. Upon receipt of the YubiKey, it is a good idea to change the PIN, PUK, and management key from the default values. See [PivSession.TryChangePin](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.PivSession.html#Yubico_YubiKey_Piv_PivSession_TryChangePin_) , [PivSession.TryChangePuk](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.PivSession.html#Yubico_YubiKey_Piv_PivSession_TryChangePuk) , and [PivSession.TryChangeManagementKey](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.PivSession.html#Yubico_YubiKey_Piv_PivSession_TryChangeManagementKey_) . ### Entering binary data If your application takes PIN, PUK, and management key input from the user typing on a keyboard, how do they enter binary data? If the PIN is "stG83C" that's easy to enter at a keyboard. But if the PUK is 0x8F2B00CA716A, how does one type that at a keyboard? The byte 0x2B is '+', 0x71 is 'q' and 0x6A is 'j', but what about 0x8F, 0x00, and 0xCA? One solution is to simply limit your application's PUK to be only ASCII characters. Even though the standard allows any binary byte, you will allow only keyboard characters. This will likely be acceptable because there is a retry count, which limits the attacker's ability to launch a brute-force attack. But what about the management key? You could specify only keyboard characters there, 24 bytes and 24 keystrokes. But this is very problematic because this severely limits the number of possible Triple-DES keys, and there is no retry limit on the management key. The answer is to simply require the user enter the data as hex. For example, if the management key is the default (0x010203...), then the user enters "0102030405060708...". They enter 48 ASCII characters ('0' '1' '0' '2' ... which is 0x30 31 30 32 ...) but your application reads it as 24 bytes. But whatever you do, please document it. Don't simply put a box into the UI and say, "Enter PUK" or "Enter management key". Let the user know they must enter the data as hex values. Or if the PUK is limited to keyboard characters, let them know. Even for the PIN, you can document that the input can be letters, numbers, or even some set of special characters. Otherwise the user might enter something that is incorrect, get an error message ("invalid PUK" or "management key not 24 bytes") and have to figure it out through trial and error. Blocking -------- A PIN or PUK can be blocked. This happens when the wrong value is entered too many times in a row. How many is too many? Upon manufacture, the number (the "retry count") is 3 for both the PIN and PUK. It is possible to change the retry count using [Set PIN retries](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#set-pin-retries) . The retry count can be any number from 1 to 255 (inclusive). When a PIN is blocked, any operation that requires the PIN will not work, even if you supply the correct PIN. You can unblock the PIN using the PUK (PIN Unblocking Key) in the [PivSession.TryResetPin](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.PivSession.html#Yubico_YubiKey_Piv_PivSession_TryResetPin) method. If you try to reset the PIN using the PUK, and provide the wrong PUK its retry count times in a row, the PUK will be blocked. At that point, you cannot unblock the PIN, even if you supply the correct PUK. There is no way to unblock the PUK, not even with the management key. When both the PIN and PUK are blocked, there is not much useful work you can do with the YubiKey's PIV application. At this point, all you can do is reset the PIV application: [PivSession.Reset](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.PivSession.html#Yubico_YubiKey_Piv_PivSession_ResetApplication) . This deletes the keys in all PIV slots and resets the PIN, PUK, and management key to their defaults. Note that this has no effect on the other YubiKey applications (OTP, FIDO, etc.). ##### Note `PivSession.Reset()` cannot be used with YubiKey Bio Multi-protocol Edition (MPE) keys — use the [device-wide reset](https://docs.yubico.com/yesdk/users-manual/sdk-programming-guide/bio-mpe.html#resetting-a-yubikey-bio-mpe) instead. YubiKey Bio MPE keys also do not have PUKs, so it is not possible to unblock a blocked PIN. See [YubiKey Bio Multi-protocol Edition considerations and quirks](https://docs.yubico.com/yesdk/users-manual/sdk-programming-guide/bio-mpe.html#) for more information. The management key cannot be blocked. If an attacker wants to try to break your management key, they can try a brute-force attack (with a Triple-DES it is a modified brute-force attack), which means trying every possible key until "stumbling" onto the correct one. That will take thousands of years for a Triple-DES key and trillions of years with an AES key. Changing the retry counts ------------------------- The YubiKey is manufactured with a retry count of three for both the PIN and PUK. If you would like to change that, call the [Change retry counts](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.PivSession.html#Yubico_YubiKey_Piv_PivSession_ChangePinAndPukRetryCounts_) method. This call will change the retry counts for both the PIN and PUK. ##### Note You must change the retry counts of both the PIN and PUK. There is no way to change the retry count for only one secret. ##### Warning Changing the retry counts will also reset the PIN and PUK to their default values. Even if you do not reset the application or change the PIN and PUK, after changing the retry counts, the PIN will be "123456" and the PUK will be "12345678". The minimum retry count is one, and the maximum retry count is 255. A retry count of one means there are no retries. If the user enters the wrong PIN or PUK just once, the secret is blocked. Because changing the retry count will reset the PIN and PUK to their default values, it is a good idea to combine this operation with changing the PIN and PUK. That is, instead of three options or menu items of "change retry count", "change PIN", and "change PUK", your application could have one option or menu item that changes the PIN, PUK, and retry count all at once. Alternatively, your application could set the retry count once during user initiation, when the PIN, PUK, and management key are first changed from the default. Then never offer the option of changing the retry count again. Operations that require the management key ------------------------------------------ * [Put data](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#put-data) * [Generate a new key pair](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.PivSession.html#Yubico_YubiKey_Piv_PivSession_GenerateKeyPair_) * [Import a private key](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.PivSession.html#Yubico_YubiKey_Piv_PivSession_ImportPrivateKey_) * [Import a certificate](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.PivSession.html#Yubico_YubiKey_Piv_PivSession_ImportCertificate_) * [Change the retry counts](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.PivSession.html#Yubico_YubiKey_Piv_PivSession_ChangePinAndPukRetryCounts_) also requires the PIN * [Change the management key](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.PivSession.html#Yubico_YubiKey_Piv_PivSession_ChangeManagementKey_) Operations that require the PIN ------------------------------- * [Verify the PIN](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.PivSession.html#Yubico_YubiKey_Piv_PivSession_TryVerifyPin_) * [Change the PIN](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.PivSession.html#Yubico_YubiKey_Piv_PivSession_TryChangePin_) * [Change the retry counts](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.PivSession.html#Yubico_YubiKey_Piv_PivSession_ChangePinAndPukRetryCounts_) also requires the management key * [Sign](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.PivSession.html#Yubico_YubiKey_Piv_PivSession_Sign_) * [Decrypt](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.PivSession.html#Yubico_YubiKey_Piv_PivSession_Decrypt_) * [Key Agreement](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.PivSession.html#Yubico_YubiKey_Piv_PivSession_KeyAgree_) * Get data for some data objects: [Get data](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#get-data) Note that it is possible, on YubiKey 4.0 and later, to change the PIN policy of the sign and decrypt operations, so that the PIN is not required. See the user's manual entry on [Pin and touch policies](https://docs.yubico.com/yesdk/users-manual/application-piv/pin-touch-policies.html) . Operations that require the PUK ------------------------------- * [Change the PUK](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.PivSession.html#Yubico_YubiKey_Piv_PivSession_TryChangePuk_) * [Reset the PIN](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.PivSession.html#Yubico_YubiKey_Piv_PivSession_TryResetPin_) Examples -------- Suppose the "retry count" for the PIN is 4. You try to sign but enter the wrong PIN. The operation fails and the "remaining count" is decremented to 3. The retry count is still 4, but you have only 3 tries remaining. Try again with the correct PIN, the operation succeeds, and the remaining count is restored to 4. The PIN retry count (and remaining count) is 4, but you know you have forgotten the PIN, so you don't even try to verify it. You simply use the PUK to reset/unblock the PIN. This works, because it is not necessary for the remaining count to go to zero before you use the PUK to reset the PIN. You changed the PIN and PUK when you first got the YubiKey. Now, you decide you want to change the PIN again. This is certainly allowed, simply call the [Change Reference Data command](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#change-reference-data) . PIN only -------- It is possible to set a YubiKey to be PIN only. This means the YubiKey is configured to require he PIN only when performing operations, even those functions that normally require management key authentication. ##### Warning A YubiKey in PIN only mode is less secure than one that requires the management key. However, there are applications for which entering a management key is simply not possible, so this feature is offered. There are two ways to achieve this: PIN-protected and PIN-derived. It is possible to have both methods active for a YubiKey. ##### Warning PIN-derived mode is not secure. You should not use this technique. It is offered only for backwards compatibility. Yubico recommends that if you must set a YubiKey to PIN only, you set it to use only PIN-protected. ### Minidriver compatibility The Yubico minidriver will configure a YubiKey to PIN-protected mode. Hence, if you know that your application will be running alongside Microsoft Windows machines using the YubiKey Minidriver, you should strongly consider adding support for setting YubiKeys to PIN-protected mode. See the User's manual [entry on PIN-only](https://docs.yubico.com/yesdk/users-manual/application-piv/pin-only.html) . [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-piv/pin-puk-mgmt-key.md/#L1) --- # How to program a slot with a challenge-response credential ##### Table of Contents How to program a slot with a challenge-response credential ========================================================== To program a [slot](https://docs.yubico.com/yesdk/users-manual/application-otp/slots.html) with a [challenge-response](https://docs.yubico.com/yesdk/users-manual/application-otp/challenge-response.html) credential, you must use a [ConfigureChallengeResponse](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.ConfigureChallengeResponse.html) instance. It is instantiated by calling the factory method of the same name on your [OtpSession](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.OtpSession.html) instance. The challenge-response credential, unlike the other configurations, is passive. It only responds when it is queried with a challenge via [CalculateChallengeResponse()](https://docs.yubico.com/yesdk/users-manual/application-otp/how-to-calculate-a-challenge-response-code.html) . Slots can be programmed with one of the following types of credentials: * [HMAC-SHA1](https://datatracker.ietf.org/doc/html/rfc2104) * [Yubico OTP](https://docs.yubico.com/yesdk/users-manual/application-otp/yubico-otp.html) During a challenge-response operation, a slot programmed with an HMAC-SHA1 credential will digest the challenge with that credential via the HMAC-SHA1 algorithm, producing an HMAC-SHA1 hash value, which can be received by the application as a byte array or 6-10 digit numeric code. If the slot was programmed with a Yubico OTP credential, the key will encrypt the challenge with that credential via the Yubico OTP algorithm, producing a Yubico OTP (as a byte array). Algorithm selection and key sizes --------------------------------- When programming a slot with a credential, you must call either [UseYubiOtp()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.ConfigureChallengeResponse.html#Yubico_YubiKey_Otp_Operations_ConfigureChallengeResponse_UseYubiOtp) or [UseHmacSha1()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.ConfigureChallengeResponse.html#Yubico_YubiKey_Otp_Operations_ConfigureChallengeResponse_UseHmacSha1) to select the algorithm you'd like to use. In addition, a secret key must be provided via [UseKey()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.ConfigureChallengeResponse.html#Yubico_YubiKey_Otp_Operations_ConfigureChallengeResponse_UseKey_System_ReadOnlyMemory_System_Byte__) or generated randomly via [GenerateKey()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.ConfigureChallengeResponse.html#Yubico_YubiKey_Otp_Operations_ConfigureChallengeResponse_GenerateKey_System_Memory_System_Byte__) . The key must be [16 bytes](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.ConfigureChallengeResponse.html#Yubico_YubiKey_Otp_Operations_ConfigureChallengeResponse_YubiOtpKeySize) in size for Yubico OTP or [20 bytes](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.ConfigureChallengeResponse.html#Yubico_YubiKey_Otp_Operations_ConfigureChallengeResponse_HmacSha1KeySize) for HMAC-SHA1. ##### Note The secret key must also be provided to the validation server for the purposes of verifying response codes sent from the YubiKey during challenge-response operations. Short challenge mode for HMAC-SHA1 ---------------------------------- An HMAC-SHA1 challenge is 64 bytes by default. The YubiKey also supports a short challenge mode ([UseSmallChallenge()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.ConfigureChallengeResponse.html#Yubico_YubiKey_Otp_Operations_ConfigureChallengeResponse_UseSmallChallenge_System_Boolean_) ) where challenges, which are sent to a YubiKey with `CalculateChallengeResponse()`, can be configured to be less than 64 bytes. `UseSmallChallenge()` is included for compatibility with legacy systems whose implementations break data sets into multiple blocks, which often results in the last element being smaller than 64 bytes (which would change the result). Due to this truncation, it’s important to use the setting that will be expected by the consumer of the OTP code. ##### Note You can use challenges smaller than 64 bytes without setting the short challenge mode by padding the end of the challenge with zeros. Regardless, both sides of the operation must agree on the length of the challenge. Requiring touch --------------- When programming a slot with a Yubico OTP or HMAC-SHA1 challenge-response credential, you can also include a setting that requires the user to touch the YubiKey before the cryptographic operation can proceed during a challenge-response operation. Requiring touch improves security by ensuring that a user performs a physical operation. To enable this setting, add the [UseButton()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.ConfigureChallengeResponse.html#Yubico_YubiKey_Otp_Operations_ConfigureChallengeResponse_UseButton_System_Boolean_) method to your `ConfigureChallengeResponse()` operation. If a YubiKey has been configured to require a button touch, you must make sure to alert the user of this requirement during a challenge-response operation. This can be accomplished by calling the [UseTouchNotifier()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.CalculateChallengeResponse.html#Yubico_YubiKey_Otp_Operations_CalculateChallengeResponse_UseTouchNotifier_System_Action_) method when sending a challenge to a YubiKey via `CalculateChallengeResponse()`. ConfigureChallengeResponse examples ----------------------------------- Before running any of the code provided below, make sure you have already connected to a particular YubiKey on your host device via the [YubiKeyDevice](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.YubiKeyDevice.html) class. To select the first available YubiKey connected to your host, use: IEnumerable yubiKeyList = YubiKeyDevice.FindAll(); var yubiKey = yubiKeyList.First(); ### HMAC-SHA1 example The following code configures the [short press](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Slot.html#Yubico_YubiKey_Otp_Slot_ShortPress) slot with a challenge-response credential and a predefined secret key. This configuration uses the HMAC-SHA1 algorithm and requires the user to touch the button during a challenge-response operation. using (OtpSession otp = new OtpSession(yubiKey)) { // The secret key, hmacKey, was set elsewhere. otp.ConfigureChallengeResponse(Slot.ShortPress) .UseHmacSha1() .UseKey(hmacKey) .UseButton() .Execute(); } ### Yubico OTP example The following code configures the [long press](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Slot.html#Yubico_YubiKey_Otp_Slot_LongPress) slot with a challenge-response credential. This configuration uses the Yubico OTP algorithm and a randomly generated secret key. using (OtpSession otp = new OtpSession(yubiKey)) { //Don't forget to share the secret key with the validation server before clearing it from memory. Memory secretKey = new byte[ConfigureYubicoOtp.KeySize]; otp.ConfigureChallengeResponse(Slot.LongPress) .UseYubiOtp() .GenerateKey(secretKey) .Execute(); } Slot reconfiguration and access codes ------------------------------------- If a slot is protected by an access code and you wish to reconfigure it with a challenge-response credential, you must provide that access code with `UseCurrentAccessCode()` during the `ConfigureChallengeResponse()` operation. Otherwise, the operation will fail and throw the following exception: `System.InvalidOperationException has been thrown. YubiKey Operation Failed. [Warning, state of non-volatile memory is unchanged.]` For more information on slot access codes, see [How to set, reset, remove, and use slot access codes](https://docs.yubico.com/yesdk/users-manual/application-otp/how-to-slot-access-codes.html) . [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-otp/how-to-program-a-challenge-response-credential.md/#L1) --- # NDEF overview ##### Table of Contents NDEF overview ============= NDEF, or NFC Data Exchange Format, is the communication protocol used by NFC (Near-Field Communication) devices. NFC-compatible YubiKeys contain an integrated NFC antenna, which allows them to wirelessly communicate with NFC readers via the NDEF protocol when both devices are within a few centimeters of each other. NFC readers generate an electromagnetic field, which is capable of powering the YubiKey and transferring data between the devices. This allows the YubiKey to generate and submit [Yubico OTPs](https://docs.yubico.com/yesdk/users-manual/application-otp/yubico-otp.html) and [OATH HOTPs](https://docs.yubico.com/yesdk/users-manual/application-otp/hotp.html) without being physically connected to a host. Tapping an NFC reader with a YubiKey is similar to touching the key when it's plugged into a host over USB/Lightning; the action triggers whichever operation the activated OTP application [slot](https://docs.yubico.com/yesdk/users-manual/application-otp/slots.html) is configured with. Unlike USB/Lightning connections, which provide the option to activate either slot based on duration of touch, only one slot may be activated over NFC. NFC-compatible YubiKeys contain an NDEF tag that can be configured to point to one of the slots. When the YubiKey is scanned by an NFC reader, the slot that is pointed to by the NDEF tag will activate. By default, YubiKeys come with the NDEF tag pointing to slot 1 (the short press slot), which is preconfigured with Yubico OTP (and registered with [YubiCloud](https://www.yubico.com/products/yubicloud/) ). Authenticating over NFC with a YubiKey -------------------------------------- Authenticating with a YubiKey over NFC involves the following major steps: 1. The YubiKey is placed on (or very close to) an NFC reader that is connected to a host device. 2. The electromagnetic field generated by the reader powers the YubiKey and triggers the generation of an OTP. 3. The YubiKey translates the binary OTP ciphertext to a UTF-encoded string representation of the OTP's [ModHex](https://docs.yubico.com/yesdk/users-manual/application-otp/modhex.html) characters. For example, the 4-bit binary string "0000" represents the ModHex character "c". In UTF-8, the letter "c" is represented by the 8-bit binary string "0110 0011". 4. The OTP (as part of a text string or URI in an NDEF message) is transmitted through the YubiKey's integrated NFC antenna to the host device via the NFC reader's electromagnetic field. ##### Note More specifically, the OTP is appended to the text string or URI that was configured when the YubiKey's NDEF tag was pointed to a [slot](https://docs.yubico.com/yesdk/users-manual/application-otp/slots.html) with the SDK's [ConfigureNdef() method](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.OtpSession.html#Yubico_YubiKey_Otp_OtpSession_ConfigureNdef_Yubico_YubiKey_Otp_Slot_) . See the [SDK functionality](https://docs.yubico.com/yesdk/users-manual/application-otp/ndef.html#net-sdk-ndef-functionality) section below for more details. 5. The application on the host device receives and decodes the NDEF message and validates the OTP. ##### Note If the application uses the SDK, it will need to call the [ReadNdefTag() method](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.OtpSession.html#Yubico_YubiKey_Otp_OtpSession_ReadNdefTag) to receive the NDEF message. See the [SDK functionality](https://docs.yubico.com/yesdk/users-manual/application-otp/ndef.html#net-sdk-ndef-functionality) section below for more details. NDEF messages ------------- Like [HID](https://docs.yubico.com/yesdk/users-manual/application-otp/hid.html) , the USB communication protocol, NDEF uses byte arrays to communicate data between device and host. These byte arrays, referred to as NDEF "messages", contain one or more records. Each NDEF record includes a header and a payload. The payload contains data (the OTP or HOTP in this case), and the header describes how to interpret that data. The NDEF record header includes the following fields: * Message flags, including the Type Name Format (TNF): 1 byte. * Type length: 1 byte. * Payload length: 1-4 bytes. * ID length: 1 byte. * Payload type: variable. * Payload ID: variable. The header fields that are most important to the YubiKey are the TNF and payload type. The YubiKey sends OTPs and HOTPs over NFC as part of text strings or URIs, which are pre-defined by the NDEF Record Type Definition (RTD) specifications. To send this type of data, the TNF has to be set to 0x01 (Well-Known). From there, the payload type can be set to "T" for text strings or "U" for URIs. To send a text payload, the payload field must include a status byte followed by the text, with each character represented by their UTF code (in byte form). The status byte specifies the UTF encoding type (0 for UTF-8 or 1 for UTF-16) and the length of the language code (the encoding type and language type tell the receiving party how to interpret the text bytes correctly). The text field begins with the language code (e.g. en-US for United States English) followed by the actual payload (the OTP or HOTP). ##### Note The YubiKey uses UTF-8 encoding by default, but the encoding type can be changed to UTF-16 via the API's [UseUtf16Encoding()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.ConfigureNdef.html#Yubico_YubiKey_Otp_Operations_ConfigureNdef_UseUtf16Encoding_System_Boolean_) method if you wish. Similarly, the key uses the en-US language code by default, but this can also be changed with the [WithLanguage()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.ConfigureNdef.html#Yubico_YubiKey_Otp_Operations_ConfigureNdef_WithLanguage_System_String_) method. To send a URI payload, the payload field must include a URI ID code (1 byte) followed by the rest of the URI as a UTF-8 byte string (receiving parties expect URIs to be in UTF-8 format only). The ID code is used to represent commonly used addresses in order to reduce the size of the URI record. For example, "https://www." is represented by the ID code of 0x02. When the NDEF tag is configured with a URI, the SDK will make a best effort at identifying the prefix and automatically setting the right value. You may not explicitly set the URI ID code via the API. For more information on NDEF messages, please see this [book chapter](https://www.oreilly.com/library/view/beginning-nfc/9781449324094/ch04.html) and [blog post](https://austinblackstoneengineering.com/nfc-p2p-basics/) . Slot configuration compatibility -------------------------------- Only Yubico OTPs and OATH HOTPs can be communicated successfully over NDEF. You can still point the NDEF tag to a slot that is configured with a [static password](https://docs.yubico.com/yesdk/users-manual/application-otp/static-password.html) or [challenge-response](https://docs.yubico.com/yesdk/users-manual/application-otp/challenge-response.html) , but the YubiKey will not be able to communicate these configurations properly using the NDEF protocol. For static passwords, the YubiKey will send the static text or URI followed by the HID usage IDs of the password characters. HID usage IDs cannot be interpreted correctly over NFC since the host expects to receive UTF characters. For example, the letter "a" is represented by the binary string "0000 0100" in HID and by the binary string "0110 0001" in UTF-8/ASCII. These binary code differences, along with the fact that upper case letters are signaled through the modifier key state in HID usage reports, mean that a password in HID form cannot be easily translated to UTF form. The YubiKey firmware does not have this translation capability, and the SDK does not include the functionality to configure the key with both the HID and UTF representations of a static password during configuration. For challenge-response, the YubiKey will send the static text or URI with nothing after. (The challenge itself cannot be sent via NDEF.) .NET SDK NDEF functionality --------------------------- The SDK provides the following major methods related to NDEF: * [ConfigureNdef()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.OtpSession.html#Yubico_YubiKey_Otp_OtpSession_ConfigureNdef_Yubico_YubiKey_Otp_Slot_) * [ReadNdefTag()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.OtpSession.html#Yubico_YubiKey_Otp_OtpSession_ReadNdefTag) ### ConfigureNdef() The [ConfigureNdef() method](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.OtpSession.html#Yubico_YubiKey_Otp_OtpSession_ConfigureNdef_Yubico_YubiKey_Otp_Slot_) allows you to point the NDEF tag to one of the two OTP application slots. When the YubiKey is scanned by an NFC reader, the slot that is pointed to by the NDEF tag will activate, causing the generation of whichever password type was configured for that slot. In addition, the [ConfigureNdef class](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.ConfigureNdef.html) allows you to send the OTP/HOTP as static text or a URI via the [AsText()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.ConfigureNdef.html#Yubico_YubiKey_Otp_Operations_ConfigureNdef_AsText_System_String_) and [AsUri()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.ConfigureNdef.html#Yubico_YubiKey_Otp_Operations_ConfigureNdef_AsUri_System_Uri_) methods, respectively. AsText() and AsUri() essentially allow you to toggle the payload type of the NDEF record to "T" or "U". They also provide the option to prepend text or an address to the OTP, which all becomes part of the NDEF record payload. With AsUri(), the intended usage is to prepend the address for an OTP validation server, such as YubiCloud. For an example of how to use these methods, please see the [ConfigureNdef() how-to guide](https://docs.yubico.com/yesdk/users-manual/application-otp/how-to-configure-ndef.html) . ### ReadNdefTag() The [ReadNdefTag() method](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.OtpSession.html#Yubico_YubiKey_Otp_OtpSession_ReadNdefTag) allows an application to receive the OTP payload that is generated when a YubiKey is scanned by a connected NFC reader. It is left to the developer to handle the payload and validate the OTP appropriately. For an example of how to use this method, please see the [ReadNdefTag() how-to guide](https://docs.yubico.com/yesdk/users-manual/application-otp/how-to-read-ndef-information.html) . [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-otp/ndef.md/#L1) --- # FIDO2 touch and fingerprint notification ##### Table of Contents FIDO2 touch and fingerprint notification ======================================== When the YubiKey is attempting to perform "User Verification" (UV), the end user must verify their fingerprint on the YubiKey's fingerprint reader (this applies to the YubiKey Bio series only). In addition, some operations, such as [MakeCredential](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Fido2Session.html#Yubico_YubiKey_Fido2_Fido2Session_MakeCredential_) or [GetAssertion](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Fido2Session.html#Yubico_YubiKey_Fido2_Fido2Session_GetAssertions_) , will not complete until the user touches the contact. For example, a YubiKey will begin an operation, but at some point will stop processing until the contact has been touched. Once touched, it will finish the operation. In those situations, you will likely want to notify the user that they need to verify their fingerprint or touch the contact. But when exactly do you make that notification? The SDK will call the KeyCollector at the moment fingerprint or touch is needed. Once it receives that call, the KeyCollector can notify the user. Normally, the KeyCollector is used to collect something from the user such as a PIN, key, or some other secret value. However, with fingerprint or touch, there is nothing to collect from the user and your application does not need to return anything to the SDK. It is necessary only to notify the user to perform some task. The [KeyCollector and touch article](https://docs.yubico.com/yesdk/users-manual/sdk-programming-guide/key-collector-touch.html) in the User's Manual "SDK programming guide" explains how the process of touch notification works, describes requirements of your `KeyCollector`, and provides rudimentary samples. [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-fido2/fido2-touch-notification.md/#L1) --- # OTP commands and APDUs ##### Table of Contents OTP commands and APDUs ====================== For each possible OTP command, there will be a class that knows how to build the command [APDU](https://docs.yubico.com/yesdk/users-manual/yubikey-reference/apdu.html) and parse the data in the response APDU. Each class will know what information is needed from the caller for that command. Because the OTP application originated as a HID transport protocol, the mappings between "commands" and APDUs is not 1:1. In fact, almost all OTP commands are routed through a single APDU and dispatched based off of the first parameter in the payload. Status structure ---------------- The only way to validate that the state of the OTP application has been changed as intended is by examining the status structure before and after the command. If the configuration has been successfully applied, the sequence number will have increased. Note that this is an imperfect detection mechanism as there is the possibility for a race condition between the initial read of the status structure and the issuance of the command. The response data is in the following form: | Size (Bytes) | Name | Description | | --- | --- | --- | | 1 | Major Version | Typically denotes the line of YubiKey (3 for NEO, 4, 5, etc.) | | 1 | Minor Version | Can represent substantial revisions within a YubiKey line. | | 1 | Patch Version | The minor and/or bug-fix revision of the firmware. | | 1 | Sequence # | Configuration sequence number. `0` if no valid configuration present. | | 2 | Touch Level | The touch level currently detected by the key's button. | Commands -------- * [Configure slot](https://docs.yubico.com/yesdk/users-manual/application-otp/commands-configure-slot.html) * [Update slot](https://docs.yubico.com/yesdk/users-manual/application-otp/commands-update-slot.html) * [Swap slot configurations](https://docs.yubico.com/yesdk/users-manual/application-otp/commands-swap-slots.html) * [Program NDEF](https://docs.yubico.com/yesdk/users-manual/application-otp/commands-program-ndef.html) * [Get serial number](https://docs.yubico.com/yesdk/users-manual/application-otp/commands-get-serial.html) * [Update scan-code map](https://docs.yubico.com/yesdk/users-manual/application-otp/commands-update-scan-code-map.html) * [Get device information](https://docs.yubico.com/yesdk/users-manual/application-otp/commands-get-device-info.html) * [Query FIPS mode](https://docs.yubico.com/yesdk/users-manual/application-otp/commands-query-fips-mode.html) * [Challenge-response](https://docs.yubico.com/yesdk/users-manual/application-otp/commands-challenge-response.html) * [Read status](https://docs.yubico.com/yesdk/users-manual/application-otp/commands-read-status.html) * [Read NDEF payload](https://docs.yubico.com/yesdk/users-manual/application-otp/commands-read-ndef.html) [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-otp/otp-commands.md/#L1) --- # CTAP2 PIN/UV authentication protocols ##### Table of Contents CTAP2 PIN/UV authentication protocols ===================================== CTAP2 (the Client To Authenticator Protocol defined as part of the FIDO2 specification) has been designed in such a way that plaintext PINs are never sent to the authenticator (the YubiKey). This is to prevent unwanted eavesdropping between applications and the YubiKey - whether that be a software hook, or someone monitoring USB traffic with hardware. The PIN/UV auth protocol is the mechanism that is used to support the exchange of PIN and User Verification (UV) data to and from the YubiKey. It ensures that the PIN is encrypted in such a way that only the application and the YubiKey have the necessary knowledge to decrypt the PIN. This is done using a secure key-agreement and key-exchange defined by the protocol. If the application provides the correct PIN, the YubiKey will return a `pinUvAuthToken`, which can be used to authenticate subsequent CTAP2 commands on the YubiKey. Similarly, user verification methods such as fingerprint verification used by the YubiKey Bio Series can also use these auth protocols to obtain a `pinUvAuthToken`. As fingerprints are securely matched and verified on the YubiKey itself, this form of user verification is sufficient enough to not require an additional PIN. The YubiKey will, however, fall back to requiring a PIN if too many failed fingerprint matches have occured. A `pinUvAuthToken`, referred to simply as "authentication token" in the rest of this document, is a randomly- generated, opaque sequence of bytes that acts as a stand-in for the PIN. The authentication token is long enough that it would be impractical to brute force. While authentication tokens are not the PIN, they still need to be handled with some care - at least for the duration that the YubiKey remain powered. Therefore, it is strongly recommended that you zero the memory that was holding the authentication token when your application has finished using it. See also the [article on AuthTokens](https://docs.yubico.com/yesdk/users-manual/application-fido2/fido2-auth-tokens.html) . The two PIN/UV auth protocols ----------------------------- The standard defines two auth protocols for the method of securing the auth token communication between the client and the YubiKey: the original protocol, now called "Protocol One", and then a second (improved) protocol, called "Protocol Two". Both prescribe using Elliptic Curve key agreement to share a base key. Also, both specify deriving encryption and authentication keys from that shared base key, but they use different key derivation functions. Furthermore, while both use AES-CBC to encrypt and HMAC with SHA-256 to authenticate, the details of each are different. Generally, older YubiKeys might support only Protocol One because it was the only choice at the time of production. Once Protocol Two was finalized in the standard, later YubiKeys added support for it. If a YubiKey supports Protocol Two, it will also support Protocol One in case it needs to communicate with a client that supports only Protocol One. When a client needs to obtain an AuthToken, it will contact the YubiKey and specify which protocol to use to make the transfer. Generally, clients will query the YubiKey for a list of protocols it supports. If the YubiKey supports only Protocol One, the client will communicate using that protocol. If the YubiKey supports both, the client will choose Protocol Two. If your code uses the [Fido2Session](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Fido2Session.html) class to perform FIDO2 operations, it will not need to choose a protocol. If a protocol is needed, the `Fido2Session` will determine which protocols the connected YubiKey supports; it will choose Protocol Two if supported, and Protocol One otherwise. [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-fido2/pin-uv-auth-protocols.md/#L1) --- # ##### Table of Contents Get the YubiKey version ----------------------- ### Inner command APDU info | CLA | INS | P1 | P2 | Lc | Data | Le | | --- | --- | --- | --- | --- | --- | --- | | 00 | 06 | 00 | 00 | 8 | _data_ | (absent) | The data is 8 random bytes. ### Response APDU info Total Length: 5 Data Length: 3 | Data | SW1 | SW2 | | --- | --- | --- | | _major, minor, patch_ | 90 | 00 | [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-fido2/apdu/version.md/#L1) --- # The minimum PIN length ##### Table of Contents The minimum PIN length ====================== This article discusses two topics: increasing the minimum PIN length and returning the minimum PIN length to a relying party. Increasing the minimum PIN length --------------------------------- The FIDO2 standard specifies that the PIN must be at least four code points (see the [User's Manual entry](https://docs.yubico.com/yesdk/users-manual/application-fido2/fido2-pin.html) on the PIN). It also specifies that the manufacturer of the authenticator can require a longer PIN and that the authenticator can offer the option of increasing this minimum PIN length. You can check the [AuthenticatorInfo](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.AuthenticatorInfo.html) to find a YubiKey's current minimum PIN length. Also, you can check the `AuthenticatorInfo.Options` property to determine if the YubiKey supports increasing the minimum PIN length. using (fido2Session = new Fido2Session(yubiKeyDevice)) { OptionValue optionValue = fido2Session.AuthenticatorInfo.GetOptionValue( AuthenticatorOptions.setMinPINLength); if (optionValue == OptionValue.True) { // Code to increase min PIN length here. } } If the option is not supported on a YubiKey, then there simply is no way to increase the minimum PIN length. In addition, it is not possible to decrease the minimum PIN length outside of resetting the entire FIDO2 application, which deletes all credentials and sets the application, including the minimum PIN length, back to its original state. To set the minimum PIN length in the SDK, use [Fido2Session.TrySetPinConfig](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Fido2Session.html#Yubico_YubiKey_Fido2_Fido2Session_TrySetPinConfig_) . That method can do any combination of three things: * Increase the minimum PIN length * Force the user to change the PIN * Set the list of relying parties that can see the minimum PIN length Suppose you want to only increase the minimum PIN length to six characters. Your code would look something like this: bool isValid = fido2Session.TrySetPinConfig(6, null, null); if (!isValid) { // The connected YubiKey does not support changing the // minimum PIN length. } } The only way that method returns `false` is if the connected YubiKey does not support changing the minimum PIN length. If the YubiKey supports this feature, and there is some error (e.g. the provided new minimum PIN length is shorter than the current minimum), then this method will throw an exception. After you increase the minimum PIN length, it is possible the current PIN is not long enough. In that case, the YubiKey requires the PIN be changed before it will perform another operation that requires an AuthToken. To verify whether a YubiKey's PIN needs to be changed following a minimum PIN length increase, check the `AuthenticatorInfo.ForcePinChange` property. For example, suppose for a YubiKey the minimum PIN length is 4, and a 4-character PIN is set. Now suppose you change the minimum PIN length to 6. At this point, the `fido2Session.AuthenticatorInfo.ForcePinChange` property is `true`. Now suppose you make a call to an operation that requires an AuthToken, such as `MakeCredential`, `EnumerateRelyingParties`, or even `TrySetPinConfig`. Such a call will throw an exception. Your application must have the user change the PIN (e.g., call `fido2Session.TryChangePin`). You can let the user know how long the PIN must be by reporting the `fido2Session.AuthenticatorInfo.MinimumPinLength` property. Now suppose the minimum PIN length is 4, and a 6-character PIN is set. You change the minimum PIN length to 6. At this point, the YubiKey will not require the PIN be changed. ### Force a PIN change If you want to make sure the user changes the PIN, either because you have changed the minimum PIN length or there is some other reason to require a new PIN (e.g. a company policy that specifies PINs be updated periodically), then call `TrySetPinConfig` with a `forceChangePin` arg of `true`. This forces a PIN change, even if the current PIN is of a length that is at least the minimum PIN length. // Force the PIN change while setting the minimum PIN length, // even if the current PIN is 6 characters long. isValid = fido2Session.TrySetPinConfig(6, null, true); // The following call forces the PIN change without setting the // minimum PIN length. It's forcing a PIN change for some reason // other than minimum PIN length. isValid = fido2Session.TrySetPinConfig(null, null, true); At this point, the `fido2Session.AuthenticatorInfo.ForcePinChange` property is `true`. Now suppose you make a call to an operation that requires an AuthToken, such as `GetAssertions`, `DeleteCredential`, or `TrySetPinConfig`. Such a call will throw an exception. Returning the minimum PIN length to a relying party --------------------------------------------------- When you make a credential, you return it to the client, which forwards it to the relying party. At that point, the RP can accept it or reject it. One reason it might reject it is if the YubiKey's minimum PIN length is not sufficient (e.g. a requirement of an RP's security policy). In order for an RP to know a YubiKey's minimum PIN length, the YubiKey has to send it. However, the YubiKey will not send the minimum PIN to an RP unless it is on one of the "authorized RPIDs" lists. That is, the RP can request the minimum PIN length, but when the YubiKey gets that request, it will check to see if that RP is on one of its authorized RPIDs lists. If it is, the YubiKey will build and return the credential with the minimum PIN length embedded therein. If the RP is not on one of the lists, the YubiKey will build and return the credential without the minimum PIN length. Fortunately, it is easy to place an RP onto one of the lists. ### Authorized RPIDs lists There are two such lists: the pre-configured, unchanging list, and the caller-defined, changeable list. The standard specifies that an authenticator manufacturer is allowed to "pre-load" a list of RPs that are allowed to see the minimum PIN length. This list will never change, even if a YubiKey is reset. You can't add to it or remove and entry from it. This will almost certainly be a special order. For example, suppose the Acme company is distributing authenticators to each employee and wants to make sure that the RP "acme.employees.com" is allowed to see the minimum PIN length. The likely reason the company wants to make sure the RP can see the minimum PIN length is so that the RP can verify that the minimum PIN length on each authenticator is following company policy. Otherwise, a credential can be rejected and an employee will not be able to log in until that issue is fixed. In this case, Acme will make a special ordert from the manufacturer to program "acme.employee.com" into the pre-configured list. The second list is one you can create. If you want a particular RP to be able to see the minimum PIN length, set this second list to contain that RP. To set the caller-defined list, call `TrySetPinConfig`. // Assume there is a variable called rp that is an instance of // the RelyingParty class. var rpidList = new List(1); rpidList.Add(rp.Id); isValid = fido2Session.TrySetPinConfig(null, rpidList, null); Any client or application is allowed to make this call. However, this call requires user approval. No RPID can be placed onto this caller-defined list unless the caller has an AuthToken with the `AuthenticatorConfiguration` permission. The only way to obtain the AuthToken is if the user enters the PIN or supplies a valid fingerprint. #### Not possible to view the lists There is no way to call into the YubiKey and find out what, if any, RPIDs are on either list. If you want to know what RPIDs are on the pre-configured list, you will likely need to contact the manufacturer. One strategy your application can take is to never worry about these lists. If an RP wants to know the minimum PIN length, it can ask. If that RP is on the pre-configured list, then it will get the value. If the RP is not on that list, it will still receive the credential, but it won't get the minimum PIN length. Your application is simply enforcing a policy that says only RPIDs the company has originally specified are allowed to see the minimum PIN length. Note that another application can set the caller-defined list, all that is needed is for the user to supply the PIN or fingerprint when the application builds an AuthToken with `AuthenticatorConfiguration` permission. Hence, it would be possible an RP is not on the pre-configured list and is nonetheless able to obtain the minimum PIN length. #### Setting the caller-defined list replaces the previous list Suppose a YubiKey already has a caller-defined list. When you call `TrySetPinConfig` with a list of RPIDs, it does not add or edit the existing list. The new list replaces the previous one. Even if the previous list is longer than the new list, the previous list is deleted and the YubiKey is set with the new list. This will not replace the pre-configured list. There is nothing anyone can do to add to or remove entries from that list, not even resetting the FIDO2 application. Because your application will almost certainly not be the only application with access to the YubiKey, and you can't see what RPIDs are on either list, you can't really know for sure whether any particular RPID is on the caller-defined list or not. What this means is that if your application is making a credential, and you want the RP to see the minimum PIN length (and you know this RP is not on the pre-configured list), a good strategy is to simply always set the caller-defined list before making the credential. #### Maximum number of entries in the caller-defined list The standard does not specify a required number of available entries for either list. However, it does allow the authenticator to declare the maximum number of entries for the caller-defined list. This number is given by the `AuthenticatorInfo.MaximumRpidsForSetMinPinLength` property. This is the maximum number of RPIDs that can be passed to the authenticator during a call to `TrySetPinConfig`. Because any setting a new list always replaces a current list, this is the maximum number of RPIDs the caller-defined list will hold. For the YubiKey, this number is likely to be one. There is logic to this number being one. Because you cannot see the contents of the RPID list, and because more than one application can have access to a YubiKey, you can never know whether an RPID is on the list or not, even if your application placed it onto the list previously. So your best bet is to simply always set the caller-defined list to the RP for which you are currently making a credential (assuming you want to allow that RP to see the minimum PIN length). #### Requesting the minimum PIN length If the RP wants to know the minimum PIN length, then the client will pass that information on to the YubiKey during the process of making a credential. With the SDK, that means specifying this request in the `MakeCredentialParameters`. // Assume there is a variable called rp that is an instance of // the RelyingParty class. var rpList = new List(1) { rp.Id }; bool isSupported = fido2Session.TrySetPinConfig(null, rpList, null)) // Assume we have a UserEntity and a client data hash. var mcParams = new MakeCredentialParameters(rp, userEntity) { ClientDataHash = clientDataHash }; mcParams.AddOption(AuthenticatorOptions.rk, true); if (isSupported) { mcParams.AddMinPinLengthExtension(fido2Session.AuthenticatorInfo); } When the credential is made, the minimum PIN length is returned in the `MakeCredentialData.AuthenticatorData.Extensions`. MakeCredentialData mcData = fido2Session.MakeCredential(mcParams); // If the RP is allowed to see the minimum PIN length, the return will // be the value. If the RP is not allowed to see it, the return will be // null. int? minPinLen = mcData.AuthenticatorData.GetMinPinLengthExtension(); [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-fido2/fido2-min-pin-len.md/#L1) --- # The SDK's "automatic" AuthToken logic ##### Table of Contents The SDK's "automatic" AuthToken logic ===================================== Before reading this document, make sure you understand AuthTokens. See [this User's Manual article on AuthTokens](https://docs.yubico.com/yesdk/users-manual/application-fido2/fido2-auth-tokens.html) , permissions, PIN/UV, and AuthParams for a detailed discussion. In order to perform most FIDO2 operations, you will need an AuthToken. This document discusses what the SDK does to obtain AuthTokens, when the caller has not done that work. That is, it is possible for the programmer to make calls to `Verify` methods which will obtain AuthTokens, and the SDK will use them when they need them. But it is also possible to simply call on the SDK's FIDO2 classes and methods and let them obtain any AuthToken they need. The task of AuthToken retrieval is done "automatically" by the SDK. Note that this is applicable only when using the [Fido2Session](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Fido2Session.html) class. KeyCollector ------------ In order to allow the SDK to obtain AuthTokens automatically, you must supply a KeyCollector. The `Fido2Session.AuthToken` property ------------------------------------- If the SDK will be calling on the YubiKey to perform some operation that requires authentication, it will first simply use the AuthToken currently in the [AuthToken](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Fido2Session.html#Yubico_YubiKey_Fido2_Fido2Session_AuthToken) property. If the operation works, there was no need to retrieve a new AuthToken. If the operation returns from the YubiKey with the error CTAP2\_ERR\_PIN\_AUTH\_INVALID, the SDK will obtain a new AuthToken making sure the new one has the appropriate permissions. The `AuthToken` property will be updated with the new AuthToken. PinToken versus PinUvAuthToken ------------------------------ If the connected YubiKey supports only FIDO2 version 2.0, which does not have the concept of permissions, this will retrieve a PinToken (user verification, i.e. fingerprints, is not possible). Generally, on a FIDO2 version 2.0 device, the only operations are `MakeCredential` and `GetAssertion`. The AuthTokenPermissions and AuthTokenRelyingPartyId properties --------------------------------------------------------------- The [AuthTokenPermissions](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Fido2Session.html#Yubico_YubiKey_Fido2_Fido2Session_AuthTokenPermissions) property usually contains the permissions of the last AuthToken retrieved. The [AuthTokenRelyingPartyId](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Fido2Session.html#Yubico_YubiKey_Fido2_Fido2Session_AuthTokenRelyingPartyId) contains the relying party ID specified when retrieving the latest AuthToken. An exception is described [below](https://docs.yubico.com/yesdk/users-manual/application-fido2/sdk-auth-token-logic.html#the-credentialmetadata-and-enumeraterelyingparties-exception) . Whenever the SDK retrieves a new AuthToken, it will use as the permissions the combination of the new, required permission with the permissions specified in the `AuthTokenPermissions` property (exception [below](https://docs.yubico.com/yesdk/users-manual/application-fido2/sdk-auth-token-logic.html#the-credentialmetadata-and-enumeraterelyingparties-exception) ). For example, if the current `AuthTokenPermissions` property is `CredentialManagement`, and the SDK needs to perform `BioEnrollment`, it will need a new AuthToken. It will retrieve one with `CredentialManagement | BioEnrollment`, and replace the `AuthTokenPermissions` property with the new combination. Also, when retrieving a new AuthToken, it will use the value in `AuthTokenRelyingPartyId` as the relying party (exception [below](https://docs.yubico.com/yesdk/users-manual/application-fido2/sdk-auth-token-logic.html#the-credentialmetadata-and-enumeraterelyingparties-exception) ). If the SDK's operation requires a new relying party ID, it will use the new ID and replace the contents of the `AuthTokenRelyingPartyId` property, [ClearAuthToken](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Fido2Session.html#Yubico_YubiKey_Fido2_Fido2Session_ClearAuthToken) ---------------------------------------------------------------------------------------------------------------------------------------------------- This method will reset the `AuthToken`, `AuthTokenPermissions`, and `AuthTokenRelyingPartyId` properties to null. In this way, you can "start over". [AddPermissions](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Fido2Session.html#Yubico_YubiKey_Fido2_Fido2Session_AddPermissions_) ----------------------------------------------------------------------------------------------------------------------------------------------------- Call this method at the beginning of a session to obtain an AuthToken with an initial set of permissions and an initial relying party. You provide as the permissions argument the set of permissions you are going to be performing in the session. For example, if you know that you will be performing (or might be performing) both GetAssertion and LargeBlobWrite, You can call `AddPermissions` with `PinUvAuthTokenPermissions.GetAssertion | PinUvAuthTokenPermissions.LargeBlobWrite` (and the appropriate relying party ID). The SDK will then retrieve an AuthToken with those permissions. Later on, when the SDK makes a call to get an assertion, the AuthToken will be valid. Then when it makes a call to write to the LargeBlob, that will work as well, there's no need for the SDK to retrieve a new AuthToken. Of course, because of [expiry](https://docs.yubico.com/yesdk/users-manual/application-fido2/fido2-auth-tokens.html#expiry) , it is possible an initial AuthToken might not work. For example, suppose you call `AddPermissions` with `GetAssertion`, `CredentialManagement`, and `LargeBlobWrite`. After getting an assertion the AuthToken is expired, meaning it loses permissions. The standard specifies that expiry means losing all permissions except `LargeBlobWrite` (see the FIDO2 standard, section 6.5.5.7). Hence, even though you specified CredentialManagement at the beginning, the original AuthToken can no longer be used to build an AuthParam that will authenticate a CredentialManagement operation. You can call this method any time, not just at the beginning. This call will add the new permissions to the ones in the `AuthTokenPermissions` property. If you provide a new relying party ID, it will replace the one in the `AuthTokenRelyingPartyId` property. If you pass null for the relying party ID, the original will remain. That is, you cannot remove the existing `RelyingPartyId` property, except by calling `ClearAuthToken`. The CredentialMetadata and EnumerateRelyingParties exception ------------------------------------------------------------ Suppose the last AuthToken we retrieved had the permisisons `GetAssertion` and `CredentialManagement`, and a relying party ID of "example.com". Now suppose you call [GetCredentialMetadata](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Fido2Session.html#Yubico_YubiKey_Fido2_Fido2Session_GetCredentialMetadata) . That method needs an AuthToken with the `CredentialManagement` permission but there can be no relying party ID (see the section in the User's Manual AuthToken article on [CredentialManagement permission](https://docs.yubico.com/yesdk/users-manual/application-fido2/fido2-auth-tokens.html#credentialmanagement-permission) ). The SDK will try the AuthToken it has, but that won't work, even though the `AuthTokenPermissions` property includes `CredentialManagement`, because there is a relying party connected to that AuthToken. At this point the SDK will need a new AuthToken. Normally, it would build a new one by "adding permissions" to the existing `AuthTokenPermissions` and using the existing `AuthTokenRelyingPartyId`. But that won't work here. In this case, the SDK will build an AuthToken with only the `CredentialManagement` permission, and no relying party ID. It will then be able to perform the operation. After the metadata is retrieved, the SDK will make sure the `AuthTokenPermissions` and `AuthTokenRelyingPartyId` properties are set to their original values (the permisisons property will now contain. These properties do not reflect the state of the current `AuthToken`, but they are retained in case future operations need them. Suppose you make a call to `GetCredentialMetadata`, which results in the `AuthToken` property now containing an AuthToken with only the `CredentialManagement` permission. Now suppose you call `EnumerateRelyingParties`. That is an operation that also requires an AuthToken with only the `CredentialManagement` permission. The SDK will first try the `AuthToken` property and that will work. This is because the SDK will always try the existing AuthToken first. It does not look at the `AuthTokenPermissions` and `AuthTokenRelyingPartyId` to decide if it should use the existing. AuthToken. [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-fido2/sdk-auth-token-logic.md/#L1) --- # YubiKey Bio Multi-protocol Edition considerations and quirks ##### Table of Contents YubiKey Bio Multi-protocol Edition considerations and quirks ============================================================ YubiKey Bio Multi-protocol Edition (MPE) keys possess some unique attributes that require special consideration when using the .NET YubiKey SDK compared to other YubiKeys with FIDO and PIV capabilities. This page details these differences and how to manage them. Shared PIN, no PUK ------------------ Typically, YubiKeys that have both the PIV and FIDO applications (like the 5 Series) have separate PIV and FIDO PINs. However, the YubiKey Bio MPE, which integrates fingerprint biometrics from the FIDO application with PIV functionality, uses a shared PIN for the FIDO and PIV applications. Use of the shared PIN results in two major changes: * The addition of a special [device-wide reset](https://docs.yubico.com/yesdk/users-manual/sdk-programming-guide/bio-mpe.html#resetting-a-yubikey-bio-mpe) , which resets both the FIDO and PIV applications simultaneously * The omission of the PIV [PUK](https://docs.yubico.com/yesdk/users-manual/application-piv/pin-puk-mgmt-key.html) (PIN Unblocking Key) No PUK means that once a YubiKey Bio MPE's PIN has been blocked, there is no way to unblock/change the PIN — the key must be reset. This also means that the SDK's [ResetRetryCommand](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#reset-retry-recover-the-pin) (used to reset the PIN using the PUK) will fail along with any attempt to change the nonexistent PUK with the [ChangeReferenceDataCommand](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#change-reference-data) . Resetting a YubiKey Bio MPE --------------------------- For all YubiKeys except for the YubiKey Bio MPE, factory resets are done strictly _by application_. For example, if you wanted to reset the PIV and FIDO applications on a YubiKey 5 Series key, you would need to perform both a [PIV reset](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.PivSession.html#Yubico_YubiKey_Piv_PivSession_ResetApplication) and a [FIDO reset](https://docs.yubico.com/yesdk/users-manual/application-fido2/fido2-reset.html) . Under most circumstances, it is not possible to perform factory resets for the PIV and FIDO applications individually with the YubiKey Bio MPE. Instead, a special device-wide reset must be used, which resets both PIV and FIDO applications at the same time. This device-wide reset can be performed via the `DeviceReset()` method, the `DeviceResetCommand()`, or by sending a command APDU with the device reset instruction. ##### Note The individual FIDO reset can technically be used with YubiKey Bio MPE keys, but _only_ if the FIDO application is not "blocked" (check the key's [ResetBlocked](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.YubiKeyDevice.html#Yubico_YubiKey_YubiKeyDevice_ResetBlocked) property to confirm). The individual PIV reset cannot be used with YubiKey Bio MPE keys regardless of the PIV application's `ResetBlocked` status. ### DeviceReset() method Using the [DeviceReset()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.YubiKeyDevice.html#Yubico_YubiKey_YubiKeyDevice_DeviceReset) method is simple: [connect](https://docs.yubico.com/yesdk/users-manual/sdk-programming-guide/making-a-connection.html) to a YubiKey with the [YubiKeyDevice](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.YubiKeyDevice.html) class, then call the method on that key. To select the first available YubiKey connected to your host, use: IEnumerable yubiKeyList = YubiKeyDevice.FindAll(); var yubiKey = yubiKeyList.First(); Then perform the reset: yubiKey.DeviceReset(); ### DeviceResetCommand() The device-wide reset can also be performed using the lower-level [DeviceResetCommand](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Management.Commands.DeviceResetCommand.html) and [DeviceResetResponse](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Management.Commands.DeviceResetResponse.html) classes (which is what the `DeviceReset()` method implements under the hood). After connecting to a particular YubiKey with the `YubiKeyDevice` class as shown in the previous example, we need to set up an additional connection to the key's management application using the [IYubiKeyConnection](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.IYubiKeyConnection.html) class: IYubiKeyConnection connection = yubiKey.Connect(YubiKeyApplication.Management); Then send the `DeviceResetCommand` to the key: DeviceResetCommand resetCommand = new DeviceResetCommand(); DeviceResetResponse resetResponse = connection.SendCommand(resetCommand); For error handling, check the `DeviceResetResponse` instance's [Status](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.IYubiKeyResponse.html#Yubico_YubiKey_IYubiKeyResponse_Status) and [StatusMessage](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.IYubiKeyResponse.html#Yubico_YubiKey_IYubiKeyResponse_StatusMessage) properties. For general information on using the SDK's command classes, see [Commands](https://docs.yubico.com/yesdk/users-manual/sdk-programming-guide/commands.html) . ### DeviceReset APDUs At the lowest level, the device-wide reset can be performed by sending a command [APDU](https://docs.yubico.com/yesdk/users-manual/yubikey-reference/apdu.html) to a YubiKey and handling its response APDU (which is what the `DeviceResetCommand` and `DeviceResetResponse` implement under the hood). The command APDU is simple, requiring the instruction `1F` with no additional data. The response APDU returned from the key will only contain the status word. **Command APDU**: | CLA | INS | P1 | P2 | Lc | Data | Le | | --- | --- | --- | --- | --- | --- | --- | | 00 | 1F | 00 | 00 | (absent) | (absent) | (absent) | **Response APDU (success)**: Total Length: 2 bytes Data Length: 0 | Data | SW1 | SW2 | | --- | --- | --- | | (no data) | 90 | 00 | **Response APDU (failure)**: Total Length: 2 bytes Data Length: 0 | Data | SW1 | SW2 | | --- | --- | --- | | (no data) | 6f | 00 | #### OpenSC example To perform the device reset on a YubiKey Bio MPE with a tool like [OpenSC](https://github.com/OpenSC/OpenSC) , you must first send a command APDU to connect to the key's management application (`00a4040008a000000527471117`) followed by the device reset command APDU (`001F0000`): opensc-tool -c default -s 00a4040008a000000527471117 -s 001F0000 Using reader with a card: Yubico YubiKey FIDO+CCID Sending: 00 A4 04 00 08 A0 00 00 05 27 47 11 17 Received (SW1=0x90, SW2=0x00): 56 69 72 74 75 61 6C 20 6D 67 72 20 2D 20 46 57 Virtual mgr - FW 20 76 65 72 73 69 6F 6E 20 35 2E 37 2E 32 version 5.7.2 Sending: 00 1F 00 00 Received (SW1=0x90, SW2=0x00) [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/sdk-programming-guide/bio-mpe.md/#L1) --- # FIDO2 HMAC secret ("hmac-secret" extension) ##### Table of Contents FIDO2 HMAC secret ("hmac-secret" extension) =========================================== When you get the [AuthenticatorInfo](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.AuthenticatorInfo.html) , you can check the extensions to see if "hmac-secret" is supported. using (fido2Session = new Fido2Session(yubiKeyDevice)) { if (fido2Session.AuthenticatorInfo.Extensions.Contains("hmac-secret")) { . . . } } If it is, when making a credential you can specify that the YubiKey create a secret value associated with that credential. Later on when getting an assertion, you can ask the YubiKey to retrieve that secret. What you do with that secret is up to you. The standard remarks that it can be used to encrypt or decrypt data. Each client will have access to this secret value, so that it is possible to securely share information among clients. The secret value is actually built from a value on the YubiKey and a salt provided by the client. The standard says, "The authenticator and the platform each only have the part of the complete secret to prevent offline attacks." Hence, for all clients to share this secret, each client must use the same salt. Requesting the YubiKey create this secret ----------------------------------------- The YubiKey will generate a secret for a credential only if instructed to do so at the time the credential is made. It is not possible to "add" this secret to an existing credential. using (fido2Session = new Fido2Session(yubiKeyDevice)) { var makeCredentialParameters = new MakeCredentialParameters(rp, userEntity); makeCredentialParameters.AddHmacSecretExtension(fido2Session.AuthenticatorInfo); . . . MakeCredentialData credentialData = fido2Session.MakeCredential(makeCredentialParameters); } Requesting the secret --------------------- When getting an assertion, you specify you want the YubiKey to return the assertion and the secret value. If you don't, the YubiKey will return the assertion, but it won't return the secret. using (fido2Session = new Fido2Session(yubiKeyDevice)) { var getAssertionParameters = new GetAssertionParameters(rp, clientDataHash); getAssertionParameters.RequestHmacSecretExtension(salt); . . . IReadOnlyList assertionDataList = fido2Session.GetAssertions(makeCredentialParameters); } Extracting the secret --------------------- Once you have an assertion, you will find the secret in the `Extensions` in the `GetAssertionData.AuthenticatorData` property. There is a method in that class that will parse and decrypt the value returned. using (fido2Session = new Fido2Session(yubiKeyDevice)) { . . . byte[] hmacSecretValue = assertionDataList[0].AuthenticatorData.GetHmacSecretExtension( fido2Session.AuthProtocol); } The result will be an array 32 bytes long. Decrypting the value returned ----------------------------- In order to generate the "hmac-secret", the YubiKey will perform HMAC with SHA-256 using the secret value it has associated with the credential as the key, and the salt provided (along with possibly other data) as the data to MAC. It will then encrypt that result using the shared key (the key shared between the client and the YubiKey, the result of the ECDH operation used to encrypt all communications between the client and the YubiKey). The value returned by the YubiKey is 32 bytes. The `AuthenticatorData.GetHmacSecretExtension` method will decrypt that value and return the result. Two salts --------- It is possible to pass in two 32-byte salts to the `GetAssertionParameters.RequestHmacSecretExtension` method. In that case, the YubiKey will return two values. The standard says the second value is used "...when the platform wants to roll over the symmetric secret...". using (fido2Session = new Fido2Session(yubiKeyDevice)) { var getAssertionParameters = new GetAssertionParameters(rp, clientDataHash); getAssertionParameters.RequestHmacSecretExtension(salt1, salt2); . . . IReadOnlyList assertionDataList = fido2Session.GetAssertions(makeCredentialParameters); . . . byte[] hmacSecretValue = assertionDataList[0].AuthenticatorData.GetHmacSecretExtension( fido2Session.AuthProtocol); } The result will be an array 64 bytes long. The first 32 bytes make up the result based on `salt1`, and the second 32 bytes make up the result based on `salt2`. [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-fido2/hmac-secret.md/#L1) --- # ##### Table of Contents Get the YubiKey's Key Agreement public key ------------------------------------------ ### Command APDU info | CLA | INS | P1 | P2 | Lc | Data | Le | | --- | --- | --- | --- | --- | --- | --- | | 00 | 10 | 00 | 00 | 06 | 06 A2 01 02 02 02 | (absent) | The Ins byte (instruction) is 10, which is the byte for CTAPHID\_CBOR. That means the command information is in a CBOR encoded structure in the Data. The data consists of the CTAP Command Byte and the CBOR encoding of the command's parameters. In this case, the CTAP Command Byte is `06`, which is the command "`authenticatorClientPin`". The CBOR encoding is the following: A2 map containing two elements 01 key (of key/value) specifying ... 0x ... PIN/UV protocol (x=1 for protocol one, x=2 for protocol two) 02 key specifying ... 02 ... subcommand, 02 = KeyAgreement ### Response APDU info #### Response APDU for a successful get Total Length: _variable + 2_ Data Length: _variable_ | Data | SW1 | SW2 | | --- | --- | --- | | _encoded info_ | 90 | 00 | The info returned is CBOR encoded. It has a structure similar to the following. A5 01 --int-- 03 --int-- 20 --int-- 21 --byte string-- 22 --byte string-- The integers describe the algorithm and curve, and the byte strings are the x- and y-coordinates of the public key. The lengths of the byte string are dependent on the algorithm. Currently only one algorithm is supported, ECDH using the NIST curve P-256. That means the byte strings are both 32 bytes long. The total length of the encoding will be 78 bytes. Hence, the total length of the response will be 80 bytes. #### Response APDU when no protocol is given Total Length: 2 Data Length: 0 | Data | SW1 | SW2 | | --- | --- | --- | | (no data) | 6F | 14 | #### Response APDU when an unsupported protocol is specified Total Length: 2 Data Length: 0 | Data | SW1 | SW2 | | --- | --- | --- | | (no data) | 6F | 33 | [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-fido2/apdu/get-key-agree.md/#L1) --- # ##### Table of Contents Get FIDO2 and device info ------------------------- ### Command APDU info | CLA | INS | P1 | P2 | Lc | Data | Le | | --- | --- | --- | --- | --- | --- | --- | | 00 | 10 | 00 | 00 | 01 | 04 | (absent) | ### Response APDU info Total Length: _variable + 2_ Data Length: _variable_ | Data | SW1 | SW2 | | --- | --- | --- | | _encoded info_ | 90 | 00 | The info returned is CBOR encoded. It has a structure similar to the following. AC 01 --data-- 02 --data-- . . . 14 --data-- The `AC` means there's a map of 12 key/value pairs. Each pair is an integer followed by data encoded as specified by the integer, defined in the CTAP 2.1 standard, section 6.4. The standard specifies integer keys from `01` to `15` (in decimal that is 1 to 21). However, the YubiKey does not support the key `15`. Most of the elements are optional, so that any one encoding may or may not have the same subset of possible key/value pairs. [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-fido2/apdu/get-info.md/#L1) --- # ##### Table of Contents Set the YubiKey's FIDO2 application to be PIN-protected ------------------------------------------------------- ### Command APDU info | CLA | INS | P1 | P2 | Lc | Data | Le | | --- | --- | --- | --- | --- | --- | --- | | 00 | 10 | 00 | 00 | _data length_ | 06 _encoded info_ | (absent) | The Ins byte (instruction) is 10, which is the byte for CTAPHID\_CBOR. That means the command information is in a CBOR encoded structure in the Data. The data consists of the CTAP Command Byte and the CBOR encoding of the command's parameters. In this case, the CTAP Command Byte is `06`, which is the command "`authenticatorClientPin`". The CBOR encoding is the following: A5 map containing five elements 01 key (of key/value) specifying ... 0x ... PIN/UV protocol (x=1 for protocol one, x=2 for protocol two) 02 key specifying ... 03 ... subcommand, 03 = SetPin 03 key specifying ... <> ... CBOR-encoded COSE_Key, the platform's public key 04 key specifying ... <> ... authentication value 05 key specifying ... <> ... encrypted new PIN ### Response APDU info #### Response APDU for a successful set PIN Total Length: 2 Data Length: 0 | Data | SW1 | SW2 | | --- | --- | --- | | (no data) | 90 | 00 | #### Response APDU when the input is not encoded correctly Total Length: 2 Data Length: 0 | Data | SW1 | SW2 | | --- | --- | --- | | (no data) | 6F | 11 | #### Response APDU when no protocol is given Total Length: 2 Data Length: 0 | Data | SW1 | SW2 | | --- | --- | --- | | (no data) | 6F | 14 | #### Response APDU when an unsupported protocol is specified Total Length: 2 Data Length: 0 | Data | SW1 | SW2 | | --- | --- | --- | | (no data) | 6F | 33 | [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-fido2/apdu/set-pin.md/#L1) --- # ##### Table of Contents Change the YubiKey's FIDO2 PIN ------------------------------ ### Command APDU info | CLA | INS | P1 | P2 | Lc | Data | Le | | --- | --- | --- | --- | --- | --- | --- | | 00 | 10 | 00 | 00 | _data length_ | 06 _encoded info_ | (absent) | The Ins byte (instruction) is 10, which is the byte for CTAPHID\_CBOR. That means the command information is in a CBOR encoded structure in the Data. The data consists of the CTAP Command Byte and the CBOR encoding of the command's parameters. In this case, the CTAP Command Byte is `06`, which is the command "`authenticatorClientPin`". The CBOR encoding is the following: A5 map containing five elements 01 key (of key/value) specifying ... 0x ... PIN/UV protocol (x=1 for protocol one, x=2 for protocol two) 02 key specifying ... 04 ... subcommand, 04 = ChangePin 03 key specifying ... <> ... CBOR-encoded COSE_Key, the platform's public key 04 key specifying ... <> ... authentication value 05 key specifying ... <> ... encrypted new PIN 06 key specifying ... <> ... encrypted hash of current PIN ### Response APDU info #### Response APDU for a successful change PIN Total Length: 2 Data Length: 0 | Data | SW1 | SW2 | | --- | --- | --- | | (no data) | 90 | 00 | #### Response APDU when the input is not encoded correctly Total Length: 2 Data Length: 0 | Data | SW1 | SW2 | | --- | --- | --- | | (no data) | 6F | 11 | #### Response APDU when no protocol is given Total Length: 2 Data Length: 0 | Data | SW1 | SW2 | | --- | --- | --- | | (no data) | 6F | 14 | #### Response APDU when an unsupported protocol is specified Total Length: 2 Data Length: 0 | Data | SW1 | SW2 | | --- | --- | --- | | (no data) | 6F | 33 | [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-fido2/apdu/change-pin.md/#L1) --- # ##### Table of Contents Get a PIN/UV Auth token using the PIN ------------------------------------- ### Command APDU info | CLA | INS | P1 | P2 | Lc | Data | Le | | --- | --- | --- | --- | --- | --- | --- | | 00 | 10 | 00 | 00 | _data length_ | 06 _encoded info_ | (absent) | The INS byte (instruction) is 10, which is the byte for CTAPHID\_CBOR. That means the command information is in a CBOR encoded structure in the Data. The Data consists of the CTAP Command Byte and the CBOR encoding of the command's parameters. In this case, the CTAP Command Byte is `06`, which is the command "`authenticatorClientPin`". The CBOR encoding is the following: A6 map containing four elements 01 key (of key/value) specifying ... 0x ... PIN/UV protocol (x=1 for protocol one, x=2 for protocol two) 02 key specifying ... 09 ... subcommand, 09 = getPinUvAuthTokenUsingPin 03 key specifying ... <> ... CBOR-encoded COSE_Key, the platform's public key 06 key specifying ... <> ... encrypted hash of current PIN 09 key specifying ... xx ... permissions, e.g. 0x01, 0x03, 0x21 0A key specifying ... <> ... relying party ID (a text string) ### Response APDU info #### Response APDU for a successful get Total Length: _variable + 2_ Data Length: _variable_ | Data | SW1 | SW2 | | --- | --- | --- | | _encoded info_ | 90 | 00 | The info returned is CBOR encoded. It has a structure similar to the following. A1 02 --byte string-- The byte string is the encrypted token. For protocol one, the string will be 32 bytes long, and for protocol two the string will be 48 bytes long. #### Response APDU when no protocol is given Total Length: 2 Data Length: 0 | Data | SW1 | SW2 | | --- | --- | --- | | (no data) | 6F | 14 | #### Response APDU when an unsupported protocol is specified Total Length: 2 Data Length: 0 | Data | SW1 | SW2 | | --- | --- | --- | | (no data) | 6F | 33 | [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-fido2/apdu/get-auth-token-using-pin.md/#L1) --- # ##### Table of Contents Get a PIN token --------------- ### Command APDU info | CLA | INS | P1 | P2 | Lc | Data | Le | | --- | --- | --- | --- | --- | --- | --- | | 00 | 10 | 00 | 00 | _data length_ | 06 _encoded info_ | (absent) | The Ins byte (instruction) is 10, which is the byte for CTAPHID\_CBOR. That means the command information is in a CBOR encoded structure in the Data. The data consists of the CTAP Command Byte and the CBOR encoding of the command's parameters. In this case, the CTAP Command Byte is `06`, which is the command "`authenticatorClientPin`". The CBOR encoding is the following: A4 map containing four elements 01 key (of key/value) specifying ... 0x ... PIN/UV protocol (x=1 for protocol one, x=2 for protocol two) 02 key specifying ... 05 ... subcommand, 05 = getPinToken 03 key specifying ... <> ... CBOR-encoded COSE_Key, the platform's public key 06 key specifying ... <> ... encrypted hash of current PIN ### Response APDU info #### Response APDU for a successful get Total Length: _variable + 2_ Data Length: _variable_ | Data | SW1 | SW2 | | --- | --- | --- | | _encoded info_ | 90 | 00 | The info returned is CBOR encoded. It has a structure similar to the following. A1 02 --byte string-- The byte string is the encrypted token. For protocol one, the string will be 32 bytes long, and for protocol two the string will be 48 bytes long. #### Response APDU when no protocol is given Total Length: 2 Data Length: 0 | Data | SW1 | SW2 | | --- | --- | --- | | (no data) | 6F | 14 | #### Response APDU when an unsupported protocol is specified Total Length: 2 Data Length: 0 | Data | SW1 | SW2 | | --- | --- | --- | | (no data) | 6F | 33 | [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-fido2/apdu/get-pin-token.md/#L1) --- # ##### Table of Contents Get a PIN/UV Auth token using user verification (UV) ---------------------------------------------------- ### Command APDU info | CLA | INS | P1 | P2 | Lc | Data | Le | | --- | --- | --- | --- | --- | --- | --- | | 00 | 10 | 00 | 00 | _data length_ | 06 _encoded info_ | (absent) | The Ins byte (instruction) is 10, which is the byte for CTAPHID\_CBOR. That means the command information is in a CBOR encoded structure in the Data. The data consists of the CTAP Command Byte and the CBOR encoding of the command's parameters. In this case, the CTAP Command Byte is `06`, which is the command "`authenticatorClientPin`". The CBOR encoding is the following: A6 map containing four elements 01 key (of key/value) specifying ... 0x ... PIN/UV protocol (x=1 for protocol one, x=2 for protocol two) 02 key specifying ... 06 ... subcommand, 06 = getPinUvAuthTokenUsingPin 03 key specifying ... <> ... CBOR-encoded COSE_Key, the platform's public key 09 key specifying ... xx ... permissions, e.g. 0x01, 0x03, 0x21 0A key specifying ... <> ... relying party ID (a text string) ### Response APDU info #### Response APDU for a successful get Total Length: _variable + 2_ Data Length: _variable_ | Data | SW1 | SW2 | | --- | --- | --- | | _encoded info_ | 90 | 00 | The info returned is CBOR encoded. It has a structure similar to the following. A1 02 --byte string-- The byte string is the encrypted token. For protocol one, the string will be 32 bytes long, and for protocol two the string will be 48 bytes long. #### Response APDU when no protocol is given Total Length: 2 Data Length: 0 | Data | SW1 | SW2 | | --- | --- | --- | | (no data) | 6F | 14 | #### Response APDU when an unsupported protocol is specified Total Length: 2 Data Length: 0 | Data | SW1 | SW2 | | --- | --- | --- | | (no data) | 6F | 33 | [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-fido2/apdu/get-auth-token-using-uv.md/#L1) --- # Migrating from SmartCard.NET to the SDK ##### Table of Contents Migrating from SmartCard.NET to the SDK ======================================= You might be using a product called the Yubico SmartCard.NET API, a C# library containing classes an application developer can call to get YubiKey functionality. If you want to migrate to the SDK, you will need to change your code. This document describes what classes and methods to call in the SDK to perform the operations available in the SmartCard.NET API. * [Migrating from SmartCard.NET to the SDK](https://docs.yubico.com/yesdk/users-manual/application-piv/migrate-smartcardnet.html#migrating-from-smartcardnet-to-the-sdk) * [Making a connection](https://docs.yubico.com/yesdk/users-manual/application-piv/migrate-smartcardnet.html#making-a-connection) * [SDK](https://docs.yubico.com/yesdk/users-manual/application-piv/migrate-smartcardnet.html#sdk) * [Get the firmware version](https://docs.yubico.com/yesdk/users-manual/application-piv/migrate-smartcardnet.html#get-the-firmware-version) * [SDK](https://docs.yubico.com/yesdk/users-manual/application-piv/migrate-smartcardnet.html#sdk-1) * [Get the serial number](https://docs.yubico.com/yesdk/users-manual/application-piv/migrate-smartcardnet.html#get-the-serial-number) * [SDK](https://docs.yubico.com/yesdk/users-manual/application-piv/migrate-smartcardnet.html#sdk-2) * [Change the management key](https://docs.yubico.com/yesdk/users-manual/application-piv/migrate-smartcardnet.html#change-the-management-key) * [SDK](https://docs.yubico.com/yesdk/users-manual/application-piv/migrate-smartcardnet.html#sdk-3) * [Change the PIN](https://docs.yubico.com/yesdk/users-manual/application-piv/migrate-smartcardnet.html#change-the-pin) * [SDK](https://docs.yubico.com/yesdk/users-manual/application-piv/migrate-smartcardnet.html#sdk-4) * [Change the PUK](https://docs.yubico.com/yesdk/users-manual/application-piv/migrate-smartcardnet.html#change-the-puk) * [SDK](https://docs.yubico.com/yesdk/users-manual/application-piv/migrate-smartcardnet.html#sdk-5) * [Unblock the PIN](https://docs.yubico.com/yesdk/users-manual/application-piv/migrate-smartcardnet.html#unblock-the-pin) * [SDK](https://docs.yubico.com/yesdk/users-manual/application-piv/migrate-smartcardnet.html#sdk-6) * [Write MSROOTS](https://docs.yubico.com/yesdk/users-manual/application-piv/migrate-smartcardnet.html#write-msroots) * [SDK](https://docs.yubico.com/yesdk/users-manual/application-piv/migrate-smartcardnet.html#sdk-7) * [Read MSROOTS](https://docs.yubico.com/yesdk/users-manual/application-piv/migrate-smartcardnet.html#read-msroots) * [SDK](https://docs.yubico.com/yesdk/users-manual/application-piv/migrate-smartcardnet.html#sdk-8) * [Delete MSROOTS](https://docs.yubico.com/yesdk/users-manual/application-piv/migrate-smartcardnet.html#delete-msroots) * [SDK](https://docs.yubico.com/yesdk/users-manual/application-piv/migrate-smartcardnet.html#sdk-9) * [Create attestation statement](https://docs.yubico.com/yesdk/users-manual/application-piv/migrate-smartcardnet.html#create-attestation-statement) * [SDK](https://docs.yubico.com/yesdk/users-manual/application-piv/migrate-smartcardnet.html#sdk-10) * [Reset the card](https://docs.yubico.com/yesdk/users-manual/application-piv/migrate-smartcardnet.html#reset-the-card) * [SDK](https://docs.yubico.com/yesdk/users-manual/application-piv/migrate-smartcardnet.html#sdk-11) Making a connection ------------------- When using the SmartCard.NET product, you started with this: IEnumerable smartCardList = YkSmartCard.GetSmartCards(); At this point you enumerate through the list to find the YubiKey you want to use. It can be something as simple as YkSmartCard ykSmartCard = smartCardList.First(); You now have the object that you will use to call the YubiKey. ### SDK See the User's Manual [entry on making a connection](https://docs.yubico.com/sdk-programming-guide/making-a-connection.md) for details. Note that to make a connection, you must specify which application you want to use. There are six possible applications: OTP, FIDO, FIDO2, OATH, OpenPgpCard, and PIV. To migrate from the SmartCard.NET API, you will use the PIV application, building a `PivSession` object. If building a PIV session, your code will likely look something like this. IEnumerable yubiKeyList = YubiKeyDevice.FindAll(); IYubiKeyDevice yubiKeyToUse = yubiKeyList.First(); using var pivSession = new PivSession(yubiKeyToUse); Get the firmware version ------------------------ In the SmartCard.NET API, here is how you get the firmware version. byte[] versionNumber = ykSmartCard.GetFirmwareVersion(); The result is five bytes. Only the first three bytes make up the actual version number. byte versionMajor = versionNumber[0]; byte versionMinor = versionNumber[1]; byte versionPatch = versionNumber[2]; ### SDK With the SDK, you do not need to perform any operation other than choosing the YubiKey, because one of the properties in the `IYubiKeyDevice` is `FirmwareVersion`. IEnumerable yubiKeyList = YubiKeyDevice.FindAll(); IYubiKeyDevice yubiKeyToUse = yubiKeyList.First(); FirmwareVersion versionNumber = yubiKeyToUse.FirmwareVersion; Inside the `FirmwareVersion` class are byte versionMajor = versionNumber.Major; byte versionMinor = versionNumber.Minor; byte versionPatch = versionNumber.Patch; Get the serial number --------------------- In the SmartCard.NET API, here is how you get the serial number. string serialNumber = ykSmartCard.GetSerialNumber(); If you want the value as an int, you can use `Parse` or `TryParse`. bool isParsed = Int32.TryParse(serialNumber, out int serialNumberAsInt); ### SDK With the SDK, you do not need to perform any operation other than choosing the YubiKey, because one of the properties in the `IYubiKeyDevice` is `SerialNumber`. IEnumerable yubiKeyList = YubiKeyDevice.FindAll(); IYubiKeyDevice yubiKeyToUse = yubiKeyList.First(); int serialNumber = yubiKeyToUse.SerialNumber; If you want the serial number as a string (as was returned in the SmartCard.NET API), use the `ToString` method. To get the exact same result, set the format. string serialNumberString = yubiKeyToUse.SerialNumber.ToString("00000000"); Change the management key ------------------------- In the SmartCard.NET API, here is how you change the management key. byte[] oldKey = CollectMgmtKey(); byte[] newKey = CollectNewMgmtKey(); ykSmartCard.ChangeManagementKey(oldKey, newKey); ### SDK To change the management key, use the `PivSession.TryChangeManagementKey`. In order to change the management key, the existing key must be authenticated first. There is a method in the `PivSession` class, `TryAuthenticateManagementKey`, but it is called automatically by the `TryChangeManagementKey` method if needed. Hence, you can authenticate the existing key first if you want, but it is not necessary. The methods that authenticate the current management key and change it will obtain the keys using the `KeyCollector`. see the User's Manual entry on [delegates](https://docs.yubico.com/sdk-programming-guide/delegates-in-sdk.md) for a discussion of the `KeyCollector`. using var pivSession = new PivSession(yubiKeyToUse) { bool isChanged = pivSession.TryChangeManagementKey(); if (!isChanged) { // handle error case. } } Change the PIN -------------- In the SmartCard.NET API, here is how you change the PIN. string oldPin = CollectPin(); string newPin = CollectNewPin(); ykSmartCard.ChangePin(oldPin, newPin, out int retriesRemaining); ### SDK The method to change the PIN will obtain the current and new PINs using the `KeyCollector`. see the User's Manual entry on [delegates](https://docs.yubico.com/sdk-programming-guide/delegates-in-sdk.md) for a discussion of the `KeyCollector`. using var pivSession = new PivSession(yubiKeyToUse) { bool isChanged = pivSession.TryChangePin(); if (!isChanged) { // handle error case. } } Change the PUK -------------- In the SmartCard.NET API, here is how you change the PUK. string oldPuk = CollectPuk(); string newPuk = CollectNewPuk(); ykSmartCard.ChangePuk(oldPuk, newPuk, out int retriesRemaining); ### SDK The method to change the PUK will obtain the current and new PUKs using the `KeyCollector`. see the User's Manual entry on [delegates](https://docs.yubico.com/sdk-programming-guide/delegates-in-sdk.md) for a discussion of the `KeyCollector`. using var pivSession = new PivSession(yubiKeyToUse) { bool isChanged = pivSession.TryChangePuk(); if (!isChanged) { // handle error case. } } Unblock the PIN --------------- In the SmartCard.NET API, here is how you use the PUK to unblock the PIN. string puk = CollectPuk(); string newPin = CollectNewPin(); ykSmartCard.UnblockPin(puk, newPin, out int retriesRemaining); ### SDK The method to change the recover the PIN using the PUK will obtain the PUK and new PIN using the `KeyCollector`. see the User's Manual entry on [delegates](https://docs.yubico.com/sdk-programming-guide/delegates-in-sdk.md) for a discussion of the `KeyCollector`. using var pivSession = new PivSession(yubiKeyToUse) { bool isChanged = pivSession.TryResetPin(); if (!isChanged) { // handle error case. } } Write MSROOTS ------------- In the SmartCard.NET API, here is how you load the MSROOTS data onto the YubiKey. // Note that there is a limit of 3058 bytes for the data. byte[] msRootsData = CollectMsRootsData(); string pin = CollectPin(); var memoryStream = new MemoryStream(msRootsData); ykSmartCard.WriteMsRootsData(pin, memoryStream); ### SDK The method to write the MSROOTS requires management key authentication. The method will make the appropriate calls to authenticate the management key, if it has not been authenticated yet, just make sure the `KeyCollector` has been loaded. see the User's Manual entry on [delegates](https://docs.yubico.com/sdk-programming-guide/delegates-in-sdk.md) for a discussion of the `KeyCollector`. Note that there are two versions of this method, one that takes in a byte array and another that takes in a `Stream`. using var pivSession = new PivSession(yubiKeyToUse) { byte[] msRootsData = CollectMsRootsData(); bool isWritten = pivSession.WriteMsroots(msrootsData); if (!isWritten) { // handle error case. } } using var pivSession = new PivSession(yubiKeyToUse) { byte[] msRootsData = CollectMsRootsData(); var memoryStream = new MemoryStream(msRootsData); bool isWritten = pivSession.WriteMsrootsStream(memoryStream); if (!isWritten) { // handle error case. } } Read MSROOTS ------------ In the SmartCard.NET API, here is how you obtain the MSROOTS data from the YubiKey. Stream getData = ykSmartCard.ReadMsroots(); ### SDK Note that there are two versions of this method, one that returns a byte array and another that returns a `Stream`. using var pivSession = new PivSession(yubiKeyToUse) { byte[] msrootsContents = pivSession.ReadMsroots(); } using var pivSession = new PivSession(yubiKeyToUse) { Stream msrootsContents = pivSession.ReadMsrootsStream(); } Delete MSROOTS -------------- In the SmartCard.NET API, here is how you delete any MSROOTS data on the YubiKey. ykSmartCard.DeleteMsroots(pinString); ### SDK The method to delete the MSROOTS requires management key authentication. The method will make the appropriate calls to authenticate the management key, if it has not been authenticated yet, just make sure the `KeyCollector` has been loaded. see the User's Manual entry on [delegates](https://docs.yubico.com/sdk-programming-guide/delegates-in-sdk.md) for a discussion of the `KeyCollector`. using var pivSession = new PivSession(yubiKeyToUse) { pivSession.DeleteMsroots(); } Create attestation statement ---------------------------- You can obtain an attestation statement (which is an X.509 certificate) only for keys generated by the YubiKey itself. You cannot get one from a key imported into the YubiKey. Suppose you generated a key pair in Slot 9A. Here's how you would get an attestation statement for that key pair. var cspParams = new CspParameters(1, "Microsoft Base Smart Card Crypto Provider"); var rsaProvider = new RSACryptoServiceProvider(cspParams); string containerGuid = rsaProvider.CspKeyContainerInfo.UniqueKeyContainerName; byte[] attestationStatement = ykSmartCard.Attest(containerGuid); ### SDK using var pivSession = new PivSession(yubiKeyToUse) { bool isValid = pivSession.TryCreateAttestationStatement(0x9A, out X509Certificate2? attestationStatement); if (!isValid) { // Handle error case. } } Reset the card -------------- In the SmartCard.NET API, here is how you load the MSROOTS data onto the YubiKey. ykSmartCard.ResetCard(); ### SDK To reset the PIV application on the YubiKey, both the PIN and PUK must be blocked. The SDK's reset method will perform the necessary operations needed to block the PIN and PUK. That is, simply call this method to reset, there's no need to do any work yourself to make sure the PIN and PUK are blocked. using var pivSession = new PivSession(yubiKeyToUse) { bool isReset = pivSession.TryResetPiv(); if (!isReset) { // handle error case. } } [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-piv/migrate-smartcardnet.md/#L1) --- # PIN complexity policy ##### Table of Contents PIN complexity policy ===================== PIN complexity is an optional feature available on YubiKeys with firmware version 5.7 or later. If PIN complexity is enabled, the YubiKey will block the usage of non-trivial PINs, such as `11111111`, `password`, or `12345678`. YubiKeys can also be programmed during the pre-registration process to refuse other specific values. For more information on PIN complexity and the full PIN blocklist, see the [YubiKey Technical Manual](https://docs.yubico.com/hardware/yubikey/yk-tech-manual/5.7-firmware-specifics.html#pin-complexity) . ##### Note PIN complexity policy is derived from the current Revision 3 of [NIST SP 800-63](https://pages.nist.gov/800-63-3/sp800-63-3.html) (specifically SP 800-63B-3), with additional consideration of [Revision 4 of SP 800-63](https://pages.nist.gov/800-63-4/sp800-63.html) (specifically SP 800-63B-4). For the SDK, PIN complexity enablement means that the YubiKey will refuse to set or change the following values if they violate the policy: * [PIV PIN and PUK](https://docs.yubico.com/yesdk/users-manual/application-piv/pin-puk-mgmt-key.html) * [FIDO2 PIN](https://docs.yubico.com/yesdk/users-manual/application-fido2/fido2-pin.html) Managing PIN complexity with the SDK ------------------------------------ PIN complexity can be managed by the SDK in two ways: 1. Reading the current PIN complexity status of a key. 2. Handling PIN complexity-related errors. ### Reading the current PIN complexity status To verify whether PIN complexity is enabled for a particular YubiKey, check the [IsPinComplexityEnabled](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.IYubiKeyDeviceInfo.html#Yubico_YubiKey_IYubiKeyDeviceInfo_IsPinComplexityEnabled) property, which is part of the [IYubiKeyDeviceInfo](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.IYubiKeyDeviceInfo.html) interface. ### Handling PIN complexity errors Applications that support setting or changing PINs should be able to handle the situation when a YubiKey refuses the user value because it violates the PIN complexity policy. The SDK communicates PIN complexity violations by throwing specific exceptions. #### PivSession exceptions During a [PivSession](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.PivSession.html) , PIN complexity violations result in a `System.Security.SecurityException` with the message, `ExceptionMessages.PinComplexityViolation`. If the application uses a [KeyCollector](https://docs.yubico.com/yesdk/users-manual/sdk-programming-guide/key-collector.html) , the violation is reported through the [KeyEntryData.IsViolatingPinComplexity](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.KeyEntryData.html#Yubico_YubiKey_KeyEntryData_IsViolatingPinComplexity) property. PIN complexity violations are reported for following PIV operations: * [PivSession.ChangePin()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.PivSession.html#Yubico_YubiKey_Piv_PivSession_ChangePin) * [PivSession.ChangePuk()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.PivSession.html#Yubico_YubiKey_Piv_PivSession_ChangePuk) * [PivSession.ResetPin()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.PivSession.html#Yubico_YubiKey_Piv_PivSession_ResetPin) #### Fido2Session exceptions During a [Fido2Session](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Fido2Session.html) , PIN complexity violations result in a [Fido2Exception](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Fido2Exception.html) object with a [Status](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Fido2Exception.html#Yubico_YubiKey_Fido2_Fido2Exception_Status) of [CtapStatus.PinPolicyViolation](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.CtapStatus.html#Yubico_YubiKey_Fido2_CtapStatus_PinPolicyViolation) . If the application uses a [KeyCollector](https://docs.yubico.com/yesdk/users-manual/sdk-programming-guide/key-collector.html) , the violation is reported through the [KeyEntryData.IsViolatingPinComplexity](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.KeyEntryData.html#Yubico_YubiKey_KeyEntryData_IsViolatingPinComplexity) property. PIN complexity violations are reported for following FIDO2 operations: * [Fido2Session.SetPin()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Fido2Session.html#Yubico_YubiKey_Fido2_Fido2Session_SetPin) * [Fido2Session.ChangePin()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Fido2Session.html#Yubico_YubiKey_Fido2_Fido2Session_ChangePin) ### Example code For code samples demonstrating how to handle PIN complexity violations, see the [PivSampleCode](https://github.com/Yubico/Yubico.NET.SDK/blob/HEAD/Yubico.YubiKey/examples/PivSampleCode/KeyCollector/SampleKeyCollector.cs) , [Fido2SampleCode](https://github.com/Yubico/Yubico.NET.SDK/blob/HEAD/Yubico.YubiKey/examples/Fido2SampleCode/KeyCollector/Fido2SampleKeyCollector.cs) , and [PinComplexityTests](https://github.com/Yubico/Yubico.NET.SDK/blob/HEAD/Yubico.YubiKey/tests/integration/Yubico/YubiKey/PinComplexityTests.cs) integration tests. [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/sdk-programming-guide/pin-complexity-policy.md/#L1) --- # FIDO2 Blobs ##### Table of Contents FIDO2 Blobs =========== In computer science, a "blob" is a "Binary Large OBject". It is generally used to describe data stored in a database, and is often multimedia files (sound, video, etc.). In FIDO2, a "blob" is arbitrary data. Furthermore, there are two kinds of blobs: * credential * large Credential Blobs ---------------- A credential blob ("credBlob" in the extensions) is a small amount of data stored with a credential. That is, if an authenticator supports the "credBlob" extension, when making a credential it is possible to provide whatever information you want and it will be stored with that newly-made credential. Later on, it is possible to retrieve that data when getting an assertion for the credential. That is, the assertion is returned along with the "credBlob". The standard specifies that if an authenticator allows "credBlobs", it must be able to store, for each credential, at least 32 bytes. The standard also allows authenticators to store more. See the [AuthenticatorInfo.MaximumCredentialBlobLength](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.AuthenticatorInfo.html) property to determine how many bytes can be stored on any specific YubiKey. [This article](https://docs.yubico.com/yesdk/users-manual/application-fido2/cred-blobs.html) describes how to store and retrieve information using the "credBlob" extension. Large Blobs ----------- A large blob is a larger amount of arbitrary data. The standard specifies that an authenticator that supports large blobs must support at least 1024 bytes. However, some of those bytes are "overhead", which the standard estimates to be 64, so that the actual amount of data stored will be around maxSerializedLargeBlobArray - 64 (e.g., if the maximum large blob size is 1024, the total number of bytes that can be stored will be about 960). This total number of bytes is for the entire FIDO2 application, not per credential. For example, if a YubiKey can hold 25 credentials, and you want to store some data with each credential, you will have about 38 bytes per credential. [This article](https://docs.yubico.com/yesdk/users-manual/application-fido2/large-blobs.html) describes how to store and retrieve information using the "largeBlobs" option. [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-fido2/fido2-blobs.md/#L1) --- # ##### Table of Contents Get credential metadata ----------------------- ### Command APDU info | CLA | INS | P1 | P2 | Lc | Data | Le | | --- | --- | --- | --- | --- | --- | --- | | 00 | 10 | 00 | 00 | _data length_ | 0A _encoded info_ | (absent) | The Ins byte (instruction) is 10, which is the byte for CTAPHID\_CBOR. That means the command information is in a CBOR encoded structure in the Data. The data consists of the CTAP Command Byte and the CBOR encoding of the command's parameters. In this case, the CTAP Command Byte is `0A`, which is the command "`authenticatorCredentialManagement`". The CBOR encoding is A3 01 --int-- subcommand = 01 03 --int-- protocol 04 --byte string-- PinUvAuthParam ### Response APDU info #### Response APDU for a successful get Total Length: _variable + 2_ Data Length: _variable_ | Data | SW1 | SW2 | | --- | --- | --- | | _encoded info_ | 90 | 00 | The info returned is CBOR encoded. It has a structure similar to the following. A2 01 --int-- 02 --int-- [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-fido2/apdu/get-cred-metadata.md/#L1) --- # ##### Table of Contents Get the next assertion ---------------------- ### Command APDU info | CLA | INS | P1 | P2 | Lc | Data | Le | | --- | --- | --- | --- | --- | --- | --- | | 00 | 10 | 00 | 00 | 01 | 08 | (absent) | The Ins byte (instruction) is 10, which is the byte for CTAPHID\_CBOR. That means the command information is in a CBOR encoded structure in the Data. The data consists of the CTAP Command Byte and the CBOR encoding of the command's parameters. In this case, the CTAP Command Byte is `08`, which is the command "`authenticatorGetNextAssertion`". There are no command parameters. ### Response APDU info #### Response APDU for a successful get Total Length: _variable + 2_ Data Length: _variable_ | Data | SW1 | SW2 | | --- | --- | --- | | _encoded info_ | 90 | 00 | The info returned is CBOR encoded. It has a structure similar to the following. A5 01 --map-- 02 --byte string-- 03 --byte string-- 04 --map-- 05 --int-- 06 --boolean-- 07 --byte string-- #### Response APDU on timeout or when there is no next assertion Total Length: 2 Data Length: 0 | Data | SW1 | SW2 | | --- | --- | --- | | (no data) | 6F | 30 | [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-fido2/apdu/get-next-assertion.md/#L1) --- # ##### Table of Contents Get large blob data ------------------- ### Command APDU info | CLA | INS | P1 | P2 | Lc | Data | Le | | --- | --- | --- | --- | --- | --- | --- | | 00 | 10 | 00 | 00 | _data length_ | 0C _encoded info_ | (absent) | The Ins byte (instruction) is 10, which is the byte for CTAPHID\_CBOR. That means the command information is in a CBOR encoded structure in the Data. The data consists of the CTAP Command Byte and the CBOR encoding of the command's parameters. In this case, the CTAP Command Byte is `0C`, which is the command "`authenticatorLargeBlobs`". The CBOR encoding has a structure similar to the following. A4 01 --int-- 03 --int-- 05 --byte string-- 06 --int-- [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-fido2/apdu/get-large-blob.md/#L1) --- # ##### Table of Contents Enumerate RPs: get next RP -------------------------- ### Command APDU info | CLA | INS | P1 | P2 | Lc | Data | Le | | --- | --- | --- | --- | --- | --- | --- | | 00 | 10 | 00 | 00 | _data length_ | 0A _encoded info_ | (absent) | The Ins byte (instruction) is 10, which is the byte for CTAPHID\_CBOR. That means the command information is in a CBOR encoded structure in the Data. The data consists of the CTAP Command Byte and the CBOR encoding of the command's parameters. In this case, the CTAP Command Byte is `0A`, which is the command "`authenticatorCredentialManagement`". The CBOR encoding is A3 01 --int-- subcommand = 03 03 --int-- protocol 04 --byte string-- PinUvAuthParam ### Response APDU info #### Response APDU for a successful get Total Length: _variable + 2_ Data Length: _variable_ | Data | SW1 | SW2 | | --- | --- | --- | | _encoded info_ | 90 | 00 | The info returned is CBOR encoded. It has a structure similar to the following. A2 03 --map-- Rp 04 --byte string-- RpIdHash [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-fido2/apdu/enum-rps-next.md/#L1) --- # ##### Table of Contents Set large blob data ------------------- ### Command APDU info | CLA | INS | P1 | P2 | Lc | Data | Le | | --- | --- | --- | --- | --- | --- | --- | | 00 | 10 | 00 | 00 | _data length_ | 0C _encoded info_ | (absent) | The Ins byte (instruction) is 10, which is the byte for CTAPHID\_CBOR. That means the command information is in a CBOR encoded structure in the Data. The data consists of the CTAP Command Byte and the CBOR encoding of the command's parameters. In this case, the CTAP Command Byte is `0C`, which is the command "`authenticatorLargeBlobs`". The CBOR encoding has a structure similar to the following. A5 02 --byte string-- 03 --int-- 04 --int-- 05 --byte string-- 06 --int-- [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-fido2/apdu/set-large-blob.md/#L1) --- # ##### Table of Contents Reset the FIDO application -------------------------- ### Command APDU info | CLA | INS | P1 | P2 | Lc | Data | Le | | --- | --- | --- | --- | --- | --- | --- | | 00 | 10 | 00 | 00 | 01 | 07 | (absent) | The Ins byte (instruction) is 10, which is the byte for CTAPHID\_CBOR. That means the command information is in a CBOR encoded structure in the Data. The data consists of the CTAP Command Byte and the CBOR encoding of the command's parameters. In this case, the CTAP Command Byte is `07`, which is the command "`authenticatorReset`". There are no command parameters. ##### Note The FIDO reset command APDU can be used with YubiKey Bio Multi-protocol Edition keys _only if_ the FIDO application is not "blocked" (check the key's [ResetBlocked](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.YubiKeyDevice.html#Yubico_YubiKey_YubiKeyDevice_ResetBlocked) property to confirm). Otherwise, the [device-wide reset](https://docs.yubico.com/yesdk/users-manual/sdk-programming-guide/bio-mpe.html#resetting-a-yubikey-bio-mpe) must be used instead. ### Response APDU info #### Response APDU for a successful reset Total Length: 2 Data Length: 0 | Data | SW1 | SW2 | | --- | --- | --- | | (no data) | 90 | 00 | #### Response APDU when the YubiKey denies the request This happens when the YubiKey will not reset over the transport through which it is connected. For example, the YubiKey might not allow the reset command over NFC. Total Length: 2 Data Length: 0 | Data | SW1 | SW2 | | --- | --- | --- | | (no data) | 6F | 27 | #### Response APDU when the YubiKey is not allowed to be reset This happens when the YubiKey has been inserted for too long. A YubiKey can only be reset within a time limit of being inserted (the standard specifies 10 seconds). Generally a program will get this error, then instruct the user to remove then reinsert the YubiKey and the command is sent again. Total Length: 2 Data Length: 0 | Data | SW1 | SW2 | | --- | --- | --- | | (no data) | 6F | 30 | #### Response APDU when the YubiKey times out This happens when the YubiKey can be reset, but the user does not touch the contact. If the YubiKey has not been inserted for too long, the Reset command can be executed. But once the YubiKey receives that command it will require touch before completing it. If the user does not touch the YubiKey within a timeout period, it will return this error. Total Length: 2 Data Length: 0 | Data | SW1 | SW2 | | --- | --- | --- | | (no data) | 6F | 3A | [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-fido2/apdu/reset.md/#L1) --- # ##### Table of Contents Enumerate RPs: begin -------------------- ### Command APDU info | CLA | INS | P1 | P2 | Lc | Data | Le | | --- | --- | --- | --- | --- | --- | --- | | 00 | 10 | 00 | 00 | _data length_ | 0A _encoded info_ | (absent) | The Ins byte (instruction) is 10, which is the byte for CTAPHID\_CBOR. That means the command information is in a CBOR encoded structure in the Data. The data consists of the CTAP Command Byte and the CBOR encoding of the command's parameters. In this case, the CTAP Command Byte is `0A`, which is the command "`authenticatorCredentialManagement`". The CBOR encoding is A3 01 --int-- subcommand = 02 03 --int-- protocol 04 --byte string-- PinUvAuthParam ### Response APDU info #### Response APDU for a successful get Total Length: _variable + 2_ Data Length: _variable_ | Data | SW1 | SW2 | | --- | --- | --- | | _encoded info_ | 90 | 00 | The info returned is CBOR encoded. It has a structure similar to the following. A3 03 --map-- Rp 04 --byte string-- RpIdHash 05 --int-- total number of Rps [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-fido2/apdu/enum-rps-begin.md/#L1) --- # The FIDO2 PIN ##### Table of Contents The FIDO2 PIN ============= The FIDO2 standards contain some special requirements on the PIN. One constraint is that the PIN must be supplied as "... the UTF-8 representation of" the "Unicode characters in Normalization Form C". Another constraint is that the PIN must be a minimum length measured in "code points" (the standard declares, "This specification attempts to count code points as an approximation of Unicode characters"), and a maximum length measured in bytes (described further [below](https://docs.yubico.com/yesdk/users-manual/application-fido2/fido2-pin.html#length-restrictions) ). What does that mean? How does one build such a PIN? Unicode characters ------------------ First, let's look at "Unicode characters". The Unicode standard specifies a number for each character supported. For example, the number for cap-A is `U+0041` or `0x000041`. The number for the lower case greek letter pi (π) is `U+03C0`. There is no logical limit to numbers, but currently the maximum Unicode number is `0x10FFFF` (21-bits, or 3 bytes). Unfortunately, it is also possible to create "combinations". There is a "block" of unicode numbers that are "combining diacritical marks", meaning that when they appear in an array of characters, software that can render Unicode will know to combine them with the previous character. For example, the Unicode for lower case `e` is `U+0065`, and the Unicode for "acute accent" is `U+0301` (the acute accent is a small, diagonal line above a letter, sort of like a single quote or forward slash). Combine the two char[] eWithAcute = new char[] { '\u0065', '\u0301' }; and the result is a lower case `e` with an acute accent: é. There is also a Unicode number for an `e` with an acute accent: `U+00E9`. In other words, there are two ways to represent this letter in Unicode. char[] eWithAcute = new char[] { '\u0065', '\u0301' }; char[] sameCharacter = new char[] { '\u00E9' }; Normalization ------------- In order to use a PIN, there has to be one and only one way to encode the characters. Otherwise, someone could enter the correct PIN and if the underlying platform encodes it differently than the original one, then it would not authenticate. So the second element of the PIN is normalization. There is a standard that specifies how to "convert" most of the combinations into single numbers. For example, normalization can convert `0065 0301` into `00E9`. Hence if your PIN is normalized, then there is only one set of numbers to represent it. The standard specifies a number of ways to normalize, and FIDO2 has chosen the technique described as "Form C". UTF-8 ----- Once the PIN has been normalized, it is in essence an array of Unicode numbers. It would be possible to specify that each character in the PIN be a 3-byte (big endian) number. It would also be possible to specify that only 16-bit characters be allowed in a PIN and encode it as an array of 2-byte values. However, the standard specifies encoding it as UTF-8. In this encoding scheme, many characters can be expressed as a single byte, rather than two or three. In addition, there are no `00` bytes in UTF-8. For example, cap-C is `U+0043` and in UTF-8, it is `0x43`. The letter pi is `U+03C0`, and is encoded in UTF-8 as `0xCB80`. In this way, it is possible to save space by "eliminating" many of the `00` bytes. Actually, the encoding scheme is efficient only in that it treats ASCII characters as single bytes. There are non-ASCII Unicode characters that are only one byte (`U+00xx`), and are UTF-8 encoded as two bytes, and some two-byte Unicode characters that are encoded using three bytes, and three-byte Unicode encoded in four bytes. However, because ASCII characters are the most-used characters, the efficienices usually outweigh the inefficiencies. C# and Unicode -------------- Your PIN collection code will likely include some code that does something like this. while (someCheck) { ConsoleKeyInfo currentKeyInfo = Console.ReadKey(); if (currentKeyInfo.Key == ConsoleKey.Enter) { break; } inputData = AppendChar(currentKeyInfo.KeyChar, inputData, ref dataLength); } You read each character in the PIN as a `char` and append it to a `char[]`. You could use the `string` class, but Microsoft recommends not using the `string` class to hold sensitive data. This is because: > System.String instances are immutable, operations that appear to modify an existing instance actually create a copy of it to manipulate. Consequently, if a String object contains sensitive information such as a password, credit card number, or personal data, there is a risk the information could be revealed after it is used because your application cannot delete the data from computer memory. By reading each PIN as a `char`, you are limiting the characters you support to those that can be represented as a 16-bit number in the Unicode space. You would not support `U-10000` to `U+10FFFF`. This will almost certainly be no problem, because these numbers almost exclusively represent emojis and other figures (e.g. U+1F994 is a hedgehog: 🦔), along with rare alphabets (e.g. U+14400 to U+14646 are for Anatolian hieroglyphs). You now have a char array to represent the PIN. ### C# and Normalization At this point, you need to normalize. For example, suppose that someone has a German keyboard and originally set a FIDO2 PIN that included a lower case `u` with an umlaut (ü). That keyboard represented the character as `U+00FC`. But now this person is using a keyboard that has no umlaut so uses the keystrokes `Option-U` followed by `u`. Maybe the platform reads it as `U+00FC`, but maybe it reads it as `U+0075, U+0308`. If the char array is normalized, `U+00FC` will stay `U+00FC`, but `U+0075, U+0308` will be converted to `U+00FC`. How does one normalize in C#? Unfortunately there are no good solutions. Here are three possibilities: ignore the problem and assume no one will use a PIN that really needs normalization, write your own normalization code (or obtain something from a vendor), or use the `String.Normalize` method which would store the PIN in a new immutable string instance. #### Assume PINs will not need normalization This might not be unsafe. While it is possible to have a PIN that when entered is not the same as the normalized version, it is not likely. First of all, a PIN that consists of only ASCII characters is normalized. Second, most people will choose a PIN that does not contain unusual characters. And third, there is a good chance that the keyboard or PIN-reading software will return the normalized version of a character even if some other form is possible. #### Write your own normalization code To do so, you will likely reference the Unicode standard along with the Normalization Annex to develop some class that can read a `char` array and convert those values to the normalized form C. For example, your program might read all the characters and determine if there are any characters from the "combining diacritical marks" block. If so, combine them with the appropriate prior character and map to the normalized value. Alternatively, you might want to use some Open Source normalization code or find some other vendor with some module that can perform the appropriate operations. char[] pinChars = CollectPin(); char[] normalizedPinChars = PerformNormalization(pinChars); #### Normalization using the `string` class As we saw above, holding sensitive data in a `string` carries some risk. Whether or not this is an acceptable risk for your application is something that you will need to determine. If your application's risk profile would allow the use of the `string` class, here's what you can do. char[] pinChars = CollectPin(); char[] normalizedPinChars = PerformNormalization(pinChars); . . . public char[] PerformNormalization(char[] pinChars) { string pinAsString = new string(pinChars); string normalizedPin = pinAsString.Normalize(); return normalizedPin.ToCharArray(); } ### C# and UTF-8 Once you have an array of characters, you can convert that into UTF-8 using the C# `Encoding` class. byte[] utf8Pin = Encoding.UTF8.GetBytes(normalizedPinChars); This byte array is what you pass to the [SetPinCommand](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Commands.SetPinCommand.html) . If you are using the `string` class to normalize, your code could look something like this. char[] pinChars = CollectPin(); string pinAsString = new string(pinChars); string normalizedPin = pinAsString.Normalize(); byte[] utf8Pin = Encoding.UTF8.GetBytes(normalizedPin); Length restrictions ------------------- The standard specifies that a PIN must be at least four code points. Remember, the standard declares, "This specification attempts to count code points as an approximation of Unicode characters". The standard also specifies that a PIN can be no more than 63 bytes. That means after the PIN has been converted to "... the UTF-8 representation of" the "Unicode characters in Normalization Form C", it is a byte array. That byte array's length must be less than or equal to 63. It is possible a YubiKey can be manufactured with a longer minimum length (that is allowed by the standard), and it is possible on some YubiKeys to programmatically increase the minimum length. You can find the minimum PIN length on any YubiKey in the AuthenticatorInfo's [MinimumPinLength](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.AuthenticatorInfo.html#Yubico_YubiKey_Fido2_AuthenticatorInfo_MinimumPinLength) property. The standard does not allow increasing or decreasing the maximum PIN length. [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-fido2/fido2-pin.md/#L1) --- # FIDO2 Authenticator Configuration ##### Table of Contents FIDO2 Authenticator Configuration ================================= The CTAP 2.1 standard, in section 6.11, defines "authenticatorConfig" operations: * Enable enterprise attestation * Toggle "always UV" * Set minimum PIN length * Vendor prototype The SDK supports the first three, but no YubiKey currently supports "vendorPrototype", so for now the SDK does not support it either. YubiKey support --------------- Not all YubiKeys support authenticatorConfig operations. There are two ways to know if a desired operation is supported: * Call the appropriate Fido2Session `Try` method, if it returns `true`, it is supported and the operation was successfully performed * Check the `Options` in the [AuthenticatorInfo](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Fido2Session.html#Yubico_YubiKey_Fido2_Fido2Session_AuthenticatorInfo) . For example, suppose you want to set the minimum PIN length. Just try to set it. if (!fido2Session.TrySetPinConfig(8, null, null)) { // Set min PIN length not supported. } Or you can check the "setMinPINLength" option. // Get the "setMinPINLength" option to know if it is possible to set the minimum PIN length. OptionValue setMinPinLenValue = AuthenticatorInfo.GetOptionValue(AuthenticatorOptions.setMinPINLength); // If the option is True, then it is supported, it is possible to set the min PIN length. if (setMinPinLenValue == OptionValue.True) { return fido2Session.TrySetPinConfig(8, null, null); } // Any other OptionValue and the operation is not supported. For enterprise attestation, call the `Try` method or check the `ep` option. if (!fido2Session.TryEnableEnterpriseAttestation()) { // Enable enterprise attestation not supported. } // Get the "ep" option to know if enterprise attestation is supported. OptionValue epValue = fido2Session.AuthenticatorInfo.GetOptionValue(AuthenticatorOptions.ep); // If the OptionValue is True, then the operation is supported and enterprise // attestation is enabled. if (epValue == OptionValue.True) { // No need to call enable. return true; } // If the OptionValue is False, then the operation is supported but enterprise // attestation is not enabled. if (epValue == OptionValue.False) { return fido2Session.TryEnableEnterpriseAttestation(); } // If the OptionValue is anything else (NotSupported or Unknown), then the // operation is not supported. return false; For toggling always UV, call the `Try` method or check the `alwaysUv` option. Note that this operation will set "alwaysUv" to `true` if it is `false` and vice versa. So if you want to make sure the value is `true` or `false`, then you will likely want to determine its state before toggling. if (!fido2Session.TryToggleAlwaysUv()) { // Toggling always UV not supported. } // Get the "alwaysUv" option to know if toggle always UV is supported. OptionValue alwaysUvValue = AuthenticatorInfo.GetOptionValue(AuthenticatorOptions.alwaysUv); // If this option is True, then it is supported and the YubiKey is currently set // to always require UV. If that's what you want, don't toggle. if (alwaysUvValue == OptionValue.True) { return true; } // If this option is False, then it is supported and the YubiKey is not currently set // to always require UV. If you want it set to be always require UV, then toggle. if (alwaysIvValue == OptionValue.False) { return fido2Session.TryToggleAlwaysUv(); } // Anything else and the operation is not supported. There is an option called "authnrCfg". If that option is present and True, then authenticatorConfig is supported. // Get the "authnrCfg" option to know if authenticatorConfig is supported. OptionValue authnrCfgValue = fido2Session.AuthenticatorInfo.GetOptionValue(AuthenticatorOptions.authnrCfg); However, even if that is True, an individual operation might not be supported. So you might as well ignore "authnrCfg" and just check the specific option. ### vendorPrototype Currently, no YubiKey supports the `vendorPrototype` command. However, if future versions of the YubiKey firmware supports this feature, you will be able to check if a particular YubiKey has this feature by looking at the `VendorPrototypeConfigCommands` property of the [AuthenticatorInfo](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Fido2Session.html#Yubico_YubiKey_Fido2_Fido2Session_AuthenticatorInfo) class. If it is null, then the operation is not supported. Commands and Fido2Session methods --------------------------------- The SDK offers two ways to perform the "authenticator config" operations: call the command classes directly or call methods inside the [Fido2Session](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Fido2Session.html) class. This article will discuss the Fido2Session class and its methods. * [TryEnableEnterpriseAttestation](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Fido2Session.html#Yubico_YubiKey_Fido2_Fido2Session_TryEnableEnterpriseAttestation) * [TryToggleAlwaysUv](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Fido2Session.html#Yubico_YubiKey_Fido2_Fido2Session_TryToggleAlwaysUv) * [TrySetPinConfig](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Fido2Session.html#Yubico_YubiKey_Fido2_Fido2Session_TrySetPinConfig_) Each of these methods will return `false` if the connected YubiKey does not support that operation. You could simply call the method, and if it returns `true`, the operation is supported and it was just executed. It it returns `false`, then it is not supported. AuthToken --------- In order to perform these operations, it is necessary to have a [PinUvAuthToken](https://docs.yubico.com/yesdk/users-manual/application-fido2/fido2-auth-tokens.html) with the [AuthenticatorConfiguration](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Commands.PinUvAuthTokenPermissions.html#Yubico_YubiKey_Fido2_Commands_PinUvAuthTokenPermissions_AuthenticatorConfiguration) permission. The Fido2Session class will obtain the AuthToken automatically if you supply a KeyCollector. If you don't want to build a [KeyCollector](https://docs.yubico.com/yesdk/users-manual/sdk-programming-guide/key-collector.html) , make sure you perform a `Verify` operation with the appropriate permission before calling any of the authenticatorConfig methods. For example: bool isVerified = fido2Session.TryVerifyPin(PinUvAuthTokenPemissions.AuthenticatorConfiguration); Enable enterprise attestation ----------------------------- Before discussing the enable enterprise attestation option, we should look at these two topics: * Attestation * Enterprise attestation ### What is attestation? Attestation is simply a process of providing some sort of data that has two features: * Information identifying the source * A way a recipient can verify the data, and hence, trust the information The data in this process is called an attestation statement. The most common attestation statement is a certificate. A certificate contains information about the source (in the name, extensions, etc.), is signed, and chains to a root allowing recipients to verify the contents. With FIDO2, an attestation statement is built when making a credential. A credential is a public key. The attestation statement contains that public key, information about the relying party (RP) for whom the credential is made, a signature, and a certificate that can be used to verify the public key. The private key partner to the public key in the attestation statement is the key used to sign the attestation statement, so this is similar to a self-signed cert. The RP that receives the attestation statement stores that public key and uses it to verify assertions. But before the RP can trust that public key, it will verify the attestation statement. It does so by first verifying the contents (e.g. is the RP correct?), then verifying the signature. If the public key in the statement verifies the statement, then the contents are correct. Now the RP can use the cert to verify the public key. Of course, the cert itself must be verified, and the RP does that by making sure the contents contain the correct information (e.g. the cert should contain the YubiKey's serial number, and the name should contain something such as "Authenticator Attestation"), and that it chains to the Yubico root. ### What is enterprise attestation? With enterprise attestation, the information in the attestation statement and the cert is specific to an enterprise. For example, it might contain a cert that chains to the enterprise's root, and the cert's name can contain the enterprise's name. When making a credential, it is possible to use this enterprise attestation instead of the "default". However, there are a number of conditions that must be met before this is done. One, the YubiKey must support enterprise attestation (see the section above on [YubiKey support](https://docs.yubico.com/yesdk/users-manual/application-fido2/fido2-authenticator-config.html#yubikey-support) ). Two, the YubiKey must have a list of RPs for which enterprise attestation is possible. This list is, as the standard says, " 'burned into' the authenticator by the vendor." In other words, Yubico must manufacture these YubiKeys with the list, and that list cannot be changed (no additions or subtractions), even if the YubiKey's FIDO2 application is reset. Three, the RP for which the credential is being made must be on that list. Four, the make credential parameters must include the instruction to create an enterprise attestation statement. And finally, five, the enterprise attestation feature must be enabled. This is what calling `TryEnableEnterpriseAttestation` will do. If any of those five conditions are not met, then the YubiKey will generate a default attestation statement. Toggle alwaysUv --------------- Generally when making a credential or getting an assertion, the user must enter the PIN or supply a fingerprint. These are the user verification (UV) operations. There are cases, however, where UV is not required. For example, an RP can set UV to "Discouraged" in a WebAuthn request. On the other hand, some standards, such as FIPS certification, require UV to happen every time, no matter what. Hence, it is possible to override "UV not required" cases by setting the `alwaysUv` option to True. Note that the toggleAlwaysUv will set it from False to True, if it is False, but it will also set it from True to False if it is True. So make sure you check the "alwaysUv" option before calling `TryToggleAlwaysUv`. Set minimum PIN length (and other PIN configuration operations) --------------------------------------------------------------- A YubiKey is manufactured with a default minimum PIN length. It will likely be 4 on regular and 6 on FIPS series YubiKeys. It is possible an organization wants to make sure that users set longer PINs. Call the `TrySetPinConfig` method to do that. While the `setMinPINLength` subcommand defined in the FIDO2 standard can change the minimum PIN length, it can do two other operations as well: specify a list of relying parties that are allowed to see the minimum PIN length, and require that the PIN be changed before any operation that requires UV be allowed to execute. Note that you can call the `TrySetPinConfig` method to do any combination of one, two, or all three of the operations it can perform. ### Minimum PIN length You can know what the current minimum PIN length is by looking at the [AuthenticatorInfo](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.AuthenticatorInfo.html#Yubico_YubiKey_Fido2_AuthenticatorInfo_MinimumPinLength) . If your oganization requires longer PINs, then call `TrySetPinConfig`. However, note that this minimum length is measured in code points. See the user's manual entry on [The FIDO2 PIN](https://docs.yubico.com/yesdk/users-manual/application-fido2/fido2-pin.html) for more information on how to count the number of code points. ### Relying parties that can see the minimum PIN length Normally, an RP is not allowed to know what the minimum PIN length is. However, some RPs might want to accept credentials only from YubiKeys that meet certain security thresholds, such as minimum PIN length. During the make credential operation, the RP will request the minimum PIN length and the client will pass that request along to the YubiKey. At that point, the YubiKey will look through its lists (there are two lists described below) of RPs that are allowed to see the minimum PIN length. If the requester is on one of the lists, the YubiKey will return that number with the credential. So how are these lists populated? The first list is set when the YubiKey is manufactured. This list is immutable, entries cannot be added or removed, even if the YubiKey's FIDO2 application is reset. Most YubiKeys are not manufactured with such a list; this feature is available through a special order process. The second list is set when you supply a list of RPs in your call to `TrySetPinConfig`. This list is mutable, meaning that each time you set this list, all previous entries in that list are replaced. Note that the immutable list is not affected by this second list. This mutable list has a limit to the number of RPs you can supply. The `AuthenticatorInfo` object has a property, [MaximumRpidsForSetMinPinLength](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.AuthenticatorInfo.html#Yubico_YubiKey_Fido2_AuthenticatorInfo_MaximumRpidsForSetMinPinLength) , which specifies the maximum number of RPs you can provide in the list. It is not possible to retrieve the RP IDs on either list. That is, there is no command you can call to have the YubiKey return the RP IDs that have permission to know the minimum PIN length. #### How the client requests the minPINLength When the client calls on the YubiKey to make a credential, it has the option of supplying extensions. One of the extensions is "minPinLength". Pass in that extension with a value of `true`. var mcParams = new MakeCredentialParameters(rp, user) { ClientDataHash = clientDataHash }; mcParams.AddOption(AuthenticatorOptions.rk, true); mcParams.AddExtension("minPinLength", new byte[] { 0xF5 }); If the YubiKey finds the given RP ID on one of its lists, it will return the credential with the minimum PIN length. It will be in the `MakeCredentialData.AuthenticatorData.Extensions` property. If the given RP ID is not on one of the lists, the YubiKey will return the credential, but that exension will not be in the `Extensions` property. MakeCredentialData mcData = fido2Session.MakeCredential(mcParams); if (!(mcData.AuthenticatorData.Extensions is null)) { if (mcData.AuthenticatorData.Extensions!.TryGetValue("minPinLength", out byte[]? eValue)) { minPinLength = eValue![0]; } } When making a credential, the RP will make a request for the minimum PIN length. The client will likely call on the YubiKey to make the credential, including the extension in the parameters, and if the RP is on a list, the minimum PIN length is returned and passed on, and if it is not on a list, the client sends the credential without the minimum PIN length to the RP. It's now up to the RP to decide whether it will accept the credential. If the RP receives a credential without the minimum PIN length, it might reject that credential and the client can now try again. It can contact the user and say the RP is requesting the minimum PIN length and ask if the user is willing to send it. If so, the client can call `TrySetPinConfig` with the RP ID, delete the previous credential (see the [credential management article](https://docs.yubico.com/yesdk/users-manual/application-fido2/fido2-cred-mgmt.html) ), and make a new one. Note that to run `TrySetPinConfig`, the PIN (or fingerprint) must be verified. ### Forcing the PIN to be changed The last operation the `TrySetPinConfig` method can perform is to force the user to change the PIN. This can be done because the minimum PIN length has been changed, or simply because the enterprise wants the PIN to be changed every so often. If you are increasing the minimum PIN length, it might not be necessary to force a PIN change because the YubiKey will force the PIN be changed when the new minimum PIN length is longer than the current PIN. For example, suppose the current minimum PIN length is 4 (the default). Suppose also that the current PIN's length is 6. Let's say the minimum PIN length is set to 6. The YubiKey will not force a PIN change. But if the minimum PIN length is set to 8, the YubiKey will require a PIN change. But if you want to require a PIN change, no matter what, call the `TrySetPinConfig` method with a `forceChangePin` arg of `true`. If the PIN is forced to be changed, no operation that requires user verification (PIN or fingerprint) will be executed until the PIN is changed. For example, if the PIN is forced to be changed, and you call `Fido2Session.EnumerateRelyingParties`, it will not execute. You would need an [AuthToken](https://docs.yubico.com/yesdk/users-manual/application-fido2/fido2-auth-tokens.html) , but you can't get one until the PIN has changed. You can call one of the `VerifyPin` methods, or even one of the `VerifyUv` methods (verify a fingerprint), but they would not work until the PIN has been changed. Once it has been changed, of course, the YubiKey will no longer require a PIN change in order to perform an operation. It is possible to know whether the PIN must be changed. The `AuthenticatorInfo` contains a property, [ForcePinChange](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.AuthenticatorInfo.html#Yubico_YubiKey_Fido2_AuthenticatorInfo_ForcePinChange) , that will be `true` if the PIN must be changed, either because the YubiKey is forcing it, or you called the `TrySetPinConfig` method with a `forceChangePin` arg of `true`. Once the PIN has been changed, that property will be reset to `false`. [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-fido2/fido2-authenticator-config.md/#L1) --- # ##### Table of Contents Make a credential ----------------- ### Command APDU info | CLA | INS | P1 | P2 | Lc | Data | Le | | --- | --- | --- | --- | --- | --- | --- | | 00 | 10 | 00 | 00 | _data length_ | 01 _encoded info_ | (absent) | The Ins byte (instruction) is 10, which is the byte for CTAPHID\_CBOR. That means the command information is in a CBOR encoded structure in the Data. The data consists of the CTAP Command Byte and the CBOR encoding of the command's parameters. In this case, the CTAP Command Byte is `01`, which is the command "`authenticatorMakeCredential`". The CBOR encoding is described in the documentation for [MakeCredentialParameters](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.MakeCredentialParameters.html) . ### Response APDU info #### Response APDU for a successful get Total Length: _variable + 2_ Data Length: _variable_ | Data | SW1 | SW2 | | --- | --- | --- | | _encoded info_ | 90 | 00 | The info returned is CBOR encoded. It has a structure similar to the following. A5 01 --string-- 02 --byte string-- 03 --map-- 04 --boolean-- 05 --byte string-- [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-fido2/apdu/make-credential.md/#L1) --- # PIV GET and PUT DATA ##### Table of Contents PIV GET and PUT DATA ==================== There is a PIV command called [GET DATA](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#get-data) . It is a general purpose command that takes in a "tag" indicating what data to get, and returns a byte array to be parsed by the caller. In this way there is one command for many different data elements, which is more efficient than creating many commands, one for each type of data element. There are currently 21 tags supported in the SDK, so rather than have 21 commands, with GET DATA there is one command with 21 different possible arguments. Some of the data elements to get are available "out of the box". That is, the YubiKey is manufactured with some data elements loaded. For example, the "Discovery" element contains the application AID (so applications can verify they are communicating with a PIV card) and the PIN usage policy. Other elements are initially empty. For example, upon manufacture, there is no "Signature" key or cert (see [Piv Slots](https://docs.yubico.com/yesdk/users-manual/application-piv/slots.html#table-1-list-of-piv-slots) ). The caller must generate or import a key, and obtain a certificate. So until that happens, calling GET DATA with the tag of "Signing Cert" will return "NoData". The [PUT DATA](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#put-data) command will fill those empty elements, or it can replace the data currently in an element. Vendor-Defined Get and Put Data =============================== In addition to the PIV-defined Data Tags, the YubiKey has a set of defined and undefined Data Tags. The Yubico-defined Data Tags specify data specific to YubiKey operations, and the undefined Data Tags allow an application to store its own data. Data format ----------- The standard-defined data elements are specified with standard-defined data formats. To be compliant with the PIV standard, a device must return the data for a supported tag in the format described. For example, the standard specifies that the return from a GET DATA call with the tag of "Discovery" must be the following. 7E 12 4F 0B A0 00 00 03 08 00 00 10 00 01 00 (Application AID, fixed) 5F 2F 02 xx yy (PIN Usage Policy) See the documentation on the [GET DATA command](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#get-data) for descriptions of every tag and the format of data. The vendor-defined elements also have specified formats. If you execute the PUT DATA command through the SDK, then the data need not follow this format. That is, the YubiKey does not enforce the format of the input data based on the tag, although it does enforce size limitations. The reason is to reduce the size of the code on the space-constrained processor that powers a YubiKey. Because of this, it is possible to put "arbitrary" data into many elements. See the section on [overloaded elements](https://docs.yubico.com/yesdk/users-manual/application-piv/get-and-put-data.html#overloaded-elements) for a more detailed discussion. It is possible to verify that data does indeed follow the defined formats. See the [PivDataTagExtensions](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.PivDataTagExtensions.html) . Hence, if you want to use the PUT DATA command and allow only data that follows the formats defined, then validate the data first. When called upon to GET DATA, the YubiKey will return whatever data was loaded. If non-specified data was put into an element, the GET DATA will return that non-specified data. Overloaded elements ------------------- Because the YubiKey itself allows any input data, applications and users (including applications built by Yubico) have "overloaded" some of the elements. There are cases of non-specified data being loaded onto YubiKeys. For example, Yubico overloads the "Printed" element. That element is really for smart cards (think of a credit card and the name, number, bank, etc. printed on the card). Because it is "unused", Yubico stores important information there. The PUT DATA command accepts it because the YubiKey does not enforce the format, and the GET DATA simply returns the loaded data exactly as it was put. Note that you should never overwrite the information in the Printed tag. If you do, it could make your YubiKey unusable. Also, [as described below](https://docs.yubico.com/yesdk/users-manual/application-piv/get-and-put-data.html#undefined-tags) , there is an alternative to overloading a DataTag, namely, use an undefined number as the DataTag. ### Recommendation It almost goes without saying that Yubico does not recommend doing this. If you do overload a data object and store some non-specified data on the YubiKey, the behavior of the YubiKey itself is not defined. It is better to store any undefined or application-specific data in an [undefined DataTag](https://docs.yubico.com/yesdk/users-manual/application-piv/get-and-put-data.html#undefined-tags) . If you feel there is no way to build your application without loading non-specified data into one of the data objects, at the very least do NOT overload these elements: CHUID Cardholder Capability Container (CCC) Discovery Biometric Information Gropt Template (BITGT) Printed certificates: Authentication Signature Key Management Card Authentication Retired 1 - Retired 20 vendor-defined: Attestation Admin Data MSCMAP MSROOTS 1 - MSROOTS 5 ### Certificates If you generate or load a private key into one of the private key slots (e.g. Signature or one of the Retired key slots), you can use PUT DATA to load its accompanying certificate. Although the YubiKey is manufactured with these data elements empty, do not consider them "unused". You should treat them as unavailable for overload. #### Attestation cert The YubiKey is manufactured with an attestation key and cert. This allows you to create an attestation statement (which is an X.509 certificate) that verifies a key was generated by the YubiKey. Rarely will a user (or administrator) want to replace the attestation key and cert. However, it is possible. If you do, it is imperative that you replace the attestation key and cert at the same time. ### MSCMAP and MSROOTS These are vendor-defined elements. These tags were created so that Yubico libraries (minidriver, SDK) can better interface with the Microsoft Smart Card Base Crypto Service Provider (CSP). There will likely never be a scenario where an application will need to use the data the SDK will PUT into and GET from these objects. If your application uses the Base CSP, and you use a YubiKey, any necessary operations with the MSCMAP will be handled by the SDK. Undefined tags -------------- The YubiKey will store data in a storage location as long as the DataTag is a number between `0x005F0000` and `0x005FFFFF` (inclusive). Only 45 of those numbers are defined to hold specific data. Hence, if you want to store data other than what is defined, pick one of the undefined numbers, there are over 12 million of them. The [User's Manual Entry](https://docs.yubico.com/yesdk/users-manual/application-piv/piv-objects.html) on PIV Data Objects has tables listing the defined tags ([PIV-defined](https://docs.yubico.com/yesdk/users-manual/application-piv/piv-objects.html#datatagtables) and [Yubico-defined](https://docs.yubico.com/yesdk/users-manual/application-piv/piv-objects.html#datatagtable2) ), along with a table listing the [undefined numbers](https://docs.yubico.com/yesdk/users-manual/application-piv/piv-objects.html#datatagtable3) . You can use the PUT DATA and GET DATA commands to store any data you like under those numbers, so there is no need to overload an existing defined Data Tag. The only possible exception would be if you want to store some data PIN-protected. Any data stored under the tags Fingerprints (`0x005FC103`), Facial Image (`0x005FC108`), Printed (`0x005FC109`), and Iris (`0x005FC121`) is retrievable only in a session where the PIN has been verified. Hence, we say the data stored under these numbers is PIN-protected. Data stored under any other Data Tag, including all undefined numbers, is available to anyone who has access to the YubiKey itself. If you want to store data PIN-protected, you will have to overload one of the PIN-protected Data Tags. However, you should not store any data under the Printed Data Tag, Yubico already uses that Data Tag to store specific PIN-protected data. Parsing the response -------------------- When you execute GET DATA using the [GetDataCommand](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.Commands.GetDataCommand.html) , you get a response object: [GetDataResponse](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.Commands.GetDataResponse.html) . You can now call the `GetData` method to see the data returned. The data returned is a byte array. It is whatever was in the element. If it follows the standard, it will be an encoding. Each response's encoding is documented in the [PIV Commands](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#get-data) page. It will be your responsibility to parse the encoding or extract the data you want. The reason we do not parse it is because there are many data formats. There are other classes that deal with parsing some of the data objects returned by a GET DATA or GET VENDOR DATA command. Probably the most useful will be the class that can parse a byte array containing an encoded cert, and build an `X509Certificate2` object. [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-piv/get-and-put-data.md/#L1) --- # Credential ##### Table of Contents Credential ========== The core component of the YubiHSM Auth application is the credential, which contains a cryptographic key set that is used to establish secure sessions with a YubiHSM 2. Once a credential is added ( see [Add Credential](https://docs.yubico.com/yesdk/users-manual/application-yubihsm-auth/commands/add-credential.html) ), it cannot be changed or modified in any way. Adding or deleting a YubiHSM Auth credential requires a 16-byte management key. Properties ---------- Each credential contains four major properties. The [cryptographic key set](https://docs.yubico.com/yesdk/users-manual/application-yubihsm-auth/objects/credential.html#cryptographic-key-set) is the property used to calculate session keys. The other properties are used for identification ([label](https://docs.yubico.com/yesdk/users-manual/application-yubihsm-auth/objects/credential.html#label) ) and access control ([password](https://docs.yubico.com/yesdk/users-manual/application-yubihsm-auth/objects/credential.html#password) and [touch requirement](https://docs.yubico.com/yesdk/users-manual/application-yubihsm-auth/objects/credential.html#touch-requirement) ). ### Cryptographic key set The YubiHSM 2 uses a [secure channel protocol](https://docs.yubico.com/yesdk/users-manual/application-yubihsm-auth/interacting-yubihsm-2.html#yubihsm-2-secure-channel) based on symmetric keys. This means that both parties (YubiKey and YubiHSM 2) must have identical copies of the key set in order to create a secure session. The key set is a pair of AES-128 keys (each 128 bits in length): * ENC: an AES-128 key used for deriving keys for command and response encryption * MAC: an AES-128 key used for deriving keys for command and response authentication The key set must be generated on the host machine and then stored on both the YubiKey (as a YubiHSM Auth credential) and the YubiHSM 2. ### Label This is a unique identifier for the credential. It is a UTF-8 encoded string and must be between 1 and 64 bytes long. ### Password This 16-byte password is always required when using the credential to calculate session keys. There is a limit of eight retries, after which the credential will be permanently deleted. The retry counter is reset when the correct password is supplied. ### Touch requirement Optionally, the credential may be configured to require touch when using the credential to calculate session keys. A touch requirement provides an additional layer of security by ensuring a user is physically present and in control of the YubiKey. The YubiKey has a capacitive touch sensor that cannot be controlled by software. [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-yubihsm-auth/objects/credential.md/#L1) --- # OTP application how-to guides ##### Table of Contents OTP application how-to guides ============================= The articles in this section provide examples on how to accomplish common operations with the OTP application and include additional discussions on how/when to call various methods from the respective [Yubico.YubiKey.Otp.Operations classes](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.html) . The topics covered include: * [How to program a slot with a Yubico OTP credential](https://docs.yubico.com/yesdk/users-manual/application-otp/how-to-program-a-yubico-otp-credential.html) * [How to program a slot with a static password](https://docs.yubico.com/yesdk/users-manual/application-otp/how-to-program-a-static-password.html) * [How to program a slot with a challenge-response credential](https://docs.yubico.com/yesdk/users-manual/application-otp/how-to-program-a-challenge-response-credential.html) * [How to calculate a response code for a challenge-response credential](https://docs.yubico.com/yesdk/users-manual/application-otp/how-to-calculate-a-challenge-response-code.html) * [How to delete a slot’s configuration](https://docs.yubico.com/yesdk/users-manual/application-otp/how-to-delete-a-slot-configuration.html) * [How to program a slot with an HMAC-SHA1 OATH-HOTP credential](https://docs.yubico.com/yesdk/users-manual/application-otp/how-to-program-an-hotp-credential.html) * [How to retrieve a slot’s status](https://docs.yubico.com/yesdk/users-manual/application-otp/how-to-retrieve-slot-status.html) * [How to configure NDEF to use a slot to generate an OTP](https://docs.yubico.com/yesdk/users-manual/application-otp/how-to-configure-ndef.html) * [How to read information from an NDEF tag](https://docs.yubico.com/yesdk/users-manual/application-otp/how-to-read-ndef-information.html) * [How to update slot settings](https://docs.yubico.com/yesdk/users-manual/application-otp/how-to-update-slot-settings.html) * [How to swap slot configurations](https://docs.yubico.com/yesdk/users-manual/application-otp/how-to-swap-slot-configs.html) * [How to set, reset, remove, and use slot access codes](https://docs.yubico.com/yesdk/users-manual/application-otp/how-to-slot-access-codes.html) Working with the OTP operations classes --------------------------------------- Before you can run the example code in the how-to articles, your application must: 1. Connect to a particular YubiKey available through the host machine via the [YubiKeyDevice class](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.YubiKeyDevice.html) . 2. Create an instance of the [OtpSession class](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.OtpSession.html) , which allows you to connect to the OTP application of that YubiKey. These steps are covered in depth in the [SDK programming guide](https://docs.yubico.com/yesdk/users-manual/sdk-programming-guide/making-a-connection.html) . ##### Note Many of the how-to guides create the OtpSession instance with `using (OtpSession otp = new OtpSession(yKey))`. This assumes that `yKey` is an IYubiKeyDevice object that represents the YubiKey. ### Additional macOS requirement: enable input monitoring Developers working with the SDK on macOS must enable input monitoring in order to interact with a YubiKey's OTP application. The YubiKey acts as a keyboard, and the SDK needs to be able to "monitor" it in order to interact with it. If you do not enable it, the SDK will throw an exception when trying to create an instance of the OtpSession class: ![Exception thrown when trying to create OtpSession instance](https://docs.yubico.com/yesdk/images/input-monitoring-error.png "Exception thrown when trying to create an OtpSession instance") To enable input monitoring, open **System Preferences** and go to **Security & Privacy**. Scroll down and click on \* _Input Monitoring_\*. Check the box next to the application that needs to monitor YubiKeys via the SDK, such as Visual Studio. You may need to click the lock icon in the bottom left corner and enter your Mac user password in order to make changes. ![Input monitoring settings](https://docs.yubico.com/yesdk/images/input-monitoring.png "Input monitoring settings in macOS") If you are building a macOS application, your users must also go through these same steps to enable input monitoring. Additionally, developers must add the following entitlements to their Entitlements.plist file (Entitlements.plist is created automatically when you create a new macOS application project in Visual Studio): * `com.apple.security.smartcard` * `com.apple.security.device.usb` ### Fluent interface The API implements a [fluent interface](https://en.wikipedia.org/wiki/Fluent_interface) . This design allows you to easily and concisely chain class methods together. For example: using (OtpSession otp = new OtpSession(yKey)) { otp.ConfigureYubicoOtp(Slot.ShortPress) .UseSerialNumberAsPublicId() .UsePrivateId(privateId) .UseKey(aesKey) .Execute(); } The code above shows how to configure the short-press slot of a YubiKey to generate Yubico OTPs (and sets the public ID to the key's serial number, the private ID to `privateId`, and the AES secret key to `aesKey`). ### The Execute() method You may notice in the how-to guide examples that the [Execute() method](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.OperationBase-1.html#Yubico_YubiKey_Otp_Operations_OperationBase_1_Execute) is called after the other OTP operations methods. \*\*In order to apply changes to the YubiKey from any Yubico.YubiKey.Otp.Operations class method, you must call Execute(). \*\* So for the previous example, this means that the Yubico OTP configuration will not be applied to the short-press slot of the YubiKey until Execute() is called. ### Slot reconfiguration and access codes If a slot you wish to reconfigure is protected by an access code, you must provide that access code with `UseCurrentAccessCode()` during the reconfiguration operation. Otherwise, the operation will fail and throw the following exception: `System.InvalidOperationException has been thrown. YubiKey Operation Failed. [Warning, state of non-volatile memory is unchanged.]` For more information on slot access codes, please see [How to set, reset, remove, and use slot access codes](https://docs.yubico.com/yesdk/users-manual/application-otp/how-to-slot-access-codes.html) . [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-otp/how-tos-overview.md/#L1) --- # FIDO2 Authentication (PIN and Fingerprint) ##### Table of Contents FIDO2 Authentication (PIN and Fingerprint) ========================================== In order to perform many FIDO2 operations, authentication is required. With the YubiKey, authentication will be either a PIN or a fingerprint. However, the rules of authentication with FIDO2 are not straightforward. For example, a PIN does not authenticate a session, but rather allows you to obtain a "token" from the YubiKey which is then passed back to the YubiKey as permission to perform various operations. Furthermore, there are times when you need more than one token (you need to authenticate or verify the PIN more than once) in a single session. In order to perform authentication in your application, there are two main options when calling on the SDK to perform FIDO2 operations: * Use only the [Fido2Session](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Fido2Session.html) APIs, supply a [KeyCollector](https://docs.yubico.com/yesdk/users-manual/sdk-programming-guide/key-collector.html) , and let the SDK handle both authentication logic and making calls to the appropriate PIN or fingerprint verification methods when needed. * Learn the rules of FIDO2 authentication and make sure your code calls the appropriate `TryVerify` methods (or the appropriate commands, e.g. `GetPinUvAuthTokenUsingPinCommand`) before performing the relevant operations. If you choose the first option (automatic auth by the SDK), then you must build a KeyCollector. See the articles ([here](https://docs.yubico.com/yesdk/users-manual/sdk-programming-guide/key-collector.html) and [here](https://docs.yubico.com/yesdk/users-manual/sdk-programming-guide/key-collector-touch.html) ) for more information on this topic. The FIDO2 sample code has a KeyCollector to help you build one for your application. There is also further information on PINs, fingerprints, and FIDO2 authentication in the following articles (make sure you read at least the first one on the rules of PIN composition): * [The FIDO2 PIN](https://docs.yubico.com/yesdk/users-manual/application-fido2/fido2-pin.html) * [The FIDO2 fingerprint and Bio Enrollment](https://docs.yubico.com/yesdk/users-manual/application-fido2/fido2-bio-enrollment.html) * [AuthTokens, permissions, PIN/UV, and AuthParams](https://docs.yubico.com/yesdk/users-manual/application-fido2/fido2-auth-tokens.html) * [The SDK's AuthToken retrieval logic](https://docs.yubico.com/yesdk/users-manual/application-fido2/sdk-auth-token-logic.html) * [Touch and fingerprint notification](https://docs.yubico.com/yesdk/users-manual/application-fido2/fido2-touch-notification.html) * [PIN/UV authentication protocols](https://docs.yubico.com/yesdk/users-manual/application-fido2/pin-uv-auth-protocols.html) If you choose the second option, possibly because you don't want to build a KeyCollector, then you must learn the standard's rules of authentication. You can do that either by studying the FIDO2 CTAP2.1 standard or the articles listed above, or ideally both. Then you must call the appropriate Verify methods before operations. This could require specifying permissions. It could also require making multiple verification calls in a single session. If you develop a strong understanding of the FIDO2 authentication rules, then you will be able to do this. [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-fido2/fido2-auth.md/#L1) --- # TLV ##### Table of Contents TLV === A "tag-length-value" (TLV) construction is a byte array that has a tag indicating what the data is, a length specifying its length (in bytes/octets), and the value itself. For example, here is one possible TLV. 08 04 72 26 9A 33 ^ ^ ^ ^ | | |---------| | | value | - length - tag The TLV allows groups of variable-length data elements to be combined into one buffer. To parse a collection of elements, a reader must know where one element ends and the next begins, and which element is which. A standard will specify a schema for the data. It is the programmer's job to "convert" that schema into a byte array. For example, this could be a schema for an RSA public key. schema for RSA public key: { 51 L1 modulus || 52 L2 publicExponent } For this schema, the tag of 51 means modulus L1 is the length of the modulus the tag of 52 means public exponent L2 is the length of the publicExponent As a stream of octets, it might look something like this. 51 81 80 A5 29 ... 3B 52 03 01 00 01 The reader sees the 51 tag and knows the modulus follows The reader sees the 81 and knows the length is represented as the one following octet The reader sees the 80 and knows the length is 128 (0x80 = decimal 128) The reader can now read the next 128 bytes as the modulus The reader sees the 52 tag and knows the public exponent follows The reader sees the 03 and knows the length of the value is 3 (because the first length octet is not 8x, then that is the length) The reader can now read the next 3 bytes as the public exponent ASN.1 and DER ------------- There is a standard called ASN.1 (Abstract Syntax Notation One), and another standard called DER (Distinguished Encoding Rules). These make up one possible TLV implementation. The ASN.1 standard specifies how to make definitions of collections of data, and the DER standard specifies how to "convert" those definitions into actual "bytes on the wire". In other words, there is the concept of "TLV" and ASN.1 with DER is one specific way to build a TLV system. The TLV classes in the SDK are not specifically ASN.1 and DER, they are more general. The SDK's TLV classes can be used to build and parse ASN.1/DER constructions. However, the SDK needs to build and parse TLV constructions that do not adhere to the ASN.1 and DER standards. For example, with ASN.1 and DER, a tag describes what type of data follows, such as INTEGER, UTCTime, or UTF8String. An INTEGER always has a tag of `02`. For example, both the RSA modulus and public exponent will have tags of `02`. However, in the standards that the SDK follows, a tag often describes the data that follows, not its type. Hence, a modulus can have a tag of `51` and the public exponent can have a tag of `52`. TLV classes in the SDK ---------------------- The two classes needed to build and parse TLV constructions are Yubico.Core.TlvWriter Yubico.Core.TlvReader These classes build and parse TLV constructions where * The tag is either one or two octets * The length follows the DER standard for length construction and represents the number of bytes/octets of the value * These classes build and parse two kinds of TLV constructions: concatenation and nested. ### Tag The tag can be one or two octets. How does the writer class know whether to write one or two octets? The input is an `int` (a 4-byte type). The minimum tag is `0x00000000` and the maximum tag is `0x0000FFFF`. For example, tlvWriter.WriteValue(0x0000725F, value); In this case, the writer class knows this is a two-octet tag. When reading a TLV, how does the reader class know a tag is one or two octets? For example, if it sees `72 5f`, how does it know this is a two-octet tag or a one-octet tag with a length of `5F`? The answer is that the caller must supply the expected tag. That is, the TLV does not simply read, it reads according to the schema. value = tlvWriter.ReadValue(0x725F); In this case, the schema says that at this point in the encoding, the value has a tag of `725F`. So when reading, your code says, "Read the next element, the expected tag is `725F`." There is a method, `PeekTag`, that allows you to look at the next tag before decoding. Use this if the tag might be one of a number of values. Take a look at the tag, then if it is one of the acceptable values, call the `ReadValue` method with the tag returned by `Peek`. ### Length It is important to know that the length describes the number of bytes/octets, which is not necessarily the number of items being represented. For example, if a schema specifies a tag for two 32-bit integers, the TLV could be something like this. 7F 08 00 00 01 00 ff ff ff ff This represents two integers: `0x00000100 = decimal 256` and `0xffffffff = decimal -1`. The length in the TLV is 8, meaning there are 8 octets. The length is not 2, even though this TLV represents 2 things. The length is constructed following the DER standard. actual length encoded length example -------------------------------------------------------------- 0x00 - 0x7f one length octet 20 (decimal 32) 0x80 - 0xFF two octets: 81 81 (decimal 129) 81 length 81 A7 (decimal 167) 0x0100 - 0xFFFF three octets: 82 01 00 (decimal 256) 82 L1 L2 82 15 4B (decimal 5,451) 0x010000 - 0xFFFFFF four octets: 83 01 83 B0 (decimal 99,248) 83 L1 L2 L3 When reading, these rules mean * If the first length octet `< 0x80`, that is the length. * If the first length octet is `0x8x`, then the length is the next `x` octets. * DER allows for a 15 octet length (`8F` as the first length octet), however, virtually all implementatations will limit the number of octets that make up the length to 3, 4, or 5. The TLV classes in the SDK limit the length to three octets (e.g. `83 01 00 00`, decimal 65,536). * If the first length octet is `> 0x8y`, where `y` is the maximum count for the implementation, that is an error. For the SDK, `y` is 3, so `84` is unsupported, but `0x92` or `0xC7` are also invalid. Note that a length of zero is allowed. That means there is no following data. ### Concatenation and nested With concatenation, the encoded data is simply TLV || TLV || ... || TLV For example: 01 01 86 02 02 05 05 08 04 01 26 9A 33 or for better visual clarity: 01 01 86 02 02 05 05 08 04 01 26 9A 33 With nested, there is more of a tree structure, where a collection of elements is packaged into a "parent" TL: TL { TLV || ... || TLV } For example: 81 0D 01 01 86 02 02 05 05 08 04 01 26 9A 33 or for better visual clarity: 81 0D 01 01 86 02 02 05 05 08 04 01 26 9A 33 The nested is a representation of one collection of multiple elements. In the example above, there was one thing with a tag of 81 and a length of `0D = decimal 13`. The 13 octets that made up the contents of that one thing happened to be 3 different elements. It is certainly possible to have a nested TLV inside another nested TLV. For example, a standard might specify a schema such as this. 7A L1 { 01 01 algorithm, 7F L2 { 02 L3 challenge, 05 L4 response } } 7A 19 01 01 07 7F 14 02 08 38 86 D9 A9 0C 91 EE 71 05 08 81 1B 40 D5 70 AB 35 0F ### Build/Encode To build a TLV construction (to create an encoding) using the SDK, use the `TlvWriter` class. #### Concatenation Suppose the standard calls for a concatenation. For example, a schema might look like the following. { 01 algorithm || 02 retry counts || 08 serial number } The code to write it could look like this. var tlvWriter = new TlvWriter(); tlvWriter.WriteByte(0x01, 0x07); tlvWriter.WriteValue(0x02, retryCountArray); tlvWriter.WriteInt32(0x08, serialNumber); byte[] encoding = tlvWriter.Encode(); tlvWriter.Clear() In the example, you simply instantiate, then add each of the elements. There are a number of ways to specify the value: as a byte, an int, a byte array, and more. The `Encode` method will build the encoding. It will be able to compute all the lengths, knowing which require a single byte (length < 0x80) and which require a longer length construction (e.g. `81 94`). If there is no data, pass in an empty `ReadOnlySpan`. // Suppose the schema calls for a key name with tag `0x78`, but // there is no name. tlvWriter.WriteValue(0x78, ReadOnlySpan.Empty); // When this gets encoded, the element will be written as // 78 00 The `Clear` method is optional. This calls on the `TlvWriter` object to overwrite any data it copied. This is discussed further later on. #### Nested elements A standard might specify a schema with nested elements, such as the following. // 7A L1 { 01 01 algorithm, 02 L2 challenge } // Build a TlvWriter, specify the NestedTlv, and then add each of the elements. var tlvWriter = new TlvWriter(); using (tlvWriter.WriteNestedTlv(0x7A)) { tlvWriter.WriteByte(0x01, 0x07); tlvWriter.WriteValue(0x02, challengeArray); } byte[] encoding = tlvWriter.Encode(); tlvWriter.Clear(); It is possible you have a Nested TLV inside another Nested TLV. // 7A L1 { 01 01 algorithm, 7F L2 { 02 L3 challenge, 05 L4 response }, 09 01 digest } var tlvWriter = new TlvWriter(); using (tlvWriter.WriteNestedTlv(0x7A)) { tlvWriter.WriteByte(0x01, 0x07); using (tlvWriter.WriteNestedTlv(0x7F)) { tlvWriter.WriteValue(0x02, challengeArray); tlvWriter.WriteValue(0x05, responseArray); } tlvWriter.WriteByte(0x09, 0x22); } byte[] encoding = tlvWriter.Encode(); tlvWriter.Clear(); #### WriteEncoded Sometimes you have something already encoded and you need to add it to an existing schema. In that case, there is a `WriteEncoded`. This does not compute the length of an input value, it simply copies the entire input into the existing schema. For example, suppose you have a schema that specifies one element as a certificate. You have code already that builds a certificate encoding. You don't want to copy that code every place a certificate is needed. When you need to add a certifiate to a schema, call the method that builds the encoding. You now have the full TLV of a certificate, not just the value. Call `WriteEncoded`. byte[] encodedCert = certObject.GetEncodedCertificate(); var tlvWriter = new TlvWriter(); using (tlvWriter.WriteNestedTlv(0x30)) { tlvWriter.WriteString(0x0C, someName); tlvWriter.WriteValue(0x04, someReference); tlvWriter.WriteEncoded(encodedCert); } byte[] encoding = tlvWriter.Encode(); tlvWriter.Clear(); If you had called `WriteValue` with the fully encoded certificate as the value, the `TlvWriter` would have written out an "extra" tag and length. #### Clear Suppose you are encoding an RSA private key. You provide to the `TlvWriter` class the two primes among other sensitive information. You want this data to appear in memory for as short of a time as possible (see the User's Manual article on [sensitive data](https://docs.yubico.com/yesdk/users-manual/sdk-programming-guide/sensitive-data.html) ). Has the `TlvWriter` object copied any of that data into a new buffer? If so, you want it to be overwritten. Call the `Clear` method when you are done with the writer object. Any information it copied will be overwritten. Any reference copies will be ignored. ### Parse/Decode To parse a TLV construction (to decode an encoding) using the SDK, use the `TlvReader` class. #### Concatenation Suppose the standard calls for a concatenation and you have a buffer that purportedly contains an encoding of the definition. // { 01 algorithm || 02 retry counts || 08 serial number } // // Suppose the encoding is // 01 01 07 02 02 05 05 08 04 01 26 9A 33 var tlvReader = new TlvReader(encoding); byte algorithm = tlvReader.ReadByte(0x01); ReadOnlyMemory retryCounts = tlvReader.ReadValue(0x02); int serialNumber = tlvReader.ReadInt32(0x08); The `TlvReader` object you instantiate will copy a reference to the `encoding`. The object begins life with an internal position of zero, the beginning of the `encoding`. When you call the `ReadByte` method, the object will look at its internal position and see if the tag there is `01`. If it is, it will read the byte that is the value of the TLV. It will then move the position to the byte just beyond the current encoding. In this case, it moves to position 3, where the first `02` is. Finally, it will return the byte it read. The next call, `ReadValue`, will verify the next tag is what was expected, determine the length of the value, build a return `ReadOnlyMemory`, move the internal position (to position 7, the `08`), and return the newly created `ReadOnlyMemory` object. This `ReadOnlyMemory` object will "point" to the input encoding array. That is, the reader object will not copy the data, it will only point to where, in the encoding, the value begins. If you ran the experiment where you decoded this element, then changed `encoding[5]`, that change would be reflected in the return value. // encoding = 01 01 07 02 02 05 05 08 04 01 26 9A 33 . . . ReadOnlyMemory retryCounts = tlvReader.ReadValue(0x02); // encoding[5] is 05 // retryCount.Span[0] is 05 // set encoding[5] = 0x06 // now look at retryCount.Span[0], it is also 06 Finally, read the last element as a 32-bit integer. Note that the `ReadByte` method will fail if the length of the element it is reading is not one, and the `ReadInt32` method will fail if the length of the element it is reading is not exactly 4. If there is no data (there is a tag and the length is `00`), the Read will return an empty `ReadOnlyMemory` object (`value.Length` is 0). Note also that there is no `Clear` method for `TlvReader`. That class never copies data, it only copies references. #### Nested Suppose the standard calls for a nested and you have a buffer that purportedly contains an encoding of the definition. // 7A L1 { 01 01 algorithm, 02 L2 challenge } // // Suppose the encoding is // 7A 0D 01 01 07 02 08 38 86 D9 A9 0C 91 EE 71 // Or for better visual clarity // 7A 0D // 01 01 // 07 // 02 08 // 38 86 D9 A9 0C 91 EE 71 You could read the entire encoding as a concatenation of one element. var tlvReader = new TlvReader(encoding); ReadOnlyMemory value = tlvReader.ReadValue(0x7A); // The contents of value are // 01 01 07 02 08 38 86 D9 A9 0C 91 EE 71 You now have a new `ReadOnlyMemory` buffer, the value. This new buffer contains a simple concatenation with two elements. You could create a new `TlvReader` with this data, and read the two elements. var tlvReader = new TlvReader(encoding); ReadOnlyMemory value = tlvReader.ReadValue(0x7A); TlvReader anotherReader = new TlvReader(value); byte algorithm = anotherReader.ReadByte(0x01); ReadOnlyMemory challenge = anotherReader.ReadValue(0x02); There is a more efficient way to do this. var tlvReader = new TlvReader(encoding); TlvReader nestedReader = tlvReader.ReadNestedTlv(0x7A); byte algorithm = nestedReader.ReadByte(0x01); ReadOnlyMemory challenge = nestedReader.ReadValue(0x02); You create the `TlvReader` object for the entire encoding. When you read the nested construction, it creates a new `TlvReader`, this one able to read only the nested data. This means you don't have to create an intermediate `ReadOnlyMemory` and make a call to create a new `TlvReader`. This will be even more efficient when there are nesteds in nesteds. After making the call to read a nested, you have a new reader object. Use that object to read what is under the nested tag. Upon instantiation, the original `tlvReader` has a reference to the encoding and its internal position is zero. After calling `ReadNestedTlv`, it moves to the end of the current element it is reading. The current element it is reading happens to be the entire encoding, so it moves to the end (a call to `tlvReader.HasData` would return `false`). The new `nestedReader` object also points to the encoding, but its internal position is 2, pointing to the first element in the nested construction. #### Multiple nesteds Suppose you have an encoding like this. // 30 17 // 02 01 // 01 // 30 0A // 04 04 // 11 22 33 44 // 0C 02 // 38 36 // 03 05 // 00 77 88 99 AA BB var tlvReader = new TlvReader(encoding); // tlvReader points to position 0. TlvReader nestedReader = tlvReader.ReadNestedTlv(0x30); // tlvReader points to position 25 (0x19), beyond the end, HasData is false // nestedReader points to position 2 byte version = nestedReader.ReadByte(0x02); // nestedReader points to position 5 TlvReader internalReader = nestedReader.ReadNestedTlv(0x30); // nestedReader points to position 17 (0x11) // internalReader points to position 7 ReadOnlyMemory valueA = internalReader.ReadValue(0x04); // internalReader points to position 13 (0x0D) // valueA is a Slice of encoding, from position 9 to 12 ReadOnlyMemory valueB = internalReader.ReadValue(0x0C); // internalReader points to position 17 (0x11) // this is beyond the end of this element, so HasData is false // valueB is a Slice of encoding, from position 15 to 16 ReadOnlyMemory valueC = nestedReader.ReadValue(03); // nestedReader points to position 25 (0x19) // this is beyond the end of this element, so HasData is false // valueC is a Slice of encoding, from position 19 to 24 When you read an element, you can read it as a value, even if it is nested. If you want to read what is in a nested, you need to create a new reader object, either by reading the value and calling `new TlvReader` yourself, or by calling `ReadNested`. The `ReadNestedTlv` method builds a new `TlvReader` (e.g. internalNested), but this new reader is only able to see the bytes that made up that element. It is looking at a Slice of the original encoding. #### Reading encoded Another read method is `ReadEncoded`. This reads an entire element, returning a "pointer" to the full TLV of that element, not just the V. For example, suppose we have this encoding. // 30 17 // 02 01 // 01 // 30 0A // 04 04 // 11 22 33 44 // 0C 02 // 38 36 // 03 05 // 00 77 88 99 AA BB var tlvReader = new TlvReader(encoding); TlvReader nestedReader = tlvReader.ReadNestedTlv(0x30); byte version = nestedReader.ReadByte(0x02); ReadOnlyMemory toBeSigned = nestedReader.ReadEncoded(0x30); ReadOnlyMemory valueC = nestedReader.ReadValue(03); Look inside the `toBeSigned` buffer and you will see 30 0A 04 04 11 22 33 44 0C 02 38 36 toBeSigned.Length will be 12 This might be useful if you have code already written to decode something very complicated. For example, suppose one element is a certificate. You don't want to write the certificate parsing code every time. You have a method for that. But that method needs the entire certificate encoding. Or maybe the data to sign (or verify) is the full encoding of something, and that something is an element in another encoding. You need to extract its entire encoding: TLV, not just V. #### Reading optional values Suppose you are reading a construction where one or more of the elements are optional. Or maybe you are reading a construction where the order of elements is optional. For example, maybe the schema is { 81 L1 RsaModulus || 82 L2 RsaPublicExponent || 87 L3 EcPublicPoint } -- If a modulus is present, there must be a public exponent, and there must not be a public point. -- The order of modulus and public exponent is not prescribed. -- If a public point is present, there must not be a modulus or public exponent. In this case, there are a number of valid encodings 81 82 01 00 modulus 82 03 01 00 01 82 03 01 00 01 81 82 01 00 modulus 87 41 publicPoint The following code looks correct, but it will lead to an exception. var reader = TlvReader(encoding); ReadOnlyMemory modulus = reader.ReadValue(0x81); ReadOnlyMemory pubExpo = reader.ReadValue(0x82); ReadOnlyMemory pubPoint = reader.ReadValue(0x87); Something is not going to be there, so at some point the `Read` will throw an exception, because it will run out of data or an expected tag is missing. In this case, you must find out what the next tag is before calling `ReadValue`. There is a method in `TlvReader` to do that. ReadOnlyMemory modulus; ReadOnlyMemory pubExpo; ReadOnlyMemory pubPoint; var reader = TlvReader(encoding); // If the next tag is modulus, read modulus, then expo, and // nothing else. // If the next tag is expo, read expo, then modulus, and // nothing else. // If the next tag is public point, read the public point and // nothing else. int nextTag = reader.PeekTag(); switch (nextTag) { case 81: modulus = reader.ReadValue(0x81); pubExpo = reader.ReadValue(0x82); break; case 82: pubExpo = reader.ReadValue(0x82); modulus = reader.ReadValue(0x81); break; case 87: pubPoint = reader.ReadValue(0x87); break; default: ReportError(); break; } [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/support/support-tlv.md/#L1) --- # FIDO U2F Reset ##### Table of Contents FIDO U2F Reset ============== It is possible to reset the U2F application on version 4 FIPS series YubiKeys. A reset will replace the U2F key along with the attestation key and its cert. It will also remove the PIN requirement, if there is one. In other words, it will reset the U2F application to factory default settings. However, there are some caveats: * Only version 4 FIPS series YubiKeys can be reset. No other YubiKeys support U2F reset. This includes non-FIPS version 4 and version 5 FIPS series YubiKeys. * The YubiKey will no longer be able to perform authentication with credentials previously created with the U2F application by that YubiKey. * After a U2F reset, the YubiKey will no longer be in FIPS mode. * After reset, it is not possible to put the YubiKey into FIPS mode, even if it had been in FIPS mode, and even if you set it with a password. * The U2F application will be configured with a new attestation cert, which includes information that the YubiKey has been reset, and hence cannot be in FIPS mode. * The process of resetting is a bit complicated; the .NET YubiKey API does not include a higer-level `U2fSession` method for performing the entire operation. Instead, you must send a series of lower-level commands described below. Steps ----- Resetting the U2F application is something you hope you never need to do. Generally, the only reason to reset the U2F application is if the password has been blocked. Note that the password is needed to add new credentials, but not to authenticate existing credentials. That means that you probably will not want to reset even if the PIN is blocked. You will obtain a new YubiKey for new credentials and continue using the old YubiKey for the existing ones. Furthermore, it is possible to have more than one YubiKey registered with a relying party. This means that a new YubiKey can be registered with the old one's relying parties. The old YubiKey can still be used to authenticate its credentials, and the new YubiKey can be used to authenticate old and new credentials. Nonetheless, if you decide to reset, here's what needs to be done: 1. "Reboot" the YubiKey by removing and re-inserting. Obtain a connection to the YubiKey once it has been reinserted. This will likely be done using a listener class (see [YubiKeyDeviceListener](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.YubiKeyDeviceListener.html) ). 2. Within a time limit from the reboot (about 5 seconds), complete the reset command: 1. Send the [ResetCommand](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.U2f.Commands.ResetCommand.html) . The initial command should return `ResponseStatus.ConditionsNotSatisfied` (i.e. the `Status` property of the [ResetResponse](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.U2f.Commands.ResetResponse.html) object is `ConditionsNotSatisfied` which happens when the `StatusWord` property is `SWConstants.ConditionsNotSatisfied`). 2. Touch the YubiKey's contact. 3. Send the `ResetCommand` again. 4. If the `Status` of the `ResetResponse` is `Success`, then the U2F application has been reset. If it is `Failed`, then the process was not completed within the time limit. Sample code ----------- The U2F sample program contains a class that demonstrates how to execute these steps. It is located at `Yubico.YubiKey/examples/U2fSampleCode`. The code that actually performs the reset is in `.../U2fSampleCode/YubiKeyOperations/U2fReset.cs`. At the moment, there is no simple SDK API that can reset the U2F application. That is, there is no single `U2fSession` method to call. Rather, the sample code demonstrates how you can 1. create a listener to determine when the YubiKey is removed and reinserted, and 2. call the lower-level SDK command API to perform the actual reset. Hence, if you want to add the option to reset the U2F applicaiton in your app, one option is to study the sample code and write something similar. You might be able to "cut-and-paste" the `U2fReset` class in the sample code, replacing the messages and `KeyCollector` to fit your needs. [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-u2f/u2f-reset.md/#L1) --- # PIV slots ##### Table of Contents PIV slots ========= The PIV (Personal Identity Verification) standard specifies 25 slots. Depending on the firmware version of the YubiKey, its PIV application will have 5, 25, 26, or 28 slots. The table below lists all the slots and the firmware version it is first supported. The first YubiKeys that implemented PIV only supported five of the slots. Starting with version 4 of the firmware, all 25 slots were supported. With 4.3, Yubico added slot F9 (attestation), which is unique to the YubiKey (it is not part of the standard). For 5.3, two more non-standard slots were added, but they are not really slots. What was added was the ability to access metadata on the PIN and PUK, so slots 80 (PIN) and (81) PUK were identified as where the PIN and PUK information is stored. Each slot has a name and number. Each slot number is given as a hex value, and all slot numbers can be represented as a single byte. For example, slot "9A" is the slot with the number `0x9A`. That is decimal 154, but it is never referred to as "slot 154". If the number of the slot is given, it will always be the hex value. Furthermore, it will usually be written without the "0x". That is, when writing hex numbers, the custom is to write it as `0x9A`. But in PIV documents, it is almost always written as "Slot 9A". Some applications refer to a slot by its name. For example, slot 9A is the "Authentication" slot. There are times in the standard or in the documentation of an application where something such as this is described, "...using the Authentication key..." or "...the key in the Authentication slot...". The table below lists each of the slots by number and name. Notice that slot 9A holds an asymmetric key, 9B holds a symmetric key, and slots 9C, 9D, and 9E hold asymmetric keys. #### Table 1: List of PIV slots | Slot number | Name | Firmware version
first offered | Description | | --- | --- | --- | --- | | 80 | PIN | 5.3 | Not a standard slot, used by the [Get metadata command](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.Commands.GetMetadataCommand.html) | | 81 | PUK | 5.3 | Not a standard slot, used by the [Get metadata command](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.Commands.GetMetadataCommand.html) | | 9B | Management | all | Triple-DES key or, beginning 5.4.2, AES 128, 192, 256, no cert | | 9A | PIV Authentication | all | RSA or ECC key and cert,
authenticate the user, usually for system login | | 9C | Digital Signature | all | RSA or ECC key and cert,
signing email, files, executables, etc. | | 9D | Key Management | all | RSA or ECC key and cert,
encryption for confidentiality, e.g. decrypting email | | 9E | Card Authentication | all | RSA or ECC key and cert,
authenticate the card, usually building access | | F9 | Attestation | 4.3 | Not a standard slot,
RSA key and cert,
used to attest other PIV keys generated by the YubiKey | | 82 | Retired 1 | 4.0 | RSA or ECC key and cert,
usually keys with expired certs,
used to decrypt older emails or other encrypted items | | 83 | Retired 2 | 4.0 | RSA or ECC key and cert,
usually keys with expired certs,
used to decrypt older emails or other encrypted items | | 84 - 94 | ... | ... | ... | | 95 | Retired 20 | 4.0 | RSA or ECC key and cert,
usually keys with expired certs,
used to decrypt older emails or other encrypted items | Attestation Key --------------- The attestation key (in slot `F9`) is used to create an attestation statement (an X.509 certificate), which attests that a key in slot `9A`, `9C`, `9D`, `9E`, or one of the retired slots (`82` - `95`) was _generated_ on the YubiKey. If a private key was _imported_ into one of those slots, it will not be possible to create an attestation statement for that slot. Upon manufacture, the attestation key (a private key and certificate pair) is loaded into slot `F9`. This key is generated by Yubico, and the cert is signed by a Yubico CA and chains to a Yubico root. The same key and cert are loaded onto many different YubiKeys. See the article on [PIV attestation](https://docs.yubico.com/yesdk/users-manual/application-piv/attestation.html) for more information on this topic. Generate and import asymmetric keys ----------------------------------- Slots `9A`, `9C`, `9D`, `9E`, `82 - 95`, and `F9` hold asymmetric keys. Or put another way, all slots other than `80`, `81`, and `9B` hold asymmetric keys. The slots that hold asymmetric keys (other than F9) are manufactured "empty". There are no keys in those slots. In order to fill them with keys, you must either generate a new key pair (see [GenerateKeyPairCommand](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.Commands.GenerateKeyPairCommand.html) ), or import a key (see [ImportAsymmetricKeyCommand](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.Commands.ImportAsymmetricKeyCommand.html) ). It is possible to generate or import a new attestation key (slot `F9`). However, if you do so, the old attestation key is lost and there is nothing you can do to recover it. The YubiKey will no longer be able to create an attestation statement, unless you obtain, for the new attestation key, a proper certificate that chains to a supported root. Signing ------- Slot `9C` is the key named "Digital Signature". You will likely use this key to sign emails, git commits, or other items. However, it is also possible to sign using the keys in slots `9A`, `9D`, `9E`, and `82` - `95` as well. The YubiKey will not compute a signature if you specify any other slot. Slots `80`, `81`, and `9B` do not hold asymmetric keys and while `F9` will sign an attestation statement, it does not perform general-purpose signing. To sign using the YubiKey, use the [Authenticate: sign](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#authenticate-sign) command. [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-piv/slots.md/#L1) --- # YubiHSM Auth session APIs ##### Table of Contents YubiHSM Auth session APIs ========================= The high level YubiHSM Auth session APIs provide a simpler way to work with the YubiHSM Auth application on the YubiKey. The YubiHSM Auth session API is a layer built on the lower level command API. Session APIs help perform YubiHSM Auth scenarios in a shorter amount of development time and without getting involved with each command's details. For more information on the YubiHSM Auth application and commands, see [YubiHSM Auth Overview](https://docs.yubico.com/yesdk/users-manual/application-yubihsm-auth/yubihsm-auth-overview.html) . A guide for creating a secure session with a YubiHSM 2 device is covered in [Interacting with a YubiHSM 2](https://docs.yubico.com/yesdk/users-manual/application-yubihsm-auth/interacting-yubihsm-2.html) YubiHsmAuthSession ------------------ To perform YubiHSM Auth operations, first select the IYubiKeyDevice you would like to use. Next, create an instance of the YubiHsmAuthSession class using that device. During the lifetime of that session, you can use the session APIs as a simple way to work with the YubiHSM Auth application on the YubiKey. // use the first YubiKey found var yubiKeyToUse = YubiKeyDevice.FindAll().First(); using (var YubiHsmAuthSession = new YubiHsmAuthSession(yubiKeyToUse)) { // call session methods } ##### Note For more information on connecting to a YubiKey with the YubiKeyDevice class, please see the [SDK programming guide](https://docs.yubico.com/yesdk/users-manual/sdk-programming-guide/making-a-connection.html) . Methods ------- Clicking on the method will bring you to the API documentation where more information can be found. | Method | Description | Try-Parse version | | --- | --- | --- | | [Add credential](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.YubiHsmAuth.YubiHsmAuthSession.html#Yubico_YubiKey_YubiHsmAuth_YubiHsmAuthSession_AddCredential_System_ReadOnlyMemory_System_Byte__Yubico_YubiKey_YubiHsmAuth_CredentialWithSecrets_) | Add a credential. | [Try add credential](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.YubiHsmAuth.YubiHsmAuthSession.html#Yubico_YubiKey_YubiHsmAuth_YubiHsmAuthSession_TryAddCredential_System_ReadOnlyMemory_System_Byte__Yubico_YubiKey_YubiHsmAuth_CredentialWithSecrets_System_Nullable_System_Int32___) | | [Change management key](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.YubiHsmAuth.YubiHsmAuthSession.html#Yubico_YubiKey_YubiHsmAuth_YubiHsmAuthSession_TryChangeManagementKey_System_ReadOnlyMemory_System_Byte__System_ReadOnlyMemory_System_Byte__System_Nullable_System_Int32___) | Change the management key. | [Try change management key](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.YubiHsmAuth.YubiHsmAuthSession.html#Yubico_YubiKey_YubiHsmAuth_YubiHsmAuthSession_TryChangeManagementKey_System_ReadOnlyMemory_System_Byte__System_ReadOnlyMemory_System_Byte__System_Nullable_System_Int32___) | | [Delete credential](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.YubiHsmAuth.YubiHsmAuthSession.html#Yubico_YubiKey_YubiHsmAuth_YubiHsmAuthSession_DeleteCredential_System_ReadOnlyMemory_System_Byte__System_String_) | Delete a credential. | [Try delete credential](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.YubiHsmAuth.YubiHsmAuthSession.html#Yubico_YubiKey_YubiHsmAuth_YubiHsmAuthSession_TryDeleteCredential_System_ReadOnlyMemory_System_Byte__System_String_System_Nullable_System_Int32___) | | [Get AES-128 session keys](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.YubiHsmAuth.YubiHsmAuthSession.html#Yubico_YubiKey_YubiHsmAuth_YubiHsmAuthSession_GetAes128SessionKeys_System_String_System_ReadOnlyMemory_System_Byte__System_ReadOnlyMemory_System_Byte__System_ReadOnlyMemory_System_Byte__) | Calculate session keys from an AES-128 credential. These session keys are used to establish a secure session with a YubiHSM 2 device. | n/a | | [Get application version](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.YubiHsmAuth.YubiHsmAuthSession.html#Yubico_YubiKey_YubiHsmAuth_YubiHsmAuthSession_GetApplicationVersion) | Get the version of the YubiHSM Auth application returned as a major, minor, and patch value. | n/a | | [Get management key retries](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.YubiHsmAuth.YubiHsmAuthSession.html#Yubico_YubiKey_YubiHsmAuth_YubiHsmAuthSession_GetManagementKeyRetries) | Get the number of retries remaining for the management key. | n/a | | [List credentials](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.YubiHsmAuth.YubiHsmAuthSession.html#Yubico_YubiKey_YubiHsmAuth_YubiHsmAuthSession_ListCredentials) | Get the public properties of all credentials in the YubiHSM Auth application, along with the number of retries remaining for each. | n/a | | [Reset application](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.YubiHsmAuth.YubiHsmAuthSession.html#Yubico_YubiKey_YubiHsmAuth_YubiHsmAuthSession_ResetApplication) | Reset the YubiHSM Auth application, which will delete all credentials and set the management key to its default value (all zeros). | n/a | [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-yubihsm-auth/yubihsm-auth-session.md/#L1) --- # Interacting with a YubiHSM 2 ##### Table of Contents Interacting with a YubiHSM 2 ============================ `Yubico.YubiKey.YubiHsmAuth` provides an easy way to programmatically manage the YubiHSM Auth application on the YubiKey. While this SDK also supports the calculation of session keys, it is instead recommended for developers to rely on the [YubiHSM SDK](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/) for interactions with the YubiHSM 2. YubiHSM SDK ----------- Once credentials are added to the YubiHSM Auth application, use the [YubiHSM SDK](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/) (and bundled tools) to establish a secure session with a YubiHSM 2 device and perform operations on it. The [YubiHSM Shell](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-sdk-tools-libraries.html#yubihsm-shell) tool supports authentication with YubiHSM Auth credentials in both interactive mode and command-line mode. Once the user is authenticated, all YubiHSM Shell commands can be used. Refer to [this guide](https://docs.yubico.com/hardware/yubikey/yk-5/tech-manual/yubihsm-auth.html#using-yubihsm-auth-with-yubihsm-shell) for more information. It is also possible to use low-level commands to communicate natively with a YubiHSM 2. The individual commands ( documented [here](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-cmd-reference.html) ) are implemented by the [libyubihsm](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-sdk-tools-libraries.html#libyubihsm) C library. YubiHSM 2 secure channel ------------------------ In order to establish an encrypted and authenticated session with a YubiHSM 2, the YubiHSM Auth application must follow the YubiHSM 2 secure channel protocol. This protocol is based on the Global Platform Secure Channel Protocol 03 (SCP03), but there are two important differences: * The YubiHSM 2 secure channel protocol does not use APDUs, so the commands and possible options do not match the complete SCP03 specification. * SCP03 uses a set of three long-lived AES keys, while the YubiHSM 2 secure channel uses a set of two long-lived AES keys. The two long-lived keys used in the YubiHSM 2 authentication protocol include an ENC key and a MAC key. In order to successfully create a secure channel, the long-lived keys in the YubiHSM Auth credential and YubiHSM 2 device must be identical. Those long-lived key sets are used by the YubiHSM Auth application to derive a set of three session-specific AES-128 keys using the challenge-response protocol as defined in SCP03: * Session Secure Channel Encryption Key (S-ENC): used for data confidentiality. * Secure Channel Message Authentication Code Key for Command (S-MAC): used for data and protocol integrity. * Secure Channel Message Authentication Code Key for Response (S-RMAC): used for data and protocol integrity. Session-specific keys can be requested from the YubiHSM Auth application and are returned to the caller. These session-specific keys are used to encrypt and authenticate commands and responses with a YubiHSM 2 device during a single session. The session keys are discarded afterwards. [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-yubihsm-auth/interacting-yubihsm-2.md/#L1) --- # FIDO2 credential blobs ("credBlob" extension) ##### Table of Contents FIDO2 credential blobs ("credBlob" extension) ============================================= When you get the [AuthenticatorInfo](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.AuthenticatorInfo.html) , you can check the extensions to see if "credBlob" is supported. using (fido2Session = new Fido2Session(yubiKeyDevice)) { int maxCredBlobLength = fido2Session.AuthenticatorInfo.MaximumCredentialBlobLength ?? 0; if (fido2Session.AuthenticatorInfo.Extensions.Contains("credBlob") && (maxCredBlobLength > 0)) { . . . } } If it does, you can add up to `maxCredBlobLength` bytes of arbitrary data to a credential. That is, when you make the credential, you can specify that the YubiKey will store this extra value with the credential. If the "credBlob" extension is supported, the standard specifies that the maximum length of the credential blob must be at least 32. Hence, if it is supported, you know that you will be able to store at least 32 bytes. Later on when you get an assertion for that credential, you can specify that the YubiKey return the "credBlob" data with the assertion. It is not possible to add a "credBlob" to an existing credential. It is only possible to store data when making a credential. It is, of course, possible to delete an existing credential and create a new one. Make credential with "credBlob" ------------------------------- With the SDK, making a credential begins with the [MakeCredentialParameters](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.MakeCredentialParameters.html) . To include a credential blob, use the [AddCredBlobExtension](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.MakeCredentialParameters.html#Yubico_YubiKey_Fido2_MakeCredentialParameters_AddCredBlobExtension_) method. using (fido2Session = new Fido2Session(yubiKeyDevice)) { // The credBlob extension is available if and only if the MaximumCredentialBlobLength // is provided and is greater than 0. if ((fido2Session.AuthenticatorInfo.MaximumCredentialBlobLength ?? 0) > 0) { var makeCredentialParameters = new MakeCredentialParameters(rp, userEntity); // Let's say we want to add the user's badge number as the "credBlob". byte[] dataToAdd = GetUserBadgeNumber(userEntity); makeCredentialParameters.AddCredBlobExtension(dataToAdd, fido2Session.AuthenticatorInfo); . . . MakeCredentialData credentialData = fido2Session.MakeCredential(makeCredentialParameters); } } GetAssertion with "credBlob" ---------------------------- To get an assetrtion with the SDK, build [GetAssertionParameters](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.GetAssertionParameters.html) . Set the "credBlob" extension. If you do not set the "credBlob" extension to true, the YubiKey will return the assertion, but it will not return the credential blob. using (fido2Session = new Fido2Session(yubiKeyDevice)) { var getAssertionParameters = new GetAssertionParameters(rp, clientDataHash); getAssertionParameters.AddExtension("credBlob", true); . . . IList assertionList = fido2Session.GetAssertions(getAssertionParameters); } Note that when making a credential, to add an extension we supplied the extension string along with a byte array. But to include the extension when getting an assertion, supply the extension string along with a boolean. This just tells the YubiKey that we want it to perform that extension's operations. In this case, the operation the YubiKey performs is return the credential blob. Find the assertion you want in the list. In most cases, the list will be only a single assertion. Now get the "credBlob" data. byte[] credentialData = assertionList[0].AuthenticatorData.GetCredBlobExtension(); [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-fido2/cred-blobs.md/#L1) --- # ##### Table of Contents Get an assertion ---------------- ### Command APDU info | CLA | INS | P1 | P2 | Lc | Data | Le | | --- | --- | --- | --- | --- | --- | --- | | 00 | 10 | 00 | 00 | _data length_ | 02 _encoded info_ | (absent) | The Ins byte (instruction) is 10, which is the byte for CTAPHID\_CBOR. That means the command information is in a CBOR encoded structure in the Data. The data consists of the CTAP Command Byte and the CBOR encoding of the command's parameters. In this case, the CTAP Command Byte is `02`, which is the command "`authenticatorGetAssertion`". The CBOR encoding is described in the documentation for [GetAssertionParameters](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.GetAssertionParameters.html) . ### Response APDU info #### Response APDU for a successful get Total Length: _variable + 2_ Data Length: _variable_ | Data | SW1 | SW2 | | --- | --- | --- | | _encoded info_ | 90 | 00 | The info returned is CBOR encoded. It has a structure similar to the following. A5 01 --map-- 02 --byte string-- 03 --byte string-- 04 --map-- 05 --int-- 06 --boolean-- 07 --byte string-- [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-fido2/apdu/get-assertion.md/#L1) --- # YubiHSM Auth commands ##### Table of Contents YubiHSM Auth commands ===================== For each possible YubiHSM Auth command, there will be a class that knows how to build the command APDU and parse the data in the response APDU. Each class will know what information is needed from the caller for that command. List of YubiHSM Auth commands ----------------------------- * [List credentials](https://docs.yubico.com/yesdk/users-manual/application-yubihsm-auth/commands/list-credentials.html) : get the public properties of all credentials present in the YubiHSM Auth application along with the number of retries remaining for each * [Add credential](https://docs.yubico.com/yesdk/users-manual/application-yubihsm-auth/commands/add-credential.html) : store long-lived keys in the YubiHSM Auth application by creating a new credential * [Delete credential](https://docs.yubico.com/yesdk/users-manual/application-yubihsm-auth/commands/delete-credential.html) : remove a credential * [Get management key retries](https://docs.yubico.com/yesdk/users-manual/application-yubihsm-auth/commands/get-management-key-retries.html) : get the number of retries for the management key * [Change management key](https://docs.yubico.com/yesdk/users-manual/application-yubihsm-auth/commands/change-management-key.html) : change the management key * [Get application version](https://docs.yubico.com/yesdk/users-manual/application-yubihsm-auth/commands/get-application-version.html) : get the version of the YubiHSM Auth application * [Reset application](https://docs.yubico.com/yesdk/users-manual/application-yubihsm-auth/commands/reset-application.html) : reset the YubiHSM Auth application * [Get AES-128 session Keys](https://docs.yubico.com/yesdk/users-manual/application-yubihsm-auth/commands/get-aes128-session-keys.html) : get SCP03 session keys from an AES-128 credential [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-yubihsm-auth/commands/yubihsm-auth-commands.md/#L1) --- # Add credential ##### Table of Contents Add credential ============== Store long-lived keys in the YubiHSM Auth application by creating a new [credential](https://docs.yubico.com/yesdk/users-manual/application-yubihsm-auth/objects/credential.html) . Available --------- All YubiKeys with the YubiHSM Auth application (included in firmware version 5.4.3 and later). ##### Note Use the .NET API's [HasFeature()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.YubiKeyFeatureExtensions.html#Yubico_YubiKey_YubiKeyFeatureExtensions_HasFeature_Yubico_YubiKey_IYubiKeyDevice_Yubico_YubiKey_YubiKeyFeature_) method to check if a key has the YubiHSM Auth application. SDK classes ----------- * AddCredentialCommand * AddCredentialResponse Input ----- This operation requires authenticating with the management key. There is a limit of 8 attempts to authenticate with the management key before the management key is blocked. Once the management key is blocked, the application itself must be reset before authentication can be attempted again. To reset the application, see [ResetApplicationCommand](https://docs.yubico.com/yesdk/users-manual/application-yubihsm-auth/commands/reset-application.html) . Supplying the correct management key before the management key is blocked will reset the retry counter to 8. The rest of the input data is related to the new credential: * Label (64 bytes) * Algorithm (1 byte) * Keys (length depends on algorithm) * Credential password (16 bytes) * Touch policy (1 byte) Further information is found in the [Data](https://docs.yubico.com/yesdk/users-manual/application-yubihsm-auth/commands/add-credential.html#data) section. ##### Note The label may only contain characters that can be encoded with UTF-8, and its UTF-8 byte count must be between 1 and 64. Non-printing characters are allowed, as long as they can be encoded with UTF-8. For example, null (UTF-8: 0x00) and Right-To-Left Mark U+200F (UTF-8: 0xE2 0x80 0x8F) would be accepted. Since the label is used for display purposes, it is recommended to prefer printable characters. Output ------ None, though some information may be included in the status word when the command fails ( see [Response APDU](https://docs.yubico.com/yesdk/users-manual/application-yubihsm-auth/commands/add-credential.html#response-apdu) ). Command APDU ------------ | CLA | INS | P1 | P2 | Lc | Data | Le | | --- | --- | --- | --- | --- | --- | --- | | 00 | 01 | 00 | 00 | _variable_ | (TLV, see below) | (absent) | ### Data The data is sent as concatenated TLV-formatted elements, as follows: | Tag (hexadecimal) | Length (decimal) | Value | Notes | | --- | --- | --- | --- | | 0x7b | 16 | managment key | used to authenticate to the YubiHSM Auth application | | 0x71 | 1-64 | label | UTF-8 encoded string | | 0x74 | 1 | cryptographic key type | See [CryptographicKeyType](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.YubiHsmAuth.CryptographicKeyType.html) | | 0x75 | 16 | ENC key | | | 0x76 | 16 | MAC key | | | 0x73 | 16 | password | byte array | | 0x7a | 1 | touch required | boolean: 0-not required, 1-required | ### Example The following example is in hexadecimal. Byte array: 00 01 00 00 4c 7b 10 00 01 02 03 04 05 06 07 08 09 0a 0b 0c/ 0d 0e 0f 71 03 61 62 63 74 01 26 75 10 ca fe b0 ba ca fe b0/ ba ca fe b0 ba ca fe b0 ba 76 10 13 37 f0 0d 13 37 f0 0d 13/ 37 f0 0d 13 37 f0 0d 73 10 a0 a1 a2 a3 b0 b1 b2 b3 c0 c1 c2/ c3 d0 d1 d2 d3 74 01 00 Notated: 00 CLA 01 INS (add credential) 00 P1 00 P2 4c Total length of the Data field -- Data -- 7b 10 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f Management key 71 03 61 62 63 Label: 'abc' 74 01 26 Algorithm: AES-128 75 10 ca fe b0 ba ca fe b0 ba ca fe b0 ba ca fe b0 ba Encryption key 76 10 13 37 f0 0d 13 37 f0 0d 13 37 f0 0d 13 37 f0 0d MAC key 73 10 a0 a1 a2 a3 b0 b1 b2 b3 c0 c1 c2 c3 d0 d1 d2 d3 Password 7a 01 00 Touch required: false Response APDU ------------- The data field is always empty. On success, the status word will be 0x90 0x00. If there was a failure, further information may be communicated in the status word. Total Length: 2\\ | Data | SW1 | SW2 | | --- | --- | --- | | (no data) | 90 | 00 | ### Common non-success status words | Value | Meaning | | --- | --- | | 0x6983 | A credential with that label already exists | | 0x6a84 | No space (30 credentials maximum) | | 0x63c# | Wrong management key, where # is the number of attempts remaining | | 0x6a80 | Wrong syntax | [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-yubihsm-auth/commands/add-credential.md/#L1) --- # Attacks on RSA decryption and mitigation ##### Table of Contents Attacks on RSA decryption and mitigation ======================================== There are attacks on RSA involving the unpad operation. This document describes those attacks, whether the YubiKey and/or SDK is vulnerable, and SDK mitigations. Chosen ciphertext attack on RSA ------------------------------- Suppose an attacker is able to obtain an RSA ciphertext block from unknown plaintext. The goal is to retrieve the plaintext of this original message. The attacker creates a different ciphertext block mathematically related to the first. If the attacker is able to somehow get the private key owner to decrypt this new block and return the plaintext, they can deduce the original message. That is, there exist P1 (plaintext 1, the unknown) C1 (ciphertext 1, known to the attacker) P2 (known) C2' (known)(the chosen ciphertext) If they are mathematically related (in a particular way), the attacker "can solve for P1". Incidentally, just to be pedantic, `C2'` (C-two-prime, the chosen ciphertext) is not the ciphertext for `P2`. Rather, while there is a `C2` (the ciphertext for `P2`), the ciphertext the attacker chooses is mathematically related to both C2 and C1. But it is not C2 exactly. There are two reasons this attack generally does not succeed in the real world. One, protocols and applications are written so that results of private key operations are not returned to outside querants. And two, even if the plaintext block were to be returned, when the chosen ciphertext is decrypted, the "unpad" operation would undoubtedly fail and an error, rather than the plaintext, would be returned. And even if the decrypted data somehow survived the unpad operation (it looked like a properly padded block), the data returned would be the unpadded data, not the entire block. Nonetheless, this is the foundation of other attacks. This document describes these attacks, when an application is susceptible (or not), and what mitigations are required. Finally, this document describes some code inside the .NET YubiKey SDK that would appear to be susceptible, and the mitigations employed to reduce its exposure. > ❗ Note that this attack only allows the adversary to recover one message. It does not threaten the private key itself. PKCS 1 padding (aka PKCS #1 v.1.5 and P1.5) ------------------------------------------- To encrypt using RSA, each plaintext block must be numerically less than the RSA modulus. However, if the plaintext is too small, then the RSA operation is not secure. Hence, to build a block that is less than the modulus, but also not a small value, the block is padded. The oldest standard padding scheme for RSA encryption is known as PKCS 1 (PKCS = Public Key Cryptography Standards, and the first of those is related to RSA). In this scheme, a block of memory or a byte array the size of the modulus is created. It is filled this way. 00 || 02 || pad bytes || 00 || plaintext The pad bytes are random, non-zero bytes. The standard specifies that there must be at least 8 pad bytes. For example, if the RSA key is 1024 bits (128 bytes) and the data to encrypt is a 32-byte value (e.g. a 256-bit AES key), the block of data would be 00 || 02 || 93 random non-zero bytes || 00 || 32 plaintext bytes This block is converted into a number and encrypted. After decrypting the ciphertext, the private key owner will check to make sure the first byte is 00 and the second is 02. If not, error, don't return any plaintext. If the first two bytes are correct, search for the first occurrence of the 00 byte. If there is none, error, don't return any plaintext. If there is a 00 byte, make sure there are at least 8 bytes of pad (i.e. the 00 appears after index 9). If not, error, don't return any plaintext. If these checks all pass, return all the bytes after the first 00 byte. Some applications and protocols are written with another check, namely, how big the unpadded data must be. For example, it's possible the encrypted data must be either 16, 24, or 32 bytes (it is an AES key), or it must be 48 bytes (it is a master session key). If not, error, don't return any plaintext. Bleichenbacher Attack --------------------- In 1998, Daniel Bleichenbacher published some results of his research, which included a way to employ the chosen-ciphertext attack on RSA, even without knowing the full plaintext block result. It relied on knowing where, in a decrypted block, the padding scheme failed. Send the private key owner a chosen ciphertext block. The owner decrypts and then tries to unpad. When that operation fails, the owner sends a response indicating what the failure was. That is, the error message might be, "Decryption failed, block\[0\] not 0." Or maybe it was "Decryption failed, block\[1\] not 2". And so on. Although the attacker does not know all the bytes of the plaintext, they do know some of them based on the error message. Now send another chosen ciphertext. And another. And keep sending messages. Depending on the private key size, thousands or millions of messages. Now based on the results, solve for the original plaintext message. This attack is not practical unless two conditions are met. One, the decryptor (private key owner) must be willing to decrypt thousands or millions of messages in a timely manner, no questions asked (the term in cryptography is "oracle"), and two, return descriptive error messages. These conditions were met in the real world. An SSL server likely responds to all handshake requests and processes them automatically. There were some implementations that did indeed return descriptive error messages. The target message to attack would be the one in which a session key was encrypted using the server's public key. Once the attacker knows the session key, they can read an entire session's messages. ### Mitigation To prevent the attack, SSL server code stopped returning descriptive error messages. All errors (failed decryption because of an unpad error or anything else) triggered a single response message. ### Attack updated Without the detailed error message, Bleichenbacher then timed the responses. How long did it take for the SSL server to respond? If it was very quick, the error was the first byte of padding. If it was a little longer, the error was the second byte. And so on. Even though the server was not explicitly returning a descriptive error code, the amount of time it was spending on the decryption was enough information to launch the attack. The number of messages required was generally estimated to be around 1,000,000 for a 2048-bit key. ### Mitigation updated Run all unpad checks, no matter what. If the first byte was wrong, note that there is an error, then check the next byte. And so on. In the end, if there were any errors, simply return the generic error message. #### Not enough Simply performing all checks is not necessarily enough. If there is a variation in the amount of time spent on the unpad operation, information is leaked. For example, if both the first byte and the second byte are incorrect, and there is no 00 marker byte, maybe the amount of time to process is greater than if the problem is in the second byte alone. The original timing attack said a quicker time meant the error was in the first byte. But for some particular implementation, a quicker time could mean the error was in the second byte. It's not enough to make the computation slower, it really needs to be uniform. No matter what the error, the time to perform the unpad operation is the same. Another mitigation: OAEP ------------------------ Another way to solve this problem is to simply not use P1.5 padding. In 1994, Mihir Bellare and Phillip Rogaway had developed a different padding scheme called Optimal Asymmetric Encryption Padding (OAEP). Because of the Bleichenbacher attack, standards and protocols had incentive to adopt this existing algorithm. With OAEP, the padded data was indistinguishable from random (to help prevent other "side-channel" attacks), and it was much more difficult to launch a Bleichenbacher attack, even if the timing was known. That is, it was still possible an implementation of OAEP unpad would leak information about where the padding went wrong, but because of how the scheme worked (comparing digests of data rather than the data itself), that information did not correlate to what bits in the chosen plaintext were different from the original plaintext. Furthermore, it was much easier to write code that was more uniform anyway. ### Attack on OAEP In 2001, James Manger published his attack on OAEP. In this, the attacker needs to know if the data decrypted from the chosen ciphertext is greater than or less than a particular value (often called "B"). It will take a few thousand chosen-ciphertext messages, but eventually the attacker will be able to recover the original message. When verifying whether unpadded data is correct, there is a check to see if the most significant byte is zero or not. If it is not zero, that's an error. Furthermore, if it is not zero, the attacker knows the result is greater than B. So if the OAEP unpad code checks the most significant byte, and then exits immediately, that's a quick response. In that case, the attacker knows the result from the chosen ciphertext is greater than B. A longer response means it is less than. ### Mitigation Once again, make sure the OAEP unpad operation performs the entire process every time, and make the total time (error or no error) as uniform as possible. ### One more mitigation There is another possible mitigation: variable times. This would be something similar to "RSA blinding". In order to thwart timing attacks on the RSA algorithm itself (not the padding scheme), an implementation could add some random amount of time to the process. This is called "blinding". When this happens, a quick response with one ciphertext block does not necessarily mean that the actual computation time is less than the actual computation time of a slow response with another ciphertext block. Now add in the unpad operation. An attacker likely knows only how long the total RSA operation took (RSA decryption and unpad). If there is too much variation in the RSA decryption time, then there is no way to tell how much of the total time was RSA and how much was unpad. It is also possible to build implementations of the P1.5 and OAEP unpad algorithms that add a variable amount of time each time it is computed. While variable-time RSA blinding implementations are used in the real world, variable-length unpad schemes are rare. Signing ------- A digital signature using RSA involves performing the padding operation, then encrypting that result using the RSA private key. The owner of the private key does not perform the unpad operation, so the attacks listed here are not relevant. What the attacker needs ----------------------- For these timing attacks on the unpad operation, the attacker needs two things: * An oracle, namely, the owner of the private key must be willing to decrypt thousands or millions of messages in a timely manner, no questions asked. * Accurate times for completion of the task. Susceptibility of the YubiKey to these timing attacks ----------------------------------------------------- The YubiKey itself does not perform the unpad operation. If you call on the YubiKey to decrypt, it will perform "raw" RSA and return the still-padded result. It is the responsibility of the calling application to unpad. Hence, the YubiKey itself is not susceptible to this class of attack. Susceptibility of the .NET YubiKey SDK to these timing attacks -------------------------------------------------------------- Because an application calling on the YubiKey to decrypt will need to perform the unpad operation, the SDK provides a class, [RsaFormat](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Cryptography.RsaFormat.html) , that can unpad the result of RSA decryption. If you use this class to unpad RSA decryption, will your application be susceptible to these timing attacks? ### The oracle requirement A YubiKey will almost certainly not be used in some application as an oracle. That is, the YubiKey will likely not be running automatically, performing decryptions no questions asked. Probably the only situation where this could happen is if someone wants to use a YubiKey as a substitute for an HSM providing cryptographic services for an SSL server. That is not recommended, by the way. The most likely use case for a YubiKey performing decryption is for an individual user to decrypt messages. In that case, it is extremely unlikely that an attacker will be able to get the user to perform thousands or millions of decrypt operations in a timely manner. ### The accurate time requirement Because the most likely use case for decrypting with a YubiKey involves user interaction, including PIN entry and touch, the time for each RSA decryption is so varied it is virtually useless. Even though it is highly unlikely an attacker could mount an unpad timing attack on the SDK's `RsaFormat` class when used in conjunction with the YubiKey, we will examine the operation's time variation. ### [RsaFormat](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Cryptography.RsaFormat.html) With the .NET YubiKey SDK, you have two choices for unpadding. One, use the [RsaFormat](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Cryptography.RsaFormat.html) class in `Yubico.YubiKey.Cryptography`. Or two, use an alternate implementation, such as one you write yourself. Note that the Unpad code that the .NET Base Class Libraries use is not publicly accessible. The engineers at Yubico have taken care to make sure the unpadding operations following P1.5 and OAEP are as uniform as possible. Yubico makes no guarantees that this code is completely immune to timing attacks. However, tests that timed how long to unpad correct versus incorrect values showed little variation. See the results below. #### RsaFormat timing results In the following tables, timing numbers are in microseconds: 0.372 microseconds = 0.000000372 seconds (372 nanoseconds, 0x000372 millisecond) 14.1 microseconds = 0.0000141 seconds (14,100 nanoseconds, 0.0141 millisecond) These are averages over several timing iterations. Where applicable, results are given based on the message size. For example, the baseline measurements (in the "Correct" column) are for no-error unpad operations when the encrypted data (the unpadded message) is 16, 24, 32, or 48 bytes long. For the "First byte wrong" column, the first byte was not valid, but everything after that was correct, including the message of given length. All timing numbers were taken on a computer with a 1.6 GHz Intel Core i5, 8th Gen chip, running Windows 10. Start with P1.5. ##### 1024-bit block PKCS 1 v1.5 | Correct
P1.5 Unpad | First Byte
Wrong (1) | Second Byte
Wrong (2) | Not Enough
Pad (3) | No Zero Byte | 1, 2, and 3 | | --- | --- | --- | --- | --- | --- | | 16: 0.354 | 16: 0.346 | 16: 0.346 | 16: 0.341 | 0.339 | 16: 0.340 | | 24: 0.370 | 24: 0.340 | 24: 0.336 | 24: 0.348 | | 24: 0.345 | | 32: 0.371 | 32: 0.335 | 32: 0.335 | 32: 0.349 | | 32: 0.346 | | 48: 0.379 | 48: 0.335 | 48: 0.336 | 48: 0.347 | | 48: 0.345 | | **Overall average** | | | | | | | 0.369 | 0.339 | 0.338 | 0.346 | 0.339 | 0.344 | ##### 2048-bit block PKCS 1 v1.5 | Correct
P1.5 Unpad | First Byte
Wrong (1) | Second Byte
Wrong (2) | Not Enough
Pad (3) | No Zero Byte | 1, 2, and 3 | | --- | --- | --- | --- | --- | --- | | 16: 0.676 | 16: 0.675 | 16: 0.670 | 16: 0.678 | 0.684 | 16: 0.669 | | 24: 0.681 | 24: 0.672 | 24: 0.670 | 24: 0.681 | | 24: 0.679 | | 32: 0.692 | 32: 0.670 | 32: 0.668 | 32: 0.683 | | 32: 0.678 | | 48: 0.692 | 48: 0.671 | 48: 0.673 | 48: 0.685 | | 48: 0.679 | | **Overall average** | | | | | | | 0.686 | 0.672 | 0.670 | 0.682 | 0.684 | 0.676 | These numbers indicate that there is very little variance between times based on message size. Secondly, there is very little variance based on error or no error. Lastly, there is very little variance based on the type of error. For example, whether the error is an incorrect first byte, or a combination of the first three errors, the amount of time the `RsaFormat` method will take is very similar. Next, let's look at OAEP. ##### 1024-bit block OAEP with SHA-256 | Correct OAEP | First Byte
Wrong (1) | Incorrect
lHash (2) | Wrong
Separator (3) | No
Separator | 1, 2, and 3 | | --- | --- | --- | --- | --- | --- | | 16: 16.38 | 16: 16.48 | 16: 16.29 | 16: 16.19 | 16: 16.21 | 16: 16.19 | | 24: 16.34 | 24: 16.36 | 24: 16.22 | 24: 16.14 | 24: 16.32 | 24: 16.14 | | 32: 16.29 | 32: 16.68 | 32: 16.52 | 32: 16.18 | 32: 16.20 | 32: 16.11 | | 48: 16.18 | 48: 16.24 | 48: 16.19 | 48: 16.11 | 48: 16.19 | 48: 16.03 | | **Overall average** | | | | | | | 16.29 | 16.44 | 16.30 | 16.15 | 16.23 | 16.11 | ##### 2048-bit block OAEP with SHA-256 | Correct OAEP | First Byte
Wrong (1) | Incorrect
lHash (2) | Wrong
Separator (3) | No
Separator | 1, 2, and 3 | | --- | --- | --- | --- | --- | --- | | 16: 28.15 | 16: 28.36 | 16: 28.24 | 16: 28.07 | 16: 28.20 | 16: 28.06 | | 24: 28.36 | 24: 28.82 | 24: 28.79 | 24: 28.19 | 24: 28.22 | 24: 28.07 | | 32: 28.11 | 32: 28.99 | 32: 28.31 | 32: 28.18 | 32: 28.04 | 32: 28.13 | | 48: 28.11 | 48: 28.32 | 48: 28.18 | 48: 28.31 | 48: 28.20 | 48: 28.08 | | **Overall average** | | | | | | | 28.18 | 28.62 | 28.38 | 27.18 | 28.16 | 28.08 | Once again, we see very little variance between times based on message size. Secondly, there is very little variance based on error or no error. Lastly, there is very little variance based on the type of error. The time it takes to perform OAEP is dependent on the digest algorithm chosen. The numbers above are from timing exercises using SHA-256. The following numbers are averages when using the other digest algorithms. ##### 1024-bit block OAEP with SHA-1, SHA-256, and SHA-384 | Correct OAEP | First Byte
Wrong (1) | Incorrect
lHash (2) | Wrong
Separator (3) | No
Separator | 1, 2, and 3 | | --- | --- | --- | --- | --- | --- | | **SHA-1** | | | | | | | 14.27 | 14.22 | 14.19 | 14.10 | 14.21 | 14.17 | | **SHA-256** | | | | | | | 16.29 | 16.44 | 16.30 | 16.15 | 16.23 | 16.11 | | **SHA-384** | | | | | | | 17.41 | 17.42 | 17.23 | 17.24 | 17.26 | 17.25 | ##### 2048-bit block OAEP with SHA-1, SHA-256, SHA-384, and SHA-512 | Correct OAEP | First Byte
Wrong (1) | Incorrect
lHash (2) | Wrong
Separator (3) | No
Separator | 1, 2, and 3 | | --- | --- | --- | --- | --- | --- | | **SHA-1** | | | | | | | 26.29 | 26.38 | 26.42 | 26.8 | 26.15 | 26.10 | | **SHA-256** | | | | | | | 28.18 | 28.62 | 28.38 | 27.18 | 28.16 | 28.08 | | **SHA-384** | | | | | | | 30.13 | 30.43 | 30.21 | 29.87 | 30.01 | 29.85 | | **SHA-512** | | | | | | | 32.26 | 32.77 | 32.39 | 32.21 | 32.41 | 32.30 | [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/support/rsa-unpad.md/#L1) --- # FIDO2 Bio Enrollment (and related operations) ##### Table of Contents FIDO2 Bio Enrollment (and related operations) ============================================= Through the Bio Enrollment commands and methods, it is possible to set a YubiKey with a fingerprint for FIDO2 authentication. There are some supporting operations as well. * [GetModality](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Fido2Session.html#Yubico_YubiKey_Fido2_Fido2Session_GetBioModality) * [GetFingerprintSensorInfo](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Fido2Session.html#Yubico_YubiKey_Fido2_Fido2Session_GetFingerprintSensorInfo) * [EnumerateBioEnrollments](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Fido2Session.html#Yubico_YubiKey_Fido2_Fido2Session_EnumerateBioEnrollments) * [EnrollFingerprint](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Fido2Session.html#Yubico_YubiKey_Fido2_Fido2Session_EnrollFingerprint_) * [SetBioTemplateFriendlyName](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Fido2Session.html#Yubico_YubiKey_Fido2_Fido2Session_SetBioTemplateFriendlyName_) * [RemoveBioEnrollment](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Fido2Session.html#Yubico_YubiKey_Fido2_Fido2Session_TryRemoveBioTemplate_) Feature detection ----------------- If you want to write code that can programmatically determine if a particular YubiKey supports the Bio Enrollment operations, look at the [AuthenticatorInfo](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.AuthenticatorInfo.html) options. using (fido2Session = new Fido2Session(yubiKeyDevice)) { if (fido2Session.AuthenticatorInfo.GetOptionValue(AuthenticatorOptions.bioEnroll) == OptionValue.True) { . . . } } Get Information --------------- You can get information about the YubiKey's bio sensor. using (fido2Session = new Fido2Session(yubiKeyDevice)) { BioModality modality = fido2Session.GetBioModality(); FingerprintSensorInfo sensorInfo = fido2Session.GetFingerprintSensorInfo(); } Neither of these calls require an [AuthToken](https://docs.yubico.com/yesdk/users-manual/application-fido2/fido2-auth-tokens.html) (authentication). It is also possible to get a list of templates a YubiKey holds. That operation requires an AuthToken and will be discussed later. Getting an AuthToken -------------------- Other than the two information operations described above, Bio Enrollment operations require an AuthToken. The SDK offers [automatic verification](https://docs.yubico.com/yesdk/users-manual/application-fido2/fido2-auth-tokens.html) , but if you will be performing verification directly, here are some things you must know. First, you must obtain a PinUvAuthToken with the permission [BioEnrollment](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Commands.PinUvAuthTokenPermissions.html#Yubico_YubiKey_Fido2_Commands_PinUvAuthTokenPermissions_BioEnrollment) . It is not possible to use a PinToken. Second, an AuthToken with the BioEnrollment permission can be reused. That is, a YubiKey will not expire an AuthToken after performing a Bio Enrollment operation. Note that a YubiKey will expire an AuthToken used to make a credential or get an assertion. An expired AuthToken will not be valid for use in a Bio Enrollment operation. Third, an AuthToken obtained using fingerprints might not work with Bio Enrollment operations. Generally there are two ways to get an AuthToken, verifying the PIN and "user verification" (UV). User verification is verifying the fingerprint. However, it is possible a YubiKey Bio series device will not allow UV for Bio enrollment operations. That is, it might not be possible to use a fingerprint to authenticate a user in order to add a new fingerprint or even to delete an existing fingerprint. Note that it will still be possible to use a fingerprint to obtain an AuthToken with other permissions, such as MakeCredential. To know whether it is possible to use fingerprint authentication to perform any Bio Enrollment operation, check the "uvBioEnroll" option. using (fido2Session = new Fido2Session(yubiKeyDevice)) { if (fido2Session.AuthenticatorInfo.GetOptionValue(AuthenticatorOptions.uvBioEnroll) == OptionValue.True) { . . . } } If this option is not supported, then you must verify the PIN in order to obtain an AuthToken to be used for Bio Enrollment operations. Enrolling a fingerprint ----------------------- If you call [EnrollFingerprint](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Fido2Session.html#Yubico_YubiKey_Fido2_Fido2Session_EnrollFingerprint_) , then you must supply a KeyCollector. The SDK will notify that KeyCollector when a fingerprint sample is needed, and it will also report on the success or failure of the most recent sample. If you do not want to supply a KeyCollector, then call the Enroll commands directly. To enroll a fingerprint, the user must supply a number of samples. How many? With each sample provided, the SDK will report the number remaining. You might notice that the [GetFingerprintSensorInfo](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Fido2Session.html#Yubico_YubiKey_Fido2_Fido2Session_GetFingerprintSensorInfo) call will return a [FingerprintSensorInfo](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.FingerprintSensorInfo.html) object, which contains the property `MaxCaptureCount`. This is not necessarily the total number of good samples required. It is a requirement of the FIDO2 standard and indicates that the number of good samples required will never be greater than the value. For example, the `MaxCaptureCount` might be 16, yet it is possible to capture a fingerprint with only five good samples. But you know that the count will never be more than 16. Upon calling the `EnrollFingerprint` method, the SDK will determine if it needs an AuthToken. If so, it will determine if it can use a fingerprint to verify. If not, it will need the PIN. It will call the KeyCollector no matter what the verification method. Once the SDK has an AuthToken, it will need fingerprint samples. It will contact the KeyCollector announcing the need for a fingerprint sample. After the user has provided one, the SDK will determine if it needs another. If so, it will contact the KeyCollector again, this time providing a [BioEnrollSampleResult](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.BioEnrollSampleResult.html) object. That object will contain information you can relay to the user, and inform them of the need for a new sample. After enough good samples have been collected, the SDK will contact the KeyCollector with the request of Release. ### Cancel Once the YubiKey has started the process of collecting a fingerprint sample, it is possible to contact it and request the operation cancel. This is done through the `KeyCollector`'s argument `KeyEntryData`. When the SDK contacts your KeyCollector indicating it needs fingerprint samples, the accompanying `KeyEntryData` will contain a property [SignalUserCancel](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.KeyEntryData.html#Yubico_YubiKey_KeyEntryData_SignalUserCancel) . This is a delegate you can copy when you get the request of [EnrollFingerprint](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.KeyEntryRequest.html#Yubico_YubiKey_KeyEntryRequest_EnrollFingerprint) . Later on, during the sampling operation, you can call the delegate to signal to the SDK that you would like the operation to be canceled. Normally, you specify canceling an operation by having your KeyCollector return `false`. However, because notifying touch or fingerprint is a "non-modal" operation, the return value cannot be used. Hence, the way to cancel is by calling the SDK's cancel delegate. If the `SignalUserCancel` property in the `KeyEntryData` is null, you indicate cancel by returning `false`. If the `SignalUserCancel` is not null, you indicate cancel by calling that delegate. See also the User's Manual [article on touch notification](https://docs.yubico.com/yesdk/users-manual/sdk-programming-guide/key-collector-touch.html) for a deeper discussion of this topic. ### Maximum failed samples The YubiKey can determine that a particular sample was not good enough, or did not match the previous samples. In that case, it will simply return a code indicating the reason it failed. Depending on the version of the YubiKey, it is possible it will have a maximum number of failed samples before it rejects the enrollment. However, it is also possible there is no maximum. That is, it is possible the YubiKey accepts unlimited bad sample attempts. Hence, if you want to enforce a limit, you will have to program that in your KeyCollector using the `SignalUserCancel`. ### Timeout Once the YubiKey is ready to accept a sample, it will wait a certain number of seconds before it gives up and cancels the operation. At that point, the SDK will throw an exception. This timeout can be 28 seconds or more. The standard specifies that a user can specify an alternate timeout. Hence, the `EnrollFingerprint` method has an argument for `timeoutMilliseconds`. However, depending on the YubiKey version, this might not be supported. The SDK will accept the argument, but the YubiKey might ignore it. Hence, if you want to enforce an alternate timeout, you will have to program that in your KeyCollector using the `SignalUserCancel`. [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-fido2/fido2-bio-enrollment.md/#L1) --- # FIDO2 Reset ##### Table of Contents FIDO2 Reset =========== The FIDO2 application can be reset on all YubiKeys that support FIDO2. A reset will remove any credentials present and set the application to the "no PIN" state. However, there are some caveats: * The YubiKey will no longer be able to perform authentication with credentials that were removed from the FIDO2 application during the reset. * The process of resetting is a bit complicated; the .NET YubiKey API does not include a higher-level `Fido2Session` method for performing the entire operation. Instead, you must use a lower-level command class as described below. ##### Note The individual FIDO reset can be used with YubiKey Bio Multi-protocol Edition keys _only if_ the FIDO application is not "blocked" (check the key's [ResetBlocked](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.YubiKeyDevice.html#Yubico_YubiKey_YubiKeyDevice_ResetBlocked) property to confirm). Otherwise, the [device-wide reset](https://docs.yubico.com/yesdk/users-manual/sdk-programming-guide/bio-mpe.html#resetting-a-yubikey-bio-mpe) must be used instead. Steps ----- To perform a FIDO2 reset, complete the following: 1. "Reboot" the YubiKey by disconnecting it and reinserting it into the host device (USB) or placing it on an NFC reader. Connect to the YubiKey and its FIDO2 application once it has been reinserted. This will likely be done using a listener class (see [YubiKeyDeviceListener](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.YubiKeyDeviceListener.html) ). 2. Within a time limit from the reboot (10 seconds for YubiKeys with firmware version 5.5.4 and later or 5 seconds for firmware versions prior to 5.5.2), send the [ResetCommand](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Commands.ResetCommand.html) . ##### Note The reboot requirement and 10-second timeout are mandated by the [CTAP 2.1 standard](https://fidoalliance.org/specs/fido-v2.1-ps-20210615/fido-client-to-authenticator-protocol-v2.1-ps-errata-20220621.html#authenticatorReset) . 3. The YubiKey will not respond with the [ResetResponse](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Commands.ResetResponse.html) immediately. For USB connections, a user must touch the contact of the YubiKey within 30 seconds. If the touch does not occur in time, the YubiKey will return the `ResetResponse` with a `StatusWord` of `0x6F3A`, the CTAP error of timeout (the `Status` property will be `Failed`). If the user touches the contact within the time limit, then the FIDO2 application will be reset (the `StatusWord` property will be `0x9000`, and the `Status` property will be `Success`). For NFC connections, the YubiKey must remain in contact with the NFC reader throughout the operation. See the [FIDO2 reset APDU documentation](https://docs.yubico.com/yesdk/users-manual/application-fido2/apdu/reset.html) for information on other possible `StatusWord` responses. Sample code ----------- The [FIDO2 sample program](https://github.com/Yubico/Yubico.NET.SDK/tree/HEAD/Yubico.YubiKey/examples/Fido2SampleCode) (located under Yubico.YubiKey/examples/Fido2SampleCode/) contains a [class](https://github.com/Yubico/Yubico.NET.SDK/blob/HEAD/Yubico.YubiKey/examples/Fido2SampleCode/YubiKeyOperations/Fido2Reset.cs) (/Fido2SampleCode/YubiKeyOperations/Fido2Reset.cs) that demonstrates how to execute the FIDO2 reset steps. This includes code for: * creating a listener to determine when the YubiKey is removed and reinserted * notifying the user to remove, reinsert, and touch the YubiKey * calling the lower-level SDK command API to perform the reset once the key has been rebooted [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-fido2/fido2-reset.md/#L1) --- # How to program a slot with a static password ##### Table of Contents How to program a slot with a static password ============================================ To configure a [slot](https://docs.yubico.com/yesdk/users-manual/application-otp/slots.html) to emit a [static password](https://docs.yubico.com/yesdk/users-manual/application-otp/static-password.html) , you will use a [ConfigureStaticPassword](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.ConfigureStaticPassword.html) instance. It is instantiated by calling the factory method of the same name ([ConfigureStaticPassword()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.OtpSession.html#Yubico_YubiKey_Otp_OtpSession_ConfigureStaticPassword_Yubico_YubiKey_Otp_Slot_) ) on your [OtpSession](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.OtpSession.html) instance. The configuration properties of the static password you wish to set are specified by calling methods on your `ConfigureStaticPassword` instance. Each of those methods return a `this` reference back to the `ConfigureStaticPassword` instance. This allows you to chain together the configuration in a flexible and simple way, regardless of the combination of options you choose. ConfigureStaticPassword() properties ------------------------------------ `ConfigureStaticPassword()` allows you to either: * provide a specific static password with [SetPassword()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.ConfigureStaticPassword.html#Yubico_YubiKey_Otp_Operations_ConfigureStaticPassword_SetPassword_System_ReadOnlyMemory_System_Char__) , or * randomly generate a static password with [GeneratePassword()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.ConfigureStaticPassword.html#Yubico_YubiKey_Otp_Operations_ConfigureStaticPassword_GeneratePassword_System_Memory_System_Char__) . Both options require you to specify a keyboard layout by calling [WithKeyboard()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.ConfigureStaticPassword.html#Yubico_YubiKey_Otp_Operations_ConfigureStaticPassword_WithKeyboard_Yubico_Core_Devices_Hid_KeyboardLayout_) . If you do not call `WithKeyboard()`, an exception will be thrown. Static password characters are stored as [HID usage IDs](https://docs.yubico.com/yesdk/users-manual/application-otp/hid.html) on the YubiKey, and these usage IDs are communicated to a host device during an authentication attempt. Because some characters do not use the same HID usage ID across all keyboard layouts, the YubiKey needs to know which keyboard layout a user's host device is likely to use so that it can store the correct usage IDs. In addition to traditional keyboard layouts, such as German and US English, the [KeyboardLayout](https://docs.yubico.com/yesdk/core-api/Yubico.Core.Devices.Hid.KeyboardLayout.html) class also includes [ModHex](https://docs.yubico.com/yesdk/users-manual/application-otp/modhex.html) . For generated static passwords, if ModHex is selected as the keyboard layout, the generated password will only be composed of ModHex characters, which have the same HID usage IDs across all latin alphabet keyboard layouts. Therefore, in cases where the YubiKey will be used with host devices that implement multiple or unknown keyboard layouts, ModHex provides a way to ensure correct interpretation of the static password by all hosts. ##### Note Technically, ModHex can be selected as the keyboard layout when providing a password with `SetPassword()`, but it essentially acts as a check. If your provided password contains any characters that aren't ModHex, an exception will be thrown. Importantly, the `SetPassword()` and `GeneratePassword()` methods take a `Memory` reference (mutable) instead of a `string` (immutable in .NET). Because you should clear out sensitive data afterwards, a mutable (i.e. changeable) collection is used. Static passwords must be 1 to 38 characters in length ( the [MaxPasswordLength](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.ConfigureStaticPassword.html#Yubico_YubiKey_Otp_Operations_ConfigureStaticPassword_MaxPasswordLength) ). An exception will be thrown if the length of the provided or generated password is outside of this range. ConfigureStaticPassword() examples ---------------------------------- Before running any of the code provided below, make sure you have already connected to a particular YubiKey on your host device via the [YubiKeyDevice](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.YubiKeyDevice.html) class. To select the first available YubiKey connected to your host, use: IEnumerable yubiKeyList = YubiKeyDevice.FindAll(); var yubiKey = yubiKeyList.First(); ### Using SetPassword() The following example code sets a specific static password ("You'll never guess this!") on the [long-press](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Slot.html#Yubico_YubiKey_Otp_Slot_LongPress) slot on a YubiKey (with the US English keyboard layout) and adds a carriage return to the end of the password: using (OtpSession otp = new OtpSession(yubiKey)) { otp.ConfigureStaticPassword(Slot.LongPress) .WithKeyboard(Yubico.Core.Devices.Hid.KeyboardLayout.en_US) .AppendCarriageReturn() .SetPassword("You'll never guess this!".ToCharArray()) .Execute(); } Because each of these calls returns a reference to the `ConfigureStaticPassword` instance, you can break up the chain if you need to. For example: bool addCR = true; using (OtpSession otp = new OtpSession(yubiKey)) { ConfigureStaticPassword operation = otp.ConfigureStaticPassword(Slot.LongPress) .WithKeyboard(Yubico.Core.Devices.Hid.KeyboardLayout.en_US); if (addCR) { operation = operation.AppendCarriageReturn(); } operation.SetPassword("You'll never guess this!".ToCharArray()) .Execute(); } ### Using GeneratePassword() The following example code generates a 38-character static password (containing only ModHex characters) to use on the long-press slot on a YubiKey: Memory password = new char[ConfigureStaticPassword.MaxPasswordLength]; using (OtpSession otp = new OtpSession(yubiKey)) { otp.ConfigureStaticPassword(Slot.LongPress) .WithKeyboard(Yubico.Core.Devices.Hid.KeyboardLayout.en_ModHex) .GeneratePassword(password) .Execute(); } Because `GeneratePassword()` stores the generated password in the `password` char array, make sure to clear the data from `password` once it is no longer needed. Additional settings ------------------- The following additional (optional) settings can be applied during configuration: * [AppendCarriageReturn()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.ConfigureStaticPassword.html#Yubico_YubiKey_Otp_Operations_ConfigureStaticPassword_AppendCarriageReturn_System_Boolean_) * [AppendDelayToFixed()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.ConfigureStaticPassword.html#Yubico_YubiKey_Otp_Operations_ConfigureStaticPassword_AppendDelayToFixed_System_Boolean_) * [SendTabFirst()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.ConfigureStaticPassword.html#Yubico_YubiKey_Otp_Operations_ConfigureStaticPassword_SendTabFirst_System_Boolean_) * [SetAllowUpdate()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.ConfigureStaticPassword.html#Yubico_YubiKey_Otp_Operations_ConfigureStaticPassword_SetAllowUpdate_System_Boolean_) * [Use10msPacing()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.ConfigureStaticPassword.html#Yubico_YubiKey_Otp_Operations_ConfigureStaticPassword_Use10msPacing_System_Boolean_) * [Use20msPacing()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.ConfigureStaticPassword.html#Yubico_YubiKey_Otp_Operations_ConfigureStaticPassword_Use20msPacing_System_Boolean_) * [UseFastTrigger()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.ConfigureStaticPassword.html#Yubico_YubiKey_Otp_Operations_ConfigureStaticPassword_UseFastTrigger_System_Boolean_) * [UseNumericKeypad()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.ConfigureStaticPassword.html#Yubico_YubiKey_Otp_Operations_ConfigureStaticPassword_UseNumericKeypad_System_Boolean_) The static password does not have both a fixed part and a variable part like Yubico OTPs do, but you can still use `AppendDelayToFixed()` without error. [AppendTabToFixed()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.ConfigureStaticPassword.html#Yubico_YubiKey_Otp_Operations_ConfigureStaticPassword_AppendTabToFixed_System_Boolean_) will succeed, but instead of sending a tab before the static password, it will break up or alter the static password. Use `SendTabFirst()` instead. These settings can also be toggled after static password configuration by calling [UpdateSlot()](https://docs.yubico.com/yesdk/users-manual/application-otp/how-to-update-slot-settings.html) . ##### Note If you call `SetAllowUpdate(false)` during the inital configuration, you will not be able to update these settings with `UpdateSlot()` (the SDK will throw an exception). This can only be undone by reconfiguring the slot with `ConfigureStaticPassword()` (or another OTP application configuration). It is not necessary to call `SetAllowUpdate(true)` during configuration because updates are allowed by default. Most settings have default parameters, but they also allow you to specify the value, as shown with `AppendCarriageReturn()` in the example below: bool addCR = true; using (OtpSession otp = new OtpSession(yubiKey)) { otp.ConfigureStaticPassword(Slot.LongPress) .WithKeyboard(Yubico.Core.Devices.Hid.KeyboardLayout.en_US) .AppendCarriageReturn(addCR) .SetPassword("You'll never guess this!".ToCharArray()) .Execute(); } ### Manual updates Another optional setting that can be applied during static password configuration is [AllowManualUpdate()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.ConfigureStaticPassword.html#Yubico_YubiKey_Otp_Operations_ConfigureStaticPassword_AllowManualUpdate_System_Boolean_) . The manual update feature allows you to update the static password to a new randomly generated password by pressing and holding the contact of the YubiKey for 8-15 seconds. When the contact is released, the indicator light will flash. Touching the contact again confirms the change, and the new static password is generated and stored in the OTP slot. To enable the manual update feature, you must: 1. set the [static ticket flag](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.ConfigurationFlags.html#Yubico_YubiKey_Otp_ConfigurationFlags_StaticTicket) , then 2. set [AllowManualUpdate()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Operations.ConfigureStaticPassword.html#Yubico_YubiKey_Otp_Operations_ConfigureStaticPassword_AllowManualUpdate_System_Boolean_) to `true` when calling `ConfigureStaticPassword()`. If the static ticket flag is not set, an exception will be thrown when calling `AllowManualUpdate()`. At this time, the SDK does not provide an operations class for toggling the static ticket flag. [Configuration flags](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.ConfigurationFlags.html) , including the static ticket flag, can only be manipulated via the lower level [ConfigureSlotCommand class](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.Commands.ConfigureSlotCommand.html) . For more information on working with command classes, see the [SDK programming guide](https://docs.yubico.com/yesdk/users-manual/sdk-programming-guide/commands.html) . Slot reconfiguration and access codes ------------------------------------- If a slot is protected by an access code and you wish to reconfigure it with a static password, you must provide that access code with `UseCurrentAccessCode()` during the `ConfigureStaticPassword()` operation. Otherwise, the operation will fail and throw the following exception: `System.InvalidOperationException has been thrown. YubiKey Operation Failed. [Warning, state of non-volatile memory is unchanged.]` For more information on slot access codes, please see [How to set, reset, remove, and use slot access codes](https://docs.yubico.com/yesdk/users-manual/application-otp/how-to-slot-access-codes.html) . [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-otp/how-to-program-a-static-password.md/#L1) --- # Get application version ##### Table of Contents Get application version ======================= Get the version of the YubiHSM Auth application returned as a major, minor, and patch value. Available --------- All YubiKeys with the YubiHSM Auth application (included in firmware version 5.4.3 and later). ##### Note Use the .NET API's [HasFeature()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.YubiKeyFeatureExtensions.html#Yubico_YubiKey_YubiKeyFeatureExtensions_HasFeature_Yubico_YubiKey_IYubiKeyDevice_Yubico_YubiKey_YubiKeyFeature_) method to check if a key has the YubiHSM Auth application. SDK classes ----------- * [GetApplicationVersionCommand](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.YubiHsmAuth.Commands.GetApplicationVersionCommand.html) * [GetApplicationVersionResponse](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.YubiHsmAuth.Commands.GetApplicationVersionResponse.html) Input ----- None. Output ------ An array of three bytes which correspond with the major, minor, and patch value. Command APDU ------------ | CLA | INS | P1 | P2 | Lc | Data | Le | | --- | --- | --- | --- | --- | --- | --- | | 00 | 07 | 00 | 00 | (absent) | (absent) | (absent) | Response APDU ------------- Total Length: _5_ Data Length: _3_ | Data | SW1 | SW2 | | --- | --- | --- | | {major, minor, patch} | 90 | 00 | [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-yubihsm-auth/commands/get-application-version.md/#L1) --- # Reset application ##### Table of Contents Reset application ================= Reset the YubiHSM Auth application. All credentials will be deleted, the management key will be reset to the default value (all zeros), and the management key retry counter will be reset to 8. Available --------- All YubiKeys with the YubiHSM Auth application (included in firmware version 5.4.3 and later). ##### Note Use the .NET API's [HasFeature()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.YubiKeyFeatureExtensions.html#Yubico_YubiKey_YubiKeyFeatureExtensions_HasFeature_Yubico_YubiKey_IYubiKeyDevice_Yubico_YubiKey_YubiKeyFeature_) method to check if a key has the YubiHSM Auth application. SDK classes ----------- * [ResetApplicationCommand](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.YubiHsmAuth.Commands.ResetApplicationCommand.html) * [ResetApplicationResponse](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.YubiHsmAuth.Commands.ResetApplicationResponse.html) Input ----- None. Output ------ None. Command APDU ------------ | CLA | INS | P1 | P2 | Lc | Data | Le | | --- | --- | --- | --- | --- | --- | --- | | 00 | 06 | de | ad | (absent) | (absent) | (absent) | Response APDU ------------- Total Length: 2\\ | Data | SW1 | SW2 | | --- | --- | --- | | (no data) | 90 | 00 | [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-yubihsm-auth/commands/reset-application.md/#L1) --- # List credentials ##### Table of Contents List credentials ================ Get the public properties of all credentials present in the YubiHSM Auth application along with the number of retries remaining for each. Available --------- All YubiKeys with the YubiHSM Auth application (included in firmware version 5.4.3 and later). ##### Note Use the .NET API's [HasFeature()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.YubiKeyFeatureExtensions.html#Yubico_YubiKey_YubiKeyFeatureExtensions_HasFeature_Yubico_YubiKey_IYubiKeyDevice_Yubico_YubiKey_YubiKeyFeature_) method to check if a key has the YubiHSM Auth application. SDK classes ----------- * [ListCredentialsCommand](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.YubiHsmAuth.Commands.ListCredentialsCommand.html) * [ListCredentialsResponse](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.YubiHsmAuth.Commands.ListCredentialsResponse.html) Input ----- None. Output ------ A byte array formatted as a series of TLVs, where each element is a credential and its number of remaining retries. Each element in the series begins with the Tag 0x72 (known as LabelList). The data is formatted in the following order: | Order | Meaning | Size (bytes) | Comments | | --- | --- | --- | --- | | 1 | Cryptographic key type | 1 | See [CryptographicKeyType](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.YubiHsmAuth.CryptographicKeyType.html) | | 2 | Touch required | 1 | Boolean | | 3 | Label | 1-64 | ASCII string | | 4 | Retries remaining | 1 | Positive integer | For example, for a YubiKey with two credentials stored in the YubiHSM Auth application, the response data (in hexadecimal) might look like: Byte array: 72 07 26 00 61 62 63 00 04 72 08 26 01 77 78 79 7A 00 00 Notated: 72 07 Tag: LabelList, Length: 7 26 Key type: AES-128 00 Touch required: False 61 62 63 00 Label: 'abc\0' 04 Retries: 4 72 08 Tag: LabelList, Length: 8 26 Key type: AES-128 01 Touch required: True 77 78 79 7A 00 Label: 'wxyz\0' 00 Retries: 0 Command APDU ------------ | CLA | INS | P1 | P2 | Lc | Data | Le | | --- | --- | --- | --- | --- | --- | --- | | 00 | 05 | 00 | 00 | (absent) | (absent) | (absent) | Response APDU ------------- Total Length: _variable + 2_ Data Length: _variable_ | Data | SW1 | SW2 | | --- | --- | --- | | _data_ | 90 | 00 | [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-yubihsm-auth/commands/list-credentials.md/#L1) --- # Get management key retries ##### Table of Contents Get management key retries ========================== Get the number of retries remaining for the management key. Some operations require authentication with the management key (such as adding and deleting credentials). There is a limit of 8 attempts to authenticate with the management key before the management key is blocked. Once the management key is blocked, the application itself must be reset before authentication can be attempted again. To reset the application, see [ResetApplicationCommand](https://docs.yubico.com/yesdk/users-manual/application-yubihsm-auth/commands/reset-application.html) . Supplying the correct management key before the management key is blocked will reset the retry counter to 8. Available --------- All YubiKeys with the YubiHSM Auth application (included in firmware version 5.4.3 and later). ##### Note Use the .NET API's [HasFeature()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.YubiKeyFeatureExtensions.html#Yubico_YubiKey_YubiKeyFeatureExtensions_HasFeature_Yubico_YubiKey_IYubiKeyDevice_Yubico_YubiKey_YubiKeyFeature_) method to check if a key has the YubiHSM Auth application. SDK classes ----------- * [GetManagementKeyRetriesCommand](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.YubiHsmAuth.Commands.GetManagementKeyRetriesCommand.html) * [GetManagementKeyRetriesResponse](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.YubiHsmAuth.Commands.GetManagementKeyRetriesResponse.html) Input ----- None. Output ------ The number of retries for the management key, as a byte. Command APDU ------------ | CLA | INS | P1 | P2 | Lc | Data | Le | | --- | --- | --- | --- | --- | --- | --- | | 00 | 09 | 00 | 00 | (absent) | (absent) | (absent) | Response APDU ------------- Total Length: _3_ Data Length: _1_ | Data | SW1 | SW2 | | --- | --- | --- | | management key retries remaining | 90 | 00 | [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-yubihsm-auth/commands/get-management-key-retries.md/#L1) --- # Delete credential ##### Table of Contents Delete credential ================= Remove a credential from the YubiHSM Auth application. Available --------- All YubiKeys with the YubiHSM Auth application (included in firmware version 5.4.3 and later). ##### Note Use the .NET API's [HasFeature()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.YubiKeyFeatureExtensions.html#Yubico_YubiKey_YubiKeyFeatureExtensions_HasFeature_Yubico_YubiKey_IYubiKeyDevice_Yubico_YubiKey_YubiKeyFeature_) method to check if a key has the YubiHSM Auth application. SDK classes ----------- * [DeleteCredentialCommand](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.YubiHsmAuth.Commands.DeleteCredentialCommand.html) * [DeleteCredentialResponse](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.YubiHsmAuth.Commands.DeleteCredentialResponse.html) Input ----- The input includes the label of the credential to be deleted, and the management key. There is a limit of 8 attempts to authenticate with the management key before the management key is blocked. Once the management key is blocked, the application must be reset before performing operations which require authentication with the management key (such as adding credentials, deleting credentials, and changing the management key). To reset the application, see [ResetApplicationCommand](https://docs.yubico.com/yesdk/users-manual/application-yubihsm-auth/commands/reset-application.html) . Supplying the correct management key before the management key is blocked will reset the retry counter to 8. Output ------ None. Command APDU ------------ | CLA | INS | P1 | P2 | Lc | Data | Le | | --- | --- | --- | --- | --- | --- | --- | | 00 | 02 | 00 | 00 | _variable_ | (TLV, see below) | (absent) | ### Data The data is sent as concatenated TLV-formatted elements, as follows: | Tag (hexadecimal) | Length (decimal) | Value | Notes | | --- | --- | --- | --- | | 0x7b | 16 | management key | used to authenticate to the YubiHSM Auth application | | 0x71 | 1-64 | label | UTF-8 encoded string | Response APDU ------------- Total Length: 2\\ | Data | SW1 | SW2 | | --- | --- | --- | | (no data) | 90 | 00 | [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-yubihsm-auth/commands/delete-credential.md/#L1) --- # Get AES-128 session keys ##### Table of Contents Get AES-128 session keys ======================== Get the SCP03 session keys from an AES-128 credential. Available --------- All YubiKeys with the YubiHSM Auth application (included in firmware version 5.4.3 and later). ##### Note Use the .NET API's [HasFeature()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.YubiKeyFeatureExtensions.html#Yubico_YubiKey_YubiKeyFeatureExtensions_HasFeature_Yubico_YubiKey_IYubiKeyDevice_Yubico_YubiKey_YubiKeyFeature_) method to check if a key has the YubiHSM Auth application. SDK classes ----------- * [GetAes128SessionKeysCommand](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.YubiHsmAuth.Commands.GetAes128SessionKeysCommand.html) * [GetAes128SessionKeysResponse](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.YubiHsmAuth.Commands.GetAes128SessionKeysResponse.html) Input ----- Before calling this operation, the host needs to generate an 8-byte challenge (the host challenge). The host challenge is typically generated using a random or pseudorandom method. The host sends the host challenge to the HSM device, which returns its own 8-byte challenge (the HSM device challenge). See [YubiHSM Shell](https://developers.yubico.com/yubihsm-shell/) for ways to communicate with the HSM device. To call GetAes128SessionKeysCommand, you must pass it the label and password of the AES-128 credential that will be used to calculate the SCP03 session keys as well as the host challenge and HSM device challenge from the initial step. There is a limit of 8 attempts to authenticate with the password before the credential is deleted. Once the credential is deleted, it cannot be recovered. Supplying the correct password before the credential is deleted will reset the retry counter to 8. The credential may require proof of user presence. This is configured when the credential is added ( see [AddCredentialCommand](https://docs.yubico.com/yesdk/users-manual/application-yubihsm-auth/commands/add-credential.html) ). In this case, the user must touch the YubiKey in order to complete the authentication procedure. Otherwise, the command will fail (though the credential password retry counter does not change). Output ------ An array which contains the ENC, MAC, and R-MAC session keys. Each key is exactly 16-bytes long. In the case of a failure, the status word in the response may include further information. For example, the credential was configured to require touch, but the user did not touch the YubiKey. Command APDU ------------ | CLA | INS | P1 | P2 | Lc | Data | Le | | --- | --- | --- | --- | --- | --- | --- | | 00 | 03 | 00 | 00 | _variable_ | (TLV, see below) | (absent) | ### Data The data is sent as concatenated TLV-formatted elements, as follows: | Tag (hexadecimal) | Length (decimal) | Value | Notes | | --- | --- | --- | --- | | 0x71 | 1-64 | label | UTF-8 encoded string | | 0x77 | 16 | {host challenge, HSM device challenge} | challenges as byte arrays, concatenated together | | 0x73 | 16 | password | byte array | Response APDU ------------- Total Length: _50_ Data Length: _48_ | Data | SW1 | SW2 | | --- | --- | --- | | {ENC, MAC, R-MAC} | 90 | 00 | [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-yubihsm-auth/commands/get-aes128-session-keys.md/#L1) --- # Change management key ##### Table of Contents Change management key ===================== This command is used to change the management key. The management key is required when [adding](https://docs.yubico.com/yesdk/users-manual/application-yubihsm-auth/commands/add-credential.html) or [deleting](https://docs.yubico.com/yesdk/users-manual/application-yubihsm-auth/commands/delete-credential.html) credentials from the YubiHSM Auth application. There is a limit of 8 attempts to authenticate with the management key before the management key is blocked. Once the management key is blocked, the application itself must be reset before authentication can be attempted again. To reset the application, see [ResetApplicationCommand](https://docs.yubico.com/yesdk/users-manual/application-yubihsm-auth/commands/reset-application.html) . Supplying the correct management key before the management key is blocked will reset the retry counter to 8. Available --------- All YubiKeys with the YubiHSM Auth application (included in firmware version 5.4.3 and later). ##### Note Use the .NET API's [HasFeature()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.YubiKeyFeatureExtensions.html#Yubico_YubiKey_YubiKeyFeatureExtensions_HasFeature_Yubico_YubiKey_IYubiKeyDevice_Yubico_YubiKey_YubiKeyFeature_) method to check if a key has the YubiHSM Auth application. SDK classes ----------- * [ChangeManagementKeyCommand](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.YubiHsmAuth.Commands.ChangeManagementKeyCommand.html) * [ChangeManagementKeyResponse](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.YubiHsmAuth.Commands.ChangeManagementKeyResponse.html) Input ----- This command takes in the current management key and the new management key. Each management key is a byte array with exactly 16 bytes. The default value of the management key is all zeros: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 Output ------ None. Command APDU ------------ | CLA | INS | P1 | P2 | Lc | Data | Le | | --- | --- | --- | --- | --- | --- | --- | | 00 | 08 | 00 | 00 | 20 | See [section below](https://docs.yubico.com/yesdk/users-manual/application-yubihsm-auth/commands/change-management-key.html#data) | (absent) | ### Data The data field is a byte array formatted as a pair of TLVs representing the current and new management keys. Both TLV elements have the same tag and must be arranged in the following order: | Order | Meaning | Tag | Size (bytes) | | --- | --- | --- | --- | | 1 | Current management key | 0x7b | 16 | | 2 | New management key | 0x7b | 16 | Response APDU ------------- The data field is always empty. On success, the status word will be 0x90 0x00. If there was a failure, further information may be communicated in the status word. Total Length: 2\\ | Data | SW1 | SW2 | | --- | --- | --- | | (no data) | 90 | 00 | ### Common failure status words | Value | Meaning | | --- | --- | | 0x6983 | A credential with that label already exists | | 0x63c# | Wrong management key, where # is the number of attempts remaining (a maximum of 8) | | 0x6a80 | Wrong syntax | [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-yubihsm-auth/commands/change-management-key.md/#L1) --- # FIDO2 large blobs ("largeBlobs" option) ##### Table of Contents FIDO2 large blobs ("largeBlobs" option) ======================================= When you build a [Fido2Session](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Fido2Session.html) object, check the [AuthenticatorInfo](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.AuthenticatorInfo.html) to see if "largeBlobs" is supported. using (fido2Session = new Fido2Session(yubiKeyDevice)) { if (fido2Session.AuthenticatorInfo.GetOptionValue("largeBlobs") == OptionValue.True) { . . . } } If it does, you can add arbitrary data. There are two possibilities for this data: * arbitrary data not formatted or encoded * arbitrary data encoded following the FIDO2 standard The standard specifies a correct encoding of the large blobs data (see below). However, it also specifies that the responsibility of making sure the data is properly encoded belongs to the client (e.g. the browser), not the authenticator (i.e. the YubiKey). This means that whatever data you supply, the YubiKey will accept it and store it. When you retrieve that data, it is returned exactly how it was stored. Hence, it is possible to store absolutely arbitrary data. With the SDK it is possible by storing and retrieving large blobs through the [SetLargeBlobCommand](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Commands.SetLargeBlobCommand.html) and [GetLargeBlobCommand](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Commands.GetLargeBlobCommand.html) . However, that is not recommended, as other FIDO2 clients may be expecting well formed data. The SDK also offers a way to store data where the SDK performs all the formatting and encoding/decoding through the [SetSerializedLargeBlobArray](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Fido2Session.html#Yubico_YubiKey_Fido2_Fido2Session_SetSerializedLargeBlobArray_) and [GetSerializedLargeBlobArray](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Fido2Session.html#Yubico_YubiKey_Fido2_Fido2Session_GetSerializedLargeBlobArray_) methods in the [Fido2Session](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Fido2Session.html) class. Why the standard specifies the client encode -------------------------------------------- During the FIDO2 operations, the client might want to get the large blob data. However, there is no way of knowing in advance which client will be making this request. Will it be Chrome on Windows? Safari on Mac? Firefox on Linux? Or some other client? If the large blobs data is encoded in a standard way, each client will be able to read any data stored by any other client. If you know that there will be only one client that ever operates using your code, and that client will be able to read un-encoded arbitrary data, then you will likely be able to get away with it. But otherwise, a client might reject the un-encoded data, and might even reject the authentication. This is why it is not recommended to store an un-encoded large blob. So why is it the client's job to encode? The standard could have specified that the client provides whatever data it wants and the authenticator must encode it. However, that would require the authenticator contain the code to compress/decompress, encrypt/decrypt, and CBOR encode/decode. Because authenticators, such as the YubiKey, have very limited space and computing power, the FIDO2 standard specifies that these operations be performed by the client which typically runs on a far more capable device. How much data ------------- The standard also declares that the total number of bytes that can be stored is really `MaximumSerializedLargeBlobArray` minus 64. The reason is that there is "overhead". There are the encoding bytes (tags and lengths), of course, but there are also other bytes in the blob array, including a message digest, authentication tags, and nonces. Suppose the `MaximumSerializedLargeBlobArray` property is 1024 (the standard specifies that the maximum allowed length is at least 1024). That means you will have space for about 960 bytes. However, that's not entirely accurate either. The standard also specifies that the data be compressed. It is possible you have 1,000 bytes to store, but it compresses to 600 bytes, so it fits. Hence, what you really have is space for 960 bytes of compressed data. The SDK will perform the compression and decompression if you call the `Fido2Session.SetSerializedLargeBlobArray` and `Fido2Session.GetSerializedLargeBlobArray` methods. If you want to know the length the compressed data will be before calling the SDK, use the C# `System.IO.Compression.DeflateStream` class. But you must always pass the uncompressed data to the `SerializedLargeBlobArray.AddEntry` method. Per credential data ------------------- The standard specifies that the data to be stored is encrypted. It also specifies that the key used to encrypt/decrypt is the "[LargeBlobKey](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.GetAssertionData.html#Yubico_YubiKey_Fido2_GetAssertionData_LargeBlobKey) ". This key is associated with a specific credential. That is, if there are no credentials on your YubiKey, then there is no `LargeBlobKey`, you cannot encrypt any large blob data, so you cannot store a large blob. If you have two credentials on your YubiKey, then there are two `LargeBlobKeys`. Hence, any data you encrypt using one of the keys will be tied to that key's credential. This also means that it is not possible to store any "general", unencrypted data. The standard specifies that the large blob stored is actually an array. Each element in the array is data encrypted by one of the `LargeBlobKeys`. That is, each element in the array is data associated with one credential. ### Making a credential with a `LargeBlobKey` If a YubiKey supports the large blob option, you must make a credential with the large blob extension set to true. var mcParams = new MakeCredentialParameters(relyingParty, userEntity) { ClientDataHash = clientDataHash }; mcParams.AddOption(AuthenticatorOptions.rk, true); mcParams.AddExtension("largeBlobKey", new byte[] { 0xF5 }); isValid = fido2Session.TryVerifyPin(pinBytes, null, null, out retries, out reboot); MakeCredentialData mcData = fido2Session.MakeCredential(mcParams); The `MakeCredentialData` returned has a property for the [LargeBlobKey](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.MakeCredentialData.html#Yubico_YubiKey_Fido2_MakeCredentialData_LargeBlobKey) . If you want, you can save that key for later on when you want to set or read any data stored against this credential. However, you will most likely not save it, but instead get the `LargeBlobKey` each time you need it by getting an assertion. var gaParams = new GetAssertionParameters(relyingParty, clientDataHash); gaParams.AddExtension("largeBlobKey", new byte[] { 0xF5 }); IReadOnlyList assertions = fido2.GetAssertions(gaParams); If a credential was made with the "largeBlobKey" extension then [assertions\[i\].LargeBlobKey](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.GetAssertionData.html#Yubico_YubiKey_Fido2_GetAssertionData_LargeBlobKey) will not be null, and will contain the same large blob key that was returned by the make credential call. The serialized large blob array ------------------------------- The standard specifies that the data store be a "serialized large blob array". This is the concatenation of the "large blob array" and a digest. CBOR-encoded large blob array || left-16( SHA-256(CBOR-encoded large blob array) ) This means that to store large blobs, the caller must build each entry, combine the entries into a single buffer encoded following the CBOR rules, then use SHA-256 to digest the encoding, and store the concatenation of the two. Most of this work is done by the SDK using the [SerializedLargeBlobArray](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.SerializedLargeBlobArray.html) class and the `Fido2Session.SetSerializedLargeBlobArray` method. The initial serialized large blob array --------------------------------------- The standard specifies that an authenticator that supports large blobs must be manufactured with an initial value. That value is an empty array, followed by the digest of the empty array. 80 76 be 8b 52 8d 00 75 f7 aa e9 8d 6f a5 7a 6d 3c The `80` is the CBOR encoding of an empty array (`8x` is the CBOR tag for array of `x` entries, so `83` is an array of three entries and `80` is an array of zero entries). Perform SHA-256 on the single byte `80` and retain only the first (or "left") 16 bytes, and the result is `76 BE ... 3C`. Getting the current large blob ------------------------------ SerializedLargeBlobArray currentLargeBlob = fido2Session.GetSerializedLargeBlobArray(); This returns the contents of the YubiKey's large blob, decoded into a new `SerializedLargeBlobArray` object. You can check the `Entries` property to see how many elements have been stored. int count = currentLargeBlob.Entries.Count; If the YubiKey contains only the initial large blob data, the `count` will be zero. You can also call the [IsDigestVerified](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.SerializedLargeBlobArray.html#Yubico_YubiKey_Fido2_SerializedLargeBlobArray_IsDigestVerified) method to verify that the digest value is correct. ### Updating the current large blob, add an entry Once you have the current large blob data, you can add, remove, or "edit" entries. To add an entry, you need the `LargeBlobKey`. currentLargeBlob.AddEntry(dataToAdd, assertion[i].LargeBlobKey); At this point, the `EncodedArray` and `Digest` properties are now null. When we first obtained the serialized large blob array, the object presented the encoded large blob array along with the digest. Now, if we add a new entry, that old encoding and old digest are no longer valid. If you want, you can call the `Encode` method, but there's no need. The SDK will call it when you try to store this new large blob. ### Updating the current large blob, remove an entry If there is an entry you no longer want stored (e.g. a credential is removed, so any large blobs associated can be removed), call the `RemoveEntry` method. currentLargeBlob.RemoveEntry(index); Note that this removes the entry at the given index, so you will likely need to decrypt entries to make sure you have the index of the one you want to remove. Note also that it will not remove it from the YubiKey, it will only remove it from the `SerializedLargeBlobArray` object. Once you set the YubiKey with the new object, the new array will overwrite the old array, meaning the removed entry no longer exists on the YubiKey. ### Updating the current large blob, "edit" an entry If you want to keep an entry, but change the contents, you must build your new blob data from the old data, call `AddEntry` with the new blob data (and appropriate large blob key), and call `RemoveEntry` on the old entry's index. [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-fido2/large-blobs.md/#L1) --- # FIDO2 Credentials ##### Table of Contents FIDO2 Credentials ================= A credential is what the YubiKey builds and sends to the relying party. In turn, the relying party uses the credential to verify an assertion the YubiKey will build during a later authentication procedure. In FIDO2, a credential is a public key. The private key partner is generated on the YubiKey (in the secure element) and never leaves the device. When authenticating to the relying party, the YubiKey will build an assertion by using the private key to sign some data that includes a challenge from the relyng party. The relying party will verify the signature, thus verifying the assertion, in order to authenticate the YubiKey. There are two kinds of credentials: * Discoverable (FIDO2 version 2.0: resident keys) * Non-discoverable or server-side (FIDO2 version 2.0: non-resident credentials) A discoverable credential is stored on the YubiKey. It can be seen or used if you have only the relying party ID. For example, if you want to get information about a discoverable credential, you can simply ask the YubiKey to enumerate all credentials associated with a particular relying party. You need only supply the relying party ID. A non-discoverable credential is not stored on the YubiKey (hence the FIDO2 version 2.0 term "non-resident"). The credential is not stored anywhere, rather, the YubiKey can reconstruct a non-discoverable credential if it has enough information. That includes the credential ID. If you build a non-discoverable credential, then you must manage the credential ID yourself. Then, when you need an assertion for that credential, supply the credential ID and the YubiKey will be able to get an assertion. There are two main operations in FIDO2: * Make a credential (registration) * Get an assertion (authenticate) Make a credential (registration) -------------------------------- The process of making a credential is generally the following: * Relying party information (name, ID), a "client data hash" (which includes a challenge from the relying party), as well as other system information is sent to the YubiKey. * The YubiKey generates a key pair, signs the input information, and returns the public key and signature, along with an attestation statement and attestation certificate. * The relying party verifies the signature using the public key and verifies the public key using the attestation statement and certificate. At this point, the YubiKey contains an entry for this credential, and the relying party can update its entry for the user. The YubiKey's entry contains the relying party information and the private key. The relying party's user entry is updated with the public key. The SDK offers two ways to make a credential: * [Fido2Session.MakeCredential](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Fido2Session.html#Yubico_YubiKey_Fido2_Fido2Session_MakeCredential_) * [MakeCredentialCommand](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Commands.MakeCredentialCommand.html) Most developers will use `Fido2Session.MakeCredential` because it is easier and more straightforward to use. ### Make credential parameters When you make a credential, you need to specify for which relying party this credential is being built. Therefore, of course, the relying party is one of the parameters for making a credential. However, there are several more parameters to consider. The standard specifies that some of them are required, and some are optional. Some of the parameters the standard describes as optional are required by the YubiKey. This is because the YubiKey requires a PIN. The standard allows an authenticator to be used without a PIN. In such a situation, if the client can connect to the authenticator, and user presence is proven (e.g. touch a sensor), then the operation will proceed. The YubiKey, in contrast, will only work with a PIN. If you want to make a credential, the YubiKey must have a PIN set, and the PIN must be entered. Two of the parameters, `Protocol` and `PinUvAuthParam` are related to the PIN, and, therefore, are required. If you make a credential using `MakeCredentialCommand`, you must supply them. However, if you use the `Fido2Session.MakeCredential` method, the SDK will collect them for you. In fact, even if you supply them, the SDK will ignore what you supply and collect them anyway. You collect all the parameters in the [MakeCredentialParameters](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.MakeCredentialParameters.html) class. According to the FIDO2 standard, these are the required elements: * ClientDataHash * RelyingParty * UserEntity * Algorithms (pubKeyCredParams) The following are optional in the FIDO2 standard, but required by the YubiKey. Remember, if you use `Fido2Session.MakeCredential`, you should not supply these parameters. If you do, they will be ignored. * Protocol * PinUvAuthParam The following are optional for both the FIDO2 standard and the YubiKey: * ExcludeList * Extensions * Options (only "rk" is allowed when making credentials on a YubiKey, see section 6.1 of the FIDO2 standard, for more information on Options and "rk") * EnterpriseAttestation ##### Note The FIDO2 standard specifies that a `UserEntity` is a required element in order to make a credential. The `UserEntity` is made up of an `ID`, a `Name`, and a `DisplayName`. The standard also says the `Name` and `DisplayName` are optional. It should be possible to make a credential using a `UserEntity` that contains only an `ID`. However, YubiKeys prior to version 5.3.0 require a `Name` in order to make a credential. ### MakeCredential example using var fido2Session = new Fido2Session(yubiKey) { // If you do not call a VerifyPin method directly, the SDK will call // it automatically. But for automatic PIN collection, you must supply // a KeyCollector. fido2Session.KeyCollector = SomeKeyCollector; // Although the YubiKey requires the Protocol and PinUvAuthParam, // don't supply them here because the SDK's Fido2Session.MakeCredential // method will set these values correctly. var makeCredentialParams = new MakeCredentialParameters( new RelyingParty("sample-rp"), new UserEntity("sample-user")) { ClientDataHash = sampleClientDataHash; }; // To make the credential discoverable (stored on the YubiKey), you must // set the "rk" option to true. makeCredParams.AddOption(AuthenticatorOptions.rk, true); MakeCredentialData credentialData = fido2Session.MakeCredential(makeCredentialParams); } Get an assertion (authenticate) ------------------------------- When the user needs to authenticate to the relying party, the YubiKey will build an assertion. If the relying party verifies the assertion, the user is authenticated. The assertion is a signature. The authenticator signed data that included a challenge from the relying party. The relying party tries to verify the signature using the public key (credential) it has in its user data. If that key does not verify the signature, either the challenge was not signed (maybe an attacker sent an old, intercepted signature in a replay attack), or the wrong private key was used (e.g. a YubiKey that has a private key associated with the relying party, but it is not the one associated with the account). Before the YubiKey can build an assertion, it must know which private key to use. It does so by finding the private key associated with the relying party. Remember that when the credential was first registered, the relying party information was stored with the appropriate private key. During authentication, the client (browser) will send a message to the YubiKey, requesting it sign the challenge (and other data) using the private key associated with the provided relying party. If the YubiKey cannot find an entry for the given relying party, it will not sign anything. This generally happens when the client is connected to an attacker and not the correct target. That is, the user wants to connect with relying party A, but has somehow been hijacked and is connected to relying party X. The client (browser) will send to the YubiKey the relying party information of who it is actually connected to, not the target. The SDK offers three ways to get an assertion: * [Fido2Session.GetAssertions](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Fido2Session.html#Yubico_YubiKey_Fido2_Fido2Session_GetAssertions_) * [GetAssertionCommand](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Commands.GetAssertionCommand.html) * [GetNextAssertionCommand](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Commands.GetNextAssertionCommand.html) if there are multiple credentials Most developers will use `Fido2Session.GetAssertions` because it is easier and more straightforward to use. ### Get assertion parameters As is the case with making a credential, there are parameters needed to get an assertion. The FIDO2 standard specifies some as required and others as optional. In addition, as with making a credential, some of the standard's optional parameters (PIN-related) are required by the YubiKey. However, if you use the `Fido2Session.GetAssertions` method, the SDK will collect them for you. In fact, even if you supply them, the SDK will ignore what you supply and collect them anyway. You collect all the parameters in the [GetAssertionParameters](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.GetAssertionParameters.html) class. According to the standard, these are the required elements: * ClientDataHash * RelyingParty The following are optional in the FIDO2 standard, but required by the YubiKey. Remember, if you use `Fido2Session.GetAssertions`, you should not supply these parameters. If you do, they will be ignored. * Protocol * PinUvAuthParam The following are optional for both the FIDO2 standard and the YubiKey: * AllowList * Extensions * Options (only "up" is allowed when getting an assertion on a YubiKey, see section 6.1 of the FIDO2 standard, for more information on Options and "up") ##### Note The `AllowList` is required if there are credentials created as non-discoverable. Multiple credentials -------------------- It is possible a YubiKey holds multiple credentials for any particular relying party. This might happen because a single user has multiple roles, such as end user, administrator, and so on. This is why the return from `Fido2Session.GetAssertions` returns an `IList`. If there is only one assertion, the list will contain only one element. But if there are more, you can examine each of the assertions to see which one you want to send. Each assertion is represented as a [GetAssertionData](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.GetAssertionData.html) object. That object contains information such as user data, which you can use to determine which one to send to the relying party. ### `GetNextAssertion` If there are multiple assertions available, and you use the `GetAssertionCommand`, it will return the first assertion found on the YubiKey, along with information about the assertion (e.g. user name) and a count of the total number of assertions available. It will then be necessary to call the [GetNextAssertionCommand](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Commands.GetNextAssertionCommand.html) . Your code will look something like this: var getAssertionCommand = new GetAssertionCommand(assertionParams); GetAssertionResponse getAssertionResponse = connection.SendCommand(getAssertionCommand); GetAssertionData getAssertionData = getAssertionResponse.GetData(); int count = getAssertionData.NumberOfCredentials ?? 0; for (int index = 1; index < count; index++) { var getNextAssertionCommand = new GetNextAssertionCommand(); getAssertionResponse = connection.SendCommand(getNextAssertionCommand); getAssertionData = getAssertionResponse.GetData(); } The data type returned by the `GetNextAssertionCommand` is the same as the type returned by the `GetAssertionCommand`, namely the assertion and identifying information. The actual data is different, of course, because they are returning the data for two assertions. There is also another difference. The return from the first call to `GetAssertionCommand` contained the total number of credentials. You need to capture that number because each successive call to the `GetNextAsssertionCommand` will not return it. That is, for each successive call to `GetNextAssertionCommand`, the `NumberOfCredentials` field will be null. It is the FIDO2 standard that specifies that the `GetNextAssertionCommand` not return the number of credentials, or number of credentials remaining. It is also important to note that the first call returned the first (index of zero) assertion, so you need to continue counting at the second (index of one) assertion. Hence, the for loop is `int index = 1; index < count; index++`. [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-fido2/fido2-credentials.md/#L1) --- # Commands ##### Table of Contents Commands ======== Any operation the YubiKey performs will be a collection of commands. Think of a command as the smallest unit of function on a YubiKey. For example, suppose the operation you want to perform is getting the serial number of the key. There is a PIV command to do that: [GetSerialNumberCommand](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.Commands.GetSerialNumberCommand.html) . But suppose you want to create a digital signature using PIV. That operation is made up of work done off the YubiKey (digesting the data and formatting a block), then calling on the YubiKey AUTHENTICATE:SIGN command. But the operation also requires authentication by entering the PIN, which is the VERIFY command. So the signing operation is made up of two commands. There are SDK APIs for operations. Those classes will call on the appropriate YubiKey commands "under the covers". But if you want to perform a particular command, there is the command API. You can find the details of all the commands in each application's namespace, such as [Yubico.YubiKey.Piv.Commands](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.Commands.html) . The command and APDU -------------------- A command is the function you want the YubiKey to perform. The message sent to the YubiKey instructing it to perform the command is a "command APDU" (Application Protocol Data Unit, see the User's Manual entry on [APDUs](https://docs.yubico.com/yesdk/users-manual/yubikey-reference/apdu.html) ). The YubiKey performs the command and returns the result in the form of a "response APDU". The command API in the SDK is a collection of classes that represent each of the commands a YubiKey can perform, and each of the responses. Under the covers, each command class will know how to build the command APDU, and each response class will know how to parse and present the response APDU. You don't really need to know about the specific APDUs, just the command and response classes. Commands and applications ------------------------- There are seven YubiKey applications: * Management * OTP * FIDO U2F * FIDO2 * PIV * OpenPGP Card * OATH Each application has its own set of commands. Generally, you will want to perform an operation for a specific application. For example, your application might want to perform a Yubico Challenge-Response OTP generation. Look in the OTP commands section to find the commands you need to perform to do so. You will not find analagous commands in the PIV or OpenPGP Card applications because computing Yubico OTP Challenge-Response OTPs is not something they can do. Executing a command in the SDK ------------------------------ In general, to execute a command, you will call on the `SendCommand` method in one of the classes that implements the [IYubiKeyConnection](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.IYubiKeyConnection.html) interface. TResponse SendCommand(IYubiKeyCommand yubiKeyCommand) where TResponse : IYubiKeyResponse; Visit the [Making a Connection](https://docs.yubico.com/yesdk/users-manual/sdk-programming-guide/making-a-connection.html) page in the User's Manual for more information on connections. What this means is that you are going to build an instance of a class that implements the [IYubiKeyCommand](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.IYubiKeyCommand-1.html) interface. You will then pass that object to the `SendCommand` method. The return from that call will be an object that implements the [IYubiKeyResponse](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.IYubiKeyResponse.html) interface. ### The command and response pair When you find the class that represents the command you want to perform, read the documentation for that class. It will describe its partner response class. You now know what type the return value to the `SendCommand` will be. For example, suppose you want to execute the PIV application's get version command. Find the class: [VersionCommand](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.Commands.VersionCommand.html) . The documentation says, > Get the YubiKey's firmware version. > The partner response class is VersionResponse. You can now write the following VersionCommand versionCommand = new VersionCommand(); VersionResponse versionResponse = connection.SendCommand(versionCommand); ### The response With the response object, you will be able to see the results of the command. There are generally three things you want to see: * The Status * A message explaining the status * The Data Note: The Status Word is the APDU's response code (see [APDU](https://docs.yubico.com/yesdk/users-manual/yubikey-reference/apdu.html) ). Most of the time you will likely not worry about this. But it is provided in case you do need to examine it. The Status is the SDK response code. It describes the result of the what the command object did. The possible values are in the [ResponseStatus](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.ResponseStatus.html) enum. The StatusMessage gives similar information to the Status, but is intended to be displayed to the end-user when an unhandled error occurs. The Data is the actual data returned by the YubiKey. The response class parsed it and now offers to return it in a more consumable form. You get the data by calling the response class's `GetData` method. If the object's state is invalid, the `GetData` method will throw an exception. Therefore it is best to first check `Status` before calling `GetData`. That way errors can be handled without relying on exceptions. Each response class will specify the format of the data returned. For example, the response to the get version command is public class FirmwareVersion { public byte Major { get; set; } public byte Minor { get; set; } public byte Patch { get; set; } . . . } After calling the `SendCommand` method, you now have a response object. First check the `Status` to ensure it executed as expected, and then call that object's `GetData` method. VersionCommand versionCommand = new VersionCommand(); VersionResponse versionResponse = connection.SendCommand(versionCommand); if (versionResponse.Status != ResponseStatus.Success) { // In this example, we're not trying to recover; simply throw an exception throw new Exception(versionResponse.StatusMessage) } FirmwareVersion versionNum = versionResponse.GetData(); You can now examine the version number as versionNum.Major, versionNum.Minor, versionNum.Patch ### Command failure data Sometimes, the SDK encounters an error when executing a command. For example, suppose you call the PIV's get serial number command and an error was encountered. The Response object ([GetSerialNumberResponse](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.Commands.GetSerialNumberResponse.html) ) will be successfully constructed, but the `Status` will be set to a non "Success" value such as `ResponseStatus.Failed`. In this state, the `GetData` method will throw an exception because it will not be able to successfuly parse the result. Therefore it is best to first check `Status` before calling `GetData`. That way errors can be handled without relying on exceptions. int serialNumber; GetSerialNumberCommand serialCommand = new GetSerialNumberCommand(); GetSerialNumberResponse serialResponse = connection.SendCommand(serialCommand); if (serialResponse.Status == ResponseStatus.Success) { serialNumber = serialResponse.GetData(); } ### Data not found It is possible that you call a command to get data from the YubiKey, yet there is no data. For example, suppose you call the PIV application's GET DATA command, requesting the cert in slot 9C -- but there is no cert in slot 9C. In this situation the `Status` will be set to `ResponseStatus.NoData`. This means that the command was simply unable to find the requested data. This should be sufficient to understand the result of the command. Because no data could be returned, if you call `GetData` it will throw an exception. ### No response data Some responses have no data. For example, the PIV applications PUT DATA command will load some information onto the YubiKey. It simply returns a `Status` indicating whether it was successful or encountered an error. That's it. For responses that do not have data, the response class will implement the [IYubiKeyResponse](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.IYubiKeyResponse.html) interface only. That interface does not have a `GetData` method. If you try to get data out of a response class that has no data, your code will not compile. Incidentally, notice that response classes that do return data implement two interfaces: * [IYubiKeyResponse](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.IYubiKeyResponse.html) * [IYubiKeyResponseWithData](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.IYubiKeyResponseWithData-1.html) The "WithData" interface is where the `GetData` method is declared. The documentation for the command class led you to its partner, the response class. The documentation for that class will indicate whether it has data or not, and if so, in what format the data is returned. ### Input data to the command In the `VersionCommand` example, there was no input data. Some commands require user input. For example, to perform the PIV's AUTHENTICATE:SIGN command, you need the PIN, the data to sign (formatted), and the slot number of the key to use. Generally, you will provide the input data in the command class's constructor. [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/sdk-programming-guide/commands.md/#L1) --- # PIV data objects ##### Table of Contents PIV data objects ================ The YubiKey's PIV application has space for storing certain elements other than keys and certificates. Most of these elements are defined by the PIV standard, but there are also Yubico-defined items. It is also possible for an app to store its own data in its own locations. A data object is made up of a tag and data. The tag is simply a number and the data is different for each tag. That is, a particular number will be defined as a PIV DataTag, and associated with it is a set of elements that are combined into a single blob of data following a specific encoding. The DataTags ------------ There are three classes of DataTag in the YubiKey: * PIV standard-defined tags * Yubico-defined tags * undefined tags On a YubiKey, any number between `0x005F0000` and `0x005FFFFF` (inclusive) can be a valid DataTag. In addition, there are two numbers not in that range that are valid DataTags: `0x0000007E` and `0x00007F61`. The following table lists the numbers the PIV standard defines as DataTags (see also the [table of PIV tags](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#getdatatable) in the article on PIV commands). #### Table 1A: PIV standard-defined DataTags | Number | Name | PIN required for read | | --- | --- | --- | | 0x0000007E | DISCOVERY | No | | 0x00007F61 | BITGT | No | | 0x005FC101 | Card Auth (cert) | No | | 0x005FC102 | CHUID | No | | 0x005FC103 | Fingerprints | Yes | | 0x005FC104 | \-unused- | No | | 0x005FC105 | Auth (cert) | No | | 0x005FC106 | Security | No | | 0x005FC107 | CCC | No | | 0x005FC108 | Facial Image | Yes | | 0x005FC109 | Printed | Yes | | 0x005FC10A | Signature (cert) | No | | 0x005FC10B | Key Mgmt (cert) | No | | 0x005FC10C | Key History | No | | 0x005FC10D - 0x005FC120 | Retired (certs) | No | | 0x005FC121 | Iris | Yes | | 0x005FC122 | SM Signer (cert) | No | | 0x005FC123 | PC Ref Data | No | This next table lists the numbers Yubico defines as DataTags (see also the [table of Yubico tags](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#getvendordatatable) in the article on PIV commands). #### Table 1B: Yubico-defined DataTags | Number | Name | PIN required for read | | --- | --- | --- | | 0x005FFF00 | Admin Data | No | | 0x005FFF01 | Attestation Cert | No | | 0x005FFF10 | MSCMAP | No | | 0x005FFF11 - 0x005FFF15 | MSROOTS | No | Finally, these are the numbers a YubiKey will accept as a DataTag, but currently have no specific meaning or data assigned to them. None of them require PIN verification in order to read the contents. #### Table 1C: Undefined DataTags | Number range | Count | PIN required for read | | --- | --- | --- | | 0x005F0000 - 0x005FC100 | over 6 million possible numbers | No | | 0x005FC124 - 0x005FFEFF | over 6 million possible numbers | No | | 0x005FFF02 - 0x005FFF0F | 14 numbers | No | | 0x005FFF16 - 0x005FFFFF | 223 numbers | No | It is possible for an application to store whatever information it wants on a YubiKey under an undefined DataTag. However, there are space limitations. It is possible to store at most approximately 3,052 bytes under any single undefined DataTag, and the total space on a YubiKey for all storage is about 51,000 bytes. The Data -------- Associated with each DataTag is a specified set of elements that make up the data, along with a definition of its encoding. The encoding is a TLV structure. TLV stands for "tag-length-value". So there is a DataTag for the data itself, specifying where, in the YubiKey, the object will be stored. Then there are tags used to encode the data itself. The YubiKey itself will enforce only one part of the encoding, the initial tag and length. Most elements are encoded as 53 length something There are two exceptions: Discovery and BITGT, see the [entry on commands](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#getdatatable) . The YubiKey verifies that the data for a data object sent in has the leading `53` tag (or the two exceptions) with a correct length, but other than that, it does not check the encoding. However, the SDK itself makes sure any input data follows the defined encoding. For example, if you want to store CHUID data in the CHUID storage area, the SDK can encode it for you if you use the [CHUID class](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.Objects.CardholderUniqueId.html) . But if you use the [GetDataCommand](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.Commands.GetDataCommand.html) , you must make sure the data is properly encoded. If you want to store some other data in the CHUID area, not encoded as defined, you will have to use a different tool. The encoding definitions are specified in the [table of PIV tags](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#getdatatable) . Reading and writing data objects -------------------------------- In the SDK, there are two ways to read data into and write data out of these storage locations: * [PivSession.Read](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.PivSession.html#Yubico_YubiKey_Piv_PivSession_ReadObject_) and [PivSession.Write](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.PivSession.html#Yubico_YubiKey_Piv_PivSession_WriteObject_) * [GET DATA](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#get-data) and [PUT DATA](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#put-data) `PivSession ReadObject` and `WriteObject` ----------------------------------------- These methods require a subclass of [PivDataObject](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.Objects.PivDataObject.html) . Each subclass is a representation of a data object. It will know what data it holds and how to Encode and Decode it. For example, the [CHUID class](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.Objects.CardholderUniqueId.html) represents the PIV standard's Cardholder Unique ID. It contains properties for each element of a CHUID: * FASC Number * GUID * Expiration Date It knows how to encode these three elements into a single byte array following the PIV standard, and how to decode a CHUID encoding into the three elements. The `Write` method will be able to take the data out of the `PivDataObject` it is given and store it in the appropriate location on the YubiKey. The `Read` method will be able to retrieve the requested data from the YubiKey and return the appropriate `PivDataObject` object containing that data. For example, using (var pivSession = new PivSession(yubiKey)) { var collectorObj = new SomeKeyCollector(); pivSession.KeyCollector = collectorObj.KeyCollectorDelegate; KeyHistory history = pivSession.ReadObject(); if (history.IsEmpty) { // There was no KeyHistory data on the YubiKey // Code to handle this case here. } DisplayResults( history.OnCardCertificates, history.OffCardCertificates, history.OffCardCertificateUrl); using (var pivSession = new PivSession(yubiKey)) { var collectorObj = new SomeKeyCollector(); pivSession.KeyCollector = collectorObj.KeyCollectorDelegate; // Build a KeyHistory to store. var history = new KeyHistory(); history.OnCardCertificates = 1; history.OffCardCertificates = 2; history.OffCardCertificateUrl = new Uri("file://user/certs"); pivSession.WriteObject(history); } Currently there are `PivDataObjects` for the following DataTags: * [CHUID](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.Objects.CardholderUniqueId.html) * [CCC](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.Objects.CardCapabilityContainer.html) * [Key History](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.Objects.KeyHistory.html) * [Admin Data](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.Objects.AdminData.html) * [Pin-Protected Data](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.Objects.PinProtectedData.html) (a special case, see below) If you need to store/retrieve other elements, use `GET DATA` and `PUT DATA`. Yubico will add more Data Objects based on customer demand. The data stored and `IsEmpty` ----------------------------- Lets look at Key History as an example. The [KeyHistory](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#encoded-key-history) data object is specified by the PIV standard to contain three things: * number of on-card certificates * number of off-card certificates * URL where the off-card certificates can be found The [KeyHistory](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.Objects.KeyHistory.html) class contains properties for each of these elements. Suppose you call using KeyHistory keyHistory = pivSession.ReadObject(); Upon return, look at the [IsEmpty](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.Objects.PivDataObject.html#Yubico_YubiKey_Piv_Objects_PivDataObject_IsEmpty_) property. If it is `true`, then there was no `KeyHistory` data on the YubiKey. It also means that the data at the other properties (`OnCardCertificates`, etc.) is meaningless. Sure, if you access the `OnCardCertificates`, it will say zero. But because the object is empty, that value is not necessarily accurate. If `IsEmpty` is `false`, then the Read operation was able to find Key History data on the YubiKey, decode it, and set the new `KeyHistory` object with the data it found. Look at the properties, this is what had been written to the YubiKey. Maybe the `OnCardCertificates` is `2`. But it can also be zero. But now because we know that there was indeed data on the YubiKey in the Key History storage area, we know that number reflects what was stored there. There is also a property public Uri? OffCardCertificateUrl { get; set; } // Note that the `Uri` class is a reference type, so `Uri?` means it is a // "nullable reference type". It is NOT `Nullable`. That is only // possible with value types, such as `ReadOnlyMemory`. Check to see if it is null. If so, then there was no URL. The standard specifies that it is possible the Key History data has no URL. if (!(keyHistory.OffcardCertificateUrl is null)) { ProcessUrl(keyHistory.OffcardCertificateUrl); } The data in the storage location is simply what some application has set it to. It is not placed there by the YubiKey. For example, suppose there are four PIV key slots on a YubiKey that have both keys and certificates. The YubiKey itself will not set the Key History data object. If you read the Key History, it will be empty. Now suppose an application sets the Key History, and says there are two `OnCardCertificates`. The YubiKey is not going to check the input against the contents of the slots. Even though there are four certificates on the card, the Key History will be set to two. ### Writing data When you create a new instance of a `PivDataObject`, it starts out as empty, `IsEmpty` is `true`. The contents of the other properties are meaningless, although they might start out as zero or null. Some properties are fixed (e.g. see the CHUID FASC number) so their initial value is correct, even if an object is empty. If you tried to encode or Write this object (see [Encode](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.Objects.PivDataObject.html#Yubico_YubiKey_Piv_Objects_PivDataObject_Encode) and [Write](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.PivSession.html#Yubico_YubiKey_Piv_PivSession_WriteObject_) ), you would get an exception. When you set one of the properties, the object is no longer empty. For example, using var adminData = new AdminData(); // At this point, adminData.IsEmpty is true. adminData.PinProtected = true; // At this point, adminData.IsEmpty is false. Now you can Encode or Write. Because you have not set the `Salt` nor the `PinLastUpdated`, the encoding won't include those elements. The encoded ADMIN DATA is 53 length 80 length 81 01 --optional bit field-- 82 length --optional salt-- 83 length --optional PinLastUpdated time Hence, the encoding with a bit field but no salt and no time value is the following. 53 05 80 03 81 01 02 It is possible to set a property to "no contents" and the object will not be empty. For example, using var pinProtected = new PinProtectedData(); // IsEmpty is true; pinProtected.ManagementKey = null; // IsEmpty is now false, the object is not empty, even though // we set it to contain no management key. byte[] encoding = pinProtected.Encode(); // This will produce an output with no data // 53 04 // 88 02 // 89 00 Using an alternate DataTag -------------------------- It is possible to store data specified by a sppecific DataTag under an alternate numer. That is, there are specific DataTags defined for specific data constructions. For example, there is a DataTag for CHUID (`0x005FC102`), and specific data formatted following a specific TLV construction. However, if you want to store CHUID data under an alternate DataTag (it will still be the CHUID data formatted following the CHUID definition), you can set the DataTag. See the [DataTag](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.Objects.PivDataObject.html#Yubico_YubiKey_Piv_Objects_PivDataObject_DataTag_) property. You will likely never have a use case in your application for an alternate DataTag, but this feature is available for those rare cases when it can be useful. For example, someone might want to use a specific CHUID for one application, and a different CHUID for a second application. Hence, there could be two CHUIDs stored on a single YubiKey, one under the CHUID DataTag and one under an alternate tag. Note that it can be dangerous to store data under an alternate DataTag, because some tags require the PIN to read and others do not. For example, if you store some sensitive data in the PRINTED storage area, PIN verification is required to retrieve it. But suppose you store that data under an alternate tag, one that is currently undefined (such as `0x005F0010`). That storage area does not require the PIN to retrieve the data. The tables above include a column indicating whether a DataTag requires the PIN for reading or not. The SDK makes it easy to store data under a different DataTag, as long as there is a [PivDataObject](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.Objects.PivDataObject.html) class for the tag. For example, there is a class [CardholderUniqueId](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.Objects.CardholderUniqueId.html) for the CHUID DataTag. In this case, to store the CHUID data under a different number, set the [DataTag](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.Objects.PivDataObject.html#Yubico_YubiKey_Piv_Objects_PivDataObject_DataTag_) property. It is not possible to change the DataTag to just any integer value. The new tag must be a number that is among the set of undefined tags. If you change the `DataTag`, then the data specified in the object, including its format, will be stored under a different tag. For example, if you build a [CardholderUniqueId](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.Objects.CardholderUniqueId.html) object and leave the `DataTag` alone, then when you store the data it will be stored in the YubiKey's CHUID storage area. But if you build the object and then change the `DataTag` to, say, `0x005F0010` (one of the undefined numbers), when you store the data, it will be the CHUID data formatted according to the PIV specification for CHUID, but stored in the `0x005F0010` storage area. `PinProtectedData` ------------------ This is an unusual `PivDataObject` because there is no specified Data Object called "PIN-Protected Data". It is used to store a specific set of elements in the PRINTED storage area. Currently, only the YubiKey's management key is included in the set. It would be possible to create a `PivDataObject` for PRINTED, just as there are classes for CHUID, CCC, and so on. There is none, however, because the PRINTED storage area is really designed for "credit-card-like" smart cards, storing the information printed on the card itself (and other data). But the YubiKey is not such a smart card, so there is no such printed information and no need to use the PRINTED storage area. Because this is an "unused" Data Object, Yubico uses it to store the management key if the customer wants a "PIN-only" YubiKey. If, in the future, Yubico decides to store more PIN-protected data, this will be extended (see below). ### PIN-only There are many PIV operations that require management key authentication in order to execute. For example, a YubiKey will not generate a new private key unless the management key has been authenticated in the current session. In order to authenticate, the management key must be entered. But that might not be an easy operation. The PIV PIN will almost certainly be "keyboard characters" and is at most eight characters long. It is easy for an application to pop up a window to enter the PIN, and it is not too hard for a user to remember an 8-character value. But the management key is 24 binary bytes. How does a user enter binary data? And very few people could remember such a long value. Some applications prefer to configure the YubiKey to PIN-only. There are two ways to do that on a YubiKey: PIN-derived and PIN-protected. ##### Warning PIN-derived should never be used and is provided only for backwards compatibility. PIN-protected simply stores the management key in the PRINTED storage area and retrieves it whenever it is needed. The YubiKey will not return the data inside PRINTED unless the PIN has been verified in the current session. In this way, the management key is PIN-protected. In order to authenticate the management key, verify the PIN, retrieve the data from the PRINTED storage area, decode, and use the resulting 24 bytes to authenticate. Note that there are `PivSession` methods that will do all this work for you. Most applications will never use the `PinProtectedData` class directly. ### Encoding The PIV standard specifies the encoding format of the data stored in PRINTED. When storing the management key, however, another format is used. In this way, it is possible to know whether the data in the Data Object is PRINTED or PIN-protected management key. If the data in the storage area looks like the following 53 length 01 length --data-- 02 length --data-- 03 length --data-- 04 length --data-- 05 length --data-- 06 length --data-- 07 length --data-- 08 length --data-- FE 00 then this is PRINTED data. If, however, it is encoded as the following 53 1C 88 1A 89 18 --management key-- then it is the PIN-protected management key. ### Using `PinProtectedData` To store something using the `PinProtectedData` class create an instance, load the data into the appropriate property and call `PivSession.WriteObject`. To read the PIN-protected data out of a YubiKey, call the `PivSession.ReadObject` method. The result is an object. Look at the properties you are interested in to see any data retrieved. using var pinProtect = new PinProtectedData(); pinProtect.ManagementKey = mgmtKeyData; pivSession.WriteObject(pinProtect); PinProtectedData getPinProtect = pivSession.ReadObject(); if (!(getPinProtect.ManagementKey is null)) { // process mgmt key. } ### Future extensions For now, the only thing that can be PIN-protected using this construction is the management key. Hence, there is a property in the `PinProtectedData` class called `ManagementKey`. In the future, however, if Yubico decides to store some other data in the PRINTED storage area, this class will be updated with other properties. [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-piv/piv-objects.md/#L1) --- # How authentication is achieved: AuthTokens, permissions, PIN/UV, and AuthParams ##### Table of Contents How authentication is achieved: AuthTokens, permissions, PIN/UV, and AuthParams =============================================================================== Usually a PIN "unlocks" an application, but with FIDO2, the PIN is used to verify that the caller is allowed to perform a requested command. That is, with FIDO2, the PIN is used to authenticate a command. The mechanism to do this begins when the PIN is used to retrieve an "AuthToken". Although an AuthToken is not what is ultimately used to authenticate (an AuthParam is, see below), most of the work in authentication is in retrieving AuthTokens from a YubiKey. It is the foundation of the process. Hence, most of this document is about AuthTokens. When you use the SDK, you will likely never make a call directly to retrieve an AuthToken most of the work is done "under the covers" or "automatically". However, you must understand the AuthToken in order to provide appropriate arguments to various method calls. Furthermore, it is important to understand many of the (sometimes very) complex rules in the FIDO2 standard that require building multiple AuthTokens in a single session. That is, there can be use cases where a PIN must be entered multiple times in a single session, and that is not a bug, or an SDK failure, but requirements of the standard. This knowledge will help you better design your product. PIN, UV, AuthToken, AuthParam ----------------------------- In order to perform many FIDO2 operations, one must pass an AuthParam to the YubiKey along with a command. An AuthParam is built from an AuthToken. The AuthToken is retrieved from the YubiKey using the PIN or UV, along with the shared secret and possibly some other info, which can include a list of permissions and a relying party ID. The permissions are values that specify for which operations an AuthToken can be used. It is also possible (and sometimes required) to specify for which relying party the operation will work. That is, you can have many credentials on a YubiKey, but by specifying the relying party, a command is only allowed to operate on those credentials associated with that relying party. The section below on [permissions](https://docs.yubico.com/yesdk/users-manual/application-fido2/fido2-auth-tokens.html#permissions) has more information on this topic. The shared secret is computed by performing the ECDH protocol between the client and YubiKey. shared secret + PIN \[+ permissions\] --> AuthToken --> AuthParam, where AuthParam used to authenticate a command Here's another way to look at it. * \[Shared Secret\] perform ECDH shared secret protocol between client and YubiKey * \[AuthToken\] the client retrieves the AuthToken from the YubiKey using one of the following methods * PIN + shared secret => PinToken * PIN + shared secret + permissions => AuthToken * UV (fingerprint) + shared secret + permissions => AuthToken * \[AuthParam\] the client builds the AuthParam * PinToken + message => AuthParam * AuthToken + message => AuthParam * The client sends a command to the YubiKey * var cmd = new SomeCommand(info, AuthParam) With the SDK, either all of this work is performed automatically (there is nothing you have to do other than supply a KeyCollector), or you make one or two calls if you want more control, and to possibly reduce the number of PIN/UV collections. ### How an AuthToken is retrieved In the SDK, an AuthToken is retrieved by calling one of the `Verify` methods, such as [VerifyPin](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Fido2Session.html#Yubico_YubiKey_Fido2_Fido2Session_VerifyPin_) and [VerifyUv](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Fido2Session.html#Yubico_YubiKey_Fido2_Fido2Session_VerifyUv_) . These `Verify` methods will carry out the following actions: * Perform ECDH to obtain a shared secret key * Perform either PIN only, PIN with permissions, or UV with permissions * PIN only * If the PIN is not provided, call the KeyCollector * Digest the PIN * Encrypt the digest of the PIN using the shared secret key * Send a command to the YubiKey containing the encrypted "PinHash" and other info * If the PIN was correct, the YubiKey verifies the "PinHash" * The YubiKey returns a PinToken, which is the AuthToken to use * PIN with permissions * The caller supplies the permissions * If the PIN is not provided, call the KeyCollector * Digest the PIN * Encrypt the digest of the PIN using the shared secret key * Send a command to the YubiKey containing the encrypted "PinHash", permissions, and other info * If the PIN was correct, the YubiKey verifies the "PinHash" * The YubiKey returns a PinUvAuthToken (with permissions attached), which is the AuthToken to use * UV with permissions * The caller supplies the permissions * Send a command to the YubiKey containing permissions, and other info * Upon receiving the command, the YubiKey will wait for the user to verify the fingerprint * The SDK sends a message to the KeyCollector announcing the YubiKey is waiting for the fingerprint * If the fingerprint is provided and it is correct, the YubiKey verifies it * The YubiKey returns a PinUvAuthToken, which is the AuthToken to use In the SDK, if you call a `Verify` method, the result will be an AuthToken. The `Fido2Session` class contains a property for the most recent AuthToken retrieved. For example, using (fido2Session = new Fido2Session(yubiKeyDevice)) { // The fido2Session.AuthToken property starts out as null. fido2Session.KeyCollector = SomeKeyCollectorDelegate; fido2Session.VerifyPin(); // If this succeeds, the fido2Session.AuthToken property is not null. } At this point, there is an AuthToken that can be used to authenticate some operations. However, it is important to note that the FIDO2 application was not "unlocked". It is not the FIDO2 application itself that was verified, but only the PIN. And that AuthToken can be used to authenticate only those operations for which it has permissions. Notice that while you can call a `Verify` method, the SDK will perform the ECDH key agreement, digest the PIN, encrypt the "PinHash", build the command message, send it to the YubiKey, and parse the response. Although all those tasks are required to obtain an AuthToken, your code only called the `Verify` method. It is also important to note that it is not necessary to call a `Verify` method directly. The SDK will call one if it is trying to perform some operation for which the existing AuthToken won't work. See the section below on [automatic verification](https://docs.yubico.com/yesdk/users-manual/application-fido2/fido2-auth-tokens.html#sdk-automatic-verification) for more information on that topic and when to let the SDK do this work and when you should intercede in the process. Note also that in the above example, the code did not specify any permissions. In that case, what the YubiKey returns is a PinToken. The sections below on [AuthToken](https://docs.yubico.com/yesdk/users-manual/application-fido2/fido2-auth-tokens.html#authtokens) provide more information on the difference between PinTokens and PinUvAuthTokens. ### Using an AuthToken more than once In some situations it is possible to build one AuthToken and use it to build several AuthParams, either for multiple commands or multiple calls to the same command. However, it is also possible an AuthToken can be used to build an AuthParam for one command and not another. There are two reasons that happens (1) permissions and (2) expiry. An AuthToken has permissions attached to it. If the set of permissions does not include the operation you have requested, the AuthParam built from that AuthToken will not work. It is even possible to have an AuthToken with the correct permissions not work because a particular permission is associated with a relying party and the operation cannot execute for that RP. See the section below on [permissions](https://docs.yubico.com/yesdk/users-manual/application-fido2/fido2-auth-tokens.html#permissions) . An AuthToken's permissions can also expire. There are a number of ways to expire, but the most common is when the YubiKey, upon receiving an AuthParam for one command, will "expire" an AuthToken, and it cannot be used again (in the FIDO2 terminology, "expire" is an active verb, it is something the YubiKey does to the PinToken). To perform another command requires the client to retrieve a new AuthToken. In still other cases an AuthToken can be "partially expired", where it can be reused for some commands, but not for others. Note that "expire" will usually have nothing to do with time. That is, a YubiKey will expire an AuthToken, not because some amount of time has passed, but because some other condition has been met. See the section below on [expiry](https://docs.yubico.com/yesdk/users-manual/application-fido2/fido2-auth-tokens.html#expiry) . ### Only one AuthToken is valid at any one time It is not possible to retrieve several AuthTokens at one time and then use each one as needed. When a client requests an AuthToken from a YubiKey, the YubiKey builds one and stores it (along with its permissions and relying party ID, if there are any) somewhere inside the FIDO2 application space. That AuthToken is used to verify any AuthParam the client sends. If a new AuthToken is requested, according to the standard, the YubiKey must perform `resetPinUvAuthToken`, and "all existing pinUvAuthTokens are invalidated". ### AuthToken and PIN/UV collection Each time the SDK builds a new AuthToken, it must have the PIN or the user must perform the UV operation (on the YubiKey Bio that's fingerprint). The SDK will not keep a local copy of the PIN, so if a PIN is needed, the SDK will call the KeyCollector. If the KeyCollector does not keep a local copy of the PIN, it will have to ask the user to enter it again. There is no way, of course, to keep a local copy of a fingerprint, so if that is the way the user authenticates, then they will have to perform that operation each time an AuthToken is needed. Unfortunately, because of the standard, depending on what your application does and how it calls the SDK, it can be unavoidable to require multiple collections in the same session. ### Reusing AuthParams The SDK will build a new AuthParam each time one is needed. There are some rare cases where an AuthParam can be used more than once. That is, it is possible to store an AuthParam and check to see if it can be reused. But it is much easier and more efficient to simply build a new AuthParam each time. AuthTokens ---------- There are four kinds of AuthTokens: * PinToken * PinUvAuthToken Using PIN * PinUvAuthToken Using UV (fingerprint) * Persistent PinUvAuthToken (PPUAT) ### PinToken This is the AuthToken from FIDO2 version 2.0. There are no permissions associated with a PinToken. Even though it is a version 2.0 construction, it can be used in FIDO2 version 2.1. However, while some commands will successfully execute using an AuthParam built from a PinToken, there are other commands that will return an error if provided an AuthParam built from a PinToken. On a FIDO2 version 2.0 YubiKey, the PinToken can be used many times and is generally not expired. Hence, the client collects one PinToken from the YubiKey and uses it for several commands or several calls to the same command. On a FIDO2 version 2.1 YubiKey, the PinToken can only be used to perform MakeCredential and GetAssertion. Furthermore, it can be expired, and in fact, it can be used to build an AuthParam that will authenticate a call to only one command. ### PinUvAuthToken This is the FIDO2 version 2.1 AuthToken. It is built with permissions. That means an AuthParam built from such an AuthToken will only authenticate commands specified in the permissions. For example, it is possible to retrieve an AuthToken with permissions set to "credential management". A client could use that AuthToken to build an AuthParam for "get assertion" (that is, it's possible to write code to produce output), but that AuthParam would not actually authenticate the GetAssertion command. The YubiKey is able to know which AuthToken was used, and would know the permissions associated with that AuthToken and authentication would fail. It is possible to request an AuthToken with multiple permissions. That AuthToken could be used for several different commands. PinUvAuthTokens can be expired easily. See the section below on [expiry](https://docs.yubico.com/yesdk/users-manual/application-fido2/fido2-auth-tokens.html#expiry) . If you use a PinToken on a FIDO2 version 2.1 YubiKey, the permissions are considered to be "make credential" and "get assertion". That is, even though a PinToken does not have the concept of permissions, a YubiKey that supports FIDO2 version 2.1, will act as if the AuthToken has those two permissions. Hence, a PinToken cannot be used to perform Credential Management, Bio Enrollment, Large Blobs, and others. Furthermore, a PinToken can expire on a FIDO2 version 2.1 device. ### PinUvAuthToken using PIN or UV It is possible to get an AuthToken using the PIN or UV (user verification, for YubiKey that is fingerprint). It doesn't matter how the user "authenticates", the YubiKey will return a PinUvAuthToken. There is no difference between an AuthToken retrieved using PIN or UV. They work exactly the same. It is just a matter of how you authenticate yourself to the YubiKey. Note that in FIDO2 version 2.0, there was no way to perform UV to get a PinToken, there is only the PIN. Fingerprint authentication was added in FIDO2 version 2.1. The FIDO2 standard currently specifies only fingerprints, but other methods, such as face recognition, could be added in the future. ##### Note When a YubiKey would like the user to verify a fingerprint, the SDK will notify your application. See the [article on the KeyCollector and touch](https://docs.yubico.com/yesdk/users-manual/sdk-programming-guide/key-collector-touch.html) for a more detailed description of how to handle fingerprint notifications. To perform UV, the fingerprint must be registered with the FIDO2 application on the YubiKey. In FIDO2 this is called enrollment. There are ways to discover whether the YubiKey has fingerprint capabilities, and if so, whether one has been enrolled. The standard says, the client "SHOULD" try UV first, and if that fails, use PIN (how to know a UV fails is a topic for another doc). Actually, it is not that simple, there are further conditions, but for the most part, if the YubiKey has fingerprints, and one has been enrolled, the client should call on the code that uses UV for authentication, and use the PIN only if the UV fails. However, that is "SHOULD" not "SHALL". Hence, it is possible a client only calls on the code that uses the PIN. Or tries PIN first, then UV. ### Persistent PinUvAuthToken (PPUAT) YubiKeys with firmware version 5.8 and later support CTAP 2.2's Persistent PinUvAuthToken (PPUAT). A PPUAT can be frequently reused and (typically) remains active for a longer period of time compared to a traditional PinUvAuthToken. However, it can only be used for read-only credential management operations, including `EnumerateRelyingParties`, `EnumerateCredentialsForRelyingParty`, and `GetCredentialMetadata`. While the PPUAT is a different flavor of AuthToken, it is also a distinct entity — the YubiKey can have both an active PPUAT and an active PinUvAuthToken at the same time. #### PPUAT benefits and expiry PPUATs enable a better user experience by allowing applications to list discoverable credentials from YubiKeys without requiring repeated PIN entry. This behavior is enabled by CTAP 2.2's rules for PPUAT expiry, which dictate that a PPUAT remains valid until one of the following occurs: * [the FIDO2 PIN is changed](https://fidoalliance.org/specs/fido-v2.2-ps-20250714/fido-client-to-authenticator-protocol-v2.2-ps-20250714.html#changingExistingPin) * [the minimum PIN length is changed, and the forceChangePin boolean is set to True](https://fidoalliance.org/specs/fido-v2.2-ps-20250714/fido-client-to-authenticator-protocol-v2.2-ps-20250714.html#setMinPINLength) * [the YubiKey's FIDO2 application is reset](https://fidoalliance.org/specs/fido-v2.2-ps-20250714/fido-client-to-authenticator-protocol-v2.2-ps-20250714.html#authenticatorReset) The YubiKey does not enforce additional PPUAT expiry rules. #### Creating and using a PPUAT with the SDK The process of creating a PPUAT with the SDK is fundamentally the same as creating a PinUvAuthToken — the difference lies in the _permissions_ assigned to the token. When building an AuthToken, if you assign the [PersistentCredentialManagementReadOnly](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Commands.PinUvAuthTokenPermissions.html#Yubico_YubiKey_Fido2_Commands_PinUvAuthTokenPermissions_PersistentCredentialManagementReadOnly) permission (as opposed to the standard [CredentialManagement](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Commands.PinUvAuthTokenPermissions.html#Yubico_YubiKey_Fido2_Commands_PinUvAuthTokenPermissions_CredentialManagement) permission), you will create a PPUAT. With the SDK's Fido2Session, there are a few ways to initiate PPUAT creation: * [GetPersistentPinUvAuthToken()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Fido2Session.html#Yubico_YubiKey_Fido2_Fido2Session_GetPersistentPinUvAuthToken) * the read-only credential management session methods ([EnumerateRelyingParties()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Fido2Session.html#Yubico_YubiKey_Fido2_Fido2Session_EnumerateRelyingParties) , [EnumerateCredentialsForRelyingParty()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Fido2Session.html#Yubico_YubiKey_Fido2_Fido2Session_EnumerateCredentialsForRelyingParty_Yubico_YubiKey_Fido2_RelyingParty_) , and [GetCredentialMetadata()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Fido2Session.html#Yubico_YubiKey_Fido2_Fido2Session_GetCredentialMetadata) ) * [TryVerifyPin()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Fido2Session.html#Yubico_YubiKey_Fido2_Fido2Session_TryVerifyPin_System_ReadOnlyMemory_System_Byte__System_Nullable_Yubico_YubiKey_Fido2_Commands_PinUvAuthTokenPermissions__System_String_System_Nullable_System_Int32___System_Nullable_System_Boolean___) `GetPersistentPinUvAuthToken()` will, as the name implies, get a new PPUAT. Note that this method requires a KeyCollector to perform the UV or PIN verification step. using (Fido2Session fido2Session = new Fido2Session(yubiKeyDevice)) { // Your app's key collector. fido2Session.KeyCollector = SomeKeyCollectorDelegate; fido2Session.GetPersistentPinUvAuthToken(); } Alternatively, the PPUAT can be created as part of a call to one of the read-only credential management session methods (again, as long as a KeyCollector is provided). During one of these operations, the SDK will preferentially (and automatically) create and use a PPUAT instead of a standard PinUvAuthToken if the YubiKey supports CTAP 2.2. using (Fido2Session fido2Session = new Fido2Session(yubiKeyDevice)) { // Your app's key collector. fido2Session.KeyCollector = SomeKeyCollectorDelegate; // If an active PPUAT does not exist, the SDK will get one using SomeKeyCollectorDelegate. fido2Session.EnumerateRelyingParties(); } To use the Fido2Session methods without a KeyCollector, you will have to manually perform the PIN verification via `TryVerifyPin()`, which will need to be passed both the PIN and the `PersistentCredentialManagementReadOnly` permission in order to create a PPUAT under the hood. Once the PPUAT is set, you can call the read-only credential management session methods, and the SDK will use that PPUAT to authenticate the operation. using (Fido2Session fido2Session = new Fido2Session(yubiKeyDevice)) { // currentPin is the PIN collected from the user (collection process defined elsewhere). fido2Session.TryVerifyPin(currentPin, PinUvAuthTokenPermissions.PersistentCredentialManagementReadOnly); } ##### Note Once a PPUAT has been created, the Fido2Session's [AuthTokenPersistent](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Fido2Session.html#Yubico_YubiKey_Fido2_Fido2Session_AuthTokenPersistent) property will be populated with the decrypted PPUAT. When the Fido2Session is disposed of, the decrypted PPUAT will be disposed of as well. Additionally, active PPUATs can also be passed in as a parameter upon instantiation of a new Fido2Session, allowing you to further reduce the frequency of PIN/UV verification: // Pass in the PPUAT (set elsewhere). using (Fido2Session fido2Session = Fido2Session(yubiKeyDevice,ppuat)) { // Execute read-only credential management operations, assuming PPUAT is valid. } As for the lower-level FIDO2 command classes for read-only credential management ([EnumerateRpsBeginCommand()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Commands.EnumerateRpsBeginCommand.html) , [EnumerateCredentialsBeginCommand()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Commands.EnumerateCredentialsBeginCommand.html) , [GetCredentialMetadataCommand()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Commands.GetCredentialMetadataCommand.html) ), the PPUAT must be passed in to those methods directly as a parameter. And to create a PPUAT via the command classes, call [GetPinUvAuthTokenUsingPinCommand()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Commands.GetPinUvAuthTokenUsingPinCommand.html) or [GetPinUvAuthTokenUsingUvCommand()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Commands.GetPinUvAuthTokenUsingUvCommand.html) , both of which need to be passed the `PersistentCredentialManagementReadOnly` permission. Permissions ----------- FIDO2 version 2.0 does not have permissions. That means that if your application is connected to a YubiKey that supports only version 2.0, you will retrieve a PinToken and that PinToken will have the permission to call on the YubiKey to do anything it supports. [Permissions](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Commands.PinUvAuthTokenPermissions.html) were introduced in FIDO2 version 2.1. The standard lists the following possible permissions: * Make Credential * Get Assertion * Credential Management * Bio Enrollment * Large Blob Write * Authenticator Configuration * Persistent Credential Management Read Only If you are programming for a YubiKey that supports FIDO2 version 2.1, then when you obtain an AuthToken, you should get a PinUvAuthToken with permissions. For example, if you know you will want to perform Bio Enrollment, get an AuthToken with that permission. Or if you know you will want to get an assertion and write data to the [large blob](https://docs.yubico.com/yesdk/users-manual/application-fido2/large-blobs.html) , get an AuthToken with those two permissions. To get an AuthToken with permissions, call one of the `VerifyPin` or `VerifyUv` methods. For example using (fido2Session = new Fido2Session(yubiKeyDevice)) { fido2Session.KeyCollector = SomeKeyCollectorDelegate; fido2Session.VerifyPin(PinUvAuthTokenPermissions.CredentialManagement); } However, there are a number of complexities to be aware of. ### Relying Party ID The standard specifies that for MakeCredential and GetAssertion, the permission must be accompanied with a relying party ID. For example, if you want to get an assertion, you must know for which relying party the assertion is. Then you get an AuthToken with the permission of GetAssertion for that relying party. That AuthToken can be used only for getting an assertion associated with the specified relying party. If you want to get an assertion for a different relying party, you must get a new AuthToken. The standard also states that with CredentialManagement, a relying party is optional. This happens to be a fairly complex topic and is fully described below in the section on [CredentialManagement permission](https://docs.yubico.com/yesdk/users-manual/application-fido2/fido2-auth-tokens.html#credentialmanagement-permission) . For the last three permissions (BioEnrollment, LargeBlobWrite, AuthenticatorConfiguration), the relying party is ignored. When you specify any of these permissions, you can include a relying party, but it won't matter. using (fido2Session = new Fido2Session(yubiKeyDevice)) { fido2Session.KeyCollector = SomeKeyCollectorDelegate; fido2Session.VerifyPin(PinUvAuthTokenPermissions.GetAssertion, "RelyingPartyIdOfInterest"); // or fido2Session.VerifyPin( PinUvAuthTokenPermissions.GetAssertion | PinUvAuthTokenPermissions.LargeBlobWrite, "RelyingPartyIdOfInterest"); } ### PinToken on a FIDO2 version 2.1 device The PinToken is from FIDO2 version 2.0, but it is possible it will still work on a FIDO2 version 2.1 device. An authenticator that supports FIDO2 version 2.1 is allowed by the standard not to support FIDO2 version 2.0. If that happens, the authenticator is allowed not to support the PinToken. The PinToken has no concept of permissions. However, if you are connected to a YubiKey that supports FIDO2 versions 2.0 and 2.1, a PinToken will behave as if it has the permissions MakeCredential and GetAssertion. That means you cannot perform CredentialManagement, BioEnrollment, etc. using a PinToken. The MakeCredential and GetAssertion permissions are required to be accompanied by the relying party ID, but there is no place in a PinToken for a relying party. If you have a PinToken, then you can make a credential or get an assertion from any relying party. You will be allowed, though, to perform only one operation using that PinToken. Once you make a credential or get an assertion, the PinToken will no longer be valid. ### CredentialManagement permission There are five CredentialManagement operations: * GetCredentialMetadata * EnumerateRelyingParties * EnumerateCredentials * DeleteCredential * UpdateUserInformation According to the standard, "The rpId parameter is optional, if it is present, the pinUvAuthToken can only be used for Credential Management operations on Credentials associated with that RP ID". However, that is not accurate. Because the standard also declares that if you want to get credential metadata or enumerate relying parties, then the AuthToken must not have an associated relying party. This means that if you want to get credential metadata, you must have an AuthToken with the CredentialManagement permission and no relying party. Or if you want to enumerate the relying parties (get information on all relying parties represented in all the [discoverable credentials](https://docs.yubico.com/yesdk/users-manual/application-fido2/fido2-credentials.html) ), you must not supply a relying party. If you want to enumerate the credentials, delete a credential, or update the user information on one credential, you must get an auth token with the CredentialManagement permission, but it will work whether or not it has an associated relying party. If a relying party is specified, the operations will work only on credentials associated with that relying party. ##### Note The read-only credential management operations (GetCredentialMetadata, EnumerateRelyingParties, and EnumerateCredentials) can also be authenticated using a PPUAT with the PersistentCredentialManagementReadOnly permission (if supported by the YubiKey). See [Persistent PinUvAuthToken (PPUAT)](https://docs.yubico.com/yesdk/users-manual/application-fido2/fido2-auth-tokens.html#persistent-pinuvauthtoken-ppuat) for more information. Suppose your application wants to list all the relying parties, then list all the credentials for each relying party. You would need to retrieve an AuthToken with the CredentialManagement permission and no relying party (or a PPUAT with the PersistentCredentialManagementReadOnly permission). Suppose you know your application will want to get credential metadata and get an assertion. You could get an AuthToken with both GetAssertion and CredentialManagement permissions. However, the GetAssertion permission requires a relying party and the get metadata operation requires no relying party. If you do not supply a relying party ID when retrieving the AuthToken, the YubiKey would return an error. If you do supply a relying party ID, the YubiKey would return an AuthToken, but that AuthToken would not work when trying to get the credential metadata. Expiry ------ The CTAP standard lists a number of ways the YubiKey can expire a regular AuthToken. See section 6.5. ##### Note Persistent PinUvAuthTokens (PPUATs) abide by a different set of expiry rules. See [PPUAT benefits and expiry](https://docs.yubico.com/yesdk/users-manual/application-fido2/fido2-auth-tokens.html#ppuat-benefits-and-expiry) for more information. The most common way to expire a PinUvAuthToken is by "user presence" (touch). Once a command that requires user presence has been completed (including the touch), the AuthToken is expired (or partially expired, see below). For example, get a PinUvAuthToken with multiple permissions: Credential Management and Get Assertion. Now use that AuthToken to enumerate the credentials on the YubiKey (one of the Credential Management oeprations). That does not require user presence so the AuthToken is not expired. Now call the Get Assertion command. That requires user presence. It works, but once it is complete, the AuthToken is expired. Try to use it to do Credential Management and the YubiKey returns an error. Side note: It is not possible to make a credential so that user presence is not required to get an assertion. In other words, if you make a credential, in order to get an assertion from that credential, user presence will be required. Hence, "by definition", on a FIDO2 version 2.1 YubiKey, an AuthToken can be used for one get assertion or one make credential. Another example: get an AuthToken with permissions for Credential Management, Get Assertion, and Large Blobs. Perform the Get Assertion and the AuthToken is only partially expired. The AuthToken can no longer be used for Credential Management nor Get Assertion, but it can still be used for Large Blobs. Think of it as a quirk in the expiry rules. In general, there is no way to know in advance whether an AuthToken has expired or not. Of course, a client could be written so that it keeps track of the operations and updates a local variable that specifies an AuthToken's state based on the rules it knows the YubiKey follows. But the only real way to definitively know whether an AuthToken will work or not is to try to use it. If an operation succeeds, it was valid. If it fails with an error of CTAP2\_ERR\_PIN\_AUTH\_INVALID, then the AuthToken did not work. That error could happen if an AuthToken has expired, but it can also happen for other reasons. Whatever the reason, it's necessary to collect the PIN again (or perform UV again) and retrieve a new AuthToken. SDK automatic verification -------------------------- You can, if you want, let the SDK take care of all the AuthToken work. You simply supply a KeyCollector. This only works if you perform all your FIDO2 work inside a [Fido2Session](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Fido2Session.html) . In this case, if the SDK is performing an operation that needs an AuthToken or PPUAT, it will try to use whatever it has (see the [AuthToken](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Fido2Session.html#Yubico_YubiKey_Fido2_Fido2Session_AuthToken) and [AuthTokenPersistent](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Fido2Session.html#Yubico_YubiKey_Fido2_Fido2Session_AuthTokenPersistent) properties). If that works, the SDK completes the operation. If not, it will determine what it needs and make the appropriate call to get a working AuthToken/PPUAT. Then it tries the original operation again. For example, if your application calls the `GetAssertions` method, the SDK will know it needs an AuthToken with the GetAssertion permission associated with the specified relying party. It will retrieve an AuthToken and use it. The only way your application will know it needed an AuthToken was that the SDK called on the KeyCollector, either to request UV or a PIN. The upside of this is that your application never needs to worry about AuthTokens at all. The downside is that it is possible the SDK will require unnecessary PIN collection. For example, suppose you know your application will do two things: enumerate the credentials for a relying party, then get an assertion for one of the credentials tied to that relying party. Your code might look like this. using (fido2Session = new Fido2Session(yubiKeyDevice)) { fido2Session.KeyCollector = SomeKeyCollectorDelegate; IList credentialList = fido2Session.EnumerateCredentialsForRelyingParty(relyingParty); CredentialUserInfo credentialToUse = ChooseCredential(credentialList); GetAssertionParameters params = GetParamsForCredential(relyingParty, credentialToUse); IList assertions = fido2Session.GetAssertions(params); } The `Fido2Session` begins with no AuthToken or PPUAT. During the call to `EnumerateCredentialsForRelyingParty` the SDK recognizes that it needs an AuthToken with the CredentialManagement permission (with or without the relying party ID) or a PPUAT with the PersistentCredentialManagementReadOnly permission (if supported by the YubiKey). It obtains such an AuthToken/PPUAT and completes the operation. Then, during the `GetAssertions` call, the SDK tries using the existing AuthToken. It doesn't work, so it needs a new AuthToken. It calls the KeyCollector again and the user needs to enter the PIN again. In this situation, it would have been possible to get an AuthToken with both permissions and the user would have had to enter the PIN only once. ### AddPermissions One option is to call the [AddPermissions](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Fido2Session.html#Yubico_YubiKey_Fido2_Fido2Session_AddPermissions_) method early in the session. using (fido2Session = new Fido2Session(yubiKeyDevice)) { fido2Session.KeyCollector = SomeKeyCollectorDelegate; fido2Session.AddPermissions( PinUvAuthTokenPermissions.CredentialManagement | PinUvAuthTokenPermissions.GetAssertion, relyingPartyId); } This is a method you can call to obtain an initial AuthToken, one that contains all the permissions your application will need during the session. Thus, it can eliminate some PIN collection or UV (fingerprint) operations. This is not foolproof, however. You could specify all the permissions you want at the beginning, but because of expiry, it is possible multiple AuthTokens will be required. Or if you want to get credential metadata or enumerate relying parties and get assertions, you will need multiple AuthTokens, there is no way around the standard in this case. Caller-managed AuthTokens ------------------------- Finally, it is possible for you to write your code in such a way that no KeyCollector is needed. Your code would be responsible for calling `TryVerifyPin` each time a new AuthToken/PPUAT is required. First, this only works with PIN-based AuthTokens/PPUATs. There is no way to collect UV-based AuthTokens/PPUATs without a KeyCollector. You could, of course, build a simple KeyCollector that does nothing, but then how would a user know the fingerprint is needed? If a YubiKey has fingerprint capabilities and one is enrolled, then the standard says your application should use the fingerprints (and only use PIN if the fingerprints fail). However, the standard also specifies that a client can use the PIN as the primary or even only method of user authentication. You could write your application so that you call the PIN-provided `Verify` method directly each time you need a new PinToken. using (fido2Session = new Fido2Session(yubiKeyDevice)) { // Assume there is a ReadOnlyMemory containing the PIN. if (!fido2Session.TryVerifyPin( pin, PinUvAuthTokenPermissions.CredentialManagement, null, out int retriesRemaining, out bool rebootRequired)) { // handle wrong PIN case. } (int discoverableCredentialCount, int remainingSlots) = fido2Session.GetCredentialMetadata(); // Assume you have some method that determines which relying party to use. // This call will probably perform other CredentialManagement operations such as // enumeration. But you know that the current AuthToken has the appropriate // permission. RelyingParty relyingParty = ChooseRelyingParty(fido2Session); // Now that you have the relying party, you can get an assertion. // But we'll need a new AuthToken. if (!fido2Session.TryVerifyPin( pin, PinUvAuthTokenPermissions.GetAssertion, relyingParty.Id, out retriesRemaining, out rebootRequired)) { // handle wrong PIN case. } var gaParams = new GetAssertionParameters(relyingParty, clientDataHash); IList assertions = fido2Session.GetAssertions(gaParams); } You could write your code in such a way that you don't need to get a new AuthToken each time you call on the SDK to do something. In that case, you must know the requirements of the standard and know for sure when the existing AuthToken is still valid for the next call. Or you could write your code to call verify right before each SDK call that will perform some FIDO2 operation that requires authentication. Or you could simply build a KeyCollector and let the SDK perform automatic AuthToken/PPUAT retrieval. Although it is not necessarily secure, your KeyCollector could collect the PIN once, store it locally, and return it each time. In this way, the user does not need to enter the PIN several times during a session. Note that the SDK will try UV first, so if you don't want the user to use the fingerprint, your KeyCollector will return `false` when the `KeyEntryData.Request` is `KeyEntryRequest.VerifyFido2Uv`. With automatic AuthToken/PPUAT retrieval, when the caller cancels the fingerprint, the SDK will move on to PIN. [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-fido2/fido2-auth-tokens.md/#L1) --- # FIDO2 credential management ##### Table of Contents FIDO2 credential management =========================== The credential management operations allow you to obtain information about the credentials on a YubiKey without getting an assertion. Note that you can get information only for discoverable credentials. Remember that to make a credential discoverable, when you make it (see [MakeCredential](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Fido2Session.html#Yubico_YubiKey_Fido2_Fido2Session_MakeCredential_) ), set the "`rk`" option to `true` var makeCredentialParameters = new MakeCredentialParameters(relyingParty, userEntity) { ClientDataHash = clientDataHash, }; makeCredParams.AddOption(AuthenticatorOptions.rk, true); MakeCredentialData credentialData = fido2Session.MakeCredential(makeCredentialParameters); These are the credential management operations: * [Get Metadata](https://docs.yubico.com/yesdk/users-manual/application-fido2/fido2-cred-mgmt.html#get-metadata) * [Enumerate Relying Parties](https://docs.yubico.com/yesdk/users-manual/application-fido2/fido2-cred-mgmt.html#enumerate-relying-parties) * [Enumerate Credentials](https://docs.yubico.com/yesdk/users-manual/application-fido2/fido2-cred-mgmt.html#enumerate-credentials) * [Delete Credential](https://docs.yubico.com/yesdk/users-manual/application-fido2/fido2-cred-mgmt.html#delete-credential) * [Update User Information](https://docs.yubico.com/yesdk/users-manual/application-fido2/fido2-cred-mgmt.html#update-user-information) Support in the YubiKey ---------------------- Not all YubiKeys support CredentialManagement. To find out if a particular YubiKey can perform these operations, check for the "`credMgmt`" options. using (fido2Session = new Fido2Session(yubiKeyDevice)) { if (fido2Session.AuthenticatorInfo.GetOptionValue("credMgmt") == OptionValue.True) { . . . } } Commands and Fido2Session methods --------------------------------- In the SDK, there are two ways to perform a CredentialManagement operation: * Commands * Fido2Session methods The commands are * [GetCredentialMetadataCommand](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Commands.GetCredentialMetadataCommand.html) * [EnumerateRpsBeginCommand](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Commands.EnumerateRpsBeginCommand.html) * [EnumerateRpsGetNextCommand](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Commands.EnumerateRpsGetNextCommand.html) * [EnumerateCredentialsBeginCommand](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Commands.EnumerateCredentialsBeginCommand.html) * [EnumerateCredentialsGetNextCommand](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Commands.EnumerateCredentialsGetNextCommand.html) * [DeleteCredentialCommand](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Commands.DeleteCredentialCommand.html) * [UpdateUserInfoCommand](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Commands.UpdateUserInfoCommand.html) Some of the commands require a PinToken. You will be responsible for building a AuthToken (see next section). The Fido2Session methods are * [GetCredentialMetadata](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Fido2Session.html#Yubico_YubiKey_Fido2_Fido2Session_GetCredentialMetadata) * [EnumerateRelyingParties](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Fido2Session.html#Yubico_YubiKey_Fido2_Fido2Session_EnumerateRelyingParties) * [EnumerateCredentialsForRelyingParty](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Fido2Session.html#Yubico_YubiKey_Fido2_Fido2Session_EnumerateCredentialsForRelyingParty_) * [DeleteCredential](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Fido2Session.html#Yubico_YubiKey_Fido2_Fido2Session_DeleteCredential_) * [UpdateUserInfoForCredential](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Fido2Session.html#Yubico_YubiKey_Fido2_Fido2Session_UpdateUserInfoForCredential_) If you use these methods, the SDK will build the proper AuthToken if needed. PIN/UV Auth Param ----------------- In order to perform some credential management operations, it is necessary to compute a PIN/UV Auth Param. The SDK will build the PIN/UV Auth Param, you do not need to supply it. The PIN/UV Auth Param is built using an `AuthToken`. If you use the Fido2Session methods, the SDK will also obtain the `AuthToken`. If supported by the YubiKey (firmware 5.8 or later), the read-only credential management operations (Get Metadata, Enumerate Relying Parties, and Enumerate Credentials) can use a special type of AuthToken called the Persistent PinUvAuthToken (PPUAT). PPUATs allow for frequent reuse, reducing the need for repeated PIN entry. See the User's Manual [entry on AuthTokens](https://docs.yubico.com/yesdk/users-manual/application-fido2/fido2-auth-tokens.html) for a detailed discussion on how they work. Get metadata ------------ This returns the number of discoverable credentials and the number of "empty" slots. For example, suppose the YubiKey has space for 25 credentials. Currently there are three discoverable credentials and two non-discoverable. The return from the credential management operation of get metadata would be 3 and 22. The number of remaining credential count of 22 means that it is possible to store 22 more discoverable credentials. The YubiKey stores no information on non-discoverable credentials, so the two non-discoverable credentials in this example have no effect on the number of spaces available. See also the User's Manual [entry on credentials](https://docs.yubico.com/yesdk/users-manual/application-fido2/fido2-credentials.html) for more information on non-discoverable credentials. The return is a `Tuple` of 2 integers: (int residentCredentialCount, int remainingCredentialCount) = fido2Session.GetCredentialMetadata(); // In the example above, residentCredentialCount would be 3 and // remainingCredentialCount would be 22. Enumerate relying parties ------------------------- This helps you to build a list of all the relying parties represented among all the credentials on the YubiKey. If you use Fido2Session.EnumerateRelyingParties, the SDK will return an array of `RelyingParty` objects. If you use the commands, you will need to use the `EnumerateRpsBeginCommand` command to obtain the first relying party and the total count of relying parties represented, and then the `EnumerateRpsGetNextCommand` to get each successive relying party. var enumBeginCmd = new EnumerateRpsBeginCommand(pinToken, protocol); EnumerateRpsBeginResponse enumBeginRsp = connection.SendCommand(enumBeginCmd); (int rpCount, RelyingParty firstRp) = enumBeginRsp.GetData(); for (int index = 1; index < rpCount; index++) { var getNextCmd = new EnumerateRpsGetNextCommand(); EnumerateRpsGetNextResponse credMgmtRsp = connection.SendCommand(getNextCmd); RelyingParty nextRp = getNextRsp.GetData(); } Enumerate credentials --------------------- This helps you to build a list of all the credentials on the YubiKey. If you use Fido2Session.EnumerateCredentialsForRelyingParty, the SDK will return an array of [CredentialUserInfo](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.CredentialUserInfo.html) objects, each one containing the `User`, `CredentialId`, `CredentialPublicKey`, `CredProtectPolicy`, and the `LargeBlobKey` (if there is one) for each credential found on the YubiKey associated with the specified relying party. You specify which relying party you are interested in by supplying the `RelyingParty` object, which you likely retrieved during a call to obtain a list of relying parties. If you use the commands, you will need to use the `EnumerateCredentialsBeginCommand` command to obtain the first credential and the total count of credentials available, and then the `EnumerateCredentialsGetNextCommand` to get each successive credential. var enumBeginCmd = new EnumerateCredentialsBeginCommand(relyingParty.RelyingPartyIdHash, pinToken, protocol); EnumerateCredentialsBeginResponse enumBeginRsp = connection.SendCommand(enumBeginCmd); (int credCount, CredentialUserInfo userInfo) = enumBeginRsp.GetData(); for (int index = 1; index < credCount; index++) { var getNextCmd = new EnumerateCredentialsGetNextCommand(); EnumerateCredentialsGetNextResponse getNextRsp = connection.SendCommand(getNextCmd); userInfo = getNextRsp.GetData(); } Delete credential ----------------- This allows you to remove one credential from the YubiKey. Whether you use the [command](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Commands.DeleteCredentialCommand.html) or the Fido2Session method, you must supply the CredentialId. This tells the YubiKey which credential to remove. You will likely use the [Enumerate commands](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Commands.EnumerateCredentialsBeginCommand.html) or the Fido2Session.EnumerateCredentialsForRelyingParty method to obtain a list of [CredentialUserInfo](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.CredentialUserInfo.html) objects, and choose the credential to delete from that list. Finally, you can use the [CredentialId](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.CredentialUserInfo.html#Yubico_YubiKey_Fido2_CredentialUserInfo_CredentialId) property in the object as the input to the delete call. This operation needs the [PIN/UV Auth Param](https://docs.yubico.com/yesdk/users-manual/application-fido2/fido2-cred-mgmt.html#pinuv-auth-param) . It is possible that there is some [large blob](https://docs.yubico.com/yesdk/users-manual/application-fido2/large-blobs.html) data stored against the credential you are deleting. If so, you will likely want to delete that data as well. If you use the commands to delete, it is your responsibility to delete the large blob data. The `Fido2Session` method will delete it for you. Update user information ----------------------- Each credential contains user information, represented as an instance of the [UserEntity](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.UserEntity.html) class. You can change what user information is stored on the YubiKey in that credential. The way to change the user information is to create a new `UserEntity` object, and then call the command or the `Fido2Session` method. This replaces the information on the YubiKey, it does not "edit" it. For example, // Find the relying party of interest by enumerating all RPs and selecting from the list. IReadOnlyList rpList = fido2Session.EnumerateRelyingParties(); int index = ChooseRelyingParty(rpList); // Find the credential of interest by enumerating all the credentials associated with // the relying party of intereset and selecting from the list. IReadOnlyList credList = fido2Session.EnumerateCredentialsForRelyingParty(rpList[index]); index = ChooseCredential(credList); // Create a new UserEntity based on the current. var updatedUserInfo = new UserEntity(credArray[index].User.Id) { Name = credArray[index].User.Name, DisplayName = "Jane Doe", }; fido2Session.UpdateUserInfoForCredential(credArray[index].CredentialId, updatedUserInfo); Suppose the original user information was the following: * Id = 0x3A 67 ... E9 * Name = jdoe * DisplayName = J Doe In the sample, the display name was changed to "Jane Doe". It built a new `UserEntity` object with the following: * Id = 0x3A 67 ... E9 * Name = jdoe * DisplayName = Jane Doe Then it called the update method. If it had supplied a `UserEntity` object with only the display name (because that is all it needed to change), then after the update, the YubiKey would have contained an entry for a user with no `Id` and no `Name`, just a `DisplayName`. You must supply all the user information in the updated object. That is, the object you provide as the update must include all the info that does not change as well as the info that does. [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-fido2/fido2-cred-mgmt.md/#L1) --- # What's new in the SDK? ##### Table of Contents What's new in the SDK? ====================== Here you can find all of the updates and release notes for published versions of the SDK. 1.14.x Releases --------------- ### 1.14.1 Release date: October 23rd, 2025 Bug Fixes: * The validation logic in the `AddPermissions()` method has been improved, which resolved an issue where the Fido2Session would incorrectly throw exceptions during calls to `AddPermissions()` on older YubiKeys. ([#316](https://github.com/Yubico/Yubico.NET.SDK/pull/316) ) * Multiple updates have been added to prevent background thread crashes caused by rapidly unplugging and reinserting YubiKeys ([#318](https://github.com/Yubico/Yubico.NET.SDK/pull/318) , [#325](https://github.com/Yubico/Yubico.NET.SDK/pull/325) ): * Improved device listening and disposal behavior, including logging, error messages, and exception handling, across base, HID (Linux, Windows, macOS), and smart card device listener classes. * Added and improved device listener disposal and integration tests. * Added new `CmDevice` class methods (`FromDevicePath`, `FromDeviceInstance`). Dependencies: * Multiple dependencies across the following projects have been updated to newer versions ([#317](https://github.com/Yubico/Yubico.NET.SDK/pull/317) , [#327](https://github.com/Yubico/Yubico.NET.SDK/pull/327) ): * Yubico.Core * Yubico.Core.UnitTests * Yubico.YubiKey * Yubico.YubiKey.IntegrationTests * Yubico.YubiKey.TestApp * Yubico.YubiKey.UnitTests * Yubico.YubiKey.TestUtilities Documentation: * Errors in the User's Manual documentation regarding YubiKey support for FIDO2 PINs and U2F private key behavior have been corrected. ([#321](https://github.com/Yubico/Yubico.NET.SDK/pull/321) , [#322](https://github.com/Yubico/Yubico.NET.SDK/pull/322) ) * * * ### 1.14.0 Release date: September 17th, 2025 Features: * Support has been added for the following CTAP 2.2 and YubiKey firmware version 5.8 features ([#299](https://github.com/Yubico/Yubico.NET.SDK/pull/299) ): * [Persistent PinUvAuthToken (PPUAT)](https://docs.yubico.com/yesdk/users-manual/application-fido2/fido2-auth-tokens.html#persistent-pinuvauthtoken-ppuat) : The [GetPersistentPinUvAuthToken()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Fido2Session.html#Yubico_YubiKey_Fido2_Fido2Session_GetPersistentPinUvAuthToken) method has been added to retrieve PPUATs for use with read-only FIDO2 credential management operations, including [EnumerateRelyingParties()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Fido2Session.html#Yubico_YubiKey_Fido2_Fido2Session_EnumerateRelyingParties) , [EnumerateCredentialsForRelyingParty()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Fido2Session.html#Yubico_YubiKey_Fido2_Fido2Session_EnumerateCredentialsForRelyingParty_Yubico_YubiKey_Fido2_RelyingParty_) , and [GetCredentialMetadata()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Fido2Session.html#Yubico_YubiKey_Fido2_Fido2Session_GetCredentialMetadata) . PPUATs enable applications to list discoverable credentials from YubiKeys without requiring repeated PIN entry. * thirdPartyPayment extension: The [GetThirdPartyPaymentExtension](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.AuthenticatorData.html#Yubico_YubiKey_Fido2_AuthenticatorData_GetThirdPartyPaymentExtension) method has been added to check for and return the status of the thirdPartyPayment extension. The thirdPartyPayment extension enables YubiKeys to be used for cross-domain credentials without redirects, as required by Secure Payment Confirmation (SPC) workflows. * hmac-secret-mc extension: [GetHmacSecretExtension](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.AuthenticatorData.html#Yubico_YubiKey_Fido2_AuthenticatorData_GetHmacSecretExtension_Yubico_YubiKey_Fido2_PinProtocols_PinUvAuthProtocolBase_) now handles both hmac-secret and hmac-secret-mc extensions when extracting and decrypting secrets. The hmac-secret-mc extension enables PRF (Pseudo-Random Function) during [MakeCredential()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Fido2Session.html#Yubico_YubiKey_Fido2_Fido2Session_MakeCredential_Yubico_YubiKey_Fido2_MakeCredentialParameters_) . * Additional `AuthenticatorInfo` properties: The SDK now supports parsing of several new [AuthenticatorInfo](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.AuthenticatorInfo.html) properties, which are returned when calling the [GetInfoCommand()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Commands.GetInfoCommand.html) . Properties include `AttestationFormats`, `UvCountSinceLastPinEntry`, `LongTouchForReset`, `EncIdentifier`, `TransportsForReset`, `PinComplexityPolicy`, `PinComplexityPolicyUrl`, and `MaxPinLength`. * The SDK has been updated to target .NET Framework 4.7.2, which provides broad reliability, security, and performance improvements. ([#274](https://github.com/Yubico/Yubico.NET.SDK/pull/274) ) * The NuGet package metadata has been updated for the `Yubico.Core.csproj` and `Yubico.YubiKey.csproj` files to improve discoverability, consistency, and clarity. The updates include new `PackageId` and `PackageTags` fields as well as a reorganized `PackageReleaseNotes` field. ([#265](https://github.com/Yubico/Yubico.NET.SDK/pull/265) ) * `ToString` overrides have been introduced in the [CommandApdu](https://docs.yubico.com/yesdk/core-api/Yubico.Core.Iso7816.CommandApdu.html) and [ResponseApdu](https://docs.yubico.com/yesdk/core-api/Yubico.Core.Iso7816.ResponseApdu.html) classes to provide a human-readable string representation of their internal state. These changes improve debugging and logging of APDUs. ([#270](https://github.com/Yubico/Yubico.NET.SDK/pull/270) ) Bug Fixes: * Previously, [DeleteSlot()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.OtpSession.html#Yubico_YubiKey_Otp_OtpSession_DeleteSlot_Yubico_YubiKey_Otp_Slot_) and [DeleteSlotConfiguration()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.OtpSession.html#Yubico_YubiKey_Otp_OtpSession_DeleteSlotConfiguration_Yubico_YubiKey_Otp_Slot_) would throw an exception when the slot configuration was successfully removed as intended. This has been fixed so that no exception occurs following a successful `DeleteSlot()` or `DeleteSlotConfiguration()` operation. ([#276](https://github.com/Yubico/Yubico.NET.SDK/pull/276) ) * Prerelease versions of Yubico packages are now prevented from being referenced into published NuGet packages. This fixes an issue where a prerelease version of Yubico.NativeShims was incorrectly referenced by Yubico.Core. ([#282](https://github.com/Yubico/Yubico.NET.SDK/pull/282) ) * The `OtpSession` logger initialization has been updated to use the correct logger. ([#275](https://github.com/Yubico/Yubico.NET.SDK/pull/275) ) * The detection logic for `NativeShimsPath` has been improved, ensuring that 32-bit processes on 64-bit systems are correctly mapped to the "x86" directory. ([#284](https://github.com/Yubico/Yubico.NET.SDK/pull/284) ) Documentation: * The [FIDO2 reset](https://docs.yubico.com/yesdk/users-manual/application-fido2/fido2-reset.html) documentation has been updated to fix an error in the instructions and clarify timeout durations. ([#278](https://github.com/Yubico/Yubico.NET.SDK/pull/278) ) * The documentation on [slot access codes](https://docs.yubico.com/yesdk/users-manual/application-otp/how-to-slot-access-codes.html) has been updated to improve clarity and examples. ([#268](https://github.com/Yubico/Yubico.NET.SDK/pull/268) ) * The documentation on PIV [public](https://docs.yubico.com/yesdk/users-manual/application-piv/public-keys.html) and [private](https://docs.yubico.com/yesdk/users-manual/application-piv/private-keys.html) keys has been updated with new sample code demonstrating how to use the latest factory methods. ([#245](https://github.com/Yubico/Yubico.NET.SDK/pull/245) , [#272](https://github.com/Yubico/Yubico.NET.SDK/pull/272) ) * The documentation for the [UseFastTrigger](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Otp.OtpSettings-1.html#Yubico_YubiKey_Otp_OtpSettings_1_UseFastTrigger_System_Boolean_) method has been updated to clarify information on behavior and applicability. ([#294](https://github.com/Yubico/Yubico.NET.SDK/pull/294) ) * All hardcoded links to the Yubico.NET.SDK GitHub repository have been updated to point to the HEAD branch. This ensures that links to sample code point to the latest version of that code. ([#286](https://github.com/Yubico/Yubico.NET.SDK/pull/286) , [#279](https://github.com/Yubico/Yubico.NET.SDK/pull/279) ) * An [SDK overview](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/.github/copilot-instructions.md) designed to help the Copilot coding agent work more efficiently has been added to the Yubico.NET.SDK GitHub repository. ([#296](https://github.com/Yubico/Yubico.NET.SDK/pull/296) ) Dependencies: * Several dependencies across the Yubico.YubiKey and Yubico.Core projects have been updated to the latest versions. ([#274](https://github.com/Yubico/Yubico.NET.SDK/pull/274) ) 1.13.x Releases --------------- ### 1.13.2 Release date: July 3rd, 2025 Features: * A new `RawData` property, which exposes raw CBOR-encoded data that can be more easily passed to third party tools for parsing, has been added to the FIDO2 `MakeCredentialData` class. ([#225](https://github.com/Yubico/Yubico.NET.SDK/pull/225) ) * A new `VersionQualifier` has been added for handling YubiKey firmware (by version number, type, and iteration), which enables apps built with the SDK to distinguish between standard production YubiKeys and release candidate (RC) YubiKeys. The `YubiKeyDeviceInfo` class has also been updated to support `VersionQualifier`. ([#240](https://github.com/Yubico/Yubico.NET.SDK/pull/240) ) * The GitHub Actions workflows have been updated to use the `windows-2022` runner instead of `windows-2019`, which ensures compatibility with newer environments and improves the consistency of the build and publish pipelines. ([#242](https://github.com/Yubico/Yubico.NET.SDK/pull/242) ) Documentation: * The documentation site has been updated with a new search bar, light/dark mode, new styling, and a modified table of contents. ([#241](https://github.com/Yubico/Yubico.NET.SDK/pull/241) ) * New documentation covering the YubiKey Bio Multi-protocol Edition and its quirks, including the `DeviceReset()` method, has been added. ([#237](https://github.com/Yubico/Yubico.NET.SDK/pull/237) ) * A discrepancy in the documentation on attestation statement generation has been fixed. ([#236](https://github.com/Yubico/Yubico.NET.SDK/pull/236) ) * The documentation covering the default management key value and algorithm has been clarified. ([#233](https://github.com/Yubico/Yubico.NET.SDK/pull/233) ) * The DER encoding details in the documentation on the PIV `AuthenticateSignCommand()` have been corrected. ([#239](https://github.com/Yubico/Yubico.NET.SDK/pull/239) ) Bug Fixes: * NativeShims now outputs Net47 build files into the correct architecture-specific folders. Supported architectures include x86, x64, and Arm64. ([#211](https://github.com/Yubico/Yubico.NET.SDK/pull/211) ) * An ongoing [dotnet issue](https://github.com/dotnet/runtime/issues/112080) that has broken the resolution of core libraries on macOS 15 prevented the SDK from locating important dependencies on Mac when using .NET8 and above. To fix macOS and .NET compatibility with the SDK, the `CoreFoundation`, `IOKitFramework`, and `WinSCard` constants have been updated to use absolute paths (`/System/Library/Frameworks/...`) instead of relative paths (`.framework/...`) to align with macOS system conventions. ([#255](https://github.com/Yubico/Yubico.NET.SDK/pull/255) ) * Use of the deprecated `PivPrivateKey` and `PivPublicKey` types when importing into the new PIV methods is now handled correctly (by throwing an exception). ([#231](https://github.com/Yubico/Yubico.NET.SDK/pull/231) ) * An issue affecting the use of the RSA-3072 and RSA-4096 algorithms with attestation certificates has been fixed. ([#230](https://github.com/Yubico/Yubico.NET.SDK/pull/230) ) Dependencies: * The Yubico.NET.SDK repository now includes the GitHub dependabot to automate dependency updates for the `nuget` and `dotnet-sdk` package ecosystems. ([#244](https://github.com/Yubico/Yubico.NET.SDK/pull/244) ) * Several dependencies across the Core (Yubico.Core.csproj), Integration Tests (Yubico.YubiKey.IntegrationTests.csproj), Sandbox (Yubico.YubiKey.TestApp.csproj), Unit Tests (Yubico.YubiKey.UnitTests.csproj), and Utilities (Yubico.YubiKey.TestUtilities.csproj) projects have been updated to newer versions. ([#256](https://github.com/Yubico/Yubico.NET.SDK/pull/256) , [#254](https://github.com/Yubico/Yubico.NET.SDK/pull/254) , [#250](https://github.com/Yubico/Yubico.NET.SDK/pull/250) ) Deprecations: * `PivEccPublic`, `PivEccPrivateKey`, `PivRsaPublic`, and `PivRsaPrivateKey` have been marked as obsolete. Use implementations of `ECPublicKey`, `ECPrivateKey`, `RSAPublicKey`, and `RSAPrivateKey` instead. ([#231](https://github.com/Yubico/Yubico.NET.SDK/pull/231) ) * The `CreateFromPkcs8` methods in the `Curve25519PublicKey`, `ECPublicKey`, and `RSAPublicKey` classes have been marked as obsolete and replaced with new `CreateFromSubjectPublicKeyInfo` methods. ([#243](https://github.com/Yubico/Yubico.NET.SDK/pull/243) ) ### 1.13.1 Release date: April 28th, 2025 This release mainly addresses an issue that was affecting FIDO2 on YubiKey 5.7.4 and greater as well as adds support for compressed certificates within the PIV application. It also contains miscellaneous and documentation updates. Features: * Support for compressed certificates in the PIV application [#219](https://github.com/Yubico/Yubico.NET.SDK/pull/219) * Ability to create a FirmwareVersion object through parsing a version string (e.g. 1.0.0) [#220](https://github.com/Yubico/Yubico.NET.SDK/pull/220) Bug Fixes: * PinUvAuthParam was erroneously truncated which caused failures on multiple FIDO2 commands for YubiKey v 5.7.4 [#222](https://github.com/Yubico/Yubico.NET.SDK/pull/222) Documentation: * Updates to challenge-response documentation to improve clarity [#221](https://github.com/Yubico/Yubico.NET.SDK/pull/221) Miscellaneous: * Integration tests will now run on Bio USB C keys as well [a4c4df](https://github.com/Yubico/Yubico.NET.SDK/commit/a4c4df10047bedf507e4ce36b80ed5001b996b9a) . ### 1.13.0 Release date: April 9th, 2025 Features: * Curve25519 support has been added for PIV [(#210)](https://github.com/Yubico/Yubico.NET.SDK/pull/210) : * Keys can now be imported or generated using the Ed25519 and X25519 algorithms. * The key agreement operation can be performed with an X25519 key. * Digital signatures can now be created with a Ed25519 key. * New related unit tests have been added. * Unit tests have been added for RSA-3072 and RSA-4096 keys. [(#197)](https://github.com/Yubico/Yubico.NET.SDK/pull/197) * Support for large APDUs has been improved [(#208)](https://github.com/Yubico/Yubico.NET.SDK/pull/208) : * When sending large APDU commands to a YubiKey via the smartcard connection, the CommandChainingTransform will now throw an exception when the cumulative APDU data (sent in chunks of up to 255 bytes) exceeds the max APDU size for the given YubiKey (varies based on firmware version; see [SmartCardMaxApduSizes](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.SmartCardMaxApduSizes.html) ). * Support for Ed25519 and P384 credentials has been added for FIDO. [(#186)](https://github.com/Yubico/Yubico.NET.SDK/pull/186) * Ubuntu runners have been upgraded from version 20.04 to 22.04 to support the compilation of Yubico.NativeShims. [(#188)](https://github.com/Yubico/Yubico.NET.SDK/pull/188) Bug Fixes: * The default logger now only writes output for the "Error" log level unless another level is specified. Previously, the logger wrote output for all log levels, which could become overly long and difficult to evaluate. [(#185)](https://github.com/Yubico/Yubico.NET.SDK/pull/185) Miscellaneous: * The [License](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/LICENSE.txt) was updated to remove the information for the AesCmac.cs file from the Bouncy Castle library. [(#196)](https://github.com/Yubico/Yubico.NET.SDK/pull/196) 1.12.x Releases --------------- ### 1.12.1 Release date: December 19th, 2024 Bug Fixes: Now selects correct device initializing Fido2Session [(#179)](https://github.com/Yubico/Yubico.NET.SDK/pull/179) ### 1.12.0 Release date: December 18th, 2024 Features: * Security Domain application and Secure Channel Protocol (SCP) ([#164](https://github.com/Yubico/Yubico.NET.SDK/pull/164) ): * SCP11a/b/c is now supported for the PIV, OATH, OTP, and YubiHSM applications. * SCP03 support has been extended to the OATH, OTP, and YubiHSM applications (previously PIV only). * The Yubico.YubiKey.Scp namespace now provides all SCP and Security Domain functionality. This namepace replaces functionality in the Yubico.YubiKey.Scp03 namespace, which has been deprecated. * The new `SecurityDomainSession` class provides an interface for managing the Security Domain application of a YubiKey. This includes SCP configuration (managing SCP03 key sets and SCP11 asymmetric keys and certificates) and creation of an encrypted communication channel with other YubiKey applications. * New key parameter classes have been added: `ScpKeyParameters`, `Scp03KeyParameters`, `Scp11KeyParameters`, `ECKeyParameters`, `ECPrivateKeyParameters`, `ECPublicKeyParameters`. * [YubiKeyDeviceListener](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.YubiKeyDeviceListener.html) has been reconfigured to run the listeners in the background instead of the main thread. In addition, the listeners can now be [stopped](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.YubiKeyDeviceListener.html#Yubico_YubiKey_YubiKeyDeviceListener_StopListening) when needed to reclaim resources. Once stopped, the listeners can be restarted. ([#89](https://github.com/Yubico/Yubico.NET.SDK/pull/89) ) * Microsoft.Extensions.Logging.Console is now the default logger. To enable logging from a dependent project (e.g. unit tests, integration tests, an app), you can either add an appsettings.json to your project or use the ConfigureLoggerFactory. ([#139](https://github.com/Yubico/Yubico.NET.SDK/pull/139) ) * The SDK now uses inferred variable types (var) instead of explicit types in all projects except Yubico.Core. This change aims to improve code readability, reduce verbosity, and enhance developer productivity while maintaining type safety. ([#141](https://github.com/Yubico/Yubico.NET.SDK/pull/141) ) Bug Fixes: * The [PivSession.ChangeManagementKey](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.PivSession.html#Yubico_YubiKey_Piv_PivSession_ChangeManagementKey_Yubico_YubiKey_Piv_PivTouchPolicy_) method was incorrectly assuming Triple-DES was the default management key algorithm for FIPS keys. The SDK now verifies the management key alorithm based on key type and firmware version. ([#162](https://github.com/Yubico/Yubico.NET.SDK/pull/162) , [#167](https://github.com/Yubico/Yubico.NET.SDK/pull/167) ) * The SDK now correctly sets the IYubiKeyDeviceInfo property [IsSkySeries](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.IYubiKeyDeviceInfo.html#Yubico_YubiKey_IYubiKeyDeviceInfo_IsSkySeries) to True for YubiKey Security Key Series Enterprise Edition keys. ([#158](https://github.com/Yubico/Yubico.NET.SDK/pull/158) ) * Exceptions are now caught when running PivSession.Dispose. This fixes an issue where the Dispose method could not close the Connection in the event of a disconnected YubiKey. ([#104](https://github.com/Yubico/Yubico.NET.SDK/issues/104) ) * A dynamic DLL resolution based on process architecture (x86/x64) has been implemented for NativeShims.dll. This fixes a reported issue with the NativeShims.dll location for 32-bit processes. ([#154](https://github.com/Yubico/Yubico.NET.SDK/pull/154) ) Miscellaneous: * Users are now able to verify that the NuGet package has been generated from our repository using [Github Attestations](https://docs.github.com/en/actions/security-for-github-actions/using-artifact-attestations/using-artifact-attestations-to-establish-provenance-for-builds) ([#169](https://github.com/Yubico/Yubico.NET.SDK/pull/169) ) like this: > \> gh attestation verify .\\Yubico.Core.1.12.0.nupkg --repo Yubico/Yubico.NET.SDK Deprecations: * Yubico.YubiKey/Scp03 namespace. * All Yubico.Yubikey.StaticKeys endpoints. Migration Notes: * Use the `SecurityDomainSession` for Security Domain operations. * Review your logging configuration if using custom logging. * Align with Android/Python SDK naming conventions. 1.11.x Releases --------------- ### 1.11.0 Release date: June 28th, 2024 This release introduces significant enhancements and new features for YubiKeys running the latest firmware (version 5.7) and YubiKey Bio/Bio Multi-Protocol Edition keys. Highlights include temporary disablement of NFC connectivity, PIN complexity status, support for RSA 3072 and 4096-bit keys, and support for biometric verification. Additionally, USB reclaim speed has been optimized and adjustments to the touch sensor sensitivity have been implemented. For details on all changes, see below. Features: * Support for YubiKeys with the latest firmware (version 5.7): * NFC connectivity can now be temporarily disabled with [SetIsNfcRestricted()](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.YubiKeyDevice.html#Yubico_YubiKey_YubiKeyDevice_SetIsNfcRestricted_System_Boolean_) ([#91](https://github.com/Yubico/Yubico.NET.SDK/pull/91) ). * Additional property pages on the YubiKey are now read into [YubiKeyDeviceInfo](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.YubiKeyDeviceInfo.html) ([#92](https://github.com/Yubico/Yubico.NET.SDK/pull/92) ). * PIN complexity: * Complexity status can now be checked with [IsPinComplexityEnabled](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.YubiKeyDevice.html#Yubico_YubiKey_YubiKeyDevice_IsPinComplexityEnabled) ([#92](https://github.com/Yubico/Yubico.NET.SDK/pull/92) ). * PIN complexity error messages and exceptions have been added ([#112](https://github.com/Yubico/Yubico.NET.SDK/pull/112) ). * The set of YubiKey applications that are capable of being put into FIPS mode can be retrieved with [FipsCapable](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.YubiKeyDevice.html#Yubico_YubiKey_YubiKeyDevice_FipsCapable) . The set of YubiKey applications that are in FIPS mode can be retrieved with [FipsApproved](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.YubiKeyDevice.html#Yubico_YubiKey_YubiKeyDevice_FipsApproved) ([#92](https://github.com/Yubico/Yubico.NET.SDK/pull/92) ). * The part number for a key’s Secure Element processor, if available, can be retrieved with [PartNumber](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.YubiKeyDevice.html#Yubico_YubiKey_YubiKeyDevice_PartNumber) ([#92](https://github.com/Yubico/Yubico.NET.SDK/pull/92) ). * The set of YubiKey applications that are blocked from being reset can be retrieved with [ResetBlocked](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.YubiKeyDevice.html#Yubico_YubiKey_YubiKeyDevice_ResetBlocked) ([#92](https://github.com/Yubico/Yubico.NET.SDK/pull/92) ). * PIV: * 3072 and 4096 RSA keys can now be generated and imported ([#100](https://github.com/Yubico/Yubico.NET.SDK/pull/100) ). * Keys can now be moved between all YubiKey PIV slots except for the attestation slot with [MoveKeyCommand](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.Commands.MoveKeyCommand.html) . Any PIV key can now be deleted from any PIV slot with [DeleteKeyCommand](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.Commands.DeleteKeyCommand.html) ([#103](https://github.com/Yubico/Yubico.NET.SDK/pull/103) ). * Support for YubiKey Bio/Bio Multi-Protocol Edition keys: * Bio metadata can now be retrieved with [GetBioMetadataCommand](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.Commands.GetBioMetadataCommand.html) ([#108](https://github.com/Yubico/Yubico.NET.SDK/pull/108) ). * New PIV PIN verification policy enum values ([MatchOnce](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.PivPinPolicy.html#Yubico_YubiKey_Piv_PivPinPolicy_MatchOnce) , [MatchAlways](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.PivPinPolicy.html#Yubico_YubiKey_Piv_PivPinPolicy_MatchAlways) ) have been added ([#108](https://github.com/Yubico/Yubico.NET.SDK/pull/108) ). * [Biometric verification](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#biometric-verification) is now supported ([#108](https://github.com/Yubico/Yubico.NET.SDK/pull/108) ). * A device-wide reset can now be performed on YubiKey Bio Multi-protocol keys with [DeviceReset](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.IYubiKeyDevice.html#Yubico_YubiKey_IYubiKeyDevice_DeviceReset) ([#110](https://github.com/Yubico/Yubico.NET.SDK/pull/110) ). * The USB reclaim speed, which controls the time it takes to switch from one YubiKey application to another, has been reduced for compatible YubiKeys. To use the previous 3-second reclaim timeout for all keys, see [UseOldReclaimTimeoutBehavior](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.YubiKeyCompatSwitches.html#Yubico_YubiKey_YubiKeyCompatSwitches_UseOldReclaimTimeoutBehavior) ([#93](https://github.com/Yubico/Yubico.NET.SDK/pull/93) ). * The sensitivity of the YubiKey’s capacitive touch sensor can now be temporarily adjusted with [SetTemporaryTouchThreshold](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.YubiKeyDevice.html#Yubico_YubiKey_YubiKeyDevice_SetTemporaryTouchThreshold_System_Int32_) ([#95](https://github.com/Yubico/Yubico.NET.SDK/pull/95) ). Bug fixes: * The ManagementKeyAlgorithm is now updated when the PIV Application is reset ([#105](https://github.com/Yubico/Yubico.NET.SDK/pull/105) ). * macOS input reports are now queued so that large responses aren't dropped ([#84](https://github.com/Yubico/Yubico.NET.SDK/pull/84) ). * Smart card handles are now opened shared by default. To open them exclusively, use [OpenSmartCardHandlesExclusively](https://docs.yubico.com/yesdk/core-api/Yubico.Core.CoreCompatSwitches.html#Yubico_Core_CoreCompatSwitches_OpenSmartCardHandlesExclusively) with AppContext.SetSwitch ([#83](https://github.com/Yubico/Yubico.NET.SDK/pull/83) ). * A build issue that occurred when compiling `Yubico.NativeShims` on MacOS has been fixed ([#109](https://github.com/Yubico/Yubico.NET.SDK/pull/109) ). * The correct certificate OID friendly names are now used for ECDsaCng (nistP256) and ECDsaOpenSsl (ECDSA\_P256) ([#78](https://github.com/Yubico/Yubico.NET.SDK/pull/78) ). Miscellaneous: * The way that YubiKey device info is read by the SDK has changed, and as a result, the following GetDeviceInfo command classes have been deprecated ([#91](https://github.com/Yubico/Yubico.NET.SDK/pull/91) ): * `Yubico.YubiKey.Management.Commands.GetDeviceInfoCommand` * `Yubico.YubiKey.Otp.Commands.GetDeviceInfoCommand` * `Yubico.YubiKey.U2f.Commands.GetDeviceInfoCommand` * `Yubico.YubiKey.Management.Commands.GetDeviceInfoResponse` * `Yubico.YubiKey.Otp.Commands.GetDeviceInfoResponse` * `Yubico.YubiKey.U2f.Commands.GetDeviceInfoResponse` * Integration test guardrails have been added to ensure tests are done only on specified keys. ([#100](https://github.com/Yubico/Yubico.NET.SDK/pull/100) ). * Unit tests were run on all platforms in CI ([#80](https://github.com/Yubico/Yubico.NET.SDK/pull/80) ). Dependencies: * The test packages xUnit and Microsoft.NET.Test.Sdk have been updated ([#94](https://github.com/Yubico/Yubico.NET.SDK/pull/94) ). 1.10.x Releases --------------- ### 1.10.0 Release date: April 10th, 2024 This release improves our native dependencies exposed through the `Yubico.NativeShims` package. We have also worked to improve the build and test experience of this repository by improving our automation and build files. Changes: * **Yubico.NativeShims targets OpenSSL version 3.x on all platforms** - OpenSSL v1.1.x has reached end-of-life. The SDK now removes this dependency on all platforms, now upgrading to the supported 3.x version. * **Dropped support for 32-bit Linux** - Yubico.NativeShims no longer builds for 32-bit (x86) Linux. We now depend on Ubuntu releases that contain OpenSSL 3.x by default. These newer releases no longer have mainstream support for this platform. * **[Compilation hardening of Yubico.NativeShims](https://github.com/Yubico/Yubico.NET.SDK/pull/67) ** - Added commonly used compiler flags to increase security and code quality **MacOS / Linux:** \-Wformat: Warn about format string issues in printf-like functions. \-Wformat-nonliteral: Warn about format strings that are not string literals. \-Wformat-security: Warn about potential security issues related to format strings. \-Wall: Enable most warning messages \-Wextra: Enable some additional warning messages not included in -Wall \-Werror: Treat all warnings as errors \-Wcast-qual: Warn when casting away const-ness \-Wshadow: Warn when a local variable shadows another variable \-pedantic: Issue warnings for language features beyond the C standard \-pedantic-errors: Treat pedantic warnings as errors \-Wbad-function-cast: Warn about dubious function pointer casts \-O2: Optimize code for performance \-fpic: Generate position-independent code \-fstack-protector-all: Enable stack protection for all functions \-D\_FORTIFY\_SOURCE=2: Enable runtime and compile-time checks for certain security-critical functions **Windows flags:** /guard:cf: Enable control flow guard security feature /GS: Enable buffer security check /Gs: Control stack security check * [Addressed compiler warning concerning Runtime Identifiers (RID)](https://github.com/Yubico/Yubico.NET.SDK/issues/59) * **Enabled `dotnet format`** - The repository now uses `dotnet format` to ensure that pull requests adhere to the repository's coding standards. A pass of the tool has been run against the entire repository and a new baseline has been checked in. 1.9.x Releases -------------- ### 1.9.1 Release date: November 14th, 2023 Bug fixes: * **SCard handle contention**. Previously, the SDK was opening all smart card handles with shared permissions, meaning that other applications and services were still able to interact with the YubiKey while the SDK performed smart card operations. However, this allowed these other entities (such as smart card minidrivers) to alter the current state of the YubiKey without the SDK's knowledge. This would sometimes cause random failures and exceptions to occur when using the SDK. The SDK now opens the handle exclusively, which means other applications will not be able to open the smart card handle for read and write operations while the SDK is using it. Callers should take care to not keep a YubiKey connection or session open longer than is needed. * **Config changes over FIDO2**. The YubiKey Management commands are now available over all three logical USB interfaces (HID keyboard, HID FIDO, and smart card). The SDK will typically use the first available interface, giving some preference to the smart card. Previously, this operation would have failed on FIDO-only devices as the management commands were not properly wired up over this interface. Miscellaneous: * **Dependency updates**. The dependencies of the SDK were updated to the latest packages available. Since the SDK itself does not take many dependencies outside of the .NET Base Class Libraries (BCL), there should not be much of a noticeable impact. The two that affect the SDK itself (and not just test code) are: * `Microsoft.Extensions.Logging.Abstractions` (6.0.1 -> 7.0.1) * `System.Memory` (4.5.4 -> 4.5.5) ### 1.9.0 Release date: October 13th, 2023 Features: * **FIDO2 PIN Config**. The PIN config feature, if supported by the connected YubiKey, is a set of operations: set the minimum PIN length, force a PIN change, and return a minimum PIN length to a relying party. * **FIDO2 GUI option for sample code**. There is now a version of the FIDO2 sample code that uses Windows Forms. This GUI version of the sample code is provided mainly to demonstrate how to build touch and fingerprint notifications in a KeyCollector. This sample code runs only in a Windows environment. * **SCP03 CMAC added to CryptographyProviders**. SCP03 operations rely on the AES-CMAC algorithm, and, starting in this release, they will call on the CryptogrphyProviders class to retrieve an implementation. The default implementation uses OpenSSL. * **SCP03 keys**. This release adds the ability to change SCP03 key sets. This includes replacing the default key set, adding new key sets, and removing key sets. This is done using the new Scp03Session class. * **SCP03 architecture**. The process for building an SCP03 connection was updated. The previous method (`Yubico.YubiKey.YubiKeyDeviceExtensions.WithScp03()`) is now deprecated, and the new method (`Yubico.YubiKey.IYubiKeyDevice.ConnectScp03()` simply requires passing in the SCP03 key set to the PivSession constructor. It is also possible to build an IYubiKeyConnection that uses SCP03 via `Yubico.YubiKey.Piv.PivSession()`. * **SCP03 documentation**. The User's Manual article on SCP03 was updated to provide more comprehensive information. 1.8.x Releases -------------- ### 1.8.0 Release date: June 30th, 2023 Features: * **FIDO2 Bio Enroll**. This allows enrolling and enumerating fingerprint templates. In addition, the SDK implemented fingerprint verification for FIDO2 and incorporated it into the automatic verification process. * **FIDO2 Authenticator Config Operations**. This is a series of new methods that allow the programmer to perform some esoteric FIDO2 configuration operations, such as enabling enterprise attestation and increasing the minimum PIN length. * **FIDO2 Update Credential Management to Support CredentialMgmtPreview**. Some older YubiKeys do not support the "credential management" feature (enumerate credentials, delete credentials, and others), but do support the "credential management preview" feature. This is the same as "credential management" except that the preview version does not include "Update User Info". The credential management commands and Fido2Session methods now support "Preview", meaning calls to the credential management methods (e.g. Fido2Session.EnumerateRelyingParties) will work on older YubiKeys that support "CredentialMgmtPreview", just as the newer YubiKeys. * **FIDO2 HMAC Secret Extension and CredProtect Extension**. These are oft-used extensions, and the SDK now has methods to make using them easier (e.g. MakeCredentialParameters.AddHmacExtension and AuthenticatorData.GetHmacSecretExtension). * **FIDO2 Encoded Attestation** The full encoded attestation statement is available when making a credential. This is useful if you are implementing or interoperating with the WebAuthn data types. That is, it is often easier to copy this field in its encoded form rather than using the parsed properties. * **FIDO2 Update Sample Code**. The FIDO2 sample project now contains examples that perform bio enroll, credential management, authenticator config, HMAC secret, and credProtect operations. * **OTP Documentation Updates**. There are new articles and information about slots (e.g. access codes, deleting), new articles on Hotp (what it is and programming an Hotp credential), new articles on static passwords (what it is and programming a slot to contain a static password), and a new article on updating slots, including manual update. Bug Fixes: * NFC response code in FIDO2 now handled properly. 1.7.x Releases -------------- ### 1.7.0 Release date: March 31st, 2023 Features: * **FIDO2 Credential Management**. The credential management feature allows a client application to retrieve information about discoverable FIDO2 credentials on a YubiKey, update user information, and delete credentials. This includes enumerating the relying parties and user information for all the discoverable credentials. 1.6.x Releases -------------- ### 1.6.1 Release date: February 2nd, 2023 Features: * Added KeyCollector variants to the YubiHsmAuthSession class for methods which require credential gathering. * [TryGetAes128SessionKeys](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.YubiHsmAuth.YubiHsmAuthSession.html#Yubico_YubiKey_YubiHsmAuth_YubiHsmAuthSession_TryGetAes128SessionKeys_System_String_System_ReadOnlyMemory_System_Byte__System_ReadOnlyMemory_System_Byte__Yubico_YubiKey_YubiHsmAuth_SessionKeys__) * [TryAddCredential](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.YubiHsmAuth.YubiHsmAuthSession.html#Yubico_YubiKey_YubiHsmAuth_YubiHsmAuthSession_TryAddCredential_Yubico_YubiKey_YubiHsmAuth_CredentialWithSecrets_) * [TryDeleteCredential](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.YubiHsmAuth.YubiHsmAuthSession.html#Yubico_YubiKey_YubiHsmAuth_YubiHsmAuthSession_TryDeleteCredential_System_String_) * [TryChangeManagementKey](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.YubiHsmAuth.YubiHsmAuthSession.html#Yubico_YubiKey_YubiHsmAuth_YubiHsmAuthSession_TryChangeManagementKey) Bug fixes: * Fixed a bug which prevented large responses from the OATH application from being received by the SDK. Fixes [GitHub Issue #35](https://github.com/Yubico/Yubico.NET.SDK/issues/35) . * The YubiKey can now accept a zero-length NDEF text prefix, which was previously prevented by the SDK. * Added an MSBuild target that instructs .NET Framework-based builds to automatically copy the correct version of `Yubico.NativeShims.dll` into the build's output directory. This requires the use of `PackageReferences` in the consuming project's csproj file in order to properly consume this dependency transitively through the `Yubico.YubiKey` package. `Packages.config` is not supported. Fixes [GitHub Issue #11](https://github.com/Yubico/Yubico.NET.SDK/issues/11) . * Addressed a difference in behavior found in EcdsaVerify that caused .NET Framework users to receive an exception. Fixes [GitHub Issue #36](https://github.com/Yubico/Yubico.NET.SDK/issues/36) . ### 1.6.0 Release date: January 16th, 2023 Features: * **FIDO2 Credential Blobs and Large Blob support.** FIDO2 allows applications to store additional information alongside a credential. Credential Blobs and Large Blobs are two separate, though related, features for achieving this. Bug fixes: * Added an MSBuild rule for projects that target .NET Framework 4.x that now automatically copy the correct version of Yubico.NativeShims.dll into the build directory. This addresses the "Missing DLL" issue that .NET Framework users would encounter. Fixes [GitHub Issue #11](https://github.com/Yubico/Yubico.NET.SDK/issues/11) . * Addressed an issue where the SDK would enumerate FIDO devices on Windows despite being un-elevated. Windows requires process elevation in order to communicate with FIDO devices. The SDK would display one or more YubiKeys with incorrect properties as a result. Fixes [GitHub Issue #20](https://github.com/Yubico/Yubico.NET.SDK/issues/20) . * A difference in behavior between .NET Framework 4.x and .NET 6 caused OAEP padding operations to fail for projects running on .NET Framework 4.x. The SDK has been updated to work around this difference in behavior and should now work for all supported versions of .NET. Fixes [GitHub Issue #33](https://github.com/Yubico/Yubico.NET.SDK/issues/33) . * The YubiKey requires a short delay when switching between its USB interfaces. Switching too quickly can result in failed operations and other strange behaviors. The SDK will now automatically wait the required amount of time to ensure stable communication with the YubiKey. Note that this may cause the first operation or command sent to the YubiKey to appear slow. Subsequent calls to the same application will not be affected. Fixes [GitHub Issue #34](https://github.com/Yubico/Yubico.NET.SDK/issues/34) . 1.5.x Releases -------------- ### 1.5.1 (Yubico.YubiKey), 1.5.2 (Yubico.NativeShims) Release date: November 18th, 2022 Bug fixes: * Fixed a bug in Yubico.NativeShims where a function parameter wasn't properly initialized. This affected enumeration of smart cards in some cases. * Upgraded System.Formats.CBOR to 7.0.0 now that .NET 7 has been released. * FIDO2 re-initializes the auth protocol after a failed PIN attempt. This now matches spec behavior. * Upgraded the version of OpenSSL that Yubico.NativeShims uses to 3.0.7. Note: the SDK was _not_ affected by any of the November 2022 security advisories. ### 1.5.0 Release date: October 28th, 2022 Features: * **YubiHSM Auth.** YubiHSM Auth is a YubiKey application that stores the long-lived credentials used to establish secure sessions with a YubiHSM 2. The secure session protocol is based on Secure Channel Protocol 3 (SCP03). The SDK adds full support for this application. This includes both management of credentials and creating the session keys for communicating with a YubiHSM 2. * **FIDO2 partial support.** The basic building blocks for FIDO2 are now available. Making credentials and generating assertions are now possible using the SDK, along with verification using both PIN and biometric touch. Both PIN protocols are also available. Future releases will add additional FIDO2 functionality. 1.4.x Releases -------------- ### 1.4.2 Release date: September 27th, 2022 Bug fixes: * The UWP .NET Native toolchain has slightly different rules around P/Invoke name resolution than normal .NET, which caused UWP projects to crash when enumerating YubiKeys. Additional annotation has been added to some of the Windows API P/Invoke definitions to help the native compiler resolve the APIs and prevent these crashes. ### 1.4.1 Release date: September 12th, 2022 Bug fixes: * TOTP calculations in the OATH application were incorrect. The OATH application was mistakenly using a random challenge instead of the time for calculation of TOTP credentials. This has been resolved. * The device listener was attempting to modify a collection that it was also iterating over in a loop. This is not allowed by .NET. The list to iterate over is now a clone of the original list. * MacOS does not always return properties of HID devices (including Vendor and Product IDs). This can cause the enumeration code path to fail on certain MacOS based devices, including Apple Silicon devices. The SDK now expects all HID properties to be optional and will skip over devices that don't have the minimum set required. ### 1.4.0 Release date: June 30th, 2022 Features: * **AES-based PIV management keys**. Newer versions of the YubiKey (firmware 5.4.2 and above) have the ability to use AES-based encryption for the management key. This is in addition to the existing Triple-DES based management keys. Read the updated [PIN, PUK, and Management Key](https://docs.yubico.com/yesdk/users-manual/application-piv/pin-puk-mgmt-key.html) article for more information. * **FIDO U2F**. Applications using this SDK can now use the YubiKey's FIDO U2F application. This means that the SDK is now also enumerating the HID FIDO device, in addition to the HID keyboard and smart card devices exposed by the YubiKey. Use this feature if your application wants to handle U2F registration or authentication. Note that on Microsoft Windows, applications must run with elevated privileges in order to talk to FIDO devices. This is a requirement set in place by Microsoft. See [FIDO U2F overview](https://docs.yubico.com/yesdk/users-manual/application-u2f/fido-u2f-overview.html) for more information. * **SCP03**. Secure Channel Protocol 03 (also referred to as SCP03) is a Global Platform specification that allows clients of smart cards to encrypt all traffic to and from the card. Since the YubiKey can act as a smart card, this means that it is now possible to encrypt all traffic for the PIV application. In order for this to work, however, your YubiKey must be pre-configured for this feature. Read more about [SCP03 here](https://docs.yubico.com/yesdk/users-manual/sdk-programming-guide/secure-channel-protocol.html) . * **Debian, RHEL, and CentOS support**. Our testing of Linux platforms has expanded to include the Debian, Red Hat Enterprise Linux (RHEL), and CentOS distributions. Please read [running on Linux](https://docs.yubico.com/yesdk/users-manual/getting-started/running-on-linux.html) for more details. Bug fixes: * High CPU usage when the SDK can't connect to the smart card subsystem. * Yubico.NativeShims DLL not found when using .NET Framework 4.x. Note that there is an additional issue with `packages.config` that is not able to be resolved. Developers are urged to upgrade to the newer `` method if at all possible. Manual installation of the Yubico.NativeShims library will be necessary if you are stuck on `packages.config`. * "Duplicate resource" error when compiling for UWP applications. 1.3.x Releases -------------- ### 1.3.1 Release date: April 13th, 2022 Bug fixes: * Applications targeting .NET Core 3.x, .NET 5, or higher would encounter an exception that said `Microsoft.BCL.HashCode` could not be found. Adding that NuGet reference manually would work around the issue. This issue has now been addressed and a work around is no longer required. * An exception would be thrown if a YubiKey with a non-visible serial number was plugged in. This was a regression in behavior and has now been fixed. * The reference to the newly introduced assembly `Yubico.NativeShims` was pinned to a pre-release version. This has been fixed and now points to the latest publicly listed package. ### 1.3.0 Release date: March 31st, 2022 This release brings enhancements across the SDK. Features: * **PIV Objects**. There is now a new namespace, `Yubico.YubiKey.Piv.Objects` that contains high level representations of common PIV objects such as [CHUID](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.Objects.CardholderUniqueId.html) , [CCC](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.Objects.CardCapabilityContainer.html) , and [KeyHistory](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.Objects.KeyHistory.html) . These objects, paired with two new methods [ReadObject](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.PivSession.html#Yubico_YubiKey_Piv_PivSession_ReadObject_) and [WriteObject](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.PivSession.html#Yubico_YubiKey_Piv_PivSession_WriteObject_Yubico_YubiKey_Piv_Objects_PivDataObject_) provide a much easier mechanism for interacting with common PIV objects. * **Direct credential gathering**. Some applications, such as PIV and OATH, require a user to authenticate using a PIN or password. The SDK has a robust mechanism called the [KeyCollector](https://docs.yubico.com/yesdk/users-manual/sdk-programming-guide/key-collector.html) for gathering credentials. Supplying a key collector will mean that your application will always be notified for the right credential at the right time. Sometimes, though, you may not want to use a key collector, and supplying the credential directly to the session is preferable. For this, we've added overloads to the most common credential gathering routines (e.g. [TryVerifyPin](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.PivSession.html#Yubico_YubiKey_Piv_PivSession_TryVerifyPin_System_ReadOnlyMemory_System_Byte__System_Nullable_System_Int32___) ) that allow you to provide the credential directly, without the need for a key collector. * **Feature queries**. Rather than keeping track of YubiKey firmware versions and other properties, your application can now directly [query a YubiKey](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.YubiKeyFeatureExtensions.html#Yubico_YubiKey_YubiKeyFeatureExtensions_HasFeature_Yubico_YubiKey_IYubiKeyDevice_Yubico_YubiKey_YubiKeyFeature_) to see whether it supports a particular feature. * **Protected PIV management keys**. Some applications, such as YubiKey Manager or the YubiKey Smart Card Mini-Driver, may opt to [only use the PIV PIN](https://docs.yubico.com/yesdk/users-manual/application-piv/pin-only.html) . It does this by storing the PIV management key in a PIN protected object and using the PIN to unlock the smart card. The SDK has been enlightened to these modes of operations and the PivSession will automatically detect and act appropriately. That is, the KeyCollector will automatically ask for a PIN instead of the Management key for keys that are configured in this way. No extra handling is required by your application. * **Yubico.NativeShims**. A new internal-use library has been introduced to help facilitate better interoperability with the underlying native platform libraries. No functional changes should have occurred as a result of this change. This will instead open the door to broader support of platforms, specifically with regards to Linux distributions. Bug fixes: * Fixed a high CPU usage issue on Windows that was introduced in 1.2.0. This bug was encountered when multiple YubiKeys were plugged into a single computer, and the user reduced the number of keys to one. * Fixed an issue where the interfaces and applications were not being reported correctly for YubiKey NEOs. 1.2.x Releases -------------- ### 1.2.0 Release date: February 7th, 2022 This release adds support for device notifications. Now, applications can be notified in real-time that a YubiKey has been inserted or removed from the computer. Read more about how device notifications work and how to use them on [this page](https://docs.yubico.com/yesdk/users-manual/sdk-programming-guide/device-notifications.html) . Device notifications are supported on all currently supported platforms. 1.1.x Releases -------------- ### 1.1.0 Release date: December 3rd, 2021 This release marks the beginning of support for Linux platforms. The primary target for testing has been against Ubuntu Linux 20.04 LTS and 21.10. Other Ubuntu-based distributions should work as well. Additional Linux platforms may work based on their [ABI](https://en.wikipedia.org/wiki/Application_binary_interface) compatibility with Ubuntu. Further distributions will be added to the supported list once thorough testing on those platforms has been completed. Limited smart card only support may be present for additional distributions, as they depend on the PCSC-lite library. Some symlinks may need to be present in order for the .NET runtime to find the appropriate system libraries (such as pcsc-lite, udev, etc.) Information about how to create these links can be found on [this page](https://docs.yubico.com/yesdk/users-manual/yubikey-reference/transports/overview.html) . 1.0.x Releases -------------- ### 1.0.2 Release date: October 26th, 2021 Added Authenticode signing to the release process. Assemblies are now signed in addition to the NuGet package. No code changes in this release. ### 1.0.1 Release date: October 1st, 2021 Bug fixes: * PIV: Fixed an issue that was preventing the SDK from allowing attestation to occur on certain slots. * OATH Sample code: Fixed an issue that was causing an exception to be thrown during `RunGetCredentials`. * PIV Sample code: Worked around an issue in the .NET BCL where certificate generation behavior was different on macOS from Windows. ### 1.0.0 Release date: August 30th, 2021 This is the first official, generally available release of the YubiKey SDK for Desktop aimed at the .NET developer community and ecosystem. In this release, the [OTP](https://docs.yubico.com/yesdk/users-manual/application-otp/otp-overview.html) , [OATH](https://docs.yubico.com/yesdk/users-manual/application-oath/oath-overview.html) , and [PIV](https://docs.yubico.com/yesdk/users-manual/application-piv/piv-overview.html) applications are fully supported. Please refer to those applications' sections within the documentation for more information. The [Overview of the SDK](https://docs.yubico.com/yesdk/users-manual/getting-started/overview-of-sdk.html) page also goes into much more depth on what this SDK contains, and how it is structured. Lastly, this SDK has also been released as open source under the Apache 2.0 license. Please refer to the `CONTRIBUTING.md` file in the root of the repository for information on how you can contribute. ### 1.0.0-Beta.20210721.1 Release date: July 21st, 2021 This is the beta refresh of the YubiKey Desktop SDK. In this release, the OATH, PIV and OTP applications are now fully supported. Many OTP features have been completed since the last beta release, we have implemented: * HOTP * Challenge-Response with HMAC and Yubico OTP algorithms * Calculate Challenge-Response with touch notification * Reading and writing NDEF tags, * Delete, swap and update OTP slot functionalities. ### 1.0.0-Beta.20210618.1 Release date: June 18th, 2021 This is the first public preview of the new YubiKey Desktop SDK. This SDK allows you to integrate the YubiKey into your .NET based application or workflow. The OATH and PIV applications are fully supported, with partial support for Yubico OTP. Full support for Yubico OTP will come in the next beta refresh. There is support for macOS and Windows, over both USB and Near-Field Communication (NFC). As the first public beta, the API surface is considered stable. However, if sufficient feedback is received, some minor breaking changes may occur prior to general availability (GA). ### 1.0.0-Alpha.20210521.1 Release date: May 21st, 2021 This was a limited availability preview. * A bug was addressed in the smart card reader code which computed an incorrect buffer offset based on the architecture of the computer running the YubiKey SDK software. * OATH functionality is now "feature complete." * YubiKey device management functionality has been added. ### 1.0.0-Alpha.20210505.1 Release date: May 5th, 2021 This was a limited availability preview. * PIV functionality is now "feature complete". OATH APIs are partially available. * A bug was identified and addressed where the default PIV management key could not be used due to a `CryptographicException` being thrown by the .NET TripleDES implementation. This is because the default management key is considered a "weak" key. * A design re-review of the PivSession class identified an over-use of the TryParse pattern. This has been addressed. Breaking API changes in Yubico.YubiKey: * Several methods on the `PivSession` class have been renamed as they no longer follow the TryParse pattern. * `KeyEntryData` and `KeyEntryRequest` have been moved from the `Yubico.YubiKey.Cryptography` namespace to the `Yubico.YubiKey` namespace. * Information previously found in `IYubiKey.DeviceInfo` has been collapsed into the YubiKey object itself by means of the `IYubiKeyDeviceInfo` interface. * Naming of the cryptography delegates have been updated to reflect the .NET Framework Design Guidelines naming conventions. For example, `CreateRng` and `CreateTripleDes` have been renamed to `RngCreator` and `TripleDesCreator` respectively. ### 1.0.0-Alpha.20210329.1 Release date: March 29th, 2021 This was a limited availability preview. * A bug was found and addressed that affected the stability of smart card connections. This would affect any command that was sent from the PIV or OATH applications, and would have a higher likelihood of occurring for long-running operations. The bug would result in certain method calls failing sporadically. Breaking API changes in Yubico.YubiKey: * The `ConnectionType` enum has been renamed to `Transport` * `YubiKeyEnumerator.GetYubiKeys()` has been replaced by `YubiKey.FindAll()` * There is no longer a concrete YubiKey instance type. Interaction should be done through the `IYubikey` interface and related types. * Certain constants related to the OTP NDEF "file ID" have been pulled out into an enumeration called `NdefFileId` * `CreateAttestationCertificateCommand` and `CreateAttestationCertificateResponse` classes have been renamed to `CreateAttestationStatementCommand` and `CreateAttestationStatementResponse`, respectively, to reflect the terminology already established in published specifications and documentation. ### 1.0.0-Alpha.20210222.1 Release date: February 22nd, 2021 This was a limited availability preview. * Enumeration of YubiKeys on macOS and Windows platforms * macOS supports CCID communication only. Windows supports CCID and HID. * OTP, OATH, PIV, and SCP03 have full low-level command support. All APDUs are mapped to a C# class. * PIV high level commands are partially implemented. Certificate enrollment scenarios were prioritized. [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/getting-started/whats-new.md/#L1) --- # Yubico Product Documentation — Yubico Product Documentation documentation * [](https://docs.yubico.com/#) * Yubico Product Documentation * [View page source](https://docs.yubico.com/_sources/index.rst.txt) * * * Yubico Product Documentation[](https://docs.yubico.com/#yubico-product-documentation "Permalink to this heading") =================================================================================================================== YubiKeys[](https://docs.yubico.com/#yubikeys "Permalink to this heading") --------------------------------------------------------------------------- [![_images/hardware.png](https://docs.yubico.com/_images/hardware.png)](https://docs.yubico.com/_images/hardware.png) _YubiKeys_ are hardware authentication devices that protect user access to computers, networks, and online accounts and services through phishing-resistant multi-factor authentication and passwordless login. * **YubiKey Technical Manual** \[[HTML](https://docs.yubico.com/hardware/yubikey/yk-tech-manual/index.html)\ \] \[[PDF](https://docs.yubico.com/hardware/yubikey/yk-tech-manual/webdocs.pdf)\ \] * **YubiKey Technical Data Sheet** \[[PDF](https://docs.yubico.com/hardware/yubikey/datasheet/_static/YubiKey_technical_data_sheet.pdf)\ \] * **YubiKey FIPS 4 Series Technical Manual** \[[HTML](https://docs.yubico.com/hardware/yubikey/yk-fips-4/index.html)\ \] \[[PDF](https://docs.yubico.com/hardware/yubikey/yk-fips-4/webdocs.pdf)\ \] * **Yubico Object ID (OID) Reference Guide** \[[HTML](https://docs.yubico.com/hardware/oid/index.html)\ \] \[[PDF](https://docs.yubico.com/hardware/oid/webdocs.pdf)\ \] * **Implementation Guidance and Support: Yubico Best Practices** \[[HTML](https://docs.yubico.com/hardware/yubikey-guidance/best-practices/index.html)\ \] \[[PDF](https://docs.yubico.com/hardware/yubikey-guidance/best-practices/webdocs.pdf)\ \] * * * YubiEnterprise Services[](https://docs.yubico.com/#yubienterprise-services "Permalink to this heading") --------------------------------------------------------------------------------------------------------- [![_images/services-icon.png](https://docs.yubico.com/_images/services-icon.png)](https://docs.yubico.com/_images/services-icon.png) _YubiEnterprise Services_ enable organizations to order and distribute YubiKeys efficiently and rapidly. Includes the _YubiEnterprise Console_ user interface and the _YubiEnterprise API_ for managing orders and delivery of YubiKeys to end users. _Yubico FIDO Pre-reg_ and _YubiEnroll_ are part of the Yubico Enrollment Suite which empowers organizations to streamline management of pre-registered and pre-enrolled YubiKeys for end users, on their path to stronger security. * **YubiEnterprise Services User Guide & Release Notes** \[[HTML](https://docs.yubico.com/cloud-services/yubienterprise/delivery/)\ \] [\[PDF](https://docs.yubico.com/cloud-services/yubienterprise/delivery/webdocs.pdf)\ \] * **YubiEnterprise API Reference** \[[HTML](https://console.yubico.com/apidocs/)\ \] * **Yubico FIDO Pre-reg with Okta - Integration Guide** \[[HTML](https://docs.yubico.com/cloud-services/fidoprereg-okta/)\ \] \[[PDF](https://docs.yubico.com/cloud-services/fidoprereg-okta/webdocs.pdf)\ \] * **Yubico FIDO Pre-reg with Microsoft - Integration Guide** \[[HTML](https://docs.yubico.com/cloud-services/fidoprereg-microsoft/)\ \] \[[PDF](https://docs.yubico.com/cloud-services/fidoprereg-microsoft/webdocs.pdf)\ \] * **YubiEnroll User Guide & Release Notes** \[[HTML](https://docs.yubico.com/software/yubikey/tools/yubienroll/)\ \] \[[PDF](https://docs.yubico.com/software/yubikey/tools/yubienroll/webdocs.pdf)\ \] * **YubiEnroll with Okta - Quick Start Guide** \[[PDF](https://docs.yubico.com/software/yubikey/tools/yubienroll/_static/YubiEnroll-with-Okta-Quick-Start-Guide.pdf)\ \] * **YubiEnroll with Microsoft - Quick Start Guide** \[[PDF](https://docs.yubico.com/software/yubikey/tools/yubienroll/_static/YubiEnroll-with-Microsoft-Quick-Start-Guide.pdf)\ \] * * * Apps & Tools[](https://docs.yubico.com/#apps-tools "Permalink to this heading") --------------------------------------------------------------------------------- [![_images/apps-tools-icon.png](https://docs.yubico.com/_images/apps-tools-icon.png)](https://docs.yubico.com/_images/apps-tools-icon.png) _Yubico Authenticator_ is a desktop and mobile application that allows end users to manage their YubiKeys and perform common operations, such as generating and displaying OATH two-factor authentication codes, managing the FIDO PIN, and performing a factory reset. The _ykman CLI_ is an advanced command line tool for desktop that provides comprehensive YubiKey management and configuration capabilities across all YubiKey applications. The _Yubico PIV tool_ is used for interacting with the Personal Identity Verification (PIV) application on a YubiKey. The _YubiKey Minidriver_ (YKMD) enables integration of the YubiKey’s PIV smart card capabilities with Windows, unlocking functionality such as certificate enrollment, management of YubiKey smart card PINs, and smart card authentication on Windows devices. * **Yubico Authenticator User Guide** \[[HTML](https://docs.yubico.com/software/yubikey/tools/authenticator/auth-guide/index.html)\ \] \[[PDF](https://docs.yubico.com/software/yubikey/tools/authenticator/auth-guide/webdocs.pdf)\ \] * **YubiKey Manager (ykman) CLI User Guide** \[[HTML](https://docs.yubico.com/software/yubikey/tools/ykman/)\ \] [\[PDF](https://docs.yubico.com/software/yubikey/tools/ykman/webdocs.pdf)\ \] * **Yubico PIV Tool User Guide** \[[HTML](https://docs.yubico.com/software/yubikey/tools/pivtool/index.html)\ \] \[[PDF](https://docs.yubico.com/software/yubikey/tools/pivtool/webdocs.pdf)\ \] * **YubiKey Minidriver User Guide** \[[HTML](https://docs.yubico.com/software/yubikey/tools/minidriver/index.html)\ \] \[[PDF](https://docs.yubico.com/software/yubikey/tools/minidriver/webdocs.pdf)\ \] * * * YubiHSM[](https://docs.yubico.com/#yubihsm "Permalink to this heading") ------------------------------------------------------------------------- [![_images/yubi-hsm-icon.png](https://docs.yubico.com/_images/yubi-hsm-icon.png)](https://docs.yubico.com/_images/yubi-hsm-icon.png) _YubiHSM_ is a Hardware Security Module (HSM) device that secures modern infrastructure, including servers. It provides advanced protection for sensitive data, like cryptographic keys, digital certificates, and passwords, as well as code signing operations. * **YubiHSM 2 User Guide** \[[HTML](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/index.html)\ \] [\[PDF](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/webdocs.pdf)\ \] * **YubiHSM 2 Technical Data Sheet** \[[PDF](https://docs.yubico.com/hardware/yubihsm-2/datasheet/_static/YubiHSM_2_Technical_Data_Sheet.pdf)\ \] * * * SDKs & Libraries[](https://docs.yubico.com/#sdks-libraries "Permalink to this heading") ----------------------------------------------------------------------------------------- [![_images/sdk-icon.png](https://docs.yubico.com/_images/sdk-icon.png)](https://docs.yubico.com/_images/sdk-icon.png) Yubico provides a range of desktop and mobile SDKs that allow developers to build YubiKey functionality into custom applications. _java-webauthn-server_ is a server-side WebAuthn library for Java that provides implementations of relying party operations for developers wanting to create their own FIDO2/WebAuthn server. _python-fido2_ is a server-side and client-side library for Python that provides functionality for communicating with FIDO devices over USB and verifying attestation and assertion signatures. * **YubiKey SDK for Desktop (.NET)** \[[HTML](https://docs.yubico.com/yesdk/index.html)\ \] * **YubiKey SDK for iOS** \[[HTML](https://developers.yubico.com/Mobile/iOS/)\ \] * **YubiKey SDK for Android** \[[HTML](https://developers.yubico.com/Mobile/Android/)\ \] * **Java WebAuthn Server-side Library** \[[HTML](https://developers.yubico.com/java-webauthn-server/)\ \] * **Python WebAuthn/FIDO2 Server-side and Client-side Library** \[[HTML](https://developers.yubico.com/python-fido2/)\ \] * * * Other Documentation[](https://docs.yubico.com/#other-documentation "Permalink to this heading") ------------------------------------------------------------------------------------------------- * [Yubico Developer Program](https://developers.yubico.com/) * [Yubico Support](https://support.yubico.com/s/) 2025-11-17 10:34:07 UTC [Cookies](https://www.yubico.com/support/terms-conditions/cookie-notice/) | [Privacy Policy](https://www.yubico.com/support/terms-conditions/privacy-notice/) --- # FIDO U2F commands ##### Table of Contents FIDO U2F commands ================= For each possible U2F command, there will be a class that knows how to build the command [APDU](https://docs.yubico.com/yesdk/users-manual/yubikey-reference/apdu.html) and parse the data in the response APDU. Each class will know what information is needed from the caller for that command. Many of the FIDO U2F commands have an APDU that is actually an inner and outer APDU. For each of these commands, there is an inner APDU to describe the command, which is "wrapped" in a CTAP1 message command. The CTAP1 message command is 00 03 00 00 len innerCommand where the `innerCommand` is itself an APDU for the specific command. For example, the inner command for the Echo command (with 8 bytes of data) is 00 40 00 00 08 11 22 33 44 55 66 77 88 That is wrapped in the CTAP1 command and sent to the YubiKey. It would be this. 00 03 00 00 0B 00 40 00 00 08 11 22 33 44 55 66 77 88 For these commands, the APDU documentation specifies the APDU as "Inner command APDU info". There are some commands that are not CTAP-wrapped. For these commands, the APDU documentation specifies the APDU as "Full command APDU". #### List of FIDO U2F commands * [Echo](https://docs.yubico.com/yesdk/users-manual/application-u2f/u2f-commands.html#echo) * [Get device info](https://docs.yubico.com/yesdk/users-manual/application-u2f/u2f-commands.html#get-device-info) * [Set device info](https://docs.yubico.com/yesdk/users-manual/application-u2f/u2f-commands.html#set-device-info) * [Set legacy device config](https://docs.yubico.com/yesdk/users-manual/application-u2f/u2f-commands.html#set-legacy-device-config) * [Get protocol version](https://docs.yubico.com/yesdk/users-manual/application-u2f/u2f-commands.html#get-protocol-version) * [Verify FIPS mode](https://docs.yubico.com/yesdk/users-manual/application-u2f/u2f-commands.html#verify-fips-mode) * [Set PIN](https://docs.yubico.com/yesdk/users-manual/application-u2f/u2f-commands.html#set-pin) * [Verify PIN](https://docs.yubico.com/yesdk/users-manual/application-u2f/u2f-commands.html#verify-pin) * [Register](https://docs.yubico.com/yesdk/users-manual/application-u2f/u2f-commands.html#register) * [Authenticate](https://docs.yubico.com/yesdk/users-manual/application-u2f/u2f-commands.html#authenticate) * [Reset](https://docs.yubico.com/yesdk/users-manual/application-u2f/u2f-commands.html#reset) * * * Echo ---- Sends data to the YubiKey which immediately echoes the same data back. This command is defined to be a uniform function for debugging, latency, and performance measurements. ### Available All YubiKeys with the FIDO U2F application. ### SDK classes [EchoCommand](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.U2f.Commands.EchoCommand.html) [EchoResponse](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.U2f.Commands.EchoResponse.html) ### Input The data to echo. ### Output `ReadOnlyMemory` The data that had been originally input. ### APDU [Technical APDU Details](https://docs.yubico.com/yesdk/users-manual/application-u2f/apdu/echo-cmd.html) * * * Get device info --------------- Reads configuration and metadata information about the YubiKey (including data not related to U2F). Similar commands exist in other applications. This is provided in the U2F application in case the Keyboard and CCID interfaces have been disabled (see [Set device info](https://docs.yubico.com/yesdk/users-manual/application-u2f/u2f-commands.html#set-device-info) ). ### Available All YubiKeys with the FIDO U2F application. ### SDK classes [GetPagedDeviceInfoCommand](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.U2f.Commands.GetPagedDeviceInfoCommand.html) [GetPagedDeviceInfoResponse](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.U2f.Commands.GetPagedDeviceInfoResponse.html) ### Input None. ### Output A byte array that contains the device info. The first byte is the length. The following bytes are TLVs. For example, 2e 01 02 02 3f 03 02 02 3f 02 04 00 b5 fe 55 04 01 01 05 03 05 04 02 06 02 00 00 07 01 0f 08 01 00 0d 02 02 3f 0e 02 02 3f 0a 01 00 0f 01 00 2e 01 02 02 3f 03 02 02 3f 02 04 00 b5 fe 55 04 01 01 05 03 05 04 02 06 02 00 00 07 01 0f 08 01 00 0d 02 02 3f 0e 02 02 3f 0a 01 00 0f 01 00 #### Table 1: List of DeviceInfo Elements | Tag | Meaning | Data | Comments | | --- | --- | --- | --- | | 01 | Pre-personalization USB capabilities | capabilities bit field | see [YubiKeyCapabilities](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.YubiKeyCapabilities.html) | | 02 | Serial number | 32-bit big-endian integer | | | 03 | Enabled USB capabilities | capabilities bit field | see [YubiKeyCapabilities](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.YubiKeyCapabilities.html) | | 04 | Form factor | form factor byte | see [FormFactor](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.FormFactor.html) | | 05 | Firmware version | 3-byte version | major, minor, patch | | 06 | Auto-eject timeout | 16-bit integer | if 0, no auto-eject, otherwise seconds to auto-eject | | 07 | Challenge-response timeout | one byte | if 0, default, otherwise seconds to timeout | | 08 | Device flags | one byte | see [DeviceFlags](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.DeviceFlags.html) | | 0A | Configuration lock present | one byte, boolean | 0x00 false, 0x01 true | | 0D | Pre-personalization NFC capabilities | capabilities bit field | see [YubiKeyCapabilities](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.YubiKeyCapabilities.html) | | 0E | Enabled NFC capabilities | capabilities bit field | see [YubiKeyCapabilities](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.YubiKeyCapabilities.html) | | 0F | iAP Detection | one byte | currently ignored | ### APDU [Technical APDU Details](https://docs.yubico.com/yesdk/users-manual/application-u2f/apdu/get-device-info.html) * * * Set device info --------------- Sets configuration and metadata information about the YubiKey (including data not related to U2F). Similar commands exist in other applications. This is provided in the U2F application in case the Keyboard and CCID interfaces have been disabled. It is possible to disable the Keyboard and CCID interfaces using this command. ### Available YubiKey 5 and later. ### SDK classes [SetDeviceInfoCommand](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.U2f.Commands.SetDeviceInfoCommand.html) [SetDeviceInfoResponse](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.U2f.Commands.SetDeviceInfoResponse.html) ### Input See also [SetDeviceInfoBaseCommand](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Management.Commands.SetDeviceInfoBaseCommand.html) for more information on the input data and how it is provided. Each is optional. That is, if you want to set one of these elements, provide the value. If you want to leave the element as-is, don't provide it. The exception is the Lock Code. If it is not set, don't provide one. If it is not yet set and you want to set it, provide it. If it is set, to make any changes, provide it. If you want to change it, provide the current and new codes. * Which USB features are to be enabled ([YubiKeyCapabilities](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.YubiKeyCapabilities.html) ) * Which NFC features are to be enabled ([YubiKeyCapabilities](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.YubiKeyCapabilities.html) ) * Challenge Response timeout * Auto eject timeout * [Device flags](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.DeviceFlags.html) * Reset after config (a boolean) * Lock code ### Output None. ### APDU [Technical APDU Details](https://docs.yubico.com/yesdk/users-manual/application-u2f/apdu/set-device-info.html) * * * Set legacy device config ------------------------ Sets configuration and metadata information about the YubiKey (including data not related to U2F). This is for YubiKey 4 and prior. To set device information on YubiKeys version 5 and later, use [Set Device Info](https://docs.yubico.com/yesdk/users-manual/application-u2f/u2f-commands.html#set-device-info) . This is provided in the U2F application in case the Keyboard and CCID interfaces have been disabled. It is possible to disable the Keyboard and CCID interfaces using this command. ### Available YubiKey version 4 and prior. ### SDK classes [SetLegacyDeviceConfigCommand](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.U2f.Commands.SetLegacyDeviceConfigCommand.html) [SetLegacyDeviceConfigResponse](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.U2f.Commands.SetLegacyDeviceConfigResponse.html) ### Input See also [SetLegacyDeviceConfigBase](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Management.Commands.SetLegacyDeviceConfigBase.html) for more information on the input data and how it is provided. Each is optional. That is, if you want to set one of these elements, provide the value. If you want to leave the element as-is, don't provide it. The exception is the Lock Code. If it is not set, don't provide one. If it is not yet set and you want to set it, provide it. If it is set, to make any changes, provide it. If you want to change it, provide the current and new codes. * Which YubiKey interfaces are to be enabled ([YubiKeyCapabilities](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.YubiKeyCapabilities.html) ) * Challenge Response timeout * Auto eject timeout * Touch eject enabled ### Output None. ### APDU [Technical APDU Details](https://docs.yubico.com/yesdk/users-manual/application-u2f/apdu/set-legacy-device-config.html) * * * Get protocol version -------------------- Get the version of the current session's protocol. ### Available All YubiKeys with the FIDO U2F application. ### SDK classes [GetProtocolVersionCommand](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.U2f.Commands.GetProtocolVersionCommand.html) [GetProtocolVersionResponse](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.U2f.Commands.GetProtocolVersionResponse.html) ### Input None. ### Output A string describing the version. ### APDU [Technical APDU Details](https://docs.yubico.com/yesdk/users-manual/application-u2f/apdu/get-protocol-version.html) * * * Verify FIPS mode ---------------- Determine if a FIPS YubiKey is in U2F FIPS mode. A version 4 FIPS YubiKey is manufactured not in FIPS mode. To place it into FIPS mode, the U2F PIN must be set. At that point the YubiKey is in U2F FIPS mode. It is possible to reset the YubiKey to take it out of FIPS mode. However, if a YubiKey is [reset](https://docs.yubico.com/yesdk/users-manual/application-u2f/u2f-commands.html#reset) , the YubiKey cannot be placed into FIPS mode again. This command will request the status. Non-FIPS YubiKeys as well as version 5 FIPS YubiKeys cannot be set to U2F FIPS mode. A version 5 FIPS YubiKey can be set to FIDO2 FIPS. If this command is sent to a YubiKey that cannot be set to U2F FIPS mode, the response will be an error. ### Available All YubiKeys with the FIDO U2F application. However, this is meaningful only on version 4 FIPS YubiKeys. ### SDK classes [VerifyFipsModeCommand](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.U2f.Commands.VerifyFipsModeCommand.html) [VerifyFipsModeResponse](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.U2f.Commands.VerifyFipsModeResponse.html) ### Input None. ### Output `bool` True if the YubiKey is a FIPS device in FIPS mode, false otherwise. ### APDU [Technical APDU Details](https://docs.yubico.com/yesdk/users-manual/application-u2f/apdu/verify-fips.html) * * * Set PIN ------- Sets the new PIN. The PIN is binary and its length must be 6 to 32 bytes. Note: This command is only available on the YubiKey FIPS series. In addition, once the PIN has been set, it is not possible to "unset" the PIN, except by resetting the entire U2F application. It is possible to change the PIN to something new, but not "remove" the PIN requirement. Note that be [resetting](https://docs.yubico.com/yesdk/users-manual/application-u2f/u2f-commands.html#reset) , the YubiKey cannot be placed into FIPS mode again. ### Available All FIPS YubiKeys with the FIDO U2F application. ### SDK classes [SetPinCommand](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.U2f.Commands.SetPinCommand.html) [SetPinResponse](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.U2f.Commands.SetPinResponse.html) ### Input The current PIN and the new PIN. If there is no current PIN (this is the first time the PIN is being set), then the only input is the new PIN. ### Output None. If the command succeeds, the `Status` will be `ResponseStatus.Success`. ### APDU [Technical APDU Details](https://docs.yubico.com/yesdk/users-manual/application-u2f/apdu/set-pin.html) * * * Verify PIN ---------- Verify the PIN for the session. Some documentation calls for "unlocking" the U2F application. Verifying the PIN is how it is unlocked. The PIN is binary and its length must be 6 to 32 bytes. Note: This command is only available on the YubiKey FIPS series. ### Available All FIPS YubiKeys with the FIDO U2F application. ### SDK classes [VerifyPinCommand](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.U2f.Commands.VerifyPinCommand.html) [VerifyPinResponse](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.U2f.Commands.VerifyPinResponse.html) ### Input The current PIN. ### Output None. If the command succeeds, the `Status` will be `ResponseStatus.Success`. ### APDU [Technical APDU Details](https://docs.yubico.com/yesdk/users-manual/application-u2f/apdu/verify-pin.html) * * * Register -------- Register the YubiKey with a new account. This is the command that will build the response to the relying party's registration challenge. It will generate a new key pair, sign the challenge, and return the public key, attestation cert, and signature. ### Available All YubiKeys with the FIDO U2F application. ### SDK classes [RegisterCommand](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.U2f.Commands.RegisterCommand.html) [RegisterResponse](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.U2f.Commands.RegisterResponse.html) ### Input The hash of the origin (application ID) and the client data hash (containing the challenge). ### Output A byte array that contains the registration data. It is encoded as follows. 05 || public key || key handle length || key handle || cert || signature where the public key is an encoded P-256 ECC public key with both coordinates: 04 || x-coordinate || y-coordinate The cert is the attestation certificate, and the signature is an ECDSA signature formatted as the following DER/BER. 30 len 02 len rValue 02 len sValue ### APDU [Technical APDU Details](https://docs.yubico.com/yesdk/users-manual/application-u2f/apdu/register.html) * * * Authenticate ------------ Authenticate the YubiKey to the relying party. This is the command that will build the response to the relying party's authentication challenge. It will use the appropriate private key to sign the challenge data. ### Available All YubiKeys with the FIDO U2F application. ### SDK classes [AuthenticateCommand](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.U2f.Commands.AuthenticateCommand.html) [AuthenticateResponse](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.U2f.Commands.AuthenticateResponse.html) ### Input The hash of the origin (application ID), the client data hash (containing the challenge), and the key handle. ### Output A byte array that contains the authentication data. It is encoded as follows. user presence || counter || signature Where the user presence is one byte (true or false, 1 or 0) indicating whether the user's presence was verified, the counter is 4 bytes (big endian), and the signature is an ECDSA signature formatted as the following DER/BER. 30 len 02 len rValue 02 len sValue ### APDU [Technical APDU Details](https://docs.yubico.com/yesdk/users-manual/application-u2f/apdu/authenticate.html) * * * Reset ----- Reset the U2F application. This will replace the master key meaning any previous key handles will be lost with no way to recover them. If the YubiKey is FIPS, it will also take the YubiKey out of FIPS mode, remove the PIN requirement, and delete the attestation key and cert. The YubiKey will no longer be able to be set to FIPS mode again. ### Available All YubiKeys with the FIDO U2F application. ### SDK classes [ResetCommand](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.U2f.Commands.ResetCommand.html) [ResetResponse](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.U2f.Commands.ResetResponse.html) ### Input None. ### Output None. ### APDU [Technical APDU Details](https://docs.yubico.com/yesdk/users-manual/application-u2f/apdu/reset.html) [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-u2f/u2f-commands.md/#L1) --- # FIDO2 commands ##### Table of Contents FIDO2 commands ============== For each possible U2F command, there will be a class that knows how to build the command [APDU](https://docs.yubico.com/yesdk/users-manual/yubikey-reference/apdu.html) and parse the data in the response APDU. Each class will know what information is needed from the caller for that command. #### List of FIDO2 commands * [Version](https://docs.yubico.com/yesdk/users-manual/application-fido2/fido2-commands.html#get-version) * [Get Info](https://docs.yubico.com/yesdk/users-manual/application-fido2/fido2-commands.html#get-info) * [Get Key Agreement](https://docs.yubico.com/yesdk/users-manual/application-fido2/fido2-commands.html#get-key-agreement) (get a public key) * [Set PIN](https://docs.yubico.com/yesdk/users-manual/application-fido2/fido2-commands.html#set-pin) * [Change PIN](https://docs.yubico.com/yesdk/users-manual/application-fido2/fido2-commands.html#change-pin) * [Get PIN Token](https://docs.yubico.com/yesdk/users-manual/application-fido2/fido2-commands.html#get-pin-token) * [Get PIN/UV Auth Token Using PIN](https://docs.yubico.com/yesdk/users-manual/application-fido2/fido2-commands.html#pin-uv-auth-using-pin) * [Get PIN/UV Auth Token Using UV](https://docs.yubico.com/yesdk/users-manual/application-fido2/fido2-commands.html#pin-uv-auth-using-uv) * [Make credential](https://docs.yubico.com/yesdk/users-manual/application-fido2/fido2-commands.html#make-credential) * [Get Assertion](https://docs.yubico.com/yesdk/users-manual/application-fido2/fido2-commands.html#get-assertion) * [Get Next Assertion](https://docs.yubico.com/yesdk/users-manual/application-fido2/fido2-commands.html#get-next-assertion) * [Get Credential Metadata](https://docs.yubico.com/yesdk/users-manual/application-fido2/fido2-commands.html#get-credential-metadata) * [Enumerate RPs Begin](https://docs.yubico.com/yesdk/users-manual/application-fido2/fido2-commands.html#enumerate-rps-begin) * [Enumerate RPs Get Next RP](https://docs.yubico.com/yesdk/users-manual/application-fido2/fido2-commands.html#enumerate-rps-get-next-rp) * [Get Large Blob](https://docs.yubico.com/yesdk/users-manual/application-fido2/fido2-commands.html#get-large-blob) * [Set Large Blob](https://docs.yubico.com/yesdk/users-manual/application-fido2/fido2-commands.html#set-large-blob) * [Reset](https://docs.yubico.com/yesdk/users-manual/application-fido2/fido2-commands.html#reset) * * * Get version ----------- Get the YubiKey's version number. ### Available All YubiKeys with the FIDO2 application. ### SDK classes \--VersionCommand--xref:Yubico.YubiKey.Fido2.Commands.VersionCommand-- \--VersionResponse--xref:Yubico.YubiKey.Fido2.Commands.VersionResponse-- ### Input None. ### Output [FirmwareVersion](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.FirmwareVersion.html) ### APDU [Technical APDU Details](https://docs.yubico.com/yesdk/users-manual/application-fido2/apdu/version.html) * * * Get info -------- Get information about the YubiKey's FIDO2 application. ### Available All YubiKeys with the FIDO2 application. ### SDK classes [GetInfoCommand](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Commands.GetInfoCommand.html) [GetInfoResponse](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Commands.GetInfoResponse.html) ### Input None. ### Output [AuthenticatorInfo](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.AuthenticatorInfo.html) Also see the FIDO2 CTAP standard (CTAP 2.1), section 6.4 for a list of possible elements returned. The standard specifies 21 possible elements an authenticator can return from a GetInfo command. Most of the elements are optional, so that any one encoding may or may not have the same subset of possible key/value pairs. The YubiKey can return up to 20 of the defined elements. It will not return `vendorPrototypeConfigCommands`. ### APDU [Technical APDU Details](https://docs.yubico.com/yesdk/users-manual/application-fido2/apdu/get-info.html) * * * Get key agreement ----------------- Get the YubiKey's public key that will be used to perform key agreement. The shared secret result of key agreement will be used to derive a shared key used for PIN operations. ### Available All YubiKeys with the FIDO2 application. ### SDK classes [GetKeyAgreementCommand](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Commands.GetKeyAgreementCommand.html) [GetKeyAgreementResponse](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Commands.GetKeyAgreementResponse.html) ### Input [The PIN/UV Auth Protocol](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.PinProtocols.PinUvAuthProtocol.html) . ### Output [The FIDO2 COSE EC Public Key](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Cose.CoseEcPublicKey.html) ### APDU [Technical APDU Details](https://docs.yubico.com/yesdk/users-manual/application-fido2/apdu/get-key-agree.html) * * * Set PIN ------- Set the YubiKey's FIDO application to be PIN-protected. ### Available All YubiKeys with the FIDO2 application. ### SDK classes [SetPinCommand](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Commands.SetPinCommand.html) [SetPinResponse](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Commands.SetPinResponse.html) ### Input A [Protocol object](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.PinProtocols.PinUvAuthProtocolBase.html) and the PIN. ### Output None ### APDU [Technical APDU Details](https://docs.yubico.com/yesdk/users-manual/application-fido2/apdu/set-pin.html) * * * Change PIN ---------- Change the YubiKey's FIDO application's PIN. ### Available All YubiKeys with the FIDO2 application. ### SDK classes [ChangePinCommand](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Commands.ChangePinCommand.html) [ChangePinResponse](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Commands.ChangePinResponse.html) ### Input A [Protocol object](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.PinProtocols.PinUvAuthProtocolBase.html) , the current PIN and the new PIN. ### Output None ### APDU [Technical APDU Details](https://docs.yubico.com/yesdk/users-manual/application-fido2/apdu/change-pin.html) * * * Get PIN token ------------- Get a PIN token, which can be used in later operations such as Make Credential. There are actually three versions of "Get PIN Token": * getPinToken * getPinUvAuthTokenUsingPinWithPermissions * getPinUvAuthTokenUsingUvWithPermissions The SDK has three different command classes to call each of the three operations: * GetPinTokenCommand * [GetPinUvAuthTokenUsingPinCommand](https://docs.yubico.com/yesdk/users-manual/application-fido2/fido2-commands.html#pin-uv-auth-using-pin) * [GetPinUvAuthTokenUsingUvCommand](https://docs.yubico.com/yesdk/users-manual/application-fido2/fido2-commands.html#pin-uv-auth-using-uv) ### Available All YubiKeys with the FIDO2 application. ### SDK classes [GetPinTokenCommand](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Commands.GetPinTokenCommand.html) [GetPinUvAuthTokenResponse](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Commands.GetPinUvAuthTokenResponse.html) ### Input * [The PIN/UV Auth Protocol](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.PinProtocols.PinUvAuthProtocolBase.html) * [The PIN](https://docs.yubico.com/yesdk/users-manual/application-fido2/fido2-pin.html) ### Output The encrypted token as a byte array. ### APDU [Technical APDU Details](https://docs.yubico.com/yesdk/users-manual/application-fido2/apdu/get-pin-token.html) * * * Get PIN/UV Auth token using PIN ------------------------------- Get A PIN/UV Auth token, to be used in later operations such as Make Credential. There are actually three versions of "Get PIN Token": * getPinToken * getPinUvAuthTokenUsingPinWithPermissions * getPinUvAuthTokenUsingUvWithPermissions The SDK has three different command classes to call each of the three operations: * [GetPinTokenCommand](https://docs.yubico.com/yesdk/users-manual/application-fido2/fido2-commands.html#get-pin-token) * GetPinUvAuthTokenUsingPinCommand * [GetPinUvAuthTokenUsingUvCommand](https://docs.yubico.com/yesdk/users-manual/application-fido2/fido2-commands.html#pin-uv-auth-using-uv) ### Available All YubiKeys with the FIDO2 application. ### SDK classes [GetPinUvAuthTokenUsingPinCommand](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Commands.GetPinUvAuthTokenUsingPinCommand.html) [GetPinUvAuthTokenResponse](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Commands.GetPinUvAuthTokenResponse.html) ### Input * [The PIN/UV Auth Protocol](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.PinProtocols.PinUvAuthProtocolBase.html) * [The PIN](https://docs.yubico.com/yesdk/users-manual/application-fido2/fido2-pin.html) * A bit field listing the [permissions](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Commands.PinUvAuthTokenPermissions.html) * An optional relying party ID (`rpId`) ### Output The encrypted token as a byte array. ### APDU [Technical APDU Details](https://docs.yubico.com/yesdk/users-manual/application-fido2/apdu/get-auth-token-using-pin.html) * * * Get PIN/UV Auth token using user verification (UV) -------------------------------------------------- Get A PIN/UV Auth token, to be used in later operations such as Make Credential. There are actually three versions of "Get PIN Token": * getPinToken * getPinUvAuthTokenUsingPinWithPermissions * getPinUvAuthTokenUsingUvWithPermissions The SDK has three different command classes to call each of the three operations: * [GetPinTokenCommand](https://docs.yubico.com/yesdk/users-manual/application-fido2/fido2-commands.html#get-pin-token) * [GetPinUvAuthTokenUsingPinCommand](https://docs.yubico.com/yesdk/users-manual/application-fido2/fido2-commands.html#pin-uv-auth-using-pin) * GetPinUvAuthTokenUsingUvCommand ### Available All YubiKeys with the FIDO2 application. ### SDK classes [GetPinUvAuthTokenUsingUvCommand](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Commands.GetPinUvAuthTokenUsingUvCommand.html) [GetPinUvAuthTokenResponse](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Commands.GetPinUvAuthTokenResponse.html) ### Input * [The PIN/UV Auth Protocol](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.PinProtocols.PinUvAuthProtocolBase.html) * A bit field listing the [permissions](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Commands.PinUvAuthTokenPermissions.html) * An optional relying party ID (`rpId`) ### Output The encrypted token as a byte array. ### APDU [Technical APDU Details](https://docs.yubico.com/yesdk/users-manual/application-fido2/apdu/get-auth-token-using-uv.html) * * * Make credential --------------- Make a credential for a relying party. ### Available All YubiKeys with the FIDO2 application. ### SDK classes [MakeCredentialCommand](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Commands.MakeCredentialCommand.html) [MakeCredentialResponse](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Commands.MakeCredentialResponse.html) ### Input The `authenticatorMakeCredential` parameters specified in section 6.1 of the FIDO2 specifications. ### Output The credential (public key) and other information. [MakeCredentialData](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.MakeCredentialData.html) ### APDU [Technical APDU Details](https://docs.yubico.com/yesdk/users-manual/application-fido2/apdu/make-credential.html) * * * Get assertion ------------- Get an assertion (credential) that will be verified by a relying party. ### Available All YubiKeys with the FIDO2 application. ### SDK classes [GetAssertionCommand](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Commands.GetAssertionCommand.html) [GetAssertionResponse](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Commands.GetAssertionResponse.html) ### Input The `authenticatorGetAssertion` parameters specified in section 6.2 of the FIDO2 specifications. [GetAssertionParameters](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.GetAssertionParameters.html) ### Output The credential, along with other information. [GetAssertionData](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.GetAssertionData.html) ### APDU [Technical APDU Details](https://docs.yubico.com/yesdk/users-manual/application-fido2/apdu/get-assertion.html) * * * Get next assertion ------------------ Get the next assertion (credential) associated with the relying party specified in a previous call to \[Get Assertion\])(get-assertion). ### Available All YubiKeys with the FIDO2 application. ### SDK classes [GetNextAssertionCommand](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Commands.GetNextAssertionCommand.html) [GetAssertionResponse](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Commands.GetAssertionResponse.html) Note that the response to `GetNextAssertion` is the same as the response to `GetAssertion`. ### Input None. ### Output The credential, along with other information. [GetAssertionData](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.GetAssertionData.html) ### APDU [Technical APDU Details](https://docs.yubico.com/yesdk/users-manual/application-fido2/apdu/get-next-assertion.html) * * * Get credential metadata ----------------------- Get information about the credentials on the YubiKey. This is one of the subcommands of the `authenticatorCredentialManagement` command. Not all YubiKeys support credential management. If you send this command to a YubiKey that does not support it, the response will be "Unsupported option". ### Available All YubiKeys with the FIDO2 application. ### SDK classes [GetCredentialMetadataCommand](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Commands.GetCredentialMetadataCommand.html) [GetCredentialMetadataResponse](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Commands.GetCredentialMetadataResponse.html) ### Input A PIN/UV auth token (built using the "cm" permission), and the protocol used to build the token. ### Output The number of existing discoverable credentials on the YubiKey, and the maximum number of additional credentials the YubiKey can store. The data is returned in the form of a Tuple of two integers. ### APDU [Technical APDU Details](https://docs.yubico.com/yesdk/users-manual/application-fido2/apdu/get-cred-metadata.html) * * * Enumerate RPs begin ------------------- Get the total number of RPs that can be found along with information about the first relying party (RP) represented by the credentials on the YubiKey . This is one of the subcommands of the `authenticatorCredentialManagement` command. Not all YubiKeys support credential management. If you send this command to a YubiKey that does not support it, the response will be "Unsupported option". ### Available All YubiKeys with the FIDO2 application. ### SDK classes [EnumerateRpsBeginCommand](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Commands.EnumerateRpsBeginCommand.html) [EnumerateRpsBeginResponse](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Commands.EnumerateRpsBeginResponse.html) ### Input A PIN/UV auth token (built using the "cm" permission), and the protocol used to build the token. ### Output Information about the first RP on the YubiKey, and the total number of RPs represented. The data is returned in the form of a Tuple consisting of an integer and a RelyingParty object. ### APDU [Technical APDU Details](https://docs.yubico.com/yesdk/users-manual/application-fido2/apdu/enum-rps-begin.html) * * * Enumerate RPs get next RP ------------------------- Get information about the next relying party (RP) represented by the credentials on the YubiKey. This is one of the subcommands of the `authenticatorCredentialManagement` command. Not all YubiKeys support credential management. If you send this command to a YubiKey that does not support it, the response will be "Unsupported option". ### Available All YubiKeys with the FIDO2 application. ### SDK classes [EnumerateRpsGetNextCommand](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Commands.EnumerateRpsGetNextCommand.html) [EnumerateRpsGetNextResponse](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Commands.EnumerateRpsGetNextResponse.html) ### Input none (but this command must follow the EnumerateRpsBeginCommand) ### Output The next RP on the YubiKey. The call to `EnumerateRpsBeginCommand` returned the first RP. If there are more RPs, each successive call to `EnumerateRpsGetNextCommand` returns the next one. The data is returned in the form of a [RelyingParty](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.RelyingParty.html) object. ### APDU [Technical APDU Details](https://docs.yubico.com/yesdk/users-manual/application-fido2/apdu/enum-rps-next.html) * * * Get large blob -------------- Get the large blob data out of the YubiKey. This command gets the raw data, it does not perform any parsing or decoding. Not all YubiKeys support large blobs. If you send this command to a YubiKey that does not support it, the response will be "Unsupported extension". ### Available All YubiKeys with the FIDO2 application. ### SDK classes [GetLargeBlobCommand](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Commands.GetLargeBlobCommand.html) [GetLargeBlobResponse](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Commands.GetLargeBlobResponse.html) ### Input offset and count Because a large blob can be bigger than the maximum message length, it is possible retrieving the entire data will require more than one call. The offset specifies the offset in the large blob data on the YubiKey where the returned data should begin. The first call specifies an offset of zero, and each subsequent call specifies an offset of the total number of bytes returned so far by each previous call. The count is the number of bytes requested this call. This value must be less than or equal to the "maximum fragment length". There is a maximum message size (specified by the YubiKey and found in the `AuthenticatorInfo`) and the `MaxFragmentLength` is the `MaxMessageSize - 64`. ### Output The bytes the YubiKey was able to return. This is in the form of a `ReadOnlyMemory`. If the number of bytes returned is less than the count given, then there are no more bytes to return. If the number is equal to the count, there could be more bytes on the YubiKey, and the caller should send another command. ### APDU [Technical APDU Details](https://docs.yubico.com/yesdk/users-manual/application-fido2/apdu/get-large-blob.html) * * * Set large blob -------------- Store large blob data on the YubiKey. This command stores the data given, it does not perform any encoding. This replaces any data currently in the large blob storage area on the YubiKey. Not all YubiKeys support large blobs. If you send this command to a YubiKey that does not support it, the response will be "Unsupported extension". ### Available All YubiKeys with the FIDO2 application. ### SDK classes [SetLargeBlobCommand](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Commands.SetLargeBlobCommand.html) [SetLargeBlobResponse](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Commands.SetLargeBlobResponse.html) ### Input data to store, offset, count, PinUvAuthParam, PinProtocol Because a large blob can be bigger than the maximum message length, it is possible storing the entire data will require more than one call. The offset specifies the offset in the large blob data on the YubiKey where the input data should be stored. The first call specifies an offset of zero, and each subsequent call specifies an offset of the total number of bytes stored so far by each previous call. The count is the total number of bytes that will be stored. That is, it is the sum of all the lengths of bytes stored by each call. The first time the set command is called, the offset is zero and the count is the total number of bytes. Each subsequent call the offset is where the previous call left off and the count is ignored. Each block of input must be less than or equal to `maxFragmentLength` bytes (`MaxMessageSize - 64`). The caller need authorization to store, and obtains that by generating a PinUvAuthParam. ### Output None ### APDU [Technical APDU Details](https://docs.yubico.com/yesdk/users-manual/application-fido2/apdu/set-large-blob.html) * * * Reset ----- Reset the FIDO2 application on a YubiKey. This will delete all existing FIDO2 keys and credentials, and remove the PIN. It is not sufficient to simply execute this command in order to reset, it must be done within a time limit of inserting a YubiKey and must be accompanied by a proof of user presence (touch). ### Available All YubiKeys with the FIDO2 application. ##### Note The FIDO2 ResetCommand can be used with YubiKey Bio Multi-protocol Edition keys _only if_ the FIDO application is not "blocked" (check the key's [ResetBlocked](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.YubiKeyDevice.html#Yubico_YubiKey_YubiKeyDevice_ResetBlocked) property to confirm). Otherwise, the [device-wide reset](https://docs.yubico.com/yesdk/users-manual/sdk-programming-guide/bio-mpe.html#resetting-a-yubikey-bio-mpe) must be used instead. ### SDK classes [ResetCommand](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Commands.ResetCommand.html) [ResetResponse](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Fido2.Commands.ResetResponse.html) ### Input None. ### Output None ### APDU [Technical APDU Details](https://docs.yubico.com/yesdk/users-manual/application-fido2/apdu/reset.html) * * * [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-fido2/fido2-commands.md/#L1) --- # PIV commands ##### Table of Contents PIV commands ============ For each possible PIV command, there will be a class that knows how to build the command [APDU](https://docs.yubico.com/yesdk/users-manual/yubikey-reference/apdu.html) and parse the data in the response APDU. Each class will know what information is needed from the caller for that command. According to the PIV standard, there is "Off-Card" and "On-Card". The off-card application is the one calling the YubiKey. The keys, data, and firmware running on the YubiKey is "on-card" #### List of PIV commands * [Get the serial number](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#get-the-serial-number) * [Get the firmware version number](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#get-the-firmware-version-number) * [Get metadata](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#get-metadata) * [Get Bio metadata](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#get-bio-metadata) * [Verify the PIN](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#verify) * [Biometric verification](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#biometric-verification) * [Authenticate: management key](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#authenticate-management-key) * [Set PIN retries](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#set-pin-retries) * [Change reference data](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#change-reference-data) (change the PIN or PUK) * [Set the management key](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#set-management-key) (change the management key) * [Reset retry](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#reset-retry-recover-the-pin) (recover the PIN) * [Generate asymmetric key pair](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#generate-asymmetric) * [Import asymmetric](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#import-asymmetric) (import a private key) * [Authenticate: sign](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#authenticate-sign) * [Authenticate: decrypt](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#authenticate-decrypt) * [Authenticate: key agreement](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#authenticate-key-agreement) * [Create attestation statement](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#create-attestation-statement) * [Get data](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#get-data) * [Put data](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#put-data) * [Reset](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#reset-the-piv-application) * * * Get the serial number --------------------- This gets the YubiKey's serial number. ### Available YubiKey 5 and later. ### SDK Classes [GetSerialNumberCommand](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.Commands.GetSerialNumberCommand.html) [GetSerialNumberResponse](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.Commands.GetSerialNumberResponse.html) ### Input None. ### Output `int` To see the serial number as a decimal string, use `ToString()`. For example, int serialNumber = serialResponse.GetData(); string decimalSerial = serialNumber.GetString(); string hexSerial = serialNumber.GetString("X"); // Print out the decimalSerial to get something like "11409355" // Print out the hexSerial to get something like "00AE17CB" ### APDU [Technical APDU Details](https://docs.yubico.com/yesdk/users-manual/application-piv/apdu/serial.html) * * * Get the firmware version number ------------------------------- This gets the YubiKey firmware version number. ### Available All YubiKeys with the PIV application. ### SDK Classes [VersionCommand](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.Commands.VersionCommand.html) [VersionResponse](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.Commands.VersionResponse.html) ### Input None. ### Output [FirmwareVersion](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.FirmwareVersion.html) ### APDU [Technical APDU Details](https://docs.yubico.com/yesdk/users-manual/application-piv/apdu/version.html) * * * Get metadata ------------ This gets information about the key in a particular slot. It is possible to get metadata about public/private key pairs in those slots that hold private keys. It is also possible to get metadata about the symmetric key that is the management key in slot 9B. Finally, it is possible to get metadata about the PIN and PUK, accessed by slots 80 and 81. There are six possible information elements (described below), but not all keys will report all six elements. Furthermore, if there is no key in a particular slot, there will be no metadata to get. That is, if you execute the Get Metadata command for a slot that has no key, the data retrieved will be "None" or "NoKey". ### Available YubiKey 5.3 and later. ### SDK Classes [GetMetadataCommand](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.Commands.GetMetadataCommand.html) [GetMetadataResponse](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.Commands.GetMetadataResponse.html) ### Input Slot number. See the User's Manual [entry on PIV slots](https://docs.yubico.com/yesdk/users-manual/application-piv/slots.html) and the enum [PivSlot](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.PivSlot.html) for information on the valid PIV slots. ### Output #### Table 1: List of Metadata Elements | Name | Meaning | Data | Slots | | --- | --- | --- | --- | | Algorithm | Algorithm of the key | PIN, PUK, Triple DES, AES-128, AES-192, AES-256,
RSA-1024, RSA-2048, RSA 3072, RSA 4096, ECC-P256, or ECC-P384 | all slots | | Policy | PIN and touch policy | PIN: Default, Never, Once, Always
Touch: Default, Never, Always, Cached | 9A, 9B, 9C, 9D, 9E, F9, 82 - 95 | | Origin | Imported or generated | imported/generated | 9A, 9C, 9D, 9E, F9, 82 - 95 | | Public | Pub key partner to the pri key | DER encoding of public key | 9A, 9C, 9D, 9E, F9, 82 - 95 | | Default | Whether PIN/PUK/Mgmt Key has default value | Default or Not Default | 80, 81, 9B | | Retries | Retry count and retries remaining | two numbers | 80, 81 | Another way to look at what is returned is the following table that lists which data elements are returned for each slot. #### Table 2: List of PIV slots and the metadata elements returned | Slot Number (hex) | Key | Data returned | | --- | --- | --- | | 80 | PIN | Algorithm, Default, Retries | | 81 | PUK | Algorithm, Default, Retries | | 9B | Management | Algorithm, Policy, Default | | 82, 83, ..., 95 (20 slots) | Retired Keys | Algorithm, Policy, Origin, Public | | 9A | Authentication | Algorithm, Policy, Origin, Public | | 9C | Signing | Algorithm, Policy, Origin, Public | | 9D | Key Management | Algorithm, Policy, Origin, Public | | 9E | Card Authentication | Algorithm, Policy, Origin, Public | | F9 | Attestation | Algorithm, Policy, Origin, Public | ### APDU [Technical APDU Details](https://docs.yubico.com/yesdk/users-manual/application-piv/apdu/metadata.html) * * * Get Bio metadata ---------------- This gets YubiKey's biometric metadata. ### Available YubiKey Bio Multi-protocol 5.6 and later. ### SDK Classes [GetBioMetadataCommand](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.Commands.GetBioMetadataCommand.html) [GetBioMetadataResponse](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.Commands.GetBioMetadataResponse.html) ### Output #### Table 1: List of Metadata Elements | Name | Meaning | Data | | --- | --- | --- | | IsConfigured | Whether the device is configured for biometric verification | bool | | RetriesRemaining | Number of remaining retries for biometric verification | integer; zero value means the biometric verification is blocked | | HasTemporaryPin | Whether a temporary PIN is generated | bool | ### APDU [Technical APDU Details](https://docs.yubico.com/yesdk/users-manual/application-piv/apdu/bio-metadata.html) * * * Verify ------ Verify a PIN. This is generally used in conjunction with other commands that require PIN entry to work. For example, to sign data using one of the PIV private keys, it is possible the PIN is needed. Use this command to enter the PIN, and if the operation is a success, execute the sign command. A YubiKey will allow "retry count" incorrect PIN verification attempts in a row, before it blocks the PIN. For example, suppose the retry count is three. That means if you call Verify with an incorrect PIN three times in a row, the PIN will be blocked. Any attempt thereafter to verify the PIN will fail, so any operation that requires the PIN will not run. There is a "retry count" and a "remaining count". The retry count is the number of tries the YubiKey will allow before locking the PIV application. The remaining count is the current number of tries still left. Note that when a PIV PIN is blocked, it is only the PIV application that will be unusable. This has no effect on the other applications. For example, suppose the program sets the retry count to 5. At that point, both the retry and remaining count are 5. Now suppose someone tries to verify the PIN with the wrong value. The remaining count drops to 4. The retry count is still 5, but at the moment there are only 4 tries left before the PIN will be blocked. If you call Verify with the incorrect PIN, the result will include the remaining count. Once you call Verify with the correct PIN, the remaining count is reset to the retry count. Note that if the remaining count is more than 15, and the wrong PIN is given, the response to the Verify command will indicate 15 retries remaining. This is because the YubiKey has only 4 bits in its response to return the remaining retry count. The default retry count is three, but you can change that using the [Set PIN retries](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#set-pin-retries) command. The retry count can be a value from 1 to 255. You can also get the PIN retry numbers (retry count and remaining count) using the [Get metadata](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#get-metadata) command (valid on YubiKeys 5.3 and later). It is possible that the remaining count is 0 before calling the verify PIN command. This means the PIN has been blocked. If you call verify PIN again, even with the correct PIN, the result will be `false` and the remaining count will remain 0. If a PIN is blocked, it is possible to unblock it using the [Reset Retry](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#reset-retry-recover-the-pin) command. If the PUK is blocked as well, the only recovery is to [Reset the PIV application](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#reset-the-piv-application) . ### Available All YubiKeys with the PIV application. ### SDK Classes [VerifyPinCommand](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.Commands.VerifyPinCommand.html) [VerifyPinResponse](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.Commands.VerifyPinResponse.html) ### Input The PIN to verify. It is six, seven, or eight characters (bytes) long. ### Output An `int?`. If the PIN verifies, this will be NULL, if it did not verify, this will be the remaining count (number of retries left before the PIN is blocked). If the PIN is correct, there will be no remaining count (it will be null), and the `Status` property will be `Success`. If the PIN is not correct, the `int` returned will be the remaining count and the `Status` property will be `AuthenticationRequired`. An incorrect PIN is not an (exception-throwing) error. This Command determines if a PIN is correct or not, and if a PIN is incorrect, the command performed its task. Each time an incorrect PIN is entered, the remaining count is decremented. Once the correct PIN has been entered, the remaining count is restored to the full retry count. See also [Set PIN retries](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#set-pin-retries) . Note that it is possible to have an error (such as malformed input data), and the PIN could not be verified. In this situation the `Status` will be set to the appropriate value and `GetData` will throw an exception. ### APDU [Technical APDU Details](https://docs.yubico.com/yesdk/users-manual/application-piv/apdu/verify.html) * * * Biometric verification ---------------------- With biometric verification, users can authenticate the PIV session with a successful match of a fingerprint. To execute biometric verification, the YubiKey must have biometrics configured and enabled. Clients can verify these conditions by reading the properties of biometric metadata (see [Get Bio metadata](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#get-bio-metadata) ). The YubiKey keeps track of failed biometric matches and will block biometric authentication if there are more than three such failures. In that case, the client should use the [PIV PIN verification](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#verify) as soon as possible. The number of remaining biometric verification attempts is returned in the command response's `AttemptsRemaining` property. The value is present only after a failed match. Clients can also request to generate a temporary PIN, which can be used with the `VerifyTemporaryPinCommand` for authentication without the need of a biometric match. The temporary PIN is stored in YubiKey's RAM and is invalidated after the PIV session is closed or an invalid temporary PIN is used. For `PIN_OR_MATCH_ALWAYS` slot policy, the temporary PIN can be used only once. ### Available YubiKey Bio Multi-Protocol keys. ### SDK Classes [VerifyUvCommand](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.Commands.VerifyUvCommand.html) [VerifyUvResponse](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.Commands.VerifyUvResponse.html) [VerifyTemporaryPinCommand](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.Commands.VerifyTemporaryPinCommand.html) [VerifyTemporaryPinResponse](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.Commands.VerifyTemporaryPinResponse.html) ### Input #### VerifyUvCommand Two boolean values: * **request temporary PIN** - if true, the YubiKey will wait for the user to perform biometric verification (match an enrolled fingerprint) and, if verification is successful, generate a temporary PIN. * **check only** - when true, the YubiKey verifies internally that the biometric state is valid. No biometric verification is performed on the YubiKey. A client application would typically call the command with `false`, `false` parameters - this will make the YubiKey request the biometric verification from the users. #### VerifyTemporaryPinCommand The temporary PIN is the only parameter. ### Output #### VerifyUvResponse If a temporary PIN was requested and the status is Success, the returned value is the temporary PIN. In case of failure (for example, the fingerprint did not match), the clients should read the `AttemptsRemaining` property, which contains the number of remaining biometric attempts. #### VerifyTemporaryPinResponse No output. The Status will be Success if the temporary PIN was verified. ### APDU [Technical APDU Details for VerifyUvCommand](https://docs.yubico.com/yesdk/users-manual/application-piv/apdu/verify-uv.html) [Technical APDU Details for VerifyTemporaryPinCommand](https://docs.yubico.com/yesdk/users-manual/application-piv/apdu/verify-temporary-pin.html) * * * Authenticate: management key ---------------------------- The Authenticate command can be used to perform several cryptographic operations: * Authenticate the Management Key to the YubiKey * Sign data using a private key * Decrypt data using a private key * Perform key agreement using a private key This section discusses authenticating the management key. See [Authenticate: sign](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#authenticate-sign) , [Authenticate: decrypt](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#authenticate-decrypt) , and [Authenticate: key agreement](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#authenticate-key-agreement) for information on signing, decrypting, and key agreement. The primary purpose of this command is to authenticate the client application (off-card application) to the YubiKey. That is, before the YubiKey is able to perform some operations, it must know that the caller has access to the management key. This section will refer to this action as **Client Authentication**. It is also possible to authenticate the YubiKey to the client application, so that the app knows it is communicating with the appropriate YubiKey. Maybe the app wants to be sure it will not call on an attacker's YubiKey to perform a sensitive operation. This section will refer to this action as **YubiKey Authentication**. Hence, the authenticate management key command can actually perform two different operations: "single authentication" (Client Authentication only), or "mutual authentication" (Client Authentication and YubiKey Authentication). How you call the API determines which operation will be performed. The authentication is done using "challenge-response". Note that the word "response" is used in "Response APDU" and "Response Class". So to avoid ambiguity, these are the terms we will use in this section. * Response APDU * Response Class or Response Object (e.g. InitializeAuthenticateManagementKeyResponse is a Response Class and an instantiation of that class is a Response Object) * Client Authentication Challenge/Response (the Challenge-Response pair associated with Client Authentication) * YubiKey Authentication Challenge/Response (the Challenge-Response pair associated with YubiKey Authenticaiton) The process is the following: | Single Authentication | | | --- | --- | | **Client (Off-Card) Application** | **YubiKey** | | _Step 1_ | | | Initiate the process (single auth) | | | | Generate random Client Authentication Challenge | | _Step 2_ | | | Compute the Client Authentication Response based on Client Authentication Challenge | | | | Verify the Client Authentication Response | | | Return `Success` or `AuthenticationRequired` | | | | | **Mutual Authentication** | | | **Client (Off-Card) Application** | **YubiKey** | | _Step 1_ | | | Initiate the process (mutual auth) | | | | Generate random Client Authentication Challenge | | _Step 2_ | | | Compute the Client Authentication Response based on Client Authentication Challenge | | | Generate random YubiKey Authentication Challenge | | | | Verify the Client Authentication Response | | | Compute the YubiKey Authentication Response based on YubiKey Authentication Challenge | | | Return `Success` or `AuthenticationRequired`
along with YubiKey Authentication Response | | _Step 3_ | | | Verify the YubiKey Authentication Response | | ### Available All YubiKeys with the PIV application. Beginning with YubiKey 5.4.2, the management key can be an AES key. ### SDK Classes [InitializeAuthenticateManagementKeyCommand](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.Commands.InitializeAuthenticateManagementKeyCommand.html) [InitializeAuthenticateManagementKeyResponse](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.Commands.InitializeAuthenticateManagementKeyResponse.html) [CompleteAuthenticateManagementKeyCommand](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.Commands.CompleteAuthenticateManagementKeyCommand.html) [CompleteAuthenticateManagementKeyResponse](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.Commands.CompleteAuthenticateManagementKeyResponse.html) ### Input Authenticating with the management key requires two calls (send two APDUs). It will be a challenge-response process. The first call will take the algorithm, the second will take in the response APDU from the first call, the management key, and the algorithm. ### Output The output of the YubiKey depends on whether the process is single or mutual authentication, and step 1 or step 2. * Single Auth, Step 1: output is Client Authentication Challenge * Single Auth, Step 2: output is the result of verifying the Client Authentication Response * Mutual Auth, Step 1: output is Client Authentication Challenge * Mutual Auth, Step 2: output is YubiKey Authentication Response (to be verified by the client (off-card) application) and the result of Client Authentication The output of the Response classes is the following. * Single Auth, Step 1: output is Client Authentication Challenge * Single Auth, Step 2: output is the result of verifying the Client Authentication Response * Mutual Auth, Step 1: output is Client Authentication Challenge * Mutual Auth, Step 2: output is the result of Client Authentication, and, if Client Authentication was successful, YubiKey Authentication Response The process is explained in the documentation for [CompleteAuthenticateManagementKeyCommand](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.Commands.CompleteAuthenticateManagementKeyCommand.html) ### APDU [Technical APDU Details](https://docs.yubico.com/yesdk/users-manual/application-piv/apdu/auth-mgmt.html) * * * Set PIN retries --------------- Set the number of PIN retries allowed before the PIN and PUK are blocked. The default is three. Note that this command will set the retry count for both the PIN and PUK. If you want to set the retry count for only one entity, you must still set the retry count for the other. Note also that this will reset the PIN and PUK to the default values. For example, current PIN: 7777777 retry count: 3 current PUK: 88888888 retry count: 3 Call this command to set the PIN retry count to 5 and the PUK retry count to 2. After successful completion of the command, the PIN and PUK are the following. current PIN: 123456 retry count: 5 current PUK: 12345678 retry count: 2 If you don't want to leave the PIN and PUK as the default values, follow this command with the [Change reference data](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#change-reference-data) command. Before the YubiKey can set the PIN retries, the caller must have authenticated the management key and verified the PIN. See the User's Manual [entry on PIV commands access control](https://docs.yubico.com/yesdk/users-manual/application-piv/access-control.html) for information on how to authenticate with the management key and/or PIN for commands. See also the sections in this page on [Authenticate: management key](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#authenticate-management-key) and [Verify the PIN](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#verify) . ### Available All YubiKeys with the PIV application. ### SDK Classes [SetPinRetriesCommand](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.Commands.SetPinRetriesCommand.html) [SetPinRetriesResponse](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.Commands.SetPinRetriesResponse.html) ### Input The management key, and the number of retries for the PIN and the number of retries for the PUK. ### Output There is no data output, only the status. If the command was not successful, it will almost certainly be because the management key or PIN supplied was not correct. This command will return an error indicating authentication is required. But it will not report which element (management key or PIN) was incorrect. Generally you will not call this command until you have successfully authenticated the management key and verified the PIN. ### APDU [Technical APDU Details](https://docs.yubico.com/yesdk/users-manual/application-piv/apdu/set-pin-retries.html) * * * Change Reference Data --------------------- Change a PIN or PUK (PIN Unblocking Key). The term "reference data" in this case refers to the "authentication data". According to NIST 800-73, there are three possible reference data elements that can be changed using this command: * Global PIN * PIV PIN * PUK However, the YubiKey does not have a global PIN. Hence, the SDK will only support changing the PIV PIN and PUK using this command. To change reference data, supply the current value and the new value. For example, to change the PIN, provide the current PIN and the new PIN. If the current PIN provided is not correct, the PIN will not be changed. A YubiKey will allow "retry count" incorrect PIN verification attempts in a row, before it blocks the PIN. For example, suppose the retry count is three. That means if you call change reference data with an incorrect PIN three times in a row, the PIN will be blocked. Any attempt thereafter to verify the PIN will fail, so the change reference data command will fail. If you call change reference data with the incorrect PIN or PUK, the result will include the remaining count (the number of retries left before it is blocked). Once you call change reference data with the correct PIN or PUK, the remaining count is reset to the full retry count. For example, suppose the retry count is 5, and no invalid PINs have been tried. Now if you call change reference data with the wrong PIN, the remaining count is 4 (the retry count is still 5). Call change reference data with the correct PIN and the remaining count is 5 again. Note that if the remaining count is more than 15, and the wrong PIN or PUK is given, the response to the change reference data command will indicate 15 retries remaining. This is because the YubiKey has only 4 bits in its response to return the remaining count. The default retry count is three, but you can change that using the [Set PIN retries](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#set-pin-retries) command. The retry count can be a value from 1 to 255. You can also get the PIN retry numbers (total count and current remaining) using the [Get metadata](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#get-metadata) command (valid on YubiKeys 5.3 and later). It is possible that the remaining count is 0 before calling the change reference data command. This means the PIN or PUK has been blocked. If you call change reference data again, even with the correct PIN or PUK, the result will be `false` and the remaining count will remain 0. If a PIN is blocked, it is possible to unblock it using the [Reset Retry](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#reset-retry-recover-the-pin) command. If the PUK is blocked as well, the only recovery is to [Reset the PIV application](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#reset-the-piv-application) . ### Available All YubiKeys with the PIV application. ##### Note YubiKey Bio Multi-protocol Edition (MPE) keys [do not have a PUK](https://docs.yubico.com/yesdk/users-manual/sdk-programming-guide/bio-mpe.html) . ### SDK Classes [ChangeReferenceDataCommand](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.Commands.ChangeReferenceDataCommand.html) [ChangeReferenceDataResponse](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.Commands.ChangeReferenceDataResponse.html) ### Input Which reference data element to change (PIN or PUK), the current reference value, and the new value. Both the PIN and the PUK are allowed to be 6 to 8 characters. The PIN can be composed of any ASCII character, but PUK composition depends on the key's firmware. For YubiKeys with firmware versions prior to 5.7, the PUK is allowed to be any character in the `0x00` - `0xFF` range. For YubiKeys with firmware version 5.7 and above, the PUK is allowed to be any character in the `0x00` - `0x7F` range. ### Output An `int?`. If the PIN or PUK was successfully changed, this will be NULL, if the correct, current PIN or PUK was not supplied, this will be the remaining count (the number of retries before the PIN or PUK is blocked). If the current reference data supplied is correct, there will be no remaining count (the return will be null), and the `Status` property will be `Success`, If the current reference data supplied is not correct, the `int` returned will be the remaining count and the `Status` property will be `AuthenticationRequired`. An incorrect PIN/PUK is not an (exception-throwing) error. This Command determines if a PIN/PUK is correct or not, and if it is correct, changes to the new value. If the PIN/PUK is incorrect, the command will return that information, so it has performed its task. Note that it is possible to have an error (such as malformed input data), and the operation could not be performed. The `Status` property in the Response object will be `Failed`. ### APDU [Technical APDU Details](https://docs.yubico.com/yesdk/users-manual/application-piv/apdu/change-ref.html) * * * Set management key ------------------ Set the management key to a new value. The YubiKey is manufactured with a default PIV management key: `hex 010203040506070801020304050607080102030405060708` (`0102030405060708` three times). If you want to change to a different key, use this command. You can also set the management key to a newer value after changing it from the default. You can use this to change the PIN and touch policies as well. If you supply the same key as before, just new PIN and/or touch policies, this will leave the key the same and change only the PIN and touch policies. Before the YubiKey can set the management key, the caller must have authenticated the current management key. See the User's Manual entry on [PIV commands access control](https://docs.yubico.com/yesdk/users-manual/application-piv/access-control.html) for information on how to authenticate with the management key for commands. See also the section in this page on [Authenticate: management key](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#authenticate-management-key) . ### Available All YubiKeys with the PIV application, although require touch is available on only 4 and 5. Beginning with YubiKey 5.4.2, the management key can be an AES key. ### SDK Classes [SetManagementKeyCommand](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.Commands.SetManagementKeyCommand.html) [SetManagementKeyResponse](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.Commands.SetManagementKeyResponse.html) ### Input The new key, a touch policy, and the algorithm. This command must be used in conjunction with the Authenticate command. See ["Authenticate: Management Key"](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#authenticate-management-key) . For YubiKeys prior to 5.4.2, the new key must be a Triple-DES key. Beginning with 5.4.2, the managment key can be AES. If the key is Triple-DES, the new key must be 24 bytes, no more, no less. If the key is AES-128, the new key must be 16 bytes, if AES-192, 24 bytes, and if AES-256, 32 bytes. The touch policy is one of three values: always, cached, or never. ### Output There is no data output, only the status. If the command was not successful, it will almost certainly be because the current management key was not authenticated. This command will return an error indicating authentication is required. Generally you will not call this command until you have successfully authenticated the management key. ### APDU [Technical APDU Details](https://docs.yubico.com/yesdk/users-manual/application-piv/apdu/set-mgmt-key.html) * * * Reset Retry (Recover the PIN) ----------------------------- Reset the PIN. This is the command to recover the PIN, using the PUK (PIN Unblocking Key), if the PIN has been lost (the user forgot the PIN). This is similar to the [Change Reference Data](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#change-reference-data) command. That command can change the PIN if the current PIN is known. This command can change the PIN (or reset it) if the current PIN is unknown, but the PUK is known. This can be run no matter what the remaining count of the PIN is. If you call reset retry with the incorrect PUK, the result will include the PUK's remaining count (the number of retries left before it is blocked). Once you call reset retry with the correct PUK, the remaining count is reset to its full retry count. For example, suppose the retry count is 5, and no invalid PUKs have been tried. Now if you call reset retry with the wrong PUK, the retry count is still 5, but the remaining count is 4. Call reset retry with the correct PUK and the retry count is still 5, and the remaining count is 5 again. Note that if the remaining count is more than 15, and the wrong PUK is given, the response to the reset retry command will indicate 15 retries remaining. This is because the YubiKey has only 4 bits in its response to return the remaining count. The default retry count is three, but you can change that using the [Set PIN retries](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#set-pin-retries) command. The retry count can be a value from 1 to 255. You can also get the PUK retry numbers (total count and current remaining) using the [Get metadata](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#get-metadata) command (valid on YubiKeys 5.3 and later). It is possible that the remaining count is 0 before calling the reset retry command. This means the PUK has been blocked. If you call reset retry again, even with the correct PUK, the result will be `false` and the remaining count will remain 0. If the PUK is blocked, the only recovery is to [Reset the PIV application](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#reset-the-piv-application) . ### Available All YubiKeys with the PIV application except for YubiKey Bio Multi-protocol Edition (MPE) keys, which [do not have a PUK](https://docs.yubico.com/yesdk/users-manual/sdk-programming-guide/bio-mpe.html) . ### SDK Classes [ResetRetryCommand](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.Commands.ResetRetryCommand.html) [ResetRetryResponse](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.Commands.ResetRetryResponse.html) ### Input The PUK and the new PIN. ### Output An `int?`. If the PUK is correct, the PIN will be changed and this will be NULL. If the PIN was not changed, it will be the remaining count. If the current reference data supplied is correct, there will be no remaining count (the return will be null), and the `Status` property will be `Success`, If the PUK supplied is not correct, the `int` returned will be the remaining count and the `Status` property will be `AuthenticationRequired`. An incorrect PUK is not an (exception-throwing) error. This Command determines if a PUK is correct or not, and if it is correct, changes the PIN to the new value. If the PUK is incorrect, the command performed its task. Each time an incorrect PUK is entered, the PUK's remaining count is decremented. Once the correct PUK has been entered, the remaining count is restored to the full retry count. See also [Set PIN retries](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#set-pin-retries) . Note that it is possible to have an error (such as malformed input data), and the operation could not be performed. The `Status` property in the Response object will be `Failed`. ### APDU [Technical APDU Details](https://docs.yubico.com/yesdk/users-manual/application-piv/apdu/reset-retry.html) * * * Generate Asymmetric ------------------- Generate a new asymmetric key pair and store it in one of the asymmetric key slots. If a slot is empty, the new generated key pair goes into that slot. If the slot already contains a key, the new key pair replaces the old one. That old key will be gone and there will be nothing you can do to recover it. There is no way to save the old key pair (e.g. move it to a retired slot) before generating the new key pair, so it will be lost. Hence, use this command with caution. You can generate a new key pair in any slot that holds asymmetric keys, including the slots described as holding retired keys. Note that you can generate a new key in slot `F9`, which holds the attestation key. If you do so, however, you could lose the ability to create an attestation statement, unless you obtain, for the new key in `F9`, a proper attestation certificate that chains to a supported root. ### Available All YubiKeys with the PIV application. ### SDK Classes [GenerateKeyPairCommand](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.Commands.GenerateKeyPairCommand.html) [GenerateKeyPairResponse](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.Commands.GenerateKeyPairResponse.html) ### Input The management key, slot number, algorithm, key size, PIN policy, and touch policy. The YubiKey supports RSA 1024, 2048, 3072, and 4096 along with ECC P-256 and P-384. ### Output The public key partner to the private key now residing in the given slot. ### APDU [Technical APDU Details](https://docs.yubico.com/yesdk/users-manual/application-piv/apdu/generate-pair.html) * * * Import Asymmetric ----------------- Import an asymmetric key, that was generated outside the YubiKey, into one of the asymmetric key slots. To load the associated public key and/or cert, use the PUT DATA command. If a slot is empty, the imported key goes into that slot. If the slot already contains a key, the new key replaces the old one. That old key will be gone and there will be nothing you can do to recover it. There is no way to save the old key (e.g. move it to a retired slot) before importing the new key, so it will be lost. Hence, use this command with caution. Note that you can import a new key in slot `F9`, which holds the attestation key. If you do so, however, you could lose the ability to create an attestation statement, unless you obtain, for the key in `F9`, a proper attestation certificate that chains to a supported root. ### Available All YubiKeys with the PIV application. ### SDK Classes [ImportAsymmetricKeyCommand](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.Commands.ImportAsymmetricKeyCommand.html) [ImportAsymmetricKeyResponse](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.Commands.ImportAsymmetricKeyResponse.html) ### Input The management key, the slot number, PIN policy, touch policy, and the new key. ### Output `bool`: was the private key successfully imported? ### APDU [Technical APDU Details](https://docs.yubico.com/yesdk/users-manual/application-piv/apdu/import-asym.html) * * * Authenticate: sign ------------------ The Authenticate command can be used to perform several cryptographic operations: * Authenticate the Management Key to the YubiKey * Sign data using a private key * Decrypt data using a private key * Perform key agreement using a private key This section discusses signing using a private key. See [Authenticate: management key](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#authenticate-management-key) , [Authenticate: decrypt](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#authenticate-decrypt) , and [Authenticate: key agreement](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#authenticate-key-agreement) for information on authenticating the management key, decrypting, and key agreement. This command signs arbitrary data. The signature process generally involves digesting the data to sign and then computing a signature based on that digest and the private key. This command does not perform the digest, only the private key operations. ### Available All YubiKeys with the PIV application. ### SDK Classes [AuthenticateSignCommand](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.Commands.AuthenticateSignCommand.html) [AuthenticateSignResponse](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.Commands.AuthenticateSignResponse.html) ### Input The PIN (maybe), the slot number, and the digest of the data to sign, possibly formatted. The data to sign is digested outside the YubiKey. Whether the PIN or touch is required before the YubiKey will sign is dependent on the PIN and touch policies specified when the key pair was generated or imported. See the sections on [generating key pairs](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#generate-asymmetric) and [importing keys](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#import-asymmetric) , along with [PIV PIN and touch policies](https://docs.yubico.com/yesdk/users-manual/application-piv/pin-touch-policies.html) . For example, if a key pair was generated with the PIN policy of "Never", then no PIN will be required to sign. However, most applications will likely set the policy to "Always" or "Once". Slot `9C` is the digital signature slot, although the YubiKey will sign using any slot holding a private key, other than `F9` (F9 holds the attestation key, which can sign a a certificate it creates, so it can sign, however, it cannot sign arbitrary data, only). For RSA signatures, the digest must be formatted into a block. The block will be the same size as the key. The two block formats allowed are PKCS 1 v 1.5 or PKCS 1 PSS. For example, if using PKCS 1 v 1.5, before calling, build the following block. formatted digest = 00 01 FF FF ... FF 00 \ For a 2048-bit key, the block is 256 bytes long (the leading 00 byte is one of the 256). If the digest algorithm is SHA-256, the DER of the DigestInfo will be 51 bytes long: 30 31 30 0d 06 09 60 86 48 01 65 03 04 02 01 05 00 04 20 <32-byte digest> The block to pass to the YubiKey will be 00 01 FF FF ... FF 00 \<51-byte DER of DigestInfo\> ^ ^ | | -------------- 202 bytes of 0xFF PSS (Probabilistic Signature Scheme) is much more complicated. If you want to learn how to build a PSS block, see RFC 8017. The formatted digest will appear to be simply random bytes. For ECC signatures, simply provide the digest. No DER encoding, just the digest. If the key is EccP256, the digest must be 256 bits (32 bytes) or shorter. You will generally use SHA-256. If the key is EccP384, the digest must be 384 bits (48 bytes) or shorter. You will generally use SHA-384. The actual APDU will format the data you provide even further: 7C len1 82 00 81 len2 \ However, you will not need to worry about this. ### Output The signature. ### APDU [Technical APDU Details](https://docs.yubico.com/yesdk/users-manual/application-piv/apdu/auth-sign.html) * * * Authenticate: decrypt --------------------- The Authenticate command can be used to perform several cryptographic operations: * Authenticate the Management Key to the YubiKey * Sign data using a private key * Decrypt data using a private key * Perform key agreement using a private key This section discusses decrypting arbitrary data. See [Authenticate: management key](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#authenticate-management-key) , [Authenticate: sign](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#authenticate-sign) , and [Authenticate: key agreement](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#authenticate-key-agreement) for information on authenticating the management key, signing, and key agreement. Decryption with a private key is possible only if the key in the slot is RSA. If the key in the slot is ECC, calling this command will produce an exception. ### Available All YubiKeys with the PIV application. ### SDK Classes [AuthenticateDecryptCommand](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.Commands.AuthenticateDecryptCommand.html) [AuthenticateDecryptResponse](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.Commands.AuthenticateDecryptResponse.html) ### Input The PIN (maybe), the slot number, and the corresponding party's public key. Whether the PIN or touch is required before the YubiKey will perform key agreement is dependent on the PIN and touch policies specified when the key pair was generated or imported. See the sections on [generating key pairs](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#generate-asymmetric) and [importing keys](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#import-asymmetric) , along with [PIV PIN and touch policies](https://docs.yubico.com/yesdk/users-manual/application-piv/pin-touch-policies.html) . For example, if a key pair was generated with the PIN policy of "Never", then no PIN will be required to sign. However, most applications will likely set the policy to "Always" or "Once". Slot `9D` is the Key Management slot, although the YubiKey will perform key agreement using any slot holding a private key, other than `F9` (the attestation key, which can only sign a certificate it creates). The input data must be the same size as the key. For example, if the key is RSA-2048, the input data (the data to decrypt) must be 256 bytes. If the data is shorter than the key, prepend as many 00 bytes as needed to make it the correct size. ### Output The decrypted data. The result will likely be formatted following PKCS 1 v. 1.5 or OAEP. It is the responsibility of the caller to extract the actual plaintext from the formatted result. ### APDU [Technical APDU Details](https://docs.yubico.com/yesdk/users-manual/application-piv/apdu/auth-decrypt.html) * * * Authenticate: key agreement --------------------------- The Authenticate command can be used to perform several cryptographic operations: * Authenticate the Management Key to the YubiKey * Sign data using a private key * Decrypt data using a private key * Perform key agreement using a private key This section discusses performing key agreement using a private key. See [Authenticate: management key](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#authenticate-management-key) , [Authenticate: sign](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#authenticate-sign) , and [Authenticate: decrypt](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#authenticate-decrypt) , for information on authenticating the management key, signing, and decrypting. Key agreement is possible only if the key in the slot is ECC. If so, this command will perform the EC Diffie-Hellman Key Agreement protocol, phase 2. If the key in the slot is RSA, calling this command will produce an exception. ### Available All YubiKeys with the PIV application. ### SDK Classes [AuthenticateKeyAgreeCommand](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.Commands.AuthenticateKeyAgreeCommand.html) [AuthenticateKeyAgreeResponse](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.Commands.AuthenticateKeyAgreeResponse.html) ### Input The PIN (maybe), the slot number, and the corresponding party's public key. Whether the PIN or touch is required before the YubiKey will perform key agreement is dependent on the PIN and touch policies specified when the key pair was generated or imported. See the sections on [generating key pairs](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#generate-asymmetric) and [importing keys](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#import-asymmetric) , along with [PIV PIN and touch policies](https://docs.yubico.com/yesdk/users-manual/application-piv/pin-touch-policies.html) . For example, if a key pair was generated with the PIN policy of "Never", then no PIN will be required to sign. However, most applications will likely set the policy to "Always" or "Once". Slot `9D` is the Key Management slot, although the YubiKey will perform key agreement using any slot holding a private key, other than `F9` (the attestation key, which can only sign a certificate it creates). The input data must be the other party's public point, and must include both the x- and y-coordinates. It will be in the form 04 || x-coordinate || y-coordinate where each coordinate is the same size as the key. For example, if the key in the slot is ECC-P256, then each coordinate must be 32 bytes. Prepend 00 bytes if necessary. The total length will be 65 bytes. ### Output The result of ECDH phase 2, which is the shared secret. The result will be the same size as the key. For example, if the key is ECC-P384, the result will be 48 bytes, possibly with leading 00 bytes. It happens to be the x-coordinate of the point result of ECC scalar multiplication, which is phase 2 of ECDH. It is the shared secret itself, no tag or length octets. ### APDU [Technical APDU Details](https://docs.yubico.com/yesdk/users-manual/application-piv/apdu/auth-key-agree.html) * * * Create attestation statement ---------------------------- Create an attestation statement for a key that had been generated by the YubiKey. See the article on [attestation](https://docs.yubico.com/yesdk/users-manual/application-piv/attestation.html) . This command will instruct the YubiKey to build and return an attestation statement. An attestation statement is an X.509 certificate. This certificate is signed by the attestation key. The cert returned will affirm that a private key was generated on the YubiKey, and not imported. The private keys that can be attested are those in slots `9A`, `9C`, `9D`, `9E` and `82` - `95`. ##### Note In version 1.0.0 of the SDK, it was not possible to create an attestation statement for keys in slots 82 - 95 (retired key slots). Beginning with version 1.0.1 of the SDK it is possible to create an attestation statement for the keys in those slots. The private key that will sign this newly-created certificate (the attestation statement) is the attestation key in slot `F9`. This slot also contains the attestation certificate. The attestation key is generated at the time of manufacture. The same attestation key is loaded onto many YubiKeys. At the same time it is generated and loaded onto YubiKeys, a certificate for it is built, signed by the YubiKey PIV Certificate Authority. The CA cert is signed by the YubiKey root. To obtain the YubiKey CA and root certs, visit the [Yubico Developer's PIV Attestation website](https://developers.yubico.com/PIV/Introduction/PIV_attestation.html) . So to verify that a private key is indeed attested, extract the public key from the attestation statement and verify that it is the appropriate public key (this is generally done by verifying a signature), extract the serial number (if part of the attestation statement) and verify it is the serial number of the YubiKey in question, and finally, verify the certificate. To verify the certificate, use the attestation cert (acquired by using the GET DATA command), the YubiKey PIV CA cert, and the YubiKey root cert. Yubico Root Cert | | Yubico PIV CA Cert | | Attestation Cert (Slot F9) (from Get Data command) | | Attestation Statement (an X.509 certificate) Note that each time this command is executed, a new cert will be created. ### Available YubiKey 4.3 and later. ### SDK Classes [CreateAttestationStatementCommand](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.Commands.CreateAttestationStatementCommand.html) [CreateAttestationStatementResponse](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.Commands.CreateAttestationStatementResponse.html) ### Input Slot number. ### Output The DER encoding of an X.509 certificate signed by the attestation key, asserting that the key in the given slot was generated by a YubiKey. The public key in the certificate is the public key partner to the private key in the specified slot, and an extension in the certificate is the serial number of the YubiKey itself. Therefore, it is possible to attest that the specific private key was generated by the specific YubiKey. ### APDU [Technical APDU Details](https://docs.yubico.com/yesdk/users-manual/application-piv/apdu/attest.html) * * * Get Data -------- Get a data element from the YubiKey. There are a number of data elements that are retrievable using a command specifically for that element (e.g. serial number). However, for other elements, it is necessary to use the GET DATA command. GET DATA is general purpose (i.e. it is not unique to the PIV application). In fact, you will likely find GET DATA commands in other areas (FIDO commands, Inter-Industry commands, etc.). However, for the PIV command namespace, there is a set of classes that represent a GET DATA command that gets specific PIV info. That is, this class will be able to construct a specific subset of GET DATA APDUs related to PIV, but not an "arbitrary" GET DATA command. See also the User's Manual entry on the [GET and PUT DATA commands](https://docs.yubico.com/yesdk/users-manual/application-piv/get-and-put-data.html) . ### Available All YubiKeys with the PIV application. ### SDK Classes [GetDataCommand](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.Commands.GetDataCommand.html) [GetDataResponse](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.Commands.GetDataResponse.html) ### Input A "tag" specifying which data element to get. Tables 4x list which data objects will be supported in the PIV GET DATA command class. It also contains links to descriptions of the data returned. Some tags require PIN authentication as well. The tags that do are listed in tables 4x. ### Output Data elements based on the input tag. The SDK returns the data as a byte array. It is the responsibility of the caller to further parse that result. Table 4A lists PIV standard elements that the YubiKey will possess upon manufacture (as long as the PIV application is initialized). Table 4B lists PIV standard elements that the YubiKey will not possess upon manufacture. Requesting these elements using GET DATA will return "NoData". If you want these elements to contain data, you will have to load them using PUT DATA. #### Table 4A: PIV GET DATA elements available upon manufacture | Name | Tag | Meaning | Authentication
Required | Data Returned | | --- | --- | --- | --- | --- | | DISCOVERY | 7E | PIV AID plus
PIN usage policy | PUT: not allowed
GET: none | [Encoded discovery](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#encoded-discovery) | #### Table 4B: PIV GET DATA elements empty upon manufacture | Name | Tag | Meaning | Authentication
Required | Data Returned | | --- | --- | --- | --- | --- | | AUTHENTICATION | 5F C1 05 | Cert for key in slot 9A | PUT: mgmt key
GET: none | [Encoded certificate](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#encoded-certificate) | | SIGNATURE | 5F C1 0A | Cert for key in slot 9C | PUT: mgmt key
GET: none | [Encoded certificate](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#encoded-certificate) | | KEY MANAGEMENT | 5F C1 0B | Cert for key in slot 9D | PUT: mgmt key
GET: none | [Encoded certificate](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#encoded-certificate) | | CARD AUTH | 5F C1 01 | Cert for key in slot 9E | PUT: mgmt key
GET: none | [Encoded certificate](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#encoded-certificate) | | RETIRED1 to
RETIRED20 | 5F C1 0D
through
5F C1 20 | Retired certs | PUT: mgmt key
GET: none | [Encoded certificate](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#encoded-certificate) | | CHUID | 5F C1 02 | Cardholder Unique
Identifier | PUT: mgmt key
GET: none | [Encoded CHUID](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#encoded-chuid) | | CAPABILITY | 5F C1 07 | Card Capability
Container (CCC) | PUT: mgmt key
GET: none | [Encoded CCC](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#encoded-ccc) | | PRINTED | 5F C1 09 | Information printed
on the card | PUT: mgmt key
GET: PIN | [Encoded printed](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#encoded-printed) | | SECURITY | 5F C1 06 | Security object | PUT: mgmt key
GET: none | [Encoded security](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#encoded-security-object) | | KEY HISTORY | 5F C1 0C | Info about retired keys | PUT: mgmt key
GET: none | [Encoded key history](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#encoded-key-history) | | IRIS | 5F C1 21 | Cardholder iris images | PUT: mgmt key
GET: PIN | [Encoded iris images](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#encoded-iris-images) | | FACIAL IMAGE | 5F C1 08 | Cardholder facial image | PUT: mgmt key
GET: PIN | [Encoded facial image](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#encoded-facial-image) | | FINGERPRINTS | 5F C1 03 | Cardholder fingerprints | PUT: mgmt key
GET: PIN | [Encoded fingerprints](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#encoded-fingerprints) | | BITGT | 7F 61 | Biometric Information
Group Template | PUT: not supported
GET: none | [Encoded BITGT](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#encoded-bitgt) | | SM SIGNER | 5F C1 22 | Secure Messaging
Certificate Signer | PUT: mgmt key
GET: none | [Encoded SM cert signer](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#encoded-sm-cert-signer) | | PC REF DATA | 5F C1 23 | Pairing Code
Reference Data | PUT: mgmt key
GET: none | [Encoded PC Ref](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#encoded-pc-ref) | All the tags supported are one, two, or three bytes long. The APDU data contains the tag, each constructed as a TLV itself. That is, there is a DER TLV with a T of `5C`, and a V of the GET DATA tag. Unfortunately, that is the terminology used in the standard. There is a tag for TLV and a value that is itself called a "tag". 5C 01 7E 5C 02 7F 61 5C 03 5F C1 xx #### Encoded certificate If the certificate retrieved is the attestation statement, it is returned encoded as follows. 53 L1 70 L2 --X.509 certificate-- The X.509 certificate is the DER encoding of the ASN.1 definition "Certificate" from the X.509 standard (see RFC 5280). All other certificates are returned as specified in the PIV standard: 53 L1 70 L2 --X.509 certificate-- 71 01 00 (compression) FE 00 (LRC) The X.509 certificate is the DER encoding of the ASN.1 definition "Certificate" from the X.509 standard (see RFC 5280). The 71 01 00 means the certificate itself is uncompressed. If it were 71 01 01, it would mean the certificate were gzipped. The "LRC" is an error detection code. While it is mandatory according to one smart card standard, the PIV standard does not use it and therefore its length is zero. #### Encoded CHUID As specified in the PIV standard: 53 3B 30 19 --FASC-N, fixed at 25 bytes-- 34 10 --GUID, fixed at 16 bytes-- 35 08 --expiration data, ASCII YYYYMMDD, fixed at 8 bytes-- 3E 00 (Issuer Asymmetric Signature, max 2816 bytes, unused in YubiKey) FE 00 (LRC, unused in PIV) The FASC-N is a value generated following the TIG SCEPACS standard (a smart card standard). The GUID is a value generated following RFC 4122. The "LRC" is an error detection code. While it is mandatory according to one smart card standard, the PIV standard does not use it and therefore its length is zero. #### Encoded CCC As specified in the PIV standard: 53 33 F0 15 (card identifier, fixed at 21 bytes) A0 00 00 01 16 FF 02 --14 random bytes-- F1 01 21 (container version number) F2 01 21 (grammar version number) F3 00 (unused by YubiKey) F4 01 00 (PKCS 15 support, YubiKey does not support) F5 01 10 (Data model number) F6 00 (unused by YubiKey) F7 00 (unused by YubiKey) FA 00 (unused by YubiKey) FB 00 (unused by YubiKey) FC 00 (unused by YubiKey) FD 00 (unused by YubiKey) FE 00 (LRC, unused in PIV) The "LRC" is an error detection code. While it is mandatory according to one smart card standard, the PIV standard does not use it and therefore its length is zero. #### Encoded discovery As specified in the PIV standard: 7E 12 4F 0B A0 00 00 03 08 00 00 10 00 01 00 (Application AID, fixed) 5F 2F 02 40 00 (PIN Usage Policy, the only policy YubiKey supports) #### Encoded printed As specified in the PIV standard: 53 L1 01 len --Name, ASCII text, up to 125 bytes-- 02 len --Employee afiliation, ASCII text, up to 20 bytes-- 04 len --Expiration date, ASCII numbers YYYYMMMDD, fixed at 9 bytes-- 05 len --Agency Card Serial Number, ASCII text, up to 20 bytes-- 06 len --Issuer Id, ASCII text, up to 15 bytes-- 07 len --Org affiliation, line 1, ASCII text, up to 20 bytes-- 08 len --Org affiliation, line 2, ASCII text, up to 20 bytes-- FE 00 (LRC, unused in PIV) The "LRC" is an error detection code. While it is mandatory according to one smart card standard, the PIV standard does not use it and therefore its length is zero. Note that the SDK does not allow putting data into the Printed tag. However, Yubico uses this tag to store information. If you GET DATA with this tag, you will likely see either no data or data that does not follow this format. You should never overwrite the information in the Printed tag. If you do, it could make your YubiKey unusable. #### Encoded security object As specified in the PIV standard: 53 L1 BA len --Mapping of DG (Data Group, see PIV standard) to ContainerID, up to 30 bytes-- BB len --Security object (See MRTD standard), up to 1298 bytes-- FE 00 (LRC, unused in PIV) The "LRC" is an error detection code. While it is mandatory according to one smart card standard, the PIV standard does not use it and therefore its length is zero. #### Encoded key history As specified in the PIV standard: 53 L1 C1 01 --number of keys with on card certs-- C2 01 --number of keys with off card certs-- F3 len --off card cert URL, only if C2 value is > 0, up to 118 bytes-- FE 00 (LRC, unused in PIV) The "LRC" is an error detection code. While it is mandatory according to one smart card standard, the PIV standard does not use it and therefore its length is zero. #### Encoded iris images As specified in the PIV standard: 53 L1 BC len --image for verification, up to 7,100 bytes-- FE 00 (LRC, unused in PIV) The "LRC" is an error detection code. While it is mandatory according to one smart card standard, the PIV standard does not use it and therefore its length is zero. #### Encoded facial image As specified in the PIV standard: 53 L1 BC len --image for verification, up to 12,704 bytes-- FE 00 (LRC, unused in PIV) The "LRC" is an error detection code. While it is mandatory according to one smart card standard, the PIV standard does not use it and therefore its length is zero. #### Encoded fingerprints As specified in the PIV standard: 53 L1 BC len --Fingerprint I and II, up to 4,000 bytes-- FE 00 (LRC, unused in PIV) The "LRC" is an error detection code. While it is mandatory according to one smart card standard, the PIV standard does not use it and therefore its length is zero. #### Encoded BITGT As specified in the PIV standard: 7F 61 L1 02 01 --number of fingers-- 7F 60 len --BIT for first finger, up to 28 bytes-- 7F 60 len (Optional) --BIT for second finger, up to 28 bytes-- #### Encoded SM cert signer As specified in the PIV standard: 53 L1 70 len --X.509 cert, up to 3,048 bytes-- 71 01 --compression-- 7F 21 len (Optional) --intermediate CVC (see PIV standard), uncompressed, up to 3,048 bytes-- FE 00 (LRC, unused in PIV) The "LRC" is an error detection code. While it is mandatory according to one smart card standard, the PIV standard does not use it and therefore its length is zero. The YubiKey will allow for up to a combined 3,048 bytes for the cert and CVC. That is, even though the maximum length of each element is 3,048 bytes, the length of the two combined must be 3,048 bytes or fewer. So a cert of 3,048 bytes with no CVC (length 0) is acceptable, but a cert of length 2,500 bytes combined with a CVC of 600 bytes would not be allowed. #### Encoded PC Ref As specified in the PIV standard: 53 0C 99 08 --Pairing code, Ascii text, fixed at 8 bytes-- FE 00 (LRC, unused in PIV) The "LRC" is an error detection code. While it is mandatory according to one smart card standard, the PIV standard does not use it and therefore its length is zero. ### APDU [Technical APDU Details](https://docs.yubico.com/yesdk/users-manual/application-piv/apdu/get-data.html) * * * Put data -------- Put the given data into a data element on the card. See also the User's Manual entry on the [GET and PUT DATA commands](https://docs.yubico.com/yesdk/users-manual/application-piv/get-and-put-data.html) . ### Available All YubiKeys with the PIV application. ### SDK Classes [PutDataCommand](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.Commands.PutDataCommand.html) [PutDataResponse](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.Commands.PutDataResponse.html) ### Input In order to put data, the management key must be authenticated. See the User's Manual [entry on PIV commands access control](https://docs.yubico.com/yesdk/users-manual/application-piv/access-control.html) for information on how to authenticate with the management key for commands. See also the section in this page on [Authenticate: management key](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#authenticate-management-key) . The input data will be a "tag" specifying where the data is to go, along with the data to PUT. [Tables 4x](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#getdatatable) in the Get Data command section above lists all possible tags. The "Data Returned" in that table is the data to put. Note that the SDK requires the data be formatted as defined in the PIV standard, described above. Note that the YubiKey will not allow putting data for the following tags. * Printed * Discovery * Biometric Information Group Template You should never overwrite the information in the Printed tag. If you do, it could make your YubiKey unusable. ### Output `bool`: was the data element successfully put? ### APDU [Technical APDU Details](https://docs.yubico.com/yesdk/users-manual/application-piv/apdu/put-data.html) * * * Get and Put Vendor Data ----------------------- The SDK also contains the ability to get and put data into tags not defined by the PIV standard. These are vendor-defined tags. The tag must be of the form 0x5FFFxx. Using this feature, a caller can also store arbitrary data into a tag, data that is not necessarily encoded following the PIV specification. This feature, however, is not publicly available. It is only callable from inside the SDK. Table 5A lists Yubico-defined elements that the YubiKey will possess upon manufacture (as long as the PIV application is initialized). Table 5B lists Yubico-defined elements that the YubiKey will not possess upon manufacture. Requesting these elements using GET DATA will return "NoData". If you want these elements to contain data, you will have to load them using PUT DATA. #### Table 5A: Yubico-defined GET DATA elements available upon manufacture | Name | Tag | Meaning | Authentication
Required | Data Returned | | --- | --- | --- | --- | --- | | ATTESTATION | 5F FF 01 | Attestation cert | PUT: mgmt key
GET: none | [Encoded certificate](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#encoded-certificate) | #### Table 5B: Yubico-defined GET DATA elements empty upon manufacture | Name | Tag | Meaning | Authentication
Required | Data Returned | | --- | --- | --- | --- | --- | | ADMIN DATA | 5F FF 00 | PIV manager application
administrative data | PUT: mgmt key
GET: none | [Encoded admin data](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#encoded-admin-data) | | MSCMAP | 5F FF 10 | Microsoft container map | PUT: mgmt key
GET: none | [MSCMAP](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#mscmap) | | MSROOTS1 to
MSROOTS5 | 5F FF 11
through
5F FF 15 | Microsoft root certs | PUT: mgmt key
GET: none | [MSROOTS](https://docs.yubico.com/yesdk/users-manual/application-piv/commands.html#msroots) | #### Encoded Admin Data The GET DATA element ADMIN DATA is used by the PIV manager application to store data about the PIV application and the data in the PIV portion of the YubiKey. The information is generally not used by the YubiKey anymore and is retained only for backwards compatibility. It is safe to ignore this element. 80 L1 81 01 (optional) --bit field, PUK blocked, Mgmt Key stored in protected data-- 82 L2 (optional) --salt, deprecated-- 83 L3 (optional) --time the PIN was last updated-- The bit field contains up to two bits: 1 is PUK blocked and 2 is PIN-protected. It is permissible to have no salt (either no TLV for tag 82, or `82 00` as the TLV) or a 16-byte value. The "PIN last updated" field is the UNIX time of seconds since 1970, in little endian order. For example, some time in Jan. 14, 2022 is 0x61E1B870. It would be encoded as 83 04 70 B8 E1 61 It will generally be a 4-byte value until sometime in January, 2038, when it will be 5 bytes. #### MSROOTS These tags were created so that Yubico libraries (minidriver, SDK) can better interface with the Microsoft Smart Card Base Crypto Service Provider (CSP). There will likely never be a scenario where an application will need to use the data the SDK will PUT into and GET from these objects. If your application uses the Base CSP, and you use a YubiKey, any necessary operations with the MSROOTS will be handled by the SDK. #### MSCMAP This tag was created so that Yubico libraries (minidriver, SDK) can better interface with the Microsoft Smart Card Base Crypto Service Provider (CSP). There will likely never be a scenario where an application will need to use the data the SDK will PUT into and GET from these objects. If your application uses the Base CSP, and you use a YubiKey, any necessary operations with the MSCMAP will be handled by the SDK. * * * Reset the PIV Application ------------------------- Delete all the credentials and keys, and set the PIN, PUK, and management key to the default values: PIN: 123456 PUK: 12345678 Mgmt Key: hex 010203040506070801020304050607080102030405060708 0102030405060708 three times This command will be accepted only if the PIN and PUK are both blocked. ### Available All YubiKeys with the PIV application except for YubiKey Bio Multi-protocol Edition (MPE) keys. For YubiKey Bio MPE, use the [device-wide reset](https://docs.yubico.com/yesdk/users-manual/sdk-programming-guide/bio-mpe.html#resetting-a-yubikey-bio-mpe) instead. ### SDK Classes [ResetPivCommand](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.Commands.ResetPivCommand.html) [ResetPivResponse](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.Commands.ResetPivResponse.html) ### Input None. ### Output There is no data output, only the status. ### APDU [Technical APDU Details](https://docs.yubico.com/yesdk/users-manual/application-piv/apdu/reset-piv.html) * * * [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-piv/commands.md/#L1) --- # Unknown YubiKey PIV Tool User Guide Yubico Sep 09, 2025 CONTENTS 1 Introduction1 1.1 PIV Standard . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 1.2 PIV Tool Design . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 1.3 PIV Usage Guides . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 1.4 General Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 1.5 Software . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 1.6 License . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 2 Set up PIV Tool5 2.1 Preparing a YubiKey for Real Use . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 2.2 Secure Channel Communication . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 2.3 Building on POSIX platforms . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6 2.4 Building on Windows . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6 2.5 Coverage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 2.6 Portability . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 2.7 Card Holder Unique Identifier . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8 3 PIV Tool Common Tasks9 3.1 YubiKey Management Related Tasks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 3.1.1 Change the management key . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 3.1.2 Display PIV tool version . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 3.1.3 Reset PIN/PUK retry counter and codes . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 3.1.4 Reset the application after PIN/PUK modified . . . . . . . . . . . . . . . . . . . . . . . . . 10 3.1.5 Set a random chuid . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 3.2 Key Related Tasks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 3.2.1 Generate a new private key . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 3.2.2 Generate a new ECC-P256 key . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 3.2.3 Import a key into slot 85 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 3.2.4 Run a signature test . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 3.2.5 Set the touch policy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 3.3 Certificate Related Tasks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 3.3.1 Compress a large certificate . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 3.3.2 Delete a certificate . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 3.3.3 Generate a certificate request . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 3.3.4 Generate a self-signed certificate . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 3.3.5 Import a certificate . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 3.3.6 Import a large certificate . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 3.3.7 Import a large certificate . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 3.3.8 Read out the certificate . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 3.3.9 Show certificate information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 i 4 PIV YKCS11 Module15 4.1 Building . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 4.2 Portability . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 4.3 YKCS11 on Windows . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 4.3.1 A Note for Developers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 4.4 Key Mapping . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 4.5 Key Generation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 4.6 Attestation Certificates . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 4.7 User Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 4.8 PINs and Management Key . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 4.9 Keys with PIN policy “never” . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 4.10 Fingerprint Authentication with YubiKey Bio . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 4.11 OpenSSL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 4.12 Testing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18 4.13 Debugging . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18 4.14 YKCS11 Functions and Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18 4.14.1 Supported PKCS#11 Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18 4.14.2 Supported PKCS#11 Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22 4.14.3 Supported Attributes per Object Type . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22 4.14.4 Key Alias per Slot and Object Type . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 4.15 YKCS11 Supported Applications . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 4.15.1 FireFox . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 4.15.1.1 Importing CA Certificate on FireFox . . . . . . . . . . . . . . . . . . . . . . . . . 28 4.15.1.2 Adding YKCS11 Security Device on FireFox . . . . . . . . . . . . . . . . . . . . . 31 4.15.1.3 Viewing and Downloading a Certificate on FireFox . . . . . . . . . . . . . . . . . 31 4.15.1.4 Other Functionality on FireFox . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31 4.15.2 Fortify . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31 4.15.2.1 Tips for using Fortify . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34 4.15.3 Java Keytool . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39 4.15.3.1 List Content . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39 4.15.3.2 Signing a JAR File . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39 4.15.4 OpenSC pkcs11-tool . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40 4.15.4.1 Display Device Info . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40 4.15.4.2 Key Generation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40 4.15.4.3 Signing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40 4.15.4.4 Testing RSA Keys . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41 4.15.4.5 Testing EC Keys . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41 4.15.5 OpenSSH . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41 4.15.6 OpenSSL via PKCS11 Engine . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42 4.15.6.1 Data Signing with OpenSSl . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42 5 PIV Tool Attestation43 5.1 What is Attestation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43 5.2 Getting and Verifying Attestation Certificates . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43 6 PIV Tool Command, Options and Actions47 6.1 yubico-piv-tool \[Option\] ... . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47 6.1.1 PIV Tool Options . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47 6.2 PIV Tool action Command Parameters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52 6.2.1 Syntax . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52 6.2.2 Description . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53 6.2.3 Parameters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53 6.3 attest . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55 6.3.1 Syntax . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55 ii 6.3.2 Description . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55 6.3.3 Examples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55 6.3.4 Parameters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56 6.4 change-pin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56 6.4.1 Syntax . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56 6.4.2 Description . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57 6.4.3 Parameters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57 6.5 change-puk . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57 6.5.1 Syntax . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57 6.5.2 Description . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57 6.5.3 Parameters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58 6.6 delete-certificate . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58 6.6.1 Syntax . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58 6.6.2 Description . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58 6.6.3 Examples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58 6.6.4 Parameters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59 6.7 delete-key . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60 6.7.1 Syntax . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60 6.7.2 Description . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60 6.7.3 Examples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60 6.7.4 Parameters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61 6.8 generate . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61 6.8.1 Syntax . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61 6.8.2 Description . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62 6.8.3 Examples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62 6.8.3.1 Example 1: Self signed certificate on slot 9a . . . . . . . . . . . . . . . . . . . . . 62 6.8.3.2 Example 2: generate Signed certificate on slot 9c . . . . . . . . . . . . . . . . . . 63 6.8.4 Parameters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64 6.9 import-certificate . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66 6.9.1 Syntax . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66 6.9.2 Description . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66 6.9.3 Examples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67 6.9.4 Parameters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67 6.10 import-key . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68 6.10.1 Syntax . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68 6.10.2 Description . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68 6.10.3 Examples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68 6.10.4 Parameters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69 6.11 list-readers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71 6.12 move-key . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71 6.12.1 Syntax . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71 6.12.2 Description . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71 6.12.3 Examples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71 6.12.4 Parameters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72 6.13 pin-retries . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73 6.14 read-certificate . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73 6.14.1 Syntax . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73 6.14.2 Description . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73 6.14.3 Examples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73 6.14.4 Parameters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74 6.15 read-object . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75 6.15.1 Syntax . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75 6.15.2 Description . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75 6.15.3 Examples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75 iii 6.15.4 Supported PIV Object IDs for read- and write-object . . . . . . . . . . . . . . . . . . . . . 76 6.15.5 Parameters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77 6.16 read-public-key . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78 6.16.1 Syntax . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78 6.16.2 Description . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78 6.16.3 Examples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78 6.16.4 Parameters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79 6.17 request-certificate . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80 6.17.1 Description . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80 6.17.2 Examples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80 6.18 reset . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80 6.18.1 Syntax . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80 6.18.2 Description . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80 6.18.3 Examples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81 6.18.4 Parameters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81 6.19 selfsign-certificate . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81 6.19.1 Description . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81 6.19.2 Examples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82 6.20 set-ccc . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82 6.21 set-chuid . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82 6.22 set-mgm-key . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82 6.23 sign-data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82 6.23.1 Syntax . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82 6.23.2 Description . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82 6.23.3 Examples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83 6.23.4 Parameters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85 6.24 status . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86 6.24.1 Syntax . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86 6.24.2 Description . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86 6.24.3 Examples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86 6.24.4 Parameters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88 6.25 test-decipher . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88 6.25.1 Syntax . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88 6.25.2 Description . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89 6.25.3 Examples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89 6.25.4 Parameters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92 6.26 test-signature . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93 6.26.1 Syntax . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93 6.26.2 Description . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93 6.26.3 Examples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93 6.26.4 Parameters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96 6.27 unblock-pin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97 6.28 verify-bio . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97 6.28.1 Description . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97 6.28.2 Examples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97 6.29 verify-pin . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97 6.29.1 Description . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97 6.29.2 Examples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97 6.30 version . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98 6.30.1 Syntax . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98 6.30.2 Description . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98 6.30.3 Examples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98 6.31 write-object . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98 6.31.1 Syntax . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98 iv 6.31.2 Description . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98 7 Copyright99 7.1 Trademarks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99 7.2 Disclaimer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99 7.3 Contact Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99 7.4 Document Updated . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100 v vi CHAPTER ONE INTRODUCTION Use the Yubico PIV tool for interacting with the Personal Identity Verification (PIV) application on a YubiKey. Through the Yubico PIV tool, you can generate keys on the device, import keys and certificates, and create certificate requests, and other operations. A shared library and a command-line tool,yubico-piv-tool, is included. The Yubico PIV tool was designed to interact with and manage the PIV functions alone. Built on the C ykpiv library, the PIV tool provides a CLI to access all of the functionality supported on the PIV function of the YubiKey. While the PIV tool allows for the CLI to be used as part of a scripted process, the lack of support beyond the PIV functions means that it is less script-friendly thanykman. However, as a purpose built interface on just the ykpiv library, the PIV tool is an excellent reference architecture for supporting the YubiKey as a PIV smart card natively. The PIV tool also provides a PKCS#11 module, called YKCS11, that can be used to expose the YubiKey’s smart card functionality to applications that communicate with hard tokens through the PKCS#11 API. For example, OpenSSL, OpenSSH, JAVA, FireFox and the like. Use the PIV tool whenykmandoes not have a specific command, or when testing the PIV functionality of the YubiKey. On POSIX platforms, PIV tool requirespcscdto be pre-installed. •See the Yubico PIV Tool Release Notes for PIV Tool versions. •See the PIV Introduction on developers.yubico.com for information about performing RSA or ECC sign/decrypt operations using a private key stored on the YubiKey smartcard, through common interfaces like PKCS#11. 1.1 PIV Standard PIV, or FIPS 201, is a US government standard. It enables RSA or ECC sign/encrypt operations using a private key stored on a smartcard (such as the YubiKey), through common interfaces like PKCS#11. YubiKeys support the PIV card interface specified in NIST SP 800-73 document Cryptographic Algorithms and Key Sizes for Personal Identity Verification. PIV enables you to perform RSA or ECC sign/decrypt operations using a private key stored on the smartcard, through common interfaces like PKCS#11. This document contain the library, tools and PKCS#11 module to interact with the hardware functionality. You can read more about the PIV standards here: PIV Standards PIV is primarily used for non-web applications. It has built-in support under Windows, and can be used on macOS and Linux via the OpenSC project. 1 YubiKey PIV Tool User Guide 1.2 PIV Tool Design The Yubico PIV tool was designed to interact with and manage the PIV functions alone. Built on the Cykpivlibrary, the PIV tool provides a CLI to access all of the functionality supported on the PIV function of the YubiKey. While PIV tool allows for the CLI to be used as part of a scripted process, the lack of support beyond the PIV functions means that it is less script-friendly thanykman. However, as a purpose built interface on just theykpivlibrary, the PIV tool is an excellent reference architecture for supporting the YubiKey as a PIV smart card natively. The PIV tool also provides a PKCS#11 module, called YKCS11, that can be used to expose the YubiKey’s smart card functionality to applications that communicate with hard tokens through the PKCS#11 API; applications like OpenSSL, OpenSSH, JAVA, FireFox and the like. Use the PIV tool whenykmandoes not have a specific command, or when testing the PIV functionality of the YubiKey. On POSIX platforms, PIV tool requirespcscdto be pre-installed. 1.3 PIV Usage Guides For information and examples on what you can do with a PIV enabled YubiKey, see https://developers.yubico.com/ PIV/. 1.4 General Information The default PIN code is123456. The default PUK code is12345678. For firmware 5.7 and above:The default AES-192 management key (9B) is 010203040506070801020304050607080102030405060708. For firmware 5.4 and below:The default 3DES management key (9B) is 010203040506070801020304050607080102030405060708. The following key slots exists: •9A, 9C, 9D, 9E: RSA 1024, RSA 2048, ECC secp256r1 or ECC secp384r1 keys (algorithms 6, 7, 11 respectively). •9B: Triple-DES key (algorithm 3) for PIV management. The maximum size of stored objects is 2025/3049 bytes for current versions of YubiKey NEO and YubiKey 4, respec- tively. Currently all functionality are available over both contact and contactless interfaces (contrary to what the specifications mandate). 1.5 Software Card management has been tested with the tools from the OpenSC project, specifically piv-tool, and Yubico PIV software. Basic features should work with any PIV compliant middleware. https://github.com/OpenSC/OpenSC/wiki https://developers.yubico.com/yubico-piv-tool/ https://developers.yubico.com/yubikey-piv-manager/ https://github.com/OpenSC/OpenSC/wiki/US-PIV 2Chapter 1. Introduction YubiKey PIV Tool User Guide https://github.com/OpenSC/OpenSC/wiki/PivTool 1.6 License In general the project is covered by the following BSD license. The file ykcs11/pkcs11.h has additional copyright and licensing information, please see it for more information. Copyright (c) 2014-2020 Yubico AB All rights reserved. Redistributionanduseinsourceandbinary forms,with orwithout modification, are permitted provided that the following conditions are met: \* Redistributions of source code must retain the above copyright notice, this list of conditionsandthe following disclaimer. \* Redistributionsinbinary form must reproduce the above copyright notice, this list of conditionsandthe following disclaimerinthe documentationand/orother materials provided withthe distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 1.6. License3 YubiKey PIV Tool User Guide 4Chapter 1. Introduction CHAPTER TWO SET UP PIV TOOL 2.1 Preparing a YubiKey for Real Use Change the management key to make sure nobody but you can modify the state of the PIV application on the YubiKey. Make sure to keep a copy of the key around for later use. All of these invocations leaves traces of keys and pins in the command line history. To avoid this, do not include the argument, then the software prompts for the key/pin to be input, and that response is not included in the command line history. For example, when changing the the management key, simply do not include the management key string. Use -kin the command, rather than-k . key=$(export LC\_CTYPE=C; dd if=/dev/urandom 2>/dev/null | tr -d'\[:lower:\]'| tr -cd ˓→'\[:xdigit:\]'| fold -w48 | head -1) echo ${key} yubico-piv-tool -aset-mgm-key -n${key} Change the PIN and PUK, as well. pin=$(export LC\_CTYPE=C; dd if=/dev/urandom 2>/dev/null | tr -cd'\[:digit:\]'| fold -w6␣ ˓→| head -1) echo ${pin} puk=$(export LC\_CTYPE=C; dd if=/dev/urandom 2>/dev/null | tr -cd'\[:digit:\]'| fold -w8␣ ˓→| head -1) echo ${puk} yubico-piv-tool -achange-pin -P123456 -N${pin} yubico-piv-tool -achange-puk -P12345678 -N${puk} 2.2 Secure Channel Communication Some YubiKeys with firmware version 5.7.0 and higher have support for encrypted communicating over a secure chan- nel. Encryption in Yubico PIV Tool is based on the SCP11b protocol. To activate Yubico PIV Tool encryption, add the--encflag in the command line tool or open a connection with the encryption boolean set totruewhen using libykpivduring development. After encryption is activated, all subsequent communication over the same session is encrypted. Note that the SCP11b based implementation entails that the communication is encrypted, but the On-Card certificate (CERT.SD.ECKA) used to setup the encrypted session is not validated. The feature is used mainly to protect sensitive communication between the host and the YubiKey against monitoring over a medium which could potentially be eavesdropped on, such as NFC. 5 YubiKey PIV Tool User Guide 2.3 Building on POSIX platforms Either clone from Git or download and unpackage the tarball, then make sure you have the pre-requisites installed and build following the steps below from theyubico-piv-tooldirectory. Please make sure to have recent versions of the following packages installed on your system. cmake libtool libssl-dev pkg-config check libpcsclite-dev gengetopt help2man zlib-devel Help2man is used to generate the manpages. Gengetopt version 2.22.6 or later is needed for command line parameter handling. The Vagrant VM has all these dependencies preinstalled. Please note that these package names are debian based. Other POSIX platforms might have different names. For exam- ple,libssl-devcan probably be replaced withopenssl-develandlibpcsclite-devcan probably be replaced bypcsc-lite-develon a Redhat platform. Also note that Gengetopt might not be available on all platforms and might need to be built from source. See Gengetop Installation. After installation of all dependencies, run the following: cd yubico-piv-tool mkdir build; cd build cmake .. make sudo make install On macOS, you might need to point out homebrew openssl version when runningpkg-config. PKG\_CONFIG\_PATH="/usr/local/opt/openssl@1.1/lib/pkgconfig" cmake .. To statically link to OpenSSL (thelibcryptolibrary), use thecmakeoption-DOPENSSL\_STATIC\_LINK=ON. Do not forget you might need to be root for the last command. On Linux it might be needed to update your linked libraries after install. sudo ldconfig The backend to use is decided at compile time, see the summary at the end of thecmakeoutput. Use --with-backend=footo choose backend, replacingfoowith the backend you want to use. The backends avail- able are “pcsc”, “macscard” and “winscard” using the PCSC interface, with slightly different shared library linkage and header file names: “pcsc” is used under GNU-like systems, “macscard” under MacOS X, and “winscard” is used under Windows. In most situations, runningcmakeshould automatically find the proper backend to use. 2.4 Building on Windows Building on Windows requires MSBuild or Visual Studio and the MSVC compiler. It also requires building the binaries from the source release package and not from the source checked out from the repository on GitHub. This is because some files that are part of the command line shell are generated but they cannot, currently, be generated on Windows. Those files are, however, included in the source release package. On Windows,getoptis needed to read command line arguments. The easiest way to installgetoptis with the vcpkg package manager The path togetoptDLL library and include file need to be specified as a command line argument to cmake. Also the path to OpenSSL needs to be specified either as a command line argument tocmakeor by setting the environment variableOPENSSL\_ROOT\_DIR. 6Chapter 2. Set up PIV Tool YubiKey PIV Tool User Guide The command line examples bellow are forPowerShelland the prerequisites were installed from source (using vcpkg). env:OPENSSL\_ROOT\_DIR ="PATH/TO/OPENSSL\_DIR" mkdir build; cd build cmake -A -DGETOPT\_LIB\_DIR="PATH/TO/GETOPT\_DIR/lib" -DGETOPT\_INCLUDE\_DIR="PATH/TO/ ˓→GETOPT\_DIR/include .. cmake --build . To run the tests,checkis used. The path to thecheckdirectory needs to be specified as a command line argument tocmake. Also the path tocheckbinaries,OpenSSLbinaries,libykpiv.dllandlibykcs11.dll\`\`need to be in the\`\`PATH. env:OPENSSL\_ROOT\_DIR ="PATH/TO/OPENSSL\_DIR" mkdir build; cd build cmake -A -DGETOPT\_LIB\_DIR="PATH/TO/GETOPT\_DIR/lib" -DGETOPT\_INCLUDE\_DIR="PATH/TO/ ˓→GETOPT\_DIR/include -DCHECK\_PATH="PATH/TO/CHECK\_DIR" .. cmake --build . $env:Path +=";PATH/TO//CHECK\_DIR/bin;PATH/TO/OPENSSL\_DIR/bin;PATH/TO/build\\lib\\Debug; ˓→PATH/TO/build\\ykcs11\\Debug" ctest.exe -C Debug For building on 32 bits system, useWin32as ARCH. For building on 64 bits systems, usex64as ARCH. 2.5 Coverage Code coverage is provided courtesy oflcovand CMake-codecov This currently only works withmake. Enable coverage with cmake -DENABLE\_COVERAGE=1 .. You can then build the project normally and run some executables (for example running the tests withmake test). At this point coverage evaluation can be generated withgcovorlcovrelated targets. For example, thismakecommand generates a single HTML report in./lcov/html/all\_targets/index.html. make lcov 2.6 Portability The main development platform is Debian GNU/Linux. The project compiles on Windows using MSVC and the PCSC backend. It can also be built for MacOS X, also using the PCSC backend. 2.5. Coverage7 YubiKey PIV Tool User Guide 2.7 Card Holder Unique Identifier For the application to be usable in windows the object CHUID (Card Holder Unique Identifier) has to be set and unique. The card contents are also aggressively cached so the CHUID has to be changed if the card contents change. 8Chapter 2. Set up PIV Tool CHAPTER THREE PIV TOOL COMMON TASKS For a list of all available options--helpcan be given. For more information about what’s happening--verbosecan be added to any command. For much more information--verbose=2may be used. 3.1 YubiKey Management Related Tasks 3.1.1 Change the management key Change the management key used for administrative authentication: yubico-piv-tool -aset-mgm-key Seeset-mgm-key. 3.1.2 Display PIV tool version Display PIV tool version running on the YubiKey: yubico-piv-tool -aversion Seeversion. 3.1.3 Reset PIN/PUK retry counter and codes Default pin 123456, puk 12345678. yubico-piv-tool -k${key} -averify -P${pin} -apin-retries --pin-retries=3 --puk-retries=3 Seeverify-pin. 9 YubiKey PIV Tool User Guide 3.1.4 Reset the application after PIN/PUK modified PIN/PUK need to be blocked hence trying a couple of times — you need to modify this if you have changed the default number of PIN/PUK retries. yubico-piv-tool -averify-pin -P471112 yubico-piv-tool -averify-pin -P471112 yubico-piv-tool -averify-pin -P471112 yubico-piv-tool -averify-pin -P471112 yubico-piv-tool -achange-puk -P471112 -N6756789 yubico-piv-tool -achange-puk -P471112 -N6756789 yubico-piv-tool -achange-puk -P471112 -N6756789 yubico-piv-tool -achange-puk -P471112 -N6756789 yubico-piv-tool -areset Seeverify-pin,change-puk, andreset. 3.1.5 Set a random chuid Set a randomchuid, import a key, and import a certificate from a PKCS12 file, into slot 9c: yubico-piv-tool -s9c -itest.pfx -KPKCS12 -aset-chuid -aimport-key -aimport-cert Seeset-chuid,import-key, andimport-certificate. 3.2 Key Related Tasks 3.2.1 Generate a new private key yubico-piv-tool -k${key} -agenerate -s9c Seegenerate. 3.2.2 Generate a new ECC-P256 key Generate a new ECC-P256 key on device in slot 9a and print the public key on stdout: yubico-piv-tool -s9a -AECCP256 -agenerate Seegenerate. 10Chapter 3. PIV Tool Common Tasks YubiKey PIV Tool User Guide 3.2.3 Import a key into slot 85 Import a key into slot 85 and set the touch policy: Both options only available on YubiKey 4 and 5: yubico-piv-tool -aimport-key -s85 --touch-policy=always -ikey.pem Seeimport-key. 3.2.4 Run a signature test Read out the certificate from a slot and then run a signature test: yubico-piv-tool -aread-cert -s9a yubico-piv-tool -averify-pin -atest-signature -s9a Seeread-certificateandverify-pin. 3.2.5 Set the touch policy Import a key into slot 85 and set the touch policy: Both options only available on YubiKey 4 and 5 or newer: yubico-piv-tool -aimport-key -s85 --touch-policy=always -ikey.pem Seeimport-keyandPIV Tool Options. 3.3 Certificate Related Tasks 3.3.1 Compress a large certificate Import a large certificate and useyubico-piv-toolto apply GZIP compression. Compression is required for certifi- cates larger than 2048 bytes in order to have fit: yubico-piv-tool -s9c -icert.pem --compress -aimport-cert Seeimport-certificateandgenerate. 3.3.2 Delete a certificate Delete a certificate in slot 9a, with management key being asked for: yubico-piv-tool -adelete-certificate -s9a -k Seedelete-certificate. 3.3. Certificate Related Tasks11 YubiKey PIV Tool User Guide 3.3.3 Generate a certificate request Generate a certificate request with public key from stdin and print the resulting request on stdout: yubico-piv-tool -s9a -S'/CN=foo/OU=test/O=example.com/'-averify -arequest Seegenerate. 3.3.4 Generate a self-signed certificate Generate a self-signed certificate with public key from stdin and print the certificate, for later import on stdout: yubico-piv-tool -s9a -S'/CN=bar/OU=test/O=example.com/'-averify -aselfsign Seegenerate. 3.3.5 Import a certificate Import a certificate from stdin: yubico-piv-tool -s9a -aimport-certificate Seeimport-certificateandgenerate. 3.3.6 Import a large certificate Import a large certificate that requires compression. Certificates larger than 2048 bytes require compression in order to fit: openssl x509 -incert.pem -outform DER | gzip -9 > der.gz yubico-piv-tool -s9c -ider.gz -KGZIP -aimport-cert Seeimport-certificate. 3.3.7 Import a large certificate Import a certificate which is larger than 2048 bytes and have the yubico-piv-tool do the GZIP compression in order to fit: yubico-piv-tool -s9c -icert.pem --compress -aimport-cert Seeimport-certificate. 12Chapter 3. PIV Tool Common Tasks YubiKey PIV Tool User Guide 3.3.8 Read out the certificate Read out the certificate from a slot and then run a signature test: yubico-piv-tool -aread-cert -s9a yubico-piv-tool -averify-pin -atest-signature -s9a Seeread-certificate,verify-pin, andtest-signature. 3.3.9 Show certificate information Show some certificate information and some other data: yubico-piv-tool -astatus Seestatus. 3.3. Certificate Related Tasks13 YubiKey PIV Tool User Guide 14Chapter 3. PIV Tool Common Tasks CHAPTER FOUR PIV YKCS11 MODULE YubicoYKCS11is a PKCS#11 module that allows external applications to communicate with the PIV application running on a YubiKey. This module is based on version 2.40 of the PKCS#11 (Cryptoki) specifications. The complete specifications are available at oasis-open.org > PKCS #11 Cryptographic Token Interface Base Specification Version 2.40. 4.1 Building YKCS11 is automatically built as part ofyubico-piv-tool. For example: $ mkdir build; cd build $ cmake .. $ make $ sudo make install For additional information about buildingyubico-piv-tool,Set up PIV Tool. After the yuvico-piv-tool is installed, the default location for the ykcs11 module is:/usr/local/lib/libykcs11.so. Optionally, you can be built it locally inyubico-piv-tool/build/ykcs11/libykcs11.so. 4.2 Portability The module has been developed and tested using Ubuntu Linux, MacOS, and Windows. Both MacOS and Windows use PCSC as a backend. 4.3 YKCS11 on Windows After installing yubico-piv-tool using the Windows installer, add theYubico PIV Tool\\bindirectory to the system path, so other applications can load it. This is also recommended, because thelibykcs11.dllis dynamically linked tolibykpiv.dllandlibcrypto-1\_1.dll, and setting the system path enablesykcs11to access both of them. On Windows 10, to set the system path: 1. Go toControl Panel > System and Security > System > Advanced system setting. 2. ClickEnvironment Variables. 3. Under System Variables, highlightPathand clickEdit. 4. ClickNewand add the absolute path toYubico PIV Tool\\bin. 15 YubiKey PIV Tool User Guide Alternatively, if you do not want to set the system path, copylibykpiv.dllandlibcrypto-1\_1.dllinto the same directory as the application that needs to access theykcs11module. 4.3.1 A Note for Developers IfLoadLibraryis called with an absolute path, it doesnotlook for dependencies of the specified DLL in that directory, but rather in the startup directory of the application that callsLoadLibrary. The solution is to either: •CallLoadLibraryExwith the flagLOAD\_WITH\_ALTERED\_SEARCH\_PATHfor absolute paths. •Add the directory where ykcs11 is located to the system PATH. •Copy the dependencies into the application directory. Note:CallingLoadLibraryExwith theLOAD\_WITH\_ALTERED\_SEARCH\_PATHflag for a non-absolute path is unde- fined behavior according to MicroSoft documentation. For example, Pkcs11Interop sets a variable toLOAD\_WITH\_ALTERED\_SEARCH\_PATHif the path looks absolute, and 0otherwise. After that, it always callsLoadLibraryEx. This means, if the flag is0thenLoadLibraryExbehaves exactly likeLoadLibrary. 4.4 Key Mapping Theykcs11module provides access to all 25 keys that can be stored on the YubiKey PIV application. These keys corre- spond to the keys in the PIV slots as described in PIV Certificate Slots and are accessible throughyubico-piv-tool. The mapping is as follows: ykcs11 idPIV 19a 29c 39d 49e 5 - 2482 - 95 25f9 4.5 Key Generation Key pair generation is a particular operation, in the sense that within PIV this is the only moment where the newly created public key is given back to the user. To prevent the key from being lost, it is automatically stored within the YubiKey by wrapping it in an X.509 certificate. 16Chapter 4. PIV YKCS11 Module YubiKey PIV Tool User Guide 4.6 Attestation Certificates Attestation certificates are also accessible with the YKCS11 module. An attestation certificate is a regular X509 Cer- tificates that has the same CKA\_ID and public key as the key it is attesting. Attestation certificates, however, are not stored in the YubiKey (CKA\_TOKEN is FALSE) and are generated when accessed. For more details about attestation, seePIV Tool AttestationandAction,attest. 4.7 User Types YKCS11 defines two types of users: a regular user and a security officer (SO). These are mapped to perform regular tasks for the private key material (PIN-associated operations) and device management (management-key associated operations). 4.8 PINs and Management Key •The default user PIN for the YubiKey is123456. •The default management key is010203040506070801020304050607080102030405060708. To perform operations involving the private keys, a regular user must be logged in (using the PIN or fingerprint). However, given the different PIN policies for different keys, subsequent operations might require a new login. This is supported by the module through theCONTEXT\_SPECIFICuser in accordance with the specifications. 4.9 Keys with PIN policy “never” It is possible to skip PIN verification when using keys with PIN policy “never” by usingVERIFY\_NONEas a PIN. 4.10 Fingerprint Authentication with YubiKey Bio It is also possible to use the fingerprint reader on the YubiKey Bio to login. Attempting to login with an empty PIN triggers a bio verification. The user is then expected to scan their fingerprint. Note: there might not be an indication on the screen that a fingerprint scan is expected, but the YubiKey blinks while it waits for a fingerprint scan. Bio verification can also be triggered by usingVERIFY\_BIOas a PIN. 4.11 OpenSSL The YubiKey only supports functions that require an asymmetric private key. Functions that do not, like encryption, signature verification, hashing and generation of a random number, are done by OpenSSL. Additionally, the YubiKey only performs raw decryption and signature. When padding is used, for example OAEP and PSS padding, applying and removing the padding is handled using OpenSSL functions. 4.6. Attestation Certificates17 YubiKey PIV Tool User Guide 4.12 Testing Apart from the internal tests, the YKCS11 has also been tested with the Pkcs11Interop .NET library. 4.13 Debugging By default, the ykcs11 module has debugging disabled. Debugging ishighlyverbose and might be confusing. To enable debugging of the ykcs11 module, set the variableYKCS11\_DBGto a numerical value1to9. The value0 indicates disabled debugging. SetYKCS11\_DBGfor debugging, using one of the methods: •Set the environment variableYKCS11\_DBG. •Rebuild the project as follows. The value2here is an example: $ mkdir build; cd build $ cmake .. -DYKCS11\_DBG=2 $ make $ sudo make install Alternatively, use PKCS#11 Spy as provided by OpenSC, to inspect the PKCS#11 communication. 4.14 YKCS11 Functions and Objects See the following tables of YKCS11 functions and objects. 4.14.1 Supported PKCS#11 Functions PKCS#11 FunctionMechanismComment C\_Initialize C\_Finalize C\_GetInfo C\_GetFunctionList C\_GetSlotList C\_GetSlotInfo C\_GetTokenInfo C\_GetMechanismList C\_GetMechanismInfo C\_InitToken C\_SetPIN C\_OpenSession C\_CloseSession C\_CloseAllSessions C\_GetSessionInfo C\_Login C\_Logout continues on next page 18Chapter 4. PIV YKCS11 Module YubiKey PIV Tool User Guide Table 1 – continued from previous page PKCS#11 FunctionMechanismComment C\_CreateObject With CKO\_PRIVATE\_KEY or CKO\_CERTIFICATE C\_DestroyObject C\_GetObjectSize C\_GetAttributeValue C\_FindObjectsInit C\_FindObjects C\_FindObjectsFinal C\_EncryptInit CKM\_RSA\_X\_509, CKM\_RSA\_PKCS, CKM\_RSA\_PKCS\_OAEP With RSA keys only. Uses OpenSSL encryption functions C\_Encrypt With RSA keys only. Uses OpenSSL encryption functions C\_EncryptUpdate With RSA keys only. Uses OpenSSL encryption functions C\_EncryptFinal With RSA keys only. Uses OpenSSL encryption functions C\_DecryptInit CKM\_RSA\_X\_509, CKM\_RSA\_PKCS, CKM\_RSA\_PKCS\_OAEP With RSA keys only. C\_DecryptWith RSA keys only. C\_DecryptUpdateWith RSA keys only. C\_DecryptFinalWith RSA keys only. C\_DigestInit CKM\_SHA\_1, CKM\_SHA256, CKM\_SHA384, CKM\_SHA512 Uses OpenSSL digest functions C\_Digest Uses OpenSSL digest functions continues on next page 4.14. YKCS11 Functions and Objects19 YubiKey PIV Tool User Guide Table 1 – continued from previous page PKCS#11 FunctionMechanismComment C\_DigestUpdate Uses OpenSSL digest functions C\_DigestFinal Uses OpenSSL digest functions C\_SignInit CKM\_RSA\_X\_509, CKM\_RSA\_PKCS, CKM\_SHA1\_RSA\_PKCS, CKM\_SHA256\_RSA\_PKCS, CKM\_SHA384\_RSA\_PKCS, CKM\_SHA512\_RSA\_PKCS, CKM\_RSA\_PKCS\_PSS, CKM\_SHA1\_RSA\_PKCS\_PSS, CKM\_SHA256\_RSA\_PKCS\_PSS, CKM\_SHA384\_RSA\_PKCS\_PSS, CKM\_SHA512\_RSA\_PKCS\_PSS, CKM\_ECDSA, CKM\_ECDSA\_SHA1, CKM\_ECDSA\_SHA224, CKM\_ECDSA\_SHA256, CKM\_ECDSA\_SHA384 CKM\_EDDSA C\_Sign C\_SignUpdate C\_SignFinal continues on next page 20Chapter 4. PIV YKCS11 Module YubiKey PIV Tool User Guide Table 1 – continued from previous page PKCS#11 FunctionMechanismComment C\_VerifyInit CKM\_RSA\_X\_509, CKM\_RSA\_PKCS, CKM\_SHA1\_RSA\_PKCS, CKM\_SHA256\_RSA\_PKCS, CKM\_SHA384\_RSA\_PKCS, CKM\_SHA512\_RSA\_PKCS, CKM\_RSA\_PKCS\_PSS, CKM\_SHA1\_RSA\_PKCS\_PSS, CKM\_SHA256\_RSA\_PKCS\_PSS, CKM\_SHA384\_RSA\_PKCS\_PSS, CKM\_SHA512\_RSA\_PKCS\_PSS, CKM\_ECDSA, CKM\_ECDSA\_SHA1, CKM\_ECDSA\_SHA224, CKM\_ECDSA\_SHA256, CKM\_ECDSA\_SHA384 CKM\_EDDSA Uses OpenSSL verification functions C\_Verify Uses OpenSSL verification functions C\_VerifyUpdate Uses OpenSSL verification functions C\_VerifyFinal Uses OpenSSL verification functions C\_GenerateKeyPair CKM\_RSA\_PKCS\_KEY\_PAIR\_GEN, CKM\_EC\_KEY\_PAIR\_GEN CKM\_EC\_EDWARDS\_KEY\_PAIR\_GEN CKM\_EC\_MONTGOMERY\_KEY\_PAIR\_GEN 4.14. YKCS11 Functions and Objects21 YubiKey PIV Tool User Guide 4.14.2 Supported PKCS#11 Objects Not all PKCS#11 Object types are implemented. This is a list of what is implemented and what it maps to. PKCS#11Supported CKKComment CKO\_PRIVATE\_KEY CKK\_RSA, CKK\_EC, CKK\_ED\_EDWARDS, CKK\_EC\_MONTGOMERY YubiKey 5.7 or later required for: RSA 1024, 2048, 3072, RSA 4096 with e=0x10001, EC with secp256r1 and secp384r1, ED2559, and X25519 CKO\_PUBLIC\_KEY Stored in X509 Certificates CKO\_CERTIFICATE X509 Certificates containing either the public key or the attestation certificate CKO\_DATA 4.14.3 Supported Attributes per Object Type AttributePrivate key object Public key object Certificate object Data object CKA\_CLASSXXXX CKA\_IDXXXX CKA\_TOKENXXXX CKA\_PRIVATEXXXX CKA\_LABELXXXX CKA\_APPLICATIONX CKA\_OBJECT\_IDX CKA\_MODIFIABLEXXXX CKA\_COPYABLEXXXX CKA\_DESTROYABLEXXXX CKA\_VALUEXX CKA\_SUBJECTX CKA\_ISSUERX CKA\_SERIALNUMBERX CKA\_CERTIFICATE\_TYPEX CKA\_TRUSTEDXX CKA\_KEY\_TYPEXX CKA\_SENSITIVEXX continues on next page 22Chapter 4. PIV YKCS11 Module YubiKey PIV Tool User Guide Table 2 – continued from previous page AttributePrivate key object Public key object Certificate object Data object CKA\_ALWAYS\_SENSITIVEXX CKA\_EXTRACTABLEXX CKA\_NEVER\_EXTRACTABLEXX CKA\_LOCALXX CKA\_ENCRYPTXX CKA\_DECRYPTXX CKA\_WRAPXX CKA\_WRAP\_WITH\_TRUSTEDXX CKA\_UNWRAPXX CKA\_SIGNXX CKA\_SIGN\_RECOVERXX CKA\_VERIFYXX CKA\_VERIFY\_RECOVERXX CKA\_DERIVEXX CKA\_MODULUSXX CKA\_EC\_POINTXX CKA\_EC\_PARAMSXX CKA\_MODULUS\_BITSXX CKA\_PUBLIC\_EXPONENTXX CKA\_ALWAYS\_AUTHENTICATEXX 4.14.4 Key Alias per Slot and Object Type Some applications, mainly Java, specify the keys to use by their key alias, which is referred to as a key’s label by PKCS#11. Objects’ labels as access by YKCS11 are fixed values and are unmodifiable. Following is the list of object labels according to their object type and the slot they reside in (See PIV Certificate Slots for the slot usage). SlotPrivate keyPublic keyCertificateAttestation certificate Data object 9a Private key for PIV Authentication Public key for PIV Authentication X.509 Certificate for PIV Authentication X.509 Certificate for PIV Attestation 9a X.509 Certificate for PIV Authentication 9c Private key for Digital Signature Public key for Digital Signature X.509 Certificate for Digital Signature X.509 Certificate for PIV Attestation 9c X.509 Certificate for Digital Signature continues on next page 4.14. YKCS11 Functions and Objects23 YubiKey PIV Tool User Guide Table 3 – continued from previous page SlotPrivate keyPublic keyCertificateAttestation certificate Data object 9d Private key for Key Management Public key for Key Management X.509 Certificate for Key Management X.509 Certificate for PIV Attestation 9d X.509 Certificate for Key Management 9e Private key for Card Authentication Public key for Card Authentication X.509 Certificate for Card Authentication X.509 Certificate for PIV Attestation 9a X.509 Certificate for Card Authentication 82 Private key for Retired Key 1 Public key for Retired Key 1 X.509 Certificate for Retired Key 1 X.509 Certificate for PIV Attestation 82 X.509 Certificate for Retired Key 1 83 Private key for Retired Key 2 Public key for Retired Key 2 X.509 Certificate for Retired Key 2 X.509 Certificate for PIV Attestation 83 X.509 Certificate for Retired Key 2 84 Private key for Retired Key 3 Public key for Retired Key 3 X.509 Certificate for Retired Key 3 X.509 Certificate for PIV Attestation 84 X.509 Certificate for Retired Key 3 85 Private key for Retired Key 4 Public key for Retired Key 4 X.509 Certificate for Retired Key 4 X.509 Certificate for PIV Attestation 85 X.509 Certificate for Retired Key 4 86 Private key for Retired Key 5 Public key for Retired Key 5 X.509 Certificate for Retired Key 5 X.509 Certificate for PIV Attestation 86 X.509 Certificate for Retired Key 5 continues on next page 24Chapter 4. PIV YKCS11 Module YubiKey PIV Tool User Guide Table 3 – continued from previous page SlotPrivate keyPublic keyCertificateAttestation certificate Data object 87 Private key for Retired Key 6 Public key for Retired Key 6 X.509 Certificate for Retired Key 6 X.509 Certificate for PIV Attestation 87 X.509 Certificate for Retired Key 6 88 Private key for Retired Key 7 Public key for Retired Key 7 X.509 Certificate for Retired Key 7 X.509 Certificate for PIV Attestation 88 X.509 Certificate for Retired Key 7 89 Private key for Retired Key 8 Public key for Retired Key 8 X.509 Certificate for Retired Key 8 X.509 Certificate for PIV Attestation 89 X.509 Certificate for Retired Key 8 8a Private key for Retired Key 9 Public key for Retired Key 9 X.509 Certificate for Retired Key 9 X.509 Certificate for PIV Attestation 8a X.509 Certificate for Retired Key 9 8b Private key for Retired Key 10 Public key for Retired Key 10 X.509 Certificate for Retired Key 10 X.509 Certificate for PIV Attestation 8b X.509 Certificate for Retired Key 10 8c Private key for Retired Key 11 Public key for Retired Key 11 X.509 Certificate for Retired Key 11 X.509 Certificate for PIV Attestation 8c X.509 Certificate for Retired Key 11 8d Private key for Retired Key 12 Public key for Retired Key 12 X.509 Certificate for Retired Key 12 X.509 Certificate for PIV Attestation 8d X.509 Certificate for Retired Key 12 continues on next page 4.14. YKCS11 Functions and Objects25 YubiKey PIV Tool User Guide Table 3 – continued from previous page SlotPrivate keyPublic keyCertificateAttestation certificate Data object 8e Private key for Retired Key 13 Public key for Retired Key 13 X.509 Certificate for Retired Key 13 X.509 Certificate for PIV Attestation 8e X.509 Certificate for Retired Key 13 8f Private key for Retired Key 14 Public key for Retired Key 14 X.509 Certificate for Retired Key 14 X.509 Certificate for PIV Attestation 8f X.509 Certificate for Retired Key 14 90 Private key for Retired Key 15 Public key for Retired Key 15 X.509 Certificate for Retired Key 15 X.509 Certificate for PIV Attestation 90 X.509 Certificate for Retired Key 15 91 Private key for Retired Key 16 Public key for Retired Key 16 X.509 Certificate for Retired Key 16 X.509 Certificate for PIV Attestation 91 X.509 Certificate for Retired Key 16 92 Private key for Retired Key 17 Public key for Retired Key 17 X.509 Certificate for Retired Key 17 X.509 Certificate for PIV Attestation 92 X.509 Certificate for Retired Key 17 93 Private key for Retired Key 18 Public key for Retired Key 18 X.509 Certificate for Retired Key 18 X.509 Certificate for PIV Attestation 93 X.509 Certificate for Retired Key 18 94 Private key for Retired Key 19 Public key for Retired Key 19 X.509 Certificate for Retired Key 19 X.509 Certificate for PIV Attestation 94 X.509 Certificate for Retired Key 19 continues on next page 26Chapter 4. PIV YKCS11 Module YubiKey PIV Tool User Guide Table 3 – continued from previous page SlotPrivate keyPublic keyCertificateAttestation certificate Data object 95 Private key for Retired Key 20 Public key for Retired Key 20 X.509 Certificate for Retired Key 20 X.509 Certificate for PIV Attestation 95 X.509 Certificate for Retired Key 20 f9 Private key for PIV Attestation Public key for PIV Attestation X.509 Certificate for PIV Attestation X.509 Certificate for PIV Attestation f9 X.509 Certificate for PIV Attestation 4.15 YKCS11 Supported Applications The YKCS11 module was tested with the following applications: •FireFox •Fortify •Java Keytool •OpenSC pkcs11-tool •OpenSSH •OpenSSL via PKCS11 Engine 4.15.1 FireFox With FireFox, it is possible to authenticate to websites and other web services with certificates stored on a smartcard and accessed through a PKCS#11 module. In order to do that, the PKCS#11 module needs to be added to FireFox as a Security Device. However, in order for FireFox to recognize the certificate in the smartcard, it needs to have previously imported its issuer certificate (typically a CA certificate) as a trusted authority. 4.15. YKCS11 Supported Applications27 YubiKey PIV Tool User Guide 4.15.1.1 Importing CA Certificate on FireFox 1. Open FireFox Certificate Manager. Go toPreferences→Privacy & Security→View Certificates. Select Privacy & Security View Certificates 2. Go toAuthoritiesand clickImport. Import Authority 3. Navigate to the issuer certificate and choose it. 28Chapter 4. PIV YKCS11 Module YubiKey PIV Tool User Guide 4.15. YKCS11 Supported Applications29 YubiKey PIV Tool User Guide 30Chapter 4. PIV YKCS11 Module YubiKey PIV Tool User Guide 4.15.1.2 Adding YKCS11 Security Device on FireFox 1. Open FireFox Device Manager. Go toPreferences→Privacy & Security→Security Devices. View Security Devices 2. ClickLoad. Load Security Devices 3. Choose a name for the YKCS11 module, navigate to libykcs11.so, and choose it, then click OK. Security Devices Load Driver The YKCS11 module should now appear in the Security devices column on the left. Device Manager Listing for Yubico Information 4.15.1.3 Viewing and Downloading a Certificate on FireFox Caution:If the certificate issuer is not trusted (aka not imported) by FireFox, the certificate details only show an error message. 1. Open FireFox Certificate Manager. Go toPreferences→Privacy & Security→View Certificates. 2. Highlight the certificate and clickView. The certificate details are displayed in a FireFox tab. Certificate Manager View 3. To download the certificate, find the download link in the certificate details tab. It is possible to download only the certificate or the entire certificate chain in PEM format. Certificate Information Download 4.15.1.4 Other Functionality on FireFox With FireFox, it is possible to access and download the certificate. It is also possible to change the PIV user pin with theChange Passwordbutton in the Certificate Manager. Generally, FireFox has functionality to export the private key (with theBackupbutton in the Certificate Manager). This, however, fails because the YubiKey does not allow the private key to leave it. Deleting a key through FireFox does not work either unless the user is logged in as an SO user. 4.15.2 Fortify Fortify is a locally installed application that listens on a known TCP port and enables web applications to use smart cards, security tokens, and locally installed certificates. Fortify has native support for YubiKey’s PIV interface through the YKCS11 module. 1. Go to fortifyapp.com to download and then install the application specific to your platform. 2. When running the application, a small shield-shaped icon close to thestart menushould appear. 3. Verify matching codes. 4.15. YKCS11 Supported Applications31 YubiKey PIV Tool User Guide 32Chapter 4. PIV YKCS11 Module YubiKey PIV Tool User Guide 4.15. YKCS11 Supported Applications33 YubiKey PIV Tool User Guide a. Click the Fortify icon and go toTools. A browser opens with the Fortify webapp interface. Fortify Tools Menu b. You are presented with a code inside the webpage and a code outside of it. If the codes match, click Approve. Fortify Interface Verification 4. View stored YubiKey certificates. In the Fortify web interface: a. Select the Yubico provider. Fortify Select Provider b. At the prompt, enter the PIN of the PIV user. Fortify PIN c. In the panel, view the list of certificates stored in the YubiKey. Fortify View Certificates 4.15.2.1 Tips for using Fortify Fortify expects to find the YKCS11 module in the following locations: •MacOS:/usr/local/lib/libykcs11.dylib •Linux:/usr/local/lib/libykcs11.so •Windows:%WINDIR/System32/libykcs11-1.dll The paths are specified in a file calledcard.json. On a Linux system, this file might reside in$HOME/.fortify/ card.json. 34Chapter 4. PIV YKCS11 Module YubiKey PIV Tool User Guide 4.15. YKCS11 Supported Applications35 YubiKey PIV Tool User Guide 36Chapter 4. PIV YKCS11 Module YubiKey PIV Tool User Guide 4.15. YKCS11 Supported Applications37 YubiKey PIV Tool User Guide 38Chapter 4. PIV YKCS11 Module YubiKey PIV Tool User Guide 4.15.3 Java Keytool The YKCS11 module can be used with Java keytool through the SunPKCS11 provider that is shipped with Java by default. To configure the SunPKCS11 provider to use the YKCS11, create a configuration file, let’s call itsun\_ykcs11. conf, with the following content: name = ykcs11 library = /path/to/libykcs11.so The name is an arbitrary string. This configuration file should then be used as the provider’s argument parameter in the command line. 4.15.3.1 List Content $ keytool -list -keystore NONE -storetype PKCS11 -providerClass sun.security.pkcs11.SunPKCS11 -providerArg /path/to/sun\_ykcs11.conf Where – -keystore NONEindicates that the keys are not stored in a soft token, aka not a file. -storetype PKCS11indicates that the keys are accessible through the PKCS#11 interface. 4.15.3.2 Signing a JAR File To sign a jar file usingjarsigner, specify the alias of the signing key. The aliases of the keys stored on the YubiKey PIV are fixed and unmodifiable. To view the list of key aliases: •Use the YubiKey command,keytool -list, shown in Example 1 above. •SeeYKCS11 Functions and Objects. Example of signing a jar file with the key on slot 9c: $ jarsigner -keystore NONE -storetype PKCS11 -providerClass sun.security.pkcs11.SunPKCS11 -providerArg /path/to/sun\_ykcs11.conf lib.jar "X.509 Certificate for Digital Signature" To display PKCS11 debug messages, add the parameter-J-Djava.security.debug=sunpkcs11: $ jarsigner -verify -keystore NONE -storetype PKCS11 -providerClass sun.security.pkcs11.SunPKCS11 -providerArg /path/to/sun\_ykcs11.conf lib.jar "X.509 Certificate for Digital Signature" -J-Djava.security.debug=sunpkcs11\\ The jarsigner command returns two files appearing under META-INF inside the jar file. One of them has the ending .SFand the other has the ending.ECor.RSAdepending on the key type of the signing key. To verify the signature of a jar file, run: $ jarsigner -verify -keystore NONE -storetype PKCS11 -providerClass sun.security.pkcs11.SunPKCS11 -providerArg /path/to/sun\_ykcs11.conf lib.jar "X.509 Certificate for Digital Signature" 4.15. YKCS11 Supported Applications39 YubiKey PIV Tool User Guide 4.15.4 OpenSC pkcs11-tool The YKCS11 module works well withpkcs11-tool. Be aware though that older versions of OpenSC (like the ones available on Linux distributions) might produce errors when running some commands. If so, try again after installing a newer version. 4.15.4.1 Display Device Info $ pkcs11-tool --module /path/to/libykcs11.so --show-info 4.15.4.2 Key Generation Only the SO user is permitted to generate keys. The SO’s PIN is the PIV management key. •Generate an EC key in slot 9A using curvesecp384r1 $ pkcs11-tool --module /path/to/libykcs11.so --login --login-type so --keypairgen --id 1 --key-type EC:secp384r1 •Generate an EC key in slot 9E using curveprime256v1 $ pkcs11-tool --module /path/to/libykcs11.so --login --login-type so --keypairgen --id 4 --key-type EC:prime256v1 •Generate an RSA key in slot 9C $ pkcs11-tool --module /path/to/libykcs11.so --login --login-type so --keypairgen --id 2 --key-type rsa:2048 4.15.4.3 Signing Signatures generated usingpkcs11-toolcan be verified using, for example,openssl. To verify the signature withopenssl, the public key needs to be extracted from the certificate. To do that, complete the steps: 1. Export the certificate from the YubiKey using the YubiKey Manager,ykman,yubico-piv-tool, FireFox or any other available tool. 2. If the certificate is not inPEMformat, convert it intoPEMformat. 3. Extract the public key from the certificate. Run the following command: $ openssl x509 -in cert.pem -pubkey -noout > pubkey.pem The following are a few command line examples of signing data withpkcs11-tooland verifying the signature with openssl. •Sign data with an RSA key in slot 9E. $ pkcs11-tool --module /path/to/libykcs11.so --sign --id 4 -i data.txt -o data.sig $ openssl rsautl -verify -in data.sig -inkey 9e\_pubkey.pem -pubin •Sign data with an RSA key in slot 9C and SHA256. 40Chapter 4. PIV YKCS11 Module YubiKey PIV Tool User Guide $ pkcs11-tool --module /path/to/libykcs11.so --sign -m RSA-SHA256 --id 2 -i data.txt -o data.sig $ openssl dgst -sha256 -verify 9c\_pubkey.pem -signature data.sig data.txt •Signing data with an EC key in slot 9A and SHA1. $ pkcs11-tool --module /path/to/libykcs11.so --sign --id 1 -m ECDSA-SHA1 --signature-format openssl -i data.txt -o data.sig $ openssl dgst -sha1 -verify 9a\_pubkey.pem -signature data.sig data.txt 4.15.4.4 Testing RSA Keys At least one RSA key needs to already exist in the YubiKey for this test to work. $ pkcs11-tool --module /path/to/libykcs11.so --login --test 4.15.4.5 Testing EC Keys With the default installation of the YubiKey’s PIV, testing EC keys works only on slot 9C. This is becausepkcs11-tool --test-ecassumes that the same user can both generate a keypair and sign data. This, however, is not allowed by the YubiKey, which implements separation of duty more strictly. By default, however, the key that resides on slot 9C has its CKA\_ALWAYS\_AUTHENTICATEattribute set to True, which prompts the user for the PIN during the different operations, and so the right PIN can be entered at the right time. $ pkcs11-tool --module /path/to/libykcs11.so --login --login-type so --test-ec --id 2 --key-type EC:secp256r1 4.15.5 OpenSSH Keys stored on the YubiKey can be used to login to remote SSH servers. This can be done either with the YubiKey PIV application using, for example, OpenSSH, or with the YubiKey PGP application. Following are some command line examples of using OpenSSH with the Yubikey PIV application through YKCS11. For guides on how to use the YubiKey PGP application with SSH, see SSH authentication. To direct OpenSSH to use keys stored on the YubiKey, specify the YKCS11 module with the-Ioption in the command. $ ssh -I /path/to/libykcs11.so git@github.com To download the public key accessible through the YKCS11 module: $ ssh-keygen -D /path/to/libykcs11.so 4.15. YKCS11 Supported Applications41 YubiKey PIV Tool User Guide 4.15.6 OpenSSL via PKCS11 Engine The easiest way to get OpenSSL to work with YKCS11 viaengine\_pkcs11is by using thepll-kitproxy module. To get the OpenSSL PKCS11 engine to use the Yubico YKCS11 module specifically, set the environment variable PKCS11\_MODULE\_PATHto point tolibykcs11.somodule. For more details on PKCS11 engine, see OpenSC libp11. For more details on how to configure OpenSSL PKCS11 engine for Yubico supported modules, see OpenSSL with YubiHSM 2 via engine\_pkcs11 and yubihsm\_pkcs11. 4.15.6.1 Data Signing with OpenSSl $ PKCS11\_MODULE\_PATH=/path/to/libykcs11.so openssl rsautl -engine pkcs11 -keyform engine␣ ˓→-inkey "pkcs11:object=Private key for PIVAuthentication;type=private" -sign -in data. ˓→txt -out data.sig Where –object=Private key for PIVAuthenticationspecifies the alias (or label) of the private key to be used. The aliases of the keys stored on the YubiKey PIV are fixed and unmodifiable. SeeYKCS11 Functions and Objects. type=private specifies that the type of the objectisa private key (CKA\_CLASS = CKO\_ ˓→PRIVATE\_KEY) For more parameters to specify keys see RFC7512. Caution:Be aware that the order of the parameters in the command line can be important. 42Chapter 4. PIV YKCS11 Module CHAPTER FIVE PIV TOOL ATTESTATION This feature is only available in YubiKey 4.3 and above. 5.1 What is Attestation The YubiKey is able to create an attestation statement in the form of an X.509 certificate. This provides evidence that a certain key was generated on a YubiKey. The certificate can be validated up to Yubico Root CA to prove authenticity and validity. The returned attestation statement is in the form of a PEM encoded X.509 certificate, signed by a key stored in PIV slot f9 on the YubiKey. For more information on attestation, see Yubico content: •Developer documentation, PIV attestation •.NET YubiKey SDK: User’s Manual, PIV attestation statements 5.2 Getting and Verifying Attestation Certificates Each YubiKey comes with a pre-loaded key and certificate. The certificate is signed by Yubico Root Certificate Au- thority (CA). The pre-loaded key and certificate can be replaced by overriding the content of the slot. Important:If the pre-loaded Yubico factory-issued key or certificate is overwritten, it cannot be restored - even a factory reset does not recover the data. The OpenSSL method listed below is an example for verifying the certificate and validating with the Yubico Root CA. This method is for testing the concept of attestation verification only. Important:Yubico recommends using production level evaluation for production verification. The following steps assume that the pre-loaded certificate and key in PIV slot f9 have not been overwritten. If they have been overwritten, you need to replace the certificate chain with your own - the one you used for the new key and certificate. To get and verify an attestation statement: 1. Get and install Yubico PIV Tool for your platform. Make note of the folder/directory where you install the PIV tool. For example, on Windows that folder might be: C:\\Program Files\\Yubico\\Yubico PIV Tool\\bin. 43 YubiKey PIV Tool User Guide The Yubico PIV tool launches automatically launches when your run ayubico-piv-toolcommand. For ex- ample: yubico-piv-tool --version When you run theyubico-piv-tool, make sure the your platform can access and understand the command: •Add the install directory to PATH or navigate to the installation folder/directory. •You might need to add the./prefix to the command. This tells the system to run the command from the current folder/directory. •If you are using PowerShell, add the file extension,.exe, to the PIV tool executable,yubico-piv-tool. exe. 2. Get an attestation statement (X.509 certificate) for a slot. yubico-piv-tool --action=attest --slot=9a --out \\ ˓→Slot9aAttestation.pem Where – is where the command stores the attestation statement. 9ais an example for the slot on the YubiKey that contains the key you generated and want to attest. See--slot command inPIV Tool Optionsfor possible slots. Note:The attestation fails when there is no key in the designated slot (slot 9a) or if the key in the slot was imported. Error message:Failed to attest data. 3. Get the intermediate CA from slotf9of the YubiKey. yubico-piv-tool --action=read-certificate --slot=f9 --out \\ ˓→SlotF9Intermediate.pem Where – is where the command stores the intermediate CA. f9is the slot on the YubiKey with the pre-loaded intermediate certificate. See--slotcommand inPIV Tool Optionsfor possible slots. 4. Determine the firmware version of your YubiKey. yubico-piv-tool --action=version 5. Download the certificate(s) appropriate for your YubiKey firmware version. •For pre-5.7.4 firmware, download the root certificate: Yubico PIV Root CA Serial 263751 •For 5.7.4 or newer firmware, download the certificate chain: Yubico Attestation Root 1 and Intermediate Certificates Note: •Record where the files are stored. •Make sure the files are saved with the correct file extension.pem(and not .pem.txt or .txt)! 44Chapter 5. PIV Tool Attestation YubiKey PIV Tool User Guide 6. Download and install openssl for your platform. See the openssl documentation for details. Note:These commands don’t work with OpenSSL 1.1.0 on YubiKey 4 series products. To verify certificate chains for such devices, see PIV Attestation Verification Fails with OpenSSL 1.1.0. 7. Verify the attestation certificate using the command appropriate for your YubiKey firmware version. •For pre-5.7.4 firmware openssl verify -CAfile \\yubico-piv-ca-1.pem -untrusted \\SlotF9Intermediate.pem \\Slot9aAttestation.pem •For 5.7.4 and newer firmware openssl verify -CAfile \\yubico-ca-1.pem -untrusted \\yubico-intermediate.pem -untrusted \\ ˓→SlotF9Intermediate.pem \\Slot9aAttestation.pem Where –,, andare the locations of the stored Yubico CA, intermediate, and attestation.pemfiles identified in Step 1 to Step 5. Expected result: Slot9Aattestation.pem: OK 5.2. Getting and Verifying Attestation Certificates45 YubiKey PIV Tool User Guide 46Chapter 5. PIV Tool Attestation CHAPTER SIX PIV TOOL COMMAND, OPTIONS AND ACTIONS 6.1 yubico-piv-tool \[Option\] ... Use the PIV tool command options. 6.1.1 PIV Tool Options OptionDescriptionPossible Values and/or Default -h,--helpPrint help and exit -a, --action ENUM Action to take. SeePIV Tool action Command Parameters for descriptions of actions. attest,change-pin,change-puk, delete-certificate,delete-key, generate,import-certificate,import-key, list-readers,move-key,pin-retries, read-certificate,read-object, read-public-key,request-certificate, reset,selfsign-certificate,set-ccc, set-chuid,set-mgm-key,sign-data, status,test-decipher,test-signature, unblock-pin,verify-bio,verify-pin, version,write-object Multiple actions may be given at once and are executed in order, for example: --action=verify-pin --action=request-certificate continues on next page 47 YubiKey PIV Tool User Guide Table 1 – continued from previous page OptionDescriptionPossible Values and/or Default -A, --algorithm ENUM The algorithm to use to generate the key pair. RSA1024,RSA2048,ECCP256,ECCP384 Values that require YubiKey 5.7 or newer: RSA3072,RSA4096,ED25519,X25519 Default:RSA2048 --attestationAdd attestation cross-signature. Default:off --compressCompress a large certificate using GZIP before import. Default:off --encCommunication with the YubiKey is done over an encrypted channel. Default:off -f, --format ENUM Format of data for write/read object. hex,base64,binary Default:hex -full-helpPrint help, including hidden options, and exit. -globalReset the whole device over all applications, including the PIV application. Default:off -H, --hash ENUM Hash to use for signatures.SHA1,SHA256,SHA384,SHA512. Default:SHA256 continues on next page 48Chapter 6. PIV Tool Command, Options and Actions YubiKey PIV Tool User Guide Table 1 – continued from previous page OptionDescriptionPossible Values and/or Default -i, --input STRING Filename to use as input. If left out, input is read fromstdin. None forstdinor filename. Default:-for stdin The only supported format for public key is PEM. --id INTThe ID of the object to write/read according to PIV Specifications -k, --key STRING Management key to use. If no value is specified, PIV tool prompts for value Default: See Note2 -K, --key-format ENUM Format of the key being read/written. PEM,PKCS12,GZIP,DER,SSH Default:PEM -m, --new-key-algo ENUM New management key algorithm to use for the action, set-mgm-key. AES128,AES192,AES256,TDES Default:TDES -n, --new-key STRING New management key to use for the action,set-mgm-key. If omitted, PIV tool prompts for key. -N, --new-pin STRING New PIN/PUK code changing to. If omitted, PIV tool prompts for PIN/PUK. continues on next page 6.1. yubico-piv-tool \[Option\] ...49 YubiKey PIV Tool User Guide Table 1 – continued from previous page OptionDescriptionPossible Values and/or Default -o, --output STRING Filename to use as output or certificate file. If not specified, output is printed tostdout. None forstdoutor filename. Default:-forstdout -p, --password STRING Password for decryption of private key file. If omitted, PIV tool prompts for password -P, --pin STRING PIN/PUK code for verification. If omitted, PIV tool prompts for PIN/PUK --pin-policy ENUM Set pin policy for actions: generateor import-key. Only available on YubiKey 4 or newer. Values PIN key verification: never,once,always Value BIO key verification: matchonce,matchalways Default: slot 9c,always slot 9a, 9d and 9e,once remaining slots,never --pin-retries INT Number of retries before the PIN code is blocked. --puk-retries INT Number of retries before the PUK code is blocked. -r, --reader STRING Only use a matching reader. Default:Yubikey continues on next page 50Chapter 6. PIV Tool Command, Options and Actions YubiKey PIV Tool User Guide Table 1 – continued from previous page OptionDescriptionPossible Values and/or Default -s, --slot ENUM The key slot to operate on. See Note1 9a,9c,9d,9e,82,83, 84,85,86,87,88,89, 8a,8b,8c,8d,8e,8f, 90,91,92,93,94,95, f9 where - 9afor PIV Authentication. 9cfor Digital Signature (PIN always checked). 9dfor Key Management. 9efor Card Authentication (PIN never checked). 82-95for Retired Key Management. f9for Attestation. -S, --subject STRING The subject to use for certificate request. The string must be written as: /CN=host.example.com/OU=test/O=example. com/ --scp11Use encrypted communication in accordance with SCP11b. DEPRECATED as of yubico-piv-tool v2.7.2. Use the--encflag. --serial INTSerial number of the self- signed certificate --to-slot ENUMThe slot to move an existing key to. See Note1 9a,9c,9d,9e,82,83, 84,85,86,87,88,89, 8a,8b,8c,8d,8e,8f, 90,91,92,93,94,95, f9 where - 9afor PIV Authentication. 9cfor Digital Signature (PIN always checked). 9dfor Key Management. 9efor Card Authentication (PIN never checked). 82-95for Retired Key Management. f9for Attestation. continues on next page 6.1. yubico-piv-tool \[Option\] ...51 YubiKey PIV Tool User Guide Table 1 – continued from previous page OptionDescriptionPossible Values and/or Default --touch-policy ENUM Set touch policy for the slot containing the key. Applies to the actions: generate,import-key orset-mgm-key. Requires YubiKey 4 or newer. never,always,caches Default:never -v, --verbose INT Print more information. Default:0 -V,--versionPrint version and exit. --valid-days INT Time (in days) until the self-signed certificate expires. Default:365 (1)For additional information on slot values, see PIV Certificate Slots. (2)--keyvalue default:010203040506070801020304050607080102030405060708. 6.2 PIV Tool action Command Parameters 6.2.1 Syntax yubico-piv-tool --action ENUM ... yubico-piv-tool -aENUM ... 52Chapter 6. PIV Tool Command, Options and Actions YubiKey PIV Tool User Guide 6.2.2 Description The tables lists the possible actions for the PIV tool command option--action ENUM. WhereENUMis replaced with options from the table. See the balance of this chapter for additional usage information. 6.2.3 Parameters ActionDescription attest Generate an X509 certificate for an asymmetric key that was generated inside the YubiKey. change-pin Change the PIN code required to access the PIV interface. change-puk Change the PUK. delete-cert, delete-certificate Delete a certificate from a specific slot. delete-key Delete a key from a specific slot. generate Generate an RSA or an EC key on a specific slot. import-cert, import-certificate Import an X509 certificate into a specific slot. import-key Import a private key into a specific slot. list-readers List the accessible smart card readers. move-keyMove a key between slots. pin-retries Change the number of retries allowed before the PIN or the PUK are blocked. read-cert, read-certificate Return the X509 certificate stored on a specific slot. continues on next page 6.2. PIV Tool action Command Parameters53 YubiKey PIV Tool User Guide Table 2 – continued from previous page ActionDescription read-object Return the content of a slot. read-public-key Return the public key stored on a specific slot. request, request-certificate Generate a certification request for an asymmetric key stored on a specific slot. Seegenerate. resetReset the YubiKey PIV interface. selfsign, selfsign-certificate Generate a self signed X509 certificate for an asymmetric key stored on a specific slot. Seegenerate. set-cccSet a new CCC. set-chuid Set or change the Card Holder Unique Identifier. set-mgm-key Set the management key required to perform administrative actions on the PIV interface. sign sign-data Sign input data. status Return the device metadata and content. test-decipher Test the decryption function. test-signature Test the digital signing function. unblock-pin Set a new PIN code after entered incorrectly too many times. verify-bio Verify the PIN code required to access the PIV interface on a bio Yubikey. Seegenerate. continues on next page 54Chapter 6. PIV Tool Command, Options and Actions YubiKey PIV Tool User Guide Table 2 – continued from previous page ActionDescription verify, verify-pin Verify the PIN code required to access the PIV interface. Seegenerate. versionReturn the device firmware version. write-objectStore an object in a slot. Seeread-object. —————————————————————————————————————————- 6.3 attest 6.3.1 Syntax yubico-piv-tool --action=attest --slot ENUM --output=\[STRING\] yubico-piv-tool -a attest 6.3.2 Description The attestation,attest, feature is only available in YubiKey 4.3 and above. Generate an X509 certificate for an asymmetric key that was generated inside the YubiKey. •See attestation in this guide,PIV Tool Attestation. •See attestation with a developer’s product, PIV Attestation. 6.3.3 Examples yubico-piv-tool --action=attest --slot=f9 --out SlotF9Intermediate.pem 6.3. attest55 YubiKey PIV Tool User Guide 6.3.4 Parameters ParameterRequired Optional DescriptionPossible values, Default -s, --slot ENUM RequiredThe key slot to operate on. See Note1 9a,9c,9d,9e,82,83, 84,85,86,87,88,89, 8a,8b,8c,8d,8e,8f, 90,91,92,93,94,95, f9 where - 9afor PIV Authentication. 9cfor Digital Signature (PIN always checked). 9dfor Key Management. 9efor Card Authentication (PIN never checked). 82-95for Retired Key Management. f9for Attestation. -o, --output STRING RequiredFilename to use as output or certificate file. If not specified, output is printed tostdout. None forstdoutor filename. Default:-forstdout (1)For additional information on slot values, see PIV Certificate Slots. —————————————————————————————————————————- 6.4 change-pin 6.4.1 Syntax yubico-piv-tool --action=change-pin --new-pin STRING yubico-piv-tool -a change-pin -N 56Chapter 6. PIV Tool Command, Options and Actions YubiKey PIV Tool User Guide 6.4.2 Description Change the Personal Identification Number (PIN) code required to access the PIV interface. 6.4.3 Parameters ParameterRequired Optional DescriptionPossible values, Default -N, --new-pin STRING RequiredNew PIN/PUK code changing to. If omitted, PIV tool prompts for PIN/PUK. —————————————————————————————————————————- 6.5 change-puk 6.5.1 Syntax yubico-piv-tool --action=change-puk --new-pin STRING yubico-piv-tool -a change-puk -N 6.5.2 Description Change the Personal Unblocking Key (PUK). 6.5. change-puk57 YubiKey PIV Tool User Guide 6.5.3 Parameters ParameterRequired Optional DescriptionPossible values, Default -N, --new-pin STRING RequiredNew PIN/PUK code changing to. If omitted, PIV tool prompts for PIN/PUK. —————————————————————————————————————————- 6.6 delete-certificate 6.6.1 Syntax yubico-piv-tool --action=delete-certificate --slot ENUM --key \[STRING\] yubico-piv-tool -a delete-certificate -s ENUM -k \[STRING\] 6.6.2 Description Deletes a certificate from the specified slot. The corresponding private key is not deleted unless it is overwritten. Deleting a certificate requires authentication by providing the management key. If no management key is provided, the PIV tool attempts authentication using the default management key. Important:It is strongly recommended you change the Yubikey PIN, PUK, and management key before you start using the Yubikey. 6.6.3 Examples $ yubico-piv-tool -a delete-certificate -s -k 58Chapter 6. PIV Tool Command, Options and Actions YubiKey PIV Tool User Guide 6.6.4 Parameters ParameterRequired Optional DescriptionPossible values, Default -s, --slot ENUM RequiredThe key slot to operate on. See Note1 9a,9c,9d,9e,82,83, 84,85,86,87,88,89, 8a,8b,8c,8d,8e,8f, 90,91,92,93,94,95, f9 where - 9afor PIV Authentication. 9cfor Digital Signature (PIN always checked). 9dfor Key Management. 9efor Card Authentication (PIN never checked). 82-95for Retired Key Management. f9for Attestation. -k, --key STRING RequiredManagement key to use. If no value is specified, PIV tool prompts for value Default: See Note2 (1)For additional information on slot values, see PIV Certificate Slots. (2)--keyvalue default:010203040506070801020304050607080102030405060708. —————————————————————————————————————————- 6.6. delete-certificate59 YubiKey PIV Tool User Guide 6.7 delete-key 6.7.1 Syntax $ yubico-piv-tool -a delete-key -s -k 6.7.2 Description Deletes a key from the specified PIV slot. The function requires YubiKey 5.7 or higher. Note:This actions deletes only the key, not the certificate. So if the slot already stores a certificate, it might still look populated even if the key is no longer there. Deleting a key is an action that requires authentication, which is done by providing the management key. If no man- agement key is provided, the tool tries to authenticate using the default management key. Important:It is strongly recommended you change the Yubikey PIN, PUK, and management key before you start using the Yubikey. 6.7.3 Examples $ yubico-piv-tool -a delete-key -s 9c -k Enter Password: Enter management key: Successfully deleted key. 60Chapter 6. PIV Tool Command, Options and Actions YubiKey PIV Tool User Guide 6.7.4 Parameters ParameterRequired Optional DescriptionPossible values, Default -s, --slot ENUM RequiredThe key slot to operate on. See Note1 9a,9c,9d,9e,82,83, 84,85,86,87,88,89, 8a,8b,8c,8d,8e,8f, 90,91,92,93,94,95, f9 where - 9afor PIV Authentication. 9cfor Digital Signature (PIN always checked). 9dfor Key Management. 9efor Card Authentication (PIN never checked). 82-95for Retired Key Management. f9for Attestation. -k, --key \[STRING\] RequiredManagement key to use. If no value is specified, PIV tool prompts for value Default: 010203040506070801020304050607080102030405060708 (1)For additional information on slot values, see PIV Certificate Slots. —————————————————————————————————————————- 6.8 generate 6.8.1 Syntax $ yubico-piv-tool -a generate -s -k \[ -A -o \] $ yubico-piv-tool -a verify-pin -a selfsign -s -S \[ -P -- ˓→pin-policy --touch-policy ˓→ -i --serial --valid-days␣ (continues on next page) 6.8. generate61 YubiKey PIV Tool User Guide (continued from previous page) ˓→DAYS -o \] $ yubico-piv-tool -a verify-pin -a request-certificate -s -S \[ -P ˓→ -i -o \] $ yubico-piv-tool -a import-certificate -s -k \[ -o \] 6.8.2 Description Generate an RSA or an EC key on a specific slot. This requires a sequence of action commands. Completed key generation can includegenerate,selfsign,request-certificate,verify-pinorverify-bio, and import-certificate. An occupied slot on the Yubikey PIV interface usually contains a private key, a public key and an X509 certificate. The key pair generate, the certificate generation and the certificate import are done using different actions in the right order. Generating a key pair sets the public key as an output (actiongenerate). The public key is used to either generate a self signed certificate (actionselfsign) or a certificate request (actionrequest-certificate). The resulting certificate should then be imported into the same slot (actionimport-certificate). Generating the key pair and importing the certificate are both actions that require authentication, which is done by providing the management key. If no management key is provided, the tool will try to authenticate using the default management key. Important:It is strongly recommended to change the Yubikey’s PIN, PUK and management key before start using it While generating the certificate/certificate request does not require authentication, the signing operation does require verifying the PIN code or the fingerprint if the YubiKey supports Bio verification, which has to be done in an action that must take place before the signing action, otherwise the operation fails. Use-a verify-pinto verify the PIN and-a verify-biofor fingerprint verification. 6.8.3 Examples 6.8.3.1 Example 1: Self signed certificate on slot 9a $ yubico-piv-tool -a generate -s 9a -A ECCP256 -k -----BEGIN PUBLIC KEY----- MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEwyLPuYF7xF4iQ+5VWUnDQsMSf9O7 Jc1gBDHQJ0kfYnZ8tV2OFk3JFyfZDL9g9g3eFaH00dzstxH7te64DtYepw== -----END PUBLIC KEY----- Successfully generated a new private key. $ yubico-piv-tool -a verify-pin -a selfsign -s 9a -S'/CN=piv\_auth/OU=test/O=example.com/ ˓→' Enter PIN: Successfully verified PIN. Please paste the public key... -----BEGIN PUBLIC KEY----- MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEwyLPuYF7xF4iQ+5VWUnDQsMSf9O7 (continues on next page) 62Chapter 6. PIV Tool Command, Options and Actions YubiKey PIV Tool User Guide (continued from previous page) Jc1gBDHQJ0kfYnZ8tV2OFk3JFyfZDL9g9g3eFaH00dzstxH7te64DtYepw== -----END PUBLIC KEY----- -----BEGIN CERTIFICATE----- MIIBujCCAWCgAwIBAgIJAJKWdUFfuvqiMAoGCCqGSM49BAMCMDgxETAPBgNVBAMM CHBpdl9hdXRoMQ0wCwYDVQQLDAR0ZXN0MRQwEgYDVQQKDAtleGFtcGxlLmNvbTAe Fw0xOTA4MTIxMzM0NTdaFw0yMDA4MTExMzM0NTdaMDgxETAPBgNVBAMMCHBpdl9h dXRoMQ0wCwYDVQQLDAR0ZXN0MRQwEgYDVQQKDAtleGFtcGxlLmNvbTBZMBMGByqG SM49AgEGCCqGSM49AwEHA0IABMMiz7mBe8ReIkPuVVlJw0LDEn/TuyXNYAQx0CdJ H2J2fLVdjhZNyRcn2Qy/YPYN3hWh9NHc7LcR+7XuuA7WHqejUzBRMB0GA1UdDgQW BBQS0iNbyP8W817uCk/2lPd19ZvNRDAfBgNVHSMEGDAWgBQS0iNbyP8W817uCk/2 lPd19ZvNRDAPBgNVHRMBAf8EBTADAQH/MAoGCCqGSM49BAMCA0gAMEUCIQC5CTvl LE0htwa89LBRRSL2BWHqciSLvqx9azjJfd63JAIgcAJSIhWpiXeBcGZdcTbnmkqU kWu4LDU2ymBRp8pp4Iw= -----END CERTIFICATE----- Successfully generated a new self signed certificate. $ yubico-piv-tool -a import-certificate -s 9a -k Please paste the certificate... -----BEGIN CERTIFICATE----- MIIBujCCAWCgAwIBAgIJAJKWdUFfuvqiMAoGCCqGSM49BAMCMDgxETAPBgNVBAMM CHBpdl9hdXRoMQ0wCwYDVQQLDAR0ZXN0MRQwEgYDVQQKDAtleGFtcGxlLmNvbTAe Fw0xOTA4MTIxMzM0NTdaFw0yMDA4MTExMzM0NTdaMDgxETAPBgNVBAMMCHBpdl9h dXRoMQ0wCwYDVQQLDAR0ZXN0MRQwEgYDVQQKDAtleGFtcGxlLmNvbTBZMBMGByqG SM49AgEGCCqGSM49AwEHA0IABMMiz7mBe8ReIkPuVVlJw0LDEn/TuyXNYAQx0CdJ H2J2fLVdjhZNyRcn2Qy/YPYN3hWh9NHc7LcR+7XuuA7WHqejUzBRMB0GA1UdDgQW BBQS0iNbyP8W817uCk/2lPd19ZvNRDAfBgNVHSMEGDAWgBQS0iNbyP8W817uCk/2 lPd19ZvNRDAPBgNVHRMBAf8EBTADAQH/MAoGCCqGSM49BAMCA0gAMEUCIQC5CTvl LE0htwa89LBRRSL2BWHqciSLvqx9azjJfd63JAIgcAJSIhWpiXeBcGZdcTbnmkqU kWu4LDU2ymBRp8pp4Iw= ----END CERTIFICATE----- Successfully imported a new certificate. It is also possible to combine all these commands above into one single command (notice the order of the actions): $ yubico-piv-tool -a generate -a verify-pin -a selfsign -a import-certificate -s 9a -k - ˓→A ECCP256 -S'/CN=piv\_auth/OU=test/O=example.com/' 6.8.3.2 Example 2: generate Signed certificate on slot 9c $ yubico-piv-tool -a generate -s 9c -A RSA2048 -o pub.key Successfully generated a new private key. $ yubico-piv-tool -a verify-pin -a request-certificate -s 9c -S'/CN=digi\_sign/OU=test/ ˓→O=example.com/'-i pub.key -o csr.pem Enter PIN: Successfully verified PIN. Successfully generated a certificate request. After sending the certificate request to the CA and getting a signed certificate: 6.8. generate63 YubiKey PIV Tool User Guide $ yubico-piv-tool -a import-certificate -s 9c -i cert.pem Successfully imported a new certificate. 6.8.4 Parameters ParameterRequired Optional DescriptionPossible values, Default -s, --slot ENUM RequiredThe key slot to operate on. See Note1 9a,9c,9d,9e,82,83, 84,85,86,87,88,89, 8a,8b,8c,8d,8e,8f, 90,91,92,93,94,95, f9 where - 9afor PIV Authentication. 9cfor Digital Signature (PIN always checked). 9dfor Key Management. 9efor Card Authentication (PIN never checked). 82-95for Retired Key Management. f9for Attestation. -k, --key \[STRING\] RequiredManagement key to use. If no value is specified, PIV tool prompts for value Default: 010203040506070801020304050607080102030405060708 -S, --subject STRING RequiredThe subject to use for certificate request. The string must be written as: /CN=host.example.com/ OU=test/O=example.com/ continues on next page 64Chapter 6. PIV Tool Command, Options and Actions YubiKey PIV Tool User Guide Table 3 – continued from previous page ParameterRequired Optional DescriptionPossible values, Default -A, --algorithm ENUM OptionalThe algorithm to use to generate the key pair. RSA1024,RSA2048,ECCP256, ECCP384 Values that require YubiKey 5.7 or newer: RSA3072,RSA4096,ED25519, X25519 Default:RSA2048 -o, --output STRING OptionalFilename to use as output or certificate file. If not specified, output is printed tostdout. None forstdoutor filename. Default:-forstdout -P, --pin STRING OptionalPIN/PUK code for verification. If omitted, PIV tool prompts for PIN/PUK --pin-policy ENUM OptionalSet pin policy for actions: generateor import-key. Only available on YubiKey 4 or newer. Values PIN key verification: never,once,always Value BIO key verification: matchonce,matchalways Default: slot 9c,always slot 9a, 9d and 9e,once remaining slots,never --touch-policy ENUM OptionalSet touch policy for the slot containing the key. Applies to the actions: generate,import-key orset-mgm-key. Requires YubiKey 4 or newer. never,always,caches Default:never continues on next page 6.8. generate65 YubiKey PIV Tool User Guide Table 3 – continued from previous page ParameterRequired Optional DescriptionPossible values, Default -i, --input STRING OptionalFilename to use as input. If left out, input is read fromstdin. None forstdinor filename. Default:-for stdin The only supported format for public key is PEM. --serial INT OptionalSerial number of the self- signed certificate --valid-days INT OptionalTime (in days) until the self-signed certificate expires. Default:365 (1)For additional information on slot values, see PIV Certificate Slots. —————————————————————————————————————————- 6.9 import-certificate 6.9.1 Syntax $ yubico-piv-tool -a import-certificate -s -k \[ -i -K \] 6.9.2 Description Import an X509 certificate into a specific slot. Part of generating an RSA or an EC key on a specific slot. This requires a sequence of action commands. Com- pleted key generation can includegenerate,selfsign,request-certificate,verify-pinorverify-bio, and import-certificate. Seegenerate. Theimport-keycommand option precedesimport-certificate. Seeimport-key. 66Chapter 6. PIV Tool Command, Options and Actions YubiKey PIV Tool User Guide 6.9.3 Examples $ yubico-piv-tool -a import-certificate -s -k \[ -o \] 6.9.4 Parameters ParameterRequired Optional DescriptionPossible values, Default -s, --slot ENUM RequiredThe key slot to operate on. See Note1 9a,9c,9d,9e,82,83, 84,85,86,87,88,89, 8a,8b,8c,8d,8e,8f, 90,91,92,93,94,95, f9 where - 9afor PIV Authentication. 9cfor Digital Signature (PIN always checked). 9dfor Key Management. 9efor Card Authentication (PIN never checked). 82-95for Retired Key Management. f9for Attestation. -k, --key \[STRING\] RequiredManagement key to use. If no value is specified, PIV tool prompts for value Default: 010203040506070801020304050607080102030405060708 -o, --output STRING OptionalFilename to use as output or certificate file. If not specified, output is printed tostdout. None forstdoutor filename. Default:-forstdout (1)For additional information on slot values, see PIV Certificate Slots. —————————————————————————————————————————- 6.9. import-certificate67 YubiKey PIV Tool User Guide 6.10 import-key 6.10.1 Syntax $ yubico-piv-tool -a import-key -s -k \[options\] 6.10.2 Description Imports a key, a certificate, or both into the Yubikey PIV interface for a specific slot. The largest accepted keys are of size 2025/3049 bytes for current versions of YubiKey NEO and YubiKey 5, respectively. It is possible to import larger certificates, but that requires compression in order for it to fit (see examples bellow). This action is also used to import decryption keys (aka. key management keys typically found in slot 9d) into the retired slots (slots 82-95) Importing either a key or a certificate is an action that requires authentication, which is done by providing the manage- ment key. If no management key is provided, the tool will try to authenticate using the default management key. Important:It is strongly recommended to change the Yubikey’s PIN, PUK and management key before start using it. 6.10.3 Examples $ yubico-piv-tool -a import-key -s -k \[ -P --pin-policy ˓→ --touch-policy -i ˓→ -p -K \] $ yubico-piv-tool -a import-certificate -s -k \[ -i -K \] $ yubico-piv-tool -a import-key -a import-certificate -s -k \[ -P --pin- ˓→policy --touch-policy - ˓→i -p -K \] $ yubico-piv-tool -a import-key -a import-certificate -s 9c -k -i key.pfx -K PKCS12 Enter Password: Enter management key: Successfully imported a new private key. Successfully imported a new certificate. $ yubico-piv-tool -a import-certificate -s 9c -k -i cert\_large.gz -K GZIP Successfully imported a new certificate. 68Chapter 6. PIV Tool Command, Options and Actions YubiKey PIV Tool User Guide 6.10.4 Parameters ParameterRequired Optional DescriptionPossible values, Default -s, --slot ENUM RequiredThe key slot to operate on. See Note1 9a,9c,9d,9e,82,83, 84,85,86,87,88,89, 8a,8b,8c,8d,8e,8f, 90,91,92,93,94,95, f9 where - 9afor PIV Authentication. 9cfor Digital Signature (PIN always checked). 9dfor Key Management. 9efor Card Authentication (PIN never checked). 82-95for Retired Key Management. f9for Attestation. -k, --key \[STRING\] RequiredManagement key to use. If no value is specified, PIV tool prompts for value Default: 010203040506070801020304050607080102030405060708 -P, --pin STRING OptionalPIN/PUK code for verification. If omitted, PIV tool prompts for PIN/PUK --pin-policy ENUM OptionalSet pin policy for actions: generateor import-key. Only available on YubiKey 4 or newer. Values PIN key verification: never,once,always Value BIO key verification: matchonce,matchalways Default: slot 9c,always slot 9a, 9d and 9e,once remaining slots,never continues on next page 6.10. import-key69 YubiKey PIV Tool User Guide Table 5 – continued from previous page ParameterRequired Optional DescriptionPossible values, Default --touch-policy ENUM OptionalSet touch policy for the slot containing the key. Applies to the actions: generate,import-key orset-mgm-key. Requires YubiKey 4 or newer. never,always,caches Default:never -i, --input STRING OptionalFilename to use as input. If left out, input is read fromstdin. None forstdinor filename. Default:-for stdin The only supported format for public key is PEM. -p, --password STRING OptionalPassword for decryption of private key file. If omitted, PIV tool prompts for password -K, --key-format ENUM OptionalFormat of the key being read/written. PEM,PKCS12,GZIP,DER,SSH Default:PEM (1)For additional information on slot values, see PIV Certificate Slots. —————————————————————————————————————————- 70Chapter 6. PIV Tool Command, Options and Actions YubiKey PIV Tool User Guide 6.11 list-readers No sample available. —————————————————————————————————————————- 6.12 move-key 6.12.1 Syntax $ yubico-piv-tool -a move-key -s --to-slot -k 6.12.2 Description Moves a key from one PIV slot to another. The function requires YubiKey 5.7 or higher. Note:This actions moves only the key, not the certificate. So if the slot already stores a certificate, it might still look populated even if the key is no longer there. Moving a key is an action that requires authentication, which is done by providing the management key. If no manage- ment key is provided, the tool will try to authenticate using the default management key. Important:It is strongly recommended to change the Yubikey’s PIN, PUK and management key before start using it. 6.12.3 Examples $ yubico-piv-tool -a move-key -s 9c --to-slot 84 -k Enter Password: Enter management key: Successfully moved key. 6.11. list-readers71 YubiKey PIV Tool User Guide 6.12.4 Parameters ParameterRequired Optional DescriptionPossible values, Default -s, --slot ENUM RequiredThe key slot to operate on. See Note1 9a,9c,9d,9e,82,83, 84,85,86,87,88,89, 8a,8b,8c,8d,8e,8f, 90,91,92,93,94,95, f9 where - 9afor PIV Authentication. 9cfor Digital Signature (PIN always checked). 9dfor Key Management. 9efor Card Authentication (PIN never checked). 82-95for Retired Key Management. f9for Attestation. -k, --key \[STRING\] RequiredManagement key to use. If no value is specified, PIV tool prompts for value Default: 010203040506070801020304050607080102030405060708 --to-slot ENUM RequiredThe slot to move an existing key to. See Note1 9a,9c,9d,9e,82,83, 84,85,86,87,88,89, 8a,8b,8c,8d,8e,8f, 90,91,92,93,94,95, f9 where - 9afor PIV Authentication. 9cfor Digital Signature (PIN always checked). 9dfor Key Management. 9efor Card Authentication (PIN never checked). 82-95for Retired Key Management. f9for Attestation. 72Chapter 6. PIV Tool Command, Options and Actions YubiKey PIV Tool User Guide (1)For additional information on slot values, see PIV Certificate Slots. —————————————————————————————————————————- 6.13 pin-retries No sample available. —————————————————————————————————————————- 6.14 read-certificate 6.14.1 Syntax $ yubico-piv-tool -a read-certificate -s \[ -o -K \] 6.14.2 Description Returns the X509 certificate stored on a certain slot. 6.14.3 Examples $ yubico-piv-tool -a read-cert -s 9a -----BEGIN CERTIFICATE----- MIIBuTCCAWCgAwIBAgIJAMOZXtijzEepMAoGCCqGSM49BAMCMDgxETAPBgNVBAMM CHBpdl9hdXRoMQ0wCwYDVQQLDAR0ZXN0MRQwEgYDVQQKDAtleGFtcGxlLmNvbTAe Fw0xOTA4MTMwODEwNDVaFw0yMDA4MTIwODEwNDVaMDgxETAPBgNVBAMMCHBpdl9h dXRoMQ0wCwYDVQQLDAR0ZXN0MRQwEgYDVQQKDAtleGFtcGxlLmNvbTBZMBMGByqG SM49AgEGCCqGSM49AwEHA0IABKPfSKeNY204JiHsSUwDAV8GuYqZOHfJJxrT4E0q VWsKdC5zwRc7xvb2YgbMonPW5BfIUi766/VwWN54UsqWVuWjUzBRMB0GA1UdDgQW BBR/bpCmGr+ark0VbGX5UvYWy9dM9DAfBgNVHSMEGDAWgBR/bpCmGr+ark0VbGX5 UvYWy9dM9DAPBgNVHRMBAf8EBTADAQH/MAoGCCqGSM49BAMCA0cAMEQCIHZZe7Xm s6y8LKEBqGnbr1cbniHgMrvM1ST6GpL27HuaAiB+UwjI21GxIsd5r2avmwvT5LeZ gQBns9KNCIgkwx+/Iw== -----END CERTIFICATE----- 6.13. pin-retries73 YubiKey PIV Tool User Guide 6.14.4 Parameters ParameterRequired Optional DescriptionPossible values, Default -s, --slot ENUM RequiredThe key slot to operate on. See Note1 9a,9c,9d,9e,82,83, 84,85,86,87,88,89, 8a,8b,8c,8d,8e,8f, 90,91,92,93,94,95, f9 where - 9afor PIV Authentication. 9cfor Digital Signature (PIN always checked). 9dfor Key Management. 9efor Card Authentication (PIN never checked). 82-95for Retired Key Management. f9for Attestation. -o, --output STRING OptionalFilename to use as output or certificate file. If not specified, output is printed tostdout. None forstdoutor filename. Default:-forstdout -K, --key-format ENUM OptionalFormat of the key being read/written. PEM,PKCS12,GZIP,DER,SSH Default:PEM (1)For additional information on slot values, see PIV Certificate Slots. —————————————————————————————————————————- 74Chapter 6. PIV Tool Command, Options and Actions YubiKey PIV Tool User Guide 6.15 read-object 6.15.1 Syntax $ yubico-piv-tool -a read-object --id \[ -o -f \] $ yubico-piv-tool -a write-object --id -k \[ -i -f ˓→\] 6.15.2 Description Theread-objectsyntax includeswrite-objectsyntax. Reads and stores raw data into a PIV slot. The form and ID of the data are detailed in section 4.3 of the PIV Specification SP 800-73-4. Writing an object is an action that requires authentication, which is done by providing the management key. If no management key is provided, the tool tries to authenticate using the default management key. Important:It is strongly recommended to change the Yubikey’s PIN, PUK and management key before start using it. 6.15.3 Examples $ yubico-piv-tool -a read-object --id 0x5fc10d 708202b2308202ae30820196a003020102020832b1fd4fd258f9bd300d06092a864886f70d01010b0500 303b3115301306035504030c0c4d616e6167656d656e74434131153013060355040a0c0c454a42434120 59756269636f310b3009060355040613025345301e170d3139303830383134333034325a170d32313038 30373134333034325a30203111300f06035504030c08757365725f333834310b30090603550406130253 453076301006072a8648ce3d020106052b810400220362000456444320b440fe49f312b023aa571da565 e9bc966dc928aef49c87e45d95cccf5b07fbe9e6620d2bb9d3c268671b2eed0e912c1dfae34f1e8f61a2 4565cb6498129618b96b7e3f38962796aa67382878cbe2cc1a8c369a55cecbd31b7a5cb032a37f307d30 0c0603551d130101ff04023000301f0603551d230418301680140c6d2aca0fe3aef788b50479477aba8a 87b08ad4301d0603551d250416301406082b0601050507030206082b06010505070304301d0603551d0e 04160414a508f3007b5344dc8efe08d87dfdbcb53191c7f3300e0603551d0f0101ff0404030205e0300d 06092a864886f70d01010b050003820101003993c325a5396ae1455e94d31dc6eda702b3e17b0f82de6d 1c22e994de13124022d7b127dff25a082c6f8a4ff74e0a965cb619bbc62787072b5d1ecb5a06e4b9d245 23534b1c4e6ac8265e8debb8111c62afbf8e1952e5ebd3ac81f6cf1900497719cb1ab60c1e92be9032db 1f69bf04d5def4fe2788de04452f2b01ced25fb186ce1b67c830dbbcc5e9d857951e347047c75f7456d4 2e9519694a7361f0b892d9acec10a55e5a61c483942543b13bd2c345b08ed1adc043647505a8d3ce2152 c4dfb8dc005e0fedc3d94aaf1e7e63b0c720c16481207451dd800e9cf7750c9bec580ce97aa540366ff1 f1ad5366fc3aac5563db73b6f44574968e3922e9e9fb710100fe00 6.15. read-object75 YubiKey PIV Tool User Guide 6.15.4 Supported PIV Object IDs for read- and write-object Type of Object DataASN.1 OIDID Card Capability Container2.16.840.1.101.3.7.1.219.00x5fc107 Card Holder Unique Identifier2.16.840.1.101.3.7.2.48.00x5fc102 X.509 Certificate for PIV Authentication2.16.840.1.101.3.7.2.1.10x5fc105 Cardholder Fingerprints2.16.840.1.101.3.7.2.96.160x5fc103 Security Object2.16.840.1.101.3.7.2.144.00x5fc106 Cardholder Facial Image2.16.840.1.101.3.7.2.96.480x5fc108 X.509 Certificate for Card Authentication2.16.840.1.101.3.7.2.5.00x5fc101 X.509 Certificate for Digital Signature2.16.840.1.101.3.7.2.1.00x5fc10a X.509 Certificate for Key Management2.16.840.1.101.3.7.2.1.20x5fc10b Printed Information2.16.840.1.101.3.7.2.48.10x5fc109 Discovery Object2.16.840.1.101.3.7.2.96.800x7e Key History Object2.16.840.1.101.3.7.2.96.960x5fc10c Retired X.509 Certificate for Key Management2.16.840.1.101.3.7.2.16.10x5fc10d Retired X.509 Certificate for Key Management2.16.840.1.101.3.7.2.16.20x5fc10e Retired X.509 Certificate for Key Management2.16.840.1.101.3.7.2.16.30x5fc10f Retired X.509 Certificate for Key Management2.16.840.1.101.3.7.2.16.40x5fc110 Retired X.509 Certificate for Key Management2.16.840.1.101.3.7.2.16.50x5fc111 Retired X.509 Certificate for Key Management2.16.840.1.101.3.7.2.16.60x5fc112 Retired X.509 Certificate for Key Management2.16.840.1.101.3.7.2.16.70x5fc113 Retired X.509 Certificate for Key Management2.16.840.1.101.3.7.2.16.80x5fc114 Retired X.509 Certificate for Key Management2.16.840.1.101.3.7.2.16.90x5fc115 Retired X.509 Certificate for Key Management2.16.840.1.101.3.7.2.16.100x5fc116 Retired X.509 Certificate for Key Management2.16.840.1.101.3.7.2.16.110x5fc117 Retired X.509 Certificate for Key Management2.16.840.1.101.3.7.2.16.120x5fc118 Retired X.509 Certificate for Key Management2.16.840.1.101.3.7.2.16.130x5fc119 Retired X.509 Certificate for Key Management2.16.840.1.101.3.7.2.16.140x5fc11a Retired X.509 Certificate for Key Management2.16.840.1.101.3.7.2.16.150x5fc11b Retired X.509 Certificate for Key Management2.16.840.1.101.3.7.2.16.160x5fc11c Retired X.509 Certificate for Key Management2.16.840.1.101.3.7.2.16.170x5fc11d Retired X.509 Certificate for Key Management2.16.840.1.101.3.7.2.16.180x5fc11e Retired X.509 Certificate for Key Management2.16.840.1.101.3.7.2.16.190x5fc11f Retired X.509 Certificate for Key Management2.16.840.1.101.3.7.2.16.200x5fc120 Cardholder Iris Images2.16.840.1.101.3.7.2.16.210x5fc121 Biometric Information Templates Group Templates 2.16.840.1.101.3.7.2.16.210x7f61 Secure Messaging Certificate Signer2.16.840.1.101.3.7.2.16.210x5fc122 Pairing Code Reference Data Container2.16.840.1.101.3.7.2.16.210x5fc123 76Chapter 6. PIV Tool Command, Options and Actions YubiKey PIV Tool User Guide 6.15.5 Parameters ParameterRequired Optional DescriptionPossible values, Default --id INT RequiredThe ID of the object to write/read according to PIV Specifications -k, --key \[STRING\] RequiredManagement key to use. If no value is specified, PIV tool prompts for value Default: 010203040506070801020304050607080102030405060708 -i, --input STRING OptionalFilename to use as input. If left out, input is read fromstdin. None forstdinor filename. Default:-for stdin The only supported format for public key is PEM. -o, --output STRING OptionalFilename to use as output or certificate file. If not specified, output is printed tostdout. None forstdoutor filename. Default:-forstdout -f, --format ENUM OptionalFormat of data for write/read object. hex,base64,binary Default:hex —————————————————————————————————————————- 6.15. read-object77 YubiKey PIV Tool User Guide 6.16 read-public-key 6.16.1 Syntax $ yubico-piv-tool -a read-public-key -s \[ -o -K \] 6.16.2 Description Returns the X509 public key stored on a certain slot. 6.16.3 Examples $ yubico-piv-tool -a read-public-key -s 9a -----BEGIN PUBLIC KEY----- MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAntRh/Q1ILx5n3KJIUJCM vW1aNGa5jjlEwMBBtFWOrgEmmHUK4BvyMIVZyL5kYZr9aJZdrRW0+ltzGWWDZ0ET nZrYIqHuJZuCaLQNk6kN+KJfW0/QGgV6WxMwniBIDL924miUlTjt8FvnuiW3oAuC xLVktNp9cPlzXlWKvHqZzwprhX1SQ9AApuKiABxxiPmVdo2qSFflKMTH3wL+DRCO Nbc/YRiJqEjqub0p67TMkgoBUfpCLYFiMFaHj4cv/RsTho/A0osnql6JSesGkDJJ YhHs5RCYytvgqpx8BQp1iEawSw15Fq1eJxUyFbyeHoUkwVfTNso39KnhgDhGt2Xf IQIDAQAB -----END PUBLIC KEY----- 78Chapter 6. PIV Tool Command, Options and Actions YubiKey PIV Tool User Guide 6.16.4 Parameters ParameterRequired Optional DescriptionPossible values, Default -s, --slot ENUM RequiredThe key slot to operate on. See Note1 9a,9c,9d,9e,82,83, 84,85,86,87,88,89, 8a,8b,8c,8d,8e,8f, 90,91,92,93,94,95, f9 where - 9afor PIV Authentication. 9cfor Digital Signature (PIN always checked). 9dfor Key Management. 9efor Card Authentication (PIN never checked). 82-95for Retired Key Management. f9for Attestation. -o, --output STRING OptionalFilename to use as output or certificate file. If not specified, output is printed tostdout. None forstdoutor filename. Default:-forstdout -K, --key-format ENUM OptionalFormat of the key being read/written. PEM,PKCS12,GZIP,DER,SSH Default:PEM (1)For additional information on slot values, see PIV Certificate Slots. —————————————————————————————————————————- 6.16. read-public-key79 YubiKey PIV Tool User Guide 6.17 request-certificate 6.17.1 Description Generate a certification request for an asymmetric key stored on a specific slot. Part of generating an RSA or an EC key on a specific slot. This requires a sequence of action commands. Com- pleted key generation can includegenerate,selfsign,request-certificate,verify-pinorverify-bio, and import-certificate. Seegenerate. 6.17.2 Examples $ yubico-piv-tool -a verify-pin -a request-certificate -s -S \[ -P ˓→ -i -o \] —————————————————————————————————————————- 6.18 reset 6.18.1 Syntax $ yubico-piv-tool -a reset 6.18.2 Description Erases all keys and certificates stored on the device and sets it to the default PIN, PUK and management key. This only affects the PIV application on the YubiKey, so any non-PIV configuration remains intact. Resetting the device does not erase the attestation key and certificate (slot f9) either, though they can be overwritten. To reset the device, the PIN and the PUK need to be blocked. This happens when the wrong PIN and PUK is entered more than the number of their retries. Global Reset Some YubiKeys with firmware version 5.7.0 or higher have support for a global support option. This option erases all data on the YubiKey and is not restricted to the PIV application. It also does not require that the PIN and PUK to be blocked. Note:The global reset option cannot be used over an encrypted session. 80Chapter 6. PIV Tool Command, Options and Actions YubiKey PIV Tool User Guide 6.18.3 Examples $ yubico-piv-tool -averify-pin -P471112 $ yubico-piv-tool -averify-pin -P471112 $ yubico-piv-tool -averify-pin -P471112 $ yubico-piv-tool -averify-pin -P471112 $ yubico-piv-tool -achange-puk -P471112 -N6756789 $ yubico-piv-tool -achange-puk -P471112 -N6756789 $ yubico-piv-tool -achange-puk -P471112 -N6756789 $ yubico-piv-tool -achange-puk -P471112 -N6756789 $ yubico-piv-tool -areset $ yubico-piv-tool -areset --global 6.18.4 Parameters ParameterRequired Optional DescriptionPossible values, Default -globalOptionalReset the whole device over all applications, including the PIV application. Default:off —————————————————————————————————————————- 6.19 selfsign-certificate 6.19.1 Description Generate a self signed X509 certificate for an asymmetric key stored on a specific slot. Part of generating an RSA or an EC key on a specific slot. This requires a sequence of action commands. Com- pleted key generation can includegenerate,selfsign,request-certificate,verify-pinorverify-bio, and import-certificate. Seegenerate. 6.19. selfsign-certificate81 YubiKey PIV Tool User Guide 6.19.2 Examples $ yubico-piv-tool -a verify-pin -a selfsign -s -S \[ -P -- ˓→pin-policy --touch-policy ˓→ -i --serial --valid-days␣ ˓→DAYS -o \] —————————————————————————————————————————- 6.20 set-ccc No sample available. —————————————————————————————————————————- 6.21 set-chuid No sample available. —————————————————————————————————————————- 6.22 set-mgm-key No sample available. —————————————————————————————————————————- 6.23 sign-data 6.23.1 Syntax $ yubico-piv-tool -a verify-pin --sign -s \[ -H -A ˓→-P -i -o \] 6.23.2 Description Signs input data. The signing operation requires verifying the PIN code or the fingerprint if the YubiKey supports Bio verification. Use -a verify-pinto verify the PIN and-a verify-biofor fingerprint verification. 82Chapter 6. PIV Tool Command, Options and Actions YubiKey PIV Tool User Guide 6.23.3 Examples $ yubico-piv-tool -a verify-pin --sign -s 9c -H SHA512 -A RSA2048 -i data.txt -o data.sig Enter PIN: Successfully verified PIN. Signature successful! $ openssl dgst -sha512 -verify pubkey.pem -signature data.sig data.txt Verified OK 6.23. sign-data83 YubiKey PIV Tool User Guide 84Chapter 6. PIV Tool Command, Options and Actions YubiKey PIV Tool User Guide 6.23.4 Parameters ParameterRequired Optional DescriptionPossible values, Default -s, --slot ENUM RequiredThe key slot to operate on. See Note1 9a,9c,9d,9e,82,83, 84,85,86,87,88,89, 8a,8b,8c,8d,8e,8f, 90,91,92,93,94,95, f9 where - 9afor PIV Authentication. 9cfor Digital Signature (PIN always checked). 9dfor Key Management. 9efor Card Authentication (PIN never checked). 82-95for Retired Key Management. f9for Attestation. -A, --algorithm ENUM OptionalThe algorithm to use to generate the key pair. RSA1024,RSA2048,ECCP256, ECCP384 Values that require YubiKey 5.7 or newer: RSA3072,RSA4096,ED25519, X25519 Default:RSA2048 -H, --hash ENUM OptionalHash to use for signatures. SHA1,SHA256,SHA384, SHA512. Default:SHA256 -P, --pin STRING OptionalPIN/PUK code for verification. If omitted, PIV tool prompts for PIN/PUK -i, --input STRING OptionalFilename to use as input. If left out, input is read fromstdin. None forstdinor filename. Default:-for stdin The only supported format for public key is PEM. -o, --output STRING OptionalFilename to use as output or certificate file. If not specified, output is printed tostdout. None forstdoutor filename. Default:-forstdout 6.23. sign-data85 YubiKey PIV Tool User Guide (1)For additional information on slot values, see PIV Certificate Slots. —————————————————————————————————————————- 6.24 status 6.24.1 Syntax $ yubico-piv-tool -a status \[ -s \] 6.24.2 Description Lists the device’s meta data and the content of slots 9a, 9c, 9d and 9e. The content of slot f9 is listed if the slot is specified as an argument. This action, however, doesnotlist the content of the retired slots (slots 82-95). 6.24.3 Examples Example 1: $ yubico-piv-tool -a status Version: 4.4.0 Serial Number: 12345678 CHUID: No data available CCC: No data available Slot 9a: Private Key Algorithm: RSA2048 Public Key Algorithm: RSA2048 Subject DN: CN=piv\_auth, C=SE Issuer DN: CN=TestCA, O=Yubico, C=SE Fingerprint: 4a1416fce853b29eaf520174bf8639d72ff30bd84e4586f81ac2a19eda43fdf1 Not Before: Aug 8 14:29:23 2019 GMT Not After: Aug 7 14:29:23 2021 GMT Slot 9c: Private Key Algorithm: ECCP384 Public Key Algorithm: RSA2048 Subject DN: CN=sign, C=SE Issuer DN: CN=TestCA, O=Yubico, C=SE Fingerprint: 803a89d5e196835d4a7e5e600e413fec1d3014712fcfd9e31fe15010829226dd Not Before: Aug 8 14:29:50 2019 GMT Not After: Aug 7 14:29:50 2021 GMT WARNING: Slot private key and certificate do not match Slot 9d: Private Key Algorithm: RSA2048 Public Key Algorithm: RSA2048 Subject DN: CN=key\_mgm, C=SE Issuer DN: CN=TestCA, O=Yubico, C=SE Fingerprint: 4a1416fce853429eaf420074bf8d39d72ff30bd84e4586f81ac2a19eda43fdf1 Not Before: Aug 8 14:29:23 2019 GMT Not After: Aug 7 14:29:23 2021 GMT (continues on next page) 86Chapter 6. PIV Tool Command, Options and Actions YubiKey PIV Tool User Guide (continued from previous page) WARNING: Slot private key and certificate do not match Slot 9e: Private Key Algorithm: RSA2048 Public Key Algorithm: RSA2048 Subject DN: CN=card\_auth, C=SE Issuer DN: CN=TestCA, O=Yubico, C=SE Fingerprint: 803a89d5e196845d4a7e5e6006413fec1d30157128cfd9e3afe15010829226dd Not Before: Aug 8 14:29:50 2019 GMT Not After: Aug 7 14:29:50 2021 GMT PIN tries left: 3 Example 2: $ yubico-piv-tool -a status -s 9a Version: 4.4.0 Serial Number: 12345678 CHUID: No data available CCC: No data available Slot 9a: Private Key Algorithm: RSA2048 Public Key Algorithm: RSA2048 Subject DN: CN=piv\_auth, C=SE Issuer DN: CN=TestCA, O=Yubico, C=SE Fingerprint: 4a1416fce853b29eaf520174bf8639d72ff30bd84e4586f81ac2a19eda43fdf1 Not Before: Aug 8 14:29:23 2019 GMT Not After: Aug 7 14:29:23 2021 GMT PIN tries left: 3 Example 3: $ yubico-piv-tool -a status -s f9 Version: 4.4.0 Serial Number: 12345678 CHUID: ␣ ˓→3019d4e739da739ced39ce739d836858210842108421c84210c3eb3410461c7c766122b38b2edf05183c3d0 41a350832303330303130313e00fe00 CCC: ␣ ˓→f015a000000116ff02f9a5b5f5fc5cd67c63a147ddf405f10121f20121f300f40100f50110f600f700fa00f b00fc00fd00fe00 Slot f9: Private Key Algorithm: RSA2048 Public Key Algorithm: RSA2048 Subject DN: CN=Test Attestation Certificate Issuer DN: CN=Test Attestation Certificate Fingerprint: 8dbc03bea80282748f0403de0922c93751fe498d376b6ae1aa87d1b8af74c7a3 Not Before: Jan 22 09:47:58 2018 GMT Not After: Jan 24 09:47:58 2018 GMT PIN tries left: 3 6.24. status87 YubiKey PIV Tool User Guide 6.24.4 Parameters ParameterRequired Optional DescriptionPossible values, Default -s, --slot ENUM RequiredThe key slot to operate on. See Note1 9a,9c,9d,9e,82,83, 84,85,86,87,88,89, 8a,8b,8c,8d,8e,8f, 90,91,92,93,94,95, f9 where - 9afor PIV Authentication. 9cfor Digital Signature (PIN always checked). 9dfor Key Management. 9efor Card Authentication (PIN never checked). 82-95for Retired Key Management. f9for Attestation. (1)For additional information on slot values, see PIV Certificate Slots. —————————————————————————————————————————- 6.25 test-decipher 6.25.1 Syntax $ yubico-piv-tool -a read-certificate -s \[ -o cert.pem \] $ yubico-piv-tool -a verify-pin -a test-decipher -s \[ -P -i cert.pem \] 88Chapter 6. PIV Tool Command, Options and Actions YubiKey PIV Tool User Guide 6.25.2 Description Test the decryption function. This applies to bothtest-signatureandtest-decipher. To test decryption: 1. Make sure there is a certificate stored on the slot being tested. To get the certificate, use theread-certificate action. 2. Verify the PIN code or the fingerprint, (for YubiKeys that support Bio verification). If the PIN code or fingerprint is not completed before a generation action, the tests fail. •To verify the PIN, use-a verify-pin •To verify the fingerprint, use-a verify-bio Important:Run the test-decypher action before you run a generate action. If test is run out of order the test- decypher action fails. 6.25.3 Examples Example 1: $ yubico-piv-tool -a read-certificate -s 9a -----BEGIN CERTIFICATE----- MIIBuTCCAWCgAwIBAgIJAMOZXtijzEepMAoGCCqGSM49BAMCMDgxETAPBgNVBAMM CHBpdl9hdXRoMQ0wCwYDVQQLDAR0ZXN0MRQwEgYDVQQKDAtleGFtcGxlLmNvbTAe Fw0xOTA4MTMwODEwNDVaFw0yMDA4MTIwODEwNDVaMDgxETAPBgNVBAMMCHBpdl9h dXRoMQ0wCwYDVQQLDAR0ZXN0MRQwEgYDVQQKDAtleGFtcGxlLmNvbTBZMBMGByqG SM49AgEGCCqGSM49AwEHA0IABKPfSKeNY204JiHsSUwDAV8GuYqZOHfJJxrT4E0q VWsKdC5zwRc7xvb2YgbMonPW5BfIUi766/VwWN54UsqWVuWjUzBRMB0GA1UdDgQW BBR/bpCmGr+ark0VbGX5UvYWy9dM9DAfBgNVHSMEGDAWgBR/bpCmGr+ark0VbGX5 UvYWy9dM9DAPBgNVHRMBAf8EBTADAQH/MAoGCCqGSM49BAMCA0cAMEQCIHZZe7Xm s6y8LKEBqGnbr1cbniHgMrvM1ST6GpL27HuaAiB+UwjI21GxIsd5r2avmwvT5LeZ gQBns9KNCIgkwx+/Iw== -----END CERTIFICATE----- Example 2: $ yubico-piv-tool -a verify-pin -a test-decipher -s 9a Enter PIN: Successfully verified PIN. Please paste the certificate to encrypt for... -----BEGIN CERTIFICATE----- MIIBuTCCAWCgAwIBAgIJAMOZXtijzEepMAoGCCqGSM49BAMCMDgxETAPBgNVBAMM CHBpdl9hdXRoMQ0wCwYDVQQLDAR0ZXN0MRQwEgYDVQQKDAtleGFtcGxlLmNvbTAe Fw0xOTA4MTMwODEwNDVaFw0yMDA4MTIwODEwNDVaMDgxETAPBgNVBAMMCHBpdl9h dXRoMQ0wCwYDVQQLDAR0ZXN0MRQwEgYDVQQKDAtleGFtcGxlLmNvbTBZMBMGByqG SM49AgEGCCqGSM49AwEHA0IABKPfSKeNY204JiHsSUwDAV8GuYqZOHfJJxrT4E0q VWsKdC5zwRc7xvb2YgbMonPW5BfIUi766/VwWN54UsqWVuWjUzBRMB0GA1UdDgQW BBR/bpCmGr+ark0VbGX5UvYWy9dM9DAfBgNVHSMEGDAWgBR/bpCmGr+ark0VbGX5 UvYWy9dM9DAPBgNVHRMBAf8EBTADAQH/MAoGCCqGSM49BAMCA0cAMEQCIHZZe7Xm s6y8LKEBqGnbr1cbniHgMrvM1ST6GpL27HuaAiB+UwjI21GxIsd5r2avmwvT5LeZ gQBns9KNCIgkwx+/Iw== (continues on next page) 6.25. test-decipher89 YubiKey PIV Tool User Guide (continued from previous page) -----END CERTIFICATE----- Successfully performed ECDH exchange with card. Example 3: It is also possible to combine the commands above into one single command. Be sure to use the correct actions order: $ yubico-piv-tool -a read-certificate -a verify-pin -a test-decipher -s 9a -o cert.pem - ˓→i cert.pem Enter PIN: Successfully verified PIN. Successfully performed ECDH exchange with card. 90Chapter 6. PIV Tool Command, Options and Actions YubiKey PIV Tool User Guide 6.25. test-decipher91 YubiKey PIV Tool User Guide 6.25.4 Parameters ParameterRequired Optional DescriptionPossible values, Default -s, --slot ENUM RequiredThe key slot to operate on. See Note1 9a,9c,9d,9e,82,83, 84,85,86,87,88,89, 8a,8b,8c,8d,8e,8f, 90,91,92,93,94,95, f9 where - 9afor PIV Authentication. 9cfor Digital Signature (PIN always checked). 9dfor Key Management. 9efor Card Authentication (PIN never checked). 82-95for Retired Key Management. f9for Attestation. -P, --pin STRING OptionalPIN/PUK code for verification. If omitted, PIV tool prompts for PIN/PUK -i, --input STRING OptionalFilename to use as input. If left out, input is read fromstdin. None forstdinor filename. Default:-for stdin The only supported format for public key is PEM. -o, --output STRING OptionalFilename to use as output or certificate file. If not specified, output is printed tostdout. None forstdoutor filename. Default:-forstdout 92Chapter 6. PIV Tool Command, Options and Actions YubiKey PIV Tool User Guide (1)For additional information on slot values, see PIV Certificate Slots. —————————————————————————————————————————- 6.26 test-signature 6.26.1 Syntax $ yubico-piv-tool -a read-certificate -s \[ -o cert.pem \] $ yubico-piv-tool -a verify-pin -a test-signature -s \[ -P -i cert.pem \] 6.26.2 Description Test the signature function. This applies to bothtest-signatureandtest-decipher. To test signing: 1. Make sure there is a certificate stored on the slot being tested. To get the certificate, use theread-certificate action. 2. Verify the PIN code or the fingerprint, (for YubiKeys that support Bio verification). If the PIN code or fingerprint is not completed before a generation action, the tests fail. •To verify the PIN, use-a verify-pin •To verify the fingerprint, use-a verify-bio Important:Run the test-decypher action before you run a generate action. If test is run out of order the test- signature action fails. 6.26.3 Examples Example 1: $ yubico-piv-tool -a read-certificate -s 9a -----BEGIN CERTIFICATE----- MIIBuTCCAWCgAwIBAgIJAMOZXtijzEepMAoGCCqGSM49BAMCMDgxETAPBgNVBAMM CHBpdl9hdXRoMQ0wCwYDVQQLDAR0ZXN0MRQwEgYDVQQKDAtleGFtcGxlLmNvbTAe Fw0xOTA4MTMwODEwNDVaFw0yMDA4MTIwODEwNDVaMDgxETAPBgNVBAMMCHBpdl9h dXRoMQ0wCwYDVQQLDAR0ZXN0MRQwEgYDVQQKDAtleGFtcGxlLmNvbTBZMBMGByqG SM49AgEGCCqGSM49AwEHA0IABKPfSKeNY204JiHsSUwDAV8GuYqZOHfJJxrT4E0q VWsKdC5zwRc7xvb2YgbMonPW5BfIUi766/VwWN54UsqWVuWjUzBRMB0GA1UdDgQW BBR/bpCmGr+ark0VbGX5UvYWy9dM9DAfBgNVHSMEGDAWgBR/bpCmGr+ark0VbGX5 UvYWy9dM9DAPBgNVHRMBAf8EBTADAQH/MAoGCCqGSM49BAMCA0cAMEQCIHZZe7Xm s6y8LKEBqGnbr1cbniHgMrvM1ST6GpL27HuaAiB+UwjI21GxIsd5r2avmwvT5LeZ gQBns9KNCIgkwx+/Iw== -----END CERTIFICATE----- Example 2: 6.26. test-signature93 YubiKey PIV Tool User Guide $ yubico-piv-tool -a verify-pin -a test-signature -s 9a Enter PIN: Successfully verified PIN. Please paste the certificate to verify against... -----BEGIN CERTIFICATE----- MIIBuTCCAWCgAwIBAgIJAMOZXtijzEepMAoGCCqGSM49BAMCMDgxETAPBgNVBAMM CHBpdl9hdXRoMQ0wCwYDVQQLDAR0ZXN0MRQwEgYDVQQKDAtleGFtcGxlLmNvbTAe Fw0xOTA4MTMwODEwNDVaFw0yMDA4MTIwODEwNDVaMDgxETAPBgNVBAMMCHBpdl9h dXRoMQ0wCwYDVQQLDAR0ZXN0MRQwEgYDVQQKDAtleGFtcGxlLmNvbTBZMBMGByqG SM49AgEGCCqGSM49AwEHA0IABKPfSKeNY204JiHsSUwDAV8GuYqZOHfJJxrT4E0q VWsKdC5zwRc7xvb2YgbMonPW5BfIUi766/VwWN54UsqWVuWjUzBRMB0GA1UdDgQW BBR/bpCmGr+ark0VbGX5UvYWy9dM9DAfBgNVHSMEGDAWgBR/bpCmGr+ark0VbGX5 UvYWy9dM9DAPBgNVHRMBAf8EBTADAQH/MAoGCCqGSM49BAMCA0cAMEQCIHZZe7Xm s6y8LKEBqGnbr1cbniHgMrvM1ST6GpL27HuaAiB+UwjI21GxIsd5r2avmwvT5LeZ gQBns9KNCIgkwx+/Iw== -----END CERTIFICATE----- Successful ECDSA verification. Example 3: It is also possible to combine the commands above into one single command. Be sure to use the correct actions order: $ yubico-piv-tool -a read-certificate -a verify-pin -a test-signature -s 9a -o cert.pem - ˓→i cert.pem Enter PIN: Successfully verified PIN. Successful ECDSA verification. 94Chapter 6. PIV Tool Command, Options and Actions YubiKey PIV Tool User Guide 6.26. test-signature95 YubiKey PIV Tool User Guide 6.26.4 Parameters ParameterRequired Optional DescriptionPossible values, Default -s, --slot ENUM RequiredThe key slot to operate on. See Note1 9a,9c,9d,9e,82,83, 84,85,86,87,88,89, 8a,8b,8c,8d,8e,8f, 90,91,92,93,94,95, f9 where - 9afor PIV Authentication. 9cfor Digital Signature (PIN always checked). 9dfor Key Management. 9efor Card Authentication (PIN never checked). 82-95for Retired Key Management. f9for Attestation. -P, --pin STRING OptionalPIN/PUK code for verification. If omitted, PIV tool prompts for PIN/PUK -i, --input STRING OptionalFilename to use as input. If left out, input is read fromstdin. None forstdinor filename. Default:-for stdin The only supported format for public key is PEM. -o, --output STRING OptionalFilename to use as output or certificate file. If not specified, output is printed tostdout. None forstdoutor filename. Default:-forstdout 96Chapter 6. PIV Tool Command, Options and Actions YubiKey PIV Tool User Guide (1)For additional information on slot values, see PIV Certificate Slots. —————————————————————————————————————————- 6.27 unblock-pin No sample available. —————————————————————————————————————————- 6.28 verify-bio 6.28.1 Description Use-a verify-pinto verify the PIN and-a verify-biofor fingerprint verification. Seegenerate,test-signature,test-decipher, orsign-data. 6.28.2 Examples $ yubico-piv-tool -a verify-bio -a selfsign -s -S \[ -P -- ˓→pin-policy --touch-policy ˓→ -i --serial --valid-days␣ ˓→DAYS -o \] $ yubico-piv-tool -a verify-bio -a request-certificate -s -S \[ -P ˓→ -i -o \] —————————————————————————————————————————- 6.29 verify-pin 6.29.1 Description Use-a verify-pinto verify the PIN and-a verify-biofor fingerprint verification. Seegenerate,test-signature,test-decipher, orsign-data. 6.29.2 Examples $ yubico-piv-tool -a verify-pin -a selfsign -s -S \[ -P -- ˓→pin-policy --touch-policy ˓→ -i --serial --valid-days␣ ˓→DAYS -o \] $ yubico-piv-tool -a verify-pin -a request-certificate -s -S \[ -P ˓→ -i -o \] 6.27. unblock-pin97 YubiKey PIV Tool User Guide —————————————————————————————————————————- 6.30 version 6.30.1 Syntax $ yubico-piv-tool -a version 6.30.2 Description Displays the application version. 6.30.3 Examples $ yubico-piv-tool -a version Application version 4.4.0 found. —————————————————————————————————————————- 6.31 write-object 6.31.1 Syntax $ yubico-piv-tool -a write-object --id -k \[ -i -f ˓→\] 6.31.2 Description Writing an object is an action that requires authentication, which is done by providing the management key. If no management key is provided, the tool tries to authenticate using the default management key. Important:It is strongly recommended to change the Yubikey’s PIN, PUK and management key before start using it. Seeread-objectforSupported PIV Object IDs for read- and write-objectand parameters. 98Chapter 6. PIV Tool Command, Options and Actions CHAPTER SEVEN COPYRIGHT ©2025 Yubico AB. All rights reserved. 7.1 Trademarks Yubico and YubiKey are registered trademarks of Yubico AB. All other trademarks are the property of their respective owners. 7.2 Disclaimer The contents of this document are subject to revision without notice due to continued progress in methodology, design, and manufacturing. Yubico shall have no liability for any error or damages of any kind resulting from the use of this document. Yubico Software referenced in this document is licensed to you under the terms and conditions accompanying the software or as otherwise agreed between you or the company that you are representing. 7.3 Contact Information Yubico AB Kungsgatan 44 111 35 Stockholm Sweden More options for getting touch with us are available on the Contact page of Yubico’s website. 99 YubiKey PIV Tool User Guide 7.4 Document Updated 2025-09-09 18:24:24 UTC 100Chapter 7. Copyright --- # Unknown Secure your sensitive data and critical applications by storing, protecting and managing cryptographic keys with the YubiHSM 2, a dedicated hardware security module (HSM) that offers superior protection against key theft and misuse. A FIPS 140-2 validated version (Level 3) is also available via the YubiHSM 2 FIPS, helping government agencies and organizations across regulated industries such as financial services, healthcare, manufacturing, energy and natural resources and others, drive highest-assurance compliance. With Yubico’s HSM offerings, you get uncompromised cryptographic hardware security for your applications, servers and computing devices at a fraction of the cost and size of traditional HSMs. Technical Specifications Cryptographic interfaces • PKCS#11 API version 2.40 • Microsoft CNG via the Yubico Key Storage • Provider (KSP), both 32 and 64-bit DLLs • Full access to device capabilities through Yubico’s YubiHSM Core Libraries (C, Python) RSA • 2048, 3072, and 4096 bit keys • Signing: PKCS#1 v1.5 and PSS • Decryption: PKCS#1 V1.5 and OAEP Elliptic Curve Cryptography (ECC) • Curves: secp224r1, secp256r1, secp256k1, secp384r1, secp521r, bp256r1, bp384r1, bp512r1, Ed25519 • Signing: ECDSA (all except Ed25519), EdDSA (Ed25519 only) • Derivation: ECDH (all except Ed25519) AES • 128, 196 and 256 bit keys • ECB and CBC mode support (non-FIPS only) Hashing functions • SHA-1, SHA-256, SHA-384, SHA-512 Key wrap • Import and export using NIST-approved AES CCM • Import and export using RSA Secure, low cost hardware protection for cryptographic keys Securing the Cryptographic Key Lifecycle SECURE KEY GENERATION ATTESTATION SECURE KEY STORAGE SECURE KEY DISTRIBUTION SECURE KEY BACKUP SECURE KEY DESTRUCTION Capabilities Random numbers • On-chip True Random Number Generator (TRNG) used to seed NIST SP 800-90A Rev.1 AES-256 CTR\_DRBG Attestation • Asymmetric key pairs generated on-device may be attested using a device-specific Yubico attestation key and certificate or using imported custom keys and certificates Storage capacity • 126KB • 256 object slots • Object types: – Authentication keys – Asymmetric private keys – Opaque binary data objects – Wrap keys – HMAC keys • The potential to store up to 127 rsa2048 or 93 rsa3072 or 68 rsa4096 or 255 of any elliptic curve type Management • Mutual authentication and secure channel between applications and the YubiHSM 2 • M of N unwrap key restore via the YubiHSM Setup Tool Physical characteristics Weight & dimensions • Weight: 0.035274 oz (1g) • Dimensions: 0.47” x 0.51” x 0.12” (12mm x 13mm x 3.1mm) Host interface • USB-A connector • Universal Serial Bus (USB) 2.0 Power consumption • Less than 150mW • Input voltage: 5V Reliability • Can withstand 500,000 write/erase cycles • Mean Time Between Failure (MTBF) is greater than 100 years in most commonly used environments, but may vary in harsher environments • Comes with a standard 1-year warranty The YubiHSM 2 enables secure, tamper-resistant key storage and operations by preventing accidental copying and distribution of cryptographic keys, and preventing remote theft of keys stored in software. Performance Performance varies depending on usage (the accompanying Software Development Kit includes performance tools that can calculate additional measurements). Example metrics from an otherwise unoccupied YubiHSM 2: • RSA-2048-PKCS1-SHA256: ~139ms • RSA-3072-PKCS1-SHA384: ~504ms • RSA-4096-PKCS1-SHA512: ~852ms • ECDSA-P224-SHA1: ~64ms • ECDSA-P256-SHA256: ~73ms • ECDSA-P384-SHA384: ~120ms • ECDSA-P521-SHA512: ~210ms • EdDSA-25519-32Bytes: ~105ms • EdDSA-25519-64Bytes: ~121ms • EdDSA-25519-128Bytes: ~137ms • EdDSA-25519-256Bytes: ~168ms • EdDSA-25519-512Bytes: ~229ms • EdDSA-25519-1024Bytes: ~353ms • AES-(128|192|256)-CCM-Wrap: ~10ms • HMAC-SHA-(1|256): ~4ms • HMAC-SHA-(384|512): ~243ms Learn more yubi.co/hsm Contact us yubi.co/contact company is a pioneer in delivering hardware-based passkey authentication to customers in 160+ countries. For more information, visit: www.yubico.com. © 2024 Yubico Yubico (Nasdaq First North Growth Market Stockholm: YUBICO) is the inventor of the YubiKey, the gold standard in phishing-resistant multi-factor authentication (MFA), and a creator and contributor to FIDO open authentication standards. The --- # Unknown YubiKey Smart Card Minidriver User Guide Yubico Sep 12, 2025 CONTENTS 1 Introduction1 2 YKMD Features3 3 YKMD Installation5 4 Manual Installation7 4.1 MSI File Install . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 4.1.1 Command Line MSI Install . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 4.2 CAB File Install . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8 5 Automated Installation9 5.1 Installing via Group Policy Object . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 5.2 Preparing the Deployment Environment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 5.3 Creating the Driver Store . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 5.4 Method 1 - Auto-Install via Startup Script . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 5.4.1 Create the Minidriver Zip File . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 5.4.2 Create the PowerShell Script . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 5.4.3 Configure the GPO . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 5.4.4 Edit YKMD Deploy GPO . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 5.5 Method 2 - Standard User Install (Manual Update) . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 5.5.1 Preparing YKMD for Distribution . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 5.5.2 Configure the GPO . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 5.5.2.1 Create a new GPO . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 5.5.3 Client Registry Setting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18 5.5.3.1 Update device path . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18 5.5.3.2 Create new Registry . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18 5.5.3.3 Update New Registry . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 5.5.4 Whitelisting the YKMD GUID . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 5.5.4.1 Locate the GUID of YKMD . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 5.5.4.2 Enable and Configure Group Policy . . . . . . . . . . . . . . . . . . . . . . . . . . 21 5.6 Completing the Installation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22 5.6.1 Issue a Group Policy Update . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 6 Verifying Installation25 6.1 Verify Installation Using Powershell . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25 7 Self-Enrolling YubiKeys on Windows27 8 Working with Enterprise Root Certificates29 8.1 Adding an Enterprise Root Certificate to the YubiKey . . . . . . . . . . . . . . . . . . . . . . . . . 29 i 8.2 Manually Delete Certificates . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29 9 Setting PIN Unblock Code (PUK)31 9.1 Set or Change Smart Card PIN . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31 9.2 Unblock a Blocked PIN . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32 10 Setting Touch Policy35 10.1 Set Policy for Touch to Allow Private Key Use . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35 10.2 Touch Policy Options . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35 11 Configure the Minidriver Registry37 11.1 YubiKey Minidriver Registry Key Reference . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37 12 Logging Minidriver Behavior41 13 Uninstall the YubiKey Minidriver43 13.1 YubiKey Minidriver Installed using MSI . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43 13.2 Manual Uninstall . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43 13.3 Preventing Reinstallation after Removal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44 14 Copyright45 14.1 Trademarks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45 14.2 Disclaimer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45 14.3 Contact Information . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45 14.4 Document Updated . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46 ii CHAPTER ONE INTRODUCTION As a tool to deploy smart cards across an environment consisting of multiple domains with multiple user identities stored on a single YubiKey, the YubiKey Minidriver (YKMD) enables management of the YubiKey smart card functionality based on the US Federal Government Personal Identity Verification (PIV) standard (for details on this functionality, see the YubiKey Technical Manual). Microsoft Windows supports traditional PIV smart cards for user authentication, allowing the YubiKey to be utilized as a strong authentication solution. The YubiKey Minidriver extends the support of the YubiKey on Windows from just authentication to allowing Windows to load and directly manage certificates on it. This enables an easy to use, easy to deploy, scalable implementation of strong multi-factor authentication across an entire organization utilizing the native Windows tools and the YubiKey. The YKMD allows for the use of native Windows services to enroll YubiKeys as smart cards, both directly by individual users and by administrators enrolling YubiKeys as smart cards on behalf of other users. The YKMD is a small, lightweight driver that builds on top of the Windows Inbox Smart Card Minidriver (Windows Minidriver). On the Windows operating system, the Windows Minidriver provides basic functionality for using PIV smart cards that have already been provisioned with at least one certificate. However, the Windows Minidriver cannot be used to provision certificates or manage PINs. Unlike this and other native Microsoft tools or legacy Yubico tools, the YKMD accomplishes this by enabling Windows to write directly to the PIV module, utilize the native CertUtil command suite, and add extended functionality when using the YubiKey as a smart card. SeeYKMD Features. Note:For Mac OS and Linux environments in conjunction with Windows PCs, use the YubiKey Manager / ykman instead of the YubiKey Minidriver and native Windows components. Note:Provisioning credentials on the YubiKey using the Windows certificate enrollment dialogs (enabled by the YubkiKey Minidriver)in parallel withother tools such as the YubiKey Manager or Yubico Authenticator is not rec- ommended. See the YubiKey Manager (ykman) CLI User Guide. This guide covers the installation of the YKMD on user PCs, as well as instructions for users enrolling YubiKeys as smart cards directly. 1 YubiKey Smart Card Minidriver User Guide 2Chapter 1. Introduction CHAPTER TWO YKMD FEATURES On the Windows operating system, the Windows Inbox Smart Card Minidriver,msclmd.inf, enables base functionality for using PIV smart cards such as YubiKeys that have been already provisioned with at least one credential. The YubiKey Minidriver provides additional features beyond the base Microsoft support: managing certificates and PINs on a YubiKey via the native Windows GUI and/or APIs and support for ECC cryptographic algorithms. This includes: Certificate Enrollment Options The YKMD adds the following certificate enrollment/deployment options: •Auto-enrollment, enabling users to register their YubiKey directly through the Windows built-in certificate provisioning process. •Enrollment-on-behalf-of: enabling administrators to enroll on behalf of other users through the Microsoft Management Console (MMC) on Windows Server. •Automatic re-enrollment Import certificate chains for user certificates When User Certificates are added to a smart card via Microsoft auto-enrollment or through Windows MMC, the intermediate certificates and root certificate (also known as the certificate chain) are not added to the smart card. If adding the complete certificate chain is required, the YKMD enables root and intermediate certificates to be imported through the MicrosoftCertutil.execommand line utility. Support for multiple authentication certificates/credentials on a single YubiKey Use the YKMD to view all user authentication certificates on the smart card. They are displayed for use by applications based on the certificates’ Key Usage Extension and Extended Key Usage Extension. Certificate Key Algorithms Support Elliptic-Curve (ECC) (Windows 10 and Windows 11) •RSA 2048-bit keys •Elliptic Curve Cryptography (ECC) –ECDH/ECDSA-P256 keys –ECC ECDH/ECDSA-P384 keys We also support 3k/4k and Ed25519/(X25519); however, since the release of Minidriver 4.6.3.252 and the 5.7 firmware on YubiKeys, please note that while Ed25519 certificates will be listed, the private key cannot be used due to limitations of the Windows BaseCSP, which does not support this algorithm. Set and change smartcard PIN via Windows GUI This feature provides the ability to set and change the PIN directly through the Windows interface (press Ctrl + Alt + Del > \[Change a password\]) without the need to install any additional third-party applications. 3 YubiKey Smart Card Minidriver User Guide Unblock a blocked PIN Utilize the Integrated Unblocking Screen. Set policy for touch This allows private key use. Note:For information on how to use these features, see our Support article, Deploying the YubiKey Minidriver to Workstations and Servers. 4Chapter 2. YKMD Features CHAPTER THREE YKMD INSTALLATION The YKMD must be installed on all machines where the YubiKey is used as a smart card for access. These include servers to which users remotely connect, as well as the connecting PC. The YKMD can be downloaded directly from the Yubico website at Smart card drivers and tools. Scroll down the page toYubiKey Smart Card Minidriver (Windows). Note:The YKMD is no longer available through Microsoft Windows Update. When installing the YKMD, there are two options. MSI installer Using either the Windows GUI or Command line We recommend using the MSI installer through the Windows command line for local installations and remote computers and Servers. SeeAutomated Installation. If the MSI installers are blocked, use the CAB installation method. CAB file For large enterprise deployments, Yubico recommends using the CAB file in conjunction with a Group Policy Object Endpoint Configuration utility. This allows installing on to domain-connected machines. SeeAutomated Installation. Yubico recommends using any software management platform already in place to deploy the YKMD to an en- terprise environment. To deploy the YKMD with specific settings, such as with legacy\_nodes and silent\_install, requires an.mstfile to enable these options in addition to the GPO. For information on setting up a Windows Certification Authority for smart card authentication or enabling enroll on behalf of permissions for administrators, see theManual Installation. When using existing keys, the YKMD updates YubiKeys PIV containers to allow Windows to access credentials already present on the YubiKey for slots containing RSA and ECC keys with corresponding valid certificates if the keys and certificates are added manually through other tools. This function is blocked if the management key is manually changed using another tool. Note:We recommendnotprovisioning credentials on the YubiKey using the Windows certificate enrollment dialogs (enabled by the YubkiKey Minidriver) in parallel with other tools such as the YubiKey Manager or Yubico Authentica- tor. If your environment uses Mac OS and Linux in conjunction with Windows PCs, use the YubiKey Manager instead of the YubiKey Minidriver and native Windows components. See the YubiKey Manager (ykman) CLI User Guide. 5 YubiKey Smart Card Minidriver User Guide 6Chapter 3. YKMD Installation CHAPTER FOUR MANUAL INSTALLATION The YubiKey Minidriver can be downloaded directly from the Yubico website and distributed and installed manually by anyone with administrator rights on the computer. The YubiKey Minidriver software is available both as an MSI installer for 32 and 64 bit systems, and as a CAB file. 4.1 MSI File Install The MSI Installer is the preferred method of manually installing the YubiKey Minidriver. Note:The MSI installer automatically looks for and uninstalls previously installed YubiKey Smart Card driver versions from CAB, Windows Update, and an earlier Windows installer package. 1. Download the YubiKey Minidriver, available as an.msifile: a. Go to Windows Smart Card Applications and Tools. b. Scroll down the page toYubiKey Smart Card Minidriver (Windows). c. Select the 32 or 64 bit installer as appropriate for the environment it is installed on. 2. Locate and double-click onYubiKey-Minidriver MSIWindows Installer. 3. Follow the prompts to install the driver. If prompted, restart your computer. 4.1.1 Command Line MSI Install The YubiKey Minidriver MSI can also be installed via command line interface (CLI) using themsiexeccommand. In the following examples, the version number,4.6.3.252, is an example. The actual number changes as downloads are updated. Basic installation The basic CLI install command is: msiexec /i YubiKey-Minidriver-4.6.3.252-x64.msi Unattended installation To install in unattended mode with no user interaction required, include the/passiveflag: msiexec /i YubiKey-Minidriver-4.6.3.252-x64.msi /passive Quiet installation To install in quiet mode with no user interaction or dialog, use the/quietflag: msiexec /i YubiKey-Minidriver-4.6.3.252-x64.msi /quiet 7 YubiKey Smart Card Minidriver User Guide Remote installation When deploying the YubiKey Minidriver to remote servers where the YubiKey cannot be physically inserted: Installing the MSI with theLegacy Nodeoption enabled on servers prevents the “Smart Card Logon Over RDP Fails withRequested Key Container is not Available” error. Create a legacy node for loading the YubiKey Minidriver. To do this, install the YubiKey Minidriver with the INSTALL\_LEGACY\_NODE=1option set: msiexec /i YubiKey-Minidriver-4.6.3.252-x64.msi INSTALL\_LEGACY\_NODE=1 /quiet 4.2 CAB File Install Installing the YubiKey Minidriver via CAB file is suggested in cases where installing via the MSI installer is prohibited. We recommend removing previous version(s) of the YubiKey Minidriver prior to installing the latest version via the CAB file. Note:Earlier versions of the YubiKey Minidriver arenotautomatically removed when installing via the CAB file. 1. Download the CAB file for the YubiKey Minidriver: a. Go to Smart card drivers and tools. b. Scroll down the page toYubiKey Smart Card Minidriver (Windows). 2. Extract the downloaded CAB file to your preferred location. This can simply be done via the CLI using theExpandcommand. For example, to extract the contents to the C:\\ykmddirectory, use the command: expand.exe yubikey-minidriver-4.6.3.252.cab -F:\* C:\\ykmd The version number,4.6.3.252, is an example. The actual number changes as downloads are updated. 3. Ensure no YubiKey is currently connected to your computer. 4. Locate and right-click onykmd.infand selectInstall. 5. Follow the prompts to install the driver. If prompted, restart your computer. 8Chapter 4. Manual Installation CHAPTER FIVE AUTOMATED INSTALLATION This section provides configuration requirements and guidance for deploying YKMD in an enterprise environment. The steps provided allow YKMD to be pushed out to all workstations from a central repository, without requiring administrative rights on the local workstation. There are two ways to automate installing YKMD: Method 1 Auto-install using a Startup Script. This is recommended for most environments. Create a startup script that can be pushed out via Group Policy Object (GPO). This automatically installs YKMD on ALL devices in the computer object OU that the GPO is linked to. Method 2 End user install using Device Manager. This is recommended when YKMD needs to be available to a large number of users but only installed on an as-needed basis: Create a registry entry on all client workstations with a GPO setting allowing standard users to update the inbox drivers to YKMD, without requiring an admin to physically touch or access the machine for the install. This way, the users can insert the YubiKey, launch the Device Manager, and automatically update the smart card driver to the latest version of YKMD. Note:The version number shown below (4.6.3.252) is only an example. The actual number changes as downloads are updated. 5.1 Installing via Group Policy Object For large deployments, YKMD can be centrally installed via Group Policy Objects. By leveraging a PowerShell script for the necessary commands and a shared network drive accessible from every client station to distribute the YKMD files, an Administrator can automate the installation. When creating an installation script, an Administrator needs to ensure they define registry entries for the PUK Policy, the Touch Policy and the Debug Log Policy, as well as installing the INF file directly. 9 YubiKey Smart Card Minidriver User Guide 5.2 Preparing the Deployment Environment The process for deploying the YKMD.cabfile requires every endpoint to be connected to the enterprise GPO domain and to have access to a shared directory. For machines where this is not an option, such as those on isolated networks, YKMD needs to be installed manually. 5.3 Creating the Driver Store The first step to deploying YKMD is creating a network shared directory for the YKMD.cabfile. If you already have a network share for driver software, we recommend using the existing location. If not, you need to create a shared network folder, which is accessible with read and execute permissions for all users. For this example, we create a new folder in theZ:\\drive. 1. Open File Explorer and browse toZ:\\. 2. Create a new folder, such as:SoftwareShare. For example: 3. Inside this folder, create another folder, for example namedYKMD. You can build this file structure per your standard naming convention. 4. Ensure the read, write, execute permissions on the folder are set as follows: •Read / Execute forEveryoneorAuthenticated Users •Read / Write / Execute forAdministrators a. Share network path. 10Chapter 5. Automated Installation YubiKey Smart Card Minidriver User Guide b. Authenticated users permissions settings. c. Administrators permission settings. 5.3. Creating the Driver Store11 YubiKey Smart Card Minidriver User Guide 5.4 Method 1 - Auto-Install via Startup Script This process creates a PowerShell script for installing YKMD. This script is run with elevated permissions via GPO. It deploys YKMD upon startup, and continues to do so until the GPO object is disabled or removed. 5.4.1 Create the Minidriver Zip File The PowerShell script deploys YKMD to the client machines as a zip file. Download the latest version of the YKMD and add it to a zip file namedYKMD.zip. 5.4.2 Create the PowerShell Script The PowerShell script used for the install script connects an endpoint to the shared network folder created previously. SeeCreating the Driver Store. 1. Copy the YKMD components to a local directory on the machine and install YKMD. 2. Create a PowerShell script with all the following items. a. Define the environmental variables at the start of the script. b. Copy theYKMD.zipto a shared folder which users have read permissions to replace the server with name of server that hosts theYKMD.zip. c. Run the script, using your values. $server="Server" $shared\_folder = "shared" $temp = "$env:windir\\temp" $YKMD = "YubiKey-Minidriver-4.6.3.252.cab.sha256" $DriverPath = "$env:windir\\System32\\DriverStore\\FileRepository" $destination = "YKMD" $fullpath = $temp+"\\"+$destination (continues on next page) 12Chapter 5. Automated Installation YubiKey Smart Card Minidriver User Guide (continued from previous page) $logdir = "$temp\\logs"; $logfile = "yubikey.log" $logfullpath = $logdir+"\\"+$logfile; New-Item $logdir -ItemType Directory -force; Start-Transcript -Path $logfullpath -force; copy-item "\\\\$server\\$shared\_folder\\YKMD.zip" -Destination $temp -force; Expand-Archive -Path "$temp\\YKMD.zip" -DestinationPath $fullpath -force; cmd.exe /c expand $fullpath\\$YKMD -F:\* $fullpath | Out-Null Get-ChildItem $fullpath -Recurse -Filter "\*inf" | ForEach-Object { PNPUtil.exe / ˓→add-driver $\_.FullName /install } rundll32.exe setupapi.dll,InstallHinfSection Yubico64\_61\_Install 132 $fullpath\\ ˓→YKMD.inf # Remove the comment\`\`#\`\`from next line to create the device node or leave the␣ ˓→comment to let Windows handle creating the device node when the YubiKey is␣ ˓→inserted. #cmd.exe /c DrvInst.exe "5" "2" "$DriverPath\\YKMD.inf\_amd64\_24989c5c4b9230ad\\ ˓→YKMD.inf" "0" "4e6904753" "0000000000000238" "WinSta0\\Default" Get-Service -Name "Scardsvr" | Set-Service -StartupType Automatic Stop-Transcript Where - •YKMD.zipis copied to a shared folder which users have read permissions to replace the server with name of server that hosts theYKMD.zip. •folder\_nameis replaced with name of shared folder on the network. •tempsets the folder location. •YKMDadds file\_name. The version number,4.6.3.252, is an example. The actual number changes as downloads are updated. •DriverPathadds driver path to the environment variable. •folder\_namereplaces the folder name of destination. •Start-Transcriptstarts recording logs. This doesn’t work if the script is run remotely. •copy-itemdownloads YKMD from the shared folder and install. •Get-ChildIteminstalls the.infdriver. •rundll32.exeimports the registry keys. •Get-Serviceenables the Smart Card Service. •Stop-Transcriptstops logging. 3. Save this PowerShell script (.ps1) on the Windows Server for deployment. 5.4. Method 1 - Auto-Install via Startup Script13 YubiKey Smart Card Minidriver User Guide 5.4.3 Configure the GPO After the installation PowerShell script file is created, create the Group Policy Object to run the script. To do this, create a new GPO and link it to the location of the computer objects which require YubiKey Minidriver. 1. ClickStart > Run > gpmc.msc. 2. Navigate to your domain and locate the OU for the computer objects. 3. Right-click and selectCreate a GPO in this domain and Link it here. 4. Create a descriptive name for this GPO, such as:YKMD Deploy. Example: 5.4.4 Edit YKMD Deploy GPO 1. Right-click the new YKMD Deploy GPO and selectEdit. 2. ExpandComputer Configuration > Policies > Windows Settings > Scripts (Startup/Shutdown). 3. Right-clickStartupand selectProperties. a. SelectAddthenBrowse. b. Using another file explorer window, browse to your startup script (.ps1), then copy and paste the file into theFile namefield. 14Chapter 5. Automated Installation YubiKey Smart Card Minidriver User Guide c. Select the file, then selectOpen. d. With the script in theScript Namefield, selectOK. 4. SelectOKonce more to complete the GPO configuration. 5.4. Method 1 - Auto-Install via Startup Script15 YubiKey Smart Card Minidriver User Guide 5.5 Method 2 - Standard User Install (Manual Update) This process configures endpoints to make YKMD available to install when the standard user is ready. This does not install YKMD until the user requests it via the Device Manager. 5.5.1 Preparing YKMD for Distribution 1. Download YKMD from the Yubico Support site. a. See Windows Smart Card Applications and Tools b. Scroll down the page toYubiKey Smart Card Minidriver (Windows). c. Download the latest release of the YubiKey Minidriver. 2. Extract the downloaded contents: a. Browse to your downloads directory. b. Double click the YKMD.cabfile to open and view the contents. c. SelectAll. d. Right-click >Extract. e. Select either a local directory or extract directly to the fileshare created in previously. SeeCreating the Driver Store. 16Chapter 5. Automated Installation YubiKey Smart Card Minidriver User Guide 5.5.2 Configure the GPO Confirm that the file share is configured and accessible to all client workstations, and that YKMD is extracted to that directory. Once this is accomplished, proceed to configure the GPO. The Group Policy Object handles two things: •Making the client workstations aware of the location of YKMD. This is accomplished via an updated Registry setting. •Allowing standard users to install YKMD without requiring admin privileges. This is accomplished via whitelist- ing the GUID of YKMD. 5.5.2.1 Create a new GPO In the location of the computer objects that require YKMD, create a new GPO and link it. 1. ClickStart > Run > gpmc.msc. 2. Navigate to your Domain and locate the OU for the computer objects. 3. Right-click and selectCreate a GPO in this domain and Link it here. 4. Create a descriptive name for this GPO, such as:YKMD Deploy. For example: 5. Edit this GPO to complete the configuration. Complete the steps in the following sections. 5.5. Method 2 - Standard User Install (Manual Update)17 YubiKey Smart Card Minidriver User Guide 5.5.3 Client Registry Setting 5.5.3.1 Update device path Update the existingDevice Pathregistry setting to reference the newly created driver store. 1. Right-click the new YKMD Deploy GPO and selectEdit. 2. ExpandComputer Configuration > Preferences > Windows Settings > Registry. 3. Right-clickRegistryand selectNew > Registry Wizard. 5.5.3.2 Create new Registry The Registry wizard walks you through creating the new Registry setting for your client machines. 1. When the registry browser comes up, browse toAnother Computeror use theLocal Computersince this registry setting should be the same on both. For this example, we are usingLocal Computer. 2. SelectLocal Computer, then clickNext. 3. Browse to:HKLM > Software > Microsoft > Windows > CurrentVersion. 4. From theCurrentVersionpanel, in the bottom window, scroll down and selectDevicePath. For example: 18Chapter 5. Automated Installation YubiKey Smart Card Minidriver User Guide 5. ClickFinish. 5.5.3.3 Update New Registry Update this new Registry value to append the newly created file share to its search locations. You can append any number of fileshare locations, just separate them with a semicolon. 1. Select theRegistry Wizard Valuescreated inCreate new Registryand rename it to something more descriptive. For example,YKMD Deploy. 2. Fully expand the new registry value. 3. Double-click theDevice Pathso you can edit the contents. 5.5. Method 2 - Standard User Install (Manual Update)19 YubiKey Smart Card Minidriver User Guide 4. Update the last field,Value Data. To update, add the following to the existing value: ;\\\\\\\\ Note the semicolon at the beginning of the string. For example: %SystemRoot%\\inf;\\\\\\SoftwareShare\\YKMD The final value should resemble the following: 5. ClickApply. Then clickOKto save your settings. 20Chapter 5. Automated Installation YubiKey Smart Card Minidriver User Guide 5.5.4 Whitelisting the YKMD GUID This step allows a silent install that does not require the user to elevate to an admin account. 5.5.4.1 Locate the GUID of YKMD 1. Browse to the extracted contents of the YKMD.cabfile. 2. Select the fileYKMD.inf, right-click and open with a text editor. 3. Find the lineClassGuid=. For example: 4. Copy and paste the full content of that line after the=. For example: ClassGuid={990A2BD7-E738-46c7-B26F-1CF8FB9F1391} The GUID:{990A2BD7-E738-46c7-B26F-1CF8FB9F1391}brackets included, is what we are whitelisting. 5.5.4.2 Enable and Configure Group Policy Enable and configure the Group Policy with the updated GUID value: 1. Select the Group PolicyYKMD Deploycreated earlier. SeeConfigure the GPO. 2. Browse to:HKLM > Policies > System > Driver Installation. 3. SelectAllow non-administrators to install drivers for these device setup classes. 4. Right-click, and selectEdit. a. SelectEnabled. b. Under Options on the bottom left, selectShow. c. Add the GUID Value fromLocate the GUID of YKMDinto the next open line. If you have not used this before, this is the first line. For example: 5.5. Method 2 - Standard User Install (Manual Update)21 YubiKey Smart Card Minidriver User Guide d. SelectOK > Apply > OK. 5.6 Completing the Installation Confirm the following installation steps are completed. 1. Creation of a network file share to host and distribute YKMD. 2. Download and extraction of YKMD. 3. GPO created and applied to the computer objects which require YKMD. 4. GPO configured based on Method 1 or Method 2 below: Method 1 Push the PowerShell script file to auto-install YKMD. Method 2 a. Client-side registry update. b. Whitelist of YKMD GUID for installation by non-admin users. Important:If any of the above is not completed, review the instructions in this chapter, before proceeding. 22Chapter 5. Automated Installation YubiKey Smart Card Minidriver User Guide 5.6.1 Issue a Group Policy Update This can be issued as soon as Method 1 or Method 2 tasks are completed.The version numbers shown are examples. The actual number changes as YKMD is updated. 1. Refresh the Group Policy for all clients and publish the new changes. From the command line, issue the command: gpupdate /force For example: 2. If the client computer does not have YKMD installed: Method 1 The end-user must reboot their computer. YKMD is installed during the next reboot. Method 2 The end-user updates YKMD through the Device Manager. a. Launch theDevice Manager. b. Select YKMD. c. SelectUpdate > Search automatically for updated driver software. 3. Confirm YKMD is successfully installed. OpenDevice Manager. 5.6. Completing the Installation23 YubiKey Smart Card Minidriver User Guide 24Chapter 5. Automated Installation CHAPTER SIX VERIFYING INSTALLATION 6.1 Verify Installation Using Powershell The following is a PowerShell script that can be used to verify proper installation of the YKMD. Note:Running the script requires elevation. 1. Run the PowerShell command: Get-WindowsDriver -Online | where {($\_.ProviderName -like "Yubico") -and ($\_. ˓→ClassName -like "SmartCard") -and ($\_.Version -like "\*")} | select ProviderName, ˓→ClassName,Version Where •The command combines thewhereandselectsteps into the single command. •ProviderName,Yubico •ClassName,SmartCard •Version,\* The response is similar to: ProviderName ClassName Version ............. .......... ....... Yubico SmartCard 4.6.3.252 25 YubiKey Smart Card Minidriver User Guide 26Chapter 6. Verifying Installation CHAPTER SEVEN SELF-ENROLLING YUBIKEYS ON WINDOWS There are two methods for enrolling the YubiKey as a smart card for the Windows environment. This chapter covers the self-enrollment process, where a user enrolls their YubiKey directly to their domain-connected Windows PC. The other method allows for an administrator to enroll a YubiKey to another user directly. If your environment has been set up to allow auto-enrollment, the process is straightforward. This section describes the steps you need to complete to enroll your YubiKey for Login. With Auto-Enrollment enabled on the Windows Server and local machines via Group Policy, the end user experience is straightforward. 1. Log into a user account. A Certificate Enrollment popup appears above the System Tray. 2. Click the Certificate Enrollment popup to open the Certificate Enrollment wizard. If the popup has disappeared (or did not initially appear) click thearrowin the System Tray to expand the list of options and click thecertificate icon. 3. On the opening dialog, clickNext. 27 YubiKey Smart Card Minidriver User Guide 4. Select the appropriate certificate template and clickEnroll. If multiple certificate templates are listed, assuming the template was set up properly,STATUS: Enrollment requiredappears next to the correct template. 5. Enter for PIN for your YubiKey and then clickOK. If a PIN has not been set, enter the default PIN,123456. 6. Windows Auto-Enrolls the YubiKey for Windows Login. The process can take several seconds, depending on the network connection to the server running the Certification Authority. When it is completed, clickFinish. 28Chapter 7. Self-Enrolling YubiKeys on Windows CHAPTER EIGHT WORKING WITH ENTERPRISE ROOT CERTIFICATES For a standard forest, Windows can manage the trust chain for the YubiKey smart card authentication automatically. However, in situations where there may not be a direct connection between the Windows computer and the server with the Certification Authority, loading the Root Certificate on a YubiKey can bridge the gap for the initial registration. Common situations covered are: including systems on a multi-forest domain, users logging onto domain accounts from non-domain systems, or deployments adding new systems to a domain using a smart card for authentication. 8.1 Adding an Enterprise Root Certificate to the YubiKey 1. Right-click the WindowsStartbutton and selectWindows PowerShell (admin)orCommand Prompt (Ad- ministrator), depending on your Windows build. 2. Type in the following command and pressEnter: certutil -scroots update 3. When prompted for your Windows Security PIN, enter the PIN for your smart card and then pressEnter. 4. To verify both the smart card certificate and the root certificate are loaded to the smart card, type in the following command and then pressEnter: certutil -scinfo 5. You are prompted to enter your smart card PIN several times. Enter it each time it is requested. 8.2 Manually Delete Certificates To delete certificates from a certificate chain manually, including a Base CSP container and associated key and certifi- cate on the YubiKey 4 or YubiKey NEO through the YubiKey Minidriver, use thecertutilcommand line program. To list the current containers on the card use the command: certutil -key -csp "Microsoft Base Smart Card Crypto Provider" This returns a list of container names and key types. To remove a container cleanly, use the following command while running with elevated permissions as administrator: certutil -delkey -csp "Microsoft Base Smart Card Crypto Provider" "" 29 YubiKey Smart Card Minidriver User Guide 30Chapter 8. Working with Enterprise Root Certificates CHAPTER NINE SETTING PIN UNBLOCK CODE (PUK) When a YubiKey is used with the YubiKey Smart Card Minidriver (YubiKey Minidriver) for the first time, the YubiKey Minidriver checks to ensure that the Management Key and the PIN Unblock Code (PUK) have been changed from the default values. If they have not been changed from the default value, the YubiKey Minidriver upgrades the Management Key to a protected non-default value and blocks the PUK so that the PIN remains blocked. A blocked PUK prevents the PIN Unblock function from being active. 9.1 Set or Change Smart Card PIN The steps in this section use the YubiKey Manager (GUI) to enable: •Setting the smart card PIN during enrollment through the Windows interface. •Changing the PIN directly through the Windows interface. 1. To prevent the PUK from being blocked, configure the local registry prior to setting up YubiKeys. Key HKLM\\\\Software\\\\Yubico\\\\ykmd Value BlockPUKOnMGMUpgrade(DWORD) -0turns off the PUK block feature, any other value enables it. 2. The YubiKey Minidriver supports unlocking a blocked PIN using the built-in Windows UI. To enable this func- tion, enable theAllow Integrated Unblock screen to be displayed at the time of logoninWindows Group Policy. This configuration setting is located in: Computer Configuration > Administrative Templates > Windows Components > Smart Card 3. For the PUK to remain unblocked, use either the YubiKey Manager, the Yubico PIV Tool, or Yubico Authenticator to set a non-default PUK prior to using the Windows interface to load or access certificates stored on the YubiKey. When the YubiKey Minidriver first accesses the YubiKey, it checks if the PUK is set to the default value. For PUKs with user supplied values, this causes the retry counter to decrement by one. This can be reset by entering the correct PUK via the Windows interface, but requires changing the PIV PIN. 4. Setting the PUK can be accomplished in YubiKey Manager by navigating to: Applications > PIV > Configure PINs > Change PUK To use the command-line version of YubiKey Manager (ykman), see theYubiKey Manager (ykman) CLI and GUI Guide, section ykman piv access change-puk. To manage the FIDO2 PIN, see the Yubico Authenticator User Guide, section PIN Protection. 31 YubiKey Smart Card Minidriver User Guide To use Yubico PIV tool, refer to the documentation on Yubico PIV Tool. 9.2 Unblock a Blocked PIN When a user enters their PIN incorrectly three times consecutively, the PIN is blocked and the smart card features are unusable until the PIN is unblocked. If a PIN Unlock Key (PUK) was created for the device, the YubiKey Minidriver allows the PIN to be unblocked directly in the Windows interface by providing the PIN Unlock Key (PUK), in hexadecimal format. Important:You cannot create a PUK with the YubiKey Minidriver. To create a PUK for a YubiKey, follow the instructions forSetting PIN Unblock Code (PUK)using either the YubiKey Manager, the Yubico PIV Tool, or Yubico Authenticator. If you do not create a PUK and you forget your PIN, recovery requires that you reset the device. Resetting the device: •Permanently deletes all private keys and certificates. •Requires new certificates and private keys! By default, the user PIN is blocked when three consecutive incorrect PINs have been entered. The PIN Unblock Code (PUK) is used for unblocking the user PIN. To use the PUK, the administrator must have the PUK enabled when the key and certificate were loaded on the YubiKey. If both the PIN and the PUK are blocked, the YubiKey must be reset, which deletes any loaded certificates and returns the PIN and PUK to default values (123456and12345678, respectively). Note:Both Windows Server 2008 and Windows Server 2008 R2 require the PIN unblock code (PUK) to be typed in as hexidecimal digits. This means that if your PUK is12345678, to unlock a pin through the Windows UI, you must type the ASCII hex-encoded bytes of the PUK string (in this case, the unlock code would be3132333435363738). Refer to an ASCII chart (for example, www.asciitable.com) to encode a PUK in hexidecimal. This does not apply to later versions of Windows. To unblock the user PIN: 1. With the YubiKey inserted, attempt to log in at the Windows login screen. When the PIN is blocked, the following screen appears (example in Windows 10). 32Chapter 9. Setting PIN Unblock Code (PUK) YubiKey Smart Card Minidriver User Guide 2. Check the checkbox next toUnblock smart card. 3. In theResponsefield, enter the PUK code in hexadecimal format. For example: the default value of12345678 in hexadecimal format is3132333435363738. 4. In theNew PINandConfirm PINfields, enter a new, properly formatted PIN, and then pressEnter. 5. Remove the YubiKey, reinsert, and test the new PIN to confirm you can access the account. Note:To enable this function, set theAllow Integrated Unblock screen to be displayed at the time of logon Group Policy Object. This setting is located in: Computer Configuration > Administrative Templates > Windows Components > Smart Card 9.2. Unblock a Blocked PIN33 YubiKey Smart Card Minidriver User Guide 34Chapter 9. Setting PIN Unblock Code (PUK) CHAPTER TEN SETTING TOUCH POLICY The YubiKey can be set to require a physical touch to confirm any cryptographic operations. This is an optional feature to increase security, ensuring that any authentication operation must be carried out in person. The YubiKey Smart Card Minidriver (YubiKey Minidriver) sets the touch policy when a key is first imported or generated. Once set for a key on the YubiKey, the policies cannot be changed. Note:The touch policy setting can influence the user experience. Consider the potential impacts before adjusting this configuration. 10.1 Set Policy for Touch to Allow Private Key Use Set the policy to determine if touching the YubiKey’s button is required to use the certificate’s private key. This is an additional protection against use of a private key without explicit user intent. The policy is stored in the YubiKey’s secure element during private key creation or import and cannot be changed. If a different policy is desired, a new certificate and private key must be created. By default, the touch policy for keys imported/generated through the YubiKey Minidriver, is created with the touch policy default setting:disabled. 10.2 Touch Policy Options To alter the policy behavior, configure the registry prior to setting up keys, either on the station enrolling the keys or pushed out to all machines using Group Policy Objects. Key HKLM\\\\Software\\\\Yubico\\\\ykmd Value NewKeyTouchPolicy(DWORD) - sets the touch policy on new keys generated/imported through the YubiKey Minidriver. Accepted values are: •1 - (No touch required) Default policy of never requiring a user touch. •2 - Policy is set to require a user touch to confirm each and every cryptographic operation. Yubico does not recommend using this setting, as some Windows services, such as login, may require multiple cryptographic operations in a short time span. •3 - (for 15 seconds per touch) Policy is set to require physical touch once, then allow for crypto- graphic operations in a small time window afterwards. For using the physical touch option with Windows Smart Card Logon, this option is required. 35 YubiKey Smart Card Minidriver User Guide Note:Due to OS limitations, there is no visual prompt on the screen when touch is required in this scenario. Microsoft’s minidriver specification that YubiKey Minidriver is based off of has no concept of touch requirement. Change the default through a Windows registry entry and apply it to all new certificate and private key pairs added to the YubiKey. If different policies are required per certificate, change the registry entry prior to creating each certificate. 36Chapter 10. Setting Touch Policy CHAPTER ELEVEN CONFIGURE THE MINIDRIVER REGISTRY The YubiKey Smart Card Minidriver can be configured for non-default behavior through the registry keys. To configure the YubiKey Minidriver registry entries: 1. As administrator, open the Registry Editor. 2. Create the key:HKEY\_LOCAL\_MACHINE\\SOFTWARE\\Yubico\\ykmd. 3. Refer to the table below to add key value(s) as applicable. 4. Close the registry editor and reboot the machine. 11.1 YubiKey Minidriver Registry Key Reference Important:Always thoroughly test configuration prior to implementation. Furthermore, to mitigate risks, we recom- mend that all testing be conducted in a controlled test environment. Finally, note that unless you use the latest version, not all of the settings are necessarily available in your YubiKey Minidriver. You should therefore use the latest version. ValueTypeDataDescription AutoFingerprintDWORD1 (0) Controls the biometric authentication dialog for the YubiKey Bio Multi-protocol Edition. Default1. The YubiKey Minidriver immediately asks for fingerprint verification if a fingerprint is enrolled on the device AND is not blocked. BlockPUKOnMGM Upgrade DWORD0 (1) Controls availability of PUK when the YubiKey is configured with known values. Default1. The YubiKey Minidriver restricts PUK access when the YubiKey value, is at factory value,12345678. Set to0, the PUK functionality is not restricted, regardless if the YubiKey factory value is unchanged. Note: Allowing unblock (PUK) with a known factory value can be a concern. continues on next page 37 YubiKey Smart Card Minidriver User Guide Table 1 – continued from previous page ValueTypeDataDescription DebugOnDWORD0 (1) (Optional) Activates creating a debug log. To enable, set value to1. The registry key value triggers generating a debug log major security that is saved to:C:\\Logs DebugVerbosityDWORD0 (1-3) Applies only when DebugOn is non-zero. Sets logging level used by the YubiKey Minidriver and its dependencies. Valid values are (0) - none to (3) - APDU level verbosity. ExternalPinCache Policy DWORD2 (1-4) This setting overrides thePIN\_CACHE\_POLICY\_TYPE\`for the external PIN\_ID in the YubiKey Minidriver. This setting controls how the YUbiKey Bio PIN (fingerprint) is cached. Default is 0 (PinCacheNormal). This key accepts any valid PIN\_CACHE\_POLICY\_TYPEnumeric value. See https: //learn.microsoft.com/en-us/windows-hardware/drivers/smartcard/ card-pin-operations#-pin\_cache\_policy\_type for more information. ManageCSPCacheDWORD1 (0) Determines if by clearing its cached data, the container map synchronization check compels the BaseCSP to retrieve the container map and certificate details from the YubiKey Minidriver. When disabled,0, this feature prevents certain card modifications from being reflected in the BaseCSP. Note: Deactivating,0, this feature can enhance the certificate enumeration performance. NewKeyTouch Pol- icy DWORD1 (2,3) Enables the touch policy for PIV. Setting is optional. Default1, touch input is not mandatory for PIV operations. Set to2, touch input is enforced at all times (similar to FIDO2). Set to3, touch input activated, with cache touch input for a limited duration with less frequent requirements. Note: While improving security, configuring touch for PIV may have an adverse effect on usability. Note also that this configuration does not impact already configured YubiKeys (the setting must be present at the time of enrollment). PinCacheTimeoutDWORD60 If eitherUserPinCachePolicyorExternalPinCachePolicyis set to ‘timed’ (1), this setting sets the number of seconds for which the BaseCSP caches the PIN. This is only a recommendation to the BaseCSP and is not implemented by the Minidriver. continues on next page 38Chapter 11. Configure the Minidriver Registry YubiKey Smart Card Minidriver User Guide Table 1 – continued from previous page ValueTypeDataDescription ProtectManagementDWORD1 (0) Governs the creation and storage of the PIV card management key within a secure object to enable write access for PIV functionality. Default1. The YubiKey Minidriver generates a new card management key and stores it in a PIN-protected object (in the YubiKey PIV application) when the factory value is present during PIN entry (such as during enrollment). Set to0. Disables feature. Third party solutions (such as CMS products), while managing YubiKeys may optionally disable this setting and assume ownership of this feature and dependant processes (suchas enrollment). RefreshDeviceKeysDWORD1 (0) Controls the behavior of container map synchronization that happens based on the timeout defined by RefreshWindow. Default,1, The YubiKey Minidriver (YKMD) checks that the container map stored in the mscmap PIV object matches the container map in the SCardCache. Additionally, the YKMD enumerates all keys and certificates in the PIV application the and then updates map accordingly. Set to0, disables feature. This can improve performance, especially over RDP. However, certificates enrolled outside of the YubiKey Minidriver might not be present in the container map as reported to theBaseCSP(!) RefreshWindowDWORD300 Sets the time interval (in seconds) for how often the YubiKey Minidriver (YKMD) synchronizes the container map reported to the BaseCSP. By default the YubiKey Minidriver (YKMD) performs synchronization when the time difference between the last call from the BaseCSP and current time exceeds 300 seconds. During synchronization the YKMD: 1. Clears the BaseCSP cache (depending on setting of ManageCSPCache). 2. Enumerates the certificates and keys in the PIV application (depending on setting of RefreshDeviceKeys). 3. Ensures the currently cached container map contains the same information as the on-card container map and the list of newly enumerated certificates. Note: Setting a higher value than default may have a positive impact on performance without using the heavier-handed settings of RefreshDeviceKeys and ManageCSPCache continues on next page 11.1. YubiKey Minidriver Registry Key Reference39 YubiKey Smart Card Minidriver User Guide Table 1 – continued from previous page ValueTypeDataDescription SupportAlwaysPinDWORD1 (0) Enables and disables support for theAlways Prompt PIN\_IDin the YubiKey Minidriver. TheAlways Prompt PIN\_ID, PIN\_CACHE\_POLICY\_TYPEis set toPinCacheAlwaysPromptand is assigned as the PIN for key containers that map to PIV slots that have thePIN\_ALWAYSpin policy in the YubiKey PIV application (such as, slot 9c) in devices that support slot metadata (YubiKey 5.2.7+). UserPinCache Policy DWORD0 (1-4) This setting overrides thePIN\_CACHE\_POLICY\_TYPEfor the user PIN\_ID in the YubiKey Minidriver. Default is 0 (PinCacheNormal). This key accepts any validPIN\_CACHE\_POLICY\_TYPEnumeric value. See https: //learn.microsoft.com/en-us/windows-hardware/drivers/smartcard/ card-pin-operations#-pin\_cache\_policy\_type for more information. 40Chapter 11. Configure the Minidriver Registry CHAPTER TWELVE LOGGING MINIDRIVER BEHAVIOR Should errors occur in the use of the YubiKey as a PIV Smart Card with YKMD, error logging can be enabled on the local computer using the registry. Once enabled, log files are created per running process inC:\\Logs. See Smart Card Basic Troubleshooting for additional troubleshooting steps. Key HKEY\_LOCAL\_MACHINE\\SOFTWARE\\Yubico\\ykmd Value DebugOn(DWORD) -1enables error logging. Note:Refer toConfigure the Minidriver Registryfor additional registry settings. 41 YubiKey Smart Card Minidriver User Guide 42Chapter 12. Logging Minidriver Behavior CHAPTER THIRTEEN UNINSTALL THE YUBIKEY MINIDRIVER 13.1 YubiKey Minidriver Installed using MSI If the YubiKey Smart Card Mindriver (YubiKey Minidriver) was installed using the MSI, Yubico recommends using the Program and Features Interface to remove it. 1. UseWindows+Rto display the run terminal window, enterappwiz.cpland clickOK. 2. The Programs and Features window opens. Scroll down and locate the entry for theYubiKey Smart Card Minidriver. 3. Right click on the YubiKey Minidriver entry and selectUninstall. 13.2 Manual Uninstall Manual install is run in a terminal. 1. OpenCommand Prompt as AdministratororPowerShell as Admin. 2. Run:%windir%\\System32\\DriverStore\\FileRepository 3. Typecd ykmdand pressTab, and then pressEnter. The current path should look similar to the following: C:\\Windows\\System32\\DriverStore\\FileRepository\\ykmd.inf\_amd64\_1e4c7d5bdb6914f9 4. If multiple versions of the YubiKey Minidriver have been installed, each has its own separate directory. Repeat this and the following steps for each installation directory. 5. Type the following command and pressEnter: rundll32 setupapi.dll,InstallHinfSection DefaultUninstall 4 .\\\\ykmd.inf 6. If you want to also delete the driver and other related files from your computer: Delete the entire YubiKey Minidriver directory in%windir%\\System32\\DriverStore\\FileRepository\\ From the example in step 3, the directory name isykmd.inf\_amd64\_1e4c7d5bdb6914f9. To do delete the driver and related files: a. The Admin needs to take ownership of the directory use thetakeowncommand. For example, using the directory from step 3, the command is: TAKEOWN /F ykmd.inf\_amd64\_1e4c7d5bdb6914f9 /R /A 43 YubiKey Smart Card Minidriver User Guide b. Following taking ownership of the directory, grant full control access to the directory and the files within with theicalcscommand. For example, using the directory from step 3, the command is: ICACLS ykmd.inf\_amd64\_1e4c7d5bdb6914f9 /grant Administrator:F /T c. After the ownership and access is set, the files can be deleted as normal. 13.3 Preventing Reinstallation after Removal To prevent the YubiKey Minidriver from being reinstalled after removal, blocked it via the Windows Group Policy. These are steps for Windows 10. Steps for Windows 11 are slightly different. 1. Right-click the WindowsStartbutton and selectRun. 2. Typegpmc.mscand pressEnter. 3. Navigate to the AD forest and Domain containing your server, double-click your server and double-clickGroup Policy Objects. 4. Right-click on the group policy you want to edit, and then selectEdit. 5. ExpandComputer Configuration > Administrative Templates > System > Device Installation > Device Installation Restrictions. 6. Right-clickPrevent installation of the of devices that match any of these device IDsand selectEdit. 7. Click the optionEnabled. 8. UnderOptions, clickShow. 9. Enter theHardware ID. This can be found via Device Manager: a. ClickSmart Cards > YubiKey Smart Card. b. Right click on theYubiKey Smart Cardand selectProperties. c. Open theDetailstab, and the drop down toHardware IDs. TheSCFILTER\\CID\_ID#value for the YubiKey is displayed. Note that YubiKey 4, YubiKey 5, and YubiKey NEO have different hardware IDs. 10. ClickOK. 44Chapter 13. Uninstall the YubiKey Minidriver CHAPTER FOURTEEN COPYRIGHT ©2024-2025 Yubico AB. All rights reserved. 14.1 Trademarks Yubico and YubiKey are registered trademarks of Yubico AB. All other trademarks are the property of their respective owners. 14.2 Disclaimer The contents of this document are subject to revision without notice due to continued progress in methodology, design, and manufacturing. Yubico shall have no liability for any error or damages of any kind resulting from the use of this document. Yubico Software referenced in this document is licensed to you under the terms and conditions accompanying the software or as otherwise agreed between you or the company that you are representing. 14.3 Contact Information Yubico AB Gävlegatan 22 113 30 Stockholm Sweden More options for getting touch with us are available on the Contact page of Yubico’s website. 45 YubiKey Smart Card Minidriver User Guide 14.4 Document Updated 2025-09-12 21:15:41 UTC 46Chapter 14. Copyright --- # Unknown .. index.rst ==================== YubiHSM 2 User Guide ==================== .. toctree:: :maxdepth: 2 :caption: Contents hsm2-introduction hsm2-core-concepts hsm2-sdk-tools-libraries hsm2-quick-start hsm2-index-tools hsm2-index-third-party hsm2-index-references .. --- # FIDO U2F overview ##### Table of Contents FIDO U2F overview ================= The acronym FIDO stands for "Fast IDentity Online". The FIDO Alliance is a standards body, of which Yubico is a member, that provides techniques for using security keys to instantly access any number of online services (such as login) with no drivers or host device software needed. There are two FIDO standards that the YubiKey currently implements: * FIDO U2F * FIDO2 These standards a related. U2F can be thought of as "version 1" of the standard, and FIDO2 is "version 2". "U2F" stands for "Universal Second Factor" authentication. The SDK treats each version as a separate application, even though there is some overlap inside the YubiKey itself. Future versions of the SDK's User's Manual will contain a FIDO2 section as well. Find the home of FIDO at the [FIDO Alliance](https://fidoalliance.org/) . You can also find Yubico's introduction to U2F [here](https://www.yubico.com/authentication-standards/fido-u2f/) . There are three components in FIDO U2F * The authenticator (YubiKey) * The client (a browser, platform component, or application) * The relying party (verifies the authentication process) With FIDO U2F, the host (e.g. the laptop or phone) does not need any drivers or other software outside of the client which implements support for U2F. If no U2F client is available, it will not be possible to perform the authentication. You will often hear the term "CTAP1" (pronounced "see-tap-one") with respect to FIDO U2F. Briefly, CTAP1 is the name given by the newer FIDO2 standard to the part dealing with communication between the authenticator (the YubiKey) and the client (the browser). In fact, it stands for "Client To Authenticator Protocol". CTAP1 is the specification used for U2F. Later on, with FIDO2, the communication protocol was updated as well. Hence, FIDO2 primarily uses CTAP2. More information on CTAP is given in further User's Manual articles. Another term you might hear is "WebAuthn" (pronounced "web-auth-en"). That is related to FIDO2 and will be described in future SDK User Manuals. [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-u2f/fido-u2f-overview.md/#L1) --- # FIDO2 overview ##### Table of Contents FIDO2 overview ============== The acronym FIDO stands for "Fast IDentity Online". The FIDO Alliance is a standards body, of which Yubico is a member, that provides techniques for using security keys to instantly access any number of online services (such as login) with no drivers or host device software needed. There are two FIDO standards that the YubiKey currently implements: * FIDO U2F * FIDO2 These standards are related. U2F can be thought of as "version 1" of the standard, and FIDO2 is "version 2". "U2F" stands for "Universal Second Factor" authentication. The SDK treats each version as a separate application, even though there is some overlap inside the YubiKey itself. Find the home of FIDO at the [FIDO Alliance](https://fidoalliance.org/) . You can also find Yubico's introduction to FIDO2 [here](https://www.yubico.com/authentication-standards/fido2/) . There are three components in FIDO U2F: * The authenticator (YubiKey) * The client (a browser, platform component, or application) * The relying party (verifies the authentication process) With FIDO2, the host (e.g. the laptop or phone) does not need any drivers or other software outside of the client which implements support for FIDO2. If no FIDO2 client is available, it will not be possible to perform the authentication. You will often hear the term "CTAP" (pronounced "see-tap") with respect to FIDO2. Briefly, CTAP is the name given by the FIDO2 standard to the section of the standard dealing with communication between the client (browser) and authenticator (the YubiKey). In fact, it stands for "Client To Authenticator Protocol". CTAP1 is the specification used for U2F. Later on, with FIDO2, the communication protocol was updated as well. Hence, FIDO2 primarily uses CTAP2. More information on CTAP is given in further User's Manual articles. Another term you might hear is "WebAuthn" (pronounced "web-auth-en", short for Web Authentication). This is a specification from the W3C (World Wide Web Consortium) and the FIDO Alliance that further defines many of the details of FIDO2, CTAP2, and the communication between the relying party and client. As often happens in computer technology, the once-precise terminology has become somewhat informal. Very often, you will hear people talking about FIDO2 and they will use the terms CTAP, CTAP2, or WebAuthn to mean the entirety of FIDO2. To help dispell any confusion, here is a brief summary of these standards and their relationships to each other. * FIDO: Fast IDentiy Online, the standards body that developed U2F and FIDO2 * CTAP: Client To Authenticator Protocol * U2F: Universal Second Factor, the first generation of the standard * Includes CTAP, later called CTAP1 * Includes Relying Party to Client communication * FIDO2: The second generation of the standard * Developed as a partnership between the FIDO Alliance and W3C * Relying Party to Client communication defined in WebAuthn * Includes CTAP2, defined in FIDO2 and W3C documents [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-fido2/fido2-overview.md/#L1) --- # YubiHSM Auth overview ##### Table of Contents YubiHSM Auth overview ===================== YubiHSM Auth is a YubiKey CCID application that stores the long-lived [credentials](https://docs.yubico.com/yesdk/users-manual/application-yubihsm-auth/objects/credential.html) used to establish secure sessions with a YubiHSM 2. The secure session protocol is based on Secure Channel Protocol 3 (SCP03). YubiHSM Auth is supported by YubiKey firmware version 5.4.3. YubiHSM Auth uses hardware to protect these credentials. In addition to providing robust security for the YubiHSM Auth application itself, this hardware protection subsequently increases the security of the default password-based solution for YubiHSM 2's authentication. For a guide on establishing a secure connection and performing operations on a YubiHSM 2, please refer to [Interacting with a YubiHSM 2](https://docs.yubico.com/yesdk/users-manual/application-yubihsm-auth/interacting-yubihsm-2.html) . Management key -------------- A 16-byte management key is required when adding or deleting credentials from the YubiHSM Auth application. The default value of the management key is all zeros, and should be changed before using the application. There is a limit of 8 attempts to authenticate with the management key before the management key is blocked. Once it is blocked, the application itself must be reset before authentication can be attempted again. Supplying the correct management key before the key is blocked will reset the retry counter to 8. Credential ---------- Each credential contains a cryptographic key set which is used to establish secure sessions with a YubiHSM 2. Once a credential is added, it cannot be changed or modified in any way. Each credential has a 16-byte password which is required when calculating session keys. There is a limit of 8 retries, after which the credential will be permanently deleted. Supplying the correct password before the credential is deleted will reset the retry counter to 8. Optionally, the credential may be configured to also require touch when calculating session keys. This proof of user presence provides an additional layer of security. For more information, see the [credential overview](https://docs.yubico.com/yesdk/users-manual/application-yubihsm-auth/objects/credential.html) . [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-yubihsm-auth/yubihsm-auth-overview.md/#L1) --- # PIV overview ##### Table of Contents PIV overview ============ Personal Identity Verification (PIV) is defined in FIPS 201. It is a US government standard defining various authentication and cryptographic operations using a smart card. It defines a set of functions and specifies behavior of a smart card. To be a PIV-compliant smart card, a device must implement these functions in the specified manner. A developer that wants to build an application that utilizes a PIV-compliant smart card can read the PIV specification, create the command APDUs (see the article on [APDUs](https://docs.yubico.com/yesdk/users-manual/yubikey-reference/apdu.html) ), send them over an appropriate transport protocol, and interpret the response APDUs. Alternatively, the developer can use the SDK. [Make the connection](https://docs.yubico.com/yesdk/users-manual/sdk-programming-guide/making-a-connection.html) , create a [PivSession](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.PivSession.html) , then call appropriate methods, such as [GenerateKeyPair](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.PivSession.html#Yubico_YubiKey_Piv_PivSession_GenerateKeyPair_) or [Sign](https://docs.yubico.com/yesdk/yubikey-api/Yubico.YubiKey.Piv.PivSession.html#Yubico_YubiKey_Piv_PivSession_Sign_) . [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-piv/piv-overview.md/#L1) --- # Unknown .. index.rst ============================ Yubico Product Documentation ============================ .. toctree:: :maxdepth: 3 :caption: CONTENTS YubiKeys ========== .. image:: graphics/hardware.png :width: 60 \*YubiKeys\* are hardware authentication devices that protect user access to computers, networks, and online accounts and services through phishing-resistant multi-factor authentication and passwordless login. \* \*\*YubiKey Technical Manual\*\* \[\`HTML <./hardware/yubikey/yk-tech-manual/index.html>\`\_\] \[\`PDF <./hardware/yubikey/yk-tech-manual/webdocs.pdf>\`\_\] \* \*\*YubiKey Technical Data Sheet\*\* \[\`PDF <./hardware/yubikey/datasheet/\_static/YubiKey\_technical\_data\_sheet.pdf>\`\_\] \* \*\*YubiKey FIPS 4 Series Technical Manual\*\* \[\`HTML <./hardware/yubikey/yk-fips-4/index.html>\`\_\] \[\`PDF <./hardware/yubikey/yk-fips-4/webdocs.pdf>\`\_\] \* \*\*Yubico Object ID (OID) Reference Guide\*\* \[\`HTML <./hardware/oid/index.html>\`\_\] \[\`PDF <./hardware/oid/webdocs.pdf>\`\_\] \* \*\*Implementation Guidance and Support: Yubico Best Practices\*\* \[\`HTML <./hardware/yubikey-guidance/best-practices/index.html>\`\_\] \[\`PDF <./hardware/yubikey-guidance/best-practices/webdocs.pdf>\`\_\] ------------------------- YubiEnterprise Services ======================== .. image:: graphics/services-icon.png :width: 90 \*YubiEnterprise Services\* enable organizations to order and distribute YubiKeys efficiently and rapidly. Includes the \*YubiEnterprise Console\* user interface and the \*YubiEnterprise API\* for managing orders and delivery of YubiKeys to end users. \*Yubico FIDO Pre-reg\* and \*YubiEnroll\* are part of the Yubico Enrollment Suite which empowers organizations to streamline management of pre-registered and pre-enrolled YubiKeys for end users, on their path to stronger security. \* \*\*YubiEnterprise Services User Guide & Release Notes\*\* \[\`HTML <./cloud-services/yubienterprise/delivery/>\`\_\] \`\[PDF <./cloud-services/yubienterprise/delivery/webdocs.pdf>\`\_\] \* \*\*YubiEnterprise API Reference\*\* \[\`HTML \`\_\] \* \*\*Yubico FIDO Pre-reg with Okta - Integration Guide\*\* \[\`HTML <./cloud-services/fidoprereg-okta/>\`\_\] \[\`PDF <./cloud-services/fidoprereg-okta/webdocs.pdf>\`\_\] \* \*\*Yubico FIDO Pre-reg with Microsoft - Integration Guide\*\* \[\`HTML <./cloud-services/fidoprereg-microsoft/>\`\_\] \[\`PDF <./cloud-services/fidoprereg-microsoft/webdocs.pdf>\`\_\] \* \*\*YubiEnroll User Guide & Release Notes\*\* \[\`HTML <./software/yubikey/tools/yubienroll/>\`\_\] \[\`PDF <./software/yubikey/tools/yubienroll/webdocs.pdf>\`\_\] \* \*\*YubiEnroll with Okta - Quick Start Guide\*\* \[\`PDF <./software/yubikey/tools/yubienroll/\_static/YubiEnroll-with-Okta-Quick-Start-Guide.pdf>\`\_\] \* \*\*YubiEnroll with Microsoft - Quick Start Guide\*\* \[\`PDF <./software/yubikey/tools/yubienroll/\_static/YubiEnroll-with-Microsoft-Quick-Start-Guide.pdf>\`\_\] ------------------------- Apps & Tools ============== .. image:: graphics/apps-tools-icon.png :width: 80 \*Yubico Authenticator\* is a desktop and mobile application that allows end users to manage their YubiKeys and perform common operations, such as generating and displaying OATH two-factor authentication codes, managing the FIDO PIN, and performing a factory reset. The \*ykman CLI\* is an advanced command line tool for desktop that provides comprehensive YubiKey management and configuration capabilities across all YubiKey applications. The \*Yubico PIV tool\* is used for interacting with the Personal Identity Verification (PIV) application on a YubiKey. The \*YubiKey Minidriver\* (YKMD) enables integration of the YubiKey's PIV smart card capabilities with Windows, unlocking functionality such as certificate enrollment, management of YubiKey smart card PINs, and smart card authentication on Windows devices. \* \*\*Yubico Authenticator User Guide\*\* \[\`HTML <./software/yubikey/tools/authenticator/auth-guide/index.html>\`\_\] \[\`PDF <./software/yubikey/tools/authenticator/auth-guide/webdocs.pdf>\`\_\] \* \*\*YubiKey Manager (ykman) CLI User Guide\*\* \[\`HTML <./software/yubikey/tools/ykman/>\`\_\] \`\[PDF <./software/yubikey/tools/ykman/webdocs.pdf>\`\_\] \* \*\*Yubico PIV Tool User Guide\*\* \[\`HTML <./software/yubikey/tools/pivtool/index.html>\`\_\] \[\`PDF <./software/yubikey/tools/pivtool/webdocs.pdf>\`\_\] \* \*\*YubiKey Minidriver User Guide\*\* \[\`HTML <./software/yubikey/tools/minidriver/index.html>\`\_\] \[\`PDF <./software/yubikey/tools/minidriver/webdocs.pdf>\`\_\] ------------------------- YubiHSM ========= .. image:: graphics/yubi-hsm-icon.png :width: 80 \*YubiHSM\* is a Hardware Security Module (HSM) device that secures modern infrastructure, including servers. It provides advanced protection for sensitive data, like cryptographic keys, digital certificates, and passwords, as well as code signing operations. \* \*\*YubiHSM 2 User Guide\*\* \[\`HTML <./hardware/yubihsm-2/hsm-2-user-guide/index.html>\`\_\] \`\[PDF <./hardware/yubihsm-2/hsm-2-user-guide/webdocs.pdf>\`\_\] \* \*\*YubiHSM 2 Technical Data Sheet\*\* \[\`PDF <./hardware/yubihsm-2/datasheet/\_static/YubiHSM\_2\_Technical\_Data\_Sheet.pdf>\`\_\] ------------------------- SDKs & Libraries ================== .. image:: graphics/sdk-icon.png :width: 90 Yubico provides a range of desktop and mobile SDKs that allow developers to build YubiKey functionality into custom applications. \*java-webauthn-server\* is a server-side WebAuthn library for Java that provides implementations of relying party operations for developers wanting to create their own FIDO2/WebAuthn server. \*python-fido2\* is a server-side and client-side library for Python that provides functionality for communicating with FIDO devices over USB and verifying attestation and assertion signatures. \* \*\*YubiKey SDK for Desktop (.NET)\*\* \[\`HTML \`\_\] \* \*\*YubiKey SDK for iOS\*\* \[\`HTML \`\_\] \* \*\*YubiKey SDK for Android\*\* \[\`HTML \`\_\] \* \*\*Java WebAuthn Server-side Library\*\* \[\`HTML \`\_\] \* \*\*Python WebAuthn/FIDO2 Server-side and Client-side Library\*\* \[\`HTML \`\_\] ------------------------- Other Documentation ===================== \* \`Yubico Developer Program \`\_ \* \`Yubico Support \`\_ |document update date| .. --- # Introduction — YubiHSM 2 User Guide documentation * [](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/index.html) * Introduction * [View page source](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/_sources/hsm2-introduction.rst.txt) * * * Introduction[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-introduction.html#introduction "Permalink to this heading") ============================================================================================================================================= The YubiHSM 2 is a USB-based, multi-purpose cryptographic device for servers. Its diminutive physical size is ideal for installation directly into internal or external server ports. It is a Hardware Security Module (HSM) that is cost-effective for all organizations. It provides advanced cryptography including hashing, asymmetric, and symmetric key cryptography to protect the cryptographic keys that secure critical applications, identities, and sensitive data in an enterprise for certificate authorities, databases, code signing and more. Operating System Requirements[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-introduction.html#operating-system-requirements "Permalink to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- The YubiHSM 2 SDK is built and provided for the following operating systems. This includes Windows, Linux distributions, and macOS. See [YubiHSM2 Releases](https://developers.yubico.com/YubiHSM2/Releases/) for most recent platform YubiHSM2 downloads. | Operating System | Architecture | Latest Date | Version | | --- | --- | --- | --- | | Centos | amd64 | 2023-11-02 | Centos7 | | Darwin | amd64 | 2025-08-11 | macOS 15, 14, 13 | | Darwin | arm64 | 2025-08-11 | macOS 15, 14, 13 | | Darwin | universal | 2025-08-11 | macOS 15, 14, 13 | | Debian | amd64 | 2025-06-12 | Debian 12, 11 | | Fedora | amd64 | 2025-06-12 | Fedora 42, 41 | | Ubuntu | amd64 | 2025-06-12 | Ubuntu 25.04, 24.10, 24.04 | | Windows | amd64 | 2025-06-12 | Windows Server 2025, 2022,

Windows 11, 10 | Physical Characteristics[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-introduction.html#physical-characteristics "Permalink to this heading") --------------------------------------------------------------------------------------------------------------------------------------------------------------------- ![_images/yk5-nano.png](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/_images/yk5-nano.png) _YubiHSM 2 Physical Device_ * Form factor: nano designed for confined spaces such as internal USB ports in servers * Dimensions: 12mm x 13mm x 3.1mm * Weight: 0.5g ### Temperatures[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-introduction.html#temperatures "Permalink to this heading") * Operational range: 0°C - 40°C (32°F - 104°F) * Storage range: -20°C - 85°C (-4°F - 185°F) ### Host Interface[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-introduction.html#host-interface "Permalink to this heading") Universal Serial Bus (USB-A) 1.x Full Speed (12 Mbit/s) Peripheral with bulk interface. ### Storage Capacity[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-introduction.html#storage-capacity "Permalink to this heading") * All data stored as objects. 256 object slots, 126KB max total * Stores up to 127 rsa2048 or 93 rsa3072 or 68 rsa4096 or 255 of any elliptic curve type, assuming only one authentication key is present * [Objects](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-core-concepts.html#hsm2-concepts-objects-label) : Authentication keys (used to establish sessions); Asymmetric private keys; Opaque binary data objects (e.g. x509 certificates); Wrap keys; HMAC keys YubiHSM 2 Cryptographic Specifications[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-introduction.html#yubihsm-2-cryptographic-specifications "Permalink to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ### Cryptographic Interfaces[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-introduction.html#cryptographic-interfaces "Permalink to this heading") * PKCS#11 API version 2.40 * Yubico Key Storage Provider (KSP) to access Microsoft CNG. The KSP is provided as 64-bit and 32-bit DLLs * Full access to device capabilities through Yubico’s YubiHSM Core Libraries (C, Python) ### Advanced Encryption Standard (AES)[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-introduction.html#advanced-encryption-standard-aes "Permalink to this heading") * 128, 192, and 256-bit keys * Support for Electronic Code Book (ECB), Cipher Block Chaining (CBC) and Counter (CCM) modes ### RSA[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-introduction.html#rsa "Permalink to this heading") * 2048-, 3072-, and 4096-bit keys (with e=65537) * Signing using PKCS#1v1.5 and PSS * Decryption using PKCS#1v1.5 and OAEP ### Elliptic Curve Cryptography (ECC)[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-introduction.html#elliptic-curve-cryptography-ecc "Permalink to this heading") * Curves: secp224r1, secp256r1, secp256k1, secp384r1, secp521r, bp256r1, bp384r1, bp512r1, Ed25519 * Signing: ECDSA (all except Ed25519), EdDSA (Ed25519 only) * Derivation: ECDH (all except Ed25519) ### Hashing Functions[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-introduction.html#hashing-functions "Permalink to this heading") SHA-1, SHA-256, SHA-384, SHA-512 ### Key Wrap[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-introduction.html#key-wrap "Permalink to this heading") Import and export using NIST-approved AES-CCM Wrap with 128-, 196-, and 256-bit keys ### Random Numbers[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-introduction.html#random-numbers "Permalink to this heading") On-chip True Random Number Generator (TRNG) used to seed NIST SP 800-90A Rev.1 AES-256 CTR\_DRBG ### Attestation[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-introduction.html#attestation "Permalink to this heading") Asymmetric key pairs generated on-device may be attested using a device-specific Yubico attestation key and certificate, or using your own keys and certificates imported into the HSM. See [Attestation](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-core-concepts.html#hsm2-concepts-attestation-label) . FIPS certified[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-introduction.html#fips-certified "Permalink to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------- Note This section applies to YubiHSM 2 FIPS devices only. YubiHSM 2 FIPS is FIPS 140-2 Level 3 certified device, which means it can be used in solutions that are meant to comply with FIPS 140-2 requirements. Certification by National Institute of Standards and Technology (NIST) can be found at: [https://csrc.nist.gov/projects/cryptographic-module-validation-program/certificate/3916](https://csrc.nist.gov/projects/cryptographic-module-validation-program/certificate/3916) YubiHSM 2 FIPS devices include the text “FIPS” laser-etched onto the surface of the device and allow YubiHSM 2 FIPS to run in FIPS Approved mode. The YubiHSM 2 is available in a FIPS-capable version called YubiHSM 2 FIPS. The YubiHSM 2 FIPS can be configured in an approved mode and a non-approved mode of operation. In the approved mode, only FIPS-approved algorithms are supported. In the non-approved mode, additional non-approved algorithms such as `rsa-pkcs1-sha1` are supported. FIPS-approved mode can be configured only after a device reset by enabling the `fips-mode` option and immediately changing the default Authentication key. For instructions on configuring the YubiHSM 2 FIPS in FIPS-approved mode, see [FIPS Mode Support Guide](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-fips-support-guide.html) . A key attestation generated on a YubiHSM 2 FIPS device with firmware version 2.4.1 or newer has an X.509 extension present with OID `1.3.6.1.4.1.41482.4.12`. If the key attestation was generated in FIPS-approved mode, this extension BOOLEAN value is `TRUE`. Otherwise, the BOOLEAN value is `FALSE`. The pre-loaded certificate of a YubiHSM 2 FIPS device has an X.509 extension present with OID `1.3.6.1.4.1.41482.4.10`. This extension has an INTEGER value encoding its FIPS certificate. Currently, the value `6` refers to the YubiHSM 2 FIPS [certificate](https://csrc.nist.gov/projects/cryptographic-module-validation-program/certificate/3916) for firmware version 2.2. Performance[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-introduction.html#performance "Permalink to this heading") ------------------------------------------------------------------------------------------------------------------------------------------- Performance varies depending on usage. The accompanying Software Development Kit includes performance tools that can be used for additional measurements. Example metrics from an otherwise unoccupied YubiHSM 2: * RSA-2048-PKCS1-SHA256: ~139ms * RSA-3072-PKCS1-SHA384: ~504ms * RSA-4096-PKCS1-SHA512: ~852ms * ECDSA-P224-SHA1: ~64ms * ECDSA-P256-SHA256: ~73ms * ECDSA-P384-SHA384: ~120ms * ECDSA-P521-SHA512: ~210ms * EdDSA-25519-32Bytes: ~105ms * EdDSA-25519-64Bytes: ~121ms * EdDSA-25519-128Bytes: ~137ms * EdDSA-25519-256Bytes: ~168ms * EdDSA-25519-512Bytes: ~229ms * EdDSA-25519-1024Bytes: ~353ms * AES-(128|192|256)-CCM-Wrap: ~10ms * HMAC-SHA-(1|256): ~4ms * HMAC-SHA-(384|512): ~243ms Management[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-introduction.html#management "Permalink to this heading") ----------------------------------------------------------------------------------------------------------------------------------------- * Mutual authentication and secure channel between applications and the YubiHSM 2. * `M of N` unwrap key restore via YubiHSM Setup Tool [Cookies](https://www.yubico.com/support/terms-conditions/cookie-notice/) | [Privacy Policy](https://www.yubico.com/support/terms-conditions/privacy-notice/) --- # Core Concepts — YubiHSM 2 User Guide documentation * [](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/index.html) * Core Concepts * [View page source](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/_sources/hsm2-core-concepts.rst.txt) * * * Core Concepts[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-core-concepts.html#core-concepts "Permalink to this heading") ================================================================================================================================================ The concepts presented here are required knowledge to be successful with operating the HSM. Objects[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-core-concepts.html#objects "Permalink to this heading") ------------------------------------------------------------------------------------------------------------------------------------ The first concept that we will present is the Object. Any persistently stored and self-contained piece of information present in a YubiHSM 2 is an Object. This is intentionally a very generic and broad definition which can be easily rephrased as _everything is an Object_. Objects have associated properties that characterize them and give them different meanings. Regardless of the kind and the specific properties, any YubiHSM 2 device can store up to 256 Objects. Their combined size cannot exceed 126 KB. ### Object Type[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-core-concepts.html#object-type "Permalink to this heading") To identify what an Object can and cannot do, we define an attribute called Object Type, or simply Type. A Type is not enough to _uniquely_ identify an Object, but it defines the set of operations that can be performed with or on it. The following types are defined: | Name | Value | yubihsm-shell name | | --- | --- | --- | | [Opaque Object](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-core-concepts.html#hsm2-opaque-key-obj) | 0x01 | opaque | | [Authentication Key Object](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-core-concepts.html#hsm2-auth-key-obj) | 0x02 | authentication-key | | [Asymmetric Key Object](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-core-concepts.html#hsm2-asymmetric-key-obj) | 0x03 | asymmetric-key | | [Wrap Key Object](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-core-concepts.html#hsm2-wrap-key-obj) | 0x04 | wrap-key | | [HMAC Key Object](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-core-concepts.html#hsm2-hmac-key-obj) | 0x05 | hmac-key | | [Template Object](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-core-concepts.html#hsm2-template-key-obj) | 0x06 | template | | [OTP AEAD Key Object](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-core-concepts.html#hsm2-otp-aead-key-obj) | 0x07 | otp-aead-key | | [Symmetric Key Object](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-core-concepts.html#hsm2-symmetric-key-obj) | 0x08 | symmetric-key | | [Public Wrap Key Object](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-core-concepts.html#hsm2-public-wrap-key-obj) | 0x09 | public-wrap-key | ### Authentication Key Object[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-core-concepts.html#authentication-key-object "Permalink to this heading") An Authentication Key is one of the most fundamental Objects there are. Authentication Keys are used to establish an encrypted Session with the device. See [Create and Authenticate a Session](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-core-concepts.html#hsm2-concepts-create-authenticate-session-label) . An Authentication Key is basically two long-lived AES keys: an encryption key and a MAC key. When establishing a Session, the long-lived keys are used to generate three session keys: * An encryption key used to encrypt the messages exchanged with the device * A MAC key used to create an authentication tag for each message sent to the device * A response MAC key used to create an authentication tag for each response message sent by the device The session keys are temporary and are destroyed when the Session is no longer in use. ### Asymmetric Key Object[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-core-concepts.html#asymmetric-key-object "Permalink to this heading") An Asymmetric Key Object is what the YubiHSM 2 uses to represent an asymmetric key-pair where only the private key can be used to perform cryptographic operations. ### HMAC Key Object[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-core-concepts.html#hmac-key-object "Permalink to this heading") An HMAC Key is a secret key used when computing and verifying HMAC signatures. ### Opaque Object[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-core-concepts.html#opaque-object "Permalink to this heading") An Opaque Object is an unchecked kind of Object, normally used to store raw data in the device. No specific restrictions (besides size limitations) are imposed to this type of Object. ### OTP AEAD Key Object[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-core-concepts.html#otp-aead-key-object "Permalink to this heading") An OTP AEAD Key Object is a secret key used to decrypt Yubico OTP values for further verification by a validation process. ### Public Wrap Key Object[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-core-concepts.html#public-wrap-key-object "Permalink to this heading") A Public Wrap Key Object is an RSA public key used to wrap Objects and (a)symmetric keys during the export process. ### Symmetric Key Object[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-core-concepts.html#symmetric-key-object "Permalink to this heading") Available with firmware version 2.3.1 or later. A Symmetric Key Object is a secret key used when encrypting and decrypting AES. Object Types are encoded as an 8-bit value. ### Template Object[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-core-concepts.html#template-object "Permalink to this heading") A Template Object is a binary template used for example to validate SSH certificate requests. ### Wrap Key Object[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-core-concepts.html#wrap-key-object "Permalink to this heading") A Wrap Key Object is a secret key used to wrap and unwrap Objects during the export and import process. Object Types are encoded as an 8-bit value. Capabilities[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-core-concepts.html#capabilities "Permalink to this heading") ---------------------------------------------------------------------------------------------------------------------------------------------- A Capability is an attribute that can be given to an [Objects](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-core-concepts.html#hsm2-concepts-objects-label) allowing specific operations to be performed on or with it. Commands like digital signature generation and data decryption require (and check) for a predetermined set of Capabilities to be present on an Object. Further below is the list of existing Capabilities. It is important to know that there are no restrictions on which Capabilities can be set on an Object. Specifically, this means that it is possible to assign meaningless Capabilities to Objects that will never be able to use them, for example it is possible to have an Asymmetric Object with the Capability `verify-hmac`. Such a Capability only makes sense for HMAC Key objects, but the device allows defining a superset. Lack of Capabilities required for a specific operation causes a command requiring that Capability to fail. ### Delegated Capabilities[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-core-concepts.html#delegated-capabilities "Permalink to this heading") Every Object stored on the device has an associated set of Capabilities. There is a second set of so-called Delegated Capabilities that only Authentication Keys and Wrap Keys have. This is used to capture the indirection that Authentication Keys and Wrap Keys can be used as a means of storing more Objects on a device. In both cases Delegated Capabilities are used as a filter. For Authentication Keys, Delegated Capabilities define the set of Capabilities that can be set or “bestowed” onto an Object created by the Authentication Key. Any operation attempting to create Objects with a Capability outside of this set fails. For Wrap Keys, Delegated Capabilities define the set of Capabilities that an Object can have when imported or exported using the Wrap Key. A larger set of Capabilities causes the import operation to fail. ### Capability Protocol Details[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-core-concepts.html#capability-protocol-details "Permalink to this heading") A Set of Capabilities is an 8-byte value. Each Capability is identified by a specific bit, as shown in the `Hex Mask` column below. | Name | Hex Mask | Applicable

Objects | Description | | --- | --- | --- | --- | | —————————**Asymmetric Keys**——————————– | | | | | delete-asymmetric

\-key | 0x0000020000000000 | authentication

\-key | Delete

Asymmetric

Key Objects | | generate-asymmetric

\-key | 0x0000000000000010 | authentication

\-key | Generate

Asymmetric Key

Objects | | put-asymmetric-key | 0x0000000000000008 | authentication

\-key | Write

Asymmetric Key

Objects | | —————————**Authentication Keys**—————————- | | | | | delete-authen-

tication-key | 0x0000010000000000 | authentication

\-key | Delete

Authentication

Key Objects | | put-authentication

\-key | 0x0000000000000004 | authentication

\-key | Write

Authentication

Key Objects | | change-

authentication-key | 0x0000400000000000 | authentication

\-key | Replace

Authentication

Key Objects | | ——————————–**Certificate**——————————- | | | | | sign-attestation-

certificate | 0x0000000400000000 | authentication

\-key,

asymmetric-key | Attest

properties of

Asymmetric

Key Objects | | sign-ssh-certificate | 0x0000000002000000 | authentication

\-key,

asymmetric-key | Sign SSH

certificates | | ———————————–**Data**———————————– | | | | | decrypt-cbc | 0x0010000000000000 | authentication

\-key,

symmetric-key | Decrypt data

using AES CBC

mode. Available

with firmware

version 2.3.1

or later. | | decrypt-ecb | 0x0004000000000000 | authentication

\-key,

symmetric-key | Decrypt data

using AES ECB

mode. Available

with firmware

version 2.3.1

or later. | | decrypt-oaep | 0x0000000000000400 | authentication

\-key,

asymmetric-key | Decrypt

data using

RSA-OAEP | | decrypt-pkcs | 0x0000000000000200 | authentication

\-key,

asymmetric-key | Decrypt

data using

RSA-PKCS1v1.5 | | encrypt-cbc | 0x0020000000000000 | authentication

\-key,

symmetric-key | Encrypt data

using AES CBC

mode. Available

with firmware

version 2.3.1

or later. | | encrypt-ecb | 0x0008000000000000 | authentication

\-key,

symmetric-key | Encrypt data

using AES ECB

mode. Available

with firmware

version 2.3.1

or later. | | ———————————–**ECDH**———————————– | | | | | derive-ecdh | 0x0000000000000800 | authentication

\-key,

asymmetric-key | Perform

ECDH | | ———————————–**Global**——————————— | | | | | get-option | 0x0000000000040000 | authentication

\-key | Read device-

global options | | set-option | 0x0000000000020000 | authentication

\-key | Write device-

global options | | ———————————–**HMAC**———————————– | | | | | delete-hmac-key | 0x0000080000000000 | authentication

\-key | Delete HMAC

Key Objects | | generate-hmac-key | 0x0000000000200000 | authentication

\-key | Generate HMAC

Key Objects | | put-mac-key | 0x0000000000100000 | authentication

\-key | Write HMAC

Key Objects | | sign-hmac | 0x0000000000400000 | authentication

\-key, hmac-key | Compute HMAC

of data | | verify-hmac | 0x0000000000800000 | authentication

\-key, hmac-key | Verify HMAC

of data | | —————————————**Log**——————————– | | | | | get-log-entries | 0x0000000001000000 | authentication

\-key | Read the Log

Store | | ———————————–**Opaque**——————————— | | | | | delete-opaque | 0x0000008000000000 | authentication

\-key | Delete Opaque

Objects | | get-opaque | 0x0000000000000001 | authentication

\-key | Read Opaque

Objects | | put-opaque | 0x0000000000000002 | authentication

\-key | Write Opaque

Objects | | ———————————–**OTP**———————————— | | | | | create-otp-aead | 0x0000000040000000 | authentication

\-key,

otp-aead-key | Create OTP

AEAD | | decrypt-otp | 0x0000000020000000 | authentication

\-key,

otp-aead-key | Decrypt OTP | | delete-otp-aead-key | 0x0000200000000000 | authentication

\-key | Delete OTP

AEAD Key

Objects | | generate-otp-aead

\-key | 0x0000001000000000 | authentication

\-key | Generate OTP

AEAD Key

Objects | | put-otp-aead-key | 0x0000000800000000 | authentication

\-key | Write OTP AEAD

Key Objects | | randomize-otp-aead | 0x0000000080000000 | authentication

\-key,

otp-aead-key | Create OTP

AEAD from

random data | | rewrap-from-otp-

aead-key | 0x0000000100000000 | authentication

\-key,

otp-aead-key | Rewrap AEADs

from one OTP

AEAD Key

Object to

another | | rewrap-to-otp-

aead-key | 0x0000000200000000 | authentication

\-key,

otp-aead-key | Rewrap AEADs

to one OTP

AEAD Key

Object from

another | | ———————————–**Random**——————————— | | | | | get-pseudo-random | 0x0000000000080000 | authentication

\-key | Extract

random bytes | | ————————————–**Reset**——————————- | | | | | reset-device | 0x0000000010000000 | authentication

\-key | Perform a

factory reset

on the device | | ———————————–**Signatures**—————————– | | | | | sign-ecdsa | 0x0000000000000080 | authentication

\-key,

asymmetric-key | Compute

digital

signatures

using ECDSA | | sign-eddsa | 0x0000000000000100 | authentication

\-key,

asymmetric-key | Compute

digital

signatures

using EDDSA | | sign-pkcs | 0x0000000000000020 | authentication

\-key,

asymmetric-key | Compute

signatures

using RSA-

PKCS1v1.5 | | sign-pss | 0x0000000000000040 | authentication

\-key,

asymmetric-key | Compute

digital

signatures

using using

RSA-PSS | | ———————————–**Template**——————————- | | | | | delete-template | 0x0000100000000000 | authentication

\-key | Delete

Template

Objects | | get-template | 0x0000000004000000 | authentication

\-key | Read Template

Objects | | put-template | 0x0000000008000000 | authentication

\-key | Write Template

Objects | | ———————————–**Wrap** ———————————- | | | | | delete-wrap-key | 0x0000040000000000 | authentication

\-key | Delete Wrap

Key Objects | | export-wrapped | 0x0000000000001000 | authentication

\-key, wrap-key | Export other

Objects under

wrap | | exportable-under

\-wrap | 0x0000000000010000 | all | Mark an Object

as exportable

under wrap | | generate-wrap-key | 0x0000000000008000 | authentication

\-key | Generate Wrap

Key Objects | | import-wrapped | 0x0000000000002000 | authentication

\-key, wrap-key | Import wrapped

Objects | | put-wrap-key | 0x0000000000004000 | authentication

\-key | Write Wrap Key

Objects | | unwrap-data | 0x0000004000000000 | authentication

\-key, wrap-key | Unwrap user-

provided data | | wrap-data | 0x0000002000000000 | authentication

\-key, wrap-key | Wrap user-

provided data | | —————————–**Public Key Wrap** —————————– | | | | | put-public-wrap

\-key | 0x0040000000000000 | authentication

\-key, wrap-key | Write RSA

Public Wrap Key | | delete-public-wrap

\-key | 0x0080000000000000 | authentication

\-key, wrap-key | Delete RSA

Public Wrap Key | | ——————————**Symmetric Keys** —————————– | | | | | generate-symmetric

\-key | 0x0001000000000000 | authentication

\-key | Generate AES

key. Available

with firmware

version 2.3.1

or later. | | put-symmetric-key | 0x0000800000000000 | authentication

\-key | Import AES key.

Available with

firmware

version 2.3.1

or later. | | delete-symmetric-key | 0x0002000000000000 | authentication

\-key | Delete AES key.

Available with

firmware

version 2.3.1

or later. | Domains[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-core-concepts.html#domains "Permalink to this heading") ------------------------------------------------------------------------------------------------------------------------------------ A Domain is a logical partition that can be conceptually mapped to a container. In a YubiHSM 2 there are `16` independent Domains; an Object can belong to one or more Domains. Note Authentication Keys are Objects and thus can belong to multiple Domains. Domains serve as a means to secure Objects so that they cannot be addressed by independent applications running on the same device. This is achieved by specifying the Object’s Domain. Only users or applications that belong to the same Domain as an Object can access it or use it. The details involved in accessing an Object are explained in the [Effective Capabilities (Tying It All Together)](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-core-concepts.html#hsm2-concepts-effective-capabilities-label) page. ### Domain Protocol Details[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-core-concepts.html#domain-protocol-details "Permalink to this heading") Domains are encoded as 16-bit values, where each Domain is represented by a bit | Domain Number | Hex Mask | | --- | --- | | 1 | 0x0001 | | 2 | 0x0002 | | 3 | 0x0004 | | 4 | 0x0008 | | 5 | 0x0010 | | 6 | 0x0020 | | 7 | 0x0040 | | 8 | 0x0080 | | 9 | 0x0100 | | 10 | 0x0200 | | 11 | 0x0400 | | 12 | 0x0800 | | 13 | 0x1000 | | 14 | 0x2000 | | 15 | 0x4000 | | 16 | 0x8000 | Label[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-core-concepts.html#label "Permalink to this heading") -------------------------------------------------------------------------------------------------------------------------------- A Label is a sequence of bytes that can be used to add a mnemonic reference to Objects. ### Label Protocol Details[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-core-concepts.html#label-protocol-details "Permalink to this heading") Labels are `40` bytes long. As far as the YubiHSM is concerned, the label is only a string of raw bytes and is not restricted to printable characters or valid UTF-8 glyphs. Object ID[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-core-concepts.html#object-id "Permalink to this heading") ---------------------------------------------------------------------------------------------------------------------------------------- The ID property is used to identify an Object of a given Type. This means that to **uniquely** identify an Object stored on a YubiHSM 2, the couple `(Type, ID)` is required. There can be more than one Object with a given ID and more than one Object with a given Type, but only one Object with a specific ID and Type. This is so that logical connections between Objects can be established by giving a set of connected Objects of different Types the same ID. An Object ID can have values in the range `[0-65535]` or `[0x0000-0xffff]` in hexadecimal. Note that this range is larger than the maximum number of Objects that can be stored in the device (256). Regardless of the type, ID `0x0000` and `0xffff` are reserved for internal Objects. ### Object ID Protocol Details[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-core-concepts.html#object-id-protocol-details "Permalink to this heading") Object IDs are encoded as 16-bit values. Origin[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-core-concepts.html#origin "Permalink to this heading") ---------------------------------------------------------------------------------------------------------------------------------- The Origin is a one-byte value that is part of the metadata associated with an asymmetric key object. The origin indicates whether the asymmetric key was generated on a YubiHSM 2 device or generated externally and subsequently imported. If a key was imported, the origin also indicates whether the key was imported in plaintext or using a wrap key. Origins are also used when generating a key attestation. The attestation certificate will contain the key’s origin as an X.509 extension. See [Attestation](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-core-concepts.html#hsm2-concepts-attestation-label) . ### Origin Protocol Details[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-core-concepts.html#origin-protocol-details "Permalink to this heading") Origins are encoded as 8-bit values, where each defined origin is represented by a bit according to the following table: | Name | Hex Mask | | --- | --- | | generated | 0x0001 | | imported | 0x0002 | | imported\_wrapped | 0x0010 | Note that not all combinations of these bits are valid. In practice, only the combinations `0x0001`, `0x0002`, and `0x0011`, `0x0012` can occur. Sequence[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-core-concepts.html#sequence "Permalink to this heading") -------------------------------------------------------------------------------------------------------------------------------------- The Sequence is a one-byte value that is part of the metadata associated with an Object. The Sequence describes how many times an Object with a given ID and Type has been written. This is mostly useful for caching to determine if new data needs to be fetched from the device. ### Sequence Protocol Details[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-core-concepts.html#sequence-protocol-details "Permalink to this heading") Sequence is 8 bits long and will wrap. Options[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-core-concepts.html#options "Permalink to this heading") ------------------------------------------------------------------------------------------------------------------------------------ Options are device-global settings. The following Options are defined: | Option Name | Hex Value | | --- | --- | | force-audit | 0x01 | | command-audit | 0x03 | The data payload is Option-specific. ### Force Audit[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-core-concepts.html#force-audit "Permalink to this heading") This Option is used to enable Force Audit mode which prevents the device from performing additional operations when the [Logs and Error Codes](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-core-concepts.html#hsm2-concepts-logs-label) is full. The Option accepts three different values: * 0x00: Option disabled * 0x01: Option enabled * 0x02: Option permanently enabled (only possible to turn off through factory reset) ### Command Audit[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-core-concepts.html#command-audit "Permalink to this heading") This Option is used to enable or disable logging of specific commands. Logging commands impacts performance. By default logging is enabled for all operations. The Option accepts three different values: * 0x00: Option disabled * 0x01: Option enabled * 0x02: Option permanently enabled (only possible to turn off through factory reset) Multiple commands can be specified at once with the syntax `C1 V1, C2 V2, ..., Cn Vn` where `Ci` is the Command Code and `Vi` is the Option Value. An example of this syntax can be found at the [SET OPTION Command](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-cmd-reference.html#hsm2-cmd-set-option-label) description. Attestation[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-core-concepts.html#attestation "Permalink to this heading") -------------------------------------------------------------------------------------------------------------------------------------------- Asymmetric keys generated in the YubiHSM can be attested by another Asymmetric key. The attestation process creates a new x509 certificate for the attested key. The device comes pre-loaded with an attestation key and certificate referenced by ID `0`. It is possible to use your own key and certificate for attestation, these then must have the same ID and the key has to have the `sign-attestation-certificate` Capability set. ### Details[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-core-concepts.html#details "Permalink to this heading") * Serial is a random 16 byte integer * Issuer is the subject of the attesting certificate * Dates is copied from the attesting certificate * Subject is the string `YubiHSM Attestation id 0x` with the attested ID appended * If the attesting key is RSA the signature is SHA256-PKCS#1v1.5 * If the attesting key is EC the signature is ECDSA-SHA256 ### Certificate Extensions[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-core-concepts.html#certificate-extensions "Permalink to this heading") Some certificate extensions are added in the generated certificate and/or the pre-loaded certificate: | OID | Description | Data Type | Generated/Pre-loaded | | --- | --- | --- | --- | | 1.3.6.1.4.1.41482.4.1 | Firmware version | Octet String | Both | | 1.3.6.1.4.1.41482.4.2 | Serial number | Integer | Both | | 1.3.6.1.4.1.41482.4.3 | [Origin](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-core-concepts.html#hsm2-concepts-origin-label) | Bit String | Generated | | 1.3.6.1.4.1.41482.4.4 | [Domains](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-core-concepts.html#hsm2-concepts-domain-label) | Bit String | Generated | | 1.3.6.1.4.1.41482.4.5 | [Capabilities](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-core-concepts.html#hsm2-concepts-capability-label) | Bit String | Generated | | 1.3.6.1.4.1.41482.4.6 | [Object ID](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-core-concepts.html#hsm2-concepts-objectid-label) | Integer | Generated | | 1.3.6.1.4.1.41482.4.9 | [Label](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-core-concepts.html#hsm2-concepts-label-label) | Utf8String | Generated | | 1.3.6.1.4.1.41482.4.10 | [FIPS certified](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-introduction.html#hsm2-concepts-fips-label) | Integer | Pre-loaded | | 1.3.6.1.4.1.41482.4.12 | [FIPS certified](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-introduction.html#hsm2-concepts-fips-label) | Boolean | Generated | ### Pre-Loaded Certificates[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-core-concepts.html#pre-loaded-certificates "Permalink to this heading") The pre-loaded certificate can be fetched as an opaque object with ID 0. This will in turn be signed by an intermediate CA which is signed by a [Yubico root CA](https://developers.yubico.com/YubiHSM2/Concepts/yubihsm2-attest-ca-crt.pem) . ### Intermediates[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-core-concepts.html#intermediates "Permalink to this heading") [E45DA5F361B091B30D8F2C6FA040DB6FEF57918E.pem](https://developers.yubico.com/YubiHSM2/Concepts/E45DA5F361B091B30D8F2C6FA040DB6FEF57918E.pem) Logs and Error Codes[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-core-concepts.html#logs-and-error-codes "Permalink to this heading") -------------------------------------------------------------------------------------------------------------------------------------------------------------- ### YubiHSM Log Store[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-core-concepts.html#yubihsm-log-store "Permalink to this heading") A YubiHSM 2 device maintains a list of recently executed commands in a portion of non-volatile memory known as the Log Store. This allows logging commands across different power cycles. Specific commands are used to extract logs from the device. Since the Log Store uses non-volatile memory, it can only store up to `62` different entries. When the Log Store is full, it is used as a circular buffer, meaning that the least recently used entry is overwritten. It is possible to set the device in Force Audit mode. When this is done entries from the Log Store must be retrieved or commands that cannot be logged will fail. Together with individual commands, power-on and reboot events are also logged. The establishment of a session is logged like any other operation; however those commands are always allowed, independent of the current status of the Log Store. This is so that it is always possible to retrieve logs and free up the Log Store, even when the device is in Force Audit mode and the Log Store is full. However, the number of unlogged authentication and power-up events is stored in a counter that is retrieved as part of the log retrieval. Entries in the Log Store are organized to form a chain of hashes. This enables auditors to verify that a given set of entries has not been tampered with after extraction, and that all entries are present. More details on the format of log entries can be found in the protocol description document for [GET LOG ENTRIES Command](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-cmd-reference.html#hsm2-cmd-get-log-entries-label) . ### Error Codes[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-core-concepts.html#error-codes "Permalink to this heading") Below are error codes returned by a YubiHSM device. | Value | Name | Description | | --- | --- | --- | | 0x00 | OK | Success | | 0x01 | INVALID COMMAND | Unknown command | | 0x02 | INVALID DATA | Malformed data for the command | | 0x03 | INVALID SESSION | The session has expired or does not exist | | 0x04 | AUTHENTICATION FAILED | Wrong Authentication Key | | 0x05 | SESSIONS FULL | No more available sessions | | 0x06 | SESSION FAILED | Session setup failed | | 0x07 | STORAGE FAILED | Storage full | | 0x08 | WRONG LENGTH | Wrong data length for the command | | 0x09 | INSUFFICIENT PERMISSIONS | Insufficient permissions for the command | | 0x10 | DEMO MODE | Demo device must be power-cycled | | 0x11 | OBJECT EXISTS | Unable to overwrite object | | 0x0a | LOG FULL | The log is full and force audit is enabled | | 0x0b | OBJECT NOT FOUND | No object found matching given ID and Type | | 0x0c | INVALID ID | Invalid ID | | 0x0e | SSH CA CONSTRAINT

VIOLATION | Constraints in SSH Template not met | | 0x0f | INVALID OTP | OTP decryption failed | Effective Capabilities (Tying It All Together)[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-core-concepts.html#effective-capabilities-tying-it-all-together "Permalink to this heading") ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- This document describes how Object-related concepts interact with each another. Let us assume that we are establishing a Session with Authentication Key `0xabcd` so that the Session can use the Asymmetric Key `0x1234` to sign some data. We are assuming that Asymmetric Key `0x1234` is an RSA 2048-bit key and that we would like to generate a signature using RSASSA-PSS. ### Create and Authenticate a Session[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-core-concepts.html#create-and-authenticate-a-session "Permalink to this heading") Creating and authenticating a Session requires knowledge of what the long-lived keys are (or what the associated derivation password is). When a valid Session is established, certain properties of the Authentication Key used to create the Session are inherited by the Session itself. These are: * The Domain(s) to which the Authentication Key belongs (for more information, see [Domains](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-core-concepts.html#hsm2-concepts-domain-label) ), * The Capabilities of the Authentication Key (see [Capabilities](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-core-concepts.html#hsm2-concepts-capability-label) ) and * The Delegated Capabilities (see [Capabilities](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-core-concepts.html#hsm2-concepts-capability-label) ) associated with Authentication Key `0xabcd` . The Session’s inherited properties serve to ensure that the only Objects stored in the HSM 2 that we can see and access are those that belong to the same Domain(s) as Authentication Key `0xabcd`. ### Generate a Signature[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-core-concepts.html#generate-a-signature "Permalink to this heading") The required capability must be set on both the Authentication Key used to establish the Session (Authentication Key `0xabcd`) and the target Object used to perform the operation (Asymmetric Key `0x1234`). Assuming that Asymmetric Key `0x1234` is in one such Domain, we can now continue and ask the HSM 2 to generate a signature. To do so we will send the `Sign Data` command over the Session. It will not execute successfully unless the arguments of the command are valid, i.e., no malformed data can be sent to the device or an error will occur. **Both** Authentication Key `0xabcd` and Asymmetric Key `0x1234` must have the Capability `sign-pss` set. ### Effective Capabilities and Role Definition[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-core-concepts.html#effective-capabilities-and-role-definition "Permalink to this heading") The overlap between * The Capabilities of the Authentication Key used to establish the Session and * The Capabilities of the target Object involved in the operation defines the **Effective Capabilities**. An operation on a given target Object over a given Session can succeed only if the Capabilities required by the operation are included in the Effective Capabilities. The interaction between Domains and Effective Capabilities enables flexible setup and role definition. For example, * It is possible to assign a set of Capabilities to an Object, and then distribute those Capabilities across different Authentication Keys so that each key is enabled to perform only a single operation on the target Object, and no key performs the same operation as any other key. * Similarly, it is possible to disable specified operations by not assigning the requisite Capabilities to an Authentication Key. For example, an “Administrator” Authentication Key could be enabled only to create keys while a “User” Authentication Key could be enabled only to use those same keys. ### Workflow[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-core-concepts.html#workflow "Permalink to this heading") 1. Determine which Objects will have operations performed on them 2. Determine which Authentication Keys you will use 3. Determine which operations will be performed 4. Use a spreadsheet (if necessary) to map out the interaction between the first three items 5. With the aid of the spreadsheet, create domains to enable the interaction. Note Authentication Keys are Objects and thus can belong to multiple Domains. 6. You could construct your domains: * per operation - put an Object and an Authentication Key into each domain, or * per Object - put the Authentication Key(s) for all the operations to be performed on each Object into a single domain * per Authentication Key - put the requisite Object(s) into each Domain. For example, if you wanted Jan to do the signing and Ola to do the importing, you could adopt any of the above options, but the Effective Capabilities enable you to assign far more complex webs of responsibilities. 7. Use the spreadsheet to set the Capabilities and Delegated Capabilities appropriately, “appropriateness” being determined by the Objects and operations to be performed on them. [Cookies](https://www.yubico.com/support/terms-conditions/cookie-notice/) | [Privacy Policy](https://www.yubico.com/support/terms-conditions/privacy-notice/) --- # Security Domain overview ##### Table of Contents Security Domain overview ======================== The Security Domain is a special application on the YubiKey responsible for managing secure communication channels and cryptographic keys. It implements protocols defined by [Global Platform Consortium](https://globalplatform.org/) that provide confidentiality and integrity for commands sent between host applications and the YubiKey. For detailed information about the protocols, use cases, and transport options, see the [Secure Channel Protocol (SCP)](https://docs.yubico.com/yesdk/users-manual/sdk-programming-guide/secure-channel-protocol.html) documentation. Requirements ------------ Hardware: * YubiKey 5 Series or later * For SCP03: Firmware 5.3 or later * For SCP11: Firmware 5.7.2 or later Transport Protocols: * Smartcard over USB or NFC Core features ------------- The Security Domain provides: * Management of secure communication channels (SCP03 and SCP11) * Storage and management of cryptographic keys * Certificate management for asymmetric protocols * Access control through certificate allowlists Basic usage ----------- // Create session without SCP protection using var session = new SecurityDomainSession(yubiKeyDevice); session.GetKeyInformation(); // Create SCP protected session using var session = new SecurityDomainSession(yubiKeyDevice, scpKeyParameters); session.GenerateEcKey(parameters...); // Protected by secure channel Documentation structure ----------------------- The Security Domain functionality is documented in the following sections: * [Key Management](https://docs.yubico.com/yesdk/users-manual/application-security-domain/security-domain-keys.html) - Managing symmetric (SCP03) and asymmetric (SCP11) keys * [Certificate Operations](https://docs.yubico.com/yesdk/users-manual/application-security-domain/security-domain-certificates.html) - Working with X.509 certificates and certificate chains * [Common Tasks](https://docs.yubico.com/yesdk/users-manual/application-security-domain/security-domain-tasks.html) - Setup, configuration, and maintenance operations * [Device Information](https://docs.yubico.com/yesdk/users-manual/application-security-domain/security-domain-device.html) - Device data and configuration management Basic security considerations ----------------------------- When working with the Security Domain: * Most operations require an authenticated session * Default SCP03 keys provide no security, replace them in production * Some operations permanently modify the YubiKey * Maintain proper key and certificate backups ##### Note For detailed implementation guidance and best practices, refer to the [Secure Channel Protocol (SCP)](https://docs.yubico.com/yesdk/users-manual/sdk-programming-guide/secure-channel-protocol.html) documentation. [Edit this page](https://github.com/Yubico/Yubico.NET.SDK/blob/develop/docs/users-manual/application-security-domain/security-domain-overview.md/#L1) --- # Getting Started — YubiHSM 2 User Guide documentation * [](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/index.html) * Getting Started * [View page source](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/_sources/hsm2-quick-start.rst.txt) * * * Getting Started[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-quick-start.html#getting-started "Permalink to this heading") ================================================================================================================================================== The purpose of this tutorial is to demonstrate basic functionalities of different key types: Authentication Key, Asymmetric Key and Wrap Key. We start with a fresh YubiHSM 2 configuration and we proceed in generating a new Authentication Key. Then we generate an Asymmetric Key for signing purposes. We sign an arbitrary amount of data and verify that our signature is correct. Part of this documentation is to demonstrate how to backup a key on a second YubiHSM 2. We do so by wrapping the Asymmetric Key and re-importing it into the same device. This tutorial covers: * [Set Up the YubiHSM 2 Environment](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-quick-start.html#hsm2-start-setup-label) * [Connect to the YubiHSM 2](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-quick-start.html#hsm2-connect-yubihsm-label) * [Initial Provisioning and Deployment for HMAC, PKCS11, or RSA](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-quick-start.html#hsm2-initial-provision-deploy-guide-label) * [Add a New Authentication Key](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-quick-start.html#hsm2-new-authentication-key-label) * [Generate an Asymmetric Key Object for Signing](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-quick-start.html#hsm2-generate-key-signing-label) * [Export an Asymmetric Key Under Wrap](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-quick-start.html#hsm2-export-asymmetric-key-wrap-label) * [Key Splitting and Key Custodians](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-configure-software-windows.html#hsm2-key-split-custodians-guide-label) * [Backup and Restore with YubiHSM Backup Keys](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-backup-restore.html#hsm2-backup-restore-label) > * Backing up and Restoring YubiHSM 2 Keys > * Backing up and Restoring Key Material Before proceeding with this document you should be familiar with concepts such as: `Sessions`, `Domains`, `Capabilities` described in [Core Concepts](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-core-concepts.html#hsm2-core-concepts-label) . Note The following code samples have arbitrary line-breaks to prevent them from running off the page. Set Up the YubiHSM 2 Environment[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-quick-start.html#set-up-the-yubihsm-2-environment "Permalink to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ 1. Get the latest binaries from SDK download [YubiHSM2/Releases](https://developers.yubico.com/YubiHSM2/Releases) . 2. Install all libraries. 3. Make sure your device is accessible by the connector. This is accomplished either by running the connector as a superuser or by using an appropriate [udev\_rule](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/) . ### Install the YubiHSM 2 Tools and Software[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-quick-start.html#install-the-yubihsm-2-tools-and-software "Permalink to this heading") To complete the procedures in this guide, install the YubiHSM 2 tools and software that will be needed for this. Tip A generic prompt, `$`, is used in command line examples in this document. Depending on your command line application, your prompt may be different. The following YubiHSM items of software are used in this guide. They are included as part of the archive file you downloaded. 1. Unzip the downloaded [archives of the SDK](https://developers.yubico.com/YubiHSM2/Releases/) containing the YubiHSM libraries and tools and move the contents to an appropriate location. 2. Complete the step for your operating system. * On your **Windows** system, run both installers: > * `yubihsm-cngprovider-windows-amd64.msi` (YubiHSM Key Storage Provider) > * `yubihsm-connector-windows-amd64.msi` (YubiHSM Connector for Windows) * On a **Debian**\-based system, run the following command: > `$ dpkg -i ./libykhsmauth1_*.deb ./libyubihsm-usb1_*.deb ./libyubihsm-http1_*.deb ./libyubihsm1_*.deb  ./yubihsm-shell_*.deb` * On a **Redhat**\-based system, run the following command: > `$ yum install ./yubihsm-shell-*.rpm` 3. (**Windows** system) Set the ADCS service dependency for the YubiHSM Connector service via an elevated/admin Windows Command Prompt. This prevents an error which occurs if the ADCS services start before the YubiHSM connector is running. 1. List the current dependencies with `sc qc “certsvc”` > \> sc qc “certsvc” > \[SC\] QueryServiceConfig SUCCESS > > SERVICE\_NAME: certsvc > TYPE : 110 WIN32\_OWN\_PROCESS (interactive) > START\_TYPE : 2 AUTO\_START > ERROR\_CONTROL : 1 NORMAL > BINARY\_PATH\_NAME : C:\\Windows\\system32\\certsrv.exe > LOAD\_ORDER\_GROUP : > TAG : 0 > DISPLAY\_NAME : Active Directory Certificate Services > DEPENDENCIES : > SERVICE\_START\_NAME : localSystem 2. Add the YubiHSM Connector dependency to ADCS with the command: `sc config "certsvc" depend="yhconsrv"` > \> sc config "certsvc" depend\="yhconsrv" > \[SC\] ChangeServiceConfig SUCCESS > > After the command is entered, the dependency can be verified with `sc qc “certsvc”` > > \[SC\] QueryServiceConfig SUCCESS > > SERVICE\_NAME: certsvc > TYPE : 110 WIN32\_OWN\_PROCESS (interactive) > START\_TYPE : 2 AUTO\_START > ERROR\_CONTROL : 1 NORMAL > BINARY\_PATH\_NAME : C:\\Windows\\system32\\certsrv.exe > LOAD\_ORDER\_GROUP : > TAG : 0 > DISPLAY\_NAME : Active Directory Certificate Services > DEPENDENCIES : yhconsrv > SERVICE\_START\_NAME : localSystem > > To remove dependencies for ACDS, use the same command for adding dependencies with a blank depend field: `sc config "certsvc" depend=""` ### Verify the Default Configuration of the YubiHSM 2[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-quick-start.html#verify-the-default-configuration-of-the-yubihsm-2 "Permalink to this heading") Verify the results of the YubiHSM Setup program using the YubiHSM Shell program. Log in using the application authentication key. The YubiHSM 2 device comes with a single factory-installed authentication key whose default password is `password`. As part of the configuration in this guide, this default authentication key will be destroyed. If the YubiHSM 2 is reset to its default configuration, any non factory-installed objects stored on it are also destroyed. Reset instructions can be found in [Reset YubiHSM to Factory Settings](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-reset-to-factory.html#hsm2-reset-to-factory-label) . We reiterate that you will need two YubiHSM 2 devices to complete all steps of this guide, because you will be deploying the first device and creating a backup of all key material on the second device. These steps also verify that neither of the YubiHSM 2 devices have been tampered with. To verify that YubiHSM 2 devices still have the default configuration by following the steps below: 1. Verify the YubiHSM 2 setup, in your Command Prompt, run the following command: $ yubihsm-shell Do one of the following: * If the application that calls the YubiHSM Connector is **running on a local host**, start the Connector with the command `yubihsm-connector` without additional parameters. In Windows Server 2012 SP2 or higher, `yubihsm-connector.exe` is located in `C:\Program Files\YubiHSM Connector\`. * If the application is **running on a VM or a different server**, start the YubiHSM Connector on the host operating system in networking mode. For example, if the host machine’s IP address is `192.168.100.252`, launch the Connector on the host OS with the command `yubihsm-connector -l 192.168.100.252:12345` Tip For testing or debugging the YubiHSM Connector, the flag `-d` can be set. 2. To gain shell access to the YubiHSM 2, launch the YubiHSM Shell program: 1. Open a Command Prompt. 2. Run the command `yubihsm-shell`. 3. If a networked Connector is used, set the parameter `--connect `. If the YubiHSM Connector is running on a host machine to which the YubiHSM 2 is physically connected, start the YubiHSM Shell program in networked mode. $ yubihsm-shell \--connector http://192.168.100.252:12345 where – The host server’s IP address is 192.168.100.252 Tip For testing or debugging the YubiHSM Shell, the flag `-d` can be set. 3. To connect to the YubiHSM 2, at the `yubihsm` command line, type `connect`. A message saying that you have a successful connection is displayed. 4. To open a session with the YubiHSM 2, type `session open 1` (where `1` is the ID of the default authentication key pre-installed on the device). 5. Type in the default password: `password`. A message confirming that the session has been set up successfully is displayed. 6. You now have an administrative connection to the YubiHSM 2 and you can list the objects available by typing `list objects 0` and pressing **Enter**. Your results should be similar to the following: Found 3 object(s) id: 0x0002, type: wrap-key, sequence: 0 id: 0x0003, type: authentication-key, sequence: 0 id: 0x0004, type: authentication-key, sequence: 0 As you can see by looking at their IDs, these objects correspond to the wrap key, the application authentication key and the audit key that were just created. 7. To obtain more information about any of the objects and its capabilities — for example, the application authentication key (object ID 3) — run the `objectinfo` command with the appropriate ID format, for example: yubihsm> get objectinfo 0 3 authentication-key The response you receive should look similar to the following: id: 0x0003, type: authentication-key, algorithm: aes128-yubico-authentication, label: "Application auth key", length: 40, domains: 1, sequence: 0, origin: imported, capabilities: exportable-under-wrap:generate-asymmetric-key: sign-attestation-certificate:sign-pkcs:sign-pss:sign-ecdsa, delegated\_capabilities:exportable-under-wrap: generate-asymmetric-key:sign-attestation-certificate:sign-pkcs: sign-pss:sign-ecdsa 8. Review the responses to confirm that YubiHSM 2 has now been configured to: * Generate asymmetric objects * Compute signatures using RSA-PKCS1v1.5 * Compute signatures using RSA-PSS * Export other objects under wrap * Import wrapped objects * Mark an object as exportable under wrap In addition, this object (the application authentication key, object ID 3) also has delegated capabilities that can be bestowed on other objects that it creates. For more information on delegated capabilities, see [Capabilities](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-core-concepts.html#hsm2-concepts-capability-label) . 9. To exit, type `quit`. Connect to the YubiHSM 2[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-quick-start.html#connect-to-the-yubihsm-2 "Permalink to this heading") -------------------------------------------------------------------------------------------------------------------------------------------------------------------- ### Start the Connector[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-quick-start.html#start-the-connector "Permalink to this heading") To physically reset the YubiHSM 2 insert the device while holding the touch sensor for 10 seconds. The following steps use the yubihsm-connector. Connection can also be made using the direct USB mode which is explained later in this document. 1. Start the connector. > $ yubihsm-connector \-d > > where – > > `-d` runs the connector in debug mode which may slow down the connector. It is not required for normal mode of operations. 2. Check the status of your connector and device by using a browser to visit [http://127.0.0.1:12345/connector/status](http://127.0.0.1:12345/connector/status) . ### Set Up YubiHSM 2 Connection[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-quick-start.html#set-up-yubihsm-2-connection "Permalink to this heading") Connecting to the YubiHSM 2 device that is typically installed physically inside a system. The YubiHSM key is a USB-A device. To connect to the YubiHSM 2 and perform tasks: Preparation steps: 1. Use one of the following to establish a physical connection. * Network USB server. * Virtual machines. * USB over IP appliances. 2. Compile the connector. See the [README](https://github.com/Yubico/yubihsm-connector/blob/master/README.adoc) doc for the YubiHSM Connector. Connection steps: 1. Start yubihsm-shell. > $ yubihsm-shell 2. Connect to YubiHSM 2. > $ yubihsm> connect ### Connect through Sessions with Applications[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-quick-start.html#connect-through-sessions-with-applications "Permalink to this heading") Many commands require a Session ID to be specified. To obtain a Session ID use the `session open` command followed by an Authentication Key ID and a derivation password. By default the YubiHSM 2 comes with a pre-installed Authentication Key with Object ID `1` and derivation password `password`. A Session is not a property of a specific Object, but rather it is used to describe a logical connection between an application and a device. Sessions are end-to-end encrypted and authenticated using Session Keys. These keys are derived from long-lived, pre-shared Authentication Key Objects as part of the sessions authentication process. The Session creation and authentication protocol is based on Global Platform SCP03. On a single YubiHSM 2 it is possible to establish up to `16` independent and concurrent Sessions. Note that while multiple concurrent Sessions can be active at a given time, the device still serves as a rendezvous point. This means that time-consuming operations such as generating a long RSA key will block commands in other Sessions. Sessions are addressed with a number in the range `[0-15]`. Sessions have an expiration period of 30 seconds of inactivity in order to prevent resource starvation. After 30 seconds, the device will consider a Session inactive and will move it to the pool of re-usable Sessions. Whenever a command is executed on a given Session, the inactivity timer is reset, meaning that if a Session is being constantly used, it will not expire. Some of the operations that can be performed on a YubiHSM 2 do **not** require a Session. The implication is that the command and its response will travel unencrypted to and from the device. These commands are only generic status commands, making Sessions required for any meaningful operation. The long-lived keys required to derive Sessions can be explicitly used in the relevant commands. However, there are built-in functionalities to derive those keys from a password using `10,000` iterations of `PBKDF2` with the salt `Yubico`, making the process more human-friendly. **Every new or factory-reset YubiHSM 2 has a default Authentication Key with ID 1 and all Capabilities and all Domains set.** This is equivalent to a superuser or an administrator. The long-lived keys for this Object are derived using the process previously described with the password password. Warning It is crucial to delete this well-known Authentication Key before deployment. #### Open Session[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-quick-start.html#open-session "Permalink to this heading") To open a Session with this Authentication Key use: yubihsm> session open 1 password Created session 0 The Session ID is the number found in the line directly below a `session open` command. where – `0` Is the Session ID. This value is used to address the newly created Session. `1` is the object ID of the pre-installed Authentication Key. `password` is the password of the pre-installed Authentication Key. #### Close Session[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-quick-start.html#close-session "Permalink to this heading") To close a Session use the command `session close` followed by the Session ID: yubihsm> session close 0 where – `0` Is the Session ID. #### List Session[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-quick-start.html#list-session "Permalink to this heading") To list the objects in the device use: yubihsm> list objects 0 where– `0` Is the Session ID. Note If you have closed Session `0`, the above command will not work. In that situation, open a new Session and use the new Session ID in the command above. Initial Provisioning and Deployment for HMAC, PKCS11, or RSA[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-quick-start.html#initial-provisioning-and-deployment-for-hmac-pkcs11-or-rsa "Permalink to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ This topic covers operations pertaining to the initial provisioning and deployment of YubiHSM 2 devices. Familiarity with the device, its features and capabilities is assumed. Important The YubiHSM 2 ships with a default Authentication Key with a well-known password. It is imperative that it is removed (single use case) or changed prior to production deployment. See also: * [Add a New Authentication Key](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-quick-start.html#hsm2-new-authentication-key-label) * [Generate an Asymmetric Key Object for Signing](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-quick-start.html#hsm2-generate-key-signing-label) * [Export an Asymmetric Key Under Wrap](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-quick-start.html#hsm2-export-asymmetric-key-wrap-label) ### Known Usage Cases[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-quick-start.html#known-usage-cases "Permalink to this heading") When only a single application needs to be provisioned, Yubico recommends that all Authentication Keys and material be provisioned only with Capabilities specific to that use case. Note This type of deployment requires devices to be physically reset and re-provisioned (single use case) or changed should a new use case arise. ### HMAC[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-quick-start.html#hmac "Permalink to this heading") 1. Establish a session with the default Authentication Key. yubihsm> connect Session keepalive set up to run every 15 seconds yubihsm> session open 1 password Created session 0 2. Create an Authentication Key for Auditing. yubihsm> put authkey 0 0 "Audit auth key" all get-log-entries none $AUDIT\_PASS Stored Authentication key 0xd054 3. Create a Wrap Key for importing application Authentication Keys and secrets. yubihsm> get random 0 16 5b61e89468cc8f2a274715c78c3d4753 yubihsm> put wrapkey 0 0 "HMAC wrap Key" all import-wrapped sign-hmac:verify-hmac 5b61e89468cc8f2a274715c78c3d4753 Stored Wrap key 0xf09a 4. Create an Authentication Key for use with the above Wrap Key. yubihsm> put authkey 0 0 "Provisioning HMAC wrap auth key" all import-wrapped none $WRAP\_PASS Stored Authentication key 0xf10f 5. Delete the default Authentication Key. yubihsm> delete 0 1 authentication-key 6. Create a wrapped Authentication Key and HMAC Key for the application. echo \-ne '\\x5b\\x61\\xe8\\x94\\x68\\xcc\\x8f\\x2a\\x27\\x47\\x15\\xc7\\x8c\\x3d\\x47\\x53' \> wrap.key echo $HMAC\_PASS | yubihsm-wrap \-a aes128-yubico-authentication \-c sign-hmac,verify-hmac \-d 1 \-l "HMAC auth key" \-k wrap.key \--in \--out auth.out \-e none echo \-ne '\\x0b\\x0b\\x0b\\x0b\\x0b\\x0b\\x0b\\x0b\\x0b\\x0b\\x0b\\x0b\\x0b\\x0b\\x0b\\x0b\\x0b\\x0b\\x0b\\x0b' \> hmac.key yubihsm-wrap \-a hmac-sha256 \-c sign-hmac,verify-hmac \-d 1 \-l "HMAC key" \-k wrap.key \--in hmac.key \--out hmac.out 7. Open a Session with the wrap Authentication Key. yubihsm> session open 0xf10f $WRAP\_PASS Created session 1 8. Import the two wrapped keys in the new Session. yubihsm> put wrapped 1 0xf09a auth.out Object imported as 0x2a74 of type authentication-key yubihsm> put wrapped 1 0xf09a hmac.out Object imported as 0xd1a2 of type hmac-key 9. Open a session with the new application Authentication Key. yubihsm> session open 0x2a74 $HMAC\_PASS Created session 2 10. Run HMAC-SHA256 Test vector #1 and get expected output. > yubihsm> hmac 2 0xd1a2b0344c61d8db38535ca8afceaf0bf12b881dc200c9833da726e9376c2e32cff7 > echo \-ne '\\x48\\x69\\x20\\x54\\x68\\x65\\x72\\x65' | openssl dgst \-hex \-mac hmac \-macopt hexkey:0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b \-sha256 (stdin)= b0344c61d8db38535ca8afceaf0bf12b881dc200c9833da726e9376c2e32cff7 ### PKCS11 / RSA[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-quick-start.html#pkcs11-rsa "Permalink to this heading") This example assumes that only RSA operations will be performed and that RSA keys will be generated on device over PKCS#11. For using the [PKCS#11](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-sdk-tools-libraries.html#hsm2-pkcs11-guide-label) a `yubihsm\_pkcs11.conf` file needs to exist and point at the desired connector. 1. Establish a Session with the default Authentication Key. yubihsm> connect Session keepalive set up to run every 15 seconds yubihsm> session open 1 password Created session 0 2. Create an Authentication Key for Auditing. yubihsm> put authkey 0 0 "Audit auth key" all audit none $AUDIT\_PASS Stored Authentication key 0xd054 3. Optionally enable forced audits. yubihsm> put option 0 force-audit 01 4. Create an Authentication Key for usage with the PKCS11 module. yubihsm> put authkey 0 0 "PKCS11 RSA" 1 delete-asymmetric-key: generate-asymmetric-key:sign-pkcs:sign-pss sign-pkcs:sign-pss $PKCS11\_PASS Stored Authentication key 0xf10f 5. Delete the default Authentication Key. yubihsm> delete 0 1 authentication-key 6. Use pkcs11-tool to generate an RSA key. pkcs11-tool \--module /path/to/yubihsm\_pkcs11.so \-l \--pin f10f${PKCS11\_PASS} \-k \--key-type rsa:2048 \--usage-sign \--label "RSA key" Using slot 0 with a present token (0x0) Key pair generated: Private Key Object; RSA label: RSA key ID: e77d Usage: sign Public Key Object; RSA 2048 bits label: RSA key ID: e77d Usage: none Add a New Authentication Key[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-quick-start.html#add-a-new-authentication-key "Permalink to this heading") ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Before moving on, make sure you are familiar with concepts of [Capabilities](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-core-concepts.html#hsm2-concepts-capability-label) and [Domains](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-core-concepts.html#hsm2-concepts-domain-label) 1. For our example we are going to generate an Authentication Key with selected Capabilities and Domains. Learn more about existing key Types at [Objects](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-core-concepts.html#hsm2-concepts-objects-label) . > yubihsm> put authkey 0 2 yubico 1,2,3 generate-asymmetric-key,export-wrapped,get-pseudo-random,put-wrap-key,import-wrapped,delete-asymmetric-key,sign-ecdsa sign-ecdsa,exportable-under-wrap,export-wrapped,import-wrapped password > > where – > > `put authkey` is the command to create a new authentication key. > > `0` is the session ID. > > `2` is the ObjectID of the new authentication key. > > `yubico` is the label of the new authentication key. > > `1,2,3` is the domain where the new authentication key will operate within. > > `generate-asymmetric-key, export-wrapped,get-pseudo-random,put-wrap-key,import-wrapped,delete-asymmetric-key,sign-ecdsa` are the capabilities for the new authentication key. > > `sign-ecdsa,exportable-under-wrap,export-wrapped,import-wrapped` the delegated capabilities for the new authentication key. > > `password` is the password used to derive the new authentication key. This is the password you specify when opening a session with the YubiHSM using this authentication key. > > Important > > `export-wrapped` allows the creation of Objects that can perform the [EXPORT WRAPPED Command](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-cmd-reference.html#hsm2-cmd-export-wrapped-label) > command. > > `exportable-under-wrap` allows the creation of Objects that can be exported under wrap. > > Note > > The command above has two distinct sets of Capabilities, separated by a space. This is because Authentication Keys, in addition to having regular Capabilities, also have [Capabilities](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-core-concepts.html#hsm2-concepts-capability-label) > . 2. List all Objects to see the newly created Authentication Key. yubihsm> list objects 0 where – `0` the Session ID used for the open session. 3. Next, let’s start using our newly created Authentication Key to establish an encrypted Session. > yubihsm> session open 2 password > Created session 1 > > where – > > `1` is the Session ID assigned to the new Session. We will use this Session ID for most of the commands below. If at any time the Session is closed or expires because of inactivity, open a new one and use the correct Session ID. > > `2` is the ObjectID of the authentication key used to open the session. > > `password` is the password of the authentication key used to open the session. Generate an Asymmetric Key Object for Signing[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-quick-start.html#generate-an-asymmetric-key-object-for-signing "Permalink to this heading") -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- We now proceed to generate a new Asymmetric Key. In our example we will use this key to sign some data. We will also export the key _under wrap_ to another YubiHSM, for backup purposes. Specifically, we will ask the device to generate an Asymmetric Key with ID `100` and a given set of Domains and Capabilities. We will also specify the kind of Asymmetric Key that we would like to generate, an EC key using the NIST P-256 curve in this case. The command is: yubihsm> generate asymmetric 1 100 label\_ecdsa\_sign 1,2,3 exportable-under-wrap,sign-ecdsa ecp256 where – `generate` is YubiHSM shell command. `asymmetric` is the key type to be generated. `1` is the session ID. `100` is the key ID. `label_ecdsa_sign` is the label for the new key object. `1,2,3` are the domains where the new key will be accessible. `exportable-under-wrap` allows this key to be exported under wrap. `sign-ecdsa` is allows this key to be used to perform ECDSA signature. `ecp256` specifies NIST P-256 curve for the key. On success, we will see the message: Generated Asymmetric key 0x0064 This signifies that an Asymmetric Key with ID `0x0064` (hexadecimal for 100) was generated. ### Prepare to Sign With the New Asymmetric Key[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-quick-start.html#prepare-to-sign-with-the-new-asymmetric-key "Permalink to this heading") 1. Assuming we have a file called `data.txt` containing the data we would like to sign, we will sign it using ECDSA with the Asymmetric Key we generated in the previous step. > yubihsm> sign ecdsa 1 100 ecdsa-sha256 data.txt > > where – > > `1` is the Session ID. > > `100` is the key ID. > > By default the output is printed to the standard output and consists of a Base64-encoded signature like the one below. > > MEUCIQDrBqS04LN5YdyWGiD4iaEjfl1dn+W4cl97uMMXDpoaiQIgEBe/G/FgP4cumnO3K2XWToAnPvnuVDOnqHPiuUS0q5g\= 2. This behavior can be changed by using the `set outformat` and `set informat` commands, and by specifying an additional output parameter to the `sign` command. > For now we will store the signature as it is in a temporary file so that we will be able to verify it later. > > $ echo MEUCIQDrBqS04LN5YdyWGiD4iaEjfl1dn+W4cl97uMMXDpoaiQIgEBe/G/FgP4cumnO3K2XWToAnPvnuVDOnqHPiuUS0q5g\= \>signature.b64 3. Next, we will extract the public key from the Asymmetric Key on the device and write it to the file `asymmetric_key.pub`, so that we can use it to verify the signature we just created. > yubihsm> get pubkey 1 100 asymmetric\_key.pub 4. We are going to use OpenSSL for the verification process. Since the signature that we created before is in Base64 format, we need to convert it first. Do so with: > $ base64 \-d signature.b64 \>signature.bin 5. It is now possible to verify the signature with OpenSSL. > $ openssl dgst \-sha256 \-signature signature.bin \-verify asymmetric\_key.pub data.txt > Verified OK Export an Asymmetric Key Under Wrap[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-quick-start.html#export-an-asymmetric-key-under-wrap "Permalink to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ Time to export the Asymmetric Key under wrap to a second YubiHSM 2 (in this example, we will export to the same YubiHSM for convenience). 1. To do that we need a Wrap Key, which fundamentally is an AES key. We use the random number generator built into the YubiHSM to generate the 16 bytes needed for an AES-128 key. yubihsm> get random 1 16 9207653411df91fd36c12faa6886d5c4 Important The result of this command (the bytes) is considered extremely sensitive data and should be stored safely, and preferably, separate from any production environment. 2. We can now store the Wrap Key on the device with ID 200 by doing: yubihsm> put wrapkey 1 200 label\_wrapkey 1,2,3 import-wrapped,export-wrapped sign-ecdsa, exportable-under-wrap 9207653411df91fd36c12faa6886d5c4 Note For the upcoming `export` command to be successful, the Delegated Capabilities of the Wrap Key have to include the Capabilities of the Object being exported. Similarly, for the `import` command to succeed the Delegated Capabilities of the Wrap Key have to include the Capabilities of the Object being imported. 3. We can now export the Asymmetric Key with ID `100` using the Wrap Key with ID `200` and save it to a file called `wrapped_asymmetric.key`. yubihsm> get wrapped 1 200 asymmetric-key 100 wrapped\_asymmetric.key 4. We are going to re-import the Asymmetric Key on the same device so we need to first delete the existing one. yubihsm> delete 1 100 asymmetric-key 5. To import the wrapped EC key back into the YubiHSM use: yubihsm> put wrapped 1 200 wrapped\_asymmetric.key [Cookies](https://www.yubico.com/support/terms-conditions/cookie-notice/) | [Privacy Policy](https://www.yubico.com/support/terms-conditions/privacy-notice/) --- # Set FIPS Mode — YubiHSM 2 User Guide documentation * [](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/index.html) * [YubiHSM 2 Management Tasks](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-index-tools.html) * Set FIPS Mode * [View page source](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/_sources/hsm2-fips-support-guide.rst.txt) * * * Set FIPS Mode[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-fips-support-guide.html#set-fips-mode "Permalink to this heading") ===================================================================================================================================================== Note This guide only applies to YubiHSM 2 FIPS devices. Putting YubiHSM 2 into FIPS Mode[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-fips-support-guide.html#putting-yubihsm-2-into-fips-mode "Permalink to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- To configure the YubiHSM 2 into the FIPS Approved mode of operation: 1. Use the `Set Option` service as follows: 4f000405000101 or put option 0 fips-mode 01 2. Import new Authentication Keys to replace the default values. Validating the Mode[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-fips-support-guide.html#validating-the-mode "Permalink to this heading") ----------------------------------------------------------------------------------------------------------------------------------------------------------------- To check the mode of operation, use the `Get Option` service. get option 0 fips-mode where- `01` return code indicates the Approved mode. `00` return code indicates the non-Approved mode. Taking it out of FIPS Mode[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-fips-support-guide.html#taking-it-out-of-fips-mode "Permalink to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- To configure the YubiHSM 2 into the non-Approved mode of operation. 1. Delete all objects on the YubiHSM 2. 2. Use the `Set Option` service as follows: 4f000405000100 or put option 0 fips-mode 00 [Cookies](https://www.yubico.com/support/terms-conditions/cookie-notice/) | [Privacy Policy](https://www.yubico.com/support/terms-conditions/privacy-notice/) --- # Set up KSP on Windows — YubiHSM 2 User Guide documentation * [](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/index.html) * [YubiHSM 2 Management Tasks](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-index-tools.html) * Set up KSP on Windows * [View page source](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/_sources/hsm2-configure-software-windows.rst.txt) * * * Set up KSP on Windows[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-configure-software-windows.html#set-up-ksp-on-windows "Permalink to this heading") ============================================================================================================================================================================= To configure the YubiHSM for use with Windows, complete the initial preparation, then complete the steps in either the Windows or Windows Server topics. * [Preparing to use YubiHSM 2 on Windows](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-configure-software-windows.html#hsm2-prepare-for-windows-label) * [Configuring YubiHSM 2 for Windows](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-configure-software-windows.html#hsm2-ksp-windows-guide-label) * [Configuring YubiHSM 2 for Microsoft Windows Server](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-configure-software-windows.html#hsm2-ksp-windows-server-guide-label) Preparing to use YubiHSM 2 on Windows[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-configure-software-windows.html#preparing-to-use-yubihsm-2-on-windows "Permalink to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Before using the YubiHSM 2 on Windows, there are two YubiHSM 2 software components to be configured: * The YubiHSM 2 Key Storage Provider (KSP). * The YubiHSM 2 Connector service. The configuration steps are described in the sections below. Important Make a backup of your Windows Registry before you make any changes. ### Configure the KSP Settings in the Windows Registry[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-configure-software-windows.html#configure-the-ksp-settings-in-the-windows-registry "Permalink to this heading") To enable Microsoft Cryptographic API Next Generation (CNG) to access the YubiHSM 2 KSP, the following registry entries must be changed from their default values. The YubiHSM 64-bit KSP subkey and the YubiHSM 32-bit KSP subkey were created during the YubiHSM SDK installation: HKEY\_LOCAL\_MACHINE\\SOFTWARE\\Yubico\\YubiHSM The edits to be made produce a result like the one illustrated below: [![_images/registry-settings-yubihsm2-ksp.png](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/_images/registry-settings-yubihsm2-ksp.png)](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/_images/registry-settings-yubihsm2-ksp.png) **Figure: Registry settings for the YubiHSM 2 KSP** 1. Click **Start > Run**, type `regedit` in the Run dialog box, and click **OK**. 2. Select the registry subkey for the **YubiHSM 64-bit KSP**. HKEY\_LOCAL\_MACHINE\\SOFTWARE\\Yubico\\YubiHSM. 3. Change the URI to the IP address and port on which the YubiHSM 2 Connector is listening by editing the following registry entry appropriately, for example: “ConnectorURL”\=http://127.0.0.1:12345 If the Connector is listening on IP address and port `192.168.100.252:12345`, for example, the ConnectorURL value should be changed to: “ConnectorURL”\=http://192.168.100.252:12345 4. Enter the ID of the application authentication key (object ID `3` was used as an example in this guide; if you used another object ID be sure to enter that). For our example, because the hexadecimal value of `0x00000003` resolves to `3` in the Windows Registry, change the entry to: “AuthKeysetID”\=3 5. The application authentication key password is stored in the registry for the KSP to use when authenticating to the device. Enter the new password that you created: “AuthKeysetPassword”\={password} 6. Select the registry subkey for the `YubiHSM 32-bit KSP`. HKEY\_LOCAL\_MACHINE\\SOFTWARE\\Wow6432Node\\Yubico\\YubiHSM 7. Repeat steps 3-5 above. 8. To save your changes, exit the Windows Registry. ### Configure the YubiHSM 2 Connector Service[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-configure-software-windows.html#configure-the-yubihsm-2-connector-service "Permalink to this heading") The YubiHSM Connector service reads the configuration file `yubihsm-connector-config.yaml`. Depending on your local setup, for instance if you are running multiple instances of the software on the same host, you may need to edit this configuration file to ensure it is consistent with the Windows Registry, i.e., that the parameters and their values are the same in the configuration file and in the Windows Registry. On Windows, the `yubihsmconnector.config.yaml` file is located at `C:\programdata\yubiHSM\yubihsmconnector.yaml` - you need administrator rights to modify the file. Configuring YubiHSM 2 for Windows[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-configure-software-windows.html#configuring-yubihsm-2-for-windows "Permalink to this heading") ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- If the target private key is managed by the Microsoft Software Key Storage Provider, another software provider, or any other KSP that allows export via PKCS#12 PFX, it is possible to move your key to the YubiHSM 2, but results may vary. This process relies on using the `-repairstore` functionality of the `certutil` command, so the private key must only be present via the YubiHSM Key Storage Provider when performing this step. Please refer to the source storage provider documentation for how to cleanly and completely delete a private key. Because KSP implementations differ, we recommend testing this procedure using your existing provider before affecting a live system. ### Export your Existing Private Key and Certificate[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-configure-software-windows.html#export-your-existing-private-key-and-certificate "Permalink to this heading") Refer to your current KSP documentation on how to obtain a PKCS#12 PFX export of your certificate and private key. 1. Obtain your PFX file. 2. Split the certificate from the PFX file using `certutil`. PS1> certutil \-split \-dump This creates a file named \`\`.crt\`\`. 3. If you are moving the key to the YubiHSM 2 on the same machine, you must delete the original private key in your current provider. PS1> certutil \-key 4. Locate the key that corresponds with the CA. It may look something like this: Microsoft Software Key Storage Provider: EXAMPLE-CA abcdef1234fedcba4321abcdef123456\_9cfc1053-1b5a-44d7-8a7e-3a8a1c0d0db0 RSA AT\_KEYEXCHANGE 5. To delete this example private key. PS1> certutil \-delkey \-csp "Microsoft Software Key Storage Provider" "abcdef1234fedcba4321abcdef123456\_9cfc1053-1b5a-44d7-8a7e-3 a8a1c0d0db0" ### Import the Target Private Key[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-configure-software-windows.html#import-the-target-private-key "Permalink to this heading") Using the instructions for importing a PFX private key, see [PUT ASYMMETRIC KEY Command](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-cmd-reference.html#hsm2-cmd-put-asymmetric-key-label) via `yubihsm-shell`, import the target private key file to your YubiHSM 2. 1. Record the `Label` property of your imported key. Important The `certutil` utility does not provide an easy way to split a key exported from the Software KSP into an unencrypted PEM file. It may be necessary to use another tool like OpenSSL to convert the key file to an unencrypted format for import into the HSM. 2. Export the private key. PS1> openssl pkcs12 \-in \-nocerts \-out ca.key \-nodes 3. To remove the passphrase from the private key. PS1> openssl rsa \-in ca.key \-out ca.key ### Restore the Target Certificate[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-configure-software-windows.html#restore-the-target-certificate "Permalink to this heading") 1. Move the target certificate file (`.crt`) to the target machine. 2. Import the certificate to the LocalMachine “My” store via your favorite method. > At this point, the certificate does not have an associated private key. We use the `-repairstore` functionality of `certutil` to re-associate the certificate to the private key. 3. Make sure that the target private key is visible via the YubiHSM KSP. PS1> certutil \-key \-csp "YubiHSM Key Storage Provider" This command lists all private keys visible to the current Authentication Key. It also lists the private keys corresponding container names - which are equal to the [Label](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-core-concepts.html#hsm2-concepts-label-label) property in the YubiHSM 2. 4. Open an elevated prompt and execute the command. PS1> certutil \-repairstore MY 5. Verify that the certificate has been associated with the YubiHSM KSP and has the correct `Key Container` property value. PS1> certutil \-store My 6. Inspect the Key Container and Provider properties. Warning If you are moving your CA key to the YubiHSM 2 on the same machine, Windows Certificate Services (CertSvc) on the local machine writes the name of the KSP to its configuration section in the registry. When signing requests, the certificate service will fail if the KSP name does not match the name in the registry. 7. Update the KSP name for the local certificate service. * Open an elevated prompt and execute the commands. > PS1> certutil \-setreg CA\\CSP\\Provider "YubiHSM Key Storage Provider" > PS1> certutil \-setreg CA\\EncryptionCSP\\Provider "YubiHSM Key Storage > Provider" * Optionally, if you have multiple CAs on the same machine, or prefer to edit the registry directly. These settings are located at: > `HKLM\System\CurrentControlSet\Services\CertSVC\Configuration\\[CSP | EncryptionCSP]` ### Example: Creating a Code-Signing Certificate using the Key Storage Provider[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-configure-software-windows.html#example-creating-a-code-signing-certificate-using-the-key-storage-provider "Permalink to this heading") This example will show you how to create a code-signing certificate request using a key generated and stored in the YubiHSM 2 via the Key Storage Provider (KSP). This type of code-signing certificate is appropriate for use with the Microsoft `signtool` utility for digitally signing Windows binaries. In this example, we use the command line `certreq` utility. All procedures documented here are available in the Certificate Manager (`certmgr.msc`) MMC snap-in if you prefer to use a GUI. Note For operations that take input data (from command line or file), releases prior to and including the current yubihsm2-sdk release have a size limit - 4kb in interactive mode, or 8kb in non-interactive mode. #### Configure the Key Storage Provider[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-configure-software-windows.html#configure-the-key-storage-provider "Permalink to this heading") By default, the KSP will use the factory authentication key in slot 1. If the factory authentication key no longer exists or a different authentication key is desired, the KSP must first be configured with the desired key ID and password. Note The configured authentication key must at a minimum have the capabilities `generate-asymmetric-key`, `sign-pkcs`, and delegated capability `sign-pkcs`. If you want the generated key to be exportable, then add the `exportable-under-wrap` delegated capability. #### Authentication Key Example[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-configure-software-windows.html#authentication-key-example "Permalink to this heading") Create a new Authentication Key capable of generating exportable asymmetric keys through KSP. yubihsm> put authkey 0 0 "GenerateKey" 1 generate-asymmetric-key, sign-pkcs sign-pkcs,exportable-under-wrap password Stored Authentication key 0x0e32 #### Create the Certificate Request Configuration File[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-configure-software-windows.html#create-the-certificate-request-configuration-file "Permalink to this heading") To specify your request, the `certreq` utility requires an `.inf` file as input. An example file is supplied here. **Sample sign.inf** \[Version\] Signature\="$Windows NT$" \[NewRequest\] Subject \= "CN=My Publisher" ; Entity name (dns name/upn for other cert types) HashAlgorithm \= sha256 ; Request uses sha256 hash KeyAlgorithm \= RSA ; Key pair generated using RSA algorithm Exportable \= FALSE ; Private key is not exportable ExportableEncrypted \= FALSE ; Private key is not exportable encrypted KeyLength \= 2048 ; YubiHSM KSP key sizes: 2048, 3072, 4096 KeySpec \= 2 ; 1 \= AT\_KEYEXCHANGE, 2 \= AT\_SIGNATURE KeyUsage \= 0x80 ; 80 \= Digital Signature, 20 \= Key Encipherment (bitmask) MachineKeySet \= FALSE ; True: cert belongs the local computer, False: current user KeyUsageProperty \= NCRYPT\_ALLOW\_SIGNING\_FLAG ; Private key only used for signing, not decryption UseExistingKeySet \= FALSE ; Do not use an existing key pair ProviderName \= "YubiHSM Key Storage Provider" ProviderType \= 1 SMIME \= FALSE ; No secure email function UseExistingKeySet \= FALSE ; Do not use an existing key pair RequestType \= PKCS10 ; Can be CMC, PKCS10, PKCS7 or Cert (self-signed) \[Strings\] szOID\_ENHANCED\_KEY\_USAGE \= "2.5.29.37" szOID\_CODE\_SIGN \= "1.3.6.1.5.5.7.3.3" szOID\_BASIC\_CONSTRAINTS \= "2.5.29.19" \[Extensions\] %szOID\_ENHANCED\_KEY\_USAGE% \= "{text}%szOID\_CODE\_SIGN%" %szOID\_BASIC\_CONSTRAINTS% \= "{text}ca=0&pathlength=0" ; If you are using ADCS with certificate templates, you may add ; a specific template under \[RequestAttributes\] ; \[RequestAttributes\] ; CertificateTemplate\= CodeSigning #### Create the Certificate Request[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-configure-software-windows.html#create-the-certificate-request "Permalink to this heading") Once you have created the certificate request configuration file, pass it to `certreq` as the input file argument. For example: certreq \-new sign.inf sign.req #### Sign the Certificate Request[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-configure-software-windows.html#sign-the-certificate-request "Permalink to this heading") In the above example, the certificate request was written to `sign.req`. 1. Take this file and submit its contents to your CA for signature. 2. Open the resulting file (for example, `sign.crt`) and install the certificate to your personal store. #### Sign using Signtool[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-configure-software-windows.html#sign-using-signtool "Permalink to this heading") 1. Open a prompt with `signtool` in the path. 2. Sign your binary. \> signtool sign 3. Identify your signing certificate by hash, if you have multiple certificates available for code signing. `signtool` shows you a list of valid certificates. Re-run sign tool with the `sha1` hash of the certificate: \> signtool sign /sha1 4. Associate the YubiHSM private key to the certificate. When importing the certificate for the first time on a new computer, you need to manually bind the certificate to the private key. This is needed because 1) the key is not stored with the certificate and 2) Windows doesn’t automatically create an association between the private key and the certificate. After you import the certificate to your personal store, use the `certutil` utility provided by Windows. \> certutil \-repairstore my ### Troubleshooting[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-configure-software-windows.html#troubleshooting "Permalink to this heading") The error messages returned from `signtool` are often unhelpful in diagnosing why a signing operation failed. In these situations there are a few commands you can use to track down the root cause. When using `signtool`, use the `/v` and `/debug` flags to get more detailed output. * The example below shows a response you might receive if the certificate is installed but the YubiHSM is not connected or is misconfigured. \> signtool sign /v /debug After EKU filter, 1 certs were left. After expiry filter, 1 certs were left. After Hash filter, 1 certs were left. After Private Key filter, 0 certs were left. SignTool Error: No certificates were found that met all the given criteria. * Use `certutil` to check the validity of the imported certificate. \> certutil \-verifystore my \================ Certificate 0 \================ Serial Number: 029fe48291dd587c1e6f42bca341291 ... Certificate is valid * Use `certutil` to check whether the KSP has been installed correctly. You should see `Provider Name: YubiHSM Key Storage Provider` as one of the entries with no errors. \> certutil \-csplist ... Provider Name: YubiHSM Key Storage Provider ... * Use `certutil` to check if the key is accessible through the storage provider. You can also add the `-v` flag to get additional details. \> certutil \-csp "YubiHSM Key Storage Provider" \-key YubiHSM Key Storage Provider: tq-75c94c4b-5e40-4e44-bcd2-ee3330d4942f RSA AT\_SIGNATURE * Use `certutil` to dump certificate information. If the command shows `Cannot find the certificate and private key for decryption.` when using a new computer, it might indicate that `certutil -repairstore` hasn’t yet been performed. \> certutil \-store my \================ Certificate 0 \================ Serial Number: 029fe48291dd587c1e6f42bca341291 ... Private key is NOT exportable Signature test passed For a detailed explanation of all options available in the request `.inf` file, see the documentation for the [certreq](https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/certreq_1) utility. To generate a similar request using the Certificate Manager: 1. Open the Certificate Manager snap-in. 2. Select the Personal/Certificates store. 3. Right click and select **All Tasks > Advanced Operations > Create Custom Request**. Configuring YubiHSM 2 for Microsoft Windows Server[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-configure-software-windows.html#configuring-yubihsm-2-for-microsoft-windows-server "Permalink to this heading") --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- This guide is intended to help systems administrators deploy YubiHSM 2 for use in a Windows server environment. The expected outcome is that the YubiHSM 2 is installed and configured with authentication keys, audit keys, and wrap keys. This guide also explains how to make backups and restore keys on a YubiHSM 2. These guidelines for deployment cover basic topics, so the instructions should be modified as required for your specific environment. It is assumed that you are familiar with the concepts and processes for working with Microsoft Windows Server. It is also assumed that the installation is performed on a single Microsoft Windows Server, but the concept can be extended to more servers. Important Before deploying to production, we recommend that you use this guide for installing and testing the setup of the YubiHSM 2 with the Microsoft Windows Server installation in a test or lab environment. ### About the YubiHSM Software[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-configure-software-windows.html#about-the-yubihsm-software "Permalink to this heading") The following YubiHSM 2 software is used in this guide. These items are included as part of the archive file you download from the [YubiHSM 2 SDK Tools And Libraries](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-sdk-tools-libraries.html#hsm2-sdk-tools-libraries-label) . **YubiHSM Connector** - Enables communication between the YubiHSM 2 and applications that use it. We recommend that the YubiHSM Connector run on the host operating system if the calling application is deployed to a VM. The Connector must always be running. **YubiHSM Shell** - The administrative command line tool used to interact with and configure the YubiHSM 2 device. If the YubiHSM Shell is installed on a VM, it will connect to the Connector over a networked connection. **YubiHSM Setup** - Helps with setting up a device for specific use cases. Currently supports setting up for use with Microsoft Windows KSP. **YubiHSM Key Storage Provider (KSP)** - Acts like a driver for the YubiHSM 2 device on Windows and enables it to work with applications that leverage Microsoft’s Cryptographic API Next Generation (CNG). Examples of calling applications are Microsoft Certificate Services or Microsoft SQL Server Always Encrypted. ### Prerequisites and Preparations[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-configure-software-windows.html#prerequisites-and-preparations "Permalink to this heading") The audience of this guide is an experienced systems administrator with a good understanding of Microsoft Windows Server management. In addition, it is helpful to be familiar with the terminology, software, and tools specific to YubiHSM 2. As a primer for these, refer to Glossary. In order to follow the steps provided in this guide, the following prerequisites must be met: * Access to Microsoft Windows Server 2012 SP2 or higher, installed in a secure computer network. The system administrator must have elevated system privileges. * The YubiHSM 2 SDK downloaded from the [Yubico YubiHSM 2 Release page](https://developers.yubico.com/YubiHSM2/Releases/) and available on the system to be used. Installation instructions are given in the following. * Two (2) YubiHSM 2 devices, one for deployment and one for backup in hardware. * Key custodians, if your organization policies require them for the YubiHSM 2 deployment. For more information about key custodians and the associated `M of N` key shares, see [Key Splitting and Key Custodians](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-configure-software-windows.html#hsm2-key-split-custodians-guide-label) . Important Although it is possible to configure the YubiHSM 2 on a networked machine, to safeguard its integrity, it is recommended that its configuration be performed on a fresh system in an air-gapped environment, i.e., the steps in this guide should be performed on a stand-alone computer with both Windows Server 2012 SP2 or higher and the YubiHSM 2 software installed. And we recommend that you do not store keys - even under wrap - on network-accessible or otherwise compromise-able storage media. Key Splitting and Key Custodians[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-configure-software-windows.html#key-splitting-and-key-custodians "Permalink to this heading") --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- The preferred method for backing up the YubiHSM 2 keys on Windows calls for key splitting and restoring or regenerating, often referred to as setting up an `M of n` scheme ([Shamir’s Secret Sharing (SSS)](https://dl.acm.org/doi/10.1145/359168.359176) ). This process ensures no individual can export key material from the YubiHSM 2 and provides a way to control the import of key material that has been exported under wrap from one device into other devices. For example, you would export and import objects for backup purposes, as described in [Backup and Restore Using YubiHSM KSP (Windows Only)](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-backup-restore.html#hsm2-backup-and-restore-using-yubihsm-ksp-windows-only-label) . The key that is split among a predetermined number (`n`) of **key custodians** (also known as key shareholders) is known as the wrap key. Each custodian receives their own unique share. To use the key, a minimum number of shares (`m`) must be present so that the key can be regenerated (sometimes called “rejoined”). This minimum number of custodians is called the **privacy threshold**. If this threshold is not attained, the wrap key cannot be regenerated. This minimum number, `n`, should be larger than one. The exact number of key shares and the privacy threshold are determined by the requirements of your organization. If your organization has policies in place that define how this procedure should be performed, be sure you know these policies before proceeding. You should also have a predetermined practice in place specifying both: * How the key shares must be recorded (written on paper, photographed, locally printed, or some other means) and * How they must be stored between uses (for example, offsite archive, safety deposit box, sealed envelope). > [![_images/privacy-threshold.png](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/_images/privacy-threshold.png)](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/_images/privacy-threshold.png) **Figure: Privacy Threshold** The YubiHSM Setup Tool enables you to perform the key splitting and assigning of shares to key custodians. To carry out the setup process, you need to know who the wrap key custodians will be. During setup, all key custodians must be physically present to record their shares. Exact instructions for key splitting and assigning of shares are given in [YubiHSM 2 Key Storage Provider (KSP)](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-sdk-tools-libraries.html#hsm2-config-device-for-ksp-label) . [Cookies](https://www.yubico.com/support/terms-conditions/cookie-notice/) | [Privacy Policy](https://www.yubico.com/support/terms-conditions/privacy-notice/) --- # YubiHSM 2 References — YubiHSM 2 User Guide documentation * [](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/index.html) * YubiHSM 2 References * [View page source](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/_sources/hsm2-index-references.rst.txt) * * * YubiHSM 2 References[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-index-references.html#yubihsm-2-references "Permalink to this heading") ================================================================================================================================================================= * [YubiHSM Algorithms](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-algorithms.html) * [YubiHSM Command Reference](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-cmd-reference.html) * [OPEN SESSION Command](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-cmd-reference.html#open-session-command) * [AUTHENTICATE SESSION Command](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-cmd-reference.html#authenticate-session-command) * [OPEN SESSION ASYMMETRIC Command](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-cmd-reference.html#open-session-asymmetric-command) * [BLINK DEVICE Command](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-cmd-reference.html#blink-device-command) * [CHANGE ASYMMETRIC AUTHENTICATION KEY Command](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-cmd-reference.html#change-asymmetric-authentication-key-command) * [CHANGE AUTHENTICATION KEY Command](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-cmd-reference.html#change-authentication-key-command) * [CLOSE SESSION Command](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-cmd-reference.html#close-session-command) * [CREATE OTP AEAD Command](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-cmd-reference.html#create-otp-aead-command) * [CREATE SESSION Command](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-cmd-reference.html#create-session-command) * [DECRYPT AES CBC Command](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-cmd-reference.html#decrypt-aes-cbc-command) * [DECRYPT AES ECB Command](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-cmd-reference.html#decrypt-aes-ecb-command) * [DECRYPT OAEP Command](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-cmd-reference.html#decrypt-oaep-command) * [DECRYPT OTP Command](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-cmd-reference.html#decrypt-otp-command) * [DECRYPT PKCS1 Command](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-cmd-reference.html#decrypt-pkcs1-command) * [DELETE OBJECT Command](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-cmd-reference.html#delete-object-command) * [DERIVE ECDH Command](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-cmd-reference.html#derive-ecdh-command) * [ECHO Command](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-cmd-reference.html#echo-command) * [ENCRYPT AES CBC Command](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-cmd-reference.html#encrypt-aes-cbc-command) * [ENCRYPT AES ECB Command](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-cmd-reference.html#encrypt-aes-ecb-command) * [EXPORT WRAPPED Command](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-cmd-reference.html#export-wrapped-command) * [EXPORT RSA WRAPPED Command](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-cmd-reference.html#export-rsa-wrapped-command) * [EXPORT RSA WRAPPED KEY Command](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-cmd-reference.html#export-rsa-wrapped-key-command) * [GENERATE ASYMMETRIC KEY Command](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-cmd-reference.html#generate-asymmetric-key-command) * [GENERATE HMAC KEY Command](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-cmd-reference.html#generate-hmac-key-command) * [GENERATE OTP AEAD KEY Command](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-cmd-reference.html#generate-otp-aead-key-command) * [GENERATE SYMMETRIC KEY Command](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-cmd-reference.html#generate-symmetric-key-command) * [GENERATE WRAP KEY Command](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-cmd-reference.html#generate-wrap-key-command) * [GET DEVICE INFO Command](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-cmd-reference.html#get-device-info-command) * [GET DEVICE PUBLIC KEY Command](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-cmd-reference.html#get-device-public-key-command) * [GET LOG ENTRIES Command](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-cmd-reference.html#get-log-entries-command) * [GET OBJECT INFO Command](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-cmd-reference.html#get-object-info-command) * [GET OPAQUE Command](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-cmd-reference.html#get-opaque-command) * [GET OPTION Command](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-cmd-reference.html#get-option-command) * [GET PSEUDO RANDOM Command](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-cmd-reference.html#get-pseudo-random-command) * [GET PUBLIC KEY Command](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-cmd-reference.html#get-public-key-command) * [GET STORAGE INFO Command](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-cmd-reference.html#get-storage-info-command) * [GET TEMPLATE Command](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-cmd-reference.html#get-template-command) * [IMPORT WRAPPED Command](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-cmd-reference.html#import-wrapped-command) * [IMPORT RSA WRAPPED Command](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-cmd-reference.html#import-rsa-wrapped-command) * [IMPORT RSA WRAPPED KEY Command](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-cmd-reference.html#import-rsa-wrapped-key-command) * [LIST OBJECTS Command](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-cmd-reference.html#list-objects-command) * [PUT ASYMMETRIC KEY Command](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-cmd-reference.html#put-asymmetric-key-command) * [PUT ASYMMETRIC AUTHENTICATION KEY Command](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-cmd-reference.html#put-asymmetric-authentication-key-command) * [PUT AUTHENTICATION KEY Command](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-cmd-reference.html#put-authentication-key-command) * [PUT HMAC KEY Command](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-cmd-reference.html#put-hmac-key-command) * [PUT OPAQUE Command](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-cmd-reference.html#put-opaque-command) * [PUT OTP AEAD KEY Command](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-cmd-reference.html#put-otp-aead-key-command) * [PUT SYMMETRIC KEY Command](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-cmd-reference.html#put-symmetric-key-command) * [PUT TEMPLATE Command](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-cmd-reference.html#put-template-command) * [PUT WRAP KEY Command](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-cmd-reference.html#put-wrap-key-command) * [PUT PUBLIC WRAP KEY Command](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-cmd-reference.html#put-public-wrap-key-command) * [RANDOMIZE OTP AEAD Command](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-cmd-reference.html#randomize-otp-aead-command) * [RESET DEVICE Command](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-cmd-reference.html#reset-device-command) * [REWRAP OTP AEAD Command](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-cmd-reference.html#rewrap-otp-aead-command) * [SESSION MESSAGE Command](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-cmd-reference.html#session-message-command) * [SET INFORMAT Command](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-cmd-reference.html#set-informat-command) * [SET LOG INDEX Command](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-cmd-reference.html#set-log-index-command) * [SET OPTION Command](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-cmd-reference.html#set-option-command) * [SET OUTFORMAT Command](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-cmd-reference.html#set-outformat-command) * [SIGN ATTESTATION CERTIFICATE Command](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-cmd-reference.html#sign-attestation-certificate-command) * [SIGN ECDSA Command](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-cmd-reference.html#sign-ecdsa-command) * [SIGN EDDSA Command](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-cmd-reference.html#sign-eddsa-command) * [SIGN HMAC Command](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-cmd-reference.html#sign-hmac-command) * [SIGN PKCS1 Command](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-cmd-reference.html#sign-pkcs1-command) * [SIGN PSS Command](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-cmd-reference.html#sign-pss-command) * [SIGN SSH CERTIFICATE Command](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-cmd-reference.html#sign-ssh-certificate-command) * [UNWRAP DATA Command](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-cmd-reference.html#unwrap-data-command) * [VERIFY HMAC Command](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-cmd-reference.html#verify-hmac-command) * [WRAP DATA Command](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-cmd-reference.html#wrap-data-command) * [Glossary](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-glossary.html) * [Copyright](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/copyright.html) * [Trademarks](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/copyright.html#trademarks) * [Disclaimer](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/copyright.html#disclaimer) * [Contact Information](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/copyright.html#contact-information) * [License](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/copyright.html#license) * [Getting Help](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/copyright.html#getting-help) * [Feedback](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/copyright.html#feedback) * [Document Updated](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/copyright.html#document-updated) [Cookies](https://www.yubico.com/support/terms-conditions/cookie-notice/) | [Privacy Policy](https://www.yubico.com/support/terms-conditions/privacy-notice/) --- # YubiHSM 2 Management Tasks — YubiHSM 2 User Guide documentation * [](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/index.html) * YubiHSM 2 Management Tasks * [View page source](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/_sources/hsm2-index-tools.rst.txt) * * * YubiHSM 2 Management Tasks[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-index-tools.html#yubihsm-2-management-tasks "Permalink to this heading") ======================================================================================================================================================================== These platforms and protocols are most commonly used. * [Set FIPS Mode](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-fips-support-guide.html) * [Putting YubiHSM 2 into FIPS Mode](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-fips-support-guide.html#putting-yubihsm-2-into-fips-mode) * [Validating the Mode](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-fips-support-guide.html#validating-the-mode) * [Taking it out of FIPS Mode](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-fips-support-guide.html#taking-it-out-of-fips-mode) * [Set up KSP on Windows](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-configure-software-windows.html) * [Preparing to use YubiHSM 2 on Windows](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-configure-software-windows.html#preparing-to-use-yubihsm-2-on-windows) * [Configuring YubiHSM 2 for Windows](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-configure-software-windows.html#configuring-yubihsm-2-for-windows) * [Configuring YubiHSM 2 for Microsoft Windows Server](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-configure-software-windows.html#configuring-yubihsm-2-for-microsoft-windows-server) * [Key Splitting and Key Custodians](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-configure-software-windows.html#key-splitting-and-key-custodians) * [Backup and Restore with YubiHSM Backup Keys](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-backup-restore.html) * [Backup using Shell, Setup, or KSP](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-backup-restore.html#backup-using-shell-setup-or-ksp) * [Backup Examples](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-backup-restore.html#backup-examples) * [Reset YubiHSM to Factory Settings](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-reset-to-factory.html) * [Physical Reset](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-reset-to-factory.html#physical-reset) * [Reset Using YubiHSM Shell](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-reset-to-factory.html#reset-using-yubihsm-shell) [Cookies](https://www.yubico.com/support/terms-conditions/cookie-notice/) | [Privacy Policy](https://www.yubico.com/support/terms-conditions/privacy-notice/) --- # Backup and Restore with YubiHSM Backup Keys — YubiHSM 2 User Guide documentation * [](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/index.html) * [YubiHSM 2 Management Tasks](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-index-tools.html) * Backup and Restore with YubiHSM Backup Keys * [View page source](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/_sources/hsm2-backup-restore.rst.txt) * * * Backup and Restore with YubiHSM Backup Keys[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-backup-restore.html#backup-and-restore-with-yubihsm-backup-keys "Permalink to this heading") ============================================================================================================================================================================================================= This document describes methods for creating a secondary YubiHSM key that is a backup of your primary YubiHSM. Topics in this document: * [Backup using Shell, Setup, or KSP](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-backup-restore.html#hsm2-backup-restore-shell-ksp-label) * [Backup Examples](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-backup-restore.html#hsm2-backup-restore-key-material-label) Backup using Shell, Setup, or KSP[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-backup-restore.html#backup-using-shell-setup-or-ksp "Permalink to this heading") --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- The YubiHSM 2 supports encrypted export and import of objects using a symmetric AES-CCM based scheme. The examples below assume the default authentication key (0x0001). If you use some other authentication key make sure that it has the capability `put-wrap-key` and has the correct delegated capabilities, otherwise you will get a `wrong permissions for operation` error. You can perform these operations using: * **YubiHSM Shell** for backing up and restoring * **YubiHSM Setup** for backing up and restoring * **YubiHSM Key Storage Provider** for backing up and restoring certificate as well as private key. Basic steps for all three cases: 1. Create a wrap key, call it _wrapkey_. 2. Import _wrapkey_ into the primary YubiHSM2. 3. Export other objects in the primary YubiHSM2 using _wrapkey_. 4. Import _wrapkey_ into the backup YubiHSM2. 5. Import the objects exported in step 3 into the backup YubiHSM2. Conditions required for a successful full backup: Any object that does not fulfill these conditions is not exported: * _wrapkey_ is accessible in all the domains the other objects are available in. * _wrapkey_ has delegated capabilities that include all the capabilities any other object has. * _wrapkey_ has the capabilities `export-wrapped` and `import-wrapped`. * All other objects have the capability `exportable-under-wrap`. ### Backup and Restore Using YubiHSM Shell[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-backup-restore.html#backup-and-restore-using-yubihsm-shell "Permalink to this heading") #### Backup[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-backup-restore.html#backup "Permalink to this heading") 1. Start by generating an asymmetric key that we then make a backup of. $ yubihsm-shell \-a generate-asymmetric-key \-A rsa2048 \--capabilities exportable-under-wrap, sign-pkcs,decrypt-pkcs ... Generated Asymmetric key 0x6e77 ... This generates an asymmetric key accessible in all domains. 2. Get a pseudo random number from the YubiHSM2 and store it in a file. This is the wrap key. $ yubihsm-shell \-a get-pseudo-random \--count\=32 \--out\=wrap.key Important The file `wrap.key` here contains the Wrap Key loaded into your YubiHSM in clear text. It should therefore be considered sensitive. 3. Import `wrap.key` into the primary YubiHSM2. ... yubihsm-shell \-a put-wrap-key \--capabilities export-wrapped,import-wrapped \--delegated\=sign-pkcs, decrypt-pkcs,exportable-under-wrap \--in\=wrap.key ... Stored Wrap key 0xd581 This imports a wrap key accessible in all domains. 4. Make an encrypted backup of the Asymmetric Key `0x6e77` in the file `key_6e77.yhw`. yubihsm-shell \-a get-wrapped \--wrap-id\=0xd581 \--object-id\=0x6e77 \-t asymmetric-key \--out\=key\_6e77.yhw #### Restore[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-backup-restore.html#restore "Permalink to this heading") This step assumes you have a fresh device where you want to restore the previously backed up key `0x6e77`. 1. Import the wrap key into the backup YubiHSM2. $ yubihsm-shell \-a put-wrap-key \-A aes256-ccm-wrap \-c export-wrapped, import-wrapped \--delegated\=sign-pkcs,decrypt-pkcs,exportable-under-wrap \--in\=wrap.key \-i 0xd581 ... Stored Wrap key 0xd581 2. Import the Asymmetric key `0x6e77` into the backup YubiHEM2. yubihsm-shell \-a put-wrapped \--wrap-id\=0xd581 \--in\=key\_6e77.yhw ... Object imported as 0x6e77 of type asymmetric-key ### Backup and Restore Using YubiHSM Setup[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-backup-restore.html#backup-and-restore-using-yubihsm-setup "Permalink to this heading") The [YubiHSM 2 Setup Tool](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-sdk-tools-libraries.html#hsm2-setup-tool-label) can be used to backup and restore all exportable objects simultaneously. #### Backup[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-backup-restore.html#id1 "Permalink to this heading") The step here assumes that a wrap key fulfilling all the conditions mentioned above already exists in the primary YubiHSM2. For the following command line examples, assume that such a key has ObjectID `0xd581`. $ yubihsm-setup dump Enter the wrapping key ID to use for exporting objects: 0xd581 ... Successfully exported object Asymmetric with ID 0x6e77 to ./0x6e77.yhw All done Note When creating a wrap key using `yubihsm-setup` with the subcommand `ksp` or `ejbca`, an option is presented to split the wrap key into shares to be held by different custodians. It would also be possible to set the minimum number of custodians required to reconstruct the wrap key. Important Split and reconstruction of the wrap key is done in the software (yubihsm-setup). The YubiHSM2 itself is not aware of such split or any shares. #### Restore[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-backup-restore.html#id2 "Permalink to this heading") Running the store command imports all `\*.yhw` files in the current directory. If some of those files are not encrypted and wrapped with a wrap key that exists in the backup YubiHSM2, they are not imported. $ yubihsm-setup restore Note If the wrap key was split, the shares to reconstruct it need to be provided in this step. ### Backup and Restore Using YubiHSM KSP (Windows Only)[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-backup-restore.html#backup-and-restore-using-yubihsm-ksp-windows-only "Permalink to this heading") YubiHSM Key Storage Provider (KSP) enables backing up and restoring the keys managed using this tool. Note Microsoft Active Directory Certificate Services (ADCS) does not set the `NCRYPT_ALLOW_EXPORT_FLAG` when generating a key, either through the setup UI or the `Install-ADCSCertificationAuthority` PowerShell module. When creating an ADCS root CA key using the YubiHSM 2, the `exportable-under-wrap` Capability is added by default. Backup and restore functionality is therefore available using the following manual processes. 1. [Identify Your Private Key Container Name](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-backup-restore.html#hsm2-backup-id-private-key-container-name-label) 2. [Backup the Target Certificate](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-backup-restore.html#hsm2-backup-target-certificate-label) 3. [Backup the Target Private Key](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-backup-restore.html#hsm2-backup-target-private-key-label) 4. [Restore the Target Private Key](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-backup-restore.html#hsm2-restore-target-private-key-label) 5. [Restore the Target Certificate](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-backup-restore.html#hsm2-restore-target-certificate-label) #### Identify Your Private Key Container Name[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-backup-restore.html#hsm2-backup-id-private-key-container-name-label "Permalink to this heading") 1. To view the currently installed certificates in the Local Machine “My” store, open an elevated command prompt/shell by using the `certutil` command. > PS1> certutil \-store My 2. Find the target certificate in the list and then find its `Key Container` property. The Provider property should be the same as `YubiHSM Key Storage Provider`. 3. To identify the certificate, record the `Cert Hash` property. #### Backup the Target Certificate[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-backup-restore.html#backup-the-target-certificate "Permalink to this heading") Using any available means (`certmgr.msc`, PowerShell, `certutil`), export the target certificate, but without the private key in DER format. Note The YubiHSM does not provide a mechanism for returning the raw private key to Windows, so generating a PKCS#12 container is not currently possible. For example, to export the certificate in `.crt ``format to a file named ``.crt`, use the command. PS1> certutil \-split \-store My . #### Backup the Target Private Key[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-backup-restore.html#backup-the-target-private-key "Permalink to this heading") Export the target private key with the `label` property equal to the `Key Container` property. 1. Use an Authentication Key with the `export-wrapped` capability set. 2. Use the instructions for exporting a private key under wrap via `yubihsm-shell` (see [Backup and Restore Using YubiHSM Shell](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-backup-restore.html#hsm2-backup-restore-using-yubihsm-shell-label) ). #### Restore the Target Private Key[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-backup-restore.html#restore-the-target-private-key "Permalink to this heading") Import the target private key file to your backup YubiHSM. 1. Use an Authentication Key with the `import-wrapped` capability set. 2. Use the instructions for importing a private key under wrap via `yubihsm-shell` (see [Backup and Restore Using YubiHSM Shell](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-backup-restore.html#hsm2-backup-restore-using-yubihsm-shell-label) ). The imported key object should have the same `Label` property as the original object. #### Restore the Target Certificate[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-backup-restore.html#restore-the-target-certificate "Permalink to this heading") Before the certificate is imported to the local machine, it does not have an associated private key. 1. Move the target certificate file generated as per [Backup and Restore Using YubiHSM Shell](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-backup-restore.html#hsm2-backup-restore-using-yubihsm-shell-label) to the target machine by importing the certificate to the LocalMachine “My” store. Use your preferred method. 2. Re-associate the certificate to the private key by using the `-repairstore` functionality of `certutil`. 3. Verify that the target private key is visible via the YubiHSM KSP: list all private keys (and their corresponding container names - which are equal to the `Label` property in the YubiHSM visible to the current Authentication Key). > PS1> certutil \-key \-csp "YubiHSM Key Storage Provider" 4. Open an elevated prompt and execute the command: > PS1> certutil \-repairstore MY 5. To verify that the certificate has been associated with the YubiHSM Key Storage Provider and has the correct `Key Container` property value, repeat the steps under [Identify Your Private Key Container Name](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-backup-restore.html#hsm2-backup-id-private-key-container-name-label) . Backup Examples[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-backup-restore.html#backup-examples "Permalink to this heading") ----------------------------------------------------------------------------------------------------------------------------------------------------- We strongly recommend you make a backup copy of all production objects residing on your primary device, particularly once the CA root key has been generated on the device. If there is an unforeseen hardware failure of the primary device, having a backup ensures that you can resume operations quickly. In addition, this provides a means to backup all objects contained on a device to reside in secure hardware offline. The backup process results in two identical YubiHSM 2 devices with the same number of objects, keys, labels, etc. Note Specific recommendations for governance of your critical key material is out of scope for this guide. Ensure that you design and document these security procedures to fit the requirements of your organization. In many cases, they are subject to audits. ### Backup and Restore the YubiHSM 2 Overview[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-backup-restore.html#backup-and-restore-the-yubihsm-2-overview "Permalink to this heading") The backup, see [Backup using Shell, Setup, or KSP](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-backup-restore.html#hsm2-backup-restore-shell-ksp-label) , of the primary YubiHSM 2 is a duplicate of all of the objects stored on the primary device. The objects are exported under wrap onto the secondary device. The objects are available using the same application authentication key used. For instance, when following this example, the wrap key (created with ID `2` previously), the application authentication key (ID `3`), the audit key (ID `4`) (if created previously), and the CA root key is duplicated onto the secondary device. The factory-installed authentication key (ID `1`) on the secondary device is destroyed. You need assistance from the wrap key custodians to provide their respective wrap key shares, if applicable. In the example we used, 2 out of the 3 shares must be available. When you create a backup, you create a duplicate of the objects on your primary YubiHSM 2 onto a secondary device. The backup and restore procedure consists of the steps listed below the following diagram. These steps are described in detail in the section, [Restore Keys on the Secondary YubiHSM 2](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-backup-restore.html#hsm2-restore-keys-secondary-yubihsm2-device-label) . [![_images/pre-post-backup-recovery-keys.png](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/_images/pre-post-backup-recovery-keys.png)](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/_images/pre-post-backup-recovery-keys.png) **Figure: Backup and recovery on YubiHSM 2 Primary keys** 1. Locate the wrapped key material that was previously exported by the steps in [YubiHSM 2 Key Storage Provider (KSP)](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-sdk-tools-libraries.html#hsm2-config-device-for-ksp-label) . 2. Set up communication between the YubiHSM 2 tools and the secondary (backup) YubiHSM 2 device. 3. Start the configuration process and authenticate to the secondary YubiHSM 2 device. 4. Identify the CA root key ID. 5. Export the CA root key. 6. Verify the key material under wrap. 7. Restore the key material onto a secondary (backup) YubiHSM 2 device. 8. Verify the objects on the secondary device are correct. [![_images/pre-post-conditions-backup-key-materials.png](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/_images/pre-post-conditions-backup-key-materials.png)](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/_images/pre-post-conditions-backup-key-materials.png) **Figure: Recovery to YubiHSM 2 Secondary keys** Tip For **test purposes** you can set the `yubihsm-setup -d` flag to keep the default authentication-key with the administrative privileges. This allows you to delete keys on the YubiHSM 2 for test purposes only. For **production purposes** however, the `yubihsm-setup` command must be executed without the `-d` flag to ensure that the factory preset authentication key is properly deleted on the YubiHSM 2. ### Symmetric Backup of the Primary YubiHSM 2[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-backup-restore.html#symmetric-backup-of-the-primary-yubihsm-2 "Permalink to this heading") The backup of the primary YubiHSM 2 is a duplicate of all of the objects stored on the primary device, to be exported under wrap and that are available using the application authentication key used. The example described here is appropriate for testing and for smaller installations, such as those whose setup involved the YubiHSM Setup program. This example is not appropriate for moving the YubiHSM 2 device from one server to another. This example gives instructions for duplicating the following on the secondary device: * Wrapkey (previously created with ID `2`), * Application authentication key (ID `3`), * Audit key (ID `4`) (if created previously) The listed objects are exported under wrap. The factory-installed authentication key (ID `1`) on the secondary YubiHSM 2 device will be destroyed, just as it was on the primary YubiHSM 2 device. If you use actual wrap key custodians (instead of just doing a proof of concept), you need the custodians to provide their respective wrap key shares. In the example we used in this guide, 2 out of the 3 custodians/shares must be available. To guarantee integrity, perform these operations in an air-gapped environment. ### Restore Keys on the Secondary YubiHSM 2[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-backup-restore.html#restore-keys-on-the-secondary-yubihsm-2 "Permalink to this heading") Since the CA root key was created on the device when setting up the CA, it currently only exists on the device. To back it up using the YubiHSM Setup program, it must first be exported from the device using the wrap key that also sits on the device alongside the application authentication key and the audit key. To export the CA root key under wrap using the wrap key on the device: 1. In your command line application, run YubiHSM Shell program. To do this, if you haven’t already: 1. Launch your command line application and navigate to the directory containing the YubiHSM Shell program. 2. Then run the following command and press **Enter**. $ yubihsm-shell 2. To connect to the YubiHSM, at the `yubihsm` prompt, type `connect` and press **Enter**. A message verifying that you have a successful connection is displayed. 3. To open a session with the YubiHSM 2, type `session open 3` and press **Enter**. 4. Type in the `password` for the application authentication key. You will receive a confirmation message that the session has been set up successfully. 5. If you already know the object ID of the root CA, you can skip this step. If you need to identify the root CA, you can list the objects available. 1. To list the objects, type `list objects 0` (where `0` is the session number) and press **Enter**. 2. You receive a list of the objects on the device that the application authentication key with ID `3` has access to, which includes the CA root key. Identify its ID. 6. To export the CA root key under wrap from the primary device to the local file system, in the YubiHSM Shell program, run yubihsm> get wrapped 0 2 seed\=0 asymmetric-key {rootkeyID} rootkey.yhw Where `seed=0` does not export a privacy key seed. See [EXPORT WRAPPED Command](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-cmd-reference.html#hsm2-cmd-export-wrapped-label) . 7. Verify that all the keys, that were previously exported from the primary YubiHSM 2 under wrap, reside in the same directory as the YubiHSM Setup program and that you have read access to that directory. If the necessary keys are not yet all available on disk, export the keys under wrap. Run the following command: yubihsm-setup dump The YubiHSM Setup tool looks for files with the `.yhw` file extension in the current working directory and attempts to read and import them into the YubiHSM 2 device. The wrap key itself is imported when the wrap key shares are provided to the tool. For example, the following files may be present: * `0x0003-AuthenticationKey.yhw` (Application authentication key under wrap) * `0x0004-AuthenticationKey.yhw` (Audit key under wrap) * `rootkey.yhw` (CA root key under wrap) * `x427a-Opaque.yhw` (Certificate under wrap - not referenced by this guide in the configuration of the primary HSM 2) * `x427a-AsymmetricKey.yhw` (Private asymmetric key under wrap - not referenced by this guide in the configuration of the primary HSM 2) If the initial authentication key (by default available as ID `0x0001`) has been deleted, the new authentication application key is identified with the flag `yubihsm-setup --authkey`. For example: $ yubihsm-setup \--authkey 0x0003 dump 8. To begin the process of restoring the data onto the secondary YubiHSM 2, if the primary YubiHSM 2 device is inserted into your computer, remove it and insert the secondary device. Important Restoring a device must be performed in an air-gapped environment in order to guarantee integrity. 9. In your command line application (where `$` is the prompt), run YubiHSM Setup with the argument `restore`. 1. Change the directory containing the `*.yhw` files, 2. Run `yubihsm-setup` with the `restore` argument: $ yubihsm-setup restore 10. To start the YubiHSM Setup process. Type the default authentication key password: `password` and press **Enter**. > A confirmation message confirms that the default authentication key was used and that you successfully have authenticated to the YubiHSM 2 device: > > Using authentication key 0x0001 11. When prompted, type the minimum number of wrap key shares required by the privacy threshold and press **Enter**. > The require number of wrap key shares were defined when you set up the primary YubiHSM 2 device. In this guide, we have specified that 2 shares are required to regenerate the key. These must be present in order to proceed. 12. When prompted for share number `1`: Have the wrap key custodian holding the first share input this information and press **Enter**. A message confirms that the share is received: > Received share 2\-1WWmTQj5PHGJQ4H9Y2ouURm8m75QkDOeYzFzOX1VyMpAOeF3YKYZyAVdM0WY4GErclVuAC 13. Continue to have each wrap key custodian enter the share information for each of the wrap key shares required to regenerate the wrap key. When the sufficient number of wrap key shares have been entered by the wrap key custodians, a final message is displayed indicating that the wrap key from the primary YubiHSM 2 is now on the secondary YubiHSM 2 as well: > Stored wrap key with ID 0x0002 on the device > > Note > > The ID of the wrap key on the secondary device is the same as the ID of the wrap key on the primary device. 14. Review the output to verify Certificate Authority (CA) root key was also generated and exported along with a private asymmetric key, both under wrap. > After the wrap key has been stored on the secondary YubiHSM 2 device, the YubiHSM Setup program reads the files containing the application authentication key, the CA root key, and, if applicable, the audit key that were saved to file under wrap during the configuration of the primary device. > > The output below shows that in this case, the Certificate Authority (CA) root key was also generated and exported along with a private asymmetric key, both under wrap. > > reading ./0x0004.yhw > Successfully imported object Authkey, with ID 0x0004 > reading ./0x0003.yhw > Successfully imported object Authkey, with ID 0x0003 > reading ./0x427a-AsymmetricKey.yhw > Successfully imported object Asymmetric, with ID 0x427a > reading ./0x427a-Opaque.yhw > Successfully imported object Opaque, with ID 0x427a > reading ./rootkey.yhw > Successfully imported object Asymmetric, with ID {rootkeyID} 15. Review the output to note if there are files containing wrapped objects with the `.yhw` file extension in this directory that were exported with a wrap key **other than** the one reconstituted by the shares here. The Setup tool attempts to read those too, but fails gracefully. The Setup tool only restores the files it can decrypt. 16. Wait for the restore process to finish and the setup tool informs you that the default, factory-installed authentication key has been deleted. > Previous authentication key 0x0001 deleted > All done > > The YubiHSM Setup application exits. ### Verify the Duplicated YubiHSM 2[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-backup-restore.html#verify-the-duplicated-yubihsm-2 "Permalink to this heading") With the steps in the previous sections completed, you now have a secondary (duplicate) of the YubiHSM 2 device configured with the three key objects you created on the primary YubiHSM 2 device earlier. Confirm that the key objects are identical on both the secondary (configured in previous section) and the primary device (configured earlier). 1. At your command prompt, run the YubiHSM Shell program. To do this, if you haven’t already: 1. Launch your command line application and navigate to the directory containing the YubiHSM Shell program. 2. Then run the following command and press **Enter**. $ yubihsm-shell 2. Connect to the YubiHSM 2, at the `yubihsm` prompt, type `connect` and press **Enter**. A message confirms that you have a successful connection. 3. Open a session with the YubiHSM 2, type `session open 3` and press **Enter**. where - `3` is the ID for your application authentication key. 4. Type the _password_ for the application authentication key. A message confirms that the session has been set up successfully. 5. List the objects, type `list objects 0` and press **Enter**. where - `0` is session number that was given to you in step 4. Replace `0` with your session number, if it is different. 6. Review the output and verify that the secondary device now contains all of the key material that you intended to restore. Depending on the order in which the keys under wrap were imported, the order of the enumerated keys on the secondary device may be different than on the primary device when using the list command. This has no practical implication and the object IDs are identical between the devices. 7. After you verify that the secondary device contains all of the key material that you intended to restore, remove the keys under wrap currently on file in the current working directory for the YubiHSM Setup program. The computer’s hard drive can be erased. [Cookies](https://www.yubico.com/support/terms-conditions/cookie-notice/) | [Privacy Policy](https://www.yubico.com/support/terms-conditions/privacy-notice/) --- # Glossary — YubiHSM 2 User Guide documentation * [](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/index.html) * [YubiHSM 2 References](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-index-references.html) * Glossary * [View page source](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/_sources/hsm2-glossary.rst.txt) * * * Glossary[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-glossary.html#glossary "Permalink to this heading") ================================================================================================================================= **A** **Application authentication key** AES key used to authenticate to the device. Performs operations according to its defined capabilities. **Audit key** AES authentication key with rights to access audit log. **authentication key** Performs operations according to its defined capabilities. **authentication key: Default** Factory-installed Advanced Encryption Standards (AES) key used when initializing the device. Possesses all capabilities. **C** **Capability** A description of what operations are allowed on or with an object such as a key. **Column Encryption Key (CEK)** CEKs are content-encryption keys used to encrypt data in a Microsoft SQL Server Always Encrypted database. **Column Master Key (CMK)** CMKs are key-protecting keys used to encrypt CEKs for a Microsoft SQL Server Always Encrypted database. **Cryptographic API Next Generation (CNG)** A CNG is Microsoft’s cryptographic architecture, which allows developers to implement applications with features for encryption, electronic signatures, certificate management, etc. **D** **Delegated capability** An operation that an object is allowed to perform by virtue of receiving those permissions from the authentication key or wrap key that was used to create it. **Domain** A logical “container” for objects that can be used to control access to objects on the device. **G** **Guarded Host** This is an attested Hyper-V host machine with a Trusted Platform Module (TPM) that can run shielded Hyper-V VMs. **H** **Host Guardian Services (HGS)** This is a Windows Server role that is composed of the Attestation Service and Key Protection Services. **Hyper-V Virtual Machine (VM)** Microsoft Hyper-V is a native hypervisor that can create VMs on x86-64 systems running Windows. **K** **Key custodian** Holder of a wrap key share. **Key Storage Provider (KSP)** This is a Dynamic Link Library (DLL) that is loaded by Microsoft CNG. KSPs can be used to create, delete, export, import, open and store keys. **M** **M of n** Scheme where a Wrap key is split into a total number of shares (n) held by key custodians, where a minimum number of shares (m) (sometimes called a quorum and sometimes a privacy threshold) is needed to regenerate and use the key. **O** **Object ID (OID)** These are unique identifiers for any kind of object stored on YubiHSM2. An ID can range from 1 to 65535; however, the device can only hold a maximum of 256 unique objects. **S** **Shielded VM** This is a Hyper-V VM with a virtual TPM; it is encrypted using BitLocker, and can run only on attested guarded hosts in a guarded fabric. **SQL Server Management Studio (SSMS)** SQL Server Management Studio (SSMS) is a software application that is used for configuring, managing, and administering all components within Microsoft SQL Server. **T** **Trusted Computing Group (TCG)** This is a group formed by AMD, Hewlett-Packard, IBM, Intel and Microsoft to implement Trusted Computing concepts across personal computers. **Trusted Platform Module (TPM)** This is a cryptographic chip on a device that stores RSA encryption keys specific to the host system for hardware authentication. **W** **Wrap key** An AES key used to protect key material when exporting to file from device and when importing from file to device. Key material exported under wrap will be encrypted and can only be decrypted using the wrap key. [Cookies](https://www.yubico.com/support/terms-conditions/cookie-notice/) | [Privacy Policy](https://www.yubico.com/support/terms-conditions/privacy-notice/) --- # YubiHSM Algorithms — YubiHSM 2 User Guide documentation * [](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/index.html) * [YubiHSM 2 References](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-index-references.html) * YubiHSM Algorithms * [View page source](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/_sources/hsm2-algorithms.rst.txt) * * * YubiHSM Algorithms[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-algorithms.html#yubihsm-algorithms "Permalink to this heading") ======================================================================================================================================================= Following table describes algorithm names to be used with YubiHSM Shell for the algorithms supported by YubiHSM 2. The table includes the externally common name, YubiHSM shell name, and common usage. | Name | yubihsm-shell name | EC Curve | Value | Usage | | --- | --- | --- | --- | --- | | AES 128 | aes128 | | | | | AES 192 | aes192 | | | | | AES 256 | aes256 | | | | | AES CBC | aes-cbc | | | | | AES ECB | aes-ecb | | | | | AES128 CCM WRAP | aes128-ccm-wrap | | 29 | Generate Wrap key | | AES192 CCM WRAP | aes192-ccm-wrap | | 41 | Generate and

store wrap key | | AES256 CCM WRAP | aes256-ccm-wrap | | 43 | Generate and

store wrap key | | AES KWP | aes-kwp | | 55 | Internal use only | | EC BP256 | ecbp256 | brainpool256r1 | 15 | Generate EC key | | EC BP384 | ecbp384 | brainpool384r1 | 16 | Generate EC key | | EC BP512 | ecbp512 | brainpool512r1 | 17 | Generate EC key | | EC ECDH | ecdh | | 24 | | | EC K256 | eck256 | secp256k1 | 15 | Generate EC key | | EC P224 | ecp224 | secp224r1 | 12 | Generate EC key | | EC P256 | ecp256 | secp256r1 | 13 | Generate EC key | | EC P384 | ecp384 | secp384r1 | 14 | Generate EC key | | EC P521 | ecp521 | secp521r1 | 47 | Generate EC key | | ECDSA SHA1 | ecdsa-sha1 | | 23 | ECDSA sign | | ECDSA SHA256 | ecdsa-sha256 | | 43 | ECDSA sign | | ECDSA SHA384 | ecdsa-sha384 | | 44 | ECDSA sign | | ECDSA SHA512 | ecdsa-sha512 | | 45 | ECDSA sign | | ED25519 | ed25519 | | 46 | Generate ED key | | HMAC SHA1 | hmac-sha1 | | 19 | Generate HMAC key | | HMAC SHA256 | hmac-sha256 | | 20 | Generate HMAC key | | HMAC SHA384 | hmac-sha384 | | 21 | Generate HMAC key | | HMAC SHA512 | hmac-sha512 | | 22 | Generate HMAC key | | MGF1 SHA1 | mgf1-sha1 | | 32 | RSA sign with

PSS and RSA

decrypt with OAEP | | MGF1 SHA256 | mgf1-sha256 | | 33 | RSA sign with

PSS and RSA

decrypt with OAEP | | MGF1 SHA384 | mgf1-sha384 | | 34 | RSA sign with

PSS and RSA

decrypt with OAEP | | MGF1 SHA512 | mgf1-sha512 | | 35 | RSA sign with

PSS and RSA

decrypt with OAEP | | Opaque Data | opaque-data | | 30 | Store raw data

as an opaque

object | | Opaque X509 Certificate | opaque-x509-certificate | | 31 | Store

X509Certificate

as an opaque

object | | RSA 2048 | rsa2048 | | 9 | Generate RSA key | | RSA 3072 | rsa3072 | | 10 | Generate RSA key | | RSA 4096 | rsa4096 | | 11 | Generate RSA key | | RSA OAEP SHA1 | rsa-oaep-sha1 | | 25 | RSA decrypt with

OAEP | | RSA OAEP SHA256 | rsa-oaep-sha256 | | 26 | RSA decrypt with

OAEP | | RSA OAEP SHA384 | rsa-oaep-sha384 | | 27 | RSA decrypt with

OAEP | | RSA OAEP SHA512 | rsa-oaep-sha512 | | 28 | RSA decrypt with

OAEP | | RSA PKCS1 SHA1 | rsa-pkcs1-sha1 | | 1 | RSA sign with

PKCS1.5 | | RSA PKCS1 SHA256 | rsa-pkcs1-sha256 | | 2 | RSA sign with

PKCS1.5 | | RSA PKCS1 SHA384 | rsa-pkcs1-sha384 | | 3 | RSA sign with

PKCS1.5 | | RSA PKCS1 SHA512 | rsa-pkcs1-sha512 | | 4 | RSA sign with

PKCS1.5 | | RSA PSS SHA1 | rsa-pss-sha1 | | 5 | RSA sign with PSS | | RSA PSS SHA256 | rsa-pss-sha256 | | 6 | RSA sign with PSS | | RSA PSS SHA384 | rsa-pss-sha384 | | 7 | RSA sign with PSS | | RSA PSS SHA512 | rsa-pss-sha512 | | 8 | RSA sign with PSS | | SSH Template | template-ssh | | 36 | Store an SSH

template (a

binary object

used to restrict

how and when an

SSH CA private

key should be

used) | | Yubico AES Authentication | aes128-yubico-authentication | | 38 | Store

authentication

key | | Yubico Asymmetric

Authentication | ecp256-yubico-authentication | | | | | Yubico OTP AES128 | aes128-yubico-otp | | 37 | Generate OTP AEAD

key | | Yubico OTP AES192 | aes192-yubico-otp | | 39 | Generate OTP AEAD

key | | Yubico OTP AES256 | aes256-yubico-otp | | 40 | Generate OTP AEAD

key | [Cookies](https://www.yubico.com/support/terms-conditions/cookie-notice/) | [Privacy Policy](https://www.yubico.com/support/terms-conditions/privacy-notice/) --- # Copyright — YubiHSM 2 User Guide documentation * [](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/index.html) * [YubiHSM 2 References](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-index-references.html) * Copyright * [View page source](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/_sources/copyright.rst.txt) * * * Copyright[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/copyright.html#copyright "Permalink to this heading") =============================================================================================================================== © 2015-2025 Yubico AB. All rights reserved. Trademarks[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/copyright.html#trademarks "Permalink to this heading") --------------------------------------------------------------------------------------------------------------------------------- Yubico and YubiKey are registered trademarks of Yubico AB. All other trademarks are the property of their respective owners. Disclaimer[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/copyright.html#disclaimer "Permalink to this heading") --------------------------------------------------------------------------------------------------------------------------------- The contents of this document are subject to revision without notice due to continued progress in methodology, design, and manufacturing. Yubico shall have no liability for any error or damages of any kind resulting from the use of this document. The Yubico Software referenced in this document is licensed to you under the terms and conditions accompanying the software or as otherwise agreed between you or the company that you are representing. Contact Information[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/copyright.html#contact-information "Permalink to this heading") --------------------------------------------------------------------------------------------------------------------------------------------------- Yubico AB Gävlegatan 22 113 30 Stockholm Sweden License[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/copyright.html#license "Permalink to this heading") --------------------------------------------------------------------------------------------------------------------------- Licensed under the Apache License, Version 2.0 (the “License”); you may not use this file except in compliance with the License. You may obtain a copy of the License at [https://www.apache.org/licenses/LICENSE-2.0](https://www.apache.org/licenses/LICENSE-2.0) Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. Getting Help[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/copyright.html#getting-help "Permalink to this heading") ------------------------------------------------------------------------------------------------------------------------------------- Documentation is continuously updated on [https://docs.yubico.com/](https://docs.yubico.com/) (this site). Additional support resources are available in the Yubico Knowledge Base. Click the links to: * [Submit a support request](https://support.yubico.com/) * [Contact our sales team](https://www.yubico.com/contact-us/) Feedback[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/copyright.html#feedback "Permalink to this heading") ----------------------------------------------------------------------------------------------------------------------------- Yubico values and welcomes your feedback. If you think you may have discovered a flaw in our product, please submit a support request at [https://support.yubico.com/](https://support.yubico.com/) and provide as much detail as you can. Document Updated[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/copyright.html#document-updated "Permalink to this heading") --------------------------------------------------------------------------------------------------------------------------------------------- 2025-10-08 23:02:52 UTC [Cookies](https://www.yubico.com/support/terms-conditions/cookie-notice/) | [Privacy Policy](https://www.yubico.com/support/terms-conditions/privacy-notice/) --- # Reset YubiHSM to Factory Settings — YubiHSM 2 User Guide documentation * [](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/index.html) * [YubiHSM 2 Management Tasks](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-index-tools.html) * Reset YubiHSM to Factory Settings * [View page source](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/_sources/hsm2-reset-to-factory.rst.txt) * * * Reset YubiHSM to Factory Settings[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-reset-to-factory.html#reset-yubihsm-to-factory-settings "Permalink to this heading") =========================================================================================================================================================================================== Before deploying the YubiHSM 2 in a production environment, it might be necessary to reset the YubiHSM to its factory settings, for instance to facilitate tests or training. A reset destroys any objects stored on the YubiHSM that are not factory-installed. Physical Reset[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-reset-to-factory.html#physical-reset "Permalink to this heading") ----------------------------------------------------------------------------------------------------------------------------------------------------- The YubiHSM can be physically reset to its factory settings. To do this, while inserting the YubiHSM 2 into a USB port, press the metal rim as you insert it and continue to press the rim for a minimum of 10 seconds. Reset Using YubiHSM Shell[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-reset-to-factory.html#reset-using-yubihsm-shell "Permalink to this heading") --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Please refer to the [RESET DEVICE Command](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-cmd-reference.html#hsm2-cmd-reset-device-label) . [Cookies](https://www.yubico.com/support/terms-conditions/cookie-notice/) | [Privacy Policy](https://www.yubico.com/support/terms-conditions/privacy-notice/) --- # YubiHSM 2 SDK Tools And Libraries — YubiHSM 2 User Guide documentation * [](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/index.html) * YubiHSM 2 SDK Tools And Libraries * [View page source](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/_sources/hsm2-sdk-tools-libraries.rst.txt) * * * YubiHSM 2 SDK Tools And Libraries[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-sdk-tools-libraries.html#yubihsm-2-sdk-tools-and-libraries "Permalink to this heading") ============================================================================================================================================================================================== YubiHSM 2 SDK Downloads[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-sdk-tools-libraries.html#yubihsm-2-sdk-downloads "Permalink to this heading") -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- YubiHSM 2 SDK can be downloaded from [https://developers.yubico.com/YubiHSM2/Releases/](https://developers.yubico.com/YubiHSM2/Releases/) and contains the following tools and libraries to interface with YubiHSM 2. | Resource | Description | | --- | --- | | bin/libcrypto-3.dll or lib/libcrypto-3.dylib | Pre-built OpenSSL (Windows and MacOS only) | | bin/yubihsm-setup | Deployment tool for YubiHSM 2 | | bin/yubihsm-wrap | A tool to create wrapped importable

objects offline | | bin/yubihsm-connector | The Connector, a tool for providing a

common interface to the device | | bin/yubihsm-shell | The shell, a REPL-style tool for

interacting with YubiHSM 2 (and the

Connector) See Note (1) | | include/pkcs11/pkcs11.h | Common and standard PKCS#11 functions and

constants definitions | | include/pkcs11/pkcs11y.h | Yubico-specific PKCS#11 functions and

constants definitions | | include/yubihsm.h | Library functions and constants definitions | | lib/libyubihsm.{dylib,so}

or bin/libyubihsm.dll | Library binary to interact with YubiHSM 2 | | lib/yubihsm\_pkcs11.{dylib,so}

or bin/yubihsm\_pkcs11.dll | PKCS#11 module to interact with YubiHSM 2 | | python-noarch (**1**) | Python implementation of the library | | yubihsm-cngprovider-windows-

amd64.msi | Installer for CNG/KSP for Windows ADCS

(Windows only) | | yubihsm-connector-windows-

amd64.msi | Installer for the Connector (Windows only) | **(1)** python-noarch is a separate download. See [python-yubihsm](https://developers.yubico.com/python-yubihsm/) . For YubiHSM 2 SDK Library components see: * [yubihsm-connector](https://developers.yubico.com/yubihsm-connector/) * [yubihsm-setup](https://developers.yubico.com/yubihsm-setup/) * [yubihsm-shell](https://developers.yubico.com/yubihsm-shell/) > * [yubihsm-auth](https://developers.yubico.com/yubihsm-shell/yubihsm-auth.html) > > * [yubihsm-pkcs11](https://developers.yubico.com/yubihsm-shell/yubihsm-pkcs11.html) > > * [yubihsm-wrap](https://developers.yubico.com/yubihsm-shell/yubihsm-wrap.html) > > * [libyubihsm](https://developers.yubico.com/yubihsm-shell/libyubihsm.html) > * [python-yubihsm](https://developers.yubico.com/python-yubihsm/) Details on these tools and libraries can be found in the later sections of this document. YubiHSM 2 Communication[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-sdk-tools-libraries.html#yubihsm-2-communication "Permalink to this heading") -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Users and applications communicate with the YubiHSM 2 through either HTTP and USB using the [yubihsm-connector](https://developers.yubico.com/yubihsm-connector/) . See [YubiHSM 2 Connector](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-sdk-tools-libraries.html#hsm2-connector-label) . ### HTTP Access to YubiHSM[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-sdk-tools-libraries.html#http-access-to-yubihsm "Permalink to this heading") This kind of connection talks to yubihsm-connector over http(s), allowing remote access to a YubiHSM2, see [YubiHSM 2 Connector](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-sdk-tools-libraries.html#yubihsm-2-connector) . In order to select this type of backend the connector URL should use the `http` or `https` scheme; for example, to use a local HTTP Connector use `http://127.0.0.1:12345`. Note HTTP is default configuration. ### USB Access to YubiHSM[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-sdk-tools-libraries.html#usb-access-to-yubihsm "Permalink to this heading") This kind of connection is a direct-access USB backend that talks directly with a YubiHSM device. The USB Connector is built into `libyubihsm`. This renders it unnecessary to run an additional component (i.e., the external Connector) at the cost of requiring exclusive access to a YubiHSM device. To select this type of backend the connector URL should use the `yhusb` scheme. For example, to use a local device with serial number 123456 use `yhusb://serial=123456`. YubiHSM 2 Setup Tool[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-sdk-tools-libraries.html#yubihsm-2-setup-tool "Permalink to this heading") -------------------------------------------------------------------------------------------------------------------------------------------------------------------- The SDK ships with a tool called [yubihsm-setup](https://developers.yubico.com/yubihsm-setup/) that helps with setting up a device for specific use cases. The tool assumes familiarity with the key concepts of YubiHSM such as [Domains](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-core-concepts.html#hsm2-concepts-domain-label) , [Capabilities](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-core-concepts.html#hsm2-concepts-capability-label) and [Object ID](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-core-concepts.html#hsm2-concepts-objectid-label) . It currently supports the following: * setup for KSP/ADCS and EJBCA; * restoring a previous configuration * resetting the device to factory defaults * exporting all existing objects The tool is based around the concept of secret-sharing. When setting up Objects, those are exported with a freshly created Wrap Key. The key is never stored on disk, but rather it is printed on the screen as shares. The key concepts here are: * The number of shares, which is the number of parts the key should be divided into. * The security threshold, which is the minimum number of shares required to reconstruct the Wrap Key. Besides splitting the Wrap Key into shares, the tool (by default) also exports under wrap all the newly created objects and saves them in the current directory. This can be used at a later time to “clone” or recover a device. This operation can be performed either with `yubihsm-setup` or manually if the Wrap Key is known. By default, the Authentication Key used to establish a Session with the device is also normally deleted at the end of the process. Default behavior can be altered with command line options. For more information, consult the tool’s help. ### Setup for EJBCA[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-sdk-tools-libraries.html#setup-for-ejbca "Permalink to this heading") When setting up the device for use by EJBCA, the setup tool also generates an asymmetric key pair and an X509 certificate suitable for use as a CA key. The setup tool can be re-run as many times as the number of asymmetric keys to be generated since each run will produce only one key pair and one corresponding X509 certificate. Note Using the `--no-new-authkey` flag prevents generation of a new Wrap Key and a new Authentication Key. ### How It Works[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-sdk-tools-libraries.html#how-it-works "Permalink to this heading") For the JAVA implementation, a key pair can be used to perform PKCS#11 operations only if the key and its corresponding X509 certificate are stored under the same ID on the device (the value of their CKA\_ID attributes is the same). To store them under the same ID, run the YubiHSM 2 Setup tool with the `ejbca` subcommand: 1. Generate an Asymmetric Key on the YubiHSM 2. 2. Generate an attestation certificate for the asymmetric key and import it into the YubiHSM 2 under the same ID as the Asymmetric Key. The attestation certificate stored on the YubiHSM 2 is, in fact, only a placeholder certificate for the public key. It is never used by EJBCA because EJBCA stores the CAs’ certificates in a dedicated database. YubiHSM 2 Shell[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-sdk-tools-libraries.html#yubihsm-2-shell "Permalink to this heading") ---------------------------------------------------------------------------------------------------------------------------------------------------------- The [yubihsm-shell tool](https://developers.yubico.com/yubihsm-shell/yubihsm-shell.html) is the administrative and testing tool you can use to interact with and configure the YubiHSM 2 device. All the commands supported by YubiHSM 2 [YubiHSM Command Reference](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-cmd-reference.html#hsm2-cmd-reference-label) can be issued to YubiHSM 2 using YubiHSM 2 Shell. The Shell can be invoked in two different ways: interactively, or as a command line tool useful for scripting. Additional information on the various commands can be obtained with the `help` command in interactive mode or by referring to the `--help` argument for the command line mode. Examples of commands can also be found in the [YubiHSM Command Reference](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-cmd-reference.html#hsm2-cmd-reference-label) reference. ### YubiHSM Shell Command Syntax[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-sdk-tools-libraries.html#yubihsm-shell-command-syntax "Permalink to this heading") Commands and subcommands require specific arguments to work. The Shell will return an error message if the command syntax is incorrect, pointing at the first invalid argument. Arguments have different types. In interactive mode pre-defined values for command types can be tab-completed (Tab Completion does not work on Windows). Command arguments are explained in the table below. | Arg | Type | Description | | --- | --- | --- | | A | Algorithm | An algorithm in string form (ex: ecp256) | | B | Byte | A generic (hex or dec) 8-bit unsigned number | | C | Capabilities | A list of Capabilities in either form:

hex (ex: 0xffffffffffffffff) or

string (ex: sign-pkcs,sign-pss, get-log-entries) | | D | Domains | A list of Domains, either in hex (ex: 0xffff) or

string form (ex: 3,5,14) | | I | Format | A format specifier in string form (ex: base64) | | I | Input data | Input data, generally defaults to standard input | | U | Number | A generic (hex or dec) unsigned number | | O | Option | A device-global option in string form

(ex: force-audit) | | F | Output filename | Output file name, generally defaults to standard

output | | E | Session | The ID of an already-established Session | | S | String | A generic string (use quotes for strings

including white spaces) | | T | Type | An Object Type in string form (ex: Asymmetric) | | W | Word | A generic (hex or dec) 16-bit unsigned number | Different commands have different default formats. These can be listed by invoking `help` on a specific command. For example, the `help sign` will display the following message: pss Sign data using RSASSA-PSS (default input format: binary) e:session,w:key\_id,a:algorithm,i:data\=\-,F:out\=\- As can be seen, the input format is binary. Additionally, arguments to a command that have `=-` after their type and name (like `i:data` and `F:out` in the example above), use the standard input or standard output by default for reading data. Different levels of debug output can be enabled by using the `-v` flag in command line mode, or by issuing the `debug LEVEL` command in interactive mode, where LEVEL is one of `all`, `crypto`, `error`, `info`, `intermediate`, `none`, or `raw`. See [YubiHSM Command Reference](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-cmd-reference.html#hsm2-cmd-reference-label) for yubihsm-shell commands interactive and command line mode examples. YubiHSM 2 Connector[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-sdk-tools-libraries.html#hsm2-connector-label "Permalink to this heading") ------------------------------------------------------------------------------------------------------------------------------------------------------------------- The [yubihsm-connector](https://developers.yubico.com/yubihsm-connector/) performs the communication between the YubiHSM 2 and the applications that use it. The Connector must have permissions to access the USB device, and different operating systems behave differently in this regard. The easiest way to get started is to run the Connector with Administrator privileges (e.g. with `sudo`), but the safest way to run the Connector is to use your operating system’s configuration to give it only the privileges necessary to access the YubiHSM 2 USB device. The Connector is not a trusted component. Sessions are established cryptographically between the application and the YubiHSM 2 using a symmetric mutual authentication scheme that is both encrypted and authenticated. The Connector is not required to run on the same host as the applications which access it. In that case, configure the Connector to listen on a different address rather than the default `localhost:12345`. Make sure that the client has access. The port number does not need to change, only the address. Also, make sure that OS firewalls are configured properly to allow access to the host machine on the specified port. To get information regarding the Connector issue a GET request on the `/connector/status` URI. ### Communicating with the YubiHSM Connector[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-sdk-tools-libraries.html#communicating-with-the-yubihsm-connector "Permalink to this heading") As mentioned earlier, the YubiHSM Connector is not meant to be a trusted component. For this reason it defaults to HTTP connections. It is possible to use HTTPS, however this requires providing a key and a certificate to the Connector. Another option is to use a reverse proxy such as nginx before the Connector and have that handle TLS. ### Sample Configuration[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-sdk-tools-libraries.html#sample-configuration "Permalink to this heading") Sample configuration for the Connector: `yubihsm-connector-config.yaml` \# Certificate (X.509) cert: "" \# Certificate key key: "" \# Listening address. Defaults to "localhost:12345". listen: localhost:12345 \# Device serial in case of multiple devices serial: "" \# Log to syslog/eventlog. Defaults to "false". syslog: false \# Use to enable host header filtering. Default to "false". \# Use this if there is an absolute need to use a web browser on the \# host where the YubiHSM 2 is installed to connect to untrusted web \# sites on the Internet. enable-host-whitelist: false \# Default list for the host header filter host-whitelist: localhost,localhost.,127.0.0.1,\[::1\] Sample `udev` rule to be placed into `/etc/udev/rules.d/` #This udev file should be used with udev 188 and newer ACTION!\="add|change", GOTO\="yubihsm2\_connector\_end" \# Yubico YubiHSM 2 \# The OWNER attribute here has to match the uid of the process \# running the Connector SUBSYSTEM\=="usb", ATTRS{idVendor}=="1050", ATTRS{idProduct}=="0030", OWNER\="yubihsm-connector" LABEL\="yubihsm2\_connector\_end" YubiHSM 2 Auth[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-sdk-tools-libraries.html#yubihsm-2-auth "Permalink to this heading") -------------------------------------------------------------------------------------------------------------------------------------------------------- **YubiHSM Auth** is a YubiKey module that serves as a key storage for authenticating against a YubiHSM 2 with a YubiKey instead of having to manually entering credential to authenticate a session. To leverage this functionality, use the latest release of [YubiHSM 2 SDK](https://developers.yubico.com/YubiHSM2/Releases/) . YubiHSM Auth is a YubiKey CCID application that stores the long-lived credentials used to establish secure sessions to a YubiHSM 2. The secure session protocol is based on [Secure Channel Protocol 3 (SCP03)](hhttps://docs.yubico.com/hardware/yubikey/yk-tech-manual/scp03-specifics.html) . YubiHSM Auth is supported by YubiKey v5.4.0 and higher. YubiHSM Auth uses hardware to protect the long-lived credentials for accessing a YubiHSM 2. This increases the security of the authentication credentials, as compared to the authentication solution for the YubiHSM 2 based on software credentials derived from the Password-Based Key Derivation Function 2 (PBKDF2) algorithm with a password as input. Note SCP03 is always used, with yubihsm-auth or not. This means that authentication is always based on a pair of 128 bit AES keys. These keys can be derived from a password on the client side, using authentication in the Yubico command line tools. ### Credentials and PIN Codes[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-sdk-tools-libraries.html#credentials-and-pin-codes "Permalink to this heading") Each YubiHSM Auth credential consists of two AES-128 keys which are used to derive the three session-specific AES-128 keys. The YubiHSM Auth application can store up to 32 YubiHSM Auth credentials in the YubiKey. Each YubiHSM Auth credential is protected by a 16-byte user access code provided to the YubiKey for each YubiHSM Auth operation. The access code is used to access the YubiHSM Auth Credential to derive the session-specific AES-128 keys. Storing or deleting YubiHSM Auth credentials requires a separate 16-byte admin access code. Each access code has a limit of eight retries and optionally, verification of user presence (touch). ### YubiHSM 2 Secure Channel[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-sdk-tools-libraries.html#yubihsm-2-secure-channel "Permalink to this heading") YubiKey YubiHSM Auth application can be used to establish an encrypted and authenticated session to a YubiHSM 2. Although the YubiHSM 2 secure channel is based on the protocol Global Platform Secure Channel Protocol **03** (SCP03), there are two important differences: * The YubiHSM 2 secure channel protocol does not use APDUs, so the commands and possible options are not those of the complete SCP03 specification. * SCP03 uses key sets with three long-lived AES keys. Two of these long-lived keys are used for authentication and the third is used to encrypt new long-lived keys when they’re transferred to the device. Since YubiHSM handles authentication keys like any other keys, the third SCP03 long-lived key is not required therefore YubiHSM 2 secure channel uses key sets with two long-lived AES keys which are required for authentication. The YubiHSM 2 authentication protocol uses a set of static credentials called a long-lived key set. This consists of two AES-128 keys: * **ENC**: Used for deriving keys for command and response encryption, as specified in SCP03. * **MAC**: Used for deriving keys for command and response authentication, as specified in SCP03. The identical long-lived keyset is protected in the YubiHSM 2 and in the YubiKey YubiHSM Auth application. Those long-lived key sets are used by the YubiHSM Auth application to derive a set of three session-specific AES-128 keys using the challenge-response protocol as defined in SCP03: * **Session Secure Channel Encryption Key (S-ENC)**: Used for data confidentiality. * **Secure Channel Message Authentication Code Key for Command (S-MAC)**: Used for data and protocol integrity. * **Secure Channel Message Authentication Code Key for Response (S-RMAC)**: Used for data and protocol integrity. The YubiHSM Auth session-specific keys are output from the YubiKey to the calling library, which uses the session keys to encrypt and authenticate commands and responses during a single session. After the session is over the session keys are discarded. Session keys are only used for a single session and are not sensitive after the session is over. ### Architecture Overview[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-sdk-tools-libraries.html#architecture-overview "Permalink to this heading") The figure below shows how the YubiHSM Auth application fits in to the YubiHSM 2 architecture. [![_images/yb-architecture-w-ybauth.png](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/_images/yb-architecture-w-ybauth.png)](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/_images/yb-architecture-w-ybauth.png) **Figure: Architecture Overview** The identical long-lived credentials (key sets) are protected in both the YubiKey YubiHSM Auth application and in the YubiHSM 2. The YubiHSM-Shell software tool can be used for generating the key sets in the YubiHSM 2, and the YubiHSM-Auth software tool can be used for importing the same key sets to the YubiKey YubiHSM Auth application. At the client, the YubiHSM authentication protocol is implemented in the `libykhsmauth` library, which derives the three session AES-keys by calling the YubiKey YubiHSM Auth CCID application. The session objects that are created can be used by the `libyubihsm` in the communication with YubiHSM. The YubiHSM session keys are therefore generated on the basis of the long-lived credentials that are protected in the YubiHSM 2 and YubiKey YubiHSM Auth in conjunction with the SCP03 derivation scheme. ### YubiHSM Auth Flowchart[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-sdk-tools-libraries.html#yubihsm-auth-flowchart "Permalink to this heading") The flowchart below illustrates the authentication protocol communication with YubiHSM using the static keys on YubiHSM Auth. It is assumed that the YubiHSM and YubiHSM Auth application share the same static keyset. The steps are explained below. [![_images/yb-auth-flowchart.png](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/_images/yb-auth-flowchart.png)](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/_images/yb-auth-flowchart.png) **Figure: YubiHSM Auth Flowchart** The following is a description of the steps in the flowchart. 1. The user launches YubiHSM-Shell and enters the commands `connect` and `session open`, with the flag `ykopen` that indicates that the YubiKey with YubiHSM Auth shall be used. 2. The YubiHSM-Shell invokes the `libyubihsm` library, with a request to open a session to the YubiHSM 2. 3. The `libyubihsm` library generates a host challenge and opens a session to the YubiHSM 2 device. 4. The YubiHSM 2 device generates an HSM challenge and generates the session keys based on the HSM challenge, the host challenge, and the static key set in the YubiHSM 2 device. The YubiHSM 2 returns the HSM challenge in an HSM response to the `libyubihsm` library. 5. The `libyubihsm` library propagates the host challenge and HSM challenge to the YubiHSM Shell. 6. The user enters the Credential password for unlocking the static keyset in the YubiHSM Auth application in the YubiKey. The YubiHSM Shell invokes the `libykhsmauth` library, with a request to generate session keys. 7. The `libykhsmauth` library invokes the YubiHSM Auth application in the YubiKey with the Credential password, the HSM challenge and host challenge are used as input parameters. 8. The Credential password unlocks the static keyset in the YubiHSM Auth application, and the YubiHSM Auth application generates the session keys based on the static keys, HSM challenge, and host challenge. 9. The `libykhsmauth` library returns the session keys to YubiHSM Shell. 10. The YubiHSM Shell acknowledges the protocol handshake to `libyubihsm`. 11. The `libyubihsm` sends the host response to the YubiHSM 2 device. The session keys can now be used for secure channel communication between `YubiHSM-Shell/libyubihsm` in the host and the YubiHSM device. ### YubiHSM-Auth Software Tool[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-sdk-tools-libraries.html#yubihsm-auth-software-tool "Permalink to this heading") The YubiHSM-Auth software tool is part of the [YubiHSM Shell](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-sdk-tools-libraries.html#yubihsm-2-shell) , which is installed with the [YubiHSM SDK](https://developers.yubico.com/YubiHSM2/Releases/) . YubiHSM-Auth tool can be used for: * Storing the YubiHSM Auth credentials on a YubiKey * Deleting the YubiHSM Auth credentials on a YubiKey * Listing the YubiHSM Auth credentials on a YubiKey * Changing the YubiHSM Auth management key on a YubiKey * Checking the number of retries of the YubiHSM Auth credential password * Checking the version of the YubiHSM Auth application * Calculating session keys, mainly for debugging and test purposes * Resetting the YubiHSM Auth application on a YubiKey First, the YubiHSM 2 device needs to be configured with an authentication key. The default authentication key password on `KeyID=1` is set to `password`, and this should be changed or replaced with other authentication keys. For the examples in this section, however, it is assumed that the default authentication key is still present on the YubiHSM 2. In order to generate and store the equivalent YubiHSM Auth credentials on the YubiKey, the `yubihsm-auth` command line tool can be used. To invoke YubiHSM-Auth simply run `yubihsm-auth` with the required commands and parameters. To get a list of available commands, parameters and their syntax, run: `yubihsm-auth --help` An example of how to use `yubihsm-auth` for storing YubiHSM Auth credentials on a YubiKey is shown below: $ yubihsm-auth \-a put \--label\="default key" \--derivation-password\="password" \--credpwd\="MyPassword" \--touch\=on \--mgmkey\="00000000000000000000000000000000" \--verbose\=5 Credential successfully stored where – `-a put` is the action to insert a YubiHSM Auth credential on the YubiKey `--label` is the label of the YubiHSM Auth credential on the YubiKey `--derivation-password` is used as input to the PBKDF2 algorithm, which is used for generating the two AES-128 keys that constitute the YubiHSM Auth credentials to be stored on the YubiKey `--credpwd` is the password protecting the YubiHSM Auth credentials on the YubiKey `--touch` is set to ‘on’, which requires the user to touch the YubiKey when accessing the YubiHSM Auth credential `--mgmkey` is the management key that is needed for writing the YubiHSM Auth credentials on the YubiKey `--verbose` is used to print more information as output Note We recommend using an offline air-gapped computer when storing the YubiHSM Auth credentials on the YubiKey. Now the YubiKey YubiHSM Auth application can be used with [YubiHSM Shell](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-sdk-tools-libraries.html#yubihsm-2-shell) for authentication to the YubiHSM 2. ### Using YubiHSM-Auth with YubiHSM Shell[](https://docs.yubico.com/hardware/yubihsm-2/hsm-2-user-guide/hsm2-sdk-tools-libraries.html#using-yubihsm-auth-with-yubihsm-shell "Permalink to this heading") It is now possible to authenticate to the YubiHSM 2 device with static credentials that are protected in the YubiKey application called YubiHSM Auth. For more information on this YubiKey feature and how to configure it, see Using YubiHSM Auth. The YubiHSM Shell tool supports authentication with YubiHSM Auth credentials in both interactive mode and command line mode. In order to use yubihsm-shell with the YubiHSM Auth-enabled YubiKey in interactive mode, open a session by executing the following yubihsm-shell command: `yubihsm> session ykopen