i am trying to implement google Authenticator mechanism in c++. i always get different OTP than that of google authenticator.
i wonder why ?
1 - i searched and found that google uses HMAC-SHA1 algorithm. but i am suspecious because :
- almost all articles i have read are old. seems irrelevent.
- i found that google authenticator code is now private before it was open source. so am afraid google might changed the algorithim used
- i found that SHA1 is no longer secure. some people managed to make SHA1-collision. i would be surprized if google still uses it instead of other more secure algorithms like SHA256,SHA512.
if you have any information regarding that, please inform me.
2 - i am sure my code is correct.
because i compared the output Hash value to automatically generated one in this website, and they always match. the website : https://www.liavaag.org/English/SHA-Generator/HMAC/
because code is pretty simple!
here's the code :
/*****************************************************************************************/
#include <iostream>
#include <cmath>
#include <ctime>
#include <stdio.h>
#include <string>
#include "SHA1.h"
#include "HMAC_SHA1.h"
using namespace std;
void IntegerToString(time_t epochTime, BYTE timeAsString[] , int length);
int TimeLength(time_t epochTime);
int main(void)
{
CHMAC_SHA1 sha1;
int one,two,three,four;
time_t result = time(nullptr);
result = (long long)floor(result/30);
cout << result <<endl;
int offset;
int truncatedHash;
int finalOTP;
BYTE key[33] = "atoqb4y572clkhj2sls5h72a76cnyzpe";
int key_len = 33; /*32 + null terminator*/
int text_len = TimeLength(result);
//cout << text_len << endl;
BYTE text[text_len+1];
IntegerToString(result , text , text_len);
text[text_len] = '\0';
//printf("%s",text);
/*the digest is always 20 bytes long*/
BYTE digest[20] = {0};
sha1.HMAC_SHA1(text,text_len,key,key_len-1,digest);
printf("0x");
for(int i = 0 ; i < 20 ; i++)
{
printf("%x",(int)digest[i]);
}
offset = digest[19] & 0xf;
one = (digest[offset+0] & 0x7f) << 24;
two = (digest[offset+1] & 0xff) << 16;
three = (digest[offset+2] & 0xff) << 8;
four = (digest[offset+3] & 0xff);
truncatedHash = one | two | three | four;
finalOTP = (truncatedHash % (1000000));
cout << "\nyour OTP : " << finalOTP << endl;
return 0;
}
void IntegerToString(time_t epochTime, BYTE timeAsString[] , int length)
{
time_t reverse = 1; /*to hold zeros*/
int i = 0;
while(epochTime >= 1) /*reverse : 1000 -> 10001*/
{
reverse = reverse*10+epochTime%10;
epochTime = epochTime / 10;
//cout << epochTime << "*" << reverse <<endl;
}
while(reverse != 1)
{
timeAsString[i] = (reverse%10 +'0');
reverse = reverse / 10;
//cout << i << timeAsString[i] << "#" << reverse << endl;
i++;
}
}
int TimeLength(time_t epochTime)
{
int counter = 0;
while(epochTime)
{
epochTime = epochTime / 10;
counter++;
}
return counter;
}
please help.