Skip to content

Commit cf5b5b4

Browse files
committed
add code that generates a self-signed certificate (without keytool)
1 parent 6d077e6 commit cf5b5b4

File tree

1 file changed

+67
-11
lines changed

1 file changed

+67
-11
lines changed

dslink-v2/src/main/java/com/acuity/iot/dsa/dslink/sys/cert/SysCertManager.java

Lines changed: 67 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,26 @@
33
import java.io.File;
44
import java.io.IOException;
55
import java.io.StringWriter;
6+
import java.math.BigInteger;
67
import java.security.KeyPair;
78
import java.security.KeyPairGenerator;
89
import java.security.NoSuchAlgorithmException;
10+
import java.security.Provider;
911
import java.security.SecureRandom;
12+
import java.security.Security;
1013
import java.security.cert.CertificateEncodingException;
14+
import java.security.cert.CertificateException;
1115
import java.security.cert.X509Certificate;
12-
import java.time.format.ResolverStyle;
13-
import java.util.Iterator;
16+
import java.util.Calendar;
17+
import java.util.Date;
1418
import javax.security.auth.x500.X500Principal;
19+
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
20+
import org.bouncycastle.asn1.x500.X500Name;
21+
import org.bouncycastle.asn1.x509.BasicConstraints;
22+
import org.bouncycastle.cert.CertIOException;
23+
import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
24+
import org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder;
25+
import org.bouncycastle.jce.provider.BouncyCastleProvider;
1526
import org.bouncycastle.openssl.jcajce.JcaPEMWriter;
1627
import org.bouncycastle.operator.ContentSigner;
1728
import org.bouncycastle.operator.OperatorCreationException;
@@ -20,19 +31,15 @@
2031
import org.bouncycastle.pkcs.PKCS10CertificationRequestBuilder;
2132
import org.bouncycastle.pkcs.jcajce.JcaPKCS10CertificationRequestBuilder;
2233
import org.iot.dsa.node.DSBool;
23-
import org.iot.dsa.node.DSIValue;
2434
import org.iot.dsa.node.DSInfo;
2535
import org.iot.dsa.node.DSMap;
2636
import org.iot.dsa.node.DSNode;
2737
import org.iot.dsa.node.DSString;
2838
import org.iot.dsa.node.DSValueType;
2939
import org.iot.dsa.node.action.ActionInvocation;
3040
import org.iot.dsa.node.action.ActionResult;
31-
import org.iot.dsa.node.action.ActionSpec;
3241
import org.iot.dsa.node.action.ActionSpec.ResultType;
33-
import org.iot.dsa.node.action.ActionValues;
3442
import org.iot.dsa.node.action.DSAbstractAction;
35-
import org.iot.dsa.node.action.DSAction;
3643
import org.iot.dsa.node.action.DSActionValues;
3744
import org.iot.dsa.security.DSPasswordAes128;
3845
import org.iot.dsa.util.DSException;
@@ -66,7 +73,6 @@ public class SysCertManager extends DSNode {
6673
private DSInfo keystore = getInfo(CERTFILE);
6774
private DSInfo keystorePass = getInfo(CERTFILE_PASS);
6875
private DSInfo keystoreType = getInfo(CERTFILE_TYPE);
69-
private DSInfo generateCSR = getInfo(GENERATE_CSR);
7076
private CertCollection localTruststore;
7177
private CertCollection quarantine;
7278

@@ -122,7 +128,8 @@ public void prepareParameter(DSInfo info, DSMap parameter) {
122128

123129
@Override
124130
public ActionResult invoke(DSInfo info, ActionInvocation invocation) {
125-
return ((SysCertManager) info.getParent()).generateCSR(info);
131+
String csr = ((SysCertManager) info.getParent()).generateCSR();
132+
return new DSActionValues(info.getAction()).addResult(DSString.valueOf(csr));
126133
}
127134
};
128135
act.setResultType(ResultType.VALUES);
@@ -198,7 +205,7 @@ public void allow(DSInfo certInfo) {
198205
getLocalTruststore().addCertificate(name, certStr);
199206
}
200207

201-
private ActionResult generateCSR(DSInfo actionInfo) {
208+
private static String generateCSR() {
202209
KeyPairGenerator keyGen;
203210
try {
204211
keyGen = KeyPairGenerator.getInstance("RSA");
@@ -209,7 +216,7 @@ private ActionResult generateCSR(DSInfo actionInfo) {
209216
keyGen.initialize(2048, new SecureRandom());
210217
KeyPair pair = keyGen.generateKeyPair();
211218
PKCS10CertificationRequestBuilder p10Builder = new JcaPKCS10CertificationRequestBuilder(
212-
new X500Principal("CN=dslink-java-v2"), pair.getPublic());
219+
new X500Principal("CN=dslink-java-v2, O=DSA, C=US"), pair.getPublic());
213220
JcaContentSignerBuilder csBuilder = new JcaContentSignerBuilder("SHA256withRSA");
214221
ContentSigner signer;
215222
try {
@@ -235,7 +242,56 @@ private ActionResult generateCSR(DSInfo actionInfo) {
235242
return null;
236243
}
237244
}
238-
return new DSActionValues(actionInfo.getAction()).addResult(DSString.valueOf(str));
245+
return str.toString();
246+
}
247+
248+
private static X509Certificate generateSelfSigned() {
249+
KeyPairGenerator keyGen;
250+
try {
251+
keyGen = KeyPairGenerator.getInstance("RSA");
252+
} catch (NoSuchAlgorithmException e) {
253+
DSException.throwRuntime(e);
254+
return null;
255+
}
256+
keyGen.initialize(2048, new SecureRandom());
257+
KeyPair pair = keyGen.generateKeyPair();
258+
259+
Provider bcProvider = new BouncyCastleProvider();
260+
Security.addProvider(bcProvider);
261+
262+
long now = System.currentTimeMillis();
263+
Date startDate = new Date(now);
264+
265+
X500Name dname = new X500Name("CN=dslink-java-v2, O=DSA, C=US");
266+
BigInteger certSerialNumber = new BigInteger(Long.toString(now)); // <-- Using the current timestamp as the certificate serial number
267+
268+
Calendar calendar = Calendar.getInstance();
269+
calendar.setTime(startDate);
270+
calendar.add(Calendar.YEAR, 1); // <-- 1 Yr validity
271+
Date endDate = calendar.getTime();
272+
273+
String signatureAlgorithm = "SHA256WithRSA"; // <-- Use appropriate signature algorithm based on your keyPair algorithm.
274+
275+
try {
276+
ContentSigner contentSigner = new JcaContentSignerBuilder(signatureAlgorithm).build(pair.getPrivate());
277+
JcaX509v3CertificateBuilder certBuilder = new JcaX509v3CertificateBuilder(dname, certSerialNumber, startDate, endDate, dname, pair.getPublic());
278+
279+
BasicConstraints basicConstraints = new BasicConstraints(true); // <-- true for CA, false for EndEntity
280+
certBuilder.addExtension(new ASN1ObjectIdentifier("2.5.29.19"), true, basicConstraints); // Basic Constraints is usually marked as critical.
281+
282+
return new JcaX509CertificateConverter().setProvider(bcProvider).getCertificate(certBuilder.build(contentSigner));
283+
} catch (OperatorCreationException e) {
284+
DSException.throwRuntime(e);
285+
return null;
286+
} catch (CertIOException e) {
287+
DSException.throwRuntime(e);
288+
return null;
289+
} catch (CertificateException e) {
290+
DSException.throwRuntime(e);
291+
return null;
292+
}
293+
294+
239295
}
240296

241297
}

0 commit comments

Comments
 (0)