65.9K
CodeProject 正在变化。 阅读更多。
Home

Microsoft Windows Vista 的下一代加密

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.88/5 (39投票s)

2007年4月30日

8分钟阅读

viewsIcon

258861

downloadIcon

5158

Cryptography API: Next Generation (CNG) 是 Windows Vista™ 中最新的加密基础设施,它支持新的 API、统一的用户模式和内核模式、敏捷加密、新的加密套件和改进的审计功能。

Screenshot - main.jpg

引言

Cryptography API: Next Generation (CNG) 是 Windows Vista™ 中一个新颖且敏捷的框架,它实现了一个可扩展的提供程序模型,允许您通过指定所需的加密算法来加载提供程序,而无需硬编码特定的提供程序。

其优点在于,算法提供程序可以被替换或升级,而您无需以任何方式更改代码即可使用新提供程序。此外,如果将来某个算法被确定为不安全,可以安装该算法的更安全版本,而不会影响您的代码。为了实现这一点,您通过识别所需的加密算法而不是特定的提供程序来加载 CNG 提供程序。大多数 CNG API 都需要由提供程序创建的提供程序或对象。

在本文中,我将尝试描述新的安全功能 Cryptography API: Next Generation (CNG),并将其与使用“Crypto API”(Vista 之前的 CAPI)的 RSA 和 AES 示例进行比较,包括托管和非托管版本,并说明如何在 Windows Vista 中使用 CNG 实现这些功能。托管版本的 CNG 尚待发布,如果您想要更多内容,请等待 Visual Studio "Orcas" 的下一个版本。

背景

关于 RSA

RSA 是公钥加密的标准。RSA 名称来源于其发明者的姓名:Ron Rivest、Adi Shamir 和 Leonard Adleman。RSA 的原理和安全性基于一个事实:以今天的知识,无法在合适的时间内找到一个大数的素数因子(n=pq,其中 p 和 q 是素数)。

简要说明

  • 公钥:n=pq(p 和 q 是大素数)
  • e 与 (p-1)(q-1) 互质
  • 私钥:d e-1 mod ((p-1)(q-1))
  • 加密:c = me mod n
  • 解密:m = cd mod n

关于 AES

Advanced Encryption Standard (AES),也称为 Rijndael,是一种对称 128 位分组密码,被美国政府采纳为加密标准。

简要说明

  • AES 在一个 4x4 字节数组上操作。
  • 对于加密,AES 的每个轮次(除了最后一个轮次)都包含四个阶段:AddRoundKey、Subbytes、Shift rows 和 Mix columns。
  • 在每个阶段,字节都会被操作和处理以进入下一级别。

Cryptography API: Next Generation (CNG)

CNG 提供了一组用于执行基本加密操作的 API,例如创建哈希、加密和解密数据。

CNG 中的每个算法类都由一个原始路由器表示。使用原始 API 的应用程序将链接到路由器二进制文件(用户模式下为 Bcrypt.dll,内核模式下为 Ksecdd.sys),并调用各种 CNG 原始函数。所有算法原语都由各种路由器组件管理。这些路由器会跟踪系统中安装的每个算法实现。路由器会将每个函数调用路由到适当的原始提供程序模块。

下图说明了 CNG 加密原语的设计和功能。

Screenshot - cng1.gif

CNG 为以下类别的算法提供原语

  • 随机数生成器:此类用于表示可插入的随机数生成 (RNG)。
  • 哈希:此类表示用于哈希的算法,例如 SHA1 和 SHA2。
  • 对称加密:此类表示用于对称加密的算法。例如 AES、3DES 和 RC4。
  • 非对称加密:此类表示支持加密的非对称(公钥)算法,例如 RSA。
  • 签名:此类表示签名算法,例如 DSA 和 ECDSA。此类也可与 RSA 一起使用。
  • 密钥协商:此类表示密钥协商算法,例如 Diffie-Hellman (DH) 和椭圆曲线 Diffie-Hellman (ECDH)。

使用代码

使用 RSA CryptoService Provider (CAPI)

在 CAPI 中,所有加密算法都在 wincrypt.h 中预定义,这使得扩展加密功能以适应您的应用程序需求变得非常困难。添加自定义对称算法并不容易。其次,CAPI 要求 Microsoft 对实现进行签名,以便其成为安全命名空间的一部分。

使用 RSACryptoServiceProvider 以传统方式进行 EncryptDecrypt

