package de.usd.cstchef.operations.signature; import java.awt.event.ActionEvent; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.PrintWriter; import java.security.KeyStore.PrivateKeyEntry; import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JComboBox; import javax.xml.crypto.dsig.CanonicalizationMethod; import javax.xml.crypto.dsig.DigestMethod; import javax.xml.crypto.dsig.Reference; import javax.xml.crypto.dsig.SignatureMethod; import javax.xml.crypto.dsig.SignedInfo; import javax.xml.crypto.dsig.Transform; import javax.xml.crypto.dsig.XMLSignature; import javax.xml.crypto.dsig.XMLSignatureFactory; import javax.xml.crypto.dsig.dom.DOMSignContext; import javax.xml.crypto.dsig.keyinfo.KeyInfo; import javax.xml.crypto.dsig.keyinfo.KeyInfoFactory; import javax.xml.crypto.dsig.keyinfo.X509Data; import javax.xml.crypto.dsig.spec.C14NMethodParameterSpec; import javax.xml.crypto.dsig.spec.TransformParameterSpec; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import javax.xml.xpath.XPath; import javax.xml.xpath.XPathConstants; import javax.xml.xpath.XPathExpression; import javax.xml.xpath.XPathFactory; import org.w3c.dom.Attr; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NodeList; import de.usd.cstchef.operations.Operation.OperationInfos; import de.usd.cstchef.operations.OperationCategory; import de.usd.cstchef.view.ui.FormatTextField; @OperationInfos(name = "Soap Multi Signature", category = OperationCategory.ENCRYPTION, description = "Create a Soap signature.") public class SoapMultiSignature extends KeystoreOperation { public SoapMultiSignature() { super(); this.digestMethods.put("sha1", DigestMethod.SHA1); this.digestMethods.put("sha256", DigestMethod.SHA256); this.digestMethods.put("sha512", DigestMethod.SHA512); this.signatureMethods.put("rsa-sha1", SignatureMethod.RSA_SHA1); this.createMyUI(); } protected HashMap<String, String> digestMethods = new HashMap<String,String>(); protected HashMap<String, String> signatureMethods = new HashMap<String,String>(); //"rsa-sha256", SignatureMethod.RSA_SHA256, //"rsa-sha512", SignatureMethod.RSA_SHA512 protected String[] availDigestMethods = new String[] {"sha1", "sha256", "sha512"}; protected String[] availSignatureMethods = new String[] {"rsa-sha1"};//, "rsa-sha256", "rsa-sha512"}; protected String[] includeKeyInfos = new String[] { "true", "false" }; protected JComboBox<String> includeKeyInfo; protected JComboBox<String> signatureMethod; protected JComboBox<String> digestMethod; protected JButton addReferenceButton; protected FormatTextField idIdentifier; protected ArrayList<FormatTextField> referenceFields = new ArrayList<FormatTextField>(); protected JCheckBox certificate; protected JCheckBox subject; protected JCheckBox issuer; protected JCheckBox serialIssuer; private ArrayList<Reference> getReferences(XMLSignatureFactory fac) throws Exception { String digMethod = (String) digestMethod.getSelectedItem(); ArrayList<Reference> referenceList = new ArrayList<Reference>(); if( referenceFields != null && referenceFields.size() > 0) { PrintWriter writer = new PrintWriter("/tmp/test", "UTF-8"); writer.println("test"); writer.close(); for( FormatTextField field : referenceFields ) { String referenceString = new String(field.getText()); Reference ref = fac.newReference("#" + referenceString, fac.newDigestMethod(digestMethods.get(digMethod), null), Collections.singletonList (fac.newTransform(Transform.ENVELOPED, (TransformParameterSpec) null)), null, null); referenceList.add(ref); } } else { Reference ref = fac.newReference("", fac.newDigestMethod(digestMethods.get(digMethod), null), Collections.singletonList (fac.newTransform(Transform.ENVELOPED, (TransformParameterSpec) null)), null, null); referenceList.add(ref); } return referenceList; } private void validateIdAttributes(Document doc) throws Exception { String idAttribute = new String(idIdentifier.getText()); XPathFactory xPathfactory = XPathFactory.newInstance(); XPath xpath = xPathfactory.newXPath(); XPathExpression expr = xpath.compile("descendant-or-self::*/@" + idAttribute); NodeList nodeList = (NodeList) expr.evaluate(doc, XPathConstants.NODESET); if(nodeList != null && nodeList.getLength() > 0) { for(int j = 0; j < nodeList.getLength(); j++) { Attr attr = (Attr)nodeList.item(j); ((Element)attr.getOwnerElement()).setIdAttributeNode(attr,true); } } } private KeyInfo getKeyInfo(XMLSignatureFactory fac, PrivateKeyEntry keyEntry) throws Exception { String keyInfoChoice = (String) includeKeyInfo.getSelectedItem(); if( Boolean.parseBoolean(keyInfoChoice) ) { KeyInfo keyInfo; X509Certificate cert = (X509Certificate)keyEntry.getCertificate(); KeyInfoFactory keyInfoFac = fac.getKeyInfoFactory(); List<Object> x509Content = new ArrayList<Object>(); if( this.subject.isSelected() ) { x509Content.add(cert.getSubjectX500Principal().getName()); } if( this.serialIssuer.isSelected() ) { x509Content.add(keyInfoFac.newX509IssuerSerial(cert.getIssuerX500Principal().getName(),cert.getSerialNumber())); } if( this.issuer.isSelected() ) { x509Content.add(cert.getIssuerX500Principal().getName()); } if( this.certificate.isSelected() ) { x509Content.add(cert); } X509Data xd = keyInfoFac.newX509Data(x509Content); keyInfo = keyInfoFac.newKeyInfo(Collections.singletonList(xd)); return keyInfo; } return (KeyInfo)null; } protected byte[] perform(byte[] input) throws Exception { String signMethod = (String)signatureMethod.getSelectedItem(); PrivateKeyEntry keyEntry = this.selectedEntry; XMLSignatureFactory fac = XMLSignatureFactory.getInstance("DOM"); ArrayList<Reference> references = getReferences(fac); SignedInfo signatureInfo = fac.newSignedInfo(fac.newCanonicalizationMethod(CanonicalizationMethod.INCLUSIVE, (C14NMethodParameterSpec)null), fac.newSignatureMethod(signatureMethods.get(signMethod), null), references); KeyInfo keyInfo = this.getKeyInfo(fac, keyEntry); XMLSignature signature = fac.newXMLSignature(signatureInfo, keyInfo); DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); dbf.setNamespaceAware(true); Document doc = dbf.newDocumentBuilder().parse(new ByteArrayInputStream(input)); try { validateIdAttributes(doc); } catch( Exception e ) { throw new IllegalArgumentException("Provided Id identifier seems to be invalid."); } DOMSignContext dsc = new DOMSignContext (keyEntry.getPrivateKey(), doc.getDocumentElement()); signature.sign(dsc); DOMSource source = new DOMSource(doc); ByteArrayOutputStream bos = new ByteArrayOutputStream(); StreamResult result = new StreamResult(bos); TransformerFactory transformerFactory = TransformerFactory.newInstance(); Transformer transformer = transformerFactory.newTransformer(); transformer.transform(source, result); return bos.toByteArray(); } public void createMyUI() { super.createMyUI(); this.includeKeyInfo = new JComboBox<>(this.includeKeyInfos); this.includeKeyInfo.addActionListener(this); this.addUIElement("IncludeKeyInfo", this.includeKeyInfo); this.certificate = new JCheckBox("Include Certificate"); this.certificate.setSelected(false); this.certificate.addActionListener(this); this.addUIElement(null, this.certificate); this.subject = new JCheckBox("Include Subject"); this.subject.setSelected(false); this.subject.addActionListener(this); this.addUIElement(null, this.subject); this.issuer = new JCheckBox("Include Issuer"); this.issuer.setSelected(false); this.issuer.addActionListener(this); this.addUIElement(null, this.issuer); this.serialIssuer = new JCheckBox("Include Issuer"); this.serialIssuer.setSelected(false); this.serialIssuer.addActionListener(this); this.addUIElement(null, this.serialIssuer); this.digestMethod = new JComboBox<String>(this.availDigestMethods); this.digestMethod.addActionListener(this); this.addUIElement("DigestMethod", this.digestMethod); this.signatureMethod = new JComboBox<String>(this.availSignatureMethods); this.signatureMethod.addActionListener(this); this.addUIElement("SignatureMethod", this.signatureMethod); this.idIdentifier = new FormatTextField(); this.addUIElement("Identifier", this.idIdentifier); addReferenceButton = new JButton("Add Reference"); addReferenceButton.addActionListener(this); this.addUIElement(null, addReferenceButton); } public void actionPerformed(ActionEvent arg0) { if( arg0.getSource() == addReferenceButton ) { FormatTextField tmpRef = new FormatTextField(); this.addUIElement("Reference", tmpRef); referenceFields.add(tmpRef); } else if( arg0.getSource() == this.includeKeyInfo) { String keyInfoChoice = (String) includeKeyInfo.getSelectedItem(); if(!Boolean.parseBoolean(keyInfoChoice) ) { this.certificate.setVisible(false); this.subject.setVisible(false); this.issuer.setVisible(false); this.serialIssuer.setVisible(false); } else { this.certificate.setVisible(true); this.subject.setVisible(true); this.issuer.setVisible(true); this.serialIssuer.setVisible(true); } } super.actionPerformed(arg0); } }