Using XML Encryption and XML Signature for Partial Signature Validation

Amir has identified a requirement that is under discussion.

  1. It should provide strong authentication of plaintext that is later encrypted.
  2. It should permit the partial revelation of an encrypted document to verify those parts of the document.
    1. The Decryption Transform for XML Signature permits one to describe the signing and encryption of a document in layered steps. For instance, if A and B were encrypted, then the document was signed, then one encrypted C and D. Using the Decryption Transform, I can decrypt C and D, then validate the signature. Note, I have to decrypt C and D; if I want validate C, but not D, its contrary to data minimization to have to reveal D just to validate the signature on C. Amir desires (and the present specification) provides for this using a DigestMethod and DigestValue in the EncryptedData. This document shows how to do it soly using XMLDSIG.
    2. Schaad does not like the plaintext of encrypted document to be in the clear. However, this is part of Amir's desired functionality, Schaad's concern can be addressed by using nonces with the plaintext, and Schaad's proposal introduces the possibility (when used for authentication instead of simple random error checksum functionality) that an attacker can find a new plaintext message and key which will yield the same CipherValue. The DigestValue that is encrypted within CipherValue will be different, but since this wasn't specifically signed, it can be replaced with the new digest of the new plaintext message without detection.
  3. Merlin and Amir have stated the partial revelation could be done with a Signature Manifest, wherein a new Reference in created for every possible partial revelation one would like to make. This isn't very different from the present specfication which spreads these places these digests in the encrypted data instead of a Signature Manfist.
  4. We need to figure out which approach is better: Amir describes the trade off well. However, the one outstanding problem with the Manifest approach is, "I'm not sure how the Reference elements in the Manifest will identify the hashed elements. They need to refer to the decrypted value of an EncryptedData element - how do you do this?"

The follow scenario attempts to address this question:

Some piece of data file://foo.xml

<AlphabetiSphagetti>
  <A id="a"/>
  <B id="b"/>
  <C id="c"/>
</AlphabetiSphagetti>

A separate Reference is created for each letter element:

<Signature Id="MyFirstSignature" xmlns="http://www.w3.org/2000/09/xmldsig#"> 
  <SignedInfo> 
    <CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/> 
    <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#dsa-sha1"/> 
    <Reference URI="#Manifest1"> 
       <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/> 
       <DigestValue>j6lwx3rvEPO0vKtMup4NbeVu8nk=</DigestValue> 
    </Reference>
  </SignedInfo> 
  <SignatureValue>MC0CFFrVLtRlk=...</SignatureValue> 
  <Object>
    <Manifest ID="Manifest1">
      <Reference URI="foo.xml#a"> 
         <Transforms>
           <Transform Algorithm="http://www.w3.org/2001/04/xmlenc#decryption"/>
         </Transforms>
         <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/> 
         <DigestValue>aj6lwx3rvEPO0vKtMup4NbeVu8nk=</DigestValue> 
      </Reference>
      <Reference URI="foo.xml#b"> 
         <Transforms>
           <Transform Algorithm="http://www.w3.org/2001/04/xmlenc#decryption"/>
         </Transforms> 
        <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/> 
         <DigestValue>bj6lwx3rvEPO0vKtMup4NbeVu8nk=</DigestValue> 
      </Reference>
      <Reference URI="foo.xml#c"> 
         <Transforms>
           <Transform Algorithm="http://www.w3.org/2001/04/xmlenc#decryption"/>
         </Transforms>
         <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/> 
         <DigestValue>cj6lwx3rvEPO0vKtMup4NbeVu8nk=</DigestValue> 
      </Reference>
    </Manifest>
</Signature>

The decryption transform means, "If I'm subsequently encrypted, to validate me, you need to decrypt all EncryptedData elements except the following (which is an empty list in this example." If I then encrypt B and C.

<AlphabetiSphagetti>
  <A id="a"/>
  <EncryptedData xmlns='http://www.w3.org/2001/04/xmlenc#'
   Type='http://www.w3.org/2001/04/xmlenc#Element'>
    <CipherData>
      <CipherValue>BA23B45C56</CipherValue>
    </CipherData>
   </EncryptedData>
  <EncryptedData xmlns='http://www.w3.org/2001/04/xmlenc#'
   Type='http://www.w3.org/2001/04/xmlenc#Element'>
    <CipherData>
      <CipherValue>BA23B45C56</CipherValue>
    </CipherData>
   </EncryptedData>
</AlphabetiSphagetti>

Results:

  1. The Signature over the original foo.xml is clearly broken, as it should be.
  2. However, the application can still confirm the integrity/authenticity of element A using the digest in the Manifest. (Note, these references must be stable even after encryption, consequently relative pointers like (3 cousin from the 2nd paragraph might be too brittle for post encryption processing).
  3. If the signer is challenged to demonstrate the authenticity/integrity of B, but doesn't want to reveal C to do this, he only has to decrypt B and can confirm the value in the manifest.
  4. I'm not convinced this is any better or worse than that already specified. If there's no faults in the scenario the trade off is as follows: this scenario doesn't have to add any processing to encryption, but it the digests have to sit in a manifest elsewhere, and it is convenient to locate them in the EncryptedData. (The functionality requires some complexity regardless, and I think I prefer to address authenticity solely with the Signature spec...)