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

kev*_*vin 21 python base64 facebook 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
Run Code Online (Sandbox Code Playgroud)

小智 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
Run Code Online (Sandbox Code Playgroud)


dae*_*len 25

尝试

s = 'iEPX-SQWIR3p67lj_0zigSWTKHg'
base64.urlsafe_b64decode(s + '=' * (4 - len(s) % 4))
Run Code Online (Sandbox Code Playgroud)

正如它写在这里

  • 链接已损坏。 (4认同)
  • 确保你使用的字符串是str的实例 - unicode会因为错误而失败.如果是这种情况,请使用`str(s)`函数进行转换. (3认同)

Gee*_*ert 19

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

  • RFC 3548和RFC 4648都声明"......实现必须在编码数据末尾包含适当的填充字符,除非引用本文档的规范另有明确说明." 这可能就是为什么Python的base64不接受未正确填充的字符串. (7认同)
  • 在所有变体中似乎并不总是需要`=`padding:http://en.wikipedia.org/wiki/Base64 (4认同)
  • 吉尔特,谢谢你。但这正是我从 facebook 得到的代码,它最后没有 =。这是预期的吗? (2认同)
  • 我不会这么说.但是,您可以通过检查base64输入的长度来验证base64输入的长度:长度必须始终是4个字节的倍数(这实际上是解码器抛出错误的原因).如果不是,您可以添加等号,直到它然后字符串将被正确解码. (2认同)
  • **警告** 这个答案是错误的;它忘记了替换 + 和 / 字符的 - 和 _ 字符。 (2认同)
  • @DmitryYudin 这是一种骇人听闻的代码破解方式;base 64 使用不填充(如果字节数可被 3 整除)、双 `==`(对于 # 个字节可被 3 + 1 整除)或单个 `=`(如果字节可被 3 + 2 整除) . 请注意,这里讨论的是基数 64,而不是基数 32。 (2认同)

小智 6

令人惊讶的是,但目前接受的答案并不完全正确。就像其他一些答案所述,它是一种称为 base64url 编码的东西,它是RFC7515的一部分。

基本上,他们分别用“-”和“_”替换了“+”和“/”字符;另外还删除了所有尾随的“=”字符,因为只需查看编码的字符串长度,您始终可以知道丢失了多少个字符。

以下是来自 RFC7515 的 C# 说明性示例:

 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
 }
Run Code Online (Sandbox Code Playgroud)


png*_*png 5

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

s = 'iEPX-SQWIR3p67lj_0zigSWTKHg'
base64.urlsafe_b64decode(s + '===')
Run Code Online (Sandbox Code Playgroud)

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