在Python中解码Base64 GUID
我正在尝试把一个base64编码的字符串转换回GUID格式的十六进制数字,使用的是Python,但遇到了一些问题。
这个base64编码的字符串是:bNVDIrkNbEySjZ90ypCLew==
我需要把它转换回:2243d56c-0db9-4c6c-928d-9f74ca908b7b
我可以用下面的PHP代码做到这一点,但我不知道在Python中怎么实现。
function Base64ToGUID($guid_b64) {
$guid_bin = base64_decode($guid_b64);
return join('-', array(
bin2hex(strrev(substr($guid_bin, 0, 4))),
bin2hex(strrev(substr($guid_bin, 4, 2))),
bin2hex(strrev(substr($guid_bin, 6, 2))),
bin2hex(substr($guid_bin, 8, 2)),
bin2hex(substr($guid_bin, 10, 6))
));
}
这里是GUID转base64的版本:
function GUIDToBase64($guid) {
$guid_b64 = '';
$guid_parts = explode('-', $guid);
foreach ($guid_parts as $k => $part) {
if ($k < 3)
$part = join('', array_reverse(str_split($part, 2)));
$guid_b64 .= pack('H*', $part);
}
return base64_encode($guid_b64);
}
这里是使用一些明显和不太明显的选项得到的结果:
import base64
import binascii
>>> base64.b64decode("bNVDIrkNbEySjZ90ypCLew==")
'l\xd5C"\xb9\rlL\x92\x8d\x9ft\xca\x90\x8b{'
>>> binascii.hexlify(base64.b64decode("bNVDIrkNbEySjZ90ypCLew=="))
'6cd54322b90d6c4c928d9f74ca908b7b'
5 个回答
0
看起来微软的GUID是以小端字节顺序存储的time_low、time_mid和time_hi_version。这就是为什么在Python3中你应该使用bytes_le的原因:
import base64, uuid
uuid.UUID(bytes_le=base64.decodebytes('bNVDIrkNbEySjZ90ypCLew=='.encode('ascii')))
0
根据上面好的回答,我写了一个版本,这个版本不需要使用bitstring这个包,并且增加了验证功能,还支持更多的输入选项。
import base64
import regex
import uuid
from typing import Optional
def to_uuid(obj) -> Optional[uuid.UUID]:
if obj is None:
return None
elif isinstance(obj, uuid.UUID):
return obj
elif isinstance(obj, str):
if regex.match(r'[0-9a-fA-F]{8}[-]{0,1}[0-9a-fA-F]{4}[-]{0,1}[0-9a-fA-F]{4}[-]{0,1}[0-9a-fA-F]{4}[-]{0,1}[0-9a-fA-F]{12}', obj):
return uuid.UUID(hex=obj)
elif regex.match(r'[0-9a-zA-Z\+\/]{22}[\=]{2}', obj):
b64_str = base64.b64decode(obj).hex()
uid_str = '-'.join([b64_str[:8], b64_str[8:][:4], b64_str[12:][:4], b64_str[16:][:4], b64_str[20:]])
return uuid.UUID(hex=uid_str)
raise ValueError(f'{obj} is not a valid uuid/guid')
else:
raise ValueError(f'{obj} is not a valid uuid/guid')
1
我需要做这个来解码一个从Mongodb导出的BASE64格式的UUID。最开始这个字段是由Mongoose创建的。我使用的代码是基于@tpatja的代码,下面是我的代码:
def base64ToGUID(b64str):
try:
bytes=base64.urlsafe_b64decode(b64str)
except Exception as e:
print("Can't decode base64 ", e)
s = bitstring.BitArray(bytes).hex
return "-".join([s[:8],s[8:][:4],s[12:][:4],s[16:][:4],s[20:]])
1
首先,如果我们正确解码,b64字符串和生成的GUID是不匹配的。
>>> import uuid
>>> import base64
>>> u = uuid.UUID("2243d56c-0db9-4c6c-928d-9f74ca908b7b")
>>> u
UUID('2243d56c-0db9-4c6c-928d-9f74ca908b7b')
>>> u.bytes
'"C\xd5l\r\xb9Ll\x92\x8d\x9ft\xca\x90\x8b{'
>>> base64.b64encode(u.bytes)
'IkPVbA25TGySjZ90ypCLew=='
>>> b = base64.b64decode('bNVDIrkNbEySjZ90ypCLew==')
>>> u2 = uuid.UUID(bytes=b)
>>> print u2
6cd54322-b90d-6c4c-928d-9f74ca908b7b
你发的这个结果GUID的base64编码版本是错误的。我不太明白你最开始是怎么编码这个GUID的。
Python有很多工具可以帮助你解决这个问题。不过,我在Python终端里做了一些简单的尝试:
import uuid
import base64
base64_guid = "bNVDIrkNbEySjZ90ypCLew=="
bin_guid = base64.b64decode(base64_guid)
guid = uuid.UUID(bytes=bin_guid)
print guid
这段代码应该能给你一些提示,帮助你自己写函数。别忘了,Python的命令行是一个很强大的工具,可以用来测试和玩弄代码和想法。我建议你试试像IPython这样的笔记本。
2
这是一个将现有功能用Python语言实现的版本(需要使用bitstring这个库)
import bitstring, base64
def base64ToGUID(b64str):
s = bitstring.BitArray(bytes=base64.b64decode(b64str)).hex
def rev2(s_):
def chunks(n):
for i in xrange(0, len(s_), n):
yield s_[i:i+n]
return "".join(list(chunks(2))[::-1])
return "-".join([rev2(s[:8]),rev2(s[8:][:4]),rev2(s[12:][:4]),s[16:][:4],s[20:]])
assert base64ToGUID("bNVDIrkNbEySjZ90ypCLew==") == "2243d56c-0db9-4c6c-928d-9f74ca908b7b"