In the Microsoft CNG API (Cryptography API: Next Generation), there are two sets of functions that appear to do the same thing.
The following functions start with BCrypt
and perform key import/export, encryption/decryption, sign/verify, and Diffe-Helman key exchange
BCryptExportKey BCryptImportKey BCryptEncrypt BCryptDecrypt BCryptSignHash BCryptVerifySignature BCryptSecretAgreement BCryptDeriveKey
But the same set of functions exist which start with NCrypt
:
NCryptExportKey NCryptImportKey NCryptEncrypt NCryptDecrypt NCryptSignHash NCryptVerifySignature NCryptSecretAgreement NCryptDeriveKey
What's the difference between these two sets of functions, and when should each one be used?
The BCrypt
family of function are classified as Cryptographic Primitives, while the NCrypt
family of functions are classified as Key Storage and Retrieval.
The primary difference is that the BCrypt
functions are used when dealing only with ephemeral keys, while the NCrypt
functions are used when persistent keys are required.
In practice, the BCrypt
functions are typically used for hashing and symmetric encryption, while the NCrypt
functions are used for public/private key encryption and decryption, public/private key signing and verification, and shared secret (e.g. DH and ECDH) negotiation.
While some public/private key operations can be done with BCrypt
functions, they can only be used with ephemeral keys and are therefore of limited use.
Persistent keys are stored in key containers specific to each user (or to the system). This is a security measure to ensure that users can't view each other's private keys.
In general, you'll want to use the following functions for the following operations:
BCryptHashData
: Used for hashing and HMAC (MD5, SHA1, SHA256, SHA384, SHA512) BCryptCreateHash
, BCryptFinishHash
, BCryptDestroyHash
BCryptEncrypt
: Symmetric key encryption (DES, 3DES, AES). BCryptGenerateSymmetricKey
, BCryptDestroyKey
BCryptDecrypt
: Symmetric key decryption (DES, 3DES, AES). BCryptGenerateSymmetricKey
, BCryptDestroyKey
NCryptEncrypt
: Asymmetric key encryption (RSA)NCryptDecrypt
: Asymmetric key decryption (RSA)NCryptSignHash
: Asymetric key signature (RSA, DSA, ECDSA)NCryptVerifySignature
: Asymmetric key signature verification (RSA, DSA, ECDSA)NCryptSecretAgreement
: Asymmetric key secret sharing (DH, ECDH) NCryptDeriveKey
Examples are available at MSDN for several of these cases.
For a real world example, I've implemented all of these in the UFTP source code, specifically the encrypt_cng.c
file (there are typedefs in place, defined in encryption.h
, to allow the functions in this file to implement a common application level API to allow the use of other crypto libraries such as CryptoAPI and OpenSSL).
Use BCrypt*
functions when you have the key in the memory of your application.
Use NCrypt*
functions when you store the key in a KSP (Key Storage Provider).
NCrypt*
functions do a lot of extra work and are less efficient, so if you are not storing the key in the KSP it is better to use the BCrypt*
functions.
As most long-term stored keys are asymmetric (RSA, ECDSA, ...) keys, NCrypt*
functions are more commonly used with aymmetric algorithms. BCrypt*
is commonly used for both asymmetric and symmetric algorithms.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With