在Python中解码Base64 GUID

1 投票
5 回答
4088 浏览
提问于 2025-04-18 05:39

我正在尝试把一个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_lowtime_midtime_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"

撰写回答