diff --git a/signxml/signer.py b/signxml/signer.py
index ac39002..0e780a9 100644
--- a/signxml/signer.py
+++ b/signxml/signer.py
@@ -136,6 +136,7 @@ def sign(
         always_add_key_value: bool = False,
         inclusive_ns_prefixes: Optional[List[str]] = None,
         signature_properties: Optional[Union[_Element, List[_Element]]] = None,
+        exclude_c14n_transform_element: bool = False,
     ) -> _Element:
         """
         Sign the data and return the root element of the resulting XML tree.
@@ -183,6 +184,11 @@ def sign(
         :param signature_properties:
             One or more Elements that are to be included in the SignatureProperies section when using the detached
             method.
+        :param exclude_c14n_transform_element:
+            When set to True, the c14n algorithm is not added to the signature's Transforms element. By default,
+            all transforms including canonicalization are added to the Transforms element, and in most cases this
+            is the correct approach. Only set this to True if you need to comply with a specification where the
+            c14n algorithm is fixed, and the specification forbids mentioning the algorithm.
 
         :returns:
             A :class:`lxml.etree._Element` object representing the root of the XML tree containing the signature and
@@ -235,6 +241,7 @@ def sign(
             references=references,
             c14n_inputs=c14n_inputs,
             inclusive_ns_prefixes=inclusive_ns_prefixes,
+            exclude_c14n_transform_element=exclude_c14n_transform_element,
         )
 
         for signature_annotator in self.signature_annotators:
@@ -377,23 +384,29 @@ def _unpack(self, data, references: List[SignatureReference]):
             references = [SignatureReference(URI="#object")]
         return sig_root, doc_root, c14n_inputs, references
 
-    def _build_transforms_for_reference(self, *, transforms_node: _Element, reference: SignatureReference):
+    def _build_transforms_for_reference(
+        self, *, transforms_node: _Element, reference: SignatureReference, exclude_c14n_transform_element: bool = True
+    ):
         assert reference.c14n_method is not None
         if self.construction_method == SignatureConstructionMethod.enveloped:
             SubElement(transforms_node, ds_tag("Transform"), Algorithm=SignatureConstructionMethod.enveloped.value)
-            SubElement(transforms_node, ds_tag("Transform"), Algorithm=reference.c14n_method.value)
+            if not exclude_c14n_transform_element:
+                SubElement(transforms_node, ds_tag("Transform"), Algorithm=reference.c14n_method.value)
         else:
-            c14n_xform = SubElement(
-                transforms_node,
-                ds_tag("Transform"),
-                Algorithm=reference.c14n_method.value,
-            )
+            if not exclude_c14n_transform_element:
+                c14n_xform = SubElement(
+                    transforms_node,
+                    ds_tag("Transform"),
+                    Algorithm=reference.c14n_method.value,
+                )
             if reference.inclusive_ns_prefixes:
                 SubElement(
                     c14n_xform, ec_tag("InclusiveNamespaces"), PrefixList=" ".join(reference.inclusive_ns_prefixes)
                 )
 
-    def _build_sig(self, sig_root, references, c14n_inputs, inclusive_ns_prefixes):
+    def _build_sig(
+        self, sig_root, references, c14n_inputs, inclusive_ns_prefixes, exclude_c14n_transform_element=False
+    ):
         signed_info = SubElement(sig_root, ds_tag("SignedInfo"), nsmap=self.namespaces)
         sig_c14n_method = SubElement(signed_info, ds_tag("CanonicalizationMethod"), Algorithm=self.c14n_alg.value)
         if inclusive_ns_prefixes:
@@ -407,7 +420,11 @@ def _build_sig(self, sig_root, references, c14n_inputs, inclusive_ns_prefixes):
                 reference = replace(reference, inclusive_ns_prefixes=inclusive_ns_prefixes)
             reference_node = SubElement(signed_info, ds_tag("Reference"), URI=reference.URI)
             transforms = SubElement(reference_node, ds_tag("Transforms"))
-            self._build_transforms_for_reference(transforms_node=transforms, reference=reference)
+            self._build_transforms_for_reference(
+                transforms_node=transforms,
+                reference=reference,
+                exclude_c14n_transform_element=exclude_c14n_transform_element,
+            )
             SubElement(reference_node, ds_tag("DigestMethod"), Algorithm=self.digest_alg.value)
             digest_value = SubElement(reference_node, ds_tag("DigestValue"))
             payload_c14n = self._c14n(
diff --git a/signxml/verifier.py b/signxml/verifier.py
index 29e3fa8..3e6b24b 100644
--- a/signxml/verifier.py
+++ b/signxml/verifier.py
@@ -87,6 +87,15 @@ class SignatureConfiguration:
     and validate the signature using X509Data only.
     """
 