RSACryptoServiceProvider MyAsymmetricAlgorithm = new RSACryptoServiceProvider();
byte[] PlainTextBytes;
byte[] CipherTextBytes;

private void Encrypt()
{
    PlainTextBytes = System.Text.Encoding.UTF8.GetBytes(TextBoxOriginal.Text);
    CipherTextBytes = MyAsymmetricAlgorithm.Encrypt(PlainTextBytes, true);
    TextBoxEncrypted.Text = TextBoxEncrypted.Text +
    + Convert.ToBase64String(CipherTextBytes);
                ShowPublicPrivate();
    // rest of the code removed for brevity
}

private void Decrypt()
{
    PlainTextBytes = MyAsymmetricAlgorithm.Decrypt(CipherTextBytes, true);
    TextBoxOriginal.Text = System.Text.Encoding.UTF8.GetString
    (PlainTextBytes);
}

private void ShowPublicPrivate()
{
   RSAParameters MyParameters = new RSAParameters();
   MyParameters = MyAsymmetricAlgorithm.ExportParameters(true);
   TextBoxPrivateKey.Text = Convert.ToBase64String(MyParameters.D);
   TextBoxPublicKey.Text = Convert.ToBase64String(MyParameters.Modulus);
   // rest of the code removed for brevity
}

使用 CryptoService Provider 和 CNG

在 CNG 中,所有加密常量都是“字符串”而不是数字常量。由于您可以使用任何您想要的字符串常量来定义您的算法,当您的应用程序尝试使用该算法时,CNG 将加载已注册该名称的加密提供程序。您还可以为 SSL 和 TLS 插入自定义加密套件。添加新插件的核心函数是 BCryptAddContextFunctionProvider2

使用 CNG API 进行加密原语操作的典型步骤包括:

  1. 打开算法提供程序
  2. 获取或设置算法属性
  3. 创建或导入密钥
  4. 执行加密操作
  5. 关闭算法提供程序

用于“加密数据”的代码,RSA 加密的字符串是 BCRYPT_RSA_ALGORITHM。以下显示了该算法的伪代码。

加密伪代码

BCryptOpenAlgorithmProvider(&hAlg...)
BCryptGetProperty(hAlg,BCRYPT_BLOCK_LENGTH,&dwBlockSize...)
//allocate buffer , rounding up to next block size

BCryptGetProperty(hAlg,BCRYPT_OBJECT_LENGTH,&cbKeyObjectLen...)
//allocate buffer for key object

BCryptGenerateSymmetricKey(hAlg,&hKey...)
BCryptEncrypt(hKey,...)
//data is now encrypted

BCryptDestroyKey(hKey)
BCryptCloseAlgorithmProvider(hAlg,0)
//deallocate buffers

加密代码的一部分,密钥生成

我在此处添加了 CNG 的 AES 示例,而不是 RSA 示例,仅为简单起见和参考。
BCRYPT_RSA_ALGORITHM 也可以以类似的方式实现。一个完整的用于使用 CNG 进行 AES-CBC 加密的示例程序随 CNG3 SDK 一起提供。

在这里,BCRYPT_AES_ALGORITHM 是一个字符串变量,它提供了指向实际算法的句柄。因此,以后如果需要更改此算法,我们所要做的就是更改 AES 的实现,而无需更改现有代码。

#include "stdafx.h"
using namespace std;
#pragma comment(lib, "bcrypt")

wchar_t *GetEncryptionAlg() 
{
    return BCRYPT_AES_ALGORITHM;
}

LPBYTE GetPwd() 
{
    static const BYTE key[] = {1,2,3,4,5,6,7,8,1,2,3,4,5,6,7,8,0};
    return (LPBYTE)key;
}

LPBYTE GetIV() 
{
    static const BYTE iv[] = {1,2,3,4,5,6,7,8,1,2,3,4,5,6,7,8};
    return (LPBYTE)iv;
}

