使用openssl命令行签名数据方式如下:
生成公私钥
Generate key pair:
openssl genrsa -out private.pem 1024
通过私钥导出公钥
Extract public key:
openssl rsa -in private.pem -out public.pem -outform PEM -pubout
生成签名
openssl dgst -sha256 -sign private.pem < data.txt > sign2
该签名结果为二进制,可以通过notepad++的查看十六进制插件进行查看。插件名称HEX-Editor, 非常好用的插件。
使用RSA_sign方法,得到的值与该结果不一致。
更换了如下方法后,可以正常签名、验签。请注意,我这边的私钥和公钥,不是通过读取文件获取的,是通过读取内存中的字符串获取,且格式是固定的,不能删除换行符和首行、尾行。如果想通过文件读取,网上的技术文章也比较多,公私钥格式如下:
-----BEGIN RSA PRIVATE KEY-----
MIICXAIBAAKBgQCwhe6xy1m5dEbtjbCEJUjUMjC05zXctPxYynGl3jeko3jfAe/k
dSAuQ44EbZWRCdRJt61th2jouREdrQsQpiTkIxyrqKQISeAa4wFQwAyxosZ3fKI5
sag7wo/w6uBAdi7DVXMra7oTrN4Ostaf9PU7RsWcJ/jblyQDfSIj8vCOnwIBAwKB
gHWunyEyO9D4L0kJIFgY2zghdc3veT3N/ZCG9m6UJRhs+z9Wn+2jasmCXq2eY7YG
jYZ6c55aRfB7YL5zXLXEGJb7mmwhVetMiV69bKI3DXRPy8vySxgy2jc5lPLVZtmt
XYiwgnsY1MmqwFHTIJXPNvfLH3wkDfvfCtWdpmoxVL2bAkEA36g8ew0ODhk4FOcc
G55rCMaX4fQWlwOfLH7hrCDADQZYrVotOYdKMrFeXZ3y0yZ6QOJQ/CrIoFT/IriO
BVL2NQJBAMoMzPuWGUj41LH3QVHaGCJOLa89fs5dSb+xov6lOeUcHZ9VRYzzmvoM
NZiHzGr8TVU0EPW5GSg+w+3v9qOefAMCQQCVGtL8s160ENAN72gSaZywhGVBTWRk
rRTIVJZywIAIruXI5sjRBNwhy5Q+aUyMxFGAluCoHIXAOKoXJbQDjKQjAkEAhrMz
UmQQ21CNy/ori+a6wYlzyij/ND4xKnZsqcN77hK+ajjZCKJnUV15EFqIR1LeOM1g
o9C7cCnX8/VPF779VwJBAMegnSQ3sl/U86Iec2LxQ44NWhwWVTcBm2nyjtxmJTBD
0vh3KeuQHMDMsw3ziMCiRt5D4KExRGCYlfXVfyDlzxk=
-----END RSA PRIVATE KEY-----
-----BEGIN PUBLIC KEY-----
MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQCwhe6xy1m5dEbtjbCEJUjUMjC0
5zXctPxYynGl3jeko3jfAe/kdSAuQ44EbZWRCdRJt61th2jouREdrQsQpiTkIxyr
qKQISeAa4wFQwAyxosZ3fKI5sag7wo/w6uBAdi7DVXMra7oTrN4Ostaf9PU7RsWc
J/jblyQDfSIj8vCOnwIBAw==
-----END PUBLIC KEY-----
int rsa_prikey_sign(const char *strprikey, unsigned char *data, int data_len, unsigned char *signtext, int *signtext_len)
{
int ret = RSA_CRYPTO_OK;
RSA *rsa = NULL;
BIO *keybio = NULL;
int len;
EVP_PKEY *evpKey = NULL;
EVP_MD_CTX ctx;
if(NULL == strprikey || NULL == data || NULL == signtext || NULL == signtext_len)
{
return RSA_PRAGMA_ERROR;
}
if('\0' == *strprikey || data_len <= 0)
{
return RSA_PRAGMA_ERROR;
}
do{
rsa = RSA_new();
keybio = BIO_new_mem_buf((unsigned char *)strprikey, -1);
rsa = PEM_read_bio_RSAPrivateKey(keybio, &rsa, NULL, NULL);
if(NULL == rsa)
{
ret = RSA_READ_PRIKEY_ERROR;
break;
}
evpKey = EVP_PKEY_new();
if (evpKey == NULL) {
ret = RSA_MALLOC_ERROR;
break;
}
if (EVP_PKEY_set1_RSA(evpKey, rsa) != 1) {
ret = RSA_READ_PRIKEY_ERROR;
break;
}
EVP_MD_CTX_init(&ctx);
if (EVP_SignInit_ex(&ctx,
EVP_sha256(), NULL) != 1) {
ret = RSA_SIGN_ERROR;
break;
}
if (EVP_SignUpdate(&ctx,
data, data_len) != 1) {
ret = RSA_SIGN_ERROR;
break;
}
if (EVP_SignFinal(&ctx,
(unsigned char*)signtext,
signtext_len, evpKey) != 1) {
ret = RSA_SIGN_ERROR;
break;
}
printf("RSA_sign len = %d\n", *signtext_len);
printHex(signtext, *signtext_len);
ret = RSA_CRYPTO_OK;
EVP_MD_CTX_cleanup(&ctx);
}while(0);
if (rsa != NULL) {
RSA_free(rsa);
rsa = NULL;
}
if (evpKey != NULL) {
EVP_PKEY_free(evpKey);
evpKey = NULL;
}
if (keybio != NULL) {
BIO_free_all(keybio);
keybio = NULL;
}
return ret;
}
int rsa_pubkey_verify(const char *strpubkey, unsigned char *data, int data_len,
unsigned char *signtext, int signtext_len)
{
int ret = RSA_CRYPTO_OK;
RSA *rsa = NULL;
BIO *keybio = NULL;
EVP_PKEY *evpKey = NULL;
EVP_MD_CTX ctx;
int len;
if(NULL == strpubkey || NULL == signtext || NULL == data)
{
return RSA_PRAGMA_ERROR;
}
if('\0' == *strpubkey || signtext_len <= 0 || data_len <= 0 )
{
return RSA_PRAGMA_ERROR;
}
do{
rsa = RSA_new();
keybio = BIO_new_mem_buf((unsigned char *)strpubkey, -1);
rsa = PEM_read_bio_RSA_PUBKEY(keybio, &rsa, NULL, NULL);
if(NULL == rsa)
{
ret = RSA_READ_PUBKEY_ERROR;
break;
}
evpKey = EVP_PKEY_new();
if (evpKey == NULL) {
ret = RSA_MALLOC_ERROR;
break;
}
if (EVP_PKEY_set1_RSA(evpKey, rsa) != 1) {
ret = RSA_READ_PRIKEY_ERROR;
break;
}
EVP_MD_CTX_init(&ctx);
if (EVP_SignInit_ex(&ctx,
EVP_sha256(), NULL) != 1) {
ret = RSA_SIGN_ERROR;
break;
}
if (EVP_VerifyUpdate(&ctx,
data, data_len) != 1) {
ret = RSA_SIGN_ERROR;
break;
}
if (EVP_VerifyFinal(&ctx,
(unsigned char*)signtext,
signtext_len, evpKey) != 1) {
ret = RSA_VERIFY_ERROR;
break;
}
ret = RSA_CRYPTO_OK;
EVP_MD_CTX_cleanup(&ctx);
}while(0);
if (rsa != NULL) {
RSA_free(rsa);
rsa = NULL;
}
if (evpKey != NULL) {
EVP_PKEY_free(evpKey);
evpKey = NULL;
}
if (keybio != NULL) {
BIO_free_all(keybio);
keybio = NULL;
}
return ret;
}