/* * 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.bku.slcommands.impl; import java.io.ByteArrayInputStream; import java.security.NoSuchAlgorithmException; import java.security.cert.CertificateException; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; import java.util.Collections; import java.util.Date; import javax.xml.crypto.MarshalException; import javax.xml.crypto.URIReferenceException; import javax.xml.crypto.dsig.XMLSignatureException; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.w3c.dom.ls.DOMImplementationLS; import org.w3c.dom.ls.LSSerializer; import at.buergerkarte.namespaces.securitylayer._1.CreateXMLSignatureRequestType; import at.buergerkarte.namespaces.securitylayer._1.DataObjectInfoType; import at.gv.egiz.bku.slcommands.CreateXMLSignatureCommand; import at.gv.egiz.bku.slcommands.SLCommandContext; import at.gv.egiz.bku.slcommands.SLResult; import at.gv.egiz.bku.slcommands.impl.xsect.AlgorithmMethodFactory; import at.gv.egiz.bku.slcommands.impl.xsect.AlgorithmMethodFactoryImpl; import at.gv.egiz.bku.slcommands.impl.xsect.IdValueFactory; import at.gv.egiz.bku.slcommands.impl.xsect.IdValueFactoryImpl; import at.gv.egiz.bku.slcommands.impl.xsect.Signature; import at.gv.egiz.bku.slexceptions.SLCommandException; import at.gv.egiz.bku.slexceptions.SLException; import at.gv.egiz.bku.slexceptions.SLRequestException; import at.gv.egiz.bku.slexceptions.SLViewerException; import at.gv.egiz.dom.DOMUtils; import at.gv.egiz.stal.InfoboxReadRequest; import at.gv.egiz.stal.InfoboxReadResponse; import at.gv.egiz.stal.STALRequest; import at.gv.egiz.stal.STALResponse; /** * This class implements the security layer command CreateXMLSignatureRequest. * * @author mcentner */ public class CreateXMLSignatureCommandImpl extends SLCommandImpl implements CreateXMLSignatureCommand { /** * Logging facility. */ protected static Log log = LogFactory.getLog(CreateXMLSignatureCommandImpl.class); /** * The signing certificate. */ protected X509Certificate signingCertificate; /** * The keybox identifier of the key used for signing. */ protected String keyboxIdentifier; /** * The to-be signed signature. */ protected Signature signature; @Override public void init(SLCommandContext ctx, Object unmarshalledRequest) throws SLCommandException { super.init(ctx, unmarshalledRequest); } @Override public void prepareXMLSignature() throws SLCommandException, SLRequestException { CreateXMLSignatureRequestType request = getRequestValue(); // TODO: make configurable? IdValueFactory idValueFactory = new IdValueFactoryImpl(); // TODO: make configurable? AlgorithmMethodFactory algorithmMethodFactory; try { algorithmMethodFactory = new AlgorithmMethodFactoryImpl(signingCertificate); } catch (NoSuchAlgorithmException e) { log.error("Failed to get DigestMethod.", e); throw new SLCommandException(4006); } signature = new Signature(getCmdCtx().getURLDereferencerContext(), idValueFactory, algorithmMethodFactory); // SigningTime signature.setSigningTime(new Date()); // SigningCertificate signature.setSignerCeritifcate(signingCertificate); // SignatureInfo if (request.getSignatureInfo() != null) { signature.setSignatureInfo(request.getSignatureInfo()); } // DataObjects for (DataObjectInfoType dataObjectInfo : request.getDataObjectInfo()) { signature.addDataObject(dataObjectInfo); } signature.buildXMLSignature(); } /** * Gets the signing certificate from STAL. * * @throws SLCommandException * if getting the singing certificate fails */ private void getSigningCertificate() throws SLCommandException { CreateXMLSignatureRequestType request = getRequestValue(); keyboxIdentifier = request.getKeyboxIdentifier(); InfoboxReadRequest stalRequest = new InfoboxReadRequest(); stalRequest.setInfoboxIdentifier(keyboxIdentifier); requestSTAL(Collections.singletonList((STALRequest) stalRequest)); STALResponse stalResponse = stalResponses.next(); if (stalResponse instanceof InfoboxReadResponse) { byte[] infobox = ((InfoboxReadResponse) stalResponse).getInfoboxValue(); try { CertificateFactory certFactory = CertificateFactory.getInstance("X509"); signingCertificate = (X509Certificate) certFactory.generateCertificate(new ByteArrayInputStream(infobox)); } catch (CertificateException e) { log.info("Failed to decode signing certificate.", e); // TODO: issue appropriate error throw new SLCommandException(4000); } } else { log.info("Failed to get signing certificate."); // TODO: issue appropriate error throw new SLCommandException(4000); } } /** * Signs the signature. * * @throws SLCommandException * if signing the signature fails * @throws SLViewerException */ private void signXMLSignature() throws SLCommandException, SLViewerException { try { signature.sign(getCmdCtx().getSTAL(), keyboxIdentifier); } catch (MarshalException e) { log.error("Failed to marshall XMLSignature.", e); throw new SLCommandException(4000); } catch (XMLSignatureException e) { if (e.getCause() instanceof URIReferenceException) { URIReferenceException uriReferenceException = (URIReferenceException) e.getCause(); if (uriReferenceException.getCause() instanceof SLCommandException) { throw (SLCommandException) uriReferenceException.getCause(); } } log.error("Failed to sign XMLSignature.", e); throw new SLCommandException(4000); } } @Override public SLResult execute() { try { // get certificate in order to select appropriate algorithms for hashing and signing getSigningCertificate(); // prepare the XMLSignature for signing prepareXMLSignature(); // sign the XMLSignature signXMLSignature(); if (log.isTraceEnabled()) { DOMImplementationLS domImplLS = DOMUtils.getDOMImplementationLS(); LSSerializer serializer = domImplLS.createLSSerializer(); String debugString = serializer.writeToString(signature.getDocument()); log.trace(debugString); } return new CreateXMLSignatureResultImpl(signature.getDocument()); } catch (SLException e) { return new ErrorResultImpl(e, cmdCtx.getLocale()); } } @Override public String getName() { return "CreateXMLSignatureRequest"; } }