Microsoft Windows Vista中的下一代加密API

Microsoft Windows Vista中的下一代加密API


    CNG是Windows Vista中最新的加密体系,其支持新的API、一体式用户及内核模式、灵活的加密方法及新的密码套件。


    简介
    CNG是Windows Vista中一种新的、灵活的框架结构,其实现了可扩展的提供者模式,可允许你通过指定所需的加密算法来加载某个提供者,而不用针对某个特殊的提供者进行硬编码。
    其好处在于算法提供者可被替换或升级,而无需修改相关程序代码就可使用新的提供者;同时,如果确定某些算法在将来会变得不安全,也可以安装更安全的版本,且对原程序代码无任何影响。这样一来,就可通过识别所需的加密算法,而不是特定的提供者来加载一个CNG提供者。大多数CNG API都需要一个提供者或由提供者创建的一个对象。
    在本文中,将会讲解CNG新的安全特性,并与RSA及AES进行比较,并在托管及非托管模式下使用“Crypto API”(Vista之前的加密API),及它们如何在Windows Vista下通过CNG来实现。


    背景知识

关于RSA
    RSA是公匙加密中已确定的标准,RSA本身的名称派生自算法发明的名字,他们是:Ron Rivest、Adi Shamir、Leonard Adleman。RSA的原理及安全性基于现今的认识——即不可能在适当的时间内找到一个大数的质数因子(如n=qp,在这p及q为质数)。细则如下:

    公匙:n=qp(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操作一个4×4的字节数组。
    加密时,每轮AES(除了最后一轮)由四阶段组成:AddRoundKey、Subbytes、Shift rows、Mix columns。
    在每一阶段,字节为下一级进行了相关操纵及处理。


下一代加密API:CNG
CNG提供一个API集,用于执行基本的加密操作,如创建哈希、加密及解密数据。CNG中的每个算法类都有一个原语路由,使用这些原语API的程序则会链接到路由库(用户模式中是Bcrypt.dll,核心模式中是Dsecdd.sys),并调用不同的CNG原语函数。所有这些算法原语都由各个不同的路由组件管理,这些路由跟踪安装在系统中每个算法的实现,并把对各个函数的调用,路由到适当的原语提供者模块中。
    下图演示了CNG加密原语的设计与函数模式。

Microsoft Windows Vista中的下一代加密API_第1张图片
 


    CNG为下列算法提供了原语:

    随机数生成:表示可插入的随机数生成(RNG)。
    哈希:表示用于哈希的算法,如SHA1及SHA2。
    对称加密:表示对称加密的算法,如AES、3DES、RC4。
    非对称加密:表示非对称加密算法,如RSA。
    签名:表示如DSA及ECDSA之类的签名算法,也可与RSA一同使用。
    秘密协定:表示私密协定算法,如Diffie-Hellman及椭圆曲线Diffie-Hellman。


使用RSA CryptoService Provider(CAPI)
    就CAPI而言,所有的加密算法都预定义在wincrypt.h中,这样就非常难以扩展加密功能以适应各自程序的需要,比如说添加一个自定义的对称加密算法就不是一件简单的事;其次,CAPI需要微软来签名其实现,所以它可作为安全命名空间的一部分。
    以下是传统方式的加密及解密,使用了RSACryptoServiceProvider。


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();
    //剩余代码已省略
}

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);
   //剩余代码已省略
}


    与CNG一同使用CryptoService Provider
    在CNG中,所有加密常量均为“字符串”而不是数值,因为可使用任何字符串常量来定义算法,所以当程序试图使用算法时,CNG会加载注册了此名字的加密算法提供者。我们也可为SSL及TLS插入自定义的加密算法,添加一个新插件的核心函数是:BCryptAddContextFunctionProvider。
    使用CNG API用于加密原语操作的一般步骤如下:

1、    打开算法提供者(Provider)。
2、    Get或Set算法属性。
3、    创建或导入一个密钥。
4、    执行加密操作。
5、    关闭算法提供者。


