Skip to content

Commit 70a648e

Browse files
authored
SignedXml docs: recommend key-taking CheckSignature overloads over the parameterless ones in the SignedXml reference remarks. (#13031)
1 parent 33710c5 commit 70a648e

1 file changed

Lines changed: 34 additions & 2 deletions

File tree

xml/System.Security.Cryptography.Xml/SignedXml.xml

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,13 @@ The data in the optional `<KeyInfo>` element (that is, the <xref:System.Security
148148
149149
In particular, when the <xref:System.Security.Cryptography.Xml.SignedXml.KeyInfo> value represents a bare RSA, DSA or ECDSA public key, the document could have been tampered with, despite the <xref:System.Security.Cryptography.Xml.SignedXml.CheckSignature*> method reporting that the signature is valid. This can happen because the entity doing the tampering just has to generate a new key and re-sign the tampered document with that new key. So, unless your application verifies that the public key is an expected value, the document should be treated as if it were tampered with. This requires that your application examine the public key embedded within the document and verify it against a list of known values for the document context. For example, if the document could be understood to be issued by a known user, you'd check the key against a list of known keys used by that user.
150150
151-
You can also verify the key after processing the document by using the <xref:System.Security.Cryptography.Xml.SignedXml.CheckSignatureReturningKey*> method, instead of using the <xref:System.Security.Cryptography.Xml.SignedXml.CheckSignature*> method. But, for the optimal security, you should verify the key beforehand.
151+
Because of this, <xref:System.Security.Cryptography.Xml.SignedXml.CheckSignature*> is not designed to authenticate documents from an untrusted source on its own. The recommended pattern is to obtain the expected signer's verification key or certificate ahead of time from a source that is independent of the signed document — for example, from application configuration or from a curated list of allowed signer keys or certificates — and pass it explicitly to one of the overloads that accepts a key:
152+
153+
- <xref:System.Security.Cryptography.Xml.SignedXml.CheckSignature(System.Security.Cryptography.AsymmetricAlgorithm)>
154+
- <xref:System.Security.Cryptography.Xml.SignedXml.CheckSignature(System.Security.Cryptography.KeyedHashAlgorithm)>
155+
- <xref:System.Security.Cryptography.Xml.SignedXml.CheckSignature(System.Security.Cryptography.X509Certificates.X509Certificate2,System.Boolean)>
156+
157+
If you must inspect the key embedded in the document, use the <xref:System.Security.Cryptography.Xml.SignedXml.CheckSignatureReturningKey*> method and verify that the returned key matches an expected value before treating the document as authentic. But for optimal security, verify the key beforehand by using one of the overloads listed above; the parameterless <xref:System.Security.Cryptography.Xml.SignedXml.CheckSignature> overload is not suitable for verifying untrusted input.
152158
153159
Alternately, consider trying the user's registered public keys, rather than reading what's in the `<KeyInfo>` element.
154160
@@ -549,13 +555,27 @@ The following code example shows how to sign and verify a single element of an X
549555
<format type="text/markdown"><![CDATA[
550556
551557
## Remarks
558+
559+
> [!IMPORTANT]
560+
> This overload selects a verification key based on the <xref:System.Security.Cryptography.Xml.SignedXml.KeyInfo> element of the signed document. Because that element is under the control of whoever produced the document, a `true` result proves only that the signed portions of the document match the signature computed with that key — not that the key belongs to a trusted signer. Do not use this overload to authenticate documents from an untrusted source unless the verification key has already been validated by other means.
561+
>
562+
> The recommended pattern is to obtain the verification key or certificate ahead of time (from application configuration or another source independent of the signed document) and pass it to one of the overloads that accepts a key:
563+
>
564+
> - <xref:System.Security.Cryptography.Xml.SignedXml.CheckSignature(System.Security.Cryptography.AsymmetricAlgorithm)>
565+
> - <xref:System.Security.Cryptography.Xml.SignedXml.CheckSignature(System.Security.Cryptography.KeyedHashAlgorithm)>
566+
> - <xref:System.Security.Cryptography.Xml.SignedXml.CheckSignature(System.Security.Cryptography.X509Certificates.X509Certificate2,System.Boolean)> with `verifySignatureOnly` set to `false`
567+
>
568+
> See the [Remarks](xref:System.Security.Cryptography.Xml.SignedXml) section on the class page for the full trust rationale.
569+
552570
This method also computes the digest of the references and the value of the signature.
553571
554572
If an XML document was signed with an X.509 signature, the <xref:System.Security.Cryptography.Xml.SignedXml.CheckSignature*> method will search the "AddressBook" store for certificates suitable for the verification. For example, if the certificate is referenced by a Subject Key Identifier (SKI), the <xref:System.Security.Cryptography.Xml.SignedXml.CheckSignature*> method will select certificates with this SKI and try them one after another until it can verify the certificate.
555573
556574
557575
558576
## Examples
577+
The following code examples show how to sign an XML document and verify the signature by passing an explicit verification key to an overload of <xref:System.Security.Cryptography.Xml.SignedXml.CheckSignature*>. Prefer this pattern over calling the parameterless overload.
578+
559579
The following code example shows how to sign and verify an entire XML document using an enveloped signature.
560580
561581
:::code language="csharp" source="~/snippets/csharp/System.Security.Cryptography.Xml/SignedXml/Overview/exampleenvelope.cs" id="Snippet1":::
@@ -817,8 +837,20 @@ The X.509 certificate is verified. The <xref:System.Security.Cryptography.Xml.Si
817837
<remarks>
818838
<format type="text/markdown"><![CDATA[
819839
840+
## Remarks
841+
842+
> [!IMPORTANT]
843+
> The key returned in `signingKey` is selected based on the <xref:System.Security.Cryptography.Xml.SignedXml.KeyInfo> element of the signed document, which is under the control of whoever produced the document. A `true` result proves only that the signed portions of the document match the signature computed with the returned key — not that the key belongs to a trusted signer. This overload is not suitable for authenticating documents from an untrusted source unless the caller compares `signingKey` against a key that the application already trusts before treating the document as authentic.
844+
>
845+
> For most scenarios, prefer an overload that takes the verification key up front so trust is established before verification:
846+
>
847+
> - <xref:System.Security.Cryptography.Xml.SignedXml.CheckSignature(System.Security.Cryptography.AsymmetricAlgorithm)>
848+
> - <xref:System.Security.Cryptography.Xml.SignedXml.CheckSignature(System.Security.Cryptography.X509Certificates.X509Certificate2,System.Boolean)>
849+
>
850+
> See the [Remarks](xref:System.Security.Cryptography.Xml.SignedXml) section on the class page for additional guidance.
851+
820852
## Examples
821-
The following code example shows how to sign and verify an entire XML document using an enveloping signature.
853+
The following code example shows how to sign an XML document, verify the signature by using <xref:System.Security.Cryptography.Xml.SignedXml.CheckSignatureReturningKey*>, and then confirm that the returned key matches a key that the application already trusts.
822854
823855
:::code language="csharp" source="~/snippets/csharp/System.Security.Cryptography.Xml/SignedXml/CheckSignatureReturningKey/exampleenvelope.cs" id="Snippet1":::
824856
:::code language="vb" source="~/snippets/visualbasic/System.Security.Cryptography.Xml/SignedXml/CheckSignatureReturningKey/exampleenvelope.vb" id="Snippet1":::

0 commit comments

Comments
 (0)