Skip to content

Commit c317785

Browse files
author
Adrià Tarroja Caubet
committed
Add legacy SigningCertificate with IssuerSerial for XAdES interoperability
Closes #281
1 parent 5350e9d commit c317785

File tree

1 file changed

+24
-1
lines changed

1 file changed

+24
-1
lines changed

signxml/xades/xades.py

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,10 @@ def add_signing_time(self, signed_signature_properties, sig_root, signing_settin
190190
signing_time.text = datetime.datetime.now(datetime.timezone.utc).isoformat(timespec="seconds")
191191

192192
def add_signing_certificate(self, signed_signature_properties, sig_root, signing_settings: SigningSettings):
193-
# TODO: check if we need to support SigningCertificate
193+
# Emit both legacy SigningCertificate (SHA1 + IssuerSerial) and SigningCertificateV2
194+
signing_cert = SubElement(
195+
signed_signature_properties, xades_tag("SigningCertificate"), nsmap=self.namespaces
196+
)
194197
signing_cert_v2 = SubElement(
195198
signed_signature_properties, xades_tag("SigningCertificateV2"), nsmap=self.namespaces
196199
)
@@ -202,6 +205,26 @@ def add_signing_certificate(self, signed_signature_properties, sig_root, signing
202205
loaded_cert = x509.load_pem_x509_certificate(add_pem_header(cert))
203206
der_encoded_cert = loaded_cert.public_bytes(Encoding.DER)
204207
cert_digest_bytes = self._get_digest(der_encoded_cert, algorithm=self.digest_alg)
208+
cert_digest_sha1_bytes = self._get_digest(der_encoded_cert, algorithm=DigestAlgorithm.SHA1)
209+
210+
# Legacy SigningCertificate
211+
cert_node_legacy = SubElement(signing_cert, xades_tag("Cert"), nsmap=self.namespaces)
212+
cert_digest = SubElement(cert_node_legacy, xades_tag("CertDigest"), nsmap=self.namespaces)
213+
SubElement(cert_digest, ds_tag("DigestMethod"), nsmap=self.namespaces, Algorithm=DigestAlgorithm.SHA1.value)
214+
digest_value_node = SubElement(cert_digest, ds_tag("DigestValue"), nsmap=self.namespaces)
215+
digest_value_node.text = b64encode(cert_digest_sha1_bytes).decode()
216+
issuer_serial = SubElement(cert_node_legacy, xades_tag("IssuerSerial"), nsmap=self.namespaces)
217+
issuer_name = SubElement(issuer_serial, ds_tag("X509IssuerName"), nsmap=self.namespaces)
218+
issuer_name.text = "C={C},O={O},OU={OU},CN={CN}".format(
219+
C=loaded_cert.issuer.get_attributes_for_oid(x509.oid.NameOID.COUNTRY_NAME)[0].value,
220+
O=loaded_cert.issuer.get_attributes_for_oid(x509.oid.NameOID.ORGANIZATION_NAME)[0].value,
221+
OU=loaded_cert.issuer.get_attributes_for_oid(x509.oid.NameOID.ORGANIZATIONAL_UNIT_NAME)[0].value,
222+
CN=loaded_cert.issuer.get_attributes_for_oid(x509.oid.NameOID.COMMON_NAME)[0].value,
223+
)
224+
serial_number = SubElement(issuer_serial, ds_tag("X509SerialNumber"), nsmap=self.namespaces)
225+
serial_number.text = str(loaded_cert.serial_number)
226+
227+
# SigningCertificateV2 (current default)
205228
cert_node = SubElement(signing_cert_v2, xades_tag("Cert"), nsmap=self.namespaces)
206229
cert_digest = SubElement(cert_node, xades_tag("CertDigest"), nsmap=self.namespaces)
207230
SubElement(cert_digest, ds_tag("DigestMethod"), nsmap=self.namespaces, Algorithm=self.digest_alg.value)

0 commit comments

Comments
 (0)