IntelliJ IDEA 2025.3.1.1 记录
JetBrains IntelliJ IDEA 2025.3.1.1 记录
前置ja-netfilter 安装
参考:
ja-netfilter.jar 文件
Release 2025.3.0 · ja-netfilter/ja-netfilter - Gitee.com
scripts 和vmoptions 目录
config和plugins 目录
注意项
要使用自生成的激活码则必须要配置power.conf 文件
参考:
ja-netfilter power插件原理 - MoYuno
激活码生成
需要将新的“生成power.conf ” 结果复制到ja-netfilter\config-jetbrains\power.conf或者ja-netfilter\config\power.conf (要根据ja-netfilter安装时的配置)
# https://github.com/just-ads/script/blob/main/idea/sign.py
import base64
import datetime
import os
from typing import Tuple
import json
#pip install pycryptodome
from Crypto.Hash import SHA256
from Crypto.Signature.pkcs1_15 import _EMSA_PKCS1_V1_5_ENCODE
from Crypto.Util.number import ceil_div
#pip install cryptography
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, padding
from cryptography.x509.oid import NameOID
# 常量定义
ONE_DAY = datetime.timedelta(days=1)
TEN_YEARS = datetime.timedelta(days=3650)
CA_COMMON_NAME = "JetProfile CA"
CERT_COMMON_NAME = "IKUN"
KEY_SIZE = 4096
PUBLIC_EXPONENT = 65537
def generate_self_signed_certificate(
cert_common_name: str = CERT_COMMON_NAME,
key_size: int = KEY_SIZE,
validity_days: int = 3650
) -> Tuple[rsa.RSAPrivateKey, x509.Certificate]:
"""
生成自签名的CA证书
Args:
cert_common_name: 证书的通用名称
key_size: RSA密钥大小
validity_days: 证书有效期(天)
Returns:
私钥和证书的元组
"""
print("\n=== 生成自签名CA证书 ===")
today = datetime.datetime.today()
not_valid_before = today - ONE_DAY
not_valid_after = today + datetime.timedelta(days=validity_days)
# 生成RSA密钥对
private_key = rsa.generate_private_key(
public_exponent=PUBLIC_EXPONENT,
key_size=key_size,
backend=default_backend()
)
public_key = private_key.public_key()
# 构建证书
builder = x509.CertificateBuilder()
builder = builder.subject_name(x509.Name([
x509.NameAttribute(NameOID.COMMON_NAME, cert_common_name),
]))
builder = builder.issuer_name(x509.Name([
x509.NameAttribute(NameOID.COMMON_NAME, 'JetProfile CA'),
]))
builder = builder.not_valid_before(not_valid_before)
builder = builder.not_valid_after(not_valid_after)
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()
)
save_key_and_certificate(private_key, certificate)
return private_key, certificate
def save_key_and_certificate(
private_key: rsa.RSAPrivateKey,
certificate: x509.Certificate,
key_filename: str = "ca.key",
cert_filename: str = "ca.crt"
) -> None:
"""
保存私钥和证书到文件
Args:
private_key: RSA私钥
certificate: X.509证书
key_filename: 私钥文件名
cert_filename: 证书文件名
"""
# 序列化私钥
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(key_filename, "wb") as f:
f.write(private_bytes)
with open(cert_filename, "wb") as f:
f.write(public_bytes)
print("✓ 证书已生成并保存到 ca.key 和 ca.crt")
def load_certificate_from_file() -> Tuple[rsa.RSAPrivateKey, x509.Certificate]:
"""
从文件加载证书,支持PEM和DER格式
Returns:
X.509证书对象
Raises:
ValueError: 如果证书格式无效
"""
print('\n======加载证书======')
with open('ca.crt', "rb") as f:
cert_data = f.read()
with open('ca.key', "rb") as f:
key_data = f.read()
try:
certificate = x509.load_pem_x509_certificate(cert_data, default_backend())
private_key = serialization.load_pem_private_key(key_data, password=None)
return private_key, certificate
except Exception:
try:
certificate = x509.load_der_x509_certificate(cert_data, default_backend())
private_key = serialization.load_der_private_key(key_data, password=None)
return private_key, certificate
except Exception as e:
raise ValueError(f"无法加载证书文件: {e}")
def create_license_signature(license_data: dict, private_key: rsa.RSAPrivateKey) -> str:
"""
创建许可证签名
Args:
license_data: 许可证数据
private_key: 私钥
Returns:
完整的许可证字符串
"""
try:
license_id = license_data.get('licenseId')
license_bytes = json.dumps(license_data).encode('utf-8')
signature = private_key.sign(
license_bytes,
padding.PKCS1v15(),
hashes.SHA1()
)
# Base64编码
license_part_base64 = base64.b64encode(license_bytes).decode('utf-8')
signature_base64 = base64.b64encode(signature).decode('utf-8')
return f"{license_id}-{license_part_base64}-{signature_base64}"
except Exception as e:
print(f"创建许可证签名时出错: {e}")
raise
def verify_license_signature(license_string: str, cert_base64: str) -> bool:
"""
验证许可证签名
Args:
license_string: 许可证字符串
cert_base64: Base64编码的证书(DER格式)
Returns:
签名是否有效
"""
try:
# 解析许可证字符串
parts = license_string.split('-')
if len(parts) < 3:
raise ValueError("无效的许可证格式")
license_part_base64 = parts[1]
signature_base64 = parts[2]
# 解码许可证数据
license_data = base64.b64decode(license_part_base64).decode('utf-8')
# 加载证书和公钥
cert = x509.load_der_x509_certificate(base64.b64decode(cert_base64))
public_key = cert.public_key()
# 验证签名
public_key.verify(
base64.b64decode(signature_base64),
license_data.encode('utf-8'),
padding=padding.PKCS1v15(),
algorithm=hashes.SHA1(),
)
return True
except Exception as e:
print(f"验证许可证签名时出错: {e}")
return False
# https://github.com/JetBrains/marketplace-makemecoffee-plugin/blob/master/src/main/java/com/company/license/CheckLicense.java
JB_ROOT_CERTS=[
"-----BEGIN CERTIFICATE-----\n" +
"MIIFOzCCAyOgAwIBAgIJANJssYOyg3nhMA0GCSqGSIb3DQEBCwUAMBgxFjAUBgNV\n" +
"BAMMDUpldFByb2ZpbGUgQ0EwHhcNMTUxMDAyMTEwMDU2WhcNNDUxMDI0MTEwMDU2\n" +
"WjAYMRYwFAYDVQQDDA1KZXRQcm9maWxlIENBMIICIjANBgkqhkiG9w0BAQEFAAOC\n" +
"Ag8AMIICCgKCAgEA0tQuEA8784NabB1+T2XBhpB+2P1qjewHiSajAV8dfIeWJOYG\n" +
"y+ShXiuedj8rL8VCdU+yH7Ux/6IvTcT3nwM/E/3rjJIgLnbZNerFm15Eez+XpWBl\n" +
"m5fDBJhEGhPc89Y31GpTzW0vCLmhJ44XwvYPntWxYISUrqeR3zoUQrCEp1C6mXNX\n" +
"EpqIGIVbJ6JVa/YI+pwbfuP51o0ZtF2rzvgfPzKtkpYQ7m7KgA8g8ktRXyNrz8bo\n" +
"iwg7RRPeqs4uL/RK8d2KLpgLqcAB9WDpcEQzPWegbDrFO1F3z4UVNH6hrMfOLGVA\n" +
"xoiQhNFhZj6RumBXlPS0rmCOCkUkWrDr3l6Z3spUVgoeea+QdX682j6t7JnakaOw\n" +
"jzwY777SrZoi9mFFpLVhfb4haq4IWyKSHR3/0BlWXgcgI6w6LXm+V+ZgLVDON52F\n" +
"LcxnfftaBJz2yclEwBohq38rYEpb+28+JBvHJYqcZRaldHYLjjmb8XXvf2MyFeXr\n" +
"SopYkdzCvzmiEJAewrEbPUaTllogUQmnv7Rv9sZ9jfdJ/cEn8e7GSGjHIbnjV2ZM\n" +
"Q9vTpWjvsT/cqatbxzdBo/iEg5i9yohOC9aBfpIHPXFw+fEj7VLvktxZY6qThYXR\n" +
"Rus1WErPgxDzVpNp+4gXovAYOxsZak5oTV74ynv1aQ93HSndGkKUE/qA/JECAwEA\n" +
"AaOBhzCBhDAdBgNVHQ4EFgQUo562SGdCEjZBvW3gubSgUouX8bMwSAYDVR0jBEEw\n" +
"P4AUo562SGdCEjZBvW3gubSgUouX8bOhHKQaMBgxFjAUBgNVBAMMDUpldFByb2Zp\n" +
"bGUgQ0GCCQDSbLGDsoN54TAMBgNVHRMEBTADAQH/MAsGA1UdDwQEAwIBBjANBgkq\n" +
"hkiG9w0BAQsFAAOCAgEAjrPAZ4xC7sNiSSqh69s3KJD3Ti4etaxcrSnD7r9rJYpK\n" +
"BMviCKZRKFbLv+iaF5JK5QWuWdlgA37ol7mLeoF7aIA9b60Ag2OpgRICRG79QY7o\n" +
"uLviF/yRMqm6yno7NYkGLd61e5Huu+BfT459MWG9RVkG/DY0sGfkyTHJS5xrjBV6\n" +
"hjLG0lf3orwqOlqSNRmhvn9sMzwAP3ILLM5VJC5jNF1zAk0jrqKz64vuA8PLJZlL\n" +
"S9TZJIYwdesCGfnN2AETvzf3qxLcGTF038zKOHUMnjZuFW1ba/12fDK5GJ4i5y+n\n" +
"fDWVZVUDYOPUixEZ1cwzmf9Tx3hR8tRjMWQmHixcNC8XEkVfztID5XeHtDeQ+uPk\n" +
"X+jTDXbRb+77BP6n41briXhm57AwUI3TqqJFvoiFyx5JvVWG3ZqlVaeU/U9e0gxn\n" +
"8qyR+ZA3BGbtUSDDs8LDnE67URzK+L+q0F2BC758lSPNB2qsJeQ63bYyzf0du3wB\n" +
"/gb2+xJijAvscU3KgNpkxfGklvJD/oDUIqZQAnNcHe7QEf8iG2WqaMJIyXZlW3me\n" +
"0rn+cgvxHPt6N4EBh5GgNZR4l0eaFEV+fxVsydOQYo1RIyFMXtafFBqQl6DDxujl\n" +
"FeU3FZ+Bcp12t7dlM4E0/sS1XdL47CfGVj4Bp+/VbF862HmkAbd7shs7sDQkHbU=\n" +
"-----END CERTIFICATE-----\n",
"-----BEGIN CERTIFICATE-----\n" +
"MIIFTDCCAzSgAwIBAgIJAMCrW9HV+hjZMA0GCSqGSIb3DQEBCwUAMB0xGzAZBgNV\n" +
"BAMMEkxpY2Vuc2UgU2VydmVycyBDQTAgFw0xNjEwMTIxNDMwNTRaGA8yMTE2MTIy\n" +
"NzE0MzA1NFowHTEbMBkGA1UEAwwSTGljZW5zZSBTZXJ2ZXJzIENBMIICIjANBgkq\n" +
"hkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAoT7LvHj3JKK2pgc5f02z+xEiJDcvlBi6\n" +
"fIwrg/504UaMx3xWXAE5CEPelFty+QPRJnTNnSxqKQQmg2s/5tMJpL9lzGwXaV7a\n" +
"rrcsEDbzV4el5mIXUnk77Bm/QVv48s63iQqUjVmvjQt9SWG2J7+h6X3ICRvF1sQB\n" +
"yeat/cO7tkpz1aXXbvbAws7/3dXLTgAZTAmBXWNEZHVUTcwSg2IziYxL8HRFOH0+\n" +
"GMBhHqa0ySmF1UTnTV4atIXrvjpABsoUvGxw+qOO2qnwe6ENEFWFz1a7pryVOHXg\n" +
"P+4JyPkI1hdAhAqT2kOKbTHvlXDMUaxAPlriOVw+vaIjIVlNHpBGhqTj1aqfJpLj\n" +
"qfDFcuqQSI4O1W5tVPRNFrjr74nDwLDZnOF+oSy4E1/WhL85FfP3IeQAIHdswNMJ\n" +
"y+RdkPZCfXzSUhBKRtiM+yjpIn5RBY+8z+9yeGocoxPf7l0or3YF4GUpud202zgy\n" +
"Y3sJqEsZksB750M0hx+vMMC9GD5nkzm9BykJS25hZOSsRNhX9InPWYYIi6mFm8QA\n" +
"2Dnv8wxAwt2tDNgqa0v/N8OxHglPcK/VO9kXrUBtwCIfZigO//N3hqzfRNbTv/ZO\n" +
"k9lArqGtcu1hSa78U4fuu7lIHi+u5rgXbB6HMVT3g5GQ1L9xxT1xad76k2EGEi3F\n" +
"9B+tSrvru70CAwEAAaOBjDCBiTAdBgNVHQ4EFgQUpsRiEz+uvh6TsQqurtwXMd4J\n" +
"8VEwTQYDVR0jBEYwRIAUpsRiEz+uvh6TsQqurtwXMd4J8VGhIaQfMB0xGzAZBgNV\n" +
"BAMMEkxpY2Vuc2UgU2VydmVycyBDQYIJAMCrW9HV+hjZMAwGA1UdEwQFMAMBAf8w\n" +
"CwYDVR0PBAQDAgEGMA0GCSqGSIb3DQEBCwUAA4ICAQCJ9+GQWvBS3zsgPB+1PCVc\n" +
"oG6FY87N6nb3ZgNTHrUMNYdo7FDeol2DSB4wh/6rsP9Z4FqVlpGkckB+QHCvqU+d\n" +
"rYPe6QWHIb1kE8ftTnwapj/ZaBtF80NWUfYBER/9c6To5moW63O7q6cmKgaGk6zv\n" +
"St2IhwNdTX0Q5cib9ytE4XROeVwPUn6RdU/+AVqSOspSMc1WQxkPVGRF7HPCoGhd\n" +
"vqebbYhpahiMWfClEuv1I37gJaRtsoNpx3f/jleoC/vDvXjAznfO497YTf/GgSM2\n" +
"LCnVtpPQQ2vQbOfTjaBYO2MpibQlYpbkbjkd5ZcO5U5PGrQpPFrWcylz7eUC3c05\n" +
"UVeygGIthsA/0hMCioYz4UjWTgi9NQLbhVkfmVQ5lCVxTotyBzoubh3FBz+wq2Qt\n" +
"iElsBrCMR7UwmIu79UYzmLGt3/gBdHxaImrT9SQ8uqzP5eit54LlGbvGekVdAL5l\n" +
"DFwPcSB1IKauXZvi1DwFGPeemcSAndy+Uoqw5XGRqE6jBxS7XVI7/4BSMDDRBz1u\n" +
"a+JMGZXS8yyYT+7HdsybfsZLvkVmc9zVSDI7/MjVPdk6h0sLn+vuPC1bIi5edoNy\n" +
"PdiG2uPH5eDO6INcisyPpLS4yFKliaO4Jjap7yzLU9pbItoWgCAYa2NpxuxHJ0tB\n" +
"7tlDFnvaRnQukqSG+VqNWg==\n" +
"-----END CERTIFICATE-----"]
def generate_power_conf(sign:int, result:int,outpath='power.conf'):
cfgs=[]
roots=x509.load_pem_x509_certificates(''.join(JB_ROOT_CERTS).encode())
for cert in roots:
public_key = cert.public_key()
pn=public_key.public_numbers()
n=pn.n
conf=f'EQUAL,{sign},{PUBLIC_EXPONENT},{n}->{result}'
cfgs.append(conf)
text='[Result]\n'+'\n'.join(cfgs)
print(text)
print('\n\n\n')
# if os.path.exists(outpath):
# os.rename(outpath,outpath+'.bak')
# print(f'backup file:{outpath}==>{outpath}.bak')
if not os.path.exists(outpath):
with open(outpath, 'w', encoding='utf-8') as f:
f.write(text)
print(f"wirte to:",outpath)
def make_products(Date:str,codes:list[str]):
out=[]
for x in codes:
d={
"code": x,
"fallbackDate": Date,
"paidUpTo": Date,
"extended": True
}
out.append(d)
return out
def main():
is_cert_exists = os.path.exists('ca.key') and os.path.exists('ca.crt')
if is_cert_exists:
private_key, cert = load_certificate_from_file()
else:
private_key, cert = generate_self_signed_certificate()
# 打印证书信息
print(f"\n证书主题: {cert.subject}")
print(f"证书颁发者: {cert.issuer}")
print(f"证书有效期: {cert.not_valid_before_utc} 到 {cert.not_valid_after_utc}")
print(f"证书序列号: {cert.serial_number} \n")
cert_base64 = base64.b64encode(cert.public_bytes(serialization.Encoding.DER)).decode('utf-8')
public_key = cert.public_key()
# 计算签名值
sign = int.from_bytes(cert.signature, byteorder="big")
print(f"证书签名值: {sign}")
# 计算TBS证书的哈希
mod_bits = public_key.key_size
digest_cert = SHA256.new(cert.tbs_certificate_bytes)
# 使用PKCS#1 v1.5编码
r = int.from_bytes(
_EMSA_PKCS1_V1_5_ENCODE(digest_cert, ceil_div(mod_bits, 8)),
byteorder='big',
signed=False
)
print(f"计算得到的签名值: {r}")
print(f"\n=== 生成power.conf ===")
generate_power_conf(sign, r)
print("\n=== 创建许可证签名 ===")
date = (datetime.datetime.today() + datetime.timedelta(5 * 365)).strftime("%Y-%m-%d")
licenseId = base64.b32encode(os.urandom(10)).decode()[:10]
licenseeName = 'IKUN'
assigneeName = 'kunkun'
# codes=["PCWMP","PRR","PDB","PSI","II", "PS", "AC", "DB", "RM", "WS", "RD", "CL", "PC", "GO", "DS", "DC", "DPN", "DM"]
codes=["II","PCWMP","PSI"]
license_data = {
'licenseId': licenseId,
'licenseeName': licenseeName,
'licenseeType': 'PERSONAL',
'assigneeName': assigneeName,
'assigneeEmail': "",
'licenseRestriction': "JetBrains",
'checkConcurrentUse': False,
"products": make_products(date,codes),
# "metadata": "0120230102PPAA013009",
"metadata": "0120230914PSAX000005",
# "hash": "41472961/0:1563609451",
"gracePeriodDays": 7,
"autoProlongated": False,
"isAutoProlongated": False,
'trial': False,
'aiAllowed': True
}
license_string = f'{create_license_signature(license_data, private_key)}-{cert_base64}'
print(f"✓ 许可证签名已创建")
print(license_string)
print("\n=== 验证许可证签名 ===")
if verify_license_signature(license_string, cert_base64):
print("✓ 许可证签名验证成功")
else:
print("✗ 许可证签名验证失败")
if __name__ == "__main__":
main()
自签名验证
def lic_test(lic:bytes):
if isinstance(lic,str):
lic=lic.encode()
licenseId,licensePartBase64,sig_results,certBase64=lic.split(b'-')
print('[-]licenseId:',licenseId)
print('[-]sig_results:',sig_results)
# print(parts)
print('[-]license:',base64.standard_b64decode(licensePartBase64) )
cert=x509.load_der_x509_certificate(base64.b64decode(certBase64))
print('[-]cert:',cert)
print('\t cert.serial_number:',cert.serial_number)
print('\t cert.issuer:',cert.issuer)
print('\t cert.subject:',cert.subject)
public_key = cert.public_key()
print(public_key.public_numbers())
try:
public_key.verify(
base64.b64decode(sig_results),
base64.b64decode(licensePartBase64),
padding=padding.PKCS1v15(),
algorithm=hashes.SHA1(),
)
print('[+]lic verify ok!')
except:
print('[!]lic verify error!')
'Ultimate' 功能需要许可证。(todo)
一段时间之后就会弹窗
'Ultimate' 功能需要许可证。
不知道哪个地方的校验,未解决,可能需要在url.conf添加项
断网使用0.0
ps

参考链接
Release 2025.3.0 · ja-netfilter/ja-netfilter - Gitee.com
marketplace-makemecoffee-plugin
ja-netfilter破解某IDE原理分析及生成激活码 - 知乎

浙公网安备 33010602011771号