int _tmain(int argc, _TCHAR* argv[]) 
{
    BCRYPT_ALG_HANDLE hAlg = NULL;
    if (BCryptOpenAlgorithmProvider(
        &hAlg,
        GetEncryptionAlg(),
        NULL,
        0) == STATUS_SUCCESS) 
        {
            BCRYPT_KEY_HANDLE hKey = NULL;
            DWORD cbKey = 0;
            DWORD cbData = 0;
            if (BCryptGetProperty(
                    hAlg,
                    BCRYPT_OBJECT_LENGTH,
                    reinterpret_cast(&cbKey),
                    sizeof cbKey,
                    &cbData,
                    0) == STATUS_SUCCESS) 
            {
                LPBYTE pbKey = new (nothrow)BYTE[cbKey];
                if (pbKey) 
                {
                        BCRYPT_KEY_HANDLE hKey = NULL;
                        LPCSTR szPwd = (LPCSTR)GetPwd();
                        if (BCryptGenerateSymmetricKey(
                                    hAlg,
                                    &hKey,
                                    pbKey,
                                    cbKey,
                                    (PUCHAR)szPwd,
                                    (ULONG)strlen(szPwd),
                                    0) == STATUS_SUCCESS) 
                        {
                                printf("!!!");
                        }
                }
            }
        }

    return 0;
}

解密数据

与上面相同,除了使用 BCryptDecrypt

BCryptOpenAlgorithmProvider(&hAlg...)
BCryptGetProperty(hAlg,BCRYPT_BLOCK_LENGTH,&dwBlockSize...)
//allocate buffer , rounding up to next block size

BCryptGetProperty(hAlg,BCRYPT_OBJECT_LENGTH,&cbKeyObjectLen...)
//allocate buffer for key object

BCryptGenerateSymmetricKey(hAlg,&hKey...)
BCryptDecrypt(hKey,...)
//data is now encrypted

BCryptDestroyKey(hKey)
BCryptCloseAlgorithmProvider(hAlg,0)
// deallocate buffers

哈希数据

BCryptOpenAlgorithmProvider(&hAlg...)
BCryptGetProperty(hAlg,BCRYPT_OBJECT_LENGTH,&cbHash...)
//allocate buffer for hash

BCryptCreateHash(hAlg,&hHash,...)
BCryptHashData(hHash,...)
// use the hash data
// your code here

BCryptDestroyHash(hHash)
BCryptCloseAlgorithmProvider(hAlg,0)
//deallocate buffers

通过 CNG,加密师可以创建自己的加密提供程序,包含提供程序所需的所有接口和功能,并将其插入 CNG 框架。实现这一点所需的核心函数是 BCryptAddContextFunctionProvider

这是添加测试算法 BCRYPT_MYTEST_ALGORITHM 所需的基本结构,有关详细信息,请参阅 CNG SDK3 中的“安装和注册 CNG 插件”步骤。
#define BCRYPT_MYTEST_ALGORITHM
status = BCryptAddContextFunctionProvider(
         CRYPT_LOCAL,
         NULL,  //default
         BCRYPT_CIPHER_INTERFACE,
         BCRYPT_MYTEST_ALGORITHM,
         L"MyTest Provider",
         CRYPT_PRIORITY_TOP);

CNG 还允许您使用 BCryptResolveProviders 函数查询所有支持的算法。

#include "stdafx.h"
#pragma comment(lib, "bcrypt")
#ifndef NT_SUCCESS
#   define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0)
#endif

int  __cdecl main(int argc, __in_ecount(argc) LPWSTR *wargv) 
{
    argc;
    wargv;

    BOOLEAN bFipsEnabled = FALSE;
    if (NT_SUCCESS(BCryptGetFipsAlgorithmMode(&bFipsEnabled)))
        printf("FIPS is %Senabled.\n",bFipsEnabled ? L"" : L"not ");

    PCRYPT_PROVIDER_REFS pProviders = NULL;
    DWORD dwBufSize = 0;
    const DWORD dwFlags = CRYPT_ALL_FUNCTIONS | CRYPT_ALL_PROVIDERS;

    for (DWORD i = BCRYPT_CIPHER_INTERFACE; i <= BCRYPT_RNG_INTERFACE; i++) 
    {
        NTSTATUS ret = BCryptResolveProviders(
                            NULL,
                            i,
                            NULL,
                            NULL,
                            CRYPT_UM,
                            dwFlags,
                            &dwBufSize,
                            &pProviders);
        if (NT_SUCCESS(ret) && pProviders) 
        {
            printf("dwInterface = %d\n", i);

            for (DWORD k=0; k < pProviders->cProviders; k++) 
            {
                PCRYPT_PROVIDER_REF pProv = pProviders->rgpProviders[k];

                printf("\tFunction = %S\n", pProv->pszFunction);
                printf("\tProvider = %S\n", pProv->pszProvider);

            // print property names
            for ( DWORD j = 0; j < pProv->cProperties; j++)
            printf("\tProperty %d = %S\n", j, 
            pProv->rgpProperties[j]->pszProperty);

                printf("\n");
            }

            BCryptFreeBuffer(pProviders);
            pProviders = NULL;
            dwBufSize = 0;
        }
    }

    return 0;
}

