This is preliminary documentation and subject to change.
To comment on this topic, please send us email at ngwssdk@microsoft.com. Thanks!
Shared Name Cryptographic Key Management
A set of helper APIs are provided to support key generation and management by compiler vendors. These are designed to provide the flexibility needed to address common development scenarios while still being easy to use.
Using these APIs, it is possible for compilers to:
- Generate shared name cryptographic key pairs and retrieve a representation (portable key blob) that can be easily stored and moved across development platforms.
- Associate a shared name key cryptographic pair with a project and use it for shared name generation. The key pair need not be permanently installed into the CSP used for shared name generation so that use of distinct key pairs for each project can be easily accommodated.
- Install a key pair into the CSP used for shared name generation such that it can easily be referred to for shared name generation with any project.
In addition, the design provides assurance that shared name key operations will not impact the use of cryptographic functionality by other applications on the user’s machine.
Typical scenarios supported include:
- Creating a shared name cryptographic key pair that may be associated with one or more projects. This is expected to be the common mode of operation. The key pair is generated using the StrongNameGenerateKey()API and the portable key blob returned. The key pair will generally not be left installed in the shared name CSP. The portable key blob, and its associated container name (or friendly name), can be stored as a file in the source control system or in the project data. If stored as a file, a standard naming convention of “<container name>.snk” is recommended. This will make it easy to locate and move test keys across development environments. When the test key is no longer needed, the key blob may simply be discarded.
- Creating a shared name cryptographic key pair and storing it on the users machine. To do this one would follow the procedure outlined above. However, at key generation time the key generation flag parameter can be set to SN_LEAVE_KEY. This will leave a copy of the key pair installed in the shared name CSP. The development environment should store the container name for this key so it can be easily referred. Note that the key can be left installed in the CSP for default use and also stored in portable form.
- Changing the default shared name key cryptographic pair on a user’s machine. This assumes the development environment has a portable key blob it wishes to make the default key for shared key operations. The StrongNameKeyInstall() API is used to load the portable key blob in the shared name CSP. The development environment should keep track of the container name for this key. If no default key was installed prior to this operation, then we simply install the new key pair. However, if a default key was previously installed, StrongNameKeyDelete() should be called with the container name of the old default key prior to installing the new default key. This will prevent the accumulation of a large number of key pairs on the user’s machine and minimize the probability of container name clashes.
- Creating a deployment shared name cryptographic key pair. There is no difference in the basic operations for creating a deployment and test shared name key. But, as a rule, one would not want to keep deployment keys in a portable form accessible to large numbers of developers. It is recommended that a single machine be used for “real” signing and that the deployment keys be left installed in the CSP. If the portable key blob is stored for backup purposes, it should be isolated and physically protected. For organizations that desire high assurance no one will forge names in their shared name namespace, they may wish to use a hardware CSP (available from several third parties). In most cases, these devices will not export the key pair, but the provided APIs can still be used to generate the key(s) desired.
In using these APIs, the following cautionary issues should be considered.
- To insure the portable key blobs can be easily transferred between development machines, they are not encrypted upon export from the CSP. This means anyone will be able to install and use the key pair. This is not a serious concern for test keys, but is an issue for deployment keys.
- We do not enforce uniqueness on key container names. Hence, it is possible for developers to create multiple key pairs using the same container name. This could lead problems since container names are the easiest to refer to key pairs. For example, one developer could create a shared name using one set of keys while a second developer could pick up the different key pair when creating a shared name reference. In such a case, it may not be immediately obvious why the shared name reference isn’t properly resolved. Tools UI can easily help in preventing such problems.
- The two primary objectives of shared names are to (1) create unique names and (2) prevent name spoofing. The cryptographic keys are required only to make the latter very difficult. A developer’s private key is used to prove they have the right to create new names in their private namespace. It is not used to prove identity or any other properties of the developer. Given this intent, one should make a distinction between a shared name key pair and key pairs used for digital identity or key exchange purposes. By convention, the key pairs used for creating shared names are stored in files with a .snk extension.
Key Management APIs
The following function will create a new key pair for shared name use and export it to the calling program.
BOOL StrongNameKeyGen(
// [in] desired key container name, must be a non-empty string
LPCWSTR szKeyContainer,
// [in] flag parameter, leave key installed is only option
DWORD dwFlags,
// [out] public/private key blob
BYTE **ppbKeyBlob,
ULONG *pcbKeyBlob)
The container name is a user defined string. CryptoAPI does not specify a size limit on this string, but individual CSPs may. It should generally be a short descriptive name. We allow user defined names so that multiple shared name keypairs (e.g., project1 vs project2, test vs deploy) can be managed. The dwFlags parameter is used to control optional actions. The only defined flag for this version is SN_LEAVE_KEY (value is 1). If set, then the key pair will be left installed in the shared name CSP.
This function will attempt to create a new signing keypair using the supplied container name. The CSP to use, and signing algorithm, are determined by the default settings described earlier.
The generated key will be marked exportable (if supported by the CSP) and the public/private keys exported in an unencrypted keyblob. This is returned to the caller. The keyblob may be stored in any way convenient for the calling application. If modified, it will no longer be usable.
To simplify use of this, and other functions, we will allocate the buffer to hold the protable key blob. The calling program should call StrongNameFreeBuffer() when the buffer is no longer needed to insure its properly de-allocated.
The following function may be used to install a portable key blob into a machine CSP. Its purpose is to support installation of default shared name keys.
BOOL StrongNameKeyInstall(
// [in] desired key container name, must be a non-empty string
LPCWSTR szKeyContainer,
// [in] public/private key blob
BYTE *pbKeyBlob,
ULONG cbKeyBlob)
This function attempts to install the key pair provided in the key blob into the shared name CSP using the provided container name. If the container name already exists or an invalid key blob is supplied, an error is returned.
The following function may be used to delete a shared name key pair from the CSP. This will only be required if the SN_LEAVE_KEY option was selected at key generation time, or the key was subsequently installed loaded into the CSP. UI should make it very clear to the user that this will result in permanent deletion of the keys. If the corresponding portable key blob was not stored, they will be unable to create any future shared names in the associated namespace.
BOOL StrongNameKeyDelete(
// [in] desired key container name
LPCWSTR szContainer)
This function will acquire the shared name CSP context for the given key container name with the flag CRYPT_DELETEKEYSET.
The following function is used to free memory allocated by the shared name functions.
VOID StrongNameFreeBuffer(
// [in] pointer to memory to be freed
BYTE *pbMemory)
pbMemory should only refer to memory allocated by the shared name functions when return key blobs to the calling program.