Python学習【365日チャレンジ!】235日目のマスターU(@Udemy11)です。
そこかしこで酷評されているマイナポイントですが、すでに最大5,000円の還元を受け取りました。
PayPayにするか、楽天カードにするか、メルペイにするか検討した結果、抽選で1,000万円が1名に当選する可能性があり、メルカリでの購入でさらに1,000円分のポイントバックがあるメルペイを選びました。
あと、よく使う釣具屋でメルペイが使えるということも、メルペイを選んだ決め手の一つです。
9月1日から還元が始まったのですが、PayPayが1ヶ月後のポイント還元に対して、メルペイは、使った次の日にポイントで還元されました。
すぐに還元されたポイントが商品の購入に使える上、使った還元ポイントがマイナポイント還元の対象となっています。
たとえば、最初の買い物で、10,000円使って2,500ポイントが還元されて、次の買い物で、7,500円と2,500ポイントで10,000円の買い物をすれば、2,500ポイントが還元されるということです。
普通に考えると、20,000円で5,000ポイントが還元されるので、20,000円で25,000円分使えます。
上記の例の場合は、17,500円使って22,500円分使えるということになります。
どちらも5,000ポイントが還元されるということに違いはないんですけどね。
それでは、今日もPython学習をはじめましょう。
昨日の復習
昨日は、バイト列、バイナリ列、Base64について学習しました。
バイト列とバイナリ列は、意味のない任意のビットパターンからなるデータの集合列のことで、バイトを単位で考えるか、ビットを単位で考えるかでどちらかの配列に分類されました。
Base64は、64種類の英数字のみを使った通信環境でマルチバイト文字やバイナリデータを扱うためのエンコード方式で、メールに添付する画像のエンコードなどで使われていました。
詳細については、昨日の記事を参考にしてください。
今日は、暗号化と復号化の基本について学習します。
16文字のランダムなコード
Pythonの暗号化ライブラリpycrypt
を使って暗号化処理をしていきます。
まずは、ターミナルからコマンドpip install pycrypt
を実行してpycrypt
をインストールします。
インストールが完了したら、アスキーコードからランダムに選んだ16文字のコードを作ります。
import string
import random
from Crypto.Cipher import AES
key = ''.join(
random.choice(string.ascii_letters) for _ in range(AES.block_size)
)
print(AES.block_size)
print(string.ascii_letters)
print(key)
最初にstring
とrandom
ライブラリをインポートします。
次にインストールしたCrypt.Cipher
パッケージから暗号規格のAES
モジュールを読み込みます。
7行目から9行目でstring.ascii_letters
で文字列にしたアスキーコードの文字をランダムに選んで、16になるAES.block_size
を使って、16文字のランダムな文字列をkey
に代入しています。
10行目でAES.block_size
、11行目でstring.ascii_letters
、13行目でkey
をそれぞれ出力しています。
出力結果
16
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ
YDngexIsrJyqhAJf
2行目の英字大文字小文字の中から1行目の16個をランダムに選んだものが3行目のkey
になります。
コードの暗号化
次に任意のコードを暗号化してみます。
暗号化するには、16の倍数の文字でないとだめなので、16で割り切れないときは割り切れるように文字の数を調整します。
key = ''.join(
random.choice(string.ascii_letters) for _ in range(AES.block_size)
)
iv = ''.join(
random.choice(string.ascii_letters) for _ in range(AES.block_size)
)
plaintext = 'jdadfaagewgofiajoi'
cipher = AES.new(key, AES.MODE_CBC, iv)
padding_length = AES.block_size - len(plaintext) % AES.block_size
plaintext += chr(padding_length) * padding_length
cipher_text = cipher.encrypt(plaintext)
print(cipher_text)
インポートするライブラリは最初と同じです。
11行目〜13行目で16文字のランダムな英字を生成してiv
に代入しています。
15行目で暗号化するplaintext
を作り、16行目のAES.newで、AES.MODE_CBC
というアルゴリズムを使い、key
とiv
を絡めた暗号化の準備をします。
暗号化は16文字の倍数でなければならないので、17行目と18行目でplaintext
の長さを16で割った余りを16からひいいた数padding_length
を求め、padding_length
の値をpadding_length
の数だけ16進数の値(chr(padding_length)
)を並べたものを暗号化するplaintext
に加えます。
これで、暗号化するplaintext
が16の倍数になり、暗号化ができるようになります。
続いて、19行目でplaintext
を暗号化します。
最後に暗号化されたcipher_text
を出力しています。
出力結果
b'Ps\xc8T\xf5\x1e\xdf]\xe58G\xb2\xb5\x97\x85\x0e)\x1a+\x8e\x9dbC\xed\x95\xa1\xc5Y\xe0:\xa0\x94'
復号化
次に、暗号化されたコードをもとのデータに戻す復号化をやってみます。
cipher2 = AES.new(key, AES.MODE_CBC, iv)
decrypted_text = cipher2.decrypt(cipher_text)
print(decrypted_text)
print(decrypted_text[-1])
print(decrypted_text[:-decrypted_text[-1]])
21行目までは上記の暗号化のコードと同じです。
22行目でcipher2
を作り、23行目でcipher2
を使って暗号化したcipher_text
をdecrypt
で復号化します。
あとは、decrypted_text
と、付け足されたpadding_lengs
の数と復号化したもとのplaintext
を出力しています。
出力結果
b'V\x8fU\xdd\x10\xfcI\xbe\xeb\x87\xba\x97\xffv\xfe\xb77\xbf"[^\\`\xe0\x06\x8c\xb0\xedhL\x19\xe3'
b'jdadfaagewgofiajoi\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e'
14
b'jdadfaagewgofiajoi'
ちなみに、decrypted_text[-1]
は、最後の文字を表しているので、decrypted_text[:-decrypted_text[-1]]
は、decrypted_text
から最後の文字である14
を16進数にしたe
を14個省いたデータとなるわけです
出力された値を見ると、2行目に\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e
という値があるのがわかります。
これは、16進数のe
、つまり10進数の14
になり、16進数のe
が14個付け足されているということです。
プログラマーみたい
当たり前ですが、暗号化と復号化は非常に重要で、ネットワークが必要不可欠な現在のデータのやり取りには欠かすことのできない技術です。
ミッション・インポッシブルなどの工作員が出てくるような映画では、必ずといっていいほど、暗号化されたデータの解読が出てきますが、基本は今日学習したような仕組みでデータが暗号化されていると思うとワクワクしてきちゃいます。
実際に運用されているシステムなどはもっと複雑な暗号化が用いられているのだと思いますが、いよいよプログラマーに近づいて来たような感じがしています。
まずは暗号化と復号化の基本を理解して、コツコツと暗号化のスキルをマスターしていきましょう。
それでは明日も、Good Python!