CNG 的托管库将随 Visual Studio "Orcas" 的下一个版本一起发布,目前在 Visual Studio 2005 中不可用。您可以下载非托管版本的 CNG SDK3 来为 Windows Vista 进行开发。

CNG 还可以访问 Microsoft Cryptographic Service Provider 使用的所有 CAPI 密钥。

CNG 加密原语函数列表

以下是 Cryptographic Next Generation (CNG) API 定义的用于执行加密操作的函数列表。

  • BCryptCloseAlgorithmProvider
  • BCryptCreateHash
  • BCryptDecrypt
  • BCryptDeriveKey
  • BCryptDestroyHash
  • BCryptDestroyKey
  • BCryptDestroySecret
  • BCryptDuplicateHash
  • BCryptDuplicateKey
  • BCryptEncrypt
  • BCryptExportKey
  • BCryptFinalizeKeyPair
  • BCryptFinishHash
  • BCryptFreeBuffer
  • BCryptGenerateKeyPair
  • BCryptGenerateSymmetricKey
  • BCryptGenRandom
  • BCryptGetProperty
  • BCryptHashData
  • BCryptImportKey
  • BCryptImportKeyPair
  • BCryptOpenAlgorithmProvider
  • BCryptSecretAgreement
  • BCryptSetProperty
  • BCryptSignHash
  • BCryptVerifySignature

有关这些函数的详细信息,请参阅 MSDN。

Orcas 中的新加密算法

Orcas 的一月 CTP 提供了 Windows Vista 中新的 CNG API 的首批托管包装器5,这些包装器将在实现类上使用“Cng 后缀”。

哈希算法

算法 所需操作系统
MD5 MD5Cng Windows Vista
SHA-1 SHA1Cng Windows Vista
SHA-256 SHA256CryptoServiceProvider
SHA256Cng
Windows 2003
Windows Vista
SHA-384 SHA384CryptoServiceProvider
SHA384Cng
Windows 2003
Windows Vista
SHA-512 SHA512CryptoServiceProvider
SHA512Cng
Windows 2003
Windows Vista

对于以 Vista 为目标且必须使用 CNG 的应用程序,这组算法也为我们所有的哈希算法提供了 CNG 包装器。

非对称算法

算法 所需操作系统
椭圆曲线 DSA ECDSACng Windows Vista
椭圆曲线 Diffie-Hellman ECDiffieHellmanCng Windows Vista

请查看 Microsoft 安全5 博客以获取关于 CNG 的最新信息。

关注点

  • Windows Vista 支持以下四种用户模式加密接口:CNG、Cryptography API 1.0 (CAPI 1.0)、Cryptography API 2.0 (CAPI 2.0) 和 .NET Framework Cryptography。
  • CNG 还包括内核模式以及用户模式。在以前版本的 Windows 中,CAPI 等技术仅限于用户模式,内核模式加密需要一套完全不同的 API。现在,通过下一代加密 (CNG),为两者提供了一套统一的 API。
  • CNG 具有高度灵活性,支持在 Windows Vista 中为安全套接字层/传输层安全 SSL/TLS 和 IP 安全 IPSec 添加新算法。
  • CNG 包含椭圆曲线加密,这是加密算法中的新兴标准。
  • Windows Vista 在平台中包含了一个 Base Smart Card Cryptographic Service Provider (Base CSP)。这将使智能卡更加易于访问,因为供应商不再需要编写复杂的 CSP。新的 CNG 基础设施中还将有一个智能卡密钥存储提供程序。
  • 只有管理员才能安装 CNG 提供程序。

参考文献

  1. 加密与密码学
  2. 为 Windows Vista 编写安全代码
  3. 下载 C++ 使用的 CNG SDK
  4. Orcas 一月 CTP 包含 CNG 的托管库
  5. CNG 参考, MSDN 安全博客
  6. 列出您计算机上可用的加密算法

历史

  • 2007 年 4 月 29 日:首次发布
  • 2007 年 5 月 2 日:CNG 枚举器和部分 AES 加密

以及感谢

希望本文能够帮助您揭开 Windows Vista 中一些新的安全概念的面纱,并且对您有所帮助。再见!

© . All rights reserved.