IDea-key

IDEA许可证的思路

离线激活需要用到一个文件,主要用到插件里面的power.conf配置规则,有了规则以后就可以根据自己的证书得到许可证

Url:https://gitcode.com/likedx/jetbra/blob/main/jetbra.zip

生成证书Python

import datetime

from cryptography import x509
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.x509.oid import NameOID

one_day = datetime.timedelta(days=1)
ten_day = datetime.timedelta(days=3650)
today = datetime.datetime.today()
yesterday = today - one_day
tomorrow = today + ten_day

private_key = rsa.generate_private_key(
    public_exponent=65537,
    key_size=4096,
    backend=default_backend()
)
public_key = private_key.public_key()
builder = x509.CertificateBuilder()

builder = builder.subject_name(x509.Name([
    x509.NameAttribute(NameOID.COMMON_NAME, 'Novice-from-2022-07-25'),
]))
builder = builder.issuer_name(x509.Name([
    x509.NameAttribute(NameOID.COMMON_NAME, 'JetProfile CA'),
]))
builder = builder.not_valid_before(yesterday)
builder = builder.not_valid_after(tomorrow)
builder = builder.serial_number(x509.random_serial_number())
builder = builder.public_key(public_key)

certificate = builder.sign(
    private_key=private_key, algorithm=hashes.SHA256(),
    backend=default_backend()
)

private_bytes = private_key.private_bytes(
    encoding=serialization.Encoding.PEM,
    format=serialization.PrivateFormat.TraditionalOpenSSL,
    encryption_algorithm=serialization.NoEncryption())
public_bytes = certificate.public_bytes(
    encoding=serialization.Encoding.PEM)
with open("ca.key", "wb") as fout:
    fout.write(private_bytes)
with open("ca.crt", "wb") as fout:
    fout.write(public_bytes)
 

在java中用生成的证书去生成key

import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.openssl.PEMKeyPair;
import org.bouncycastle.openssl.PEMParser;
import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;

import java.io.FileInputStream;
import java.io.FileReader;
import java.nio.charset.StandardCharsets;
import java.security.KeyPair;
import java.security.PrivateKey;
import java.security.Security;
import java.security.Signature;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.Base64;

public class Demo {
    public static void main(String[] args) throws Exception {

        CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
        X509Certificate cert = (X509Certificate) certificateFactory.generateCertificate(new FileInputStream("ca.crt"));

        // 自己修改 license内容
        // 注意licenseId要一致
        // 里面的内容是激活webstorm
        String licensePart = "{\"licenseId\":\"AB598FD8A4\",\"licenseeName\":\"blogdx\",\"assigneeName\":\"\",\"products\":[{\"code\":\"II\",\"fallbackDate\":\"2099-12-31\",\"paidUpTo\":\"2099-12-31\"},{\"code\":\"PCWMP\",\"fallbackDate\":\"2099-12-31\",\"paidUpTo\":\"2099-12-31\"},{\"code\":\"PSI\",\"fallbackDate\":\"2099-12-31\",\"paidUpTo\":\"2099-12-31\"}],\"metadata\":\"0120230914PSAX000005\"}\n";


        String licenseId = "AB598FD8A4";
        byte[] licensePartBytes = licensePart.getBytes(StandardCharsets.UTF_8);
        String licensePartBase64 = Base64.getEncoder().encodeToString(licensePartBytes);

        PrivateKey privateKey = getPrivateKey();


        Signature signature = Signature.getInstance("SHA1withRSA");
        signature.initSign(privateKey);
        signature.update(licensePartBytes);
        byte[] signatureBytes = signature.sign();

        String sigResultsBase64 = Base64.getEncoder().encodeToString(signatureBytes);
//        verify
//        Signature verifySignature = Signature.getInstance("SHA1withRSA");
//        verifySignature.initVerify(cert.getPublicKey());
//        verifySignature.update(Base64.getDecoder().decode(licensePartBase64));
//        boolean verify = verifySignature.verify(Base64.getDecoder().decode(sigResultsBase64));
//        System.out.println(verify);


        // Combine results as needed
        String result = licenseId + "-" + licensePartBase64 + "-" + sigResultsBase64 + "-" + Base64.getEncoder().encodeToString(cert.getEncoded());
        System.out.println(result);

    }


    static PrivateKey getPrivateKey() throws Exception {
        Security.addProvider(new BouncyCastleProvider());
        PEMParser pemParser = new PEMParser(new FileReader("ca.key"));
        JcaPEMKeyConverter converter = new JcaPEMKeyConverter().setProvider("BC");
        Object object = pemParser.readObject();
        KeyPair kp = converter.getKeyPair((PEMKeyPair) object);
        return kp.getPrivate();
    }

}

