Axelle wrote: [ snip ]
- how can I build an enveloping signature ? (not an
enveloped one).
I once used enveloping sigs in a project. I pulled the essential code into a testcase and attached it. The exception handling is left to junit in this case.
The build.xml simply creates a keystore with private key and corresponding certificate. The java-file thinks it's in package test.
Put junit.jar and xmlsec.jar on your classpath, compile and run the example.
To look at the XML documents use toString(). My guess was it would give me a [EMAIL PROTECTED], but it actualy prints out element and attrubute names and values.
HTH,
Heiner
/* * No copyright. Use as you see fit. * * Created on 01.02.2005 */ package test;
import java.io.FileInputStream; import java.io.IOException; import java.io.StringReader; import java.security.GeneralSecurityException; import java.security.KeyStore; import java.security.PrivateKey; import java.security.cert.X509Certificate; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.transform.TransformerException; import junit.framework.TestCase; import org.apache.xml.security.c14n.Canonicalizer; import org.apache.xml.security.exceptions.XMLSecurityException; import org.apache.xml.security.keys.content.X509Data; import org.apache.xml.security.keys.content.x509.XMLX509IssuerSerial; import org.apache.xml.security.signature.ObjectContainer; import org.apache.xml.security.signature.XMLSignature; import org.apache.xml.security.transforms.Transforms; import org.apache.xml.security.utils.Constants; import org.w3c.dom.Document; import org.w3c.dom.Node; import org.xml.sax.InputSource; import org.xml.sax.SAXException; /** * Test an enveloping Signature. * * @author [EMAIL PROTECTED] */ public class EnvelopingSignatureTest extends TestCase { static { org.apache.xml.security.Init.init(); } private DocumentBuilder documentBuilder; public static void main(String[] args) { junit.textui.TestRunner.run(EnvelopingSignatureTest.class); } public void setUp() { DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); dbf.setNamespaceAware(true); try { documentBuilder = dbf.newDocumentBuilder(); } catch (ParserConfigurationException e) { e.printStackTrace(); throw new RuntimeException(e); } } public void testEnvelopingXmlSignature() throws Exception { final String keyStoreFileName = "keyncert.jks"; final String keyStorePass = "changeit"; final String privateKeyPass = "changeit"; final String signerId = "testId"; final String payloadDoc = "<root name=\"testdoc\">\n" + " <subelem>\n" + " <subsub name=\"way\"/>\n" + " </subelem>\n" + "</root>\n"; Document doc = documentBuilder .parse(new InputSource(new StringReader(payloadDoc))); KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); keyStore.load(new FileInputStream(keyStoreFileName), keyStorePass.toCharArray()); X509Certificate cert = (X509Certificate) keyStore.getCertificate(signerId); PrivateKey privateKey = (PrivateKey) keyStore.getKey(signerId, privateKeyPass .toCharArray()); Document signedDoc = signEnveloping(doc, "payload", cert, privateKey); assertEquals("Signature", signedDoc.getDocumentElement().getLocalName()); // if you delete the .toString() calls it's not equal. Probably some invisible // namespace issue I do not care about. assertEquals(doc.getDocumentElement().toString(), ((Node) signedDoc.getDocumentElement() .getElementsByTagNameNS("*", "Object").item(0)).getFirstChild().toString()); } private Document signEnveloping(final Document doc, final String objectId, final X509Certificate cert, final PrivateKey privateKey) throws GeneralSecurityException, SAXException, IOException, XMLSecurityException, TransformerException, Exception { Document signedDoc = documentBuilder.newDocument(); String baseUri = null; final String publicKeyAlgorithm = cert.getPublicKey().getAlgorithm(); String signatureMethod; if (publicKeyAlgorithm.equalsIgnoreCase("DSA")) { signatureMethod = XMLSignature.ALGO_ID_SIGNATURE_DSA; } else if (publicKeyAlgorithm.equalsIgnoreCase("RSA")) { signatureMethod = XMLSignature.ALGO_ID_SIGNATURE_RSA; } else { throw new Exception("Unknown public key algorithm '" + publicKeyAlgorithm + "' in certificate."); } XMLSignature sig = new XMLSignature(signedDoc, baseUri, signatureMethod); signedDoc.appendChild(sig.getElement()); ObjectContainer obj = new ObjectContainer(signedDoc); obj.setId(objectId); boolean deepCopy = true; Node payloadElem = signedDoc.importNode(doc.getDocumentElement(), deepCopy); obj.appendChild(payloadElem); sig.appendObject(obj); Transforms transforms = new Transforms(signedDoc); transforms.addTransform(Transforms.TRANSFORM_C14N_WITH_COMMENTS); sig.addDocument("#" + objectId, transforms, Constants.ALGO_ID_DIGEST_SHA1); X509Data x509data = new X509Data(signedDoc); x509data.add(new XMLX509IssuerSerial(signedDoc, cert)); sig.getKeyInfo().add(x509data); sig.sign(privateKey); byte[] canonicalized = Canonicalizer.getInstance( Canonicalizer.ALGO_ID_C14N_WITH_COMMENTS).canonicalizeSubtree(signedDoc); return signedDoc; } }
<?xml version="1.0"?> <project name="Create keystore file" default="gen" basedir="."> <target name="gen"> <genkey alias="testId" keyalg="RSA" keypass="changeit" keystore="keyncert.jks" storepass="changeit" validity="2006"> <dname> <param name="CN" value="test ID"/> <param name="O" value="verit GmbH"/> <param name="L" value="Kaiserslautern"/> <param name="C" value="DE"/> </dname> </genkey> </target> </project>