someone know why this TOTP code doesn't generate the same OTP like google authenticator??? the SHA1-HASH function is working well, it's just the final OTP that dosen't generated correct. I tried to check everything and I couldn't find where my mistake. can someone help please? this code supposed to be a very basic code to generate TOTP.
#include <stdio.h>
#include <math.h>
#include <time.h>
#include "SHA_1.h"
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);
for (i = strlen(counter)-1; i >= 0; i--)
{
counter[i] = (unsigned char)(CT & 0xFF);
CT >>= 8;
}
// HMAC
// Inner Key = K xor 0x36
memset(inner_key, 0, 64);
memcpy(inner_key, secretKey, strlen(secretKey));
xor(inner_key, sizeof(inner_key), i_pad);
// Outter Key = K xor 0x5C
memset(outter_key, 0, 64);
memcpy(outter_key, secretKey, strlen(secretKey));
xor(outter_key, sizeof(outter_key), o_pad);
// Hash Inner
memset(block, 0, sizeof(block));
for (i = 0; i < 64; i++)
{
block[i] = inner_key[i];
}
for (i = 0; i < strlen(counter); i++)
{
block[i + 64] = counter[i];
}
SHA1_HASH(block, strlen(block), result);
// Hash Outter
memset(block, 0, sizeof(block));
for (i = 0; i < 64; i++)
{
block[i] = outter_key[i];
}
for (i = 0; i < strlen(result); i++)
{
block[i + 64] = result[i];
}
SHA1_HASH(block, strlen(block), result);
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", finalOTP);
return 0;
}
EDITED
My SHA_1 code:
#include <stdio.h>
#include <string.h>
// circular rotate function
unsigned int S(int n, unsigned int word)
{
return ((word << n) | (word >> (32 - n)));
}
// constant K
const unsigned int K[4] = {
0x5A827999,
0x6ED9EBA1,
0x8F1BBCDC,
0xCA62C1D6};
// H values
unsigned int H[5] = {
0x67452301,
0xEFCDAB89,
0x98BADCFE,
0x10325476,
0xC3D2E1F0};
void SHA1_HASH(unsigned char *input,int input_length, char *output)
{
// Variabels Declaration
unsigned char M[128];
unsigned int W[80];
unsigned int j, i, TEMP, A, B, C, D, E;
unsigned char HH[20], temp_HH[20];
int M_size;
// clear M
memset(M, 0, sizeof(M));
// Copy the messege into M
strcpy(M, input);
// add the length of the messege to the end of M
if (input_length > 55)
{
M[127] = (unsigned char)(input_length * 8);
M[126] = (unsigned char)(input_length * 8 >> 8);
M_size = 2;
}
else
{
M[63] = (unsigned char)(input_length * 8);
M[62] = (unsigned char)(input_length * 8 >> 8);
M_size = 1;
}
// set bit '1' after the messege
M[input_length] |= (unsigned char)0x80;
for(j=0; j<M_size; j++){
//init Words in W[0] - W[15]
for (i = 0; i < 16; i++)
{
W[i] = ((unsigned int)M[(4 * i)+(64*j)] << 24) | ((unsigned int)M[(1 + (4 * i))+(64*j)] << 16) | ((unsigned int)M[(2 + (4 * i))+(64*j)] << 8) | ((unsigned int)M[(3 + (4 * i))+(64*j)]);
}
for (i = 16; i < 80; i++)
{
W[i] = S(1, W[i - 3] ^ W[i - 8] ^ W[i - 14] ^ W[i - 16]);
}
//start of the SHA-1 alghoritem
A = H[0];
B = H[1];
C = H[2];
D = H[3];
E = H[4];
for (i = 0; i < 20; i++) // round 1
{
TEMP = S(5, A) + ((B & C) | ((~B) & D)) + E + W[i] + K[0];
E = D;
D = C;
C = S(30, B);
B = A;
A = TEMP;
}
for (i = 20; i < 40; i++) //round 2
{
TEMP = S(5, A) + (B ^ C ^ D) + E + W[i] + K[1];
E = D;
D = C;
C = S(30, B);
B = A;
A = TEMP;
}
for (i = 40; i < 60; i++) //round 3
{
TEMP = S(5, A) + ((B & C) | (B & D) | (C & D)) + E + W[i] + K[2];
E = D;
D = C;
C = S(30, B);
B = A;
A = TEMP;
}
for (i = 60; i < 80; i++) //round 4
{
TEMP = S(5, A) + (B ^ C ^ D) + E + W[i] + K[3];
E = D;
D = C;
C = S(30, B);
B = A;
A = TEMP;
}
H[0] += A;
H[1] += B;
H[2] += C;
H[3] += D;
H[4] += E;
}
sprintf(HH, "%x", H[0]);
for (i = 1; i < 5; i++)
{
sprintf(temp_HH, "%x", H[i]);
strcat(HH, temp_HH);
}
// end of SHA-1 alghoritem
// return the algoritem result
strcpy(output, HH);
}