简体   繁体   English

在python中解码base64 guid

[英]decoding base64 guid in python

I am trying to convert a base64 string back to a GUID style hex number in python and having issues.我正在尝试在 python 中将 base64 字符串转换回 GUID 样式的十六进制数并且遇到问题。

Base64 encoded string is: bNVDIrkNbEySjZ90ypCLew== Base64 编码的字符串是: bNVDIrkNbEySjZ90ypCLew==

And I need to get it back to: 2243d56c-0db9-4c6c-928d-9f74ca908b7b我需要把它恢复到: 2243d56c-0db9-4c6c-928d-9f74ca908b7b

I can do it with the following PHP code but can't work out how to to it in Python我可以使用以下 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))
    ));
  }

Here is the GUIDtoBase64 version:这是 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);
  }

Here are some of the results using some of the obvious and not so obvious options:以下是使用一些明显和不那么明显的选项的一些结果:

import base64
import binascii
>>> base64.b64decode("bNVDIrkNbEySjZ90ypCLew==")
'l\xd5C"\xb9\rlL\x92\x8d\x9ft\xca\x90\x8b{'
>>> binascii.hexlify(base64.b64decode("bNVDIrkNbEySjZ90ypCLew=="))
'6cd54322b90d6c4c928d9f74ca908b7b'

Python port of the existing function ( bitstring required)现有函数的 Python 端口(需要位

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"

First off, the b64 string and the resultant GUID doesn't match if we decode properly.首先,如果我们正确解码,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

The base64 encoded version of the resultant GUID you posted is wrong.您发布的结果 GUID 的 base64 编码版本是错误的。 I'm not sure I understand the way you're encoding the GUID in the first place.我不确定我是否理解您首先对 GUID 进行编码的方式。

Python has in its arsenal all the tools required for you to be able to answer this problem. Python 拥有您能够回答这个问题所需的所有工具。 However, here's the rough scratching I did in a python terminal:但是,这是我在 python 终端中进行的粗略处理:

import uuid
import base64

base64_guid = "bNVDIrkNbEySjZ90ypCLew=="
bin_guid = base64.b64decode(base64_guid)
guid = uuid.UUID(bytes=bin_guid)
print guid

This code should give you enough of a hint to build your own functions.这段代码应该给你足够的提示来构建你自己的函数。 Don't forget, the python shell gives you a powerful tool to test and play with code and ideas.不要忘记,python shell 为您提供了一个强大的工具来测试和玩弄代码和想法。 I would investigate using something like IPython notebooks.我会使用IPython notebooks 之类的东西进行调查。

I needed to do this to decode a BASE64 UUID that had been dumped from Mongodb.我需要这样做来解码从 Mongodb 转储的 BASE64 UUID。 Originally the field had been created by Mongoose.最初该领域是由猫鼬创建的。 The code I used, based on the code by @tpatja is here:我使用的代码基于@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:]])

Based on good answers above, I wrote a version that does not require the bitstring package and includes validations and support for more input options.基于上面的好答案,我编写了一个不需要 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')

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM