从十六进制转换为base64

时间:2019-07-03 19:29:03

标签: python python-3.x cryptography base64

我受命接受一个十六进制文本并将其转换为base64系统。我的问题是我的代码输出不正确。

给出的输入:

  

49276d206b696c6c696e6720796f757220627261696e206c696b65206120706f69736f6e6f7573206d757368726f6f6d

预期输出:

  

SSdtIGtpbGxpbmcgeW91ciBicmFpbiBsaWtlIGEgcG9pc29ub3VzIG11c2hyb29t

我的程序的输出:

  

kk7aga2lY2NL5nIHLe6uiBicMLS3IGxp1spAhIHBe0ub9ub3rmQNXVzaOTe3

我希望我的代码如何工作:

注意: 我了解Python建立了将某些东西转换为base64的方法,以及使用int()将任何基数转换为十进制的方法,我选择使用自己的方法作为更多了解问题的方式。

  1. 采用十六进制文本字符串并将其转换为十进制数字。
  2. 将十进制数字转换为二进制数字。
  3. 将二进制数分成24位的块。
  4. 将24位块分成4部分,每部分6位。
  5. 将每6位转换为十进制数字。
  6. 将十进制数字转换为以base64编码的字母/数字。从“ A”(索引为0)到“ /”(索引为63)

我的代码:

def convertToDecimal(text, original_base):
    '''
    Program assumes user is using it correctly. It does not bother checking for weird cases like a base being 0 or a negative.
    '''

    decimal = 0  # used for converting to decimal base first
    exp = len(text) - 1  # starting exponent of the base (8^1, 8^0, etc)

    hex_nums = {"a": 10, "b": 11, "c": 12, "d": 13, "e": 14, "f": 15}

    # convert original_base to a decimal number
    for val in text:
        if val in hex_nums:  # have to worry about letters
            val = hex_nums[val]
        decimal += int(val) * (original_base ** exp)
        exp -= 1

    return decimal


def base64(text, base):
    letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"

    bin_num = bin(convertToDecimal(text, base))[2:]

    base64_val = ""

    # used for indexing each chunk of binary values
    i = 0
    j = 25

    # used for each chunk of six bits to be converted into a number
    six_bit_chunk = ""

    while True:
        if j > len(bin_num):
            # prevents index out of bounds error
            break

        bin_chunk = bin_num[i:j]  # take a chunk of 24 bits
        for x in range(0, 24, 6):
            six_bit_chunk += bin_chunk[x:x + 6]  # take a smaller chunk of 6 bits
            index = convertToDecimal(six_bit_chunk, 2)  # use the 6 bits to create a decimal value from 0-63
            base64_val += letters[index]
            six_bit_chunk = ""

        i += 25
        j += 25

    return base64_val


new_text = base64("49276d206b696c6c696e6720796f757220627261696e206c696b65206120706f69736f6e6f7573206d757368726f6f6d",
                  16)

print(new_text)

我为解决此问题所做的尝试是查看六位的块产生了什么,它们正在base64中创建正确的十进制数字和正确的字母/数字。

2 个答案:

答案 0 :(得分:1)

我不确定这是否正确,但是通过一些更改,我实现了该函数的输出与您提供的预期输出相匹配。

更改(还考虑了@JamesKPolt用户的评论):

  • 您有25岁的任何地方都改用24岁
  • bin_num的开头添加零填充以将长度补全为24的倍数

修改后的代码:

def base64(text, base):
    letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"

    bin_num = bin(convertToDecimal(text, base))[2:]

    # pad with zeros to the left to get multiple of 24
    remainder = divmod(len(bin_num), 24)[1]
    if remainder > 0:
        additional_zeros = 24 - remainder
        bin_num = ('0' * additional_zeros) + bin_num

    base64_val = ""

    # used for indexing each chunk of binary values
    i = 0
    j = 24

    # used for each chunk of six bits to be converted into a number
    six_bit_chunk = ""

    while True:
        if j > len(bin_num):
            # prevents index out of bounds error
            break

        bin_chunk = bin_num[i:j]  # take a chunk of 24 bits
        for x in range(0, 24, 6):
            six_bit_chunk += bin_chunk[x:x + 6]  # take a smaller chunk of 6 bits
            index = convertToDecimal(six_bit_chunk, 2)  # use the 6 bits to create a decimal value from 0-63
            base64_val += letters[index]
            six_bit_chunk = ""

        i += 24
        j += 24

    return base64_val