+    default_reference_c14n_method: CanonicalizationMethod = CanonicalizationMethod.CANONICAL_XML_1_1
+    """
+    The default canonicalization method to use for referenced data structures, if there is no canonicalization
+    algorithm specified in the Transforms element. In most cases, it should not be necessary to override this
+    setting; SignedInfo should include every transformation that were applied to the reference before creating
+    the digests and signature, but there are some uses of XML Signatures where the canonicalization method is
+    fixed, and not added to the Transforms. This setting can be used to validate signatures in those use-cases.
+    """
+
 
 @dataclass(frozen=True)
 class VerifyResult:
@@ -116,8 +125,6 @@ class XMLVerifier(XMLSignatureProcessor):
     Create a new XML Signature Verifier object, which can be used to verify multiple pieces of data.
     """
 
-    _default_reference_c14n_method = CanonicalizationMethod.CANONICAL_XML_1_0
-
     def _get_signature(self, root):
         if root.tag == ds_tag("Signature"):
             return root
@@ -207,7 +214,13 @@ def _get_inclusive_ns_prefixes(self, transform_node):
         else:
             return inclusive_namespaces.get("PrefixList").split(" ")
 
-    def _apply_transforms(self, payload, *, transforms_node: etree._Element, signature: etree._Element):
+    def _apply_transforms(
+        self,
+        payload,
+        *,
+        transforms_node: etree._Element,
+        signature: etree._Element,
+    ):
         transforms, c14n_applied = [], False
         if transforms_node is not None:
             transforms = self._findall(transforms_node, "Transform")
@@ -239,8 +252,9 @@ def _apply_transforms(self, payload, *, transforms_node: etree._Element, signatu
             c14n_applied = True
 
         if not c14n_applied and not isinstance(payload, (str, bytes)):
-            payload = self._c14n(payload, algorithm=self._default_reference_c14n_method)
-
+            # Create a separate copy of the node, see above
+            payload = self._fromstring(self._tostring(payload))
+            payload = self._c14n(payload, algorithm=self.config.default_reference_c14n_method)
         return payload
 
     def get_cert_chain_verifier(self, ca_pem_file):
@@ -523,14 +537,27 @@ def verify(
 
         return verify_results if self.config.expect_references > 1 else verify_results[0]
 
-    def _verify_reference(self, reference, index, root, uri_resolver, c14n_algorithm, signature, signature_key_used):
+    def _verify_reference(
+        self,
+        reference,
+        index,
+        root,
+        uri_resolver,
+        c14n_algorithm,
+        signature,
+        signature_key_used,
+    ):
         copied_root = self._fromstring(self._tostring(root))
         copied_signature_ref = self._get_signature(copied_root)
         transforms = self._find(reference, "Transforms", require=False)
         digest_method_alg_name = self._find(reference, "DigestMethod").get("Algorithm")
         digest_value = self._find(reference, "DigestValue")
         payload = self._resolve_reference(copied_root, reference, uri_resolver=uri_resolver)
-        payload_c14n = self._apply_transforms(payload, transforms_node=transforms, signature=copied_signature_ref)
+        payload_c14n = self._apply_transforms(
+            payload,
+            transforms_node=transforms,
+            signature=copied_signature_ref,
+        )
         digest_alg = DigestAlgorithm(digest_method_alg_name)
         self.check_digest_alg_expected(digest_alg)
 
diff --git a/test/test.py b/test/test.py
index 6559478..a663062 100755
--- a/test/test.py
+++ b/test/test.py
@@ -585,7 +585,7 @@ def test_inclusive_namespaces_signing(self):
         )
 
         # Test correct default c14n method for payload when c14n transform metadata is omitted
-        def _build_transforms_for_reference(transforms_node, reference):
+        def _build_transforms_for_reference(transforms_node, reference, exclude_c14n_transform_element=False):
             etree.SubElement(
                 transforms_node, ds_tag("Transform"), Algorithm=SignatureConstructionMethod.enveloped.value
             )
@@ -676,6 +676,56 @@ def test_xmlns_insulation_of_reference_c14n(self):
         root = XMLSigner().sign(doc, cert=cert, key=key, reference_uri="#target")
         XMLVerifier().verify(root, x509_cert=cert)
 
+    def test_include_c14n_transform_element_by_default(self):
+        cert, key = self.load_example_keys()
+        doc = etree.fromstring(
+            ''
+            '91'
+            ""
+        )
+        root = XMLSigner().sign(doc, cert=cert, key=key, reference_uri="#target")
+        XMLVerifier().verify(root, x509_cert=cert)
+        transform_elements = root.findall(
+            "ds:Signature/ds:SignedInfo/ds:Reference/ds:Transforms/ds:Transform", namespaces=namespaces
+        )
+        transform_algorithms = [el.attrib["Algorithm"] for el in transform_elements]
+        self.assertEqual(len(transform_elements), 2)
+        self.assertIn("http://www.w3.org/2000/09/xmldsig#enveloped-signature", transform_algorithms)
+        self.assertIn("http://www.w3.org/2006/12/xml-c14n11", transform_algorithms)
+
+    def test_exclude_c14n_transform_element_option(self):
+        cert, key = self.load_example_keys()
+        doc = etree.fromstring(
+            ''
+            '91'
+            ""
+        )
+        root = XMLSigner(c14n_algorithm=CanonicalizationMethod.CANONICAL_XML_1_0_WITH_COMMENTS).sign(
+            doc, cert=cert, key=key, reference_uri="#target", exclude_c14n_transform_element=True
+        )
+
+        # The default to use is CANONICAL_XML_1_1 (no comments), and since it's not specified in Transforms,
+        # verification without specifying the reference canonicalization algorithm should fail.
+        self.assertRaises(
+            InvalidDigest,
+            XMLVerifier().verify,
+            root,
+            x509_cert=cert,
+        )
+
+        # However, if we use the right configuration, it should verify correctly
+        config = SignatureConfiguration(
+            default_reference_c14n_method=CanonicalizationMethod.CANONICAL_XML_1_0_WITH_COMMENTS
+        )
+        XMLVerifier().verify(root, x509_cert=cert, expect_config=config)
+        transform_elements = root.findall(
+            "ds:Signature/ds:SignedInfo/ds:Reference/ds:Transforms/ds:Transform", namespaces=namespaces
+        )
+        transform_algorithms = [el.attrib["Algorithm"] for el in transform_elements]
+        self.assertEqual(len(transform_elements), 1)
+        self.assertIn("http://www.w3.org/2000/09/xmldsig#enveloped-signature", transform_algorithms)
+        self.assertNotIn("http://www.w3.org/2006/12/xml-c14n11", transform_algorithms)
+
     def test_verify_config(self):
         data = etree.parse(self.example_xml_files[0]).getroot()
         cert, key = self.load_example_keys()