Skip to content

Commit d9574d2

Browse files
committed
commits from PR204
1 parent 11389a1 commit d9574d2

File tree

3 files changed

+65
-77
lines changed

3 files changed

+65
-77
lines changed

docs/users-manual/application-otp/challenge-response.md

Lines changed: 38 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,10 @@ limitations under the License. -->
2020

2121
The other OTP application configurations ([Yubico OTP](xref:OtpYubicoOtp), [OATH HOTP](xref:OtpHotp),
2222
and [static password](xref:OtpStaticPassword)) require the user to activate the configured [slot](xref:OtpSlots) (by
23-
touching the YubiKey or scanning it with an [NFC reader](xref:OtpNdef)) in order to generate and submit the password
23+
touching the YubiKey or scanning it with an [NFC reader](xref:OtpNdef)) in order to generate and transmit the password
2424
from the YubiKey to a host device. Challenge-response, on the other hand, begins with a “challenge” that a host sends to
25-
the YubiKey. The YubiKey receives the challenge (as a byte array) and “responds” by encrypting or digesting (hashing)
26-
the challenge with a stored secret key and sending the response code back to the host for authentication.
25+
the YubiKey. The YubiKey receives the challenge as a byte array and “responds” by encrypting or digesting (hashing)
26+
the challenge with a stored secret key and sending the response back to the host for authentication.
2727

2828
Challenge-response is flexible. It can be used in single and multi-factor authentication for logging into applications
2929
or devices, and validation can take place on a host device itself or on a validation server on an internal or external
@@ -39,34 +39,36 @@ To implement challenge-response authentication with a .NET application, the foll
3939

4040
* The validating party must be able to validate responses and pass the result back to the application.
4141

42-
> [!NOTE]
42+
> [!IMPORTANT]
4343
> All YubiKey-host communication for challenge-response is done via the [HID communication protocol](xref:OtpHID).
4444
> Therefore, challenge-response authentication will only work when a YubiKey is physically plugged into a host over USB
4545
> or
4646
> Lightning. Challenges and responses cannot be communicated wirelessly with NFC.
4747
4848
## Supported challenge-response algorithms
4949

50-
The .NET SDK and the YubiKey support the following encryption and hashing algorithms for challenge-response:
50+
The .NET SDK and the YubiKey support the following algorithms for challenge-response:
5151

5252
* [Yubico OTP](xref:OtpYubicoOtp) (encryption)
5353

5454
* HMAC-SHA1 as defined in [RFC2104](https://datatracker.ietf.org/doc/html/rfc2104) (hashing)
5555

56-
For Yubico OTP challenge-response, the key will receive a 6-byte challenge. The YubiKey will then create a 16-byte
56+
For Yubico OTP challenge-response, an application will send the YubiKey a 6-byte challenge. The YubiKey will then create a 16-byte
5757
string by concatenating the challenge with 10 bytes of unique device fields. For Yubico OTP challenge-response, these 10
58-
bytes of additional data are not important. They are merely added as padding so that the challenge may then be encrypted
58+
bytes of additional data are not important—they are merely added as padding so that the challenge may then be encrypted
5959
with a 16-byte key using the AES encryption algorithm (AES requires that data be encrypted in blocks of the same size as
60-
the encryption key). The resulting Yubico OTP becomes the response code.
60+
the encryption key). The resulting Yubico OTP (as a byte array) becomes the response.
6161

62-
For HMAC-SHA1 challenge-response, the key will receive a challenge of up to 64 bytes in size, which will be digested (
63-
hashed) with a 20-byte secret key, resulting in a 6-10 digit HOTP as the response code.
62+
For HMAC-SHA1 challenge-response, an application will send the YubiKey a challenge of up to 64 bytes in size, which will be digested (
63+
hashed) with a 20-byte secret key, resulting in a 20-byte response (the HMAC-SHA1 hash value). Responses can be received
64+
by an application as a byte array or a 6-10 digit numeric code. With HMAC-SHA1, the challenge can be either an
65+
application-specified byte array or the current Unix time.
6466

6567
> [!NOTE]
6668
> Hashing/digesting is a one-way operation, meaning that once a block of data is hashed, it cannot be converted back
6769
> into its original form. Encryption, on the other hand, is a two-way operation. When a block of data is encrypted, it
6870
> can
69-
> be decrypted back into its original form at any time. This is an important distinction because the validating party
71+
> be decrypted back into its original form. This is an important distinction because the validating party
7072
> will
7173
> have to respond differently to Yubico OTP responses (encrypted) and HMAC-SHA1 responses (hashed). For Yubico OTP, the
7274
> validating party will have to decrypt the response and compare the result with the original challenge. For HMAC-SHA1,
@@ -85,23 +87,18 @@ The challenge-response process works as follows:
8587
1. The YubiKey receives the challenge and encrypts/digests it with the secret key and encryption/hashing algorithm that
8688
the slot was configured with.
8789

