NGWS SDK Documentation  

This is preliminary documentation and subject to change.
To comment on this topic, please send us email at ngwssdk@microsoft.com. Thanks!

Defining a Shared Name

To securely define a shared name namespace, the PE file containing the Assembly metadata is signed with the private key corresponding to the public key that defines the namespace. This operation requires several steps.

The development environment is expected to perform the following operations in sequence in generating a shared name.

  1. The Shared Name public key blob is retrieved. Space is reserved in the metadata section to hold the key blob and it is inserted. The shared name public key blob should also be stored by the project system so that it can be used when creating references in other assemblies.
  2. The size of the shared name signature blob is retrieved. Space is allocated in the PE file to hold the signature and information in the NGWS runtime file header set to point to this space.
  3. The PE file is saved to disk.
  4. The Shared Name signature blob is then generated. The calling program provides the name of the PE file and the shared name keys to use. The signature function will compute the signature and, optionally, insert it into the defined section in the PE file.

The below APIs support these operations. In each function, the shared name key pair may be provided as a portable key blob, or a container name reference to a key pair already installed in the shared name CSP. The shared name CSP, hash algorithm, and signing algorithms based on the default machine settings.

This method below supports retrieval of the public key blob.

   BOOL StrongNameGetPublicKey (  
      // [in] desired key container name
      LPCWSTR         szContainer, 
      // [in] public/private key blob (optional)
      BYTE            *pbKeyBlob,
      ULONG            cbKeyBlob
      // [out] public key blob
      BYTE            **ppbPublicKeyBlob,
      ULONG            *pcbPublicKeyBlob)

This function will attempt to acquire the shared name CSP context with the provided szContainer name. If pbKeyBlob is NULL, then it is assumed the key pair is already installed in the CSP so the container must exist and it must contain a public key pair associated with a signing algorithm.

If pbKeyBlob is non-NULL, then the CSP is acquired with CRYPT_NEWKEYSET. In this case, an error is returned if the container name exists. If we acquire the CSP successfully, then the key pair in key blob will be imported. In this case, the key pair will be deleted before the function returns.

We will allocate the buffer to hold the public key blob and return a reference to it in ppbPublicKeyBlob. This buffer should be freed by calling StrongNameFreeBuffer().

The returned PublicKeyBlob with be encoded as:

   Struct {
      ALG_ID   SigAlgID;     // strong name signature algorithm
      ALG_ID   HashAlgID;    // strong name hash algorithm
      ULONG      cbPublicKey; // length of the key in bytes
      BTYE[]   PublicKey;    // variable length byte array 
                              containing the key value in format 
                              output by CryptoAPI
   } PublicKeyBlob;

The following method supports the signature operations. It can be used to retrieve the size of signature blob so that space in the PE file can be allocated. It is then used to generate the signature. The function will optionally write the signature directly into the PE file or return the signature blob to the caller.

     BOOL StrongNameSignatureGeneration(  
      // [in] valid path to the PE file for the Assembly
      LPCWSTR         szFilePath, 
      // [in] name of key, if NULL will default to StrongNameKey
      LPCWSTR        szKeyContainer,       
      // [in] public/private key blob (optional)
      BYTE            *pbKeyBlob,
      ULONG            cbKeyBlob
   // [in/out] signature blob
      BYTE             **ppbSignatureBlob, 
      ULONG          *pcbSignatureBlob)

This function will attempt to acquire the shared name CSP context with the provided szContainer name. If pbKeyBlob is NULL, then it is assumed the key pair is already installed in the CSP so the container must exist and it must contain a public key pair associated with a signing algorithm.

If pbKeyBlob is non-NULL, then the CSP is acquired with CRYPT_NEWKEYSET. In this case, the container name should not exist. If we acquire the CSP successfully,then the key pair in key blob will be imported. In this case, the key pair will be deleted before the function returns.

If szFilePath is NULL, it indicates that only the size of the signature blob should be returned. This is returned in the location pointed at by *pcbSignatureBlob.

If szFilePath is non_NULL, then we then hash the PE file and sign the hash signed using the private key. Hash computation excludes some sections of the PE image (section reserved for the signature blob, file CRC, and so on) that will change once the signature blob is added to the file.

If ppbSignatureBlob is NULL, this function will insert the signature blob into a reserved section in the PE and perform any required PE fix-ups (e.g., CRC). If the caller wishes to handle the signature blob and its insertion into the PE file, then ppbSignatureBlob should be a valid pointer to a pointer variable.

If the signature blob is returned to the calling program, the buffer holding it will be allocated by this function. When no longer needed, it should be freed by calling StrongNameFreeBuffer().

The following method returns the size of the signature blob given only the public key. This is to support the “Deferred Signing” and “Test Signing” approaches described below.

SNAPI StrongNameSignatureSize(
 BYTE    *pbPublicKeyBlob, // [in] public key blob
 ULONG    cbPublicKeyBlob,
 DWORD   *pcbSize);        // [out] size of the signature in bytes