Reputation: 798
I have sample program (taken from online samples) that creates RSA encryption.
#include <cstring>
#include <iostream>
#include <openssl/pem.h>
#include <openssl/rsa.h>
#include <openssl/bio.h>
RSA * createPublicRSA(unsigned char * key)
{
RSA * rsa= NULL;
BIO * keybio = BIO_new_mem_buf(key, -1);
rsa = PEM_read_bio_RSA_PUBKEY(keybio, &rsa, NULL, NULL);
return rsa;
}
int public_encrypt(unsigned char * data, int data_len, unsigned char * key, unsigned char * encrypted)
{
RSA * rsa = createPublicRSA(key);
int result = RSA_public_encrypt(data_len, data, encrypted, rsa, RSA_PKCS1_PADDING);
return result;
}
int main(int argc, char* argv[]) {
unsigned char publicKey[]="-----BEGIN PUBLIC KEY-----\n"\
"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAy8Dbv8prpJ/0kKhlGeJY\n"\
"ozo2t60EG8L0561g13R29LvMR5hyvGZlGJpmn65+A4xHXInJYiPuKzrKUnApeLZ+\n"\
"vw1HocOAZtWK0z3r26uA8kQYOKX9Qt/DbCdvsF9wF8gRK0ptx9M6R13NvBxvVQAp\n"\
"fc9jB9nTzphOgM4JiEYvlV8FLhg9yZovMYd6Wwf3aoXK891VQxTr/kQYoq1Yp+68\n"\
"i6T4nNq7NWC+UNVjQHxNQMQMzU6lWCX8zyg3yH88OAQkUXIXKfQ+NkvYQ1cxaMoV\n"\
"PpY72+eVthKzpMeyHkBn7ciumk5qgLTEJAfWZpe4f4eFZj/Rc8Y8Jj2IS5kVPjUy\n"\
"wQIDAQAB\n"\
"-----END PUBLIC KEY-----\n";
unsigned char plainText[2048/8] = "plain text"; //key length : 2048
size_t length = strlen(reinterpret_cast<const char*>(plainText));
unsigned char encrypted[4098]= {};
int encrypted_length = public_encrypt(plainText, length, publicKey, encrypted);
if (argc > 1) {
printf("Encrypted length: %d (Actual length: %lu)\n", encrypted_length, strlen(const_cast<const char*>(reinterpret_cast<char*>(encrypted))));
} else {
std::cout << encrypted;
}
}
And private key is:
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAy8Dbv8prpJ/0kKhlGeJYozo2t60EG8L0561g13R29LvMR5hy
vGZlGJpmn65+A4xHXInJYiPuKzrKUnApeLZ+vw1HocOAZtWK0z3r26uA8kQYOKX9
Qt/DbCdvsF9wF8gRK0ptx9M6R13NvBxvVQApfc9jB9nTzphOgM4JiEYvlV8FLhg9
yZovMYd6Wwf3aoXK891VQxTr/kQYoq1Yp+68i6T4nNq7NWC+UNVjQHxNQMQMzU6l
WCX8zyg3yH88OAQkUXIXKfQ+NkvYQ1cxaMoVPpY72+eVthKzpMeyHkBn7ciumk5q
gLTEJAfWZpe4f4eFZj/Rc8Y8Jj2IS5kVPjUywQIDAQABAoIBADhg1u1Mv1hAAlX8
omz1Gn2f4AAW2aos2cM5UDCNw1SYmj+9SRIkaxjRsE/C4o9sw1oxrg1/z6kajV0e
N/t008FdlVKHXAIYWF93JMoVvIpMmT8jft6AN/y3NMpivgt2inmmEJZYNioFJKZG
X+/vKYvsVISZm2fw8NfnKvAQK55yu+GRWBZGOeS9K+LbYvOwcrjKhHz66m4bedKd
gVAix6NE5iwmjNXktSQlJMCjbtdNXg/xo1/G4kG2p/MO1HLcKfe1N5FgBiXj3Qjl
vgvjJZkh1as2KTgaPOBqZaP03738VnYg23ISyvfT/teArVGtxrmFP7939EvJFKpF
1wTxuDkCgYEA7t0DR37zt+dEJy+5vm7zSmN97VenwQJFWMiulkHGa0yU3lLasxxu
m0oUtndIjenIvSx6t3Y+agK2F3EPbb0AZ5wZ1p1IXs4vktgeQwSSBdqcM8LZFDvZ
uPboQnJoRdIkd62XnP5ekIEIBAfOp8v2wFpSfE7nNH2u4CpAXNSF9HsCgYEA2l8D
JrDE5m9Kkn+J4l+AdGfeBL1igPF3DnuPoV67BpgiaAgI4h25UJzXiDKKoa706S0D
4XB74zOLX11MaGPMIdhlG+SgeQfNoC5lE4ZWXNyESJH1SVgRGT9nBC2vtL6bxCVV
WBkTeC5D6c/QXcai6yw6OYyNNdp0uznKURe1xvMCgYBVYYcEjWqMuAvyferFGV+5
nWqr5gM+yJMFM2bEqupD/HHSLoeiMm2O8KIKvwSeRYzNohKTdZ7FwgZYxr8fGMoG
PxQ1VK9DxCvZL4tRpVaU5Rmknud9hg9DQG6xIbgIDR+f79sb8QjYWmcFGc1SyWOA
SkjlykZ2yt4xnqi3BfiD9QKBgGqLgRYXmXp1QoVIBRaWUi55nzHg1XbkWZqPXvz1
I3uMLv1jLjJlHk3euKqTPmC05HoApKwSHeA0/gOBmg404xyAYJTDcCidTg6hlF96
ZBja3xApZuxqM62F6dV4FQqzFX0WWhWp5n301N33r0qR6FumMKJzmVJ1TA8tmzEF
yINRAoGBAJqioYs8rK6eXzA8ywYLjqTLu/yQSLBn/4ta36K8DyCoLNlNxSuox+A5
w6z2vEfRVQDq4Hm4vBzjdi3QfYLNkTiTqLcvgWZ+eX44ogXtdTDO7c+GeMKWz4XX
uJSUVL5+CVjKLjZEJ6Qc2WZLl94xSwL71E41H4YciVnSCQxVc4Jw
-----END RSA PRIVATE KEY-----
When I build it
g++ encr.cpp -o encr -lcrypto -I/opt/local/include/
and run it several times, I get variable "Actual length"
$ ./encr show-length
Encrypted length: 256 (Actual length: 256) <--- Correct
$ ./encr show-length
Encrypted length: 256 (Actual length: 79)
$ ./encr show-length
Encrypted length: 256 (Actual length: 215)
$ ./encr show-length
Encrypted length: 256 (Actual length: 52)
$ ./encr show-length
Encrypted length: 256 (Actual length: 256) <--- Correct
$ ./encr show-length
Encrypted length: 256 (Actual length: 48)
You may also do ./encr | wc | awk '{print $3;}'
to get sizes
Whereever I mentioned "correct" it will decrypt fine otherwise I get errors (here are sample)
$ ./encr | openssl rsautl -decrypt -inkey private.pem
RSA operation error
140735156518992:error:0407109F:rsa routines:RSA_padding_check_PKCS1_type_2:pkcs decoding error:rsa_pk1.c:273:
140735156518992:error:04065072:rsa routines:RSA_EAY_PRIVATE_DECRYPT:padding check failed:rsa_eay.c:602:
$ ./encr | openssl rsautl -decrypt -inkey private.pem <---------------------------------- CORRECTLY PADDED
plain text$ ./encr | openssl rsautl -decrypt -inkey private.pem
RSA operation error
140735156518992:error:0407109F:rsa routines:RSA_padding_check_PKCS1_type_2:pkcs decoding error:rsa_pk1.c:273:
140735156518992:error:04065072:rsa routines:RSA_EAY_PRIVATE_DECRYPT:padding check failed:rsa_eay.c:602:
$ ./encr | openssl rsautl -decrypt -inkey private.pem <---------------------------------- CORRECTLY PADDED
plain text$ ./encr | openssl rsautl -decrypt -inkey private.pem <---------------------------------- CORRECTLY PADDED
plain text$ ./encr | openssl rsautl -decrypt -inkey private.pem
RSA operation error
140735156518992:error:0407109F:rsa routines:RSA_padding_check_PKCS1_type_2:pkcs decoding error:rsa_pk1.c:273:
140735156518992:error:04065072:rsa routines:RSA_EAY_PRIVATE_DECRYPT:padding check failed:rsa_eay.c:602:
What is it that I'm doing wrong in my usage of RSA_public_encrypt
?
Upvotes: 1
Views: 1346
Reputation: 33266
In C/C++ char*
and unsigned char*
can either mean "a string" or "some bytes", and it's up to the developer to know which is which (though unsigned char*
usually means "some bytes", the "unsigned" being the clue).
RSA, like almost all computer-designed cryptographic routines, operates on bytes. Sometimes the input bytes are text, but the output bytes are almost always not.
If you had a 40-bit RSA key, it could produce as an answer 21 74 65 78 74
. strlen
on a pointer to that location will return... some number that is at least 5
. If it returns exactly 5 it means that we got lucky and the next segment of memory was already assigned as 0x00
. And in this lucky case we could printf (%s) the pointer and it will emit !text
.
It could have just as likely produced 25 00 F2 1B D5
, which will strlen
as 1
because the second byte being 0x00
is how strlen
interprets "end of string".
If you need your output to be text, you'll need to convert it to a textual form. Hexadecimal is a common way for short values, but RSA-2048 produces a 256-byte answer. That would be 512 hex characters, or in Base64 it would only be 344, which is why Base64 encoding tends to be used in these situations.
Upvotes: 2