簡體   English   中英

如何在 python 中解碼 base64 url?

[英]How to decode base64 url in python?

對於 Facebook fbml 應用程序 Facebook 正在發送此處解釋的簽名請求參數:

http://developers.facebook.com/docs/authentication/canvas

他們給出了解碼此簽名請求的 php 版本:

http://pastie.org/1054154

如何在 python 中做同樣的事情?

我嘗試了 base64 模塊,但我收到了不正確的填充錯誤:

>>> base64.urlsafe_b64decode("eyJhbGdvcml0aG0iOiJITUFDLVNIQTI1NiIsImV4cGlyZXMiOjEyNzk3NDYwMDAsIm9hdXRoX3Rva2VuIjoiMjk1NjY2Njk1MDY0fDIuRXpwem5IRVhZWkJVZmhGQ2l4ZzYzUV9fLjM2MDAuMTI3OTc0NjAwMC0xMDAwMDA0ODMyNzI5MjN8LXJ6U1pnRVBJTktaYnJnX1VNUUNhRzlNdEY4LiIsInVzZXJfaWQiOiIxMDAwMDA0ODMyNzI5MjMifQ")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/base64.py", line 112, in urlsafe_b64decode
    return b64decode(s, '-_')
  File "/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/base64.py", line 76, in b64decode
    raise TypeError(msg)
TypeError: Incorrect padding

我在http://sunilarora.org/parsing-signedrequest-parameter-in-python-bas中共享了一個基於Python的Facebook canvas應用程序中的signed_request參數解析代碼段:

import base64
import hashlib
import hmac
import simplejson as json

def base64_url_decode(inp):
    padding_factor = (4 - len(inp) % 4) % 4
    inp += "="*padding_factor 
    return base64.b64decode(unicode(inp).translate(dict(zip(map(ord, u'-_'), u'+/'))))

def parse_signed_request(signed_request, secret):

    l = signed_request.split('.', 2)
    encoded_sig = l[0]
    payload = l[1]

    sig = base64_url_decode(encoded_sig)
    data = json.loads(base64_url_decode(payload))

    if data.get('algorithm').upper() != 'HMAC-SHA256':
        log.error('Unknown algorithm')
        return None
    else:
        expected_sig = hmac.new(secret, msg=payload, digestmod=hashlib.sha256).digest()

    if sig != expected_sig:
        return None
    else:
        log.debug('valid signed request received..')
return data

嘗試

s = 'iEPX-SQWIR3p67lj_0zigSWTKHg'
base64.urlsafe_b64decode(s + '=' * (4 - len(s) % 4))

正如寫在這里

顯然,在復制原始的base64編碼的字符串時,您錯過了最后兩個字符。 給輸入字符串加上兩個等號(=)后綴,它將被正確解碼。

替代@ dae.eklen解決方案,您可以在其后附加===

s = 'iEPX-SQWIR3p67lj_0zigSWTKHg'
base64.urlsafe_b64decode(s + '===')

之所以有效,是因為Python僅抱怨缺少填充,而沒有抱怨多余的填充。

令人驚訝,但目前接受的答案並不完全正確。 像其他一些答案一樣,它稱為base64url編碼,它是RFC7515的一部分。

基本上,它們分別用'-'和'_'替換'+'和'/'字符; 並另外刪除了所有結尾的'='字符,因為您始終可以通過查看編碼的字符串長度來知道缺少了多少個字符。

這是C#中RFC7515的說明性示例:

 static string base64urlencode(byte [] arg)
 {
   string s = Convert.ToBase64String(arg); // Regular base64 encoder
   s = s.Split('=')[0]; // Remove any trailing '='s
   s = s.Replace('+', '-'); // 62nd char of encoding
   s = s.Replace('/', '_'); // 63rd char of encoding
   return s;
 }

 static byte [] base64urldecode(string arg)
 {
   string s = arg;
   s = s.Replace('-', '+'); // 62nd char of encoding
   s = s.Replace('_', '/'); // 63rd char of encoding
   switch (s.Length % 4) // Pad with trailing '='s
   {
     case 0: break; // No pad chars in this case
     case 2: s += "=="; break; // Two pad chars
     case 3: s += "="; break; // One pad char
     default: throw new System.Exception(
       "Illegal base64url string!");
   }
   return Convert.FromBase64String(s); // Standard base64 decoder
 }
import base64
import simplejson as json

def parse_signed_request( signed_request ):
    encoded_sig, payload = signed_request.split('.',2)
    data = json.loads(base64.b64decode( payload.replace('-_', '+/') ))
    return data

這是正確的解決方案。 在python中,有base64.b64encode,但只有base64編碼,它與base64 url​​編碼不同。 這是將base64encoded格式轉換為base64urlencoded字符串的步驟的正確設置:
1.從結果字符串中,將“ /”替換為“ _”,將“ +”替換為“-”
2.刪除尾隨的“ ==”。

瞧! 這將使其成為base64 url​​解碼的有效字符串。 順便說一句,@ dae.eklen在上面的答案中的鏈接現在已斷開。

如果您是從.net作為參數發送base64字符串,則似乎在URI中具有特殊含義的字符+/被替換為" "

因此,在將字符串發送到.net之前,您可能應該執行以下操作

base64img.Replace("+", "-").Replace("/", "_"))

然后在python中解碼字符串(還添加'='直到長度被4整除)

def decode_base64(data):
    data += '=' * (len(data) % 4)
    return base64.urlsafe_b64decode(data)

此外,如果要在openCV中使用圖像

def get_cv2_img_from_base64(base_64_string):
    data = decode_base64(base_64_string)
    np_data = np.frombuffer(data, dtype=np.uint8)
    return cv2.imdecode(np_data, cv2.IMREAD_UNCHANGED)

我的解決方案是將舊的 c# 代碼轉換為 python。

import base64

def base64_encode_url(value):
    encoded = str(base64.b64encode(bytes(value, "utf-8")), 'utf-8')
    return encoded.replace('=', '').replace('+', '-').replace('/', '_')

def base64_decode_url(data):
    value = data.replace('-', '+').replace('_', '/')
    value += '=' * (len(value) % 4)
    return str(base64.urlsafe_b64decode(value), 'utf-8')

只是

base64.urlsafe_b64decode(s)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM