Table of Contents

Class PivSession

Namespace
Yubico.YubiKey.Piv
Assembly
Yubico.YubiKey.dll

Create a session and perform PIV operations within that session.

public sealed class PivSession : ApplicationSession
Inheritance
object
PivSession
Inherited Members

Remarks

When you need to perform PIV operations, instantiate this class to create a session, then call on the methods in the class.

Generally you will choose the YubiKey to use by building an instance of IYubiKeyDevice. This object will represent the actual hardware.

IYubiKeyDevice SelectYubiKey()
    {
        IEnumerable<IYubiKeyDevice> yubiKeyList = YubiKey.FindAll();
        foreach (IYubiKeyDevice current in yubiKeyList)
        {
            /* determine which YubiKey to use */
            if(selected)
            {
                return current;
            }
        }
    }

Once you have the YubiKey to use, you will build an instance of this PivSession class to represent the PIV application on the hardware. Because this class implements IDisposable, use the using keyword. For example,

IYubiKeyDevice yubiKeyToUse = SelectYubiKey();
    using (var piv = new PivSession(yubiKeyToUse))
    {
        /* Perform PIV operations. */
    }

If this class is used as part of a using expression, when the session goes out of scope, the Dispose method will be called to dispose the active PIV session, clearing any authenticated state, and ultimately releasing the connection to the YubiKey.

Note that while a session is open, any management key authentication and PIN verification will be active. That is, you need to authenticate the management key or verify the PIN only once per session. Touch might be needed more than once.

There are some exceptions to the "verify the PIN once per session" rule. For example, to change a PIN, you need to enter the current and new PIN, even if the current PIN has been verified. The documentation for each method in this class will indicate if the PIN is needed, and if so, must it be verified or entered. See also the User's Manual entries on the PIV PIN, PUK, and Management Key and PIV commands access control.

Note that PIN/PUK/Management Key verification or authentication will happen automatically when you call a method that needs it. You can call the TryVerifyPin or TryAuthenticateManagementKey methods if you want, but any method that can be executed only if the PIN and/or management key has been verified or authenticated will determine if the appropriate values have been verified/authenticated, and if not, will make the appropriate calls to do so. The caller must supply a PIN/PUK/management key collector delegate (callback).

This class needs a delegate (callback): a method to enter the PIN, PUK, or management key. Although some operations will not need this delegate, any useful application will almost certainly call one or more methods that do need it. You will need to set the appropriate property after instantiating this class.

using (var pivSession = new PivSession(yubiKeyToUse))
    {
        KeyCollector = SomeCollectorDelegate;
    };

You supply the delegate as the KeyCollector property. See also the User's Manual entry on delegates in the SDK.

Note that the YubiKey is manufactured with default PIN, PUK, and management key values. This is a requirement of the PIV standard.

management key (hex): 01 02 03 04 05 06 07 08
                          01 02 03 04 05 06 07 08
                          01 02 03 04 05 06 07 08
<pre><code class="lang-csharp">PIN (hex): 31 32 33 34 35 36
as an ASCII string, this would be "123456"</code></pre>

<pre><code class="lang-csharp">PUK (hex): 31 32 33 34 35 36 37 38
as an ASCII string, this would be "12345678"</code></pre>

The PIN, PUK, and management key are supplied as byte arrays. The reason is that they can be binary data (they are not necessarily strings, ASCII or otherwise), and a byte array can be overwritten to limit the contents' exposure. See the User's Manual entries on sensitive data.

This class will also need a random number generator and Triple-DES and AES encryptors/decryptors. It will get them from CryptographyProviders. That class will return default implementations, unless you replace them. Very few applications will choose to replace the defaults, but if you want to, see the documentation for that class and the User's Manual entry on alternate crypto implementations to learn how to do so.

Constructors

PivSession(IYubiKeyDevice, ScpKeyParameters?)

Create an instance of PivSession, the object that represents the PIV application on the YubiKey. The communication between the SDK and the YubiKey will be protected by SCP03.

public PivSession(IYubiKeyDevice yubiKey, ScpKeyParameters? keyParameters = null)

Parameters

yubiKey IYubiKeyDevice

The object that represents the actual YubiKey which will perform the operations.

keyParameters ScpKeyParameters

The SCP key parameters, if any, to use in establishing the SCP connection.

Remarks

See the User's Manual entry on SCP03 for more information on this communication protocol.

Because this class implements IDisposable, use the using keyword. For example,

IYubiKeyDevice yubiKeyToUse = SelectYubiKey();
    // Assume you have some method that obtains the appropriate SCP03
    // key set.
    using StaticKeys scp03Keys = CollectScp03Keys();
    using (var piv = new PivSession(yubiKeyToUse, scp03Keys))
    {
        /* Perform PIV operations. */
    }

Exceptions

ArgumentNullException

The yubiKey argument is null.

InvalidOperationException

This exception is thrown when unable to determine the management key type.

Properties

KeyCollector

The Delegate this class will call when it needs a PIN, PUK, or management key.

public Func<KeyEntryData, bool>? KeyCollector { get; set; }

Property Value

Func<KeyEntryData, bool>

Remarks

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. That is often the case when the user has entered the wrong value a number of times, the remaining tries count is getting low, and they would like to stop trying before the YubiKey is blocked.

Note that the SDK will call the KeyCollector with a Request of Release when the process completes. In this case, the KeyCollector MUST NOT throw an exception. The Release is called from inside a finally block, and it is a bad idea to throw exceptions from inside finally.

ManagementKeyAlgorithm

This specifies the algorithm of the management key.

public PivAlgorithm ManagementKeyAlgorithm { get; }

Property Value

PivAlgorithm

ManagementKeyAuthenticated

This indicates whether the management key is authenticated or not.

public bool ManagementKeyAuthenticated { get; }

Property Value

bool

Remarks

Upon instantiation of this class, this property will be set to false. If the management key is authenticated (either single or mutual), it will be updated to true. To see the result of a management key authentication process, see the property ManagementKeyAuthenticationResult.

ManagementKeyAuthenticationResult

This reports the result of the latest management key authentication attempt.

public AuthenticateManagementKeyResult ManagementKeyAuthenticationResult { get; }

Property Value

AuthenticateManagementKeyResult

Remarks

Upon instantiation of this class, this property will be set to AuthenticateManagementKeyResult.Unauthenticated. After authentication is attempted, this will be updated to the result.

The ManagementKeyAuthenticated property reports on whether the management key is authenticated or not, this reports on the result of an authentication.

For example, if the management key is authenticated, this will be either SingleAuthenticated or MutualFullyAuthenticated. If it is "single" and you want "Mutual", you know to run the TryAuthenticateManagementKey method again, this time specifying mutual auth.

Another example would be if ManagementKeyAuthenticated is false, you can check to see if this property is Unauthenticated (never attempted), or maybe it is MutualYubiKeyAuthenticationFailed which indicates you might be connected to a counterfeit YubiKey.

PinVerified

This indicates the current state of the PIN verification.

public bool PinVerified { get; }

Property Value

bool

Remarks

Upon instantiation of this class, this property will be set to false. If the PIN is authenticated (using TryVerifyPin), this will be updated to true

Methods

AuthenticateManagementKey(bool)

Authenticate the management key, throw an exception if the user cancels.

public void AuthenticateManagementKey(bool mutualAuthentication = true)

Parameters

mutualAuthentication bool

If true the method will perform mutual authentication, if false, only the application will authenticate to the YubiKey.

Remarks

This is the same as TryAuthenticateManagementKey, except this method will throw an exception if the KeyCollected indicates user cancellation.

See the TryAuthenticateManagementKey(bool) method for further documentation on this method.

Exceptions

InvalidOperationException

There is no KeyCollector loaded, the key provided was not a valid Triple-DES or AES key, or the YubiKey had some other error, such as unreliable connection.

MalformedYubiKeyResponseException

The YubiKey returned malformed data and authentication, either single or double, could not be performed.

OperationCanceledException

The user canceled management key collection.

SecurityException

Mutual authentication was performed and the YubiKey was not authenticated.

ChangeManagementKey(PivTouchPolicy)

Change the management key, throw an exception if the user cancels. The default management key algorithm will be used. (Firmware 5.7.x and later: AES-192. Firmware 5.6.x and earlier: TDES.)

public void ChangeManagementKey(PivTouchPolicy touchPolicy = PivTouchPolicy.Default)

Parameters

touchPolicy PivTouchPolicy

Remarks

This is the same as TryChangeManagementKey(PivTouchPolicy), except this method will throw an exception if the KeyCollector indicates user cancellation.

See the TryChangeManagementKey(PivTouchPolicy) method for further documentation on this method.

Exceptions

InvalidOperationException

There is no KeyCollector loaded, the key provided was not a valid Triple-DES or AES key, or the YubiKey had some other error, such as unreliable connection.

MalformedYubiKeyResponseException

The YubiKey returned malformed data and authentication, either single or double, could not be performed.

OperationCanceledException

The user canceled management key collection.

SecurityException

Mutual authentication was performed and the YubiKey was not authenticated.

ChangeManagementKey(PivTouchPolicy, PivAlgorithm)

Change the management key, throw an exception if the user cancels. The new key will be of the specified algorithm.

public void ChangeManagementKey(PivTouchPolicy touchPolicy, PivAlgorithm newKeyAlgorithm)

Parameters

touchPolicy PivTouchPolicy
newKeyAlgorithm PivAlgorithm

Remarks

This is the same as TryChangeManagementKey(PivTouchPolicy,PivAlgorithm), except this method will throw an exception if the KeyCollecter indicates user cancellation.

See the TryChangeManagementKey(PivTouchPolicy, PivAlgorithm) method for further documentation on this method.

Exceptions

InvalidOperationException

There is no KeyCollector loaded, the key provided was not a valid Triple-DES or AES key, or the YubiKey had some other error, such as unreliable connection.

MalformedYubiKeyResponseException

The YubiKey returned malformed data and authentication, either single or double, could not be performed.

OperationCanceledException

The user canceled management key collection.

SecurityException

Mutual authentication was performed and the YubiKey was not authenticated.

ChangePin()

Change the PIN, throw an exception if the user cancels.

public void ChangePin()

Remarks

This is the same as TryChangePin, except this method will throw an exception if the KeyCollector indicates user cancellation.

See the TryChangePin() method for further documentation on this method.

Exceptions

InvalidOperationException

There is no KeyCollector loaded, or the YubiKey had some other error, such as unreliable connection.

OperationCanceledException

The user canceled PIN collection.

SecurityException

The remaining retries count indicates the PIN is blocked.

ChangePinAndPukRetryCounts(byte, byte)

Change the retry counts for the PIN and PUK.

Warning

This will reset the PIN and PUK to their default values as well as set the retry counts.

public void ChangePinAndPukRetryCounts(byte newRetryCountPin, byte newRetryCountPuk)

Parameters

newRetryCountPin byte

The PIN's new retry count.

newRetryCountPuk byte

The PUK's new retry count.

Remarks

See the user's manual entry on changing the retry counts.

The retry count is the number of times a wrong PIN or PUK can be entered before the PIN or PUK is blocked. The YubiKey is manufactured with a retry count of three for both the PIN and PUK.

