Xml digital signatures with X 509 certificate in Java
A tutorial on how to create xml digital signatures
XML digital signatures are mainly used for authentication of the sender, to ensure data integrity,to prevent modification of the data during transmission etc.In this tutorial we will see how to create XML Digital Signatures and how to use them in order to sign xml documents.
An xml digital signature consists of several elements.The structure of the signature is shown in the below snippet
<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
<SignedInfo>
<CanonicalizationMethod />
<SignatureMethod />
<Reference URI="">
<Transforms>
<Transform />
</Transforms>
<DigestMethod />
<DigestValue></DigestValue>
</Reference>
</SignedInfo>
<SignatureValue>
</SignatureValue>
<KeyInfo>
<X509Data>
<X509Certificate/>
</X509Data>
<KeyValue>
<RSAKeyValue>
<Modulus>
</Modulus>
<Exponent/>
</RSAKeyValue>
</KeyValue>
</KeyInfo>
</Signature>
Before we proceed in the implementation lets see the meaning of the above mentioned elements:
SignedInfo:A container element that consists of the canonicalization algorithm,the signature algorithm and one or more references.
CanonicalizationMethod: Defines the canocalization algorithm that will be used
Signature Method: Defines the algorithm that will be used for creating and validating the signature
Reference:A container element that contains the digest algorithm and value and also the trasformations that can be applied to the data before digesting.
Transforms:Also a container element that contains the transformations that will be applied to the data.
DigestMethod:Specifies the hashing algorithm for the digest calculation
Digest Value:Contains the digest value in an encoded form
KeyInfo:This element contain all the appropriate data such as keys and certificates that the recipients of the document can use for validating the document.In the above mentioned signature keyInfo elements contain the X509 certifcate and RSA key data.
In this example we will use RSA-SHA1 as a signature method and also a keystore file (.ks) from which we will take the needed data for the X509 certificate.
package com.javaonly.xmlDigitalSignatures;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.InvalidAlgorithmParameterException;
import java.security.KeyException;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.KeyStore;
import java.security.KeyStore.Entry;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.Provider;
import java.security.UnrecoverableEntryException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.Collections;
import javax.xml.crypto.MarshalException;
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.XMLSignatureException;
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.KeyValue;
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.parsers.ParserConfigurationException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document;
import org.xml.sax.SAXException;
public class XMLDigitalSignatureTest {
public static void main(String args[]) {
String providerName = System.getProperty("jsr105Provider", "org.jcp.xml.dsig.internal.dom.XMLDSigRI");
try {
XMLSignatureFactory factory = XMLSignatureFactory.getInstance("DOM", (Provider) Class.forName(providerName).newInstance());
DigestMethod digestMethod = factory.newDigestMethod(DigestMethod.SHA1, null);
Transform transform = factory.newTransform(Transform.ENVELOPED, (TransformParameterSpec) null);
Reference reference = factory.newReference("", digestMethod, Collections.singletonList(transform), null, null);
CanonicalizationMethod canonicalizationMethod = factory.newCanonicalizationMethod(CanonicalizationMethod.INCLUSIVE_WITH_COMMENTS, (C14NMethodParameterSpec) null);
SignatureMethod signatureMethod = factory.newSignatureMethod(SignatureMethod.RSA_SHA1, null);
SignedInfo signedInfo = factory.newSignedInfo(canonicalizationMethod, signatureMethod, Collections.singletonList(reference));
KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
kpg.initialize(512);
KeyPair keyPair = kpg.generateKeyPair();
KeyInfoFactory keyInfoFactory = factory.getKeyInfoFactory();
KeyStore keyStore = KeyStore.getInstance("JKS");
keyStore.load(new FileInputStream("C:\\keystore.ks"), null);
KeyStore.TrustedCertificateEntry entry = (KeyStore.TrustedCertificateEntry) keyStore.getEntry("gw2test", null);
KeyValue keyValue = keyInfoFactory.newKeyValue(entry.getTrustedCertificate().getPublicKey());
X509Certificate cert = (X509Certificate) entry.getTrustedCertificate();
List x509 = new ArrayList();
x509.add(cert);
X509Data x509Data = keyInfoFactory.newX509Data(x509);
List items = new ArrayList();
items.add(x509Data);
items.add(keyValue);
KeyInfo keyInfo = keyInfoFactory.newKeyInfo(items);
DocumentBuilderFactory dbf =
DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(true);
Document doc =
dbf.newDocumentBuilder().
parse(new FileInputStream("C:\\XmlFile.xml"));
DOMSignContext dsc = new DOMSignContext(keyPair.getPrivate(), doc.getDocumentElement());
XMLSignature signature = factory.newXMLSignature(signedInfo, keyInfo);
signature.sign(dsc);
TransformerFactory tf = TransformerFactory.newInstance();
Transformer transformer = tf.newTransformer();
transformer.transform(
new DOMSource(doc),
new StreamResult(
new FileOutputStream("C:\\mySignedFile.xml")));
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvalidAlgorithmParameterException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (KeyException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (TransformerException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SAXException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ParserConfigurationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (MarshalException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (XMLSignatureException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (KeyStoreException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (CertificateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (UnrecoverableEntryException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Finally the result signature will be something like this:
<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
<SignedInfo>
<CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments"/>
<SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
<Reference URI="">
<Transforms>
<Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
</Transforms>
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<DigestValue>Nrrv6wLNZV/uuy0dJUR5GDhsLE3=</DigestValue>
</Reference>
</SignedInfo>
<SignatureValue>aq4zp8gmb16+YPFYC6OrSR9WAQDo3aXsK+XqLO3ZPUPn4LA3+WpI75eUeajDlrYM9CNZtIGAQb2n
trZVVC6EMA==
</SignatureValue>
<KeyInfo>
<X509Data>
<X509Certificate>MIIHnTCCBgGgAwIBAgIIWqsaODRqwXQwDQYJKoZIhvcNAQEFBQAwdjELMAkGA1UEBhMCREUxJTAj
BgNVBAoTHFQtU3lzdGVtcyBJbnRlcm5hdGlvbmFsIEdtYkgxHjAcBgNVBAsTFVRydXN0IENlbnRl
ciBTZXJ2aWNlczEgMB4GA1UEAxMXVGVsZVNlYyBTZXJ2ZXJQYXNzIENBIDEwHhcNMTIwNTA3MTA1
NDE4WhcNMTQwNTEyMjM1OTU5WjCBwDELMAkGA1UEBhMCREUxGjAYBgNVBAoTEVNDSFVGQSBIb2xk
aW5nIEFHMRYwFAYDVQQLEw1TeXN0ZW10ZWNobmlrMQ8wDQYDVQQIEwZIZXNzZW4xEjAQBgNVBAcT
CVdJRVNCQURFTjEyMDAGCSqGSIb3DQEJARYjemVydGlmaWthdGUtc3lzdGVtdGVjaG5pa0BzY2h1
ZmEuZGUxJDAiBgNVBAMTG3htbDItZ2F0ZXdheS10ZXN0LnNjaHVmYS5kZTCCASIwDQYJKoZIhvcN
AQEBBQADggEPADCCAQoCggEBAMdWBkF1V2MknNA1N4ZWxesjDFkugVWVpxOw0QgV/+nwjACxA4N/
AODwaid9SIbs6e0JRD7J0IZTAmJkZjlAOjB3V4zRujfwG0ZoiLtq7iFcbqMyEJ4mimTONAK3heHR
nGeqt493/4zbl0LL5fY6+xx+XfMYvuTo+t2/pbaSMAU5pISdfeE1kAHHgneUaqKcWv1fb/EHFvDf
E4LowCbcg/dALeclWg0chtlS6FztQyWQPf+t5xC0dsIWHK71PKM64kVF7H6ir0ghzXU2hGpSkfi2
KqxPzWb0JJ4s/5eCIeD51KXTkD1ejTK+9NeeQBY3tztEy2mmsbZugmGzd/ILKa0CAwEAAaOCA14w
ggNaMB8GA1UdIwQYMBaAFDPcnpbs2Og1H22QGws4pK90G8ZYMA4GA1UdDwEB/wQEAwIFoDAdBgNV
HSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwHQYDVR0OBBYEFLgJPSExww0ePqWbKkXBr+A6S0v1
ME8GA1UdIARIMEYwRAYJKwYBBAG9Rw0CMDcwNQYIKwYBBQUHAgEWKWh0dHA6Ly93d3cudGVsZXNl
Yy5kZS9zZXJ2ZXJwYXNzL2Nwcy5odG1sMIIBIgYDVR0fBIIBGTCCARUwRaBDoEGGP2h0dHA6Ly9j
cmwuc2VydmVycGFzcy50ZWxlc2VjLmRlL3JsL1RlbGVTZWNfU2VydmVyUGFzc19DQV8xLmNybDCB
y6CByKCBxYaBwmxkYXA6Ly9sZGFwLnNlcnZlcnBhc3MudGVsZXNlYy5kZS9jbj1UZWxlU2VjJTIw
U2VydmVyUGFzcyUyMENBJTIwMSxvdT1UcnVzdCUyMENlbnRlciUyMFNlcnZpY2VzLG89VC1TeXN0
ZW1zJTIwSW50ZXJuYXRpb25hbCUyMEdtYkgsYz1kZT9jZXJ0aWZpY2F0ZVJldm9jYXRpb25saXN0
P2Jhc2U/Y2VydGlmaWNhdGVSZXZvY2F0aW9ubGlzdD0qMIIBOgYIKwYBBQUHAQEEggEsMIIBKDAz
BggrBgEFBQcwAYYnaHR0cDovL29jc3Auc2VydmVycGFzcy50ZWxlc2VjLmRlL29jc3ByMEwGCCsG
AQUFBzAChkBodHRwOi8vY3JsLnNlcnZlcnBhc3MudGVsZXNlYy5kZS9jcnQvVGVsZVNlY19TZXJ2
ZXJQYXNzX0NBXzEuY2VyMIGiBggrBgEFBQcwAoaBlWxkYXA6Ly9sZGFwLnNlcnZlcnBhc3MudGVs
ZXNlYy5kZS9jbj1UZWxlU2VjJTIwU2VydmVyUGFzcyUyMENBJTIwMSxvdT1UcnVzdCUyMENlbnRl
ciUyMFNlcnZpY2VzLG89VC1TeXN0ZW1zJTIwSW50ZXJuYXRpb25hbCUyMEdtYkgsYz1kZT9jQUNl
cnRpZmljYXRlMAwGA1UdEwEB/wQCMAAwJgYDVR0RBB8wHYIbeG1sMi1nYXRld2F5LXRlc3Quc2No
dWZhLmRlMA0GCSqGSIb3DQEBBQUAA4IBAQByK84EpA5BZ6pbIQIC36lKWH1nZmmBopEjgkX5rg6n
6M3H9BwPmDX9VqyelnDfhQbG15pUzX/cC1rF0oISCO9ILs5YgNe4iaBfoHEH2P1w/sUdnPkE8nlo
5c4frnHTLdRLdPiAsRe9RTxahEwxZOxvebu7eHAPIuo+vuOPnGYIv5a+OGDkqD6snt+RKA7z3XDZ
ZRZXuu8mubhKCMT7n+pxQOznvSzkzbyfL5H1FUlo/697g7bij6BgTYm55bnZ2wdtTMS0F9FLnuSF
h8hVJKlNmVuhSS4eqmwFmYTi7dLeHwe/i6hk9/TQ7+iF92JbhPbnTYupdFBIkS1jZDA1zY0N
</X509Certificate>
</X509Data>
<KeyValue>
<RSAKeyValue>
<Modulus>x1YGQXVXYySc0DU3hlbF6yMMWS6BVZWnE7DRCBX/6fCMALEDg38A4PBqJ31Ihuzp7QlEPsnQhlMC
YmRmOUA6MHdXjNG6N/AbRmiIu2ruIVxuozIQniaKZM40AreF4dGcZ6q3j3f/jNuXQsvl9jr7HH5d
8xi+5Oj63b+ltpIwBTmkhJ194TWQAceCd5Rqopxa/V9v8QcW8N8TgujAJtyD90At5yVaDRyG2VLo
XO1DJZA9/63nELR2whYcrvU8ozriRUXsfqKvSCHNdTaEalKR+LYqrE/NZvQkniz/l4Ih4PnUpdOQ
PV6NMr70155AFje3O0TLaaaxtm6CYbN38gsprQ==
</Modulus>
<Exponent>AQAB</Exponent>
</RSAKeyValue>
</KeyValue>
</KeyInfo>
</Signature>
Copyright © 2012 Design and Development Nikos Lianeris

- 21

- 1




