Java tutorial
/* * MSS Code Factory CFLib 2.1 * * Copyright (c) 2015 Mark Sobkow * * This program is available as free software under the GNU LGPL v3, or * under a commercial license from Mark Sobkow. For commercial licensing * details, please contact msobkow@sasktel.net. * * Under the terms of the LGPL: * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this program. If not, * see http://www.gnu.org/licenses/. */ package net.sourceforge.msscodefactory.cflib.v2_1.CFLib.Tip; import java.io.File; import java.io.PrintStream; import java.net.URL; import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; import java.security.KeyFactory; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; import java.security.PublicKey; import java.security.SecureRandom; import java.security.spec.InvalidKeySpecException; import java.security.spec.X509EncodedKeySpec; import javax.crypto.BadPaddingException; import javax.crypto.Cipher; import javax.crypto.IllegalBlockSizeException; import javax.crypto.NoSuchPaddingException; import javax.crypto.SecretKey; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; import net.sourceforge.msscodefactory.cflib.v2_1.CFLib.*; import org.xml.sax.*; import org.apache.commons.codec.binary.Base64; public class CFTipEnvelopeHandler extends CFLibXmlCoreSaxParser implements ContentHandler { // The namespace URI of the supported schema public final static String SCHEMA_XMLNS = "uri://net.sourceforge.msscodefactory/cftipenvelope"; // The source for loading the supported schema public final static String SCHEMA_URI = "xsd/cftip-envelope.xsd"; public final static String SCHEMA_ROOT_URI = "/xsd/cftip-envelope.xsd"; // Constructors public CFTipEnvelopeHandler() { super(); setRootElementHandler(getSaxRqstRootHandler()); File file = new File(SCHEMA_URI); if (file.exists()) { addSchema(SCHEMA_URI); } else { URL url = getClass().getResource(SCHEMA_ROOT_URI); if (url != null) { addSchema(url.toString()); } } initParser(); } public CFTipEnvelopeHandler(ICFLibMessageLog logger) { super(logger); setRootElementHandler(getSaxRqstRootHandler()); File file = new File(SCHEMA_URI); if (file.exists()) { addSchema(SCHEMA_URI); } else { URL url = getClass().getResource(SCHEMA_ROOT_URI); if (url != null) { addSchema(url.toString()); } } initParser(); } // The Request Handler for the incoming AppRequest and LoginRequest messages private ICFTipRequestHandler requestHandler = null; public ICFTipRequestHandler getRequestHandler() { return (requestHandler); } public void setRequestHandler(ICFTipRequestHandler value) { final String S_ProcName = "setRequestHandler"; if (value == null) { throw CFLib.getDefaultExceptionFactory().newNullArgumentException(getClass(), S_ProcName, 1, "value"); } requestHandler = value; } // Accessors for invoker private String response = ""; public String getResponse() { return (response); } void setResponse(String str) { if (str == null) { response = ""; } else { response = str; } } // Server Information private CFTipServerInfo serverInfo = null; public CFTipServerInfo getServerInfo() { return (serverInfo); } public void setServerInfo(CFTipServerInfo value) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, IllegalBlockSizeException { final String S_ProcName = "setServerInfo"; if (value == null) { throw CFLib.getDefaultExceptionFactory().newNullArgumentException(getClass(), S_ProcName, 1, "value"); } serverInfo = value; initServerKeys(); byte encodedPKey[] = getEncodedServerPublicKey(); String encoded = new String(Base64.encodeBase64(encodedPKey)); serverInfo.setServerLoginKey(encoded); } // Encryption Support // Session key and accessors private SecretKey sessionKey = null; public void setEncodedSessionKey(byte encoded[]) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidKeySpecException { sessionKey = new SecretKeySpec(encoded, "AES"); } public byte[] encryptWithSessionKey(IvParameterSpec ivspec, byte value[]) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException, InvalidAlgorithmParameterException { final String S_ProcName = "encryptWithClientPrivateKey"; if (sessionKey == null) { throw CFLib.getDefaultExceptionFactory().newUsageException(getClass(), S_ProcName, "Session key must be initialized by setEncodedSessionKey()"); } Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); if (cipher == null) { throw CFLib.getDefaultExceptionFactory().newNullArgumentException(getClass(), S_ProcName, 0, "cipher"); } cipher.init(Cipher.ENCRYPT_MODE, sessionKey, ivspec); byte encrypted[] = cipher.doFinal(value); return (encrypted); } public byte[] decryptWithSessionKey(IvParameterSpec ivspec, byte value[]) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException, InvalidAlgorithmParameterException { final String S_ProcName = "decryptWithClientPrivateKey"; if (sessionKey == null) { throw CFLib.getDefaultExceptionFactory().newUsageException(getClass(), S_ProcName, "Session key must be initialized by setEncodedSessionKey()"); } Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); if (cipher == null) { throw CFLib.getDefaultExceptionFactory().newNullArgumentException(getClass(), S_ProcName, 0, "cipher"); } cipher.init(Cipher.DECRYPT_MODE, sessionKey, ivspec); byte decrypted[] = cipher.doFinal(value); return (decrypted); } // Client device public key for decrypting password hash private PublicKey clientPublicKey = null; public void setEncodedClientPublicKey(byte encoded[]) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidKeySpecException { X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(encoded); KeyFactory kf = KeyFactory.getInstance("RSA"); clientPublicKey = kf.generatePublic(x509KeySpec); } public byte[] decryptWithClientPublicKey(byte value[]) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException { final String S_ProcName = "decryptWithClientPublicKey"; if (clientPublicKey == null) { throw CFLib.getDefaultExceptionFactory().newUsageException(getClass(), S_ProcName, "Client public key must be set by calling setEncodedClientPublicKey() first"); } Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); if (cipher == null) { throw CFLib.getDefaultExceptionFactory().newNullArgumentException(getClass(), S_ProcName, 0, "cipher"); } cipher.init(Cipher.DECRYPT_MODE, clientPublicKey); byte decrypted[] = cipher.doFinal(value); return (decrypted); } // Server keys and accessors private static KeyPair serverKeyPair = null; public void initServerKeys() throws NoSuchAlgorithmException, InvalidKeyException, NoSuchPaddingException, IllegalBlockSizeException { if (serverKeyPair == null) { KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA"); kpg.initialize(2048, new SecureRandom()); serverKeyPair = kpg.generateKeyPair(); } byte encodedPKey[] = getEncodedServerPublicKey(); String encoded = new String(Base64.encodeBase64(encodedPKey)); serverInfo.setServerLoginKey(encoded); } public byte[] getEncodedServerPublicKey() throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException { final String S_ProcName = "getEncodedServerPublicKey"; if (serverKeyPair == null) { throw CFLib.getDefaultExceptionFactory().newUsageException(getClass(), S_ProcName, "Server key must be initialized by initServerKeys()"); } PublicKey pk = serverKeyPair.getPublic(); if (pk == null) { throw CFLib.getDefaultExceptionFactory().newNullArgumentException(getClass(), S_ProcName, 0, "serverKeyPair.getPublic()"); } byte encoded[] = pk.getEncoded(); return (encoded); } public byte[] decryptWithServerPrivateKey(byte value[]) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException { final String S_ProcName = "decryptWithServerPrivateKey"; if (serverKeyPair == null) { throw CFLib.getDefaultExceptionFactory().newUsageException(getClass(), S_ProcName, "Server keys must be initialized by initServerKeys()"); } PrivateKey pk = serverKeyPair.getPrivate(); if (pk == null) { throw CFLib.getDefaultExceptionFactory().newNullArgumentException(getClass(), S_ProcName, 0, "serverKeyPair.getPrivate()"); } Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); if (cipher == null) { throw CFLib.getDefaultExceptionFactory().newNullArgumentException(getClass(), S_ProcName, 0, "cipher"); } cipher.init(Cipher.DECRYPT_MODE, pk); byte decrypted[] = cipher.doFinal(value); return (decrypted); } // Element Handler instances private CFTipQueryServerInfoHandler queryServerInfoHandler = null; private CFTipAppRequestHandler appRequestHandler = null; private CFTipLoginRequestHandler loginRequestHandler = null; private CFTipSaxEnvelopeDocHandler saxEnvelopeDocHandler = null; private CFTipSaxEnvelopeRootHandler saxEnvelopeRootHandler = null; // Element Handler Resolver Factories protected CFTipQueryServerInfoHandler getQueryServerInfoHandler() { if (queryServerInfoHandler == null) { queryServerInfoHandler = new CFTipQueryServerInfoHandler(this); } return (queryServerInfoHandler); } protected CFTipAppRequestHandler getAppRequestHandler() { if (appRequestHandler == null) { appRequestHandler = new CFTipAppRequestHandler(this); } return (appRequestHandler); } protected CFTipLoginRequestHandler getLoginRequestHandler() { if (loginRequestHandler == null) { loginRequestHandler = new CFTipLoginRequestHandler(this); } return (loginRequestHandler); } protected CFTipSaxEnvelopeDocHandler getSaxEnvelopeDocHandler() { if (saxEnvelopeDocHandler == null) { saxEnvelopeDocHandler = new CFTipSaxEnvelopeDocHandler(this); saxEnvelopeDocHandler.addElementHandler("AppRequest", getAppRequestHandler()); saxEnvelopeDocHandler.addElementHandler("LoginRequest", getLoginRequestHandler()); saxEnvelopeDocHandler.addElementHandler("QueryServerInfo", getQueryServerInfoHandler()); } return (saxEnvelopeDocHandler); } // Root Element Handler Resolver Factory protected CFTipSaxEnvelopeRootHandler getSaxRqstRootHandler() { if (saxEnvelopeRootHandler == null) { saxEnvelopeRootHandler = new CFTipSaxEnvelopeRootHandler(this); saxEnvelopeRootHandler.addElementHandler("CFTIPEnvelope", getSaxEnvelopeDocHandler()); } return (saxEnvelopeRootHandler); } // Root Element Handler /* * CFTipSaxEnvelopeRootHandler XML SAX Root Element Handler implementation */ public class CFTipSaxEnvelopeRootHandler extends CFLibXmlCoreElementHandler { public CFTipSaxEnvelopeRootHandler(CFTipEnvelopeHandler xmsgRqstHandler) { super(xmsgRqstHandler); } public void startElement(String uri, String localName, String qName, Attributes attrs) throws SAXException { } public void endElement(String uri, String localName, String qName) throws SAXException { } } // Document Element Handler /* * CFTipSaxEnvelopeDocHandler XML SAX Doc Element Handler implementation */ public class CFTipSaxEnvelopeDocHandler extends CFLibXmlCoreElementHandler { public CFTipSaxEnvelopeDocHandler(CFTipEnvelopeHandler xmsgRqstHandler) { super(xmsgRqstHandler); } public void startElement(String uri, String localName, String qName, Attributes attrs) throws SAXException { } public void endElement(String uri, String localName, String qName) throws SAXException { } } // Parse XML string contents public void parseStringContents(String str) { setResponse(""); try { super.parseStringContents(str); } catch (RuntimeException e) { ICFLibMessageLog log = getLog(); if (log != null) { PrintStream printStream = log.getPrintStream(); log.message("Caught " + e.getClass().getName() + " -- " + e.getMessage()); e.printStackTrace(printStream); } else { e.printStackTrace(); } setResponse(""); } catch (Error e) { ICFLibMessageLog log = getLog(); if (log != null) { PrintStream printStream = log.getPrintStream(); log.message("Caught " + e.getClass().getName() + " -- " + e.getMessage()); e.printStackTrace(printStream); } else { e.printStackTrace(); } setResponse(""); } } // Parse a URL public void parse(String url) { setResponse(""); try { super.parse(url); } catch (RuntimeException e) { ICFLibMessageLog log = getLog(); if (log != null) { PrintStream printStream = log.getPrintStream(); log.message("Caught " + e.getClass().getName() + " -- " + e.getMessage()); e.printStackTrace(printStream); } else { e.printStackTrace(); } setResponse(""); } catch (Error e) { ICFLibMessageLog log = getLog(); if (log != null) { PrintStream printStream = log.getPrintStream(); log.message("Caught " + e.getClass().getName() + " -- " + e.getMessage()); e.printStackTrace(printStream); } else { e.printStackTrace(); } setResponse(""); } } // Parse a file public void parseFile(String url) { setResponse(""); try { super.parse(url); } catch (RuntimeException e) { ICFLibMessageLog log = getLog(); if (log != null) { PrintStream printStream = log.getPrintStream(); log.message("Caught " + e.getClass().getName() + " -- " + e.getMessage()); e.printStackTrace(printStream); } else { e.printStackTrace(); } setResponse(""); } catch (Error e) { ICFLibMessageLog log = getLog(); if (log != null) { PrintStream printStream = log.getPrintStream(); log.message("Caught " + e.getClass().getName() + " -- " + e.getMessage()); e.printStackTrace(printStream); } else { e.printStackTrace(); } setResponse(""); } } /* * CFTipQueryServerInfoHandler XML SAX Element Handler implementation */ public class CFTipQueryServerInfoHandler extends CFLibXmlCoreElementHandler { public CFTipQueryServerInfoHandler(CFTipEnvelopeHandler envelopeHandler) { super(envelopeHandler); } public void startElement(String uri, String localName, String qName, Attributes attrs) throws SAXException { final String S_ProcName = "startElement"; final String S_LocalName = "LocalName"; CFTipEnvelopeHandler envelopeHandler = (CFTipEnvelopeHandler) getParser(); if (envelopeHandler == null) { throw CFLib.getDefaultExceptionFactory().newNullArgumentException(getClass(), S_ProcName, 0, "getParser()"); } try { // Common XML Attributes String attrId = null; // Request Attributes // Attribute Extraction String attrLocalName; int numAttrs; int idxAttr; assert qName.equals("QueryServerInfo"); // Extract Attributes numAttrs = attrs.getLength(); for (idxAttr = 0; idxAttr < numAttrs; idxAttr++) { attrLocalName = attrs.getLocalName(idxAttr); if (attrLocalName.equals("Id")) { if (attrId != null) { throw CFLib.getDefaultExceptionFactory().newUniqueIndexViolationException(getClass(), S_ProcName, S_LocalName, attrLocalName); } attrId = attrs.getValue(idxAttr); } else if (attrLocalName.equals("schemaLocation")) { // ignored } else { throw CFLib.getDefaultExceptionFactory().newUnrecognizedAttributeException(getClass(), S_ProcName, getParser().getLocationInfo(), attrLocalName); } } // Prepare the server information response message CFTipServerInfo serverInfo = envelopeHandler.getServerInfo(); String clusterURL = serverInfo.getClusterURL(); String clusterDescr = serverInfo.getClusterDescr(); String schemaName = serverInfo.getSchemaName(); String schemaDescr = serverInfo.getSchemaDescr(); CFTipServerInfo.AltSchema altSchemas[] = serverInfo.getAltSchemas(); String serverLoginKey = serverInfo.getServerLoginKey(); int numSchemas = altSchemas.length; CFTipServerInfo.AltSchema altSchema; String altSchemaName; String altSchemaDescr; StringBuffer buff = new StringBuffer(); buff.append("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" + "<CFTipServerInfo\n" + "\t\txmlns=\"uri://net.sourceforge.msscodefactory/CFTipServerInfo\"\n" + "\t\txmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n" + "\t\txmlns:xs=\"http://www.w3.org/2001/XMLSchema\"\n" + "\t\txsi:schemaLocation=\"uri://net.sourceforge.msscodefactory/CFTipServerInfo file://xsd/cftip-serverinfo.xsd\"" + "\t\tClusterURL=\"" + CFLibXmlUtil.formatXmlString(clusterURL) + "\"\n" + "\t\tClusterDescr=\"" + CFLibXmlUtil.formatXmlString(clusterDescr) + "\"\n" + "\t\tSchemaName=\"" + CFLibXmlUtil.formatXmlString(schemaName) + "\"\n" + "\t\tSchemaDescr=\"" + CFLibXmlUtil.formatXmlString(schemaDescr) + "\"\n" + "\t\tServerLoginKey=\"" + CFLibXmlUtil.formatXmlString(serverLoginKey) + "\" >\n"); for (int idx = 0; idx < numSchemas; idx++) { altSchema = altSchemas[idx]; if (altSchema != null) { altSchemaName = altSchema.getSchemaName(); altSchemaDescr = altSchema.getSchemaDescr(); buff.append("\t<AltSchema SchemaName=\"" + CFLibXmlUtil.formatXmlString(altSchemaName) + "\" SchemaDescr=\"" + CFLibXmlUtil.formatXmlString(altSchemaDescr) + "\" />\n"); } } buff.append("</CFTipServerInfo>\n"); envelopeHandler.setResponse(buff.toString()); } catch (RuntimeException e) { ICFLibMessageLog log = getLog(); if (log != null) { PrintStream printStream = log.getPrintStream(); log.message("Caught " + e.getClass().getName() + " -- " + e.getMessage()); e.printStackTrace(printStream); } else { e.printStackTrace(); } envelopeHandler.setResponse(""); } catch (Error e) { ICFLibMessageLog log = getLog(); if (log != null) { PrintStream printStream = log.getPrintStream(); log.message("Caught " + e.getClass().getName() + " -- " + e.getMessage()); e.printStackTrace(printStream); } else { e.printStackTrace(); } envelopeHandler.setResponse(""); } } public void endElement(String uri, String localName, String qName) throws SAXException { } } /* * CFTipQueryServerInfoHandler XML SAX Element Handler implementation */ public class CFTipLoginRequestHandler extends CFLibXmlCoreElementHandler { public CFTipLoginRequestHandler(CFTipEnvelopeHandler envelopeHandler) { super(envelopeHandler); } public void startElement(String uri, String localName, String qName, Attributes attrs) throws SAXException { final String S_ProcName = "startElement"; final String S_LocalName = "LocalName"; CFTipEnvelopeHandler envelopeHandler = (CFTipEnvelopeHandler) getParser(); if (envelopeHandler == null) { throw CFLib.getDefaultExceptionFactory().newNullArgumentException(getClass(), S_ProcName, 0, "getParser()"); } ICFTipRequestHandler rqstHandler = envelopeHandler.getRequestHandler(); if (rqstHandler == null) { throw CFLib.getDefaultExceptionFactory().newNullArgumentException(getClass(), S_ProcName, 0, "getParser().getRequestHandler()"); } try { // Common XML Attributes String attrId = null; // Request Attributes String attrMessageIV = null; String attrAES256Key = null; String attrPayload = null; // Attribute Extraction String attrLocalName; int numAttrs; int idxAttr; assert qName.equals("LoginRequest"); // Extract Attributes numAttrs = attrs.getLength(); for (idxAttr = 0; idxAttr < numAttrs; idxAttr++) { attrLocalName = attrs.getLocalName(idxAttr); if (attrLocalName.equals("Id")) { if (attrId != null) { throw CFLib.getDefaultExceptionFactory().newUniqueIndexViolationException(getClass(), S_ProcName, S_LocalName, attrLocalName); } attrId = attrs.getValue(idxAttr); } else if (attrLocalName.equals("MessageIV")) { if (attrMessageIV != null) { throw CFLib.getDefaultExceptionFactory().newUniqueIndexViolationException(getClass(), S_ProcName, S_LocalName, attrLocalName); } attrMessageIV = attrs.getValue(idxAttr); } else if (attrLocalName.equals("AES256Key")) { if (attrAES256Key != null) { throw CFLib.getDefaultExceptionFactory().newUniqueIndexViolationException(getClass(), S_ProcName, S_LocalName, attrLocalName); } attrAES256Key = attrs.getValue(idxAttr); } else if (attrLocalName.equals("Payload")) { if (attrPayload != null) { throw CFLib.getDefaultExceptionFactory().newUniqueIndexViolationException(getClass(), S_ProcName, S_LocalName, attrLocalName); } attrPayload = attrs.getValue(idxAttr); } else if (attrLocalName.equals("schemaLocation")) { // ignored } else { throw CFLib.getDefaultExceptionFactory().newUnrecognizedAttributeException(getClass(), S_ProcName, getParser().getLocationInfo(), attrLocalName); } } // Verify that the key and payload was provided if ((attrMessageIV == null) || (attrMessageIV.length() <= 0)) { throw CFLib.getDefaultExceptionFactory().newNullArgumentException(getClass(), S_ProcName, 0, "MessageIV"); } if ((attrAES256Key == null) || (attrAES256Key.length() <= 0)) { throw CFLib.getDefaultExceptionFactory().newNullArgumentException(getClass(), S_ProcName, 0, "AES256Key"); } if ((attrPayload == null) || (attrPayload.length() <= 0)) { throw CFLib.getDefaultExceptionFactory().newNullArgumentException(getClass(), S_ProcName, 0, "Payload"); } // Unmarshall the IV byte[] iv = Base64.decodeBase64(attrMessageIV); IvParameterSpec ivspec = new IvParameterSpec(iv); // Convert the AES256Key string from Base64 to a byte array byte[] base64AES256Key = Base64.decodeBase64(attrAES256Key); byte[] decryptedAES256Key = envelopeHandler.decryptWithServerPrivateKey(base64AES256Key); envelopeHandler.setEncodedSessionKey(decryptedAES256Key); // Convert the payload from Base64 to a byte array byte payload[] = Base64.decodeBase64(attrPayload); // Decrypt the payload using the application session private key byte decrypted[] = envelopeHandler.decryptWithSessionKey(ivspec, payload); // The payload's password and client public key are further encrypted by the device key, // but that processing is handled by the request parser // Process the decrypted payload using the envelope's request handler String rqst = new String(decrypted); rqstHandler.parseStringContents(rqst); String rspn = rqstHandler.getResponse(); if (rspn == null) { rspn = ""; } // Encrypt the response using the session AES key byte bytes[] = rspn.getBytes(); byte clientEncrypted[] = envelopeHandler.encryptWithSessionKey(ivspec, bytes); // Encode the encrypted response as Base64 String rspnString = new String(Base64.encodeBase64(clientEncrypted)); envelopeHandler.setResponse(rspnString); } catch (RuntimeException e) { ICFLibMessageLog log = getLog(); if (log != null) { PrintStream printStream = log.getPrintStream(); log.message("Caught " + e.getClass().getName() + " -- " + e.getMessage()); e.printStackTrace(printStream); } else { e.printStackTrace(); } envelopeHandler.setResponse(""); } catch (Error e) { ICFLibMessageLog log = getLog(); if (log != null) { PrintStream printStream = log.getPrintStream(); log.message("Caught " + e.getClass().getName() + " -- " + e.getMessage()); e.printStackTrace(printStream); } else { e.printStackTrace(); } envelopeHandler.setResponse(""); } catch (InvalidKeyException e) { ICFLibMessageLog log = getLog(); if (log != null) { PrintStream printStream = log.getPrintStream(); log.message("Caught InvalidKeyException -- " + e.getMessage()); e.printStackTrace(printStream); } else { e.printStackTrace(); } envelopeHandler.setResponse(""); } catch (NoSuchAlgorithmException e) { ICFLibMessageLog log = getLog(); if (log != null) { PrintStream printStream = log.getPrintStream(); log.message("Caught NoSuchAlgorithmException -- " + e.getMessage()); e.printStackTrace(printStream); } else { e.printStackTrace(); } envelopeHandler.setResponse(""); } catch (NoSuchPaddingException e) { ICFLibMessageLog log = getLog(); if (log != null) { PrintStream printStream = log.getPrintStream(); log.message("Caught NoSuchPaddingException -- " + e.getMessage()); e.printStackTrace(printStream); } else { e.printStackTrace(); } envelopeHandler.setResponse(""); } catch (IllegalBlockSizeException e) { ICFLibMessageLog log = getLog(); if (log != null) { PrintStream printStream = log.getPrintStream(); log.message("Caught IllegalBlockSizeException -- " + e.getMessage()); e.printStackTrace(printStream); } else { e.printStackTrace(); } envelopeHandler.setResponse(""); } catch (BadPaddingException e) { ICFLibMessageLog log = getLog(); if (log != null) { PrintStream printStream = log.getPrintStream(); log.message("Caught BadPaddingException -- " + e.getMessage()); e.printStackTrace(printStream); } else { e.printStackTrace(); } envelopeHandler.setResponse(""); } catch (InvalidKeySpecException e) { ICFLibMessageLog log = getLog(); if (log != null) { PrintStream printStream = log.getPrintStream(); log.message("Caught InvalidKeySpecException -- " + e.getMessage()); e.printStackTrace(printStream); } else { e.printStackTrace(); } envelopeHandler.setResponse(""); } catch (InvalidAlgorithmParameterException e) { ICFLibMessageLog log = getLog(); if (log != null) { PrintStream printStream = log.getPrintStream(); log.message("Caught InvalidAlgorithmParameterException -- " + e.getMessage()); e.printStackTrace(printStream); } else { e.printStackTrace(); } envelopeHandler.setResponse(""); } } public void endElement(String uri, String localName, String qName) throws SAXException { } } /* * CFTipQueryServerInfoHandler XML SAX Element Handler implementation */ public class CFTipAppRequestHandler extends CFLibXmlCoreElementHandler { public CFTipAppRequestHandler(CFTipEnvelopeHandler envelopeHandler) { super(envelopeHandler); } public void startElement(String uri, String localName, String qName, Attributes attrs) throws SAXException { final String S_ProcName = "startElement"; final String S_LocalName = "LocalName"; CFTipEnvelopeHandler envelopeHandler = (CFTipEnvelopeHandler) getParser(); if (envelopeHandler == null) { throw CFLib.getDefaultExceptionFactory().newNullArgumentException(getClass(), S_ProcName, 0, "getParser()"); } ICFTipRequestHandler rqstHandler = envelopeHandler.getRequestHandler(); if (rqstHandler == null) { throw CFLib.getDefaultExceptionFactory().newNullArgumentException(getClass(), S_ProcName, 0, "getParser().getRequestHandler()"); } try { // Common XML Attributes String attrId = null; // Request Attributes String attrMessageIV = null; String attrPayload = null; // Attribute Extraction String attrLocalName; int numAttrs; int idxAttr; assert qName.equals("AppRequest"); // Extract Attributes numAttrs = attrs.getLength(); for (idxAttr = 0; idxAttr < numAttrs; idxAttr++) { attrLocalName = attrs.getLocalName(idxAttr); if (attrLocalName.equals("Id")) { if (attrId != null) { throw CFLib.getDefaultExceptionFactory().newUniqueIndexViolationException(getClass(), S_ProcName, S_LocalName, attrLocalName); } attrId = attrs.getValue(idxAttr); } else if (attrLocalName.equals("MessageIV")) { if (attrMessageIV != null) { throw CFLib.getDefaultExceptionFactory().newUniqueIndexViolationException(getClass(), S_ProcName, S_LocalName, attrLocalName); } attrMessageIV = attrs.getValue(idxAttr); } else if (attrLocalName.equals("Payload")) { if (attrPayload != null) { throw CFLib.getDefaultExceptionFactory().newUniqueIndexViolationException(getClass(), S_ProcName, S_LocalName, attrLocalName); } attrPayload = attrs.getValue(idxAttr); } else if (attrLocalName.equals("schemaLocation")) { // ignored } else { throw CFLib.getDefaultExceptionFactory().newUnrecognizedAttributeException(getClass(), S_ProcName, getParser().getLocationInfo(), attrLocalName); } } // Verify that a payload was provided if ((attrMessageIV == null) || (attrMessageIV.length() <= 0)) { throw CFLib.getDefaultExceptionFactory().newNullArgumentException(getClass(), S_ProcName, 0, "MessageIV"); } if ((attrPayload == null) || (attrPayload.length() <= 0)) { throw CFLib.getDefaultExceptionFactory().newNullArgumentException(getClass(), S_ProcName, 0, "Payload"); } // Unmarshall the IV byte[] iv = Base64.decodeBase64(attrMessageIV); IvParameterSpec ivspec = new IvParameterSpec(iv); // Convert the payload from Base64 to a byte array byte payload[] = Base64.decodeBase64(attrPayload); // Decrypt the payload using the application session private key byte decrypted[] = envelopeHandler.decryptWithSessionKey(ivspec, payload); // Process the decrypted payload using the envelope's request handler String rqst = new String(decrypted); rqstHandler.parseStringContents(rqst); String rspn = rqstHandler.getResponse(); if (rspn == null) { rspn = ""; } // Encrypt the response using the session private key to prevent MITM attacks byte bytes[] = rspn.getBytes(); byte encrypted[] = envelopeHandler.encryptWithSessionKey(ivspec, bytes); // Encode the encrypted response as Base64 String rspnString = new String(Base64.encodeBase64(encrypted)); envelopeHandler.setResponse(rspnString); } catch (RuntimeException e) { ICFLibMessageLog log = getLog(); if (log != null) { PrintStream printStream = log.getPrintStream(); log.message("Caught " + e.getClass().getName() + " -- " + e.getMessage()); e.printStackTrace(printStream); } else { e.printStackTrace(); } envelopeHandler.setResponse(""); } catch (Error e) { ICFLibMessageLog log = getLog(); if (log != null) { PrintStream printStream = log.getPrintStream(); log.message("Caught " + e.getClass().getName() + " -- " + e.getMessage()); e.printStackTrace(printStream); } else { e.printStackTrace(); } envelopeHandler.setResponse(""); } catch (InvalidKeyException e) { ICFLibMessageLog log = getLog(); if (log != null) { PrintStream printStream = log.getPrintStream(); log.message("Caught InvalidKeyException -- " + e.getMessage()); e.printStackTrace(printStream); } else { e.printStackTrace(); } envelopeHandler.setResponse(""); } catch (NoSuchAlgorithmException e) { ICFLibMessageLog log = getLog(); if (log != null) { PrintStream printStream = log.getPrintStream(); log.message("Caught NoSuchAlgorithmException -- " + e.getMessage()); e.printStackTrace(printStream); } else { e.printStackTrace(); } envelopeHandler.setResponse(""); } catch (NoSuchPaddingException e) { ICFLibMessageLog log = getLog(); if (log != null) { PrintStream printStream = log.getPrintStream(); log.message("Caught NoSuchPaddingException -- " + e.getMessage()); e.printStackTrace(printStream); } else { e.printStackTrace(); } envelopeHandler.setResponse(""); } catch (IllegalBlockSizeException e) { ICFLibMessageLog log = getLog(); if (log != null) { PrintStream printStream = log.getPrintStream(); log.message("Caught IllegalBlockSizeException -- " + e.getMessage()); e.printStackTrace(printStream); } else { e.printStackTrace(); } envelopeHandler.setResponse(""); } catch (BadPaddingException e) { ICFLibMessageLog log = getLog(); if (log != null) { PrintStream printStream = log.getPrintStream(); log.message("Caught BadPaddingException -- " + e.getMessage()); e.printStackTrace(printStream); } else { e.printStackTrace(); } envelopeHandler.setResponse(""); } catch (InvalidAlgorithmParameterException e) { ICFLibMessageLog log = getLog(); if (log != null) { PrintStream printStream = log.getPrintStream(); log.message("Caught InvalidAlgorithmParameterException -- " + e.getMessage()); e.printStackTrace(printStream); } else { e.printStackTrace(); } envelopeHandler.setResponse(""); } } public void endElement(String uri, String localName, String qName) throws SAXException { } } }