`

Microsoft CryptoAPI加密技术(二)

阅读更多
上次我们讲了Microsoft CryptoAPI的构成以及会话密钥的使用。接下来我们将看一下公私密钥对的使用、HASH算法、数字签名等技术。

一、 公用密钥加密技术

公用密钥加密技术使用两个不同的密钥:公钥和私钥。私钥必须安全的保管好不能被外人知道,而公钥可以告诉任何人,只要他需要。通常公钥是以数字证书的形式发布的。
用公私密钥对中的一个密钥加密的数据只能用密钥对中的另一个密钥才能解密。也就是说用用户A的公钥加密的数据只能用A的私钥才能解密,同样,用A的私钥加密的数据只能用A的公钥才能解密。
如果用私钥签名一个消息,那么必须用与之对应的公钥去验证签名的有效性。
不幸的是公用密钥加密技术的效率非常低甚至只有对称加密的千分之一,所以不适合对大量的数据进行加密。实际上,公用密钥加密技术一般用来加密会话密钥,而数据加密可以用对称加密的方法。
好了,让我们回到Microsoft CryptoAPI。我们知道一个CSP有一个密钥库,这个密钥库有一个或多个密钥容器。而密钥容器中有什么呢?一般来说,一个密钥容器中有两对公私密钥对,一对用来加密会话密钥,而另一对用来进行数字签名,也就是大家知道的key exchange key pair和signature key pair。

那么,怎么得到这些密钥对呢?

if(CryptGetUserKey(
   hCryptProv,                     // 我们已经得到的CSP句柄
   AT_SIGNATURE,                   // 这里想得到signature key pair
   &hKey))                         // 返回密钥句柄
{
    printf("A signature key is available.\n");
}
else //取signature key pair错误
{
    printf("No signature key is available.\n");
    if(GetLastError() == NTE_NO_KEY) //密钥容器里不存在signature key pair
    {
       // 创建 signature key pair.
       printf("The signature key does not exist.\n");
       printf("Create a signature key pair.\n");
       if(CryptGenKey(
          hCryptProv, //CSP句柄
          AT_SIGNATURE, //创建的密钥对类型为signature key pair
          0, //key类型,这里用默认值
          &hKey)) //创建成功返回新创建的密钥对的句柄
       {
          printf("Created a signature key pair.\n");
       }
       else
       {
          printf ("Error occurred creating a signature key.\n");
       }
    }
    else
    {
        printf ("An error other than NTE_NO_KEY getting signature\key.\n");
    }
} // end if

将参数AT_SIGNATURE换成AT_KEYEXCHANGE就可以得到key exchange key pair。
现在我们得到的仅仅是一个句柄,我们需要把这个key值存储的磁盘或文件中,这样才能传给对方来进行解密。下面让我们来看一个用于导出密钥的API。
BOOL WINAPI CryptExportKey(
  HCRYPTKEY hKey,
  HCRYPTKEY hExpKey,
  DWORD dwBlobType,
  DWORD dwFlags,
  BYTE* pbData,
  DWORD* pdwDataLen
);

hKey:需要被导出的密钥句柄

hExpKey:前面咱们提到公用密钥加密技术的效率非常低所以公用密钥加密技术
一般用来加密会话密钥。这里传入的密钥就是用来加密被导出的密钥
的。也就是说,被导出的密钥hKey的数据是经过这个密钥hExpKey
加密的。如果为NULL表示不经过加密直接导出。

dwBlobType:被导出的密钥类型,比如公钥还是私钥等

dwFlags:标志位

pbData:保存导出的数据,如果为NULL, pdwDataLen将返回导出数据的长度

pdwDataLen:输入pbData缓冲区的大小,输出导出数据的长度
下面的例子演示如何导出密钥。

if(CryptExportKey(  
   hKey,   
   NULL,   
   PUBLICKEYBLOB, //导出公钥
   0,   
   NULL,
   &dwBlobLen)) //返回密钥数据长度
{
     printf("Size of the BLOB for the public key determined. \n");
}
else
{
     printf("Error computing BLOB length.\n");
     exit(1);
}
//--------------------------------------------------------------------
// Allocate memory for the pbKeyBlob.

if(pbKeyBlob = (BYTE*)malloc(dwBlobLen))
{
    printf("Memory has been allocated for the BLOB. \n");
}
else
{
    printf("Out of memory. \n");
    exit(1);
}
//--------------------------------------------------------------------
// Do the actual exporting into the key BLOB.

if(CryptExportKey(  
   hKey,
   NULL,   
   PUBLICKEYBLOB,   
   0,   
   pbKeyBlob,    //返回密钥数据
   &dwBlobLen)) //导出的密钥数据的长度
{
     printf("Contents have been written to the BLOB. \n");
}
else
{
    printf("Error exporting key.\n");
    exit(1);
}

如果要导出用公用密钥加密技术加密的密钥,只要把API的第二个参数传入一个key exchange key pair句柄就可以了。
既然有了导出当然要有导入。

BOOL WINAPI CryptImportKey(
  HCRYPTPROV hProv, //CSP句柄
  BYTE* pbData, //要导入的密钥数据
  DWORD dwDataLen, //数据长度
  HCRYPTKEY hPubKey, //如果数据是被加密的这里输入解密用的密钥句柄
  DWORD dwFlags, //标志位
  HCRYPTKEY* phKey //导入后返回的密钥句柄
);

这个API比较简单,这里就不举例说明了,在以后的例子里会看到。
二、 HASH

Hash简单点讲就是把任意一段数据经过某种算法生成一段唯一的固定长度的数据。也叫做摘要。为了确保数据A免受意外或者故意(恶意)的修改,往往用这段数据A产生一个hash数据一起发送出去,接收方可以通过相同的hash算法用这段接收到的数据A产生一个新的hash数据并与接收到的hash数据比较,来验证数据A是否为真实完整的数据。

下面的API用来创建hash对象

BOOL WINAPI CryptCreateHash(
  HCRYPTPROV hProv, //CSP句柄
  ALG_ID Algid, //选择hash算法,比如CALG_MD5等
  HCRYPTKEY hKey, //HMAC 和MAC算法时有用
  DWORD dwFlags, //保留,传入0即可
  HCRYPTHASH* phHash //返回hash句柄
);

if(CryptCreateHash(
   hCryptProv,
   CALG_MD5,
   0,
   0,
   &hHash))
{
    printf("An empty hash object has been created. \n");
}
else
{
    printf("Error during CryptBeginHash!\n");
    exit(1);
}

// Insert code that uses the hash object here.

//--------------------------------------------------------------------
// After processing, hHash must be released.

if(hHash)
   CryptDestroyHash(hHash); //释放句柄

我们已经得到hash对象了,下面就找点数据试试,咱也去哈一下,当然这里可不是哈日哈韩的哈,更不是哈巴狗的哈,嘿嘿。Let’s go!!
哎呀!!不好意思,忘记了介绍一个API,看看先。
BOOL WINAPI CryptHashData(
  HCRYPTHASH hHash, //hash对象
  BYTE* pbData, //被hash的数据
  DWORD dwDataLen, //数据的长度
  DWORD dwFlags //微软的CSP这个值会被忽略
);

下面代码:BYTE *pbBuffer= (BYTE *)"The data that is to be hashed.";
DWORD dwBufferLen = strlen((char *)pbBuffer)+1;

if(CryptHashData(
   hHash,
   pbBuffer,
   dwBufferLen,
   0))
{
     printf("The data buffer has been added to the hash.\n");
}
else
{
     printf("Error during CryptHashData.\n");
     exit(1);
}


现在,pbBuffer里的内容已经被hash了,然后我们需要导出哈希后的数据。BYTE         *pbHash;
BYTE         *pbHashSize;
DWORD        dwHashLen = sizeof(DWORD);
DWORD        i;

if(!(pbHashSize =(BYTE *) malloc(dwHashLen)))
MyHandleError("Memory allocation failed.");

//下面的这次调用我没搞清楚:( 我怎么觉得没有必要!!
if(CryptGetHashParam(
   hHash,
   HP_HASHSIZE, //取hash数据的大小
   pbHashSize, //输出hash数据大小的缓冲区
   &dwHashLen, //缓冲区大小
   0))
{
// It worked. Free pbHashSize.
   free(pbHashSize);
}
else
{
    MyHandleError("CryptGetHashParam failed to get size.");
}

if(CryptGetHashParam(
   hHash,
   HP_HASHVAL, //取hash值
   NULL, //设为NULL,在dwHashLen返回需要的输出缓冲区大小
   &dwHashLen, //输出缓冲区大小
   0))
{
// It worked. Do nothing.
}
else
{
    MyHandleError("CryptGetHashParam failed to get length.");
}

if(pbHash = (BYTE*)malloc(dwHashLen))
{
// It worked. Do nothing.
}
else
{
     MyHandleError("Allocation failed.");
}

if(CryptGetHashParam(
   hHash,
   HP_HASHVAL, //取hash值
   pbHash, //返回Hash数据
   &dwHashLen, //hash数据长度
   0))
{
// Print the hash value.
printf("The hash is:  ");
   for(i = 0 ; i < dwHashLen ; i++)
   {
       printf("%2.2x ",pbHash[i]);
   }
printf("\n");
}
else
{
    MyHandleError("Error during reading hash value.");
}
free(pbHash);


三、 数字签名

发布一个纯文本形式信息时,接收者可以用数字签名来鉴别和验证信息的发送者。对信息签名并不改变这个信息,只是生成一个数字签名串随信息一起传送,或单独传送。
一个数字签名,就是一段被用发送者的私钥加密的数据段,而接收者只有拥有发送者的公钥才能解密这个数据段。表示如下:

由Message生成数字签名有两步。首先,对Message进行hash处理,产生hash数据。然后用签名者A的私钥对这个hash数据加密。具体如下:


验证一个签名需要上图表示的Message和Digital signatures。首先跟生成时一样对Message进行hash处理,产生hash数据。然后通过签名者A的公钥、Digital signatures以及刚生成的hash数据进行验证。具体如下:


好了,你是否学会数字签名了呢?很多技术名词听起来很唬人,其实本来是很简单的!!嘿嘿。
随文档的例程几乎将用到我们上面讲的所有内容。
分享到:
评论

相关推荐

    Microsoft CryptoAPI加密技术 源代码.zip

    Microsoft CryptoAPI(加密应用程序接口)是Windows操作系统内核的一部分,它为开发者提供了一种标准的方式来实现各种加密和安全相关的操作。这个压缩包包含了与CryptoAPI相关的源代码,可以帮助我们深入理解其工作...

    Microsoft CryptoAPI加密技术

    在这个信息爆炸的时代,我们不得不对信息的安全提高警惕。加密作为保障数据信息安全的一种方式,越来越受到人们的关注。...我将把自己对Microsoft CryptoAPI的一些肤浅的理解与大家共享,有什么不妥之处望不吝赐教。

    信息安全实验:利用Windows CryptoAPI开发加解密工具软件

    CryptoAPI是微软提供的一个强大的接口,它允许开发者在Windows系统中实现各种复杂的密码学操作,包括对称加密、非对称加密以及数字签名等。 首先,我们要理解对称加密的概念。对称加密是加密技术中最基础的一种,它...

    crypto_cryptoapi.rar_CRYPTO_Crypto++_cryptoAPI

    本文将深入探讨标题为“crypto_cryptoapi.rar_CRYPTO_Crypto++_cryptoAPI”的主题,该主题涉及到一个用C++编写的加密库,用于封装微软的CryptoAPI(Cryptographic Application Programming Interface)。这个压缩包...

    信息安全实验:利用Windows CryptoAPI开发加解密工具软件2

    Windows CryptoAPI(Cryptographic Application Programming Interface)是微软提供的一套强大的加密服务,允许开发者在Windows操作系统上实现安全的加密算法和密码学操作。在这个实验中,我们将深入探讨如何利用...

    aaa.zip.zip_cryptoAPI_www.aaa.chm_zip

    《深入理解CryptoAPI:微软加密技术的基石》 在信息技术领域,数据安全是至关重要的,尤其是在网络通信中。Microsoft CryptoAPI(加密应用程序编程接口)是一个强大的工具,它为开发者提供了在Windows操作系统上...

    基于CryptoAPI 实现基于本地证书的签名实例

    CryptoAPI是微软提供的一套用于加密、解密、哈希计算和数字签名等安全操作的底层接口,它简化了开发人员处理这些复杂任务的过程。 首先,我们需要理解本地证书。在Windows系统中,本地证书存储于用户的个人证书存储...

    CryptoAPI2_Encrypt_zip_

    【标题】"CryptoAPI2_Encrypt_zip_" 涉及的是使用CryptoAPI(加密应用程序编程接口)对ZIP文件进行加密的技术。CryptoAPI是Windows操作系统提供的一组服务,用于实现密码学功能,包括加密、解密、哈希和数字签名等。...

    MFC-CryptoAPI-文件传输

    **MFC-CryptoAPI-文件传输** ...总的来说,MFC-CryptoAPI文件传输项目是一个结合了GUI编程、网络编程、加密解密等多方面技术的实践,对于深入理解这些技术以及提升软件安全性的实践有着重要的学习价值。

    cryptoapi.rar

    加密API(CryptoAPI)是微软开发的一套用于在Windows操作系统中实现加密功能的接口,它为应用程序提供了统一的方式来处理加密、解密、数字签名以及证书管理等任务。OpenSSL则是一个开源的库,包含了各种加密算法、...

    CryptoAPI生成随机数实例代码

    在IT领域,安全性和随机性是至关重要的因素,特别是在加密技术中。`CryptoAPI`是微软为Windows操作系统提供的一套应用程序编程接口(API),它允许开发者实现各种安全功能,包括密钥生成、数字签名和随机数生成。在...

    wincrypt.h的delphi声明 CryptoAPI

    《深入理解CryptoAPI:Delphi中的加密技术应用》 在计算机科学领域,特别是在信息安全和密码学中,CryptoAPI(加密应用程序编程接口)扮演着至关重要的角色。它是由微软开发的一套用于实现各种加密操作的系统级接口...

    Encrypting and decrypting sensitive data using CryptoAPI. (6

    CryptoAPI是微软提供的一组接口,它允许程序员实现安全的加密算法,如RSA、DES、3DES、AES等,以保护数据的安全性。 在实际应用中,加密敏感数据通常是必要的,比如存储用户密码、个人隐私信息或商业机密。Crypto...

    C++利用Crypto对字符串的加密

    在IT行业中,加密技术是确保数据安全的重要手段。在C++编程环境中,我们可以利用Windows API中的CryptoAPI(也称为Crypto)来实现字符串的加密。本文将深入探讨如何在Visual Studio 2005环境下,使用C++和CryptoAPI...

    CryproApi RSA

    总结,CryptoAPI RSA是Windows平台上实现RSA加密技术的重要工具,它为开发者提供了便捷的接口,用于构建安全的应用程序。结合2048位的密钥长度,可以确保数据在传输和存储过程中的安全性。理解和掌握CryptoAPI RSA的...

    Windows API CryptAPI函数库

    这个框架简化了密码学算法的使用,使得开发者无需深入理解底层的加密细节,就可以利用标准的加密技术进行程序开发。CryptoAPI支持多种加密算法,包括对称加密(如DES、3DES、AES)、非对称加密(RSA、DSA)、哈希...

    crypto加密解密

    5. **CryptoAPI**: CryptoAPI是微软Windows操作系统提供的一套接口,用于实现各种密码学功能,包括加密、解密、数字签名、哈希计算等。它简化了开发人员使用复杂的密码学算法的难度。虽然这里没有具体的CryptoAPI...

    FreeOTFE文档

    FreeOTFE 磁盘加密技术能够实现对文件特定位置进行解密,也能够对光盘中的每一个字节进行加密,克服了... 本文档主要介绍了FreeOTFE 磁盘加密技术及FreeOTFE的安装于使用,另外还介绍了Microsoft CryptoAPI加密技术。

    Ccryptoapi教程

    CryptoAPI(Cryptographic Application Programming Interface)是微软为Windows操作系统提供的一组接口,用于处理加密、签名、哈希等安全相关的任务。这个教程将深入讲解CryptoAPI的基本概念、核心功能以及如何在...

    WindowsCryptoAPI和密码学API:Delphi的下一代.zip

    在Windows操作系统中,Windows CryptoAPI(也称为CryptoAPI)是一个重要的组件,用于处理加密、解密、数字签名和哈希等安全操作。这个压缩包文件"WindowsCryptoAPI和密码学API:Delphi的下一代.zip"可能包含了一组...

Global site tag (gtag.js) - Google Analytics