Y's note

Web技術・プロダクトマネジメント・そして経営について

本ブログの更新を停止しており、今後は下記Noteに記載していきます。
https://note.com/yutakikuchi/

Pythonでの暗号化/復号化(AEC-DES,RSA)

概要

Pythonで文字列の暗号化を行う場合は、Python Cryptography Toolkitを利用すると簡単に実装ができます。
Python Cryptography ToolkitはGoogle App Engineでもサポートされています。
http://www.amk.ca/python/code/crypto.html
http://code.google.com/intl/ja/appengine/docs/python/tools/libraries.html#PyCrypto

この記事ではAES-DES,RSAの実装について説明したいと思います。

始めに注意

Google App Engineのサーバに下記のプログラムを配布すれば利用ができますが、
localの場合は最初に
http://www.amk.ca/python/code/crypto.html
からファイルをダウンロード、installする必要があります。
Macでやりましたが、以下の手順でinstallが可能です。

fetch http://www.amk.ca/files/python/crypto/pycrypto-2.0.1.tar.gz 
tar -xzf pycrypto-2.0.1.tar.gz
cd pycrypto-2.0.1
python setup.py build
sudo python setup.py install

AES-DES

メッセージを特定のkEYで暗号化します。しかしこの方法には以下のようなByte数の制限があります。
KEY : 16,24,32Byteのいずれか
MESSAGE : 16Byteの倍数
以下のサンプルコードでは16ByteのKEYを利用し、unixtimeと文字を結合した文字列を暗号化/復号化しているサンプルになります。

サンプルコード
#! /usr/bin/env python
# -*- coding: utf-8 -*-

import Crypto.Cipher.AES as AES
import datetime,time

#16,24,32byteの文字列が暗号化KEY
CRYPTO_KEY = "16bytes  strings"
crypto_object = AES.new( CRYPTO_KEY, AES.MODE_ECB )

#unixtimeの取得
d = datetime.datetime.today()
utime = int( time.mktime( d.timetuple() ) )

#暗号化できる文字列は16byteの倍数
message = str( utime ) + "string"
crypto_message = crypto_object.encrypt( message ) 
decrypto_message = crypto_object.decrypt( crypto_message ) 

html  = '''Content-Type: text/html; charset=UTF-8
<html>
<head>
<title>web-pro.appspot.com</title>
</head>
<body>
<table>
<tr><th>message     </th><td>%s </td></tr>
<tr><th>encrypto      </th><td>%s </td></tr>
<tr><th>decrypto  </th><td>%s </td></tr>
</table>
</body>
<html>
'''
print html % ( message, crypto_message, decrypto_message )
実行結果
message	1297070807string
encrypto	&#65533;7]&#65533;Q&#65533;&#60063;&#761;&#65533;
decrypto	1297070807string

RSA

RSAによる暗号化/復号化は以下のようになります。
RSAの場合、暗号化する文字列のByte数の制限をプログラムコード中で指定します。
( 例 ) RSA.generate(128, RANDOM.RandomPool().get_bytes ) ← 128bit( 16Byteまで )

サンプルコード
#! /usr/bin/env python
# -*- coding: utf-8 -*-

import Crypto.PublicKey.RSA as RSA
import Crypto.Util.randpool  as RANDOM
import datetime,time

#鍵オブジェクト( 鍵を16ByteまでOKとする )
rsa = RSA.generate(128, RANDOM.RandomPool().get_bytes )

#公開鍵
rsa_pub_key = rsa.publickey()

#秘密鍵
rsa_private_key = RSA.construct((rsa.n, rsa.e, rsa.d))

#message
message = "This is RSA Test"

#暗号化
encrypto = rsa_pub_key.encrypt( message, "" )

#復号化
decrypto = rsa_private_key.decrypt( encrypto ) 

#署名確認
digest = rsa_private_key.sign( message, "" )
digest_flag = rsa_pub_key.verify( message, digest )
html  = '''Content-Type: text/html; charset=UTF-8
<html>
<head>
<title>web-pro.appspot.com</title>
</head>
<body>
<table>
<tr><th>message     </th><td>%s </td></tr>
<tr><th>encrypto      </th><td>%s </td></tr>
<tr><th>decrypto  </th><td>%s </td></tr>
<tr><th>digest flag  </th><td>%s </td></tr>
</table>
</body>
<html>
'''
実行結果
message	This is RSA Test
encrypto	('\x1e\xccC\x99w\xe4\xbf\x05\x0bA\x19\xeaLU\xe1}',)
decrypto	This is RSA Test
digest flag	1