why my code doesn't generate the same OTP like google authenticator?

You have some UB (undefined behavior).

You're doing strlen(counter) but counter is unitialized.

And, for crypto, you probably want sizeof(counter) as you've done in other places.

There are other places to use sizeof instead of strlen. In the code below, I changed all of them. That may or may not be correct, so you'll have to review that.


Here's a refactored version:

I've used cpp conditionals to denote old vs new code:

#if 0
// old code
#else
// new code
#endif

Here is the code. I didn't have access to your version of the SHA1 code, so I used openssl. If you use that, link the code with -lssl -lcrypto:

#include <stdio.h>
#include <string.h>
#include <math.h>
#include <time.h>

#if 0
#include "SHA_1.h"
#else
#include <openssl/sha.h>
void
SHA1_HASH(const unsigned char *buf,size_t len,unsigned char *result)
{
    SHA_CTX ctx;

    SHA1_Init(&ctx);
    SHA1_Update(&ctx,buf,len);
    SHA1_Final(result,&ctx);
}
#endif

void
xor(char *arr, int length, int value)
{
    int i;

    for (i = 0; i < length; i++)
        arr[i] ^= value;
}

int
main()
{
    int CT, i, j;
    long int T;
    const int T0 = 0,
        Tx = 30;
    const char o_pad = 0x5C,
        i_pad = 0x36;
    unsigned char result[20];
    unsigned char counter[8];
    unsigned char secretKey[64] = "abcdefghijklmnop";

    // HMAC
    unsigned char block[128];
    unsigned char inner_key[64];
    unsigned char outter_key[64];

    // HOTP
    int offset;
    long int truncatedHash;
    long int finalOTP;

    T = (long int) (time(NULL));
    CT = floor((T - T0) / Tx);

#if 0
    for (i = strlen(counter) - 1; i >= 0; i--) {
#else
    for (i = sizeof(counter) - 1; i >= 0; i--) {
#endif
        counter[i] = (unsigned char) (CT & 0xFF);
        CT >>= 8;
    }

    // HMAC

    // Inner Key = K xor 0x36
#if 0
    memset(inner_key, 0, 64);
    memcpy(inner_key, secretKey, strlen(secretKey));
#else
    memset(inner_key, 0, sizeof(inner_key));
    strcpy(inner_key, secretKey);
#endif
    xor(inner_key, sizeof(inner_key), i_pad);

    // Outter Key = K xor 0x5C
#if 0
    memset(outter_key, 0, 64);
    memcpy(outter_key, secretKey, strlen(secretKey));
#else
    memset(outter_key, 0, sizeof(outter_key));
    strcpy(outter_key, secretKey);
#endif
    xor(outter_key, sizeof(outter_key), o_pad);

    // Hash Inner
    memset(block, 0, sizeof(block));
#if 0
    for (i = 0; i < 64; i++) {
        block[i] = inner_key[i];
    }
#else
    for (i = 0; i < sizeof(inner_key); i++) {
        block[i] = inner_key[i];
    }
#endif

#if 0
    for (i = 0; i < strlen(counter); i++) {
        block[i + 64] = counter[i];
    }
#else
    for (i = 0; i < sizeof(counter); i++) {
        block[i + sizeof(inner_key)] = counter[i];
    }
#endif

#if 0
    SHA1_HASH(block, strlen(block), result);
#else
    SHA1_HASH(block, sizeof(block), result);
#endif

    // Hash Outter
    memset(block, 0, sizeof(block));
#if 0
    for (i = 0; i < 64; i++) {
        block[i] = outter_key[i];
    }
#else
    for (i = 0; i < sizeof(outter_key); i++) {
        block[i] = outter_key[i];
    }
#endif

#if 0
    for (i = 0; i < strlen(result); i++) {
        block[i + 64] = result[i];
    }
#else
    for (i = 0; i < sizeof(result); i++) {
        block[i + sizeof(outter_key)] = result[i];
    }
#endif

#if 0
    SHA1_HASH(block, strlen(block), result);
#else
    SHA1_HASH(block, sizeof(block), result);
#endif

    offset = result[19] & 0x0f;

    truncatedHash = ((result[offset] & 0x7f) << 24) |
        ((result[offset + 1] & 0xff) << 16) |
        ((result[offset + 2] & 0xff) << 8) |
        (result[offset + 3] & 0xff);

    finalOTP = (truncatedHash % (long int) pow(10, 6));

    printf("%d\n", finalOTP);

    return 0;
}