购物网站开发实战/seo是干啥的
TOTP定义:基于时间的一次性密码算法(英语:Time-based One-Time Password,简称:TOTP)是一种根据共享密钥
与当前时间
计算一次性密码的算法。
Google Authenticator,谷歌动态口令,Google身份验证器Google Authenticator是谷歌推出的基于时间的一次性密码(Time-based One-time Password,简称TOTP),只需要在手机上安装该APP,就可以生成一个随着时间变化的一次性密码,用于帐户验证。
微信小程序搜索TOTP也可以找到不少实现该功能的小程序。
根据TOTP定义以及谷歌动态口令APP,我们可以实现postgresql数据库基于TOTP的二次认证
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <math.h>
#include <openssl/hmac.h>
#include <openssl/sha.h>#define OTP_LENGTH 6
#define TIME_STEP 30
#define BASE32_LENGTH 32// Base32 编码字符集
static const char base32_chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";// Base32 解码函数
void base32_decode(const char* base32, unsigned char* output, size_t* output_len) {size_t bit_index = 0;int shift = 0;*output_len = 0;for (const char *ptr = base32; *ptr; ptr++) {char value;if (*ptr >= 'A' && *ptr <= 'Z') {value = *ptr - 'A';} else if (*ptr >= '2' && *ptr <= '7') {value = *ptr - '2' + 26;} else {continue; // 非法字符跳过}bit_index += 5;if (bit_index >= 8) {output[*output_len] |= (value >> (bit_index - 8));(*output_len)++;output[*output_len] = 0; // 初始化下一个字节bit_index -= 8;}output[*output_len] |= (value << (8 - bit_index));}
}// 计算时间间隔
long get_time_interval() {return time(NULL) / TIME_STEP; // 获取当前时间步长
}// HMAC-SHA1 计算
unsigned char* hmac_sha1(const unsigned char* key, int key_len,const unsigned char* data, int data_len,unsigned char* result, unsigned int* result_len) {return HMAC(EVP_sha1(), key, key_len, data, data_len, result, result_len);
}// 生成TOTP
int generate_totp(const unsigned char* key, int key_len) {long time_interval = get_time_interval();unsigned char time_bytes[8] = {0};// 将时间步长转换为8字节大端格式for (int i = 0; i < 8; i++) {time_bytes[7 - i] = time_interval & 0xFF;time_interval >>= 8;}// 生成HMAC-SHA1unsigned char hmac_result[SHA_DIGEST_LENGTH];unsigned int hmac_len = 0;hmac_sha1(key, key_len, time_bytes, sizeof(time_bytes), hmac_result, &hmac_len);// 计算动态截断的OTPint offset = hmac_result[hmac_len - 1] & 0x0F;int otp = (hmac_result[offset] & 0x7F) << 24 |(hmac_result[offset + 1] & 0xFF) << 16 |(hmac_result[offset + 2] & 0xFF) << 8 |(hmac_result[offset + 3] & 0xFF);otp %= (int)pow(10, OTP_LENGTH); // 限制OTP长度return otp;
}int main(int argc, char *argv[]) {// 使用固定的Base32编码密钥const char* secret = "JBSWY3DPEHPK3PXP"; // 这是 Base32 编码的密钥unsigned char key[20] = {0}; // 用于存储解码后的密钥size_t key_len;if (argc > 1)secret= argv[1];// Base32 解码密钥base32_decode(secret, key, &key_len);int generated_otp = generate_totp(key, key_len);printf("生成的OTP: %06d\n", generated_otp);return 0;
}
将上述示例程序中的基础密钥"JBSWY3DPEHPK3PXP"输入到谷歌APP或微信小程序中,即可以查看生成的基于时间的一次性密码;把示例程序稍作改动即可做成totp客户端。