diff options
Diffstat (limited to 'smccSTAL')
10 files changed, 783 insertions, 0 deletions
diff --git a/smccSTAL/pom.xml b/smccSTAL/pom.xml new file mode 100644 index 00000000..4af8c6de --- /dev/null +++ b/smccSTAL/pom.xml @@ -0,0 +1,40 @@ +<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + <parent> + <artifactId>bku</artifactId> + <groupId>at.gv.egiz</groupId> + <version>1.0-SNAPSHOT</version> + </parent> + <modelVersion>4.0.0</modelVersion> + <groupId>at.gv.egiz</groupId> + <artifactId>smccSTAL</artifactId> + <name>smcc STAL</name> + <version>1.0-SNAPSHOT</version> + <description />
+ <dependencies>
+ <dependency>
+ <groupId>at.gv.egiz</groupId>
+ <artifactId>STAL</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>at.gv.egiz</groupId>
+ <artifactId>smcc</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>at.gv.egiz</groupId>
+ <artifactId>BKUCommonGUI</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>iaik</groupId>
+ <artifactId>iaik_jce_me4se</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>commons-logging</groupId>
+ <artifactId>commons-logging</artifactId>
+ </dependency>
+ </dependencies> +</project>
\ No newline at end of file diff --git a/smccSTAL/src/main/java/META-INF/MANIFEST.MF b/smccSTAL/src/main/java/META-INF/MANIFEST.MF new file mode 100644 index 00000000..5e949512 --- /dev/null +++ b/smccSTAL/src/main/java/META-INF/MANIFEST.MF @@ -0,0 +1,3 @@ +Manifest-Version: 1.0
+Class-Path:
+
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();
+ }
+}
diff --git a/smccSTAL/src/test/java/at/gv/egiz/smcc/ASN1Test.java b/smccSTAL/src/test/java/at/gv/egiz/smcc/ASN1Test.java new file mode 100644 index 00000000..f2d61e7f --- /dev/null +++ b/smccSTAL/src/test/java/at/gv/egiz/smcc/ASN1Test.java @@ -0,0 +1,105 @@ +/* +* 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.smcc;
+
+import iaik.me.asn1.ASN1;
+import iaik.me.utils.Base64;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.Vector;
+
+import org.junit.Ignore;
+
+@Ignore
+public class ASN1Test {
+
+ public static void main(String[] args) throws IOException {
+
+ ClassLoader classLoader = ASN1Test.class.getClassLoader();
+
+ InputStream stream = classLoader.getResourceAsStream("IdentityLink.bin");
+
+ if (stream != null) {
+
+ ASN1 identityLink = new ASN1(stream);
+ System.out.println("BaseId:" + getBaseId(identityLink));
+ identityLink = replaceBaseId(identityLink, "test");
+ System.out.println("BaseId:" + getBaseId(identityLink));
+
+ String bpk = "hansi";
+ MessageDigest sha = null;
+ try {
+ sha = MessageDigest.getInstance("SHA");
+ } catch (NoSuchAlgorithmException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ sha.update((identityLink + "+" + bpk).getBytes());
+ String bpkStr = new String(Base64.encode(sha.digest()));
+ System.out.println("bpk: "+bpkStr);
+ identityLink = replaceBaseId(identityLink, bpkStr);
+ System.out.println(getBaseId(identityLink));
+
+ } else {
+ System.out.println("Not found.");
+ }
+
+ }
+
+ 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;
+
+ }
+
+}
|