Xades-Bes转换为Xades-T

时间:2014-08-11 20:34:00

标签: java timestamp digital-signature xml-signature xades4j

如何将XAdES-BES转换为XAdES-T。我使用Xades4j库。我有一个时间戳帐户。

我的SignerBes.class

package xades4j.production;

import java.security.PrivateKey;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import org.apache.xml.security.exceptions.XMLSecurityException;
import org.apache.xml.security.signature.ObjectContainer;
import org.apache.xml.security.signature.Reference;
import org.apache.xml.security.signature.XMLSignature;
import org.apache.xml.security.signature.XMLSignatureException;
import org.apache.xml.security.utils.Constants;
import org.apache.xml.security.utils.ElementProxy;
import org.w3c.dom.Element;
import org.w3c.dom.Node;

import xades4j.UnsupportedAlgorithmException;
import xades4j.XAdES4jException;
import xades4j.XAdES4jXMLSigException;
import xades4j.properties.DataObjectDesc;
import xades4j.properties.QualifyingProperties;
import xades4j.properties.QualifyingProperty;
import xades4j.properties.SignedSignatureProperty;
import xades4j.properties.SigningCertificateProperty;
import xades4j.properties.UnsignedSignatureProperty;
import xades4j.properties.data.SigAndDataObjsPropertiesData;
import xades4j.providers.AlgorithmsProvider;
import xades4j.providers.BasicSignatureOptionsProvider;
import xades4j.providers.DataObjectPropertiesProvider;
import xades4j.providers.KeyingDataProvider;
import xades4j.providers.SignaturePropertiesProvider;
import xades4j.providers.SigningCertChainException;
import xades4j.utils.DOMHelper;
import xades4j.utils.ObjectUtils;
import xades4j.xml.marshalling.SignedPropertiesMarshaller;
import xades4j.xml.marshalling.UnsignedPropertiesMarshaller;

import com.google.inject.Inject;
import org.apache.xml.security.c14n.InvalidCanonicalizerException;
import org.apache.xml.security.signature.SignedInfo;
import org.w3c.dom.Document;
import xades4j.providers.MessageDigestEngineProvider;
import xades4j.providers.impl.DefaultMessageDigestProvider;

/**
 * Base logic for producing XAdES signatures (XAdES-BES).
 *
 * @author Luis
 * @author murat.demir
 */
class SignerBES implements XadesSigner {

    static {
        Init.initXMLSec();
//        Security.addProvider(new RemoteTokenProvider());
    }
    /**/
    private final KeyingDataProvider keyingProvider;
    private final AlgorithmsProvider algorithmsProvider;
    private final PropertiesDataObjectsGenerator propsDataObjectsGenerator;
    private final SignedPropertiesMarshaller signedPropsMarshaller;
    private final UnsignedPropertiesMarshaller unsignedPropsMarshaller;
    /**/
    private final DataObjectDescsProcessor dataObjectDescsProcessor;
    private final KeyInfoBuilder keyInfoBuilder;
    private final QualifyingPropertiesProcessor qualifPropsProcessor;

    /**/
    private MessageDigestEngineProvider messageDigestEngineProvider = null;
    private XMLSignature signature = null;
    private X509Certificate x509Certificate = null;
    private String signatureId = null;
    private PropertiesDataGenerationContext propsDataGenCtx = null;
    private QualifyingProperties qualifProps = null;
    private Element qualifyingPropsElem = null;
    private Document signatureDocument = null;

    @Inject
    protected SignerBES(KeyingDataProvider keyingProvider, AlgorithmsProvider algorithmsProvider, BasicSignatureOptionsProvider basicSignatureOptionsProvider, SignaturePropertiesProvider signaturePropsProvider, DataObjectPropertiesProvider dataObjPropsProvider, PropertiesDataObjectsGenerator propsDataObjectsGenerator, SignedPropertiesMarshaller signedPropsMarshaller, UnsignedPropertiesMarshaller unsignedPropsMarshaller) {
        if (ObjectUtils.anyNull(keyingProvider, algorithmsProvider, signaturePropsProvider, dataObjPropsProvider, propsDataObjectsGenerator,
                signedPropsMarshaller, unsignedPropsMarshaller)) {
            throw new NullPointerException("One or more arguments are null");
        }

        this.keyingProvider = keyingProvider;
        this.algorithmsProvider = algorithmsProvider;
        this.propsDataObjectsGenerator = propsDataObjectsGenerator;
        this.signedPropsMarshaller = signedPropsMarshaller;
        this.unsignedPropsMarshaller = unsignedPropsMarshaller;

        this.dataObjectDescsProcessor = new DataObjectDescsProcessor(algorithmsProvider);
        this.keyInfoBuilder = new KeyInfoBuilder(basicSignatureOptionsProvider, algorithmsProvider);
        this.qualifPropsProcessor = new QualifyingPropertiesProcessor(signaturePropsProvider, dataObjPropsProvider);

        this.messageDigestEngineProvider = new DefaultMessageDigestProvider();
    }

