Extract public key ASN.1 encode from X.509 certificate with OpenSSL

    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:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值