

/ Url Encoding (with upper-case hexadecimal per OATH specification) Return Pin.ToString(CultureInfo.InvariantCulture).PadLeft(PinLength, '0') generate number of digits for given pin length Var TruncatedHash = SelectedInteger & 0x7FFFFFFF remove the most significant bit for interoperability per spec Var SelectedInteger = BitConverter.ToInt32(SelectedBytes, 0) spec interprets bytes in big-endian order Var SelectedBytes = new byte īuffer.BlockCopy(Hash, Offset, SelectedBytes, 0, SizeOfInt32) Var Hash = new HMACSHA1(key).ComputeHash(CounterBytes) spec requires bytes in big-endian order Var CounterBytes = BitConverter.GetBytes(counter) Static string GeneratePin(byte key, long counter) / Generates a pin by hashing a key and counter. Return GeneratePin(key, CurrentInterval) Var ProvisionUrl = Encoder.UrlEncode(string.Format("otpauth://totp/", width, height, ProvisionUrl) Var KeyString = Encoder.Base32Encode(key)

Public byte GenerateProvisioningImage(string identifier, byte key, int width, int height) / Generates a QR code bitmap for provisioning. Var ElapsedSeconds = (long)Math.Floor((DateTime.UtcNow - Uni圎poch).TotalSeconds) / Number of intervals that have elapsed. Static readonly DateTime Uni圎poch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc) Static readonly int PinModulo = (int)Math.Pow(10, PinLength) Introduced check for little-endian byte ordering and convert to big-endian as necessary.įor more information on the provisioning url format, see also: įeel free to use if you like, and thanks to Espo for the initial work.I personally wasn't satisfied with the conversion from Java to C# and so I thought I would share my version. While playing around with Google Authenticator, I came across this question and in particular the code contributed by Espo.
