OtpCore 1.2.0-dev-72
See the version list below for details.
dotnet add package OtpCore --version 1.2.0-dev-72
NuGet\Install-Package OtpCore -Version 1.2.0-dev-72
<PackageReference Include="OtpCore" Version="1.2.0-dev-72" />
paket add OtpCore --version 1.2.0-dev-72
#r "nuget: OtpCore, 1.2.0-dev-72"
// Install OtpCore as a Cake Addin #addin nuget:?package=OtpCore&version=1.2.0-dev-72&prerelease // Install OtpCore as a Cake Tool #tool nuget:?package=OtpCore&version=1.2.0-dev-72&prerelease
<img src="OTP.png" width="28" height="28" /> OtpCore
HOTP, TOTP, OTP Auth URI, and Base32 implementation in C# targeting .NET standard 2.0, compliant with:
It has been verified against test vectors supplied in the RFCs. The interface includes support for multiple algorithms:
- HMAC-SHA1
- HMAC-SHA256
- HMAC-SHA384
- HMAC-SHA512
It supports variable code lengths (6 - 10) and an adjustable period, or time step, (1 second - 1 hour) for TOTP.
The reason for creating this library was to fetch multiple HOTP counters or a TOTP time range in a single call.
A parser for OTP Auth URIs (otpauth://) is also included that conforms to the documentation found at: https://github.com/google/google-authenticator/wiki/Key-Uri-Format.
This implementation also includes a Base32 encoder and decoder. It is compliant with RFC 4648, using the standard alphabet from section 6, and has been tested against the test vectors from section 10.
It's free. Enjoy!
Examples
Authenticators
OtpCore provides HotpAuthenticator
and TotpAuthenticator
classes which can be instantiated from a
OTP Auth URI using the GetAuthenticator()
method in the Hotp
and Totp
classes.
HOTP
// Create from string
var uriString = "otpauth://hotp/NOBODY:petrsnd@gmail.com?issuer=NOBODY&secret=GEZDGNBVGY3TQOJQGEZDGNBVGY3TQOJQ&algorithm=SHA1&digits=6&counter=0";
var authenticator = Hotp.GetAuthenticator(uriString);
// Create from Uri object
var uri = new Uri(uriString);
authenticator = Hotp.GetAuthenticator(uri);
// Create from scratch by supplying parameters
var secret = Encoding.ASCII.GetBytes("12345678901234567890");
var account = "bob@example.corp";
var issuer = "Example";
var counter = 0;
var otpAuthUri = new OtpAuthUri(OtpType.Hotp, secret, account, issuer, counter); // issuer is optional, digits defaults to 6
authenticator = Hotp.GetAuthenticator(otpAuthUri);
// Get a code or a sequence of codes
var code = authenticator.GetCode();
var sequence = authenticator.GetSequence(3);
// Increment or set the counter
authenticator.IncrementCounter();
authenticator.SetCounter(3);
// Revert back to a string for storage with updated counter in URI
// The URI is left unchanged unless IncrementCounter() or SetCounter() are called
uriString = authenticator.ToString();
TOTP
// Create from string
var uriString = "otpauth://totp/NOBODY:petrsnd@gmail.com?issuer=NOBODY&secret=GEZDGNBVGY3TQOJQGEZDGNBVGY3TQOJQGEZDGNBVGY3TQOJQGEZA&algorithm=SHA256&digits=8";
var authenticator = Totp.GetAuthenticator(uriString);
// Create from Uri object
var uri = new Uri(uriString);
authenticator = Totp.GetAuthenticator(uri);
// Create from scratch by supplying parameters
var secret = Encoding.ASCII.GetBytes("12345678901234567890");
var account = "bob@example.corp";
var issuer = "Example";
// issuer is optional, digits defaults to 6, period defaults to 30
var otpAuthUri = new OtpAuthUri(OtpType.Totp, secret, account, issuer);
authenticator = Totp.GetAuthenticator(otpAuthUri);
// Get a code or a range of codes
var code = authenticator.GetCode();
var range = authenticator.GetRange(TimeSpan.FromSeconds(90));
// No counter to manage with TOTP. Yay!!!
// Revert back to a string for storage if it was created from scratch
uriString = authenticator.ToString();
Static Methods
OtpCore may also be used as a static utility library by only calling the static methods for HOTP and TOTP. When used this way, no object tracks counters or store secrets.
Fetch a simple code.
// Hotp
var secret = Encoding.ASCII.GetBytes("12345678901234567890");
long counter = 0;
int digits = 6;
var hotpCode = Hotp.GetHotpCode(secret, counter, OtpHmacAlgorithm.HmacSha1, digits));
// Totp
int period = 30;
digits = 8;
long unixTime = 1111111111; // 2005-03-18 01:58:31 +0:00
var totpCode = Totp.GetTotpCode(secret, unixTime, period, OtpHmacAlgorithm.HmacSha1, digits);
var timeFuture = DateTimeOffset.Parse("2033-05-18 03:33:20 -7:00"); // future DateTimeOffset
totpCode = Totp.GetTotpCode(secret, timeFuture, period, OtpHmacAlgorithm.HmacSha1, digits);
totpCode = Totp.GetTotpCode(secret, DateTimeOffset.Now, period, OtpHmacAlgorithm.HmacSha1, digits); // Now
Fetch multiple codes.
// Hotp
var secret = Encoding.ASCII.GetBytes("12345678901234567890");
long counter = 0;
int sequenceLength = 5; // next 5 codes
int digits = 6;
var hotpValues = Hotp.GetHotpSequence(secret, counter, sequenceLength, OtpHmacAlgorithm.HmacSha1, digits));
// Totp
int period = 30;
digits = 8;
var range = TimeSpan.FromSeconds(120); // two minutes worth of codes
var totpValues = Totp.GetTotpRange(secret, DateTimeOffset.Now, range, period, OtpHmacAlgorithm.HmacSha1, digits);
- HOTP Values format: HotpValue.cs
- TOTP Values format: TotpValue.cs
Base32 Encoding and Decoding
You may just want a simple Base32 encoder/decoder, because it isn't supplied in the .NET SDK.
var buffer = Encoding.ASCII.GetBytes("12345678901234567890");
var encoded = Utilities.Base32Encode(buffer); // GEZDGNBVGY3TQOJQGEZDGNBVGY3TQOJQ
var decoded = Utilities.Base32Decode(encoded);
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. |
.NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
.NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
.NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
MonoAndroid | monoandroid was computed. |
MonoMac | monomac was computed. |
MonoTouch | monotouch was computed. |
Tizen | tizen40 was computed. tizen60 was computed. |
Xamarin.iOS | xamarinios was computed. |
Xamarin.Mac | xamarinmac was computed. |
Xamarin.TVOS | xamarintvos was computed. |
Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.0
- No dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
Version | Downloads | Last updated |
---|---|---|
1.2.0-dev-78 | 82 | 10/3/2024 |
1.2.0-dev-72 | 79 | 10/3/2024 |
1.2.0-dev-70 | 78 | 10/3/2024 |
1.2.0-dev-67 | 186 | 7/5/2023 |
1.2.0-dev-66 | 198 | 1/24/2023 |
1.2.0-dev-65 | 195 | 1/24/2023 |
1.2.0-dev-64 | 181 | 1/24/2023 |
1.2.0-dev-58 | 186 | 1/24/2023 |
1.1.4 | 232 | 10/3/2024 |
1.1.2 | 2,689 | 1/24/2023 |
1.1.1 | 370 | 1/23/2023 |
1.1.0 | 397 | 1/17/2023 |
1.1.0-dev-54 | 181 | 1/23/2023 |
1.1.0-dev-52 | 179 | 1/23/2023 |
1.1.0-dev-48 | 204 | 1/17/2023 |
1.1.0-dev-46 | 178 | 1/17/2023 |
1.1.0-dev-44 | 187 | 1/17/2023 |
1.1.0-dev-40 | 198 | 1/16/2023 |
1.1.0-dev-32 | 215 | 8/18/2022 |
1.1.0-dev-28 | 197 | 8/18/2022 |
1.1.0-dev-24 | 189 | 8/17/2022 |
1.1.0-dev-22 | 207 | 7/30/2022 |
1.0.3 | 528 | 8/18/2022 |
1.0.2 | 482 | 8/17/2022 |
1.0.1 | 508 | 7/30/2022 |
1.0.1-dev-17 | 224 | 7/30/2022 |
1.0.0 | 515 | 7/29/2022 |
0.9.0-dev-9 | 203 | 7/29/2022 |
0.9.0-dev-8 | 199 | 7/29/2022 |
0.9.0-dev-7 | 189 | 7/29/2022 |
0.9.0-dev-6 | 208 | 7/28/2022 |
0.9.0-dev-14 | 220 | 7/29/2022 |
0.9.0-dev-13 | 210 | 7/29/2022 |
0.9.0-dev-12 | 207 | 7/29/2022 |
0.9.0-dev-11 | 205 | 7/29/2022 |
0.9.0-dev-10 | 211 | 7/29/2022 |
- Tested against more 2FA provider URIs to ensure compatibility
- Added a test tool for generating QR codes
- Fixed some library and parsing bugs