[英]How to decode base64 url in python?
对于 Facebook fbml 应用程序 Facebook 正在发送此处解释的签名请求参数:
http://developers.facebook.com/docs/authentication/canvas
他们给出了解码此签名请求的 php 版本:
如何在 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
显然,在复制原始的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.