0

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.

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.

  • This is a programming question, which makes it relevant to [so]. But as the question is right now, it's too low quality to be migrated. Please [edit] your question to format it better. Use the preview to see if formatting works as expected. – MechMK1 May 19 '21 at 09:48
  • now cool ? if any thing ambigous ask me please. – Ismael W. Mohamed May 19 '21 at 10:00
  • Have you read the relevant standards [RFC6238](https://datatracker.ietf.org/doc/html/rfc6238) and [RFC4226](https://datatracker.ietf.org/doc/html/rfc4226)? – vidarlo May 19 '21 at 10:09
  • yes i did. RFC4226 says google uses HMAC-SHA1. – Ismael W. Mohamed May 19 '21 at 10:16

2 Answers2

1

The key you use atoqb4y572clkhj2sls5h72a76cnyzpe does not seem to be in hex format. You should be using hex (hex of your string is 04dd00f31dfe84b51d3a92e5d3ff40ff84dc65e4 If you need to use base32, you need to convert it to hex first

STA
  • 30,729
  • 8
  • 45
  • 59
Emin
  • 573
  • 3
  • 13
0

This repo works out perfectly: https://github.com/RavuAlHemio/cpptotp

Just tested.

steps on ubuntu:

git clone https://github.com/RavuAlHemio/cpptotp.git

cd cpptotp/

mkdir build

cd build/

cmake ..

make

./gauche

Input your key