5.3.3.1.2 Signing a Proprietary Certificate

The Proprietary Certificate is signed by using RSA to encrypt the hash of the first six fields with the Terminal Services private signing key (specified in section 5.3.3.1.1) and then appending the result to the end of the certificate. Mathematically the signing operation is formulated as follows:

 s = m^d mod n

Where

 s = signature; 
 m = hash of first six fields of certificate
 d = private exponent
 n = modulus

The structure of the Proprietary Certificate is detailed in section 2.2.1.4.3.1.1. The structure of the public key embedded in the certificate is described in 2.2.1.4.3.1.1.1. An example of public key bytes (in little-endian format) follows.

 0x52 0x53 0x41 0x31: magic (0x31415352)
 0x48 0x00 0x00 0x00: keylen (72 bytes)
 0x00 0x02 0x00 0x00: bitlen (512 bits)
 0x3f 0x00 0x00 0x00: datalen (63 bytes)
 0x01 0x00 0x01 0x00: pubExp (0x00010001)
  
 0xaf 0xfe 0x36 0xf2 0xc5 0xa1 0x44 0x2e
 0x47 0xc1 0x31 0xa7 0xdb 0xc6 0x67 0x02
 0x64 0x71 0x5c 0x00 0xc9 0xb6 0xb3 0x04
 0xd0 0x89 0x9f 0xe7 0x6b 0x24 0xe8 0xe8
 0xe5 0x2d 0x0b 0x13 0xa9 0x0c 0x6d 0x4d
 0x91 0x5e 0xe8 0xf6 0xb3 0x17 0x17 0xe3
 0x9f 0xc5 0x4d 0x4a 0xba 0xfa 0xb9 0x2a
 0x1b 0xfb 0x10 0xdd 0x91 0x8c 0x60 0xb7: modulus

A 128-bit MD5 hash over the first six fields of the proprietary certificate (which are all in little-endian format) appears as follows.

 PublicKeyBlob = wBlobType + wBlobLen + PublicKeyBytes
 hash = MD5(dwVersion + dwSigAlgID + dwKeyAlgID + PublicKeyBlob)

Because the Terminal Services private signing key has a 64-byte modulus, the maximum number of bytes that can be encoded by using the key is 63 (the size of the modulus, in bytes, minus 1). An array of 63 bytes is created and initialized as follows.

 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 
 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff
 0x00 0xff 0xff 0xff 0xff 0xff 0xff 0xff 
 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff
 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 
 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff
 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 
 0xff 0xff 0xff 0xff 0xff 0xff 0x01

The 128-bit MD5 hash is copied into the first 16 bytes of the array. For example, assume that the generated hash is as follows.

 0xf5 0xcc 0x18 0xee 0x45 0xe9 0x4d 0xa6
 0x79 0x02 0xca 0x76 0x51 0x33 0xe1 0x7f

The byte array will appear as follows after copying in the 16 bytes of the MD5 hash.

 0xf5 0xcc 0x18 0xee 0x45 0xe9 0x4d 0xa6
 0x79 0x02 0xca 0x76 0x51 0x33 0xe1 0x7f
 0x00 0xff 0xff 0xff 0xff 0xff 0xff 0xff 
 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff
 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 
 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff
 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 
 0xff 0xff 0xff 0xff 0xff 0xff 0x01

The 63-byte array is then treated as an unsigned little-endian integer and signed with the Terminal Services private key by using RSA. The resultant signature has to be in little-endian format before appending it to the Proprietary Certificate structure. The final structure of the certificate has to conform to the specification in section 2.2.1.4.3.1.1. This means that fields 7 through to 9 will be the signature BLOB type, the number of bytes in the signature and the actual signature bytes respectively. The BLOB type and number of bytes have to be in little-endian format.

Example Java source code that shows how to use a private 64-byte asymmetric key to sign an array of 63 bytes using RSA is presented in section 4.9. The code also shows how to use the associated public key to verify the signature.