I need to test if a ECC certificate in PEM format is of good shape in C using the wolfssl library.
I do not want to test any further information only if it is a certificate and not any random Base64 encoded bytes between the
-----BEGIN CERTIFICATE-----
-----END CERTIFICATE-----
lines.
What is the easiest way to do so?
You can use the wolfSSL_X509_load_certificate_file to check if it's a valid certificate, as shown in the example bellow.
You can find the function documentation here.
#include <wolfssl/openssl/x509.h>
int is_x509_cert(const char* pem_cert_file_path) {
WOLFSSL_X509 *cert = wolfSSL_X509_load_certificate_file(pem_cert_file_path, SSL_FILETYPE_PEM);
if (cert != NULL) {
wolfSSL_X509_free(cert);
return 1;
} else {
return 0;
}
}
Related
I'm developing an application based on OpenSSL version 0.9.8a API and I need to verify an RSA signature (4096 bit RSA key) using an RSA public key pubkey.
This is my code:
const EVP_MD* md = EVP_get_digestbyname("SHA512");
if (!md)
{
return false;
}
if(EVP_DigestInit_ex(ctx, md, NULL)<=0)
{
return false;
}
if(EVP_DigestVerifyInit( ctx, NULL, md, NULL, pubKey)<=0)
{
return false;
}
if (EVP_DigestUpdate(ctx, Msg, MsgLen) <= 0)
{
return false;
}
int res = EVP_DigestFinal_ex(ctx, MsgHash, &MsgHashLen);
The problem is that the EVP_DigestVerifyInit function is not defined in openssl0.9.8a.
Is there an other way to verify an RSA signature in the version that predate OpenSSL version 1.0.0?
Here are my inputs:
/* Text_message saved to "sample.txt" file (text ends with the last chacracter '\n') */
My secret message.\n
/* generated RSA public key */
-----BEGIN PUBLIC KEY-----
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAl44E9YikPF9RzjAWxZXO
/GaJVCVdQOjp6pmSgL38WvS7glqMwQFwBzSqAiuvVkf3j9C+9Cgs2pypamfDBabC
CZX9+c4oE9zxW2wz0yT5dKL+lUuvIeKfDTMvttjHPtMn23S4ASqLZFAeJX0bCd9H
6l2/8KBjV+uinVlwvKGjXbE5ds2/8S2gei17WvdTb2ypvAUhdw7dc8IaSosG5lOa
EycLN6XKq0z8UX336PiuY0FzLa2B3FOOc6TuPpjkRuf73YKt/Xtm+78ztkfwHLUs
v+EX0TJpB8jE4DISiogNrceOPOnFipppxau2t0VjLivmYTnvSbJzIbOmutFGX8HV
17m3tUpATCdVDuMJ3ouCWOjIJSvw60gizOUHqmMBX+qG95mQ1h3QGP7SExYDKgfp
VpIEAVsnv+CvZTGOEIYcO9ROI2FM6fBgDxkHAdWFCkBVK6o5JxYmsHAXOfFVh+FD
K/pxCBuQINn5B6xanBJYmtpbtq7D0UcvVn6HP7w/9X/pvdU90+KMx1p5AZ6WFeNB
BWLp4whPnU6VEFo+UwXyrCWPIlq3vAz/TjxOXW0Plw+xtsoyw15C8+mS9/4x9XyV
O9v4vlvsRL46T/h4axVsbf2B5w4JC4VoNTuomObecQ0s3v+v54ZYJNsp/tLMa02n
+N9hImCjf+Y6HF8s6BKQ1B0CAwEAAQ==
-----END PUBLIC KEY-----
/* base64 encoded Signatue saved to "PKGC_sample_singed.enc64" file */
NIInzKblrnRZ3olbVUSJbYQhnn9VvDaadcsLNLAVRS/2rryzQr8FVo7ty4oQYqQT
KwRkwVakCxqs+Dg+wHCHQ+K6D6d43nGodC0kNgD1++vYeorUbpK7QNdMu+73g5pW
TiYCicKp6DfeYGWPLI0aYivQJqwNMxqrFd/CdNWhIap4f4fZb5WHcszqlsLCqtrr
qVLP3fXVlHzfiA6jqx2GVE5m43iXLB2H3DwXmjS8eX0veRTlcU5lOtoH/yAGRxmL
p3Mg/s3LSdiAL4Gki4nSORWVmsJ0IwtRttLAl5wYN2VAWz8n21wjCTcr9f2k7BQy
/W74zug+8rbnejFoS50YOKB27PKUTcv0Qn5tWYrk/BK4FPovXyj+tPHZ+jIvAdvX
7UbGl1fkyylb2C6DUxlPPZRxjiaoA4xKwaSFrwcMQnVFphE/LuyQ5aBQZVtAI8Sj
K4zws2BjbCUh+JWzJawCZmIt8IEq1IavW/t/YaMIqR4IMMnHghZGhN8Hm34UOIwB
uyTx1bX/AlKIs7h2ibKSL5JKunQ2IbLqvPeyhjLoFdqiv57JsIzA154xFyl1uXlj
Y32kmtn2LO8SsJcJmDFaD63sj3+WbTR+BRw0QZf9lE94Fa/MPooF0I49aNIx59Wa
2uRR9r0oBgMkpNH+kNmCXcRdPyWIbILGZShkKMcp0Oo=
/* The following steps describe openssl command line used to sign then verify the signature */
/* ***** Step 1: sign the message ***** */
/* Sing the message using the RSA private key genrated before */
dgst -sha512 -sign '/PATH...private_key.pem' -out '/PATH.../PKGC_sample_signed.binr' '/PATH.../sample.txt'
/* Base64 Encoding the signature */
base64 -in '/PATH.../PKGC_sample_signed.binr' -out '/PATH.../PKGC_sample_singed.enc64'
/* ***** Step 2: signature verification ***** */
/* Base64 Decode the signature */
base64 -d -in '/PATH.../PKGC_sample_singed.enc64' -out '/PATH.../PKGC_sample_signed.decod64'
/* Verify the signature using the public key */
dgst -sha512 -verify '/PATH.../public_key.pem' -signature '/PATH.../PKGC_sample_signed.decod64' '/PATH.../sample.txt'
==> I get Verify OK.
I am new to Elliptic Curve Cryptography, openSSL and wolfSSL. My context is that I generate KeyPair from command line with openssl and import the private key to my code. Then I use wolfSSL to generate signature and output it.
I save the output in DER format and try to verify with openSSL, the verification fails.
If I Sign and Verify inside my code with wolfSSL, it verifies successfully and also it's successful if I sign and verify in command line with openSSL.
Is there an encoding issue, which I am not sure about?
Update Code
// ECC public key
const uint8_t pubKey[] ={Hex Format key};
// ECC Signature from wolfSSL
char* sigString = {Signature from wolfSSL returned as char};
/* TYPE CONVERTIONS*/
const uint8_t *der_bytes_copy;
const uint8_t *pub_bytes_copy;
der_bytes_copy = (const unsigned char*)sigString;
pub_bytes_copy = pubKey;
EC_KEY *ECpubkey;
size_t keySize = sizeof(pubKey);
int eccgrp;
eccgrp = OBJ_txt2nid("secp256r1");
ECpubkey = EC_KEY_new_by_curve_name(eccgrp);
o2i_ECPublicKey(&ECpubkey, &pub_bytes_copy, keySize);
ECDSA_SIG *signature;
signature = d2i_ECDSA_SIG(NULL, &der_bytes_copy, signedSize);
uint8_t digest[36];
int verified;
const char message[] = "Test for Authenticate Kernel with ECC";
SHA256_CTX ctx;
SHA256_Init(&ctx);
SHA256_Update(&ctx, (const uint8_t*)message,sizeof(message));
SHA256_Final(digest, &ctx);
verified = ECDSA_do_verify(digest, sizeof(digest), signature, ECpubkey);
The private key is used with wolfSSL to sign the message and then the public key with openssl to verify, but this stops abruptly.
In the past when working with openSSL and comparing sign values to wolfSSL I have found that OpenSSL does the following steps when signing:
Read in and decode the key
compute a hash
Signature Encode the hash
sign the encoded hash
Base64 Encode the signature
OpenSSL does not make this apparent or user-friendly so unfortunately it's something you have to discover as you have.
Please use the following steps in wolfSSL to achieve your desired output:
1 Create or import your ECC key
2 Compute the sha hash on the input as you did previously
3 Encode the hash with this API call: encodedSz = wc_EncodeSignature(encodedOutput, hashInput, SHA256_DIGEST_SIZE, SHA256h);
4 Sign the encoded hash
5 Now do the verify
Let us know if that works for you.
I generated a public/private keypair with openssl:
openssl genrsa -out private.pem 1024
openssl pkcs8 -topk8 -in private.pem -outform DER -out private.der -nocrypt
openssl rsa -in private.pem -pubout -outform DER -out public.der
Now after that I created test code with Python, that was encrypting and deciphering strings. I took the example straight from PyCrypto documentation, encrypting:
string_to_encrypt = str(raw_input("Enter a string to encrypt: "))
print "Encrypting: %s" % string_to_encrypt
key = RSA.importKey(open('./public.der').read())
cipher = PKCS1_OAEP.new(key)
ciphertext = cipher.encrypt(string_to_encrypt)
and decrypting:
dec_key = RSA.importKey(open('./private.der').read())
d_cipher = PKCS1_OAEP.new(dec_key)
dec_message = d_cipher.decrypt(ciphertext)
Now this works as expected, and next I wanted to try deciphering same using C. I transfer the data via socket to the C application.. but now I'm unable to get the message back to clear text, even though the deciphering is not throwing errors.
Before I try to decipher the text, I print out the data to the screen, and the bytes match on both ends. The receiving function looks like this:
char* decrypt_packet(char* encrypted_buffer, int size) {
FILE *keyfile = fopen("./private.pem", "r");
RSA *rsa_pri = PEM_read_RSAPrivateKey (keyfile, NULL, NULL, NULL);
int rsa_private_len = RSA_size(rsa_pri);
for(i; i < size;i++)
printf("%02x:",(unsigned char)encrypted_buffer[i]);
printf("\n");
char * decrypt = (char*)malloc(rsa_private_len+1);
memset(decrypt,0,rsa_private_len+1); //Zero the buffer for printing
int res = RSA_private_decrypt(rsa_private_len, (unsigned char*)encrypted_buffer, (unsigned char*)decrypt, rsa_pri , RSA_NO_PADDING);
if(res == -1) {
ERR_load_crypto_strings();
printf("ERROR: %s\n",ERR_error_string(ERR_get_error(),NULL));
}
printf("size decrypt: %i\n", res);
printf("decrypted: %s\n", decrypt);
....
The deciphering doesn't fail, but the output is garbage (here sending just a test string "hello world"):
received buffer:
82:9d:a7:f7:3c:d6:71:12:01:31:ba:c6:a2:90:94:90:fd:69:d3:fe:14:11:2f:af:a9:8a:25:99:55:d2:84:1f:dc:e3:5e:a9:be:7b:8a:ac:cd:38:76:a2:91:ec:24:da:06:c7:8d:67:c8:15:19:73:c8:57:ce:a5:87:f0:da:db:c2:6d:5b:55:a3:ba:7e:7d:ca:6b:02:23:fd:fe:cb:b4:04:53:e2:74:c3:91:77:ee:5f:7a:61:7a:87:a6:42:37:28:c6:9c:cb:6a:46:f4:c0:bd:fe:8a:92:da:86:53:3b:5c:e2:e3:79:81:2c:32:28:9c:4c:be:0a:fa:75:7b:b2:
size decrypt: 128
decrypted: dÕf`5åiõuy<òáµÛ~G=/
Ä
I have chosen to use RSA_NO_PADDING? I have no idea really if this is correct.
But if I use something else, the decrypt function complains: RSA_padding_check_PKCS1_type_2:block type is not 02 or RSA_padding_check_PKCS1_OAEP:oaep decoding error
Am I correctly calling the RSA_private_decrypt function ? Could the problem be that I'm reading the private.pem file in C (in Python I was reading the .der file)?
One more thing came to mind. I used default openssl from Ubuntu to generate the keys, but my C application I'm linking against a downloaded and compiled source. The Makefile contains:
SOURCE_FILES = main.c client_handler.c
CC=gcc
$(CC) $(SOURCE_FILES) -o client_control_srv -lpthread -lssl -lcrypto -I/home/jlumme/openssl-1.0.1f_x86/include
Thanks for any tips!
Looks like my key generation was messed up.
I regenerated the keys:
openssl genrsa -out mykey_priv.pem 1024
openssl rsa -in mykey_priv.pem -out mykey_publ.der -outform DER -pubout
and now it works with the same code. As CBHacking pointed out, I also needed to have padding set to RSA_PKCS1_OAEP_PADDING.
I'm tryng to sign using DSA from OpenSSL. I have the files containing public and private keys.
First of all I make an unicast connection and every thing is fine. After that I need a multicast UDP connection and I want to sign the packets. I'm trying to use function PEM_read_DSA_PUBKEY() in order to load my public key from my cert but it doesn't work. It returns always NULL instead of a DSA struct.
Here you have a simplistic version of the code. I compile like this:
gcc -Wall -g -lm prueba.c -o prueba -lcrypto
Any idea? Thank you!
#include <stdio.h>
#include <openssl/dsa.h>
#include <openssl/pem.h>
int main()
{
FILE *DSA_cert_file = fopen("./certs/cert.pem", "r");
if (DSA_cert_file == NULL)
return 1;
printf("Certificate read\n");
DSA *dsa = DSA_new();
if((dsa = PEM_read_DSA_PUBKEY(DSA_cert_file, 0, 0, 0)) == NULL)
return 1;
printf("DSA public key read\n");
return 0;
}
Are you using a password-protected public key?
If yes, you are required to pass a callback function as the third argument to PEM_read_DSA_PUBKEY, so if the provided password matches, it will be able to properly load your key.
Update:
Alternatively, as pointed by Hasturkun, you can pass a null-terminated string as the fourth argument. Quoting the official documentation:
If the cb parameters is set to NULL
and the u parameter is not NULL then
the u parameter is interpreted as a
null terminated string to use as the
passphrase. If both cb and u are NULL
then the default callback routine is
used which will typically prompt for
the passphrase on the current terminal
with echoing turned off.
Does your cert.pem contains a X.509 certificate ? It looks like PEM_read_DSA_PUBKEY expects a PEM-encoded DSA public key without the X.509 container.
Try something like that instead:
X509 *cert;
EVP_PKEY *pk;
DSA *dsa;
cert = PEM_read_X509(DSA_cert_file,NULL,NULL,NULL);
if (!cert) { /* error */ }
pk = X509_get_pubkey(cert);
if (!pk) { /* error */ }
if (pk->type != 116) { /* not a dsa key */ }
dsa = pk->pkey.dsa
I have 2 separate programs (spliced together below). The first generates the key pair and saves to files (works fine). The second opens the private key, decrypting with a pass phrase and then I need it to sign a string of text. The code below fails on the PEM_read_PrivateKey() (last) call (can't see why). Can anyone point me at what I am doing wrong and then what openssl calls I should make to use the private key to sign some text?
int main (int argc, char *argv[])
{
char *priv_pem = "priv.pem";
char *pub_pem = "pub.pem";
char *pass = "Password";
FILE *fp;
int bits = 4096;
unsigned long exp = RSA_F4;
RSA *rsa;
EVP_PKEY *pkey;
// GENERATE KEY
rsa=RSA_generate_key(bits,exp,NULL,NULL);
if (RSA_check_key(rsa)!=1)
Exit(1,"Error whilst checking key","");
pkey = EVP_PKEY_new();
EVP_PKEY_assign_RSA(pkey, rsa);
// WRITE ENCRYPTED PRIVATE KEY
if (!(fp = fopen(priv_pem, "w")))
Exit(2,"Error opening PEM file",priv_pem);
if (!PEM_write_PrivateKey(fp,pkey,EVP_aes_256_cbc(),NULL,0,NULL,pass))
Exit(3,"Error writing PEM file",priv_pem);
fclose(fp);
// WRITE PUBLIC KEY
if (!(fp = fopen(pub_pem, "w")))
Exit(4,"Error opening PEM file",pub_pem);
if (!PEM_write_PUBKEY(fp, pkey))
Exit(5,"Error writing PEM file",pub_pem);
fclose(fp);
// ------- End of key generation program -------
// ------- Start of text signing program -------
// READ IN ENCRYPTED PRIVATE KEY
if (!(fp = fopen(priv_pem, "r")))
Exit(6,"Error reading encrypted private key file",priv_pem);
if (!PEM_read_PrivateKey(fp,&pkey,NULL,pass))
Exit(7,"Error decrypting private key file",priv_pem);
fclose(fp);
// Sign some text using the private key....
// FREE
RSA_free(rsa);
return 0;
}
Have you initialised pkey to NULL before you pass &pkey to PEM_read_PrivateKey()? If not, it will attempt to re-use the EVP_PKEY structure that pkey points to - and if pkey is uninitialised, it will be looking at a random spot in memory.
You can use ERR_print_errors_fp(stderr); to dump the OpenSSL error stack to stderr when an error occurs - this is often helpful in finding the problem.
Thanks #caf for your help.
By trial and error I fixed PEM_read_PrivateKey() error by adding the following to the start:
if (EVP_get_cipherbyname("aes-256-cbc") == NULL)
OpenSSL_add_all_algorithms();
However, I'm still looking for the best (practice) way of generating the keys and then using the private key for signing. From my limited understanding, I am looking for openssl methods that adhere to RSA's "PKCS #1 v2.0: RSA Cryptography Standard"