Re: Combining signing and encrypting

Joseph Reagle, <>, writes:
> As an aside, I was thinking along the line of an inverse of Hiroshi:
> always process Signature first and decrypt only where instructed to.
> Unfortunately, subsequent encryption will invalidate the Signature. If
> the author wishes to ensure that this does not happen, he needs to
> provide a decrypt transform. If someone other than the author wants to
> encrypt, he violates the Signature and things get confusing from what
> I can see. Regardless here examples under the policy that (1) do 
> Signatures first and any of the decryptions they specify and 
> then (2) decrypt all others.

As you say, the problem with this is that when you add a decryption
transform to the signature, you break the signature.  Analyzing this
in a bit more detail:

Signature verification has two parts: first, calculating the digests
of the data pointed to by the references (processed by transforms)
and comparing with the stored DigestValues; second, canonicalizing and
signing the SignedInfo block.  Encrypting part of a signed document breaks
the first step because it changes the digest.  Adding an xmlenc:Decrypt
transform when you do the encryption fixes the first step but breaks
the second one, because the SignedInfo is changed.

You suggest that this could be addressed by the author providing suitable
xmlenc:Decrypt transforms at signature-generation time.  This would
only work if he knew exactly which elements were going to be encrypted,
and even then the signature wouldn't verify until the elements actually
were encrypted (would it?).

Another way to address the problem would be to define a new
CanonicalizationMethod for the SignedInfo block, one which deletes
any xmlenc:Decrypt transforms.  A signer could prepare signatures which
would be "encryptable" by specifying this new canonicalization algorithm.
Then anyone else could add all the xmlenc:Decrypt transforms they wanted
without breaking the signature (although of course the data they reference
would have to be decrypted before the sig can be verified).

This would still not work for a signer who lacked the foresight to
specify this canonicalization method.  (Because CanonicalizationMethod is
included in SignedInfo, it is signed, hence changing it would invalidate
the signature.)  We could be even more ambitious and define yet another
new canonicalization method, one which not only deleted xmlenc:Decrypt
transforms, but which replaced the CanonicalizationMethod with the
original one the user specified.  If he had specified C14N we could define
a new canonicalization transform which replaced its own specification
with C14N.  Then the sigs would verify.

Here is your example, modified along these lines:

<!-- author: sign root then encrypt b -->
<!-- consumer: validate signature which automagically decrypts b
               in order to restore the root as signed -->
<eg:root ns:eg=""
   <EncryptedData ns:xmlenc="">
   <xmlenc:EncryptionInfo Id="b">...</xmlenc:EncryptionInfo>
   <dsig:Signature ns:xmldsig="h&dsig;">
+        <dsig:CanonicalizationMethod Algorithm="&xmlenc;StripDecryptTransforms"/>
         <dsig:Reference URI="">
            <dsig:Transform Algorithm="&xmlenc;decrypt">
               <xmlenc:Decrypt data="#b"/>
            <dsig:Transform Algorithm="&dsig;enveloped-signature"/>

After canonicalization the SignedInfo would look something like:

         <dsig:Reference URI="">
            <dsig:Transform Algorithm="&dsig;enveloped-signature"/>

which is how it looked before we encrypted the data, hence the sig
can verify.

I am not too comfortable with being so aggressive and hacking on someone
else's signature block, changing the canonicalization transform so that
the signature validates more permissively than he originally specified.
We are weakening the signature semantics, for a good cause, but still
there is the danger of introducing security weaknesses.

Hal Finney
PGP Security

Received on Tuesday, 28 November 2000 19:44:45 UTC