【发布时间】:2019-12-25 09:28:52
【问题描述】:
我有一个小型 react-native 应用程序,它使用 RSA 私钥对消息进行签名。这是对消息进行签名的代码段(在本例中为 Hello World)
import { RSA } from 'react-native-rsa-native'
RSA.generateKeys(2048).then(keys => {
RSA.signWithAlgorithm('Hello World', keys.private, RSA.SHA512withRSA).then(message => {
console.log(message)
// "TfAgdPqm+CPxAqxPdV1jfGQvZAZ+uQ/sAlaHCK0ZvHKnRhHnKj+I2PHZhHhM5tJ14hgPd9H48Pe5\nbPFXj0KTk/Ty8YOcd7h98STwmJyNzlqM03Get42q9fD//ofyFZfQrm3R2OZjgOlQ5myepqko8+nk\nobuawPNVsi2Eu+N6PBBAW86hX9pRfKP3gkrOCK8ae1k9O9ysOXucSguaV1++WHkv30O2mN2rsEAT\nATi6SFxYry6n9G+6gIxOyWF9X8qleg3dJgURAPwpD1SWnTOb2hZChpYOWnIreqO9hGQlTgMVzDx3\nncdGpuJ4EatW4ETBO9ox+s7OeqI4TQxt0kH09Q==\n"
})
})
现在,我正在尝试使用 OpenSSL 的 RSA_public_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;
}
但解密(验证)没有发生,因为 RSA_public_decrypt(RSA_verify) 失败并返回 -1(0) 值。任何帮助表示赞赏。
【问题讨论】:
-
(1) 每当 libcrypto 例程返回错误指示 look at the errror queue (aka error stack) 时(对于 libssl sometimes,您需要在 ERR_* 之前使用 SSL_get_error)。 (2) 您的“加密”是 base64 编码的。您可以使用 EVP_DecodeBlock 将实际(二进制/原始)数据“解密”(您说得对,实际上是签名验证而不是加密,但由于历史原因,我们坚持使用该名称)
-
RSASSA-PKCS1-v1_5 为带有摘要算法标识符
ID的数据的哈希H加上前缀,在本例中为 SHA512 的0x3051300d060960864801650304020305000440。RSA_public_decrypt不会删除此前缀,因此它会返回ID || H。使用专用功能进行签名/验证更容易,例如RSA_verify,如果成功则简单地返回1。 -
我已经尝试了你的两种方法(正如你在代码中看到的修改)。但似乎没有一个工作。 EVP_DecodeBlock 以 -1 失败。 RSA_public_decrypt 已经失败,RSA_verify 也是如此(返回值为 0)。
标签: authentication encryption openssl rsa