/* * Copyright @ 2013 CurisTEC, S.A.S. All Rights Reserved. */ package net.curisit.securis; import java.io.File; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.nio.file.Files; import java.nio.file.Paths; import java.nio.file.StandardOpenOption; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.security.Signature; import java.security.SignatureException; import java.security.spec.InvalidKeySpecException; import java.util.Date; import java.util.Map; import net.curisit.securis.beans.LicenseBean; import net.curisit.securis.beans.RequestBean; import net.curisit.securis.beans.SignedLicenseBean; import net.curisit.securis.utils.JsonUtils; import net.curisit.securis.utils.SignatureHelper; import org.apache.commons.codec.binary.Base64; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import jakarta.inject.Singleton; /** * LicenseGenerator *
* Factory for building and signing {@link LicenseBean} instances. Uses a process-wide
* singleton and expects a PKCS#8 private key at:
* ~/.SeCuris/keys/securis_private_key.pkcs8.
*
* @author JRA
* Last reviewed by JRA on Oct 5, 2025.
*/
@Singleton
public class LicenseGenerator {
private static final Logger LOG = LogManager.getLogger(LicenseGenerator.class);
private static LicenseGenerator singleton = new LicenseGenerator();
/**
* getInstance
* Singleton accessor. */ public static LicenseGenerator getInstance() { return singleton; } /** * generateLicense
* Generate a license bean with the specified data
*
* @param req
* @param licCode
* @param metadata
* @param expirationDate
* @param licenseCode
* @param appName
* @return
* @throws SeCurisException
*/
public LicenseBean generateLicense(RequestBean req, Map
* Persist a pretty-printed JSON representation of the signed license to disk.
*
* @param license source license
* @param file target file path
* @throws SeCurisException if serialization or IO fails
*/
public void save(LicenseBean license, File file) throws SeCurisException {
SignedLicenseBean signedLic = new SignedLicenseBean(license);
byte[] json;
try {
json = JsonUtils.toPrettyJSON(signedLic).getBytes("utf-8");
Files.write(Paths.get(file.toURI()), json, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING);
} catch (UnsupportedEncodingException e) {
LOG.error("Error creating json doc from license: " + license, e);
throw new SeCurisException("Error creating json doc from license: " + license, e);
} catch (IOException e) {
LOG.error("Error creating license file: " + file, e);
throw new SeCurisException("Error creating json doc from license: " + license, e);
}
LOG.info("License saved in {}", file);
}
/**
* sign
*
* Compute a Base64 signature for the given license and set it into the bean.
*
* @param licBean license to sign (in-place)
* @return Base64 signature string
* @throws SeCurisException if the signature process fails
*/
public String sign(LicenseBean licBean) throws SeCurisException {
SignatureHelper sh = SignatureHelper.getInstance();
Signature signature;
try {
signature = Signature.getInstance(SignatureHelper.SIGNATURE_GENERATION_ALGORITHM);
signature.initSign(sh.generatePrivateKey(new File(System.getProperty("user.home") + File.separator + ".SeCuris" + File.separator + "keys"
+ File.separator + "securis_private_key.pkcs8")));
sh.prepareSignature(signature, licBean);
byte[] signatureData = signature.sign();
licBean.setSignature(Base64.encodeBase64String(signatureData));
return licBean.getSignature();
} catch (NoSuchAlgorithmException | InvalidKeyException | InvalidKeySpecException | IOException | SignatureException e) {
LOG.error("Error signing license for {}", licBean, e);
}
throw new SeCurisException("License could not be generated");
}
}