Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CNG: When to use BCrypt* vs NCrypt* family of functions

Tags:

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?

like image 351
dbush Avatar asked Nov 14 '16 19:11

dbush


2 Answers

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)
    • Related: BCryptCreateHash, BCryptFinishHash, BCryptDestroyHash
  • BCryptEncrypt: Symmetric key encryption (DES, 3DES, AES).
    • Related: BCryptGenerateSymmetricKey, BCryptDestroyKey
  • BCryptDecrypt: Symmetric key decryption (DES, 3DES, AES).
    • Related: 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)
    • Related: 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).

like image 171
dbush Avatar answered Oct 03 '22 02:10

dbush


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.

like image 30
Niels Ferguson Avatar answered Oct 03 '22 04:10

Niels Ferguson