2013-04-25 156 views
5

我想编写代码来验证一些RSA签名。签名使用OpenSSL命令行工具制造,使用此命令行的等效:OpenSSL RSA签名验证:散列和填充?

openssl dgst -sha1 -sign private_key_file.pem <binary_data_file> sig 

我试图用libtomcrypt做验证:

http://www.libtom.org/

这里是调用RSA验证功能的签名libtomcrypt

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_idxlibtomcrypt附带的示例代码中清楚;这是一个索引的支持的哈希算法的表,我能找到正确的值与此代码段使用:hash_idx = find_hash("sha1")

但我想知道有关paddingsaltlen值。 padding并不担心我太多,因为只有两个可能的值,我可以尝试它们两个。但是,我应该通过什么saltlen

用于RSA验证的OpenSSL函数的OpenSSL文档不显示saltlen参数。 openssl dgst的手册页(即man dgst的结果)不讨论盐。

所以我的问题:

  • 我怎样才能确定正确的盐长度使用?
  • 是否OpenSSL的dgst命令插入输入任何多余的东西,如:(stdin)=

(我发现(stdin)=东西通过搜索的StackOverflow:Why are the RSA-SHA256 signatures I generate with OpenSSL and Java different?

  • libtomcrypt也有一个名为pkcs_1_pss_decode()功能其被记录为“解码PSS编码的签名块”。这是我需要调用的函数吗?

感谢您给我的任何帮助。

编辑:感谢下面的帮助,来自@Jonathan Ben-Avraham,今天我能够得到这个工作。我的问题的答案分别是:

  • 使用长度为0的盐,根本没有盐。
  • 没有,OpenSSL的并不如(stdin)=
  • 我需要调用rsa_verify_hash_ex()插入任何额外的东西,我需要到指定padding参数作为LTC_LTC_PKCS_1_V1_5

回答

7

无盐:

首先,生成你的数据的二进制SHA1哈希:

openssl dgst -sha1 -binary -out hash1 some_data_file 

这是一个SHA1哈希或消化。没有任何盐预加载到文件some_data_fileopenssl dgst -sha1本身不添加盐。请注意,输出文件只是一个不含盐的20字节SHA1哈希。如果有盐,哈希将不得不包含它,可能在保存SHA1哈希的最后20个字节之前加上。

接下来,签署SHA1散列文件hash1用私钥:

openssl pkeyutl -sign -in hash1 -inkey privkey.pem -pkeyopt digest:sha1 -out sig1 

现在签署some_data_fileopenssl dgst

openssl dgst -sha1 -sign privkey.pem <some_data_file> sig2 

最后,比较两个签名:

diff sig1 sig2 

你应该看到它们是相同。这告诉我们,签署没有盐的文件的原始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

+0

谢谢你的一个非常好的答案。你给了我自己的工具,看看没有盐。我现在有'libtomcrypt'代码成功验证签名! +1并接受答案。 – steveha 2013-04-30 06:03:57

+0

@ steveha:谢谢!您可能还想查看关于'rsautl''的后续文章:http://stackoverflow.com/questions/9951559/difference-between-openssl-rsautl-and-dgst – 2013-04-30 09:46:20

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"); 
    } 
} 
+0

感谢您的示例代码。 – 2016-11-17 13:11:53

+0

我为特定的rsa sig检查获取'CRYPT_PK_INVALID_SIZE'。你有什么问题吗?这个错误由​​'rsa_verify_hash_ex'返回 – 2016-12-21 16:20:57