第三步根据key生成power的规则

import base64
import hashlib
 
from cryptography import x509
 
 
def padding(b):
    return f"0001{'ff' * (512 - len(b) // 2 - 3)}00{b}"
 
 
def getRule(key):
    subcert = x509.load_der_x509_certificate(base64.b64decode(key.split('-')[3]))
    s = int.from_bytes(subcert.signature, byteorder='big', signed=False)
    sha = hashlib.sha256()
    sha.update(subcert.tbs_certificate_bytes)
    r = int.from_bytes(bytes.fromhex(padding("3031300D060960864801650304020105000420" + sha.digest().hex())),
                       byteorder='big', signed=False)
    return f"EQUAL,{s},65537,860106576952879101192782278876319243486072481962999610484027161162448933268423045647258145695082284265933019120714643752088997312766689988016808929265129401027490891810902278465065056686129972085119605237470899952751915070244375173428976413406363879128531449407795115913715863867259163957682164040613505040314747660800424242248055421184038777878268502955477482203711835548014501087778959157112423823275878824729132393281517778742463067583320091009916141454657614089600126948087954465055321987012989937065785013284988096504657892738536613208311013047138019418152103262155848541574327484510025594166239784429845180875774012229784878903603491426732347994359380330103328705981064044872334790365894924494923595382470094461546336020961505275530597716457288511366082299255537762891238136381924520749228412559219346777184174219999640906007205260040707839706131662149325151230558316068068139406816080119906833578907759960298749494098180107991752250725928647349597506532778539709852254478061194098069801549845163358315116260915270480057699929968468068015735162890213859113563672040630687357054902747438421559817252127187138838514773245413540030800888215961904267348727206110582505606182944023582459006406137831940959195566364811905585377246353->{r}"
 
 
