Java tutorial
/* * Digital Signature Service Protocol Project. * Copyright (C) 2013-2015 e-Contract.be BVBA. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version * 3.0 as published by the Free Software Foundation. * * This software 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 this software; if not, see * http://www.gnu.org/licenses/. */ package be.e_contract.dssp.client; import java.io.ByteArrayInputStream; import java.io.IOException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.security.cert.CertificateException; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; import java.util.Date; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.UUID; import javax.activation.DataHandler; import javax.activation.DataSource; import javax.mail.util.ByteArrayDataSource; import javax.xml.bind.JAXBElement; import javax.xml.namespace.QName; import javax.xml.ws.Binding; import javax.xml.ws.BindingProvider; import javax.xml.ws.handler.Handler; import javax.xml.ws.handler.MessageContext; import org.apache.commons.io.IOUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.ws.security.conversation.ConversationException; import org.apache.ws.security.conversation.dkalgo.P_SHA1; import org.joda.time.DateTime; import org.w3c.dom.Element; import be.e_contract.dssp.ws.DigitalSignatureServiceConstants; import be.e_contract.dssp.ws.DigitalSignatureServiceFactory; import be.e_contract.dssp.ws.jaxb.dss.AnyType; import be.e_contract.dssp.ws.jaxb.dss.AttachmentReferenceType; import be.e_contract.dssp.ws.jaxb.dss.Base64Data; import be.e_contract.dssp.ws.jaxb.dss.DocumentType; import be.e_contract.dssp.ws.jaxb.dss.DocumentWithSignature; import be.e_contract.dssp.ws.jaxb.dss.InputDocuments; import be.e_contract.dssp.ws.jaxb.dss.ObjectFactory; import be.e_contract.dssp.ws.jaxb.dss.ResponseBaseType; import be.e_contract.dssp.ws.jaxb.dss.Result; import be.e_contract.dssp.ws.jaxb.dss.SignRequest; import be.e_contract.dssp.ws.jaxb.dss.SignResponse; import be.e_contract.dssp.ws.jaxb.dss.SignaturePlacement; import be.e_contract.dssp.ws.jaxb.dss.VerifyRequest; import be.e_contract.dssp.ws.jaxb.dss.async.PendingRequest; import be.e_contract.dssp.ws.jaxb.dss.vr.CertificateValidityType; import be.e_contract.dssp.ws.jaxb.dss.vr.DetailedSignatureReportType; import be.e_contract.dssp.ws.jaxb.dss.vr.IndividualReportType; import be.e_contract.dssp.ws.jaxb.dss.vr.ReturnVerificationReport; import be.e_contract.dssp.ws.jaxb.dss.vr.SignedObjectIdentifierType; import be.e_contract.dssp.ws.jaxb.dss.vr.SignerRoleType; import be.e_contract.dssp.ws.jaxb.dss.vr.VerificationReportType; import be.e_contract.dssp.ws.jaxb.dssp.DeadlineType; import be.e_contract.dssp.ws.jaxb.wssc.SecurityContextTokenType; import be.e_contract.dssp.ws.jaxb.wsse.ReferenceType; import be.e_contract.dssp.ws.jaxb.wsse.SecurityTokenReferenceType; import be.e_contract.dssp.ws.jaxb.wst.BinarySecretType; import be.e_contract.dssp.ws.jaxb.wst.CancelTargetType; import be.e_contract.dssp.ws.jaxb.wst.EntropyType; import be.e_contract.dssp.ws.jaxb.wst.RequestSecurityTokenResponseCollectionType; import be.e_contract.dssp.ws.jaxb.wst.RequestSecurityTokenResponseType; import be.e_contract.dssp.ws.jaxb.wst.RequestSecurityTokenType; import be.e_contract.dssp.ws.jaxb.wst.RequestedSecurityTokenType; import be.e_contract.dssp.ws.jaxb.xades.ClaimedRolesListType; import be.e_contract.dssp.ws.jaxb.xmldsig.DigestMethodType; import be.e_contract.dssp.ws.jaxws.DigitalSignatureService; import be.e_contract.dssp.ws.jaxws.DigitalSignatureServicePortType; /** * Client for eID DSS products that support the Digital Signature Service * Protocol. Note that this client is not thread-safe. * * @author Frank Cornelis * */ public class DigitalSignatureServiceClient { private static final Log LOG = LogFactory.getLog(DigitalSignatureServiceClient.class); private final DigitalSignatureServicePortType dssPort; private final ObjectFactory objectFactory; private final be.e_contract.dssp.ws.jaxb.wst.ObjectFactory wstObjectFactory; private final be.e_contract.dssp.ws.jaxb.xmldsig.ObjectFactory dsObjectFactory; private final SecureRandom secureRandom; private final AttachmentsLogicalHandler attachmentsSOAPHandler; private final be.e_contract.dssp.ws.jaxb.dss.async.ObjectFactory asyncObjectFactory; private final WSSecuritySOAPHandler wsSecuritySOAPHandler; private final WSTrustSOAPHandler wsTrustSOAPHandler; private final be.e_contract.dssp.ws.jaxb.wsse.ObjectFactory wsseObjectFactory; private final be.e_contract.dssp.ws.jaxb.dss.vr.ObjectFactory vrObjectFactory; private final CertificateFactory certificateFactory; private String username; private String password; /** * Main constructor. * * @param address * the location of the DSSP web service. */ public DigitalSignatureServiceClient(String address) { DigitalSignatureService digitalSignatureService = DigitalSignatureServiceFactory.newInstance(); this.dssPort = digitalSignatureService.getDigitalSignatureServicePort(); BindingProvider bindingProvider = (BindingProvider) this.dssPort; bindingProvider.getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, address); Binding binding = bindingProvider.getBinding(); List<Handler> handlerChain = binding.getHandlerChain(); this.attachmentsSOAPHandler = new AttachmentsLogicalHandler(); handlerChain.add(this.attachmentsSOAPHandler); this.wsSecuritySOAPHandler = new WSSecuritySOAPHandler(); handlerChain.add(this.wsSecuritySOAPHandler); this.wsTrustSOAPHandler = new WSTrustSOAPHandler(); handlerChain.add(this.wsTrustSOAPHandler); // cannot add LoggingSOAPHandler here, else we break SOAP with // attachments on Apache CXF binding.setHandlerChain(handlerChain); this.objectFactory = new ObjectFactory(); this.wstObjectFactory = new be.e_contract.dssp.ws.jaxb.wst.ObjectFactory(); this.dsObjectFactory = new be.e_contract.dssp.ws.jaxb.xmldsig.ObjectFactory(); this.asyncObjectFactory = new be.e_contract.dssp.ws.jaxb.dss.async.ObjectFactory(); this.wsseObjectFactory = new be.e_contract.dssp.ws.jaxb.wsse.ObjectFactory(); this.vrObjectFactory = new be.e_contract.dssp.ws.jaxb.dss.vr.ObjectFactory(); this.secureRandom = new SecureRandom(); this.secureRandom.setSeed(System.currentTimeMillis()); try { this.certificateFactory = CertificateFactory.getInstance("X.509"); } catch (CertificateException e) { throw new RuntimeException(e); } } /** * Sets the username/password credentials to be used during the document * uploading. * * @param username * your application username. * @param password * your application password. */ public void setCredentials(String username, String password) { this.username = username; this.password = password; } /** * Uploads a given document to the DSS in preparation of a signing ceremony. * * @param mimetype * @param signatureType * the optional signature type. If none is provided, the DSS will * select the most appropriate. * @param data * @return * @throws UnsupportedDocumentTypeException * @throws IncorrectSignatureTypeException * @throws UnsupportedSignatureTypeException * @throws AuthenticationRequiredException */ public DigitalSignatureServiceSession uploadDocument(String mimetype, SignatureType signatureType, byte[] data) throws UnsupportedDocumentTypeException, UnsupportedSignatureTypeException, IncorrectSignatureTypeException, AuthenticationRequiredException { return uploadDocument(mimetype, signatureType, data, false); } /** * Uploads a given document to the DSS in preparation of a signing ceremony. * * @param mimetype * @param data * @return * @throws UnsupportedDocumentTypeException * @throws IncorrectSignatureTypeException * @throws UnsupportedSignatureTypeException * @throws AuthenticationRequiredException */ public DigitalSignatureServiceSession uploadDocument(String mimetype, byte[] data) throws UnsupportedDocumentTypeException, UnsupportedSignatureTypeException, IncorrectSignatureTypeException, AuthenticationRequiredException { return uploadDocument(mimetype, null, data, false); } /** * Uploads a given document to the DSS in preparation of a signing ceremony. * * @param mimetype * the mime-type of the document. * @param signatureType * the optional signature type. If none is provided, the DSS will * select the most appropriate. * @param data * the data bytes of the document. * @param useAttachments * set to <code>true</code> to use SOAP attachments. * @return a session object. Should be saved within the HTTP session for * later usage. * @throws UnsupportedDocumentTypeException * @throws UnsupportedSignatureTypeException * @throws IncorrectSignatureTypeException * @throws AuthenticationRequiredException */ public DigitalSignatureServiceSession uploadDocument(String mimetype, SignatureType signatureType, byte[] data, boolean useAttachments) throws UnsupportedDocumentTypeException, UnsupportedSignatureTypeException, IncorrectSignatureTypeException, AuthenticationRequiredException { SignRequest signRequest = this.objectFactory.createSignRequest(); signRequest.setProfile(DigitalSignatureServiceConstants.PROFILE); InputDocuments inputDocuments = this.objectFactory.createInputDocuments(); signRequest.setInputDocuments(inputDocuments); DocumentType document = addDocument(mimetype, data, useAttachments, inputDocuments); AnyType optionalInputs = this.objectFactory.createAnyType(); signRequest.setOptionalInputs(optionalInputs); optionalInputs.getAny().add( this.objectFactory.createAdditionalProfile(DigitalSignatureServiceConstants.DSS_ASYNC_PROFILE)); RequestSecurityTokenType requestSecurityToken = this.wstObjectFactory.createRequestSecurityTokenType(); optionalInputs.getAny().add(this.wstObjectFactory.createRequestSecurityToken(requestSecurityToken)); requestSecurityToken.getAny().add( this.wstObjectFactory.createTokenType(DigitalSignatureServiceConstants.WS_SEC_CONV_TOKEN_TYPE)); requestSecurityToken.getAny().add(this.wstObjectFactory .createRequestType(DigitalSignatureServiceConstants.WS_TRUST_ISSUE_REQUEST_TYPE)); EntropyType entropy = this.wstObjectFactory.createEntropyType(); BinarySecretType binarySecret = this.wstObjectFactory.createBinarySecretType(); binarySecret.setType(DigitalSignatureServiceConstants.WS_TRUST_BINARY_SECRET_NONCE_TYPE); byte[] nonce = new byte[256 / 8]; this.secureRandom.setSeed(System.currentTimeMillis()); this.secureRandom.nextBytes(nonce); binarySecret.setValue(nonce); entropy.getAny().add(this.wstObjectFactory.createBinarySecret(binarySecret)); requestSecurityToken.getAny().add(this.wstObjectFactory.createEntropy(entropy)); requestSecurityToken.getAny().add(this.wstObjectFactory.createKeySize(256L)); SignaturePlacement signaturePlacement = this.objectFactory.createSignaturePlacement(); optionalInputs.getAny().add(signaturePlacement); signaturePlacement.setCreateEnvelopedSignature(true); signaturePlacement.setWhichDocument(document); if (null != signatureType) { optionalInputs.getAny().add(this.objectFactory.createSignatureType(signatureType.getUri())); } String responseId = null; String securityTokenId = null; byte[] serverNonce = null; this.wsSecuritySOAPHandler.setCredentials(this.username, this.password); SignResponse signResponse = this.dssPort.sign(signRequest); Result result = signResponse.getResult(); String resultMajor = result.getResultMajor(); String resultMinor = result.getResultMinor(); if (false == DigitalSignatureServiceConstants.PENDING_RESULT_MAJOR.equals(resultMajor)) { if (DigitalSignatureServiceConstants.REQUESTER_ERROR_RESULT_MAJOR.equals(resultMajor)) { if (DigitalSignatureServiceConstants.UNSUPPORTED_MIME_TYPE_RESULT_MINOR.equals(resultMinor)) { throw new UnsupportedDocumentTypeException(); } else if (DigitalSignatureServiceConstants.UNSUPPORTED_SIGNATURE_TYPE_RESULT_MINOR .equals(resultMinor)) { throw new UnsupportedSignatureTypeException(); } else if (DigitalSignatureServiceConstants.INCORRECT_SIGNATURE_TYPE_RESULT_MINOR .equals(resultMinor)) { throw new IncorrectSignatureTypeException(); } else if (DigitalSignatureServiceConstants.AUTHENTICATION_REQUIRED_RESULT_MINOR .equals(resultMinor)) { throw new AuthenticationRequiredException(); } } throw new RuntimeException("not successfull: " + resultMajor + " " + resultMinor); } AnyType optionalOutputs = signResponse.getOptionalOutputs(); List<Object> optionalOutputsList = optionalOutputs.getAny(); for (Object optionalOutputsObject : optionalOutputsList) { LOG.debug("optional outputs object type: " + optionalOutputsObject.getClass().getName()); if (optionalOutputsObject instanceof JAXBElement) { JAXBElement jaxbElement = (JAXBElement) optionalOutputsObject; QName name = jaxbElement.getName(); LOG.debug("value name: " + name); if (DigitalSignatureServiceConstants.ASYNC_RESPONSEID_QNAME.equals(name)) { responseId = (String) jaxbElement.getValue(); LOG.debug("async:ResponseID = " + responseId); } else if (jaxbElement.getValue() instanceof RequestSecurityTokenResponseCollectionType) { RequestSecurityTokenResponseCollectionType requestSecurityTokenResponseCollection = (RequestSecurityTokenResponseCollectionType) jaxbElement .getValue(); List<RequestSecurityTokenResponseType> rstsList = requestSecurityTokenResponseCollection .getRequestSecurityTokenResponse(); if (rstsList.size() == 1) { RequestSecurityTokenResponseType rstr = rstsList.get(0); for (Object rstrObject : rstr.getAny()) { JAXBElement rstrElement = (JAXBElement) rstrObject; if (rstrElement.getValue() instanceof RequestedSecurityTokenType) { RequestedSecurityTokenType requestedSecurityToken = (RequestedSecurityTokenType) rstrElement .getValue(); SecurityContextTokenType securityContextToken = ((JAXBElement<SecurityContextTokenType>) requestedSecurityToken .getAny()).getValue(); securityTokenId = ((JAXBElement<String>) securityContextToken.getAny().get(0)) .getValue(); LOG.debug("security token id: " + securityTokenId); } else if (rstrElement.getValue() instanceof EntropyType) { EntropyType serverEntropy = (EntropyType) rstrElement.getValue(); BinarySecretType serverBinarySecret = ((JAXBElement<BinarySecretType>) serverEntropy .getAny().get(0)).getValue(); serverNonce = serverBinarySecret.getValue(); } } } } } } if (null == responseId) { throw new RuntimeException("missing async:ResponseID in response"); } if (null == securityTokenId) { throw new RuntimeException("missing WS-SecureConversation token identifier"); } if (null == serverNonce) { throw new RuntimeException("missing Nonce in response"); } P_SHA1 p_SHA1 = new P_SHA1(); byte[] key; try { key = p_SHA1.createKey(nonce, serverNonce, 0, 256 / 8); } catch (ConversationException e) { throw new RuntimeException("error generating P_SHA1 key"); } Element securityTokenElement = this.wsTrustSOAPHandler.getRequestedSecurityToken(); DigitalSignatureServiceSession digitalSignatureServiceSession = new DigitalSignatureServiceSession( responseId, securityTokenId, key, securityTokenElement); return digitalSignatureServiceSession; } /** * Downloads the signed document. * * @param session * the session object. * @return the signed document. */ public byte[] downloadSignedDocument(DigitalSignatureServiceSession session) { if (false == session.isSignResponseVerified()) { throw new SecurityException("SignResponse not verified"); } PendingRequest pendingRequest = this.asyncObjectFactory.createPendingRequest(); pendingRequest.setProfile(DigitalSignatureServiceConstants.PROFILE); AnyType optionalInputs = this.objectFactory.createAnyType(); pendingRequest.setOptionalInputs(optionalInputs); optionalInputs.getAny().add( this.objectFactory.createAdditionalProfile(DigitalSignatureServiceConstants.DSS_ASYNC_PROFILE)); optionalInputs.getAny().add(this.asyncObjectFactory.createResponseID(session.getResponseId())); RequestSecurityTokenType requestSecurityToken = this.wstObjectFactory.createRequestSecurityTokenType(); optionalInputs.getAny().add(this.wstObjectFactory.createRequestSecurityToken(requestSecurityToken)); requestSecurityToken.getAny().add(this.wstObjectFactory .createRequestType(DigitalSignatureServiceConstants.WS_TRUST_CANCEL_REQUEST_TYPE)); CancelTargetType cancelTarget = this.wstObjectFactory.createCancelTargetType(); requestSecurityToken.getAny().add(this.wstObjectFactory.createCancelTarget(cancelTarget)); SecurityTokenReferenceType securityTokenReference = this.wsseObjectFactory .createSecurityTokenReferenceType(); cancelTarget.setAny(this.wsseObjectFactory.createSecurityTokenReference(securityTokenReference)); ReferenceType reference = this.wsseObjectFactory.createReferenceType(); securityTokenReference.getAny().add(this.wsseObjectFactory.createReference(reference)); reference.setValueType(DigitalSignatureServiceConstants.WS_SEC_CONV_TOKEN_TYPE); reference.setURI(session.getSecurityTokenId()); this.wsSecuritySOAPHandler.setSession(session); SignResponse signResponse = this.dssPort.pendingRequest(pendingRequest); AnyType optionalOutputs = signResponse.getOptionalOutputs(); List<Object> optionalOutputsList = optionalOutputs.getAny(); for (Object optionalOutputsObject : optionalOutputsList) { LOG.debug("optional outputs object type: " + optionalOutputsObject.getClass().getName()); if (optionalOutputsObject instanceof DocumentWithSignature) { DocumentWithSignature documentWithSignature = (DocumentWithSignature) optionalOutputsObject; DocumentType document = documentWithSignature.getDocument(); if (document.getBase64XML() != null) { return document.getBase64XML(); } if (document.getBase64Data() != null) { return document.getBase64Data().getValue(); } if (document.getAttachmentReference() != null) { AttachmentReferenceType attachmentReference = document.getAttachmentReference(); String attachmentUri = attachmentReference.getAttRefURI(); LOG.debug("attachment URI: " + attachmentUri); // skip 'cid:' String attachmentContentId = attachmentUri.substring(4); LOG.debug("attachment content id: " + attachmentContentId); Map<String, DataHandler> inboundAttachments = this.attachmentsSOAPHandler .getInboundAttachments(); for (String attachmentId : inboundAttachments.keySet()) { LOG.debug("actual attachment id: " + attachmentId); } DataHandler dataHandler; if (inboundAttachments.size() == 1) { dataHandler = inboundAttachments.values().iterator().next(); } else { // JAX-WS RI 1.8 and CXF dataHandler = inboundAttachments.get(attachmentContentId); if (null == dataHandler) { // JAX-WS RI 1.7 adds '<' and '>'. attachmentContentId = '<' + attachmentContentId + '>'; dataHandler = inboundAttachments.get(attachmentContentId); } } LOG.debug("received data handler: " + (null != dataHandler)); try { byte[] signedDocument = IOUtils.toByteArray(dataHandler.getInputStream()); LOG.debug("signed document size: " + signedDocument.length); return signedDocument; } catch (IOException e) { throw new RuntimeException("IO error: " + e.getMessage(), e); } } } } return null; } /** * Verifies the signatures on the given document. * * @param mimetype * the mime-type of the document. * @param data * the document data. * @return the verification result. * @throws UnsupportedDocumentTypeException * for unsupported mime-types * @throws DocumentSignatureException * when the document or signature is incorrect. */ public VerificationResult verify(String mimetype, byte[] data) throws UnsupportedDocumentTypeException, DocumentSignatureException { return verify(mimetype, data, false); } /** * Verifies the signatures on the given document. * * @param mimetype * the mime-type of the document. * @param data * the document data. * @param useAttachments * <code>true</code> when you want to use SOAP attachments. * @return the verification result. * @throws UnsupportedDocumentTypeException * for unsupported mime-types * @throws DocumentSignatureException * when the document or signature is incorrect. */ public VerificationResult verify(String mimetype, byte[] data, boolean useAttachments) throws UnsupportedDocumentTypeException, DocumentSignatureException { List<SignatureInfo> signatureInfos = new LinkedList<SignatureInfo>(); VerifyRequest verifyRequest = this.objectFactory.createVerifyRequest(); verifyRequest.setProfile(DigitalSignatureServiceConstants.PROFILE); InputDocuments inputDocuments = this.objectFactory.createInputDocuments(); verifyRequest.setInputDocuments(inputDocuments); addDocument(mimetype, data, useAttachments, inputDocuments); AnyType optionalInputs = this.objectFactory.createAnyType(); verifyRequest.setOptionalInputs(optionalInputs); ReturnVerificationReport returnVerificationReport = this.vrObjectFactory.createReturnVerificationReport(); optionalInputs.getAny().add(returnVerificationReport); returnVerificationReport.setIncludeVerifier(false); returnVerificationReport.setIncludeCertificateValues(true); this.wsSecuritySOAPHandler.setSession(null); ResponseBaseType response = this.dssPort.verify(verifyRequest); Result result = response.getResult(); String resultMajor = result.getResultMajor(); String resultMinor = result.getResultMinor(); if (false == DigitalSignatureServiceConstants.SUCCESS_RESULT_MAJOR.equals(resultMajor)) { if (DigitalSignatureServiceConstants.REQUESTER_ERROR_RESULT_MAJOR.equals(resultMajor)) { if (DigitalSignatureServiceConstants.UNSUPPORTED_MIME_TYPE_RESULT_MINOR.equals(resultMinor)) { throw new UnsupportedDocumentTypeException(); } if (DigitalSignatureServiceConstants.INCORRECT_SIGNATURE_RESULT_MINOR.equals(resultMinor)) { throw new DocumentSignatureException(); } } throw new RuntimeException("not successfull: " + resultMajor + " " + resultMinor); } DateTime timeStampRenewalBefore = null; AnyType optionalOutputs = response.getOptionalOutputs(); List<Object> optionalOutputsList = optionalOutputs.getAny(); for (Object optionalOutput : optionalOutputsList) { if (false == optionalOutput instanceof JAXBElement) { continue; } JAXBElement jaxbElement = (JAXBElement) optionalOutput; LOG.debug("optional output: " + optionalOutput.getClass().getName()); if (jaxbElement.getValue() instanceof DeadlineType) { DeadlineType deadlineType = (DeadlineType) jaxbElement.getValue(); timeStampRenewalBefore = new DateTime(deadlineType.getBefore().toGregorianCalendar()); } else if (jaxbElement.getValue() instanceof VerificationReportType) { LOG.debug("found VerificationReport"); VerificationReportType verificationReport = (VerificationReportType) jaxbElement.getValue(); List<IndividualReportType> individualReports = verificationReport.getIndividualReport(); for (IndividualReportType individualReport : individualReports) { if (!DigitalSignatureServiceConstants.SUCCESS_RESULT_MAJOR .equals(individualReport.getResult().getResultMajor())) { LOG.warn("some invalid VR result reported: " + individualReport.getResult().getResultMajor()); continue; } SignedObjectIdentifierType signedObjectIdentifier = individualReport .getSignedObjectIdentifier(); Date signingTime = signedObjectIdentifier.getSignedProperties().getSignedSignatureProperties() .getSigningTime().toGregorianCalendar().getTime(); String location = signedObjectIdentifier.getSignedProperties().getSignedSignatureProperties() .getLocation(); SignerRoleType signerRole = signedObjectIdentifier.getSignedProperties() .getSignedSignatureProperties().getSignerRole(); String role = null; if (null != signerRole) { ClaimedRolesListType claimedRolesList = signerRole.getClaimedRoles(); if (null != claimedRolesList) { List<be.e_contract.dssp.ws.jaxb.xades.AnyType> claimedRoles = claimedRolesList .getClaimedRole(); be.e_contract.dssp.ws.jaxb.xades.AnyType claimedRole = claimedRoles.get(0); role = claimedRole.getContent().get(0).toString(); } } List<Object> details = individualReport.getDetails().getAny(); X509Certificate certificate = null; String name = null; for (Object detail : details) { if (detail instanceof JAXBElement<?>) { JAXBElement<?> detailElement = (JAXBElement<?>) detail; if (detailElement.getValue() instanceof DetailedSignatureReportType) { DetailedSignatureReportType detailedSignatureReport = (DetailedSignatureReportType) detailElement .getValue(); List<CertificateValidityType> certificateValidities = detailedSignatureReport .getCertificatePathValidity().getPathValidityDetail() .getCertificateValidity(); CertificateValidityType certificateValidity = certificateValidities.get(0); name = certificateValidity.getSubject(); byte[] encodedCertificate = certificateValidity.getCertificateValue(); try { certificate = (X509Certificate) this.certificateFactory .generateCertificate(new ByteArrayInputStream(encodedCertificate)); } catch (CertificateException e) { throw new RuntimeException("cert decoding error: " + e.getMessage(), e); } } } } signatureInfos.add(new SignatureInfo(name, certificate, signingTime, role, location)); } } } if (signatureInfos.isEmpty()) { return null; } return new VerificationResult(signatureInfos, timeStampRenewalBefore); } private DocumentType addDocument(String mimetype, byte[] data, boolean useAttachments, InputDocuments inputDocuments) { DocumentType document = this.objectFactory.createDocumentType(); String documentId = "document-" + UUID.randomUUID().toString(); document.setID(documentId); inputDocuments.getDocumentOrTransformedDataOrDocumentHash().add(document); if (useAttachments) { AttachmentReferenceType attachmentReference = this.objectFactory.createAttachmentReferenceType(); document.setAttachmentReference(attachmentReference); attachmentReference.setMimeType(mimetype); DigestMethodType digestMethod = this.dsObjectFactory.createDigestMethodType(); digestMethod.setAlgorithm(DigitalSignatureServiceConstants.SHA1_DIGEST_METHOD_TYPE); attachmentReference.setDigestMethod(digestMethod); MessageDigest messageDigest; try { messageDigest = MessageDigest.getInstance("SHA-1"); } catch (NoSuchAlgorithmException e) { throw new RuntimeException("SHA-1 algo error: " + e.getMessage(), e); } byte[] digest = messageDigest.digest(data); attachmentReference.setDigestValue(digest); String contentId = addAttachment(mimetype, data); String attachmentUri = "cid:" + contentId; attachmentReference.setAttRefURI(attachmentUri); } else { if ("application/xml".equals(mimetype)) { document.setBase64XML(data); } else { Base64Data base64Data = this.objectFactory.createBase64Data(); base64Data.setMimeType(mimetype); base64Data.setValue(data); document.setBase64Data(base64Data); } } return document; } private String addAttachment(String mimetype, byte[] data) { String contentId = UUID.randomUUID().toString(); LOG.debug("adding attachment: " + contentId); DataSource dataSource = new ByteArrayDataSource(data, mimetype); DataHandler dataHandler = new DataHandler(dataSource); BindingProvider bindingProvider = (BindingProvider) this.dssPort; Map<String, Object> requestContext = bindingProvider.getRequestContext(); Map<String, DataHandler> outputMessageAttachments = new HashMap<String, DataHandler>(); requestContext.put(MessageContext.OUTBOUND_MESSAGE_ATTACHMENTS, outputMessageAttachments); outputMessageAttachments.put(contentId, dataHandler); return contentId; } }