This seems to imply that if a password is entered in a script like Armenian or Ethiopic then the characters will be replaced all by a single character 0×3F, making the protection feature useless. This is unacceptable.
Proposed change: Remedy so password hashes can be calculated on any Unicode password.
3.2.29 [p1916, Armenian and Ethiopic ]
te
Proposed Disposition of DIS 29500 Comment GB-0292 (Modified: 2008-01-13) Agreed; several national bodies provided valid concerns that the existing legacy hashing mechanisms were insufficient within the context of the specification, and we believe that these concerns warrant the replacement of the existing mechanisms with a new mechanism which: Takes as input the UTF-16 encoding of the input string (and therefore does not have problems with characters above the Latin-1 Unicode subrange) Feeds them directly to hash algorithms which have been standardized after appropriate cryptographic review Stores the resulting hash value, salt, and spin count within the Office Open XML document This change will be made in each instance where a password is stored throughout WordprocessingML, SpreadsheetML, and PresentationML. However, in order to ensure that existing binary documents which contain the “legacy” hash can be correctly interpreted and migrated across multiple vendors/platforms, we will remove these mechanisms from their current location in the specification, and place them into a new annex for deprecated features. Following the precedent set by other ISO standards (such as SQL’s ISO 9075:2003 Part 1 and C++’s ISO/IEC 14882:1998), we will make use of a new Annex that contains normative descriptions of all deprecated features. The intent of this Annex is to enable a transitional period during which existing binary documents being migrated to DIS 29500 can make use of those deprecated features to preserve their fidelity, while noting that new documents should not use them. Accordingly, the Conformance clause will also be changed to state that newly created documents (those not created by migrating existing binary documents) should not use deprecated features. All deprecated features will be removed from their current locations in the standard, but will be fully defined in this new Annex. To complete this replacement, the following changes will be made: Part 4, §2.15.1.28, pages 1,1581,172: 2.15.1.28 documentProtection (Document Editing Restrictions) This element specifies the set of document protection restrictions which have been applied to the contents of a WordprocessingML document. These restrictions shall be enforced by applications editing this document when the enforcement attribute is turned on, and should be ignored (but persisted) otherwise. Document protection is a set of restrictions used to prevent unintentional changes to all or part of a WordprocessingML document - since this protection does not encrypt the document, malicious applications may circumvent its use. This protection is not intended as a security feature and may be ignored. If this element is omitted, then no protection shall be applied to this document. When a password is to be hashed and stored in this element, it shall be hashed as defined below, starting from a UTF-16 encoded string value. When a password is supplied via an application which shall be hashed and stored in this element, that process shall be done in two stages: First, the password shall be hashed using the following algorithm: Truncate the password to 15 characters. Construct a new NULL-terminated string consisting of single-byte characters: Get the single-byte values by iterating through the Unicode characters of the truncated password. For each character, if the low byte is not equal to 0, take it. Otherwise, take the high byte. From now on, the single-byte character string is used. If the password is empty, return 0. Compute the high-order word of the new key: Initialize from the initial code array (see below), depending on the password’s length. For each character in the password: For every bit in the character, starting with the least significant and progressing to (but excluding) the most significant, if the bit is set, XOR the key’s high-order word with the corresponding word from the encryption matrix Compute the low-order word of the new key: Initialize with 0 For each character in the password, going backwards, low-order word = (((low-order word SHR 14) AND 0×0001) OR (low-order word SHL 1) AND 0×7FFF)) XOR character Lastly, low-order word = (((low-order word SHR 14) AND 0×0001) OR (low-order word SHL 1) AND 0×7FFF)) XOR password length XOR 0xCE4B. Initial code array The initial code array contains the initial values for the key’s high-order word. The initial value depends on the length of the password, as follows: Password length Initial value for the key’s high-order word 1 0xE1F0 2 0×1D0F 3 0xCC9C 4 0×84C0 5 0×110C 6 0×0E10 7 0xF1CE 8 0×313E 9 0×1872 10 0xE139 11 0xD40F 12 0×84F9 13 0×280C 14 0xA96A 15 0×4EC3 Encryption matrix The encryption matrix contains codes used during the calculation of the key’s high-order word. As described in the algorithm above, for every bit of the password’s characters, if the bit is set, a corresponding value is taken from this encryption matrix and is used to XOR the key’s high-order word with it. Each row in the encryption matrix corresponds to a single character from the password, and each of the seven columns corresponds to a particular bit (0-6) in this character. The values are taken in such a way so that the last character of the password uses the last row in the encryption matrix. The next-to-last character uses the next-to-last row in the matrix, and so on. This means that the beginning of the matrix may be unused, depending on the length of the password. Bit 0 Bit 1 Bit 2 Bit 3 Bit 4 Bit 5 Bit 6 Last-14 0xAEFC 0×4DD9 0×9BB2 0×2745 0×4E8A 0×9D14 0×2A09 Last-13 0×7B61 0xF6C2 0xFDA5 0xEB6B 0xC6F7 0×9DCF 0×2BBF Last-12 0×4563 0×8AC6 0×05AD 0×0B5A 0×16B4 0×2D68 0×5AD0 Last-11 0×0375 0×06EA 0×0DD4 0×1BA8 0×3750 0×6EA0 0xDD40 Last-10 0xD849 0xA0B3 0×5147 0xA28E 0×553D 0xAA7A 0×44D5 Last-9 0×6F45 0xDE8A 0xAD35 0×4A4B 0×9496 0×390D 0×721A Last-8 0xEB23 0xC667 0×9CEF 0×29FF 0×53FE 0xA7FC 0×5FD9 Last-7 0×47D3 0×8FA6 0×0F6D 0×1EDA 0×3DB4 0×7B68 0xF6D0 Last-6 0xB861 0×60E3 0xC1C6 0×93AD 0×377B 0×6EF6 0xDDEC Bit 0 Bit 1 Bit 2 Bit 3 Bit 4 Bit 5 Bit 6 Last-5 0×45A0 0×8B40 0×06A1 0×0D42 0×1A84 0×3508 0×6A10 Last-4 0xAA51 0×4483 0×8906 0×022D 0×045A 0×08B4 0×1168 Last-3 0×76B4 0xED68 0xCAF1 0×85C3 0×1BA7 0×374E 0×6E9C Last-2 0×3730 0×6E60 0xDCC0 0xA9A1 0×4363 0×86C6 0×1DAD Last-1 0×3331 0×6662 0xCCC4 0×89A9 0×0373 0×06E6 0×0DCC Last 0×1021 0×2042 0×4084 0×8108 0×1231 0×2462 0×48C4 [Example: Consider a password which has been supplied - the string “Example”. It is already under 15 characters, so truncation does not affect it. It is then converted to a string of single-byte characters. The password is 7 characters long, so, from the initial code array, the initial value for the key’s high-order word is 0xF1CE. The key’s high-order word is then computed further depending on the password’s characters: The first character is `E’ (0×45). This is the first character of a 7-character password, so its corresponding row in the encryption matrix is “Last-6″. Bit 0 is set, therefore the key’s high-order word is combined (via XOR) with the corresponding value for Bit 0 on row “Last-6″, which is 0xB861. The new result is 0xF1CE XOR 0xB861 = 0×49AF. Bit 2 is set, so the key’s high-order word is XOR-ed with the corresponding value for Bit 2 on row “Last-6″, which is 0xC1C6. The new result is 0×49AF XOR 0xC1C6 = 0×8869. This process is repeated for each bit. The next character is `x’ (0×78). Its corresponding row in the encryption matrix is “Last-5″. Bit 3 is set. The value for Bit 3 on row “Last-5″ in the encryption matrix is 0×0D42. The current value for the key’s high-order byte is 0×5585, so the new one should be 0×5585 XOR 0×0D42 = 0×58C7. This process is repeated for each bit. This process is repeated for all characters. After the last character has been processed, the above step produced 0×64CE for the key’s high-order word. Now the low-order word needs to be calculated: The initial value is 0. It is then calculated using the password: The last character of the password is `e’ (0×65), so, by the formula, low-order word = (((low-order word SHR 14) AND 0×0001) OR ((low-order word SHL 1) AND 0×7FFF)) XOR `e’ = (((0 SHR 14) AND 0×0001) OR ((0 SHL 1) AND 0×7FFF)) XOR 0×65 = 0×0065. The next to last character of the password is `l’ (0×6C). Again, by the formula, (((0×0065 SHR 14) AND 0×0001) OR ((0×0065 SHL 1) AND 0×7FFF)) XOR 0×6C = (0×0000 OR 0×00CA) XOR 0×6C = 0×00CA XOR 0×6C = 0×00A6. This process is repeated for each character. After the password’s first character has been processed, we have 0×1199 for the key’s low-order word. Lastly, the password’s length is combined into it: low-order word = (((0×1199 SHR 14) AND 0×0001) OR ((0×1199 SHL 1) AND 0×7FFF)) XOR 0×0007 XOR 0xCE4B = 0×2332 XOR 0×0007 XOR 0xCE4B = 0×2335 XOR 0xCE4B = 0xED7E. The end result for the key is 0×64CEED7E. end example] [Rationale: This pre-processing step is necessary for compatibility with legacy word processing applications which hashed their password solely using this mechanism. end rationale] Second, the byte order of the result shall be reversed [Example: 0×64CEED7E becomes 7EEDCE64. end example], and that value shall be hashed as defined by the attribute values. [Note: The algorithm above can be stated as follows using diagrams: Start Convert password to single-byte Password is empty? Compute key’s high-order word No Compute key’s low-order word Initialize encryption array and index End Key is 0 Yes Calculate Key Start Initialize high-order word from the initial code array depending on password’s length For each character in the password starting with the first one For each bit in the character starting with the least- significant one Is the bit set? XOR high-order word with the corresponding word from the encryption matrix Yes Next bit, up to but excluding the most-significant one Next character End No Compute Key’s High-Order Word Start Initialize low-order word with 0 For each character in the password, going backwards Low-order word = F(low-order word) XOR character Previous character Low-order word = F(low-order word) XOR password length XOR 0xCE4B End Compute Key’s Low -Order Word F(x)=((x SHR 14) AND 0×0001) OR ((x SHL 1) AND 0×7FFF) end note] [Example: Consider a WordprocessingML document which specifies that applications shall not allow any modifications to this document other than the addition of comments. This requirement would be specified using the following WordprocessingML in the document settings: <w:documentProtection w:edit="comments" w:enforcement="true" … w:cryptAlgorithmClass="hash" w:cryptAlgorithmType="typeAny" w:cryptAlgorithmSid="1" w:hash="9oN7nWkCAyEZib1RomSJTjmPpCY=" /> The documentProtection element has an edit attribute value of comments , specifying that the only modification allowed should be comments, the enforcement attribute has a value of true , specifying that the document protection specified is to be enforced on the given document. Finally, in order for the hosting application to stop enforcement of the document protection applied to the document, the hosting application would have to be provided with a password that the hosting application would then hash, compare to the value of the hash attribute ( 9oN7nWkCAyEZib1RomSJTjmPpCY= ), and if the two values matched, halt enforcement of any document protection. end example] Parent Elements settings (§2.15.1.78) Attributes Description algorithmName (Cryptographic Algorithm Name) Specifies the specific cryptographic hashing algorithm which shall be used along with the salt attribute and input password in order to compute the hash value. The following values are reserved: Value Algorithm MD2 Specifies that the MD2 algorithm, as defined by RFC 1319, shall be used. [Note: It is recommended that applications should avoid using this algorithm to store new hash values, due to publically known breaks. end note] MD4 Specifies that the MD4 algorithm, as defined by RFC 1320, shall be used. [Note: It is recommended that applications should avoid using this algorithm to store new hash values, due to publically known breaks. end note] MD5 Specifies that the MD5 algorithm, as defined by RFC 1321, shall be used. [Note: It is recommended that applications should avoid using Attributes Description this algorithm to store new hash values, due to publically known breaks. end note] RIPEMD-128 Specifies that the RIPEMD-128 algorithm, as defined by ISO/IEC 10118-3:2004 shall be used. [Note: It is recommended that applications should avoid using this algorithm to store new hash values, due to publically known breaks. end note] RIPEMD-160 Specifies that the RIPEMD-160 algorithm, as defined by ISO/IEC 10118-3:2004 shall be used. SHA-1 Specifies that the SHA-1 algorithm, as defined by ISO/IEC 10118-3:2004 shall be used. SHA-256 Specifies that the SHA-256 algorithm, as defined by ISO/IEC 10118-3:2004 shall be used. SHA-384 Specifies that the SHA-384 algorithm, as defined by ISO/IEC 10118-3:2004 shall be used. SHA-512 Specifies that the SHA-512 algorithm, as defined by ISO/IEC 10118-3:2004 shall be used. WHIRLPOOL Specifies that the WHIRLPOOL algorithm, as defined by ISO/IEC 10118-3:2004 shall be used. [Example: Consider an Office Open XML document with the following information stored in one of its protection elements: < … algorithmName="SHA-1" hashValue="9oN7nWkCAyEZib1RomSJTjmPpCY=" /> The algorithmName attribute value of “SHA-1″ specifies that the SHA-1 hashing algorithm shall be used to generate a hash from the user-defined password. end example] The possible values for this attribute are defined by the ST_String simple type (§2.18.19). algIdExt (Cryptographic Algorithm Extensibility) Specifies that a cryptographic algorithm which was not defined by this Office Open XML Standard has been used to generate the hash value stored with this document. This value, when present, shall be interpreted based on the value of the algIdExtSource attribute in order to determine the algorithm used, which shall be application-defined. [Rationale: This extensibility affords the fact that with exponentially increasing computing power, documents created in the future will likely need to utilize as yet undefined hashing algorithms in order to remain secure. end rationale] Attributes Description If this value is present, the cryptAlgorithmClass, cryptAlgorithmType, and cryptAlgorithmSid attribute values shall be ignored in favor of the algorithm defined by this attribute. [Example: Consider a WordprocessingML document with the following information stored in one of its protection elements: <w:… w:algIdExt="0000000A" w:algIdExtSource="futureCryptography" w:hash="9oN7nWkCAyEZib1RomSJTjmPpCY=" /> The algIdExt attribute value of 0000000A specifies that the algorithm with hex code A shall be used as defined by the futureCryptography application. end example] The possible values for this attribute are defined by the ST_LongHexNumber simple type (§2.18.57). algIdExtSource (Algorithm Extensibility Source) Specifies the application which defined the algorithm value specified by the algIdExt attribute. [Example: Consider a WordprocessingML document with the following information stored in one of its protection elements: <w:… w:algIdExt="0000000A" w:algIdExtSource="futureCryptography" w:hash="9oN7nWkCAyEZib1RomSJTjmPpCY=" /> The algIdExtSource attribute value of futureCryptography specifies that the algorithm used here was published by the futureCryptography application. end example] The possible values for this attribute are defined by the ST_String simple type (§2.18.89). cryptAlgorithmCl ass (Cryptographic Algorithm Class) Specifies the class of cryptographic algorithm used by this protection. [Note: The initial version of this Office Open XML Standard only supports a single version - hash - but future versions may expand this as necessary. end note] [Example: Consider a WordprocessingML document with the following information stored in one of its protection elements: <w:… w:cryptAlgorithmClass="hash" w:cryptAlgorithmType="typeAny" w:cryptAlgorithmSid="1" w:hash="9oN7nWkCAyEZib1RomSJTjmPpCY=" /> Attributes Description The cryptAlgorithmClass attribute value of hash specifies that the algorithm used for the password is a hashing algorithm. end example] The possible values for this attribute are defined by the ST_AlgClass simple type (§2.18.1). cryptAlgorithmSi d (Cryptographic Hashing Algorithm) Specifies the specific cryptographic hashing algorithm which shall be used along with the salt attribute and user-supplied password in order to compute a hash value for comparison. The possible values for this attribute shall be interpreted as follows: Value Algorithm 1 MD2 2 MD4 3 MD5 4 SHA-1 5 MAC 6 RIPEMD 7 RIPEMD-160 8 Undefined. Shall not be used. 9 HMAC 10 Undefined. Shall not be used. 11 Undefined. Shall not be used. 12 SHA-256 13 SHA-384 14 SHA-512 Any other value Undefined. Shall not be used. [Example: Consider a WordprocessingML document with the following information stored in one of its protection elements: <w:… w:cryptAlgorithmClass="hash" w:cryptAlgorithmType="typeAny" w:cryptAlgorithmSid="1" w:hash="9oN7nWkCAyEZib1RomSJTjmPpCY=" /> The cryptAlgorithmSid attribute value of 1 specifies that the SHA-1 hashing algorithm shall be used to generate a hash from the user-defined password. end example] Attributes Description The possible values for this attribute are defined by the ST_DecimalNumber simple type (§2.18.16). cryptAlgorithmT ype (Cryptographic Algorithm Type) Specifies the type of cryptographic algorithm used by this protection. [Note: The initial version of this Office Open XML Standard only supports a single type - typeAny - but future versions may expand this as necessary. end note] [Example: Consider a WordprocessingML document with the following information stored in one of its protection elements: <w:… w:cryptAlgorithmClass="hash" w:cryptAlgorithmType="typeAny" w:cryptAlgorithmSid="1" w:hash="9oN7nWkCAyEZib1RomSJTjmPpCY=" /> The cryptAlgorithmType attribute value of typeAny specifies that any type of algorithm may have been used for the password. end example] The possible values for this attribute are defined by the ST_AlgType simple type (§2.18.2). cryptProvider (Cryptographic Provider) Specifies the cryptographic provider which was used to generate the hash value stored in this document. If the user provided a cryptographic provider which was not the system’s built-in provider, then that provider shall be stored here so it can subsequently be used if available. If this attribute is omitted, then the built-in cryptographic provider on the system shall be used. [Example: Consider a WordprocessingML document with the following information stored in one of its protection elements: <w:… w:cryptProvider="Krista’sProvider" w:hash="9oN7nWkCAyEZib1RomSJTjmPpCY=" /> The cryptProvider attribute value of Krista’sProvider specifies that the cryptographic provider with name "Krista’s Provider" shall be used if available. end example] The possible values for this attribute are defined by the ST_String simple type (§2.18.89). cryptProviderTyp e (Cryptographic Provider Type) Specifies the type of cryptographic provider to be used. [Example: Consider a WordprocessingML document with the following information stored in one of its protection elements: <w:… w:cryptProviderType="rsaAES" Attributes Description w:hash="9oN7nWkCAyEZib1RomSJTjmPpCY=" /> The cryptProviderType attribute value of rsaAES specifies that the cryptographic provider type shall be an Advanced Encryption Standard provider. end example] The possible values for this attribute are defined by the ST_CryptProv simple type (§2.18.14). cryptProviderTyp eExt (Cryptographic Provider Type Extensibility) Specifies that a cryptographic provider type which was not defined by this Office Open XML Standard has been used to generate the hash value stored with this document. This value, when present, shall be interpreted based on the value of the cryptProviderTypeExtSource attribute in order to determine the provider type used, which shall be application-defined. [Rationale: This extensibility affords the fact that with exponentially increasing computing power, documents created in the future will likely need to utilize as yet undefined cryptographic provider types in order to remain secure. end rationale] If this value is present, the cryptProviderType attribute value shall be ignored in favor of the provider type defined by this attribute. [Example: Consider a WordprocessingML document with the following information stored in one of its protection elements: <w:… w:cryptProviderTypeExt="00A5691D" w:cryptProvideTypeExtSource="futureCryptography" w:hash="9oN7nWkCAyEZib1RomSJTjmPpCY=" /> The cryptProviderTypeExt attribute value of 00A5691D specifies that the provider type associated with hex code A5691D shall be used as defined by the futureCryptography application. end example] The possible values for this attribute are defined by the ST_LongHexNumber simple type (§2.18.57). cryptProviderTypeExtSource (Provider Type Extensibility Source) Specifies the application which defined the provider type value specified by the cryptProviderTypeExt attribute. [Example: Consider a WordprocessingML document with the following information stored in one of its protection elements: <w:… w:cryptProviderTypeExt="00A5691D" w:cryptProvideTypeExtSource="futureCryptography" w:hash="9oN7nWkCAyEZib1RomSJTjmPpCY=" /> The cryptProvideTypeExtSource attribute value of futureCryptography Attributes Description specifies that the provider type used here was published by the futureCryptography application. end example] The possible values for this attribute are defined by the ST_String simple type (§2.18.89). cryptSpinCount (Iterations to Run Hashing Algorithm) Specifies the number of times the hashing function shall be iteratively run (using each iteration’s result as the input for the next iteration) when attempting to compare a user-supplied password with the value stored in the hash attribute. [Rationale: Running the algorithm many times increases the cost of exhaustive search attacks correspondingly. Storing this value allows for the number of iterations to be increased over time to accommodate faster hardware (and hence the ability to run more iterations in less time). end rationale] [Example: Consider a WordprocessingML document with the following information stored in one of its protection elements: <w:… w:cryptSpinCount="100000" w:hash="9oN7nWkCAyEZib1RomSJTjmPpCY=" /> The cryptSpinCount attribute value of 100000 specifies that the hashing function shall be run one hundred thousand times to generate a hash value for comparison with the hash attribute. end example] The possible values for this attribute are defined by the ST_DecimalNumber simple type (§2.18.16). edit (Document Editing Restrictions) Specifies the set of editing restrictions which shall be enforced on a given WordprocessingML document, as defined by the simple type referenced below If this attribute is omitted, the consumer shall behave as though there are no editing restrictions applied to this document; equivalent to an attribute value of none . [Example: Consider a WordprocessingML document that contains the following WordprocessingML specifying that hosting applications shall enforce read-only protection for a given document: <w:documentProtection w:edit="readOnly" w:enforcement="1" /> The edit attribute has a value of readOnly and a enforcement attribute with a value of 1 , specifying that read-only document protection shall be enforced on the given document. end example] The possible values for this attribute are defined by the ST_DocProtect simple type (§2.18.22). Attributes Description enforcement (Enforce Document Protection Settings) Specifies if the document protection settings shall be enforced for a given WordprocessingML document. If the value of this element is off , 0 , or false , all the WordprocessingML pertaining to document protection is still preserved in the document, but is not enforced. If the value of this element is on , 1, or true , the document protection is enforced. If this attribute is omitted, then document protection settings shall not be enforced by applications. [Example: Consider a WordprocessingML document that contains the following WordprocessingML specifying that hosting applications shall apply read-only protection for a given document: <w:documentProtection w:edit="readOnly" w:enforcement="1" /> The enforcement attribute has a value of 1, specifying that the document protection specified shall be enforced on the given document. end example] The possible values for this attribute are defined by the ST_OnOff simple type (§2.18.67). formatting (Only Allow Formatting With Unlocked Styles) Specifies if formatting restrictions are in effect for a given WordprocessingML document. This enables the document to restrict the types of styles that may exist in a given WordprocessingML document. Specifically, by setting this attribute’s value equal to true , every style whose locked element (§2.7.3.7) has a value of true (or latent styles (§2.7.3.5) whose locked attribute is true ) shall not be available for use in the application, nor should any direct formatting. Only styles with a locked value of false may be used. If this attribute is omitted, then no formatting restrictions shall be applied, even when document protection is enforced. [Example: Consider a WordprocessingML document that shall apply formatting protection. This requirement would be specified using the following WordprocessingML in the document settings: <w:documentProtection w:formatting="true" w:enforcement="true" /> If the following definition for a style was also present in the document: <w:style w:type="paragraph" w:styleId="Heading1"> <w:name w:val="heading 1" /> <w:locked="1" /> … </w:style> Attributes Description The formatting attribute has a value of true specifying that the applications shall not allow the style above to be added to the WordprocessingML document. This does not preclude previous uses of that style (which shall not be removed), but does prevent new uses of this style from being added. end example] The possible values for this attribute are defined by the ST_OnOff simple type (§2.18.67). hash (Password Hash) Specifies the hash value for the password stored with this document. This value shall be compared with the resulting hash value after hashing the user-supplied password using the algorithm specified by the preceding attributes and parent XML element, and if the two values match, the protection shall no longer be enforced. If this value is omitted, then no password shall be associated with the protection, and it may be turned off without supplying any password. [Example: Consider a WordprocessingML document with the following information stored in one of its protection elements: <w:… w:cryptAlgorithmClass="hash" w:cryptAlgorithmType="typeAny" w:cryptAlgorithmSid="1" w:hash="9oN7nWkCAyEZib1RomSJTjmPpCY=" /> The hash attribute value of 9oN7nWkCAyEZib1RomSJTjmPpCY= specifies that the user-supplied password shall be hashed using the pre-processing defined by the parent element (if any) followed by the SHA-1 algorithm (specified via the cryptAlgorithmSid attribute value of 1 ) and that the resulting has value must be 9oN7nWkCAyEZib1RomSJTjmPpCY= for the protection to be disabled. end example] The possible values for this attribute are defined by the XML Schema base64Binary datatype. salt (Salt for Password Verifier) Specifies the salt which was prepended to the user-supplied password before it was hashed using the hashing algorithm defined by the preceding attribute values to generate the hash attribute, and which shall also be prepended to the user-supplied password before attempting to generate a hash value for comparison. A salt is a random string which is added to a user-supplied password before it is hashed in order to prevent a malicious party from pre-calculating all possible password/hash combinations and simply using those precalculated values (often referred to as a "dictionary attack"). If this attribute is omitted, then no salt shall be prepended to the user-supplied password before it is hashed for comparison with the stored hash value. Attributes Description [Example: Consider a WordprocessingML document with the following information stored in one of its protection elements: <w:… w:salt="ZUdHa+D8F/OAKP3I7ssUnQ==" w:hash="9oN7nWkCAyEZib1RomSJTjmPpCY=" /> The salt attribute value of ZUdHa+D8F/OAKP3I7ssUnQ== specifies that the user- supplied password shall have this value prepended before it is run through the specified hashing algorithm to generate a resulting hash value for comparison. end example] The possible values for this attribute are defined by the XML Schema base64Binary datatype. hashValue (Password Hash Value) Specifies the hash value for the password stored with this document. This value shall be compared with the resulting hash value after hashing the user-supplied password using the algorithm specified by the preceding attributes and parent XML element, and if the two values match, the protection shall no longer be enforced. If this value is omitted, then the reservationPassword attribute shall contain the password hash for the workbook. [Example: Consider an Office Open XML document with the following information stored in one of its protection elements: <… AlgorithmName="SHA-1" hashValue="9oN7nWkCAyEZib1RomSJTjmPpCY=" /> The hashValue attribute value of 9oN7nWkCAyEZib1RomSJTjmPpCY= specifies that the user-supplied password shall be hashed using the pre-processing defined by the parent element (if any) followed by the SHA-1 algorithm (specified via the algorithmName attribute value of SHA-1 ) and that the resulting has value must be 9oN7nWkCAyEZib1RomSJTjmPpCY= for the protection to be disabled. end example] The possible values for this attribute are defined by the XML Schema base64Binary datatype. saltValue (Salt Value for Password Verifier) Specifies the salt which was prepended to the user-supplied password before it was hashed using the hashing algorithm defined by the preceding attribute values to generate the hashValue attribute, and which shall also be prepended to the user-supplied password before attempting to generate a hash value for comparison. A salt is a random string which is added to a user-supplied password before it is hashed in order to prevent a malicious party from pre-calculating all possible password/hash combinations and simply using those pre-calculated Attributes Description values (often referred to as a "dictionary attack"). If this attribute is omitted, then no salt shall be prepended to the user-supplied password before it is hashed for comparison with the stored hash value. [Example: Consider an Office Open XML document with the following information stored in one of its protection elements: <… saltValue="ZUdHa+D8F/OAKP3I7ssUnQ==" hashValue="9oN7nWkCAyEZib1RomSJTjmPpCY=" /> The saltValue attribute value of ZUdHa+D8F/OAKP3I7ssUnQ== specifies that the user-supplied password shall have this value prepended before it is run through the specified hashing algorithm to generate a resulting hash value for comparison. end example] The possible values for this attribute are defined by the XML Schema base64Binary datatype. spinCount (Iterations to Run Hashing Algorithm) Specifies the number of times the hashing function shall be iteratively run (using each iteration’s result as the input for the next iteration) when attempting to compare a user-supplied password with the value stored in the hashValue attribute. [Rationale: Running the algorithm many times increases the cost of exhaustive search attacks correspondingly. Storing this value allows for the number of iterations to be increased over time to accommodate faster hardware (and hence the ability to run more iterations in less time). end rationale] [Example: Consider an Office Open XML document with the following information stored in one of its protection elements: <… spinCount="100000" hashValue="9oN7nWkCAyEZib1RomSJTjmPpCY=" /> The spinCount attribute value of 100000 specifies that the hashing function shall be run one hundred thousand times to generate a hash value for comparison with the hashValue attribute. end example] The possible values for this attribute are defined by the ST_DecimalNumber simple type (§2.18.16). The following XML Schema fragment defines the contents of this element: <complexType name="CT_DocProtect"> <attribute name="algorithmName" type="ST_String" use="optional"/> <attribute name="edit" type="ST_DocProtect" use="optional"/> <attribute name="formatting" type="ST_OnOff" use="optional"/> <attribute name="enforcement" type="ST_OnOff"/> <attribute name="hashValue" type="xsd:base64binary" use="optional"/> <attribute name="saltValue" type="xsd:base64binary" use="optional"/> <attribute name="spinCount" type="ST_DecimalNumber" use="optional"/> <attributeGroup ref="AG_Password"/> </complexType> Part 4, §3.2.12, pages 1,8951,896: 3.2.12 fileSharing (File Sharing) This element tracks file sharing File sharing settings for the workbook. When a password is to be hashed and stored in this element, it shall be hashed starting from a UTF-16 encoded string value. Parent Elements workbook (§3.2.27) Attributes Description algorithmName (Cryptographic Algorithm Name) Specifies the specific cryptographic hashing algorithm which shall be used along with the salt attribute and input password in order to compute the hash value. The following values are reserved: Value Algorithm MD2 Specifies that the MD2 algorithm, as defined by RFC 1319, shall be used. [Note: It is recommended that applications should avoid using this algorithm to store new hash values, due to publically known breaks. end note] MD4 Specifies that the MD4 algorithm, as defined by RFC 1320, shall be used. [Note: It is recommended that applications should avoid using this algorithm to store new hash values, due to publically known breaks. end note] MD5 Specifies that the MD5 algorithm, as defined by RFC 1321, shall be used. [Note: It is recommended that applications should avoid using this algorithm to store new hash values, due to publically known Attributes Description breaks. end note] RIPEMD-128 Specifies that the RIPEMD-128 algorithm, as defined by ISO/IEC 10118-3:2004 shall be used. [Note: It is recommended that applications should avoid using this algorithm to store new hash values, due to publically known breaks. end note] RIPEMD-160 Specifies that the RIPEMD-160 algorithm, as defined by ISO/IEC 10118-3:2004 shall be used. SHA-1 Specifies that the SHA-1 algorithm, as defined by ISO/IEC 10118-3:2004 shall be used. SHA-256 Specifies that the SHA-256 algorithm, as defined by ISO/IEC 10118-3:2004 shall be used. SHA-384 Specifies that the SHA-384 algorithm, as defined by ISO/IEC 10118-3:2004 shall be used. SHA-512 Specifies that the SHA-512 algorithm, as defined by ISO/IEC 10118-3:2004 shall be used. WHIRLPOOL Specifies that the WHIRLPOOL algorithm, as defined by ISO/IEC 10118-3:2004 shall be used. [Example: Consider an Office Open XML document with the following information stored in one of its protection elements: < … algorithmName="SHA-1" hashValue="9oN7nWkCAyEZib1RomSJTjmPpCY=" /> The algorithmName attribute value of “SHA-1″ specifies that the SHA-1 hashing algorithm shall be used to generate a hash from the user-defined password. end example] The possible values for this attribute are defined by the ST_XString simple type (§3.18.96). hashValue (Password Hash Value) Specifies the hash value for the password required for editing this workbook. This value shall be compared with the resulting hash value after hashing the user-supplied password using the algorithm specified by the preceding attributes and parent XML element, and if the two values match, the protection shall no longer be enforced. If this value is omitted, then the reservationPassword attribute shall contain the password hash for the workbook. [Example: Consider an Office Open XML document with the following information stored in one of its protection elements: Attributes Description <… AlgorithmName="SHA-1" hashValue="9oN7nWkCAyEZib1RomSJTjmPpCY=" /> The hashValue attribute value of 9oN7nWkCAyEZib1RomSJTjmPpCY= specifies that the user-supplied password shall be hashed using the pre-processing defined by the parent element (if any) followed by the SHA-1 algorithm (specified via the cryptAlgorithmSid attribute value of 1 ) and that the resulting has value must be 9oN7nWkCAyEZib1RomSJTjmPpCY= for the protection to be disabled. end example] The possible values for this attribute are defined by the XML Schema base64Binary datatype. saltValue (Salt Value for Password Verifier) Specifies the salt which was prepended to the user-supplied password before it was hashed using the hashing algorithm defined by the preceding attribute values to generate the hashValue attribute, and which shall also be prepended to the user-supplied password before attempting to generate a hash value for comparison. A salt is a random string which is added to a user-supplied password before it is hashed in order to prevent a malicious party from pre-calculating all possible password/hash combinations and simply using those pre-calculated values (often referred to as a "dictionary attack"). If this attribute is omitted, then no salt shall be prepended to the user-supplied password before it is hashed for comparison with the stored hash value. [Example: Consider an Office Open XML document with the following information stored in one of its protection elements: <… saltValue="ZUdHa+D8F/OAKP3I7ssUnQ==" hashValue="9oN7nWkCAyEZib1RomSJTjmPpCY=" /> The saltValue attribute value of ZUdHa+D8F/OAKP3I7ssUnQ== specifies that the user-supplied password shall have this value prepended before it is run through the specified hashing algorithm to generate a resulting hash value for comparison. end example] The possible values for this attribute are defined by the XML Schema base64Binary datatype. spinCount (Iterations to Run Hashing Algorithm) Specifies the number of times the hashing function shall be iteratively run (using each iteration’s result as the input for the next iteration) when attempting to compare a user-supplied password with the value stored in the hashValue attribute. [Rationale: Running the algorithm many times increases the cost of exhaustive search attacks correspondingly. Storing this value allows for the number of iterations to be increased over time to accommodate faster hardware (and hence Attributes Description the ability to run more iterations in less time). end rationale] [Example: Consider an Office Open XML document with the following information stored in one of its protection elements: <… spinCount="100000" hashValue="9oN7nWkCAyEZib1RomSJTjmPpCY=" /> The SpinCount attribute value of 100000 specifies that the hashing function shall be run one hundred thousand times to generate a hash value for comparison with the hashValue attribute. end example] The possible values for this attribute are defined by the ST_DecimalNumber simple type (§2.18.16). readOnlyRecom mended (Read Only Recommended) Specifies a boolean value that indicates on open, whether the application alerts the user that the file be marked as read-only. The possible values for this attribute are defined by the XML Schema boolean datatype. reservationPassw ord (Write Reservation Password) Specifies the hash of the password required for editing this workbook. This hash is optional and may be ignored. The hash is generated from an 8-bit wide character. 16-bit Unicode characters must be converted down to 8 bits before the hash is computed, using the logic defined in the revisionsPassword attribute of §3.2.29. The resulting value is hashed using the algorithm defined below. [Note: An example algorithm to hash the user input into the value stored is as follows: // Function Input: // szPassword: NULL terminated C-Style string // cchPassword: The number of characters in szPassword (not including the NULL terminator) WORD GetPasswordHash(const CHAR *szPassword, int cchPassword) { WORD wPasswordHash; const CHAR *pch; wPasswordHash = 0; if (cchPassword > 0) { pch = &szPassword[cchPassword]; while (pch– != szPassword) { wPasswordHash = ((wPasswordHash >> 14) & Attributes Description 0×01) | ((wPasswordHash << 1) & 0×7fff); wPasswordHash ^= *pch; } wPasswordHash ^= (0×8000 | (’N’ <<
| ‘K’); } return(wPasswordHash); } end note] The possible values for this attribute are defined by the ST_UnsignedShortHex simple type (§3.18.87). userName (User Name) Specifies the username of the person with write reservation for this workbook. The possible values for this attribute are defined by the ST_Xstring simple type (§3.18.96). The following XML Schema fragment defines the contents of this element: <complexType name="CT_FileSharing"> <attribute name="algorithmName" type="ST_String" use="optional"/> <attribute name="hashValue" type="xsd:base64binary" use="optional"/> <attribute name="saltValue" type="xsd:base64binary" use="optional"/> <attribute name="spinCount" type="ST_DecimalNumber" use="optional"/> <attribute name="readOnlyRecommended" type="xsd:boolean" use="optional" default="false"/> <attribute name="userName" type="ST_Xstring"/> <attribute name="reservationPassword" type="ST_UnsignedShortHex"/> </complexType> Part 4, §3.2.29, pages 1,9151,923: 3.2.29 workbookProtection (Workbook Protection) This element specifies options for protecting data in the workbook. Applications may use workbook protection to prevent anyone from accidentally changing, moving, or deleting important data. This protection may be ignored by applications which choose not to support this optional protection mechanism. When a password is to be hashed and stored in this element, it shall be hashed as defined below, starting from a UTF-16 encoded string value. [Note: Worksheet or workbook element protection should not be confused with file security. It is not meant to make your workbook safe from unintentional modification, and cannot protect it from malicious modification. end note] Parent Elements workbook (§3.2.27) Attributes Description lockRevision (Lock Revisions) Specifies a boolean value that indicates whether the workbook is locked for revisions. The possible values for this attribute are defined by the XML Schema boolean datatype. lockStructure (Lock Structure) Specifies a boolean value that indicates whether structure of workbook is locked. A value of on, 1, or true indicates the structure of the workbook is locked. Worksheets in the workbook can’t be moved, deleted, hidden, unhidden, or renamed, and new worksheets can’t be inserted. A value of off, 0, or false indicates the structure of the workbook is not locked. The default value for this attribute is false. The possible values for this attribute are defined by the XML Schema boolean datatype. lockWindows (Lock Windows) Specifies a boolean value that indicates whether the windows that comprise the workbook are locked. A value of on, 1, or true indicates the workbook windows are locked. Windows are the same size and position each time the workbook is opened. A value of off, 0, or false indicates the workbook windows are not locked. The default value for this attribute is false. The possible values for this attribute are defined by the XML Schema boolean datatype. revisionsAlgorith mName (Cryptographic Algorithm Name) Specifies the specific cryptographic hashing algorithm which shall be used along with the salt attribute and input password in order to compute the hash value for the revisionsHashValue attribute. The following values are reserved: Value Algorithm MD2 Specifies that the MD2 algorithm, as defined by RFC 1319, shall be used. [Note: It is recommended that applications should avoid using this algorithm to store new hash values, due to publically known breaks. end note] MD4 Specifies that the MD4 algorithm, as defined by RFC 1320, shall Attributes Description be used. [Note: It is recommended that applications should avoid using this algorithm to store new hash values, due to publically known breaks. end note] MD5 Specifies that the MD5 algorithm, as defined by RFC 1321, shall be used. [Note: It is recommended that applications should avoid using this algorithm to store new hash values, due to publically known breaks. end note] RIPEMD-128 Specifies that the RIPEMD-128 algorithm, as defined by ISO/IEC 10118-3:2004 shall be used. [Note: It is recommended that applications should avoid using this algorithm to store new hash values, due to publically known breaks. end note] RIPEMD-160 Specifies that the RIPEMD-160 algorithm, as defined by ISO/IEC 10118-3:2004 shall be used. SHA-1 Specifies that the SHA-1 algorithm, as defined by ISO/IEC 10118-3:2004 shall be used. SHA-256 Specifies that the SHA-256 algorithm, as defined by ISO/IEC 10118-3:2004 shall be used. SHA-384 Specifies that the SHA-384 algorithm, as defined by ISO/IEC 10118-3:2004 shall be used. SHA-512 Specifies that the SHA-512 algorithm, as defined by ISO/IEC 10118-3:2004 shall be used. WHIRLPOOL Specifies that the WHIRLPOOL algorithm, as defined by ISO/IEC 10118-3:2004 shall be used. [Example: Consider an Office Open XML document with the following information stored in one of its protection elements: < … revisionsAlgorithmName="SHA-1" revisionsHashValue="9oN7nWkCAyEZib1RomSJTjmPpCY=" /> The revisionsAlgorithmName attribute value of “SHA-1″ specifies that the SHA-1 hashing algorithm shall be used to generate a hash from the user-defined password. end example] The possible values for this attribute are defined by the ST_String simple type (§3.18.96). Attributes Description revisionsHashVal ue (Password Hash Value) Specifies the hash value for the password stored for unlocking revisions in this workbook. This value shall be compared with the resulting hash value after hashing the user-supplied password using the algorithm specified by the preceding attributes and parent XML element, and if the two values match, the protection shall no longer be enforced. If this value is omitted, then the reservationPassword attribute shall contain the password hash for the workbook. [Example: Consider a SpreadsheetML document with the following information stored in one of its protection elements: <… revisionsAlgorithmName="SHA-1" revisionsHashValue="9oN7nWkCAyEZib1RomSJTjmPpCY=" /> The revisionsHashValue attribute value of 9oN7nWkCAyEZib1RomSJTjmPpCY= specifies that the user-supplied password shall be hashed using the pre-processing defined by the parent element (if any) followed by the SHA-1 algorithm (specified via the revisionsAlgorithmName attribute value of SHA-1 ) and that the resulting has value must be 9oN7nWkCAyEZib1RomSJTjmPpCY= for the protection to be disabled. end example] The possible values for this attribute are defined by the XML Schema base64Binary datatype. revisionsSaltValu e (Salt Value for Password Verifier) Specifies the salt which was prepended to the user-supplied password before it was hashed using the hashing algorithm defined by the preceding attribute values to generate the revisionsHashValue attribute, and which shall also be prepended to the user-supplied password before attempting to generate a hash value for comparison. A salt is a random string which is added to a user-supplied password before it is hashed in order to prevent a malicious party from pre-calculating all possible password/hash combinations and simply using those pre-calculated values (often referred to as a "dictionary attack"). If this attribute is omitted, then no salt shall be prepended to the user-supplied password before it is hashed for comparison with the stored hash value. [Example: Consider an Office Open XML document with the following information stored in one of its protection elements: <… revisionsSaltValue="ZUdHa+D8F/OAKP3I7ssUnQ==" revisionsHashValue="9oN7nWkCAyEZib1RomSJTjmPpCY=" /> The revisionsSaltValue attribute value of ZUdHa+D8F/OAKP3I7ssUnQ== specifies that the user-supplied password shall have this value prepended before it is run through the specified hashing algorithm to generate a resulting hash value for comparison. end example] Attributes Description The possible values for this attribute are defined by the XML Schema base64Binary datatype. revisionsSpinCou nt (Iterations to Run Hashing Algorithm) Specifies the number of times the hashing function shall be iteratively run (using each iteration’s result as the input for the next iteration) when attempting to compare a user-supplied password with the value stored in the revisionsHashValue attribute. [Rationale: Running the algorithm many times increases the cost of exhaustive search attacks correspondingly. Storing this value allows for the number of iterations to be increased over time to accommodate faster hardware (and hence the ability to run more iterations in less time). end rationale] [Example: Consider an Office Open XML document with the following information stored in one of its protection elements: <… revisionsSpinCount="100000" revisionHashValue="9oN7nWkCAyEZib1RomSJTjmPpCY=" /> The revisionsSpinCount attribute value of 100000 specifies that the hashing function shall be run one hundred thousand times to generate a hash value for comparison with the revisionsHashValue attribute. end example] The possible values for this attribute are defined by the ST_DecimalNumber simple type (§2.18.16). revisionsPasswor d (Revisions Password) Specifies the hash of the password required for unlocking revisions in this workbook. The hash is generated from an 8-bit wide character. 16-bit Unicode characters must be converted down to 8 bits before the hash is computed, using the following logic: For SpreadsheetML password hash purposes, Unicode UTF-16 input code points are converted to an “ansi” single or double byte code page from the following list: 874 windows-874 ANSI/OEM Thai (same as 28605, ISO 8859-15); Thai (Windows) 932 shift_jis ANSI/OEM Japanese; Japanese (Shift-JIS) 936 gb2312 ANSI/OEM Simplified Chinese (PRC, Singapore); Chinese Simplified (GB2312) 949 ks_c_5601-1987 ANSI/OEM Korean (Unified Hangul Code) 950 big5 ANSI/OEM Traditional Chinese (Taiwan; Hong Kong SAR, PRC); Chinese Traditional (Big5) 1250 windows-1250 ANSI Central European; Central European (Windows) 1251 windows-1251 ANSI Cyrillic; Cyrillic (Windows) Attributes Description Code points with no representation in the target code page are replaced with Unicode character 0×3f (?). The necessary mapping tables can be found at the following location: http://www.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WindowsBestFit/ . Code pages 932, 936, 949, and 950 are “Double Byte” code pages. The remainder of the “ANSI” code pages supported by windows are “Single Byte” code pages. For single byte code pages each Unicode code point is replaced by a single byte or 0×3f if an appropriate character doesn’t exist in the code page. For double byte code pages, each Unicode code point is replaced by either a single byte, or a two byte sequence, depending on the input character, or 0×3f if an appropriate character doesn’t exist in the code page. In our tables the target is a single byte sequence if the most significant byte is 0×00, otherwise it is a double byte sequence, with the lead byte being the most significant byte. To convert, first check if conversion is being done to a single or double byte code page and load the appropriate WCTABLE code page table. For each input WCHAR, look up the code point in the WCTABLE. There are 3 possibilities: Not found, single byte, or double byte. If the input WCHAR is not found, append 0×3f and continue to the next WCHAR. If the result is a single byte, check to make sure the entry in the MBTABLE matches the input. If it matches, append the single byte to the output. If it does not match, append 0×3f to the output. If the result is a double byte,check to make sure the entry in the DBCSENTRY table for the appropriate lead byte matches the input WCHAR. If it matches, append the lead byte and trail byte to the output. If it does not match, append 0×3f to the output. The following pueudocode describes how this conversion should be done: 1252 windows-1252 ANSI Latin 1; Western European (Windows) 1253 windows-1253 ANSI Greek; Greek (Windows) 1254 windows-1254 ANSI Turkish; Turkish (Windows) 1255 windows-1255 ANSI Hebrew; Hebrew (Windows) 1256 windows-1256 ANSI Arabic; Arabic (Windows) 1257 windows-1257 ANSI Baltic; Baltic (Windows) 1258 windows-1258 ANSI/OEM Vietnamese; Vietnamese (Windows) Attributes Description int WideCharToMultiByte(WCHAR* wszInput, byte* szOutput) { // Remember output start so we can return length byte* szOutputStart = szOutput; // Ask the system for the current ANSI code page, which // on windows is a system setting. int iCodePage = GetCurrentAnsiCodePage(); // Load Code Page Tables // This will depend on how the code pages are represented on // the target machine. TABLECLASS represents some abstract // representation of this structure here. TABLECLASS pTables = LoadCodePageTables(iCodePage); bool bDoubleByte = false; if (iCodePage == 932 || iCodePage == 936 || iCodePage == 949 || iCodePage == 950) bDoubleByte = true; while (*wszInput != 0) { if (bDoubleByte) szOutput = AppendDoubleByte(pTables, *wszInput, szOutput); else szOutput = AppendSingleByte(pTables, *wszInput, szOutput); // Read next input WCHAR wszInput++; } // Null terminate the output *szOutput = 0; // Return output length return szOutput szOutputStart; } byte* AppendSingleByte(TABLECLASS pTables, WCHAR wcIn, byte* szOutput) { Attributes Description // Look up byte that we want to append. byte bOut = pTables->LookUpSingleByte(wcIn); // Make sure that bOut matches the input, otherwise use ? // (ie: no best fit behavior allowed) if (wcIn != pTables->LookUpWideChar(bOut)) bOut = 0×3f; *szOutput = bOut; szOutput++; return szOutput; } byte* AppendDoubleByte(TABLECLASS pTables, WCHAR wcIn, byte* szOutput) { // Look up bytes that we want to append. UINT16 bytesOut = pTables->LookUpDoubleByte(wcIn); // See if it is a single or double byte sequence if (bytesOut & 0xFF00) { // It is a double byte sequence // Make sure that bytesOut matches the input, otherwise use ? // (ie: no best fit behavior allowed) if (wcIn != pTables->LookUpWideChar(bytesOut)) { // Use ?, it will be added below bytesOut = 0×003f; } else { // It matched, use the lead byte we found // trail byte will be added below *szOutput = bytesOut >> 8; szOutput++; } else { // It is a single byte sequence // Make sure that bytesOut matches the input, otherwise use ? // (ie: no best fit behavior allowed) if (wcIn != pTables->LookUpWideChar(bytesOut & 0xFF)) bytesOut = 0×003f; Attributes Description } // Add the single or trail byte *szOutput = bytesOut & 0xFF; szOutput++; return szOutput; } class pTables { // Construction depends on how you choose to store & load the // table files byte LookUpSingleByte(WCHAR wcIn) { // How you access the table depends on your storage mechanism. // Look up the line in WCTABLE where the first column matches wcIn, // and then return the byte value from the second column. if (exists WCTABLE{wcIn}) return WCTABLE{wcIn}.SecondColumn; // If it doesn’t exist, return ? return 0×3f; } UINT16 LookUpDoubleByte(WCHAR wcIn) { // How you access the table depends on your storage mechanism. // Look up the line in WCTABLE where the first column matches wcIn, // and then return the double byte value from the second column. if (exists WCTABLE{wcIn}) return WCTABLE{wcIn}.SecondColumn; // If it doesn’t exist, return ? return 0×003f; } // Overload that looks up wide chars from single byte code points. WCHAR LookUpWideChar(byte bIn) Attributes Description { // How you access the table depends on your storage mechanism. // Look up the line in MBTABLE where the first column matches bIn, // and then return the WCHAR value from the second column. if (exists MBTABLE{bIn}) return MBTABLE{bIn}.SecondColumn; // If it doesn’t exist, return ? return 0×003f; } // Overload that looks up wide chars from double byte code points WCHAR LookUpWideChar(UINT16 bytesIn) { // How you access the table depends on your storage mechanism. // First find the DBCSTABLE where the LeadByte matches // the lead (most significant) input byte. if (exists DBCSTABLE{bytesIn >> 8)) { DbcsTable = DBCSTABLE{bytesIn >> 8); // Look up the line in DbcsTable where the first column // matches the input trail (least significant) byte, // and then return the WCHAR value from the second column. if (exists DbcsTable{bytesIn & 0xFF}) return DbcsTable{bytesIn & 0xFF}.SecondColumn; } // Either the lead byte table or specific trail byte // doesn’t exist in the table, return ? return 0×003f; } } The resulting value is hashed using the algorithm defined below. [Note: An example algorithm to hash the resulting single-byte user input into the value stored is as follows: Attributes Description // Function Input: // szPassword: NULL terminated C-Style string // cchPassword: The number of characters in szPassword (not including the NULL terminator) WORD GetPasswordHash(const CHAR *szPassword, int cchPassword) { WORD wPasswordHash; const CHAR *pch; wPasswordHash = 0; if (cchPassword > 0) { pch = &szPassword[cchPassword]; while (pch– != szPassword) { wPasswordHash = ((wPasswordHash >> 14) & 0×01) | ((wPasswordHash << 1) & 0×7fff); wPasswordHash ^= *pch; } wPasswordHash ^= (0×8000 | (’N’ <<
| ‘K’); } return(wPasswordHash); } end note] The possible values for this attribute are defined by the ST_UnsignedShortHex simple type (§3.18.87). workbookPasswo rd (Workbook Password) Specifies the hash of the password required for unlocking revisions in this workbook. The hash is generated from an 8-bit wide character. 16-bit Unicode characters must be converted down to 8 bits before the hash is computed, using the following logic: For SpreadsheetML password hash purposes, Unicode UTF-16 input code points are converted to an “ansi” single or double byte code page using the logic defined in the preceding revisionsPassword attribute. The resulting value is hashed using the algorithm defined below. [Note: An example algorithm to hash the user input into the value stored is as follows: // Function Input: // szPassword: NULL terminated C-Style string // cchPassword: The number of characters in szPassword Attributes Description (not including the NULL terminator) WORD GetPasswordHash(const CHAR *szPassword, int cchPassword) { WORD wPasswordHash; const CHAR *pch; wPasswordHash = 0; if (cchPassword > 0) { pch = &szPassword[cchPassword]; while (pch– != szPassword) { wPasswordHash = ((wPasswordHash >> 14) & 0×01) | ((wPasswordHash << 1) & 0×7fff); wPasswordHash ^= *pch; } wPasswordHash ^= (0×8000 | (’N’ <<
| ‘K’); } return(wPasswordHash); } end note] The possible values for this attribute are defined by the ST_UnsignedShortHex simple type (§3.18.87). workbookAlgorit hmName (Cryptographic Algorithm Name) Specifies the specific cryptographic hashing algorithm which shall be used along with the salt attribute and input password in order to compute the hash value for the workbookHashValue attribute. The following values are reserved: Value Algorithm MD2 Specifies that the MD2 algorithm, as defined by RFC 1319, shall be used. [Note: It is recommended that applications should avoid using this algorithm to store new hash values, due to publically known breaks. end note] MD4 Specifies that the MD4 algorithm, as defined by RFC 1320, shall be used. [Note: It is recommended that applications should avoid using this algorithm to store new hash values, due to publically known breaks. end note] MD5 Specifies that the MD5 algorithm, as defined by RFC 1321, shall Attributes Description be used. [Note: It is recommended that applications should avoid using this algorithm to store new hash values, due to publically known breaks. end note] RIPEMD-128 Specifies that the RIPEMD-128 algorithm, as defined by ISO/IEC 10118-3:2004 shall be used. [Note: It is recommended that applications should avoid using this algorithm to store new hash values, due to publically known breaks. end note] RIPEMD-160 Specifies that the RIPEMD-160 algorithm, as defined by ISO/IEC 10118-3:2004 shall be used. SHA-1 Specifies that the SHA-1 algorithm, as defined by ISO/IEC 10118-3:2004 shall be used. SHA-256 Specifies that the SHA-256 algorithm, as defined by ISO/IEC 10118-3:2004 shall be used. SHA-384 Specifies that the SHA-384 algorithm, as defined by ISO/IEC 10118-3:2004 shall be used. SHA-512 Specifies that the SHA-512 algorithm, as defined by ISO/IEC 10118-3:2004 shall be used. WHIRLPOOL Specifies that the WHIRLPOOL algorithm, as defined by ISO/IEC 10118-3:2004 shall be used. [Example: Consider an Office Open XML document with the following information stored in one of its protection elements: < … workbookAlgorithmName="SHA-1" workbookHashValue="9oN7nWkCAyEZib1RomSJTjmPpCY=" /> The workbookAlgorithmName attribute value of “SHA-1″ specifies that the SHA- 1 hashing algorithm shall be used to generate a hash from the user-defined password. end example] The possible values for this attribute are defined by the ST_XString simple type (§3.18.96). workbookHashVa lue (Password Hash Value) Specifies the hash value for the password stored for unlocking this workbook. This value shall be compared with the resulting hash value after hashing the user-supplied password using the algorithm specified by the preceding attributes and parent XML element, and if the two values match, the protection shall no longer be enforced. If this value is omitted, then the reservationPassword attribute shall contain the Attributes Description password hash for the workbook. [Example: Consider a SpreadsheetML document with the following information stored in one of its protection elements: <… workbookAlgorithmName="SHA-1" workbookHashValue="9oN7nWkCAyEZib1RomSJTjmPpCY=" /> The workbookHashValue attribute value of 9oN7nWkCAyEZib1RomSJTjmPpCY= specifies that the user-supplied password shall be hashed using the pre-processing defined by the parent element (if any) followed by the SHA-1 algorithm (specified via the workbookAlgorithmName attribute value of SHA-1 ) and that the resulting has value must be 9oN7nWkCAyEZib1RomSJTjmPpCY= for the protection to be disabled. end example] The possible values for this attribute are defined by the XML Schema base64Binary datatype. workbookSaltVal ue (Salt Value for Password Verifier) Specifies the salt which was prepended to the user-supplied password before it was hashed using the hashing algorithm defined by the preceding attribute values to generate the workbookHashValue attribute, and which shall also be prepended to the user-supplied password before attempting to generate a hash value for comparison. A salt is a random string which is added to a user-supplied password before it is hashed in order to prevent a malicious party from pre-calculating all possible password/hash combinations and simply using those pre-calculated values (often referred to as a "dictionary attack"). If this attribute is omitted, then no salt shall be prepended to the user-supplied password before it is hashed for comparison with the stored hash value. [Example: Consider an Office Open XML document with the following information stored in one of its protection elements: <… workbookSaltValue="ZUdHa+D8F/OAKP3I7ssUnQ==" workbookHashValue="9oN7nWkCAyEZib1RomSJTjmPpCY=" /> The workbookSaltValue attribute value of ZUdHa+D8F/OAKP3I7ssUnQ== specifies that the user-supplied password shall have this value prepended before it is run through the specified hashing algorithm to generate a resulting hash value for comparison. end example] The possible values for this attribute are defined by the XML Schema base64Binary datatype. workbookSpinCo unt (Iterations to Run Hashing Specifies the number of times the hashing function shall be iteratively run (using each iteration’s result as the input for the next iteration) when attempting to compare a user-supplied password with the value stored in the