I've been meaning to make a couple of posts about Crypto API performance. This one is just about CryptAcquireContext. Also, we're about to find out if my "free-hand" HTML is as good as it was when I was in college (doubt it).

  1. Many applications that use Crypto API 1.0 require only non-public key type services, such as hashing, bulk encryption, and random number generation. When building a context handle to be used in that way, always use the CRYPT_VERIFYCONTEXT flag with Cr yptAcquireContext, and be sure to set the container name parameter to NULL (**). For example, call the API in the following way:

    if (FALSE == CryptAcquireContext(&hProv, NULL, MS_STRONG_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) { // Handle error }

    The performance benefit of using the CRYPT_VERIFYCONTEXT flag in this case is considerable. Without it (i.e. with dwFlags=0), the provider will attempt to find and open the specified container. If a NULL container name is passed, that means the default container will be opened.

    Opening a key container typically consists of the following operations.

    1. Query for the appropriate user profile path.
    2. Read the container file from the disk.
    3. Decrypt a portion of the container (via Cry ptUnprotectData) and load it into memory.
    If you pass the VERIFYCONTEXT flag, you skip all of that.

  2. On the other hand, if your application needs to access persisted private keys, then you can't use the VERIFYCONTEXT flag. In this situation, the best thing to do is to design your application so that you'll only have to call CryptAcquireContext once.

** As a side note, CryptAcquireContext may or may not fail if called with the VERIFYCONTEXT flag and a non-NULL container name. For software based providers (e.g. MS_STRONG_PROV), this combination is expected to fail, since key container access is not allowed with that flag. However, for smartcard based providers, this is a legal combination! The expected behavior in the smartcard case is that public information can be queried using the resulting provider handle, but no operations that modify data on the card, or that require the PIN, are allowed.