Call this method to change the retry count of both the PIN and PUK. It is allowed to change the counts to different values. For example, it is acceptable to change the PIN retry count to 7 and the PUK retry count to 4. > [!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.

Supply the new retry counts in this method. The maximum retry count is 255, hence, the input arguments are bytes. The minimum retry count is 1. If one of the arguments is 0, this method will throw an exception. Note that a retry count of 1 means there are no retries. If the user enters the wrong PIN or PUK just once, the secret is blocked.

After resetting the retry counts, the PIN and PUK will be reset to their default values (PIN: "123456", PUK: "12345678"). Even though you never reset the application (ResetApplication()) or explicitly changed the PIN and PUK (TryChangePin() and TryChangePuk()), after changing the retry counts, the PIN and PUK will be the defaults.

You will likely want to write your application to immediately follow changing the retry counts with setting the PIN and PUK: (TryChangePin() and TryChangePuk(). Another option is to change these counts during the initial user setup before changing the PIN and PUK from their defaults, then never offer the user the option of changing the retry counts again.

In order to perform this operation, the management key must be authenticated and the PIN must be verified during this session. If the have not been authenticated/verified, this method will call AuthenticateManagementKey(bool) and VerifyPin(). That is, your application does not need to authenticate the management key and verify the PIN separately, this method will determine if they have been authenticated/verified or not, and if not, it will make the calls to perform authentication and verification.

The authentication and verification methods will collect the management key and PIN using the KeyCollector delegate. If no such delegate has been set, this method will throw an exception.

The KeyCollector has an option to cancel the operation. That is, the Authenticate and Verify methods will call the KeyCollector requesting the management key or PIN, and it is possible that during the collection operations, the user cancels. The KeyCollector will return to the authentication or verification method noting the cancellation. In that case, this method will throw an exception. If you want the authentication to return false on user cancellation, you must call TryAuthenticateManagementKey(bool) or TryVerifyPin() directly before calling this method.

Exceptions

ArgumentException

The new retry count provided is invalid.

InvalidOperationException

There is no KeyCollector loaded, the key provided was not a valid Triple-DES key, or the YubiKey had some other error, such as unreliable connection.

OperationCanceledException

The user canceled management key collection.

SecurityException

Mutual authentication was performed and the YubiKey was not authenticated.

ChangePuk()

Change the PUK (PIN Unblocking Key), throw an exception if the user cancels.

public void ChangePuk()

Remarks

This is the same as TryChangePuk, except this method will throw an exception if the KeyCollector indicates user cancellation.

See the TryChangePuk() method for further documentation on this method.

Note: YubiKey Bio Multi-protocol Edition (MPE) keys do not have a PUK.

Exceptions

InvalidOperationException

There is no KeyCollector loaded, or the YubiKey had some other error, such as unreliable connection.

OperationCanceledException

The user canceled PUK collection.

SecurityException

The remaining retries count indicates the PUK is blocked.

CreateAttestationStatement(byte)

Create an attestation statement for the private key in the given slot.

public X509Certificate2 CreateAttestationStatement(byte slotNumber)

Parameters

slotNumber byte

The slot containing the key to be attested.

Returns

X509Certificate2

The resulting attestation statement (a certificate).

Remarks

See the User's Manual entry on PIV attestation for more information on attestation statements.

Note that attestation is a feature available on YubiKeys version 4.3 and later.

An attestation statement is an X.509 certificate that certifies a private key was generated by a YubiKey.

It is possible to create attestation statements only for keys generated on a YubiKey. If the slotNumber argument is for any other slot, or if there is no key in the slot, or if the key in the slot was imported and not generated by the YubiKey, this method will throw an exception.

Note that it is not possible to get an attestation statement for the key in slot F9. That is the attestation key itself.

The key that will sign the attestation statement is the "attestation key" in slot F9. To verify the attestation statement, chain up to the attestation key's cert (see the method GetAttestationCertificate()), which will chain to a root. The YubiKey is manufactured with an attestation key and cert that chain to the Yubico root cert. The User's Manual entry on PIV attestation has more information on chaining attestation statements.

It is possible to replace the attestation key and cert. In that case, the attestation statement created by this method will chain up to a different root. See ReplaceAttestationKeyAndCertificate(IPrivateKey, X509Certificate2). There are restrictions on the key and certificate. The documentation for the Replace method lists those restrictions.

It is not necessary to authenticate the management key or verify the PIN in order to create an attestation statement.

Exceptions

ArgumentException

The slot specified is not valid for creating an attestation statement.

InvalidOperationException

The YubiKey is pre-4.3, or there is no YubiKey-generated key in the slot, or the attestation key and cert were replaced with invalid values, or the YubiKey could not complete the task for some reason such as unreliable connection.

Decrypt(byte, ReadOnlyMemory<byte>)

Decrypt the given data using the key in the given slot.

public byte[] Decrypt(byte slotNumber, ReadOnlyMemory<byte> dataToDecrypt)

Parameters

slotNumber byte

The slot containing the key to use.

dataToDecrypt ReadOnlyMemory<byte>

The ciphertext.

Returns

byte[]

The resulting decrypted block.

Remarks

The YubiKey supports decryption only with RSA keys.

This method returns the raw decrypted data, if it can decrypt. It will not parse the formatted data. If it cannot decrypt for some reason, it will throw an exception.

If the slot specified is not one that can decrypt, or it does not contain a key, or it contains an ECC key (instead of RSA), this method will throw an exception. If the input data is not the correct length, the method will throw an exception.

If the key is RSA 1024, then the input must be exactly 128 bytes. If the key is RSA 2048, then the input must be exactly 256 bytes. If the key is RSA 3072, then the input must be exactly 384 bytes. If the key is RSA 4096, then the input must be exactly 512 bytes. If the input data is not the correct length, the method will throw an exception.

The return will be the raw decrypted data. You can use the RsaFormat class to parse the data and extract the actual unpadded plaintext. That class will be able to parse from either PKCS #1 v1.5 or a subset of PKCS #1 OAEP. However, if that class does not support the exact format you want, you will have to write your own parsing code.

Decrypting might require the PIN and/or touch, depending on the PIN and touch policies specified at the time the key was generated or imported.

If a PIN is required, this method will call the necessary routines to verify the PIN. See VerifyPin() for more information on PIN verification. If the user cancels, this method will throw an exception.

If touch is required, the YubiKey itself will flash its touch signal and wait. If the YubiKey is not touched before the touch timeout, the YubiKey will return with an error, and this method will throw an exception (OperationCanceledException). Note that this method will not make another effort to decrypt if the YubiKey is not touched, it will simply throw the exception.

Note that on YubiKeys prior to version 5.3, it is not possible to know programmatically what the PIN or touch policies are without actually trying to decrypt. Also, it is not possible to know programmatically if an authentication failure is due to PIN or touch. This means that on older YubiKeys, this method will try to decrypt without the PIN, and if it does not work because of authentication failure, it will not know if the failure was due to PIN or touch. Hence, it will try to verify the PIN then try to sign again. This all means that on older YubiKeys, it is possible a YubiKey slot was originally configured with a PIN policy of "never" and a touch policy of "always", and this method will call for the PIN anyway. This happens if the user does not touch the YubiKey before the timeout. See the User's Manual entry on keeping track of slot contents.

Exceptions

ArgumentException

The slot number given was not valid, or the data to decrypt was an invalid length.

InvalidOperationException

There was no key in the slot specified or the data did not match the key (e.g. the data to decrypt was 128 bytes long but the key was RSA 2048).

OperationCanceledException

Either the PIN was required and the user canceled collection or touch was required and the user did not touch within the timeout period.

SecurityException

The remaining retries count indicates the PIN is blocked.

DeleteKey(byte)

Deletes/clears any key at a given PivSlot.

public void DeleteKey(byte slotToClear)

Parameters

slotToClear byte

The Yubikey slot of the key you want to clear. This must be a valid slot number.

Remarks

Internally this method attempts to authenticate to the Yubikey by calling AuthenticateManagementKey(bool) which may in turn throw its' own exceptions.

Exceptions

InvalidOperationException

Either the call to the Yubikey was unsuccessful or there wasn't any KeyCollector loaded, the key provided was not a valid Triple-DES key, or the YubiKey had some other error, such as unreliable connection. Refer to the specific exception message.

MalformedYubiKeyResponseException

The YubiKey returned malformed data and authentication, either single or double, could not be performed.

OperationCanceledException

The user canceled management key collection.

SecurityException

Mutual authentication was performed and the YubiKey was not authenticated.

NotSupportedException

Thrown when the Yubikey doesn't support the Delete-operation.

See Also

DeleteMsroots()

Delete any contents stored in the MSROOTS data objects.

public void DeleteMsroots()

Remarks

In order to perform this operation, the management key must be authenticated during this session. If it has not been authenticated, this method will call AuthenticateManagementKey(bool). That is, your application does not need to authenticate the management key separately (i.e., call TryAuthenticateManagementKey or AuthenticateManagementKey), this method will determine if the management key has been authenticated or not, and if not, it will make the call to perform mutual authentication.

The authentication method will collect the management key using the KeyCollector delegate. If no such delegate has been set, it will throw an exception.

The KeyCollector has an option to cancel the operation. That is, the AuthenticateManagementKey method will call the KeyCollector requesting the management key, and it is possible that during the collection operations, the user cancels. The KeyCollector will return to the authentication method noting the cancellation. In that case, it will throw an exception. If you want the authentication to return false on user cancellation, you must call TryAuthenticateManagementKey(bool) directly before calling this method.

Exceptions

InvalidOperationException

There is no KeyCollector loaded, the key provided was not a valid Triple-DES key, or the YubiKey had some other error, such as unreliable connection.

MalformedYubiKeyResponseException

The YubiKey returned malformed data and authentication, either single or double, could not be performed.

OperationCanceledException

The user canceled management key collection.

SecurityException

Mutual authentication was performed and the YubiKey was not authenticated.

Dispose(bool)

protected override void Dispose(bool disposing)

Parameters

disposing bool

GenerateKeyPair(byte, KeyType, PivPinPolicy, PivTouchPolicy)

Generate a new key pair in the given slot.

public IPublicKey GenerateKeyPair(byte slotNumber, KeyType keyType, PivPinPolicy pinPolicy = PivPinPolicy.Default, PivTouchPolicy touchPolicy = PivTouchPolicy.Default)

Parameters

slotNumber byte

The slot into which the key pair will be generated.

keyType KeyType

The type of the key to generate.

pinPolicy PivPinPolicy

The PIN policy the key will have. If no argument is given, the policy will be Default.

touchPolicy PivTouchPolicy

The touch policy the key will have. If no argument is given, the policy will be Default.

Returns

IPublicKey

The public key partner to the private key generated on the YubiKey.

Remarks

When you generate a key pair, you specify which slot will hold this new key. If there is a key in that slot already, this method will replace it. That old key will be gone and there will be nothing you can do to recover it. Hence, use this method with caution.

You also have the opportunity to specify the PIN and touch policies of the private key generated. These policies describe what will be required when using the key. For example, if the PIN policy is Always, then every time the key is used (to sign, decrypt, or perform key agreement), it will be necessary to verify the PIV PIN. With the touch policy, for instance, setting it to Always will require touch every time the key is used. This method has the policies as optional arguments. If you do not specify these arguments, the key pair will be generated with the policies set to Default. Currently for all YubiKeys, the default PIN policy is Once, and the default touch policy is Never.

This method will return the public key partner to the private key generated in the slot. For YubiKeys before version 5.3, it is the only time you will have the opportunity to obtain the public key, so make sure your application manages it right from the start. Beginning with version 5.3, it is possible to get a public key out of a slot at any time.

Note that while this method will return the public key, you will still need to obtain a certificate for the private key outside of this SDK. Once you have the certificate, you can load it into the YubiKey using the ImportCertificate(byte, X509Certificate2, bool) method.

In order to perform this operation, the management key must be authenticated during this session. If it has not been authenticated, this method will call AuthenticateManagementKey(bool). That is, your application does not need to authenticate the management key separately (i.e., call TryAuthenticateManagementKey or AuthenticateManagementKey), this method will determine if the management key has been authenticated or not, and if not, it will make the call to perform mutual authentication.

The authentication method will collect the management key using the KeyCollector delegate. If no such delegate has been set, it will throw an exception.

The KeyCollector has an option to cancel the operation. That is, the AuthenticateManagementKey method will call the KeyCollector requesting the management key, and it is possible that during the collection operations, the user cancels. The KeyCollector will return to the authentication method noting the cancellation. In that case, it will throw an exception. If you want the authentication to return false on user cancellation, you must call TryAuthenticateManagementKey(bool) directly before calling this method.

Exceptions

ArgumentException

The slot or algorithm specified is not valid for generating a key pair.

InvalidOperationException

There is no KeyCollector loaded, the key provided was not a valid Triple-DES key, or the YubiKey had some other error, such as unreliable connection.

OperationCanceledException

The user canceled management key collection.

SecurityException

Mutual authentication was performed and the YubiKey was not authenticated.

NotSupportedException

If the specified PivAlgorithm is not supported by the provided IYubiKeyDevice.

GetAttestationCertificate()

Get the attestation certificate.

public X509Certificate2 GetAttestationCertificate()

Returns

X509Certificate2

The attestation cert.

Remarks

Note that attestation is a feature available on YubiKeys version 4.3 and later.

The private key in slot F9 (PivSlot.Attestation) is the key used to sign the attestation statement (see CreateAttestationStatement(byte)). To verify the attestation statement, one needs the certificate of the key that signed it. The certificate returned by this method is that certificate.

  Root Cert
      |
  [CA Cert] (there may or may not be a CA cert between
      |      the root and Attestation Cert)
      |
 Attestation Cert (returned by this method)
      |
Attestation Statement (returned by CreateAttestationStatement)

The YubiKey is manufactured with an attestation key and cert that chain to the Yubico root cert. The User's Manual entry on PIV attestation has more information on chaining attestation statements and certs.

It is possible to replace the attestation key and cert. In that case, the attestation statement created by this method will chain up to a different root. See ReplaceAttestationKeyAndCertificate(IPrivateKey, X509Certificate2).

Exceptions

InvalidOperationException

The YubiKey is pre-4.3, or there is no attestation certificate, or it could not complete the task for some reason such as unreliable connection.

TlvException

If the attestation certificate was replaced by data that is not a certificate.

GetBioMetadata()

Get information about YubiKey Bio multi-protocol.

public PivBioMetadata GetBioMetadata()

Returns

PivBioMetadata

A new instance of a PivBioMetadata object.

Remarks

This feature is available only on YubiKey Bio multi-protocol keys (FW 5.6 and later). If you call this method on an incompatible YubiKey, it will throw a NotSupportedException.

IEnumerable<IYubiKeyDevice> list = YubiKey.FindByTransport(Transport.UsbSmartCard);
IYubiKeyDevice yubiKey = list.First();
using (var pivSession = new PivSession(yubiKey))
{
    try
    {
        var bioMetaData = PivSession.GetBioMetadata();
        /* use bioMetaData */
    }
    catch (NotSupportedException e) {
        /* this device does not support Bio multi-protocol metadata */
    }
}

See the User's Manual entry on getting bio metadata for specifics about what information is returned.

Exceptions

NotSupportedException

The queried YubiKey does not support bio metadata.

ApduException

The operation could not be completed.

GetCertificate(byte)

Get the certificate in the given slot.

public X509Certificate2 GetCertificate(byte slotNumber)

Parameters

slotNumber byte

The slot containing the requested cert.

Returns

X509Certificate2

The cert residing in the slot specified.

Remarks

After obtaining a cert, you can install it into the slot containing the associated private key (ImportCertificate(byte, X509Certificate2, bool)). Later on, when you need the cert (e.g. to send it along with a signed message), call this method to retrieve it.

It is not necessary to authenticate the management key nor verify the PIN in order to obtain a certificate.

If the slotNumber given is for a slot that does not hold asymmetric keys, or if there is no cert in the slot, this method will throw an exception.

If you want to get the attestation cert, do not use this method, call GetAttestationCertificate(). If you call this method with slot number 0xF9 (PivSlot.Attestation) it will throw an exception.

Exceptions

ArgumentException

The slot specified is not valid for getting a certificate.

InvalidOperationException

The slot did not contain a cert, or the YubiKey had some other error, such as unreliable connection.

GetMetadata(byte)

Get information about the specified slot.

public PivMetadata GetMetadata(byte slotNumber)

Parameters

slotNumber byte

The slot for which the information is requested.

Returns

PivMetadata

A new instance of a PivMetadata object containing information about the given slot.

Remarks

This feature is available only on YubiKeys 5.3 and later. If you call this method on an earlier YubiKey, it will throw an exception. A good idea is to verify that the version number is valid before calling.

IEnumerable<IYubiKeyDevice> list = YubiKey.FindByTransport(Transport.UsbSmartCard);
IYubiKeyDevice yubiKey = list.First();

using (var pivSession = new PivSession(yubiKey))
{
    if (yubiKey.FirmwareVersion >= new FirmwareVersion(5, 3, 0))
    {
        PivMetadata metadataSlot9A =
            pivSession.GetMetadata(PivSlot.Authentication);
    }
}

See the User's Manual entry on getting metadata for specific information about what information is returned. Different slots return different sets of data. That page also lists the valid slots for which metadata is available.

Exceptions

ArgumentException

The slot specified is not valid for getting metadata.

InvalidOperationException

The YubiKey queried does not support metadata, or the operation could not be completed because of some error such as unreliable connection.

GetPinOnlyMode()

Return an enum indicating the PIN-only mode, if any, for which the YubiKey PIV application is configured.

public PivPinOnlyMode GetPinOnlyMode()

Returns

PivPinOnlyMode

A PivPinOnlyMode, which is an enum indicating the mode or modes.

Remarks

PIN-only mode means that the application does not need to enter the management key in order to perform PIV operations that normally require it, only the PIN is needed.

See the User's Manual entry on PIV PIN-only mode for a deeper discussion of this feature.

This returns a result based on the contents of ADMIN DATA. That storage location contains information about PIN-protected and PIN-derived. It is possible for a different application to overwrite the data to make it inaccurate. That is unlikely, however, if all applications follow good programming practices outlined by the SDK documentation. This method will not actually verify the management key in order to ensure the return value is correct.

If the ADMIN DATA is overwritten, it is possible to call TryRecoverPinOnlyMode() to restore the YubiKey to a proper PIN-only state.

Note also that it is possible that the ADMIN DATA says the YubiKey is PIN-protected, but some app has overwritten the data in PRINTED. In that case, this method will return a result indicating PinProtected, when in reality PIN-protected is unavailable. That is because this returns a value based only on the contents of ADMIN DATA. The method TryRecoverPinOnlyMode will check more than ADMIN DATA.

Note that the return is a bit field and the return can be one or more of the bits set. There are bits that indicate a YubiKey is unavailable for PIN-protected or PIN-derived. Call this method before trying to set a YubiKey to PIN-only to make sure it is not already set, and if not, it can be set.

Note that this returns the PIN-only mode for the PIV application on the YubiKey, it has nothing to do with OATH, FIDO, or OpenPGP.

Exceptions

InvalidOperationException

The YubiKey is not able to return the ADMIN DATA.

ImportCertificate(byte, X509Certificate2, bool)

Import a certificate into the given slot.

public void ImportCertificate(byte slotNumber, X509Certificate2 certificate, bool compress = false)

Parameters

slotNumber byte

The slot into which the key will be imported.

certificate X509Certificate2

The certificate to import into the YubiKey.

compress bool

If true the certificate will be compressed before being stored on the YubiKey.

Remarks

When you import a certificate, you specify which slot will hold this cert. If there is a cert in that slot already, this method will replace it.

The PIV standard specifies that the maximum length of a cert is 1,856 bytes. The YubiKey allows for certs up to 3,052 bytes. However, if you want your application to be PIV-compliant, then use certs no longer than 1,856 bytes.

This method will not verify that the cert matches the private key in the slot. It will simply store the cert given in the slot specified.

In order to perform this operation, the management key must be authenticated during this session. If it has not been authenticated, this method will call AuthenticateManagementKey(bool). That is, your application does not need to authenticate the management key separately (i.e., call TryAuthenticateManagementKey or AuthenticateManagementKey), this method will determine if the management key has been authenticated or not, and if not, it will make the call to perform mutual authentication.

The authentication method will collect the management key using the KeyCollector delegate. If no such delegate has been set, it will throw an exception.

The KeyCollector has an option to cancel the operation. That is, the AuthenticateManagementKey method will call the KeyCollector requesting the management key, and it is possible that during the collection operations, the user cancels. The KeyCollector will return to the authentication method noting the cancellation. In that case, it will throw an exception. If you want the authentication to return false on user cancellation, you must call TryAuthenticateManagementKey(bool) directly before calling this method.

Exceptions

ArgumentNullException

The certificate argument is null.

ArgumentException

The slot specified is not valid for importing a certificate.

InvalidOperationException

There is no KeyCollector loaded, the key provided was not a valid Triple-DES key, or the YubiKey had some other error, such as unreliable connection.

OperationCanceledException

The user canceled management key collection.

SecurityException

Mutual authentication was performed and the YubiKey was not authenticated.

ImportPrivateKey(byte, IPrivateKey, PivPinPolicy, PivTouchPolicy)

Import a private key into the given slot.

public void ImportPrivateKey(byte slotNumber, IPrivateKey privateKey, PivPinPolicy pinPolicy = PivPinPolicy.Default, PivTouchPolicy touchPolicy = PivTouchPolicy.Default)

Parameters

slotNumber byte

The slot into which the key will be imported.

privateKey IPrivateKey

The private key parameters and values to import into the YubiKey.

pinPolicy PivPinPolicy

The PIN policy the key will have. If no argument is given, the policy will be Default.

touchPolicy PivTouchPolicy

The touch policy the key will have. If no argument is given, the policy will be Default.

Remarks

When you import a key, you specify which slot will hold this key. If there is a key in that slot already, this method will replace it. That old key will be gone and there will be nothing you can do to recover it. Hence, use this method with caution.

This method will not return to you the public key partner to the private key imported into the slot. For YubiKeys before version 5.3, you will not have the opportunity to obtain the public key, so make sure your application manages it right from the start. Beginning with version 5.3, it is possible to get a public key out of a slot at any time.

You also have the opportunity to specify the PIN and touch policies of the private key generated. These policies describe what will be required when using the key. For example, if the PIN policy is Always, then every time the key is used (to sign, decrypt, or perform key agreement), it will be necessary to verify the PIV PIN. With the touch policy, for instance, setting it to Always will require touch every time the key is used. This method has the policies as optional arguments. If you do not specify these arguments, the key pair will be generated with the policies set to Default. Currently for all YubiKeys, the default PIN policy is Once, and the default touch policy is Never.

In order to perform this operation, the management key must be authenticated during this session. If it has not been authenticated, this method will call AuthenticateManagementKey(bool). That is, your application does not need to authenticate the management key separately (i.e., call TryAuthenticateManagementKey or AuthenticateManagementKey), this method will determine if the management key has been authenticated or not, and if not, it will make the call to perform mutual authentication.

The authentication method will collect the management key using the KeyCollector delegate. If no such delegate has been set, it will throw an exception.

The KeyCollector has an option to cancel the operation. That is, the AuthenticateManagementKey method will call the KeyCollector requesting the management key, and it is possible that during the collection operations, the user cancels. The KeyCollector will return to the authentication method noting the cancellation. In that case, it will throw an exception. If you want the authentication to return false on user cancellation, you must call TryAuthenticateManagementKey(bool) directly before calling this method.

Exceptions

ArgumentNullException

The privateKey argument is null.

ArgumentException

The slot specified is not valid for generating a key pair, or the privateKey object is empty.

InvalidOperationException

There is no KeyCollector loaded, the key provided was not a valid Triple-DES key, or the YubiKey had some other error, such as unreliable connection.

OperationCanceledException

The user canceled management key collection.

SecurityException

Mutual authentication was performed and the YubiKey was not authenticated.

NotSupportedException

If the specified PivAlgorithm is not supported by the provided IYubiKeyDevice.

KeyAgree(byte, IPublicKey)

Perform Phase 2 of EC Diffie-Hellman Key Agreement using the private key in the given slot, and the corresponding party's public key.

public byte[] KeyAgree(byte slotNumber, IPublicKey correspondentPublicKey)

Parameters

slotNumber byte

The slot containing the key to use.

correspondentPublicKey IPublicKey

The correspondent's public key.

Returns

byte[]

The resulting shared secret data.

Remarks

The YubiKey supports key agreement only with ECC keys.

This method returns the raw shared secret data, if it can perform the key agreement operation. It will not perform any derivation operations. The result will be the same size as the key. That is, for a 256-bit ECC key, the shared secret is 32 bytes, and for a 384-bit key, the shared secret is 48 bytes.

The data returned is not formatted, nor encoded, it is simply a byte array. It happens to be the x coordinate of an ECC point that is the result of an EC scalar multiplication operation.

Key Agreement might require the PIN and/or touch, depending on the PIN and touch policies specified at the time the key was generated or imported.

If a PIN is required, this method will call the necessary routines to verify the PIN. See VerifyPin() for more information on PIN verification. If the user cancels, this method will throw an exception.

If touch is required, the YubiKey itself will flash its touch signal and wait. If the YubiKey is not touched before the touch timeout, the YubiKey will return with an error, and this method will throw an exception (OperationCanceledException). Note that this method will not make another effort to perform key agreement if the YubiKey is not touched, it will simply throw the exception.

Note that on YubiKeys prior to version 5.3, it is not possible to know programmatically what the PIN or touch policies are without actually trying to perform key agreement. Also, it is not possible to know programmatically if an authentication failure is due to PIN or touch. This means that on older YubiKeys, this method will try to perform the key agreement operation without the PIN, and if it does not work because of authentication failure, it will not know if the failure was due to PIN or touch. Hence, it will try to verify the PIN then try to perform the key agreement operation again. This all means that on older YubiKeys, it is possible a YubiKey slot was originally configured with a PIN policy of "never" and a touch policy of "always", and this method will call for the PIN anyway. This happens if the user does not touch the YubiKey before the timeout. See the User's Manual entry on keeping track of slot contents.

Exceptions

ArgumentNullException

The correspondentPublicKey argument is null.

ArgumentException

The slot number given was not valid, or the public key was invalid (e.g. empty, wrong algorithm).

InvalidOperationException

There was no key in the slot specified or the public key did not match the private key (e.g. the public key was for ECC P256 but the private key in the given slot was ECC P384).

OperationCanceledException

Either the PIN was required and the user canceled collection or touch was required and the user did not touch within the timeout period.

SecurityException

The remaining retries count indicates the PIN is blocked.

MoveKey(byte, byte)

Moves a key from one slot to another. The source slot must not be the Attestation-slot and the destination slot must be empty. Any key except the attestation key can be moved from one slot to another.

public void MoveKey(byte sourceSlot, byte destinationSlot)

Parameters

sourceSlot byte

The Yubikey slot of the key you want to move. This must be a valid slot number.

destinationSlot byte

The target Yubikey slot for the key you want to move. This must be a valid slot number.

Remarks

Internally this method attempts to authenticate to the Yubikey by calling AuthenticateManagementKey(bool) which may in turn throw its' own exceptions.

Exceptions

InvalidOperationException

There is no KeyCollector loaded, the key provided was not a valid key, the slot contained an attestation key, the or the YubiKey had some other error, such as unreliable connection.

MalformedYubiKeyResponseException

The YubiKey returned malformed data and authentication, either single or double, could not be performed.

OperationCanceledException

The user canceled management key collection.

SecurityException

Mutual authentication was performed and the YubiKey was not authenticated.

NotSupportedException

Thrown when the Yubikey doesn't support the Move-operation.

ReadMsroots()

Returns the contents of the MSROOTS data objects.

public byte[] ReadMsroots()

Returns

byte[]

A new byte array containing the data stored in the MSROOTS data objects.

Remarks

The YubiKey PIV application can store data objects. There is a set of data elements defined by the PIV standard. See the User's Manual entry on GET DATA for information on these elements and their tags. The standard also allows for vendor-defined data objects. MSROOTS is one such vendor-defined element.

The intention of the MSROOTS data object is to store and retrieve a PKCS 7 construction containing a set of root certificates. These certificates will make it easier for the SDK to interface with the Microsoft Smart Card Base Crypto Service Provider (CSP).

Very few applications will need to use this feature. If you don't already know what the MSROOTS are, how to use them, and that they are part of your application already, then you almost certainly will never need to use this method.

This method will return whatever data is stored in the YubiKey under the tag "MSROOTS". This method will not verify that the data is a PKCS 7 construction, or that it contains root certificates, it will simply return the bytes from the data object.

While it is necessary to authenticate the management key in order to store the MSROOTS data (see WriteMsroots(ReadOnlySpan<byte>)), it is not needed to retrieve this data. Anyone with access to a YubiKey can retrieve this data.

The method will return the data as a new byte array. It is possible there is no data on the YubiKey in the MSROOTS data objects. In that case, this method will return an empty byte array (Length of 0).

Note that YubiKey stores the data formatted as a TLV:

tag || length || value

for example, it might be

53 20 (contents, 32 bytes)

or

7F 61 20 (contents, 32 bytes)

The tag used varies depending on the data being stored. This method returns the contents, not the full TLV.

Note that the full amount of data might be stored in more than one data object. This method will collect all the data in all the MSROOTS data objects (in order) and concatenate.

Exceptions

InvalidOperationException

The YubiKey encountered an error, such as an unreliable connection.

ReadMsrootsStream()

Returns the contents of the MSROOTS data objects as a Stream.

public Stream ReadMsrootsStream()

Returns

Stream

A new Stream which will be readable and will contain the MSROOTS contents.

Remarks

This is the same as the ReadMsroots() method that returns a byte array, except this method returns a Stream.

Exceptions

InvalidOperationException

The YubiKey encountered an error, such as an unreliable connection.

ReadObject<T>()

Read the data at the storage location specified by the defined data tag for the PivDataObject T, storing and returning this data in a new object of type T.

public T ReadObject<T>() where T : PivDataObject, new()

Returns

T

A new object of the type T. It contains the data stored on the YubiKey under the object's defined data tag. If there is no data stored, the returned object's IsEmpty property will be true.

Type Parameters

T

The type of PivDataObject to create, set, and return.

Remarks

For example,

using CardholderUniqueId chuid = pivSession.ReadObject<CardholderUniqueId>();

See also the user's manual entry on PIV data objects.

It is possible that there is no data on the YubiKey in the specified storage location. If so, this method will return a new object with the IsEmpty property set to true.

If there is data stored under the specified data tag, this method will expect it to be formatted as defined by the class T. If it is not formatted as expected, this method will throw an exception.

Note that there is a method that can read using an alternate tag. This method will use the defined tag for the given class.

Exceptions

ArgumentException

The data is not properly encoded for the data object.

ReadObject<T>(int)

Read the data at the storage location specified by the given dataTag, storing and returning this data in a new object of type T.

public T ReadObject<T>(int dataTag) where T : PivDataObject, new()

Parameters

dataTag int

The alternate data tag, the tag of the storage location to look.

Returns

T

A new object of the type T. It contains the data stored on the YubiKey under the object's defined data tag. If there is no data stored, the returned object's IsEmpty property will be true.

Type Parameters

T

The type of PivDataObject to create, set, and return.

Remarks

For example,

using CardholderUniqueId chuid = pivSession.ReadObject<CardholderUniqueId>(0x005FFF55);

See also the user's manual entry on PIV data objects.

This is the same as the ReadObject<T>() method that takes no arguments, except this one will get the data in the storage location specified by dataTag, as opposed to the defined data tag for the class T. This method will still expect the data to be formatted as defined in the class T, it's just that the data is stored under a different tag.

This method is used when you have stored data under an alternate tag. It is likely you will never need this feature, and it is dangerous, because if done incorrectly, sensitive data that should require PIN verification to access will be available without a PIN). But there are rare cases when this feature is useful.

Exceptions

ArgumentException

The dataTag in not allowed to be an alternate tag, or the data from the YubiKey is not properly encoded for the data object.

ReplaceAttestationKeyAndCertificate(IPrivateKey, X509Certificate2)

Replace the attestation key and certificate.

public void ReplaceAttestationKeyAndCertificate(IPrivateKey privateKey, X509Certificate2 certificate)

Parameters

privateKey IPrivateKey

The private key that will be the new attestation key.

certificate X509Certificate2

The cert that will be the new attestation cert.

Remarks

See the User's Manual entry on PIV attestation for more information on attestation statements and replacing them.

Note that attestation is a feature available on YubiKeys version 4.3 and later.

The YubiKey is manufactured with an attestation key and cert. This is the key that is used to sign the attestation statement, and the cert that verifies the attestation key.

This key was generated by Yubico, and the cert chains to a Yubico root. They are shared by many YubiKeys. If you want to replace them with your own, call this method.

Note that if you replace the Yubico key and cert, there is no way to recover them, they will be gone for good. So use this method with caution.

Note also that this is an operation that very few users will want to do. There are some companies who want to make sure the cert that is the attestation statement chains to one of their roots, instead of a Yubico root. For those companies, this feature is available. However, this is not common. If you are wondering if you want to replace the attestation key and cert, you almost certainly do not. If this is not already a requirement in your application, it almost certainly is not something you will be doing.

There are limitations placed on the key and cert. The key must be either RSA-2048, RSA-3072, RSA-4096, ECC-P256, or ECC-P384. The cert must be X.509, it must be version 2 or 3, the full DER encoding of the SubjectName must be fewer than 1029 bytes, and the total length of the certificate must be fewer than 3052 bytes. This method will verify that these restrictions are met.

YubiKeys before version 5 allowed 1024-bit RSA keys as the attestation key. However, this method, regardless of the YubiKey version, will not accept 1024-bit RSA keys.

This method will NOT, however, 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, see the User's Manual entry on PIV attestation for a discussion on verifying compatibility.

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.

The method will not verify the cert itself, nor will it verify the validity dates inside the cert.

In order to perform this operation, the management key must be authenticated during this session. If it has not been authenticated, this method will call AuthenticateManagementKey(bool). That is, your application does not need to authenticate the management key separately (i.e., call TryAuthenticateManagementKey or AuthenticateManagementKey), this method will determine if the management key has been authenticated or not, and if not, it will make the call to perform mutual authentication.

The authentication method will collect the management key using the KeyCollector delegate. If no such delegate has been set, it will throw an exception.

The KeyCollector has an option to cancel the operation. That is, the AuthenticateManagementKey method will call the KeyCollector requesting the management key, and it is possible that during the collection operations, the user cancels. The KeyCollector will return to the authentication method noting the cancellation. In that case, it will throw an exception. If you want the authentication to return false on user cancellation, you must call TryAuthenticateManagementKey(bool) directly before calling this method.

Exceptions

ArgumentNullException

One of the inputs is null.

ArgumentException

One of the inputs is not allowed (e.g. private key is 1024-bit RSA).

InvalidOperationException

There is no KeyCollector loaded, the key provided was not a valid Triple-DES key, or the YubiKey had some other error, such as unreliable connection.

MalformedYubiKeyResponseException

The YubiKey returned malformed data and authentication, either single or double, could not be performed.

OperationCanceledException

The user canceled management key collection.

SecurityException

Mutual authentication was performed and the YubiKey was not authenticated.

ResetApplication()

Reset the PIV application to the default state.

public void ResetApplication()

Remarks

This will delete all keys and certs in all the asymmetric key slots other than F9, delete any added information to the data elements and set the PIN, PUK, and management key to their default values. That is, this will set the PIV application's state to what it was upon manufacture. See the User's Manual entries on the PIV PIN, PUK, and management key and data elements for more information on the defaults and data added to elements.

Note that this has no effect on the other YubiKey applications. This does NOT reset OTP, OATH, OpenPgp Card, FIDO U2F, or FIDO2.

Users will generally want to reset only if both the PIN and PUK are blocked. If a PIN has been blocked, it can only be restored using the PUK, but if the PUK is also blocked, there is no way to recover the PIN. Once there is no PIN, and no way to recover it, there is very little useful work the PIV application on a YubiKey can do. Resetting the application does not make the situation worse, but it does improve things somewhat, because the PIV application is usable again, just with new key pairs.

However, it is important to note that this method will reset the PIV application even if the PIN and/or PUK are not blocked. The YubiKey will not allow itself to be reset until both the PIN and PUK are blocked. This method will take steps necessary to block the PIN and PUK, then call on the YubiKey to reset.

This method does not work with YubiKey Bio Multi-protocol Edition (MPE) keys. For MPE keys, use DeviceReset() instead.

Exceptions

SecurityException

The application could not be reset because of some error such as unreliable connection.

ResetPin()

Reset the PIN, using the PUK (PIN Unblocking Key), throw an exception if the user cancels.

public void ResetPin()

Remarks

This is the same as TryResetPin, except this method will throw an exception if the KeyCollector indicates user cancellation.

See the TryResetPin() method for further documentation on this method.

If the PUK is blocked, this method will not execute. If a YubiKey is configured PIN-only, the PUK will be blocked.

Note: YubiKey Bio Multi-protocol Edition (MPE) keys do not have a PUK.

Exceptions

InvalidOperationException

There is no KeyCollector loaded, or the YubiKey had some other error, such as unreliable connection.

OperationCanceledException

The user canceled PUK and PIN collection.

SecurityException

The remaining retries count indicates the PUK is blocked.

SetPinOnlyMode(PivPinOnlyMode)

Set the YubiKey's PIV application to be PIN-only with a PIN-derived and/or PIN-Protected management key. The default management key algorithm will be used (AES-192 for YubiKeys with firmware 5.7.x and later, TDES for keys with firmware 5.6.x and earlier). This sets the YubiKey to either

PivPinOnlyMode.PinProtected
PivPinOnlyMode.PinDerived
PivPinOnlyMode.PinProtected | PivPinOnlyMode.PinDerived
PivPinOnlyMode.None

If the YubiKey is set to PinProtected, PinDerived, or both, the PUK will also be blocked.

Warning

You should not set a YubiKey for PIN-derived, this feature is provided only for backwards compatibility.

public void SetPinOnlyMode(PivPinOnlyMode pinOnlyMode)

Parameters

pinOnlyMode PivPinOnlyMode

The mode to which the YubiKey is to be set.

Remarks

PIN-only mode means that the application does not need to enter the management key in order to perform PIV operations that normally require it, only the PIN is needed.

See the documentation for SetPinOnlyMode(PivPinOnlyMode, PivAlgorithm) and the User's Manual entry on PIV PIN-only mode for a deeper discussion of this feature.

Note that this sets the PIV application on the specific YubiKey to a PIN-only mode, it has nothing to do with OATH, FIDO, or OpenPGP.

Note also that this will make sure that the management key algorithm will be default management key algorithm (Firmware 5.7.x and later: AES-192. Firmware 5.6.x and earlier: TDES.), even if the current management key is a different algorithm. This behavior matches how this method operated in previous versions of the SDK.

Exceptions

InvalidOperationException

There is no KeyCollector loaded, one of the keys provided was not of a valid key algorithm type (Firmware 5.7.x and later: AES-192. Firmware 5.6.x and earlier: TDES.), the data stored on the YubiKey is incompatible with PIN-only, or the YubiKey had some other error, such as unreliable connection.

OperationCanceledException

The user canceled management key or PIN collection.

SecurityException

Mutual authentication was performed and the YubiKey was not authenticated, or the remaining retries count indicates the PIN is blocked.

SetPinOnlyMode(PivPinOnlyMode, PivAlgorithm)

Set the YubiKey's PIV application to be PIN-only with a PIN-derived and/or PIN-Protected management key of the specified algorithm. This sets the YubiKey to either

PivPinOnlyMode.PinProtected
PivPinOnlyMode.PinDerived
PivPinOnlyMode.PinProtected | PivPinOnlyMode.PinDerived
PivPinOnlyMode.None

If the YubiKey is set to PinProtected, PinDerived, or both, the PUK will also be blocked.

Warning

You should not set a YubiKey for PIN-derived, this feature is provided only for backwards compatibility.

public void SetPinOnlyMode(PivPinOnlyMode pinOnlyMode, PivAlgorithm mgmtKeyAlgorithm)

Parameters

pinOnlyMode PivPinOnlyMode

The mode to which the YubiKey is to be set.

mgmtKeyAlgorithm PivAlgorithm

The algorithm to which the management key will be set.

Remarks

PIN-only mode means that the application does not need to enter the management key in order to perform PIV operations that normally require it, only the PIN is needed.

See the User's Manual entry on PIV PIN-only mode for a deeper discussion of this feature.

Note that this sets the PIV application on the specific YubiKey to a PIN-only mode, it has nothing to do with OATH, FIDO, or OpenPGP.

Upon successful completion of this method, the PUK will be blocked.

The management key derived and/or stored in PRINTED will be for the specified algorithm. For all YubiKeys, TripleDes is a valid algorithm. For YubiKeys 5.4.2 and later, it is possible to set the management key to an AES key. For YubiKeys 5.7 and later, AES192 is the default. Before setting the mgmtKeyAlgorithm arg to an AES algorithm, make sure it is allowed on the YubiKey. You can use the HasFeature call. For example,

PivAlgorithm mgmtKeyAlgorithm = yubiKey.HasFeature(YubiKeyFeature.PivAesManagementKey) ?
        PivAlgorithm.Aes192 : PivAlgorithm.TripleDes;
    pivSession.SetPinOnlyMode(PivPinOnlyMode.PinProtected, mgmtKeyAlgorithm);
If the algorithm is not supported by the YubiKey, this method will throw an exception. It will not change the YubiKey, it will not set it to PIN-only.

If the YubiKey is already set to the specified PIN-protected mode and algorithm, this will not reset the YubiKey, but will simply authenticate the management key.

If the YubiKey is already set to PIN-only, but not the specified mode, this method will make sure the YubiKey is set to both PIN-only modes.

If the YubiKey is already set to PIN-only, but not the specified algorithm, this method will change to a new management key of the specified algorithm.

If the requested pinOnlyMode is both, then this will make sure the YubiKey is both PIN-protected and PIN-derived.

If the input pinOnlyMode is None, and the YubiKey is currently set to PIN-only (and neither PinProtected nor PinDerived is Unavailable), this method will remove the contents of the storage locations ADMIN DATA and PRINTED, and reset the management key to the default management key. In this case, the mgmtKeyAlgorithm arg will be ignored, the management key's algorithm after removing PIN-only status will be the default management key algorithm (Firmware 5.7.x and later: AES-192. Firmware 5.6.x and earlier: TDES.). The touch policy of the management key will also be set to the default (Never). Note that the management key must be authenticated and the PIN verified in order to perform this task. This method will authenticate the management key using the PIN-only mode to which the YubiKey is currently set, then clear the contents. It will then change the management key to the default value. Hence, after setting the YubiKey out of PIN-only mode, you should change the management key. Note also that the PUK will still be blocked. The only way to unblock the PUK is to reset the retry counts. This will set both the PIN and PUK to their default values. Resetting the retry counts requires management key authentication.

If the input pinOnlyMode is None, and the YubiKey is currently set to one PIN-only mode, but the other is Unavailable, this method will clear the one that is set but leave the one that is Unavailable as is. For example, suppose the current mode is PinProtected | PinDerivedUnavailable, then after setting to None, the PRINTED storage area will be empty and the ADMIN DATA storage area will be left as is.

If the input pinOnlyMode is None, and the YubiKey is currently NOT set to either PIN-only modes, this method will do nothing. It will not remove anything from ADMIN DATA or PRINTED, it will not try to authenticate the management key, nor will it try to verify the PIN. It will not change the management to the default. It will ignore the mgmtKeyAlgorithm argument.

If a YubiKey is currently set to both modes, and you call this method with only one of the modes, this method will NOT "remove" the other mode.

If a YubiKey is currently set to both PIN-only modes and you want to "remove" one of them, call this method and set the YubiKey to None, then call this method a second time and set the YubiKey to the desired mode.

In order to set the YubiKey to be PIN-only, this method must authenticate the management key. Even if the management key is already authenticated, this method will authenticate. It will try to authenticate using the PIN-only techniques, and if that does not work, it will try to authenticate using the default management key. If either of those techniques works, the user will not have to enter the management key. But if the YubiKey is not PIN-only, and the default management key does not authenticate, the method will call on the KeyCollector to obtain the correct value.

If the mode to set is PIN-protected, then this method will use the existing mgmt key, unless it is the default. In that case, this method will generate a new, random mgmt key, set the YubiKey with this new value, and PIN-protect the new key.

This method also requires the PIN to be verified. If setting to PIN-derived, even if the PIN is already verified, this method will call on the KeyCollector to obtain the PIN. If setting to PIN-protected, this method will verify the PIN only if it has not yet been verified.

Note that this method will throw an exception if the current contents of ADMIN DATA and/or PRINTED are not compatible with PIN-only mode. If there are no current contents, then this method will set one or both of those storage locations with appropriate data. But if there is already something in one or both, and it is not PIN-only information, then this method will not replace that data, it will throw an exception.

Exceptions

InvalidOperationException

There is no KeyCollector loaded, one of the keys provided was not of a valid key algorithm type, the data stored on the YubiKey is incompatible with PIN-only, or the YubiKey had some other error, such as unreliable connection.

OperationCanceledException

The user canceled management key or PIN collection.

SecurityException

Mutual authentication was performed and the YubiKey was not authenticated, or the remaining retries count indicates the PIN is blocked.

Sign(byte, ReadOnlyMemory<byte>)

Create a digital signature using the key in the given slot.

public byte[] Sign(byte slotNumber, ReadOnlyMemory<byte> dataToSign)

Parameters

slotNumber byte

The slot containing the key to use.

dataToSign ReadOnlyMemory<byte>

The formatted message digest.

Returns

byte[]

The resulting signature.

Remarks

The caller supplies the data to sign in the form of a formatted message digest.

This method returns the digital signature created, if it can build one. Otherwise it will throw an exception.

If the slot specified is not one that can sign, or it does not contain a key, this method will throw an exception. If the input data is not the correct length, the method will throw an exception.

If the key is ECC P-256, then the formatted digest is simply the message digest itself, but it must be exactly 32 bytes. If the input is not exactly 32 bytes, the method will throw an exception. If the input data is shorter than 32 bytes, prepend pad bytes of 00 until the length is exactly 32 bytes. You will almost certainly want to use SHA-256 as the digest algorithm. The signature will be the BER encoding of

SEQUENCE {
  r   INTEGER,
  s   INTEGER }

If the key is ECC P-384, then the formatted digest is simply the message digest itself, but it must be exactly 48 bytes. If the input is not exactly 48 bytes, the method will throw an exception. If the input data is shorter than 48 bytes, prepend pad bytes of 00 until the length is exactly 48 bytes. You will almost certainly want to use SHA-384 as the digest algorithm. The signature will be the BER encoding of

SEQUENCE {
  r   INTEGER,
  s   INTEGER }

If the key is RSA 1024/2048/3072/4096, then the input must be exactly 128/256/384/512 bytes, otherwise the method will throw an exception. You can use the RsaFormat class to format the data. That class will be able to format the digest into either PKCS #1 v1.5 or a subset of PKCS #1 PSS. However, if that class does not support the exact format you want, you will have to write your own formatting code and guarantee the input to this method is exactly 128/256/384/512 bytes (prepend pad bytes of 00 until the length is exactly 128/256/384/512 if needed). The signature will be a 128/256/384/512-byte block.

Signing might require the PIN and/or touch, depending on the PIN and touch policies specified at the time the key was generated or imported.

If a PIN is required, this method will call the necessary routines to verify the PIN. See VerifyPin() for more information on PIN verification. If the user cancels, this method will throw an exception.

If touch is required, the YubiKey itself will flash its touch signal and wait. If the YubiKey is not touched before the touch timeout, the YubiKey will return with an error, and this method will throw an exception (OperationCanceledException). Note that this method will not make another effort to sign if the YubiKey is not touched, it will simply throw the exception.

Note that on YubiKeys prior to version 5.3, it is not possible to know programmatically what the PIN or touch policies are without actually trying to sign. Also, it is not possible to know programmatically if an authentication failure is due to PIN or touch. This means that on older YubiKeys, this method will try to sign without the PIN, and if it does not work because of authentication failure, it will not know if the failure was due to PIN or touch. Hence, it will try to verify the PIN then try to sign again. This all means that on older YubiKeys, it is possible a YubiKey slot was originally configured with a PIN policy of "never" and a touch policy of "always", and this method will call for the PIN anyway. This happens if the user does not touch the YubiKey before the timeout. See the User's Manual entry on keeping track of slot contents.

Exceptions

ArgumentException

The slot number given was not valid, or the data to sign was an invalid length.

InvalidOperationException

There was no key in the slot specified or the data did not match the key (e.g. the data to sign was 32 bytes long but the key was ECC P-384).

OperationCanceledException

Either the PIN was required and the user canceled collection or touch was required and the user did not touch within the timeout period.

SecurityException

The remaining retries count indicates the PIN is blocked.

NotSupportedException

If the specified PivAlgorithm is not supported by the provided IYubiKeyDevice.

TryAuthenticateManagementKey(bool)

Try to authenticate the management key.

public bool TryAuthenticateManagementKey(bool mutualAuthentication = true)

Parameters

mutualAuthentication bool

If true the method will perform mutual authentication, if false, only the application will authenticate to the YubiKey.

Returns

bool

A boolean, true if the management key authenticates, false if the user cancels.

Remarks

You need to authenticate the management key only once per session. But if you have already authenticated, and you call this method, it will perform the authentication again. If the authentication fails the second time, the previous auth will be nullified.

See the ManagementKeyAuthenticated property for the current state of management key authentication.

This method will determine if the YubiKey is set for PIN-only. If so, it will collect the management key using the PIN and authenticate. If not, it will use the KeyCollector to obtain the management key. The ADMIN DATA and PRINTED storage locations contain information about PIN-only (PIN-protected, PIN-derived, or both). If that information is inaccurate (some other application overwrote the data in one or both locations, PIN-only authentication might fail and this method will use the KeyCollector.

If the YubiKey is not set for PIN-only, this method will collect the management key using the KeyCollector delegate. If no such delegate has been set, this method will throw an exception.

Beginning with YubiKey 5.4.2, the management key can be AES as well as Triple-DES. When the SDK calls the KeyCollector delegate, it will not specify the expected algorithm or length of the management key. If you need to know which algorithm the management keys is, look at the property PivSession.ManagementKeyAlgorithm. Maybe your Key Collector is an object and you can let it know which algorithm the management key is so when the management key is requested, the user will know how many bytes to provide. For example,

KeyCollectorClass.ManagementKeyAlgorithm = pivSession.ManagementKeyAlgorithm;
pivSession.KeyCollector = KeyCollectorClass.KeyCollectorDelegate;

The KeyCollector has an option to cancel the operation. That is, this TryAuthenticateManagementKey method will call the KeyCollector requesting the management key, and it is possible that during the collection operations, the user cancels. The KeyCollector will return to this method noting the cancellation. In that case, this method will return false.

Note that this is the only way to get a false return. Any other error and this method will throw an exception. In other words, a false return from this method means the user canceled.

It is possible to perform single or mutual authentication. In single, only the "off-card" application authenticates itself to the YubiKey. In mutual authentication, both the off-card application and the YubiKey authenticate each other. If the bool argument mutualAuthentication is true, this method will perform mutual authentication. If false, it will perform single. The default is true, so if no argument is given, this method will perform mutual authentication.

This method will also set the ManagementKeyAuthenticated and ManagementKeyAuthenticationResult properties. The "Result" is an AuthenticateManagementKeyResult enum, listing the possible results. For example, if you call for mutual authentication and it fails, the property will be set to AuthenticateManagementKeyResult.MutualOffCardAuthenticationFailed or MutualYubiKeyAuthenticationFailed, depending on what went wrong.

If the management key authenticates, the method will return true. If not, and the KeyCollector cancels the process, the method will return false and set the ManagementKeyAuthenticationResult property to the failure reason.

If the call is for mutual authentication, and the off-card application authenticates but the YubiKey does not, this method will set the ManagementKeyAuthenticationResult property to MutualYubiKeyAuthenticationFailed and throw an exception. This can happen when the there is an unreliable connection with the YubiKey, but it is also possible the device is a fraudulent YubiKey. In this case it is still possible to call on the connected device to perform operations, after all, the device trusts the off-card application. Generally, however, an application will not want to use the device if this happens. Nonetheless, an application could catch the exception and continue, either try again or use the device knowing it is untrusted.

The method will call the KeyCollector delegate to obtain the management key. If the management key obtained authenticates, the method will call the KeyCollector again with the Request of Release. Upon the return from this release call to the KeyCollector, the method will return true and set the ManagementKeyAuthenticated property to true and the ManagementKeyAuthenticationResult property to SingleAuthenticated or MutualFullyAuthenticated. Note that this method ignores the return from the KeyCollector when the request is Release. That is, this method will return true or false depending on what happened before the Release. Note also that the KeyCollector MUST NEVER throw an exception when the request is Release.

If the off-card application authentication fails, the method will call the KeyCollector delegate again, this time indicating the previous management key provided failed to authenticate (KeyEntryRequest.IsRetry will be set to true). The method will continue to call the KeyCollector and try to authenticate as long as the returned management key does not authenticate, and the return from the KeyCollector is true. If you want to cancel the authentication process after some number of failed attempts, build your KeyCollector to allow the user to cancel or keep track of the failures and return false after the limit has been reached.

Note that there is no limit on the number of tries to authenticate the management key. That is, the management key will never be blocked.

Note also that if the call is for mutual authentication and the YubiKey fails to authenticate, then the method will not call the KeyCollector again, it will set the ManagementKeyAuthenticated property to false, the ManagementKeyAuthenticationResult property to MutualYubiKeyAuthenticationFailed, and throw an exception.

If there is an error during the process, this method will simply call the KeyCollector with Release, set the ManagementKeyAuthenticated property to false, the ManagementKeyAuthenticationResult property to Unauthenticated, and throw an exception.

Exceptions

InvalidOperationException

There is no KeyCollector loaded, the key provided was not a valid key, or the YubiKey had some other error, such as unreliable connection.

MalformedYubiKeyResponseException

The YubiKey returned malformed data and authentication, either single or double, could not be performed.

SecurityException

Mutual authentication was performed and the YubiKey was not authenticated.

TryAuthenticateManagementKey(ReadOnlyMemory<byte>, bool)

Try to authenticate the management key. This method will use the key data provided, rather than the KeyCollector.

public bool TryAuthenticateManagementKey(ReadOnlyMemory<byte> managementKey, bool mutualAuthentication = true)

Parameters

managementKey ReadOnlyMemory<byte>

The key to authenticate.

mutualAuthentication bool

If true the method will perform mutual authentication, if false, only the application will authenticate to the YubiKey. The default is true.

Returns

bool

A boolean, true if the management key authenticates, false if it does not.

Remarks

Normally, an application will not call any AuthenticateManagementKey method. Under the covers, the SDK determines when the management key needs to be verified and calls the KeyCollector. It is only at that point the application needs to supply the key. The SDK will call the application-supplied KeyCollector, indicating what it needs (PIN, PUK, management key), and the KeyCollector does what it needs to obtain the value requested. This system also contains a mechanism to report if the previous value was incorrect. If the management key is never needed, the key is never provided.

See the User's Manual entry on the Key Collector for a more detailed explanation of this process.

With this method, however, the caller provides the management key and the KeyCollector is never contacted.

See the TryAuthenticateManagementKey(bool) method for further documentation on this method.

Generally, it is necessary to authenticate a management key once per session. Once the key is authenticated, any operation that required the key in order to execute, called during that session, will work. The exceptions include changing the management key, and setting a YubiKey to PIN-only.

Some applications would like to avoid using a KeyCollector. For such situations, this method is provided. As long as the application does not perform an operation that requires the management key even if it has been authenticated in the session, the KeyCollector is not needed.

Note that if the management key is needed during the session even after the key is authenticated using this method (see exceptions above), and no KeyCollector is provided, the SDK will throw an exception.

The management key is provided to this method as a ReadOnlyMemory<byte>. It is possible to pass a byte[], because it will be automatically cast. The management key is 24 bytes, no more, no less.

If the wrong key is provided, this method will return false.

Exceptions

InvalidOperationException

The key provided was not a valid Triple-DES or AES key, or the YubiKey had some other error, such as unreliable connection.

MalformedYubiKeyResponseException

The YubiKey returned malformed data and authentication, either single or double, could not be performed.

SecurityException

Mutual authentication was performed and the YubiKey was not authenticated.

TryChangeManagementKey(ReadOnlyMemory<byte>, ReadOnlyMemory<byte>, PivTouchPolicy)

Try to change the management key. This method will use the currentKey and newKey provided.

public bool TryChangeManagementKey(ReadOnlyMemory<byte> currentKey, ReadOnlyMemory<byte> newKey, PivTouchPolicy touchPolicy = PivTouchPolicy.Default)

Parameters

currentKey ReadOnlyMemory<byte>

The current management key.

newKey ReadOnlyMemory<byte>

What the management key will be changed to.

touchPolicy PivTouchPolicy

The touch policy for the new management key. If no argument is given, the policy will be PivTouchPolicy.Default.

Returns

bool

A boolean, true if the management key is changed, false if not.

Remarks

Normally, an application would call the TryChangeManagementKey(PivTouchPolicy) method and the SDK would call on the loaded KeyCollector to retrieve the current and new keys. With this method, the caller provides the keys and the KeyCollector is never contacted.

Some applications would like to avoid using a KeyCollector. For such situations, this method is provided.

See the TryChangeManagementKey(PivTouchPolicy) method for further documentation on this method.

If the wrong current key is provided, this method will return false.

Exceptions

InvalidOperationException

One of the keys provided was not a valid Triple-DES or AES key, or the YubiKey had some other error, such as unreliable connection.

MalformedYubiKeyResponseException

The YubiKey returned malformed data and authentication, either single or double, could not be performed.

SecurityException

Mutual authentication was performed and the YubiKey was not authenticated.

TryChangeManagementKey(ReadOnlyMemory<byte>, ReadOnlyMemory<byte>, PivTouchPolicy, PivAlgorithm)

Try to change the management key. This method will use the currentKey and newKey provided. The new key's algorithm will be as specified.

public bool TryChangeManagementKey(ReadOnlyMemory<byte> currentKey, ReadOnlyMemory<byte> newKey, PivTouchPolicy touchPolicy, PivAlgorithm newKeyAlgorithm)

Parameters

currentKey ReadOnlyMemory<byte>

The current management key.

newKey ReadOnlyMemory<byte>

What the management key will be changed to.

touchPolicy PivTouchPolicy

The touch policy for the new management key.

newKeyAlgorithm PivAlgorithm

The algorithm the new management key will be.

Returns

bool

A boolean, true if the management key is changed, false if not.

Remarks

Normally, an application would call the TryChangeManagementKey(PivTouchPolicy) method and the SDK would call on the loaded KeyCollector to retrieve the current and new keys. With this method, the caller provides the keys and the KeyCollector is never contacted.

Some applications would like to avoid using a KeyCollector. For such situations, this method is provided.

See the TryChangeManagementKey(PivTouchPolicy, PivAlgorithm) method for further documentation on this method.

Note that with this method, a touch policy argument is required, there is no default value.

If the wrong current key is provided, this method will return false.

Exceptions

InvalidOperationException

One of the keys provided was not a valid Triple-DES or AES key, or the YubiKey had some other error, such as unreliable connection.

MalformedYubiKeyResponseException

The YubiKey returned malformed data and authentication, either single or double, could not be performed.

SecurityException

Mutual authentication was performed and the YubiKey was not authenticated.

TryChangeManagementKey(PivTouchPolicy)

Try to change the management key. The default management key algorithm will be used. (Firmware 5.7.x and later: AES-192. Firmware 5.6.x and earlier: TDES.)

public bool TryChangeManagementKey(PivTouchPolicy touchPolicy = PivTouchPolicy.Default)

Parameters

touchPolicy PivTouchPolicy

The touch policy for the new management key. If no argument is given, the policy will be PivTouchPolicy.Default.

Returns

bool

A boolean, true if the management key is changed, false if not.

Remarks

Upon manufacture of a YubiKey, the PIV application begins with a default management key (see the User's Manual entry on the management key). This method changes it. Note that this method can be run at any time, either during the initial YubiKey setup to change from the default management key, or later, to change it again.

If the YubiKey is set for PIN-only, this method will throw an exception.

Beginning with YubiKey 5.4.2, the management key can be either Triple-DES or AES. When changing the management key, the SDK can obtain the metadata for the management key slot to determine the algorithm of the current key. However, the caller must supply the algorithm of the new key (if it is 24 bytes, is it Triple-DES or AES-192?). There is a Try method for changing the management key that has an input argument for the algorithm. This method does not have such an arg. This one will set the new key to Triple-DES.

The Triple-DES management key is 24 byte long, no more, no less. It is binary. That's 192 bits. But note that because of "parity" bits, the actual bit strength of a Triple-DES key is 124 bits. And then further, there are attacks on Triple-DES that leave its effective bit strength at 112 bits.

In order to change it, the current management key must be authenticated. If it has already been authenticated in this session, this method will still make the appropriate calls to authenticate (it will perform mutual authentication). That is, if you want to change the management key, it is not necessary to call TryAuthenticateManagementKey or AuthenticateManagementKey first. You can, but it doesn't matter, because this method will call it again.

This method will collect the current and new management keys using the KeyCollector delegate. If no such delegate has been set, this method will throw an exception.

The KeyCollector has an option to cancel the operation. That is, this TryAuthenticateManagementKey method will call the KeyCollector requesting the current management key, and it is possible that during the collection operations, the user cancels. The KeyCollector will return to this method noting the cancellation. In that case, this method will return false.

Note that this is the only way to get a false return. Any other error and this method will throw an exception. In other words, a false return from this method means the user canceled.

Along with the key data itself, a management key has a touch policy. See the User's Manual entry on the PIV touch policy.

This method takes in a touch policy argument, but the argument has a default value, so it is valid to pass no argument to this method. The default argument value is the Default touch policy.

Note: touch policy for the management key is available only on YubiKey 4 and later. A YubiKey prior to 4 will ignore the touch policy and simply set the touch policy of the management key to the default.

The touch policy refers to whether use of the management key will require touch or not, and if so, always or cached. The policy is specified using the PivTouchPolicy enum. If the input is None or Never, the YubiKey will not require touch to complete an operation that requires the management key. Always means every operation requires touch, even if the YubiKey had been touched for an operation shortly before. If Cached, one touch will last for 15 seconds. That is, touch for an operation, and if a second operation requires the management key, and it is executing less than 15 seconds after the first, touch is not required. Default will use the YubiKey's default touch policy.

After this method is called, the management key will be authenticated for this session. That is, in order to change the key, the current management key must be authenticated. After changing, the new management key will be considered authenticated, and any subsequent operation that requires management key authentication in order to execute (e.g. generate a key pair) will work.

Exceptions

InvalidOperationException

There is no KeyCollector loaded, one of the keys provided was not a valid Triple-DES or AES key, or the YubiKey had some other error, such as unreliable connection.

MalformedYubiKeyResponseException

The YubiKey returned malformed data and authentication, either single or double, could not be performed.

SecurityException

Mutual authentication was performed and the YubiKey was not authenticated.

TryChangeManagementKey(PivTouchPolicy, PivAlgorithm)

Try to change the management key. The new key will be the specified algorithm.

public bool TryChangeManagementKey(PivTouchPolicy touchPolicy, PivAlgorithm newKeyAlgorithm)

Parameters

touchPolicy PivTouchPolicy

The touch policy for the new management key.

newKeyAlgorithm PivAlgorithm

The new management key's algorithm.

Returns

bool

A boolean, true if the management key is changed, false if not.

Remarks

Upon manufacture of a YubiKey, the PIV application begins with a default management key (see the User's Manual entry on the management key). This method changes it. Note that this method can be run at any time, either during the initial YubiKey setup to change from the default management key, or later, to change it again.

If the YubiKey is set for PIN-only, this method will throw an exception.

Beginning with YubiKey 5.4.2, the management key can be either Triple-DES or AES. When changing the management key, the SDK can obtain the metadata for the management key slot to determine the algorithm of the current key. However, the caller must supply the algorithm of the new key (if it is 24 bytes, is it Triple-DES or AES-192?).

Note that a Triple-DES key is 24 byte long, no more, no less. It is binary. That's 192 bits. But because of "parity" bits, the actual bit strength of a Triple-DES key is 124 bits. Furthermore, there are attacks on Triple-DES that leave its effective bit strength at 112 bits.

In order to change it, the current management key must be authenticated. If it has already been authenticated in this session, this method will still make the appropriate calls to authenticate (it will perform mutual authentication). That is, if you want to change the management key, it is not necessary to call TryAuthenticateManagementKey or AuthenticateManagementKey first. You can, but it doesn't matter, because this method will call it again.

This method will collect the current and new management keys using the KeyCollector delegate. If no such delegate has been set, this method will throw an exception.

The KeyCollector has an option to cancel the operation. That is, this TryAuthenticateManagementKey method will call the KeyCollector requesting the current management key, and it is possible that during the collection operations, the user cancels. The KeyCollector will return to this method noting the cancellation. In that case, this method will return false.

Note that this is the only way to get a false return. Any other error and this method will throw an exception. In other words, a false return from this method means the user canceled.

Along with the key data itself, a management key has a touch policy. See the User's Manual entry on the PIV touch policy. This method requires a touch policy argument, it does not have a default.

Note: touch policy for the management key is available only on YubiKey 4 and later. A YubiKey prior to 4 will ignore the touch policy and simply set the touch policy of the management key to the default.

The touch policy refers to whether use of the management key will require touch or not, and if so, always or cached. The policy is specified using the PivTouchPolicy enum. If the input is None or Never, the YubiKey will not require touch to complete an operation that requires the management key. Always means every operation requires touch, even if the YubiKey had been touched for an operation shortly before. If Cached, one touch will last for 15 seconds. That is, touch for an operation, and if a second operation requires the management key, and it is executing less than 15 seconds after the first, touch is not required. Default will use the YubiKey's default touch policy.

After this method is called, the management key will be authenticated for this session. That is, in order to change the key, the current management key must be authenticated. After changing, the new management key will be considered authenticated, and any subsequent operation that requires management key authentication in order to execute (e.g. generate a key pair) will work.

Exceptions

InvalidOperationException

There is no KeyCollector loaded, one of the keys provided was not a valid key for the specified algorithm, or the YubiKey had some other error, such as unreliable connection.

MalformedYubiKeyResponseException

The YubiKey returned malformed data and authentication, either single or double, could not be performed.

SecurityException

Mutual authentication was performed and the YubiKey was not authenticated.

TryChangePin()

Try to change the PIN.

public bool TryChangePin()

Returns

bool

A boolean, true if the PIN is changed, false if not.

Remarks

Upon manufacture of a YubiKey, the PIV application begins with a default PIN (see the User's Manual entry on the PIN). This method changes it. Note that this method can be run at any time, either during the initial YubiKey setup to change from the default PIN, or later, to change it again.

The PIN is six to eight bytes byte long. Although most PINs will be characters, the YubiKey allows any binary data to be a PIN. The default is the ASCII string "123456" which is the byte array

0x31 0x32 0x33 0x34 0x35 0x36

In order to change the PIN, both the current PIN and new PIN must be provided. Even if the current PIN had been verified already (using one of the methods TryVerifyPin or VerifyPin), the current PIN must be provided again. This method will call the KeyCollector delegate with the Request of KeyEntryRequest.ChangePivPin. The KeyCollector must then provide to this method both the current and new PIN.

The KeyCollector has an option to cancel the operation. That is, this TryChangePin method will call the KeyCollector requesting the PIN, and it is possible that during the collection operations, the user cancels. The KeyCollector will return to this method noting the cancellation. In that case, this method will return false.

Note that this is the only way to get a false return. Any other error and this method will throw an exception. In other words, a false return from this method means the user canceled.

An incorrect current PIN will decrement the remaining tries count. Hence, trying to change the PIN with the wrong current PIN too many times (retry count times) will cause the PIN to be blocked.

If the wrong current PIN is provided, and the remaining retries count is not zero, the method will call the KeyCollector again with KeyEntryData.IsRetry set to true and KeyEntryData.RetriesRemaining set to the number of tries remaining until the PIN is blocked. The KeyCollector can try to collect the PIN again, but will likely report the retries remaining to the user and offer the option of canceling. If the KeyCollector returns false, this method will call the KeyCollector with Release and return false.

If the wrong current PIN is provided, and the remaining retries count is zero, the method will call the KeyCollector again, indicating Release and then throw an exception. That is, once the remaining retries count goes to zero the PIN is blocked. At this point, this method will not try to collect the PIN any more and will throw an exception.

If there is an error during the process, this method will simply call the KeyCollector with Release and throw an exception.

Note that when this method calls the KeyCollector with Release, the return from the KeyCollector is ignored, this method will return true or false depending on what happened before the Release.

Changing the PIN does not affect the status of the Session's PIN verification. That is, the PinVerified property will not change after this method completes. If the status is false (unverified), and the PIN is successfully changed, the PIN will still be unverified and any operation that requires the PIN (such as signing), will need the PIN verified (with the new PIN). If the status is true (verified) and this method succeeds, the PIN will still be considered verified (the previous PIN), even though there is a new PIN. If the status is true (verified) and this method fails, the PIN will still be considered verified (the current PIN).

Exceptions

InvalidOperationException

There is no KeyCollector loaded, or the YubiKey had some other error, such as unreliable connection.

SecurityException

The remaining retries count indicates the PIN is blocked.

TryChangePin(ReadOnlyMemory<byte>, ReadOnlyMemory<byte>, out int?)

Try to change the PIN. This method will use the currentPin and newPin provided.

public bool TryChangePin(ReadOnlyMemory<byte> currentPin, ReadOnlyMemory<byte> newPin, out int? retriesRemaining)

Parameters

currentPin ReadOnlyMemory<byte>

The current PIN, the PIN that is to be changed.

newPin ReadOnlyMemory<byte>

The new PIN, what the PIN will be changed to.

retriesRemaining int?

An output, it will be set to the number of retries remaining if the current PIN is not verified. If the current PIN is verified and the PIN is changed, this will be set to null.

Returns

bool

A boolean, true if the PIN is changed, false if not.

Remarks

Normally, an application would call the TryChangePin() method (no arguments) and the SDK would call on the loaded KeyCollector to retrieve the PINs. With this method, the caller provides the PINs and the KeyCollector is never contacted.

Some applications would like to avoid using a KeyCollector. For such situations, this method is provided.

See the TryChangePin() method for further documentation on this method.

If the wrong current PIN is provided, this method will return false.

Changing the PIN does not affect the status of the Session's PIN verification. That is, the PinVerified property will not change after this method completes. If the status is false (unverified), and the PIN is successfully changed, the PIN will still be unverified and any operation that requires the PIN (such as signing), will need the PIN verified (with the new PIN). If the status is true (verified) and this method succeeds, the PIN will still be considered verified (the previous PIN), even though there is a new PIN. If the status is true (verified) and this method fails, the PIN will still be considered verified (the current PIN).

If the YubiKey is configured for PIN-derived, this method will update the management key, so that it is derived from the new PIN. Note that if the ADMIN DATA and/or PRINTED storage locations have been overwritten, this method might not be able to correctly update the management key. It is a good idea to call TryRecoverPinOnlyMode() before changing the PIN. See also the User's Manual entry on PIN-only modes.

Exceptions

InvalidOperationException

The YubiKey had some error, such as unreliable connection.

SecurityException

The remaining retries count indicates the PIN is blocked.

TryChangePinAndPukRetryCounts(ReadOnlyMemory<byte>, ReadOnlyMemory<byte>, byte, byte, out int?)

Try to change the retry counts for both the PIN and PUK. This method will use the managementKey and pin provided.

Warning

This will reset the PIN and PUK to their default values as well as set the retry counts.

public bool TryChangePinAndPukRetryCounts(ReadOnlyMemory<byte> managementKey, ReadOnlyMemory<byte> pin, byte newRetryCountPin, byte newRetryCountPuk, out int? retriesRemaining)

Parameters

managementKey ReadOnlyMemory<byte>

The current management key. If it is Empty, the method will authenticate using PIN-only.

pin ReadOnlyMemory<byte>

The current PIN.

newRetryCountPin byte

The PIN's new retry count.

newRetryCountPuk byte

The PUK's new retry count.

retriesRemaining int?

An output, it will be set to the number of retries remaining if the PIN is not verified. If the management key is not authenticated or the PIN is verified, this will be set to null.

Returns

bool

A boolean, true if the retry counts are changed, false if not.

Remarks

Normally, an application would call the ChangePinAndPukRetryCounts(int, int) method and the SDK would call on the loaded KeyCollector to retrieve the management key and PIN. With this method, the caller provides the management key and PIN and the KeyCollector is never contacted.

Some applications would like to avoid using a KeyCollector. For such situations, this method is provided.

See the ChangePinAndPukRetryCounts(byte, byte) method for further documentation on this method.

If the wrong management key or PIN is provided, this method will return false.

This method will authenticate the management key provided and verify the PIN provided, even if one or both have already been authenticated/verified.

If the YubiKey is configured for PIN-only, the managementKey argument will be ignored. In this case, you can pass in an empty management key: ReadOnlyMemory<byte>.Empty.

Exceptions

InvalidOperationException

The YubiKey had some error, such as unreliable connection.

SecurityException

The remaining retries count indicates the PIN is blocked.

TryChangePuk()

Try to change the PUK (PIN Unblocking Key).

public bool TryChangePuk()

Returns

bool

A boolean, true if the PUK is changed, false if not.

Remarks

Upon manufacture of a YubiKey, the PIV application begins with a default PUK (see the User's Manual entry on the PUK). This method changes it. Note that this method can be run at any time, either during the initial YubiKey setup to change from the default PUK, or later, to change it again.

The PUK must be 6-8 characters. For YubiKeys with firmware versions prior to 5.7, the PUK is allowed to be any character in the 0x00 - 0xFF range for a total length of 6-8 bytes. For YubiKeys with firmware version 5.7 and above, the PUK is allowed to be any character in the 0x00 - 0x7F range for a total length of 6-8 Unicode code points. The default PUK is the ASCII string "12345678", which is the byte array

0x31 0x32 0x33 0x34 0x35 0x36 0x37 0x38

In order to change the PUK, both the the current PUK and new PUK must be provided. This method will call the KeyCollector delegate with the Request of KeyEntryRequest.ChangePivPuk. The KeyCollector provides both the current and new PUK.

The KeyCollector has an option to cancel the operation. That is, this TryChangePuk method will call the KeyCollector requesting the PUK, and it is possible that during the collection operations, the user cancels. The KeyCollector will return to this method noting the cancellation. In that case, this method will return false.

Note that this is the only way to get a false return. Any other error and this method will throw an exception. In other words, a false return from this method means the user canceled.

An incorrect current PUK will decrement the remaining tries count. Hence, trying to change the PUK with the wrong current PUK too many times (retry count times) will cause the PUK to be blocked.

If the wrong current PUK is provided, and the remaining retries count is not zero, the method will call the KeyCollector again with KeyEntryData.IsRetry set to true and KeyEntryData.RetriesRemaining set to the number of tries remaining until the PUK is blocked. The KeyCollector can try to collect the PUK again, but will likely report the retries remaining to the user and offer the option of canceling. If the KeyCollector returns false, this method will call the KeyCollector with Release and return false.

If the wrong current PUK is provided, and the remaining retries count is zero, the method will call the KeyCollector again, indicating Release and then throw an exception. That is, once the remaining retries count goes to zero the PUK is blocked. At this point, this method will not try to collect the PUK any more and will throw an exception.

If there is an error during the process, this method will simply call the KeyCollector with Release and throw an exception.

Note that when this method calls the KeyCollector with Release, the return from the KeyCollector is ignored, this method will return true or false depending on what happened before the Release.

Exceptions

InvalidOperationException

There is no KeyCollector loaded, or the YubiKey had some other error, such as unreliable connection.

SecurityException

The remaining retries count indicates the PUK is blocked.

TryChangePuk(ReadOnlyMemory<byte>, ReadOnlyMemory<byte>, out int?)

Try to change the PUK. This method will use the currentPuk and newPuk provided.

public bool TryChangePuk(ReadOnlyMemory<byte> currentPuk, ReadOnlyMemory<byte> newPuk, out int? retriesRemaining)

Parameters

currentPuk ReadOnlyMemory<byte>

The current PUK, the PUK that is to be changed.

newPuk ReadOnlyMemory<byte>

The new PUK, what the PUK will be changed to.

retriesRemaining int?

An output, it will be set to the number of retries remaining if the current PUK is not correct. If the PUK is changed, this will be set to null.

Returns

bool

A boolean, true if the PUK is changed, false if not.

Remarks

Normally, an application would call the TryChangePuk() method (no arguments) and the SDK would call on the loaded KeyCollector to retrieve the PUKs. With this method, the caller provides the current and new PUKs and the KeyCollector is never contacted.

Some applications would like to avoid using a KeyCollector. For such situations, this method is provided.

See the TryChangePuk() method for further documentation on this method.

If the wrong current PUK is provided, this method will return false.

Exceptions

InvalidOperationException

The YubiKey had some error, such as unreliable connection.

SecurityException

The remaining retries count indicates the PUK is blocked.

TryReadObject<T>(int, out T)

Try to read the data at the storage location specified by the defined data tag for the PivDataObject T, storing and returning this data in a new object of type T.

public bool TryReadObject<T>(int dataTag, out T pivDataObject) where T : PivDataObject, new()

Parameters

dataTag int

The alternate data tag, the tag of the storage location to look.

pivDataObject T

An output argument, this method will create a new object containing the data from the storage location, as long as it is formatted as expected.

Returns

bool

A boolean, true if the storage location contains data formatted as expected, or no data, and false if the storage location contains data formatted in an unexpected way.

Type Parameters

T

The type of PivDataObject to create, set, and return.

Remarks

For example,

bool isValid = pivSession.TryReadObject<KeyHistory>(out KeyHistory keyHistory);
if (isValid)
{
    // perform operations
}
keyHistory.Dispose();

or alternatively,

bool isValid = pivSession.ReadObject<KeyHistory>(out KeyHistory keyHistory);
using (keyHistory)
{
    if (isValid)
    {
        // perform operations
    }
}

Note that the PivDataObject is Disposable so make sure you use the using keyword or call Dispose directly.

See also the user's manual entry on PIV data objects.

The method will look in the storage location specified by the dataTag argument.

It is possible that there is no data on the YubiKey in the specified storage location. If so, this method will build a new, empty object as the pivDataObject and return false.

If there is data and it is formatted as expected, the method will build a new object set with the data and return true.

If there is data stored under the specified data tag, and it is not formatted as expected, this method will build a new, empty object as the pivDataObject and return false.

Exceptions

ArgumentException

The dataTag in not allowed to be an alternate tag.

TryReadObject<T>(out T)

Try to read the data at the storage location specified by the defined data tag for the PivDataObject T, storing and returning this data in a new object of type T.

public bool TryReadObject<T>(out T pivDataObject) where T : PivDataObject, new()

Parameters

pivDataObject T

An output argument, this method will create a new object containing the data from the storage location, as long as it is formatted as expected.

Returns

bool

A boolean, true if the storage location contains data formatted as expected, or no data, and false if the storage location contains data formatted in an unexpected way.

Type Parameters

T

The type of PivDataObject to create, set, and return.

Remarks

For example,

bool isValid = pivSession.TryReadObject<PinProtectedData>(out PinProtectedData pinProtect);
if (isValid)
{
    // perform operations
}
pinProtect.Dispose();

or alternatively,

bool isValid = pivSession.ReadObject(out PinProtectedData pinProtect);
using (pinProtect)
{
    if (isValid)
    {
        // perform operations
    }
}

Note that the PivDataObject is Disposable so make sure you use the using keyword or call Dispose directly.

See also the user's manual entry on PIV data objects.

The method will look in the storage location specified by the defined data tag of the pivDataObject.

It is possible that there is no data on the YubiKey in the specified storage location. If so, this method will build a new, empty object as the pivDataObject and return false.

If there is data and it is formatted as expected, the method will build a new object set with the data and return true.

If there is data stored under the specified data tag, but it is not formatted as expected, this method will build a new, empty object as the pivDataObject and return false.

TryRecoverPinOnlyMode()

Try to recover the PIN-only state. If successful, this will authenticate the management key and reset the ADMIN DATA and or PRINTED storage locations.

Warning

This can overwrite the contents of ADMIN DATA and/or PRINTED. If some other application relies on that data it will be lost.

public PivPinOnlyMode TryRecoverPinOnlyMode()

Returns

PivPinOnlyMode

A PivPinOnlyMode, which is an enum indicating the mode or modes the YubiKey is in.

Remarks

See the User's Manual entry on PIV PIN-only mode for a deeper discussion of this operation.

The ADMIN DATA contains information about PIN-only. The PIN-protected management key is stored in PRINTED. Applications should never store information in those locations, only Yubico-supplied products should use them. However, it is possible for an application to overwrite the contents of one or both of these storage locations, making the PIN-only data inaccurate.

This method will obtain the data stored in the two storage locations, and determine if they contain PIN-only data that can be used to authenticate the management key. If it can't, it will return PivPinOnlyMode.None or Unavailable. If it can, it will authenticate and set the ADMIN DATA and PRINTED to contain data compatible with correct PIN-only modes. It will return a PivPinOnlyMode value indicating which mode is set.

For example, suppose the data in both is correct, and it indicates the management key is PIN-protected. After calling this method, the management key will be authenticated, the storage locations will not be changed, and the return will be PivPinOnlyMode.PinProtected.

Another possibility is the ADMIN DATA was overwritten by some application so it is inaccurate, but the PIN-protected data is still in PRINTED. This method will be able to authenticate the management key using that data. It will replace the contents of ADMIN DATA with correct PIN-only information and return PivPinOnlyMode.PinProtected.

If ADMIN DATA and PRINTED contain no data, or if ADMIN DATA contains correct information that indicates the YubiKey is not set to PIN-only mode, then this method will not authenticate the management key, it will not put any data into the storage locations, and it will return PivPinOnlyMode.None.

It is possible this method is not able to recover. For example, suppose the ADMIN DATA is correct and indicates the YubiKey is PIN-protected, but not PIN-derived (there is no salt to use to derive a key), but the data in PRINTED is not correct. In this case, the method will not be able to authenticate the management key as PIN-protected. It will try to authenticate using the default management key, and if that does not work, it will call on the KeyCollector to obtain the it. If that does succeeds, it will set ADMIN DATA to indicate the YubiKey is not PIN-protected, it will clear the contents of PRINTED, and it will return PivPinOnlyMode.None. If the KeyCollector is not able to provide the management key, this method will not be able to reset the ADMIN DATA nor PRINTED (management key authentication is necessary to set a storage location), and will return Unavailable.

This method will require the PIN to be verified. It is possible that the PIN has already been verified and this method will verify it again. If it needs to verify the PIN, it will call on the KeyCollector to obtain it.

TryResetPin()

Try to reset the PIN, using the PUK (PIN Unblocking Key).

public bool TryResetPin()

Returns

bool

A boolean, true if the PIN is reset, false if not.

Remarks

If a user loses (or forgets) the PIN, it is possible to reset it using the PUK. Whether the PIN has been blocked (the wrong value was entered too many times in calls to TryVerifyPin or TryChangePin, and the retry count was exhausted) or not, it is possible to reset the PIN to a new value. That is, if the PIN is blocked, use this method to unblock it. But even if the PIN is not blocked, you can use this method to reset it.

This is essentially the same operation as TryChangePin, except instead of using the current PIN to provide permission to change the PIN, it uses the PUK.

If the PUK is blocked, this method will not execute. Note that if a YubiKey is configured PIN-only, the PUK will be blocked.

The PIN is six to eight bytes byte long. Although most PINs will be characters, the YubiKey allows any binary data to be a PIN.

In order to change the PUK, both the the current PUK and a new PIN must be provided. This method will call the KeyCollector delegate with the Request of KeyEntryRequest.ResetPivPinWithPuk. The KeyCollector provides both the current PUK and a new PIN. Once it has both the PUK and a new PIN, this method will try to reset the PIN. That is, this method will not verify the current PUK in a separate step, the current PUK will only be verified for the reset with the new PIN.

The KeyCollector has an option to cancel the operation. That is, this TryResetPin method will call the KeyCollector requesting the PUK and PIN, and it is possible that during the collection operations, the user cancels. The KeyCollector will return to this method noting the cancellation. In that case, this method will return false.

Note that this is the only way to get a false return. Any other error and this method will throw an exception. In other words, a false return from this method means the user canceled.

An incorrect current PUK will decrement the remaining tries count. Hence, trying to change the PIN with the wrong current PUK too many times (retry count times) will cause the PUK to be blocked.

If the wrong current PUK is provided, and the remaining retries count is not zero, the method will call the KeyCollector again with KeyEntryData.IsRetry set to true and KeyEntryData.RetriesRemaining set to the number of tries remaining until the PUK is blocked. The KeyCollector can try to collect the PUK again, but will likely report the retries remaining to the user and offer the option of canceling. If the KeyCollector returns false, this method will call the KeyCollector with Release and return false.

If the wrong current PUK is provided, and the remaining retries count is zero, the method will call the KeyCollector again, indicating Release and then throw an exception. That is, once the remaining retries count goes to zero the PUK is blocked. At this point, this method will not try to collect the PUK any more and will throw an exception.

If there is an error during the process, this method will simply call the KeyCollector with Release and throw an exception.

Note that when this method calls the KeyCollector with Release, the return from the KeyCollector is ignored, this method will return true or false depending on what happened before the Release.

Resetting the PIN does not affect the status of the Session's PIN verification. That is, the PinVerified property will not change after this method completes. If the status is false (unverified), and the PIN is successfully reset, the PIN will still be unverified and any operation that requires the PIN (such as signing), will need the PIN verified (with the new PIN). If the status is true (verified) and this method succeeds, the PIN will still be considered verified (the previous PIN), even though there is a new PIN. If the status is true (verified) and this method fails, the PIN will still be considered verified (the current PIN).

Exceptions

InvalidOperationException

There is no KeyCollector loaded, or the YubiKey had some other error, such as unreliable connection.

SecurityException

The remaining retries count indicates the PUK is blocked.

TryResetPin(ReadOnlyMemory<byte>, ReadOnlyMemory<byte>, out int?)

Try to reset the PIN using the PUK (PIN Unblocking Key). This method will use the puk and pin provided.

public bool TryResetPin(ReadOnlyMemory<byte> puk, ReadOnlyMemory<byte> newPin, out int? retriesRemaining)

Parameters

puk ReadOnlyMemory<byte>

The PIN Unblocking Key.

newPin ReadOnlyMemory<byte>

The new PIN, what the PIN will be changed to.

retriesRemaining int?

An output, it will be set to the number of retries remaining if the PUK is not correct. If the PIN is reset, this will be set to null.

Returns

bool

A boolean, true if the PIN is changed, false if not.

Remarks

Normally, an application would call the TryResetPin() method (no arguments) and the SDK would call on the loaded KeyCollector to retrieve the PUK and new PIN. With this method, the caller provides the PUK and new PIN and the KeyCollector is never contacted.

Some applications would like to avoid using a KeyCollector. For such situations, this method is provided.

See the TryResetPin() method for further documentation on this method.

If the wrong PUK is provided, this method will return false.

Changing the PIN does not affect the status of the Session's PIN verification. That is, the PinVerified property will not change after this method completes. If the status is false (unverified), and the PIN is successfully changed, the PIN will still be unverified and any operation that requires the PIN (such as signing), will need the PIN verified (with the new PIN). If the status is true (verified) and this method succeeds, the PIN will still be considered verified (the previous PIN), even though there is a new PIN. If the status is true (verified) and this method fails, the PIN will still be considered verified (the current PIN).

If the PUK is blocked, this method will not execute. Note that if a YubiKey is configured PIN-only, the PUK will be blocked.

Exceptions

InvalidOperationException

The YubiKey had some error, such as unreliable connection.

SecurityException

The remaining retries count indicates the PIN is blocked.

TryVerifyPin()

Try to verify the PIN. If the user cancels, return false

public bool TryVerifyPin()

Returns

bool

A boolean, true if the PIN verifies, false if the KeyCollector cancels.

Remarks

You need to verify the PIN only once per session. But if you have already verified, and you call this method, it will perform the verification again. If the verification fails the second time, the previous verification will be nullified.

See the PinVerified property for the current state of PIN verification.

This method will collect the PIN using the KeyCollector delegate. If no such delegate has been set, this method will throw an exception.

The KeyCollector has an option to cancel the operation. That is, this TryVerifyPin method will call the KeyCollector requesting the PIN, and it is possible that during the collection operations, the user cancels. The KeyCollector will return to this method noting the cancellation. In that case, this method will return false.

Note that this is the only way to get a false return. Any other error and this method will throw an exception. In other words, a false return from this method means the user canceled.

This method will also set the PinVerified property of this class. That property is a boolean. If true, the PIN has been verified this session, otherwise it is false.

If the PIN verifies, the method will return true. If not, and the KeyCollector cancels the process, the method will return false and set the PinVerified property to false.

If the PIN does not verify, and the remaining retries count is not zero, the method will call the KeyCollector again with KeyEntryData.IsRetry set to true and KeyEntryData.RetriesRemaining set to the number of tries remaining until the PIN is blocked. The KeyCollector can try to collect the PIN again, but will likely report the retries remaining to the user and offer the option of canceling. If the KeyCollector returns false, this method will call the KeyCollector with Release and return false.

If the PIN does not verify, and the remaining retries count is zero, the method will call the KeyCollector again, indicating Release and then throw an exception. That is, once the remaining retries count goes to zero the PIN is blocked. At this point, this method will not try to collect the PIN any more and will throw an exception.

If there is an error during the process, this method will simply call the KeyCollector with Release, set the PinVerified property to false, and throw an exception.

Note that when this method calls the KeyCollector with Release, the return from the KeyCollector is ignored, this method will return true or false depending on what happened before the Release.

Exceptions

InvalidOperationException

There is no KeyCollector loaded, or the YubiKey had some other error, such as unreliable connection.

SecurityException

The remaining retries count indicates the PIN is blocked.

TryVerifyPin(ReadOnlyMemory<byte>, out int?)

Try to verify the PIN. This method will use the PIN provided, rather than the KeyCollector.

public bool TryVerifyPin(ReadOnlyMemory<byte> pin, out int? retriesRemaining)

Parameters

pin ReadOnlyMemory<byte>

The PIN to verify.

retriesRemaining int?

An output, it will be set to the number of retries remaining if the PIN is not verified. If the PIN is verified, this will be set to null.

Returns

bool

A boolean, true if the PIN verifies, false if not.

Remarks

Normally, an application will not call any VerifyPin method. Under the covers, the SDK determines when the PIN needs to be verified and calls the KeyCollector. It is only at that point the application needs to supply the PIN. The SDK will call the application-supplied KeyCollector, indicating what it needs (PIN, PUK, management key), and the KeyCollector does what it needs to obtain the value requested. This system also contains a mechanism to report if the previous value was incorrect and how many retries remain before the value is blocked. If the PIN is never needed, the PIN is never provided.

See the User's Manual entry on the Key Collector for a more detailed explanation of this process.

With this method, the caller provides the PIN and the KeyCollector is never contacted.

Generally, it is necessary to verify a PIN once per session. Once the PIN is verified, any operation that required the PIN in order to execute, called during that session, will work. The exceptions include performing a private key operation using a key that was generated or imported with the PIN policy of always, changing or resetting a PIN, and setting a YubiKey or session to PIN-derived (note that you should never set a YubiKey to PIN-derived, that feature is provided only for backwards compatibility).

Some applications would like to avoid using a KeyCollector. For such situations, this method is provided. As long as the application does not perform an operation that requires the PIN even if it has been verified in the session, the KeyCollector is not needed.

Note that if the PIN is needed during the session even after the PIN is verified using this method (see exceptions above), and no KeyCollector is provided, the SDK will throw an exception.

The PIN is provided to this method as a ReadOnlyMemory<byte>. It is possible to pass a byte[], because it will be automatically cast. Most PINs will be six to eight numbers, but the YubiKey allows any binary data. For example, if the PIN is "123456" (the default value), what is actually supplied to the YubiKey are the six bytes 0x31 32 33 34 35 36, the ASCII representation of the numerals '1' through '6'. If the PIN is "ABCDefg", then the value to send to the YubiKey is the byte array 0x41 42 43 44 65 66 67. But a PIN could also be 0xE7 05 3F 81 1C C9. Those are not ASCII characters, but a YubiKey would accept them.

If the wrong PIN is provided, this method will return false.

Exceptions

InvalidOperationException

The YubiKey had some error, such as unreliable connection.

OperationCanceledException

The wrong PIN was provided.

SecurityException

The remaining retries count indicates the PIN is blocked.

VerifyPin()

Verify the PIN, throw an exception if the user cancels.

public void VerifyPin()

Remarks

This is the same as TryVerifyPin, except this method will throw an exception if the KeyCollecter indicates user cancellation.

See the TryVerifyPin() method for further documentation on this method.

Exceptions

InvalidOperationException

There is no KeyCollector loaded, or the YubiKey had some other error, such as unreliable connection.

OperationCanceledException

The user canceled PIN collection.

SecurityException

The remaining retries count indicates the PIN is blocked.

WriteMsroots(ReadOnlySpan<byte>)

Write contents to the MSROOTS data objects. This will replace any data already stored in the MSROOTS data objects.

public void WriteMsroots(ReadOnlySpan<byte> contents)

Parameters

contents ReadOnlySpan<byte>

The data to store, represented as a ReadOnlySpan (a byte array).

Remarks

The YubiKey PIV application can store data objects. There is a set of data elements defined by the PIV standard. See the User's Manual entry on GET DATA for information on these elements and their tags. The standard also allows for vendor-defined data objects. MSROOTS is one such vendor-defined element.

The intention of the MSROOTS data object is to store (and retrieve) a PKCS 7 constuction containing a set of root certificates. These certificates will make it easier for the SDK to interface with the Microsoft Smart Card Base Crypto Service Provider (CSP).

Very few applications will need to use this feature. If you don't already know what the MSROOTS are, how to use them, and that they are part of your application already, then you almost certainly will never need to use this method.

This method will take whatever data it is given and store it on the YubiKey under the tag "MSROOTS". This method will not verify that the data is a PKCS 7 construction, or that it contains root certificates, it will simply write the bytes given.

Note that in order to store any data on the YubiKey, it must be formatted as a TLV (tag-length-value):

tag || length || value

for example, it might be

53 20 (contents, 32 bytes)

or

7F 61 20 (contents, 32 bytes)

The tag used varies depending on the data being stored. This method builds the TLV. That is, the caller supplies the contents only, this method will format it into a construction the YubiKey expects. This method knows what tag to use for MSROOTS and how to specify the length.

Note also that there is a limit to the number of bytes that can be stored in a data object. If the contents to store is longer, then this method will break the data into blocks and store each block in a different data object. The caller simply supplies all the data as a single byte array, this method will take care of the bookkeeping of breaking it into blocks and storing them in separate data objects.

There is a limit on the number of data objects, however, so there is indeed a limit on the total size of the data.

There is a limit of 5 MSROOTS data objects
The limit on data length for each data object is
  pre 4.0 YubiKeys (e.g. NEO)  :  2030 bytes
  4.0 and later YubiKeys       :  2800 bytes
The total input limit is
  pre 4.0 YubiKeys (e.g. NEO)  :  2030*5 bytes  :  10,150
  4.0 and later YubiKeys       :  2800*5 bytes  :  14,000
If the data passed in is too long, this method will throw an exception.

Note that the input is a ReadOnlySpan. If you have the data in a byte array (byte[]), just pass it in as the argument, it will be cast to a ReadOnlySpan automatically. Also, if you have no data to store (which is the same as DeleteMsroots), you can pass in null, but the preferred input in this case is ReadOnlySpan.Empty.

Input with a length of 0 is equivalent to calling DeleteMsroots.

In order to perform this operation, the management key must be authenticated during this session. If it has not been authenticated, this method will call AuthenticateManagementKey(bool). That is, your application does not need to authenticate the management key separately (i.e., call TryAuthenticateManagementKey or AuthenticateManagementKey), this method will determine if the management key has been authenticated or not, and if not, it will make the call to perform mutual authentication.

The authentication method will collect the management key using the KeyCollector delegate. If no such delegate has been set, it will throw an exception.

The KeyCollector has an option to cancel the operation. That is, the AuthenticateManagementKey method will call the KeyCollector requesting the management key, and it is possible that during the collection operations, the user cancels. The KeyCollector will return to the authentication method noting the cancellation. In that case, it will throw an exception. If you want the authentication to return false on user cancellation, you must call TryAuthenticateManagementKey(bool) directly before calling this method.

Exceptions

ArgumentOutOfRangeException

The input data was too long.

InvalidOperationException

There is no KeyCollector loaded, the key provided was not a valid Triple-DES key, or the YubiKey had some other error, such as unreliable connection.

MalformedYubiKeyResponseException

The YubiKey returned malformed data and authentication, either single or double, could not be performed.

OperationCanceledException

The user canceled management key collection.

SecurityException

Mutual authentication was performed and the YubiKey was not authenticated.

WriteMsrootsStream(Stream)

Write contents to the MSROOTS data objects. This will replace any data already stored in the MSROOTS data objects.

public void WriteMsrootsStream(Stream contents)

Parameters

contents Stream

The data to store, represented as a Stream (the CanRead property is true and the data read will be bytes).

Remarks

This is the same as WriteMsroots(ReadOnlySpan<byte>) except the contents are provided as a Stream.

Exceptions

ArgumentNullException

The contents argument is null.

ArgumentException

The stream is not readable.

ArgumentOutOfRangeException

The input data was too long.

InvalidOperationException

There is no KeyCollector loaded, the key provided was not a valid Triple-DES key, or the YubiKey had some other error, such as unreliable connection.

MalformedYubiKeyResponseException

The YubiKey returned malformed data and authentication, either single or double, could not be performed.

OperationCanceledException

The user canceled management key collection.

SecurityException

Mutual authentication was performed and the YubiKey was not authenticated.

WriteObject(PivDataObject)

Write the contents of the given object to the storage location specified by the DataTag property.

public void WriteObject(PivDataObject pivDataObject)

Parameters

pivDataObject PivDataObject

The object containing the data to store (and the definition of its formatting), along with the data tag under which it is to be stored.

Remarks

This method will call on the pivObject to encode the data following its definition, then store that data on the YubiKey under the PivObject.DataTag storage location.

See also the user's manual entry on PIV data objects.

Note that it is possible to change the DataTag, and this method will store the data under whatever DataTag is set to.

Note also that this method will overwrite any data already on the YubiKey, if there is any. Hence, make sure you know what data is stored there currently, and that it is safe to overwrite, before calling this method.

If the pivDataObject has no data (the IsEmpty property is true), then this method will "clear" a storage location. If there was data in the storage location before the call to WriteObject, it will be gone after.

Exceptions

ArgumentNullException

The pivDataObject argument is null.

InvalidOperationException

The method was not able to store the data onto the YubiKey.