none
MS-OFFCRYPTO Agile encryption RRS feed

  • Question

  • I have been looking into decrypting Office files using Agile Encryption and I was hoping for some clarification around the OFFCRYPTO documentation.

    My understanding is that to decrypt the document, I have to generate the key and IV based on password. To do this, section 2.3.4.15 says that the IV must be obtained using the zero-based segment number as a blockkey and the salt value. My first question is, what is the zero-based segment number? Also is the IV generated by hashing the block key and salt value together?

    In section 2.3.4.11, for generating the encryption key, the doc says that to obtain the final hash data I must run the hash function on Hn + block_key. However, it does not clarify what the block_key should be.

    Thanks
    Friday, September 10, 2010 2:31 PM

Answers

  • c7dev0,

    In the first paragraph of Section 2.3.4.15 (Data Encryption), you will notice that the EncryptedPackage stream MUST be encrypted in 4096-byte segments. These segments are numbered via a 32-bit unsigned integer starting with 0, then incrementing monotonically: 1, 2, etc. To answer your second question, yes, the IV is generated by the designated hash denoted by H where IV = H(KeyData.saltValue + blockKey). Also remember that if the number of bytes in IV is less than blockSize, you must pad the array of bytes with 0x36 until the array is of size blockSize. If the array so happens to be larger than blockSize, then you must truncate the array to blockSize.

    In regards to block_key referenced in Section 2.3.4.11, this section is explaining in general the hashing algorithm that will be used in processes later defined in the specification. You will notice the references in Section 2.3.4.13 (PasswordKeyEncryptor Generation) to the aforementioned section. For example, to calculate encryptedVerifierHashInput, step 2 of the process calls for generating an encryption key as specified in 2.3.4.11 and then provides the block_key. This section is also referenced in the calculation of the encryptedVerifierHashValue and the encryptedkeyValue.

    Does this answer your questions?

    Dominic Salemno
    Escalation Engineer
    Open Specifications
    • Proposed as answer by Dominic Salemno _MSFT Wednesday, September 22, 2010 1:52 AM
    • Marked as answer by C7Dev0 Monday, October 25, 2010 1:07 PM
    Wednesday, September 22, 2010 1:52 AM
  • Sumit,

    Each 4096-byte segment is encrypted independently of each other with a unique initialization vector (IV). The IV for each segment is calculated as follows:

    iv_n = hash + segment-number

    If the plaintext is not a multiple of 4096, then it should be padded. The value of the padding is not important as it is ignored in the process. This is described in section 2.3.4.15:

    "The final data block MUST be padded to the next integral multiple of the KeyData.blockSize value. Any padding bytes can be used."

    Dominic Salemno
    Escalation Engineer
    Open Specifications

    • Proposed as answer by King Salemno Friday, October 22, 2010 5:46 PM
    • Marked as answer by C7Dev0 Monday, October 25, 2010 1:01 PM
    Friday, October 22, 2010 5:45 PM

