2.5.1.5 CryptoAPI Digital Signature Generation
The hash used to generate a document signature is created by recursively traversing the OLE compound file streams (1) and storages. Certain streams (1) and storages MUST NOT be used, as specified later in this section. A document can have more than one signature, each of which MUST be generated by using the GenerateSignature function. Each individual certificate MUST be stored in the CertificateInfoArray of the CryptoAPI Digital Signature structure.
Let H() be a hashing function, which MUST be MD5, and a plus sign (+) represent concatenation. Let HashObject be an object that can be initialized, that can append data in blocks into the object, and that can finalize to extract the resultant hash value Hfinal.
Let ClsID be the GUID identifier for an OLE compound file storage as specified in [MS-CFB].
Let TimeStamp be a FILETIME structure as specified in [MS-DTYP], containing the current system time, expressed in Coordinated Universal Time (UTC). TimeStamp MUST be stored in the CryptoAPI Digital Signature Structure SignTime field, as specified in section 2.5.1.3.
Let ExcludedStorages be defined as follows:
0x06DataSpaces
0x05Bagaaqy23kudbhchAaq5u2chNd
Let ExcludedStreams be defined as follows:
_signatures
0x09DRMContent
FUNCTION GenerateSignature PARAMETERS Storage, Certificate RETURNS Signature CALL HashObject.Initialize CALL GenerateSignatureHash(Storage, HashObject, IsFiltered, AppFilter) SET Hdata TO HashObject.Finalize SET Hfinal TO H(Hdata + TimeStamp) SET Signature TO RFC3447(Hfinal, Certificate) RETURN Signature END FUNCTION
In the GenerateSignatureHash function, IsFiltered MUST be true if the document conforms to the details as specified in [MS-XLS] and the stream (1) name is "Workbook" or if the document conforms to the details as specified in [MS-PPT] and the stream (1) name is "Current User". It MUST be false for all other document types and streams (1).
For documents that conform to the details as specified in [MS-XLS], let AppFilter be defined as the process specified in [MS-XLS] section 2.1.7.15, which appends data to HashObject, excluding a portion of the stream (1) from being used in the hashing operation.
For documents that conform to the details as specified in [MS-PPT], let AppFilter be defined as a process that returns without appending data to HashObject. The result is that the name of the CurrentUser stream (1) MUST be appended to the HashObject, but the data contained within the CurrentUser stream (1) MUST NOT be appended to the HashObject.
When stream (1) or storage names are appended to a HashObject, the terminating Unicode null character MUST NOT be included.
Let SORT be a string sorting method that is case sensitive and ascending and that skips any nonprintable characters, such that if two streams (1) named "Data" and "0x05DocumentSummaryInformation" are input, the stream (1) named "Data" is ordered first.
-
FUNCTION GenerateSignatureHash PARAMETERS Storage, HashObject, IsFiltered, AppFilter RETURNS VOID DECLARE StorageNameArray as (empty array of Unicode strings) DECLARE StreamNameArray as (empty array of Unicode strings) SET ClsID TO Storage.GUID CALL HashObject.AppendData(ClsID) FOR EACH Child IN Storage.Children IF Child IS a storage AND Child.Name NOT IN ExcludedStorages APPEND Child.Name to StorageNameArray END IF IF Child IS a stream AND Child.Name NOT IN ExcludedStreams APPEND Child.Name to StreamNameArray END IF END FOR SORT StorageNameArray SORT StreamNameArray FOR EACH StreamName IN StreamNameArray CALL HashObject.AppendData(StreamName) SET ChildStream TO Storage.Children[StreamName] IF IsFiltered IS true CALL AppFilter(ChildStream, HashObject) ELSE CALL HashObject.AppendData(ChildStream.Data) ENDIF ENDFOR FOR EACH StorageName IN StorageNameArray CALL HashObject.AppendData(StorageName) SET ChildStorage TO Storage.Children[StorageName] CALL GenerateSignatureHash(ChildStorage, HashObject, IsFiltered, AppFilter) END FOR END FUNCTION
When signing Hfinal, the certificate MUST be an RSA certificate as specified in [RFC3447], and the signing operation MUST be performed as specified in [RFC3447] section 9.2.
If a document is protected as specified in section 2.2, the hash MUST be created by first appending the unencrypted form of the storage that is decrypted from the 0x09DRMContent stream (1), followed by the entire original encrypted file storage with the 0x09DRMContent stream (1) excluded as noted previously.