【问题标题】:TOTP implementation using C++ and OpenSSL使用 C++ 和 OpenSSL 实现 TOTP
【发布时间】:2022-08-19 01:58:25
【问题描述】:

我正在尝试使用 OpenSSL 在 C++ 中实现 TOTP。我知道有大量现有的实现;但是,我想自己实现它。

目前。我有以下代码:

bool verifyTOTP(char* code, char* key, int codeLen, int keyLen) {
    if (codeLen != 6 || keylen != 20) {
        return false;
    }
    unsigned long long intCounter = floor(time(NULL)/30);
    char md[20];
    unsigned int mdLen;
    HMAC(EVP_sha1(), key, keylen, (const unsigned char*)&intCounter, sizeof(intCounter), (unsigned char*)&md, &mdLen);
    OPENSSL_cleanse(key, keylen);
    int offset = md[19] & 0x0f;
    int bin_code = (md[offset] & 0x7f) << 24
        | (md[offset+1] & 0xff) << 16
        | (md[offset+2] & 0xff) << 8
        | (md[offset+3] & 0xff);
    bin_code = bin_code % 1000000;
    char correctCode[7];
    snprintf((char*)&correctCode, 7,\"%06d\", bin_code);
    int compR = compHash(&correctCode, code, 6); // Compares the two char arrays in a way that avoids timing attacks. Returns 0 on success.
    delete[] key;
    delete[] code;
    if (compR == 0) {
        return true;
    }
    std::this_thread::sleep_for(std::chrono::seconds(5));
    return false;
}

此代码没有给出任何错误,但未能生成正确的 TOTP,因此在验证正确的 TOTP 时它返回 false

例如,当运行下面它应该返回true

char* newKey = new char[20];
char* key = \"aaaaaaaaaaaaaaaaaaaa\";
memcpy(newKey, key, 20);
verifyTOTP(newKey, code, 6, 20);

其中code 是来自TOTP Generator 的令牌(使用生成器时请确保将密钥设置为MFQWCYLBMFQWCYLBMFQWCYLBMFQWCYLB)。

谁能发现我哪里出错了?我查看了其他人如何实现它,但找不到问题所在。

非常感谢您的关注和参与。

  • 您可以编辑它以给出一个正确的 TOTP 示例,该示例应该返回 true,但不返回 true?
  • 另外,compHash 是什么?这似乎很关键。
  • @NicholasM 我添加了示例! compHash 只是比较两个数组以确保它们具有相同的内容。实际上,它与== 相同,不同之处在于compHash 在定时攻击方面更安全。
  • 您的时钟是否与令牌生成器网站合理同步?
  • 请注意,delete[] key 在您的示例中具有未定义的行为,因为key 没有分配给new

标签: c++ openssl totp


【解决方案1】:

将 Unix 时间戳除以 30 后,需要确保 intCounter 是大端:

unsigned long long endianness = 0xdeadbeef;
if ((*(const uint8_t *)&endianness) == 0xef) {
  intCounter = ((intCounter & 0x00000000ffffffff) << 32) | ((intCounter & 0xffffffff00000000) >> 32);
  intCounter = ((intCounter & 0x0000ffff0000ffff) << 16) | ((intCounter & 0xffff0000ffff0000) >> 16);
  intCounter = ((intCounter & 0x00ff00ff00ff00ff) <<  8) | ((intCounter & 0xff00ff00ff00ff00) >>  8);
};

信用:我在this GitHub Gist 中找到了解决方案。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-06-07
    • 2019-07-11
    • 2020-07-19
    • 1970-01-01
    • 2022-08-19
    • 1970-01-01
    • 1970-01-01
    • 2012-04-26
    相关资源
    最近更新 更多