if __name__ == '__main__':
    key = "AB598FD8A4-eyJsaWNlbnNlSWQiOiJBQjU5OEZEOEE0IiwibGljZW5zZWVOYW1lIjoiYmxvZ2R4IiwiYXNzaWduZWVOYW1lIjoiIiwicHJvZHVjdHMiOlt7ImNvZGUiOiJJSSIsImZhbGxiYWNrRGF0ZSI6IjIwOTktMTItMzEiLCJwYWlkVXBUbyI6IjIwOTktMTItMzEifSx7ImNvZGUiOiJQQ1dNUCIsImZhbGxiYWNrRGF0ZSI6IjIwOTktMTItMzEiLCJwYWlkVXBUbyI6IjIwOTktMTItMzEifSx7ImNvZGUiOiJQU0kiLCJmYWxsYmFja0RhdGUiOiIyMDk5LTEyLTMxIiwicGFpZFVwVG8iOiIyMDk5LTEyLTMxIn1dLCJtZXRhZGF0YSI6IjAxMjAyMzA5MTRQU0FYMDAwMDA1In0K-HfZZgCi60BD6TUnWqFGaENYlIfIFSwoHBGXahyZB3+XrZodZojetJXpvDhzQJutWU2KjOMX110ssbQoGxje+koaHsxJjI2Lte0A1VB26aCAsDT40Jjzy3cHfSdT1O1Icwhz0rW2aaMUszMggOzvEs7sfb964J/q3F1lmNWNUIbtTL0TN+4BBMghnOoOjQx/cCT5ej2zPB/PmHHAaDkdW9HotzYHNS/jNBwNEJx+VX9UH2Mc+Xkx4sk596VQw7ycUhpbtf3elCCV3GkFAwI1dnPgFPtkVMF6h6pWGwGwoOL82dGvyvKeK3RjLz7iy+OIDWWJV2UkDjoREivs/uexCPge7II4PBVZcys0HrgU/WwS2FFVHgTy+49ig1PkPU1D6/qqcQOe3exnZzHmFU51Wef2FuencOaeZLTNInDk5xseCfFDJs+dPvyniLPkmhPfnEZaSE7udlaljUury1fQ6PSC1W9615qCIJu8Cc+Wx0PvbiWVUNiIQ5LnUdMjhAdZVDx0DFbzHsEtIaXUN4W9QVlHKPPKqCJeB7y4dW8DCWTbBPhzt67ZCWD3mz0+pHSjfqyjgihk4c4SvqSrbfnc03Rhecyw+eurbQBKe2O1ZDcBejrkYrf9G6hFb3lpmTviOf5crWK2ibvIZECE0cT7kolZPOFIeEaCdIt25hUNHQ+0=-MIIEwDCCAqigAwIBAgIUcCXd1w38NmkCcYj1eaNOAU1GE0YwDQYJKoZIhvcNAQELBQAwGDEWMBQGA1UEAwwNSmV0UHJvZmlsZSBDQTAeFw0yNTEwMDYwMTI5MTlaFw0zNTEwMDUwMTI5MTlaMBwxGjAYBgNVBAMMEUNOPUpldEJyYWlucy1IZWxwMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAyTvq42HDD5mheiwshmBwPSXAKLk+b3p6aAxxnPkW/wsmbUj9xI5EiR5vWv+rRHJuf+mKXj81mUBDhT6D/h1KvcFJ+8sKAhFPlYXTl/QEPfMPe+AtZE3Sf73nTF+sgme1DeNEIBfQFy5WiwJG5CEn6q8ux2qdY0RtJPt9AkohoMyLMtqaYFZ2UOe2iX4alN7ZnJxR2QnY7aQsozq5b1EAj87OdkV6YTN6gA53k1EHYG33nC+rb0yokBZ2fgfTNyAadu6DhUK+KJdhwsqMCYIP3EvhMeeySB96aj3Od/gTYZES496ElwODgZtxi3IZSKCOBD9R22ikv+XOxFscnWAyS6YcB8TBpaOyrexvIWNMgIzJ6yqYXz0zOuJOtVK66zfBLu05BUBiMEJSvMx48D5WqJfHyp1qh2oaqH26wYbrWXkAzu7S2IytCUwFHcucaiDS1Urzxhp8/31AilOyBUVKwgXT37BfTpp8zk4idIEYTKGjXzEw1IP0F/wa7XxhFwQ4uAIto1EPC5KHYljCbQ8uEySIF5mLJpxu2AK9UlULD3sflfyxrVMrDjvNHf9VznxIiYYeKlfFk8ESOc+futs9gXeH6pvICcCdF+22Z5keR5sLK2rmqLxFirRXFBcfoN+s6cXjhbvF/KYcrxKgGSwhXjdrZ7s2t/yTyyZTTZUJSNUCAwEAATANBgkqhkiG9w0BAQsFAAOCAgEAkCZ9rD+rfdkkRNh6YjIUxgOK5ogfuaHSU4/+/npAAO3quaxcBi6UzUoe/l+vVEvoitoLy+PybQ4wfP0Jb24z4V09c4maQVPAbQdUiD7GrjldYaWYQNF/WYRpNTOSdodiy9ZFZnkHTiVSrwCnYOmDAbA8kCMxXw2fKXgax9gRTJy4Pz8/g5EO1XGvJzfmQsDfN2i9gk4LCKHXAxC7BpL3q9J4vl1AVvPpe6UyBP5JM4Cmxnfj6N1rFPMys1DJWOvxYM0oadWkg0rIReNFc6Qlx3+2Lgs3S5MQnvzyZ5JcRQJJmtiD6Kfndi2TQCtThttJMsaMxSww/razLCMUi8jU8Ghbefr1p70i08C+MF+Imh+qktA8V4sLQWzxJruIETmuPrspQp7fzkUMGbFkCYdYaSaV2aYB/vCVLdFvyAYN/B9AY5bGeZUPch7rdtXPze1YnlyD35pego2h7zO1+anSOAOgaF30CQimY9ZQKu6dQGI8SCsXwdF8HS/T42YyX1yl8Jt3PTp+Ed8CDT8QhniGTnXbM5n3L7m+EuzZlLoTZ853IioO7PQ8nDpTzcbZU+p79hSjodN8BYA1Z29QnydSXre/gBdoqPhMUQ2jgUCehvXz+VxFJ1gieIoYdWgnkNzmX7wzkMfIuJstlOjpIJjMQbAxhkhJjypU12P0i+ml6/0="
    
    rtn = getRule(key)

    print(rtn)

Pyhton版本

以下可以直接生成证书,根据证书来生成对应的规则和Key 可以直接使用

import base64
import json
import hashlib
import random
import string
import datetime
from cryptography import x509
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.asymmetric import padding, rsa
from cryptography.x509.oid import NameOID

