package art.servers.gost.atex5; import art.servers.gost.access.configuration.Configuration; import art.servers.gost.access.configuration.ConfigurationDetail_ATEX5; import java.io.ByteArrayOutputStream; import java.util.Base64; import org.w3c.dom.Document; import org.xml.sax.SAXException; import javax.xml.crypto.dom.DOMStructure; import javax.xml.crypto.dsig.Reference; import javax.xml.crypto.dsig.SignedInfo; import javax.xml.crypto.dsig.Transform; import javax.xml.crypto.dsig.XMLSignatureFactory; import javax.xml.crypto.dsig.dom.DOMSignContext; import javax.xml.crypto.dsig.keyinfo.KeyInfoFactory; import javax.xml.crypto.dsig.spec.C14NMethodParameterSpec; import javax.xml.crypto.dsig.spec.TransformParameterSpec; import javax.xml.parsers.ParserConfigurationException; import javax.xml.soap.*; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.OutputStream; import java.security.KeyStore; import java.security.PrivateKey; import java.security.Provider; import java.security.cert.Certificate; import java.util.ArrayList; public class RequestXML { protected static Document readInXMLFile() throws ParserConfigurationException, SAXException, IOException { return null; } protected static SOAPMessage createSOAPEnvelope(Document xmlDocument) throws SOAPException { // Create SOAP Message MessageFactory messageFactory = MessageFactory.newInstance(SOAPConstants.SOAP_1_1_PROTOCOL); SOAPMessage soapMessage = messageFactory.createMessage(); soapMessage.setProperty(SOAPMessage.CHARACTER_SET_ENCODING, "UTF-8"); soapMessage.setProperty(SOAPMessage.WRITE_XML_DECLARATION, "true"); SOAPEnvelope soapEnvelope = soapMessage.getSOAPPart().getEnvelope(); // Add DOM object to SOAP body SOAPBody soapBody = soapMessage.getSOAPBody(); soapBody.addDocument(xmlDocument); soapBody.addAttribute(soapEnvelope.createName("Id", "wsu", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"), "Body"); return soapMessage; } protected static SOAPMessage signSOAPMessage(SOAPMessage soapMessage) throws Exception { // Create the security element SOAPElement soapHeader = soapMessage.getSOAPHeader(); SOAPElement securityElement = soapHeader.addChildElement("Security", "wsse", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"); securityElement.addNamespaceDeclaration("wsu", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"); // (i) Extract the certificate java.security.cert.Certificate cert = getCertificate(); // (ii) Add Binary Security Token. The base64 encoded value of the ROS digital certificate. addBinarySecurityToken(securityElement, cert); //(iii) Add Timestamp element //SOAPElement timestamp = addTimestamp(securityElement, soapMessage); // (iv) Add signature element addSignature(securityElement, soapMessage.getSOAPBody()); return soapMessage; } protected static java.security.cert.Certificate getCertificate() throws Exception { Configuration configuration = ((Configuration)art.servers.gost.access.Shared.configuration); ConfigurationDetail_ATEX5 configurationATEX5 = configuration.detail.atex5; KeyStore keystore = KeyStore.getInstance(configurationATEX5.keystoreType); char[] password = new char[configurationATEX5.keystorePassword.length()]; configurationATEX5.keystorePassword.getChars(0, configurationATEX5.keystorePassword.length(), password, 0); keystore.load(new FileInputStream(configuration.detail.atex5.keystoreLocation), password); KeyStore.PrivateKeyEntry keyEntry = (KeyStore.PrivateKeyEntry)keystore.getEntry(configurationATEX5.certificateAlias, new KeyStore.PasswordProtection(configurationATEX5.certificatePassword.toCharArray())); Certificate cert = keyEntry.getCertificate(); return cert; } protected static SOAPElement addBinarySecurityToken(SOAPElement securityElement, java.security.cert.Certificate cert) throws Exception { // Get byte array of cert. byte[] certByte = cert.getEncoded(); // Add the Binary Security Token element SOAPElement binarySecurityToken = securityElement.addChildElement("BinarySecurityToken", "wsse"); binarySecurityToken.setAttribute("ValueType", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3"); binarySecurityToken.setAttribute("EncodingType", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary"); binarySecurityToken.setAttribute("wsu:Id", "X509Token"); binarySecurityToken.addTextNode(Base64.getEncoder().encodeToString(certByte)); return securityElement; } protected static SOAPElement addSignature(SOAPElement securityElement, SOAPBody soapBody) throws Exception { // Get private key from ROS digital certificate PrivateKey key = getKeyFormCert(); SOAPElement securityTokenReference = addSecurityToken(securityElement); // Add signature createDetachedSignature(securityElement, key, securityTokenReference, soapBody); return securityElement; } protected static PrivateKey getKeyFormCert() throws Exception { Configuration configuration = ((Configuration)art.servers.gost.access.Shared.configuration); ConfigurationDetail_ATEX5 configurationATEX5 = configuration.detail.atex5; KeyStore keystore = KeyStore.getInstance(configurationATEX5.keystoreType); char[] password = new char[configurationATEX5.keystorePassword.length()]; configurationATEX5.keystorePassword.getChars(0, configurationATEX5.keystorePassword.length(), password, 0); keystore.load(new FileInputStream(configurationATEX5.keystoreLocation), password); KeyStore.PrivateKeyEntry keyEntry = (KeyStore.PrivateKeyEntry)keystore.getEntry(configurationATEX5.certificateAlias, new KeyStore.PasswordProtection(configurationATEX5.certificatePassword.toCharArray())); return keyEntry.getPrivateKey(); } protected static SOAPElement addSecurityToken(SOAPElement signature) throws SOAPException { SOAPElement securityTokenReference = signature.addChildElement("SecurityTokenReference", "wsse"); SOAPElement reference = securityTokenReference.addChildElement("Reference", "wsse"); reference.setAttribute("URI", "#X509Token"); return securityTokenReference; } protected static void createDetachedSignature(SOAPElement signatureElement, PrivateKey privateKey, SOAPElement securityTokenReference, SOAPBody soapBody) throws Exception { String providerName = System.getProperty("jsr105Provider", "org.jcp.xml.dsig.internal.dom.XMLDSigRI"); XMLSignatureFactory xmlSignatureFactory = XMLSignatureFactory.getInstance("DOM",(Provider) Class.forName(providerName).newInstance()); //Digest method javax.xml.crypto.dsig.DigestMethod digestMethod = xmlSignatureFactory.newDigestMethod("http://www.w3.org/2000/09/xmldsig#sha1", null); ArrayList transformList = new ArrayList(); //Transform Transform envTransform = xmlSignatureFactory.newTransform("http://www.w3.org/2001/10/xml-exc-c14n#", (TransformParameterSpec) null); transformList.add(envTransform); //References ArrayList refList = new ArrayList(); Reference refBody = xmlSignatureFactory.newReference("#Body", digestMethod, transformList, null, null); refList.add(refBody); javax.xml.crypto.dsig.CanonicalizationMethod cm = xmlSignatureFactory.newCanonicalizationMethod("http://www.w3.org/2001/10/xml-exc-c14n#",(C14NMethodParameterSpec) null); javax.xml.crypto.dsig.SignatureMethod sm = xmlSignatureFactory.newSignatureMethod("http://www.w3.org/2000/09/xmldsig#rsa-sha1", null); SignedInfo signedInfo = xmlSignatureFactory.newSignedInfo(cm, sm, refList); DOMSignContext signContext = new DOMSignContext(privateKey, signatureElement); signContext.setDefaultNamespacePrefix("ds"); signContext.putNamespacePrefix("http://www.w3.org/2000/09/xmldsig#", "ds"); //These are required for new Java versions signContext.setIdAttributeNS(soapBody,"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd", "Id"); KeyInfoFactory keyFactory = KeyInfoFactory.getInstance(); DOMStructure domKeyInfo = new DOMStructure(securityTokenReference); javax.xml.crypto.dsig.keyinfo.KeyInfo keyInfo = keyFactory.newKeyInfo(java.util.Collections.singletonList(domKeyInfo)); javax.xml.crypto.dsig.XMLSignature signature = xmlSignatureFactory.newXMLSignature(signedInfo, keyInfo); signContext.setBaseURI(""); signature.sign(signContext); } protected static String outputSOAPMessageToString(SOAPMessage soapMessage) throws SOAPException, IOException { ByteArrayOutputStream bos = new ByteArrayOutputStream(); soapMessage.writeTo(bos); String result = new String(bos.toByteArray()); bos.close(); return result; } protected static void outputSOAPMessageToScreen(SOAPMessage soapMessage) throws SOAPException, IOException { OutputStream os = System.out; soapMessage.writeTo(os); } protected static void outputSOAPMessageToFile(SOAPMessage soapMessage, File outputFile) throws SOAPException, IOException { java.io.FileOutputStream fos = new java.io.FileOutputStream(outputFile); soapMessage.writeTo(fos); fos.close(); } }