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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3302946/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-18 10:21:11  来源:igfitidea点击:

How to decode base64 url in python?

pythonfacebookbase64decode

提问by kevin

For Facebook fbml Apps Facebook is sending in a signed_request parameter explained here:

对于 Facebook fbml 应用,Facebook 正在发送这里解释的 signed_request 参数:

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

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

They have given the php version of decoding this signed request:

他们给出了解码这个签名请求的 php 版本:

http://pastie.org/1054154

http://pastie.org/1054154

How to do the same in python?

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

I tried base64 module but I am getting Incorrect padding error:

我尝试了 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

采纳答案by Geert

Apparently you missed the last two characters when copying the original base64-encoded string. Suffix the input string with two is-equal (=) signs and it will be decoded correctly.

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

回答by sunil

I have shared a code snippet for parsing signed_request parameter in a python based facebook canvas application at http://sunilarora.org/parsing-signedrequest-parameter-in-python-bas:

我在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

回答by FazalSap

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

回答by dae.eklen

try

尝试

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

as it is written here

正如这里所写

回答by png

Alternative to @dae.eklen's solution, you can append ===to it:

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

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

This works because Python only complains about missing padding, but not extra padding.

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

回答by Vladimir Menshakov

Surprising, but currently accepted answer is not exactly correct. Like some other answers stated, it's something called base64url encoding, and it's a part of RFC7515.

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

Basically, they replaced '+' and '/' chars by '-' and '_' respectively; and additionally removed any trailing '=' chars, because you can always tell how many chars you're missing, just by looking at the encoded string length.

基本上,他们分别用 '-' 和 '_' 替换了 '+' 和 '/' 字符;并另外删除了任何尾随的 '=' 字符,因为您总是可以通过查看编码的字符串长度来判断您丢失了多少个字符。

Here's illustrative example from RFC7515 in C#:

以下是 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
 }

回答by arunsudhir

This is the right solution. In python there is base64.b64encode but that only base64 encodes and its is different from base64 url encoding. Here is the right set to of steps to convert form base64encoded to base64urlencoded string:
1. From the resultant string, replace "/" with "_" and "+" with "-"
2. Strip the trailing "==".

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

Et voila! That will make it a valid string for base64 url decoding. Btw, that link in @dae.eklen 's answer above is broken now.

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

回答by Gabriel P.

If you are sending your base64string from .netas a param it seems that chars that have special meaning in the URI ie +or /are replaced with " "spaces.

如果您将base64字符串.net作为参数发送,则似乎在 URI 中具有特殊含义的字符 ie+或被空格/替换" "

So before you send your string in .net you should probably do something like this

所以在你在 .net 中发送你的字符串之前,你可能应该做这样的事情

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

Then in python decode the string (also add '=' until the length is divisible by 4)

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

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

Further if you want to use the image in openCV

此外,如果您想在 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)