From f81b3716ac27094ab1845668cb38a1fe6a2d5f8c Mon Sep 17 00:00:00 2001 From: Alexander Marsalek Date: Wed, 4 Jun 2014 18:50:50 +0200 Subject: added DocumentService --- .../documentservice/utils/EncryptionHelper.java | 182 +++++++++++++++++ .../documentservice/utils/ExternalDocservice.java | 105 ++++++++++ .../documentservice/utils/GetDSSFileAction.java | 84 ++++++++ .../src/eu/stork/documentservice/utils/Utils.java | 172 ++++++++++++++++ .../eu/stork/documentservice/utils/XmlHelper.java | 224 +++++++++++++++++++++ 5 files changed, 767 insertions(+) create mode 100644 DocumentService/src/eu/stork/documentservice/utils/EncryptionHelper.java create mode 100644 DocumentService/src/eu/stork/documentservice/utils/ExternalDocservice.java create mode 100644 DocumentService/src/eu/stork/documentservice/utils/GetDSSFileAction.java create mode 100644 DocumentService/src/eu/stork/documentservice/utils/Utils.java create mode 100644 DocumentService/src/eu/stork/documentservice/utils/XmlHelper.java (limited to 'DocumentService/src/eu/stork/documentservice/utils') diff --git a/DocumentService/src/eu/stork/documentservice/utils/EncryptionHelper.java b/DocumentService/src/eu/stork/documentservice/utils/EncryptionHelper.java new file mode 100644 index 000000000..1c55e59e3 --- /dev/null +++ b/DocumentService/src/eu/stork/documentservice/utils/EncryptionHelper.java @@ -0,0 +1,182 @@ +package eu.stork.documentservice.utils; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.security.AlgorithmParameters; +import java.security.PublicKey; +import java.security.cert.CertificateFactory; +import java.security.cert.X509Certificate; + +import javax.crypto.*; +import javax.crypto.spec.IvParameterSpec; +import javax.crypto.spec.SecretKeySpec; + +import com.sun.org.apache.xml.internal.security.utils.Base64; + +import eu.stork.documentservice.exceptions.EncryptionException; + +public class EncryptionHelper { + + private static String key; + private static String iv; + private static Cipher cipher; + + public EncryptionHelper() throws EncryptionException + { + this.generateKeys(); + } + + public EncryptionHelper(String inKey, String inIv) throws EncryptionException + { + this.initKeys(inKey, inIv); + } + + /** + * Generate new symmetric keys + * @throws EncryptionException + */ + public void generateKeys() throws EncryptionException + { + try + { + KeyGenerator keyGen = KeyGenerator.getInstance("AES"); + keyGen.init(256); + SecretKey secretKey = keyGen.generateKey(); + cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); + cipher.init(Cipher.ENCRYPT_MODE, secretKey); + AlgorithmParameters params = cipher.getParameters(); + key = Base64.encode(secretKey.getEncoded()); + iv = Base64.encode(params.getParameterSpec(IvParameterSpec.class).getIV()); + } + catch (Exception e) + { + e.printStackTrace(); + throw new EncryptionException("Unable to generate encryption key.", e); + } + } + + /** + * Initialize keys with specified keys + * @param inKey the key to use + * @param inIv the IV to use + * @throws EncryptionException the exception thrown + */ + public void initKeys(String inKey, String inIv) throws EncryptionException + { + try + { + key = inKey; + iv = inIv; + SecretKeySpec skeySpec = new SecretKeySpec(Base64.decode(inKey), "AES"); + cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); + cipher.init(Cipher.DECRYPT_MODE, skeySpec, new IvParameterSpec(Base64.decode(inIv))); + } + catch (Exception e) + { + e.printStackTrace(); + throw new EncryptionException("Unable to initialize encryption key.", e); + } + } + + /** + * Encrypt data with key + * @param clearData the clear data + * @return the encrypted data + * @throws EncryptionException the exception thrown + */ + public byte[] encrypt(byte[] clearData) throws EncryptionException + { + if (clearData != null) + { + try + { + return cipher.doFinal(clearData); + } + catch (Exception ex) + { + throw new EncryptionException("Could not decrypt data.", ex); + } + } + else + throw new EncryptionException("Clear data is null."); + } + + /** + * Decrypt data with keys + * @param encData the encrypted data + * @return decrypted data + * @throws EncryptionException the exception thrown + */ + public byte[] decrypt(byte[] encData) throws EncryptionException + { + if (encData != null) + { + try + { + return cipher.doFinal(encData); + } + catch (Exception ex) + { + throw new EncryptionException("Could not encrypt data.", ex); + } + } + else + throw new EncryptionException("Encrypted data is null."); + } + + /** + * Get the key string + * @return the key + */ + public String getKey() + { + return key; + } + + /** + * Get the IV string + * @return the iv + */ + public String getIv() + { + return iv; + } + + /** + * Encrypt string with certificate + * @param certString the PEM formated certificate + * @param input the string to encrypt + * @return encrypted string + * @throws EncryptionException the exception thrown + */ + public String encryptWithCert(String certString, String input) throws EncryptionException + { + if (certString != null && !certString.isEmpty()) + { + if (input != null && !input.isEmpty()) + { + try { + certString = certString.replace("-----BEGIN CERTIFICATE-----", ""); + certString = certString.replace("-----END CERTIFICATE-----", ""); + InputStream inStream = new ByteArrayInputStream(Base64.decode(certString)); + CertificateFactory cf = CertificateFactory.getInstance("X.509"); + X509Certificate cert = (X509Certificate)cf.generateCertificate(inStream); + PublicKey pk = cert.getPublicKey(); + Cipher rsaCipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); + rsaCipher.init(Cipher.ENCRYPT_MODE, pk); + byte[] encrypted = rsaCipher.doFinal(input.getBytes("UTF-8")); + return Base64.encode(encrypted); + } + catch (Exception e) { + e.printStackTrace(); + throw new EncryptionException("Unabled to encrypt string.", e); + } + } + else + throw new EncryptionException("Input is null or empty."); + } + else + throw new EncryptionException("Certificate is null or empty."); + } + +} diff --git a/DocumentService/src/eu/stork/documentservice/utils/ExternalDocservice.java b/DocumentService/src/eu/stork/documentservice/utils/ExternalDocservice.java new file mode 100644 index 000000000..821d636a2 --- /dev/null +++ b/DocumentService/src/eu/stork/documentservice/utils/ExternalDocservice.java @@ -0,0 +1,105 @@ +package eu.stork.documentservice.utils; + +import java.net.MalformedURLException; +import java.net.URL; + +import javax.xml.namespace.QName; +import javax.xml.ws.BindingProvider; +import javax.xml.ws.Service; +import javax.xml.ws.soap.SOAPBinding; + +import eu.stork.documentservice.DocumentService; +import eu.stork.documentservice.exceptions.DocumentServiceException; + +public class ExternalDocservice { + + /** + * Get document from external DTL + * @param documentTransferRequest the document transfer request (attribute query) + * @param dtlUrl the URL of external DTL + * @return the document found + * @throws DocumentServiceException + */ + public static byte[] getDocument(String documentTransferRequest, String dtlUrl) throws DocumentServiceException + { + if (documentTransferRequest != null && !documentTransferRequest.isEmpty()) + { + if (dtlUrl != null && !dtlUrl.isEmpty()) + { + try + { + URL url = new URL(dtlUrl); + + QName qname = new QName("http://stork.eu", + "DocumentService"); + + Service service = Service.create(url, qname); + DocumentService docservice = service.getPort(DocumentService.class); + + BindingProvider bp = (BindingProvider) docservice; + SOAPBinding binding = (SOAPBinding) bp.getBinding(); + binding.setMTOMEnabled(true); + + return docservice.getDocument(documentTransferRequest, dtlUrl); + } + catch (MalformedURLException e) { + e.printStackTrace(); + throw new DocumentServiceException("DTL url is invalid.", e); + } + catch (Exception e) { + e.printStackTrace(); + throw new DocumentServiceException(e); + } + } + else + throw new DocumentServiceException("DTL url is empty."); + } + else + throw new DocumentServiceException("Document transfer request is empty."); + } + + /** + * Get document mime from external DTL + * @param docId the document id + * @param dtlUrl the URL of external DTL + * @return the document mime found + * @throws DocumentServiceException + */ + public static String getDocumentMime(String docId, String dtlUrl) throws DocumentServiceException + { + if (docId != null && !docId.isEmpty()) + { + if (dtlUrl != null && !dtlUrl.isEmpty()) + { + try + { + URL url = new URL(dtlUrl); + + QName qname = new QName("http://stork.eu", + "DocumentService"); + + Service service = Service.create(url, qname); + DocumentService docservice = service.getPort(DocumentService.class); + + BindingProvider bp = (BindingProvider) docservice; + SOAPBinding binding = (SOAPBinding) bp.getBinding(); + binding.setMTOMEnabled(true); + + return docservice.getDocumentMime(docId, dtlUrl); + } + catch (MalformedURLException e) { + e.printStackTrace(); + throw new DocumentServiceException("DTL url is invalid.", e); + } + catch (Exception e) { + e.printStackTrace(); + throw new DocumentServiceException(e); + } + } + else + throw new DocumentServiceException("DTL url is empty."); + } + else + throw new DocumentServiceException("Document Id is empty."); + } +} diff --git a/DocumentService/src/eu/stork/documentservice/utils/GetDSSFileAction.java b/DocumentService/src/eu/stork/documentservice/utils/GetDSSFileAction.java new file mode 100644 index 000000000..b80c63dc2 --- /dev/null +++ b/DocumentService/src/eu/stork/documentservice/utils/GetDSSFileAction.java @@ -0,0 +1,84 @@ +package eu.stork.documentservice.utils; +/* + * This work is Open Source and licensed by the European Commission under the + * conditions of the European Public License v1.1 + * + * (http://www.osor.eu/eupl/european-union-public-licence-eupl-v.1.1); + * + * any use of this file implies acceptance of the conditions of this license. + * 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. + */ + + +import org.apache.log4j.Logger; +import org.bouncycastle.util.encoders.UrlBase64; + +import eu.stork.peps.auth.commons.IPersonalAttributeList; +import eu.stork.peps.auth.commons.PEPSUtil; + +import eu.stork.peps.auth.commons.PersonalAttribute; +import eu.stork.peps.auth.commons.STORKAttrQueryRequest; + +//import eu.stork.peps.auth.cpeps.AUCPEPS; +import eu.stork.peps.auth.engine.STORKSAMLEngine; +import eu.stork.peps.exceptions.STORKSAMLEngineException; + +/** + * This Action will be invoked by file transfer in order to validate saml + * + * @author Advania + * + * @version $Revision: $, $Date: $ + * + */ +public final class GetDSSFileAction { + /** + * Unique identifier. + */ + private static final long serialVersionUID = 6233180247896844849L; + /** + * Logger object. + */ + private static final Logger LOG = Logger.getLogger(GetDSSFileAction.class.getName()); +// public String SAMLRequest; +// public String docId; + private static final String SAML_INSTANCE = "VIDP"; + + public static String processDocRequest(String samlRequest) + { + String result = ""; + //final Map parameters = getHttpRequestParameters(); + STORKAttrQueryRequest request; + try { + request = processDocRequest_(samlRequest); + final IPersonalAttributeList pal = request.getPersonalAttributeList(); + final PersonalAttribute sdoc = pal.get("docRequest"); + if (sdoc != null) + { + String docId = sdoc.getValue().get(0); + return docId; + } + } catch (final STORKSAMLEngineException e) { + e.printStackTrace(); + } + return null; + } + + private static STORKAttrQueryRequest processDocRequest_(String samlRequest) + throws STORKSAMLEngineException{ + + // fetch the samlToken from the request + final byte[] samlToken = UrlBase64.decode(samlRequest); + + final STORKSAMLEngine engine = STORKSAMLEngine.getInstance(SAML_INSTANCE); + + final STORKAttrQueryRequest attrData= engine.validateSTORKAttrQueryRequest(samlToken); + //SAMLRequest = new String(samlToken); + LOG.trace("Processing doc request done. SAML: " + new String(samlToken)); + return attrData; + } +} diff --git a/DocumentService/src/eu/stork/documentservice/utils/Utils.java b/DocumentService/src/eu/stork/documentservice/utils/Utils.java new file mode 100644 index 000000000..45072a0be --- /dev/null +++ b/DocumentService/src/eu/stork/documentservice/utils/Utils.java @@ -0,0 +1,172 @@ +package eu.stork.documentservice.utils; + +import java.io.BufferedReader; +import java.io.ByteArrayInputStream; +import java.io.DataOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.FileReader; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.UnsupportedEncodingException; +import java.net.HttpURLConnection; +import java.net.URL; + +import org.bouncycastle.util.encoders.Base64; +import org.bouncycastle.util.encoders.UrlBase64; + +public class Utils { + + public static boolean saveData(byte[] data, String PATH, String fileName) + { + boolean ok = false; + if (data != null) + { + try + { + FileOutputStream fos; + File outputDir = new File(PATH); + File saveFile = new File(outputDir, fileName); + fos = new FileOutputStream(saveFile); + fos.write(data); + fos.flush(); + fos.close(); + ok = true; + } + catch (Exception e) + { + e.printStackTrace(); + } + } + return ok; + } + + public static byte[] readData(String fileName) + { + byte[] data = null; + + if (fileName != "") + { + try + { + FileInputStream fis; + File inputDir = new File(fileName); + fis = new FileInputStream(inputDir); + data = new byte[(int)inputDir.length()]; + fis.read(data); + fis.close(); + } + catch (Exception e) + { + e.printStackTrace(); + } + } + + return data; + } + + public static String readString(String fileName) + { + File file = new File(fileName); + StringBuilder text = new StringBuilder(); + + try { + BufferedReader br = new BufferedReader(new FileReader(file)); + String line; + + while ((line = br.readLine()) != null) { + text.append(line); + } + br.close(); + } + catch (Exception e) { + e.printStackTrace(); + } + return text.toString(); + } + + public static InputStream getStream(String string, String codePage) throws UnsupportedEncodingException + { + return new ByteArrayInputStream(string.getBytes(codePage)); + } + + public static String encodeBase64bytes(final byte[] bytes, boolean urlSafe) { + try { + if (urlSafe) + return new String(UrlBase64.encode(bytes), "UTF8"); + else + return new String(Base64.encode(bytes), "UTF8"); + } catch (UnsupportedEncodingException e) { + return null; + } + } + + public static byte[] decodeBase64String(final String base64string, boolean urlSave) { + if (urlSave) + return UrlBase64.decode(base64string); + else + return Base64.decode(base64string); + } + + // HTTP GET request + public static String sendGet(String url) throws Exception + { + URL obj = new URL(url); + HttpURLConnection con = (HttpURLConnection) obj.openConnection(); + + // optional default is GET + con.setRequestMethod("GET"); + + //add request header + con.setRequestProperty("User-Agent", "unknown"); + + //int responseCode = con.getResponseCode(); + + BufferedReader in = new BufferedReader( + new InputStreamReader(con.getInputStream())); + String inputLine; + StringBuffer response = new StringBuffer(); + + while ((inputLine = in.readLine()) != null) { + response.append(inputLine); + } + in.close(); + + return response.toString(); + + } + + // HTTP POST request + public static String sendPost(String url, String urlParameters) throws Exception + { + URL obj = new URL(url); + HttpURLConnection con = (HttpURLConnection) obj.openConnection(); + + //add request header + con.setRequestMethod("POST"); + con.setRequestProperty("User-Agent", "unknown"); + con.setRequestProperty("Accept-Language", "en-US,en;q=0.5"); + + // Send post request + con.setDoOutput(true); + DataOutputStream wr = new DataOutputStream(con.getOutputStream()); + wr.writeBytes(urlParameters); + wr.flush(); + wr.close(); + + //int responseCode = con.getResponseCode(); + + BufferedReader in = new BufferedReader( + new InputStreamReader(con.getInputStream())); + String inputLine; + StringBuffer response = new StringBuffer(); + + while ((inputLine = in.readLine()) != null) { + response.append(inputLine); + } + in.close(); + + return response.toString(); + } +} diff --git a/DocumentService/src/eu/stork/documentservice/utils/XmlHelper.java b/DocumentService/src/eu/stork/documentservice/utils/XmlHelper.java new file mode 100644 index 000000000..cd325db2e --- /dev/null +++ b/DocumentService/src/eu/stork/documentservice/utils/XmlHelper.java @@ -0,0 +1,224 @@ +package eu.stork.documentservice.utils; + +import java.io.InputStream; +import java.util.Properties; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.xpath.XPath; +import javax.xml.xpath.XPathFactory; + +import org.w3c.dom.Document; +import org.w3c.dom.NodeList; +import org.w3c.dom.Node; +import org.w3c.dom.Element; + +//import at.gv.egovernment.moa.id.protocols.stork2.attributeproviders.GetDSSFileAction; + +import eu.stork.documentservice.data.DatabaseConnectorMySQLImpl; +import eu.stork.documentservice.exceptions.DocumentServiceException; + +public class XmlHelper { + + private static Properties props = new Properties(); + + public static String getRequestId(String xmlRequest) throws DocumentServiceException + { + if (xmlRequest == null || xmlRequest.isEmpty()) + throw new DocumentServiceException("XML request is empty"); + else + { + try + { + InputStream is = Utils.getStream(xmlRequest, "UTF-8"); + DocumentBuilder dBuilder = DocumentBuilderFactory.newInstance() + .newDocumentBuilder(); + Document doc = dBuilder.parse(is); + Element reqElement = doc.getDocumentElement(); + String reqId = reqElement.getAttribute("RequestID"); + return reqId.replace("_", ""); + } + catch (Exception ex) + { + throw new DocumentServiceException("Unabled to parse xml.", ex); + } + } + } + + public static String getRequestDocument(String xmlRequest) throws DocumentServiceException + { + if (xmlRequest == null || xmlRequest.isEmpty()) + throw new DocumentServiceException("XML request is empty"); + else + { + try + { + InputStream is = Utils.getStream(xmlRequest, "UTF-8"); + DocumentBuilder dBuilder = DocumentBuilderFactory.newInstance() + .newDocumentBuilder(); + Document doc = dBuilder.parse(is); + String document = ""; + Element req = doc.getDocumentElement(); + NodeList nList0 = req.getChildNodes(); + for (int i = 0; i < nList0.getLength(); i++) + { + Node node = nList0.item(i); + NodeList nList1 = node.getChildNodes(); + for (int j = 0; j < nList1.getLength(); j++) + { + NodeList nList2 = nList1.item(j).getChildNodes(); + for (int k = 0; k < nList2.getLength(); k++) + { + Node docNode =nList2.item(k); + document = docNode.getTextContent(); + } + } + } + return document; + } + catch (Exception ex) + { + throw new DocumentServiceException("Unabled to parse xml.", ex); + } + } + } + + public static String getRequestDocumentData(String xmlRequest) throws DocumentServiceException + { + if (xmlRequest == null || xmlRequest.isEmpty()) + throw new DocumentServiceException("XML request is empty"); + else + { + try + { + InputStream is = Utils.getStream(xmlRequest, "UTF-8"); + DocumentBuilderFactory xmlFactory = DocumentBuilderFactory.newInstance(); + DocumentBuilder docBuilder = xmlFactory.newDocumentBuilder(); + Document xmlDoc = docBuilder.parse(is); + XPathFactory xpathFact = XPathFactory.newInstance(); + XPath xpath = xpathFact.newXPath(); + return xpath.evaluate("/SignRequest/InputDocuments/Document/Base64Data/text()", xmlDoc); + + } + catch (Exception ex) + { + throw new DocumentServiceException("Unabled to parse xml.", ex); + } + } + } + + public static String getRequestDocumentMime(String xmlRequest) throws DocumentServiceException + { + if (xmlRequest == null || xmlRequest.isEmpty()) + throw new DocumentServiceException("XML request is empty"); + else + { + try + { + InputStream is = Utils.getStream(xmlRequest, "UTF-8"); + DocumentBuilderFactory xmlFactory = DocumentBuilderFactory.newInstance(); + DocumentBuilder docBuilder = xmlFactory.newDocumentBuilder(); + Document xmlDoc = docBuilder.parse(is); + XPathFactory xpathFact = XPathFactory.newInstance(); + XPath xpath = xpathFact.newXPath(); + return xpath.evaluate("/SignRequest/InputDocuments/Document/Base64Data/@MimeType", xmlDoc); + + } + catch (Exception ex) + { + throw new DocumentServiceException("Unabled to parse xml.", ex); + } + } + } + + private static String getDocId(String response) throws DocumentServiceException + { + if (response == null || response.isEmpty()) + throw new DocumentServiceException("Response is empty"); + else + { + if (response.contains("docId")) + { + int index = response.indexOf("docId"); + String docText = response.substring(response.indexOf(">" ,index), response.indexOf("<", index)); + String docId = docText.replaceAll("[<>]", ""); //s:label name="docId" value="%{docId}"/ + docId = docId.substring(docId.indexOf("/")+1); + docId = docId.substring(docId.indexOf('/')+1); + return docId.replace("/", ""); + } + else + throw new DocumentServiceException("No document ID in response."); + } + } + + /** + * String the document id + * @param docId the document id to strip + * @return the stripped ID + * @throws DocumentServiceException + */ + public static String StripDocId(String docId) throws DocumentServiceException + { + if (docId == null || docId.isEmpty()) + throw new DocumentServiceException("Doc ID is empty"); + else + { + docId = docId.substring(docId.indexOf("/")+1); + docId = docId.substring(docId.indexOf('/')+1); + return docId.replace("/", ""); + } + } + + public static String verifyRequest(String transferRequest) throws DocumentServiceException + { + if (transferRequest == null || transferRequest.isEmpty()) + throw new DocumentServiceException("Transfer request is empty"); + else + { + try { + String docId=""; + try{ + +// props.load(DatabaseConnectorMySQLImpl.class.getResourceAsStream("docservice.properties")); +// System.out.println("url:"+props.getProperty("peps.url")); + +// final byte[] samlToken = PEPSUtil.decodeSAMLTokenUrlSafe(parameters +// .get(PEPSParameters.SAML_REQUEST.toString())); +// +// final STORKSAMLEngine engine = STORKSAMLEngine.getInstance("VIDP"); +// +// final STORKAttrQueryRequest attrData= engine.validateSTORKAttrQueryRequest(samlToken); + +// String response = Utils.sendPost(props.getProperty("peps.url"), "SAMLRequest=" + transferRequest); +// docId=getDocId(response);; + docId = GetDSSFileAction.processDocRequest(transferRequest); + }catch(Exception e){e.printStackTrace();} + return docId; + //FIXME +// String response = Utils.sendPost(props.getProperty("peps.url"), "SAMLRequest=" + transferRequest); +// return getDocId(response); + } catch (Exception e) { + e.printStackTrace(); + throw new DocumentServiceException("Could verify request.", e); + } + } + } + + public static String verifyRequestByte(byte[] transferRequest) throws DocumentServiceException + { + if (transferRequest == null) + throw new DocumentServiceException("Transfer request is empty"); + else + { + try { + props.load(DatabaseConnectorMySQLImpl.class.getResourceAsStream("docservice.properties")); + String response = Utils.sendPost(props.getProperty("peps.url"),"SAMLRequest=" + Utils.encodeBase64bytes(transferRequest, true)); + return getDocId(response); + } catch (Exception e) { + e.printStackTrace(); + throw new DocumentServiceException("Could not read properties.", e); + } + + } + } +} -- cgit v1.2.3