我使用以下代码检查签名。为简单起见,公共密钥,消息和签名在main
初始化。
#include <openssl/sha.h>
#include <openssl/rsa.h>
#include <openssl/pem.h>
#include <openssl/evp.h>
int main(){
const unsigned char key[] = "-----BEGIN PUBLIC KEY-----\n"
"MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBALulMfYFyX1kSm7oUxZyCWWhrBBcWrRA\n"
"V7LSz1PzMPxoxG3KS8H7PRKFkIk42yM8/vhobmcCmj7UM5572wWch50CAwEAAQ==\n"
"-----END PUBLIC KEY-----\n";
unsigned int key_len = sizeof(key);
const unsigned char data[] = {0x6d,0x65,0x73,0x65,0x0a};
unsigned int data_len = sizeof(data);
const unsigned char sig[] = {0xa9,0x29,0x81,0x07,0x8c,0xeb,0xf0,0x1b,0x2a,0x31,0xe5,0x60,0x94,0x8a,0x47,0x94,0x3a,0x8f,0x6b,
0x4e,0x85,0xb9,0xe7,0xe5,0x4a,0x6c,0x56,0x46,0xd1,0x80,0x15,0x57,0xce,0xcb,0x0a,0x3a,0x67,0x15,0xed,
0x68,0x03,0x58,0x99,0xa4,0x73,0x61,0xe3,0x30,0x85,0xff,0x89,0x7e,0x32,0xef,0x16,0xec,0x23,0x7f,0x14,
0xde,0xbf,0x53,0xe0,0x3a};
unsigned int sig_len = sizeof(sig);
EVP_PKEY* evp_pubkey = EVP_PKEY_new();
RSA* rsa_pubkey = NULL;
EVP_MD_CTX ctx;
BIO* bufio = BIO_new_mem_buf((void*)key, key_len);
if(bufio == NULL){
fprintf(stderr, "BIO not created.\n");
EVP_PKEY_free(evp_pubkey);
BIO_free(bufio);
return 3;
}
evp_pubkey = PEM_read_bio_PUBKEY(bufio, NULL, NULL, NULL);
if(evp_pubkey == NULL){
fprintf(stderr, "evp_pubkey not created.\n");
EVP_PKEY_free(evp_pubkey);
BIO_free(bufio);
return 4;
}
EVP_MD_CTX_init(&ctx);
if (!EVP_VerifyInit(&ctx, EVP_sha256())) {
fprintf(stderr, "EVP_SignInit: failed.\n");
EVP_PKEY_free(evp_pubkey);
BIO_free(bufio);
return 5;
}
if (!EVP_VerifyUpdate(&ctx, data, data_len)) {
fprintf(stderr, "EVP_SignUpdate: failed.\n");
EVP_PKEY_free(evp_pubkey);
BIO_free(bufio);
return 6;
}
if (!EVP_VerifyFinal(&ctx, sig, sig_len, evp_pubkey)) {
fprintf(stderr, "EVP_VerifyFinal: failed.\n");
EVP_PKEY_free(evp_pubkey);
BIO_free(bufio);
return 7;
}
EVP_PKEY_free(evp_pubkey);
BIO_free(bufio);
return 0;
}
使用gcc evp.c -lssl -lcrypto
进行编译并在其上运行valgrind --tool=memcheck --leak-check=full ./a.out
后,我遇到了一些内存泄漏:
==7492== 56 bytes in 1 blocks are definitely lost in loss record 9 of 12
==7492== at 0x4C2BBCF: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==7492== by 0x4E9AD77: CRYPTO_malloc (in /lib/x86_64-linux-gnu/libcrypto.so.1.0.0)
==7492== by 0x4F5D459: EVP_PKEY_new (in /lib/x86_64-linux-gnu/libcrypto.so.1.0.0)
==7492== by 0x400C4C: main (in a.out)
==7492==
==7492== 120 bytes in 1 blocks are definitely lost in loss record 10 of 12
==7492== at 0x4C2BBCF: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==7492== by 0x4E9AD77: CRYPTO_malloc (in /lib/x86_64-linux-gnu/libcrypto.so.1.0.0)
==7492== by 0x4F55678: EVP_DigestInit_ex (in /lib/x86_64-linux-gnu/libcrypto.so.1.0.0)
==7492== by 0x400D6A: main (in a.out)
我做错了吗?
答案 0 :(得分:3)
你在这里覆盖指针
evp_pubkey = PEM_read_bio_PUBKEY(bufio, NULL, NULL, NULL);
所以第一次EVP_PKEY_new()
返回的指针的引用会丢失,你不能再释放它了。
答案 1 :(得分:3)
@ iharob在his answer写的内容,
您使用了EVP_MD_CTX_init()
但没有释放使用EVP_MD_CTX_cleanup(&ctx)
分配的数据或 - 取决于您的openssl版本 - EVP_MD_CTX_free(&ctx)
。
如果使用调试信息进行编译(在gcc / clang中使用-g) valgrind 将显示负责泄漏的源代码行。
您也可以使用EVP_MD_CTX_create()
代替静态EVP_MD_CTX
。
以下是更新后的代码:
#include <openssl/sha.h>
#include <openssl/rsa.h>
#include <openssl/pem.h>
#include <openssl/evp.h>
int main() {
const unsigned char key[] =
"-----BEGIN PUBLIC KEY-----\n"
"MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBALulMfYFyX1kSm7oUxZyCWWhrBBcWrRA\n"
"V7LSz1PzMPxoxG3KS8H7PRKFkIk42yM8/vhobmcCmj7UM5572wWch50CAwEAAQ==\n"
"-----END PUBLIC KEY-----\n";
unsigned int key_len = sizeof(key) - 1;
const unsigned char data[] = { 0x6d,0x65,0x73,0x65,0x0a };
unsigned int data_len = sizeof(data);
const unsigned char sig[] = {
0xa9,0x29,0x81,0x07,0x8c,0xeb,0xf0,0x1b,0x2a,0x31,0xe5,0x60,
0x94,0x8a,0x47,0x94,0x3a,0x8f,0x6b,0x4e,0x85,0xb8,0xe7,0xe5,
0x4a,0x6c,0x56,0x46,0xd1,0x80,0x15,0x57,0xce,0xcb,0x0a,0x3a,
0x67,0x15,0xed,0x68,0x03,0x58,0x99,0xa4,0x73,0x61,0xe3,0x30,
0x85,0xff,0x89,0x7e,0x32,0xef,0x16,0xec,0x23,0x7f,0x14,0xde,
0xbf,0x53,0xe0,0x3a
};
unsigned int sig_len = sizeof(sig);
int ret = 0;
EVP_PKEY* evp_pubkey = NULL;
RSA* rsa_pubkey = NULL;
EVP_MD_CTX* evp_ctx;
BIO* bufio = NULL;
if (!(bufio = BIO_new_mem_buf((void*)key, key_len))) {
fprintf(stderr, "BIO not created.\n");
ret = 1;
goto out;
}
if (!(evp_pubkey = PEM_read_bio_PUBKEY(bufio, NULL, NULL, NULL))) {
fprintf(stderr, "evp_pubkey not created.\n");
ret = 2;
goto out;
}
if (!(evp_ctx = EVP_MD_CTX_create())) {
fprintf(stderr, "ctx not created.\n");
ret = 3;
goto out;
}
if (!EVP_VerifyInit(evp_ctx, EVP_sha256())) {
fprintf(stderr, "EVP_SignInit: failed.\n");
ret = 4;
goto out;
}
if (!EVP_VerifyUpdate(evp_ctx, data, data_len)) {
fprintf(stderr, "EVP_SignUpdate: failed.\n");
ret = 5;
goto out;
}
if (!EVP_VerifyFinal(evp_ctx, sig, sig_len, evp_pubkey)) {
fprintf(stderr, "EVP_VerifyFinal: failed.\n");
ret = 6;
goto out;
}
out:
if (evp_ctx)
EVP_MD_CTX_destroy(evp_ctx);
if (evp_pubkey)
EVP_PKEY_free(evp_pubkey);
if (bufio)
BIO_free(bufio);
return 0;
}