You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用xades4j库签署厄瓜多尔SRI合规XML发票遇结构错误求助

厄瓜多尔SRI XML发票XAdES-BES签名结构错误排查与修复

SRI合规要求回顾

  • 签名标准:XAdES-BES
  • Schema版本:1.3.2
  • 编码:UTF-8
  • 签名类型:Enveloped

代码问题分析与修复方案

1. 核心算法适配问题

SRI 1.3.2 Schema已弃用SHA-1算法,必须使用SHA-256作为摘要和签名算法,这是签名结构验证失败的核心原因之一。同时要修正DSA算法ID的错误配置。

2. 证书链配置缺失

fullChain(false)会导致签名中缺少完整证书链,SRI要求完整信任链来验证签名有效性,需改为fullChain(true)。

3. Enveloped签名的Transform顺序

需先执行XML规范化(Canonicalization),再应用Enveloped转换,确保签名计算的内容与SRI验证逻辑一致。

4. XML输出编码强制指定

Transformer默认编码可能不是UTF-8,需显式设置输出编码为UTF-8。

5. 签名引用与属性完善

明确DataObject的MIME类型,避免属性缺失导致结构验证失败。

修改后的完整代码

public static void main(String[] args) {
    Document doc = null;
    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
    factory.setNamespaceAware(true);
    factory.setXIncludeAware(true); // 适配SRI Schema的XInclude要求
    
    try {
        DocumentBuilder builder = factory.newDocumentBuilder();
        doc = builder.parse(new File("filepath")); 
    } catch (ParserConfigurationException e) {
        System.err.println("无法解析XML");
        e.printStackTrace();
    } catch (SAXException | IOException e) {
        e.printStackTrace();
    }   
                
    // 配置完整证书链的KeyStore
    KeyingDataProvider kp = FileSystemKeyStoreKeyingDataProvider
            .builder("pkcs12", "keystorepath", SigningCertificateSelector.single())
            .storePassword(new DirectPasswordProvider(args[1]))
            .entryPassword(new DirectPasswordProvider(args[1]))
            .fullChain(true)
            .build();
        
    // 配置SHA-256系列算法,适配SRI要求
    XadesBesSigningProfile p = new XadesBesSigningProfile(kp)
            .withSignatureAlgorithms(new SignatureAlgorithms()
                    .withDigestAlgorithmForDataObjectReferences(MessageDigestAlgorithm.ALGO_ID_DIGEST_SHA256)
                    .withDigestAlgorithmForReferenceProperties(MessageDigestAlgorithm.ALGO_ID_DIGEST_SHA256)
                    .withDigestAlgorithmForTimeStampProperties(MessageDigestAlgorithm.ALGO_ID_DIGEST_SHA256)
                    .withSignatureAlgorithm("RSA", XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA256)
                    .withSignatureAlgorithm("EC", XMLSignature.ALGO_ID_SIGNATURE_ECDSA_SHA256)
                    .withSignatureAlgorithm("DSA", XMLSignature.ALGO_ID_SIGNATURE_DSA_SHA256))
            .withBasicSignatureOptions(new BasicSignatureOptions()
                    .includePublicKey(true)
                    .signKeyInfo(true));
                    
    // 配置Enveloped签名的引用与Transform顺序
    DataObjectDesc obj = new DataObjectReference("")
            .withTransform(new CanonicalizationMethod(CanonicalizationMethod.INCLUSIVE_WITH_COMMENTS))
            .withTransform(new EnvelopedSignatureTransform())
            .withDataObjectFormat(new DataObjectFormatProperty("text/xml")
                    .withDescription("contenido comprobante")
                    .withMimeType("text/xml"));
    SignedDataObjects dataObjs = new SignedDataObjects(obj);
        
    try {
        XadesSigner signer = p.newSigner();
        Element elemToSign = doc.getDocumentElement();
        signer.sign(dataObjs, elemToSign);
        
        // 强制UTF-8编码输出XML
        TransformerFactory tf = TransformerFactory.newInstance();
        Transformer transformer = tf.newTransformer();
        transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
        transformer.setOutputProperty(OutputKeys.INDENT, "yes"); // 可选,便于调试
        
        DOMSource source = new DOMSource(elemToSign);
        StreamResult result = new StreamResult(new File("outputPathFile"));
        transformer.transform(source, result);
            
    } catch (XadesProfileResolutionException e) {
        System.err.println("无法创建签名器");
        e.printStackTrace();
    } catch (XAdES4jException | TransformerException e) {
        e.printStackTrace();
    }
}

额外排查步骤

  • 逐节点对比参考XML:重点检查命名空间(XAdES/DSIG)、Signature节点位置、SignedInfo中的Reference属性、KeyInfo证书链是否与有效参考XML完全一致
  • Schema验证:使用SRI提供的1.3.2 Schema对签名后的XML做结构验证,排查节点缺失或格式错误
  • 证书有效性检查:确认使用的证书为SRI认可的机构颁发,未过期且私钥未损坏
  • 时间戳配置:若SRI要求签名包含时间戳,需补充对应的时间戳服务配置

内容的提问来源于stack exchange,提问作者JazzDTap

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 21:53:22