def generate_license():
    """一键生成许可证和规则"""
    # 1. 生成证书(如果不存在)
    try:
        with open("ca.key", "rb") as f:
            private_key = serialization.load_pem_private_key(f.read(), password=None)
        with open("ca.crt", "rb") as f:
            certificate = x509.load_pem_x509_certificate(f.read())
        print("使用现有证书")
    except:
        print("生成新证书...")
        private_key, certificate = generate_certificate()
    
    # 2. 生成许可证数据
    license_id = ''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(10))
    license_data = {
        "licenseId": license_id,
        "licenseeName": "blogdx",
        "assigneeName": "",
        "products": [
            {"code": "II", "fallbackDate": "2099-12-31", "paidUpTo": "2099-12-31"},
            {"code": "PCWMP", "fallbackDate": "2099-12-31", "paidUpTo": "2099-12-31"},
            {"code": "PSI", "fallbackDate": "2099-12-31", "paidUpTo": "2099-12-31"}
        ],
        "metadata": "0120230914PSAX000005"
    }
    
    # 3. 生成许可证密钥
    license_json = json.dumps(license_data, separators=(',', ':')) + "\n"
    license_bytes = license_json.encode('utf-8')
    
    signature = private_key.sign(license_bytes, padding.PKCS1v15(), hashes.SHA1())
    
    license_base64 = base64.b64encode(license_bytes).decode('utf-8')
    signature_base64 = base64.b64encode(signature).decode('utf-8')
    cert_base64 = base64.b64encode(certificate.public_bytes(serialization.Encoding.DER)).decode('utf-8')
    
    license_key = f"{license_id}-{license_base64}-{signature_base64}-{cert_base64}"
    
    # 4. 生成规则
    rule = generate_rule(license_key)
    
    return license_key, rule

def generate_certificate():
    """生成证书"""
    one_day = datetime.timedelta(days=1)
    ten_day = datetime.timedelta(days=3650)
    today = datetime.datetime.today()
    yesterday = today - one_day
    tomorrow = today + ten_day

    private_key = rsa.generate_private_key(
        public_exponent=65537,
        key_size=4096,
        backend=default_backend()
    )
    
    builder = x509.CertificateBuilder()
    builder = builder.subject_name(x509.Name([
        x509.NameAttribute(NameOID.COMMON_NAME, 'JetBrains-Help'),
    ]))
    builder = builder.issuer_name(x509.Name([
        x509.NameAttribute(NameOID.COMMON_NAME, 'JetProfile CA'),
    ]))
    builder = builder.not_valid_before(yesterday)
    builder = builder.not_valid_after(tomorrow)
    builder = builder.serial_number(x509.random_serial_number())
    builder = builder.public_key(private_key.public_key())

    certificate = builder.sign(private_key=private_key, algorithm=hashes.SHA256(), backend=default_backend())

    with open("ca.key", "wb") as f:
        f.write(private_key.private_bytes(
            encoding=serialization.Encoding.PEM,
            format=serialization.PrivateFormat.TraditionalOpenSSL,
            encryption_algorithm=serialization.NoEncryption()))
    
    with open("ca.crt", "wb") as f:
        f.write(certificate.public_bytes(encoding=serialization.Encoding.PEM))
    
    return private_key, certificate

def generate_rule(license_key):
    """生成规则"""
    def padding(b):
        return f"0001{'ff' * (512 - len(b) // 2 - 3)}00{b}"
    
    parts = license_key.split('-')
    cert_base64 = parts[3]
    
    cert_der = base64.b64decode(cert_base64)
    subcert = x509.load_der_x509_certificate(cert_der, backend=default_backend())
    
    s = int.from_bytes(subcert.signature, byteorder='big', signed=False)
    
    sha = hashlib.sha256()
    sha.update(subcert.tbs_certificate_bytes)
    cert_hash_hex = sha.digest().hex()
    
    asn1_prefix = "3031300D060960864801650304020105000420"
    hash_data = asn1_prefix + cert_hash_hex
    
    padded_data = padding(hash_data)
    r = int.from_bytes(bytes.fromhex(padded_data), byteorder='big', signed=False)
    
    rule = f"EQUAL,{s},65537,860106576952879101192782278876319243486072481962999610484027161162448933268423045647258145695082284265933019120714643752088997312766689988016808929265129401027490891810902278465065056686129972085119605237470899952751915070244375173428976413406363879128531449407795115913715863867259163957682164040613505040314747660800424242248055421184038777878268502955477482203711835548014501087778959157112423823275878824729132393281517778742463067583320091009916141454657614089600126948087954465055321987012989937065785013284988096504657892738536613208311013047138019418152103262155848541574327484510025594166239784429845180875774012229784878903603491426732347994359380330103328705981064044872334790365894924494923595382470094461546336020961505275530597716457288511366082299255537762891238136381924520749228412559219346777184174219999640906007205260040707839706131662149325151230558316068068139406816080119906833578907759960298749494098180107991752250725928647349597506532778539709852254478061194098069801549845163358315116260915270480057699929968468068015735162890213859113563672040630687357054902747438421559817252127187138838514773245413540030800888215961904267348727206110582505606182944023582459006406137831940959195566364811905585377246353->{r}"
    
    return rule