此修改后的功能通过了以下所有测试用例:

sample_data = [
    (
        '49276d206b696c6c696e6720796f757220627261696e206c696b65206120706f69736f6e6f7573206d757368726f6f6d',
        'SSdtIGtpbGxpbmcgeW91ciBicmFpbiBsaWtlIGEgcG9pc29ub3VzIG11c2hyb29t',
    ),
    (
        '24e1f218372064987d5457b639819715bddb51558cc4acb3ce6eeacd7afa2751bac0a5c7c3c636f24babff4ad68473db',
        'JOHyGDcgZJh9VFe2OYGXFb3bUVWMxKyzzm7qzXr6J1G6wKXHw8Y28kur/0rWhHPb',
    ),
    (
        '79d6e3a9d5bfba9902274e1b1c2d956fa92d16ba9a972825eb0b32aecd2401653624f900fe79b4550c24aae136ae7260',
        'edbjqdW/upkCJ04bHC2Vb6ktFrqalygl6wsyrs0kAWU2JPkA/nm0VQwkquE2rnJg',
    ),
    (
        'd251b89c473d6336dfeb3714d92c6b2080c863624ca2746e1380bd0642893ba64ebdae23bb7ad9a1f3ad9efbdc2f18e6',
        '0lG4nEc9Yzbf6zcU2SxrIIDIY2JMonRuE4C9BkKJO6ZOva4ju3rZofOtnvvcLxjm',
    ),
    (
        '5c2b578064178ad329f37041b063ec05c3ce8f202bb44e9a1260c6ded11ddd91d25ac83bba31bac7987e2da3a188c23d',
        'XCtXgGQXitMp83BBsGPsBcPOjyArtE6aEmDG3tEd3ZHSWsg7ujG6x5h+LaOhiMI9',
    ),
    (
        '018b79f5c3c1a4f59d12cda25c5ca2a29c4c1fdd1cfdf3f0a4faf350fe384d21bcfd83a8350b49231cf8536595f2a43a',
        'AYt59cPBpPWdEs2iXFyiopxMH90c/fPwpPrzUP44TSG8/YOoNQtJIxz4U2WV8qQ6',
    ),
    (
        'a617cfbe469cecd19f5ac75303a3049319ffb03d9a757c690d7c09d94dbabd6dce2314e1f409e6285fc0a0220eb803fe',
        'phfPvkac7NGfWsdTA6MEkxn/sD2adXxpDXwJ2U26vW3OIxTh9AnmKF/AoCIOuAP+',
    ),
    (
        '2bc40041dbe6937e1113b191fd136bcdd741169e9e81809e83ad3104d447d700ed9d1ab5cfbc113c0731b855fde98f87',
        'K8QAQdvmk34RE7GR/RNrzddBFp6egYCeg60xBNRH1wDtnRq1z7wRPAcxuFX96Y+H',
    ),
    (
        '1904435f5964861c5284b08e0ebf3d201da3ec795a3d9b0f7d5056c4369daed59d42cac72c897356a46305f7aac5fcb4',
        'GQRDX1lkhhxShLCODr89IB2j7HlaPZsPfVBWxDadrtWdQsrHLIlzVqRjBfeqxfy0',
    ),
]

for i, (input_str, expected_output) in enumerate(sample_data):
    print('i              ', i)
    print('input_str      ', input_str)
    print('expected_output', expected_output)

    function_output = base64(input_str, 16)
    print('function_output', function_output)
    assert expected_output == function_output

答案 1 :(得分:0)

难道您不能直接遍历以6为一组的二进制表示形式,而不是按24分组并再次分成4组吗?

但是在拆分为6组之前,仍必须用零填充24的倍数。

