diff options
| author | mcentner <mcentner@8a26b1a7-26f0-462f-b9ef-d0e30c41f5a4> | 2008-08-29 12:11:34 +0000 | 
|---|---|---|
| committer | mcentner <mcentner@8a26b1a7-26f0-462f-b9ef-d0e30c41f5a4> | 2008-08-29 12:11:34 +0000 | 
| commit | 32d17447a258188b2d534bcb0bf65a659ba7b7d0 (patch) | |
| tree | 4ad8bb267eb29f7091a7da283f6d7eec1e2188e1 /smccSTAL/src/main/java/at | |
| download | mocca-32d17447a258188b2d534bcb0bf65a659ba7b7d0.tar.gz mocca-32d17447a258188b2d534bcb0bf65a659ba7b7d0.tar.bz2 mocca-32d17447a258188b2d534bcb0bf65a659ba7b7d0.zip | |
Initial import.
git-svn-id: https://joinup.ec.europa.eu/svn/mocca/trunk@1 8a26b1a7-26f0-462f-b9ef-d0e30c41f5a4
Diffstat (limited to 'smccSTAL/src/main/java/at')
7 files changed, 635 insertions, 0 deletions
| diff --git a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractRequestHandler.java b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractRequestHandler.java new file mode 100644 index 00000000..e5afa478 --- /dev/null +++ b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractRequestHandler.java @@ -0,0 +1,86 @@ +/* +* Copyright 2008 Federal Chancellery Austria and +* Graz University of Technology +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +*     http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package at.gv.egiz.bku.smccstal;
 +
 +import java.awt.event.ActionEvent;
 +import java.awt.event.ActionListener;
 +
 +import org.apache.commons.logging.Log;
 +import org.apache.commons.logging.LogFactory;
 +
 +import at.gv.egiz.bku.gui.BKUGUIFacade;
 +import at.gv.egiz.smcc.PINProvider;
 +import at.gv.egiz.smcc.SignatureCard;
 +import at.gv.egiz.stal.STALRequest;
 +import at.gv.egiz.stal.STALResponse;
 +
 +public abstract class AbstractRequestHandler implements SMCCSTALRequestHandler,
 +    ActionListener {
 +  private final static Log log = LogFactory
 +      .getLog(AbstractRequestHandler.class);
 +
 +  protected SignatureCard card;
 +  protected BKUGUIFacade gui;
 +  protected static STALMessageConsumer messageConsumer = null;
 +  protected String actionCommand;
 +  protected boolean actionPerformed = false;
 +
 +  @Override
 +  public abstract STALResponse handleRequest(STALRequest request);
 +
 +  @Override
 +  public void init(SignatureCard sc, BKUGUIFacade gui) {
 +    if ((sc == null) || (gui == null)) {
 +      throw new NullPointerException("Parameter must not be set to null");
 +    }
 +    this.card = sc;
 +    this.gui = gui;
 +  }
 +  
 +  public static void setMessageConsumer(STALMessageConsumer messageConsumer) {
 +    AbstractRequestHandler.messageConsumer = messageConsumer;
 +  }
 +
 +  protected static void newSTALMessage(String caption, String message) {
 +    if (messageConsumer != null) {
 +      messageConsumer.consumeNewSTALMessage(caption, message);
 +    }
 +  }
 +
 +  protected synchronized void waitForAction() {
 +    try {
 +      while (!actionPerformed) {
 +        wait();
 +      }
 +    } catch (InterruptedException e) {
 +      log.info(e);
 +    }
 +    actionPerformed = false;
 +  }
 +
 +  private synchronized void actionPerformed() {
 +    actionPerformed = true;
 +    notifyAll();
 +  }
 +  
 +  @Override
 +  public void actionPerformed(ActionEvent e) {
 +    actionCommand = e.getActionCommand();
 +    actionPerformed();
 +  }
 +
 +}
 diff --git a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractSMCCSTAL.java b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractSMCCSTAL.java new file mode 100644 index 00000000..7bd9e264 --- /dev/null +++ b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractSMCCSTAL.java @@ -0,0 +1,116 @@ +/* +* Copyright 2008 Federal Chancellery Austria and +* Graz University of Technology +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +*     http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package at.gv.egiz.bku.smccstal;
 +
 +import java.util.ArrayList;
 +import java.util.HashMap;
 +import java.util.List;
 +import java.util.Locale;
 +import java.util.Map;
 +
 +import org.apache.commons.logging.Log;
 +import org.apache.commons.logging.LogFactory;
 +
 +import at.gv.egiz.bku.gui.BKUGUIFacade;
 +import at.gv.egiz.smcc.PINProvider;
 +import at.gv.egiz.smcc.SignatureCard;
 +import at.gv.egiz.smcc.util.SMCCHelper;
 +import at.gv.egiz.stal.ErrorResponse;
 +import at.gv.egiz.stal.InfoboxReadRequest;
 +import at.gv.egiz.stal.STAL;
 +import at.gv.egiz.stal.STALRequest;
 +import at.gv.egiz.stal.STALResponse;
 +import at.gv.egiz.stal.SignRequest;
 +
 +public abstract class AbstractSMCCSTAL implements STAL {
 +  private static Log log = LogFactory.getLog(AbstractSMCCSTAL.class);
 +
 +  protected Locale locale = Locale.getDefault();
 +  protected SMCCHelper smccHelper = new SMCCHelper();
 +  protected SignatureCard signatureCard = null;
 +  protected static Map<String, SMCCSTALRequestHandler> handlerMap = new HashMap<String, SMCCSTALRequestHandler>();
 +
 +  static {
 +    addRequestHandler(InfoboxReadRequest.class, new InfoBoxReadRequestHandler());
 +    addRequestHandler(SignRequest.class, new SignRequestHandler());
 +  }
 +
 +  public AbstractSMCCSTAL() {
 +  }
 +
 +  /**
 +   * Implementations must assign the signature card within this method.
 +   * 
 +   * @return if the user canceled
 +   */
 +  protected abstract boolean waitForCard();
 +
 +  protected abstract BKUGUIFacade getGUI();
 +
 +  @Override
 +  public List<STALResponse> handleRequest(
 +      List<STALRequest> requestList) {
 +    log.debug("Got request list containing " + requestList.size()
 +        + " STAL requests");
 +    List<STALResponse> responseList = new ArrayList<STALResponse>(requestList
 +        .size());
 +    for (STALRequest request : requestList) {
 +      log.info("Processing: " + request);
 +      SMCCSTALRequestHandler handler = null;
 +      handler = handlerMap.get(request.getClass().getSimpleName());
 +      if (handler != null) {
 +        if (handler.requireCard()) {
 +          if (waitForCard()) {
 +            responseList.add(new ErrorResponse(6001));
 +            break;
 +          }
 +        }
 +        try {
 +          handler = handler.newInstance();
 +          handler.init(signatureCard, getGUI());
 +          responseList.add(handler.handleRequest(request));
 +        } catch (Exception e) {
 +          log.info("Error while handling STAL request:" + e);
 +          responseList.add(new ErrorResponse(6000));
 +        }
 +      } else {
 +        log.error("Cannot find a handler for STAL request: " + request);
 +        responseList.add(new ErrorResponse());
 +      }
 +    }
 +    return responseList;
 +  }
 +
 +  public static void addRequestHandler(Class<? extends STALRequest> id,
 +      SMCCSTALRequestHandler handler) {
 +    log.debug("Registering STAL request handler: " + id.getSimpleName());
 +    handlerMap.put(id.getSimpleName(), handler);
 +  }
 +
 +  public static SMCCSTALRequestHandler getRequestHandler(
 +      Class<? extends STALRequest> request) {
 +    return handlerMap.get(request.getSimpleName());
 +  }
 +
 +  @Override
 +  public void setLocale(Locale locale) {
 +    if (locale == null) {
 +      throw new NullPointerException("Locale must not be set to null");
 +    }
 +    this.locale = locale;
 +  }
 +}
 diff --git a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/DomainIdConverter.java b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/DomainIdConverter.java new file mode 100644 index 00000000..3a564b91 --- /dev/null +++ b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/DomainIdConverter.java @@ -0,0 +1,85 @@ +/* +* Copyright 2008 Federal Chancellery Austria and +* Graz University of Technology +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +*     http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package at.gv.egiz.bku.smccstal;
 +
 +import iaik.me.asn1.ASN1;
 +import iaik.me.utils.Base64;
 +
 +import java.io.IOException;
 +import java.security.MessageDigest;
 +import java.security.NoSuchAlgorithmException;
 +import java.util.Vector;
 +
 +public class DomainIdConverter {
 +
 +  private static String getBaseId(ASN1 identityLink) throws IOException {
 +
 +    if (identityLink.getType() == ASN1.TYPE_SEQUENCE) {
 +      ASN1 personData = identityLink.getElementAt(4);
 +      if (personData.getType() == ASN1.TAG_CONTEXT_SPECIFIC) {
 +        ASN1 physicalPersonData = personData.gvASN1();
 +        ASN1 baseId = physicalPersonData.getElementAt(0);
 +        return baseId.gvString();
 +      }
 +      throw new IOException("Invalid structure.");
 +
 +    }
 +    throw new IOException("Invalid structure.");
 +
 +  }
 +
 +  private static ASN1 replaceBaseId(ASN1 identityLink, String newBaseId)
 +      throws IOException {
 +
 +    ASN1 newIdentityLink = new ASN1(ASN1.TYPE_SEQUENCE, new Vector<ASN1>());
 +    for (int i = 0; i < identityLink.getSize(); i++) {
 +      ASN1 asn1 = identityLink.getElementAt(i);
 +      if (i == 4 && asn1.getType() == ASN1.TAG_CONTEXT_SPECIFIC) {
 +        ASN1 physicalPersonData = asn1.gvASN1();
 +        ASN1 newPhysicalPersonData = new ASN1(ASN1.TYPE_SEQUENCE,
 +            new Vector<ASN1>());
 +        newPhysicalPersonData.addElement(new ASN1(ASN1.TYPE_UTF8_STRING,
 +            newBaseId));
 +        for (int j = 1; j < physicalPersonData.getSize(); j++) {
 +          newPhysicalPersonData.addElement(physicalPersonData.getElementAt(j));
 +        }
 +        asn1 = new ASN1(ASN1.TAG_CONTEXT_SPECIFIC, newPhysicalPersonData);
 +      }
 +      newIdentityLink.addElement(asn1);
 +    }
 +    return newIdentityLink;
 +
 +  }
 +
 +  public static byte[] convertDomainId(byte[] data, String domainId)
 +      throws IOException, NoSuchAlgorithmException {
 +    if (domainId == null) {
 +      return data;
 +    }
 +    ASN1 identityLink = new ASN1(data);
 +    MessageDigest sha = null;
 +    sha = MessageDigest.getInstance("SHA");
 +    String base = getBaseId(identityLink);
 +    sha.update((base + "+" + domainId).getBytes());
 +    String bpkStr = new String(Base64.encode(sha.digest()));
 +    bpkStr = bpkStr.trim();
 +    identityLink = replaceBaseId(identityLink, bpkStr);
 +    System.out.println(getBaseId(identityLink));
 +    return identityLink.getEncoded();
 +  }
 +
 +}
 diff --git a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/InfoBoxReadRequestHandler.java b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/InfoBoxReadRequestHandler.java new file mode 100644 index 00000000..7dc2e202 --- /dev/null +++ b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/InfoBoxReadRequestHandler.java @@ -0,0 +1,140 @@ +/* +* Copyright 2008 Federal Chancellery Austria and +* Graz University of Technology +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +*     http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package at.gv.egiz.bku.smccstal;
 +
 +import org.apache.commons.logging.Log;
 +import org.apache.commons.logging.LogFactory;
 +
 +import at.gv.egiz.smcc.CancelledException;
 +import at.gv.egiz.smcc.PINProvider;
 +import at.gv.egiz.smcc.PINSpec;
 +import at.gv.egiz.smcc.SignatureCard;
 +import at.gv.egiz.smcc.SignatureCardException;
 +import at.gv.egiz.stal.ErrorResponse;
 +import at.gv.egiz.stal.InfoboxReadRequest;
 +import at.gv.egiz.stal.InfoboxReadResponse;
 +import at.gv.egiz.stal.STALRequest;
 +import at.gv.egiz.stal.STALResponse;
 +
 +public class InfoBoxReadRequestHandler extends AbstractRequestHandler implements
 +    PINProvider {
 +
 +  private static Log log = LogFactory.getLog(InfoBoxReadRequestHandler.class);
 +
 +  private int retryCounter = 0;
 +
 +  @Override
 +  public STALResponse handleRequest(STALRequest request) {
 +    if (request instanceof InfoboxReadRequest) {
 +      InfoboxReadRequest infoBox = (InfoboxReadRequest) request;
 +      try {
 +        if (infoBox.getInfoboxIdentifier().equals("IdentityLink")) {
 +          newSTALMessage("Message.RequestCaption", "Message.IdentityLink");
 +          log.debug("Handling identitylink infobox");
 +          byte[] resp = card.getInfobox(infoBox.getInfoboxIdentifier(), this,
 +              infoBox.getDomainIdentifier());
 +          if (resp == null) {
 +            log.info("Got null as result->user cancelled");
 +            return new ErrorResponse(6001);
 +          } else {
 +            try {
 +              resp = DomainIdConverter.convertDomainId(resp, infoBox
 +                  .getDomainIdentifier());
 +            } catch (Exception e) {
 +              log.error("Cannot convert domain specific id", e);
 +              return new ErrorResponse(1000);
 +            }
 +          }
 +          InfoboxReadResponse stalResp = new InfoboxReadResponse();
 +          stalResp.setInfoboxValue(resp);
 +          return stalResp;
 +        } else if (SignatureCard.KeyboxName.CERITIFIED_KEYPAIR.equals(infoBox
 +            .getInfoboxIdentifier())) {
 +          newSTALMessage("Message.RequestCaption", "Message.CertifiedKeypair");
 +          log.debug("Handling certified keypair infobox");
 +          byte[] resp = card
 +              .getCertificate(SignatureCard.KeyboxName.CERITIFIED_KEYPAIR);
 +          if (resp == null) {
 +            return new ErrorResponse(6001);
 +          }
 +          InfoboxReadResponse stalResp = new InfoboxReadResponse();
 +          stalResp.setInfoboxValue(resp);
 +          return stalResp;
 +        } else if (SignatureCard.KeyboxName.SECURE_SIGNATURE_KEYPAIR
 +            .equals(infoBox.getInfoboxIdentifier())) {
 +          newSTALMessage("Message.RequestCaption",
 +              "Message.SecureSignatureKeypair");
 +          log.debug("Handling secure signature keypair infobox");
 +          byte[] resp = card
 +              .getCertificate(SignatureCard.KeyboxName.SECURE_SIGNATURE_KEYPAIR);
 +          if (resp == null) {
 +            return new ErrorResponse(6001);
 +          }
 +          InfoboxReadResponse stalResp = new InfoboxReadResponse();
 +          stalResp.setInfoboxValue(resp);
 +          return stalResp;
 +        } else {
 +          newSTALMessage("Message.RequestCaption", "Message.InfoboxReadRequest");
 +          log.warn("Unknown infobox identifier: "
 +              + infoBox.getInfoboxIdentifier() + " trying generic request");
 +          byte[] resp = card.getInfobox(infoBox.getInfoboxIdentifier(), this,
 +              infoBox.getDomainIdentifier());
 +          if (resp == null) {
 +            return new ErrorResponse(6001);
 +          }
 +          InfoboxReadResponse stalResp = new InfoboxReadResponse();
 +          stalResp.setInfoboxValue(resp);
 +          return stalResp;
 +        }
 +      } catch (CancelledException cx) {
 +        log.debug("User cancelled request", cx);
 +        return new ErrorResponse(6001);
 +      } catch (SignatureCardException e) {
 +        log.info("Error while reading infobox: " + e);
 +        return new ErrorResponse(4000);
 +      }
 +    } else {
 +      log.fatal("Got unexpected STAL request: " + request);
 +      return new ErrorResponse(1000);
 +    }
 +  }
 +
 +  @Override
 +  public boolean requireCard() {
 +    return true;
 +  }
 +
 +  @Override
 +  public String providePIN(PINSpec spec, int retries) {
 +    if (retryCounter++ > 0) {
 +      log.info("PIN wrong retrying ...");
 +      gui.showCardPINRetryDialog(spec, retries, this, "ok", this, "cancel");
 +    } else {
 +      gui.showCardPINDialog(spec, this, "ok", this, "cancel");
 +    }
 +    waitForAction();
 +    if (actionCommand.equals("cancel")) {
 +      return null;
 +    }
 +    return new String(gui.getPin());
 +  }
 +
 +  @Override
 +  public SMCCSTALRequestHandler newInstance() {
 +    return new InfoBoxReadRequestHandler();
 +  }
 +}
 diff --git a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/SMCCSTALRequestHandler.java b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/SMCCSTALRequestHandler.java new file mode 100644 index 00000000..7badb2a0 --- /dev/null +++ b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/SMCCSTALRequestHandler.java @@ -0,0 +1,36 @@ +/* +* Copyright 2008 Federal Chancellery Austria and +* Graz University of Technology +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +*     http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package at.gv.egiz.bku.smccstal;
 +
 +
 +import at.gv.egiz.bku.gui.BKUGUIFacade;
 +import at.gv.egiz.smcc.PINProvider;
 +import at.gv.egiz.smcc.SignatureCard;
 +import at.gv.egiz.stal.STALRequest;
 +import at.gv.egiz.stal.STALResponse;
 +
 +public interface SMCCSTALRequestHandler {
 +  
 +  public void init(SignatureCard sc, BKUGUIFacade gui);
 +  
 +  public STALResponse handleRequest(STALRequest request);
 +  
 +  public boolean requireCard();
 +  
 +  public SMCCSTALRequestHandler newInstance();
 +
 +}
 diff --git a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/STALMessageConsumer.java b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/STALMessageConsumer.java new file mode 100644 index 00000000..7d7a6ec0 --- /dev/null +++ b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/STALMessageConsumer.java @@ -0,0 +1,21 @@ +/* +* Copyright 2008 Federal Chancellery Austria and +* Graz University of Technology +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +*     http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package at.gv.egiz.bku.smccstal;
 +
 +public interface STALMessageConsumer {
 +  public void consumeNewSTALMessage(String captionId, String messageId);
 +}
 diff --git a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/SignRequestHandler.java b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/SignRequestHandler.java new file mode 100644 index 00000000..6ae4fa01 --- /dev/null +++ b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/SignRequestHandler.java @@ -0,0 +1,151 @@ +/* +* Copyright 2008 Federal Chancellery Austria and +* Graz University of Technology +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +*     http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package at.gv.egiz.bku.smccstal;
 +
 +import java.io.ByteArrayInputStream;
 +import java.io.InputStream;
 +import java.security.MessageDigest;
 +import java.security.NoSuchAlgorithmException;
 +
 +import javax.xml.bind.JAXBContext;
 +import javax.xml.bind.JAXBElement;
 +import javax.xml.bind.JAXBException;
 +import javax.xml.bind.Unmarshaller;
 +
 +import org.apache.commons.logging.Log;
 +import org.apache.commons.logging.LogFactory;
 +
 +import at.gv.egiz.smcc.CancelledException;
 +import at.gv.egiz.smcc.PINProvider;
 +import at.gv.egiz.smcc.PINSpec;
 +import at.gv.egiz.smcc.SignatureCard;
 +import at.gv.egiz.smcc.SignatureCardException;
 +import at.gv.egiz.smcc.SignatureCard.KeyboxName;
 +import at.gv.egiz.stal.ErrorResponse;
 +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 at.gv.egiz.stal.signedinfo.ObjectFactory;
 +import at.gv.egiz.stal.signedinfo.SignedInfoType;
 +import at.gv.egiz.stal.util.JCEAlgorithmNames;
 +
 +public class SignRequestHandler extends AbstractRequestHandler implements
 +    PINProvider {
 +  private static Log log = LogFactory.getLog(SignRequestHandler.class);
 +
 +  private static JAXBContext jaxbContext;
 +
 +  static {
 +    try {
 +      jaxbContext = JAXBContext.newInstance(ObjectFactory.class.getPackage()
 +          .getName());
 +    } catch (JAXBException e) {
 +      log.fatal("Cannot init jaxbContext", e);
 +    }
 +  }
 +
 +  private int retryCounter = 0;
 +
 +  public SignRequestHandler() {
 +  }
 +
 +  @SuppressWarnings("unchecked")
 +  @Override
 +  public STALResponse handleRequest(STALRequest request) {
 +    if (request instanceof SignRequest) {
 +      SignRequest signReq = (SignRequest) request;
 +      newSTALMessage("Message.RequestCaption", "Message.SignRequest");
 +      try {
 +        Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
 +        InputStream is = new ByteArrayInputStream(signReq.getSignedInfo());
 +        JAXBElement<SignedInfoType> signedInfo = (JAXBElement<SignedInfoType>) unmarshaller
 +            .unmarshal(is);
 +        String signatureMethod = signedInfo.getValue().getSignatureMethod()
 +            .getAlgorithm();
 +        log.debug("Found signature method: " + signatureMethod);
 +        String jceName = JCEAlgorithmNames.getJCEHashName(signatureMethod);
 +        if (jceName == null) {
 +          log.error("Hash algorithm not supported:");
 +          return new ErrorResponse(1000);
 +        }
 +        MessageDigest md = MessageDigest.getInstance(jceName);
 +        md.update(signReq.getSignedInfo());
 +        KeyboxName kb = SignatureCard.KeyboxName.getKeyboxName(signReq
 +            .getKeyIdentifier());
 +        byte[] resp = card.createSignature(md.digest(), kb, this);
 +        if (resp == null) {
 +          return new ErrorResponse(6001);
 +        }
 +        SignResponse stalResp = new SignResponse();
 +        stalResp.setSignatureValue(resp);
 +        return stalResp;
 +      } catch (CancelledException cx) {
 +        log.debug("User cancelled request");
 +        return new ErrorResponse(6001);
 +      } catch (SignatureCardException e) {
 +        log.error("Error while creating signature: " + e);
 +        return new ErrorResponse(4000);
 +      } catch (JAXBException e) {
 +        log.error("Cannot unmarshall signed info", e);
 +        return new ErrorResponse(1000);
 +      } catch (NoSuchAlgorithmException e) {
 +        log.error(e);
 +        return new ErrorResponse(1000);
 +      }
 +    } else {
 +      log.fatal("Got unexpected STAL request: " + request);
 +      return new ErrorResponse(1000);
 +    }
 +  }
 +
 +  @Override
 +  public boolean requireCard() {
 +    return true;
 +  }
 +
 +  @Override
 +  public String providePIN(PINSpec spec, int retries) {
 +    if (retryCounter++ > 0) {
 +      log.info("PIN wrong retrying ...");
 +      gui.showSignaturePINRetryDialog(spec, retries, this, "sign", this,
 +          "cancel", this, "hashData");
 +    } else {
 +      gui.showSignaturePINDialog(spec, this, "sign", this, "cancel", this,
 +          "hashData");
 +    }
 +    do {
 +      waitForAction();
 +      if (actionCommand.equals("cancel")) {
 +        return null;
 +      } else if (actionCommand.equals("hashData")) {
 +        // FIXME provide hashdata input
 +        gui.showHashDataInputDialog(null, this, "ok");
 +      } else if (actionCommand.equals("sign")) {
 +        return new String(gui.getPin());
 +      } else if (actionCommand.equals("ok")) {
 +        gui.showSignaturePINDialog(spec, this, "sign", this, "cancel", this,
 +        "hashData"); 
 +      }
 +    } while (true);
 +  }
 +
 +  @Override
 +  public SMCCSTALRequestHandler newInstance() {
 +    return new SignRequestHandler();
 +  }
 +}
 | 
