Last active
July 28, 2024 03:10
-
-
Save 61131/83cd87c2c1fa0a9d612abc5b6805a63e to your computer and use it in GitHub Desktop.
HMAC-based and time-based one-time password generation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdint.h> | |
#include <time.h> | |
#include <openssl/hmac.h> | |
int powi[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000 }; | |
// RFC 4226 HTOP: An HMAC-Based One-Time Password Algorithm | |
uint32_t | |
alg_hotp(const char *key, size_t length, int64_t count, size_t digits) { | |
int64_t value; | |
uint32_t bin, otp; | |
uint8_t buffer[8], offset, *result; | |
int index; | |
// Step 1: Generate an HMAC-SHA-1 value | |
for (value = count, index = 7; index >= 0; index--) { | |
buffer[index] = (uint8_t)(value & 0xff); | |
value >>= 8; | |
} | |
result = HMAC(EVP_sha1(), key, length, (const unsigned char *) buffer, sizeof(buffer), NULL, 0); | |
// Step 2: Generate four-byte string (dynamic truncation) | |
offset = result[19] & 0x0f; | |
bin = ((result[offset] & 0x7f) << 24) | | |
((result[offset + 1] & 0xff) << 16) | | |
((result[offset + 2] & 0xff) << 8) | | |
(result[offset + 3] & 0xff); | |
// Step 3: Compute HOTP value | |
otp = bin % powi[digits]; | |
return otp; | |
} | |
// RFC 6238 TOTP: Time-Based One-Time Password Algorithm | |
uint32_t | |
alg_totp(const char *key, size_t length, time_t t0, time_t step, size_t digits) { | |
int64_t count; | |
if (step < 1) { | |
step = 1; | |
} | |
count = (time(NULL) - t0) / step; | |
return alg_hotp(key, length, count, digits); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment