Skip to content

Commit

Permalink
SDK: Add ca extension when issue CA certificates (eclipse-hawkbit#2277)
Browse files Browse the repository at this point in the history
Signed-off-by: Avgustin Marinov <[email protected]>
  • Loading branch information
avgustinmm authored Feb 13, 2025
1 parent c31c832 commit 653df8a
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 23 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@
import javax.security.auth.x500.X500Principal;

import lombok.Data;
import org.bouncycastle.asn1.x509.BasicConstraints;
import org.bouncycastle.asn1.x509.Extension;
import org.bouncycastle.asn1.x509.X509Extension;
import org.bouncycastle.cert.CertIOException;
import org.bouncycastle.cert.X509v3CertificateBuilder;
import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
import org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder;
Expand Down Expand Up @@ -70,35 +74,47 @@ public Certificate issue(final String subject) throws CertificateException {
return issue(subject, null, null);
}

// generate key and issue a certificate
// generate key and issue a CA certificate
public CA issueCA(final String subject, final Date notBefore, final Date notAfter) throws CertificateException {
return new CA(issue(subject, notBefore, notAfter, true));
}

// generate key and issue an end certificate
public Certificate issue(final String subject, final Date notBefore, final Date notAfter) throws CertificateException {
return issue(subject, notBefore, notAfter, false);
}

public String getFingerprint() {
try {
final X509Certificate[] certificateChain = certificate.getCertificateChain();
return toHex(MessageDigest.getInstance("SHA-256").digest(certificateChain[certificateChain.length - 1].getEncoded()));
} catch (final NoSuchAlgorithmException | CertificateEncodingException e) {
throw new IllegalArgumentException(e);
}
}

private Certificate issue(final String subject, final Date notBefore, final Date notAfter, final boolean ca) throws CertificateException {
Objects.requireNonNull(subject);
try {
final KeyPair keyPair = genKey();
final X509Certificate[] certificateChain = certificate.getCertificateChain();
final ContentSigner signer = new JcaContentSignerBuilder(SHA_256_WITH_RSA_ENCRYPTION).build(certificate.getKeyPair().getPrivate());
final X509v3CertificateBuilder caCertBuilder = new JcaX509v3CertificateBuilder(
final X509v3CertificateBuilder certBuilder = new JcaX509v3CertificateBuilder(
certificateChain[0].getSubjectX500Principal(),
BigInteger.valueOf(nextSerial++), notBefore(notBefore), notAfter(notAfter), new X500Principal(subject),
keyPair.getPublic());
if (ca) {
certBuilder.addExtension(Extension.basicConstraints, false, new BasicConstraints(true));
}
final X509Certificate[] subjectCertificateChain = new X509Certificate[certificateChain.length + 1];
certificateChain[0] = new JcaX509CertificateConverter().getCertificate(caCertBuilder.build(signer));
subjectCertificateChain[0] = new JcaX509CertificateConverter().getCertificate(certBuilder.build(signer));
System.arraycopy(certificateChain, 0, subjectCertificateChain, 1, certificateChain.length);
return new Certificate(keyPair, subjectCertificateChain);
} catch (final NoSuchAlgorithmException | OperatorCreationException e) {
} catch (final NoSuchAlgorithmException | OperatorCreationException | CertIOException e) {
throw new CertificateException(e);
}
}

public String getFingerprint() {
try {
final X509Certificate[] certificateChain = certificate.getCertificateChain();
return toHex(MessageDigest.getInstance("SHA-256").digest(certificateChain[certificateChain.length - 1].getEncoded()));
} catch (final NoSuchAlgorithmException | CertificateEncodingException e) {
throw new IllegalArgumentException(e);
}
}

private static String toHex(final byte[] bytes) {
final StringBuilder sb = new StringBuilder();
for (final byte b : bytes) {
Expand All @@ -115,8 +131,9 @@ private static Certificate selfSign(final String caDN, final Date notBefore, fin
final ContentSigner selfSigner = new JcaContentSignerBuilder(SHA_256_WITH_RSA_ENCRYPTION).build(keyPair.getPrivate());
final X509v3CertificateBuilder caCertBuilder = new JcaX509v3CertificateBuilder(
caPrincipal, BigInteger.valueOf(0L), notBefore(notBefore), notAfter(notAfter), caPrincipal, keyPair.getPublic());
caCertBuilder.addExtension(Extension.basicConstraints, false, new BasicConstraints(true));
return new Certificate(keyPair, new X509Certificate[] { new JcaX509CertificateConverter().getCertificate(caCertBuilder.build(selfSigner)) });
} catch (final NoSuchAlgorithmException | OperatorCreationException e) {
} catch (final NoSuchAlgorithmException | OperatorCreationException | CertIOException e) {
throw new CertificateException(e);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ public void setupCertificateAuthentication() throws CertificateException {
CA ddiCA = tenant.getDdiCA();
if (ddiCA == null) {
final CA ddiRootCA = new CA();
ddiCA = new CA(ddiRootCA.issue(CA.DEFAULT_INTERMEDIATE_CA_DN, null, null));
ddiCA = ddiRootCA.issueCA(CA.DEFAULT_INTERMEDIATE_CA_DN, null, null);
tenant.setDdiCA(ddiCA);
}
if (!Boolean.TRUE.equals(Objects.requireNonNull(mgmtTenantManagementRestApi
Expand Down Expand Up @@ -104,18 +104,16 @@ public void setupGatewayTokenAuthentication() {
.getBody()).getValue()))) {
mgmtTenantManagementRestApi.updateTenantConfiguration(Map.of(AUTHENTICATION_MODE_GATEWAY_SECURITY_TOKEN_ENABLED, true));
}
if (!gatewayToken.equals(
Objects.requireNonNull(mgmtTenantManagementRestApi
.getTenantConfigurationValue(AUTHENTICATION_MODE_GATEWAY_SECURITY_TOKEN_KEY)
.getBody()).getValue())) {
if (!gatewayToken.equals(Objects.requireNonNull(mgmtTenantManagementRestApi
.getTenantConfigurationValue(AUTHENTICATION_MODE_GATEWAY_SECURITY_TOKEN_KEY)
.getBody()).getValue())) {
mgmtTenantManagementRestApi.updateTenantConfiguration(Map.of(AUTHENTICATION_MODE_GATEWAY_SECURITY_TOKEN_KEY, gatewayToken));
}
}

// if gateway token is configured then the gateway auth is enabled key is set
// so all devices use gateway token authentication
// otherwise target token authentication is enabled. Then all devices shall be registered
// and the target token shall be set to the one from the DDI controller instance
// if gateway token is configured then the gateway auth is enabled, so all devices use gateway token authentication.
// otherwise, target token authentication is enabled - then all devices shall be registered and the target token shall be set to the one from
// the DDI controller instance
public void setupTargetAuthentication() {
final String gatewayToken = tenant.getGatewayToken();
if (ObjectUtils.isEmpty(gatewayToken)) {
Expand Down

0 comments on commit 653df8a

Please sign in to comment.