RequestHmacSecretExtension Method
RequestHmacSecretExtension(ReadOnlyMemory<Byte>, Nullable<ReadOnlyMemory<Byte>>)
Specify that the YubiKey should return the "hmac-secret" with the assertion. Provide the salt (or salts) to use, which must be exactly 32 bytes long. Once this extension is added to this object, it is not possible to remove it, although it is possible to "change" the salt by calling this method again with a different salt.
public void RequestHmacSecretExtension(ReadOnlyMemory<byte> salt1, Nullable<ReadOnlyMemory<byte>> salt2 = null)
Parameters
Type | Name | Description |
---|---|---|
System.ReadOnlyMemory<System.Byte> | salt1 | The salt the YubiKey will use in combination with the stored secret to build the resulting value. |
System.Nullable<System.ReadOnlyMemory<System.Byte>> | salt2 | An optional second salt the YubiKey can use in combination with the stored secret to build a second value. If no arg is given, the default of null will be used (the YubiKey will not build a second result). |
Exceptions
Type | Condition |
---|---|
System.ArgumentException | Either |
Remarks
Because this extension is used more often, a dedicated method is provided as a convenience. Note that the hmac-secret extension is valid for both discoverable and non-discoverable credentials.
Note that there will be an hmac-secret only if the credential was made with the "hmac-secret" extension. See AddHmacSecretExtension(AuthenticatorInfo). If the "hmac-secret" extension was not specified when making the credential, then the YubiKey will simply not return anything. It is not an error.
If you are getting assertions using GetAssertions(GetAssertionParameters), calling this method is sufficient, the SDK will take care of everything else needed to get the hmac-secret extension.
var gaParams = new GetAssertionParameters(relyingParty, clientDataHash);
gaParams.RequestHmacSecretExtension(salt);
IReadOnlyList<GetAssertionData> assertions = fido2.GetAssertions(gaParams);
But if you are getting assertions using the GetAssertionCommand, then you must call EncodeHmacSecretExtension(PinUvAuthProtocolBase) with an appropriate instance of PinUvAuthProtocolBase for which the Encapsulate(CoseKey) method has been successfully called. If the HmacSecret extension is not encoded, then it will not be sent to the YubiKey, and the value will not be returned.
var pinProtocol = new PinUvAuthProtocolTwo();
var keyAgreeCmd = new new GetKeyAgreementCommand(PinProtocol.Protocol);
GetKeyAgreementResponse keyAgreeRsp = Connection.SendCommand(keyAgreeCmd);
CoseEcPublicKey authenticatorPublicKey = keyAgreeRsp.GetData();
pinProtocol.Encapsulate(authenticatorPublicKey);
var getTokenCmd = new GetPinUvAuthTokenUsingPinCommand(
protocol, currentPin, PinUvAuthTokenPermissions.GetAssertion, null);
GetPinUvAuthTokenResponse getTokenRsp = Connection.SendCommand(getTokenCmd);
ReadOnlyMemory<byte> pinToken = getTokenRsp.GetData();
byte[] pinUvAuthParam = pinProtocol.AuthenticateUsingPinToken(
pinToken, clientDataHash);
var gaParams = new GetAssertionParameters(relyingParty, clientDataHash);
gaParams.Protocol = protocol.Protocol;
gaParams.PinUvAuthParam = pinUvAuthParam;
gaParams.AddOption("up", true);
gaParams.RequestHmacSecretExtension(salt);
gaParams.EncodeHmacSecretExtension(pinProtocol);
var cmd = new GetAssertionCommand(gaParams);
GetAssertionResponse rsp = connection.SendCommand(cmd);
GetAssertionData assertion = rsp.GetData();</code></pre>
The caller supplies a 32-byte salt which will be combined with the
YubiKey's secret stored with the credential to produce the output. A
second 32-byte salt is optional, but if provided, the YubiKey will
build a second result. The standard indicates that the second secret
is to be used when a secret rolls over.
The hmac-secret data will be returned with the assertion. The result
is returned in the
AuthenticatorData and can be
retrieved using
GetHmacSecretExtension(PinUvAuthProtocolBase)
References to the salt inputs will be stored in this object. If there
is already salt data in the object, this method will replace the
previous references with the new ones. It will also delete any
encoding (see EncodeHmacSecretExtension(PinUvAuthProtocolBase)).
If an invalid salt is passed in, this method will throw an exception.
In the unlikely event that you are replacing a salt, and you catch
the exception and use the GetAssertionParameters
object
anyway, the previous salt which was being replaced will be removed as
well. If salt1
is invalid, both previous salts will be
removed. For example, if there is a valid "salt1" and "salt2" in the
object, and you call this method with a valid salt1 and an invalid
salt2, then the original salt1 would be replaced and the original
salt2 would be removed. If you catch the exception and get an
assertion with this parameter object, only one hmac-secret value
would be returned, one based on salt1
.