Skip to content

Commit 38c2320

Browse files
committed
Code cleanup.
1 parent 107a03c commit 38c2320

File tree

2 files changed

+157
-188
lines changed

2 files changed

+157
-188
lines changed

src/main/java/ro/kuberam/libs/java/crypto/digitalSignature/GenerateSignature.java

Lines changed: 151 additions & 186 deletions
Original file line numberDiff line numberDiff line change
@@ -19,24 +19,22 @@
1919
*/
2020
package ro.kuberam.libs.java.crypto.digitalSignature;
2121

22-
import java.io.*;
23-
import java.nio.file.Files;
24-
import java.nio.file.Paths;
22+
import java.io.InputStream;
2523
import java.security.KeyPair;
2624
import java.security.KeyPairGenerator;
2725
import java.security.KeyStore;
2826
import java.security.PrivateKey;
2927
import java.security.PublicKey;
3028
import java.security.Signature;
3129
import java.security.cert.X509Certificate;
32-
import java.util.*;
30+
import java.util.ArrayList;
31+
import java.util.Arrays;
32+
import java.util.Collections;
33+
import java.util.List;
3334

3435
import javax.xml.crypto.XMLStructure;
3536
import javax.xml.crypto.dom.DOMStructure;
36-
import javax.xml.crypto.dsig.CanonicalizationMethod;
37-
import javax.xml.crypto.dsig.DigestMethod;
3837
import javax.xml.crypto.dsig.Reference;
39-
import javax.xml.crypto.dsig.SignatureMethod;
4038
import javax.xml.crypto.dsig.SignedInfo;
4139
import javax.xml.crypto.dsig.Transform;
4240
import javax.xml.crypto.dsig.XMLObject;
@@ -52,7 +50,6 @@
5250
import javax.xml.crypto.dsig.spec.TransformParameterSpec;
5351
import javax.xml.crypto.dsig.spec.XPathFilterParameterSpec;
5452
import javax.xml.parsers.DocumentBuilderFactory;
55-
import javax.xml.parsers.ParserConfigurationException;
5653
import javax.xml.xpath.XPath;
5754
import javax.xml.xpath.XPathConstants;
5855
import javax.xml.xpath.XPathExpression;
@@ -64,193 +61,161 @@
6461
import org.w3c.dom.bootstrap.DOMImplementationRegistry;
6562
import org.w3c.dom.ls.DOMImplementationLS;
6663
import org.w3c.dom.ls.LSSerializer;
67-
import org.xml.sax.InputSource;
68-
import org.xml.sax.SAXException;
6964

