3 ms·
The issue isn't that the signature is based on a computed value—the input would always be computed at some point. The issue is that the signature checking code
by nybble41 5y ago
The issue isn't that the signature is based on a computed value—the input would always be computed at some point. The issue is that the signature checking code interprets the document one way and the code using the document interprets it another way. This is less likely to occur (though not quite impossible) when the input to the signature check is defined to be a simple byte array rather than a complex XML document where only certain parts are covered by the signature.
One way to avoid this would be to require the input to be in some non-malleable normalized form: If normalization changes the document in any way then it fails the signature check. The advantages of this approach are that it doesn't require Base64-encoding the signed content and that it has no problem with embedded signature blocks.
- labawi 5y agoIMO the crazy part is reusing the input directly, instead of normalizing, serializing, then verifing signature, deserializing and only ever trusting the deserialized verified data. This way you always accept as validated exactly the same input that is signed, and any normalization or processing is irrelevant¹. OTOH, once you do it like this, I'm not sure what's the benefit of allowing malleable data in the first place. You may need to splice data back from multiple signed parts, but I'm not sure what else would be proper, if only parts of a document are signed. -- Note: Only ever trust SignedData. playWithData :: Dangerous -> Dangerous -> Dangerous verifySignature :: Dangerous -> VerificationParameters -> (SignatureInfo, Maybe SignedData) ¹ Normalization/processing will be exposed to attackers, so it still needs to be memory and computationally safe, and you should carefully evaluate do you really need preprocessing.