使用了ecdh算法,非标准椭圆曲线参数。
分析过程懒得写了,直接上demo
python
import os
import base64
from util.ENCUtils import ENCUtils
from ecdsa.ellipticcurve import Point, CurveFp
class SoulCustomCurve:
_INSTANCE = None
def __new__(cls, *args, **kwargs):
if not cls._INSTANCE:
cls._INSTANCE = super(SoulCustomCurve, cls).__new__(cls, *args, **kwargs)
return cls._INSTANCE
@staticmethod
def get_instance():
if SoulCustomCurve._INSTANCE is None:
SoulCustomCurve._INSTANCE = SoulCustomCurve()
return SoulCustomCurve._INSTANCE
def __init__(self):
# 自定义的椭圆曲线参数
self.p = 6277101735386680763835789423207666416102355444459739541047 # p 参数
self.a = 0 # a 参数
self.b = 3 # b 参数
self.Gx = 5377521262291226325198505011805525673063229037935769709693 # G 的 x 坐标
self.Gy = 3805108391982600717572440947423858335415441070543209377693 # G 的 y 坐标
self.curve = CurveFp(self.p, self.a, self.b) # 定义椭圆曲线
self.G = Point(self.curve, self.Gx, self.Gy) # 定义椭圆曲线上的基点 G
self.n = 6277101735386680763835789423061264271957123915200845512077 # n 参数
# 创建私钥和公钥
self.client_private_key = int.from_bytes(os.urandom(24), byteorder='big') # 使用 os.urandom 生成私钥
self.client_public_key = self.point_multiply(self.client_private_key, self.G)
self.server_public_key = (5400262085967213433717992037101256438732384858453335109798,
6167642468723156401569091099299085180686314126654549364092)
self.shared_key = None
self.shared_key_encoded = None
def get_curve(self):
# 返回椭圆曲线
return self.curve
def get_base_point(self):
# 返回基点 G
return self.G
def get_order(self):
# 返回阶数
return self.n
# 倍点运算:计算 k * P
def point_multiply(self, k, p: Point):
"""点乘 kP = Q (mod p)"""
R = (0, 0) # 零点
Q = (p.x(), p.y())
while k:
if k & 1:
R = self.point_add(R, Q)
Q = self.point_add(Q, Q)
k >>= 1
return R
def point_add(self, P, Q):
"""点加法 P + Q = R (mod p)"""
if P == (0, 0): # 零点,返回 Q
return Q
if Q == (0, 0): # 零点,返回 P
return P
# 如果 P 或 Q 是 Point 对象,则需要使用 P.x 和 P.y 来获取坐标
if P[0] == 0 and P[1] == 0:
return Q
if Q[0] == 0 and Q[1] == 0:
return P
# 计算斜率 λ
if P != Q:
m = (Q[1] - P[1]) * pow(Q[0] - P[0], self.curve.p() - 2, self.curve.p()) % self.curve.p()
else:
m = (3 * P[0] ** 2 + self.curve.a()) * pow(2 * P[1], self.curve.p() - 2, self.curve.p()) % self.curve.p()
# 计算新的 x 和 y 坐标
x_r = (m ** 2 - P[0] - Q[0]) % self.curve.p()
y_r = (m * (P[0] - x_r) - P[1]) % self.curve.p()
return x_r, y_r
def get_client_public_key(self):
return b"\x04" + \
self.client_public_key[0].to_bytes(24, byteorder="big") + \
self.client_public_key[1].to_bytes(24, byteorder="big")
# return bytes.fromhex("04cf6b0577c58d70bac18ca92f435620f42712ba76a1ba5dc2552c9df82aff1a0f5a12e3fa08c03c4e5e79032b83fb613f")
def get_server_public_key(self):
return b"\x04" + \
self.server_public_key[0].to_bytes(24, byteorder="big") + \
self.server_public_key[1].to_bytes(24, byteorder="big")
def get_client_private_key(self):
return self.client_private_key.to_bytes(24, byteorder="big")
def get_shared_key(self):
if self.shared_key is None:
pub_key = self.server_public_key
pub_key_point = Point(self.get_curve(), pub_key[0], pub_key[1])
shared_key_tuple = self.client_private_key * pub_key_point
shared_key: int = shared_key_tuple.x()
self.shared_key = shared_key.to_bytes(24, byteorder="big")
return self.shared_key
def get_shared_key_encoded(self):
if self.shared_key_encoded is None:
shared_key = self.get_shared_key()
shared_key_base64: str = base64.b64encode(shared_key[0:16]).decode("utf-8")
salt = ENCUtils.md5("w[" + shared_key_base64[0:4] + "t}")
self.shared_key_encoded = salt[-2:] + shared_key_base64 + salt[0:2]
key = self.shared_key_encoded.encode("utf-8")
if len(key) < 16:
key = key + ("\x00" * (16 - len(key)))
return key
# return bytes.fromhex("343179723633667448627543777366535a34324c4e7635513d3d3664").decode("utf-8")
class ExchangeKeyUtil:
_COMMON_AES_KEY = b"V0hRuZT+zZmj\x00\x00\x00\x00"
@staticmethod
def get_shared_key():
return SoulCustomCurve.get_instance().get_shared_key_encoded()
@staticmethod
def encrypted_pub_key():
client_pub_key = SoulCustomCurve.get_instance().get_client_public_key()
return ExchangeKeyUtil._encrypt(client_pub_key, ExchangeKeyUtil._COMMON_AES_KEY)
@staticmethod
def encrypt_data(d):
key = SoulCustomCurve.get_instance().get_shared_key_encoded()
return ExchangeKeyUtil._encrypt(d, key)
@staticmethod
def decrypt_data(d):
key = SoulCustomCurve.get_instance().get_shared_key_encoded()
return ExchangeKeyUtil._decrypt(d, key)
@staticmethod
def _decrypt(d, aes_key):
not_use = d[0:2]
random = d[2:6]
zero = d[6:7]
raw_encrypted = d[7:]
iv = ENCUtils.sha1(random)[0:16]
decrypted = ENCUtils.aes_decrypt(raw_encrypted, aes_key[0:16], iv)
return decrypted
@staticmethod
def _encrypt(d, aes_key):
# key = SoulCustomCurve.get_instance().get_shared_key_encoded()
random = os.urandom(4)
iv = ENCUtils.sha1(random)[0:16]
pad_len = 16 - (len(d) & 0xF)
final_data = d + (pad_len * pad_len.to_bytes(1, byteorder="big"))
encrypted = ENCUtils.aes_encrypt_no_padding(final_data, aes_key[0:16], iv)
return bytes.fromhex("0203") + random + b"\x00" + encrypted
if __name__ == "__main__":
# 使用自定义曲线
custom_curve = SoulCustomCurve.get_instance()
print(custom_curve.get_shared_key_encoded())
print(ExchangeKeyUtil.encrypted_pub_key().hex())