7065
public class GenerateSignature {
7166

72-
public static byte[] generateSignature(final byte[] data, final PrivateKey key, final String algorithm, String provider)
73-
throws Exception {
74-
final Signature signer = Signature.getInstance(algorithm);
75-
signer.initSign(key);
76-
signer.update(data);
77-
return signer.sign();
78-
}
79-
80-
public static String GenerateDigitalSignature(final org.w3c.dom.Document inputDoc,
81-
final String canonicalizationAlgorithmURI, final String digestAlgorithmURI, final String signatureAlgorithmURI,
82-
final String keyPairAlgorithm, final String signatureNamespacePrefix, final String signatureType,
83-
final String xpathExprString, final String[] certificateDetails, final InputStream keyStoreInputStream)
84-
throws Exception {
85-
// Create a DOM XMLSignatureFactory
86-
final String providerName = System.getProperty("jsr105Provider",
87-
"org.jcp.xml.dsig.internal.dom.XMLDSigRI");
88-
final XMLSignatureFactory sigFactory = XMLSignatureFactory.getInstance("DOM");
89-
90-
// Create a Reference to the signed element
91-
Node sigParent;
92-
final List<Transform> transforms;
93-
94-
if (xpathExprString == null) {
95-
sigParent = inputDoc.getDocumentElement();
96-
transforms = Collections.singletonList(sigFactory.newTransform(Transform.ENVELOPED,
97-
(TransformParameterSpec) null));
98-
} else {
99-
final XPathFactory factory = XPathFactory.newInstance();
100-
final XPath xpath = factory.newXPath();
101-
// Find the node to be signed by PATH
102-
final XPathExpression expr = xpath.compile(xpathExprString);
103-
final NodeList nodes = (NodeList) expr.evaluate(inputDoc, XPathConstants.NODESET);
104-
if (nodes.getLength() < 1) {
105-
throw new Exception("Can't find node by this XPath expression: " + xpathExprString);
106-
}
107-
108-
// Node nodeToSign = nodes.item(0);
109-
// sigParent = nodeToSign.getParentNode();
110-
sigParent = nodes.item(0);
111-
/*
112-
* if ( signatureType.equals( "enveloped" ) ) { sigParent = (
113-
* nodes.item(0) ).getParentNode(); }
67+
public static byte[] generateSignature(byte[] data, PrivateKey key, String algorithm, String provider)
68+
throws Exception {
69+
Signature signer = Signature.getInstance(algorithm);
70+
signer.initSign(key);
71+
signer.update(data);
72+
73+
return signer.sign();
74+
}
75+
76+
public static String GenerateDigitalSignature(org.w3c.dom.Document inputDoc, String canonicalizationAlgorithmURI,
77+
String digestAlgorithmURI, String signatureAlgorithmURI, String keyPairAlgorithm,
78+
String signatureNamespacePrefix, String signatureType, String xpathExprString, String[] certificateDetails,
79+
InputStream keyStoreInputStream) throws Exception {
80+
// Create a DOM XMLSignatureFactory
81+
String providerName = System.getProperty("jsr105Provider", "org.jcp.xml.dsig.internal.dom.XMLDSigRI");
82+
XMLSignatureFactory sigFactory = XMLSignatureFactory.getInstance("DOM");
83+
84+
// Create a Reference to the signed element
85+
Node sigParent;
86+
List<Transform> transforms;
87+
88+
if (xpathExprString == null) {
89+
sigParent = inputDoc.getDocumentElement();
90+
transforms = Collections
91+
.singletonList(sigFactory.newTransform(Transform.ENVELOPED, (TransformParameterSpec) null));
92+
} else {
93+
XPathFactory factory = XPathFactory.newInstance();
94+
XPath xpath = factory.newXPath();
95+
// Find the node to be signed by PATH
96+
XPathExpression expr = xpath.compile(xpathExprString);
97+
NodeList nodes = (NodeList) expr.evaluate(inputDoc, XPathConstants.NODESET);
98+
if (nodes.getLength() < 1) {
99+
throw new Exception("Can't find node by this XPath expression: " + xpathExprString);
100+
}
101+
102+
// Node nodeToSign = nodes.item(0);
103+
// sigParent = nodeToSign.getParentNode();
104+
sigParent = nodes.item(0);
105+
/*
106+
* if ( signatureType.equals( "enveloped" ) ) { sigParent = ( nodes.item(0)
107+
* ).getParentNode(); }
114108
*/
115-
transforms = Arrays.asList(
116-
sigFactory.newTransform(Transform.XPATH, new XPathFilterParameterSpec(
117-
xpathExprString)),
118-
sigFactory.newTransform(Transform.ENVELOPED, (TransformParameterSpec) null));
119-
}
120-
121-
final Reference ref = sigFactory.newReference("", sigFactory.newDigestMethod(digestAlgorithmURI, null),
122-
transforms, null, null);
123-
124-
// http://www.massapi.com/source/xml-security-1_4_4/src/org/jcp/xml/dsig/internal/dom/DOMXPathFilter2Transform.java.html
125-
126-
// Create the SignedInfo
127-
final SignedInfo si = sigFactory.newSignedInfo(sigFactory.newCanonicalizationMethod(
128-
canonicalizationAlgorithmURI, (C14NMethodParameterSpec) null), sigFactory
129-
.newSignatureMethod(signatureAlgorithmURI, null), Collections.singletonList(ref));
130-
131-
// generate key pair
132-
final KeyInfo ki;
133-
final PrivateKey privateKey;
134-
if (certificateDetails[0].length() != 0) {
135-
final KeyStore keyStore;
136-
try {
137-
keyStore = KeyStore.getInstance(certificateDetails[0]);
138-
} catch (Exception ex) {
139-
throw new Exception("The keystore type '" + certificateDetails[0] + "' is not supported!.");
140-
}
141-
keyStore.load(keyStoreInputStream, certificateDetails[1].toCharArray());
142-
String alias = certificateDetails[2];
143-
if (!keyStore.containsAlias(alias)) {
144-
throw new Exception("Cannot find key for alias '" + alias + "' in given keystore!.");
145-
}
146-
privateKey = (PrivateKey) keyStore.getKey(alias, certificateDetails[3].toCharArray());
147-
148-
final X509Certificate cert = (X509Certificate) keyStore.getCertificate(alias);
149-
final PublicKey publicKey = cert.getPublicKey();
150-
final KeyInfoFactory kif = sigFactory.getKeyInfoFactory();
151-
152-
final List<XMLStructure> kiContent = new ArrayList<>();
153-
final KeyValue keyValue = kif.newKeyValue(publicKey);
154-
kiContent.add(keyValue);
155-
156-
final List<Object> x509Content = new ArrayList<>();
157-
final X509IssuerSerial issuer = kif.newX509IssuerSerial(cert.getIssuerX500Principal().getName(),
158-
cert.getSerialNumber());
159-
x509Content.add(cert.getSubjectX500Principal().getName());
160-
x509Content.add(issuer);
161-
x509Content.add(cert);
162-
163-
final X509Data x509Data = kif.newX509Data(x509Content);
164-
kiContent.add(x509Data);
165-
ki = kif.newKeyInfo(kiContent);
166-
} else {
167-
final KeyPairGenerator kpg = KeyPairGenerator.getInstance(keyPairAlgorithm);
168-
kpg.initialize(512);
169-
final KeyPair kp = kpg.generateKeyPair();
170-
final KeyInfoFactory kif = sigFactory.getKeyInfoFactory();
171-
final KeyValue kv = kif.newKeyValue(kp.getPublic());
172-
ki = kif.newKeyInfo(Collections.singletonList(kv));
173-
privateKey = kp.getPrivate();
174-
}
109+
transforms = Arrays.asList(
110+
sigFactory.newTransform(Transform.XPATH, new XPathFilterParameterSpec(xpathExprString)),
111+
sigFactory.newTransform(Transform.ENVELOPED, (TransformParameterSpec) null));
112+
}
113+
114+
Reference ref = sigFactory.newReference("", sigFactory.newDigestMethod(digestAlgorithmURI, null), transforms,
115+
null, null);
116+
117+
// http://www.massapi.com/source/xml-security-1_4_4/src/org/jcp/xml/dsig/internal/dom/DOMXPathFilter2Transform.java.html
118+
119+
// Create the SignedInfo
120+
SignedInfo si = sigFactory.newSignedInfo(
121+
sigFactory.newCanonicalizationMethod(canonicalizationAlgorithmURI, (C14NMethodParameterSpec) null),
122+
sigFactory.newSignatureMethod(signatureAlgorithmURI, null), Collections.singletonList(ref));
123+
124+
// generate key pair
125+
KeyInfo ki;
126+
PrivateKey privateKey;
127+
if (certificateDetails[0].length() != 0) {
128+
KeyStore keyStore;
129+
try {
130+
keyStore = KeyStore.getInstance(certificateDetails[0]);
131+
} catch (Exception ex) {
132+
throw new Exception("The keystore type '" + certificateDetails[0] + "' is not supported!.");
133+
}
134+
keyStore.load(keyStoreInputStream, certificateDetails[1].toCharArray());
135+
String alias = certificateDetails[2];
136+
if (!keyStore.containsAlias(alias)) {
137+
throw new Exception("Cannot find key for alias '" + alias + "' in given keystore!.");
138+
}
139+
privateKey = (PrivateKey) keyStore.getKey(alias, certificateDetails[3].toCharArray());
140+
141+
X509Certificate cert = (X509Certificate) keyStore.getCertificate(alias);
142+
PublicKey publicKey = cert.getPublicKey();
143+
KeyInfoFactory kif = sigFactory.getKeyInfoFactory();
144+
145+
List<XMLStructure> kiContent = new ArrayList<>();
146+
KeyValue keyValue = kif.newKeyValue(publicKey);
147+
kiContent.add(keyValue);
148+
149+
List<Object> x509Content = new ArrayList<>();
150+
X509IssuerSerial issuer = kif.newX509IssuerSerial(cert.getIssuerX500Principal().getName(),
151+
cert.getSerialNumber());
152+
x509Content.add(cert.getSubjectX500Principal().getName());
153+
x509Content.add(issuer);
154+
x509Content.add(cert);
155+
156+
X509Data x509Data = kif.newX509Data(x509Content);
157+
kiContent.add(x509Data);
158+
ki = kif.newKeyInfo(kiContent);
159+
} else {
160+
KeyPairGenerator kpg = KeyPairGenerator.getInstance(keyPairAlgorithm);
161+
kpg.initialize(512);
162+
KeyPair kp = kpg.generateKeyPair();
163+
KeyInfoFactory kif = sigFactory.getKeyInfoFactory();
164+
KeyValue kv = kif.newKeyValue(kp.getPublic());
165+
ki = kif.newKeyInfo(Collections.singletonList(kv));
166+
privateKey = kp.getPrivate();
167+
}
175168

176169
/*
177170
* <element name="X509Data" type="ds:X509DataType"/> <complexType
178171
* name="X509DataType"> <sequence maxOccurs="unbounded"> <choice> SOLVED
179-
* <element name="X509IssuerSerial" type="ds:X509IssuerSerialType"/>
180-
* <element name="X509SKI" type="base64Binary"/> SOLVED <element
181-
* name="X509SubjectName" type="string"/> SOLVED <element
182-
* name="X509Certificate" type="base64Binary"/> <element name="X509CRL"
183-
* type="base64Binary"/> <any namespace="##other"
172+
* <element name="X509IssuerSerial" type="ds:X509IssuerSerialType"/> <element
173+
* name="X509SKI" type="base64Binary"/> SOLVED <element name="X509SubjectName"
174+
* type="string"/> SOLVED <element name="X509Certificate" type="base64Binary"/>
175+
* <element name="X509CRL" type="base64Binary"/> <any namespace="##other"
184176
* processContents="lax"/> </choice> </sequence> </complexType> >
185177
*/
186178

187-
// Create a DOMSignContext and specify the location of the resulting
188-
// XMLSignature's parent element
189-
final DOMSignContext dsc;
190-
final XMLSignature signature;
191-
Document signatureDoc = null;
192-
if (signatureType.equals("enveloped")) {
193-
dsc = new DOMSignContext(privateKey, sigParent);
194-
signature = sigFactory.newXMLSignature(si, ki);
195-
} else if (signatureType.equals("detached")) {
196-
final DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
197-
dbf.setNamespaceAware(true);
198-
sigParent = dbf.newDocumentBuilder().newDocument();
199-
dsc = new DOMSignContext(privateKey, sigParent);
200-
signature = sigFactory.newXMLSignature(si, ki);
201-
} else if (signatureType.equals("enveloping")) {
202-
final DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
203-
dbf.setNamespaceAware(true);
204-
signatureDoc = dbf.newDocumentBuilder().newDocument();
205-
final XMLStructure content = new DOMStructure(sigParent);
206-
final XMLObject xmlobj = sigFactory.newXMLObject(Collections.singletonList(content), "object", null,
207-
null);
208-
dsc = new DOMSignContext(privateKey, signatureDoc);
209-
signature = sigFactory.newXMLSignature(si, ki, Collections.singletonList(xmlobj), null, null);
210-
} else {
211-
//TODO(AR) error, as below will cause NPE...
212-
dsc = null;
213-
signature = null;
214-
}
215-
216-
dsc.setDefaultNamespacePrefix(signatureNamespacePrefix);
217-
218-
// Marshal, generate and sign
219-
signature.sign(dsc);
220-
221-
final DOMImplementationRegistry registry = DOMImplementationRegistry.newInstance();
222-
final DOMImplementationLS impl = (DOMImplementationLS) registry.getDOMImplementation("LS");
223-
final LSSerializer serializer = impl.createLSSerializer();
224-
if (signatureType.equals("enveloping")) {
225-
return serializer.writeToString(signatureDoc);
226-
} else {
227-
return serializer.writeToString(sigParent);
228-
}
229-
}
230-
231-
public static void main(final String[] args) throws ParserConfigurationException, SAXException, IOException,
232-
Exception {
233-
final String docString = "<data><a xml:id=\"type\"><b>23</b><c><d/></c></a></data>";
234-
final DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
235-
dbf.setNamespaceAware(true);
236-
237-
try (final Reader reader = new StringReader(docString)) {
238-
final Document inputDoc = dbf.newDocumentBuilder().parse(new InputSource(reader));
239-
240-
final String[] certificateDetails = {
241-
"JKS",
242-
"ab987c",
243-
"eXist",
244-
"kpi135"
245-
};
246-
247-
try (final InputStream is = Files.newInputStream(Paths.get("/home/claudius/mykeystoreEXist.ks"))) {
248-
249-
final String domString = GenerateDigitalSignature(inputDoc, CanonicalizationMethod.EXCLUSIVE,
250-
DigestMethod.SHA1, SignatureMethod.DSA_SHA1, "DSA", "ds", "enveloped", "//b",
251-
certificateDetails, is);
252-
System.out.print(domString + "\n");
253-
}
254-
}
255-
}
179+
// Create a DOMSignContext and specify the location of the resulting
180+
// XMLSignature's parent element
181+
DOMSignContext dsc;
182+
XMLSignature signature;
183+
Document signatureDoc = null;
184+
if (signatureType.equals("enveloped")) {
185+
dsc = new DOMSignContext(privateKey, sigParent);
186+
signature = sigFactory.newXMLSignature(si, ki);
187+
} else if (signatureType.equals("detached")) {
188+
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
189+
dbf.setNamespaceAware(true);
190+
sigParent = dbf.newDocumentBuilder().newDocument();
191+
dsc = new DOMSignContext(privateKey, sigParent);
192+
signature = sigFactory.newXMLSignature(si, ki);
193+
} else if (signatureType.equals("enveloping")) {
194+
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
195+
dbf.setNamespaceAware(true);
196+
signatureDoc = dbf.newDocumentBuilder().newDocument();
197+
XMLStructure content = new DOMStructure(sigParent);
198+
XMLObject xmlobj = sigFactory.newXMLObject(Collections.singletonList(content), "object", null, null);
199+
dsc = new DOMSignContext(privateKey, signatureDoc);
200+
signature = sigFactory.newXMLSignature(si, ki, Collections.singletonList(xmlobj), null, null);
201+
} else {
202+
// TODO(AR) error, as below will cause NPE...
203+
dsc = null;
204+
signature = null;
205+
}
206+
207+
dsc.setDefaultNamespacePrefix(signatureNamespacePrefix);
208+
209+
// Marshal, generate and sign
210+
signature.sign(dsc);
211+
212+
DOMImplementationRegistry registry = DOMImplementationRegistry.newInstance();
213+
DOMImplementationLS impl = (DOMImplementationLS) registry.getDOMImplementation("LS");
214+
LSSerializer serializer = impl.createLSSerializer();
215+
if (signatureType.equals("enveloping")) {
216+
return serializer.writeToString(signatureDoc);
217+
} else {
218+
return serializer.writeToString(sigParent);
219+
}
220+
}
256221
}

0 commit comments

Comments
 (0)