Authentication RSA_public_解密失败,错误为-1

Authentication RSA_public_解密失败,错误为-1,authentication,encryption,openssl,rsa,Authentication,Encryption,Openssl,Rsa,我有一个小型的react本机应用程序,它使用RSA私钥对消息进行签名。以下是对消息进行签名的代码段(在本例中为Hello World) 现在,我正在尝试使用OpenSSL的RSA\u public\u decrypt函数验证(并用相应的公钥解密)来自C程序的签名。这是嵌入公钥和加密签名的C代码 #include <stdio.h> #include <string.h> #include <openssl/pem.h> #include <openssl

我有一个小型的react本机应用程序,它使用RSA私钥对消息进行签名。以下是对消息进行签名的代码段(在本例中为Hello World

现在,我正在尝试使用OpenSSL的RSA\u public\u decrypt函数验证(并用相应的公钥解密)来自C程序的签名。这是嵌入公钥和加密签名的C代码

#include <stdio.h>
#include <string.h>
#include <openssl/pem.h>
#include <openssl/rsa.h>
#include <openssl/bio.h>
#include <openssl/err.h>
#include <openssl/evp.h>


unsigned char key[] = "-----BEGIN RSA PUBLIC KEY-----\nMIIBCgKCAQEAmz6Z6jk2qQ0kPUNCcxTz/dJmUEdVWDWeOeTKS2jwSd5vlwqPHH8Y\nC5BVCuDJ2EKRmB3k18bIDrBqqG9mguqimCY5FA2E5FyIWMOswrnvgzmmyO0RFLUK\nBNUhQ2A3fegL3TNwU8S9bWZV4Bb4zgGIq51QVL8r9yCNd2TC5Y0PHvT36ZbP1W/K\nAvfSsJZYarbVz3QhcEnSXcnllK8AADqMp6jX6zf6vpIEDaf+gs3wg6ubaq7Du81I\nc7iMHfxNL6Uv803T0LKJLOiDXsZZB4K8AKLy86ZsXIkU8NHb2fX4bFvncBZraWGD\nreEDlMNMfwxX6UJR/scnj9R/spiV+9XJqwIDAQAB\n-----END RSA PUBLIC KEY-----\n";


//digest for "Hello World"
unsigned char encrypted[] = "TfAgdPqm+CPxAqxPdV1jfGQvZAZ+uQ/sAlaHCK0ZvHKnRhHnKj+I2PHZhHhM5tJ14hgPd9H48Pe5\nbPFXj0KTk/Ty8YOcd7h98STwmJyNzlqM03Get42q9fD//ofyFZfQrm3R2OZjgOlQ5myepqko8+nk\nobuawPNVsi2Eu+N6PBBAW86hX9pRfKP3gkrOCK8ae1k9O9ysOXucSguaV1++WHkv30O2mN2rsEAT\nATi6SFxYry6n9G+6gIxOyWF9X8qleg3dJgURAPwpD1SWnTOb2hZChpYOWnIreqO9hGQlTgMVzDx3\nncdGpuJ4EatW4ETBO9ox+s7OeqI4TQxt0kH09Q==\n";


unsigned char decoded_encrypted[4096] = {0}, decrypted[4096] = {0};


int main() {

    RSA *rsa = RSA_new();
    BIO *keybio = BIO_new_mem_buf((void *) key, -1);
    if (keybio == NULL) {
        printf("Failed to create key BIO\n");
        return -1;
    }
    rsa = PEM_read_bio_RSAPublicKey(keybio, &rsa, NULL, NULL);
    if (rsa == NULL) {
        printf("Failed to create RSA\n");
        return -1;
    }

    int result = EVP_DecodeBlock((unsigned char *) decoded_encrypted, (const unsigned char *) encrypted, strlen((const char *) encrypted));
    printf("\n----------%s(%d)------------\n", decoded_encrypted, result);



    // result = RSA_public_decrypt(strlen((const char *) decoded_encrypted), decoded_encrypted, decrypted, rsa, RSA_PKCS1_PADDING);
    // printf("\n----------%s(%d)------------\n", decrypted, result);
    // ERR_print_errors(keybio);



    // const unsigned char m[] = "Hello World";
    // result = RSA_verify(NID_sha1, (const unsigned char *) m, strlen((const char *) m), (unsigned char *) encrypted, strlen((const char *) encrypted), rsa);
    // printf("\n----------(%d)------------\n", result);


    RSA_free(rsa);
    BIO_free(keybio);

    return 0;
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
无符号字符键[]="-----开始公开RSA2.2。2。2。2。2。2。2。2。2。2。2。6。2。2。6。6。2。6。2。2。6。6。6。6。6。6。6。6。6。6。6。6。6。6。6。6。6。6。6。6。6。6。6。6。6。6。6。6。6。6。6。6。6。6。6。6。6。6。6。6。6。6。6。6。6。6。6。6。6。6。6。6。6。6。6。6。6。6。6。6。6。6。6。6。6。6。6。6。6。6。6。6。6。6。6。6。6。6。6。6。6。6。6。6。6。6。6。6。6。6。6。6。6。6。6。6。6。6。6。6 BFVNCBZRAWGD\nREDLMNMFwxX6UJR/scnj9R/spiV+9XJQWIDAKAB\n------结束RSA公钥------\n”;
//《你好世界》文摘
未签名字符加密[]=“(2)2)2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 EATW4ETBO9OX+s7OeqI4TQxt0kH09Q==\n”;
无符号字符解码\u加密[4096]={0},解密[4096]={0};
int main(){
RSA*RSA=RSA_new();
BIO*keybio=BIO_new_mem_buf((void*)键,-1);
if(keybio==NULL){
printf(“未能创建密钥BIO\n”);
返回-1;
}
rsa=PEM_read_bio_RSAPublicKey(keybio,&rsa,NULL,NULL);
if(rsa==NULL){
printf(“未能创建RSA\n”);
返回-1;
}
int result=EVP_DecodeBlock((unsigned char*)解码_加密,(const unsigned char*)加密,strlen((const char*)加密));
printf(“\n------%s(%d)-------------\n”,解码\u加密,结果);
//结果=RSA_public_decrypt(strlen((const char*)解码_加密)、解码_加密、解密、RSA、RSA_PKCS1_填充);
//printf(“\n------%s(%d)-------------\n”,已解密,结果);
//错误打印错误(keybio);
//const unsigned char m[]=“Hello World”;
//结果=RSA验证(NID_sha1,(const unsigned char*)m,strlen((const char*)m,(unsigned char*)加密,strlen((const char*)加密),RSA);
//printf(“\n--------------(%d)------\n”,结果);
RSA_-free(RSA);
无生物素(keybio);
返回0;
}

但是解密(验证)没有发生,因为RSA_public_decrypt(RSA_verify)返回值为-1(0)失败。非常感谢您的帮助。

有几个小缺陷:换行符(
\n
)必须删除。请注意,Internet上有各种Base64实现,其中一些处理带或不带换行符的Base64编码字符串,例如默认情况下考虑换行符的Base64 BIO筛选器(可以使用标志更改).在本例中,为简单起见,
EVP_DecodeBlock
与不带换行符的签名一起使用。以下代码与我的机器有关:

RSA* rsa = RSA_new();
...
// RSA_public_decrypt
// SHA512-ID: 3051300d060960864801650304020305000440
const unsigned char encrypted[] = "TfAgdPqm+CPxAqxPdV1jfGQvZAZ+uQ/sAlaHCK0ZvHKnRhHnKj+I2PHZhHhM5tJ14hgPd9H48Pe5bPFXj0KTk/Ty8YOcd7h98STwmJyNzlqM03Get42q9fD//ofyFZfQrm3R2OZjgOlQ5myepqko8+nkobuawPNVsi2Eu+N6PBBAW86hX9pRfKP3gkrOCK8ae1k9O9ysOXucSguaV1++WHkv30O2mN2rsEATATi6SFxYry6n9G+6gIxOyWF9X8qleg3dJgURAPwpD1SWnTOb2hZChpYOWnIreqO9hGQlTgMVzDx3ncdGpuJ4EatW4ETBO9ox+s7OeqI4TQxt0kH09Q==";

unsigned char decoded[258]; // length(encrypted) / 4 * 3, possibly padded with 0, see EVP_DecodeBlock
EVP_DecodeBlock(decoded, encrypted, strlen((const char*)encrypted));

unsigned char decrypted[19 + 64]; // length(hash-ID) + length(hash)
int decryptedLength = RSA_public_decrypt(RSA_size(rsa), decoded, decrypted, rsa, RSA_PKCS1_PADDING); // RSA_NO_PADDING reveals the padding (in conjunction with 256 bytes buffer) 

for (int i = 0; i < decryptedLength; i++)
    printf("%02x", decrypted[i]);

在这两个代码段中,仅实现了与各自流程的说明相关的步骤,即跳过了不太重要的步骤,如删除换行符、确定哈希等。

有几个小缺陷:换行符(
\n
)必须删除。请注意,Internet上有各种Base64实现,其中一些处理带或不带换行符的Base64编码字符串,例如默认情况下考虑换行符的Base64 BIO筛选器(可以使用标志更改).在本例中,为简单起见,
EVP_DecodeBlock
与不带换行符的签名一起使用。以下代码与我的机器有关:

RSA* rsa = RSA_new();
...
// RSA_public_decrypt
// SHA512-ID: 3051300d060960864801650304020305000440
const unsigned char encrypted[] = "TfAgdPqm+CPxAqxPdV1jfGQvZAZ+uQ/sAlaHCK0ZvHKnRhHnKj+I2PHZhHhM5tJ14hgPd9H48Pe5bPFXj0KTk/Ty8YOcd7h98STwmJyNzlqM03Get42q9fD//ofyFZfQrm3R2OZjgOlQ5myepqko8+nkobuawPNVsi2Eu+N6PBBAW86hX9pRfKP3gkrOCK8ae1k9O9ysOXucSguaV1++WHkv30O2mN2rsEATATi6SFxYry6n9G+6gIxOyWF9X8qleg3dJgURAPwpD1SWnTOb2hZChpYOWnIreqO9hGQlTgMVzDx3ncdGpuJ4EatW4ETBO9ox+s7OeqI4TQxt0kH09Q==";

unsigned char decoded[258]; // length(encrypted) / 4 * 3, possibly padded with 0, see EVP_DecodeBlock
EVP_DecodeBlock(decoded, encrypted, strlen((const char*)encrypted));

unsigned char decrypted[19 + 64]; // length(hash-ID) + length(hash)
int decryptedLength = RSA_public_decrypt(RSA_size(rsa), decoded, decrypted, rsa, RSA_PKCS1_PADDING); // RSA_NO_PADDING reveals the padding (in conjunction with 256 bytes buffer) 

for (int i = 0; i < decryptedLength; i++)
    printf("%02x", decrypted[i]);

在这两个代码段中,仅实现了与各自流程的说明相关的步骤,即跳过了不太重要的步骤,如删除换行符、确定哈希等。

(1)每当libcrypto例程返回错误指示时(对于libssl,有时需要在ERR_*之前先执行SSL_get_error)。(2)您的“加密”是base64编码的。您可以使用EVP_DecodeBlock获取要“解密”的实际(二进制/原始)数据(您是正确的,实际上是签名验证而不是加密,但由于历史原因,我们仍使用该名称)在SHA512中,使用摘要算法标识符
ID
作为数据哈希
H
的前缀。不删除此前缀,因此它返回
ID | | H
。使用专用函数签名/验证更容易,例如,如果成功,它只返回
1
。我已经尝试了这两种方法ches(正如您在代码中看到的修改)。但似乎没有一个起作用。EVP_DecodeBlock在-1中失败。RSA_public_decrypt已经失败,RSA_verify(返回值为0)也是如此。(1)每当libcrypto例程返回错误指示时(对于libssl,有时您需要在ERR_*之前先出现SSL_get_error)。(2)您的“加密”是base64编码的。您可以使用EVP_DecodeBlock获取要“解密”的实际(二进制/原始)数据(您是正确的,实际上是签名验证而不是加密,但由于历史原因,我们仍使用该名称)在SHA512中,使用摘要算法标识符
ID
作为数据哈希
H
的前缀。不删除此前缀,因此它返回
ID | | H
。使用专用函数签名/验证更容易,例如,如果成功,它只返回
1
。我已经尝试了这两种方法ches(正如您在代码中看到的修改)。但是似乎没有一个能起作用。EVP_DecodeBlock在-
// RSA_verify
const unsigned char hash[64] = { 0x2c, 0x74, 0xfd, 0x17, 0xed, 0xaf, 0xd8, 0x0e, 0x84, 0x47, 0xb0, 0xd4, 0x67, 0x41, 0xee, 0x24, 0x3b, 0x7e, 0xb7, 0x4d, 0xd2, 0x14, 0x9a, 0x0a, 0xb1, 0xb9, 0x24, 0x6f, 0xb3, 0x03, 0x82, 0xf2, 0x7e, 0x85, 0x3d, 0x85, 0x85, 0x71, 0x9e, 0x0e, 0x67, 0xcb, 0xda, 0x0d, 0xaa, 0x8f, 0x51, 0x67, 0x10, 0x64, 0x61, 0x5d, 0x64, 0x5a, 0xe2, 0x7a, 0xcb, 0x15, 0xbf, 0xb1, 0x44, 0x7f, 0x45, 0x9b };
int verified = RSA_verify(NID_sha512, hash, sizeof(hash), decoded, RSA_size(rsa), rsa);

printf("\n%d\n", verified);