我的功能:

def base64_v2(text, base):
    base64_letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
    n1 = 24
    n2 = 6

    dec_num = int(text, base)
    bin_str = bin(dec_num)[2:]

    # pad with zeros to the left to get multiple of 'n1'
    remainder = divmod(len(bin_str), n1)[1]
    if remainder > 0:
        additional_zeros = n1 - remainder
        bin_str = ('0' * additional_zeros) + bin_str

    return ''.join(
        base64_letters[int(bin_str[i:i+n2], 2)]
        for i in range(0, len(bin_str), n2))

我的函数通过了以下所有测试用例:

sample_data = [
    (
        '49276d206b696c6c696e6720796f757220627261696e206c696b65206120706f69736f6e6f7573206d757368726f6f6d',
        'SSdtIGtpbGxpbmcgeW91ciBicmFpbiBsaWtlIGEgcG9pc29ub3VzIG11c2hyb29t',
    ),
    (
        '24e1f218372064987d5457b639819715bddb51558cc4acb3ce6eeacd7afa2751bac0a5c7c3c636f24babff4ad68473db',
        'JOHyGDcgZJh9VFe2OYGXFb3bUVWMxKyzzm7qzXr6J1G6wKXHw8Y28kur/0rWhHPb',
    ),
    (
        '79d6e3a9d5bfba9902274e1b1c2d956fa92d16ba9a972825eb0b32aecd2401653624f900fe79b4550c24aae136ae7260',
        'edbjqdW/upkCJ04bHC2Vb6ktFrqalygl6wsyrs0kAWU2JPkA/nm0VQwkquE2rnJg',
    ),
    (
        'd251b89c473d6336dfeb3714d92c6b2080c863624ca2746e1380bd0642893ba64ebdae23bb7ad9a1f3ad9efbdc2f18e6',
        '0lG4nEc9Yzbf6zcU2SxrIIDIY2JMonRuE4C9BkKJO6ZOva4ju3rZofOtnvvcLxjm',
    ),
    (
        '5c2b578064178ad329f37041b063ec05c3ce8f202bb44e9a1260c6ded11ddd91d25ac83bba31bac7987e2da3a188c23d',
        'XCtXgGQXitMp83BBsGPsBcPOjyArtE6aEmDG3tEd3ZHSWsg7ujG6x5h+LaOhiMI9',
    ),
    (
        '018b79f5c3c1a4f59d12cda25c5ca2a29c4c1fdd1cfdf3f0a4faf350fe384d21bcfd83a8350b49231cf8536595f2a43a',
        'AYt59cPBpPWdEs2iXFyiopxMH90c/fPwpPrzUP44TSG8/YOoNQtJIxz4U2WV8qQ6',
    ),
    (
        'a617cfbe469cecd19f5ac75303a3049319ffb03d9a757c690d7c09d94dbabd6dce2314e1f409e6285fc0a0220eb803fe',
        'phfPvkac7NGfWsdTA6MEkxn/sD2adXxpDXwJ2U26vW3OIxTh9AnmKF/AoCIOuAP+',
    ),
    (
        '2bc40041dbe6937e1113b191fd136bcdd741169e9e81809e83ad3104d447d700ed9d1ab5cfbc113c0731b855fde98f87',
        'K8QAQdvmk34RE7GR/RNrzddBFp6egYCeg60xBNRH1wDtnRq1z7wRPAcxuFX96Y+H',
    ),
    (
        '1904435f5964861c5284b08e0ebf3d201da3ec795a3d9b0f7d5056c4369daed59d42cac72c897356a46305f7aac5fcb4',
        'GQRDX1lkhhxShLCODr89IB2j7HlaPZsPfVBWxDadrtWdQsrHLIlzVqRjBfeqxfy0',
    ),
]

for i, (input_str, expected_output) in enumerate(sample_data):
    print('i              ', i)
    print('input_str      ', input_str)
    print('expected_output', expected_output)

    function_output = base64_v2(input_str, 16)
    print('function_output', function_output)
    assert expected_output == function_output