用sqlalchemy的时候要实现密码的双向加密不方便调用mysql的ENCODE函数
这里给出一个基于rsa实现双向加密,在sqlalchemy定义model的时候用起来很方便,其他ORM应该也能采用相同的思路(话说我也不知道mysql是基于什么双向加密的)
加密解密函数
import rsa
def encrypt(msg, priv_str):
if isinstance(msg, str):
msg = msg.encode()
if isinstance(priv_str, str):
priv_str = priv_str.encode()
privkey = rsa.PrivateKey.load_pkcs1(priv_str)
return rsa.encrypt(msg, privkey)
def decrypt(msg, priv_str):
if isinstance(msg, str):
msg = msg.encode()
if isinstance(priv_str, str):
priv_str = priv_str.encode()
privkey = rsa.PrivateKey.load_pkcs1(priv_str)
return rsa.decrypt(msg, privkey).decode('utf-8')
有几个注意的地方:
- 参数是私钥字符串,因为直接从rem文件读取比较方便
- rsa加解密函数返回的都是bytes
- 解密decode了加密没有,是因为rsa加密后的bytes是没法decode到utf-8的,所以存储类型是Binary。这点在http发送签名的时候会出现坑,那就是另外的故事了
model定义
class User(Base):
_pw = Column(Binary)
@property
def pw(self):
with open('private.rem', 'r') as f:
return decrypt(self._pw, f.read())
@pw.setter
def pw(self, pw):
with open('private.rem', 'r') as f:
self._pw = encrypt(pw, f.read())
def pw_verify(self, pw):
return pw == self.pw
# Usage
user = User(pw='password')
user.pw = 'password'
print(user.pw) # 'password'
print(user._pw) # b'eK:\x0f)\xa7}Gx\xe6\xfd\x14\xf3\xd8\xf1\x08f\xac\xdbL\xf23\x07#\...'
这里没啥说的,就是用了property装饰器。
有个问题是,如果在初始化对象的时候给pw赋值,能行是能行,IDE不干,非要给你标出来,强迫症就很烦,我都在下一行赋
网友评论