keygen.py 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. #!/usr/bin/env python3
  2. # -*- coding: utf-8 -*-
  3. """
  4. RSA 密钥对生成与 License 签发工具
  5. 使用方法:
  6. python keygen.py genkey
  7. python keygen.py genlicense --expire "never" --product "laser_cal" --version "1.0.0" --licensee "客户名"
  8. """
  9. import os
  10. import sys
  11. import json
  12. import argparse
  13. import base64
  14. import uuid
  15. from datetime import datetime
  16. from pathlib import Path
  17. try:
  18. from cryptography.hazmat.primitives import hashes, serialization
  19. from cryptography.hazmat.primitives.asymmetric import rsa, padding
  20. from cryptography.hazmat.backends import default_backend
  21. except ImportError:
  22. print("错误: 缺少 cryptography 库,请先安装: pip install cryptography")
  23. sys.exit(1)
  24. BASE_DIR = Path(__file__).parent
  25. LICENSE_DIR = BASE_DIR / "dist" / "license"
  26. PRIVATE_KEY_FILE = LICENSE_DIR / "private_key.pem"
  27. PUBLIC_KEY_FILE = LICENSE_DIR / "public_key.pem"
  28. LICENSE_FILE = LICENSE_DIR / "license.lic"
  29. RSA_KEY_SIZE = 2048
  30. def ensure_dir():
  31. LICENSE_DIR.mkdir(parents=True, exist_ok=True)
  32. def generate_rsa_keys():
  33. """生成 RSA 密钥对"""
  34. ensure_dir()
  35. private_key = rsa.generate_private_key(
  36. public_exponent=65537, key_size=RSA_KEY_SIZE, backend=default_backend()
  37. )
  38. private_pem = private_key.private_bytes(
  39. encoding=serialization.Encoding.PEM,
  40. format=serialization.PrivateFormat.PKCS8,
  41. encryption_algorithm=serialization.NoEncryption()
  42. )
  43. public_pem = private_key.public_key().public_bytes(
  44. encoding=serialization.Encoding.PEM,
  45. format=serialization.PublicFormat.SubjectPublicKeyInfo
  46. )
  47. PRIVATE_KEY_FILE.write_bytes(private_pem)
  48. PUBLIC_KEY_FILE.write_bytes(public_pem)
  49. print(f"[成功] RSA 密钥对已生成:")
  50. print(f" 私钥: {PRIVATE_KEY_FILE}")
  51. print(f" 公钥: {PUBLIC_KEY_FILE}")
  52. print(f" 密钥长度: {RSA_KEY_SIZE} bits")
  53. print(f"\n[重要] 请妥善保管私钥文件,切勿泄露!")
  54. def generate_license(expire_date, product="laser_cal", version="1.0.0",
  55. licensee="default", max_instances=1):
  56. """生成 License 文件"""
  57. ensure_dir()
  58. if not PRIVATE_KEY_FILE.exists():
  59. print("[错误] 私钥文件不存在,请先执行 genkey。")
  60. sys.exit(1)
  61. private_key = serialization.load_pem_private_key(
  62. PRIVATE_KEY_FILE.read_bytes(), password=None, backend=default_backend()
  63. )
  64. license_data = {
  65. "license_id": str(uuid.uuid4()),
  66. "product": product,
  67. "version": version,
  68. "licensee": licensee,
  69. "issue_date": datetime.now().strftime("%Y-%m-%d"),
  70. "expire_date": expire_date,
  71. "max_instances": max_instances,
  72. "features": ["all"]
  73. }
  74. license_json = json.dumps(license_data, sort_keys=True, ensure_ascii=False)
  75. signature = private_key.sign(
  76. license_json.encode("utf-8"), padding.PKCS1v15(), hashes.SHA256()
  77. )
  78. license_content = {
  79. "license_data": license_data,
  80. "signature": base64.b64encode(signature).decode("utf-8")
  81. }
  82. LICENSE_FILE.write_text(json.dumps(license_content, indent=2, ensure_ascii=False), encoding="utf-8")
  83. print(f"[成功] License 文件已生成: {LICENSE_FILE}")
  84. print(f" License ID : {license_data['license_id']}")
  85. print(f" 产品 : {license_data['product']}")
  86. print(f" 版本 : {license_data['version']}")
  87. print(f" 被授权人 : {license_data['licensee']}")
  88. print(f" 过期日期 : {license_data['expire_date']}")
  89. def main():
  90. parser = argparse.ArgumentParser(description="RSA License 工具")
  91. subparsers = parser.add_subparsers(dest="command")
  92. subparsers.add_parser("genkey", help="生成 RSA 密钥对")
  93. lic_parser = subparsers.add_parser("genlicense", help="生成 License")
  94. lic_parser.add_argument("--expire", type=str, default="never")
  95. lic_parser.add_argument("--product", type=str, default="laser_cal")
  96. lic_parser.add_argument("--version", type=str, default="1.0.0")
  97. lic_parser.add_argument("--licensee", type=str, default="default")
  98. lic_parser.add_argument("--max-instances", type=int, default=1)
  99. args = parser.parse_args()
  100. if args.command == "genkey":
  101. generate_rsa_keys()
  102. elif args.command == "genlicense":
  103. expire = args.expire
  104. if expire.lower() != "never":
  105. try:
  106. datetime.strptime(expire, "%Y-%m-%d")
  107. except ValueError:
  108. print("[错误] 日期格式不正确,请使用 YYYY-MM-DD 或 'never'。")
  109. sys.exit(1)
  110. generate_license(expire, args.product, args.version, args.licensee, args.max_instances)
  111. else:
  112. parser.print_help()
  113. if __name__ == "__main__":
  114. main()