PKIHelper.java
package de.dlr.shepard.util;
import io.quarkus.logging.Log;
import jakarta.enterprise.context.RequestScoped;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.KeyFactory;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import lombok.Getter;
@RequestScoped
public class PKIHelper {
private static final String RSA = "RSA";
private Path keysDir = Paths.get(System.getProperty("user.home"), ".shepard/keys");
private Path pubKey = Paths.get(keysDir.toString(), "public.key");
private Path privKey = Paths.get(keysDir.toString(), "private.key");
@Getter
private PublicKey publicKey;
@Getter
private PrivateKey privateKey;
public void init() {
generateKeyPairIfNecessary();
try {
publicKey = importPublicKey();
} catch (NoSuchAlgorithmException | InvalidKeySpecException | IOException e) {
Log.errorf("Exception while reading public key specification: %s", e);
}
try {
privateKey = importPrivateKey();
} catch (NoSuchAlgorithmException | InvalidKeySpecException | IOException e) {
Log.errorf("Exception while reading private key specification: %s", e);
}
}
private void generateKeyPairIfNecessary() {
if (Files.isRegularFile(keysDir)) {
Log.error("keys directory is a file, cannot create keys");
return;
}
if (Files.notExists(keysDir)) {
Log.info("keys directory does not exist, creating...");
try {
Files.createDirectories(keysDir);
} catch (IOException e) {
Log.errorf("Error while generating keys directory: %s", e.toString());
return;
}
}
if (!Files.isReadable(keysDir) || !Files.isWritable(keysDir)) {
Log.error("insufficient permissions for the keys directory");
return;
}
if (Files.exists(pubKey) && Files.isRegularFile(pubKey) && Files.exists(privKey) && Files.isRegularFile(privKey)) {
Log.info("keys found, importing...");
return;
}
Log.info("No keys available. Generating...");
try {
generateKeyPair();
} catch (NoSuchAlgorithmException | IOException e) {
Log.errorf("Error while generating keys: %s", e.toString());
}
}
private PublicKey importPublicKey() throws IOException, NoSuchAlgorithmException, InvalidKeySpecException {
byte[] key;
try (var fis = Files.newInputStream(pubKey)) {
key = fis.readAllBytes();
}
var keyFactory = KeyFactory.getInstance(RSA);
var spec = new X509EncodedKeySpec(key);
return keyFactory.generatePublic(spec);
}
private PrivateKey importPrivateKey() throws IOException, NoSuchAlgorithmException, InvalidKeySpecException {
byte[] key;
try (var fis = Files.newInputStream(privKey)) {
key = fis.readAllBytes();
}
var keyFactory = KeyFactory.getInstance(RSA);
var spec = new PKCS8EncodedKeySpec(key);
return keyFactory.generatePrivate(spec);
}
private void generateKeyPair() throws NoSuchAlgorithmException, IOException {
var kpg = KeyPairGenerator.getInstance(RSA);
kpg.initialize(2048);
var kp = kpg.generateKeyPair();
try (var pubFos = Files.newOutputStream(pubKey); var privFos = Files.newOutputStream(privKey);) {
pubFos.write(kp.getPublic().getEncoded());
privFos.write(kp.getPrivate().getEncoded());
}
}
}