Published Date : 2022年1月3日11:15

030 Pythonでビットコインを学ぶ (BASE58の仕組みをPythonと図を使って理解してみよう パート5)
030 Use python to learn bitcoin (Understand how BASE 58 works in using Python and diagrams Part 5)


This blog has an English translation


ニコニコ動画にアップした動画のまとめ記事です。

This is a summary blog post about a video I uploaded to NicoNico.

細かい部分は動画を参考にしてください。

Please refer to the video for details.


目次

Table of Contents




① 動画の説明
① Video Description



00:00 BASE58の仕組みをPythonを使って理解してみよう。パート5

00:00 Understand how BASE 58 works in using Python. Part 5

00:05 ではデコード作業をおこないましょう。

00:05 Then, let's do the decoding work.

00:09 Pythonのスライス機能を使って、16進数表記の文字列を1バイトずつ取り出してみましょう。

00:09 Let's use the Python slicing feature to extract a string in hexadecimal notation byte by byte.

00:17 文字列の先頭の「0x」の部分を除くには、2番目の文字から表示させるようにします。

00:17 To exclude the [0x] at the beginning of the string, display begins with the second character in the string.

hex(int_value)[2:]

00:23 そして文字列の2番目から2ずつずらして表示させ、1バイトの2桁目を表示させます。

00:23 Then, the second digit of the byte is displayed by shifting the character string by 2 from the second position from the head of the character string.

hex(int_value)[2::2]

00:30 そして今度は文字列の3番目から2ずつずらして表示させ、1バイトの1桁目を表示させます。

00:30 Then, the first digit of the byte is displayed by shifting the character string by two from the third position from the beginning of the character string.

hex(int_value)[3::2]

00:42 それらをZIP関数とリスト内包表記で1バイトの文字列としてまとめます。

00:42 It then uses the ZIP function and list comprehension to combine them into a single-byte string.

list(zip(hex(int_value)[2::2], hex(int_value)[3::2]))
[(i + j) for (i, j) in zip(hex(int_value)[2::2], hex(int_value)[3::2])]

01:24 まとめられた文字列の先頭に16進数表記であることを表す「0x」を加えます。

01:24 Add [0x] to the beginning of the string to indicate it is in hexadecimal notation.

['0x' + (i + j) for (i, j) in zip(hex(int_value)[2::2], hex(int_value)[3::2])]

01:38 そしてintメソッドを利用して、一文字ずつ16進数表記から整数に直します。

01:38 The int method is then used to convert character by character from hexadecimal to an integer.

int('0x68', 16)

02:04 それらの整数をchrメソッドを使って、文字に直していきます。

02:04 Use the chr method to convert them to characters.

hex(ord('h'))
ord('h')
[int('0x' + (i + j), 16) for (i, j) in zip(hex(int_value)[2::2], hex(int_value)[3::2])]
chr(int('0x68', 16))

02:09 あとはjoinメソッドを使って、リストを結合させてエンコード前の文字列に直します。

02:09 The join method is then used to join the list and restore the string before encoding.

''.join([chr(int('0x' + (i + j), 16)) for (i, j) in zip(hex(int_value)[2::2], hex(int_value)[3::2])])

02:40 では日本語の文字列の場合どうなるかを試してみましょう。

02:40 Now, let's see what happens when you encode or decode Japanese strings.

plain_text = 'こんにちは世界'

02:53 エンコード作業は前回の時と同じように文字列をバイト列に変換します。

02:53 The encoding process converts strings into bytes as before.

b_text = b''
if isinstance(plain_text, str):
    b_text = plain_text.encode('utf-8')

03:19 そして、整数に直して、エンコード関数に引数として渡すだけです。

03:19 You simply convert it to an integer and pass it as an argument to the encoding function.

int_value = int.from_bytes(b_text, byteorder='big')
encode_base58(int_value)
base58_encoded_string = encode_base58(int_value)

04:21 ではデコード作業をしてみましょう。

04:21 Let's do the decoding work.

base58_decoded_int_value = decode_base58(base58_encoded_string)

04:24 今回の日本語はどうやら、一文字が1バイトではなく、3バイトになっているようです。

04:24 In Japanese this time, it seems that each character is not 1 byte but 3 bytes.

len(b_text)
len('こんにちは世界')
'こ'.encode('utf-8')
for c in 'こんにちは世界':
    print(c.encode('utf-8'))
for c in 'こんにちは世界':
    print(len(c.encode('utf-8')))
b_t = b''
for c in 'こんにちは世界':
    b_t += c.encode('utf-8')
print(b_t)
print(b_t.decode('utf-8'))

04:54 先ほどの時のようなめんどくさい作業でデコードされた整数を文字列に直さなくても、to_bytesメソッドを使えば整数からバイト列に変換できます。

04:54 Instead of converting an integer decoded with the hassle described above to a string, you can convert it to a string of bytes using the to_bytes method.

base58_decoded_int_value.to_bytes(len(b_text), byteorder='big')

05:50 あとはこのバイト列をutf8でデコードしてやれば、元の日本語の文字列に直すことができます。

05:50 The byte sequence can then be decoded with utf8 and converted back to the original Japanese string.

decoded_bytes = base58_decoded_int_value.to_bytes(len(b_text), byteorder='big')
print(decoded_bytes.decode('utf-8'))

06:10 Part6へ続く。

06:10 Continued to Part 6.



以上です。お疲れ様です。

That's all. Thank you for your hard work.