【发布时间】: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