Club Delphi  
    Paypal   FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Proyecto SIF/Veri*Factu/Ley Antifraude > Envío de registros y sus respuestas
Registrarse FAQ Miembros Calendario Guía de estilo Temas de Hoy

 
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 24-11-2025
Daviid Daviid is offline
Miembro
 
Registrado: sep 2025
Ubicación: Barcelona
Posts: 49
Poder: 0
Daviid Va por buen camino
Ejemplo Registro de Eventos

Alguien tiene un ejemplo de registro de evento? Firmado y sin firmar?

Creo que tengo uno pero VALIDe me da error, EADTrust también me falla.

Este código me sale todo bien, pero es ChatGPT así que....


Código:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# Full XAdES-EPES validation script
# Validates:
#  - Canonicalization of SignedInfo
#  - Digest of SignedProperties
#  - Digest of the enveloped document
#  - SignatureValue (RSA-SHA256)
#  - Certificate used for signing
#  - XAdES EPES requirements: SigningCertificate, SignaturePolicyIdentifier

import base64
import hashlib
import urllib.request
from lxml import etree
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.asymmetric import padding
from cryptography import x509

XML_FILE = r"firmado.xml"

NS = {
    "ds": "http://www.w3.org/2000/09/xmldsig#",
    "xades": "http://uri.etsi.org/01903/v1.3.2#",
}

def c14n(node, with_comments=False):
    """Returns canonicalized XML for a node."""
    return etree.tostring(
        node,
        method="c14n",
        exclusive=True,
        with_comments=with_comments
    )

def sha256(data):
    return base64.b64encode(hashlib.sha256(data).digest()).decode()

def sha1(data):
    return base64.b64encode(hashlib.sha1(data).digest()).decode()

def load_xml():
    parser = etree.XMLParser(remove_blank_text=True)
    return etree.parse(XML_FILE, parser)

def extract_certificate(cert_b64):
    cert_bytes = base64.b64decode(cert_b64)
    return x509.load_der_x509_certificate(cert_bytes)

def validate_reference_digest(node, expected_digest):
    canon = c14n(node)
    digest = sha256(canon)
    return digest == expected_digest, digest

def validate_signature_value(public_key, signed_info_c14n, signature_value):
    try:
        public_key.verify(
            signature_value,
            signed_info_c14n,
            padding.PKCS1v15(),
            hashes.SHA256()
        )
        return True
    except Exception:
        return False

