/*
* JBoss, Home of Professional Open Source.
* Copyright 2012, Red Hat Middleware LLC, and individual contributors
* as indicated by the @author tags. See the copyright.txt file in the
* distribution for a full listing of individual contributors.
*
* This 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 2.1 of
* the License, or (at your option) any later version.
*
* This software 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 software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jboss.as.test.integration.ws.wsse.crypto;
import org.w3c.dom.Document;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.crypto.AlgorithmMethod;
import javax.xml.crypto.KeySelector;
import javax.xml.crypto.KeySelectorException;
import javax.xml.crypto.KeySelectorResult;
import javax.xml.crypto.XMLCryptoContext;
import javax.xml.crypto.dsig.CanonicalizationMethod;
import javax.xml.crypto.dsig.DigestMethod;
import javax.xml.crypto.dsig.Reference;
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.dom.DOMValidateContext;
import javax.xml.crypto.dsig.keyinfo.KeyInfo;
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.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.IOException;
import java.io.StringReader;
import java.security.Key;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.util.Collections;
@WebServlet(name = "TestServlet", urlPatterns = "/*")
public class TestServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
try {
final Document document = createDocument();
final KeyPair keyPair = createKeyPair();
signDocument(document, keyPair.getPrivate());
if (validateSignature(document, keyPair.getPublic())) {
res.getWriter().print("OK");
} else {
res.getWriter().print("null");
}
} catch (Exception e) {
res.getWriter().println(e.getClass() + ": " + e.getMessage());
}
}
private static boolean validateSignature(final Document document, final PublicKey publicKey) throws Exception {
final KeySelector ks = new KeySelector() {
@Override
public KeySelectorResult select(KeyInfo keyInfo, Purpose purpose, AlgorithmMethod method, XMLCryptoContext context) throws KeySelectorException {
return new KeySelectorResult() {
public Key getKey() {
return publicKey;
}
};
}
};
final DOMValidateContext context = new DOMValidateContext(ks, document.getElementsByTagNameNS(XMLSignature.XMLNS, "Signature").item(0));
return XMLSignatureFactory.getInstance("DOM").unmarshalXMLSignature(context).validate(context);
}
private static void signDocument(final Document doc, final PrivateKey privateKey) throws Exception {
final XMLSignatureFactory xsf = XMLSignatureFactory.getInstance("DOM");
final Reference ref = xsf.newReference(
"",
xsf.newDigestMethod(DigestMethod.SHA256, null),
Collections.singletonList(xsf.newTransform(Transform.ENVELOPED, (TransformParameterSpec) null)),
null,
null);
final SignedInfo si = xsf.newSignedInfo(xsf.newCanonicalizationMethod(CanonicalizationMethod.EXCLUSIVE,
(C14NMethodParameterSpec) null),
xsf.newSignatureMethod("http://www.w3.org/2001/04/xmldsig-more#rsa-sha256", null),
Collections.singletonList(ref));
final KeyInfo ki = KeyInfoFactory.getInstance().newKeyInfo(Collections.singletonList(KeyInfoFactory.getInstance().newKeyName("dummy")));
xsf.newXMLSignature(si, ki).sign(new DOMSignContext(privateKey, doc.getDocumentElement()));
}
private static Document createDocument() throws IOException, SAXException, ParserConfigurationException {
return DocumentBuilderFactory
.newInstance()
.newDocumentBuilder()
.parse(new InputSource(new StringReader("<dummy dummy=\"dummy\"/>")));
}
private static KeyPair createKeyPair() throws NoSuchAlgorithmException {
return KeyPairGenerator.getInstance("RSA").generateKeyPair();
}
}