使用OpenSSL API的私钥生成签名

时间:2020-12-05 18:24:30

I'm trying to implement the SSL equivalent of:

我正在尝试实现SSL的等价物:

openssl dgst -sha1 -binary -out digest.txt what.txt

openssl rsautl -sign -inkey key.pem -in what.txt -out signature.txt

I have my 7 lines private key, 304 chars:

我有7行私钥,304个字符:

const char* k = "-----BEGIN... \n... \n... END RSA.."

The code I use is this one:

我使用的代码是这样的:

BIO* bio = BIO_new_mem_buf((void*)k, (int)strlen(k));

RSA* privateKey = PEM_read_bio_RSAPrivateKey(bio, NULL, 0, NULL);

std::string appName = "hello";

unsigned char SHA[20];

SHA1((const unsigned char*)appName.c_str(), appName.size(), SHA);

Then I sign using the following code, passing the SHA and it's size as buffer and bufferSize (which should always be 20 in this case and it's correct) while the signature size is 32:

然后我使用以下代码进行签名,传递SHA并将其大小作为缓冲区和缓冲区大小(在这种情况下应该始终为20并且它是正确的),而签名大小为32:

unsigned int privateKeySize = RSA_size(privateKey);
*signature = new unsigned char[ privateKeySize ];

RSA_sign(NID_sha1, buffer, bufferSize, *signature, signatureSize, privateKey);

RSA_sign return 0, I can't find any error code etc. The SHA[] array content is the same of the file digest.txt, but the signature is totally wrong. I can't find any example of this.. Do you have any idea how this should work, or point me into the right direction?

RSA_sign返回0,我找不到任何错误代码等.Shart []数组内容与文件digest.txt相同,但签名完全错误。我找不到任何这方面的例子。你知道这应该如何运作,还是指出我正确的方向?

Thank You.

谢谢。

1 个解决方案

#1


1  

First of all, the digest is never treated as hexadecimals in a signature, which is what you seem to assume by the extension of digest.txt. The output of the dgst command within OpenSSL is also binary (although the manual pages on my system seem to indicate otherwise - openssl's documentation isn't known to be very precise). This is only a superficial problem as the rest of your code does seem to treat the SHA-1 hash as binary.

首先,摘要永远不会被视为签名中的十六进制,这正是您通过digest.txt的扩展所假设的。 OpenSSL中dgst命令的输出也是二进制的(尽管我系统上的手册页似乎表示不同 - openssl的文档不是很精确)。这只是一个表面问题,因为其余代码确实将SHA-1哈希视为二进制。

What's probably hurting you is that, although openssl rsautl -sign seems to pad the data, it doesn't seem to surround it with the structure that indicates the hash algorithm used. You need to append this structure yourself. This is probably a legacy from OpenSSL's support for SSLv3 RSA authentication where this structure may be absent.

可能会让你受伤的是,尽管openssl rsautl -sign似乎填充了数据,但它似乎并没有用表示所使用的哈希算法的结构来包围它。您需要自己附加此结构。这可能是OpenSSL支持SSLv3 RSA身份验证的遗留问题,其中可能缺少此结构。

A quick and dirty fix that is actually present in the PKCS#1 standard is to prefix the hash before signing. In the case of SHA-1 you should prefix the hash with the binary value of the following hex representation:

PKCS#1标准中实际存在的快速而脏的修复是在签名之前为哈希添加前缀。在SHA-1的情况下,您应该在哈希前面加上以下十六进制表示的二进制值:

30 21 30 09 06 05 2b 0e 03 02 1a 05 00 04 14

this should be easy to do in your shell language of choice. Even the windows command line is able to do this through the COPY command.

这应该很容易用您选择的shell语言。甚至Windows命令行也可以通过COPY命令执行此操作。

#1


1  

First of all, the digest is never treated as hexadecimals in a signature, which is what you seem to assume by the extension of digest.txt. The output of the dgst command within OpenSSL is also binary (although the manual pages on my system seem to indicate otherwise - openssl's documentation isn't known to be very precise). This is only a superficial problem as the rest of your code does seem to treat the SHA-1 hash as binary.

首先,摘要永远不会被视为签名中的十六进制,这正是您通过digest.txt的扩展所假设的。 OpenSSL中dgst命令的输出也是二进制的(尽管我系统上的手册页似乎表示不同 - openssl的文档不是很精确)。这只是一个表面问题,因为其余代码确实将SHA-1哈希视为二进制。

What's probably hurting you is that, although openssl rsautl -sign seems to pad the data, it doesn't seem to surround it with the structure that indicates the hash algorithm used. You need to append this structure yourself. This is probably a legacy from OpenSSL's support for SSLv3 RSA authentication where this structure may be absent.

可能会让你受伤的是,尽管openssl rsautl -sign似乎填充了数据,但它似乎并没有用表示所使用的哈希算法的结构来包围它。您需要自己附加此结构。这可能是OpenSSL支持SSLv3 RSA身份验证的遗留问题,其中可能缺少此结构。

A quick and dirty fix that is actually present in the PKCS#1 standard is to prefix the hash before signing. In the case of SHA-1 you should prefix the hash with the binary value of the following hex representation:

PKCS#1标准中实际存在的快速而脏的修复是在签名之前为哈希添加前缀。在SHA-1的情况下,您应该在哈希前面加上以下十六进制表示的二进制值:

30 21 30 09 06 05 2b 0e 03 02 1a 05 00 04 14

this should be easy to do in your shell language of choice. Even the windows command line is able to do this through the COPY command.

这应该很容易用您选择的shell语言。甚至Windows命令行也可以通过COPY命令执行此操作。