部分的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下打开证书,如下图所示: