/*
* XAdES4j - A Java library for generation and verification of XAdES signatures.
* Copyright (C) 2011 Luis Goncalves.
*
* XAdES4j is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 3 of the License, or any later version.
*
* XAdES4j is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License along
* with XAdES4j. If not, see <http://www.gnu.org/licenses/>.
*/
package xades4j.production;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import org.apache.xml.security.exceptions.XMLSecurityException;
import org.apache.xml.security.keys.content.X509Data;
import org.apache.xml.security.signature.XMLSignature;
import org.apache.xml.security.signature.XMLSignatureException;
import org.apache.xml.security.transforms.Transforms;
import xades4j.UnsupportedAlgorithmException;
import xades4j.algorithms.Algorithm;
import xades4j.providers.AlgorithmsProviderEx;
import xades4j.providers.BasicSignatureOptionsProvider;
import xades4j.utils.CanonicalizerUtils;
import xades4j.utils.TransformUtils;
import xades4j.xml.marshalling.algorithms.AlgorithmsParametersMarshallingProvider;
/**
* Helper class that creates the {@code ds:KeyInfo} element accordingly to some
* signature options. The signing certificate validity and key usages are validated.
* @author Luís
*/
class KeyInfoBuilder
{
private final BasicSignatureOptionsProvider basicSignatureOptionsProvider;
private final AlgorithmsProviderEx algorithmsProvider;
private final AlgorithmsParametersMarshallingProvider algorithmsParametersMarshaller;
KeyInfoBuilder(
BasicSignatureOptionsProvider basicSignatureOptionsProvider,
AlgorithmsProviderEx algorithmsProvider,
AlgorithmsParametersMarshallingProvider algorithmsParametersMarshaller)
{
this.basicSignatureOptionsProvider = basicSignatureOptionsProvider;
this.algorithmsProvider = algorithmsProvider;
this.algorithmsParametersMarshaller = algorithmsParametersMarshaller;
}
void buildKeyInfo(
X509Certificate signingCertificate,
XMLSignature xmlSig) throws KeyingDataException, UnsupportedAlgorithmException
{
// Check key usage.
// - KeyUsage[0] = digitalSignature
// - KeyUsage[1] = nonRepudiation
boolean[] keyUsage = signingCertificate.getKeyUsage();
if (keyUsage != null && !keyUsage[0] && !keyUsage[1])
{
throw new SigningCertKeyUsageException(signingCertificate);
}
try
{
signingCertificate.checkValidity();
} catch (CertificateException ce)
{
// CertificateExpiredException or CertificateNotYetValidException
throw new SigningCertValidityException(signingCertificate);
}
if (this.basicSignatureOptionsProvider.includeSigningCertificate())
{
try
{
X509Data x509Data = new X509Data(xmlSig.getDocument());
x509Data.addCertificate(signingCertificate);
x509Data.addSubjectName(signingCertificate);
x509Data.addIssuerSerial(signingCertificate.getIssuerX500Principal().getName(), signingCertificate.getSerialNumber());
xmlSig.getKeyInfo().add(x509Data);
if (this.basicSignatureOptionsProvider.signSigningCertificate())
{
String keyInfoId = xmlSig.getId() + "-keyinfo";
xmlSig.getKeyInfo().setId(keyInfoId);
// Use same canonicalization URI as specified in the ds:CanonicalizationMethod for Signature.
Algorithm canonAlg = this.algorithmsProvider.getCanonicalizationAlgorithmForSignature();
CanonicalizerUtils.checkC14NAlgorithm(canonAlg);
Transforms transforms = TransformUtils.createTransforms(canonAlg, this.algorithmsParametersMarshaller, xmlSig.getDocument());
xmlSig.addDocument(
'#' + keyInfoId,
transforms,
this.algorithmsProvider.getDigestAlgorithmForDataObjsReferences());
}
} catch (XMLSignatureException ex)
{
throw new UnsupportedAlgorithmException(
"Digest algorithm not supported in the XML Signature provider",
this.algorithmsProvider.getDigestAlgorithmForDataObjsReferences(), ex);
} catch (XMLSecurityException ex)
{
throw new KeyingDataException(ex.getMessage(), ex);
}
}
if (this.basicSignatureOptionsProvider.includePublicKey())
{
xmlSig.addKeyInfo(signingCertificate.getPublicKey());
}
}
}