if __name__ == "__main__":
    # 一键生成
    license_key, rule = generate_license()
    
    print("生成的许可证:")
    print(license_key)
    print("\n生成的规则:")
    print(rule)
    
    # 保存文件
    with open("license.txt", "w") as f:
        f.write(license_key)
    with open("power.conf", "w") as f:
        f.write(rule)
    
    print("\n文件已保存: license.txt, power.conf")

PHP接口版本

此接口用来返回Key 前提条件是需要有证书才可以运行

<?php
header('Content-Type: application/json');
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET, POST');

class LicenseAPI {
    private $privateKey;
    
    public function __construct($privateKeyPath = "ca.key") {
        if (!file_exists($privateKeyPath)) {
            throw new Exception("私钥文件不存在");
        }
        
        $this->privateKey = openssl_pkey_get_private(file_get_contents($privateKeyPath));
        if (!$this->privateKey) {
            throw new Exception("无法加载私钥");
        }
    }
    
    public function generateLicense($licenseeName = "blogdx") {
        $dateSeed = date('Ymd');
        
        $licenseId = $this->generateDailyId(10, $dateSeed);
        $metadata = $this->generateMetadata($dateSeed);
        
        $licenseData = [
            "licenseId" => $licenseId,
            "licenseeName" => $licenseeName,
            "assigneeName" => "",
            "products" => [
                (object)["code" => "II", "fallbackDate" => "2099-12-31", "paidUpTo" => "2099-12-31"],
                (object)["code" => "PCWMP", "fallbackDate" => "2099-12-31", "paidUpTo" => "2099-12-31"],
                (object)["code" => "PSI", "fallbackDate" => "2099-12-31", "paidUpTo" => "2099-12-31"]
            ],
            "metadata" => $metadata
        ];
        
        $licenseJson = json_encode($licenseData, JSON_UNESCAPED_SLASHES);
        $licenseJson = preg_replace('/,\s*"/', ',"', $licenseJson);
        $licenseJson = preg_replace('/:\s*/', ':', $licenseJson) . "\n";
        
        openssl_sign($licenseJson, $signature, $this->privateKey, OPENSSL_ALGO_SHA1);
        
        $certDer = $this->getCertificate();
        
        $licenseKey = $licenseId . "-" . 
                     base64_encode($licenseJson) . "-" . 
                     base64_encode($signature) . "-" . 
                     base64_encode($certDer);
        
        return $licenseKey;
    }
    
    private function generateDailyId($length, $dateSeed) {
        $chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
        $result = '';
        mt_srand(crc32($dateSeed));
        
        for ($i = 0; $i < $length; $i++) {
            $result .= $chars[mt_rand(0, strlen($chars) - 1)];
        }
        return $result;
    }
    
    private function generateMetadata($dateSeed) {
        mt_srand(crc32($dateSeed . '_metadata'));
        return "01" . date('Ymd') . "PSAX" . str_pad(mt_rand(0, 999999), 6, '0', STR_PAD_LEFT);
    }
    
    private function getCertificate() {
        if (!file_exists("ca.crt")) {
            throw new Exception("证书文件不存在");
        }
        
        $certContent = file_get_contents("ca.crt");
        $pemData = preg_replace('/-----BEGIN CERTIFICATE-----|-----END CERTIFICATE-----|\s/', '', $certContent);
        return base64_decode($pemData);
    }
    
    public function __destruct() {
        if ($this->privateKey) {
            openssl_pkey_free($this->privateKey);
        }
    }
}

try {
    $licenseeName = $_POST['licenseeName'] ?? $_GET['licenseeName'] ?? 'blogdx';
    
    $generator = new LicenseAPI();
    $licenseKey = $generator->generateLicense($licenseeName);
    
    echo json_encode([
        'message' => '200',
        'data' => [
            'download_url' => 'https://gitcode.com/likedx/jetbra/blob/main/jetbra.zip',
            'key' => $licenseKey,
            'current_time' => date('Y-m-d H:i:s')
        ]
    ], JSON_UNESCAPED_UNICODE);
    
} catch (Exception $e) {
    http_response_code(500);
    echo json_encode([
        'message' => '500',
        'data' => null
    ], JSON_UNESCAPED_UNICODE);
}
?>

