<commit_before>#include <stdio.h>
#include <time.h>
#include <string.h>
#include <gcrypt.h>
#include <stdint.h>

#define BITS_PER_BASE32_CHAR 5

/* ToDo:
 * - 2 funcs, 1 google auth based and 1 normal otp
 * - add possibility to retrieve only HOTP (see how to create C)
 */

int base32_decode (const uint8_t *, uint8_t *, int);
int base32_encode (const uint8_t *, int, uint8_t *, int);

int DIGITS_POWER[] = {1,10,100,1000,10000,100000,1000000,10000000,100000000};

int Truncate (unsigned char *hmac, int N)
{
    int O = (hmac[19] & 0x0f);
    int bin_code = ((hmac[O] & 0x7f) << 24) | ((hmac[O+1] & 0xff) << 16) | ((hmac[O+2] & 0xff) << 8) | ((hmac[O+3] & 0xff));
    int token = bin_code % DIGITS_POWER[N];
    return token;
}

unsigned char *HMAC (const char *K, long C)
{
	/* Estimated number of bytes needed to represent the decoded secret. Because
	 * of white-space and separators, this is an upper bound of the real number,
	 * which we later get as a return-value from base32_decode()
     */
    int secret_len = (strlen (K) + 7)/8*BITS_PER_BASE32_CHAR;

    /* Sanity check, that our secret will fixed into a reasonably-sized static
	 * array.
     */
	if (secret_len < 0 || secret_len > 100)
		return NULL;

    uint8_t secret[secret_len];

    /* Decode secret from Base32 to a binary representation, and check that we
	 * have at least one byte's worth of secret data.
     */
    if ((secret_len = base32_decode ((const uint8_t *) K, secret, secret_len)) < 1)
        return NULL;

    unsigned char C_reverse_byte_order[8];
    int j, i;
    for (j=0, i=7; j<8 && i>=0; j++, i--)
        C_reverse_byte_order[i] = ((unsigned char *)&C)[j];

    gcry_md_hd_t hd;
    gcry_md_open (&hd, GCRY_MD_SHA1, GCRY_MD_FLAG_HMAC);
    gcry_md_setkey (hd, secret, secret_len);
    gcry_md_write (hd, C_reverse_byte_order, sizeof (C_reverse_byte_order));
    gcry_md_final (hd);
    unsigned char *hmac =  gcry_md_read (hd, GCRY_MD_SHA1);
    return hmac;
}


int HOTP (const char *K, long C, int N)
{
    unsigned char *hmac = HMAC(K, C);
    int token = Truncate (hmac, N);
    return token;
}


char *TOTP (const char *K, int N)
{
    if ((N != 6) && (N != 8))
    {
        printf ("[E]: You must choose between 6 or 8 digits\n");
        return NULL;
    }
    char *token = NULL;
    int tk;
    long TC = ((long) time (NULL))/30;
    tk = HOTP(K, TC, N);
    token = malloc (N+1);
    if (token == NULL)
    {
        printf ("[E] Error during memory allocation\n");
        return NULL;
    }
    else
    {
        if (N == 6)
            snprintf(token, 7, "%.6d", tk);
        else
            snprintf(token, 9, "%.8d", tk);
    }
    return token;
}



<commit_msg>Update otp.c<commit_after>#include <stdio.h>
#include <time.h>
#include <string.h>
#include <gcrypt.h>
#include <stdint.h>

#define BITS_PER_BASE32_CHAR 5

/* ToDo:
 * - 2 funcs, 1 google auth based and 1 normal otp
 */

int base32_decode (const uint8_t *, uint8_t *, int);
int base32_encode (const uint8_t *, int, uint8_t *, int);

int DIGITS_POWER[] = {1,10,100,1000,10000,100000,1000000,10000000,100000000};

int Truncate (unsigned char *hmac, int N)
{
    int O = (hmac[19] & 0x0f);
    int bin_code = ((hmac[O] & 0x7f) << 24) | ((hmac[O+1] & 0xff) << 16) | ((hmac[O+2] & 0xff) << 8) | ((hmac[O+3] & 0xff));
    int token = bin_code % DIGITS_POWER[N];
    return token;
}

unsigned char *HMAC (const char *K, long C)
{
	/* Estimated number of bytes needed to represent the decoded secret. Because
	 * of white-space and separators, this is an upper bound of the real number,
	 * which we later get as a return-value from base32_decode()
     */
    int secret_len = (strlen (K) + 7)/8*BITS_PER_BASE32_CHAR;

    /* Sanity check, that our secret will fixed into a reasonably-sized static
	 * array.
     */
	if (secret_len < 0 || secret_len > 100)
		return NULL;

    uint8_t secret[secret_len];

    /* Decode secret from Base32 to a binary representation, and check that we
	 * have at least one byte's worth of secret data.
     */
    if ((secret_len = base32_decode ((const uint8_t *) K, secret, secret_len)) < 1)
        return NULL;

    unsigned char C_reverse_byte_order[8];
    int j, i;
    for (j=0, i=7; j<8 && i>=0; j++, i--)
        C_reverse_byte_order[i] = ((unsigned char *)&C)[j];

    gcry_md_hd_t hd;
    gcry_md_open (&hd, GCRY_MD_SHA1, GCRY_MD_FLAG_HMAC);
    gcry_md_setkey (hd, secret, secret_len);
    gcry_md_write (hd, C_reverse_byte_order, sizeof (C_reverse_byte_order));
    gcry_md_final (hd);
    unsigned char *hmac =  gcry_md_read (hd, GCRY_MD_SHA1);
    return hmac;
}


char *finalize (int N, int tk)
{
	char *token = NULL;
    token = malloc (N+1);
    if (token == NULL)
    {
        printf ("[E] Error during memory allocation\n");
        return NULL;
    }
    else
    {
        if (N == 6)
            snprintf(token, 7, "%.6d", tk);
        else
            snprintf(token, 9, "%.8d", tk);
    }
    return token;
}


int check_otp_len(int N)
{
	if ((N != 6) && (N != 8))
    {
        printf ("[E]: You must choose between 6 or 8 digits\n");
        return -1;
    }
    else
    	return 0;
}


char *HOTP (const char *K, long C, int N)
{
    if (check_otp_len(N) == -1)
    	return -1
    unsigned char *hmac = HMAC(K, C);
    int tk = Truncate (hmac, N);
    return finalize (N, tk);
}


char *TOTP (const char *K, int N)
{
    if (check_otp_len(N) == -1)
    	return -1;
    long TC = ((long) time (NULL))/30;
    int tk = HOTP(K, TC, N);
    return finalize (N, tk);
}
{'fraction_non_alphanumeric': 0.14194838240639768, 'fraction_numerical': 0.04180298073427845, 'mean_word_length': 2.8241834607366227, 'pattern_counts': {'":': 0, '<': 31, '<?xml version=': 0, '>': 17, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 4, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6285202', 'n_tokens_mistral': 2292, 'n_tokens_neox': 2099, 'n_words': 637}