我正在尝试编写代码来验证一些RSA签名。签名是使用OpenSSL命令行工具制作的,使用此命令行的等效命令:
openssl dgst -sha1 -sign private_key_file.pem < binary_data_file > sig
我正在尝试使用libtomcrypt
进行验证:
以下是libtomcrypt
中的RSA验证功能的调用签名:
int rsa_verify_hash_ex(
const unsigned char *sig, unsigned long siglen, // signature to verify
const unsigned char *hash, unsigned long hashlen, // hash value to check against sig
int padding, // defined constant value, see below
int hash_idx, // identifies which hash algorithm, see below
unsigned long saltlen, // specify salt length, see below
int *stat, // output parameter, returns whether verify succeeded or not
rsa_key *key); // RSA public key to use for verify
如果该操作没有错误,则返回0,否则返回错误代码。如果它无错误地运行,stat
输出参数指示签名是否已验证。
大多数参数看起来很简单:传入签名以进行检查,用于比较它的哈希值以及用于检查的RSA密钥。 hash_idx
中包含的示例代码清楚地显示了libtomcrypt
;它是支持的哈希算法表的索引,我可以找到与此代码段一起使用的正确值:hash_idx = find_hash("sha1")
但我想知道padding
和saltlen
值。 padding
并不会让我太担心,因为只有两个可能的值,我可以尝试两者。但是我应该为saltlen
传递什么?
用于RSA验证的OpenSSL函数的OpenSSL文档不显示saltlen
参数。 openssl dgst
的手册页(即man dgst
的结果)不讨论盐。
所以我的问题:
dgst
命令是否在输入中插入任何额外的内容,例如:(stdin)=
(我通过搜索StackOverflow找到(stdin)=
事物:Why are the RSA-SHA256 signatures I generate with OpenSSL and Java different?)
libtomcrypt
还有一个名为pkcs_1_pss_decode()
的函数,该函数记录为“解码PSS编码的签名块”。这是我需要打电话的功能吗?感谢您提供任何帮助。
编辑:感谢下面的帮助,来自@Jonathan Ben-Avraham,我今天能够开始工作。我的问题的答案分别是:
(stdin)=
rsa_verify_hash_ex()
,我需要将padding
参数指定为LTC_LTC_PKCS_1_V1_5
。答案 0 :(得分:7)
没有盐:
首先,生成数据的二进制SHA1哈希:
openssl dgst -sha1 -binary -out hash1 some_data_file
这是SHA1哈希或摘要。文件some_data_file
中没有预先添加盐。 openssl dgst -sha1
本身不添加盐。请注意,输出文件只是一个20字节的SHA1哈希,没有盐。如果有salt,则哈希必须包含它,可能在保存SHA1哈希的最后20个字节之前加上。
接下来,使用您的私钥对SHA1哈希文件hash1
进行签名:
openssl pkeyutl -sign -in hash1 -inkey privkey.pem -pkeyopt digest:sha1 -out sig1
现在使用some_data_file
:
openssl dgst
签名
openssl dgst -sha1 -sign privkey.pem < some_data_file > sig2
最后,比较两个签名:
diff sig1 sig2
你应该看到它们是一样的。这告诉我们,对没有salt的文件的原始SHA1哈希进行签名与使用openssl dgst -sha1 -sign
命令对文件进行签名相同,因此openssl dgst -sha1 -sign
命令也必须使用任何盐为sig2
生成SHA1哈希时。
另请注意,使用已弃用的rsautl
:
openssl rsautl -sign -in hash1 -inkey privkey.pem -out sig1
而不是openssl pkeyutl
,显然是因为openssl rsautl -sign
在输出中包含加密文本以及签名。有关详细信息,请参阅this SE post。
答案 1 :(得分:3)
需要强调的一点是:确保传递哈希而不是实际数据。那让我离开了一段时间。这是一个有效的代码片段(但使用sha256):
void
verify_tomcrypt(unsigned char *keyblob, size_t klen,
unsigned char *payload, size_t dlen,
unsigned char *signature, size_t slen)
{
rsa_key key;
int stat;
unsigned long len;
unsigned char digest2[SHA256_DIGEST_LENGTH];
ltc_mp = ltm_desc;
register_hash(&sha256_desc);
/* try reading the key */
if (rsa_import(keyblob, klen, &key) != CRYPT_OK) {
printf("Error reading key\n");
exit(-1);
}
int hash_idx = find_hash("sha256");
if (hash_idx == -1) {
printf("LTC_SHA256 not found...?\n");
exit(-1);
}
len = sizeof(digest2);
if (hash_memory(hash_idx, payload, dlen, digest2, &len) != CRYPT_OK) {
printf("sha256 fails...?\n");
exit(-1);
}
if (rsa_verify_hash_ex(signature, slen, digest2, sizeof(digest2), LTC_LTC_PKCS_1_V1_5, hash_idx, 0, &stat, &key) == CRYPT_OK) {
if (stat == 1)
printf("Tomcrypt: Signature OK!\n");
else
printf("Tomcrypt: Signature NOK?\n");
} else {
printf("Tomcrypt: Signature error\n");
}
}