【发布时间】:2011-10-15 22:26:37
【问题描述】:
我想使用 OpenSSL 为文件创建签名。 我相信我的结果应该与 openssl 这样生成的 testfile.sig 匹配:
$ openssl dgst -sha1 -binary < testfile > testfile.sha1
$ openssl rsautl -sign -in testfile.sha1 -inkey rsa_private.pem -keyform PEM -out testfile.sig
$ openssl rsautl -verify -inkey rsa_public.pem -pubin -in testfile.sig -hexdump
Loading 'screen' into random state - done
0000 - 9f 23 88 15 2b af d6 a6-9f 4f 1f 7e ee b0 90 dd .#..+....O.~....
0010 - 69 99 2b 3d i.+=
所以,我使用了 caf 发布的代码: How to read key file for use with HMAC_Init_ex() 并且只是添加了一小块来将 EVP_SignFinal() 之后的数据保存到文件中,所以我 可以用 openssl 和公钥验证它:
FILE * fp = fopen("out.sig", "wb");
if (fp) {
printf("Writing the signature in a file. # of bytes: %u.\n", sig_len);
fwrite(sig, 1, sig_len, fp);
fclose(fp);
}
令我惊讶的是,我得到了这个:
$ openssl rsautl -verify -inkey rsa_public.pem -pubin -in out.sig -hexdump
Loading 'screen' into random state - done
0000 - 30 21 30 09 06 05 2b 0e-03 02 1a 05 00 04 14 9f 0!0...+.........
0010 - 23 88 15 2b af d6 a6 9f-4f 1f 7e ee b0 90 dd 69 #..+....O.~....i
0020 - 99 2b 3d .+=
现在,如果您观察 out.sig 的验证输出,您会看到最后 20 字节匹配 testfile.sig 验证的数据输出。那20个字节是 确实是我文件的 SHA-1 哈希。但是开头的前 15 个字节是什么? EVP_SignInit() / EVP_SignUpdate() / EVP_SignFinal() 不应该只放入散列吗 消息,还是我遗漏了一些明显的东西?
如果您需要更多信息,请告诉我。 谢谢
用于签署文件的完整功能:
int do_evp_sign(FILE * rsa_pkey_file, FILE * in_file)
{
OpenSSL_add_all_digests();
ERR_load_crypto_strings();
EVP_PKEY * pkey = PEM_read_PrivateKey(rsa_pkey_file, NULL, NULL, NULL);
if (pkey == NULL) {
ERR_print_errors_fp(stderr);
return 1;
}
fseek(in_file, 0, SEEK_END);
const size_t lSize = ftell(in_file);
rewind(in_file);
EVP_MD_CTX md_ctx;
EVP_SignInit(&md_ctx, EVP_sha1());
size_t len;
unsigned char buffer[4096];
size_t bytesLeft = lSize;
while (bytesLeft > 0) {
const size_t count = (bytesLeft > sizeof(buffer) ? sizeof(buffer) : bytesLeft);
len = fread(buffer, 1, count, in_file);
if (len != count) {
fprintf(stderr, "Read error! len (%u) != count (%u).\n", len, count);
EVP_PKEY_free(pkey);
return 1;
}
if (!EVP_SignUpdate(&md_ctx, buffer, len))
{
ERR_print_errors_fp(stderr);
EVP_PKEY_free(pkey);
return 1;
}
bytesLeft -= len;
}
unsigned int sig_len;
unsigned char * sig = (unsigned char *)malloc(EVP_PKEY_size(pkey));
if (!sig) {
fprintf(stderr, "Couldn't allocate %u bytes of memory.\n", EVP_PKEY_size(pkey));
EVP_PKEY_free(pkey);
return 1;
}
if (!EVP_SignFinal(&md_ctx, sig, &sig_len, pkey))
{
ERR_print_errors_fp(stderr);
EVP_PKEY_free(pkey);
free(sig);
return 1;
}
FILE * fTemp = fopen("out.sig", "wb");
if (fTemp) {
printf("Writing the signature to a file. Number of bytes: %u.\n", sig_len);
fwrite(sig, 1, sig_len, fTemp);
fclose(fTemp);
}
printf("Signature: \n");
for (unsigned int i = 0; i != sig_len; ++i)
{
printf("%02x", sig[i]);
if (i % 16 == 15)
printf("\n");
}
printf("\n");
EVP_PKEY_free(pkey);
free(sig);
return 0;
}
【问题讨论】: