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.


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.


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.


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.

[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')
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.

for c in 'こんにちは世界':
for c in 'こんにちは世界':
b_t = b''
for c in 'こんにちは世界':
    b_t += c.encode('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')

06:10 Part6へ続く。

06:10 Continued to Part 6.


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