    //------------------------------  for Remote Signature -------------------------------------
    @Override
    public XadesSignatureResult sign(byte[] signedHash) throws Exception {
        this.signature.setSignatureValueElement(signedHash);

        // Set the ds:SignatureValue id.
        Element sigValueElem = DOMHelper.getFirstDescendant(this.signature.getElement(), Constants.SignatureSpecNS, Constants._TAG_SIGNATUREVALUE);
        sigValueElem.setAttributeNS(null, Constants._ATT_ID, String.format("%s-sigvalue", signatureId));

        /* Marshal unsigned properties */
        // Generate the unsigned properties data objects. The data objects
        // structure
        // is verifier in the process.
        this.propsDataGenCtx.setTargetXmlSignature(this.signature);
        SigAndDataObjsPropertiesData unsignedPropsData = this.propsDataObjectsGenerator.generateUnsignedPropertiesData(this.qualifProps.getUnsignedProperties(), this.propsDataGenCtx);

        // Marshal the unsigned properties to the final QualifyingProperties  node.
        this.unsignedPropsMarshaller.marshal(unsignedPropsData, String.format("%s-unsignedprops", this.signatureId), this.qualifyingPropsElem);

        return new XadesSignatureResult(this.signature, this.qualifProps);
    }

    @Override
    public byte[] prepareDataToSign(SignedDataObjects signedDataObjects, Node parent, X509Certificate certificate) throws XAdES4jException {
        if (null == signedDataObjects) {
            throw new NullPointerException("References cannot be null");
        }
        if (null == parent) {
            throw new NullPointerException("Parent node cannot be null");
        }
        if (signedDataObjects.isEmpty()) {
            throw new IllegalArgumentException("Data objects list is empty");
        }

        this.signatureDocument = DOMHelper.getOwnerDocument(parent);

        // Generate unique identifiers for the Signature and the
        // SignedProperties.
        this.signatureId = String.format("xmldsig-%s", UUID.randomUUID());
        String signedPropsId = String.format("%s-signedprops", signatureId);

        // Signing certificate chain (may contain only the signing certificate).
        this.x509Certificate = certificate;
        List<X509Certificate> signingCertificateChain = new ArrayList<X509Certificate>();
        signingCertificateChain.add(this.x509Certificate);
        if (null == signingCertificateChain || signingCertificateChain.isEmpty()) {
            throw new SigningCertChainException("Signing certificate not provided");
        }

        // Get the specific signature algorithm for the key's algorithm.
        String sigAlgUri = this.algorithmsProvider.getSignatureAlgorithm(this.x509Certificate.getPublicKey().getAlgorithm());
        if (null == sigAlgUri) {
            throw new NullPointerException("Signature algorithm URI not provided");
        }

        String canonAlgUri = this.algorithmsProvider.getCanonicalizationAlgorithmForSignature();
        if (null == canonAlgUri) {
            throw new NullPointerException("Canonicalization algorithm URI not provided");
        }

        String digestAlgUri = this.algorithmsProvider.getDigestAlgorithmForDataObjsReferences();
        if (null == digestAlgUri) {
            throw new NullPointerException("Digest algorithm URI not provided");
        }

        try {
            this.signature = new XMLSignature(this.signatureDocument, signedDataObjects.getBaseUri(), sigAlgUri, canonAlgUri);
            this.signature.setId(this.signatureId);
        } catch (XMLSecurityException ex) {
            // Following the code, doesn't seem to be thrown at all.
            throw new XAdES4jXMLSigException(ex.getMessage());
        }

        /* References */
        // Process the data object descriptions to get the References and
        // mappings.
        // After this call all the signed data objects References and XMLObjects
        // are added to the signature.
        Map<DataObjectDesc, Reference> referenceMappings = this.dataObjectDescsProcessor.process(signedDataObjects.getDataObjectsDescs(), this.signature);

        /* SignedProperties reference */
        // XAdES 6.3.1: "In order to protect the properties with the signature,
        // a ds:Reference element MUST be added to the XMLDSIG signature (...)
        // composed in such a way that it uses the SignedProperties element
        // (...)
        // as the input for computing its corresponding digest. Additionally,
        // (...) use the Type attribute of this particular ds:Reference element,
        // with its value set to: http://uri.etsi.org/01903#SignedProperties."
        try {
            this.signature.addDocument('#' + signedPropsId, null, digestAlgUri, null, QualifyingProperty.SIGNED_PROPS_TYPE_URI);
        } catch (XMLSignatureException ex) {
            // Seems to be thrown when the digest algorithm is not supported. In
            // this case, if it wasn't thrown when processing the data objects
            // it
            // shouldn't be thrown now!
            throw new UnsupportedAlgorithmException("Digest algorithm not supported in the XML Signature provider: " + ex.getMessage(), digestAlgUri);
        }

        /* QualifyingProperties element */
        // Create the QualifyingProperties element
        this.qualifyingPropsElem = ElementProxy.createElementForFamily(this.signature.getDocument(), QualifyingProperty.XADES_XMLNS, QualifyingProperty.QUALIFYING_PROPS_TAG);
        this.qualifyingPropsElem.setAttributeNS(null, QualifyingProperty.TARGET_ATTR, '#' + this.signatureId);
        this.qualifyingPropsElem.setAttributeNS(Constants.NamespaceSpecNS, "xmlns:xades141", QualifyingProperty.XADESV141_XMLNS);
        // ds:Object to contain QualifyingProperties
        ObjectContainer qPropsXmlObj = new ObjectContainer(signature.getDocument());
        qPropsXmlObj.appendChild(this.qualifyingPropsElem);
        try {
            this.signature.appendObject(qPropsXmlObj);
        } catch (XMLSignatureException ex) {
            // -> xmlSignature.appendObject(xmlObj): not thrown when signing.
            throw new IllegalStateException(ex);
        }

        /* Collect the properties */
        // Get the format specific signature properties.
        Collection<SignedSignatureProperty> fsssp = new ArrayList<SignedSignatureProperty>(2);
        Collection<UnsignedSignatureProperty> fsusp = new ArrayList<UnsignedSignatureProperty>(2);
        getFormatSpecificSignatureProperties(fsssp, fsusp, signingCertificateChain);
        // Gather all the signature and data objects properties.
        this.qualifProps = this.qualifPropsProcessor.getQualifyingProperties(signedDataObjects, fsssp, fsusp);

        /* Marshal the signed properties */
        // Create the context for signed properties data objects generation.
        this.propsDataGenCtx = new PropertiesDataGenerationContext(signedDataObjects.getDataObjectsDescs(), referenceMappings, parent, this.algorithmsProvider);

        // Generate the signed properties data objects. The data objects
        // structure
        // is verifier in the process.
        SigAndDataObjsPropertiesData signedPropsData = this.propsDataObjectsGenerator.generateSignedPropertiesData(this.qualifProps.getSignedProperties(), this.propsDataGenCtx);

        // Marshal the signed properties data to the QualifyingProperties node.
        this.signedPropsMarshaller.marshal(signedPropsData, signedPropsId, this.qualifyingPropsElem);

        /* ds:KeyInfo */
        this.keyInfoBuilder.buildKeyInfo(this.x509Certificate, this.signature);

        try {
            parent.appendChild(this.signature.getElement());
            try {
                SignedInfo si = this.signature.getSignedInfo();
                si.generateDigestValues();
                byte[] data = si.getCanonicalizedOctetStream();

//                byte[] raw = this.signature.getDataToSign();
//                MessageDigest messageDigest = this.messageDigestEngineProvider.getEngine(digestAlgUri);
//                byte[] digestedData = messageDigest.digest(raw);
//                DigestInfo dInfo = new DigestInfo(new AlgorithmIdentifier(new DERObjectIdentifier(NISTObjectIdentifiers.id_sha256.getId()), new DERNull()), digestedData);
//                byte[] der = dInfo.getEncoded("DER");
//                return this.signature.getDataToSign();
                return data;
            } catch (XMLSignatureException ex) {
                throw new XAdES4jXMLSigException(ex.getMessage(), ex);
            } catch (InvalidCanonicalizerException ex) {
                ex.printStackTrace();
            } catch (XMLSecurityException ex) {
                ex.printStackTrace();
            }
        } catch (XAdES4jException ex) {
            parent.removeChild(signature.getElement());
            throw ex;
        }
        return null;
    }
}

我修改了SignerBes类。我的签约操作分为两部分。

  • 第一步,prepareDataToSign()
  • 第二步,签署()

到目前为止对Xades-Bes格式有好处..我想将Xades-Bes转换为Xades-T

相关问题