1. 程式人生 > >記第一次接觸RSA加密----python

記第一次接觸RSA加密----python

記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