Ответ 1
В конце концов я обнаружил, что это было хорошо задокументировано в RFC 4226 и в отношении целочисленного преобразования это можно сделать с помощью побитового операция показанная на стр. 7, по существу, такая же, как в приведенном ниже ответе.
Был fooobar.com/questions/395964/... относительно этого в контексте С#, который, возможно, стоит прочитать, если вы находитесь в аналогичной позиции.
В С# я в основном, hashed идентификатор времени (т.е. текущее время в секундах, деленное на 30, чтобы получить длинный, который действителен для текущего 30-секундного интервала). Затем хэшировал это, используя мой секретный ключ как СОЛЬ.
И затем...
// Use a bitwise operation to get a representative binary code from the hash
// Refer section 5.4 at http://tools.ietf.org/html/rfc4226#page-7
int offset = hashBytes[19] & 0xf;
int binaryCode = (hashBytes[offset] & 0x7f) << 24
| (hashBytes[offset + 1] & 0xff) << 16
| (hashBytes[offset + 2] & 0xff) << 8
| (hashBytes[offset + 3] & 0xff);
// Generate the OTP using the binary code. As per RFC 4426 [link above] "Implementations MUST extract a 6-digit code at a minimum
// and possibly 7 and 8-digit code"
int otp = binaryCode % (int)Math.Pow(10, 6); // where 6 is the password length
return otp.ToString().PadLeft(6, '0');
Для тех из вас, кто не знал, Google Authenticator - проект с открытым исходным кодом - вы можете просмотреть исходный код здесь.