Windows Cryptography API: Next Generation (CNG), Page 2
The parties now exchange public keys, and the public key of the external party is imported and used to create a secret handle.
//get these two bits of data for the other side //of the secret exchange PUCHAR publicKeyFromOtherParty; ULONG publicKeyFromOtherPartySize; //import the other parties public key BCRYPT_KEY_HANDLE importedPublicKey; BCryptImportKeyPair(algHandle, NULL, BCRYPT_ECCPUBLIC_BLOB, &importedPublicKey, publicKeyFromOtherParty, publicKeyFromOtherPartySize, 0); //create the secret BCRYPT_SECRET_HANDLE secretHandle; BCryptSecretAgreement(fullKey, importedPublicKey, &secretHandle, 0);
Once the secret handle has been generated, a symmetric key can be derived. It will be the same for both parties that have exchanged public keys:
PUCHAR derivedSymmetricKey; ULONG derivedKeySize; //get the size of the derived key BCryptDeriveKey(secretHandle, L"HASH", NULL, NULL, 0, &derivedKeySize, 0); //allocate a buffer for the derived key derivedSymmetricKey = new UCHAR[derivedKeySize]; //get the derived key BCryptDeriveKey(secretHandle, L"HASH", NULL, derivedSymmetricKey, derivedKeySize, &derivedKeySize, 0);
With the derived symmetric key in place, the parties can exchange encrypted messages with no performance issues.
As this code shows, once it is known which CNG functions need to be called in which order, the actual code to complete a given cryptographic task is fairly easy. Even once error handling and memory clean-up has been added to the code contained in this article, the entire programming task still fits within a function of only a few dozen lines. Implementing hashing, encryption, and random number generation are also fairly quick in terms of lines-of-code count. If a system is being developed that will be targeted to Windows Vista or Windows Server 2008 exclusively, preferring CNG over the CryptoAPI makes a lot of sense.
Download the Code
You can download the code that accompanies this article here.
Nick Wienholt is a Windows and .NET consultant based in Sydney, Australia. He has worked on a variety of IT projects over the last decade and continues to stay involved in the developer community. Nick is the co-founder and president of the Sydney Deep .NET User group, writes technical articles for Pinnacle Publishing and the Microsoft Developer Network, and is a participant in many .NET-related newsgroups. Nick's most recent book is Maximizing .NET Performance.