Python實(shí)現(xiàn)RSA無填充加密,兼容BouncyCastle
場景
某系統(tǒng)登錄時密碼經(jīng)過前臺rsa加密傳給后端,為實(shí)現(xiàn)模擬登錄需要原樣生成加密串。
分析
前臺通過RSA.js、BigInt.js、Barrett.js三個js文件實(shí)現(xiàn)加密,公鑰通過ajax請求獲得empoent、module。

rsa算法其實(shí)就是通過這兩個參數(shù)計(jì)算實(shí)現(xiàn)公鑰加密,所以正常情況下使用常規(guī)加密庫即可達(dá)到目的。
但實(shí)際測試發(fā)現(xiàn)使用cryptography、pycryptodem等庫加密結(jié)果與js輸出不一致且每次都不同。其實(shí)常規(guī)庫會按一定規(guī)則對原文隨機(jī)填充后再加密,這樣可保證相當(dāng)?shù)陌踩浴?/p>
于是考慮如何用python實(shí)現(xiàn)無填充的加密。
代碼
經(jīng)過搜索發(fā)現(xiàn)了相當(dāng)簡單(不安全)的實(shí)現(xiàn)方式,代碼如下:
if __name__ == '__main__': # 實(shí)為16進(jìn)制串,前補(bǔ)0 e = '010001' # m也需要補(bǔ)00 m = '008eb933413be3234dddd2730fbb1d05c8848a43d5dc3bdd997f2a9935fba6beb9ffb36854482b0b46cf7e6f9afbbe2e2e7d606fde20bec57dbf722e7985192e8813e6b67628a6f202cf655b7d2ffce4e9dc682dd6034ae706c8e255f25e4051b9ca43f25b3ad686aac9c8f6aeb71d921c13a255c806f78a5a7b9a356c2dd274e3' m = int.from_bytes(bytearray.fromhex(m), byteorder='big') e = int.from_bytes(bytearray.fromhex(e), byteorder='big') # js加密為反向,為保持一致原文應(yīng)反向處理,所以這里原文實(shí)際為204dowls plaintext = 'slwod402'.encode('utf-8') # 無填充加密邏輯 input_nr = int.from_bytes(plaintext, byteorder='big') crypted_nr = pow(input_nr, e, m) keylength = math.ceil(m.bit_length() / 8) crypted_data = crypted_nr.to_bytes(keylength, byteorder='big') print(crypted_data.hex()) # 72ff82c8f227ba9cf429635b89291b2d7ef54bcf8635af432b9917bd3593d8d8aa0c186764cef86c8530d349db6132521a9c70af939a0242bb3d01ce7094cf91f3a058742fc680d70b17c4441ebf60fd4f92bce660e4785fe56d85ac7f7023f4ccf702c247f37b36a255dc04d9ce14745f422c6113290ff9b479494fd805557e
另附上從empoent、module生成公鑰方法,需要的朋友可以參考:
from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives import serialization, hashes from cryptography.hazmat.primitives.asymmetric import rsa, padding if __name__ == "__main__": m = int.from_bytes(bytearray.fromhex(m), byteorder='big') e = int.from_bytes(bytearray.fromhex(e), byteorder='big') key = rsa.RSAPublicNumbers(e, m).public_key(default_backend()) pem = key.public_bytes( encoding=serialization.Encoding.PEM, format=serialization.PublicFormat.SubjectPublicKeyInfo ) with open('key.pem', 'w+') as f: f.writelines(pem.decode())
參考
Java-web中利用RSA進(jìn)行加密解密操作的方法示例
Java 進(jìn)行 RSA 加解密時不得不考慮到的那些事兒
https://github.com/pyca/cryptography/issues/2735
浙公網(wǎng)安備 33010602011771號