如何在python中解码base64 url​​?

时间:2010-07-21 19:18:35

标签: python facebook base64 decode

对于Facebook fbml应用程序Facebook发送的signed_request参数在此解释:

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

9 个答案:

答案 0 :(得分:25)

我已经共享了一个代码片段,用于在http://sunilarora.org/parsing-signedrequest-parameter-in-python-bas的基于python的Facebook画布应用程序中解析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

答案 1 :(得分:23)

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

正如它写的here

答案 2 :(得分:19)

显然,在复制原始base64编码的字符串时,您错过了最后两个字符。输入字符串后缀为两个等于(=)符号,它将被正确解码。

答案 3 :(得分:5)

@ dae.eklen解决方案的替代方案,您可以将===附加到其中:

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

这是有效的,因为Python只会抱怨缺少填充,而不是额外的填充。

答案 4 :(得分:1)

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

答案 5 :(得分:1)

令人惊讶,但目前接受的答案并不完全正确。 像其他一些答案一样,它叫做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
 }

答案 6 :(得分:0)

这是正确的解决方案。在python中,有base64.b64encode,但只有base64编码,它与base64 url​​编码不同。这是将base64encoded格式转换为base64urlencoded字符串的步骤的正确设置:
1.从结果字符串中,将“ /”替换为“ _”,将“ +”替换为“-”
2.删除尾随的“ ==”。

瞧!这将使其成为base64 url​​解码的有效字符串。顺便说一句,@ dae.eklen在上面的答案中的链接现在已断开。

答案 7 :(得分:0)

如果您将base64的{​​{1}}字符串作为参数发送,则似乎URI中具有特殊含义的字符,即.net+被{ {1}}空格。

因此,在.net中发送字符串之前,您可能应该做类似的事情

/

然后在python中解码字符串(还添加'='直到长度被4整除)

" "

如果要在openCV中使用图片

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

答案 8 :(得分:-1)

只是

base64.urlsafe_b64decode(s)