rsa_service.py 2.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. """RSA 密钥管理服务 - 用于前端传输密码的非对称加密"""
  2. import base64
  3. import os
  4. from pathlib import Path
  5. from cryptography.hazmat.primitives.asymmetric import rsa, padding
  6. from cryptography.hazmat.primitives import hashes, serialization
  7. # 密钥文件存储路径(backend/data/rsa_private_key.pem)
  8. _KEY_DIR = Path(__file__).parent.parent / "data"
  9. _PRIVATE_KEY_PATH = _KEY_DIR / "rsa_private_key.pem"
  10. _PUBLIC_KEY_PATH = _KEY_DIR / "rsa_public_key.pem"
  11. _private_key = None
  12. _public_key = None
  13. def init_rsa_keys():
  14. """初始化 RSA 密钥对:如果密钥文件已存在则加载,否则生成新密钥"""
  15. global _private_key, _public_key
  16. _KEY_DIR.mkdir(parents=True, exist_ok=True)
  17. if _PRIVATE_KEY_PATH.exists():
  18. # 加载已有密钥
  19. with open(_PRIVATE_KEY_PATH, "rb") as f:
  20. _private_key = serialization.load_pem_private_key(f.read(), password=None)
  21. with open(_PUBLIC_KEY_PATH, "rb") as f:
  22. _public_key = serialization.load_pem_public_key(f.read())
  23. else:
  24. # 生成新 RSA 2048 密钥对
  25. _private_key = rsa.generate_private_key(
  26. public_exponent=65537,
  27. key_size=2048,
  28. )
  29. _public_key = _private_key.public_key()
  30. # 保存私钥
  31. with open(_PRIVATE_KEY_PATH, "wb") as f:
  32. f.write(_private_key.private_bytes(
  33. encoding=serialization.Encoding.PEM,
  34. format=serialization.PrivateFormat.PKCS8,
  35. encryption_algorithm=serialization.NoEncryption(),
  36. ))
  37. # 保存公钥
  38. with open(_PUBLIC_KEY_PATH, "wb") as f:
  39. f.write(_public_key.public_bytes(
  40. encoding=serialization.Encoding.PEM,
  41. format=serialization.PublicFormat.SubjectPublicKeyInfo,
  42. ))
  43. print(f"✅ RSA密钥已{'加载' if _PRIVATE_KEY_PATH.exists() else '生成'}")
  44. print(f" 私钥: {_PRIVATE_KEY_PATH}")
  45. print(f" 公钥: {_PUBLIC_KEY_PATH}")
  46. def get_public_key_pem() -> str:
  47. """获取公钥 PEM 字符串(用于前端加密)"""
  48. global _public_key
  49. if _public_key is None:
  50. init_rsa_keys()
  51. return _public_key.public_bytes(
  52. encoding=serialization.Encoding.PEM,
  53. format=serialization.PublicFormat.SubjectPublicKeyInfo,
  54. ).decode()
  55. def decrypt_data(encrypted_b64: str) -> str:
  56. """解密前端 RSA-OAEP 加密的 Base64 数据"""
  57. global _private_key
  58. if _private_key is None:
  59. init_rsa_keys()
  60. try:
  61. ciphertext = base64.b64decode(encrypted_b64)
  62. plaintext = _private_key.decrypt(
  63. ciphertext,
  64. padding.OAEP(
  65. mgf=padding.MGF1(algorithm=hashes.SHA256()),
  66. algorithm=hashes.SHA256(),
  67. label=None,
  68. ),
  69. )
  70. return plaintext.decode()
  71. except Exception as e:
  72. raise ValueError(f"RSA解密失败: {e}")