You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
104 lines
2.9 KiB
104 lines
2.9 KiB
/**
|
|
* @file otp.cpp
|
|
*
|
|
* @brief Implementations of one-time-password-related functions.
|
|
*
|
|
* @copyright The contents of this file have been placed into the public domain;
|
|
* see the file COPYING for more details.
|
|
*/
|
|
|
|
#include "otp.h"
|
|
|
|
#include <iostream>
|
|
|
|
#include <cassert>
|
|
#include <cinttypes>
|
|
#include <cstring>
|
|
|
|
namespace CppTotp
|
|
{
|
|
|
|
Bytes::ByteString hmacSha1_64(const Bytes::ByteString & key, const Bytes::ByteString & msg)
|
|
{
|
|
return hmacSha1(key, msg, 64);
|
|
}
|
|
|
|
//uint32_t hotp(const Bytes::ByteString & key, const Bytes::ByteString & msg, size_t digitCount, HmacFunc hmacf)
|
|
uint32_t hotp(const Bytes::ByteString & key, uint64_t counter, size_t digitCount, HmacFunc hmacf)
|
|
{
|
|
Bytes::ByteString msg = Bytes::u64beToByteString(counter);
|
|
Bytes::ByteStringDestructor dmsg(&msg);
|
|
|
|
Bytes::ByteString hmac = hmacf(key, msg);
|
|
Bytes::ByteStringDestructor dhmac(&hmac);
|
|
|
|
uint32_t digits10 = 1;
|
|
for (size_t i = 0; i < digitCount; ++i)
|
|
{
|
|
digits10 *= 10;
|
|
}
|
|
|
|
// fetch the offset (from the last nibble)
|
|
uint8_t offset = hmac[hmac.size()-1] & 0x0F;
|
|
|
|
// fetch the four bytes from the offset
|
|
Bytes::ByteString fourWord = hmac.substr(offset, 4);
|
|
Bytes::ByteStringDestructor dfourWord(&fourWord);
|
|
|
|
// turn them into a 32-bit integer
|
|
uint32_t ret =
|
|
(fourWord[0] << 24) |
|
|
(fourWord[1] << 16) |
|
|
(fourWord[2] << 8) |
|
|
(fourWord[3] << 0)
|
|
;
|
|
|
|
// snip off the MSB (to alleviate signed/unsigned troubles)
|
|
// and calculate modulo digit count
|
|
return (ret & 0x7fffffff) % digits10;
|
|
}
|
|
|
|
uint32_t totp(const Bytes::ByteString & key, uint64_t timeNow, uint64_t timeStart, uint64_t timeStep, size_t digitCount, HmacFunc hmacf)
|
|
{
|
|
uint64_t timeValue = (timeNow - timeStart) / timeStep;
|
|
return hotp(key, timeValue, digitCount, hmacf);
|
|
}
|
|
|
|
}
|
|
|
|
#if TEST_OTP
|
|
int main(void)
|
|
{
|
|
using namespace CppTotp;
|
|
|
|
uint64_t start = 0;
|
|
uint64_t step = 30;
|
|
uint8_t digitsH = 6;
|
|
uint8_t digitsT = 8;
|
|
const Bytes::ByteString key = reinterpret_cast<const uint8_t *>("12345678901234567890");
|
|
|
|
std::cout
|
|
<< (hotp(key, 0, digitsH) == 755224)
|
|
<< (hotp(key, 1, digitsH) == 287082)
|
|
<< (hotp(key, 2, digitsH) == 359152)
|
|
<< (hotp(key, 3, digitsH) == 969429)
|
|
<< (hotp(key, 4, digitsH) == 338314)
|
|
<< (hotp(key, 5, digitsH) == 254676)
|
|
<< (hotp(key, 6, digitsH) == 287922)
|
|
<< (hotp(key, 7, digitsH) == 162583)
|
|
<< (hotp(key, 8, digitsH) == 399871)
|
|
<< (hotp(key, 9, digitsH) == 520489)
|
|
<< (totp(key, 59, start, step, digitsT) == 94287082)
|
|
<< (totp(key, 1111111109, start, step, digitsT) == 7081804)
|
|
<< (totp(key, 1111111111, start, step, digitsT) == 14050471)
|
|
<< (totp(key, 1234567890, start, step, digitsT) == 89005924)
|
|
<< (totp(key, 2000000000, start, step, digitsT) == 69279037)
|
|
<< (totp(key, 20000000000, start, step, digitsT) == 65353130)
|
|
<< std::endl;
|
|
|
|
const Bytes::ByteString tutestkey = reinterpret_cast<const uint8_t *>("HelloWorld");
|
|
std::cout << totp(tutestkey, time(NULL), 0, 30, 6) << std::endl;
|
|
|
|
return 0;
|
|
}
|
|
#endif
|
|
|