当前位置: 首页 > article >正文

PostgreSQL学习之一次一密口令认证(TOTP)

        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-SHA1
    unsigned 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);

    // 计算动态截断的OTP
    int 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客户端。


http://www.kler.cn/a/619555.html

相关文章:

  • 【LeetCode 题解】算法:8.字符串转换整数(atoi)
  • 清晰易懂的Rust安装与配置教程
  • SmolDocling文档处理模型介绍
  • git命令使用小记(打补丁)
  • IP综合实验
  • Flutter_学习记录_AppBar中取消leading的占位展示
  • WEB攻防-Java安全SPEL表达式SSTI模版注入XXEJDBCMyBatis注入
  • 结合C#技术栈--大规模Modbus设备通信的高性能、高实时性需求技术方案
  • Pytorch实现FSGAN实现少样本视网膜血管分割
  • C语言_数据结构_二叉树
  • pagehelper 分页插件使用说明
  • docker启动nacos+redis+seata
  • 合规+增效 正也科技携智能营销产品出席中睿论坛
  • 18.PCIe总线入门理解与Linux上PCIe设备配置与使用
  • 大厂算法面试 7 天冲刺:第2天-链表算法深度解析 - 高频面试题与Java实战
  • 网页的性能优化
  • MySQL 主从同步数据一致性问题解决方案
  • 基于Spring Boot的戒烟网站的设计与实现(LW+源码+讲解)
  • linux两个重要的固态硬盘驱动说明
  • C语言术语