Extracting Public Key Blobs

(Updated 12/3/04 for code refactoring)

Before letting another two months pass, its time to once again update the managed sn.exe port.  Today's update adds three modes, each of which allow extraction of a public key blob from various sources:

Flag Description StrongName API
-e Extract the public key from an assembly StrongNameTokenFromAssemblyEx
-p Extract the public key from a key blob StrongNameGetPublicKey
-pc Extract the public key from a key container StrongNameGetPublicKey

These are both relatively easy APIs, so lets take a look at them one at a time.

StrongNameTokenFromAssemblyEx

StrongNameTokenFromAssemblyEx extracts the public key token from an assembly's PE file, however it also extracts the public key from the file.  Since it gives both pieces of information, we can use this API to implement the -e flag, and just throw away the token.  StrongNameTokenFromAssemblyEx takes five parameters:

Parameter Use
wszFilePath full path to the assembly to extract the key/token from
ppbStrongNameToken [out] pointer to a buffer containing the token
pcbStrongNameToken [out] size of the buffer returned in ppbStrongNameToken
ppbPublicKeyBlob [out] pointer to a buffer containing the public key blob
pcbPublicKeyBlob [out] size of the buffer returned in ppbPublicKeyBlob

Using this method is extremely easy.  Simply pass the path of the assembly who's public key information is required in, and it passes you out the public key token and public key blob for that assembly.  Of course you must call StrongNameFreeBuffer on both of the output buffers, or your code will leak memory.

Since this method is very straight forward to use, you'll find the code in Keys::ExtractPublicKeyFromAssembly (in MS.StrongName\Keys.cs) very easy to follow as well.  All this method does is call into the StrongNameFromTokenEx method, copy the returned byte array into a managed array, then free the two returned arrays.

StrongNameGetPublicKey

StrongNameGetPublicKey is almost as easy to use as StrongNameTokenFromAssembly.  It also requires five parameters:

Parameter Use
wszKeyContainer key container to extract the public key from
pbKeyBlob key blob to extract the public key from
cbKeyBlob size of pbKeyBlob
ppbPublicKeyBlob [out] pointer to a buffer containing the public key blob
pcbPublicKeyBlob [out] size of the buffer returned in ppbPublicKeyBlob

StrongNameGetPublicKey is overloaded to get the public key out of a key blob that is either stored in a key container, or held in a key pair blob.  Either way, the return value is placed in a buffer pointed to by ppbPublicKeyBlob, and that buffer's size is placed in pcbKeyBlob.  Again, you must call StrongNameFreeBuffer on this key blob, or you'll end up leaking memory.

If you'd like to extract the public key from a key container, simply pass in the key container name in the wszKeyContainer parameter, and place null values in pbKeyBlob and cbKeyBlob.  This is the approach taken by Keys::ExtractPublicKeyFromKeyContainer in MS.StrongName\Keys.cs.  This method simply pases the key container name into StrongNameGetPublicKey, copies the key into a managed array, and releases the buffer allocated by the API.

Extracting a public key from a key pair is just as easy.  This time, pass null for the key container name, and pass in the key pair blob in pbKeyBlob and cbKeyBlob.  You'll recall from how we generate keys that .snk files are simply raw dumps of key pair blobs.  Since the -p mode is used to extract the public key from a .snk file, all we need to do is read the .snk into a byte array, and pass that to StrongNameGetPublicKey.  You'll see that's exactly what Keys::ExtractPublicKeyFromKeyPair() (again in MS.StrongName\Keys.cs) does.

Source Changes

Modified

  • msn\msn.cs
    • added the -e, -p, and -pc modes
  • msn\msn.resx
    • added extra resources to support public key extraction

Added

  • StrongName.Native\Extraction.cs
    • P/Invoke declarations for StrongNameGetPublicKey and StrongNameTokenFromAssemblyEx
  • msn\Extraction.cs
    • Implementation of -e, -p, and -pc