> From: [email protected] On Behalf Of Luca Costantino
> Sent: Saturday, 12 December, 2009 17:14
> i'm having some troubles with this (simple) code...
>
> #include
> #include
> #include
> #include
> #include
> #include
> #include
> #include
> #include
> #include
> #include
> #include
> #include
> #include
> #include
> #include
> #include
> #include
>
I assume those are actually #include <header> and just got
stripped by some HTML or pseudo-HTML (or XML) mailing process.
> #define PUB_KEY "../chiave/pubkey.pem"
> #define PRIV_KEY "../chiave/keynopwd.pem"
>
> int cifra_messaggio(char* messaggio_in_chiaro, char*
> messaggio_cifrato) {
> FILE* fdpub = fopen(PUB_KEY, "r");
> RSA* chiave_pubblica = RSA_new();
> PEM_read_RSA_PUBKEY(fdpub, &chiave_pubblica, NULL, NULL);
> messaggio_cifrato = malloc(RSA_size(chiave_pubblica));
>
This sets the pointer *in cifra_ only* see below.
> printf("Info:\tPubkey successfully loaded\n");
> printf("Info:\tMessage length is %d byte\n",
> strlen(messaggio_in_chiaro));
>
> int n_byte_cifrati =
> RSA_public_encrypt(strlen(messaggio_in_chiaro) +
> 1, messaggio_in_chiaro, messaggio_cifrato, chiave_pubblica,
> RSA_PKCS1_OAEP_PADDING);
> if(n_byte_cifrati == 0 || n_byte_cifrati == -1) {
> printf("Err :\tUnable to encrypt\n");
Here you ought to display the error(stack) in the same way
you do below in decifra_ .
> errore_non_recuperabile();
> exit(-1);
> }
>
> printf("Info:\tText successfully encrypted\n");
> printf("Info:\t%d byte encrypted\n", n_byte_cifrati);
> RSA_free(chiave_pubblica);
> fclose(fdpub);
>
> return n_byte_cifrati;
> }
>
> int decifra_messaggio(char* messaggio_cifrato, char*
> messaggio_decifrato) {
> FILE* fdpriv = fopen(PRIV_KEY, "r");
> RSA* chiave_privata;
>
> chiave_privata = PEM_read_RSAPrivateKey(fdpriv, NULL,
> NULL, NULL);
In cifra_ you preallocated pubkey and used the second argument;
here you let OpenSSL allocate and use the return value.
Both are legal, but it's confusing to be inconsistent.
> messaggio_decifrato = malloc(RSA_size(chiave_privata));
>
This sets the pointer *in decifra_ only* see below.
> printf("Info:\tPrivkey successfully loaded\n");
>
> int n_byte_decifrati = RSA_private_decrypt(512,
> messaggio_cifrato,
> messaggio_decifrato, chiave_privata, RSA_PKCS1_OAEP_PADDING);
Even if _cifrato were valid (see below), 512 is the correct length
only for a 4Kbit key. Which is possible but rare. cifra_ should
return both the pointer and count, the caller (main) should save
both and pass both in to decifra_ which should use them.
> if(n_byte_decifrati == 0 || n_byte_decifrati == -1) {
> printf("Err :\tUnable to decrypt\n");
>
> char* errore = malloc(1024);
> bzero(errore, 1024);
> printf("%s\n",
> ERR_error_string(ERR_get_error(), errore));
>
Minor points: no need to use malloc() here, much less bzero();
just declare a local array. There can be more than one item
in the error stack; best to loop until ERR_get_error() returns
zero, which requires you put it (temporarily) in a variable.
If you just want output to a file, as here (stdout),
ERR_print_errors_fp is easier to use. See below about strings.
> errore_non_recuperabile();
> exit(-1);
>
> }
>
> printf("Info:\tText successfully decripted\n");
>
> RSA_free(chiave_privata);
> fclose(fdpriv);
>
> return n_byte_decifrati;
> }
>
> int main(int argc, char* argv[]) {
> char* messaggio = "Questo รจ un messaggio di prova lungo qualche
> decina di caratteri...";
> char* cifrato;
> char* decifrato;
>
Only the first pointer is initialized here; the others are garbage
(and are NOT set by the calls below).
> cifra_messaggio(messaggio, cifrato);
This does the encryption, but throws away (leaks) the pointer
to malloc'ed storage, and also the length.
> decifra_messaggio(cifrato, decifrato);
>
This attempts to decrypt some random memory, and in the very
unlikely case it succeeds, throws away (leaks) the result.
> printf("Plaintext\t%s\n", messaggio);
> printf("Cyphertext\t%s\n", decifrato);
>
Once the other bugs are fixed that label is misleading: the
result of deciphering is plaintext again, not ciphertext.
(And if you do want to display 'cifrato', printf %s won't
come even close; it's not printable nor null-terminated.)
> if(strncmp(messaggio, decifrato, 512) != 0) {
> printf("Info:\tMessages are different\n");
> errore_non_recuperabile();
> exit(-1);
> }
>
> printf("Info:\tMessages are equal\n");
>
> return 1;
> }
>
Aside: Unix programs conventionally exit with 0 for success,
and a value >0 (not negative) for error.
> i got this error
>
> error:0407A079:lib(4):func(122):reason(121)
>
> and i'm not able to understand why...
>
1) You got the error because of the bugs above.
2) You got an unhelpful *display* of the error because you
didn't load errorstrings before using ERR_error_string .
Easiest is to call ERR_load_crypto_strings() at startup.
There are other possibilities for very constrained systems.
3) Having gotten the unhelpful display, you can decode it
with the commandline utility 'errstr'; in this case:
>openssl errstr 0407A079
error:0407A079:rsa routines:RSA_padding_check_PKCS1_OAEP:oaep decoding error
4) 2 and 3 are FAQs: http://www.openssl.org/support/faq.html#PROG7
Also, in general you should always check the return values
from fopen(), malloc(), *_new and other allocating routines
e.g. PEM_read*(,NULL...) for null before using them.
______________________________________________________________________
OpenSSL Project http://www.openssl.org
Development Mailing List [email protected]
Automated List Manager [email protected]