RFC Errata

Errata Search

Source of RFC  
Summary Table Full Records

RFC 4226, "HOTP: An HMAC-Based One-Time Password Algorithm", December 2005

Area Assignment: sec

Errata ID: 6702
Status: Reported
Type: Technical
Publication Format(s) : TEXT

Reported By: Darian Miller
Date Reported: 2021-10-03

Section 5.2 says:

The Key (K), the Counter (C), and Data values are hashed high-order byte first.

It should say:

When hashing, the Key (K) value is provided in little-endian format while the Counter (C) value is in big-endian format.


This byte reversal for the Counter (movingFactor) value is indeed demonstrated in the RFC's reference implementation code within Appendix C but this fact is not mentioned within RFC text body.

byte[] text = new byte[8];
for (int i = text.length - 1; i >= 0; i--) {
text[i] = (byte) (movingFactor & 0xff);
movingFactor >>= 8;

This specific issue is called out in a related wikipedia article:
https://en.wikipedia.org/wiki/HMAC-based_one-time_password: "counter must be big endian"

This can also be verified by looking at archived source of Google Authenticator on GitHub: https://github.com/google/google-authenticator/blob/51781910ae2bb1abf8ac51b290272f86f3651235/mobile/ios/Classes/OTPGenerator.m

Related code snippet:
(counter = NSSwapHostLongLongToBig(counter);)

FreeOTP also reverses the byte order of the counter

code comment "// Encode counter in network byte order"
The code uses a Byte buffer which defaults to big_endian order.

Report New Errata