我正在尝试实现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相同,但签名完全错误。我找不到任何这方面的例子。你知道这应该如何运作,或者指出我正确的方向吗?
谢谢。
答案 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
命令执行此操作。