server
This commit is contained in:
		@@ -41,9 +41,5 @@
 | 
			
		||||
            <source>${project.parent.basedir}/jetbra-agent/target/jetbra-agent.jar</source>
 | 
			
		||||
            <destName>jetbra-agent.jar</destName>
 | 
			
		||||
        </file>
 | 
			
		||||
        <file>
 | 
			
		||||
            <source>${project.parent.basedir}/readme.md</source>
 | 
			
		||||
            <destName>readme.md</destName>
 | 
			
		||||
        </file>
 | 
			
		||||
    </files>
 | 
			
		||||
</assembly>
 | 
			
		||||
 
 | 
			
		||||
@@ -27,12 +27,31 @@
 | 
			
		||||
            <groupId>org.springframework.boot</groupId>
 | 
			
		||||
            <artifactId>spring-boot-starter-web</artifactId>
 | 
			
		||||
        </dependency>
 | 
			
		||||
        <dependency>
 | 
			
		||||
            <groupId>org.springframework.boot</groupId>
 | 
			
		||||
            <artifactId>spring-boot-starter-validation</artifactId>
 | 
			
		||||
        </dependency>
 | 
			
		||||
 | 
			
		||||
        <dependency>
 | 
			
		||||
            <groupId>org.springframework.boot</groupId>
 | 
			
		||||
            <artifactId>spring-boot-starter-test</artifactId>
 | 
			
		||||
            <scope>test</scope>
 | 
			
		||||
        </dependency>
 | 
			
		||||
        <dependency>
 | 
			
		||||
            <groupId>org.bouncycastle</groupId>
 | 
			
		||||
            <artifactId>bcpkix-jdk18on</artifactId>
 | 
			
		||||
            <version>1.72</version>
 | 
			
		||||
        </dependency>
 | 
			
		||||
        <dependency>
 | 
			
		||||
            <groupId>org.bouncycastle</groupId>
 | 
			
		||||
            <artifactId>bcprov-jdk18on</artifactId>
 | 
			
		||||
            <version>1.72</version>
 | 
			
		||||
        </dependency>
 | 
			
		||||
        <dependency>
 | 
			
		||||
            <groupId>org.projectlombok</groupId>
 | 
			
		||||
            <artifactId>lombok</artifactId>
 | 
			
		||||
            <optional>true</optional>
 | 
			
		||||
        </dependency>
 | 
			
		||||
    </dependencies>
 | 
			
		||||
 | 
			
		||||
    <build>
 | 
			
		||||
@@ -40,8 +59,17 @@
 | 
			
		||||
            <plugin>
 | 
			
		||||
                <groupId>org.springframework.boot</groupId>
 | 
			
		||||
                <artifactId>spring-boot-maven-plugin</artifactId>
 | 
			
		||||
                <configuration>
 | 
			
		||||
                    <excludes>
 | 
			
		||||
                        <exclude>
 | 
			
		||||
                            <groupId>org.projectlombok</groupId>
 | 
			
		||||
                            <artifactId>lombok</artifactId>
 | 
			
		||||
                        </exclude>
 | 
			
		||||
                    </excludes>
 | 
			
		||||
                </configuration>
 | 
			
		||||
            </plugin>
 | 
			
		||||
        </plugins>
 | 
			
		||||
    </build>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
</project>
 | 
			
		||||
@@ -0,0 +1,92 @@
 | 
			
		||||
package win.novice.li.controller;
 | 
			
		||||
 | 
			
		||||
import com.fasterxml.jackson.databind.ObjectMapper;
 | 
			
		||||
import lombok.SneakyThrows;
 | 
			
		||||
import org.bouncycastle.jce.provider.BouncyCastleProvider;
 | 
			
		||||
import org.bouncycastle.openssl.PEMKeyPair;
 | 
			
		||||
import org.bouncycastle.openssl.PEMParser;
 | 
			
		||||
import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
 | 
			
		||||
import org.springframework.core.io.ClassPathResource;
 | 
			
		||||
import org.springframework.validation.annotation.Validated;
 | 
			
		||||
import org.springframework.web.bind.annotation.PostMapping;
 | 
			
		||||
import org.springframework.web.bind.annotation.RequestBody;
 | 
			
		||||
