/* * 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 metadata, Date expirationDate, String licenseCode, String appName) throws SeCurisException { LOG.debug("Generating license: MAC: {}, Customer code: {}, AppName: {}", req.getMacAddresses(), req.getCustomerCode(), appName); LicenseBean license = new LicenseBean(req); license.setAppName(appName); license.setLicenseCode(licenseCode); license.setExpirationDate(expirationDate); license.setMetadata(metadata); sign(license); return license; } /** * save *

* 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"); } }