The Cryptography API, or How to Keep a Secret(三)

    技术2022-05-11  26

    几个加密API函数

    [编者注:下面缩进部分的文件引用自MSDN Library, Platform, SDK, DDK 文档。]

    初始化CSPCryptAcquireContext, CryptReleaseContext

    函数CryptAcquireContext用来获得CSP中一个特定密鈅容器的句柄。返回的句柄然后就可以对选择的CSP进行调用。

    函数CryptReleaseContext用于释放函数CryptAcquireContext返回的句柄。 CryptReleaseContext 不会删除任何Cryptography API 对象,它仅仅释放对象的句柄。

    函数CryptAcquireContext执行两个操作。 首先试着查找变量中指定的CSP 如果找到,函数试着查找CSP中匹配指定密鈅容器名的密鈅容器。此函数也可以用于建立、删除密鈅容器,这取决于函数中的参数值。

    取得默认CSP中默认密鈅容器的代码如下所示:(译注:原文章代码中注释为英文,此处译为中文,下面情况同)

    #include <wincrypt.h>      // 对CryptoAPI的定义 /* 对于非C/C++用户,此处用到的常量如下: #define MS_DEF_PROV       "Microsoft Base Cryptographic Provider v1.0" #define PROV_RSA_FULL           1 */   BOOL bResult; HCRYPTPROC hProv;   // 试图取得转为密鈅容器的句柄 bResult = CryptAcquireContext(             &hProv,            // 保存返回句柄的变量             NULL,              // 默认密鈅容器             MS_DEF_PROV,       // 默认CSP             PROV_RSA_FULL,     // 要取得的CSP类型             0);                // 未指定动作 . . . // 此处执行操作 . . . // 释放容器句柄 CryptReleaseContext(hProv);

    如果CryptAcquireContext调用成功,返回值非零,变量hProv 即为要取得的密鈅容器句柄。

    要在默认CSP中添加或者创建一个密鈅容器,要写的代码如下:

    #include <wincrypt.h>      // 对CryptoAPI的定义 /* 对于非C/C++用户,此处用到的常量如下: #define MS_DEF_PROV       "Microsoft Base Cryptographic Provider v1.0" #define PROV_RSA_FULL           1 #define CRYPT_NEWKEYSET         0x8 */   BOOL bResult; HCRYPTPROC hProv;   // 试图添加一个新的密鈅容器 BResult = CryptAcquireContext(             &hProv,              // 保存返回句柄的变量             NULL,                // 默认密鈅容器             MS_DEF_PROV,         // 默认CSP             PROV_RSA_FULL,       // 要取得的CSP类型             CRYPT_NEWKEYSET);    // 创建一个新密鈅容器 . . . // 此处执行操作 . . . // 释放容器句柄 CryptReleaseContext(hProv);

    如果CryptAcquireContext调用成功,返回值非零,变量hProv 即为新的密鈅容器句柄。

    要从默认CSP中删除一个存在的密鈅容器,要写的代码如下:

    #include <wincrypt.h>      // 对CryptoAPI的定义 /* 对于非C/C++用户,此处用到的常量如下: #define MS_DEF_PROV       "Microsoft Base Cryptographic Provider v1.0" #define PROV_RSA_FULL           1 #define CRYPT_DELETEKEYSET         0x10 */ BOOL bResult; HCRYPTPROC hProv;   // 试图删除密鈅容器 BResult = CryptAcquireContext(             &hProv,                // 保存返回句柄的变量             NULL,                  // 默认密鈅容器             MS_DEF_PROV,           // 默认CSP             PROV_RSA_FULL,         // 要取得的CSP类型             CRYPT_DELETEKEYSET);   // 删除存在的密鈅容器

    如果CryptAcquireContext调用成功,返回值非零,变量hProv 指向的密鈅容器已经删除,此密鈅容器不再有效。

    散列数据:CryptCreateHash, CryptHashData, CryptGetHashParam, CryptDestroyHash

    当我说“散列法”或“散列”("hashing" or "hash" )时,是指从一块数据中派生出一个数值的方法或算法。这可能是简单的将所有数据位相加,或复杂到要对数据进行傅立叶变换。(译注:散列也被称为哈希,杂凑)

    上面列出的四个函数是用于创建或者维护从提供的数据生成的散列值的,一般一起使用:

    函数 CryptCreateHash用于散列数据时初始化。它返回CSP散列对象的句柄,此句柄会在后续CryptHashData函数散列数据时使用。下一步是调用CryptGetHashParam 函数取得散列值。函数 CryptDestroyHash 释放函数 CryptCreateHash返回的句柄。CryptDestroyHash不会删除任何加密 API 对象,它仅仅释放散列对象的句柄。

    CryptHashData 函数用来从提供的数据中计算密码散列。为计算一个大数据块或者数据块的几个部分时,此函数可被调用多次。例如,我们要对缓冲区pBufferdwBufferLen字节长的数据进行散列。在此例子中我仅使用CALG_MD5 散列算法来实现此目的。 加密 API SDK 文档中还提供对许多其它算法详细的描述。 本例子假定只散列一块数据。一旦调用CryptGetHashParam函数取得了散列值,此散列实例对象便不能再散列其它数据了。

    #include <wincrypt.h>      // 对CryptoAPI的定义 /* 对于非C/C++用户,此处用到的常量如下: #define ALG_CLASS_HASH                  (4 << 13) #define ALG_TYPE_ANY                    (0) #define ALG_SID_MD5                     3 #define CALG_MD5        (ALG_CLASS_HASH | ALG_TYPE_ANY | ALG_SID_MD5) #define HP_HASHVAL              0x0002  // 散列值 #define HP_HASHSIZE             0x0004  // 散列值长度 */ BOOL bResult; HCRYPTHASH hHash; DWORD dwBufferSize; DWORD dwValue; PBYTE pBuffer;   // 获得散列对象句柄 bResult = CryptCreateHash(             hProv,               // 之前获得的CSP句柄             CALG_MD5,            // 散列算法             0,                   // 非密鈅散列             0,                   // 置0             &hHash);             // 保存散列对象句柄的变量   // 散列数据 bResult = CryptHashData(             hHash,               // 散列对象句柄             pBuffer,             // 数据缓冲区指针             dwBufferlen,         // 数据长度             0);                  // 未指定值   // 得到散列值尺寸 dwBufferSize = sizeof(DWORD); bResult = CryptGetHashParam(             hHash,               // 散列对象句柄             HP_HASHSIZE,         // 得到散列值尺寸             &dwValue,            // 保存散列值长度缓冲区             &dwBufferSize,       // 缓冲区长度             0);                  // 必须置0   // 创建保存散列值的缓冲区 pBuffer = new char [dwBufferSize];   // Get hash value. bResult = CryptGetHashParam(             hHash,              // 散列对象句柄             HP_HASHVAL,         // 得到散列值             pBuffer,            // 保存散列值长度缓冲区             &dwBufferSize,      // 缓冲区长度             0);                 // 必须置0   // 释放散列对象 CryptDestroyHash(hHash);

    上面例子为pBuffer 指向的数据生成一个散列值。如果还要散列其它数据,用这个数据调用 CryptHashData,产生的散列值仍会是原来的值。已警告过使用HP_HASHVALUE参数调用 CryptGetHashParam 会阻止使用此对象继续进行散列。


    最新回复(0)