Published Date : 2022年1月3日11:15
ニコニコ動画にアップした動画のまとめ記事です。
This is a summary blog post about a video I uploaded to NicoNico.
細かい部分は動画を参考にしてください。
Please refer to the video for details.
目次
Table of Contents
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.