![]() |
Platforms, Frameworks & Libraries »
Vista Security »
Cryptography
Beginner
Next Generation of Cryptography for Microsoft Windows VistaBy Quartz.Cryptography API: Next Generation (CNG) is the latest cryptographic infrastructure in Windows Vista™ which supports new APIs, unified user and kernel mode, agile cryptography, new cipher suits and improved auditing |
VC8.0, C# 2.0.NET 2.0, VistaVS2005, Dev
|
|
Advanced Search |
|
|
|
||||||||||||||||
The Cryptography API: Next Generation(CNG) is a new and agile framework in Windows Vista�, which implements an extensible provider model that allows you to load a provider by specifying the required cryptographic algorithm rather than having to hardcode a specific provider.
The advantage is that an algorithm provider can be replaced or upgraded and you will not have to change your code in any way to use the new provider. Also, if some algorithm is determined to be unsafe in the future, a more secure version of that algorithm can be installed with no effect to your code. To facilitate this, you load a CNG provider by identifying the cryptographic algorithm that you require, not the specific provider. Most of the CNG APIs require a provider or an object created by a provider.
In this article, I try to describe the new security feature Cryptography API: Next Generation(CNG) and compare it with an RSA and AES samples, both managed and unmanaged, using "Crypto API" (CAPI before Vista) and how it can be implemented using CNG in Windows Vista. Managed version of CNG is yet to come, if you feel like you want more, wait for the next release of Visual Studio "Orcas".
RSA is the established standard for public key encryption. The name RSA is derived from the names of the inventors of this algorithm, which are: Ron Rivest, Adi Shamir and Leonard Adleman. The principle and security of RSA is based on the fact that with today's knowledge, it is not possible to find the prime factors of a big number (n=pq, where p and q are prime numbers) in suitable time.
Advanced Encryption Standard (AES), also known as Rijndael, is a symmetric 128-bit block cipher adopted as an encryption standard by the US government.
CNG provides a set of APIs that are used for performing basic cryptographic operations, such as creating hashes, encrypting, and decrypting data.
Each algorithm class in CNG is represented by a primitive router. Applications making use of the primitive APIs will link to the router binary (Bcrypt.dll in user mode, or Ksecdd.sys in kernel mode), and make calls to the various CNG primitive functions. All of the algorithm primitives are managed by various router components. These routers keep track of each algorithm implementation that has been installed on the system. The router will route each function call to the appropriate primitive provider module.
The following illustration shows the design and function of the CNG cryptographic primitives.

CNG provides primitives for the following classes of algorithms:
In CAPI, all cryptographic algorithms are predefined in wincrypt.h which makes it very difficult to extend cryptographic functionality to suit your application's need. Adding a custom symmetric algorithm is not easy. Secondly the CAPI requires Microsoft to sign the implementation, so that it can be a part of a security namespace.
Encrypt and Decrypt in a traditional way, with 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();
// 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
}
In CNG, all cryptographic constants are "strings" rather than numeric constants. And since you can use any string constant you want to define your algorithm, when your application attempts to use the algorithm, CNG will load the crypto-provider that registered the name. You can also plug in custom cipher-suits for SSL and TLS. The core function that adds a new add-in is BCryptAddContextFunctionProvider2.
The typical steps involved in using the CNG API for cryptographic primitive operations are:
The code for "encrypting data", the string for RSA encryption is BCRYPT_RSA_ALGORITHM. The following shows a pseudocode for the 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
I have added this example of CNG for AES, and not for RSA for simplicity and reference only.BCRYPT_RSA_ALGORITHM can also be implemented in a similar fashion. A complete sample program for AES-CBC encryption using CNG comes with the CNG3 SDK.
Here BCRYPT_AES_ALGORITHM is the string variable which gives the handle to the actual algorithm. So later if this algorithm needs to be changed, all we will need to do is change the implementation of AES, keeping the existing code.
#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;
}
Same as above, except for 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
With CNG, a cryptographer can create his own cryptographic provider, with all the needed interfaces and functionality for the provider and plug in the CNG framework. The core function which is required for this is BCryptAddContextFunctionProvider.
BCRYPT_MYTEST_ALGORITHM, for details please refer to the steps to install and register "CNG add-ins" in the CNG SDK3.
#define BCRYPT_MYTEST_ALGORITHM
status = BCryptAddContextFunctionProvider(
CRYPT_LOCAL,
NULL, //default
BCRYPT_CIPHER_INTERFACE,
BCRYPT_MYTEST_ALGORITHM,
L"MyTest Provider",
CRYPT_PRIORITY_TOP);
A CNG also allows you to query for all supported algorithms using the function 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;
}
Managed library for CNG is coming with the next version of Visual Studio "Orcas" and is not available right now in Visual Studio 2005. You can download the unmanaged version of the CNG SDK3 to develop for Windows Vista.
CNG also has access to all the CAPI keys used by Microsoft Cryptographic Service providers.
Here is a the list of functions defined by the Cryptographic Next Generation (CNG) API that are used for performing cryptographic operations.
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 Look for details on each of these functions in MSDN.
The January CTP of Orcas, has the first set of managed wrappers around the new CNG APIs in Windows Vista5, which will use the "Cng suffix" on the implementation classes.
| Algorithm | Class | OS Required |
| MD5 | MD5Cng |
Windows Vista |
| SHA-1 | SHA1Cng |
Windows Vista |
| SHA-256 | SHA256CryptoServiceProviderSHA256Cng |
Windows 2003 Windows Vista |
| SHA-384 | SHA384CryptoServiceProvider SHA384Cng |
Windows 2003 Windows Vista |
| SHA-512 | SHA512CryptoServiceProvider SHA512Cng |
Windows 2003 Windows Vista |
For applications targeting Vista which must use CNG, this set of algorithms also provides CNG wrappers for all of our hashing algorithms.
| Algorithm | Class | OS Required |
| Elliptic Curve DSA | ECDSACng |
Windows Vista |
| Elliptic Curve Diffie-Hellman | ECDiffieHellmanCng |
Windows Vista |
Check Microsoft security5 blogs for the latest information on CNG.
For coming so far, I hope this article will help demystify some of the new security concepts in Windows Vista, and you will find it useful. Adios!
General
News
Question
Answer
Joke
Rant
Admin
|
PermaLink |
Privacy |
Terms of Use
Last Updated: 30 Apr 2007 Editor: Deeksha Shenoy |
Copyright 2007 by Quartz. Everything else Copyright © CodeProject, 1999-2009 Web12 | Advertise on the Code Project |