在python中解码base64 guid

时间:2014-05-07 10:26:57

标签: python base64

我正在尝试将base64字符串转换回python中的GUID样式十六进制数并出现问题。

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))
    ));
  }

这是GUIDtoBase64版本:

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'

4 个答案:

答案 0 :(得分: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 shell为您提供了一个强大的工具来测试和使用代码和想法。我会调查使用类似IPython笔记本的内容。

答案 1 :(得分:1)

现有函数的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"

答案 2 :(得分:0)

我需要执行此操作以解码从Mongodb转储的BASE64 UUID。最初,该字段是由猫鼬创建的。我使用的基于@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:]])

答案 3 :(得分: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')