Skip to content

Instantly share code, notes, and snippets.

@61131
Last active July 28, 2024 03:10
Show Gist options
  • Save 61131/83cd87c2c1fa0a9d612abc5b6805a63e to your computer and use it in GitHub Desktop.
Save 61131/83cd87c2c1fa0a9d612abc5b6805a63e to your computer and use it in GitHub Desktop.
HMAC-based and time-based one-time password generation
#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