返回的格式如下

{
  "message": "200",
  "data": {
    "download_url": "https://gitcode.com/likedx/jetbra/blob/main/jetbra.zip",
    "key": "JEL3XPN047-eyJsaWNlbnNlSWQiOiJKRUwzWFBOMDQ3IiwibGljZW5zZWVOYW1lIjoiYmxvZ2R4IiwiYXNzaWduZWVOYW1lIjoiIiwicHJvZHVjdHMiOlt7ImNvZGUiOiJJSSIsImZhbGxiYWNrRGF0ZSI6IjIwOTktMTItMzEiLCJwYWlkVXBUbyI6IjIwOTktMTItMzEifSx7ImNvZGUiOiJQQ1dNUCIsImZhbGxiYWNrRGF0ZSI6IjIwOTktMTItMzEiLCJwYWlkVXBUbyI6IjIwOTktMTItMzEifSx7ImNvZGUiOiJQU0kiLCJmYWxsYmFja0RhdGUiOiIyMDk5LTEyLTMxIiwicGFpZFVwVG8iOiIyMDk5LTEyLTMxIn1dLCJtZXRhZGF0YSI6IjAxMjAyNTEwMDhQU0FYNTE2OTQyIn0K-LLSY7miATE3A0hN0glpyRDec9RX7lx21UAeomgRQHA6scoDx7sXsNVH/S3LFNR4ylLrXVfrE+54cl5KsGEhOt5sWz9i43NKtKRhXNXTco7H+Kcr1/SQUY5kL9oZEJgwj0aa4I9P0jverE/czV/ObmJLBnarXaKchN3j58iBmbAm7XWfyxkekSm8P15QygiVS5WuTG7iqVc0IvTtDkkNzUgtapYxegYW/0KRH8SB/y2PHNcInobWwC+yhXYHmU8jHU4vgm+ECrYWpAGSvBrhuiIqQCq0P9E43QD4ADkUec1pSeVmxPONujzgvpyyYge0ha+s/ZZ+iYDo9hh389L4ok5Dy7bCjeyOhvsZGCD0LC1gdTKYthgRTSMkxpv+Fwoew7dsi3bVrMzk58HdDaofLcWyEcCzhMd2x/1JGt/DHP67k2J76NqY+/167U9rfZrUQZoR3aQeLFwEWKYD9m+2AhgV2r4OwGYEltRanxHCbNMhdCf2SWZMo5wyp/CIHxJPbtAqBtiv+mNS3AuRp7E6446ddVrwYxV5BgV8QIPC+prNuNAM9y0skZ5PR/KTwZRidtW6TzrW0UGVIgnk1WoAhpSh+4YMcpGM9UKwtbFq8/5Ug8TJo7wWfni/Dns14RXv/XBNnT+FZrk453m6I1XMnIMbnZSN+Qm04pOeRbcjArZk=-MIIEwDCCAqigAwIBAgIUcCXd1w38NmkCcYj1eaNOAU1GE0YwDQYJKoZIhvcNAQELBQAwGDEWMBQGA1UEAwwNSmV0UHJvZmlsZSBDQTAeFw0yNTEwMDYwMTI5MTlaFw0zNTEwMDUwMTI5MTlaMBwxGjAYBgNVBAMMEUNOPUpldEJyYWlucy1IZWxwMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAyTvq42HDD5mheiwshmBwPSXAKLk+b3p6aAxxnPkW/wsmbUj9xI5EiR5vWv+rRHJuf+mKXj81mUBDhT6D/h1KvcFJ+8sKAhFPlYXTl/QEPfMPe+AtZE3Sf73nTF+sgme1DeNEIBfQFy5WiwJG5CEn6q8ux2qdY0RtJPt9AkohoMyLMtqaYFZ2UOe2iX4alN7ZnJxR2QnY7aQsozq5b1EAj87OdkV6YTN6gA53k1EHYG33nC+rb0yokBZ2fgfTNyAadu6DhUK+KJdhwsqMCYIP3EvhMeeySB96aj3Od/gTYZES496ElwODgZtxi3IZSKCOBD9R22ikv+XOxFscnWAyS6YcB8TBpaOyrexvIWNMgIzJ6yqYXz0zOuJOtVK66zfBLu05BUBiMEJSvMx48D5WqJfHyp1qh2oaqH26wYbrWXkAzu7S2IytCUwFHcucaiDS1Urzxhp8/31AilOyBUVKwgXT37BfTpp8zk4idIEYTKGjXzEw1IP0F/wa7XxhFwQ4uAIto1EPC5KHYljCbQ8uEySIF5mLJpxu2AK9UlULD3sflfyxrVMrDjvNHf9VznxIiYYeKlfFk8ESOc+futs9gXeH6pvICcCdF+22Z5keR5sLK2rmqLxFirRXFBcfoN+s6cXjhbvF/KYcrxKgGSwhXjdrZ7s2t/yTyyZTTZUJSNUCAwEAATANBgkqhkiG9w0BAQsFAAOCAgEAkCZ9rD+rfdkkRNh6YjIUxgOK5ogfuaHSU4/+/npAAO3quaxcBi6UzUoe/l+vVEvoitoLy+PybQ4wfP0Jb24z4V09c4maQVPAbQdUiD7GrjldYaWYQNF/WYRpNTOSdodiy9ZFZnkHTiVSrwCnYOmDAbA8kCMxXw2fKXgax9gRTJy4Pz8/g5EO1XGvJzfmQsDfN2i9gk4LCKHXAxC7BpL3q9J4vl1AVvPpe6UyBP5JM4Cmxnfj6N1rFPMys1DJWOvxYM0oadWkg0rIReNFc6Qlx3+2Lgs3S5MQnvzyZ5JcRQJJmtiD6Kfndi2TQCtThttJMsaMxSww/razLCMUi8jU8Ghbefr1p70i08C+MF+Imh+qktA8V4sLQWzxJruIETmuPrspQp7fzkUMGbFkCYdYaSaV2aYB/vCVLdFvyAYN/B9AY5bGeZUPch7rdtXPze1YnlyD35pego2h7zO1+anSOAOgaF30CQimY9ZQKu6dQGI8SCsXwdF8HS/T42YyX1yl8Jt3PTp+Ed8CDT8QhniGTnXbM5n3L7m+EuzZlLoTZ853IioO7PQ8nDpTzcbZU+p79hSjodN8BYA1Z29QnydSXre/gBdoqPhMUQ2jgUCehvXz+VxFJ1gieIoYdWgnkNzmX7wzkMfIuJstlOjpIJjMQbAxhkhJjypU12P0i+ml6/0=",
    "current_time": "2025-10-08 15:39:03"
  }
}