88-
1. The YubiKey sends the response back to the host, and the application receives it as a string object containing
89-
numeric digits, a byte array, or a single integer (as determined by the SDK).
90+
1. The YubiKey sends the response back to the host, and the application receives it as a raw byte array, a string object of
91+
numeric digits, or an integer (as configured with the SDK).
9092

9193
1. The application sends the response to the validating party. For Yubico OTP challenge-response, the response must be
9294
decrypted using the YubiKey’s unique secret key. For HMAC-SHA1 challenge-response, the validating party must digest
93-
the challenge with the secret key using the same HMAC-SHA1 algorithm.
95+
the challenge with the secret key and the HMAC-SHA1 algorithm.
9496

9597
1. For Yubico OTP, if the decrypted response matches the original challenge that was sent to the YubiKey, authentication
9698
was successful, and the user is logged in. (For Yubico OTP challenge-response, the 6-byte challenge must match the
9799
first 6 bytes of the decrypted response—the other bytes are ignored.) For HMAC-SHA1, if the response matches the
98100
validating party's digested challenge, authentication was successful, and the user is logged in.
99101

100-
> [!NOTE]
101-
> For the authentication process to succeed, the size of the challenge must align with the algorithm that the YubiKey
102-
> was configured with. Similarly, the validating party must decrypt the response using the same algorithm that the
103-
> challenge was encrypted with.
104-
105102
## SDK functionality
106103