def main():
    print("Loading XML…")
    doc = load_xml()

    signature = doc.find(".//ds:Signature", NS)
    signed_info = signature.find("ds:SignedInfo", NS)
    signature_value_el = signature.find("ds:SignatureValue", NS)
    key_info = signature.find("ds:KeyInfo/ds:X509Data/ds:X509Certificate", NS)

    # Extract certificate
    cert_b64 = key_info.text.strip()
    cert = extract_certificate(cert_b64)
    public_key = cert.public_key()

    # Canonicalize SignedInfo
    signed_info_c14n = c14n(signed_info)

    # Decode SignatureValue
    signature_value = base64.b64decode(signature_value_el.text.strip())

    print("\n=== Step 1: Validate SignatureValue (RSA-SHA256) ===")
    if validate_signature_value(public_key, signed_info_c14n, signature_value):
        print("✔ SignatureValue is VALID")
    else:
        print("✘ SignatureValue is INVALID")

    print("\n=== Step 2: Validate each Reference digest ===")
    references = signed_info.findall("ds:Reference", NS)
    for ref in references:
        uri = ref.get("URI")
        expected_digest = ref.find("ds:DigestValue", NS).text.strip()

        if uri.startswith("#"):
            target_id = uri[1:]
            target = doc.find(f".//*[@Id='{target_id}']")
        else:
            # Empty URI => enveloped signing of root element
            target = doc.getroot()

        # Root must exclude the <Signature> itself (enveloped signature transform)
        transforms = ref.find("ds:Transforms", NS)
        if transforms is not None:
            for t in transforms.findall("ds:Transform", NS):
                algo = t.get("Algorithm")
                if algo == "http://www.w3.org/2000/09/xmldsig#enveloped-signature":
                    sig_node = signature
                    sig_node.getparent().remove(sig_node)

        valid, computed_digest = validate_reference_digest(target, expected_digest)

        print(f"\nReference URI='{uri}'")
        print(f"Expected digest: {expected_digest}")
        print(f"Computed digest: {computed_digest}")
        print("✔ Digest VALID" if valid else "✘ Digest INVALID")

    print("\n=== Step 3: Validate XAdES SignedProperties digest ===")
    signed_props_ref = signature.find(
        "ds:SignedInfo/ds:Reference[@Type='http://uri.etsi.org/01903#SignedProperties']",
        NS
    )
    if signed_props_ref is not None:
        uri = signed_props_ref.get("URI")[1:]
        expected_digest = signed_props_ref.find("ds:DigestValue", NS).text.strip()

        signed_props = signature.find(
            f"ds:Object/xades:QualifyingProperties/xades:SignedProperties[@Id='{uri}']",
            NS
        )
        valid, computed_digest = validate_reference_digest(signed_props, expected_digest)

        print(f"Expected: {expected_digest}")
        print(f"Computed: {computed_digest}")
        print("✔ SignedProperties digest VALID" if valid else "✘ SignedProperties digest INVALID")

    print("\n=== Step 4: Validate SigningCertificate digest (XAdES requirement) ===")
    signing_cert = signature.find(
        "ds:Object/xades:QualifyingProperties/xades:SignedProperties/"
        "xades:SignedSignatureProperties/xades:SigningCertificate/"
        "xades:Cert/xades:CertDigest/ds:DigestValue",
        NS
    )

    method = signature.find(
        "ds:Object/xades:QualifyingProperties/xades:SignedProperties/"
        "xades:SignedSignatureProperties/xades:SigningCertificate/"
        "xades:Cert/xades:CertDigest/ds:DigestMethod",
        NS
    ).get("Algorithm")

    expected_cert_digest = signing_cert.text.strip()

    if method == "http://www.w3.org/2000/09/xmldsig#sha1":
        computed_cert_digest = sha1(cert.public_bytes(serialization.Encoding.DER))
    else:
        computed_cert_digest = sha256(cert.public_bytes(serialization.Encoding.DER))

    print(f"Expected: {expected_cert_digest}")
    print(f"Computed: {computed_cert_digest}")
    if expected_cert_digest == computed_cert_digest:
        print("✔ SigningCertificate digest VALID")
    else:
        print("✘ SigningCertificate digest INVALID")

    print("\n=== Step 5: Validate XAdES SignaturePolicyHash (EPES) ===")
    policy_hash_el = signature.find(
        "ds:Object/xades:QualifyingProperties/xades:SignedProperties/"
        "xades:SignedSignatureProperties/xades:SignaturePolicyIdentifier/"
        "xades:SignaturePolicyId/xades:SigPolicyHash/ds:DigestValue",
        NS
    )
    policy_method = signature.find(
        "ds:Object/xades:QualifyingProperties/xades:SignedProperties/"
        "xades:SignedSignatureProperties/xades:SignaturePolicyIdentifier/"
        "xades:SignaturePolicyId/xades:SigPolicyHash/ds:DigestMethod",
        NS
    ).get("Algorithm")

    expected_policy_hash = policy_hash_el.text.strip()

    print(f"Policy digest given in XML: {expected_policy_hash}")
    print(f"Digest method: {policy_method}")

    print("\nValidating policy hash...")
    policy_identifier_el = signature.find(
        "ds:Object/xades:QualifyingProperties/xades:SignedProperties/"
        "xades:SignedSignatureProperties/xades:SignaturePolicyIdentifier/"
        "xades:SignaturePolicyId/xades:SigPolicyId/xades:Identifier",
        NS
    )
    if policy_identifier_el is None:
        print("✘ No policy identifier found")
    else:
        policy_identifier = policy_identifier_el.text.strip()
        print(f"Policy Identifier: {policy_identifier}")
        try:
            if policy_identifier.startswith("urn:oid:"):
                if policy_identifier == "urn:oid:2.16.724.1.3.1.1.2.1.9":
                    policy_url = "https://sede.administracion.gob.es/politica_de_firma_anexo_1.pdf"
                else:
                    raise ValueError(f"Unknown OID: {policy_identifier}")
            else:
                policy_url = policy_identifier

            with urllib.request.urlopen(policy_url) as response:
                policy_data = response.read()
            if policy_method == "http://www.w3.org/2000/09/xmldsig#sha1":
                computed_hash = base64.b64encode(hashlib.sha1(policy_data).digest()).decode()
            elif policy_method == "http://www.w3.org/2001/04/xmlenc#sha256":
                computed_hash = base64.b64encode(hashlib.sha256(policy_data).digest()).decode()
            else:
                print(f"Unsupported digest method: {policy_method}")
                computed_hash = None
            if computed_hash:
                print(f"Computed policy hash: {computed_hash}")
                if computed_hash == expected_policy_hash:
                    print("✔ Policy hash VALID")
                else:
                    print("✘ Policy hash INVALID")
        except Exception as e:
            print(f"Error fetching or computing policy hash: {e}")


    print("\n=== VALIDATION FINISHED ===")


if __name__ == "__main__":
    main()
Responder Con Cita
 



Normas de Publicación
no Puedes crear nuevos temas
no Puedes responder a temas
no Puedes adjuntar archivos
no Puedes editar tus mensajes

El código vB está habilitado
Las caritas están habilitado
Código [IMG] está habilitado
Código HTML está deshabilitado
Saltar a Foro

Temas Similares
Tema Autor Foro Respuestas Último mensaje
Cuando generar registro de eventos. y duda certificado FelixInasa Registros de Facturacion y Eventos (XML) 4 19-01-2026 17:36:30
Ejemplo registro de ANULACIÓN Decanato Envío de registros y sus respuestas 2 30-05-2025 19:47:19
XML Registro de Eventos Firmado ilisoft21 Registros de Facturacion y Eventos (XML) 1 10-02-2025 09:49:49
Registro de eventos en modo Veri*Factu rci Registros de Facturacion y Eventos (XML) 15 15-01-2025 16:27:39


La franja horaria es GMT +2. Ahora son las 11:30:32.


Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2026, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi
Copyright 1996-2007 Club Delphi