test_apikey_crypto.py 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. #!/usr/bin/env python3
  2. """
  3. API Key 加解密测试脚本
  4. 测试三种场景:
  5. 1. Python 加密 → Python 解密
  6. 2. Python 加密 → JavaScript 解密(输出 JS 代码供浏览器控制台测试)
  7. 3. 多个不同长度的 key 测试
  8. """
  9. import os
  10. import sys
  11. # 设置测试密钥
  12. os.environ['APIKEY_ENCRYPT_KEY'] = '25e9e87b18cf40d0ed0f102b8d2ec3a8'
  13. sys.path.insert(0, 'backend')
  14. from app.utils.apikey_crypto import encrypt_api_key, decrypt_api_key
  15. def test_python():
  16. print("=" * 60)
  17. print("测试 1: Python 加密 → Python 解密")
  18. print("=" * 60)
  19. test_cases = [
  20. "sk-1234567890abcdef",
  21. "sk-very-long-api-key-with-special-chars-!@#$%^&*()",
  22. "short",
  23. "中文测试密钥",
  24. "a" * 100, # 长 key
  25. ]
  26. all_ok = True
  27. for i, original in enumerate(test_cases, 1):
  28. try:
  29. encrypted = encrypt_api_key(original)
  30. decrypted = decrypt_api_key(encrypted)
  31. ok = original == decrypted
  32. all_ok = all_ok and ok
  33. print(f"\n[{i}] {'✓' if ok else '✗'}")
  34. print(f" 原文: {original[:50]}{'...' if len(original) > 50 else ''}")
  35. print(f" 密文: {encrypted[:60]}{'...' if len(encrypted) > 60 else ''}")
  36. print(f" 解密: {decrypted[:50]}{'...' if len(decrypted) > 50 else ''}")
  37. if not ok:
  38. print(f" ❌ 解密失败!")
  39. except Exception as e:
  40. print(f"\n[{i}] ✗ 异常: {e}")
  41. all_ok = False
  42. print(f"\n{'='*60}")
  43. print(f"Python 测试结果: {'全部通过 ✓' if all_ok else '有失败 ✗'}")
  44. print(f"{'='*60}\n")
  45. return all_ok
  46. def test_javascript():
  47. print("=" * 60)
  48. print("测试 2: JavaScript 解密验证")
  49. print("=" * 60)
  50. test_key = "sk-test-key-for-javascript-1234567890"
  51. encrypted = encrypt_api_key(test_key)
  52. secret = os.environ['APIKEY_ENCRYPT_KEY']
  53. print(f"\n原文: {test_key}")
  54. print(f"密文: {encrypted}")
  55. print(f"密钥: {secret}")
  56. print("\n复制以下 JavaScript 代码到浏览器控制台运行:")
  57. print("-" * 60)
  58. js_code = f"""
  59. // ── 解密函数 ──────────────────────────────────────────────────────────────────
  60. async function deriveKeystream(key, length) {{
  61. const enc = new TextEncoder();
  62. const keyBytes = enc.encode(key);
  63. const stream = [];
  64. let block = 0;
  65. while (stream.length < length) {{
  66. const blockBytes = new Uint8Array(4);
  67. new DataView(blockBytes.buffer).setUint32(0, block, false);
  68. const input = new Uint8Array([...keyBytes, ...blockBytes]);
  69. const hash = await crypto.subtle.digest('SHA-256', input);
  70. stream.push(...new Uint8Array(hash));
  71. block++;
  72. }}
  73. return stream.slice(0, length);
  74. }}
  75. function rotr8(byte, n) {{
  76. n = n % 8;
  77. return ((byte >>> n) | (byte << (8 - n))) & 0xFF;
  78. }}
  79. function base64urlDecode(str) {{
  80. str = str.replace(/-/g, '+').replace(/_/g, '/');
  81. while (str.length % 4) str += '=';
  82. return Uint8Array.from(atob(str), c => c.charCodeAt(0));
  83. }}
  84. async function decryptApiKey(ciphertext, secretKey) {{
  85. const data = base64urlDecode(ciphertext);
  86. const keystream = await deriveKeystream(secretKey, data.length);
  87. const result = new Uint8Array(data.length);
  88. for (let i = 0; i < data.length; i++) {{
  89. const unshifted = rotr8(data[i], i % 5 + 1);
  90. result[i] = unshifted ^ keystream[i];
  91. }}
  92. return new TextDecoder().decode(result);
  93. }}
  94. // ── 测试数据 ──────────────────────────────────────────────────────────────────
  95. const encrypted = "{encrypted}";
  96. const secretKey = "{secret}";
  97. const expected = "{test_key}";
  98. // ── 执行解密 ──────────────────────────────────────────────────────────────────
  99. decryptApiKey(encrypted, secretKey).then(decrypted => {{
  100. console.log('原文:', expected);
  101. console.log('密文:', encrypted);
  102. console.log('解密:', decrypted);
  103. console.log('验证:', decrypted === expected ? '✓ 通过' : '✗ 失败');
  104. }});
  105. """
  106. print(js_code)
  107. print("-" * 60)
  108. print("\n预期输出: 解密结果应该等于原文")
  109. print(f"{'='*60}\n")
  110. def test_edge_cases():
  111. print("=" * 60)
  112. print("测试 3: 边界情况")
  113. print("=" * 60)
  114. cases = [
  115. ("空字符串", ""),
  116. ("单字符", "a"),
  117. ("特殊符号", "!@#$%^&*()_+-=[]{{}}|;':\",./<>?"),
  118. ("Emoji", "🔑🚀💻"),
  119. ]
  120. all_ok = True
  121. for name, original in cases:
  122. if not original: # 空字符串跳过
  123. print(f"\n[{name}] 跳过(空字符串)")
  124. continue
  125. try:
  126. encrypted = encrypt_api_key(original)
  127. decrypted = decrypt_api_key(encrypted)
  128. ok = original == decrypted
  129. all_ok = all_ok and ok
  130. print(f"\n[{name}] {'✓' if ok else '✗'}")
  131. print(f" 原文: {original}")
  132. print(f" 密文: {encrypted}")
  133. print(f" 解密: {decrypted}")
  134. except Exception as e:
  135. print(f"\n[{name}] ✗ 异常: {e}")
  136. all_ok = False
  137. print(f"\n{'='*60}")
  138. print(f"边界测试结果: {'全部通过 ✓' if all_ok else '有失败 ✗'}")
  139. print(f"{'='*60}\n")
  140. return all_ok
  141. if __name__ == "__main__":
  142. print("\n🔐 API Key 加解密测试\n")
  143. r1 = test_python()
  144. test_javascript()
  145. r2 = test_edge_cases()
  146. print("=" * 60)
  147. print("总结")
  148. print("=" * 60)
  149. print(f"Python 加解密: {'✓ 通过' if r1 else '✗ 失败'}")
  150. print(f"边界情况: {'✓ 通过' if r2 else '✗ 失败'}")
  151. print(f"\n最终结果: {'🎉 全部通过' if r1 and r2 else '❌ 有失败'}")
  152. print("=" * 60)
  153. sys.exit(0 if r1 and r2 else 1)