Yubico / Yubico.NET.SDK

A YubiKey SDK for .NET developers
Apache License 2.0
96 stars 48 forks source link

Documentation: HMAC-SHA1 not implemented as the default algorithm for challenge-response #62

Closed joes closed 3 months ago

joes commented 7 months ago

I am using v1.9.0 of this SDK:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net6.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Yubico.YubiKey" Version="1.9.0" />
  </ItemGroup>

</Project>

Your documentation on How to calculate a response code for a challenge-response credential says this about HMAC-SHA1:

HMAC-SHA1 is the default algorithm; to use Yubico OTP, you must specify UseYubiOtp() in your code

And there's also this example for HMAC-SHA1 in the documentation:

using (OtpSession otp = new OtpSession(key))
{
  // The challenge, yOtpChal, has been set elsewhere.
  ReadOnlyMemory<byte> resp = otp.CalculateChallengeResponse(Slot.ShortPress)
    .UseChallenge(yOtpChal)
    .UseTouchNotifier(() => Console.WriteLine("Touch the key."))
    .GetDataBytes();
  string result = ModHex.EncodeBytes(resp.Span);
}

However, when I run this GetDataBytes() raises the following exception:

Unhandled exception. System.InvalidOperationException: You must choose either the HMAC-SHA1 or Yubico OTP algorithm for the challenge response.
   at Yubico.YubiKey.Otp.Operations.CalculateChallengeResponse.PreLaunchOperation()
   at Yubico.YubiKey.Otp.Operations.OperationBase`1.PreLaunch()
   at Yubico.YubiKey.Otp.Operations.OperationBase`1.Execute()
   at Yubico.YubiKey.Otp.Operations.CalculateChallengeResponse.GetDataBytes()
   at KeepassXcYubikeyChallengeResponseKeyGenerator.Program.Main(String[] args) 

Thus, it seems that HMAC-SHA1 is not selected by default as the docs will have you believe (or at least not in my case).

The only way I get this to run is by adding .UseYubiOtp(false) to the configuration/code as follows:

using (OtpSession otp = new OtpSession(key))
{
    // The challenge, yOtpChal, has been set elsewhere.
    ReadOnlyMemory<byte> resp = otp.CalculateChallengeResponse(Slot.LongPress)
      .UseChallenge(yOtpChal)
      .UseTouchNotifier(() => Console.WriteLine("Touch the key."))
      .UseYubiOtp(false)
      .GetDataBytes();
   string result = ModHex.EncodeBytes(resp.Span);
}
GregDomzalski commented 7 months ago

Thanks for the report. We'll get this updated on our docs soon.

samuel-lucas6 commented 3 months ago

Please can this be updated. I noticed the same thing when testing the library this morning.

DennisDyallo commented 3 months ago

Hi @samuel-lucas6 ! Our documentation currently builds from a private repository. We've now fixed the issue there, so this should be fixed the next time we rebuild the documentation

Regardless of the challenge type, you must call UseYubiOtp() when sending a challenge with CalculateChallengeResponse() (more specifially, call UseYubiOtp(false) for HOTP and TOTP challenges or UseYubiOtp(true) for Yubico OTP challenges). There is no default setting; an exception will occur if you do not call UseYubiOtp().

DennisDyallo commented 3 months ago

Closing now as the docs have now been updated. https://docs.yubico.com/yesdk/users-manual/application-otp/how-to-calculate-a-challenge-response-code.html#settings-and-quirks Thanks for the report @samuel-lucas6 !