下面代码实现了调用CSP实现数据的签名和验签,函数中有些细节没有处理好,但总体流程上应该是没有问题的,测试通过:
//本程序通过调用CSP实现签名及验签功能 #include "stdafx.h" #include <windows.h> #include <wincrypt.h> #define IN #define OUT /***************************************************** *函数名:SignHash *功 能:对一段数据进行哈稀签名,并导出公钥 *入 参:IN BYTE* pData, //欲进行哈稀签名的数据 IN DWORD dwDataLen, //数据长度 *出 参:OUT BYTE** pSignature, //哈稀签名数据的地址,使用完后由调用者释放 OUT DWORD* dwSigLen, //签名实际长度 OUT BYTE** pPublicKey, //公钥数据的地址,使用完后由调用者释放 OUT DWORD* dwPubKeyLen);//公钥实际长度 *返回值:BOOL,TRU为签名成功,FALSE为签名失败 ******************************************************/ BOOL SignHash(IN BYTE* pData, IN DWORD dwDataLen, OUT BYTE** pSignature, OUT DWORD* dwSigLen, OUT BYTE** pPublicKey, OUT DWORD* dwPubKeyLen); /***************************************************** *函数名:VerifySignature *功 能:对一段数据进行签名验证 *入 参:IN BYTE* pData, //欲进行哈稀验证的数据 IN DWORD dwDataLen, //数据长度 IN BYTE* pSignature, //签名 IN DWORD dwSigLen, //签名长度 IN BYTE* pPublicKey, //公钥 IN DWORD dwPublicKeyLen);//公钥长度 *出 参:无 *返回值:BOOL,TRU为验证签名成功,FALSE为验证签名失败 ******************************************************/ BOOL VerifySignature(IN BYTE* pData, IN DWORD dwDataLen, IN BYTE* pSignature, IN DWORD dwSigLen, IN BYTE* pPublicKey, IN DWORD dwPublicKeyLen); int _tmain(int argc, CHAR* argv[]) { CHAR* pData = (CHAR*)"35704uoifhroqfoierfqqe7r89qre"; BYTE* pSignature = NULL; DWORD dwSigLen = 0; BYTE* pPublicKey = NULL; DWORD dwPublicKeyLen = 0; SignHash((BYTE*)pData, strlen(pData), &pSignature, &dwSigLen, &pPublicKey, &dwPublicKeyLen); printf("signature:%s, publickey:%s", pSignature, pPublicKey); VerifySignature((BYTE*)pData, strlen(pData), pSignature, dwSigLen, pPublicKey,dwPublicKeyLen); if(pPublicKey) free(pPublicKey); if(pSignature) free(pSignature); getchar(); return 0; } BOOL SignHash(IN BYTE* pData, IN DWORD dwDataLen, OUT BYTE** pSignature, OUT DWORD* dwSigLen, OUT BYTE** pPublicKey, OUT DWORD* dwPubKeyLen) { //一、获得一个CSP句柄 HCRYPTPROV hCryptProv; BOOL bRet = CryptAcquireContext( &hCryptProv, NULL, //密钥容器名,NULL表示使用默认容器 NULL, //CSP_NAME PROV_RSA_FULL, 0 ); if(!bRet) { bRet = CryptAcquireContext( &hCryptProv, NULL, //密钥容器名,NULL表示使用默认容器 NULL, //CSP_NAME PROV_RSA_FULL, CRYPT_NEWKEYSET //创建密钥容器 ); if(!bRet) { printf("CryptAcquireContext fail!"); return FALSE; } } //二,获取签名密钥 HCRYPTKEY hKey; bRet = CryptGetUserKey(hCryptProv,AT_SIGNATURE,&hKey); if(!bRet) { //获取失败,现在创建新的RSA密钥对。\n"); bRet = CryptGenKey(hCryptProv, 2, CRYPT_EXPORTABLE | 0X04000000, &hKey); if(!bRet) { printf("CryptGenKey fail!\n"); return FALSE; } } //三、导出公钥 if(CryptExportKey(hKey, NULL, PUBLICKEYBLOB, 0, NULL, dwPubKeyLen)) printf("we get the length of the public key.\n"); else printf("CryptExportKey erro.\n"); if(*pPublicKey = (BYTE*)malloc(*dwPubKeyLen)) printf("we get the memory.\n"); else printf("malloc erro.\n"); if(CryptExportKey(hKey, NULL, PUBLICKEYBLOB, 0, *pPublicKey,dwPubKeyLen)) printf("export the public key.\n"); else printf("CryptExportKeya error.\n"); //四、对数据进行哈稀签名 HCRYPTHASH hHash; if(CryptCreateHash(hCryptProv, CALG_SHA1, 0, 0, &hHash)) printf("CreateHash succeed.\n"); else printf("CreatHash error.\n"); if(CryptHashData(hHash, pData, dwDataLen, 0)) printf("HashData succeed.\n "); else printf("HashData error.\n"); //获取签名的长度 if(CryptSignHash(hHash, AT_SIGNATURE, NULL, 0, NULL, dwSigLen)) printf("Get the length of signature.\n"); else printf("CryptSignHash error.\n"); if(*pSignature = (BYTE*) malloc(*dwSigLen)) printf("get the memory.\n"); else printf("memory error.\n"); //签名 if(CryptSignHash(hHash, AT_SIGNATURE, NULL, 0, *pSignature, dwSigLen)) printf("signature succeed.\n"); else { printf("Signature error.\n"); return FALSE; } if(hKey) CryptDestroyKey(hKey); if(hHash) CryptDestroyHash(hHash); if(hCryptProv) CryptReleaseContext(hCryptProv, 0); return TRUE; } BOOL VerifySignature(IN BYTE* pData, IN DWORD dwDataLen, IN BYTE* pSignature, IN DWORD dwSigLen, IN BYTE* pPublicKey, IN DWORD dwPublicKeyLen) { //一、获得一个CSP句柄 HCRYPTPROV hCryptProv; BOOL bRet = CryptAcquireContext( &hCryptProv, NULL, //密钥容器名,NULL表示使用默认容器 NULL, //CSP_NAME PROV_RSA_FULL, 0 ); if(!bRet) { bRet = CryptAcquireContext( &hCryptProv, NULL, //密钥容器名,NULL表示使用默认容器 NULL, //CSP_NAME PROV_RSA_FULL, CRYPT_NEWKEYSET //创建密钥容器 ); if(!bRet) { printf("CryptAcquireContext fail!"); return FALSE; } } //二、导入公钥 HCRYPTKEY hPubKey; if(CryptImportKey(hCryptProv, pPublicKey, dwPublicKeyLen, 0, 0, &hPubKey)) printf("Import the key.\n"); else printf("erro"); //计算哈稀 HCRYPTHASH hHash; if(CryptCreateHash(hCryptProv, CALG_SHA1, 0, 0, &hHash)) printf("创建哈希对象成功 \n"); else printf("调用CryptCreateHash失败"); if(CryptHashData(hHash, pData, dwDataLen, 0)) printf("数据哈希完成.\n"); else printf("调用CryptHashData失败"); //验证哈稀签名 if(CryptVerifySignature(hHash, pSignature, dwSigLen, hPubKey, NULL, 0)) printf("验证签名成功。\n"); else printf("签名验证失败,签名无效"); if(hHash) CryptDestroyHash(hHash); if(hCryptProv) CryptReleaseContext(hCryptProv,0); return TRUE; }