本文由网上各类汇总····
加密与解密第二版 222 页查看 学习:
下面的实验顺序颠倒,便于复习```````````````````````````````````````````
实验9`````````````````````````````
CALG_AES_128 但是发现好像加密解密出来不对的感觉
#include "stdafx.h"
#include
#include
#include
#include
#include
#pragma comment (lib, "crypt32.lib")
using namespace std;
void cryptoAPI_encrypt(string text, unsigned char* pwd, unsigned char** encryptText, int &out_len)
{
HCRYPTPROV hCryptProv = NULL;
HCRYPTKEY hKey = 0;
HCRYPTHASH hHash = 0;
int dwLength = 0;
OSVERSIONINFOW VersionInformation = {sizeof(OSVERSIONINFOW)};
GetVersionExW(&VersionInformation);
LPCWSTR CSP_NAME = MS_ENH_RSA_AES_PROV_XP_W;
if ( VersionInformation.dwMajorVersion != 5 )
CSP_NAME = MS_ENH_RSA_AES_PROV_W;
if(!CryptAcquireContext(&hCryptProv,
NULL,
CSP_NAME,//CSP_NAME
PROV_RSA_AES,
CRYPT_VERIFYCONTEXT))
{
DWORD dwLastErr = GetLastError();
if(NTE_BAD_KEYSET == dwLastErr)
{
return;
}
else{
if(!CryptAcquireContext(&hCryptProv,
NULL,
CSP_NAME,
PROV_RSA_AES,
CRYPT_NEWKEYSET))
{
return;
}
}
}
if(!CryptCreateHash(hCryptProv, CALG_MD5, 0, 0, &hHash))
{
return;
}
BYTE *pPwd = pwd;
if(!CryptHashData(hHash, pPwd, 16, 0))
{
return;
}
//CRYPT_EXPORTABLE
if(!CryptDeriveKey(hCryptProv, CALG_AES_128, hHash,0x800000 , &hKey))//得到最后用来加密的密钥
{
return;
}
int len = text.length();
BYTE *pData ;
pData = (BYTE*)malloc(len*4);
memcpy(pData,text.c_str(),len);
DWORD dwLen = len;
if(!CryptEncrypt(hKey, NULL, true, 0, pData, &dwLen, len*4))
{
return;
}
cout <<"\n--------------------------\n" << endl << "cryptoAPI encrypt"<
实验8`````````````````````````````
DES加密解密
#include "stdafx.h"
#include
#include
#include
#pragma comment (lib, "crypt32.lib")
void main()
{
struct
{
BLOBHEADER hdr;
DWORD cbKeySize;
BYTE rgbKeyData[8];
} keyBlob;
keyBlob.hdr.bType = PLAINTEXTKEYBLOB;//The key is a session key.
keyBlob.hdr.bVersion = CUR_BLOB_VERSION;
keyBlob.hdr.reserved = 0;
keyBlob.hdr.aiKeyAlg = CALG_DES;
keyBlob.cbKeySize = 8;
BYTE Key[8] = {0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31};
BYTE Ciphertext[8];
CopyMemory(keyBlob.rgbKeyData, Key, keyBlob.cbKeySize);
BYTE pData[256] = {0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38};
DWORD dwDataLen = 8;
HCRYPTPROV hProv;
if (CryptAcquireContext(&hProv, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, 0))
{
HCRYPTKEY hKey;
if (CryptImportKey(hProv, (BYTE*)(&keyBlob), sizeof(keyBlob), 0, 0, &hKey))
{
DWORD dwMode = CRYPT_MODE_CBC;
CryptSetKeyParam(hKey, KP_MODE, (BYTE*)(&dwMode), 0);
CryptEncrypt(hKey, 0, TRUE, 0, pData, &dwDataLen, _countof(pData));
for (int i = 0; i != 8 /*dwDataLen*/; ++i)
{
_tprintf(_T("%02x "), pData[i]);
Ciphertext[i] = pData[i];
}
_tprintf(_T("\r\n"));
CryptDestroyKey(hKey);
}
CryptReleaseContext(hProv, 0);
}
if (CryptAcquireContext(&hProv, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, 0))
{
HCRYPTKEY hKey2;
if (CryptImportKey(hProv, (BYTE*)(&keyBlob), sizeof(keyBlob), 0, 0, &hKey2))
{
DWORD dwMode = CRYPT_MODE_CBC;
CryptSetKeyParam(hKey2, KP_MODE, (BYTE*)(&dwMode), 0);
CryptDecrypt(hKey2, 0, TRUE, 0, pData, &dwDataLen);
for (int i = 0; i != 8 /*dwDataLen*/; ++i)
{
_tprintf(_T("%02x "), pData[i]);
Ciphertext[i] = pData[i];
}
_tprintf(_T("\r\n"));
CryptDestroyKey(hKey2);
}
CryptReleaseContext(hProv, 0);
}
return ;
} // end main
实验7`````````````````````````````
/*
下面我们来看看如何哈希一个对话密钥,这个密钥可以用来对一个消息,文件进行加密。我们依旧从一个程序开始。
*/
#include "stdafx.h"
#include
#include
#include
#pragma comment (lib, "crypt32.lib")
#define MY_ENCODING_TYPE (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING)
void MyHandleError(LPTSTR psz)
{
_ftprintf(stderr, TEXT("An error occurred in the program. \n"));
_ftprintf(stderr, TEXT("%s\n"), psz);
_ftprintf(stderr, TEXT("Error number %x.\n"), GetLastError());
_ftprintf(stderr, TEXT("Program terminating. \n"));
exit(1);
} // End of MyHandleError.
void main()
{
//--------------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
// Declare variables.
HCRYPTPROV hCryptProv;
HCRYPTHASH hHash;
HCRYPTKEY hKey;
//--------------------------------------------------------------------
// Begin processing.
printf("Process beginning. Creating a session key. \n");
BYTE pData[11]="1234567890";
if(CryptAcquireContext( // 首先依旧是获取一个缺省的CSP句柄
&hCryptProv,
NULL,
NULL,
PROV_RSA_FULL,
0))
{
printf("CryptAcquireContext complete. \n");
}
else
{
MyHandleError(TEXT("Acquisition of context failed."));
}
if(CryptCreateHash( // 创建一个CALG_MD5算法的HASH对象,这个hash对象用的是MD5算法
hCryptProv, // 指定一个CSP句柄
CALG_MD5, // 指定算法
0,
0,
&hHash))
{
printf("An empty hash object has been created. \n");
}
else
{
MyHandleError(TEXT("Error during CryptBeginHash!\n"));
}
if(CryptGenKey( // 创建密钥
hCryptProv, // 传入一个CSP句柄
CALG_RC2, // 指明密钥身成所用算法
CRYPT_EXPORTABLE, // 说明密钥是可以导出到CSP,用于这个应用程序外的
&hKey))
{
printf("A random session key has been created. \n");
}
else
{
MyHandleError(TEXT("Error during CryptGenKey!\n"));
}
if(CryptHashSessionKey( //对生成的密钥进行hash
hHash,
hKey,
0))
{
printf("The session key has been hashed. \n");
}
else
{
MyHandleError(TEXT("Error during CryptHashSessionKey!\n"));
}
DWORD dwRead;
//在这里就可以添加代码,用生成的密钥进行加密
if(hHash)
{
if(!(CryptDestroyHash(hHash)))
MyHandleError(TEXT("Error during CryptDestroyHash"));
}
if(hKey)
{
if(!(CryptDestroyKey(hKey)))
MyHandleError(TEXT("Error during CryptDestroyKey"));
}
// Release the CSP.
if(hCryptProv)
{
if(!(CryptReleaseContext(hCryptProv,0)))
MyHandleError(TEXT("Error during CryptReleaseContext"));
}
printf("Create random session key completed without error. \n");
} // end main
实验6`````````````````````````````
/*
下面逐渐进入主题了,现在来讲讲是如何对数据进行Encoding and Decoding的。依旧是从一段程序中开始。
*/
#include "stdafx.h"
#include
#include
#include
#pragma comment (lib, "crypt32.lib")
#define MY_ENCODING_TYPE (X509_ASN_ENCODING | PKCS_7_ASN_ENCODING)
void MyHandleError(LPTSTR psz)
{
_ftprintf(stderr, TEXT("An error occurred in the program. \n"));
_ftprintf(stderr, TEXT("%s\n"), psz);
_ftprintf(stderr, TEXT("Error number %x.\n"), GetLastError());
_ftprintf(stderr, TEXT("Program terminating. \n"));
exit(1);
} // End of MyHandleError.
void main(void)
{
HCRYPTMSG hMsg; //指向一个消息句柄
BYTE* pbContent; //一个BYTE指针指向消息
DWORD cbContent; //消息长度
DWORD cbEncodedBlob; //ECODE的BLOB的大小
BYTE *pbEncodedBlob; //一个BYTE指针指向ENCODE BLOB
DWORD cbData = sizeof(DWORD); //数据大小
DWORD cbDecoded; //Decode内容大小
BYTE *pbDecoded; //指向Decode的指针
pbContent = (BYTE*)"Security is our only business";
cbContent = strlen((char *) pbContent)+1;
printf("The original message => %s\n",pbContent);
if(cbEncodedBlob = CryptMsgCalculateEncodedLength(
MY_ENCODING_TYPE, //指定Encode类型,在程序的开头已经预定义了,MY_ENCODING_TYPE 就是 PKCS_7_ASN_ENCODING | X509_ASN_ENCODING
0, //Flags
CMSG_DATA, // 定义了数据的类型,这里指定为BYTE型的字符串
NULL,
NULL,
cbContent)) // 内容的大小
//这里的的函数的作用是计算指定消息Encode所需要的最大的长度,通过计算,为一个BLOB分配内存空间。
{
printf("The length of the data has been calculated. \n");
}
else
{
MyHandleError(TEXT("Getting cbEncodedBlob length failed"));
}
//为encode blob分配内存空间
if(pbEncodedBlob = (BYTE *) malloc(cbEncodedBlob))
{
printf("Memory has been allocated for the signed message. \n");
}
else
{
MyHandleError(TEXT("Memory allocation failed"));
}
if(hMsg = CryptMsgOpenToEncode( //CryptMsgOpenToEncode为Encode,开一个消息
MY_ENCODING_TYPE, // Encode类型,文件开始有说明
0, // Flags
CMSG_DATA, // 指定Message的类型,CMSG_DATA说明类型没用到
NULL, // 现在没有到,为NULL
NULL, // 同上
NULL)) // 不是流加密,这个参数为NULL
{
printf("The message to be encoded has been opened. \n");
}
else
{
MyHandleError(TEXT("OpenToEncode failed"));
}
if(CryptMsgUpdate( // CryptMsgUpdate将数据加到消息中,可以通过循环,将数据一段段的加得到消息中
hMsg, // 一个小心句柄
pbContent, // 指向数据的指针
cbContent, // 数据的大小
TRUE)) // TRUE表明这个是最后一段数据,在开个消息的时候,如果CMSG_DETACHED_FLAG有使用到,这设为FALSE,否则为TRUE。
{
printf("Content has been added to the encoded message. \n");
}
else
{
MyHandleError(TEXT("MsgUpdate failed"));
}
if(CryptMsgGetParam( // CryptMsgGetParam是获取一个消息中的参数
hMsg, // 一个消息句柄
CMSG_BARE_CONTENT_PARAM, //指定要获取的参数的类型
0,
pbEncodedBlob, // 一个接受数据的内存地址
&cbEncodedBlob)) // BLOB的大小,即是上面接受的数据的大小
{
printf("Message encoded successfully. \nencoded");
printf("The message is %s.\n",(LPSTR)pbEncodedBlob);
}
else
{
MyHandleError(TEXT("MsgGetParam failed"));
}
//释放消息句柄
if(hMsg)
CryptMsgClose(hMsg);
//
if(hMsg = CryptMsgOpenToDecode( //开个Decode的小心句柄,参数和上面的Encode一样
MY_ENCODING_TYPE,
0,
CMSG_DATA,
NULL,
NULL,
NULL))
{
printf("The message to decode is open. \n");
}
else
{
MyHandleError(TEXT("OpenToDecode failed"));
}
//下面的过程和Encode类似,调用的函数和上面相同,只不过是过程逆向
printf("\nThe length of the encoded message is %d.\n\n",
cbEncodedBlob);
if(CryptMsgUpdate(
hMsg, // Handle to the message
pbEncodedBlob, // Pointer to the encoded BLOB
cbEncodedBlob, // Size of the encoded BLOB
TRUE)) // Last call
{
printf("The encoded BLOB has been added to the message. \n");
}
else
{
MyHandleError(TEXT("Decode MsgUpdate failed"));
}
if(CryptMsgGetParam( // CryptMsgGetParam的调用和上面有所不同,这里一共是调用两次,第一次的作用主要是得到消息的大小,第二次是得到消息所在的内存地址
hMsg, //消息句柄
CMSG_CONTENT_PARAM, // Parameter type
0,
NULL, // Address for returned
// information
&cbDecoded)) // Size of the returned
// information
{
printf("The decoded message size is %d. \n", cbDecoded);
}
else
{
MyHandleError(TEXT("Decode CMSG_CONTENT_PARAM failed"));
}
if(pbDecoded = (BYTE *) malloc(cbDecoded))
{
printf("Memory has been allocated for the decoded message.\n");
}
else
{
MyHandleError(TEXT("Decoding memory allocation failed."));
}
if(CryptMsgGetParam(
hMsg, // Handle to the message
CMSG_CONTENT_PARAM, // Parameter type
0, // Index
pbDecoded, // Address for returned
// information
&cbDecoded)) // Size of the returned
// information
{
printf("The message is %s.\n",(LPSTR)pbDecoded);
}
else
{
MyHandleError(TEXT("Decode CMSG_CONTENT_PARAM #2 failed"));
}
if(pbEncodedBlob)
free(pbEncodedBlob);
if(pbDecoded)
free(pbDecoded);
if(hMsg)
CryptMsgClose(hMsg);
printf("This program ran to completion without error. \n");
} // End of main
实验5`````````````````````````````
/*
当我们已经生成了一个密钥,我们下面要做的是如何保存,导出,导入一个对话密钥。将一个密钥保存起来,导出,保存到硬盘上。这样,这个密钥就可以在其它应用程序上使用,而不会随着生成密钥程序的关闭而丢失了。
下面这段程序就是用来演示如何保存,导出一个对话密钥的。
*/
#include "stdafx.h"
#include
#include
#include
#define MY_ENCODING_TYPE (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING)
void MyHandleError(LPTSTR psz)
{
_ftprintf(stderr, TEXT("An error occurred in the program. \n"));
_ftprintf(stderr, TEXT("%s\n"), psz);
_ftprintf(stderr, TEXT("Error number %x.\n"), GetLastError());
_ftprintf(stderr, TEXT("Program terminating. \n"));
exit(1);
} // End of MyHandleError.
void main(void)
{
//--------------------------------------------------------------------
// Declare and initialize variables.
HCRYPTPROV hProv; // CSP handle
HCRYPTKEY hSignKey; // Signature key pair handle
HCRYPTKEY hXchgKey; // Exchange key pair handle
HCRYPTKEY hKey; // Session key handle
BYTE *pbKeyBlob; // Pointer to a simple key BLOB
DWORD dwBlobLen; // The length of the key BLOB
//--------------------------------------------------------------------
// Acquire a cryptographic provider context handle.
if(CryptAcquireContext( // 获取一个缺省容器的CSP句柄
&hProv,
NULL,
NULL,
PROV_RSA_FULL,
0))
{
printf("The CSP has been acquired. \n");
}
else
{
MyHandleError(TEXT("Error during CryptAcquireContext."));
}
if(CryptGetUserKey( // CryptGetUserKey是获取一个密钥//句柄的函数,成功返回TRUE
hProv, //指定容器的CSP模块句柄
AT_SIGNATURE, //指定私钥的类型
&hSignKey)) //原来接收获取的密钥句柄
{
_tprintf(TEXT("A signature key is available.\n"));
}
else
{
_tprintf(TEXT("No signature key is available.\n"));
if(GetLastError() == NTE_NO_KEY) // NTE_NO_KEY意味着密钥不存在,下面就生成一个密钥
{
_tprintf(TEXT("The signature key does not exist.\n"));
_tprintf(TEXT("Create a signature key pair.\n"));
if(CryptGenKey( // CryptGenKey生成一个密钥
hProv, //指定CSP模块的句柄
AT_SIGNATURE, //对于公钥密码系统,生成一个私钥和一个公钥,这个参数指定了这个密钥是公钥,于是生成了一个密码对。如果不是公钥系统,则指定了密码算法,具体看MSDN。
0, //指定了生成密钥的类型,这个参数的说明挺多的,想获取更为详尽的资料请看MSDN。
&hSignKey))
{
_tprintf(TEXT("Created a signature key pair.\n"));
}
else
{
MyHandleError(TEXT("Error occurred creating a ")
TEXT("signature key.\n"));
}
}
else
{
MyHandleError(TEXT("An error other than NTE_NO_KEY ")
TEXT("getting a signature key.\n"));
}
} // End if.
//--------------------------------------------------------------------
if(CryptGetUserKey( // 获取一个AT_KEYEXCHANGE,类型的密钥句柄,保存在hXchgKey中
hProv,
AT_KEYEXCHANGE,
&hXchgKey))
{
printf("The key exchange key has been acquired. \n");
}
else
{
printf("Error during CryptGetUserKey exchange key.");
}
// Generate a session key.
if (CryptGenKey( //生成一个CRYPT_EXPORTABLE(可导出的),CALG_RC4(指定算法)的密钥,保存在hKey
hProv,
CALG_RC4,
CRYPT_EXPORTABLE,
&hKey))
{
printf("Original session key is created. \n");
}
else
{
MyHandleError(TEXT("ERROR -- CryptGenKey."));
}
if(CryptExportKey( // CryptExportKey导出一个密钥
hKey, // 将要导出的密钥的句柄
hXchgKey, //用户最终使用到的密钥的句柄
SIMPLEBLOB, // 指定BLOB的类型,SIMPLEBLOB说明是 用来导出对话密钥的
0, // 指定密钥的附加属性
NULL,
&dwBlobLen)) // 当时这个函数在这里的主要
//目的是得到这个BLOB的长度
{
printf("Size of the BLOB for the session key determined. \n");
}
else
{
MyHandleError(TEXT("Error computing BLOB length."));
}
if(pbKeyBlob = (BYTE*)malloc(dwBlobLen))
{
printf("Memory has been allocated for the BLOB. \n");
}
else
{
MyHandleError(TEXT("Out of memory. \n"));
}
if(CryptExportKey( //这是这个函数才是真正的导出密钥
hKey,
hXchgKey,
SIMPLEBLOB,
0,
pbKeyBlob,
&dwBlobLen))
{
printf("Contents have been written to the BLOB. \n");
}
else
{
MyHandleError(TEXT("Error during CryptExportKey."));
}
free(pbKeyBlob); //释放内存
// Destroy the session key.
if(hKey)
CryptDestroyKey(hKey);
// Destroy the signature key handle.
if(hSignKey)
CryptDestroyKey(hSignKey);
// Destroy the key exchange key handle.
if(hXchgKey)
CryptDestroyKey(hXchgKey);
// Release the provider handle.
if(hProv)
CryptReleaseContext(hProv, 0);
printf("The program ran to completion without error. \n");
}
实验4`````````````````````````````
/*
讲如何复制一个对话密钥,照例是从一个程序讲起,完成以下任务。获取一个CSP句柄,
创建一个对话密钥,复制密钥。改变密钥生成过程,随机填充一个缓冲区,销毁密钥句柄,释放CSP句柄
*/
#include "stdafx.h"
#include
#include
#include
#include
#include
#include
#define MY_ENCODING_TYPE (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING)
void MyHandleError(LPTSTR psz)
{
_ftprintf(stderr, TEXT("An error occurred in the program. \n"));
_ftprintf(stderr, TEXT("%s\n"), psz);
_ftprintf(stderr, TEXT("Error number %x.\n"), GetLastError());
_ftprintf(stderr, TEXT("Program terminating. \n"));
exit(1);
} // End of MyHandleError.
void GetConsoleInput(char* strInput,
int intMaxChars)
{
char ch;
char minChar = ' ';
minChar++;
ch = getch();
while (ch != '\r')
{
if (ch == '\b' && strlen(strInput) > 0)
{
strInput[strlen(strInput)-1] = '\0';
printf("\b \b");
}
else if (ch >= minChar && strlen(strInput) < intMaxChars)
{
strInput[strlen(strInput)+1] = '\0';
strInput[strlen(strInput)] = ch;
putch('*');
}
ch = getch();
}
putch('\n');
}
void main()
{
//-------------------------------------------------------------------
// Declare and initialize variables.
HCRYPTPROV hCryptProv; // CSP句柄
HCRYPTKEY hOriginalKey; // 源密钥句柄
HCRYPTKEY hDuplicateKey; // 复制后的密钥句柄
DWORD dwMode;
BYTE pbData[16];
printf("This program creates a session key and duplicates \n");
printf("that key. Next, parameters are added to the original \n");
printf("key. Finally, both keys are destroyed. \n\n");
if(CryptAcquireContext( // 获取CSP句柄,前面叙述过了,这里就不叙述了
&hCryptProv,
NULL,
NULL,
PROV_RSA_FULL,
0))
{
printf("CryptAcquireContext succeeded. \n");
}
else
{
MyHandleError(TEXT("Error during CryptAcquireContext!\n"));
}
//-------------------------------------------------------------------
if (CryptGenKey( // 生成一个CALG_RC4算法生成的密钥,保存在hOriginalKey中
hCryptProv,
CALG_RC4, // ALG_ID结构,指定生成这个密钥使用的算法
0,
&hOriginalKey))
{
printf("Original session key is created. \n");
}
else
{
MyHandleError(TEXT("ERROR - CryptGenKey."));
}
if (CryptDuplicateKey( // 复制密钥
hOriginalKey, // 源密钥
NULL, // 保留参数,必须为NULL
0, // 保留参数,必须为0
&hDuplicateKey)) // 副本密钥
{
printf("The session key has been duplicated. \n");
}
else
{
MyHandleError(TEXT("ERROR - CryptDuplicateKey"));
}
// 给源密钥设置附加参数
dwMode = CRYPT_MODE_ECB; //CRYPT_MODE_ECB是一个没有反馈的块加密模式
if(CryptSetKeyParam(
hOriginalKey,
KP_MODE, // KP_MODE指定密钥的某种属性被改变,
// 意味着改变的是加密模式
(BYTE*)&dwMode, // 指向一个已经被初始化的缓冲区
0))
{
printf("Key Parameters set. \n");
}
else
{
MyHandleError(TEXT("Error during CryptSetKeyParam."));
}
if(CryptGenRandom( // 随机填充一块缓冲区
hCryptProv, // CSP句柄
8, // 缓冲区大小
pbData)) // 缓冲区地址
{
printf("Random sequence generated. \n");
}
else
{
MyHandleError(TEXT("Error during CryptGenRandom."));
}
if(CryptSetKeyParam( //再次给密钥设置属性
hOriginalKey,
KP_IV, // KP_IV意味着,这个函数的第三个参数指向一个BYTE数组,数组大小为块大小/8。
pbData,
0))
{
printf("Parameter set with random sequence as "
"initialization vector. \n");
}
else
{
MyHandleError(TEXT("Error during CryptSetKeyParam."));
}
//-------------------------------------------------------------------
if (hOriginalKey) // 以下依次销毁,释放源密钥句柄,副本句柄,CSP句柄,
if (!CryptDestroyKey(hOriginalKey))
MyHandleError(TEXT("Failed CryptDestroyKey\n"));
if (hDuplicateKey)
if (!CryptDestroyKey(hDuplicateKey))
MyHandleError(TEXT("Failed CryptDestroyKey\n"));
if(hCryptProv)
if (!CryptReleaseContext(hCryptProv, 0))
MyHandleError(TEXT("Failed CryptReleaseContext\n"));
printf("\nThe program ran to completion without error. \n");
} // End of main.
实验3`````````````````````````````
/*任务一:调用CryptAcquireContext,获取一个缺省CSP和缺省密钥容器的句柄
任务二:用CryptCreateHash去创建一个空的哈希对象
任务三:用CryptHashData.哈希密码
任务四:调用CryptDeriveKey获取一个对话密钥
任务五:销毁密码和哈希后的数据
任务六:释放CSP
*/
#include "stdafx.h"
#include
#include
#include
#include
#include
#include
void MyHandleError(LPTSTR psz)
{
_ftprintf(stderr, TEXT("An error occurred in the program. \n"));
_ftprintf(stderr, TEXT("%s\n"), psz);
_ftprintf(stderr, TEXT("Error number %x.\n"), GetLastError());
_ftprintf(stderr, TEXT("Program terminating. \n"));
exit(1);
} // End of MyHandleError.
void GetConsoleInput(char* strInput,
int intMaxChars)
{
char ch;
char minChar = ' ';
minChar++;
ch = getch();
while (ch != '\r')
{
if (ch == '\b' && strlen(strInput) > 0)
{
strInput[strlen(strInput)-1] = '\0';
printf("\b \b");
}
else if (ch >= minChar && strlen(strInput) < intMaxChars)
{
strInput[strlen(strInput)+1] = '\0';
strInput[strlen(strInput)] = ch;
putch('*');
}
ch = getch();
}
putch('\n');
}
void main()
{
HCRYPTPROV hCryptProv; // 定义CSP句柄
HCRYPTKEY hKey; // 定义密钥句柄
HCRYPTHASH hHash; // 定义一个HASH对象的句柄
CHAR szPassword[512] = ""; // 定义512大小的字符数组,用来保存密码
DWORD dwLength; // 保存密码长度
fprintf(stderr,"Enter a password to be used to create a key:");
GetConsoleInput(szPassword, 512); // 获取密码,这个是自己写的函数,目的是在屏幕上显示的是*。
printf("The password has been stored.\n");
dwLength = strlen(szPassword);
if(CryptAcquireContext( //以下是获取一个缺省的PROV_RSA_FULL CSP 句柄
&hCryptProv,
NULL,
NULL,
PROV_RSA_FULL,
0))
{
printf("A context has been acquired. \n");
}
else
{
MyHandleError(TEXT("Error during CryptAcquireContext!"));
}
//--------------------------------------------------------------------
if(CryptCreateHash( // 调用CryptCreateHash创建一个HASH对象
hCryptProv, // 一个CSP句柄
CALG_MD5, // 确定哈希算法 8003h
0, //对于非密钥算法,这个参数一定是0,如果是密钥算法,那么这个参数就是密钥
0, // 保留参数,为0
&hHash)) // 一个哈希对象的指针
{
printf("An empty hash object has been created. \n");
}
else
{
MyHandleError(TEXT("Error during CryptCreateHash!"));
}
//--------------------------------------------------------------------
if(CryptHashData( // 调用CryptHashData哈希密码
hHash, // 哈希对象
(BYTE *)szPassword, // 指向缓冲区的地址
dwLength, // 密码长度
0))
{
printf("The password has been hashed. \n");
}
else
{
MyHandleError(TEXT("Error during CryptHashData!"));
}
//--------------------------------------------------------------------
if(CryptDeriveKey( //调用CryptDeriveKey获取对话密码
hCryptProv, // CSP句柄
CALG_RC2, // 6602h 一个ALG_ID结构,用来指定对称密钥生成的算法
hHash, // 哈希对象
CRYPT_EXPORTABLE, //指定生成密钥的类型,CRYPT_EXPORTABLE意味着这个程序生成的密钥可以被其它程序调用,而不是仅仅限于这个程序当中。但是它不能用于非对称密码中。
&hKey))
{
printf("The key has been derived. \n");
}
else
{
MyHandleError(TEXT("Error during CryptDeriveKey!"));
}
if(hHash) // 销毁哈希对象
{
if(!(CryptDestroyHash(hHash)))
MyHandleError(TEXT("Error during CryptDestroyHash"));
}
if(hKey) // 销毁密钥句柄
{
if(!(CryptDestroyKey(hKey)))
MyHandleError(TEXT("Error during CryptDestroyKey"));
}
if(hCryptProv) // 销毁CSP句柄
{
if(!(CryptReleaseContext(hCryptProv, 0)))
MyHandleError(TEXT("Error during CryptReleaseContext"));
}
printf("The program to derive a key completed without error. \n");
} // end main
实验2`````````````````````````````
/*这个程序演示了以下内容和几个函数。
一. 用CryptAcquireContext获取一个缺省容器的缺省CSP的句柄。如果缺省容器不存在,用CryptAcquireContext创建一个。
二. 用CryptGetProvParam获取CSP和容器的信息。
三. 用CryptContextAddRef增加CSP的引用计数器的数值。
四. 用CryptAcquireContext创建一个指定的容器
五. 用CryptAcquireContext删除一个容器
六. 用一个新创建的容器获取一个CSP的句柄。
*/
#include
#include "stdafx.h"
#include
#include
#include
void MyHandleError(LPTSTR psz)
{
_ftprintf(stderr, TEXT("An error occurred in the program. \n"));
_ftprintf(stderr, TEXT("%s\n"), psz);
_ftprintf(stderr, TEXT("Error number %x.\n"), GetLastError());
_ftprintf(stderr, TEXT("Program terminating. \n"));
exit(1);
} // End of MyHandleError.
void main(void)
{
HCRYPTPROV hCryptProv; //定义CSP句柄
if(CryptAcquireContext(
&hCryptProv,
NULL, //缺省容器
NULL, //缺省CSP
PROV_RSA_FULL,
0))
{
_tprintf(TEXT("CryptAcquireContext succeeded.\n"));
}
else
{
if (GetLastError() == NTE_BAD_KEYSET) //同样,如果当不存在这样的容器的时候,创建一个
{
if(CryptAcquireContext(
&hCryptProv,
NULL,
NULL,
PROV_RSA_FULL,
CRYPT_NEWKEYSET))
{
_tprintf(TEXT("CryptAcquireContext succeeded.\n"));
}
else
{
MyHandleError(TEXT("Could not create the default ")
TEXT("key container.\n"));
}
}
else
{
MyHandleError(TEXT("A general error running ")
TEXT("CryptAcquireContext."));
}
}
CHAR pszName[1000];
DWORD cbName;
cbName = 1000;
if(CryptGetProvParam(
hCryptProv, //CSP模块句柄
PP_NAME, //指定获取哪些信息,这里是指定获取CSP名字的信息
(BYTE*)pszName, //缓冲区接受信息返回值
&cbName,
0))
{
_tprintf(TEXT("CryptGetProvParam succeeded.\n"));
printf("Provider name: %s\n", pszName);
}
else
{
MyHandleError(TEXT("Error reading CSP name.\n"));
}
//---------------------------------------------------------------
// Read the name of the key container.
cbName = 1000;
if(CryptGetProvParam(
hCryptProv,
PP_CONTAINER, //获取容器名字
(BYTE*)pszName,
&cbName,
0))
{
_tprintf(TEXT("CryptGetProvParam succeeded.\n"));
printf("Key Container name: %s\n", pszName);
}
else
{
MyHandleError(TEXT("Error reading key container name.\n"));
}
//增加CSP的引用计数器的数值。
if(CryptContextAddRef( // CryptContextAddRef是向一个CSP的引用计数器增加一个值的函数
hCryptProv,
NULL, //保留值,必须为NULL
0)) //保留值,必须为0
{
_tprintf(TEXT("CryptcontextAddRef succeeded.\n"));
}
else
{
MyHandleError(TEXT("Error during CryptContextAddRef!\n"));
}
//---------------------------------------------------------------
// The reference count on hCryptProv is now greater than one.
// The first call to CryptReleaseContext will not release the
// provider handle.
//---------------------------------------------------------------
// Release the context once.
if (CryptReleaseContext(hCryptProv, 0)) // CryptReleaseContext是用来释放CSP句柄的,当这个函数调用一次的时候,CSP里面的引用计数就减少一,当引用计数减少的0的时候。CSP将不能再被这个程序中的任何函数调用了。
{
_tprintf(TEXT("The first call to CryptReleaseContext ")
TEXT("succeeded.\n"));
}
else
{
MyHandleError(TEXT("Error during ")
TEXT("CryptReleaseContext #1!\n"));
}
if (CryptReleaseContext(hCryptProv, 0)) //再次释放CSP模块
{
_tprintf(TEXT("The second call to CryptReleaseContext ")
TEXT("succeeded.\n"));
}
else
{
MyHandleError(TEXT("Error during ")
TEXT("CryptReleaseContext #2!\n"));
}
//下面是从PROV_RSA_FULL的CSP模块中创建一个自己的容器
LPCTSTR pszContainerName = TEXT("My Sample Key Container");
hCryptProv = NULL;
if(CryptAcquireContext(
&hCryptProv,
pszContainerName,
NULL,
PROV_RSA_FULL,
CRYPT_NEWKEYSET))
{
_tprintf(TEXT("CryptAcquireContext succeeded. \n"));
_tprintf(TEXT("New key set created. \n"));
//-----------------------------------------------------------
// Release the provider handle and the key container.
if(hCryptProv)
{
if(CryptReleaseContext(hCryptProv, 0))
{
hCryptProv = NULL;
_tprintf(TEXT("CryptReleaseContext succeeded. \n"));
}
else
{
MyHandleError(TEXT("Error during ")
TEXT("CryptReleaseContext!\n"));
}
}
}
else
{
if(GetLastError() == NTE_EXISTS)
{
_tprintf(TEXT("The named key container could not be ")
TEXT("created because it already exists.\n"));
}
else
{
MyHandleError(TEXT("Error during CryptAcquireContext ")
TEXT("for a new key container."));
}
}
if(CryptAcquireContext(
&hCryptProv,
pszContainerName,
NULL,
PROV_RSA_FULL,
0))
{
_tprintf(TEXT("Acquired the key set just created. \n"));
}
else
{
MyHandleError(TEXT("Error during CryptAcquireContext!\n"));
}
//---------------------------------------------------------------
// Perform cryptographic operations.
//---------------------------------------------------------------
if(CryptReleaseContext(
hCryptProv,
0))
{
_tprintf(TEXT("CryptReleaseContext succeeded. \n"));
}
else
{
MyHandleError(TEXT("Error during CryptReleaseContext!\n"));
}
if(CryptAcquireContext(
&hCryptProv,
pszContainerName,
NULL,
PROV_RSA_FULL,
CRYPT_DELETEKEYSET)) //CRYPT_DELETEKEYSET意味着CryptAcquireContex删除一个指定的容器
{
_tprintf(TEXT("Deleted the key container just created. \n"));
}
else
{
MyHandleError(TEXT("Error during CryptAcquireContext!\n"));
}
}
实验1`````````````````````````````
#include "stdafx.h"
#include
#include
#include
#include
/*
任务一:获取一个指定的密钥容器,如果这个容器不存在,创建一个。
任务二:如果容器中不存在一个签名密钥对,创建一个
任务三:如果容器中不存在一个交换密钥对,创建一个
*/
void MyHandleError(LPTSTR psz)
{
_ftprintf(stderr, TEXT("An error occurred in the program. \n"));
_ftprintf(stderr, TEXT("%s\n"), psz);
_ftprintf(stderr, TEXT("Error number %x.\n"), GetLastError());
_ftprintf(stderr, TEXT("Program terminating. \n"));
exit(1);
} // End of MyHandleError.
int _tmain(int argc, _TCHAR* argv[])
{
HCRYPTPROV hCryptProv; //定义一个CSP模块的句柄。“CSP模块,请查看《加密解密二》222页,那里有简单的说明,这里就不说了。
LPCTSTR pszContainerName = TEXT("My Sample Key Container");//用一个TEXT宏定义一个容器的名字,
if(CryptAcquireContext( //这个函数是获取有某个容器的CSP模块的指针,成功返回TRUE。
&hCryptProv, //指向一个CSP模块句柄指针,里面用指定的容器
pszContainerName, //指定容器的名称
NULL, //这个参数这里用的是缺省值,指得是缺省得CSP模块,你也可以传入一个LPCTSTR类型的字符串,指定CSP模块
PROV_RSA_FULL, //确定密钥的类型
0)) //常设为0,还有些其他的类型,请看MSDN
{
_tprintf(
TEXT("A crypto context with the %s key container ")
TEXT("has been acquired.\n"),
pszContainerName);
}
else
{
//不成功的处理段
if(GetLastError() == NTE_BAD_KEYSET)// NTE_BAD_KEYSET意味着密钥容器不存在,
//下面就去创建一个
//新的密钥容器
{
if(CryptAcquireContext(
&hCryptProv,
pszContainerName,
NULL,
PROV_RSA_FULL,
CRYPT_NEWKEYSET)) // CRYPT_NEWKEYSET意味着当指定容器不存在的时候,去创建一个容器。
{
_tprintf(TEXT("A new key container has been ")
TEXT("created.\n"));
}
else
{
MyHandleError(TEXT("Could not create a new key ")
TEXT("container.\n"));
}
}
else
{
MyHandleError(TEXT("CryptAcquireContext failed.\n"));
}
}
HCRYPTKEY hKey; //创建一个密钥句柄
if(CryptGetUserKey( // CryptGetUserKey是获取一个密钥//句柄的函数,成功返回TRUE
hCryptProv, //指定容器的CSP模块句柄
AT_SIGNATURE, //指定私钥的类型
&hKey)) //原来接收获取的密钥句柄
{
_tprintf(TEXT("A signature key is available.\n"));
}
else
{
_tprintf(TEXT("No signature key is available.\n"));
if(GetLastError() == NTE_NO_KEY) // NTE_NO_KEY意味着密钥不存在,下面就生成一个密钥
{
_tprintf(TEXT("The signature key does not exist.\n"));
_tprintf(TEXT("Create a signature key pair.\n"));
if(CryptGenKey( // CryptGenKey生成一个密钥
hCryptProv, //指定CSP模块的句柄
AT_SIGNATURE, //对于公钥密码系统,生成一个私钥和一个公钥,这个参数指定了这个密钥是公钥,于是生成了一个密码对。如果不是公钥系统,则指定了密码算法,具体看MSDN。
0, //指定了生成密钥的类型,这个参数的说明挺多的,想获取更为详尽的资料请看MSDN。
&hKey))
{
_tprintf(TEXT("Created a signature key pair.\n"));
}
else
{
MyHandleError(TEXT("Error occurred creating a ")
TEXT("signature key.\n"));
}
}
else
{
MyHandleError(TEXT("An error other than NTE_NO_KEY ")
TEXT("getting a signature key.\n"));
}
} // End if.
_tprintf(TEXT("A signature key pair existed, or one was ")
TEXT("created.\n\n"));
if(hKey) //将密钥句柄销毁
{
if(!(CryptDestroyKey(hKey)))
{
MyHandleError(TEXT("Error during CryptDestroyKey."));
}
hKey = NULL;
}
//下面这部分和上面是类似的,只不过密钥类型不相同而已。
if(CryptGetUserKey(
hCryptProv,
AT_KEYEXCHANGE,
&hKey))
{
_tprintf(TEXT("An exchange key exists.\n"));
}
else
{
_tprintf(TEXT("No exchange key is available.\n"));
// Check to determine whether an exchange key
// needs to be created.
if(GetLastError() == NTE_NO_KEY)
{
// Create a key exchange key pair.
_tprintf(TEXT("The exchange key does not exist.\n"));
_tprintf(TEXT("Attempting to create an exchange key ")
TEXT("pair.\n"));
if(CryptGenKey(
hCryptProv,
AT_KEYEXCHANGE,
0,
&hKey))
{
_tprintf(TEXT("Exchange key pair created.\n"));
}
else
{
MyHandleError(TEXT("Error occurred attempting to ")
TEXT("create an exchange key.\n"));
}
}
else
{
MyHandleError(TEXT("An error other than NTE_NO_KEY ")
TEXT("occurred.\n"));
}
}
// Destroy the exchange key.
if(hKey)
{
if(!(CryptDestroyKey(hKey)))
{
MyHandleError(TEXT("Error during CryptDestroyKey."));
}
hKey = NULL;
}
// Release the CSP.
if(hCryptProv)
{
if(!(CryptReleaseContext(hCryptProv, 0)))
{
MyHandleError(TEXT("Error during CryptReleaseContext."));
}
}
_tprintf(TEXT("Everything is okay. A signature key "));
_tprintf(TEXT("pair and an exchange key exist in "));
_tprintf(TEXT("the %s key container.\n"), pszContainerName);
return 0;
}
转载至: http://bbs.pediy.com/showthread.php?t=31357&highlight=Crypto+API