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