Class PinUvAuthProtocolBase
- Namespace
- Yubico.YubiKey.Fido2.PinProtocols
- Assembly
- Yubico.YubiKey.dll
Base class for FIDO2 PIN/UV auth protocol implementations.
public abstract class PinUvAuthProtocolBase
- Inheritance
-
objectPinUvAuthProtocolBase
- Derived
Remarks
A PIN/UV auth protocol is a set of methods defined by the FIDO2 CTAP specification. The abstract interface is defined in section 6.5.4. As of FIDO 2.1, there are only two PIN protocols defined: protocol one and protocol two. These two implementations share some common code. The abstract interface as well as any shared code is defined by this class.
Properties
AuthenticationKey
Gets the authentication key derived from the shared value computed during the call to Encapsulate(CoseKey). This can be the same as the EncryptionKey.
public ReadOnlyMemory<byte>? AuthenticationKey { get; protected set; }
Property Value
- ReadOnlyMemory<byte>?
Remarks
This will be null
until the Encapsulate
method is
called.
AuthenticatorPublicKey
The public key returned by the YubiKey.
public CoseKey? AuthenticatorPublicKey { get; protected set; }
Property Value
Remarks
The caller will obtain the YubiKey's public key using the GetKeyAgreementCommand and pass it to the Encapsulate(CoseKey) method. A reference to the key passed into that method will be stored in this property.
A call to Initialize() will set this to null
. That
is, a new public key must be obtained for each PIN/UV authentication
session with the YubiKey. Even if the new session is initiated with
the previously-used YubiKey, the public key must be obtained, because
the YubiKey might generate a new public key.
EncryptionKey
Gets the encryption key derived from the shared value computed during the call to Encapsulate(CoseKey). This can be the same as the AuthenticationKey.
public ReadOnlyMemory<byte>? EncryptionKey { get; protected set; }
Property Value
- ReadOnlyMemory<byte>?
Remarks
This will be null
until the Encapsulate
method is
called.
PlatformPublicKey
Gets the public key generated during the call to Encapsulate(CoseKey).
public CoseKey? PlatformPublicKey { get; protected set; }
Property Value
Remarks
This will be null
until the Encapsulate
method is
called.
Protocol
Gets the identifier of the PIN / UV authentication protocol that this instance implements.
public PinUvAuthProtocol Protocol { get; protected set; }
Property Value
Methods
Authenticate(byte[])
Returns the result of computing HMAC-SHA-256 on the given message using the AuthenticationKey. With protocol 1, the result is the first 16 bytes of the HMAC, and with protocol 2 it is the entire 32-byte result.
public abstract byte[] Authenticate(byte[] message)
Parameters
message
byte[]The data to be authenticated.
Returns
- byte[]
A new byte array containing the authentication result.
Exceptions
- ArgumentNullException
The
message
argument is null.- InvalidOperationException
The object has been created or initialized, but the Encapsulate(CoseKey) method has not been called.
Authenticate(byte[], byte[])
Returns the result of computing HMAC-SHA-256 on the given message
using the provided keyData
. With protocol 1, the result is the
first 16 bytes of the HMAC, and with protocol 2 it is the entire
32-byte result.
protected abstract byte[] Authenticate(byte[] keyData, byte[] message)
Parameters
keyData
byte[]The key to use to authenticate.
message
byte[]The data to be authenticated.
Returns
- byte[]
A new byte array containing the authentication result.
Exceptions
- ArgumentNullException
The
keyData
ormessage
argument is null.
AuthenticateUsingPinToken(byte[], byte[])
Returns the result of computing HMAC-SHA-256 on the given message
using the pinToken
as the key. With protocol 1, the result is
the first 16 bytes of the HMAC, and with protocol 2 it is the entire
32-byte result.
public byte[] AuthenticateUsingPinToken(byte[] pinToken, byte[] message)
Parameters
pinToken
byte[]The PIN token returned by the YubiKey. This is the encrypted value, do not decrypt it.
message
byte[]The data to be authenticated.
Returns
- byte[]
A new byte array containing the authentication result.
Remarks
It is possible to obtain the PIN token by calling the command GetPinTokenCommand. The YubiKey will return the PIN token encrypted using the shared secret.
Pass that encrypted PIN token to this method as the first argument.
This method will decrypt the PIN token using the EncryptionKey
and then perform the authentication on the message
.
Exceptions
- ArgumentNullException
The
pinToken
ormessage
argument is null.- InvalidOperationException
The object has been created or initialized, but the Encapsulate(CoseKey) method has not been called.
AuthenticateUsingPinToken(byte[], int, int, byte[])
Returns the result of computing HMAC-SHA-256 on the given message
using the pinToken
as the key. With protocol 1, the result is
the first 16 bytes of the HMAC, and with protocol 2 it is the entire
32-byte result.
public virtual byte[] AuthenticateUsingPinToken(byte[] pinToken, int offset, int length, byte[] message)
Parameters
pinToken
byte[]The PIN token returned by the YubiKey. This is the encrypted value, do not decrypt it.
offset
intThe offset into
pinToken
buffer where the data begins.length
intThe length, in bytes, of the pin token.
message
byte[]The data to be authenticated.
Returns
- byte[]
A new byte array containing the authentication result.
Remarks
This is the same as AuthenticateUsingPinToken(byte[], byte[]),
except this specifies an offset and length of the pinToken
argument.
Exceptions
- ArgumentNullException
The
pinToken
ormessage
argument is null.- InvalidOperationException
The object has been created or initialized, but the Encapsulate(CoseKey) method has not been called.
Decrypt(byte[], int, int)
Returns the AES-256-CBC decryption of ciphertext using an IV specified
by the protocol and the EncryptionKey. With protocol 1
the IV is all 00 bytes. With protocol 2, it is the first block size
bytes of ciphertext
.
public abstract byte[] Decrypt(byte[] ciphertext, int offset, int length)
Parameters
ciphertext
byte[]The data to decrypt.
offset
intThe offset in
ciphertext
where the method will begin decrypting.length
intThe number of bytes to decrypt.
Returns
- byte[]
A new byte array containing the decrypted data.
Remarks
Note that this method will verify that the input buffer, offset, and length are valid.
Exceptions
- ArgumentNullException
The
ciphertext
argument is null.- InvalidOperationException
The object has been created or initialized, but the Encapsulate(CoseKey) method has not been called.
- ArgumentException
The length of the
ciphertext
is not a multiple of the AES block size (16 bytes).
DeriveKeys(byte[])
The key derivation function to run while performing ECDH. This will derive both the EncryptionKey and the AuthenticationKey.
protected abstract void DeriveKeys(byte[] buffer)
Parameters
buffer
byte[]The shared value computed by ECDH.
Exceptions
- ArgumentNullException
The
buffer
argument is null.- InvalidOperationException
The HMAC with SHA-256 provider failed.
Dispose()
Release resources, overwrite sensitive data.
public void Dispose()
Dispose(bool)
Release resources, overwrite sensitive data.
protected virtual void Dispose(bool disposing)
Parameters
disposing
bool
Encapsulate(CoseKey)
Generates a new platform key pair and uses the private key along with the peerPublicKey to compute the shared value. It then derives the shared keys (encryption and authentication) from the shared value.
public virtual void Encapsulate(CoseKey authenticatorPublicKey)
Parameters
authenticatorPublicKey
CoseKeyThe YubiKey's public key obtained by calling the GetKeyAgreementCommand.
Remarks
This will generate a new public and private key, compute the shared value, and discard the private key. The resulting public key will be found in the PlatformPublicKey property, and the derived keys will be found in the EncryptionKey and AuthenticationKey properties.
This method can be called only after instantiation or a call to Initialize(). Otherwise, this method will throw an exception.
Exceptions
- ArgumentNullException
The
authenticatorPublicKey
argument is null.- ArgumentException
The
authenticatorPublicKey
argument is not an appropriate key object (e.g. wrong algorithm).- InvalidOperationException
The object is not available for
Encapsulate
because it still contains data from a previous operation. It is necessary to callInitialize
before reusing a Protocol object.
Encrypt(byte[], int, int)
Returns the AES-256-CBC encryption of plaintext using an IV specified by the protocol and the EncryptionKey. With protocol 1 the IV is all 00 bytes. With protocol 2, it is a new, random value.
public abstract byte[] Encrypt(byte[] plaintext, int offset, int length)
Parameters
plaintext
byte[]The data to encrypt.
offset
intThe offset in
plaintext
where the method will begin encrypting.length
intThe number of bytes to encrypt.
Returns
- byte[]
A new byte array containing the encrypted data. With protocol 2, the ciphertext is actually the concatenation of the IV and the encrypted data.
Exceptions
- ArgumentNullException
The
plaintext
argument is null.- InvalidOperationException
The object has been created or initialized, but the Encapsulate(CoseKey) method has not been called.
- ArgumentException
The length of the
plaintext
is not a multiple of the AES block size (16 bytes).
Initialize()
This is run by the platform when starting a series of transactions with a specific authenticator.
public virtual void Initialize()
Remarks
This will reset the internal state of the object to the same as immediately after instantiation. Any data acquired, generated, or computed during operations in a session of PIN/UV Authentication with a specific authenticator will be lost.
Generally you will create an instance of one of the protocols and use
it to perform the appropriate PIN/UV authentication operations with
an authenticator. Then, to operate on a different authenticator (or
the same authenticator in a new session), create a new instance of
the protocol or reuse an existing object but call Initialize
before beginning operations.