使用OpenSSL API的私钥生成签名

时间:2015-06-10 06:55:32

标签: c++ security openssl cryptography sha1

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

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

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

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

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

我使用的代码就是这个:

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);

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

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

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

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

谢谢。

1 个答案:

答案 0 :(得分:1)

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

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

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

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

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