From 77be634933e081c2b47fef58ee8944f6575de038 Mon Sep 17 00:00:00 2001 From: "novice.li" Date: Sun, 26 Nov 2023 12:33:38 +0800 Subject: [PATCH] server --- jetbra-dist/package.xml | 4 - jetbra-server/pom.xml | 28 ++++++ .../li/controller/LicenseController.java | 92 +++++++++++++++++++ .../java/win/novice/li/model/License.java | 40 ++++++++ .../java/win/novice/li/model/Product.java | 19 ++++ jetbra-server/src/main/resources/jetbra.crt | 28 ++++++ .../src/main/resources/public/index.html | 3 - readme.md | 1 + 8 files changed, 208 insertions(+), 7 deletions(-) create mode 100644 jetbra-server/src/main/java/win/novice/li/controller/LicenseController.java create mode 100644 jetbra-server/src/main/java/win/novice/li/model/License.java create mode 100644 jetbra-server/src/main/java/win/novice/li/model/Product.java create mode 100644 jetbra-server/src/main/resources/jetbra.crt delete mode 100644 jetbra-server/src/main/resources/public/index.html diff --git a/jetbra-dist/package.xml b/jetbra-dist/package.xml index a37e7ff..8dd7eef 100644 --- a/jetbra-dist/package.xml +++ b/jetbra-dist/package.xml @@ -41,9 +41,5 @@ ${project.parent.basedir}/jetbra-agent/target/jetbra-agent.jar jetbra-agent.jar - - ${project.parent.basedir}/readme.md - readme.md - diff --git a/jetbra-server/pom.xml b/jetbra-server/pom.xml index a72ac5f..dd2f83d 100644 --- a/jetbra-server/pom.xml +++ b/jetbra-server/pom.xml @@ -27,12 +27,31 @@ org.springframework.boot spring-boot-starter-web + + org.springframework.boot + spring-boot-starter-validation + org.springframework.boot spring-boot-starter-test test + + org.bouncycastle + bcpkix-jdk18on + 1.72 + + + org.bouncycastle + bcprov-jdk18on + 1.72 + + + org.projectlombok + lombok + true + @@ -40,8 +59,17 @@ org.springframework.boot spring-boot-maven-plugin + + + + org.projectlombok + lombok + + + + \ No newline at end of file diff --git a/jetbra-server/src/main/java/win/novice/li/controller/LicenseController.java b/jetbra-server/src/main/java/win/novice/li/controller/LicenseController.java new file mode 100644 index 0000000..3c637be --- /dev/null +++ b/jetbra-server/src/main/java/win/novice/li/controller/LicenseController.java @@ -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 generateLicense(@RequestBody @Validated License license) { + Map 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()); + } +} + diff --git a/jetbra-server/src/main/java/win/novice/li/model/License.java b/jetbra-server/src/main/java/win/novice/li/model/License.java new file mode 100644 index 0000000..5cf6224 --- /dev/null +++ b/jetbra-server/src/main/java/win/novice/li/model/License.java @@ -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; +} diff --git a/jetbra-server/src/main/java/win/novice/li/model/Product.java b/jetbra-server/src/main/java/win/novice/li/model/Product.java new file mode 100644 index 0000000..417cdc8 --- /dev/null +++ b/jetbra-server/src/main/java/win/novice/li/model/Product.java @@ -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; +} \ No newline at end of file diff --git a/jetbra-server/src/main/resources/jetbra.crt b/jetbra-server/src/main/resources/jetbra.crt new file mode 100644 index 0000000..bd113b7 --- /dev/null +++ b/jetbra-server/src/main/resources/jetbra.crt @@ -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----- diff --git a/jetbra-server/src/main/resources/public/index.html b/jetbra-server/src/main/resources/public/index.html deleted file mode 100644 index 2fe743e..0000000 --- a/jetbra-server/src/main/resources/public/index.html +++ /dev/null @@ -1,3 +0,0 @@ - -

hello world

- \ No newline at end of file diff --git a/readme.md b/readme.md index 09903f3..e29fc35 100644 --- a/readme.md +++ b/readme.md @@ -1 +1,2 @@ # Jetbra +适用于jetbrains家族产品的一款工具,参照[热老的项目](https://jetbra.in/s)自己写了点代码 ,使用方式与之一至 \ No newline at end of file