記第一次接觸RSA加密----python
阿新 • • 發佈:2018-11-11
記python使用支付寶RSA生成祕鑰工具遇到的問題
報錯 AttributeError: ‘str’ object has no attribute ’
我在和第三方對接介面時,第三方要求使用支付寶rsa祕鑰工具來生成公鑰和私鑰(由於第一次接觸,都不太懂)我需要對我請求他時帶的引數需要進行簽名,和對他的簽名進行驗證,但是中間一直出現VerificationError: Verification failed 驗證錯誤,因為我使用的阿里的SDK進行的驗籤和加簽,所以懷疑是因為沒有使用對SDK使用正確,我問第三方他們有沒有使用阿里的SDK,他說只用祕鑰生成公鑰和私鑰沒有使用, 於是我用python rsa模組進行加簽和驗籤,在加簽時出現了這個錯誤
後來經過一系列搜尋,因為阿里生成的是是單純的str需要轉換成公鑰物件和私鑰物件, 舉個栗子:
In [4]: pubkey
Out[4]: PublicKey(11690135687533933382360195974198542320855561302916716673520411392050566078072206589551125140476896542230602422113630896040254008411359287782630915870990731, 65537)
In [5]: privkey
Out[5]: PrivateKey(11690135687533933382360195974198542320855561302916716673520411392050566078072206589551125140476896542230602422113630896040254008411359287782630915870990731 , 65537, 1942320940866335056540887955857728112849172330553124614461506624472261683428563987435789823643183600581268208466749887437038591129786226046998711491544681, 7096194277812885680822727267687878129579066157151458337565184598926324047667321479, 1647381008730914280393162847196573429038377988150536898752334551643712989 )
然後我就檢視SDK原始碼因為原始碼是可以生成簽名
def sign_with_rsa2(private_key, sign_content, charset):
if PYTHON_VERSION_3: # 判斷是否是python3,我是python2這個不用管
sign_content = sign_content.encode(charset)
private_key = fill_private_key_marker(private_key) # 對私鑰進行標記,沒有標記在下方format='PEM'會報錯
signature = rsa.sign(sign_content,
priv_key=rsa.PrivateKey.load_pkcs1(private_key, format='PEM'),
hash='SHA-256') # 對內容加簽
sign = base64.b64encode(signature) # 對簽名進行編碼
if PYTHON_VERSION_3:
sign = str(sign, encoding=charset)
return sign
所以需要像sdk一樣將對私鑰進行標記
但是…驗籤的時候還是會報錯驗籤錯誤
於是
def verify_with_rsa(public_key, message, sign):
public_key = fill_public_key_marker(public_key) # 對公鑰進行標記
sign = base64.b64decode(sign) # 對簽名進行64位解碼
return rsa.verify(message, sign,
rsa.PublicKey.load_pkcs1_openssl_pem(public_key)) # 進行驗證
於是我呼叫這個方法但是發現依然驗證錯誤,將這程式碼單獨取出來卻可以了,但是本地測試沒有,獲取請求資料再驗證又回出現驗證錯誤, 我列印了兩次資料的區別由於python2的編碼預設unicode,所以一個本地測試時資料編碼是utf-8,但是獲取到的是unicode
但是資料都在字典中, 例
d = {u'aa': u'aa', u'bb', u'bb'}
需要將字典內的資料轉換為
d = {'aa': 'aa', 'bb': 'bb'}
所以:
import json
d = {u'aa': u'aa', u'bb', u'bb'}
d = eval(json.dumps(d).encode('utf-8'))
>>> d
>{'aa': 'aa', 'bb': 'bb'}
最後
>>> rsa.verify(sign_content, sign, rsa.PublicKey.load_pkcs1_openssl_pem(public_key))
> True