密钥(Cryptographic key)是一个基于RSA公匙加密体系的邮件加密软件。它能对你的邮件加上数字签名从而使收信人可以确信邮件是你发来的。它让你可以安全地和你从未见过的人们通讯,事先并不需要任何保密的渠道用来传递密匙。它采用了:审慎的密匙管理,一种RSA和传统加密的杂合算法,用于数字签名的邮件文摘算法,加密前压缩等,还有一个良好的人机工程设计。它的功能强大,有很快的速度。密钥(Cryptographic key)是用在加密和解密过程的会话(均衡)密钥和用在认证过程中公共密钥和私有密钥。在这三种密钥中,会话密钥和私有密钥必须一直保密。(
PGP加密系统是采用公开密钥加密与传统密钥加密相结合的一种加密技术。它使用一对数学上相关的钥匙,其中一个(公钥)用来加密信息,另一个(私钥)用来解密信息。 PGP采用的传统加密技术部分所使用的密钥称为“会话密钥”(sek)。每次使用时,PGP都随机产生一个128位的IDEA会话密钥,用来加密报文。公开密钥加密技术中的公钥和私钥则用来加密会话密钥,并通过它间接地保护报文内容。 PGP中的每个公钥和私钥都伴随着一个密钥证书。它一般包含以下内容: 密钥内容(用长达百位的大数字表示的密钥) 密钥类型(表示该密钥为公钥还是私钥) 密钥长度(密钥的长度,以二进制位表示) 密钥编号(用以唯一标识该密钥) 创建时间 用户标识 (密钥创建人的信息,如姓名、电子邮件等) 密钥指纹(为128位的数字,是密钥内容的提要表示密钥唯一的特征) 中介人签名(中介人的数字签名,声明该密钥及其所有者的真实性,包括中介人的密钥编号和标识信息) PGP把公钥和私钥存放在密钥环(KEYR)文件中。PGP提供有效的算法查找用户需要的密钥。 PGP在多处需要用到口令,它主要起到保护私钥的作用。由于私钥太长且无规律,所以难以记忆。PGP把它用口令加密后存入密钥环,这样用户可以用易记的口令间接使用私钥。 PGP的每个私钥都由一个相应的口令加密。PGP主要在3处需要用户输入口令: 需要解开受到的加密信息时,PGP需要用户输入口令,取出私钥解密信息 当用户需要为文件或信息签字时,用户输入口令,取出私钥加密 对磁盘上的文件进行传统加密时,需要用户输入口令
我们来用VC++实现导出会话密钥例子程序,请见代码实现与注释讲解
#include <stdio.h>
#include <windows.h>
#include <wincrypt.h>
#define MY_ENCODING_TYPE (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING)
HCRYPTPROV GetCryptProv();
void HandleError(char *s);
void main(void)
{
//--------------------------------------------------------------------
// 变量申明与初始化
HCRYPTPROV hProv; // CSP句柄
HCRYPTKEY hXchgKey; // 交换密钥对句柄
HCRYPTKEY hKey; // 会话密钥句柄
BYTE *pbKeyBlob; // 简单密钥块指针
DWORD dwBlobLen; // 密钥块长度
//--------------------------------------------------------------------
//获取加密服务者句柄
hProv = GetCryptProv();
//--------------------------------------------------------------------
// 创建交换密钥
if(CryptGenKey(
hProv,
AT_KEYEXCHANGE,
0,
&hXchgKey))
{
printf("交换密钥已被创建.\n");
}
else
{
HandleError("在试图创建交换密钥时发生错误.\n");
}
//--------------------------------------------------------------------
// 创建会话密钥.
if (CryptGenKey(
hProv,
CALG_RC4,
CRYPT_EXPORTABLE,
&hKey))
{
printf("原会话密钥被创建. \n");
}
else
{
HandleError("ERROR -- CryptGenKey.");
}
// 确定密钥数据块的长度.
if(CryptExportKey(
hKey, //待导出的密钥
hXchgKey, //密钥数据块用此密钥加密
SIMPLEBLOB,
0,
NULL, //密钥块,为空时用于返回密钥块的长度
&dwBlobLen)) //密钥块数据长度
{
printf("此会话密钥数据块长度已确定. \n");
}
else
{
HandleError("计算密钥数据块长度出错.");
}
if(pbKeyBlob = (BYTE*)malloc(dwBlobLen))
{
printf("已经为此数据块分配了内存空间. \n");
}
else
{
HandleError("所需内存不够. \n");
}
//--------------------------------------------------------------------
// 导出密钥到简单密钥数据块
if(CryptExportKey(
hKey, //待导出的密钥
hXchgKey, //密钥数据块用此密钥加密
SIMPLEBLOB, //导出的密钥块类型
0,
pbKeyBlob, //密钥块
&dwBlobLen)) //密钥块数据长度
{
printf("待导出密钥的内容已经被写入此数据块. \n");
}
else
{
HandleError("Error during CryptExportKey.");
}
//--------------------------------------------------------------------
// 从CSP导出密钥到密钥数据块后,可以通过一些其他处理来保存密钥块,
// 比如把密钥数据块写到文件中.
//--------------------------------------------------------------------
// 释放密钥数据块内存.
free(pbKeyBlob);
// 销毁会话密钥.
if(hKey)
CryptDestroyKey(hKey);
// 销毁交换密钥对
if(hXchgKey)
CryptDestroyKey(hXchgKey);
// 释放CSP句柄
if(hProv)
CryptReleaseContext(hProv, 0);
printf("此程序运行完成无错. \n");
}// End of main
//获取加密提供者句柄
HCRYPTPROV GetCryptProv()
{
HCRYPTPROV hCryptProv; // 加密服务提供者句柄
//获取加密提供者句柄
if(CryptAcquireContext(
&hCryptProv, // 加密服务提供者句柄
NULL, // 密钥容器名,这里使用登陆用户名
MS_ENHANCED_PROV, // 加密服务提供者
PROV_RSA_FULL, // 加密服务提供者类型,可以提供加密和签名等功能
0)) // 标志
{
printf("加密服务提供者句柄获取成功!\n");
}
else
{
//重新建立一个新的密钥集
if(!CryptAcquireContext(&hCryptProv, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, CRYPT_NEWKEYSET))
{
HandleError("重新建立一个新的密钥集出错!");
}
}
return hCryptProv;
}
// HandleError:错误处理函数,打印错误信息,并退出程序
void HandleError(char *s)
{
printf("程序执行发生错误!\n");
printf("%s\n",s);
printf("错误代码为: %x.\n",GetLastError());
printf("程序终止执行!\n");
exit(1);
}