X509_get0_pubkey_bitstr( ) function is declared in x509.h of OpenSSL source code set. Let's have a look at it:
ASN1_BIT_STRING *X509_get0_pubkey_bitstr(const X509 *x);
When the public key ASN.1 encode is needed to be extracted from X.509 certificate, this function can be used. Example programs are given in several files as follows:
1) extract_pub_key.h:
/**************************************************
* File name: extract_pub_key.h
* Author: HAN Wei
* Author's blog: http://blog.csdn.net/henter/
* Date: Sept 25th, 2018
* Description: declare functions of extracting public
key encode from X.509 certificate
**************************************************/
#ifndef HEADER_EXTRACT_PUBLIC_KEY_ENCODE_FROM_X509_CERTIFICATE_H
#define HEADER_EXTRACT_PUBLIC_KEY_ENCODE_FROM_X509_CERTIFICATE_H
#ifdef __cplusplus
extern "C" {
#endif
/**************************************************
* Name: ExtractPubKeyEncodeFromCert
* Function: extract public key ASN.1 encode from X.509 certificate
* Parameters:
cert[in] certificate in the form of X.509 DER
encode
cert_len[in] certificate byte length
pub_key_encode[out] ASN.1 encode of public key
pub_key_encode_len[in, out] ASN.1 encode byte length of public key
* Return value:
0: function executes successfully
any other value: an error occurs
* Notes:
1. When the value of pub_key_encode is NULL, this function only
calculates the byte length of public key ASN.1 encode, and assigns
the length to the integer that parameter pub_key_encode points to.
It does not extract public key encode from certificate.
2. When the value of pub_key_encode is not NULL, this function
extracts public key encode from certificate, and the byte
length of public key encode is assigned to the integer that
the parameter pub_key_encode points to.
**************************************************/
int ExtractPubKeyEncodeFromCert(unsigned char *cert,
const int cert_len,
unsigned char *pub_key_encode,
int *pub_key_encode_len);
/**************************************************
* Name: ExtractPubKeyEncodeFromCertFile
* Function: extract public key ASN.1 encode from X.509 certificate file
* Parameters:
cert_file[in] certificate file name. The file is in
the form of X.509 DER encode, and file
path can be included
pub_key_encode[out] ASN.1 encode of public key
pub_key_encode_len[in, out] ASN.1 encode byte length of public key
* Return value:
0: function executes successfully
any other value: an error occurs
* Notes:
1. When the value of pub_key_encode is NULL, this function only
calculates the byte length of public key ASN.1 encode, and assigns
the length to the integer that parameter pub_key_encode points to.
It does not extract public key encode from certificate.
2. When the value of pub_key_encode is not NULL, this function
extracts public key encode from certificate, and the byte
length of public key encode is assigned to the integer that
the parameter pub_key_encode points to.
**************************************************/
int ExtractPubKeyEncodeFromCertFile(char *cert_file,
unsigned char *pub_key_encode,
int *pub_key_encode_len);
#ifdef __cplusplus
}
#endif
#endif /* end of HEADER_EXTRACT_PUBLIC_KEY_ENCODE_FROM_X509_CERTIFICATE_H */
2) extract_pub_key.c:
/**************************************************
* File name: extract_pub_key.c
* Author: HAN Wei
* Author's blog: http://blog.csdn.net/henter/
* Date: Sept 25th, 2018
* Description: implement functions of extracting public
key encode from X.509 certificate
**************************************************/
#include <openssl/x509.h>
#include "extract_pub_key.h"
#include "c_file_operation.h"
/*************************************************************/
int ExtractPubKeyEncodeFromCert(unsigned char *cert,
const int cert_len,
unsigned char *pub_key_encode,
int *pub_key_encode_len)
{
X509 *certificate = NULL;
const unsigned char *p = cert;
unsigned char *q = pub_key_encode;
ASN1_BIT_STRING *pub_key_bit_str;
int encode_len;
if ( !(d2i_X509(&certificate, &p, cert_len)) )
{
#ifdef _DEBUG
printf("X509 certificate decode failed at %s, line %d!\n", __FILE__, __LINE__);
#endif
return (-1);
}
if ( !(pub_key_bit_str = X509_get0_pubkey_bitstr(certificate)) )
{
#ifdef _DEBUG
printf("Get public key from X.509 certificate decode failed at %s, line %d!\n", __FILE__, __LINE__);
#endif
X509_free(certificate);
return (-1);
}
encode_len = i2d_ASN1_BIT_STRING(pub_key_bit_str, NULL);
if (encode_len <= 0)
{
#ifdef _DEBUG
printf("Calculate public key ASN.1 encode length failed at %s, line %d!\n", __FILE__, __LINE__);
#endif
X509_free(certificate);
return (-1);
}
if (pub_key_encode)
{
if (*pub_key_encode_len < encode_len)
{
#ifdef _DEBUG
printf("Error! Buffer length is not enough at %s, line %d!\n", __FILE__, __LINE__);
#endif
X509_free(certificate);
return (-1);
}
if ( (i2d_ASN1_BIT_STRING(pub_key_bit_str, &q)) <= 0 )
{
#ifdef _DEBUG
printf("Encode public key failed at %s, line %d!\n", __FILE__, __LINE__);
#endif
X509_free(certificate);
return (-1);
}
}
*pub_key_encode_len = encode_len;
X509_free(certificate);
return 0;
}
/*************************************************************/
int ExtractPubKeyEncodeFromCertFile(char *cert_file,
unsigned char *pub_key_encode,
int *pub_key_encode_len)
{
int error_code;
long long file_length;
int file_len;
char *buffer;
if ( error_code = GetFileLength(cert_file, &file_length) )
{
#ifdef _DEBUG
printf("Get certificate file length failed at %s, line %d!\n", __FILE__, __LINE__);
#endif
return error_code;
}
file_len = (int)file_length;
if ( error_code = ReadFileIntoMemoryBuffer(cert_file, &buffer) )
{
#ifdef _DEBUG
printf("Read certificate file into memory failed at %s, line %d!\n", __FILE__, __LINE__);
#endif
return error_code;
}
if ( error_code = ExtractPubKeyEncodeFromCert((unsigned char *)buffer,
file_len,
pub_key_encode,
pub_key_encode_len) )
{
#ifdef _DEBUG
printf("Get public key encode from X.509 certificate file failed at %s, line %d!\n", __FILE__, __LINE__);
#endif
FreeFileInMemoryBuffer(buffer);
return error_code;
}
FreeFileInMemoryBuffer(buffer);
return 0;
}
3) Two files: c_file_operation.h and c_file_operation.c . They are published in the blog 'Some simple file operation functions implemented in C' . The website is: https://blog.csdn.net/henter/article/details/77937393
4) test.c :
/**************************************************
* File name: test.c
* Author: HAN Wei
* Author's blog: http://blog.csdn.net/henter/
* Date: Sept 25th, 2018
* Description: demonstrate how to invoke functions
of extracting public key from X.509 certificate
**************************************************/
#include <stdio.h>
#include <stdlib.h>
#include "extract_pub_key.h"
int main(void)
{
int error_code;
char cert[] = {"sample_cert.cer"};
unsigned char *pub_key_encode;
int pub_key_encode_len, i;
if (error_code = ExtractPubKeyEncodeFromCertFile(cert,
NULL,
&pub_key_encode_len))
{
printf("Get public key ASN.1 encode length failed!\n");
return error_code;
}
if ( !(pub_key_encode = (unsigned char *)(malloc)(pub_key_encode_len)) )
{
printf("Memory allocation failed!\n");
return (-1);
}
if (error_code = ExtractPubKeyEncodeFromCertFile(cert,
pub_key_encode,
&pub_key_encode_len))
{
printf("Extract public key ASN.1 encode failed!\n");
free(pub_key_encode);
return error_code;
}
printf("Extract public key ASN.1 encode succeeded!\n");
printf("Public key encode length is %d bytes.\n", pub_key_encode_len);
printf("Public key encode:\n");
for (i = 0; i < pub_key_encode_len; i++)
{
printf("0x%x ", pub_key_encode[i]);
}
printf("\n");
free(pub_key_encode);
return 0;
}
An sample certificate file named by 'sample_cert.cer' is used here. Its internal structure can be viewed by a tool called 'Asn1View':
When the demo program is runned, the output is: