CryptoAPI解析X509格式的证书 c语言版本

   部分的CryptoAPI函数在VC++6.0上并没有定义,如CertGetNameString函数为CryptoAPI的管理函数,但是在VC++6.0下编译会报错,查看相应的wincrypt.h文件时会发现里边没有声明该函数。可以直接在vs2008下编译即可。

  以下代码在vs2008下编译:

//#ifndef _WIN32_WINNT
//#define _WIN32_WINNT    0X0400
//#endif

#include <windows.h>
#include <wincrypt.h>
#include <stdio.h>
#include <tchar.h>
#include <dos.h>
#include <string>
#include <ctime>
#pragma comment(lib, "crypt32.lib")
#define ENCODING (X509_ASN_ENCODING | PKCS_7_ASN_ENCODING)
#include <iostream> 
#include <time.h>

using namespace std;
 
int get_file_size(FILE * file_handle)///获得文件的大小
{
	
	//获取当前读取文件的位置 进行保存
	unsigned int current_read_position=ftell( file_handle );
	int file_size;
	fseek( file_handle,0,SEEK_END );
	//获取文件的大小
	file_size=ftell( file_handle );
	//恢复文件原来读取的位置
	fseek( file_handle,current_read_position,SEEK_SET );
	
	return file_size;
	
}

void hexdump(unsigned char *buf, int len) 
{
	int i = 0; 
	
	printf("\n----------------------hexdump------------------------\n");
	for(i = 0; i < len; i++) {
		printf("%02x ", buf[i]);
		if( (i+1) % 16 == 0) {
			printf("\n");
		}
	}
	
	if(i%16 != 0) {
		printf("\n");
	}
	
	printf("---------------------hexdump-------------------------\n\n");
}

void  FileTimeToTime_t(  FILETIME  ft,  time_t  *t  )  
{   
	ULARGE_INTEGER ui;  
	
	ui.LowPart =  ft.dwLowDateTime;  
	ui.HighPart =  ft.dwHighDateTime;  
	*t  =  ((LONGLONG)(ui.QuadPart  -  116444736000000000)/10000000); 
}

string time_t2string(const time_t time_t_time)
{
    char szTime[100] = {'\0'};
	
    tm *pTm;
    pTm = localtime(&time_t_time);
    pTm->tm_year += 1900;
    pTm->tm_mon +=1;
	
    sprintf(szTime, "%04d/%02d/%02d %02d:%02d:%02d",
        pTm->tm_year,
        pTm->tm_mon,
        pTm->tm_mday,
        pTm->tm_hour,
        pTm->tm_min,
        pTm->tm_sec);
	
    string strTime = szTime;
	
    return strTime;
}


int main()
{

	
	unsigned char* pbX509Data; // 证书数据
	unsigned long ulX509DataLen; // 证书数据长度
    FILE *fp = NULL;
	int nErrCode;
	int i;
	
	fp = fopen("newcert.cer", "a+");
	if(fp == NULL)
	{
		printf("fopen failed!\n");
	}
	ulX509DataLen = get_file_size(fp);
	printf("file size = %d\n",ulX509DataLen);
	pbX509Data = (unsigned char*)malloc(ulX509DataLen);
	fread(pbX509Data,ulX509DataLen ,1, fp);
	hexdump((unsigned char *)pbX509Data,ulX509DataLen);
    PCCERT_CONTEXT pCertContext = CertCreateCertificateContext(X509_ASN_ENCODING,pbX509Data, ulX509DataLen);
	if(pCertContext == NULL)
	{
		printf("pCertContext == NULL\n");		
		nErrCode = GetLastError();
		printf("nErrCode = 0x%x\n",nErrCode);
		printf("%s\n",strerror(nErrCode));///如果X509证书文件格式有问题,也许会报错8009310b
		return -1;
	}
	CRYPT_INTEGER_BLOB snBlob = pCertContext->pCertInfo->SerialNumber; 
	char SNchar[100];
	int j=0;
	for(i=snBlob.cbData-1;i>=0;i--)
	{
		sprintf(SNchar+j,"%02X ",snBlob.pbData[i]);
		j+=3;
	}
	printf("证书版本号:%s\n",SNchar);

	//证书名称
	wchar_t Issuer[256];
	CertGetNameString(pCertContext,CERT_NAME_SIMPLE_DISPLAY_TYPE,0,NULL,Issuer,sizeof(Issuer));
	///
	
	
    //获取转换所需的目标缓存大小
    DWORD dBufSize=WideCharToMultiByte(CP_OEMCP, 0, Issuer, -1, NULL,0,NULL, FALSE);
	
    //分配目标缓存
    char *dBuf = new char[dBufSize];
    memset(dBuf, 0, dBufSize);
	
    //转换
    int nRet=WideCharToMultiByte(CP_OEMCP, 0, Issuer, -1, dBuf, dBufSize, NULL, FALSE);
    
    if(nRet<=0)
    {
        printf("转换失败\n");
    }
    else
	{
        printf("证书名称:%s\n", dBuf);
    }
    delete []dBuf;
	///

	//证书颁发者
	wchar_t Subject[256];
	CertGetNameString(pCertContext,CERT_NAME_RDN_TYPE,0,NULL,Subject,sizeof(Subject));
	///
	
	
    //获取转换所需的目标缓存大小
    DWORD dBufSize1=WideCharToMultiByte(CP_OEMCP, 0, Subject, -1, NULL,0,NULL, FALSE);
	
    //分配目标缓存
    char *dBuf1 = new char[dBufSize1];
    memset(dBuf1, 0, dBufSize);
	
    //转换
    nRet=WideCharToMultiByte(CP_OEMCP, 0, Subject, -1, dBuf1, dBufSize1, NULL, FALSE);
    
    if(nRet<=0)
    {
        printf("转换失败\n");
    }
    else
	{
        printf("证书颁发者:%s\n", dBuf1);
    }
    delete []dBuf1;
	///

	
	
	//证书有效时间
	time_t start_time ;
	time_t end_time;
	FileTimeToTime_t(pCertContext->pCertInfo->NotBefore,&start_time); 
	FileTimeToTime_t(pCertContext->pCertInfo->NotAfter,&end_time); 
	
	cout<<"证书有效起始时间:"<<time_t2string(start_time)<<endl;
	cout<<"证书有效终止时间"<<time_t2string(end_time)<<endl;
	
	
	  
	//公钥
	CRYPT_BIT_BLOB PublicKey=pCertContext->pCertInfo->SubjectPublicKeyInfo.PublicKey;
	char Keychar[1024];
	j=0;
	for(i=0;i<PublicKey.cbData;i++)
	{
		sprintf(Keychar+j,"%02X ",PublicKey.pbData[i]);
		j+=3;
	}
	printf("证书公钥:%s\n",Keychar);
	
	return 0;
}

  上面的代码解析了X509格式证书的公钥、证书有效时间、证书颁发者、证书名称、证书版本号等。

运行代码如下图所示:

在win7下打开证书,如下图所示:

  

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值