随笔-10  评论-36  文章-6  trackbacks-0
// examCrypt.cpp : 定义控制台应用程序的入口点。
//

#include 
"stdafx.h"

// Link with the Crypt32.lib file.
#pragma comment(lib, "Crypt32")
#pragma comment(lib, 
"comsuppw.lib")
#define MY_ENCODING_TYPE (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING)

//============================================================================================

// 暂停
void pause()
{
    _tprintf(L
"\nPress ENTER key to continue \n");
    getchar();
}


// 错误报告
void CancelByError(TCHAR* str)
{
    _tprintf(L
"\nFAULT:\n");
    _tprintf(L
"An error occurred in running the program. \n");
    _tprintf(L
"%s", str);
    _tprintf(L
"Error number %x. \n", GetLastError());
    _tprintf(L
"Program terminating. \n");
    pause();
    exit(
1);
}


// 字节反序
void reverse(BYTE* data, int nLen)
{
    
for(int ii=0; ii < nLen/2; ii++)
    
{
        BYTE c 
= data[ii];
        data[ii] 
= data[nLen -ii -1];
        data[nLen 
-ii -1= c;
    }

}


// 输出文件
void writeFile(const char* sFileName, BYTE* data, DWORD nSize)
{
    FILE
* fp = fopen(sFileName, "wb");
    
if(fp == NULL)
    
{
        printf(
"Can not open output file '%s'! \n", sFileName);
        
return;
    }


    
if(fwrite(data, 1, nSize, fp) != nSize)
    
{
        fclose(fp);
        printf(
"Write to file '%s' failed! \n", sFileName);
        
return;
    }


    fclose(fp);
    printf(
"Write %d bytes to file '%s'! \n", nSize, sFileName);
}


// 读取文件(data = NULL for get file size ONLY)
void readFile(const char* sFileName, BYTE* data, DWORD & nSize)
{
    nSize 
= 0;

    FILE
* fp = fopen(sFileName, "rb");
    
if(fp == NULL)
    
{
        printf(
"Can not open input file '%s'! \n", sFileName);
        
return;
    }


    fseek(fp, 
0, SEEK_END);
    nSize 
= ftell(fp);
    fseek(fp, 
0, SEEK_SET);

    
if(data != NULL)
    
{
        
if(fread(data, 1, nSize, fp) != nSize)
        
{
            fclose(fp);
            printf(
"Read from file '%s' failed! \n", sFileName);
            
return;
        }

        printf(
"Read %d bytes from file '%s'! \n", nSize, sFileName);
    }

    fclose(fp);
}


// 显示HEX码
void showData(BYTE* data, DWORD nSize)
{
    printf(
"\n****\n");
    
for(DWORD ii=0; ii < nSize; ii++)
    
{
        printf(
"%02x ", data[ii]);
        
if((ii+1% 16 ==0) printf("\n");
    }

    printf(
"\n**** %d bytes\n", nSize);
}


// 准备数据(Auto new outData)
void prepareData(BYTE* inData, DWORD inSize, LPCSTR inFileName, BYTE* &outData, DWORD& outSize)
{
    
if(inData == NULL && inFileName != NULL)
    
{
        
// Read from file
        readFile(inFileName, NULL, outSize);
        
if(outSize != 0)
        
{
            outData 
= (BYTE*new char[outSize];
            
if(outData == NULL)    CancelByError(L"Not enough memory. \n");
            readFile(inFileName, outData, outSize);
        }

    }

    
else
    
{
        
// Read from buffer
        outSize = inSize;
        outData 
= (BYTE*new char[outSize];
        
if(outData == NULL)    CancelByError(L"Not enough memory. \n");
        memcpy(outData, inData, outSize);
    }

}


//=====================================================================================================

//============================ 离散算法

// SHA1 
void hashSHA1(BYTE* inData, int inSize, LPCSTR inFileName = NULL, LPCSTR outFileName = NULL)
{
    
// 准备数据
    CRYPT_DATA_BLOB orgBlob;
    memset(
&orgBlob, 0sizeof(orgBlob));
    prepareData(inData, inSize, inFileName, orgBlob.pbData, orgBlob.cbData);

/*
BOOL WINAPI CryptAcquireContext(
  __out         HCRYPTPROV* phProv,
  __in          LPCTSTR pszContainer,
  __in          LPCTSTR pszProvider,
  __in          DWORD dwProvType,
  __in          DWORD dwFlags
);
*/

    
// 获取CSP句柄
    HCRYPTPROV hProv = NULL; 
    
if(!CryptAcquireContext(
        
&hProv,                // 返回的句柄
        NULL,                // CSP 容器名称
        NULL,                // CSP 提供者名称
        PROV_RSA_FULL,        // CSP 提供者类型
        0))                    // 附加参数:
    {
        delete [] orgBlob.pbData;
        CancelByError(L
"Get CSP provider context failed! \n");
    }


/*
BOOL WINAPI CryptCreateHash(
__in          HCRYPTPROV hProv,
__in          ALG_ID Algid,
__in          HCRYPTKEY hKey,
__in          DWORD dwFlags,
__out         HCRYPTHASH* phHash
);
*/

    
// 创建HASH句柄
    HCRYPTHASH hHash = NULL;
    
if(!CryptCreateHash(
        hProv,                
// 容器句柄 
        CALG_SHA1,            // 算法标识
        NULL,                // 算法使用的Key
        0,                    // 算法标识
        &hHash))            // 返回的HASH对象
    {
        delete [] orgBlob.pbData;
        CryptReleaseContext(hProv, 
0);
        CancelByError(L
"Get SHA1 provider failed!\n");
    }


/*
BOOL WINAPI CryptHashData(
  __in          HCRYPTHASH hHash,
  __in          BYTE* pbData,
  __in          DWORD dwDataLen,
  __in          DWORD dwFlags
);
*/

    
// 添加HASH内容
    if(!CryptHashData(hHash, orgBlob.pbData, orgBlob.cbData, 0))
    
{
        delete [] orgBlob.pbData;
        CryptReleaseContext(hProv, 
0);
        CancelByError(L
"Calc SHA1 data failed!\n");
    }


/* TODO: Calc other blocks
    if(CryptHashData(hHash, (BYTE*) "12345", 5, 0) == 0)
    {
        CancelByError(L"Calc SHA1 data failed!\n");
        return; 
    }
*/


/*
BOOL WINAPI CryptGetHashParam(
  __in          HCRYPTHASH hHash,
  __in          DWORD dwParam,
  __out         BYTE* pbData,
  __in_out      DWORD* pdwDataLen,
  __in          DWORD dwFlags
);
*/

    
// 获取HASH值
    BYTE byHashVal[21];    // SHA1 output have 20 bytes. 
    memset(byHashVal, 0x0021); 
    DWORD dwDataLen 
= 20
    
if(!CryptGetHashParam(hHash, HP_HASHVAL, byHashVal, &dwDataLen, 0))
    
{
        delete [] orgBlob.pbData;
        CryptDestroyHash(hHash); 
        CryptReleaseContext(hProv, 
0);
        CancelByError(L
"Calc SHA1 data failed!\n");
    }


    showData(byHashVal, dwDataLen);
    
if(outFileName != NULL)
    
{
        writeFile(outFileName, byHashVal, dwDataLen);
    }


    
// 清理

    delete [] orgBlob.pbData;

    
if(hHash != NULL)
    
{
        CryptDestroyHash(hHash); 
        hHash 
= NULL;
    }


    
if(hProv != NULL)
    
{
        CryptReleaseContext(hProv, 
0);
        hProv 
= NULL;
    }

}


// ============================ 对称加密解密

// DES(CBC/PKCS5Padding)
void DESEncrypt(BYTE* key, BYTE* iv, BYTE* inData, int inSize, LPCSTR inFileName = NULL, LPCSTR outFileName = NULL)
{
    
// 准备数据
    CRYPT_DATA_BLOB orgBlob;
    memset(
&orgBlob, 0sizeof(orgBlob));
    prepareData(inData, inSize, inFileName, orgBlob.pbData, orgBlob.cbData);

/*
BOOL WINAPI CryptAcquireContext(
  __out         HCRYPTPROV* phProv,
  __in          LPCTSTR pszContainer,
  __in          LPCTSTR pszProvider,
  __in          DWORD dwProvType,
  __in          DWORD dwFlags
);
*/


    
// 获取CSP句柄
    HCRYPTPROV hProv = NULL; 
    
if(!CryptAcquireContext(
        
&hProv,                // 返回的句柄
        NULL,                // CSP 容器名称
        NULL,                // CSP 提供者名称
        PROV_RSA_FULL,        // CSP 提供者类型
        0))                    // 附加参数:
    {
        delete [] orgBlob.pbData;
        CancelByError(L
"Get CSP provider context failed!\n");
    }


    
// 创建 Key
    struct keyBlob
    
{
        BLOBHEADER hdr;
        DWORD cbKeySize;
        BYTE rgbKeyData[
8];
    }
 keyBlob;

    keyBlob.hdr.bType 
= PLAINTEXTKEYBLOB;
    keyBlob.hdr.bVersion 
= CUR_BLOB_VERSION;
    keyBlob.hdr.reserved 
= 0;
    keyBlob.hdr.aiKeyAlg 
= CALG_DES;
    keyBlob.cbKeySize 
= 8;
    CopyMemory(keyBlob.rgbKeyData, key, keyBlob.cbKeySize);

/*
BOOL WINAPI CryptImportKey(
  __in          HCRYPTPROV hProv,
  __in          BYTE* pbData,
  __in          DWORD dwDataLen,
  __in          HCRYPTKEY hPubKey,
  __in          DWORD dwFlags,
  __out         HCRYPTKEY* phKey
);
*/


    HCRYPTKEY hKey 
= NULL;
    
if (!CryptImportKey(hProv, (BYTE*)(&keyBlob), sizeof(keyBlob), NULL, CRYPT_EXPORTABLE, &hKey))
    
{
        delete [] orgBlob.pbData;
        CryptReleaseContext(hProv, 
0);
        CancelByError(L
"Create key failed!\n");
    }


/*
BOOL WINAPI CryptSetKeyParam(
  __in          HCRYPTKEY hKey,
  __in          DWORD dwParam,
  __in          const BYTE* pbData,
  __in          DWORD dwFlags
);
*/


    
// 设置初始向量
    if(iv == NULL)
    
{
        
if(!CryptSetKeyParam(hKey, KP_IV, key, 0))
        
{
            delete [] orgBlob.pbData;
            CryptDestroyKey(hKey);
            CryptReleaseContext(hProv, 
0);
            CancelByError(L
"Set key's IV parameter failed!\n");
        }

    }

    
else
    
{
        
if(!CryptSetKeyParam(hKey, KP_IV, iv, 0))
        
{
            delete [] orgBlob.pbData;
            CryptDestroyKey(hKey);
            CryptReleaseContext(hProv, 
0);
            CancelByError(L
"Set key's IV parameter failed!\n");
        }

    }


/*
BOOL WINAPI CryptEncrypt(
  __in          HCRYPTKEY hKey,
  __in          HCRYPTHASH hHash,
  __in          BOOL Final,
  __in          DWORD dwFlags,
  __in_out      BYTE* pbData,
  __in_out      DWORD* pdwDataLen,
  __in          DWORD dwBufLen
);
*/


    
// 加密处理
    CRYPT_DATA_BLOB encBlob;
    memset(
&encBlob, 0sizeof(encBlob));
    encBlob.cbData 
= orgBlob.cbData;
    encBlob.pbData 
= (BYTE*new char[(orgBlob.cbData/8+1)*8];
    memcpy(encBlob.pbData, orgBlob.pbData, orgBlob.cbData);
    
if(!CryptEncrypt(hKey, NULL, TRUE, 0, encBlob.pbData, &encBlob.cbData, (orgBlob.cbData/8+1)*8))
    
{
        delete [] orgBlob.pbData;
        delete [] encBlob.pbData;
        CryptDestroyKey(hKey);
        CryptReleaseContext(hProv, 
0);
        CancelByError(L
"DES encrypt failed!\n");
    }


    showData(encBlob.pbData, encBlob.cbData);
    
if(outFileName != NULL)
    
{
        writeFile(outFileName, encBlob.pbData, encBlob.cbData);
    }


    
// 清理

    delete [] orgBlob.pbData;
    delete [] encBlob.pbData;

    
if(hKey != NULL)
    
{
        CryptDestroyKey(hKey);
        hKey 
= NULL;
    }


    
if(hProv != NULL)
    
{
        CryptReleaseContext(hProv, 
0);
        hProv 
= NULL;
    }

}


// AES-128/CBC/PKCS5Padding
// AES-256: KeySize=256, IVSize=128, Result=128
void AESEncrypt(BYTE* key, BYTE* iv, BYTE* inData, int inSize, LPCSTR inFileName = NULL, LPCSTR outFileName = NULL)
{
    
// 准备数据
    CRYPT_DATA_BLOB orgBlob;
    memset(
&orgBlob, 0sizeof(orgBlob));
    prepareData(inData, inSize, inFileName, orgBlob.pbData, orgBlob.cbData);

/*
BOOL WINAPI CryptAcquireContext(
  __out         HCRYPTPROV* phProv,
  __in          LPCTSTR pszContainer,
  __in          LPCTSTR pszProvider,
  __in          DWORD dwProvType,
  __in          DWORD dwFlags
);
*/


    HCRYPTPROV hProv 
= NULL; 
    
if(!CryptAcquireContext(
        
&hProv,                // 返回的句柄
        NULL,                // CSP 容器名称
        NULL,                // CSP 提供者名称
        PROV_RSA_AES,        // CSP 提供者类型
        0))            // 附加参数:
    {
        delete [] orgBlob.pbData;
        CancelByError(L
"Get provider context failed!\n");
    }


    
// 创建 Key
    struct keyBlob
    
{
        BLOBHEADER hdr;
        DWORD cbKeySize;
        BYTE rgbKeyData[
16];                // FOR AES-256 = 32
    }
 keyBlob;

    keyBlob.hdr.bType 
= PLAINTEXTKEYBLOB;
    keyBlob.hdr.bVersion 
= CUR_BLOB_VERSION;
    keyBlob.hdr.reserved 
= 0;
    keyBlob.hdr.aiKeyAlg 
= CALG_AES_128;    // FOR AES-256 = CALG_AES_256
    keyBlob.cbKeySize = 16;                    // FOR AES-256 = 32
    CopyMemory(keyBlob.rgbKeyData, key, keyBlob.cbKeySize);

/*
BOOL WINAPI CryptImportKey(
  __in          HCRYPTPROV hProv,
  __in          BYTE* pbData,
  __in          DWORD dwDataLen,
  __in          HCRYPTKEY hPubKey,
  __in          DWORD dwFlags,
  __out         HCRYPTKEY* phKey
);
*/


    HCRYPTKEY hKey 
= NULL;
    
if (!CryptImportKey(hProv, (BYTE*)(&keyBlob), sizeof(keyBlob), NULL, CRYPT_EXPORTABLE, &hKey))
    
{
        delete [] orgBlob.pbData;
        CryptReleaseContext(hProv, 
0);
        CancelByError(L
"Create key failed!\n");
    }


/*
BOOL WINAPI CryptSetKeyParam(
  __in          HCRYPTKEY hKey,
  __in          DWORD dwParam,
  __in          const BYTE* pbData,
  __in          DWORD dwFlags
);
*/


    
// 设置初始向量
    if(iv == NULL)
    
{
        
if(!CryptSetKeyParam(hKey, KP_IV, key, 0))
        
{
            delete [] orgBlob.pbData;
            CryptDestroyKey(hKey);
            CryptReleaseContext(hProv, 
0);
            CancelByError(L
"Set key's IV parameter failed!\n");
        }

    }

    
else
    
{
        
if(!CryptSetKeyParam(hKey, KP_IV, iv, 0))
        
{
            delete [] orgBlob.pbData;
            CryptDestroyKey(hKey);
            CryptReleaseContext(hProv, 
0);
            CancelByError(L
"Set key's IV parameter failed!\n");
        }

    }


/*
BOOL WINAPI CryptEncrypt(
  __in          HCRYPTKEY hKey,
  __in          HCRYPTHASH hHash,
  __in          BOOL Final,
  __in          DWORD dwFlags,
  __in_out      BYTE* pbData,
  __in_out      DWORD* pdwDataLen,
  __in          DWORD dwBufLen
);
*/


    
// 加密处理
    CRYPT_DATA_BLOB encBlob;
    memset(
&encBlob, 0sizeof(encBlob));
    encBlob.cbData 
= orgBlob.cbData;
    encBlob.pbData 
= (BYTE*new char[(orgBlob.cbData/16+1)*16];
    memcpy(encBlob.pbData, orgBlob.pbData, orgBlob.cbData);
    
if(!CryptEncrypt(hKey, NULL, TRUE, 0, encBlob.pbData, &encBlob.cbData, (orgBlob.cbData/16+1)*16))
    
{
        delete [] orgBlob.pbData;
        delete [] encBlob.pbData;
        CryptDestroyKey(hKey);
        CryptReleaseContext(hProv, 
0);
        CancelByError(L
"AES encrypt failed!\n");
    }


    showData(encBlob.pbData, encBlob.cbData);
    
if(outFileName != NULL)
    
{
        writeFile(outFileName, encBlob.pbData, encBlob.cbData);
    }


    
// 释放获取的对象
    delete [] orgBlob.pbData;
    delete [] encBlob.pbData;

    
if(hKey != NULL)
    
{
        CryptDestroyKey(hKey);
        hKey 
= NULL;
    }


    
if(hProv != NULL)
    
{
        CryptReleaseContext(hProv, 
0);
        hProv 
= NULL;
    }

}


// AES-128/CBC/PKCS5Padding
// AES-256: KeySize=256, IVSize=128, Result=128
void AESDecrypt(BYTE* key, BYTE* iv, BYTE* inData, int inSize, LPCSTR inFileName = NULL, LPCSTR outFileName = NULL)
{
    
// 准备数据
    CRYPT_DATA_BLOB encBlob;
    memset(
&encBlob, 0sizeof(encBlob));
    prepareData(inData, inSize, inFileName, encBlob.pbData, encBlob.cbData);

/*
BOOL WINAPI CryptAcquireContext(
  __out         HCRYPTPROV* phProv,
  __in          LPCTSTR pszContainer,
  __in          LPCTSTR pszProvider,
  __in          DWORD dwProvType,
  __in          DWORD dwFlags
);
*/


    HCRYPTPROV hProv 
= NULL; 
    
if(!CryptAcquireContext(
        
&hProv,                // 返回的句柄
        NULL,                // CSP key 容器名称
        NULL,                // CSP 提供者名称
        PROV_RSA_AES,        // CSP 提供者类型
        0))            // 附加参数:
    {
        delete [] encBlob.pbData;
        CancelByError(L
"Get provider context failed!\n");
    }


    
// 创建 Key
    struct keyBlob
    
{
        BLOBHEADER hdr;
        DWORD cbKeySize;
        BYTE rgbKeyData[
16];                // FOR AES-256 = 32
    }
 keyBlob;

    keyBlob.hdr.bType 
= PLAINTEXTKEYBLOB;
    keyBlob.hdr.bVersion 
= CUR_BLOB_VERSION;
    keyBlob.hdr.reserved 
= 0;
    keyBlob.hdr.aiKeyAlg 
= CALG_AES_128;    // FOR AES-256 = CALG_AES_256
    keyBlob.cbKeySize = 16;                    // FOR AES-256 = 32
    CopyMemory(keyBlob.rgbKeyData, key, keyBlob.cbKeySize);

/*
BOOL WINAPI CryptImportKey(
  __in          HCRYPTPROV hProv,
  __in          BYTE* pbData,
  __in          DWORD dwDataLen,
  __in          HCRYPTKEY hPubKey,
  __in          DWORD dwFlags,
  __out         HCRYPTKEY* phKey
);
*/


    HCRYPTKEY hKey 
= NULL;
    
if (!CryptImportKey(hProv, (BYTE*)(&keyBlob), sizeof(keyBlob), NULL, CRYPT_EXPORTABLE, &hKey))
    
{
        delete [] encBlob.pbData;
        CryptReleaseContext(hProv, 
0);
        CancelByError(L
"Create key failed!\n");
    }


/*
BOOL WINAPI CryptSetKeyParam(
  __in          HCRYPTKEY hKey,
  __in          DWORD dwParam,
  __in          const BYTE* pbData,
  __in          DWORD dwFlags
);
*/


    
// 设置初始向量
    if(iv == NULL)
    
{
        
if(!CryptSetKeyParam(hKey, KP_IV, key, 0))
        
{
            delete [] encBlob.pbData;
            CryptDestroyKey(hKey);
            CryptReleaseContext(hProv, 
0);
            CancelByError(L
"Set key's IV parameter failed!\n");
        }

    }

    
else
    
{
        
if(!CryptSetKeyParam(hKey, KP_IV, iv, 0))
        
{
            delete [] encBlob.pbData;
            CryptDestroyKey(hKey);
            CryptReleaseContext(hProv, 
0);
            CancelByError(L
"Set key's IV parameter failed!\n");
        }

    }


/*
BOOL WINAPI CryptDecrypt(
  __in          HCRYPTKEY hKey,
  __in          HCRYPTHASH hHash,
  __in          BOOL Final,
  __in          DWORD dwFlags,
  __in_out      BYTE* pbData,
  __in_out      DWORD* pdwDataLen
);
*/


    
// 加密处理
    CRYPT_DATA_BLOB orgBlob;
    memset(
&orgBlob, 0sizeof(orgBlob));
    orgBlob.cbData 
= encBlob.cbData;
    orgBlob.pbData 
= (BYTE*new char[encBlob.cbData];
    memcpy(orgBlob.pbData, encBlob.pbData, encBlob.cbData);
    
if(!CryptDecrypt(hKey, NULL, TRUE, 0, orgBlob.pbData, &orgBlob.cbData))
    
{
        delete [] orgBlob.pbData;
        delete [] encBlob.pbData;
        CryptDestroyKey(hKey);
        CryptReleaseContext(hProv, 
0);
        CancelByError(L
"AES encrypt failed!\n");
    }


    showData(orgBlob.pbData, orgBlob.cbData);
    
if(outFileName != NULL)
    
{
        writeFile(outFileName, orgBlob.pbData, orgBlob.cbData);
    }


    
// 清理
    delete [] orgBlob.pbData;
    delete [] encBlob.pbData;

    
if(hKey != NULL)
    
{
        CryptDestroyKey(hKey);
        hKey 
= NULL;
    }


    
if(hProv != NULL)
    
{
        CryptReleaseContext(hProv, 
0);
        hProv 
= NULL;
    }

}


// ============================ 证书管理

// 获取证书名称
void viewCertCN(PCCERT_CONTEXT hCert)
{
/*
DWORD WINAPI CertGetNameString(
  __in          PCCERT_CONTEXT pCertContext,
  __in          DWORD dwType,
  __in          DWORD dwFlags,
  __in          void* pvTypePara,
  __out         LPTSTR pszNameString,
  __in          DWORD cchNameString
);
*/


    TCHAR sName[
1024];
    DWORD nNameSize 
= 1000;
    DWORD nNameType 
= 0;                // CERT_X500_NAME_STR for FULL name, like C=.., O=.., OU=.., CN=,
    nNameSize = CertGetNameString(
        hCert,
        CERT_NAME_SIMPLE_DISPLAY_TYPE,    
// CERT_NAME_RDN_TYPE for FULL name.
        0,
        
&nNameType,
        sName,
        nNameSize);

    _tprintf(L
"CN: %s\n", sName); 
}


// 获取证书签发者
void viewCertIS(PCCERT_CONTEXT hCert)
{
/*
DWORD WINAPI CertGetNameString(
  __in          PCCERT_CONTEXT pCertContext,
  __in          DWORD dwType,
  __in          DWORD dwFlags,
  __in          void* pvTypePara,
  __out         LPTSTR pszNameString,
  __in          DWORD cchNameString
);
*/


    TCHAR sName[
1024];
    DWORD nNameSize 
= 1000;
    DWORD nNameType 
= 0;                // CERT_X500_NAME_STR for FULL name, like C=.., O=.., OU=.., CN=,
    nNameSize = CertGetNameString(
        hCert,
        CERT_NAME_SIMPLE_DISPLAY_TYPE,    
// CERT_NAME_RDN_TYPE for FULL name.
        CERT_NAME_ISSUER_FLAG,
        
&nNameType,
        sName,
        nNameSize);
    
    _tprintf(L
"IS: %s\n", sName); 
}


// 获取证书序列号
void viewCertSN(PCCERT_CONTEXT hCert)
{
/*
BOOL WINAPI CryptFormatObject(
  __in          DWORD dwCertEncodingType,
  __in          DWORD dwFormatType,
  __in          DWORD dwFormatStrType,
  __in          void* pFormatStruct,
  __in          LPCSTR lpszStructType,
  __in          const BYTE* pbEncoded,
  __in          DWORD cbEncoded,
  __out         void* pbFormat,
  __in_out      DWORD* pcbFormat
);
*/

    
// 获取解码后的长度
    CRYPT_INTEGER_BLOB  SerialNumber;
    BOOL bRet 
= FALSE;
    bRet 
= CryptFormatObject(
        hCert
->dwCertEncodingType,
        
0,
        
0,
        NULL,
        
0,
        hCert
->pCertInfo->SerialNumber.pbData,
        hCert
->pCertInfo->SerialNumber.cbData,
        NULL,
        
&SerialNumber.cbData);
    
if(!bRet)
    
{
        CancelByError(L
"Get SerialNumber decode length failed!\n");
    }


    
// 分配解码空间
    SerialNumber.pbData = (BYTE*new char[SerialNumber.cbData];

    
// 获取解码数据
    bRet = CryptFormatObject(
        hCert
->dwCertEncodingType,
        
0,
        
0,
        NULL,
        
0,
        hCert
->pCertInfo->SerialNumber.pbData,
        hCert
->pCertInfo->SerialNumber.cbData,
        SerialNumber.pbData,
        
&SerialNumber.cbData);
    
if(!bRet)
    
{
        delete [] SerialNumber.pbData;
        CancelByError(L
"SerialNumber decode failed!\n");
    }


//    char* tmpStr = _com_util::ConvertBSTRToString((BSTR)SerialNumber.pbData);
    _tprintf(L"SN: %s\n", SerialNumber.pbData);

    delete [] SerialNumber.pbData;
//    delete [] tmpStr;
}


// 获取证书有效期
void viewCertDate(PCCERT_CONTEXT hCert)
{
    CTime dtBefore(hCert
->pCertInfo->NotBefore);
    CTime dtAfter(hCert
->pCertInfo->NotAfter);
    _tprintf(L
"DT: %s TO %s\n", dtBefore.Format(L"%Y-%m-%d %H:%M:%S"), dtAfter.Format(L"%Y-%m-%d %H:%M:%S"));
}


// 校验证书合法性
void verifyCert(PCCERT_CONTEXT hCert)
{
/*
LONG WINAPI CertVerifyTimeValidity(
  __in          LPFILETIME pTimeToVerify,
  __in          PCERT_INFO pCertInfo
);
*/

    
// 校验证书日期
    int nRetCode = CertVerifyTimeValidity(NULL, hCert->pCertInfo);
    
if(nRetCode < 0)
    
{
        _tprintf(L
"Verify cert's date failed: BEFORE date after TODAY!\n");
    }


    
if(nRetCode > 0)
    
{
        _tprintf(L
"Verify cert's date failed: Cert has expired!\n");
    }


    
if(nRetCode == 0)
    
{
        _tprintf(L
"Verify cert's date succeed!\n");
    }


    
// 校验签名者证书

    HCERTSTORE hCertStore 
= CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, NULL, CERT_SYSTEM_STORE_CURRENT_USER, L"ROOT");
    
if(hCertStore != NULL)
    
{
/*
PCCERT_CONTEXT WINAPI CertGetIssuerCertificateFromStore(
  __in          HCERTSTORE hCertStore,
  __in          PCCERT_CONTEXT pSubjectContext,
  __in_opt      PCCERT_CONTEXT pPrevIssuerContext,
  __in_out      DWORD* pdwFlags
);
*/

        
// 2.
        DWORD dwFlags = CERT_STORE_SIGNATURE_FLAG;
        PCCERT_CONTEXT hIssuserCert 
= CertGetIssuerCertificateFromStore(hCertStore, hCert, NULL, &dwFlags); 
        
if(hIssuserCert != NULL)
        
{
            BOOL bCheckOK 
= FALSE;
            
while(hIssuserCert != NULL)
            
{
    
/*
    BOOL WINAPI CertVerifySubjectCertificateContext(
      __in          PCCERT_CONTEXT pSubject,
      __in_opt      PCCERT_CONTEXT pIssuer,
      __in_out      DWORD* pdwFlags
    );
    
*/

                
// 校验证书签发者信息合法性
                dwFlags = CERT_STORE_SIGNATURE_FLAG;
                
if(CertVerifySubjectCertificateContext(hCert, hIssuserCert, &dwFlags))
                
{
                    
if(dwFlags == 0)
                    
{
                        _tprintf(L
"Verify cert by issuser's cert succeed! \n");
                        bCheckOK 
= TRUE;
                        
break;
                    }

                }

                
else
                
{
                    _tprintf(L
"Verify cert by issuser's cert failed! \n");
                    
break;
                }


                
// Next ..
                hIssuserCert = CertGetIssuerCertificateFromStore(hCertStore, hCert, hIssuserCert, &dwFlags); 
            }


            
if(!bCheckOK)
            
{
                _tprintf(L
"Verify cert by issuser's cert failed! \n");
            }


        }

        
else
        
{
            _tprintf(L
"Can not find cert issuser's cert!\n");
        }


        
if(hIssuserCert != NULL)
        
{
            CertFreeCertificateContext(hIssuserCert);
            hIssuserCert 
= NULL;
        }

    }

    
else
    
{
        _tprintf(L
"Open ROOT CertStore failed!\n");
    }


    
if(hCertStore != NULL)
    
{
        CertCloseStore(hCertStore, CERT_CLOSE_STORE_FORCE_FLAG);
        hCertStore 
= NULL;
    }



    
// 校验 CRL 列表

    
// 1.
    BYTE* pbCrlData = NULL;
    DWORD cbCrlData 
= 0;
    readFile(
"c:\\cfcaT.crl", NULL, cbCrlData);
    
if(cbCrlData > 0)
    
{
        pbCrlData 
= (BYTE*new char[cbCrlData];
        readFile(
"c:\\cfcaT.crl", pbCrlData, cbCrlData);
    }


/*
PCCRL_CONTEXT WINAPI CertCreateCRLContext(
  __in          DWORD dwCertEncodingType,
  __in          const BYTE* pbCrlEncoded,
  __in          DWORD cbCrlEncoded
);
*/


    
// 2.转换CRL数据为CRL句柄
    PCCRL_CONTEXT hCRL = CertCreateCRLContext(MY_ENCODING_TYPE, pbCrlData, cbCrlData);
    delete [] pbCrlData;
    
if(hCRL != NULL)
    
{
/*
    BOOL WINAPI CertIsValidCRLForCertificate(
  __in          PCCERT_CONTEXT pCert,
  __in          PCCRL_CONTEXT pCRL,
  __in          DWORD dwFlags,
  __in          void* pvReserved
*/

        
if(CertIsValidCRLForCertificate(hCert, hCRL, 0, NULL))
        
{
            _tprintf(L
"CRL is valid for the cert!\n");
        }

        
else
        
{
            _tprintf(L
"CRL is invalid for the cert!!\n");
        }


    
/*
    BOOL WINAPI CertFindCertificateInCRL(
      __in          PCCERT_CONTEXT pCert,
      __in          PCCRL_CONTEXT pCrlContext,
      __in          DWORD dwFlags,
      __in_opt      void* pvReserved,
      __out         PCRL_ENTRY* pCrlEntry
    );
    
*/

        
// Step 4: 检查CRL是否包含该证书
        PCRL_ENTRY pCrlEntry = NULL;
        
if(CertFindCertificateInCRL(hCert, hCRL, 00&pCrlEntry))
        
{
            
if(pCrlEntry != NULL)
            
{
                _tprintf(L
"Cert has been revoked!\n");
            }

            
else
            
{
                _tprintf(L
"Cert not be revoked!\n");
            }

        }

        
else
        
{
            _tprintf(L
"Find cert in CRL failed!\n");
        }

    }

    
else
    
{
        _tprintf(L
"Create CRL context failed!\n");
    }


    
if(hCRL != NULL)
    
{
        CertFreeCRLContext(hCRL);
    }

}


// ============================ 证书库管理

// 列出证书库证书
void listCerts(HCERTSTORE hCertStore)
{
/*
PCCERT_CONTEXT WINAPI CertEnumCertificatesInStore(
  __in          HCERTSTORE hCertStore,
  __in          PCCERT_CONTEXT pPrevCertContext
);
*/

    _tprintf(L
"======== L I S T   C E R T   I N   S T O R E ========\n");

    
int nCnt = 0;
    PCCERT_CONTEXT hCert 
= NULL; 
    
while(hCert = CertEnumCertificatesInStore(hCertStore, hCert))
    
{
        viewCertCN(hCert);
        viewCertIS(hCert);
        viewCertSN(hCert);
        viewCertDate(hCert);
        verifyCert(hCert);
        
++ nCnt;
        _tprintf(L
"-----------------------------\n");
    }


    _tprintf(L
"**** Count: %d \n", nCnt);

    
// 清理
    if(hCert != NULL)
    
{
        CertFreeCertificateContext(hCert);
        hCert 
= NULL;
    }

}


// 列出系统证书库证书
void viewSystemCertStore(LPCTSTR storeName)
{
/*
HCERTSTORE WINAPI CertOpenStore(
  __in          LPCSTR lpszStoreProvider,
  __in          DWORD dwMsgAndCertEncodingType,
  __in          HCRYPTPROV_LEGACY hCryptProv,
  __in          DWORD dwFlags,
  __in          const void* pvPara
);
*/


    
// 打开证书库
    HCERTSTORE hCertStore = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, NULL, CERT_SYSTEM_STORE_CURRENT_USER, storeName);
    
if(hCertStore == NULL)
    
{
        CancelByError(L
"Open CertStore failed!\n");
    }


    listCerts(hCertStore);

    
// 清理
    if(hCertStore != NULL)
    
{
        CertCloseStore(hCertStore, CERT_CLOSE_STORE_FORCE_FLAG);
        hCertStore 
= NULL;
    }

}


// 文件证书库(CRT/P7B)
void viewCrtCertStore(LPCTSTR crtFileName)
{
/*
HCERTSTORE WINAPI CertOpenStore(
  __in          LPCSTR lpszStoreProvider,
  __in          DWORD dwMsgAndCertEncodingType,
  __in          HCRYPTPROV_LEGACY hCryptProv,
  __in          DWORD dwFlags,
  __in          const void* pvPara
);
*/


    
// 打开证书库
    HCERTSTORE hCertStore = CertOpenStore(CERT_STORE_PROV_FILENAME, 0, NULL, 0, crtFileName);
    
if(hCertStore == NULL)
    
{
        CancelByError(L
"Open CertStore failed!\n");
    }


    listCerts(hCertStore);

    
// 清理
    if(hCertStore != NULL)
    
{
        CertCloseStore(hCertStore, CERT_CLOSE_STORE_FORCE_FLAG);
        hCertStore 
= NULL;
    }

}


// 证书库文件(PFX)
void viewPfxCertStore(LPCSTR sCertFileName, LPCTSTR sCertPassword)
{
    
// 读取证书库文件
    CRYPT_DATA_BLOB pfxData;
    memset(
&pfxData, 0sizeof(pfxData));
    readFile(sCertFileName, NULL, pfxData.cbData);
    
if(pfxData.cbData > 0)
    
{
        pfxData.pbData 
= (BYTE*new char[pfxData.cbData];
        readFile(sCertFileName, pfxData.pbData, pfxData.cbData);
    }


/*
HCERTSTORE WINAPI PFXImportCertStore(
  __in          CRYPT_DATA_BLOB* pPFX,
  __in          LPCWSTR szPassword,
  __in          DWORD dwFlags
);
*/


    HCERTSTORE hCertStore 
= PFXImportCertStore(&pfxData, sCertPassword, 0);
    delete [] pfxData.pbData;
    
if(hCertStore == NULL)
    
{
        CancelByError(L
"Open CertStore failed!\n");
    }


    
// 列出证书
    listCerts(hCertStore);

    
// 清理
    if(hCertStore != NULL)
    
{
        CertCloseStore(hCertStore, CERT_CLOSE_STORE_FORCE_FLAG);
        hCertStore 
= NULL;
    }

}


// ================================= 数据签名、核签、加密、解密、数字信封

// 裸签
void BareSignData(BYTE* orgData, int orgSize, LPCSTR inFileName = NULL, LPCSTR outFileName = NULL)
{
    
// 准备数据
    CRYPT_DATA_BLOB orgBlob;
    prepareData(orgData, orgSize, inFileName, orgBlob.pbData, orgBlob.cbData);

    
// 打开证书库
    HCERTSTORE hCertStore = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, NULL, CERT_SYSTEM_STORE_CURRENT_USER, L"MY");
    
if(hCertStore == NULL)
    
{
        delete [] orgBlob.pbData;
        CancelByError(L
"Open CertStore failed!\n");
    }


    
// 查找证书
    PCCERT_CONTEXT hCert = CertFindCertificateInStore(
       hCertStore,
       MY_ENCODING_TYPE,
       
0,
       CERT_FIND_SUBJECT_STR,
       L
"lny",
       NULL);
    
if(hCert == NULL)
    
{
        delete [] orgBlob.pbData;
        CertCloseStore(hCertStore, CERT_CLOSE_STORE_FORCE_FLAG);
        CancelByError(L
"Signer certificate not found.");
    }


    viewCertCN(hCert);
    viewCertIS(hCert);
    viewCertSN(hCert);
    viewCertDate(hCert);

/*
BOOL WINAPI CryptAcquireCertificatePrivateKey(
  __in          PCCERT_CONTEXT pCert,
  __in          DWORD dwFlags,
  __in          void* pvReserved,
  __out         HCRYPTPROV_OR_NCRYPT_KEY_HANDLE* phCryptProvOrNCryptKey,
  __out         DWORD* pdwKeySpec,
  __out         BOOL* pfCallerFreeProvOrNCryptKey
);
*/

    
// 请求证书私钥服务
    HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hKeyProv = NULL;
    DWORD dwKeyType 
= 0;
    BOOL bFreeKeyProv 
= FALSE;
    
if(!CryptAcquireCertificatePrivateKey(hCert, 00&hKeyProv, &dwKeyType, &bFreeKeyProv))
    
{
        delete [] orgBlob.pbData;
        CertFreeCertificateContext(hCert);
        CertCloseStore(hCertStore, CERT_CLOSE_STORE_FORCE_FLAG);
        CancelByError(L
"Acquire certificate privateKey failed!\n");
    }


    
// 创建离散对象
    HCRYPTHASH hHash = NULL;
    
if(!CryptCreateHash(
        hKeyProv,                    
// 容器句柄 
        CALG_SHA1,                    // 算法标识
        NULL,                        // 算法使用的Key
        0,                            // 算法标识
        &hHash))                    // 返回的HASH对象
    {
        delete [] orgBlob.pbData;
        CertFreeCertificateContext(hCert);
        CertCloseStore(hCertStore, CERT_CLOSE_STORE_FORCE_FLAG);
        CancelByError(L
"Get SHA1 provider failed!\n");
    }


    
// 计算数据摘要
    if(CryptHashData(hHash, orgBlob.pbData, orgBlob.cbData, 0== 0)
    
{
        delete [] orgBlob.pbData;
        CryptDestroyHash(hHash); 
        CryptReleaseContext(hKeyProv, 
0);
        CertFreeCertificateContext(hCert);
        CertCloseStore(hCertStore, CERT_CLOSE_STORE_FORCE_FLAG);
        CancelByError(L
"Calc SHA1 data failed!\n");
    }


/*
BOOL WINAPI CryptSignHash(
  __in          HCRYPTHASH hHash,
  __in          DWORD dwKeySpec,
  __in          LPCTSTR sDescription,
  __in          DWORD dwFlags,
  __out         BYTE* pbSignature,
  __in_out      DWORD* pdwSigLen
);
*/


    DWORD cbSign 
= 4096;
    BYTE  pbSign[
4096];
    
if(!CryptSignHash(hHash, dwKeyType, NULL, 0, pbSign, &cbSign))
    
{
        delete [] orgBlob.pbData;
        CryptDestroyHash(hHash); 
        CryptReleaseContext(hKeyProv, 
0);
        CertFreeCertificateContext(hCert);
        CertCloseStore(hCertStore, CERT_CLOSE_STORE_FORCE_FLAG);
        CancelByError(L
"Calc SignData failed!\n");
    }


    reverse(pbSign, cbSign);
    showData(pbSign, cbSign);
    
if(outFileName != NULL)
    
{
        writeFile(outFileName, pbSign, cbSign);
    }


    
// 释放获取的对象
    delete [] orgBlob.pbData;

    
if(hHash != NULL)
    
{
        CryptDestroyHash(hHash); 
        hHash 
= NULL;
    }


    
if(hKeyProv != NULL && bFreeKeyProv)
    
{
        CryptReleaseContext(hKeyProv, 
0);
        hKeyProv 
= NULL;
    }


    
if(hCert != NULL)
    
{
        CertFreeCertificateContext(hCert);
        hCert 
= NULL;
    }


    
if(hCertStore != NULL)
    
{
        CertCloseStore(hCertStore, CERT_CLOSE_STORE_FORCE_FLAG);
        hCertStore 
= NULL;
    }

}


// 校验裸签名
void VerifyBareSignData(BYTE* orgData, int orgSize, BYTE* sigData, int sigSize, LPCSTR orgFileName = NULL, LPCSTR sigFileName = NULL)
{
    
// 准备数据
    CRYPT_DATA_BLOB orgBlob, sigBlob;
    memset(
&orgBlob, 0sizeof(orgBlob));
    memset(
&sigBlob, 0sizeof(sigBlob));
    prepareData(orgData, orgSize, orgFileName, orgBlob.pbData, orgBlob.cbData);
    prepareData(sigData, sigSize, sigFileName, sigBlob.pbData, sigBlob.cbData);
    reverse(sigBlob.pbData, sigBlob.cbData);

    
// 请求容器服务
    HCRYPTPROV hProv = NULL; 
    
if(!CryptAcquireContext(
        
&hProv,                // 返回的句柄
        NULL,                // CSP key 容器名称
        NULL,                // CSP 提供者名称
        PROV_RSA_FULL,        // CSP 提供者类型
        0))                    // 附加参数
    {
        delete [] orgBlob.pbData;
        delete [] sigBlob.pbData;
        CancelByError(L
"Get provider context failed!\n");
    }


    
// 创建离散对象
    HCRYPTHASH hHash = NULL;
    
if(!CryptCreateHash(
        hProv,                        
// 容器句柄 
        CALG_SHA1,                    // 算法标识
        NULL,                        // 算法使用的Key
        0,                            // 算法标识
        &hHash))                    // 返回的HASH对象
    {
        delete [] orgBlob.pbData;
        delete [] sigBlob.pbData;
        CryptReleaseContext(hProv, 
0);
        CancelByError(L
"Get SHA1 provider failed!\n");
    }


    
// 计算数据摘要
    if(CryptHashData(hHash, orgBlob.pbData, orgBlob.cbData, 0== 0)
    
{
        delete [] orgBlob.pbData;
        delete [] sigBlob.pbData;
        CryptDestroyHash(hHash); 
        CryptReleaseContext(hProv, 
0);
        CancelByError(L
"Calc SHA1 data failed!\n");
    }


    
// 获取签名者证书公钥
/*
HCERTSTORE WINAPI CertOpenStore(
  __in          LPCSTR lpszStoreProvider,
  __in          DWORD dwMsgAndCertEncodingType,
  __in          HCRYPTPROV_LEGACY hCryptProv,
  __in          DWORD dwFlags,
  __in          const void* pvPara
);
*/


    
// 打开证书库
    HCERTSTORE hCertStore = CertOpenStore(CERT_STORE_PROV_FILENAME, 0, NULL, 0, L"c:\\ca\\certs\\lny.crt");
    
if(hCertStore == NULL)
    
{
        delete [] orgBlob.pbData;
        delete [] sigBlob.pbData;
        CryptDestroyHash(hHash); 
        CryptReleaseContext(hProv, 
0);
        CancelByError(L
"Open CertStore failed!\n");
    }


    
// 查找证书
    PCCERT_CONTEXT hCert = CertFindCertificateInStore(
       hCertStore,
       MY_ENCODING_TYPE,
       
0,
       CERT_FIND_SUBJECT_STR,
       L
"lny",
       NULL);
    
if(hCert == NULL)
    
{
        delete [] orgBlob.pbData;
        delete [] sigBlob.pbData;
        CryptDestroyHash(hHash); 
        CertCloseStore(hCertStore, CERT_CLOSE_STORE_FORCE_FLAG);
        CryptReleaseContext(hProv, 
0);
        CancelByError(L
"Signer certificate not found.\n");
    }


/*
BOOL WINAPI CryptImportPublicKeyInfo(
  __in          HCRYPTPROV hCryptProv,
  __in          DWORD dwCertEncodingType,
  __in          PCERT_PUBLIC_KEY_INFO pInfo,
  __out         HCRYPTKEY* phKey
);
*/

    HCRYPTKEY hPubKey;
    
if(!CryptImportPublicKeyInfo(hProv, MY_ENCODING_TYPE, &hCert->pCertInfo->SubjectPublicKeyInfo, &hPubKey))
    
{
        delete [] orgBlob.pbData;
        delete [] sigBlob.pbData;
        CryptDestroyKey(hPubKey);
        CryptDestroyHash(hHash); 
        CertCloseStore(hCertStore, CERT_CLOSE_STORE_FORCE_FLAG);
        CryptReleaseContext(hProv, 
0);
        CancelByError(L
"Get public key from cert failed.");
    }


    
// 校验签名
/*
BOOL WINAPI CryptVerifySignature(
  __in          HCRYPTHASH hHash,
  __in          BYTE* pbSignature,
  __in          DWORD dwSigLen,
  __in          HCRYPTKEY hPubKey,
  __in          LPCTSTR sDescription,
  __in          DWORD dwFlags
);
*/

    
if(!CryptVerifySignature(hHash, sigBlob.pbData, sigBlob.cbData, hPubKey, NULL, 0))
    
{
        _tprintf(L
"Verify hash signature failed.\n");
    }

    
else
    
{
        _tprintf(L
"Verify hash signature succeed.\n");
    }


    
// 释放获取的对象
    delete [] orgBlob.pbData;
    delete [] sigBlob.pbData;

    
if(hPubKey != NULL)
    
{
        CryptDestroyKey(hPubKey);
        hPubKey 
= NULL;
    }


    
if(hHash != NULL)
    
{
        CryptDestroyHash(hHash); 
        hHash 
= NULL;
    }


    
if(hCert != NULL)
    
{
        CertFreeCertificateContext(hCert);
        hCert 
= NULL;
    }


    
if(hCertStore != NULL)
    
{
        CertCloseStore(hCertStore, CERT_CLOSE_STORE_FORCE_FLAG);
        hCertStore 
= NULL;
    }


    
if(hProv != NULL)
    
{
        CryptReleaseContext(hProv, 
0);
        hProv 
= NULL;
    }

}


// 含证书的签名(RSA/SHA1RSA)
void SignData(BYTE* orgData, int orgSize, LPCSTR orgFileName = NULL, BOOL bDetached = TRUE, LPCSTR sigFileName = NULL)
{
    
// 准备数据
    CRYPT_DATA_BLOB orgBlob;
    memset(
&orgBlob, 0sizeof(orgBlob));
    prepareData(orgData, orgSize, orgFileName, orgBlob.pbData, orgBlob.cbData);

    
// 打开证书库
    HCERTSTORE hCertStore = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, NULL, CERT_SYSTEM_STORE_CURRENT_USER, L"MY");
    
if(hCertStore == NULL)
    
{
        delete [] orgBlob.pbData;
        CancelByError(L
"Open CertStore failed!\n");
    }


    
// 查找证书
    PCCERT_CONTEXT hCert = CertFindCertificateInStore(
       hCertStore,
       MY_ENCODING_TYPE,
       
0,
       CERT_FIND_SUBJECT_STR,
       L
"lny",
       NULL);
    
if(hCert == NULL)
    
{
        delete [] orgBlob.pbData;
        CertCloseStore(hCertStore, CERT_CLOSE_STORE_FORCE_FLAG);
        CancelByError(L
"Signer certificate not found.");
    }


/*
BOOL WINAPI CryptSignMessage(
  __in          PCRYPT_SIGN_MESSAGE_PARA pSignPara,
  __in          BOOL fDetachedSignature,
  __in          DWORD cToBeSigned,
  __in          const BYTE* rgpbToBeSigned[],
  __in          DWORD rgcbToBeSigned[],
  __out         BYTE* pbSignedBlob,
  __in_out      DWORD* pcbSignedBlob
);

typedef struct _CRYPT_SIGN_MESSAGE_PARA 
{  
    DWORD cbSize;  
    DWORD dwMsgEncodingType;  
    PCCERT_CONTEXT pSigningCert;  
    CRYPT_ALGORITHM_IDENTIFIER HashAlgorithm;  
    void* pvHashAuxInfo;  
    DWORD cMsgCert;  
    PCCERT_CONTEXT* rgpMsgCert;  
    DWORD cMsgCrl;  
    PCCRL_CONTEXT* rgpMsgCrl;  
    DWORD cAuthAttr;  
    PCRYPT_ATTRIBUTE rgAuthAttr;  
    DWORD cUnauthAttr;  
    PCRYPT_ATTRIBUTE rgUnauthAttr;  
    DWORD dwFlags;  
    DWORD dwInnerContentType;  
    CRYPT_ALGORITHM_IDENTIFIER HashEncryptionAlgorithm;  
    void pvHashEncryptionAuxInfo;
} CRYPT_SIGN_MESSAGE_PARA;
*/


    CRYPT_SIGN_MESSAGE_PARA  SigParams;
    SigParams.cbSize 
= sizeof(CRYPT_SIGN_MESSAGE_PARA);
    SigParams.dwMsgEncodingType 
= MY_ENCODING_TYPE;
    SigParams.pSigningCert 
= hCert;
    SigParams.HashAlgorithm.pszObjId 
= szOID_RSA_SHA1RSA;
    SigParams.HashAlgorithm.Parameters.cbData 
= 0;
    SigParams.pvHashAuxInfo 
= NULL;
    SigParams.cMsgCert 
= 1;    // 签名中包含的证书数
    SigParams.rgpMsgCert = &hCert;
    SigParams.cMsgCrl 
= 0;    // 签名中包含的CRL数
    SigParams.rgpMsgCrl = NULL;
    SigParams.cAuthAttr 
= 0;
    SigParams.rgAuthAttr 
= NULL;
    SigParams.cUnauthAttr 
= 0;
    SigParams.rgUnauthAttr 
= NULL;
    SigParams.dwInnerContentType 
= 0;
    SigParams.dwFlags 
= 0;
    SigParams.pvHashAuxInfo 
= NULL;

    
const BYTE* dataArray[1];
    DWORD_PTR sizeArray[
1];
    dataArray[
0= orgBlob.pbData;
    sizeArray[
0= orgBlob.cbData;

    
// 计算签名值的长度
    CRYPT_DATA_BLOB sigData;
    memset(
&sigData, 0sizeof(sigData));
    
if(!CryptSignMessage(&SigParams, bDetached, 1, dataArray, sizeArray, NULL, &(sigData.cbData)))
    
{
        delete [] orgBlob.pbData;
        CertFreeCertificateContext(hCert);
        CertCloseStore(hCertStore, CERT_CLOSE_STORE_FORCE_FLAG);
        CancelByError(L
"Get sign data size failed!\n");
    }


    
// 分配内存
    sigData.pbData = (BYTE*new char[sigData.cbData];
    
if(sigData.pbData == NULL)
    
{
        delete [] orgBlob.pbData;
        CertFreeCertificateContext(hCert);
        CertCloseStore(hCertStore, CERT_CLOSE_STORE_FORCE_FLAG);
        CancelByError(L
"Not enough memory. \n");
    }


    
// 签名
    if(!CryptSignMessage(&SigParams, bDetached, 1, dataArray, sizeArray, sigData.pbData, &(sigData.cbData)))
    
{
        delete [] orgBlob.pbData;
        delete [] sigData.pbData;
        CertFreeCertificateContext(hCert);
        CertCloseStore(hCertStore, CERT_CLOSE_STORE_FORCE_FLAG);
        CancelByError(L
"Sign data failed!\n");
    }


    showData(sigData.pbData, sigData.cbData);
    
if(sigFileName != NULL)
    
{
        writeFile(sigFileName, sigData.pbData, sigData.cbData);
    }


    
// 释放获取的对象
    delete [] orgBlob.pbData;
    delete [] sigData.pbData;

    
if(hCert != NULL)
    
{
        CertFreeCertificateContext(hCert);
        hCert 
= NULL;
    }


    
if(hCertStore != NULL)
    
{
        CertCloseStore(hCertStore, CERT_CLOSE_STORE_FORCE_FLAG);
        hCertStore 
= NULL;
    }

}


// 校验无原文的签名
void VerifyDetachedSignData(BYTE* orgData, DWORD orgSize, LPCSTR orgFileName, LPCSTR sigFileName)
{
    
// 准备数据
    CRYPT_DATA_BLOB orgBlob, sigBlob;
    memset(
&orgBlob, 0sizeof(orgBlob));
    memset(
&sigBlob, 0sizeof(sigBlob));
    prepareData(orgData, orgSize, orgFileName, orgBlob.pbData, orgBlob.cbData);
    prepareData(NULL, 
0, sigFileName, sigBlob.pbData, sigBlob.cbData);

    
// 设定校验参数
    CRYPT_VERIFY_MESSAGE_PARA VerifyParams;
    VerifyParams.cbSize 
= sizeof(CRYPT_VERIFY_MESSAGE_PARA);
    VerifyParams.dwMsgAndCertEncodingType 
= MY_ENCODING_TYPE;
    VerifyParams.hCryptProv 
= 0;
    VerifyParams.pfnGetSignerCertificate 
= NULL;
    VerifyParams.pvGetArg 
= NULL;

/*
    BOOL WINAPI CryptVerifyDetachedMessageSignature(
  __in          PCRYPT_VERIFY_MESSAGE_PARA pVerifyPara,
  __in          DWORD dwSignerIndex,
  __in          const BYTE* pbDetachedSignBlob,
  __in          DWORD cbDetachedSignBlob,
  __in          DWORD cToBeSigned,
  __in          const BYTE* rgpbToBeSigned[],
  __in          DWORD rgcbToBeSigned[],
  __out_opt     PCCERT_CONTEXT* ppSignerCert
);
*/


    
const BYTE* dataArray[1];
    DWORD_PTR   sizeArray[
1];
    dataArray[
0= orgBlob.pbData;
    sizeArray[
0= orgBlob.cbData;

    PCCERT_CONTEXT hCert 
= NULL;
    
if(CryptVerifyDetachedMessageSignature(
        
&VerifyParams,
        
0,
        sigBlob.pbData,
        sigBlob.cbData,
        
1,
        dataArray,
        sizeArray,
        
&hCert))
    
{
        _tprintf(L
"Verification message succeed.\n");
        viewCertCN(hCert);
    }

    
else
    
{
        _tprintf(L
"Verification message failed.\n");
    }


    
// 清理
    delete [] orgBlob.pbData;
    delete [] sigBlob.pbData;

    
if(hCert != NULL)
    
{
        CertFreeCertificateContext(hCert);
        hCert 
= NULL;
    }

}


// 校验含原文的签名
void VerifySignedData(LPCSTR sigFileName, LPCSTR orgFileName = NULL)
{
    
// 准备数据
    CRYPT_DATA_BLOB sigBlob;
    memset(
&sigBlob, 0sizeof(sigBlob));
    prepareData(NULL, 
0, sigFileName, sigBlob.pbData, sigBlob.cbData);

    
// 设定校验参数
    CRYPT_VERIFY_MESSAGE_PARA VerifyParams;
    VerifyParams.cbSize 
= sizeof(CRYPT_VERIFY_MESSAGE_PARA);
    VerifyParams.dwMsgAndCertEncodingType 
= MY_ENCODING_TYPE;
    VerifyParams.hCryptProv 
= 0;
    VerifyParams.pfnGetSignerCertificate 
= NULL;
    VerifyParams.pvGetArg 
= NULL;

/*
BOOL WINAPI CryptVerifyMessageSignature(
  __in          PCRYPT_VERIFY_MESSAGE_PARA pVerifyPara,
  __in          DWORD dwSignerIndex,
  __in          const BYTE* pbSignedBlob,
  __in          DWORD cbSignedBlob,
  __out         BYTE* pbDecoded,
  __in_out      DWORD* pcbDecoded,
  __out_opt     PCCERT_CONTEXT* ppSignerCert
);
*/

    
// 获取原文字节数
    CRYPT_DATA_BLOB orgBlob;
    memset(
&orgBlob, 0sizeof(orgBlob));
    
if(!CryptVerifyMessageSignature(
        
&VerifyParams,
        
0,
        sigBlob.pbData,
        sigBlob.cbData,
        NULL,
        
&orgBlob.cbData,
        NULL))
    
{
        delete [] sigBlob.pbData;
        CancelByError(L
"Verification message failed. \n");
    }


    _tprintf(L
"%d bytes needed for the decoded message.\n", orgBlob.cbData);

    
// 分配内存
    orgBlob.pbData = (BYTE*new char[orgBlob.cbData];
    
if(orgBlob.pbData == NULL)
    
{
        delete [] sigBlob.pbData;
        CancelByError(L
"Not enough memory. \n");
    }


    PCCERT_CONTEXT hCert 
= NULL;
    
if(CryptVerifyMessageSignature(
        
&VerifyParams,
        
0,
        sigBlob.pbData,
        sigBlob.cbData,
        orgBlob.pbData,
        
&orgBlob.cbData,
        
&hCert))
    
{
        _tprintf(L
"Verification message succeed. \n");
        showData(orgBlob.pbData, orgBlob.cbData);
        
if(orgFileName != NULL)
        
{
            writeFile(orgFileName, orgBlob.pbData, orgBlob.cbData);
        }


        viewCertCN(hCert);
    }

    
else
    
{
        _tprintf(L
"Verification message failed. \n");
    }


    
// 清理
    delete [] sigBlob.pbData;
    delete [] orgBlob.pbData;

    
if(hCert != NULL)
    
{
        CertFreeCertificateContext(hCert);
        hCert 
= NULL;
    }

}


// 使用证书公钥加密
void CertEncrypt(BYTE* orgData, int orgSize, LPCSTR orgFileName, LPCSTR encFileName = NULL)
{
    
// 准备数据
    CRYPT_DATA_BLOB orgBlob;
    memset(
&orgBlob, 0sizeof(orgBlob));
    prepareData(orgData, orgSize, orgFileName, orgBlob.pbData, orgBlob.cbData);

    
// 获取CSP句柄
    HCRYPTPROV hCryptProv = NULL;
    
if(!CryptAcquireContext(
        
&hCryptProv,        // Address for handle to be returned.
        NULL,               // Use the current user's logon name.
        NULL,               // Use the default provider.
        PROV_RSA_FULL,      // Need to both encrypt and sign.
        NULL))              // No flags needed.
    {
        delete [] orgBlob.pbData;
        CancelByError(L
"Cryptographic context could not be acquired.");
    }


    
// 获取加密者证书
    HCERTSTORE hCertStore = NULL;
    hCertStore 
= CertOpenStore(
        CERT_STORE_PROV_SYSTEM, 
        
0
        NULL, 
        CERT_SYSTEM_STORE_CURRENT_USER, 
        L
"MY");
    
if(hCertStore == NULL)
    
{
        delete [] orgBlob.pbData;
        CryptReleaseContext(hCryptProv, 
0);
        CancelByError(L
"Open CertStore failed!\n");
    }


    
// 查找签名者证书
    PCCERT_CONTEXT pCert = NULL;
    pCert 
= CertFindCertificateInStore(
       hCertStore,
       MY_ENCODING_TYPE,
       
0,
       CERT_FIND_SUBJECT_STR,
       L
"lny",
       NULL);
    
if(pCert == NULL)
    
{
        delete [] orgBlob.pbData;
        CryptReleaseContext(hCryptProv, 
0);
        CancelByError(L
"Encrypter certificate not found.");
    }


    _tprintf(L
"Encrypter certificate has been found.\n");
    viewCertCN(pCert);

    
// 设置加密算法
    CRYPT_ALGORITHM_IDENTIFIER EncryptAlgorithm;
    memset(
&EncryptAlgorithm, 0sizeof(EncryptAlgorithm));
    EncryptAlgorithm.pszObjId 
= szOID_RSA_DES_EDE3_CBC;

    
// 设置加密参数
    CRYPT_ENCRYPT_MESSAGE_PARA EncryptParams;
    memset(
&EncryptParams, 0sizeof(EncryptParams));
    EncryptParams.cbSize 
=  sizeof(EncryptParams);
    EncryptParams.dwMsgEncodingType 
= PKCS_7_ASN_ENCODING;
    EncryptParams.hCryptProv 
= hCryptProv;
    EncryptParams.ContentEncryptionAlgorithm 
= EncryptAlgorithm;

    
// 设置加密的证书清单
    PCCERT_CONTEXT RecipientCertArray[1];
    RecipientCertArray[
0= pCert;

    
// 获取加密消息的字节数
    CRYPT_DATA_BLOB encBlob;
    memset(
&encBlob, 0sizeof(encBlob));
    
if(!CryptEncryptMessage(
        
&EncryptParams,
        
1,
        RecipientCertArray,
        orgBlob.pbData,
        orgBlob.cbData,
        NULL,
        
&encBlob.cbData))
    
{
        delete [] orgBlob.pbData;
        CryptReleaseContext(hCryptProv, 
0);
        CancelByError(L
"Getting encrypted message size failed.");
    }


    _tprintf(L
"The encrypted message is %d bytes. \n",encBlob.cbData);

    
// 分配空间
    encBlob.pbData = (BYTE*new char[encBlob.cbData];
    
if(encBlob.pbData == NULL)
    
{
        delete [] orgBlob.pbData;
        CryptReleaseContext(hCryptProv, 
0);
        CancelByError(L
"Memory allocation error while encrypting.");
    }


    
// 加密处理
    if(!CryptEncryptMessage(
        
&EncryptParams,
        
1,
        RecipientCertArray,
        orgBlob.pbData,
        orgBlob.cbData,
        encBlob.pbData,
        
&encBlob.cbData))
    
{
        delete [] orgBlob.pbData;
        delete [] encBlob.pbData;
        CryptReleaseContext(hCryptProv, 
0);
        CancelByError(L
"Encrypted message failed.");
    }


    showData(encBlob.pbData, encBlob.cbData);
    
if(encFileName != NULL)
    
{
        writeFile(encFileName, encBlob.pbData, encBlob.cbData);
    }


    
// 清理
    delete [] orgBlob.pbData;
    delete [] encBlob.pbData;

    
if(hCryptProv != NULL)
    
{
        CryptReleaseContext(hCryptProv, 
0);
        hCryptProv 
= NULL;
    }

}


// 使用证书私钥解密
void CertDecrypt(LPCSTR encFileName, LPCSTR orgFileName)
{
    
// 准备数据
    CRYPT_DATA_BLOB encBlob;
    memset(
&encBlob, 0sizeof(encBlob));
    prepareData(NULL, 
0, encFileName, encBlob.pbData, encBlob.cbData);

    
// 获取加密者证书
    HCERTSTORE hCertStore = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, NULL, CERT_SYSTEM_STORE_CURRENT_USER, L"MY");
    
if(hCertStore == NULL)
    
{
        delete [] encBlob.pbData;
        CancelByError(L
"Open CertStore failed!\n");
    }


    
// 设置解密参数
    HCERTSTORE CertStoreArray[] = {hCertStore};
    CRYPT_DECRYPT_MESSAGE_PARA  DecryptParams;
    memset(
&DecryptParams, 0sizeof(DecryptParams));
    DecryptParams.cbSize 
= sizeof(DecryptParams);
    DecryptParams.dwMsgAndCertEncodingType 
= MY_ENCODING_TYPE;
    DecryptParams.cCertStore 
= 1;
    DecryptParams.rghCertStore 
= CertStoreArray;

    
// 解密
    CRYPT_DATA_BLOB orgBlob;
    memset(
&orgBlob, 0sizeof(orgBlob));
    
if(!CryptDecryptMessage(
        
&DecryptParams,
        encBlob.pbData,
        encBlob.cbData,
        NULL,
        
&orgBlob.cbData,
        NULL))
    
{
        delete [] encBlob.pbData;
        CancelByError(L
"Error getting decrypted message size. \n");
    }


    _tprintf(L
"The size for the decrypted message is: %d.\n", orgBlob.cbData);

    
// 分配空间
    orgBlob.pbData = (BYTE*new char[orgBlob.cbData];
    
if(orgBlob.pbData == NULL)
    
{
        delete [] encBlob.pbData;
        CancelByError(L
"Memory allocation error while decrypting. \n");
    }


    
// 解密
    if(!CryptDecryptMessage(
        
&DecryptParams,
        encBlob.pbData,
        encBlob.cbData,
        orgBlob.pbData,
        
&orgBlob.cbData,
        NULL))
    
{
        delete [] encBlob.pbData;
        delete [] orgBlob.pbData;
        CancelByError(L
"Decrypted message failed! \n");
    }


    _tprintf(L
"Message Decrypted Successfully. %d\n", orgBlob.cbData);

    showData(orgBlob.pbData, orgBlob.cbData);
    
if(orgFileName != NULL)
    
{
        writeFile(orgFileName, orgBlob.pbData, orgBlob.cbData);
    }


    delete [] encBlob.pbData;
    delete [] orgBlob.pbData;
}


// 证书加密并签名生成数字信封
void SignAndEncryptData(BYTE* orgData, int orgSize, LPCSTR orgFileName, LPCSTR encFileName)
{
    
// 准备数据
    CRYPT_DATA_BLOB orgBlob;
    memset(
&orgBlob, 0sizeof(orgBlob));
    prepareData(orgData, orgSize, orgFileName, orgBlob.pbData, orgBlob.cbData);
    
    
// 存取证书库
    HCERTSTORE hCertStore = NULL;
    hCertStore 
= CertOpenStore(
        CERT_STORE_PROV_SYSTEM,
        
0,
        NULL,
        CERT_SYSTEM_STORE_CURRENT_USER,
        L
"my");
    
if(hCertStore == NULL)
    
{
        delete [] orgBlob.pbData;
        CancelByError(L
"The MY store could not be opened.");
    }


    
// 获取签名者证书
    PCCERT_CONTEXT pSignerCertContext = NULL;
    pSignerCertContext 
= CertFindCertificateInStore(
        hCertStore,
        MY_ENCODING_TYPE,
        
0,
        CERT_FIND_SUBJECT_STR,
        L
"lny",
        NULL);
    
if(pSignerCertContext == NULL)
    
{
        delete [] orgBlob.pbData;
        CertCloseStore(hCertStore, 
0);
        CancelByError(L
"Signer cert not found.\n");
    }


    
// 获取接收者证书
    PCCERT_CONTEXT pReceiverCertContext = NULL;
    pReceiverCertContext 
= CertFindCertificateInStore(
        hCertStore,
        MY_ENCODING_TYPE,
        
0,
        CERT_FIND_SUBJECT_STR,
        L
"lny",
        NULL);
    
if(pReceiverCertContext == NULL)
    
{
        delete [] orgBlob.pbData;
        CertFreeCertificateContext(pSignerCertContext);
        CertCloseStore(hCertStore, 
0);
        CancelByError(L
"Receiver cert not found.\n");
    }


    
// pReceiverCertContext = pSignerCertContext;

    
// 申请签名者私钥服务
    DWORD dwKeySpec;
    HCRYPTPROV hCryptProv;
    
if(!CryptAcquireCertificatePrivateKey(
        pSignerCertContext,
        
0,
        NULL,
        
&hCryptProv,
        
&dwKeySpec,
        NULL))
    
{
        delete [] orgBlob.pbData;
        CertFreeCertificateContext(pSignerCertContext);
        CertFreeCertificateContext(pReceiverCertContext);
        CertCloseStore(hCertStore, 
0);
        CancelByError(L
"CryptAcquireCertificatePrivateKey.\n");
    }


    
// 设置签名参数
    CRYPT_SIGN_MESSAGE_PARA SignPara;
    memset(
&SignPara, 0sizeof(SignPara));
    SignPara.cbSize 
= sizeof(CRYPT_SIGN_MESSAGE_PARA);
    SignPara.dwMsgEncodingType 
= MY_ENCODING_TYPE;
    SignPara.pSigningCert 
= pSignerCertContext ;
    SignPara.HashAlgorithm.pszObjId 
= szOID_RSA_MD2;
    SignPara.HashAlgorithm.Parameters.cbData 
= 0;
    SignPara.pvHashAuxInfo 
= NULL;
    SignPara.cMsgCert 
= 1;
    SignPara.rgpMsgCert 
= &pSignerCertContext ;
    SignPara.cMsgCrl 
= 0;
    SignPara.rgpMsgCrl 
= NULL;
    SignPara.cAuthAttr 
= 0;
    SignPara.rgAuthAttr 
= NULL;
    SignPara.cUnauthAttr 
= 0;
    SignPara.rgUnauthAttr 
= NULL;
    SignPara.dwFlags 
= 0;
    SignPara.dwInnerContentType 
= 0;

    
// 设置加密参数
    CRYPT_ENCRYPT_MESSAGE_PARA EncryptPara;
    memset(
&EncryptPara, 0sizeof(EncryptPara));
    EncryptPara.cbSize 
= sizeof(CRYPT_ENCRYPT_MESSAGE_PARA);
    EncryptPara.dwMsgEncodingType 
= MY_ENCODING_TYPE;
    EncryptPara.hCryptProv 
= 0;
    EncryptPara.ContentEncryptionAlgorithm.pszObjId 
= szOID_RSA_DES_EDE3_CBC;
    EncryptPara.ContentEncryptionAlgorithm.Parameters.cbData 
= 0;
    EncryptPara.pvEncryptionAuxInfo 
= NULL;
    EncryptPara.dwFlags 
= 0;
    EncryptPara.dwInnerContentType 
= 0;

    
// 设置加密的证书
    DWORD cRecipientCert;
    PCCERT_CONTEXT rgpRecipientCert[
5];
    cRecipientCert 
= 1;
    rgpRecipientCert[
0= pReceiverCertContext;

    
// 获取签名并加密消息长度
    CRYPT_DATA_BLOB encBlob;
    memset(
&encBlob, 0sizeof(encBlob));
    
if(!CryptSignAndEncryptMessage(
        
&SignPara,
        
&EncryptPara,
        cRecipientCert,
        rgpRecipientCert,
        orgBlob.pbData,
        orgBlob.cbData,
        NULL,
        
&encBlob.cbData))
    
{
        delete [] orgBlob.pbData;
        CertFreeCertificateContext(pSignerCertContext);
        CertFreeCertificateContext(pReceiverCertContext);
        CertCloseStore(hCertStore, 
0);
        CancelByError(L
"Getting Signed&Encrypted message length failed.");
    }


    _tprintf(L
"SignAndEncrypte message size is %d bytes.\n", encBlob.cbData);

    
// 分配空间
    encBlob.pbData = (BYTE*new char[encBlob.cbData];
    
if(encBlob.pbData == NULL)
    
{
        delete [] orgBlob.pbData;
        CertFreeCertificateContext(pSignerCertContext);
        CertFreeCertificateContext(pReceiverCertContext);
        CertCloseStore(hCertStore, 
0);
        CancelByError(L
"Memory allocation error while SignAndEncrypting. \n");
    }


    
// 签名并加密消息
    if(!CryptSignAndEncryptMessage(
        
&SignPara,
        
&EncryptPara,
        cRecipientCert,
        rgpRecipientCert,
        orgBlob.pbData,
        orgBlob.cbData,
        encBlob.pbData,
        
&encBlob.cbData))
    
{
        delete [] orgBlob.pbData;
        delete [] encBlob.pbData;
        CertFreeCertificateContext(pSignerCertContext);
        CertFreeCertificateContext(pReceiverCertContext);
        CertCloseStore(hCertStore, 
0);
        CancelByError(L
"The message failed to sign and encrypt.");
    }


    _tprintf(L
"The message is signed and encrypted.\n");

    showData(encBlob.pbData, encBlob.cbData);
    
if(encFileName != NULL)
    
{
        writeFile(encFileName, encBlob.pbData, encBlob.cbData);
    }


    
// 清理
    delete [] orgBlob.pbData;
    delete [] encBlob.pbData;
    CertFreeCertificateContext(pSignerCertContext);
    CertFreeCertificateContext(pReceiverCertContext);
    CertCloseStore(hCertStore, 
0);
}


// 解密并校验数字信封
void DecryptAndVerifyData(LPCSTR encFileName, LPCSTR orgFileName)
{
    
// 准备数据
    CRYPT_DATA_BLOB encBlob;
    memset(
&encBlob, 0sizeof(encBlob));
    prepareData(NULL, 
0, encFileName, encBlob.pbData, encBlob.cbData);

    
// 存取证书库
    HCERTSTORE hCertStore = NULL;
    hCertStore 
= CertOpenStore(
        CERT_STORE_PROV_SYSTEM,
        
0,
        NULL,
        CERT_SYSTEM_STORE_CURRENT_USER,
        L
"my");
    
if(hCertStore == NULL)
    
{
        delete [] encBlob.pbData;
        CancelByError(L
"The MY store could not be opened.");
    }


    
// 设置解密参数
    CRYPT_DECRYPT_MESSAGE_PARA DecryptPara;
    memset(
&DecryptPara, 0sizeof(DecryptPara));
    DecryptPara.cbSize 
= sizeof(CRYPT_DECRYPT_MESSAGE_PARA);
    DecryptPara.dwMsgAndCertEncodingType 
= MY_ENCODING_TYPE;
    DecryptPara.cCertStore 
= 1;
    DecryptPara.rghCertStore 
= &hCertStore;

    
// 设置校验参数
    CRYPT_VERIFY_MESSAGE_PARA VerifyPara;
    memset(
&VerifyPara, 0sizeof(VerifyPara));
    VerifyPara.cbSize 
= sizeof(CRYPT_VERIFY_MESSAGE_PARA);
    VerifyPara.dwMsgAndCertEncodingType 
= MY_ENCODING_TYPE;
    VerifyPara.hCryptProv 
= 0;
    VerifyPara.pfnGetSignerCertificate 
= NULL;
    VerifyPara.pvGetArg 
= NULL;

    
// 获取解密消息长度
    DWORD dwSignerIndex = 0;
    CRYPT_DATA_BLOB orgBlob;
    memset(
&orgBlob, 0sizeof(orgBlob));
    
if(!(CryptDecryptAndVerifyMessageSignature(
        
&DecryptPara,
        
&VerifyPara,
        dwSignerIndex,
        encBlob.pbData,
        encBlob.cbData,
        NULL,           
        
&orgBlob.cbData,
        NULL,
        NULL)))
    
{
        delete [] encBlob.pbData;
        CertCloseStore(hCertStore, 
0);
        CancelByError(L
"Get decrypted message size failed.");
    }


    _tprintf(L
"DecryptAndVerify message size is %d bytes.\n", orgBlob.cbData);

    
// 分配空间
    orgBlob.pbData = (BYTE*new char[orgBlob.cbData];
    
if(orgBlob.pbData == NULL)
    
{
        delete [] encBlob.pbData;
        CertCloseStore(hCertStore, 
0);
        CancelByError(L
"Memory allocation error while DecryptAndVerifyMessage. \n");
    }


    
// 解密并校验
    PCCERT_CONTEXT pRecverCert;
    PCCERT_CONTEXT pSignerCert;
    
if(!(CryptDecryptAndVerifyMessageSignature(
        
&DecryptPara,
        
&VerifyPara,
        dwSignerIndex,
        encBlob.pbData,
        encBlob.cbData,
        orgBlob.pbData,           
        
&orgBlob.cbData,
        
&pRecverCert,
        
&pSignerCert)))
    
{
        delete [] orgBlob.pbData;
        delete [] encBlob.pbData;
        CertCloseStore(hCertStore, 
0);
        CancelByError(L
"The message failed to sign and encrypt.");
    }


    _tprintf(L
"The message is decrypted and verifyed.\n");

    showData(orgBlob.pbData, orgBlob.cbData);
    
if(orgFileName != NULL)
    
{
        writeFile(orgFileName, orgBlob.pbData, orgBlob.cbData);
    }


    viewCertCN(pSignerCert);
    viewCertCN(pRecverCert);

    
// 清理
    delete [] orgBlob.pbData;
    delete [] encBlob.pbData;
    CertCloseStore(hCertStore, 
0);
}


// 加密并签名的数字信封(低级)
void EnvelopeData(BYTE* orgData, int orgSize, LPCSTR orgFileName, LPCSTR encFileName = NULL)
{
    
// 准备数据
    CRYPT_DATA_BLOB orgBlob;
    memset(
&orgBlob, 0sizeof(orgBlob));
    prepareData(orgData, orgSize, orgFileName, orgBlob.pbData, orgBlob.cbData);

    
// 从MY证书库获取签名者证书
    HCERTSTORE hCertStore = NULL;
    hCertStore 
= CertOpenStore(
        CERT_STORE_PROV_SYSTEM, 
        
0
        NULL, 
        CERT_SYSTEM_STORE_CURRENT_USER, 
        L
"MY");
    
if(hCertStore == NULL)
    
{
        delete [] orgBlob.pbData;
        CancelByError(L
"Open CertStore failed!\n");
    }


    
// 查找签名者证书
    PCCERT_CONTEXT pSignerCert = NULL;
    pSignerCert 
= CertFindCertificateInStore(
       hCertStore,
       MY_ENCODING_TYPE,
       
0,
       CERT_FIND_SUBJECT_STR,
       L
"lny",
       NULL);
    
if(pSignerCert == NULL)
    
{
        delete [] orgBlob.pbData;
        CertCloseStore(hCertStore, CERT_CLOSE_STORE_FORCE_FLAG);
        CancelByError(L
"Signer certificate not found.");
    }


    _tprintf(L
"Signer certificate has been found.\n");
    viewCertCN(pSignerCert);

    
// 申请私钥服务
    HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hKeyProv = NULL;
    DWORD dwKeyType 
= 0;
    BOOL bFreeKeyProv 
= FALSE;
    
if(!CryptAcquireCertificatePrivateKey(pSignerCert, 00&hKeyProv, &dwKeyType, &bFreeKeyProv))
    
{
        delete [] orgBlob.pbData;
        CertFreeCertificateContext(pSignerCert);
        CertCloseStore(hCertStore, CERT_CLOSE_STORE_FORCE_FLAG);
        CancelByError(L
"Acquire certificate privateKey failed!\n");
    }


    
// 设置签名算法
    CRYPT_ALGORITHM_IDENTIFIER HashAlgorithm;
    memset(
&HashAlgorithm, 0sizeof(HashAlgorithm));
    HashAlgorithm.pszObjId 
= szOID_RSA_MD5;

    
// 设置签名编码参数
    CMSG_SIGNER_ENCODE_INFO SignerEncodeInfo;
    CMSG_SIGNER_ENCODE_INFO SignerEncodeInfoArray[
1];
    memset(
&SignerEncodeInfo, 0sizeof(CMSG_SIGNER_ENCODE_INFO));
    SignerEncodeInfo.cbSize 
= sizeof(CMSG_SIGNER_ENCODE_INFO);
    SignerEncodeInfo.pCertInfo 
= pSignerCert->pCertInfo;
    SignerEncodeInfo.hCryptProv 
= hKeyProv;
    SignerEncodeInfo.dwKeySpec 
= AT_KEYEXCHANGE;
    SignerEncodeInfo.HashAlgorithm 
= HashAlgorithm;
    SignerEncodeInfo.pvHashAuxInfo 
= NULL;
    SignerEncodeInfoArray[
0= SignerEncodeInfo;
    
    
// 设置签名证书
    CERT_BLOB SignerCertBlob;
    CERT_BLOB SignerCertBlobArray[
1];
    SignerCertBlob.cbData 
= pSignerCert->cbCertEncoded;
    SignerCertBlob.pbData 
= pSignerCert->pbCertEncoded;
    SignerCertBlobArray[
0= SignerCertBlob;

    
// 设置签名编码参数
    CMSG_SIGNED_ENCODE_INFO SignedMsgEncodeInfo;
    memset(
&SignedMsgEncodeInfo, 0sizeof(CMSG_SIGNED_ENCODE_INFO));
    SignedMsgEncodeInfo.cbSize 
= sizeof(CMSG_SIGNED_ENCODE_INFO);
    SignedMsgEncodeInfo.cSigners 
= 1;
    SignedMsgEncodeInfo.rgSigners 
= SignerEncodeInfoArray;
    SignedMsgEncodeInfo.cCertEncoded 
= 1;
    SignedMsgEncodeInfo.rgCertEncoded 
= SignerCertBlobArray;
    SignedMsgEncodeInfo.cCrlEncoded 
= 0;
    SignedMsgEncodeInfo.rgCrlEncoded 
= NULL;

    
// 获取编码输出的签名块长度
    CRYPT_DATA_BLOB sigBlob;
    memset(
&sigBlob, 0sizeof(sigBlob));
    sigBlob.cbData 
= CryptMsgCalculateEncodedLength(
        MY_ENCODING_TYPE,
        
0,
        CMSG_SIGNED,
        
&SignedMsgEncodeInfo,
        NULL,
        orgBlob.cbData);
    
if(sigBlob.cbData == 0)
    
{
        delete [] orgBlob.pbData;
        CertFreeCertificateContext(pSignerCert);
        CertCloseStore(hCertStore, CERT_CLOSE_STORE_FORCE_FLAG);
        CancelByError(L
"Getting signed message length failed.");
    }


    
// 分配编码空间
    sigBlob.pbData = (BYTE *new char[sigBlob.cbData];
    
if(sigBlob.pbData == NULL)
    
{
        delete [] orgBlob.pbData;
        CertFreeCertificateContext(pSignerCert);
        CertCloseStore(hCertStore, CERT_CLOSE_STORE_FORCE_FLAG);
        CancelByError(L
"Memory allocation failed. \n");
    }


    
// 编码签名消息
    HCRYPTMSG hMsg;
    hMsg 
= CryptMsgOpenToEncode(
        MY_ENCODING_TYPE,        
// encoding type
        0,                       // flags
        CMSG_SIGNED,             // message type
        &SignedMsgEncodeInfo,    // pointer to structure
        NULL,                    // inner content OID
        NULL);                   // stream information (not used)
    if(hMsg == NULL) 
    
{
        delete [] orgBlob.pbData;
        delete [] sigBlob.pbData;
        CertFreeCertificateContext(pSignerCert);
        CertCloseStore(hCertStore, CERT_CLOSE_STORE_FORCE_FLAG);
        CancelByError(L
"The message to be encoded failed. \n");
    }


    
// 添加数据
    if(!CryptMsgUpdate(
        hMsg,                
// handle to the message
        orgBlob.pbData,        // pointer to the content
        orgBlob.cbData,        // size of the content
        TRUE))                // last call
    {
        delete [] orgBlob.pbData;
        delete [] sigBlob.pbData;
        CryptMsgClose(hMsg);
        CertFreeCertificateContext(pSignerCert);
        CertCloseStore(hCertStore, CERT_CLOSE_STORE_FORCE_FLAG);
        CancelByError(L
"CryptMsgUpdate failed.\n");
    }


    
// 获取签名结果
    if(!CryptMsgGetParam(
        hMsg,                        
// handle to the message
        CMSG_CONTENT_PARAM,            // parameter type
        0,                            // index
        sigBlob.pbData,                // pointer to the BLOB
        &sigBlob.cbData))            // size of the BLOB
    {
        delete [] orgBlob.pbData;
        delete [] sigBlob.pbData;
        CryptMsgClose(hMsg);
        CertFreeCertificateContext(pSignerCert);
        CertCloseStore(hCertStore, CERT_CLOSE_STORE_FORCE_FLAG);
        CancelByError(L
"CryptMsgGetParam signed message failed.\n");
    }


    
// 清理签名部分
    delete [] orgBlob.pbData;

    
if(pSignerCert != NULL)
    
{
        CertFreeCertificateContext(pSignerCert);
        pSignerCert 
= NULL;
    }


    
if(hMsg != NULL)
    
{
       CryptMsgClose(hMsg);
       hMsg 
= NULL;
    }


    
if(hKeyProv != NULL)
    
{
        CryptReleaseContext(hKeyProv, 
0);
        hKeyProv 
= NULL;
    }


    
// ----------------------- 签名结束:得到带原文的签名

    
// 公钥加密

    
// 查找接收者证书
    PCCERT_CONTEXT pRecverCert = NULL;
    pRecverCert 
= CertFindCertificateInStore(
       hCertStore,
       MY_ENCODING_TYPE,
       
0,
       CERT_FIND_SUBJECT_STR,
       L
"lny",
       NULL);
    
if(pRecverCert == NULL)
    
{
        delete [] sigBlob.pbData;
        CertCloseStore(hCertStore, CERT_CLOSE_STORE_FORCE_FLAG);
        CancelByError(L
"Receiver certificate not found.");
    }


    _tprintf(L
"Receiver certificate has been found.\n");
    viewCertCN(pRecverCert);

    
// 设置加密证书
    PCERT_INFO RecipCertArray[1];
    RecipCertArray[
0= pRecverCert->pCertInfo;

    
// 设置加密算法
    CRYPT_ALGORITHM_IDENTIFIER ContentEncryptAlgorithm;
    memset(
&ContentEncryptAlgorithm, 0sizeof(ContentEncryptAlgorithm));
    ContentEncryptAlgorithm.pszObjId 
= szOID_RSA_RC2CBC;

    
// 设置信封参数
    CMSG_ENVELOPED_ENCODE_INFO EnvelopedEncodeInfo;
    memset(
&EnvelopedEncodeInfo, 0sizeof(CMSG_ENVELOPED_ENCODE_INFO));
    EnvelopedEncodeInfo.cbSize 
= sizeof(CMSG_ENVELOPED_ENCODE_INFO);
    EnvelopedEncodeInfo.hCryptProv 
= NULL;
    EnvelopedEncodeInfo.ContentEncryptionAlgorithm 
= ContentEncryptAlgorithm;
    EnvelopedEncodeInfo.pvEncryptionAuxInfo 
= NULL;
    EnvelopedEncodeInfo.cRecipients 
= 1;
    EnvelopedEncodeInfo.rgpRecipients 
= RecipCertArray;
    
    
// 获取消息编码的长度
    CRYPT_DATA_BLOB encBlob;
    memset(
&encBlob, 0sizeof(encBlob));
    encBlob.cbData 
= CryptMsgCalculateEncodedLength(
        MY_ENCODING_TYPE,
        
0,
        CMSG_ENVELOPED,
        
&EnvelopedEncodeInfo,
        NULL,
        sigBlob.cbData);
    
if(encBlob.cbData == 0)
    
{
        delete [] sigBlob.pbData;
        CertFreeCertificateContext(pRecverCert);
        CertCloseStore(hCertStore, CERT_CLOSE_STORE_FORCE_FLAG);
        CancelByError(L
"Getting enveloped cbEncodedBlob length failed.");
    }


    _tprintf(L
"Enveloped message size is %d bytes.", encBlob.cbData);

    
// 分配编码空间
    encBlob.pbData = (BYTE *new char[encBlob.cbData];
    
if(encBlob.pbData == NULL)
    
{
        delete [] sigBlob.pbData;
        CertFreeCertificateContext(pRecverCert);
        CertCloseStore(hCertStore, CERT_CLOSE_STORE_FORCE_FLAG);
        CancelByError(L
"Memory allocation failed. \n");
    }


    
// 编码加密
    hMsg = CryptMsgOpenToEncode(
        MY_ENCODING_TYPE,        
// encoding type
        0,                       // flags
        CMSG_ENVELOPED,          // message type
        &EnvelopedEncodeInfo,    // pointer to structure
        NULL,                     // szOID_RSA_signedData,    // inner content OID
        NULL);
    
if(hMsg == NULL) 
    
{
        delete [] encBlob.pbData;
        delete [] sigBlob.pbData;
        CertFreeCertificateContext(pRecverCert);
        CertCloseStore(hCertStore, CERT_CLOSE_STORE_FORCE_FLAG);
        CancelByError(L
"The message open to be encode failed. \n");
    }


    
// 添加数据
    if(!CryptMsgUpdate(
        hMsg,                
// handle to the message
        sigBlob.pbData,        // pointer to the content
        sigBlob.cbData,        // size of the content
        TRUE))                // last call
    {
        delete [] encBlob.pbData;
        delete [] sigBlob.pbData;
        CryptMsgClose(hMsg);
        CertFreeCertificateContext(pRecverCert);
        CertCloseStore(hCertStore, CERT_CLOSE_STORE_FORCE_FLAG);
        CancelByError(L
"Enveloped CryptMsgUpdate failed.\n");
    }


    
// 获取加密结果
    if(!CryptMsgGetParam(
        hMsg,                        
// handle to the message
        CMSG_CONTENT_PARAM,            // parameter type
        0,                            // index
        encBlob.pbData,                // pointer to the BLOB
        &encBlob.cbData))            // size of the BLOB
    {
        delete [] encBlob.pbData;
        delete [] sigBlob.pbData;
        CryptMsgClose(hMsg);
        CertFreeCertificateContext(pRecverCert);
        CertCloseStore(hCertStore, CERT_CLOSE_STORE_FORCE_FLAG);
        CancelByError(L
"CryptMsgGetParam enveloped message failed.\n");
    }


    showData(encBlob.pbData, encBlob.cbData);
    
if(encFileName != NULL)
    
{
        writeFile(encFileName, encBlob.pbData, encBlob.cbData);
    }


    
// 清理
    delete [] encBlob.pbData;
    delete [] sigBlob.pbData;

    
if(hMsg != NULL)
    
{
        CryptMsgClose(hMsg);
        hMsg 
= NULL;
    }


    
if(pRecverCert != NULL)
    
{
        CertFreeCertificateContext(pRecverCert);
        pRecverCert 
= NULL;
    }


    
if(hCertStore != NULL)
    
{
        CertCloseStore(hCertStore, CERT_CLOSE_STORE_FORCE_FLAG);
    }

}


// 解密信封并校验签名(低级)
void DevelopeData(LPCSTR encFileName, LPCSTR orgFileName)
{
    
// 准备数据
    CRYPT_DATA_BLOB encBlob;
    memset(
&encBlob, 0sizeof(encBlob));
    prepareData(NULL, 
0, encFileName, encBlob.pbData, encBlob.cbData);

    
// Open
    HCRYPTMSG hMsg = NULL; 
    hMsg 
= CryptMsgOpenToDecode( 
        MY_ENCODING_TYPE,    
// Encoding type. 
        0,                    // Flags. 
        0,                    // Use the default message type which is listed in the message header. 
        NULL,                // Cryptographic provider. Use NULL for the default provider. 
        NULL,                // Recipient information. 
        NULL);                // Stream information. 
    if(hMsg == NULL) 
    

        delete [] encBlob.pbData;
        CancelByError(L
"Failed in CryptMsgOpenToDecode."); 
    }
 

    
// Update
    if(!CryptMsgUpdate( 
        hMsg,                
// Handle to the message 
        encBlob.pbData,        // Pointer to the encoded BLOB 
        encBlob.cbData,        // Size of the encoded BLOB 
        TRUE))
    
{
        delete [] encBlob.pbData;
        CryptMsgClose(hMsg);
        CancelByError(L
"Failed in CryptMsgUpdate."); 
    }


    
// 释放加密数据
    delete [] encBlob.pbData;

    
// 开始操作解码后的加密数据 ================================

    
// 消息类型
    DWORD dwType = 0
    DWORD dwSize 
= sizeof(dwType);
    
if(!CryptMsgGetParam( 
        hMsg,                
// Handle to the message 
        CMSG_TYPE_PARAM,    // Parameter type 
        0,                    // Index 
        &dwType,            // Buffer
        &dwSize))            // Size of the returned 
    
        CryptMsgClose(hMsg);
        CancelByError(L
"Failed in CryptMsgGetParam for CMSG_TYPE_PARAM."); 
    }


    
// 校验消息类型
    if (dwType != CMSG_ENVELOPED) 
    

        CryptMsgClose(hMsg);
        CancelByError(L
"Not an enveloped data."); 
    }
 

    
// 消息格式
    char szTypeName[1024];
    dwSize 
= 1024;
    
if(!CryptMsgGetParam( 
        hMsg,                            
// Handle to the message 
        CMSG_INNER_CONTENT_TYPE_PARAM,    // Parameter type 
        0,                                // Index 
        szTypeName,                        // Buffer 
        &dwSize))                        // Size of the returned 
    {
        CryptMsgClose(hMsg);
        CancelByError(L
"Failed in CryptMsgGetParam for CMSG_INNER_CONTENT_TYPE_PARAM."); 
    }


    
// 检查消息格式
    if(strcmp(szTypeName, szOID_PKCS_7_DATA) != 0
    
{
//        CryptMsgClose(hMsg);
//      CancelByError(L"The inner content is not szOID_PKCS_7_DATA."); 
    }
 

    
// 获取接收者证书大小
    if(!CryptMsgGetParam( 
        hMsg,                        
// Handle to the message 
        CMSG_RECIPIENT_INFO_PARAM,    // Parameter type 
        0,                            // Index 
        NULL,                        // Buffer
        &dwSize))                    // Size of the returned 
    
        CryptMsgClose(hMsg);
        CancelByError(L
"Failed in CryptMsgGetParam for CMSG_RECIPIENT_INFO_PARAM."); 
    }
 

    
// 分配内存
    PCERT_INFO pRecverCertInfo = (PCERT_INFO) new char[dwSize]; 
    
if (pRecverCertInfo == NULL)
    
{
        CryptMsgClose(hMsg);
        CancelByError(L
"Not enough memory."); 
    }


    
// 获取接收者证书信息
    if(!CryptMsgGetParam( 
        hMsg,                        
// Handle to the message 
        CMSG_RECIPIENT_INFO_PARAM,    // Parameter type 
        0,                            // Index 
        pRecverCertInfo,                    // Buffer
        &dwSize))                    // Size of the returned 
    
        delete [] pRecverCertInfo;
        CryptMsgClose(hMsg);
        CancelByError(L
"Failed in CryptMsgGetParam for CMSG_RECIPIENT_INFO_PARAM."); 
    }
 

    
// 访问证书库
    HCERTSTORE hCertStore = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, NULL, CERT_SYSTEM_STORE_CURRENT_USER, L"MY");
    
if(hCertStore == NULL)
    
{
        delete [] pRecverCertInfo;
        CryptMsgClose(hMsg);
        CancelByError(L
"Open CertStore failed!\n");
    }


    
// 获取接收者证书
    PCCERT_CONTEXT hRcverCertContext = CertGetSubjectCertificateFromStore(hCertStore, MY_ENCODING_TYPE, pRecverCertInfo); 
    delete [] pRecverCertInfo;
    
if(hRcverCertContext == NULL) 
    

        CryptMsgClose(hMsg);
        CertCloseStore(hCertStore, CERT_CLOSE_STORE_FORCE_FLAG);
        CancelByError(L
"No matched certificate found in store."); 
    }
 

    viewCertCN(hRcverCertContext);

    
// 申请私钥服务
    HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hCryptProv = NULL;
    DWORD dwKeyType 
= 0;
    BOOL bFreeKeyProv 
= FALSE;
    
if(!CryptAcquireCertificatePrivateKey(hRcverCertContext, 00&hCryptProv, &dwKeyType, &bFreeKeyProv))
    
{
        CryptMsgClose(hMsg);
        CertFreeCertificateContext(hRcverCertContext);
        CertCloseStore(hCertStore, CERT_CLOSE_STORE_FORCE_FLAG);
        CancelByError(L
"Acquire certificate privateKey failed!\n");
    }


    
/* ------ 另外一种申请私钥服务的做法:沒验证
            bReturn = CertGetCertificateContextProperty( 
                        context, 
                        CERT_KEY_PROV_INFO_PROP_ID , 
                        NULL, 
                        &dwSize 
                        ); 
            if (!bReturn) 
            { 
                CancelByError(L"Failed in CertGetCertificateContextProperty."); 
            } 


            CRYPT_KEY_PROV_INFO * key_info = (CRYPT_KEY_PROV_INFO *) malloc (dwSize); 
            if (!key_info) 
                CancelByError(L"Not enough memory."); 
                     
            bReturn = CertGetCertificateContextProperty( 
                        context, 
                        CERT_KEY_PROV_INFO_PROP_ID , 
                        key_info, 
                        &dwSize 
                        ); 
            if (!bReturn) 
            { 
                CancelByError(L"Failed in CertGetCertificateContextProperty."); 
            } 

            // acquire a CSP 
            HCRYPTPROV hCryptProv; 

    bReturn = CryptAcquireContext(
        &hCryptProv,                // 返回的句柄
        NULL,                // CSP key 容器名称
        NULL,                // CSP 提供者名称
        PROV_RSA_FULL,        // CSP 提供者类型
        0);                    // 附加参数:

        bReturn = CryptAcquireContext( 
                        &hCryptProv, 
                        key_info->pwszContainerName, 
                        key_info->pwszProvName, 
                        key_info->dwProvType, 
                        key_info->dwFlags 
                        ); 
            if (!bReturn) 
            { 
                CancelByError(L"Failed in CryptAcquireContext."); 
            } 
*/


    
// 解密解码的数据
    CMSG_CTRL_DECRYPT_PARA para; 
    para.cbSize 
= sizeof (CMSG_CTRL_DECRYPT_PARA); 
    para.dwKeySpec 
= dwKeyType; 
    para.hCryptProv 
= hCryptProv; 
    para.dwRecipientIndex 
= 0
    
if(!CryptMsgControl( 
        hMsg,                
// Handle to the message 
        0,                    // Flags 
        CMSG_CTRL_DECRYPT,    // Control type 
        &para))                // Pointer to the CERT_INFO 
    {
        CryptMsgClose(hMsg);
        CertFreeCertificateContext(hRcverCertContext);
        CertCloseStore(hCertStore, CERT_CLOSE_STORE_FORCE_FLAG);
        CancelByError(L
"Failed in CryptMsgControl."); 
    }


    
// 获取解密消息大小
    CRYPT_DATA_BLOB sigBlob;
    memset(
&sigBlob, 0sizeof(sigBlob));
    
if(!CryptMsgGetParam( 
        hMsg,                
// Handle to the message 
        CMSG_CONTENT_PARAM, // Parameter type 
        0,                    // Index 
        NULL,                //
        &sigBlob.cbData))    // Size of the returned 
    {                    
        CryptMsgClose(hMsg);
        CertFreeCertificateContext(hRcverCertContext);
        CertCloseStore(hCertStore, CERT_CLOSE_STORE_FORCE_FLAG);
        CancelByError(L
"Failed in CryptMsgGetParam for CMSG_CONTENT_PARAM."); 
    }
 

    
// 分配内存
    sigBlob.pbData = (BYTE *new char[sigBlob.cbData];
    
if(sigBlob.pbData == NULL)
    
{
        CryptMsgClose(hMsg);
        CertFreeCertificateContext(hRcverCertContext);
        CertCloseStore(hCertStore, CERT_CLOSE_STORE_FORCE_FLAG);
        CancelByError(L
"Not enough memory."); 
    }


    
// 获取解码消息
    if(!CryptMsgGetParam( 
        hMsg,                
// Handle to the message 
        CMSG_CONTENT_PARAM, // Parameter type 
        0,                    // Index 
        sigBlob.pbData,        //
        &sigBlob.cbData))    // Size of the returned 
    {                    
        delete [] sigBlob.pbData;
        CryptMsgClose(hMsg);
        CertFreeCertificateContext(hRcverCertContext);
        CertCloseStore(hCertStore, CERT_CLOSE_STORE_FORCE_FLAG);
        CancelByError(L
"Failed in CryptMsgGetParam for CMSG_CONTENT_PARAM."); 
    }


    
// 清理解密过程数据
    CryptMsgClose(hMsg);
    CertFreeCertificateContext(hRcverCertContext);
    CertCloseStore(hCertStore, CERT_CLOSE_STORE_FORCE_FLAG);

    _tprintf(L
"Enveloped message decrypt successfully. \n"); 

    
// ----------------------------------- 解密处理完成:得到一个带原文的签名

    
// 解码带原文的数字签名
    hMsg = CryptMsgOpenToDecode( 
        MY_ENCODING_TYPE,    
// Encoding type. 
        0,                    // Flags. 
        0,                    // Use the default message type which is listed in the message header. 
        NULL,                // Cryptographic provider. Use NULL for the default provider. 
        NULL,                // Recipient information. 
        NULL);                // Stream information. 
    if(hMsg == NULL) 
    

        delete [] sigBlob.pbData;
        CancelByError(L
"Failed in CryptMsgOpenToDecode."); 
    }
 

    
// Update
    if(!CryptMsgUpdate( 
        hMsg,                
// Handle to the message 
        sigBlob.pbData,        // Pointer to the encoded BLOB 
        sigBlob.cbData,        // Size of the encoded BLOB 
        TRUE))
    
{
        delete [] sigBlob.pbData;
        CryptMsgClose(hMsg);
        CancelByError(L
"Failed in CryptMsgUpdate."); 
    }


    
// 释放数字签名数据
    delete [] sigBlob.pbData;

    
// 开始操作解码后的签名数据 ================================

    
// 获取原文字节数
    CRYPT_DATA_BLOB orgBlob;
    memset(
&orgBlob, 0sizeof(orgBlob));
    
if(!CryptMsgGetParam(
        hMsg,
        CMSG_CONTENT_PARAM,
        
0,
        NULL,
        
&orgBlob.cbData))
    
{
        CryptMsgClose(hMsg);
        CancelByError(L
"Get the decoded message failed. \n");
    }


    _tprintf(L
"%d bytes needed for the decoded message.\n", orgBlob.cbData);

    
// 分配内存
    orgBlob.pbData = (BYTE*new char[orgBlob.cbData];
    
if(orgBlob.pbData == NULL)
    
{
        CryptMsgClose(hMsg);
        CancelByError(L
"Not enough memory. \n");
    }


    
// 获取原文
    if(!CryptMsgGetParam(
        hMsg,
        CMSG_CONTENT_PARAM,
        
0,
        orgBlob.pbData,
        
&orgBlob.cbData))
    
{
        delete [] orgBlob.pbData;
        CryptMsgClose(hMsg);
        CancelByError(L
"Get the decoded message failed. \n");
    }


    showData(orgBlob.pbData, orgBlob.cbData);
    
if(orgFileName != NULL)
    
{
        writeFile(orgFileName, orgBlob.pbData, orgBlob.cbData);
    }


    
// 释放原文数据
    delete [] orgBlob.pbData;

    
// 获取签名者证书信息大小
    DWORD cbSignerCertInfo;
    
if(!CryptMsgGetParam(
        hMsg,                         
// handle to the message
        CMSG_CERT_PARAM,              // parameter type
        0,                            // index
        NULL,   
        
&cbSignerCertInfo))           // size of the returned 
    {
        CryptMsgClose(hMsg);
        CancelByError(L
"Get SIGNER_CERT_INFO #1 failed.");
    }


    
// 分配内存
    BYTE* pSignerCertInfo = (BYTE*new char[cbSignerCertInfo];
    
if(pSignerCertInfo == NULL)
    
{
        CryptMsgClose(hMsg);
        CancelByError(L
"Not enough memory."); 
    }


    
// 获取签名者证书信息
    if(!CryptMsgGetParam(
        hMsg,                            
// handle to the message
        CMSG_CERT_PARAM,                // parameter type
        0,                                // index
        pSignerCertInfo,   
        
&cbSignerCertInfo))                // size of the returned 
    {
        delete [] pSignerCertInfo;
        CryptMsgClose(hMsg);
        CancelByError(L
"Get SIGNER_CERT_INFO #1 failed.");
    }


    
// 创建证书上下文
    PCCERT_CONTEXT pSignerCertContext = NULL;
    pSignerCertContext 
= CertCreateCertificateContext(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, (BYTE*) pSignerCertInfo, cbSignerCertInfo);
    
if(pSignerCertContext == NULL)
    
{
        delete [] pSignerCertInfo;
        CryptMsgClose(hMsg);
        CancelByError(L
"Get Subject Cert failed. ");
    }


    viewCertCN(pSignerCertContext);

    
// 校验数字签名
    if(!CryptMsgControl(
        hMsg,
        
0,
        CMSG_CTRL_VERIFY_SIGNATURE,
        pSignerCertContext
->pCertInfo))
    
{
        delete [] pSignerCertInfo;
        CryptMsgClose(hMsg);
        CertFreeCertificateContext(pSignerCertContext);
        CancelByError(L
"Verify signature failed. \n");
    }


    _tprintf(L
"Verify signature succeeded. \n");

    
// 清理
    delete [] pSignerCertInfo;
    CryptMsgClose(hMsg);
    CertFreeCertificateContext(pSignerCertContext);
}


int _tmain(int argc, _TCHAR* argv[])
{
    
// HASH
//    hashSHA1((BYTE*)"123456789012345", 15, NULL, "c:\\li.sha1");
//    hashSHA1(NULL, 0, "c:\\li.txt", "c:\\li.sha1");

    
// Encrypt & Decrypt
//    DESEncrypt((BYTE*)"12345678", (BYTE*)"XXXXXXXX", (BYTE*)"123456789012345", 15, NULL, "c:\\li.des");
//    DESEncrypt((BYTE*)"12345678", (BYTE*)"XXXXXXXX", NULL, 0, "c:\\li.txt", "c:\\li.des");

//    AESEncrypt((BYTE*)"12345678901234561234567890123456", (BYTE*)"XXXXXXXXXXXXXXXX", (BYTE*)"123456789012345", 15, NULL, "c:\\li.aes");
//    AESEncrypt((BYTE*)"12345678901234561234567890123456", (BYTE*)"XXXXXXXXXXXXXXXX",  NULL, 0,  "c:\\1.txt", "c:\\li.aes");

//    BYTE* pEncData = (BYTE*) "\xCA\x89\x39\xC2\x2F\xB3\x4B\x39\x54\x2e\xd6\xb1\x14\xc9\x31\x10";
//    AESDecrypt((BYTE*)"12345678901234561234567890123456", (BYTE*)"XXXXXXXXXXXXXXXX", pEncData, 16, NULL, "c:\\li.org");
//    AESDecrypt((BYTE*)"12345678901234561234567890123456", (BYTE*)"XXXXXXXXXXXXXXXX", NULL, 0, "c:\\li.aes", "c:\\1.org");

    
// CertStore & Cert
//    viewSystemCertStore(L"MY");
//    viewSystemCertStore(L"CA");
//    viewSystemCertStore(L"ROOT");
//    viewCrtCertStore(L"c:\\ca\\certs\\lny.crt");
//    viewCrtCertStore(L"c:\\cfcaT.p7b");
//    viewPfxCertStore("c:\\ca\\lny.pfx", L"welcome2008");

    
// HASH SignData
//    BareSignData((BYTE*) "1234567890", 10, NULL, "c:\\li.sha1.sig");
//    VerifyBareSignData((BYTE*) "1234567890", 10, NULL, 0, NULL, "c:\\li.sha1.sig");
//    BareSignData(NULL, 0, "c:\\li.txt", "c:\\li.sha1.sig");
//    VerifyBareSignData(NULL, 0, NULL, 0, "c:\\li.txt", "c:\\li.sha1.sig");

    
// TACHED SignData
//    SignData((BYTE*)"1234567890", 10, NULL, FALSE, "c:\\li.tch.sig");
//    VerifySignedData("c:\\li.tch.sig");
//    SignData(NULL, 0, "c:\\li.txt", FALSE, "c:\\li.tch.sig");
//    VerifySignedData("c:\\1li.tch.sig", "c:\\li.txt.org");

    
// DETACHED SignData
//    SignData((BYTE*)"1234567890", 10, NULL, TRUE, "c:\\li.detch.sig");
//    VerifyDetachedSignData((BYTE*) "1234567890", 10, NULL, "c:\\li.detch.sig");
//    VerifyDetachedSignData(NULL, 0, "c:\\li.txt", "c:\\li.detch.sig");

    
// Cert Encrypt & Decrypt
//    CertEncrypt((BYTE*)"1234567890", 10, NULL, "c:\\li.enc");
//    CertEncrypt(NULL, 0, "c:\\li.txt", "c:\\li.enc");
//    CertDecrypt("c:\\li.enc", "c:\\li.org");

//    SignAndEncryptData((BYTE*)"1234567890", 10, NULL, "c:\\li.enc");
//    DecryptAndVerifyData("c:\\li.enc", "c:\\li.org");

    printf(
"========================================================================\n");

    
// Other cert Encrypt & Decrypt (低级消息函数)
//    EnvelopeData((BYTE*)"welcome2008WWWWW", 17, NULL, "c:\\li.enc");
    DevelopeData("c:\\li.enc""c:\\li.org");

    pause();
    
return 0;
}


posted on 2009-08-07 00:23 飞鹰 阅读(2821) 评论(2)  编辑  收藏 所属分类: C++

评论:
# re: MS CryptoAPI Samples[未登录] 2010-06-07 20:44 | 过客
很全很专业  回复  更多评论
  
# re: MS CryptoAPI Samples 2014-03-20 10:44 | daifei4321
代码已用,感谢。  回复  更多评论
  

只有注册用户登录后才能发表评论。


网站导航: