package com.aip.gateway.api; import lombok.Data; import lombok.extern.slf4j.Slf4j; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import java.io.File; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; @Slf4j public class LicenseManager { @Data private static class License { private boolean isValid; private int errorCode; private String product; private String serialId; private String issueDay; private Date startDate; private String licensee; private String edition; private String type; private int accounts; private String identifiedHost; private String signature; private int demoDuration; private boolean isDemo; public License() { this.isValid = false; this.errorCode = 0; this.product = ""; this.serialId = ""; this.issueDay = ""; this.licensee = ""; this.edition = ""; this.type = ""; this.accounts = 0; this.identifiedHost = ""; this.signature = ""; this.demoDuration = 0; this.isDemo = false; } } private static String getComputerName() { String hostName = System.getenv("COMPUTERNAME"); if (hostName == null || hostName.isEmpty()) { hostName = "localhost"; } return hostName; } private static NodeList getXmlNodeList(String filePath, String nodeTag) { try { DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance(); DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder(); File xmlFile = new File(filePath); Document document = documentBuilder.parse(xmlFile); document.getDocumentElement().normalize(); return document.getElementsByTagName(nodeTag); } catch (ParserConfigurationException e) { log.error("getXmlNodeList(ParserConfigurationException): {}, {}: {}", filePath, nodeTag, e.toString()); } catch (SAXException e) { log.error("getXmlNodeList(SAXException): {}, {}: {}", filePath, nodeTag, e.toString()); } catch (IOException e) { log.error("getXmlNodeList(IOException): {}, {}: {}", filePath, nodeTag, e.toString()); } catch (Exception e) { log.error("getXmlNodeList(Exception): {}, {}: {}", filePath, nodeTag, e.toString()); } return null; } private static String getElementTagValue(Element element, String tagName) { NodeList list = element.getElementsByTagName(tagName); if (list == null) { return null; } Node node = list.item(0); if (node == null) { return null; } return node.getTextContent().trim(); } private static License errorLicenseItem(License license, int errorCode) { license.setErrorCode(errorCode); if (errorCode > 20) { log.error("License item data validation error: {}", errorCode); } else { log.error("License item data not found: {}", errorCode); } return license; } private static boolean errorLicenseItemValue(String orgValue, String curValue, int errorCode) { log.error("License value error: {}, {}", curValue, errorCode); return false; } private static Date getDay(String dayString) { try { SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); Date date = dateFormat.parse(dayString); return date; } catch (ParseException e) { return null; } } private static boolean isValidIntegerString(String inputString) { try { Integer.parseInt(inputString); return true; } catch (NumberFormatException e) { return false; } } private static License loadLicenseFile() { License license = new License(); String filePath = System.getProperty("user.dir") + File.separator + "conf" + File.separator + "license.xml"; //log.info("Loading license: {}", filePath); NodeList nodeList = getXmlNodeList(filePath, "license"); if (nodeList == null) { return license; } for (int ii = 0; ii < nodeList.getLength(); ii++) { Node node = nodeList.item(ii); if (node.getNodeType() != 1) continue; Element element = (Element) node; // log.info(" product: {}", getElementTagValue(element, "product")); // log.info(" serialId: {}", getElementTagValue(element, "serialId")); // log.info(" issueDay: {}", getElementTagValue(element, "issueDay")); // log.info(" edition: {}", getElementTagValue(element, "edition")); // log.info(" type: {}", getElementTagValue(element, "type")); // log.info(" accounts: {}", getElementTagValue(element, "accounts")); // log.info("identifiedHost: {}", getElementTagValue(element, "identifiedHost")); // log.info(" signature: {}", getElementTagValue(element, "signature")); // log.info(" demoDuration: {}", getElementTagValue(element, "demoDuration")); String product = getElementTagValue(element, "product"); if (product == null) { return errorLicenseItem(license, 1); } license.setProduct(product); String serialId = getElementTagValue(element, "serialId"); if (serialId == null) { return errorLicenseItem(license, 2); } license.setSerialId(serialId); String issueDay = getElementTagValue(element, "issueDay"); if (issueDay == null) { return errorLicenseItem(license, 3); } Date day = getDay(issueDay); if (day == null) { return errorLicenseItem(license, 33); } license.setIssueDay(issueDay); license.setStartDate(day); String edition = getElementTagValue(element, "edition"); if (edition == null) { return errorLicenseItem(license, 4); } if (!"standard".equalsIgnoreCase(edition) && !"enterprise".equalsIgnoreCase(edition)) { return errorLicenseItem(license, 34); } license.setEdition(edition); String type = getElementTagValue(element, "type"); if (type == null) { return errorLicenseItem(license, 5); } if (!"demo".equalsIgnoreCase(type) && !"product".equalsIgnoreCase(type)) { return errorLicenseItem(license, 35); } license.setType(type); if ("demo".equalsIgnoreCase(type)) { license.setDemo(true); } String accounts = getElementTagValue(element, "accounts"); if (accounts == null) { return errorLicenseItem(license, 6); } if (!isValidIntegerString(accounts)) { return errorLicenseItem(license, 36); } license.setAccounts(Integer.parseInt(accounts)); String identifiedHost = getElementTagValue(element, "identifiedHost"); if (identifiedHost == null) { return errorLicenseItem(license, 7); } license.setIdentifiedHost(identifiedHost); String signature = getElementTagValue(element, "signature"); if (signature == null) { return errorLicenseItem(license, 8); } license.setSignature(signature); if (license.isDemo()) { String demoDuration = getElementTagValue(element, "demoDuration"); if (demoDuration == null) { return errorLicenseItem(license, 9); } if (!isValidIntegerString(demoDuration)) { return errorLicenseItem(license, 39); } license.setDemoDuration(Integer.parseInt(demoDuration)); } } license.setValid(true); return license; } public static String getSha256Encrypt(String str) { String SHA = ""; try { MessageDigest msgDigest = MessageDigest.getInstance("SHA-256"); //msgDigest.update(str.getBytes()); msgDigest.update(str.getBytes(StandardCharsets.UTF_8)); byte byteData[] = msgDigest.digest(); StringBuffer builder = new StringBuffer(); for (byte b : byteData) { builder.append(String.format("%02x", b)); } SHA = builder.toString(); } catch (NoSuchAlgorithmException e) { SHA = ""; } return SHA; } public static boolean validateLicense() { log.info("Application License validateLicense: Start."); License license = loadLicenseFile(); if (!license.isValid()) { return false; } if (license.isDemo()) { // 데모 모드 일 경우 유효기간 체크 Calendar calendar = Calendar.getInstance(); calendar.setTime(license.getStartDate()); calendar.add(Calendar.DAY_OF_MONTH, license.getDemoDuration()); Date resultDate = calendar.getTime(); Date currentDate = new Date(); if (!currentDate.before(resultDate)) { log.error("License Issue Day expired."); return false; } } String identifiedHost = getComputerName(); if (!identifiedHost.equalsIgnoreCase(license.getIdentifiedHost())) { // 컴퓨터 이름 체크 return errorLicenseItemValue(identifiedHost, license.getIdentifiedHost(), 1); } String encKey = license.getProduct().toUpperCase() + "hanteinfo12#$!" + license.getSerialId().toLowerCase() + license.getIssueDay() + license.getEdition().toUpperCase() + license.getType().toLowerCase() + String.valueOf(license.getAccounts() + 10000) + license.getIdentifiedHost().toLowerCase(); String signature = getSha256Encrypt(encKey); if (!signature.equalsIgnoreCase(license.getSignature())) { // 컴퓨터 이름 체크 return errorLicenseItemValue(signature, license.getSignature(), 2); } System.setProperty("AIP_GATEWAY_ACCOUNT", String.valueOf(license.getAccounts())); log.info("Application License validateLicense: ..End.[OK]"); return true; } }