diff options
| author | Bonato, Martin <martin.bonato@prime-sign.com> | 2018-02-08 22:19:55 +0100 | 
|---|---|---|
| committer | Bonato, Martin <martin.bonato@prime-sign.com> | 2018-02-08 22:19:55 +0100 | 
| commit | b9ccb62d35a755efb505d426ce924d5a8fbe937a (patch) | |
| tree | 00d17aa7dc660eb0e90ae753e36a623d672fc0e0 /bkucommon/src | |
| parent | 84794c877062fe0424f357be0e83bdd045d75d52 (diff) | |
| download | mocca-b9ccb62d35a755efb505d426ce924d5a8fbe937a.tar.gz mocca-b9ccb62d35a755efb505d426ce924d5a8fbe937a.tar.bz2 mocca-b9ccb62d35a755efb505d426ce924d5a8fbe937a.zip | |
BulkSignature implementationfb-bulksignature
Diffstat (limited to 'bkucommon/src')
28 files changed, 1826 insertions, 121 deletions
| diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/BulkCommand.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/BulkCommand.java new file mode 100644 index 00000000..7deb8e22 --- /dev/null +++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/BulkCommand.java @@ -0,0 +1,27 @@ +/* + * Copyright 2015 Datentechnik Innovation and Prime Sign GmbH, Austria + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://www.osor.eu/eupl/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + */ + +package at.gv.egiz.bku.slcommands; + + +public interface BulkCommand extends SLCommand { + +} diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/BulkSignatureResult.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/BulkSignatureResult.java new file mode 100644 index 00000000..8670d635 --- /dev/null +++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/BulkSignatureResult.java @@ -0,0 +1,31 @@ +/* + * Copyright 2015 Datentechnik Innovation and Prime Sign GmbH, Austria + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://www.osor.eu/eupl/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + */ + + +package at.gv.egiz.bku.slcommands; + +import org.w3c.dom.Element; + +public interface BulkSignatureResult extends SLResult { + +  public Element getContent(); + +} diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/BulkCommandFactory.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/BulkCommandFactory.java new file mode 100644 index 00000000..7f7d7f1e --- /dev/null +++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/BulkCommandFactory.java @@ -0,0 +1,40 @@ +/* + * Copyright 2015 Datentechnik Innovation and Prime Sign GmbH, Austria + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://www.osor.eu/eupl/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + */ + + +package at.gv.egiz.bku.slcommands.impl; + +import javax.xml.bind.JAXBElement; + +import at.gv.egiz.bku.slcommands.AbstractSLCommandFactory; +import at.gv.egiz.bku.slcommands.SLCommand; +import at.gv.egiz.bku.slexceptions.SLCommandException; + +public class BulkCommandFactory extends AbstractSLCommandFactory { + +  @Override +  public SLCommand createSLCommand(JAXBElement<?> element) throws SLCommandException { +    BulkCommandImpl command = new BulkCommandImpl(); +    command.init(element); +    command.setConfiguration(configuration); +    return command; +  } +} diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/BulkCommandImpl.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/BulkCommandImpl.java new file mode 100644 index 00000000..7094e284 --- /dev/null +++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/BulkCommandImpl.java @@ -0,0 +1,439 @@ +/* + * Copyright 2015 Datentechnik Innovation GmbH and Prime Sign GmbH, Austria + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://www.osor.eu/eupl/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + */ + +package at.gv.egiz.bku.slcommands.impl; + +import iaik.asn1.DerCoder; +import iaik.asn1.INTEGER; +import iaik.asn1.SEQUENCE; +import iaik.asn1.structures.AlgorithmID; +import iaik.cms.CMSException; +import iaik.cms.CMSSignatureException; +import iaik.utils.Util; + +import java.math.BigInteger; +import java.security.InvalidParameterException; +import java.security.SignatureException; +import java.security.cert.X509Certificate; +import java.util.Arrays; +import java.util.Collections; +import java.util.Date; +import java.util.LinkedList; +import java.util.List; + +import org.apache.commons.configuration.Configuration; +import org.apache.commons.io.FilenameUtils; +import org.apache.commons.lang.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import at.buergerkarte.namespaces.securitylayer._1_2_3.BulkRequestType; +import at.buergerkarte.namespaces.securitylayer._1_2_3.BulkRequestType.CreateSignatureRequest; +import at.buergerkarte.namespaces.securitylayer._1_2_3.CreateCMSSignatureRequestType; +import at.buergerkarte.namespaces.securitylayer._1_2_3.ExcludedByteRangeType; +import at.gv.egiz.bku.conf.MoccaConfigurationFacade; +import at.gv.egiz.bku.slcommands.BulkCommand; +import at.gv.egiz.bku.slcommands.SLCommandContext; +import at.gv.egiz.bku.slcommands.SLResult; +import at.gv.egiz.bku.slcommands.impl.cms.BulkCollectionSecurityProvider; +import at.gv.egiz.bku.slcommands.impl.cms.BulkSignature; +import at.gv.egiz.bku.slcommands.impl.cms.BulkSignatureInfo; +import at.gv.egiz.bku.slcommands.impl.cms.CMSHashDataInput; +import at.gv.egiz.bku.slcommands.impl.xsect.STALSignatureException; +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.stal.BulkSignRequest; +import at.gv.egiz.stal.BulkSignResponse; +import at.gv.egiz.stal.ErrorResponse; +import at.gv.egiz.stal.HashDataInput; +import at.gv.egiz.stal.InfoboxReadRequest; +import at.gv.egiz.stal.STALRequest; +import at.gv.egiz.stal.STALResponse; +import at.gv.egiz.stal.SignRequest; +import at.gv.egiz.stal.SignRequest.SignedInfo; + +/** + * This class implements the security layer command <code>BulkRequest</code>. + *  + * @author szoescher + */ +public class BulkCommandImpl extends SLCommandImpl<BulkRequestType> implements BulkCommand { + +  private final static String ID_ECSIGTYPE = "1.2.840.10045.4"; + +  /** +   * Logging facility. +   */ +  private final static Logger log = LoggerFactory.getLogger(BulkCommandImpl.class); + +  /** +   * The signing certificate. +   */ +  protected X509Certificate signingCertificate; + +  /** +   * The keybox identifier of the key used for signing. +   */ +  protected String keyboxIdentifier; + +  /** +   * The configuration facade used to access the MOCCA configuration. +   */ +  private ConfigurationFacade configurationFacade = new ConfigurationFacade(); + +  private class ConfigurationFacade implements MoccaConfigurationFacade { +    private Configuration configuration; + +    public static final String USE_STRONG_HASH = "UseStrongHash"; + +    public void setConfiguration(Configuration configuration) { +      this.configuration = configuration; +    } + +    public boolean getUseStrongHash() { +      return configuration.getBoolean(USE_STRONG_HASH, true); +    } +  } + +  @Override +  public String getName() { +    return "BulkRequest"; +  } + +  public void setConfiguration(Configuration configuration) { +    configurationFacade.setConfiguration(configuration); +  } + +  @Override +  public SLResult execute(SLCommandContext commandContext) { + +    List<BulkSignature> signatures = new LinkedList<BulkSignature>(); + +    try { + +      List<CreateSignatureRequest> signatureRequests = getRequestValue().getCreateSignatureRequest(); +       +       +      List<String> requestIds = new LinkedList<String>(); + +      if (signatureRequests != null && signatureRequests.size() != 0) { + +        BulkCollectionSecurityProvider securityProvider = new BulkCollectionSecurityProvider(); + +        log.debug("get keyboxIdentifier from BulkSingatureRequest"); +        keyboxIdentifier = setKeyboxIdentifier(signatureRequests); + +        log.info("Requesting signing certificate."); +        signingCertificate = requestSigningCertificate(keyboxIdentifier, commandContext); +        log.debug("Got signing certificate. {}", signingCertificate); + + +        for (int i=0; i<signatureRequests.size(); i++) { +           +          CreateSignatureRequest request = signatureRequests.get(i); +          if (request.getCreateCMSSignatureRequest() != null) { +            log.info("execute CMSSignature request."); +             +            requestIds.add(request.getId()); +             +            BulkSignature signature = prepareCMSSignatureRequests(securityProvider, request.getCreateCMSSignatureRequest(), +                commandContext); +             +            signatures.add(signature); +       +            for(HashDataInput hashDataInput : securityProvider.getBulkSignatureInfo().get(i).getHashDataInput()){ +               +              if(hashDataInput instanceof CMSHashDataInput) { +              	CMSHashDataInput cmsHashDataInput = (CMSHashDataInput) hashDataInput; +                 log.debug("setting fileName {}", getFileName(request, i+1)); +                 cmsHashDataInput.setFilename(getFileName(request, i+1)); +                 cmsHashDataInput.setDigest(signature.getSignerInfo().getDigest()); +              }  +               + +            } +          }  else { +            if (request.getCreateXMLSignatureRequest() != null) { +              log.error("XML signature requests are currently not supported in bulk signature requests."); +              throw new SLCommandException(4124); +            } +          } +        } + + +        return new BulkSignatureResultImpl(signBulkRequest(securityProvider.getBulkSignatureInfo(), commandContext, +            signatures), requestIds); +         + + +      } + +    } catch (SLException e) { +      return new ErrorResultImpl(e, commandContext.getLocale()); +      +    } catch (CMSException e) { +       log.error("Error reading message digest.",e); +     } +    return null; +  } + +  private String getFileName(CreateSignatureRequest request, int requestCounter) { + +    String referenceURL = null; +    		   +		if (request.getCreateCMSSignatureRequest().getDataObject() != null +				&& request.getCreateCMSSignatureRequest().getDataObject().getContent() != null) { +			referenceURL = request.getCreateCMSSignatureRequest().getDataObject().getContent().getReference(); +		} + +    if (StringUtils.isNotEmpty(referenceURL)) { +      return FilenameUtils.getBaseName(referenceURL); +    } else { + +      StringBuilder fileNameBuilder = new StringBuilder(); + +      if (StringUtils.isNotEmpty(request.getDisplayName())) { +        fileNameBuilder.append(request.getDisplayName()); +      } else { +        fileNameBuilder.append(HashDataInput.DEFAULT_FILENAME); +        fileNameBuilder.append("_"); +        fileNameBuilder.append(requestCounter); +      } +       +      return fileNameBuilder.toString(); +    } +  } + +  private List<byte[]> signBulkRequest(List<BulkSignatureInfo> bulkSignatureInfo, SLCommandContext commandContext, +      List<BulkSignature> signatures) throws SLCommandException, SLRequestException { + +    try { + +      List<byte[]> signatureValues; + +      BulkSignRequest signRequest = getSTALSignRequest(bulkSignatureInfo); + +      // send BulkStalRequest +      List<STALResponse> responses = commandContext.getSTAL().handleRequest( +          Collections.singletonList((STALRequest) signRequest)); + +      if (responses == null || responses.size() != 1) { +        throw new SignatureException("Failed to access STAL."); +      } + +      STALResponse response = responses.get(0); +       +      // setSignatureValues from STALResponse   +      if (response instanceof BulkSignResponse) { +        BulkSignResponse bulkSignatureResponse = ((BulkSignResponse) response); + +        signatureValues = new LinkedList<byte[]>(); +        for (int i = 0; i < bulkSignatureResponse.getSignResponse().size(); i++) { +          byte[] sig = ((BulkSignResponse) response).getSignResponse().get(i).getSignatureValue(); +          log.debug("Got signature response: " + Util.toBase64String(sig)); +          signatures.get(i).getSignerInfo() +              .setSignatureValue(wrapSignatureValue(sig, bulkSignatureInfo.get(i).getSignatureAlgorithm())); +          signatureValues.add(signatures.get(i).getEncoded()); +        } + +        return signatureValues; + +      } else if (response instanceof ErrorResponse) { + +        ErrorResponse err = (ErrorResponse) response; +        log.debug("Error signing bulk request. Error response code: " + err.getErrorCode() + " (" + err.getErrorMessage() + ")."); +        throw new SLCommandException(err.getErrorCode()); +      } + +    } catch (SignatureException e) { +      log.error("Error creating CMSSignature", e); +      throw new SLCommandException(4000); +    } catch (CMSException e) { +      log.error("Error creating CMSSignature", e); +    } +    return null; +  } + +  private String setKeyboxIdentifier(List<CreateSignatureRequest> signatureRequests) throws SLCommandException { +     +    String keyboxIdentifier = null; + +    for (CreateSignatureRequest request : signatureRequests) { +      if (request.getCreateCMSSignatureRequest() != null) { + +        if (keyboxIdentifier == null) { +          keyboxIdentifier = request.getCreateCMSSignatureRequest().getKeyboxIdentifier(); +        } else { +          if (request.getCreateCMSSignatureRequest().getKeyboxIdentifier() == null) { +            log.error("No keyboxIdentifier has been specified for this signature request."); +            throw new SLCommandException(3003); + +          } else if (!request.getCreateCMSSignatureRequest().getKeyboxIdentifier().equals(keyboxIdentifier)) { + +            log.error("Error creating bulk signature. The bulkSignature value has to be the same fo all signature requests."); +            throw new SLCommandException(3003); +          } +        } +      } +    } + + +    return keyboxIdentifier; +  } + +  private BulkSignature prepareCMSSignatureRequests(BulkCollectionSecurityProvider securityProvieder, +      CreateCMSSignatureRequestType request, SLCommandContext commandContext) throws SLCommandException, +      SLRequestException, SLViewerException { + +    BulkSignature signature; + +    // prepare the CMSSignature for signing +    log.debug("Preparing CMS signature."); +    signature = prepareCMSSignature(request, commandContext); +     +    try { +      +      // update securityProvieder with parameters of the given signature +      securityProvieder.updateBulkCollectionSecurityProvider(keyboxIdentifier, signature.getHashDataInput(), +          signature.getExcludedByteRange()); + +      // prepare the CMSSignatures of the Bulk Request +      log.debug("Signing CMS signature."); +      +     +     +    return prepareStalRequest(securityProvieder, signature, commandContext); +    +    } catch (Exception e) { +      log.error("Error creating CMS Signature.", e); +      throw new SLCommandException(4000); +    } + +  } + +  private BulkSignature prepareCMSSignature(CreateCMSSignatureRequestType request, SLCommandContext commandContext) +      throws SLCommandException, SLRequestException { + +    // DataObject, SigningCertificate, SigningTime +    Date signingTime = new Date(); +    try { +      return new BulkSignature( +          request.getDataObject() != null ? request.getDataObject() : request.getReferenceObject(), +          request.getStructure(), signingCertificate, signingTime, commandContext.getURLDereferencer(), +          configurationFacade.getUseStrongHash()); +    } catch (SLCommandException e) { +      log.error("Error creating CMS Signature.", e); +      throw e; +    } catch (InvalidParameterException e) { +      log.error("Error creating CMS Signature.", e); +      throw new SLCommandException(3004); +    } catch (Exception e) { +      log.error("Error creating CMS Signature.", e); +      throw new SLCommandException(4000); +    } +  } + +  private BulkSignature prepareStalRequest(BulkCollectionSecurityProvider securityProvieder, BulkSignature signature, +      SLCommandContext commandContext) throws SLCommandException, SLViewerException { + +    try { + +      signature.sign(securityProvieder, commandContext.getSTAL(), keyboxIdentifier); +      return signature; +    } catch (CMSException e) { +      log.error("Error creating CMSSignature", e); +      throw new SLCommandException(4000); +    } catch (CMSSignatureException e) { +      log.error("Error creating CMSSignature", e); +      throw new SLCommandException(4000); +    } +  } + +  private X509Certificate requestSigningCertificate(String keyboxIdentifier, SLCommandContext commandContext) +      throws SLCommandException { + +    InfoboxReadRequest stalRequest = new InfoboxReadRequest(); +    stalRequest.setInfoboxIdentifier(keyboxIdentifier); + +    STALHelper stalHelper = new STALHelper(commandContext.getSTAL()); + +    stalHelper.transmitSTALRequest(Collections.singletonList((STALRequest) stalRequest)); +    List<X509Certificate> certificates = stalHelper.getCertificatesFromResponses(); +    if (certificates == null || certificates.size() != 1) { +      log.info("Got an unexpected number of certificates from STAL."); +      throw new SLCommandException(4000); +    } +    return signingCertificate = certificates.get(0); + +  } + +  private static BulkSignRequest getSTALSignRequest(List<BulkSignatureInfo> bulkSignatureInfo) { +    BulkSignRequest bulkSignRequest = new BulkSignRequest(); + +    for (int i = 0; i< bulkSignatureInfo.size(); i++) { +       +      BulkSignatureInfo signatureInfo = bulkSignatureInfo.get(i); +      SignRequest signRequest = new SignRequest(); +      signRequest.setKeyIdentifier(signatureInfo.getKeyboxIdentifier()); +      log.debug("SignedAttributes: " + Util.toBase64String(signatureInfo.getSignedAttributes())); +      SignedInfo signedInfo = new SignedInfo(); +      signedInfo.setValue(signatureInfo.getSignedAttributes()); +      signedInfo.setIsCMSSignedAttributes(true); +      signRequest.setSignedInfo(signedInfo);    +      log.info("set displayName for Request {}", signatureInfo.getHashDataInput().get(0).getFilename()); +      signRequest.setDisplayName(signatureInfo.getHashDataInput().get(0).getFilename()); +      signRequest.setMimeType(signatureInfo.getHashDataInput().get(0).getMimeType()); + +      signRequest.setSignatureMethod(signatureInfo.getSignatureMethod()); +      signRequest.setDigestMethod(signatureInfo.getDigestMethod()); +      signRequest.setHashDataInput(signatureInfo.getHashDataInput()); + +      ExcludedByteRangeType excludedByteRange = signatureInfo.getExcludedByteRange(); +      if (excludedByteRange != null) { +        SignRequest.ExcludedByteRange ebr = new SignRequest.ExcludedByteRange(); +        ebr.setFrom(excludedByteRange.getFrom()); +        ebr.setTo(excludedByteRange.getTo()); +        signRequest.setExcludedByteRange(ebr); +      } + +      bulkSignRequest.getSignRequests().add(signRequest); +    } +    return bulkSignRequest; +  } + +  private static byte[] wrapSignatureValue(byte[] sig, AlgorithmID sigAlgorithmID) { +    String id = sigAlgorithmID.getAlgorithm().getID(); +    if (id.startsWith(ID_ECSIGTYPE)) // X9.62 Format ECDSA signatures +    { +      // Wrap r and s in ASN.1 SEQUENCE +      byte[] r = Arrays.copyOfRange(sig, 0, sig.length / 2); +      byte[] s = Arrays.copyOfRange(sig, sig.length / 2, sig.length); +      SEQUENCE sigS = new SEQUENCE(); +      sigS.addComponent(new INTEGER(new BigInteger(1, r))); +      sigS.addComponent(new INTEGER(new BigInteger(1, s))); +      return DerCoder.encode(sigS); +    } else +      return sig; +  } + +}
\ No newline at end of file diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/BulkSignatureResultImpl.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/BulkSignatureResultImpl.java new file mode 100644 index 00000000..2a88b6be --- /dev/null +++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/BulkSignatureResultImpl.java @@ -0,0 +1,138 @@ +/* + * Copyright 2015 Datentechnik Innovation and Prime Sign GmbH, Austria + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://www.osor.eu/eupl/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + */ + +package at.gv.egiz.bku.slcommands.impl; + +import java.util.List; + +import javax.xml.bind.JAXBElement; +import javax.xml.bind.JAXBException; +import javax.xml.bind.Marshaller; +import javax.xml.transform.Result; +import javax.xml.transform.Templates; +import javax.xml.transform.dom.DOMResult; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import at.buergerkarte.namespaces.securitylayer._1_2_3.BulkResponseType; +import at.buergerkarte.namespaces.securitylayer._1_2_3.BulkResponseType.CreateSignatureResponse; +import at.buergerkarte.namespaces.securitylayer._1_2_3.CreateCMSSignatureResponseType; +import at.buergerkarte.namespaces.securitylayer._1_2_3.ObjectFactory; +import at.gv.egiz.bku.slcommands.BulkSignatureResult; +import at.gv.egiz.bku.slcommands.SLMarshallerFactory; +import at.gv.egiz.bku.slexceptions.SLRuntimeException; + +/** + * This implements the result of the security layer command + * <code>BulkRequest</code>. + *  + * @author szoescher + */ +public class BulkSignatureResultImpl extends SLResultImpl implements BulkSignatureResult { + +  /** +   * Logging facility. +   */ +  private final Logger log = LoggerFactory.getLogger(BulkSignatureResultImpl.class); + +  /** +   * The CMSSignatures data. +   */ +  protected List<byte[]> signatures; +   +   +  protected List<String> requestIds; +   +   +  /** +   * The BulkResponse. +   */ +  private Element content; + +  /** +   * Creates a new instance of this BulkSignatureResultImpl with the given +   * signatures <code>signatures</code>. +   */ +  public BulkSignatureResultImpl(List<byte[]> signatures, List<String> requestIds) { +    super(); + +    if (signatures == null || signatures.size() == 0) +      throw new NullPointerException("Argument 'signature' must not be null."); +    this.signatures = signatures; +     +    this.requestIds = requestIds; + +    marshallBulkSignatureResponse(); +  } + +  /** +   * Marshalls the <code>BulkResponseType</code>. +   */ +  private void marshallBulkSignatureResponse() { + +    ObjectFactory factory = new ObjectFactory(); + +    BulkResponseType bulkResponseType = factory.createBulkResponseType(); + +    for (int i=0; i< signatures.size(); i++) { + +      byte[] signature = signatures.get(i); +      CreateSignatureResponse createSignatureResponse = factory.createBulkResponseTypeCreateSignatureResponse(); +       +      if (requestIds.get(i) != null) { +        createSignatureResponse.setId(requestIds.get(i)); +      } +      CreateCMSSignatureResponseType createCreateCMSSignatureResponseType = factory +          .createCreateCMSSignatureResponseType(); +      createCreateCMSSignatureResponseType.setCMSSignature(signature); +      createSignatureResponse.setCreateCMSSignatureResponse(createCreateCMSSignatureResponseType); +      bulkResponseType.getCreateSignatureResponse().add(createSignatureResponse); +       + +    } + +    JAXBElement<BulkResponseType> createBulkResponse = factory.createBulkResponse(bulkResponseType); +    DOMResult res = new DOMResult(); + +    Marshaller marshaller = SLMarshallerFactory.getInstance().createMarshaller(false); + +    try { +      marshaller.marshal(createBulkResponse, res); +    } catch (JAXBException e) { +      log.error("Failed to marshall 'createBulkResponse'.", e); +      throw new SLRuntimeException(e); +    } +    content = ((Document) res.getNode()).getDocumentElement(); +  } + +  @Override +  public void writeTo(Result result, Templates templates, boolean fragment) { +    writeTo(content, result, templates, fragment); +  } + +  @Override +  public Element getContent() { +    return content; +  } +} diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/CreateCMSSignatureCommandImpl.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/CreateCMSSignatureCommandImpl.java index eaf3e70a..93e0eee8 100644 --- a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/CreateCMSSignatureCommandImpl.java +++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/CreateCMSSignatureCommandImpl.java @@ -123,8 +123,9 @@ public class CreateCMSSignatureCommandImpl extends      // DataObject, SigningCertificate, SigningTime        Date signingTime = request.isPAdESCompatibility() ? null : new Date(); -      signature = new Signature(request.getDataObject(), request.getStructure(), -          signingCertificate, signingTime, commandContext.getURLDereferencer(), +      signature = new Signature(request.getDataObject() != null ? request.getDataObject() +          : request.getReferenceObject(), request.getStructure(), signingCertificate, signingTime, +          commandContext.getURLDereferencer(),            configurationFacade.getUseStrongHash());      }       } catch (SLCommandException e) { diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/DataObjectHashDataInput.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/DataObjectHashDataInput.java index d0451138..74a0b4da 100644 --- a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/DataObjectHashDataInput.java +++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/DataObjectHashDataInput.java @@ -76,4 +76,8 @@ public class DataObjectHashDataInput implements HashDataInput {        return dataObject.getFilename();      } +    @Override +    public byte[] getDigest() { +      return dataObject.getReference().getDigestValue(); +    }  } diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/cms/BulkCollectionSecurityProvider.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/cms/BulkCollectionSecurityProvider.java new file mode 100644 index 00000000..6bbdc682 --- /dev/null +++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/cms/BulkCollectionSecurityProvider.java @@ -0,0 +1,114 @@ +/* + * Copyright 2015 Datentechnik Innovation GmbH and Prime Sign GmbH, Austria + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://www.osor.eu/eupl/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + */ + + + +package at.gv.egiz.bku.slcommands.impl.cms; + +import iaik.asn1.structures.AlgorithmID; +import iaik.cms.IaikProvider; + +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import java.security.PrivateKey; +import java.security.SignatureException; +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import at.buergerkarte.namespaces.securitylayer._1_2_3.ExcludedByteRangeType; +import at.gv.egiz.stal.HashDataInput; + + +/** + * This security Provider is used to collect multiple sign Requests to create one Stal BulkRequest. + * The related signature parameters are stored as a List of <code>BulkSignatureInfo</code>. + * @author szoescher + * + */ +public class BulkCollectionSecurityProvider extends IaikProvider { + +  private final static Logger log = LoggerFactory.getLogger(BulkCollectionSecurityProvider.class); + +  private String keyboxIdentifier; +  private List<HashDataInput> hashDataInput; +  private ExcludedByteRangeType excludedByteRange; +   +  private List<BulkSignatureInfo> bulkSignatureInfo; +   + +	public BulkCollectionSecurityProvider() { +		bulkSignatureInfo = new LinkedList<BulkSignatureInfo>(); +	} +	 +	public BulkCollectionSecurityProvider(String keyboxIdentifier, HashDataInput hashDataInput, +			ExcludedByteRangeType excludedByteRange) { +  +		bulkSignatureInfo = new LinkedList<BulkSignatureInfo>(); +		updateBulkCollectionSecurityProvider(keyboxIdentifier, hashDataInput, excludedByteRange); + +	} + +	public void updateBulkCollectionSecurityProvider(String keyboxIdentifier, HashDataInput hashDataInput, +			ExcludedByteRangeType excludedByteRange) { + +		this.keyboxIdentifier = keyboxIdentifier; +		this.hashDataInput = new ArrayList<HashDataInput>(); +		this.hashDataInput.add(hashDataInput); +		this.excludedByteRange = excludedByteRange; + +	} +  +  /* (non-Javadoc) +   * @see iaik.cms.IaikProvider#calculateSignatureFromSignedAttributes(iaik.asn1.structures.AlgorithmID, iaik.asn1.structures.AlgorithmID, java.security.PrivateKey, byte[]) +   */ +  @Override +  public byte[] calculateSignatureFromSignedAttributes(AlgorithmID signatureAlgorithm, +      AlgorithmID digestAlgorithm, PrivateKey privateKey, +      byte[] signedAttributes) +      throws SignatureException, InvalidKeyException, NoSuchAlgorithmException { +    log.debug("calculateSignatureFromSignedAttributes: " + signatureAlgorithm + ", " + digestAlgorithm); + +     +    STALPrivateKey spk = (STALPrivateKey) privateKey; +     +    //Store signature information that is required to create a StalBulkSignatureRequest. +    bulkSignatureInfo.add(new BulkSignatureInfo(privateKey, signatureAlgorithm, keyboxIdentifier, signedAttributes, +        spk.getAlgorithm(), spk.getDigestAlgorithm(), hashDataInput, excludedByteRange)); + +      //Size of placeholder doesn't matter +      byte[] signaturePlaceholder = new byte[1]; +      return signaturePlaceholder;    +  } + +public List<BulkSignatureInfo> getBulkSignatureInfo() { +	return bulkSignatureInfo; +} + +   +   +   +  + +} diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/cms/BulkSignature.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/cms/BulkSignature.java new file mode 100644 index 00000000..bf220034 --- /dev/null +++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/cms/BulkSignature.java @@ -0,0 +1,116 @@ +/* + * Copyright 2015 Datentechnik Innovation GmbH and Prime Sign GmbH, Austria + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://www.osor.eu/eupl/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + */ + + + +package at.gv.egiz.bku.slcommands.impl.cms; + +import iaik.asn1.CodingException; +import iaik.cms.CMSException; +import iaik.cms.CMSSignatureException; +import iaik.cms.ContentInfo; +import iaik.cms.SecurityProvider; +import iaik.cms.SignedData; +import iaik.cms.SignerInfo; +import iaik.x509.X509ExtensionException; + +import java.io.IOException; +import java.security.InvalidParameterException; +import java.security.NoSuchAlgorithmException; +import java.security.cert.CertificateEncodingException; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import java.util.Date; + +import at.buergerkarte.namespaces.securitylayer._1_2_3.CMSDataObjectOptionalMetaType; +import at.buergerkarte.namespaces.securitylayer._1_2_3.ExcludedByteRangeType; +import at.gv.egiz.bku.slexceptions.SLCommandException; +import at.gv.egiz.bku.utils.urldereferencer.URLDereferencer; +import at.gv.egiz.stal.STAL; + +/** + * This class represents a CMS-Signature as to be created by the + * security layer command <code>BulkSignatureRequest</code>. + *  + * @author szoescher + */ +public class BulkSignature extends Signature { + +  public final static String ID_AA_ETS_MIMETYPE = "0.4.0.1733.2.1"; + +  public BulkSignature(CMSDataObjectOptionalMetaType dataObject, String structure, +      X509Certificate signingCertificate, Date signingTime, URLDereferencer urlDereferencer, +      boolean useStrongHash) +          throws NoSuchAlgorithmException, CertificateEncodingException, +          CertificateException, X509ExtensionException, InvalidParameterException, +          CodingException, SLCommandException, IOException, CMSException { +		super(dataObject, structure, signingCertificate, signingTime, urlDereferencer, useStrongHash); +  } + +  /** +   * Additionally to the <code>sign()<code> method from the supertype,  +   * contains a additional parameter to set a custom securityProvider. +   * @param securityProvider The Security Provider that handles the sign request. +   */ +  public byte[] sign(SecurityProvider securityProvider, STAL stal, String keyboxIdentifier) throws CMSException, CMSSignatureException, SLCommandException { +	    signedData.setSecurityProvider(securityProvider); +	    try { +	      signedData.addSignerInfo(signerInfo); +	    } catch (NoSuchAlgorithmException e) { +	      throw new CMSSignatureException(e); +	    } +	    if (digestValue != null) { +	      try { +	        signedData.setMessageDigest(digestAlgorithm, digestValue); +	      } catch (NoSuchAlgorithmException e) { +	        throw new CMSSignatureException(e); +	      } +	    } +	    ContentInfo contentInfo = new ContentInfo(signedData); +	    return contentInfo.getEncoded(); +	  } +   +   +  public ExcludedByteRangeType getExcludedByteRange() { +		return excludedByteRange; +	} +   +  public SignerInfo getSignerInfo() { +		return signerInfo; +	} + +	public void setSignerInfo(SignerInfo signerInfo) { +		this.signerInfo = signerInfo; +	} +	 +	 +	public SignedData getSignedData()  { +	  return signedData; +	} +	 +	public byte[] getEncoded() throws CMSException{ +	    ContentInfo contentInfo = new ContentInfo(signedData); +	    return contentInfo.getEncoded(); +	} +   +	 +} + diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/cms/BulkSignatureInfo.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/cms/BulkSignatureInfo.java new file mode 100644 index 00000000..1d918f9f --- /dev/null +++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/cms/BulkSignatureInfo.java @@ -0,0 +1,104 @@ +/* + * Copyright 2015 Datentechnik Innovation GmbH and Prime Sign GmbH, Austria + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://www.osor.eu/eupl/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + */ + +package at.gv.egiz.bku.slcommands.impl.cms; + +import iaik.asn1.structures.AlgorithmID; + +import java.security.PrivateKey; +import java.util.List; + +import at.buergerkarte.namespaces.securitylayer._1_2_3.ExcludedByteRangeType; +import at.gv.egiz.stal.HashDataInput; + + +/** + *  + * @author szoescher + * + */ +public class BulkSignatureInfo { + +	AlgorithmID signatureAlgorithm; + +	String keyboxIdentifier; +	 +    byte[] signedAttributes; +     +    String signatureMethod; +     +    String digestMethod; +     +    List<HashDataInput> hashDataInput; +     +    ExcludedByteRangeType excludedByteRange; +     +    PrivateKey privateKey; + +	public BulkSignatureInfo(PrivateKey privateKey, AlgorithmID signatureAlgorithm, String keyboxIdentifier, +			byte[] signedAttributes, String signatureMethod, String digestMethod, List<HashDataInput> hashDataInput, +			ExcludedByteRangeType excludedByteRange) { +		this.privateKey = privateKey; +		this.signatureAlgorithm = signatureAlgorithm; +		this.keyboxIdentifier = keyboxIdentifier; +		this.signedAttributes = signedAttributes; +		this.signatureMethod = signatureMethod; +		this.digestMethod = digestMethod; +		this.hashDataInput = hashDataInput; +		this.excludedByteRange = excludedByteRange; +	} + +	public String getKeyboxIdentifier() { +		return keyboxIdentifier; +	} + +	public byte[] getSignedAttributes() { +		return signedAttributes; +	} + +	public String getSignatureMethod() { +		return signatureMethod; +	} + +	public String getDigestMethod() { +		return digestMethod; +	} + +	public List<HashDataInput> getHashDataInput() { +		return hashDataInput; +	} + +	public ExcludedByteRangeType getExcludedByteRange() { +		return excludedByteRange; +	} + +	public AlgorithmID getSignatureAlgorithm() { +		return signatureAlgorithm; +	} + +	public PrivateKey getPrivateKey() { +		return privateKey; +	} +	 +	 +	 +		 +} diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/cms/CMSHashDataInput.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/cms/CMSHashDataInput.java index e51c5823..25162dc4 100644 --- a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/cms/CMSHashDataInput.java +++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/cms/CMSHashDataInput.java @@ -25,6 +25,7 @@  package at.gv.egiz.bku.slcommands.impl.cms;  import java.io.ByteArrayInputStream; +import java.io.IOException;  import java.io.InputStream;  import at.gv.egiz.bku.gui.viewer.MimeTypes; @@ -32,18 +33,33 @@ import at.gv.egiz.stal.HashDataInput;  public class CMSHashDataInput implements HashDataInput { -  private final static String DEFAULT_FILENAME = "SignatureData"; +  public final static String DEFAULT_FILENAME = "SignatureData";    private byte[] data; -  private String mimeType; +  private byte[] digest; +  protected String mimeType; +  private String referenceId; +  private String fileName;    public CMSHashDataInput(byte[] data, String mimeType) {      this.data = data;      this.mimeType = mimeType;    } +  public CMSHashDataInput(byte[] data, String mimeType, byte[] digest) { +    this.data = data; +    this.mimeType = mimeType; +  } + +	public CMSHashDataInput() { +	} +    @Override    public String getReferenceId() { + +    if (referenceId != null) { +      return referenceId; +    }      return CMS_DEF_REFERENCE_ID;    } @@ -59,11 +75,38 @@ public class CMSHashDataInput implements HashDataInput {    @Override    public String getFilename() { +	  if (fileName != null) { +		  return fileName; +	  } + +	  if (mimeType != null) {      return DEFAULT_FILENAME + MimeTypes.getExtension(mimeType);    } +	  return DEFAULT_FILENAME; +  } +    @Override -  public InputStream getHashDataInput() { +  public InputStream getHashDataInput() throws IOException {      return new ByteArrayInputStream(data);    } + +  @Override +  public byte[] getDigest() { +    return digest; +  } + + +  public void setFilename(String fileName) { +    this.fileName = fileName; +  } +  +  public void setDigest(byte[] digest) { +    this.digest = digest; +  } + +  public void setReferenceId(String referenceId) { +    this.referenceId = referenceId; +  } +  } diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/cms/ReferencedHashDataInput.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/cms/ReferencedHashDataInput.java new file mode 100644 index 00000000..96e0e7de --- /dev/null +++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/cms/ReferencedHashDataInput.java @@ -0,0 +1,81 @@ +/* + * Copyright 2015 Datentechnik Innovation GmbH and Prime Sign GmbH, Austria + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://www.osor.eu/eupl/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + */ + +package at.gv.egiz.bku.slcommands.impl.cms; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; + +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang.ArrayUtils; + +import at.buergerkarte.namespaces.securitylayer._1_2_3.ExcludedByteRangeType; +import at.gv.egiz.bku.utils.urldereferencer.URLDereferencer; + +public class ReferencedHashDataInput extends CMSHashDataInput { + +  private String urlReference; +  private URLDereferencer urlDereferencer; +  private ExcludedByteRangeType excludedByteRange; +   +	public ReferencedHashDataInput(String mimeType, URLDereferencer urlDereferencer, String urlReference, ExcludedByteRangeType excludedByteRange) { +		super(null, mimeType);	 +		this.urlDereferencer = urlDereferencer; +		this.urlReference = urlReference; +		this.excludedByteRange = excludedByteRange; +	} + 	 +	 +	public URLDereferencer getUrlDereferencer() { +		return urlDereferencer; +	} + + +	public void setUrlDereferencer(URLDereferencer urlDereferencer) { +		this.urlDereferencer = urlDereferencer; +	} + +	public InputStream getHashDataInput() throws IOException { + +		InputStream hashDataInputStream = urlDereferencer.dereference(urlReference).getStream(); + +		try { +			byte[] content = IOUtils.toByteArray(hashDataInputStream); + +			if (excludedByteRange != null) { + +				int from = excludedByteRange.getFrom().intValue(); +				int to = excludedByteRange.getTo().intValue(); + +				byte[] signedContent = ArrayUtils.addAll(ArrayUtils.subarray(content, 0, from), ArrayUtils.subarray(content, to, content.length)); + +				return new ByteArrayInputStream(signedContent); + +			} else { +				return new ByteArrayInputStream(content); +			} + +		} finally { +			hashDataInputStream.close(); +		} +	} +} diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/cms/STALSecurityProvider.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/cms/STALSecurityProvider.java index 87c00644..1dd6cc9e 100644 --- a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/cms/STALSecurityProvider.java +++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/cms/STALSecurityProvider.java @@ -69,8 +69,8 @@ public class STALSecurityProvider extends IaikProvider {    private ExcludedByteRangeType excludedByteRange;    private STALSignatureException stalSignatureException; -  public STALSecurityProvider(STAL stal, String keyboxIdentifier, -      HashDataInput hashDataInput, ExcludedByteRangeType excludedByteRange) { +  public STALSecurityProvider(STAL stal, String keyboxIdentifier, HashDataInput hashDataInput, +      ExcludedByteRangeType excludedByteRange) {      this.keyboxIdentifier = keyboxIdentifier;      this.stal = stal;      this.hashDataInput = new ArrayList<HashDataInput>(); @@ -78,23 +78,27 @@ public class STALSecurityProvider extends IaikProvider {      this.excludedByteRange = excludedByteRange;    } -  /* (non-Javadoc) -   * @see iaik.cms.IaikProvider#calculateSignatureFromSignedAttributes(iaik.asn1.structures.AlgorithmID, iaik.asn1.structures.AlgorithmID, java.security.PrivateKey, byte[]) +  /* +   * (non-Javadoc) +   *  +   * @see +   * iaik.cms.IaikProvider#calculateSignatureFromSignedAttributes(iaik.asn1. +   * structures.AlgorithmID, iaik.asn1.structures.AlgorithmID, +   * java.security.PrivateKey, byte[])     */    @Override -  public byte[] calculateSignatureFromSignedAttributes(AlgorithmID signatureAlgorithm, -      AlgorithmID digestAlgorithm, PrivateKey privateKey, -      byte[] signedAttributes) -      throws SignatureException, InvalidKeyException, NoSuchAlgorithmException { +  public byte[] calculateSignatureFromSignedAttributes(AlgorithmID signatureAlgorithm, AlgorithmID digestAlgorithm, +      PrivateKey privateKey, byte[] signedAttributes) throws SignatureException, InvalidKeyException, +      NoSuchAlgorithmException { +    stalSignatureException = null;      log.debug("calculateSignatureFromSignedAttributes: " + signatureAlgorithm + ", " + digestAlgorithm);      STALPrivateKey spk = (STALPrivateKey) privateKey; -    SignRequest signRequest = getSTALSignRequest(keyboxIdentifier, signedAttributes, -        spk.getAlgorithm(), spk.getDigestAlgorithm(), hashDataInput, excludedByteRange); +    SignRequest signRequest = getSTALSignRequest(keyboxIdentifier, signedAttributes, spk.getAlgorithm(), +        spk.getDigestAlgorithm(), hashDataInput, excludedByteRange);      log.debug("Sending STAL request ({})", privateKey.getAlgorithm()); -    List<STALResponse> responses = -      stal.handleRequest(Collections.singletonList((STALRequest) signRequest)); +    List<STALResponse> responses = stal.handleRequest(Collections.singletonList((STALRequest) signRequest));      if (responses == null || responses.size() != 1) {        throw new SignatureException("Failed to access STAL."); @@ -114,9 +118,9 @@ public class STALSecurityProvider extends IaikProvider {      }    } -  private static SignRequest getSTALSignRequest(String keyboxIdentifier, -      byte[] signedAttributes, String signatureMethod, String digestMethod, -      List<HashDataInput> hashDataInput, ExcludedByteRangeType excludedByteRange) { +  private static SignRequest getSTALSignRequest(String keyboxIdentifier, byte[] signedAttributes, +      String signatureMethod, String digestMethod, List<HashDataInput> hashDataInput, +      ExcludedByteRangeType excludedByteRange) {      SignRequest signRequest = new SignRequest();      signRequest.setKeyIdentifier(keyboxIdentifier);      log.debug("SignedAttributes: " + Util.toBase64String(signedAttributes)); @@ -147,8 +151,7 @@ public class STALSecurityProvider extends IaikProvider {        sigS.addComponent(new INTEGER(new BigInteger(1, r)));        sigS.addComponent(new INTEGER(new BigInteger(1, s)));        return DerCoder.encode(sigS); -    } -    else +    } else        return sig;    } diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/cms/Signature.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/cms/Signature.java index 7be546de..4a94ca7f 100644 --- a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/cms/Signature.java +++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/cms/Signature.java @@ -24,48 +24,32 @@  package at.gv.egiz.bku.slcommands.impl.cms; -import iaik.asn1.ASN1Object; -import iaik.asn1.CodingException; -import iaik.asn1.ObjectID; -import iaik.asn1.SEQUENCE; -import iaik.asn1.UTF8String; -import iaik.asn1.structures.AlgorithmID; -import iaik.asn1.structures.Attribute; -import iaik.asn1.structures.ChoiceOfTime; -import iaik.cms.CMSException; -import iaik.cms.CMSSignatureException; -import iaik.cms.CertificateIdentifier; -import iaik.cms.ContentInfo; -import iaik.cms.IssuerAndSerialNumber; -import iaik.cms.SignedData; -import iaik.cms.SignerInfo; -import iaik.smime.ess.ESSCertID; -import iaik.smime.ess.ESSCertIDv2; -import iaik.x509.X509ExtensionException; -  import java.io.ByteArrayOutputStream;  import java.io.IOException;  import java.io.InputStream; +import java.net.URI; +import java.net.URISyntaxException;  import java.security.InvalidParameterException;  import java.security.NoSuchAlgorithmException;  import java.security.PrivateKey; -import java.security.PublicKey;  import java.security.cert.CertificateEncodingException;  import java.security.cert.CertificateException;  import java.security.cert.X509Certificate; -import java.security.interfaces.ECPublicKey; -import java.security.interfaces.RSAPublicKey; -import java.security.spec.ECParameterSpec;  import java.util.ArrayList;  import java.util.Arrays;  import java.util.Date;  import java.util.List; +import javax.xml.crypto.dsig.DigestMethod; +  import org.apache.commons.lang.ArrayUtils;  import org.slf4j.Logger;  import org.slf4j.LoggerFactory; +import org.w3._2000._09.xmldsig_.DigestMethodType; +import at.buergerkarte.namespaces.securitylayer._1_2_3.CMSDataObjectOptionalMetaType;  import at.buergerkarte.namespaces.securitylayer._1_2_3.CMSDataObjectRequiredMetaType; +import at.buergerkarte.namespaces.securitylayer._1_2_3.DigestAndRefType;  import at.buergerkarte.namespaces.securitylayer._1_2_3.ExcludedByteRangeType;  import at.gv.egiz.bku.slcommands.impl.xsect.AlgorithmMethodFactory;  import at.gv.egiz.bku.slcommands.impl.xsect.AlgorithmMethodFactoryImpl; @@ -74,6 +58,24 @@ import at.gv.egiz.bku.slexceptions.SLCommandException;  import at.gv.egiz.bku.utils.urldereferencer.URLDereferencer;  import at.gv.egiz.stal.HashDataInput;  import at.gv.egiz.stal.STAL; +import iaik.asn1.ASN1Object; +import iaik.asn1.CodingException; +import iaik.asn1.ObjectID; +import iaik.asn1.SEQUENCE; +import iaik.asn1.UTF8String; +import iaik.asn1.structures.AlgorithmID; +import iaik.asn1.structures.Attribute; +import iaik.asn1.structures.ChoiceOfTime; +import iaik.cms.CMSException; +import iaik.cms.CMSSignatureException; +import iaik.cms.CertificateIdentifier; +import iaik.cms.ContentInfo; +import iaik.cms.IssuerAndSerialNumber; +import iaik.cms.SignedData; +import iaik.cms.SignerInfo; +import iaik.smime.ess.ESSCertID; +import iaik.smime.ess.ESSCertIDv2; +import iaik.x509.X509ExtensionException;  /**   * This class represents a CMS-Signature as to be created by the @@ -90,25 +92,51 @@ public class Signature {     */    private final Logger log = LoggerFactory.getLogger(Signature.class); -  private SignedData signedData; -  private SignerInfo signerInfo; -  private byte[] signedDocument; -  private String mimeType; -  private AlgorithmID signatureAlgorithm; -  private AlgorithmID digestAlgorithm; -  private String signatureAlgorithmURI; -  private String digestAlgorithmURI; -  private ExcludedByteRangeType excludedByteRange; +  protected SignedData signedData; +  protected SignerInfo signerInfo; +  protected byte[] signedDocument; +  protected String mimeType; +  protected AlgorithmID signatureAlgorithm; +  protected AlgorithmID digestAlgorithm; +  protected byte[] digestValue; +  protected String signatureAlgorithmURI; +  protected String digestAlgorithmURI; +  protected ExcludedByteRangeType excludedByteRange; +  private HashDataInput hashDataInput; +   -  public Signature(CMSDataObjectRequiredMetaType dataObject, String structure, +public Signature(CMSDataObjectOptionalMetaType dataObject, String structure,        X509Certificate signingCertificate, Date signingTime, URLDereferencer urlDereferencer,        boolean useStrongHash)            throws NoSuchAlgorithmException, CertificateEncodingException,            CertificateException, X509ExtensionException, InvalidParameterException, -          CodingException, SLCommandException, IOException { -    byte[] dataToBeSigned = getContent(dataObject, urlDereferencer); +          CodingException, SLCommandException, IOException, CMSException {      int mode = structure.equalsIgnoreCase("enveloping") ? SignedData.IMPLICIT : SignedData.EXPLICIT; +    if (dataObject.getContent() != null) { +    byte[] dataToBeSigned = getContent(dataObject, urlDereferencer);      this.signedData = new SignedData(dataToBeSigned, mode); +	  if (dataObject.getMetaInfo() != null) { +			this.mimeType = dataObject.getMetaInfo().getMimeType(); +		} +	   +      hashDataInput = new CMSHashDataInput(signedDocument, mimeType); +       +    } else { +      DigestAndRefType digestAndRef = dataObject.getDigestAndRef(); +      DigestMethodType digestMethod = digestAndRef.getDigestMethod();      +       +      hashDataInput = new ReferencedHashDataInput(dataObject.getMetaInfo().getMimeType(), urlDereferencer, +					digestAndRef.getReference(), dataObject.getExcludedByteRange()); +	 +      try { +        digestAlgorithm = getAlgorithmID(digestMethod.getAlgorithm()); +      } catch (URISyntaxException e) { +        //TODO: choose proper execption +        throw new NoSuchAlgorithmException(e); +      } +      digestValue = digestAndRef.getDigestValue(); +      this.signedData = new SignedData(ObjectID.pkcs7_data); +    }      setAlgorithmIDs(signingCertificate, useStrongHash);      createSignerInfo(signingCertificate);      setSignerCertificate(signingCertificate); @@ -208,7 +236,7 @@ public class Signature {      attributes.add(signingTime);    } -  private byte[] getContent(CMSDataObjectRequiredMetaType dataObject, URLDereferencer urlDereferencer) +  private byte[] getContent(CMSDataObjectOptionalMetaType dataObject, URLDereferencer urlDereferencer)        throws InvalidParameterException, SLCommandException, IOException {      byte[] data = dataObject.getContent().getBase64Content();      if (data == null) { @@ -252,63 +280,36 @@ public class Signature {    }    private void setAlgorithmIDs(X509Certificate signingCertificate, boolean useStrongHash) throws NoSuchAlgorithmException { -    PublicKey publicKey = signingCertificate.getPublicKey(); -    String algorithm = publicKey.getAlgorithm();      AlgorithmMethodFactory amf = new AlgorithmMethodFactoryImpl(signingCertificate, useStrongHash);      signatureAlgorithmURI = amf.getSignatureAlgorithmURI(); +    signatureAlgorithm = amf.getSignatureAlgorithmID(); +    if (digestAlgorithm != null) { +      if (AlgorithmID.sha1.equals(digestAlgorithm)) { +        digestAlgorithmURI = DigestMethod.SHA1; +      } else if (AlgorithmID.sha256.equals(digestAlgorithm)) { +        digestAlgorithmURI = DigestMethod.SHA256; +      } else if (AlgorithmID.sha512.equals(digestAlgorithm)) { +        digestAlgorithmURI = DigestMethod.SHA512; +      } else if (AlgorithmID.ripeMd160.equals(digestAlgorithm)) { +        digestAlgorithmURI = DigestMethod.RIPEMD160; +      } else { +        throw new NoSuchAlgorithmException("Algorithm '" + digestAlgorithm + "' not supported."); +      } +    } else {      digestAlgorithmURI = amf.getDigestAlgorithmURI(); - -    if ("DSA".equals(algorithm)) { -      signatureAlgorithm = AlgorithmID.dsaWithSHA1; -    } else if ("RSA".equals(algorithm)) { - -      int keyLength = 0; -      if (publicKey instanceof RSAPublicKey) { -        keyLength = ((RSAPublicKey) publicKey).getModulus().bitLength(); +      digestAlgorithm = amf.getDigestAlgorithmID();        } - -      if (useStrongHash && keyLength >= 2048) { -        signatureAlgorithm = AlgorithmID.sha256WithRSAEncryption; -        digestAlgorithm = AlgorithmID.sha256; -//      } else if (useStrongHash) { // Cannot be used if not enabled in AlgorithmMethodFactoryImpl -//        signatureAlgorithm = AlgorithmID.rsaSignatureWithRipemd160; -//        digestAlgorithm = AlgorithmID.ripeMd160; -      } else { -        signatureAlgorithm = AlgorithmID.sha1WithRSAEncryption; -        digestAlgorithm = AlgorithmID.sha1;        } -    } else if (("EC".equals(algorithm)) || ("ECDSA".equals(algorithm))) { -      int fieldSize = 0; -      if (publicKey instanceof ECPublicKey) { -        ECParameterSpec params = ((ECPublicKey) publicKey).getParams(); -        fieldSize = params.getCurve().getField().getFieldSize(); -      } else { -        throw new NoSuchAlgorithmException("Public key type not supported."); -      } +	public HashDataInput getHashDataInput() { -      if (useStrongHash && fieldSize >= 512) { -        signatureAlgorithm = AlgorithmID.ecdsa_With_SHA512; -        digestAlgorithm = AlgorithmID.sha512; -      } else if (useStrongHash && fieldSize >= 256) { -        signatureAlgorithm = AlgorithmID.ecdsa_With_SHA256; -        digestAlgorithm = AlgorithmID.sha256; -      } else if (useStrongHash) { -          signatureAlgorithm = AlgorithmID.ecdsa_plain_With_RIPEMD160; -          digestAlgorithm = AlgorithmID.ripeMd160; +		if (hashDataInput != null) { +			return hashDataInput;        } else { -        signatureAlgorithm = AlgorithmID.ecdsa_With_SHA1; -        digestAlgorithm = AlgorithmID.sha1; -      } -    } else { -      throw new NoSuchAlgorithmException("Public key algorithm '" + algorithm -          + "' not supported."); +			return new CMSHashDataInput(signedDocument, mimeType);      }    } -  private HashDataInput getHashDataInput() { -    return new CMSHashDataInput(signedDocument, mimeType); -  }    public byte[] sign(STAL stal, String keyboxIdentifier) throws CMSException, CMSSignatureException, SLCommandException {      STALSecurityProvider securityProvider = new STALSecurityProvider(stal, keyboxIdentifier, getHashDataInput(), this.excludedByteRange); @@ -322,7 +323,29 @@ public class Signature {        }        throw new CMSSignatureException(e);      } +    if (digestValue != null) { +      try { +        signedData.setMessageDigest(digestAlgorithm, digestValue); +      } catch (NoSuchAlgorithmException e) { +        throw new CMSSignatureException(e); +      } +    }      ContentInfo contentInfo = new ContentInfo(signedData);      return contentInfo.getEncoded();    } +   +  protected AlgorithmID getAlgorithmID(String uri) throws URISyntaxException { +    String oid = null; +    URI urn = new URI(uri); +    String scheme = urn.getScheme(); +    if ("URN".equalsIgnoreCase(scheme)) { +      String schemeSpecificPart = urn.getSchemeSpecificPart().toLowerCase(); +      if (schemeSpecificPart.startsWith("oid:")) { +        oid = schemeSpecificPart.substring(4, schemeSpecificPart.length()); +} +    } +    return new AlgorithmID(new ObjectID(oid)); +  }  } + + diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/xsect/AlgorithmMethodFactory.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/xsect/AlgorithmMethodFactory.java index d2484b56..1b801ec5 100644 --- a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/xsect/AlgorithmMethodFactory.java +++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/xsect/AlgorithmMethodFactory.java @@ -32,6 +32,8 @@ import javax.xml.crypto.dsig.CanonicalizationMethod;  import javax.xml.crypto.dsig.DigestMethod;
  import javax.xml.crypto.dsig.SignatureMethod;
 +import iaik.asn1.structures.AlgorithmID;
 +
  /**
   * A factory for creating {@link AlgorithmMethod}s.
   * 
 @@ -87,4 +89,8 @@ public interface AlgorithmMethodFactory {    public String getSignatureAlgorithmURI();    public String getDigestAlgorithmURI(); + +  AlgorithmID getSignatureAlgorithmID(); + +  AlgorithmID getDigestAlgorithmID();  }
 diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/xsect/AlgorithmMethodFactoryImpl.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/xsect/AlgorithmMethodFactoryImpl.java index 896552d8..c3fcd146 100644 --- a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/xsect/AlgorithmMethodFactoryImpl.java +++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/xsect/AlgorithmMethodFactoryImpl.java @@ -24,6 +24,7 @@  package at.gv.egiz.bku.slcommands.impl.xsect;
 +import iaik.asn1.structures.AlgorithmID;  import iaik.xml.crypto.XmldsigMore;  import java.security.InvalidAlgorithmParameterException; @@ -55,11 +56,21 @@ public class AlgorithmMethodFactoryImpl implements AlgorithmMethodFactory {    private String signatureAlgorithmURI;    /** +   * The signature algorithm ID. +   */ +  private AlgorithmID signatureAlgorithmID; +   +  /**     * the digest algorithm URI.     */    private String digestAlgorithmURI = DigestMethod.SHA1;
    /**
 +   * The digest algorithm ID. +   */ +  private AlgorithmID digestAlgorithmID = AlgorithmID.sha1;
 +
 +  /**
     * The algorithm parameters for the signature algorithm.
     */
    private SignatureMethodParameterSpec signatureMethodParameterSpec;
 @@ -82,6 +93,7 @@ public class AlgorithmMethodFactoryImpl implements AlgorithmMethodFactory {      if ("DSA".equals(algorithm)) {
        signatureAlgorithmURI = SignatureMethod.DSA_SHA1;
 +      signatureAlgorithmID = AlgorithmID.dsaWithSHA1;
      } else if ("RSA".equals(algorithm)) {        int keyLength = 0; @@ -91,12 +103,12 @@ public class AlgorithmMethodFactoryImpl implements AlgorithmMethodFactory {        if (useStrongHash && keyLength >= 2048) {          signatureAlgorithmURI = XmldsigMore.SIGNATURE_RSA_SHA256; +        signatureAlgorithmID = AlgorithmID.sha256WithRSAEncryption;          digestAlgorithmURI = DigestMethod.SHA256; -//      } else if (useStrongHash) { -//        signatureAlgorithmURI = XmldsigMore.SIGNATURE_RSA_RIPEMD160_ERRATA; -//        digestAlgorithmURI = DigestMethod.RIPEMD160; +        digestAlgorithmID = AlgorithmID.sha256;        } else {          signatureAlgorithmURI = SignatureMethod.RSA_SHA1; +        signatureAlgorithmID = AlgorithmID.sha1WithRSAEncryption;        }      } else if (("EC".equals(algorithm)) || ("ECDSA".equals(algorithm))) { @@ -111,15 +123,22 @@ public class AlgorithmMethodFactoryImpl implements AlgorithmMethodFactory {        if (useStrongHash && fieldSize >= 512) {          signatureAlgorithmURI = XmldsigMore.SIGNATURE_ECDSA_SHA512; +        signatureAlgorithmID = AlgorithmID.ecdsa_With_SHA512;          digestAlgorithmURI = DigestMethod.SHA512; +        digestAlgorithmID = AlgorithmID.sha512;        } else if (useStrongHash && fieldSize >= 256) {          signatureAlgorithmURI = XmldsigMore.SIGNATURE_ECDSA_SHA256; +        signatureAlgorithmID = AlgorithmID.ecdsa_With_SHA256;          digestAlgorithmURI = DigestMethod.SHA256; +        digestAlgorithmID = AlgorithmID.sha256;        } else if (useStrongHash) {            signatureAlgorithmURI = XmldsigMore.SIGNATURE_ECDSA_RIPEMD160; +          signatureAlgorithmID = AlgorithmID.ecdsa_plain_With_RIPEMD160;            digestAlgorithmURI = DigestMethod.RIPEMD160; +          digestAlgorithmID = AlgorithmID.ripeMd160;        } else {          signatureAlgorithmURI = XmldsigMore.SIGNATURE_ECDSA_SHA1; +        signatureAlgorithmID = AlgorithmID.ecdsa_With_SHA1;        }      } else {
 @@ -185,4 +204,14 @@ public class AlgorithmMethodFactoryImpl implements AlgorithmMethodFactory {      return digestAlgorithmURI;    }
 +  @Override +  public AlgorithmID getSignatureAlgorithmID() { +    return signatureAlgorithmID; +  } + +  @Override +  public AlgorithmID getDigestAlgorithmID() { +    return digestAlgorithmID; +  }
 +
  }
 diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/spring/URLDereferencerFactoryBean.java b/bkucommon/src/main/java/at/gv/egiz/bku/spring/URLDereferencerFactoryBean.java new file mode 100644 index 00000000..1a95a146 --- /dev/null +++ b/bkucommon/src/main/java/at/gv/egiz/bku/spring/URLDereferencerFactoryBean.java @@ -0,0 +1,75 @@ +package at.gv.egiz.bku.spring; + +import javax.net.ssl.HostnameVerifier; +import javax.net.ssl.SSLSocketFactory; + +import org.apache.commons.configuration.Configuration; +import org.springframework.beans.factory.FactoryBean; + +import at.gv.egiz.bku.conf.MoccaConfigurationFacade; +import at.gv.egiz.bku.utils.urldereferencer.FileURLProtocolHandlerImpl; +import at.gv.egiz.bku.utils.urldereferencer.URLDereferencerImpl; + +public class URLDereferencerFactoryBean implements FactoryBean { + +  private HostnameVerifier hostnameVerifier; +  private SSLSocketFactory sslSocketFactory; + +  protected final ConfigurationFacade configurationFacade = new ConfigurationFacade(); + +  public class ConfigurationFacade implements MoccaConfigurationFacade { + +      private Configuration configuration; +      public static final String ENABLE_FILEURIS = "enableFileURIs"; + +      public boolean isEnableFileURIs() { +          return configuration.getBoolean(ENABLE_FILEURIS, false); +      } +       +  } +   +  public void setConfiguration(Configuration configuration) { +    configurationFacade.configuration = configuration; +  } +   +	@Override +	public Object getObject() throws Exception { +		 +	  URLDereferencerImpl urlDereferencer = URLDereferencerImpl.getInstance(); +    urlDereferencer.setHostnameVerifier(hostnameVerifier); +    urlDereferencer.setSSLSocketFactory(sslSocketFactory); + +	  if(!configurationFacade.isEnableFileURIs()) { +	    urlDereferencer.registerHandler(FileURLProtocolHandlerImpl.FILE, new FileURLProtocolHandlerImpl()); +	  } +			 +		return urlDereferencer; +	} + +	@Override +	public Class<URLDereferencerImpl> getObjectType() { +		return URLDereferencerImpl.class; +	} + +	@Override +	public boolean isSingleton() { +		return true; +	} + +	public HostnameVerifier getHostnameVerifier() { +		return hostnameVerifier; +	} + +	public void setHostnameVerifier(HostnameVerifier hostnameVerifier) { +		this.hostnameVerifier = hostnameVerifier; +	} + +	public SSLSocketFactory getSslSocketFactory() { +		return sslSocketFactory; +	} + +	public void setSslSocketFactory(SSLSocketFactory sslSocketFactory) { +		this.sslSocketFactory = sslSocketFactory; +	} +	 +} diff --git a/bkucommon/src/main/resources/at/gv/egiz/bku/slexceptions/SLExceptionMessages.properties b/bkucommon/src/main/resources/at/gv/egiz/bku/slexceptions/SLExceptionMessages.properties index de54e9b2..92955fc9 100644 --- a/bkucommon/src/main/resources/at/gv/egiz/bku/slexceptions/SLExceptionMessages.properties +++ b/bkucommon/src/main/resources/at/gv/egiz/bku/slexceptions/SLExceptionMessages.properties @@ -108,3 +108,6 @@ ec4011.notimplemented=Befehl {0} ist nicht implementiert.  lec2901.notimplemented=Die in der Anfrage verwendete Version des Security-Layer Protokolls ({0}) wird nicht mehr unterstützt. 
 +# custom error messages for bulk signature +ec4124= XML Signatur Requests werden aktuell in der Stapelsignatur nicht unterstützt. + diff --git a/bkucommon/src/main/resources/at/gv/egiz/bku/slexceptions/SLExceptionMessages_en.properties b/bkucommon/src/main/resources/at/gv/egiz/bku/slexceptions/SLExceptionMessages_en.properties index 471f4a13..4d90f71c 100644 --- a/bkucommon/src/main/resources/at/gv/egiz/bku/slexceptions/SLExceptionMessages_en.properties +++ b/bkucommon/src/main/resources/at/gv/egiz/bku/slexceptions/SLExceptionMessages_en.properties @@ -106,3 +106,5 @@ ec4011.notimplemented=Command {0} not implemented.  # Legacy error codes  #  lec2901.notimplemented=The version ({0}) of the security-layer protocol used in the request is not supported. +# custom error messages for bulk signature +ec4124= XML signature requests are currently not supported in bulk signature requests. diff --git a/bkucommon/src/site/apt/configuration.apt b/bkucommon/src/site/apt/configuration.apt index ec6b7cd0..2aca5dc7 100644 --- a/bkucommon/src/site/apt/configuration.apt +++ b/bkucommon/src/site/apt/configuration.apt @@ -54,6 +54,10 @@ MOCCA Configuration  	Default: <<<true>>> +  [<<<enableFileURIs>>>] Whether to allow dereferencing of "file" URIs. + +  Default: <<<false>>>     +	  	[<<<SSL>>>]  		The following two configuration elements must provide an URL which resolves to a directory in the file system. It may either be an absolute URL or a relative URL, which is resolved using the URL of the configuration file. diff --git a/bkucommon/src/test/java/at/gv/egiz/bku/slcommands/impl/BulkCommandImplTest.java b/bkucommon/src/test/java/at/gv/egiz/bku/slcommands/impl/BulkCommandImplTest.java new file mode 100644 index 00000000..b91bec98 --- /dev/null +++ b/bkucommon/src/test/java/at/gv/egiz/bku/slcommands/impl/BulkCommandImplTest.java @@ -0,0 +1,130 @@ +/* + * Copyright 2015 Datentechnik Innovation and Prime Sign GmbH, Austria + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://www.osor.eu/eupl/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + */ + +package at.gv.egiz.bku.slcommands.impl; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import iaik.asn1.ObjectID; +import iaik.cms.SignedData; +import iaik.xml.crypto.XSecProvider; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.io.InputStreamReader; + +import javax.xml.bind.JAXBException; +import javax.xml.bind.Unmarshaller; +import javax.xml.transform.stream.StreamResult; +import javax.xml.transform.stream.StreamSource; + +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.springframework.context.ApplicationContext; +import org.springframework.context.support.ClassPathXmlApplicationContext; + +import at.buergerkarte.namespaces.securitylayer._1_2_3.BulkResponseType; +import at.gv.egiz.bku.slcommands.BulkCommand; +import at.gv.egiz.bku.slcommands.BulkSignatureResult; +import at.gv.egiz.bku.slcommands.SLCommand; +import at.gv.egiz.bku.slcommands.SLCommandContext; +import at.gv.egiz.bku.slcommands.SLCommandFactory; +import at.gv.egiz.bku.slcommands.SLResult; +import at.gv.egiz.bku.utils.urldereferencer.URLDereferencer; +import at.gv.egiz.stal.STAL; +import at.gv.egiz.stal.STALFactory; + +public class BulkCommandImplTest { + +  protected static ApplicationContext appCtx; +  private SLCommandFactory factory; + +  private STAL stal; + +  private URLDereferencer urlDereferencer; + +  @BeforeClass +  public static void setUpClass() { +    appCtx = new ClassPathXmlApplicationContext("at/gv/egiz/bku/slcommands/testApplicationContext.xml"); +    XSecProvider.addAsProvider(true); +  } + +  @Before +  public void setUp() throws JAXBException { + +    Object bean = appCtx.getBean("slCommandFactory"); +    assertTrue(bean instanceof SLCommandFactory); + +    factory = (SLCommandFactory) bean; + +    bean = appCtx.getBean("stalFactory"); +    assertTrue(bean instanceof STALFactory); + +    stal = ((STALFactory) bean).createSTAL(); + +    bean = appCtx.getBean("urlDereferencer"); +    assertTrue(bean instanceof URLDereferencer); + +    urlDereferencer = (URLDereferencer) bean; + +  } + +  @Test +  public void testCreateCMSSignatureRequest() throws Exception { +    InputStream inputStream = getClass().getClassLoader().getResourceAsStream( +        "at/gv/egiz/bku/slcommands/bulksignaturerequest/BulkSignatureRequest.xml"); +    assertNotNull(inputStream); + +    SLCommand command = factory.createSLCommand(new StreamSource(new InputStreamReader(inputStream))); +    assertTrue(command instanceof BulkCommand); + +    SLCommandContext context = new SLCommandContext(stal, urlDereferencer, null); +    SLResult result = command.execute(context); + +    assertTrue(result instanceof BulkSignatureResult); + +    BulkSignatureResult bulkResult = (BulkSignatureResult) result; +    System.out.println(bulkResult.getContent()); + +    bulkResult.getContent(); + +    // unmarshall response +    Unmarshaller unmarshaller = factory.getJaxbContext().createUnmarshaller(); + +    BulkResponseType response = unmarshaller.unmarshal(bulkResult.getContent(), BulkResponseType.class).getValue(); + +    // verify ContentType of singature +    byte[] cmsSignature = response.getCreateSignatureResponse().get(0).getCreateCMSSignatureResponse() +        .getCMSSignature(); +    SignedData signedData = new SignedData(new ByteArrayInputStream(cmsSignature)); + +    assertNotNull(signedData); +    assertEquals(ObjectID.pkcs7_signedData, signedData.getContentType()); +    assertNotNull(response.getCreateSignatureResponse()); +    assertEquals(2, response.getCreateSignatureResponse().size()); + +    result.writeTo(new StreamResult(System.out), false); + +  } + +} diff --git a/bkucommon/src/test/java/at/gv/egiz/bku/slcommands/impl/CreateCMSSignatureCommandImplTest.java b/bkucommon/src/test/java/at/gv/egiz/bku/slcommands/impl/CreateCMSSignatureCommandImplTest.java index b1ec7777..09b70f09 100644 --- a/bkucommon/src/test/java/at/gv/egiz/bku/slcommands/impl/CreateCMSSignatureCommandImplTest.java +++ b/bkucommon/src/test/java/at/gv/egiz/bku/slcommands/impl/CreateCMSSignatureCommandImplTest.java @@ -24,13 +24,21 @@  package at.gv.egiz.bku.slcommands.impl;
 +import static org.junit.Assert.assertEquals;  import static org.junit.Assert.assertNotNull;  import static org.junit.Assert.assertTrue; +import iaik.asn1.ObjectID; +import iaik.cms.CMSParsingException; +import iaik.cms.SignedData;  import iaik.xml.crypto.XSecProvider; +import java.io.ByteArrayInputStream; +import java.io.IOException;  import java.io.InputStream;  import java.io.InputStreamReader; +import javax.xml.bind.JAXBException; +import javax.xml.bind.Unmarshaller;  import javax.xml.transform.stream.StreamResult;  import javax.xml.transform.stream.StreamSource; @@ -40,7 +48,9 @@ import org.junit.Test;  import org.springframework.context.ApplicationContext;  import org.springframework.context.support.ClassPathXmlApplicationContext; +import at.buergerkarte.namespaces.securitylayer._1_2_3.CreateCMSSignatureResponseType;  import at.gv.egiz.bku.slcommands.CreateCMSSignatureCommand; +import at.gv.egiz.bku.slcommands.CreateCMSSignatureResult;  import at.gv.egiz.bku.slcommands.SLCommand;  import at.gv.egiz.bku.slcommands.SLCommandContext;  import at.gv.egiz.bku.slcommands.SLCommandFactory; @@ -89,8 +99,11 @@ public class CreateCMSSignatureCommandImplTest {    }
    @Test
 -  public void testCreateCMSSignatureRequest() throws SLCommandException, SLRuntimeException, SLRequestException, SLVersionException {
 -    InputStream inputStream = getClass().getClassLoader().getResourceAsStream("at/gv/egiz/bku/slcommands/createcmssignaturerequest/CreateCMSSignatureRequest.xml");
 +  public void testCreateCMSSignatureRequest() throws SLCommandException, SLRuntimeException, SLRequestException, +      SLVersionException, JAXBException, CMSParsingException, IOException { +     +    InputStream inputStream = getClass().getClassLoader().getResourceAsStream( +        "at/gv/egiz/bku/slcommands/createcmssignaturerequest/CreateCMSSignatureRequest.xml");      assertNotNull(inputStream);
      SLCommand command = factory.createSLCommand(new StreamSource(new InputStreamReader(inputStream)));
 @@ -98,6 +111,22 @@ public class CreateCMSSignatureCommandImplTest {      SLCommandContext context = new SLCommandContext(stal, urlDereferencer, null);      SLResult result = command.execute(context);
 + +    assertTrue(result instanceof CreateCMSSignatureResult); +    CreateCMSSignatureResult sigResult = (CreateCMSSignatureResult) result; +     +    //unmarshall response +    Unmarshaller unmarshaller = factory.getJaxbContext().createUnmarshaller(); +     +    CreateCMSSignatureResponseType response = unmarshaller.unmarshal(sigResult.getContent(), CreateCMSSignatureResponseType.class).getValue(); + +    //verify ContentType of singature  +    byte[] cmsSignature = response.getCMSSignature(); +    SignedData signedData = new SignedData(new ByteArrayInputStream(cmsSignature)); + +    assertNotNull(signedData); +    assertEquals(ObjectID.pkcs7_signedData, signedData.getContentType()); +       result.writeTo(new StreamResult(System.out), false);
    }
  }
 diff --git a/bkucommon/src/test/java/at/gv/egiz/bku/slcommands/impl/cms/SignatureTest.java b/bkucommon/src/test/java/at/gv/egiz/bku/slcommands/impl/cms/SignatureTest.java new file mode 100644 index 00000000..56229b83 --- /dev/null +++ b/bkucommon/src/test/java/at/gv/egiz/bku/slcommands/impl/cms/SignatureTest.java @@ -0,0 +1,130 @@ +package at.gv.egiz.bku.slcommands.impl.cms; + +import static org.junit.Assert.*; + +import java.io.ByteArrayInputStream; +import java.net.URI; +import java.net.URISyntaxException; +import java.nio.charset.Charset; +import java.security.MessageDigest; +import java.util.Date; + +import org.junit.BeforeClass; +import org.junit.Test; +import org.w3._2000._09.xmldsig_.DigestMethodType; + +import at.buergerkarte.namespaces.securitylayer._1_2_3.Base64OptRefContentType; +import at.buergerkarte.namespaces.securitylayer._1_2_3.CMSDataObjectRequiredMetaType; +import at.buergerkarte.namespaces.securitylayer._1_2_3.DigestAndRefType; +import at.buergerkarte.namespaces.securitylayer._1_2_3.MetaInfoType; +import at.gv.egiz.stal.dummy.DummySTAL; +import iaik.asn1.ObjectID; +import iaik.asn1.structures.AlgorithmID; +import iaik.cms.InvalidSignatureValueException; +import iaik.cms.SignedData; +import iaik.cms.SignerInfo; +import iaik.security.ecc.provider.ECCProvider; +import iaik.security.provider.IAIK; +import iaik.x509.X509Certificate; + +public class SignatureTest { + +  private DummySTAL stal = new DummySTAL(); +   +  @BeforeClass +  public static void setUpClass() { +    IAIK.addAsProvider(); +    ECCProvider.addAsProvider(); +  } + +  @Test +  public void testSignCMSDataObject() throws Exception { +     +    byte[] plaintext = "Plaintext".getBytes(Charset.forName("UTF-8")); +     +    CMSDataObjectRequiredMetaType dataObject = new CMSDataObjectRequiredMetaType(); +    Base64OptRefContentType base64OptRefContentType = new Base64OptRefContentType(); +    base64OptRefContentType.setBase64Content(plaintext); +    dataObject.setContent(base64OptRefContentType); +    MetaInfoType metaInfoType = new MetaInfoType(); +    metaInfoType.setMimeType("text/plain"); +    dataObject.setMetaInfo(metaInfoType); + +    Signature signature = new Signature(dataObject, "detached", stal.getCert(), new Date(), null, true); +    byte[] cmsSignature = signature.sign(stal, "SecureSignatureKeypair"); +     +    SignedData signedData = new SignedData(new ByteArrayInputStream(cmsSignature)); +    signedData.setContent(plaintext); +    assertEquals(ObjectID.pkcs7_data, signedData.getEncapsulatedContentType()); +    SignerInfo[] signerInfos = signedData.getSignerInfos(); +    assertEquals(1, signerInfos.length); +    SignerInfo signerInfo = signerInfos[0]; +    signedData.verify((X509Certificate) stal.getCert()); +    assertEquals(AlgorithmID.sha1, signerInfo.getDigestAlgorithm()); +    assertEquals(AlgorithmID.sha1WithRSAEncryption, signerInfo.getSignatureAlgorithm()); +     +    System.out.println(AlgorithmID.sha1); +     +  } + +  @Test +  public void testSignCMSReferenceSha1() throws Exception { +    testSignCMSReference(AlgorithmID.sha1); +  } + +  //TODO Why doesn't it work this way?? +  @Test(expected = InvalidSignatureValueException.class) +  public void testSignCMSReferenceSha256() throws Exception { +    testSignCMSReference(AlgorithmID.sha256); +  } +   +  private void testSignCMSReference(AlgorithmID digestAlgorithmID) throws Exception { +     +    byte[] plaintext = "Plaintext".getBytes(Charset.forName("UTF-8")); +     +    MessageDigest messageDigest = MessageDigest.getInstance(digestAlgorithmID.getImplementationName()); +    byte[] digestValue = messageDigest.digest(plaintext); +     +    CMSDataObjectRequiredMetaType dataObject = new CMSDataObjectRequiredMetaType(); +    DigestAndRefType digestAndRefType = new DigestAndRefType(); +    DigestMethodType digestMethodType = new DigestMethodType(); +    digestMethodType.setAlgorithm("URN:OID:" + digestAlgorithmID.getAlgorithm().getID()); +    digestAndRefType.setDigestMethod(digestMethodType); +    digestAndRefType.setDigestValue(digestValue); +    dataObject.setDigestAndRef(digestAndRefType); +    MetaInfoType metaInfoType = new MetaInfoType(); +    metaInfoType.setMimeType("text/plain"); +    dataObject.setMetaInfo(metaInfoType); + +    Signature signature = new Signature(dataObject, "detached", stal.getCert(), new Date(), null, true); +    byte[] cmsSignature = signature.sign(stal, "SecureSignatureKeypair"); +     +    SignedData signedData = new SignedData(new ByteArrayInputStream(cmsSignature)); +    signedData.setContent(plaintext); +    assertEquals(ObjectID.pkcs7_data, signedData.getEncapsulatedContentType()); +    SignerInfo[] signerInfos = signedData.getSignerInfos(); +    assertEquals(1, signerInfos.length); +    SignerInfo signerInfo = signerInfos[0]; +    signedData.verify((X509Certificate) stal.getCert()); +    assertEquals(digestAlgorithmID, signerInfo.getDigestAlgorithm()); +    assertEquals(AlgorithmID.sha1WithRSAEncryption, signerInfo.getSignatureAlgorithm()); +     +  } + +  @Test +  public void test() throws URISyntaxException { +     +    String oid = null; +    URI uri = new URI("URN:OID:1.3.14.3.2.26"); +    String scheme = uri.getScheme(); +    if ("URN".equalsIgnoreCase(scheme)) { +      String schemeSpecificPart = uri.getSchemeSpecificPart().toLowerCase(); +      if (schemeSpecificPart.startsWith("oid:")) { +        oid = schemeSpecificPart.substring(4, schemeSpecificPart.length()); +      } +    } +    assertEquals("1.3.14.3.2.26", oid); +     +  } +   +} diff --git a/bkucommon/src/test/java/at/gv/egiz/bku/slcommands/impl/xsect/SignatureTest.java b/bkucommon/src/test/java/at/gv/egiz/bku/slcommands/impl/xsect/SignatureTest.java index 6e5612f6..04cf3552 100644 --- a/bkucommon/src/test/java/at/gv/egiz/bku/slcommands/impl/xsect/SignatureTest.java +++ b/bkucommon/src/test/java/at/gv/egiz/bku/slcommands/impl/xsect/SignatureTest.java @@ -27,7 +27,7 @@ package at.gv.egiz.bku.slcommands.impl.xsect;  import static org.junit.Assert.assertNotNull;  import static org.junit.Assert.assertNull;  import static org.junit.Assert.assertTrue; - +import iaik.asn1.structures.AlgorithmID;  import iaik.xml.crypto.XSecProvider;  import java.io.IOException; @@ -140,6 +140,16 @@ public class SignatureTest {        return DigestMethod.SHA1;      } +    @Override +    public AlgorithmID getSignatureAlgorithmID() { +      return null; +    } + +    @Override +    public AlgorithmID getDigestAlgorithmID() { +      return null; +    } +        }    private static final String RESOURCE_PREFIX = "at/gv/egiz/bku/slcommands/impl/"; diff --git a/bkucommon/src/test/java/at/gv/egiz/stal/dummy/DummySTAL.java b/bkucommon/src/test/java/at/gv/egiz/stal/dummy/DummySTAL.java index 61d0d480..0f054cf0 100644 --- a/bkucommon/src/test/java/at/gv/egiz/stal/dummy/DummySTAL.java +++ b/bkucommon/src/test/java/at/gv/egiz/stal/dummy/DummySTAL.java @@ -36,9 +36,13 @@ import java.util.ArrayList;  import java.util.Enumeration;  import java.util.List; +import javax.xml.crypto.dsig.SignatureMethod; +  import org.slf4j.Logger;  import org.slf4j.LoggerFactory; +import at.gv.egiz.stal.BulkSignRequest; +import at.gv.egiz.stal.BulkSignResponse;  import at.gv.egiz.stal.ErrorResponse;  import at.gv.egiz.stal.InfoboxReadRequest;  import at.gv.egiz.stal.InfoboxReadResponse; @@ -47,6 +51,7 @@ import at.gv.egiz.stal.STALRequest;  import at.gv.egiz.stal.STALResponse;  import at.gv.egiz.stal.SignRequest;  import at.gv.egiz.stal.SignResponse; +import iaik.xml.crypto.XmldsigMore;  public class DummySTAL implements STAL {  @@ -58,11 +63,9 @@ public class DummySTAL implements STAL {    public DummySTAL() {      try {        KeyStore ks = KeyStore.getInstance("pkcs12"); -      InputStream ksStream = getClass().getClassLoader().getResourceAsStream( -      "at/gv/egiz/bku/slcommands/impl/Cert.p12"); +      InputStream ksStream = getClass().getClassLoader().getResourceAsStream("at/gv/egiz/bku/slcommands/impl/Cert.p12");        ks.load(ksStream, "1622".toCharArray()); -      for (Enumeration<String> aliases = ks.aliases(); aliases -          .hasMoreElements();) { +      for (Enumeration<String> aliases = ks.aliases(); aliases.hasMoreElements();) {          String alias = aliases.nextElement();          log.debug("Found alias " + alias + " in keystore");          if (ks.isKeyEntry(alias)) { @@ -78,25 +81,28 @@ public class DummySTAL implements STAL {    } +  public X509Certificate getCert() { +    return cert; +  } +    @Override    public List<STALResponse> handleRequest(List<? extends STALRequest> requestList) {      List<STALResponse> responses = new ArrayList<STALResponse>();      for (STALRequest request : requestList) { -      log.debug("Got STALRequest " + request + "."); +      log.info("Got STALRequest " + request + ".");        if (request instanceof InfoboxReadRequest) { -        String infoboxIdentifier = ((InfoboxReadRequest) request) -            .getInfoboxIdentifier(); +        String infoboxIdentifier = ((InfoboxReadRequest) request).getInfoboxIdentifier();          InputStream stream = getClass().getClassLoader().getResourceAsStream(              "at/gv/egiz/stal/dummy/infoboxes4/" + infoboxIdentifier + ".bin");          STALResponse response;          if (stream != null) { -          log.debug("Infobox " + infoboxIdentifier + " found."); +          log.info("Infobox " + infoboxIdentifier + " found.");            byte[] infobox;            try { @@ -114,7 +120,8 @@ public class DummySTAL implements STAL {            infoboxReadResponse.setInfoboxValue(infobox);            response = infoboxReadResponse; -        } else if ((infoboxIdentifier.equals("SecureSignatureKeypair")) ||(infoboxIdentifier.equals("CertifiedKeypair"))) { +        } else if ((infoboxIdentifier.equals("SecureSignatureKeypair")) +            || (infoboxIdentifier.equals("CertifiedKeypair"))) {            try {              InfoboxReadResponse infoboxReadResponse = new InfoboxReadResponse();              infoboxReadResponse.setInfoboxValue(cert.getEncoded()); @@ -135,7 +142,13 @@ public class DummySTAL implements STAL {          try {            SignRequest signReq = (SignRequest) request; -          Signature s = Signature.getInstance("SHA1withRSA"); +          String signatureMethod = ((SignRequest) request).getSignatureMethod(); +          Signature s = null; +          if (SignatureMethod.RSA_SHA1.equals(signatureMethod)) { +            s = Signature.getInstance("SHA1withRSA"); +          } else if (XmldsigMore.SIGNATURE_RSA_SHA256.equals(signatureMethod)) { +            s = Signature.getInstance("SHA256withRSA");  +          }            s.initSign(privateKey);            s.update(signReq.getSignedInfo().getValue());            byte[] sigVal = s.sign(); @@ -147,7 +160,37 @@ public class DummySTAL implements STAL {            responses.add(new ErrorResponse());          } -      } else { +      } + +      //dummy handler for BulkSignRequest +      else if (request instanceof BulkSignRequest) { + +        try { +          BulkSignRequest bulkSignReq = (BulkSignRequest) request; + +          BulkSignResponse bulkSignResp = new BulkSignResponse(); + +          for (int i = 0; i < bulkSignReq.getSignRequests().size(); i++) { + +            Signature s = Signature.getInstance("SHA1withRSA"); +            s.initSign(privateKey); +            s.update(bulkSignReq.getSignRequests().get(i).getSignedInfo().getValue()); +            byte[] sigVal = s.sign(); +            SignResponse resp = new SignResponse(); +            resp.setSignatureValue(sigVal); +            bulkSignResp.getSignResponse().add(resp); +          } + +          responses.add(bulkSignResp); + +        } catch (Exception e) { +          log.error("Failed to create signature.", e); +          responses.add(new ErrorResponse()); +        } + +      } + +      else {          log.debug("Request not implemented."); diff --git a/bkucommon/src/test/resources/at/gv/egiz/bku/slcommands/bulksignaturerequest/BulkSignatureRequest.xml b/bkucommon/src/test/resources/at/gv/egiz/bku/slcommands/bulksignaturerequest/BulkSignatureRequest.xml new file mode 100644 index 00000000..7fa39f57 --- /dev/null +++ b/bkucommon/src/test/resources/at/gv/egiz/bku/slcommands/bulksignaturerequest/BulkSignatureRequest.xml @@ -0,0 +1,34 @@ +<?xml version="1.0" encoding="UTF-8"?> +<sl:BulkRequest +	xmlns:sl="http://www.buergerkarte.at/namespaces/securitylayer/1.2#" > +	<sl:CreateSignatureRequest displayName="Urlaubsantrag "Rössler""> +		<sl:CreateCMSSignatureRequest Structure="detached"> +			<sl:KeyboxIdentifier>SecureSignatureKeypair</sl:KeyboxIdentifier> +			<sl:DataObject> +				<sl:MetaInfo> +					<sl:MimeType>text/plain</sl:MimeType> +				</sl:MetaInfo> +				<sl:Content Reference=""> +					<sl:Base64Content>QW5kIG5vdyB0byBzb21ldGhpbmcgY29tcGxldGx5IGRpZmZlcmVudA== +					</sl:Base64Content> +				</sl:Content> +			</sl:DataObject> +		</sl:CreateCMSSignatureRequest> +	</sl:CreateSignatureRequest> +	<sl:CreateSignatureRequest displayName="Krankmeldung "Meyer""> +		<sl:CreateCMSSignatureRequest +			xmlns:sl="http://www.buergerkarte.at/namespaces/securitylayer/1.2#" +			Structure="detached"> +			<sl:KeyboxIdentifier>SecureSignatureKeypair</sl:KeyboxIdentifier> +			<sl:DataObject> +				<sl:MetaInfo> +					<sl:MimeType>text/plain</sl:MimeType> +				</sl:MetaInfo> +				<sl:Content Reference=""> +					<sl:Base64Content>Vm9uIGRlciBTaWduYXR1ciB1bXNjaGxvc3NlbmUgRGF0ZW4u +					</sl:Base64Content> +				</sl:Content> +			</sl:DataObject> +		</sl:CreateCMSSignatureRequest> +	</sl:CreateSignatureRequest> +</sl:BulkRequest>
\ No newline at end of file diff --git a/bkucommon/src/test/resources/at/gv/egiz/bku/slcommands/bulksignaturerequest/BulkSignatureRequestWithReference.xml b/bkucommon/src/test/resources/at/gv/egiz/bku/slcommands/bulksignaturerequest/BulkSignatureRequestWithReference.xml new file mode 100644 index 00000000..a506d50c --- /dev/null +++ b/bkucommon/src/test/resources/at/gv/egiz/bku/slcommands/bulksignaturerequest/BulkSignatureRequestWithReference.xml @@ -0,0 +1,37 @@ +<?xml version="1.0" encoding="UTF-8"?> +<sl:BulkRequest +	xmlns:sl="http://www.buergerkarte.at/namespaces/securitylayer/1.2#" +	xmlns:dsig="http://www.w3.org/2000/09/xmldsig#" > +	<sl:CreateSignatureRequest displayName="Urlaubsantrag "Rössler""> +    <sl:CreateCMSSignatureRequest +      xmlns:sl="http://www.buergerkarte.at/namespaces/securitylayer/1.2#" +      Structure="detached"> +      <sl:KeyboxIdentifier>SecureSignatureKeypair</sl:KeyboxIdentifier> +      <sl:ReferenceObject> +        <sl:MetaInfo> +          <sl:MimeType>text/plain</sl:MimeType> +        </sl:MetaInfo> +       <sl:DigestAndRef> +           <dsig:DigestMethod Algorithm="urn:oid:1.3.14.3.2.26"/>  +           <dsig:DigestValue>j6lwx3rvEPO0vKtMup4NbeVu8nk=</dsig:DigestValue>  +       </sl:DigestAndRef> +      </sl:ReferenceObject> +    </sl:CreateCMSSignatureRequest> +	</sl:CreateSignatureRequest> +	<sl:CreateSignatureRequest displayName="Krankmeldung "Meyer""> +		<sl:CreateCMSSignatureRequest +			xmlns:sl="http://www.buergerkarte.at/namespaces/securitylayer/1.2#" +			Structure="detached"> +			<sl:KeyboxIdentifier>SecureSignatureKeypair</sl:KeyboxIdentifier> +			<sl:ReferenceObject> +				<sl:MetaInfo> +					<sl:MimeType>text/plain</sl:MimeType>heis +				</sl:MetaInfo> +       <sl:DigestAndRef> +           <dsig:DigestMethod Algorithm="urn:oid:1.3.14.3.2.26"/>  +           <dsig:DigestValue>j6lwx3rvEPO0vKtMup4NbeVu8nk=</dsig:DigestValue>  +       </sl:DigestAndRef> +			</sl:ReferenceObject> +		</sl:CreateCMSSignatureRequest> +	</sl:CreateSignatureRequest> +</sl:BulkRequest>
\ No newline at end of file diff --git a/bkucommon/src/test/resources/at/gv/egiz/bku/slcommands/testApplicationContext.xml b/bkucommon/src/test/resources/at/gv/egiz/bku/slcommands/testApplicationContext.xml index fffabb47..9a76291c 100644 --- a/bkucommon/src/test/resources/at/gv/egiz/bku/slcommands/testApplicationContext.xml +++ b/bkucommon/src/test/resources/at/gv/egiz/bku/slcommands/testApplicationContext.xml @@ -119,6 +119,14 @@        value="http://www.buergerkarte.at/namespaces/securitylayer/1.2#" />      <constructor-arg value="CreateCMSSignatureRequest" />    </bean> +    <bean id="bulkCommandFactory" +    class="at.gv.egiz.bku.slcommands.impl.BulkCommandFactory" +    parent="abstractCommandFactory" /> +  <bean id="bulkRequest" class="javax.xml.namespace.QName"> +    <constructor-arg +      value="http://www.buergerkarte.at/namespaces/securitylayer/1.2#" /> +    <constructor-arg value="BulkRequest"/> +  </bean>    <bean id="getStatusCommandFactory" class="at.gv.egiz.bku.slcommands.impl.GetStatusCommandFactory"      parent="abstractCommandFactory" />    <bean id="getStatusRequest" class="javax.xml.namespace.QName"> @@ -136,6 +144,7 @@          <entry key-ref="infoboxUpdateRequest" value-ref="infoboxUpdateCommandFactory" />          <entry key-ref="createXMLSignatureRequest" value-ref="createXMLSignatureCommandFactory" />          <entry key-ref="createCMSSignatureRequest" value-ref="createCMSSignatureCommandFactory" /> +        <entry key-ref="bulkRequest" value-ref="bulkCommandFactory" />          <entry key-ref="getStatusRequest" value-ref="getStatusCommandFactory" />        </map>      </property> | 