import org.springframework.web.bind.annotation.RestController;
 | 
			
		||||
import win.novice.li.model.License;
 | 
			
		||||
 | 
			
		||||
import java.io.FileInputStream;
 | 
			
		||||
import java.io.InputStreamReader;
 | 
			
		||||
import java.nio.charset.StandardCharsets;
 | 
			
		||||
import java.security.*;
 | 
			
		||||
import java.security.cert.CertificateFactory;
 | 
			
		||||
import java.security.cert.X509Certificate;
 | 
			
		||||
import java.util.Base64;
 | 
			
		||||
import java.util.HashMap;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
 | 
			
		||||
@RestController
 | 
			
		||||
public class LicenseController {
 | 
			
		||||
    private static final PrivateKey PRIVATE_KEY = getPrivateKey();
 | 
			
		||||
    private static final X509Certificate CRT = getCertificate();
 | 
			
		||||
 | 
			
		||||
    private static final ObjectMapper MAPPER = new ObjectMapper();
 | 
			
		||||
 | 
			
		||||
    @PostMapping("/generateLicense")
 | 
			
		||||
    @SneakyThrows
 | 
			
		||||
    public Map<String, Object> generateLicense(@RequestBody @Validated License license) {
 | 
			
		||||
        Map<String, Object> ans = new HashMap<>();
 | 
			
		||||
 | 
			
		||||
        String licenseId = generateLicenseId();
 | 
			
		||||
        license.setLicenseId(licenseId);
 | 
			
		||||
 | 
			
		||||
        String licensePart = MAPPER.writeValueAsString(license);
 | 
			
		||||
        byte[] licensePartBytes = licensePart.getBytes(StandardCharsets.UTF_8);
 | 
			
		||||
        String licensePartBase64 = Base64.getEncoder().encodeToString(licensePartBytes);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        Signature signature = Signature.getInstance("SHA1withRSA");
 | 
			
		||||
        signature.initSign(PRIVATE_KEY);
 | 
			
		||||
        signature.update(licensePartBytes);
 | 
			
		||||
        byte[] signatureBytes = signature.sign();
 | 
			
		||||
        String sigResultsBase64 = Base64.getEncoder().encodeToString(signatureBytes);
 | 
			
		||||
 | 
			
		||||
        String result = licenseId + "-" + licensePartBase64 + "-" + sigResultsBase64 + "-" + Base64.getEncoder().encodeToString(CRT.getEncoded());
 | 
			
		||||
 | 
			
		||||
        ans.put("license",result);
 | 
			
		||||
        return ans;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    private static final String ALLOWED_CHARACTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
 | 
			
		||||
    private static final SecureRandom random = new SecureRandom();
 | 
			
		||||
 | 
			
		||||
    public static String generateLicenseId() {
 | 
			
		||||
        int licenseLength = 10;
 | 
			
		||||
        StringBuilder sb = new StringBuilder(licenseLength);
 | 
			
		||||
        for (int i = 0; i < licenseLength; i++) {
 | 
			
		||||
            int randomIndex = random.nextInt(ALLOWED_CHARACTERS.length());
 | 
			
		||||
            char randomChar = ALLOWED_CHARACTERS.charAt(randomIndex);
 | 
			
		||||
            sb.append(randomChar);
 | 
			
		||||
        }
 | 
			
		||||
        return sb.toString();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    @SneakyThrows
 | 
			
		||||
    static PrivateKey getPrivateKey() {
 | 
			
		||||
        ClassPathResource licenseKeyResource = new ClassPathResource("jetbra.key");
 | 
			
		||||
        Security.addProvider(new BouncyCastleProvider());
 | 
			
		||||
        PEMParser pemParser = new PEMParser(new InputStreamReader(licenseKeyResource.getInputStream()));
 | 
			
		||||
        JcaPEMKeyConverter converter = new JcaPEMKeyConverter().setProvider("BC");
 | 
			
		||||
        Object object = pemParser.readObject();
 | 
			
		||||
        KeyPair kp = converter.getKeyPair((PEMKeyPair) object);
 | 
			
		||||
        return kp.getPrivate();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @SneakyThrows
 | 
			
		||||
    static X509Certificate getCertificate() {
 | 
			
		||||
        CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
 | 
			
		||||
        ClassPathResource crtResource = new ClassPathResource("jetbra.crt");
 | 
			
		||||
        return (X509Certificate) certificateFactory.generateCertificate(crtResource.getInputStream());
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										40
									
								
								jetbra-server/src/main/java/win/novice/li/model/License.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								jetbra-server/src/main/java/win/novice/li/model/License.java
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,40 @@
 | 
			
		||||
package win.novice.li.model;
 | 
			
		||||
 | 
			
		||||
import jakarta.validation.Valid;
 | 
			
		||||
import jakarta.validation.constraints.Min;
 | 
			
		||||
import jakarta.validation.constraints.NotBlank;
 | 
			
		||||
import jakarta.validation.constraints.NotEmpty;
 | 
			
		||||
import jakarta.validation.constraints.NotNull;
 | 
			
		||||
import lombok.Data;
 | 
			
		||||
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
@Data
 | 
			
		||||
public class License {
 | 
			
		||||
    private String licenseId;
 | 
			
		||||
    @NotBlank
 | 
			
		||||
    private String licenseeName = "Test";
 | 
			
		||||
    @NotBlank
 | 
			
		||||
    private String assigneeName = "novice.li";
 | 
			
		||||
    @NotNull
 | 
			
		||||
    private String assigneeEmail = "";
 | 
			
		||||
    @NotNull
 | 
			
		||||
    private String licenseRestriction = "";
 | 
			
		||||
    @NotNull
 | 
			
		||||
    private Boolean checkConcurrentUse = false;
 | 
			
		||||
 | 
			
		||||
    @NotEmpty
 | 
			
		||||
    private List<@Valid Product> products;
 | 
			
		||||
    @NotBlank
 | 
			
		||||
    private String metadata = "0120230102PPAA013009";
 | 
			
		||||
    @NotBlank
 | 
			
		||||
    private String hash = "41472961/0:1563609451";
 | 
			
		||||
 | 
			
		||||
    @NotNull
 | 
			
		||||
    @Min(1)
 | 
			
		||||
    private Integer gracePeriodDays = 7;
 | 
			
		||||
    @NotNull
 | 
			
		||||
    private Boolean autoProlongated = true;
 | 
			
		||||
    @NotNull
 | 
			
		||||
    private Boolean isAutoProlongated = true;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										19
									
								
								jetbra-server/src/main/java/win/novice/li/model/Product.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								jetbra-server/src/main/java/win/novice/li/model/Product.java
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,19 @@
 | 
			
		||||
 | 
			
		||||
package win.novice.li.model;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
import jakarta.validation.constraints.NotBlank;
 | 
			
		||||
import jakarta.validation.constraints.NotNull;
 | 
			
		||||
import lombok.Data;
 | 
			
		||||
 | 
			
		||||
@Data
 | 
			
		||||
public class Product {
 | 
			
		||||
    @NotBlank
 | 
			
		||||
    private String code;
 | 
			
		||||
    @NotBlank
 | 
			
		||||
    private String fallbackDate = "2025-12-31";
 | 
			
		||||
    @NotBlank
 | 
			
		||||
    private String paidUpTo = "2025-12-31";
 | 
			
		||||
    @NotNull
 | 
			
		||||
    private Boolean extended = false;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										28
									
								
								jetbra-server/src/main/resources/jetbra.crt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								jetbra-server/src/main/resources/jetbra.crt
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,28 @@
 | 
			
		||||
-----BEGIN CERTIFICATE-----
 | 
			
		||||
MIIEtTCCAp2gAwIBAgIUDyuccmylba71lZQAQic5TJiAhwwwDQYJKoZIhvcNAQEL
 | 
			
		||||
BQAwGDEWMBQGA1UEAwwNSmV0UHJvZmlsZSBDQTAeFw0yMzA5MjkxNDA2MTJaFw0z
 | 
			
		||||
MzA5MjcxNDA2MTJaMBExDzANBgNVBAMMBk5vdmljZTCCAiIwDQYJKoZIhvcNAQEB
 | 
			
		||||
BQADggIPADCCAgoCggIBALenqcGP2ZxGkYqmKA9c4Hzf8+YD1smvmOxKjd+bmTLr
 | 
			
		||||
utM/hXv1cj1rW3/lqyDtdDk7K6W8/TDq1CRrEt+Do6l30DxhAiC34aH8DmGwgq77
 | 
			
		||||
xEoLimvH5LpePxflF+tbB1RZtFgFDOIYLdSQaKFH2JDgVKxhLiV3S6jniPhkCtWW
 | 
			
		||||
rTs+E6vq4N15Bm3NnM5AJILqjtUbOjNfaxVq6RrOoTc0R3Fqqo6yvxo/+JYa2UnH
 | 
			
		||||
IC+r2dbKuDLMUrtgnydEUdJNX0zH9FtcdELvr48uc9mY038TWUsZUK1pnQbxA2bP
 | 
			
		||||
yA4qnYJ9IvUgO6LtLXvGFm137YQMS1N41AHDBOrwoNI8UoDX+qI3rM96biFOFvn7
 | 
			
		||||
Edky7rByzybt3H+zxdojfjvpL1E0NO98BT9zfufHAaAxZtlmDOu5LDJe3CGurnyR
 | 
			
		||||
MRExbtc+Qjl1mUh6tG4lakAwdsoxry0GdG72yaYyb9it53kaFks/T/s7Z7bRJzVF
 | 
			
		||||
zQDV1Y4bzUtk43vKm2vztBVlQkBkZY5f2Jbe5Ig3b8swQzBnOT0mrL5SPUhwmQ6I
 | 
			
		||||
xkEWztj55OEujBMmRr92oESuq9ZYMaeLidKWVR3/++HA8BRZaRGEKtSHZCbFEFdi
 | 
			
		||||
hDxxJv9Xh6NuT/ewJ6HYp+0NQpFnUnJ72n8wV+tudpam7aKcdzVmz7cNwOhG2Ls7
 | 
			
		||||
AgMBAAEwDQYJKoZIhvcNAQELBQADggIBAIdeaQfKni7tXtcywC3zJvGzaaj242pS
 | 
			
		||||
WB1y40HW8jub0uHjTLsBPX27iA/5rb+rNXtUWX/f2K+DU4IgaIiiHhkDrMsw7piv
 | 
			
		||||
azqwA9h7/uA0A5nepmTYf/HY4W6P2stbeqInNsFRZXS7Jg4Q5LgEtHKo/H8USjtV
 | 
			
		||||
w9apmE3BCElkXRuelXMsSllpR/JEVv/8NPLmnHSY02q4KMVW2ozXtaAxSYQmZswy
 | 
			
		||||
P1YnBcnRukoI4igobpcKQXwGoQCIUlec8LbFXYM9V2eNCwgABqd4r67m7QJq31Y/
 | 
			
		||||
1TJysQdMH+hoPFy9rqNCxSq3ptpuzcYAk6qVf58PrrYH/6bHwiYPAayvvdzNPOhM
 | 
			
		||||
9OCwomfcazhK3y7HyS8aBLntTQYFf7vYzZxPMDybYTvJM+ClCNnVD7Q9fttIJ6eM
 | 
			
		||||
XFsXb8YK1uGNjQW8Y4WHk1MCHuD9ZumWu/CtAhBn6tllTQWwNMaPOQvKf1kr1Kt5
 | 
			
		||||
etrONY+B6O+Oi75SZbDuGz7PIF9nMPy4WB/8XgKdVFtKJ7/zLIPHgY8IKgbx/VTz
 | 
			
		||||
6uBhYo8wOf3xzzweMnn06UcfV3JGNvtMuV4vlkZNNxXeifsgzHugCvJX0nybhfBh
 | 
			
		||||
fIqVyfK6t0eKJqrvp54XFEtJGR+lf3pBfTdcOI6QFEPKGZKoQz8Ck+BC/WBDtbjc
 | 
			
		||||
/uYKczZ8DKZu
 | 
			
		||||
-----END CERTIFICATE-----
 | 
			
		||||
@@ -1,3 +0,0 @@
 | 
			
		||||
<html>
 | 
			
		||||
<p>hello world</p>
 | 
			
		||||
</html>
 | 
			
		||||
		Reference in New Issue
	
	Block a user