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

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客户端。

相关文章:

  • 【Git】git cherry-pick(将某个分支的 commit 改动复制到当前分支)
  • 诠视科技MR眼镜如何安装apk应用
  • 《Linux运维实战:Ubuntu 22.04使用pam_faillock实现登录失败处理策略》
  • Linux Shell 脚本使用YAD工具实现Shell图形化界面
  • CodeBrick笔记,一种支持低功耗的嵌入式操作系统
  • 【TCP/IP、HTTP等网络协议】
  • Android开发: Java文件中操作基础UI组件
  • spring security设置多个数据源和登录验证码
  • 第二届计算机网络和云计算国际会议(CNCC 2025)
  • 如何让AI套用现有ppt模板,并通过改文字批量生成新的ppt?【翻车版】
  • AI如何实际应用到自动化测试-实战篇
  • [python]基于yolov12实现热力图可视化支持图像视频和摄像头检测
  • scala基础学习-类(1.定义类)
  • 【身份安全】OAuth 2.0工作原理(一)
  • 企业搭建AI大模型平台,存储难题如何破?Infortrend普安存储GSx并行文件存储系统
  • 质量工程师的2025:从“找bug“到“造质量“的职业进化
  • 多省发布!第27届中国机器人及人工智能大赛各赛区比赛通知
  • 【VirtualBox 安装 Ubuntu 22.04】
  • 数据库基础之DDLDML
  • UnderPressure 部署笔记
  • 李强签署国务院令,公布修订后的《中华人民共和国植物新品种保护条例》
  • 新华时评:需要“重新平衡”的是美国心态
  • 新华时评:防范安全事故须臾不可放松
  • 神舟十九号航天员乘组平安抵京
  • 湖北鄂城:相继4所小学有学生腹泻呕吐,供餐企业负责人已被采取强制措施
  • 东风着陆场近日气象条件满足神舟十九号安全返回要求