All replies

  • Hi C7Dev0,

    Thank you for your question.  A colleague will contact you soon to investigate this issue.

    Regards,

    Mark Miller

    Escalation Engineer

    US-CSS DSC PROTOCOL TEAM

     

    Friday, September 10, 2010 2:50 PM
  • c7dev0,

    i am the engineer who has taken ownership of your issue. i am currently researching this and will update you as things progress.

    dominic salemno
    escalation engineer
    open specifications

    Monday, September 13, 2010 7:33 PM
  • c7dev0,

    In the first paragraph of Section 2.3.4.15 (Data Encryption), you will notice that the EncryptedPackage stream MUST be encrypted in 4096-byte segments. These segments are numbered via a 32-bit unsigned integer starting with 0, then incrementing monotonically: 1, 2, etc. To answer your second question, yes, the IV is generated by the designated hash denoted by H where IV = H(KeyData.saltValue + blockKey). Also remember that if the number of bytes in IV is less than blockSize, you must pad the array of bytes with 0x36 until the array is of size blockSize. If the array so happens to be larger than blockSize, then you must truncate the array to blockSize.

    In regards to block_key referenced in Section 2.3.4.11, this section is explaining in general the hashing algorithm that will be used in processes later defined in the specification. You will notice the references in Section 2.3.4.13 (PasswordKeyEncryptor Generation) to the aforementioned section. For example, to calculate encryptedVerifierHashInput, step 2 of the process calls for generating an encryption key as specified in 2.3.4.11 and then provides the block_key. This section is also referenced in the calculation of the encryptedVerifierHashValue and the encryptedkeyValue.

    Does this answer your questions?

    Dominic Salemno
    Escalation Engineer
    Open Specifications
    • Proposed as answer by Dominic Salemno _MSFT Wednesday, September 22, 2010 1:52 AM
    • Marked as answer by C7Dev0 Monday, October 25, 2010 1:07 PM
    Wednesday, September 22, 2010 1:52 AM
  • Hi Dominic,

     

    Thanks for you reply. Some things have become much clearer. However, I am still unclear as to the final steps of the decryption process. My understanding is that I must generate an intermediate key by decrypting the encryptedKeyValue using the encryptedKey.saltValue and other attributes on the encryptedKey element. I am still not sure how to proceed with generating the IV itself. You said that the IV needs to be generated by incrementing an unsigned int monotonically. Is this similar to the process for the key generation? Is the following psuedo code correct?

    iv = encryptedKey.saltValue //initialize IV

    for i = 0 to segmentCount  -1

         iv = H(iv, i)

     

    if iv.Length < encryptedKey.blockSize

        pad using 0x36

    else if iv.Length > encryptedKey.blockSize

        truncate iv to blockSize

     

    Set up decryption with algorithm, key size, and chaining mode  as per keyData element and a padding mode of none. Decrypt the encrypted stream excluding the first 8 bytes in blocks of 4096.

     

    Is the above correct? If so how do I obtain the segment count?

     

    Thanks for your assistance.

     

    Regards

     

    Sumit

    Wednesday, September 22, 2010 1:12 PM
  • I am in the same mode of trying to understand the decryption process of Agile encrypted Office Documents.  Is there an answer for Sumit's question above or even better an up to date example of the decryption process.  The only example code that I can find is using the Office 2007 format encrypted files and is 2 years or more out of date.  There has to be better documentaiton or examples than what we see in the MS-OFFCRYPTO specification.  

     

    Thanks,

     

    David

    Thursday, September 23, 2010 7:42 PM
  • I am in the same mode of trying to understand the decryption process of Agile encrypted Office Documents.  Is there an answer for Sumit's question above or even better an up to date example of the decryption process.  The only example code that I can find is using the Office 2007 format encrypted files and is 2 years or more out of date.  There has to be better documentaiton or examples than what we see in the MS-OFFCRYPTO specification.  

     

    Thanks,

     

    David

    Thursday, September 23, 2010 7:44 PM
  • David,

    I will see if a more up-to-date example can be added. I am still researching c7dev0's pseudocode. I will post the solution to the forum upon confirmation.

    dominic salemno
    escalation engineer
    open specifications

    Monday, September 27, 2010 3:43 PM
  • Sumit,

    The EncryptedPackage stream MUST be encrypted in 4096-byte segments (Section 2.3.4.15 of [MS-OFFCRYPTO]). It is this stream that is broken into 4096-byte segments. These segments are then numbered from 0 and increases monotomically with 1, 2, 3, 4, 5, etc. The segment number is represented as a 32-bit number.. therefore the actual representation is 0x00000001, 0x00000002, 0x00000003, etc. This is the protected content stream and it MUST be contained within the root storage. Please note, this only applies to ECMA-376 documents. This stream contains the data which comprises the entire ECMA-376 document in compressed form. This data is encrypted per the algorithm specified in the \EncryptedInfo Stream.

    In regards to your inquiry regarding decryption, the decryption process is merely the reverse of the encryption process that has been presented in the documentation. Thus, the \EncryptedInfo stream contains all the relevant information needed for decryption (reversing the encryption process that has been applied).

    The encryption algorithms used in the process are publicly available, a few for example are as follows:

    [FIPS197] National Institute of Standards and Technology, "Federal Information Processing
    Standards Publication 197: Advanced Encryption Standard (AES)", November 2001,
    http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf

    [RFC1321] Rivest, R., "The MD5 Message-Digest Algorithm", RFC 1321, April 1992,
    http://www.ietf.org/rfc/rfc1321.txt

    All of the reference algorithms are cross-referenced in [MS-OFREF] (http://msdn.microsoft.com/en-us/library/cc308726%28v=office.12%29.aspx).

    dominic salemno
    escalation engineer
    open specifications

    • Proposed as answer by King Salemno Friday, October 8, 2010 2:51 PM
    Friday, October 8, 2010 2:51 PM
  • Hi Dominic,

     

    Is the pseudo code correct at all? It is still unclear how the segment numbers are to be used in the encryption or decryption process itself.

    As David said, any sort of code sample would make it significantly clearer about what the spec is about. Is there no possibility of getting one?

     

    Thanks

     

    Sumit

    Tuesday, October 12, 2010 11:51 AM
  • Sumit,

    We will evaluate the documentation and potentially add a sample in a future release of the documentation.

    The agile encryption method in question is only applicable to ECMA-376 documents. This entire document is in the \EncryptedPackage stream (Protected Content Stream) of a CFB file ([MS-CFB] Section 1.1, & [MS-OFFCRYPTO] Section 2.2.10). This stream will sit underneath the root storage object. The detailed encryption metadata can be found in the \EncryptionInfo stream.

    A stream is analogous to the notion of a file.


    The entire \EncryptedPackage stream is subsequently broken into 4096-byte blocks. These blocks are then numbered starting from 0 and increases by 1. It is this numbering which is also the equivalent to the segment number noted in the document.


    Therefore, one must understand the concepts of the [MS-CFB] (
    http://msdn.microsoft.com/en-us/library/dd942138%28PROT.13%29.aspx ) specification to decrypt the document in question. Subsequently, one must also know the concepts of an OOXML file to parse the document after decryption.

    Dominic Salemno

    Escalation Engineer

    Open Specifications

    • Marked as answer by King Salemno Thursday, October 14, 2010 11:08 PM
    • Unmarked as answer by C7Dev0 Friday, October 15, 2010 9:08 AM
    Thursday, October 14, 2010 11:08 PM
  • Dominic,

     

    I am afraid you are no longer answering the question I asked. My queries do not lie with either the OOXML file format or the structured file format.  The question I asked was:

    What is the final step of the decryption process? My understanding is that I must generate an intermediate key by decrypting the encryptedKeyValue using the encryptedKey.saltValue and other attributes on the encryptedKey element.

    However, the spec does not specify how to generate the IV itself. You said that the IV needs to be generated by incrementing an unsigned int monotonically. But can you confirm if this is similar to the process for the key generation where the IV is first initialized with the salt value and then computed iteratively for the number of segments using iv = H(iv, i). Also what happens if the length of the encrypted data is not a multiple of 4096 and therefore the segment count is not an integer?

     

     

    Sumit

    Friday, October 15, 2010 9:35 AM
  • Sumit,

    Each 4096-byte segment is encrypted independently of each other with a unique initialization vector (IV). The IV for each segment is calculated as follows:

    iv_n = hash + segment-number

    If the plaintext is not a multiple of 4096, then it should be padded. The value of the padding is not important as it is ignored in the process. This is described in section 2.3.4.15:

    "The final data block MUST be padded to the next integral multiple of the KeyData.blockSize value. Any padding bytes can be used."

    Dominic Salemno
    Escalation Engineer
    Open Specifications

    • Proposed as answer by King Salemno Friday, October 22, 2010 5:46 PM
    • Marked as answer by C7Dev0 Monday, October 25, 2010 1:01 PM
    Friday, October 22, 2010 5:45 PM
  • Hi Dominic,

     

    Thanks for the clarification. With your help we have now got the decryption process to work.

     

    Regards,

    Sumit

    Monday, October 25, 2010 1:07 PM
  • Hi C7Dev0,

    I am also working on the office 2010 encryption/decryption....And I am little bit confused in the steps of this algorithm for generating an encryption key and Initialization vector both uses block key.Now i want to ask:
    1) Which block key i should use in both cases ?

     

    Monday, January 2, 2012 7:42 AM
  • Hi prateek1108,
     
    It appears that your problem is being discussed on this thread:
     
    Therefore, we won't duplicate efforts here.
    Best regards,
    Tom Jebo
    Escalation Engineer
    Microsoft Open Specifications 
    Tuesday, January 3, 2012 3:34 PM
    Moderator