Here is a certificate in x509 format that stores the public key and the modulo:
const unsigned char *certificateDataBytes = {/*data*/};
Using OpenSSL and C, how can I convert it into an RSA object? I've tried several methods but I can't get it to work in RSA_public_encrypt
I think you mean public key into RSA * structure.
Since, you have certificate in bytes, if it is in DER encoded bytes, then you need to first convert it into X509 * structure.
X509 * cert;
EVP_PKEY * pubkey;
//length is the length of the certificateDataBytes in terms of bytes.
cert = d2i_x509 (NULL, certificateDataBytes, length);
pubkey = X509_get_pubkey (cert);
Please note that if certificate has RSA public key, then you can get RSA public key as follows:
RSA * rsa
rsa = EVP_PKEY_get1_RSA(pubkey);
//Now rsa contains RSA public key. Use it.
//After use, free the pubkey
EVP_PKEY_free (pubkey);
I hope this must solve your purpose.
If certificate encoding is different, use different function. Once, you get X509 *, rest step is same.
Related
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.
If I have an X509* that openssl has provided me, what's the best way to figure out the bit-ness of the RSA public key in the certificate? I can't quite figure this out. I'm pretty sure that if I'm in the SSL certificate verification callback, I can get the X509 ptr with
X509 * cert = X509_STORE_CTX_get_current_cert(the_x509_store_ctx);
and I would surmise I get the public key like this
EVP_PKEY *public_key = X509_get_pubkey(cert);
and then I need to check whether it's RSA, presumably?
if (public_key && (EVP_PKEY_RSA == public_key->type))
and once I know that I got a public key back and that it's RSA, I'd like to do this:
int key_length = BN_num_bits(public_key->pkey.rsa->n);
but I've found that while this works quite nicely on openssl 0.9.8, on 1.0.1h it segfaults on Windows. The BIGNUM 'n' doesn't seem to be valid - the data ptr in it has a garbage pointer.
Any idea what's wrong?
As already suggested, to get the RSA modulus size in bytes (so not "bit size"...) use:
EVP_PKEY * public_key = X509_get_pubkey(cert);
RSA *rsa_key = EVP_PKEY_get1_RSA(public_key);
int key_length = RSA_size(rsa_key);
...
RSA_free(rsa_key);
I'm trying to read a RSA public key generated with openssl like this:
Private Key:
openssl genrsa -out mykey.pem 1024
Public Key afterwards:
openssl rsa -in mykey.pem -pubout > somewhere.pub
Then I try to read:
FILE *keyfile = fopen("somewhere.pub", "r");
RSA *rsa_pub = PEM_read_RSAPublicKey(keyfile, NULL, NULL, NULL);
//rsa_pub == NULL!
When I'm reading the private key it works
FILE *keyfile = fopen("mykey.pem", "r");
RSA *rsa_pri = PEM_read_RSAPrivateKey(keyfile, NULL, NULL, NULL);
//all good
Any ideas?
I've read that openssl generate a X509 key of the RSA public key. But I could not manage to load even a X509 pub key.
Thanks
You might try PEM_read_RSA_PUBKEY() instead of PEM_read_RSAPublicKey().
This is all about formats.
The default public key file format generated by openssl is the PEM format.
PEM_read_RSA_PUBKEY() reads the PEM format. PEM_read_RSAPublicKey() reads the PKCS#1 format.
So if you want to stick to PEM_read_RSAPublicKey() you could generate the public key file using the PKCS#1 format by specifying the -outform DER option when generating the public key.
it seems there are two format of rsa public key, with different encoding.
A. RSA_PUBKEY
RSA* rsaPubKey = PEM_read_bio_RSA_PUBKEY( bio, NULL, 0, pass ) ;
read PUBKEY with this format
-----BEGIN PUBLIC KEY-----
...
-----END PUBLIC KEY-----
generated by
$ openssl rsa -in key.pri -pubout -out key.pub1
B. RSAPublicKey
RSA* rsaPubKey = PEM_read_bio_RSAPublicKey( bio, NULL, 0, pass ) ;
read PublicKey with this format
-----BEGIN RSA PUBLIC KEY-----
...
-----END RSA PUBLIC KEY-----
generated by
$ openssl rsa -in key.pri -RSAPublicKey_out -out key.pub2
convert
A to B format
$ openssl rsa -in key.pub1 -pubin -RSAPublicKey_out -out key.pub2_
B to A format
$ openssl rsa -in key.pub2 -RSAPublicKey_in -pubout -out key.pub1_
The openssl rsa utility saves the public key using the
function PEM_write_bio_RSA_PUBKEY and not PEM_write_bio_RSAPubicKey. So,
if you want your program to be compatible with its output, then you
should use PEM_write_bio_RSA_PUBKEY and PEM_read_bio_RSA_PUBKEY for
saving/loading public key files.
http://openssl.6102.n7.nabble.com/RSA-public-private-keys-only-work-when-created-programatically-td12532.html
Using C, I can generate and write an RSA public key to a PEM file using PEM_write_RSAPublicKey(),
But I want to write multiple public keys to a single file (like known_hosts or authorized_hosts), rather than have a separate PEM file for each.
I know how to encode/decode base64,
But how do I get the public key from the RSA structure (which I can base64 encode) and later read the same key from file and put it back into the RSA structure for encrypting/decrypting?
PEM_write_RSAPublicKey() will append to the file if opened with "a+" but there is no indication of which keys are for which client. I don't want PEM formatting, only to write each public key to a single line in the file.
I found that the public key is in DER format, which I can get from the RSA struct using:
len = i2d_RSAPublicKey(rsap, 0);
buf1 = buf2 = (unsigned char *)malloc(len + 1);
rc = i2d_RSAPublicKey(rsap, (unsigned char **)&buf2);
Then I base64-encode buf1 and write it to my file.
After reading it from file, putting it back into the RSA struct is just the reverse:
rsap = d2i_RSAPublicKey(NULL, (const unsigned char **)&buf1, (long)len);
I want to create a RSA key pair in C/C++ and export it to a string to work with it.
I managed to create the key
rsa = RSA_generate_key(bits, exp, NULL, NULL);
if(RSA_check_key(rsa)!=1){
std::cout << "Error while checking key" << std::endl << std::flush;
}
pkey = EVP_PKEY_new();
EVP_PKEY_assign_RSA(pkey, rsa);
From this point I can write the private and public key to a file with PEM_write_PUBKEY() and PEM_write_PrivateKey(). But what I want to do is to get the private and public key from pkey directly into a variable, preferable in the PEM format. I already looked around but couldn't find the right function. Any hints?
If you really need the PEM representation, then PEM_write_bio_RSA_PUBKEY() and PEM_write_bio_RSAPrivateKey() (along with their read counterparts) are the functions you want; give them memory BIOs to have them write into a memory buffer.
You can create a memory BIO by invoking e.g.
BIO * b = BIO_new(BIO_s_mem());
and get the memory buffer by invoking
void * buf;
BIO_get_mem_ptr(b, &buf);
You can also create a memory BIO around existing memory by invoking e.g.
BIO * b = BIO_new_mem_buf(buf, 9001)
but the resulting BIO will be read-only.