用作RSA加密的字符串是:BCRYPT_RSA_ALGORITHM,以下是此算法的伪代码:


BCryptOpenAlgorithmProvider(&hAlg...)
BCryptGetProperty(hAlg,BCRYPT_BLOCK_LENGTH,&dwBlockSize...)
//分配缓冲区,取整到下一块大小

BCryptGetProperty(hAlg,BCRYPT_OBJECT_LENGTH,&cbKeyObjectLen...)
//为密钥对象分配缓冲区

BCryptGenerateSymmetricKey(hAlg,&hKey...)
BCryptEncrypt(hKey,...)
//数据现在已被加密

BCryptDestroyKey(hKey)
BCryptCloseAlgorithmProvider(hAlg,0)
//释放缓冲区


    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...)
//分配缓冲区,取整到下一块大小

BCryptGetProperty(hAlg,BCRYPT_OBJECT_LENGTH,&cbKeyObjectLen...)
//为密钥对象分配缓冲区

BCryptGenerateSymmetricKey(hAlg,&hKey...)
BCryptDecrypt(hKey,...)
//数据现在已被加密

BCryptDestroyKey(hKey)
BCryptCloseAlgorithmProvider(hAlg,0)
//释放缓冲区


    以下代码是对数据进行哈希处理。


BCryptOpenAlgorithmProvider(&hAlg...)
BCryptGetProperty(hAlg,BCRYPT_OBJECT_LENGTH,&cbHash...)
//为哈希分配缓冲区

BCryptCreateHash(hAlg,&hHash,...)
BCryptHashData(hHash,...)
//使用哈希数据

//其他程序代码

BCryptDestroyHash(hHash)
BCryptCloseAlgorithmProvider(hAlg,0)
//释放缓冲区


    一个加密程序可通过CNG,创建其自己的加密提供者,在CNG框架中,已自带了所有相关所需的接口及功能插件,此核心函数为:BCryptAddContextFunctionProvider。
    以下是添加一个BCRYPT_MYTEST_ALGORITHM测试算法所需的基本结构,详细步骤请查阅CNG SDK3中的Install and register “CNG add-ins”。


#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 2008提供,如果使用Visual Studio 2005,可使用CNG SDK3的非托管版本在Windows Vista上进行开发。同时,CNG也可访问Microsoft Cryptographic Service providers中所使用的所有CAPI密钥。


    CNG加密原语函数列表
    以下是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


    Visual Studio 2008中新的加密算法
    在Visual Studio 2008中,已自带了Windows Vista中新的CNG API托管包装函数,其在实现类中以Cng后缀表明。

    哈希算法

算法

所支持的操作系统

Elliptic Curve DSA

ECDSACng

Windows Vista

Elliptic Curve Diffie-Hellman

ECDiffieHellmanCng

Windows Vista



    几点说明

    Windows Vista支持以下四种用户模式的加密接口:CNG、Cryptographic API 1.0 (CAPI 1.0)、Cryptographic API 2.0 (CAPI 2.0)、.NET Framework加密。
    在提供用户模式的同时,CNG也包含了核心模式,在Vista之前的Windows版本中,像CAPI就只能在用户模式,而核心模式加密则需要完全不同的API。现在有了CNG,两者都可以使用同一组API了。
    CNG非常灵活,可以向Windows Vista中添加新的算法,以用在Secure Socket Layer(SSL)、Transport Layer Security(TLS)、Internet Protocol Security(IPSec)中。
    CNG包含了椭圆曲线加密,它正在成为当今加密算法中的一项新标准。
    Windows Vista中已包含了智能卡基本加密服务提供者(Base Smart Card Cryptographic Service Provider  Base CSP),能让智能卡更易使用,开发者也无需再与复杂的CSP打交道了,在新的CNG基础架构中,也提供了一个智能卡密钥存储提供者(Key Storage Provider)。
    只有管理员才能安装一个CNG提供者(Provider)。

你可能感兴趣的:(其他)