番外

已知在已有环境下运行的时候,需要输入Key才可以激活、在插件环境条件的支持下可以生成一个Key文件,替换掉本地的idea.key也可以做到不用输入,旧版本使用PowerSHell在线运行脚本是可以做到这一点的,中间有一个操作是从服务器生成出来的Key替换在了本地

本地的路径为C:\Users\likedx\AppData\Roaming\JetBrains\IntelliJIdea2025.2\idea.key

以下是一个PHP版本,可以直接返回一个idea.key,若后续需要扩展脚本可以用此版本来实现,此版本需要证书在本地才可以实现,证书可以根据上面的进行生成、以下版本需要Post传递参数

{
  "assigneeName": "",
  "expiryDate": "2099-12-31",
  "productCode": "II,PCWMP,PSI",
  "licenseName": "blogdx"
}
<?php
class CorrectLicenseGenerator {
    private $privateKey;
    
    public function __construct($privateKeyPath = "ca.key") {
        $this->loadPrivateKey($privateKeyPath);
    }
    
    private function loadPrivateKey($privateKeyPath) {
        if (!file_exists($privateKeyPath)) {
            throw new Exception("私钥文件不存在: " . $privateKeyPath);
        }
        
        $privateKeyContent = file_get_contents($privateKeyPath);
        $this->privateKey = openssl_pkey_get_private($privateKeyContent);
        if (!$this->privateKey) {
            throw new Exception("无法加载私钥: " . openssl_error_string());
        }
    }
    
