/*
* Copyright 2008 Federal Chancellery Austria and
* Graz University of Technology
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package at.gv.egiz.xades;
import at.gv.egiz.marshal.MarshallerFactory;
import at.gv.egiz.marshal.NamespacePrefixMapperImpl;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateEncodingException;
import java.security.cert.X509Certificate;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.TimeZone;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.PropertyException;
import javax.xml.crypto.dsig.DigestMethod;
import javax.xml.datatype.DatatypeConfigurationException;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.XMLGregorianCalendar;
import org.etsi.uri._01903.v1_1.CertIDListType;
import org.etsi.uri._01903.v1_1.CertIDType;
import org.etsi.uri._01903.v1_1.DataObjectFormatType;
import org.etsi.uri._01903.v1_1.DigestAlgAndValueType;
import org.etsi.uri._01903.v1_1.QualifyingPropertiesType;
import org.etsi.uri._01903.v1_1.SignaturePolicyIdentifierType;
import org.etsi.uri._01903.v1_1.SignedDataObjectPropertiesType;
import org.etsi.uri._01903.v1_1.SignedPropertiesType;
import org.etsi.uri._01903.v1_1.SignedSignaturePropertiesType;
import org.w3._2000._09.xmldsig_.DigestMethodType;
import org.w3._2000._09.xmldsig_.X509IssuerSerialType;
import org.w3c.dom.Node;
public class QualifyingPropertiesFactory {
public static String NS_URI_V1_1_1 = "http://uri.etsi.org/01903/v1.1.1#";
public static String SIGNED_PROPERTIES_REFERENCE_TYPE_V1_1_1 = NS_URI_V1_1_1 + "SignedProperties";
private static QualifyingPropertiesFactory instance;
/**
* The JAXBContext
.
*/
private static JAXBContext jaxbContext;
public static synchronized QualifyingPropertiesFactory getInstance() {
if (instance == null) {
instance = new QualifyingPropertiesFactory();
}
return instance;
}
private DatatypeFactory datatypeFactory;
private org.etsi.uri._01903.v1_1.ObjectFactory qpFactory;
private org.w3._2000._09.xmldsig_.ObjectFactory dsFactory;
public QualifyingPropertiesFactory() {
try {
datatypeFactory = DatatypeFactory.newInstance();
} catch (DatatypeConfigurationException e) {
throw new RuntimeException(e);
}
qpFactory = new org.etsi.uri._01903.v1_1.ObjectFactory();
dsFactory = new org.w3._2000._09.xmldsig_.ObjectFactory();
StringBuffer packageNames = new StringBuffer();
packageNames.append(org.etsi.uri._01903.v1_1.ObjectFactory.class.getPackage().getName());
packageNames.append(":");
packageNames.append(org.w3._2000._09.xmldsig_.ObjectFactory.class.getPackage().getName());
try {
jaxbContext = JAXBContext.newInstance(packageNames.toString());
} catch (JAXBException e) {
// we should not get an JAXBException initializing the JAXBContext
throw new RuntimeException(e);
}
}
public DigestAlgAndValueType createDigestAlgAndValueType(X509Certificate certificate) throws QualifyingPropertiesException {
DigestMethodType digestMethodType = dsFactory.createDigestMethodType();
digestMethodType.setAlgorithm(DigestMethod.SHA1);
byte[] digest;
try {
MessageDigest messageDigest = MessageDigest.getInstance("SHA-1");
digest = messageDigest.digest(certificate.getEncoded());
} catch (CertificateEncodingException e) {
throw new QualifyingPropertiesException(e);
} catch (NoSuchAlgorithmException e) {
throw new QualifyingPropertiesException(e);
}
DigestAlgAndValueType digestAlgAndValueType = qpFactory.createDigestAlgAndValueType();
digestAlgAndValueType.setDigestMethod(digestMethodType);
digestAlgAndValueType.setDigestValue(digest);
return digestAlgAndValueType;
}
public X509IssuerSerialType createX509IssuerSerialType(X509Certificate certificate) {
String name = certificate.getIssuerX500Principal().getName("RFC2253");
BigInteger serialNumber = certificate.getSerialNumber();
X509IssuerSerialType issuerSerialType = dsFactory.createX509IssuerSerialType();
issuerSerialType.setX509IssuerName(name);
issuerSerialType.setX509SerialNumber(serialNumber);
return issuerSerialType;
}
public DataObjectFormatType createDataObjectFormatType(String objectReference, String mimeType, String description) {
DataObjectFormatType dataObjectFormatType = qpFactory.createDataObjectFormatType();
dataObjectFormatType.setObjectReference(objectReference);
if (mimeType != null) {
dataObjectFormatType.setMimeType(mimeType);
}
if (description != null) {
dataObjectFormatType.setDescription(description);
}
return dataObjectFormatType;
}
public JAXBElement createQualifyingProperties111(Date signingTime, List certificates, String idValue, List dataObjectFormats) throws QualifyingPropertiesException {
GregorianCalendar gregorianCalendar = new GregorianCalendar();
gregorianCalendar.setTimeZone(TimeZone.getTimeZone("UTC"));
gregorianCalendar.setTime(signingTime);
SignedSignaturePropertiesType signedSignaturePropertiesType = qpFactory.createSignedSignaturePropertiesType();
// SigningTime
XMLGregorianCalendar xmlGregorianCalendar = datatypeFactory.newXMLGregorianCalendar(gregorianCalendar);
xmlGregorianCalendar.setFractionalSecond(null);
signedSignaturePropertiesType.setSigningTime(xmlGregorianCalendar);
// SigningCertificate
CertIDListType certIDListType = qpFactory.createCertIDListType();
List certIDs = certIDListType.getCert();
for (X509Certificate certificate : certificates) {
CertIDType certIDType = qpFactory.createCertIDType();
certIDType.setCertDigest(createDigestAlgAndValueType(certificate));
certIDType.setIssuerSerial(createX509IssuerSerialType(certificate));
certIDs.add(certIDType);
}
signedSignaturePropertiesType.setSigningCertificate(certIDListType);
// SignaturePolicy
SignaturePolicyIdentifierType signaturePolicyIdentifierType = qpFactory.createSignaturePolicyIdentifierType();
signaturePolicyIdentifierType.setSignaturePolicyImplied(new SignaturePolicyIdentifierType.SignaturePolicyImplied());
signedSignaturePropertiesType.setSignaturePolicyIdentifier(signaturePolicyIdentifierType);
// SignedProperties
SignedPropertiesType signedPropertiesType = qpFactory.createSignedPropertiesType();
signedPropertiesType.setSignedSignatureProperties(signedSignaturePropertiesType);
// DataObjectFormat
if (dataObjectFormats != null && !dataObjectFormats.isEmpty()) {
SignedDataObjectPropertiesType signedDataObjectPropertiesType = qpFactory.createSignedDataObjectPropertiesType();
List dataObjectFormatTypes = signedDataObjectPropertiesType.getDataObjectFormat();
dataObjectFormatTypes.addAll(dataObjectFormats);
signedPropertiesType.setSignedDataObjectProperties(signedDataObjectPropertiesType);
}
signedPropertiesType.setId(idValue);
// QualifyingProperties
QualifyingPropertiesType qualifyingPropertiesType = qpFactory.createQualifyingPropertiesType();
qualifyingPropertiesType.setSignedProperties(signedPropertiesType);
return qpFactory.createQualifyingProperties(qualifyingPropertiesType);
}
public void marshallQualifyingProperties(JAXBElement qualifyingProperties, Node parent) throws JAXBException {
try {
Marshaller marshaller = MarshallerFactory.createMarshaller(jaxbContext, true);
marshaller.marshal(qualifyingProperties, parent);
} catch (PropertyException e) {
throw new RuntimeException(e);
}
}
}