107104
The SDK’s challenge-response functionality centers around the following two methods:
@@ -131,10 +128,8 @@ call ``UseHmacSha1()``, the YubiKey will digest challenges it receives with the
131128
> [!NOTE]
132129
> It’s important that the size of your secret key matches the size that is expected for the algorithm you
133130
> chose ([16 bytes](xref:Yubico.YubiKey.Otp.Operations.ConfigureChallengeResponse.YubiOtpKeySize) for Yubico OTP
134-
> and [20 bytes](xref:Yubico.YubiKey.Otp.Operations.ConfigureChallengeResponse.HmacSha1KeySize) for HMAC-SHA1). For
135-
> example, if you call ``UseYubiOtp()``, the key that you set with ``UseKey()`` must be 16 bytes long. Otherwise, the
136-
> YubiKey will not be able to respond to a challenge correctly. The SDK will throw an exception if the key length is
137-
> incorrect for the chosen configuration.
131+
> and [20 bytes](xref:Yubico.YubiKey.Otp.Operations.ConfigureChallengeResponse.HmacSha1KeySize) for HMAC-SHA1). The SDK will throw an exception if the key length is
132+
> incorrect for the chosen algorithm.
138133
139134
The ``ConfigureChallengeResponse`` class also provides optional methods for requiring users to touch the YubiKey to
140135
initiate the challenge-response
@@ -146,52 +141,48 @@ bytes ([UseSmallChallenge()](xref:Yubico.YubiKey.Otp.Operations.ConfigureChallen
146141
> ``UseSmallChallenge()`` is included for compatibility with legacy systems whose implementations break data sets into
147142
> multiple blocks, which often results in the last element being smaller than 64 bytes.
148143
149-
For a full list of the methods in the ``ConfigureChallengeResponse`` class, please see
144+
For a full list of the methods in the ``ConfigureChallengeResponse`` class, see
150145
the [API documentation](xref:Yubico.YubiKey.Otp.Operations.ConfigureChallengeResponse).
151146

152-
For an example of how to use ``ConfigureChallengeResponse()``, please
153-
see [How to program a slot with a challenge-response credential](xref:OtpProgramChallengeResponse).
147+
For an example of how to use ``ConfigureChallengeResponse()``, see
148+
[How to program a slot with a challenge-response credential](xref:OtpProgramChallengeResponse).
154149

155150
### CalculateChallengeResponse()
156151

157152
In order for a host to send a challenge to a YubiKey and receive a response, an application on the host must
158153
call ``CalculateChallengeResponse()``. With this method, you can:
159154

160-
* send the challenge to the YubiKey as a byte array
161-
with [UseChallenge()](xref:Yubico.YubiKey.Otp.Operations.CalculateChallengeResponse.UseChallenge%28System.Byte%5B%5D%29).
155+
* send a Yubico OTP or HMAC-SHA1 challenge to the YubiKey as an application-specified byte array
156+
with [UseChallenge()](xref:Yubico.YubiKey.Otp.Operations.CalculateChallengeResponse.UseChallenge%28System.Byte%5B%5D%29).
157+
Alternatively, the current Unix time can be sent as a challenge with
158+
[UseTotp()](xref:Yubico.YubiKey.Otp.Operations.CalculateChallengeResponse.UseTotp) for HMAC-SHA1 challenge-response.
162159

163160
* send a message to the user to notify them to touch the YubiKey to initiate the challenge-response operation
164161
with [UseTouchNotifier()](xref:Yubico.YubiKey.Otp.Operations.CalculateChallengeResponse.UseTouchNotifier%28System.Action%29).
165162
This is only needed if the YubiKey slot was configured to require the button touch with ``UseButton()``.
166163

167-
* receive the response from the YubiKey. The response can be received as a string object of numeric digits
168-
via [GetCode()](xref:Yubico.YubiKey.Otp.Operations.CalculateChallengeResponse.GetCode%28System.Int32%29), as a byte
169-
array via [GetDataBytes()](xref:Yubico.YubiKey.Otp.Operations.CalculateChallengeResponse.GetDataBytes) (the only
170-
response type that is compatible with Yubico OTPs), or as a single 32-bit integer
171-
via [GetDataInt()](xref:Yubico.YubiKey.Otp.Operations.CalculateChallengeResponse.GetDataInt).
164+
* receive the response from the YubiKey. The response can be received as a string object of 6-10 numeric digits
165+
via [GetCode()](xref:Yubico.YubiKey.Otp.Operations.CalculateChallengeResponse.GetCode%28System.Int32%29) (HMAC-SHA1), as a byte
166+
array via [GetDataBytes()](xref:Yubico.YubiKey.Otp.Operations.CalculateChallengeResponse.GetDataBytes) (Yubico OTP, HMAC-SHA1), or as a single 10-digit, 32-bit integer
167+
via [GetDataInt()](xref:Yubico.YubiKey.Otp.Operations.CalculateChallengeResponse.GetDataInt) (HMAC-SHA1).
168+
169+
In addition, the time period for time-based challenges sent with ``UseTotp()`` (i.e. how long a TOTP response is valid for) can be set
170+
via [WithPeriod()](xref:Yubico.YubiKey.Otp.Operations.CalculateChallengeResponse.WithPeriod%28System.Int32%29). The
171+
default period is 30 seconds. Time-based challenges can only be used with keys configured for HMAC-SHA1 challenge-response.
172+
The SDK will throw an exception if you call both ``UseTotp()`` and ``UseChallenge()``.
172173

173174
> [!NOTE]
174175
> The size of the challenge sent to the YubiKey with ``UseChallenge()`` must align with the slot's configuration. If the
175176
> slot is configured to perform Yubico OTP, the challenge must
176177
> be [6 bytes](xref:Yubico.YubiKey.Otp.Operations.CalculateChallengeResponse.YubicoOtpChallengeSize) long. If the slot
177178
> is
178-
> configured for HMAC-SHA1, the challenge must
179+
> configured for HMAC-SHA1, the HOTP challenge must
179180
> be [64 bytes](xref:Yubico.YubiKey.Otp.Operations.CalculateChallengeResponse.MaxHmacChallengeSize) long. However, if
180181
> the
181-
> slot has been configured with ``UseSmallChallenge()``, an HMAC-SHA1 challenge smaller than 64 bytes is acceptable. The
182+
> slot has been configured with ``UseSmallChallenge()``, an HOTP challenge smaller than 64 bytes is acceptable. The
182183
> SDK will throw an exception if the challenge size does not match the YubiKey slot's configuration.
183184
184-
Alternatively, the application can send a TOTP challenge to the YubiKey
185-
with [UseTotp()](xref:Yubico.YubiKey.Otp.Operations.CalculateChallengeResponse.UseTotp). The time period of the TOTP
186-
challenge (i.e. how long a TOTP is valid for) can be set
187-
via [WithPeriod()](xref:Yubico.YubiKey.Otp.Operations.CalculateChallengeResponse.WithPeriod%28System.Int32%29) (the
188-
default period is 30 seconds). TOTP challenges can only be used with keys configured for HMAC-SHA1 challenge-response.
189-
With ``UseTotp()``, the application will send the current time as the challenge, and the YubiKey will digest it with the
190-
stored secret key and the HMAC-SHA1 algorithm. The SDK will throw an exception if you call both ``UseTotp()``
191-
and ``UseChallenge()``.
192-
193-
For a full list of the methods in the ``CalculateChallengeResponse`` class, please see
185+
For a full list of the methods in the ``CalculateChallengeResponse`` class, see
194186
the [API documentation](xref:Yubico.YubiKey.Otp.Operations.CalculateChallengeResponse).
195187

196-
For an example of how to use ``CalculateChallengeResponse()``, please
197-
see [How to calculate a response code for a challenge-response credential](xref:OtpCalcChallengeResponseCode).
188+
For an example of how to use ``CalculateChallengeResponse()``, see [How to calculate a response code for a challenge-response credential](xref:OtpCalcChallengeResponseCode).

docs/users-manual/application-otp/how-to-calculate-a-challenge-response-code.md

Lines changed: 22 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -25,23 +25,21 @@ a [CalculateChallengeResponse](xref:Yubico.YubiKey.Otp.Operations.CalculateChall
2525
instantiated by calling the factory method of the same name on your [OtpSession](xref:Yubico.YubiKey.Otp.OtpSession)
2626
instance.
2727

28-
You can send three types of challenges to a YubiKey:
28+
You can send two types of challenges to a YubiKey:
2929

30-
- [HMAC-SHA1](https://datatracker.ietf.org/doc/html/rfc2104)
31-
- [Yubico OTP](xref:OtpYubicoOtp)
32-
- [Time-based one-time password (TOTP)](https://www.yubico.com/resources/glossary/oath-totp/)
30+
- an application-specified byte array (Yubico OTP and HMAC-SHA1)
31+
- the current Unix time (HMAC-SHA1 configurations only)
3332

34-
The challenge type must align with the type of credential that the YubiKey was programmed with, otherwise an exception
35-
will occur. To send an HMAC-SHA1 or TOTP challenge, the key must be programmed with an HMAC-SHA1 credential. To send a
36-
Yubico OTP challenge, the key must be programmed with a Yubico OTP credential.
33+
The challenge type and size must align with the type of credential that the YubiKey was programmed with, otherwise an exception
34+
will be thrown.
3735

38-
For HMAC-SHA1 and TOTP challenge-response, the YubiKey will digest the challenge with the HMAC-SHA1 credential that it
39-
was programmed with. The resulting code can then be compared to the code produced by the validation server via the same
40-
hashing operation. For Yubico OTP challenge-response, the YubiKey will encrypt the challenge using its Yubico OTP
41-
credential, producing a Yubico OTP. This OTP can then be decrypted by the validation server with the credential's secret
36+
For HMAC-SHA1 challenge-response, the YubiKey will digest the challenge with the HMAC-SHA1 credential that it
37+
was programmed with. The resulting hash value can then be compared to the hash value produced by the validation server via the HMAC-SHA1 algorithm.
38+
For Yubico OTP challenge-response, the YubiKey will encrypt the challenge using its Yubico OTP
39+
credential, producing a Yubico OTP (as a byte array). This OTP can then be decrypted by the validation server with the credential's secret
4240
key.
4341

44-
## Response code types
42+
## Response types
4543

4644
The response from a YubiKey can be received via one of three methods:
4745

@@ -51,10 +49,10 @@ The response from a YubiKey can be received via one of three methods:
5149
will be returned by default unless a larger number is specified when calling this method (for
5250
example, ``GetCode(8)``).
5351
1. [GetDataBytes()](xref:Yubico.YubiKey.Otp.Operations.CalculateChallengeResponse.GetDataBytes): returns a byte array.
54-
1. [GetDataInt()](xref:Yubico.YubiKey.Otp.Operations.CalculateChallengeResponse.GetDataInt): returns a single 32-bit
55-
integer. For HOTP challenges, the integer returned will represent the same number as ``GetCode(10)``.
52+
1. [GetDataInt()](xref:Yubico.YubiKey.Otp.Operations.CalculateChallengeResponse.GetDataInt): returns a single 10-digit, 32-bit
53+
integer. The integer returned will represent the same code as ``GetCode(10)``.
5654

57-
Any of these response methods can be used for HOTP and TOTP challenges. However, ``GetDataBytes()`` is the only
55+
Any of these response methods can be used for HMAC-SHA1 challenges. However, ``GetDataBytes()`` is the only
5856
compatible method for Yubico OTP challenges.
5957

6058
## Touch
@@ -79,21 +77,20 @@ When the YubiKey requires a touch, the SDK spawns your handler as a Task. There
7977

8078
Regardless of the challenge type, you must
8179
call [UseYubiOtp()](xref:Yubico.YubiKey.Otp.Operations.CalculateChallengeResponse.UseYubiOtp%28System.Boolean%29) when
82-
sending a challenge with ``CalculateChallengeResponse()`` (more specifially, call ``UseYubiOtp(false)`` for HOTP and
83-
TOTP challenges or ``UseYubiOtp(true)`` for Yubico OTP challenges). There is no default setting; an exception will occur
80+
sending a challenge with ``CalculateChallengeResponse()`` Specifically, call ``UseYubiOtp(false)`` for HMAC-SHA1 challenges
81+
or ``UseYubiOtp(true)`` for Yubico OTP challenges. There is no default setting; an exception will occur
8482
if you do not call ``UseYubiOtp()``.
8583

8684
For Yubico OTP challenge-response, the challenge must be 6 bytes
8785
long ([YubicoOtpChallengeSize](xref:Yubico.YubiKey.Otp.Operations.CalculateChallengeResponse.YubicoOtpChallengeSize)).
88-
For HOTP and TOTP challenge-response, the challenge must be 64 bytes
86+
For HMAC SHA-1 challenge-response, the application-specified challenge must be 64 bytes
8987
long ([MaxHmacChallengeSize](xref:Yubico.YubiKey.Otp.Operations.CalculateChallengeResponse.MaxHmacChallengeSize)) unless
9088
the YubiKey was previously configured
9189
with [UseSmallChallenge()](xref:Yubico.YubiKey.Otp.Operations.ConfigureChallengeResponse.UseSmallChallenge%28System.Boolean%29).
9290

93-
Additionally, for TOTP challenges, you can set the time period that the response code is valid for
91+
Additionally, for time-based HMAC-SHA1 challenges sent with [UseTotp()](xref:Yubico.YubiKey.Otp.Operations.CalculateChallengeResponse.UseTotp), you can set the time period that the response is valid for
9492
via [WithPeriod()](xref:Yubico.YubiKey.Otp.Operations.CalculateChallengeResponse.WithPeriod%28System.Int32%29) (the
95-
default is 30 seconds). Calling this method with an HMAC-SHA1 or Yubico OTP challenge will still succeed, but it has no
96-
effect on the challenge sent to the YubiKey.
93+
default is 30 seconds).
9794

9895
## CalculateChallengeResponse() examples
9996

@@ -110,7 +107,7 @@ var yubiKey = yubiKeyList.First();
110107

111108
### HMAC-SHA1 challenge-response example
112109

113-
In this example, we send an HOTP challenge (``hmacChal``) to the short press slot of the YubiKey
110+
In this example, we send an HMAC-SHA1 challenge (``hmacChal``) to the short press slot of the YubiKey
114111
with [UseChallenge()](xref:Yubico.YubiKey.Otp.Operations.CalculateChallengeResponse.UseChallenge%28System.Byte%5B%5D%29)
115112
and get the response as a string object containing eight 32-bit integers via ``GetCode()``.
116113

@@ -122,7 +119,7 @@ configured with an HMAC-SHA1 credential for this operation to succeed.
122119
```C#
123120
using (OtpSession otp = new OtpSession(yubiKey))
124121
{
125-
// The challenge, hmacChal, has been set elsewhere.
122+
// The challenge, hmacChal, was set elsewhere.
126123
string result = otp.CalculateChallengeResponse(Slot.ShortPress)
127124
.UseChallenge(hmacChal)
128125
.UseYubiOtp(false)
@@ -143,7 +140,7 @@ The YubiKey's short press slot must be configured with a Yubico OTP credential f
143140
```C#
144141
using (OtpSession otp = new OtpSession(yubiKey))
145142
{
146-
// The challenge, yOtpChal, has been set elsewhere.
143+
// The challenge, yOtpChal, was set elsewhere.
147144
ReadOnlyMemory<byte> resp = otp.CalculateChallengeResponse(Slot.ShortPress)
148145
.UseChallenge(yOtpChal)
149146
.UseYubiOtp(true)
@@ -153,7 +150,7 @@ using (OtpSession otp = new OtpSession(yubiKey))
153150
}
154151
```
155152

156-
### TOTP challenge-response example
153+
### Time-based HMAC-SHA1 challenge-response example
157154

158155
In this final example, we send a time-based challenge to the long press slot of the key
159156
with [UseTotp()](xref:Yubico.YubiKey.Otp.Operations.CalculateChallengeResponse.UseTotp) and get the response from the

0 commit comments

Comments
 (0)