    public function generateLicense($licenseeName = "blogdx", $assigneeName = "", $expiryDate = "2099-12-31", $productCodes = "II,PCWMP,PSI") {
        // 生成许可证ID
        $licenseId = $this->generateLicenseId(10);
        
        // 解析产品代码
        $products = [];
        $productArray = explode(',', $productCodes);
        foreach ($productArray as $code) {
            $products[] = (object)[
                "code" => trim($code),
                "fallbackDate" => $expiryDate,
                "paidUpTo" => $expiryDate
            ];
        }
        
        // 构建许可证数据
        $licenseData = [
            "licenseId" => $licenseId,
            "licenseeName" => $licenseeName,
            "assigneeName" => $assigneeName,
            "products" => $products,
            "metadata" => "0120230914PSAX000005"
        ];
        
        // 生成JSON
        $licenseJson = json_encode($licenseData, JSON_UNESCAPED_SLASHES);
        $licenseJson = preg_replace('/,\s*"/', ',"', $licenseJson);
        $licenseJson = preg_replace('/:\s*/', ':', $licenseJson);
        $licenseJson .= "\n";
        
        // 签名
        $signature = '';
        $success = openssl_sign($licenseJson, $signature, $this->privateKey, OPENSSL_ALGO_SHA1);
        if (!$success) {
            throw new Exception("签名失败: " . openssl_error_string());
        }
        
        // 读取证书
        $certDer = $this->getCertificateDER();
        
        // Base64编码
        $licenseBase64 = base64_encode($licenseJson);
        $signatureBase64 = base64_encode($signature);
        $certBase64 = base64_encode($certDer);
        
        // 构建许可证密钥
        $licenseKey = "{$licenseId}-{$licenseBase64}-{$signatureBase64}-{$certBase64}";
        
        return $licenseKey;
    }
    
    private function generateLicenseId($length) {
        $characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
        $result = '';
        $max = strlen($characters) - 1;
        for ($i = 0; $i < $length; $i++) {
            $result .= $characters[random_int(0, $max)];
        }
        return $result;
    }
    
    private function getCertificateDER() {
        if (!file_exists("ca.crt")) {
            throw new Exception("证书文件不存在: ca.crt");
        }
        
        $certContent = file_get_contents("ca.crt");
        $pemData = preg_replace('/-----BEGIN CERTIFICATE-----|-----END CERTIFICATE-----|\s/', '', $certContent);
        return base64_decode($pemData);
    }
    
    public function downloadLicenseWithHeader($licenseKey, $filename = "idea") {
        // 创建特殊格式的内容 - 以U+FFFF字符开头,然后是头信息和许可证密钥
        $bom = "\xFF\xFF"; // U+FFFF 字符的 UTF-16 LE 编码
        $header = "<certificate-key>\n"; // 头信息单独一行
        $content = $bom . mb_convert_encoding($header . $licenseKey, 'UTF-16LE', 'UTF-8');
        
        // 设置HTTP头以触发下载
        header('Content-Type: application/octet-stream');
        header('Content-Disposition: attachment; filename="' . $filename . '.key"');
        header('Content-Length: ' . strlen($content));
        
        // 输出文件内容
        echo $content;
        exit;
    }
    
    public function __destruct() {
        if ($this->privateKey) {
            openssl_pkey_free($this->privateKey);
        }
    }
}

// 处理POST请求
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    try {
        // 获取POST数据
        $input = file_get_contents('php://input');
        $data = json_decode($input, true);
        
        // 设置参数,如果没有提供则使用默认值
        $assigneeName = isset($data['assigneeName']) ? $data['assigneeName'] : "";
        $expiryDate = isset($data['expiryDate']) ? $data['expiryDate'] : "2099-12-31";
        $productCode = isset($data['productCode']) ? $data['productCode'] : "II,PCWMP,PSI";
        $licenseName = isset($data['licenseName']) ? $data['licenseName'] : "blogdx";
        
        $generator = new CorrectLicenseGenerator();
        $licenseKey = $generator->generateLicense($licenseName, $assigneeName, $expiryDate, $productCode);
        
        // 下载带有特殊格式的UTF-16 LE编码文件
        $generator->downloadLicenseWithHeader($licenseKey, "idea");
        
    } catch (Exception $e) {
        // 如果有错误,返回JSON错误信息
        header('Content-Type: application/json');
        echo json_encode(["error" => $e->getMessage()]);
        exit(1);
    }
} else {
     echo "It works!";
     exit(1);
}
?>

参考资料

https://blog.novitechie.com/archives/idea-cracking

https://www.xuzhengtong.com/2022/07/25/ja-netfilter/ja-netfilter-plugins-power/

https://bbs.kanxue.com/thread-271578.htm

https://bbs.kanxue.com/thread-271052.htm

https://ckey.run

https://3.jetbra.in/

以上仅供学习交流使用

最后修改:2025 年 10 月 25 日
如果觉得我的文章对你有用,请随意赞赏