前言
公司的接口全部采用 libsodium
加密了,導致接口測試非常不方便;
先前,也找到了pynacl
,但是鉆研了好久始終沒成功,網上搜了個遍,沒有看到一個完整的可適用的例子,心塞;
然后,曲線救國,把 JAVA
的加密方法打包成 jar
包,然后 Python
調 jar
去執行加解密方法。能用,但是心里不爽,畢竟走了彎路;
然后又開始鉆研pynacl
。其實 python
的 libsodium
庫有好幾個,具體可以看這里,而pynacl
是 star 最多的,所以就選擇這個;
然后反復*100次對比 java
的加解密步驟及轉碼方式,最終調通了 Python
的,看到最終的代碼其實也不難,但是官方文檔都沒有太好的例子,我是通過pynacl
項目的測試用例找到的具體怎么調用,才最終完成代碼,實屬不易;
安裝pynacl
pip install pynacl
代碼
# @author: chengjie142039
# @file: libsodium.py
# @time: 2020/12/24
# @desc: python libsodium 加解密
try:
from nacl.encoding import HexEncoder, Base64Encoder
from nacl.public import Box, PrivateKey, PublicKey
except ImportError:
raise ImportWarning('python環境中未找到nacl,請先執行 pip install pynacl 進行安裝')
def encrypt(public_key: str, private_key: str, nonce: str, plain_text: str):
"""
libsodium 加密
:param public_key: 公鑰
:param private_key: 私鑰
:param nonce: 隨機碼
:param plain_text: 加密文本
:return:加密后的密文,str 類型
"""
if len(public_key) != 64:
raise ValueError('public_key 長度必須為64')
if len(private_key) != 64:
raise ValueError('private_key 長度必須為64')
if len(nonce) != 32:
raise ValueError('nonce 長度必須為32')
# 公鑰轉 bytes,注意encoder指定HexEncoder
public = PublicKey(
public_key.encode(),
encoder=HexEncoder,
)
# 私鑰轉 bytes,注意encoder指定HexEncoder
private = PrivateKey(
private_key.encode(),
encoder=HexEncoder,
)
# 生成 box
box = Box(private, public)
# 隨機碼先轉成 bytes,再 base64 decode
nonce_bytes = Base64Encoder.decode(nonce.encode())
encrypted = box.encrypt(
plain_text.encode(),
nonce_bytes
)
ciphertext = Base64Encoder.encode(encrypted.ciphertext)
return str(ciphertext, encoding="utf8")
def decrypt(public_key: str, private_key: str, nonce: str, ciphertext: str):
"""
libsodium 解密
:param public_key: 公鑰
:param private_key: 私鑰
:param nonce: 隨機碼
:param ciphertext: 密文
:return: 解密后的文本,str 類型
"""
if len(public_key) != 64:
raise ValueError('public_key 長度必須為64')
if len(private_key) != 64:
raise ValueError('private_key 長度必須為64')
if len(nonce) != 32:
raise ValueError('nonce 長度必須為32')
public = PublicKey(
public_key.encode(),
encoder=HexEncoder,
)
private = PrivateKey(
private_key.encode(),
encoder=HexEncoder,
)
box = Box(private, public)
nonce_bytes = Base64Encoder.decode(nonce.encode())
ciphertextByte = Base64Encoder.decode(ciphertext.encode())
decrypted = box.decrypt(ciphertextByte, nonce_bytes)
return str(decrypted, encoding='utf-8')
if __name__ == '__main__':
# pass
import json
public = '5116b4433193568bf77c0a036f7cbe2476bd4701d7c2083bb8f397c56ee83255'
private = '749ac37351cf4c0232958227018658f1f67490337f4b48dd40c622b65345c099'
nonce = 'luN2OEQoVCXQUPwCa9Fu7n22mmnewqe1'
text = json.dumps({"password": "123456", "jigsawVerificationCode": {"offset": "", "token": ""}, "account": "LS5"})
ciphertext = encrypt(public, private, nonce, text)
print(ciphertext)
text_1 = decrypt(public, private, nonce, ciphertext)
print(text_1)
使用
調用encrypt()
加密
調用decrypt()
解密