2010年4月9日金曜日

PythonでPHPのopenssl_seal()相当の処理を実現

PHPには、openssl_seal()が用意されていて、複数の受信者に対して、受信者ごとの公開鍵で暗号化したデーターを、一度に暗号化するインターフェースが用意されている。

これと同じことを、Pythonでやろうとすると、インターフェースが用意されていないので、M2Cryptoを利用してやる必要があるが、その方法がやっと分かった。

まず、opensslコマンドでテスト用に、公開鍵と秘密鍵を作成しておく。

$ openssl genrsa -out privatekey.pem
$ openssl rsa -pubout -in privatekey.pem -out publickey.pem


次にPythonの暗号化用のスクリプトで、データーを暗号化し、暗号化したデーターと、エンベロープキーをゲットする。

#!/usr/bin/python

import M2Crypto
import M2Crypto.Rand
import M2Crypto.RSA
import base64

PUBKEY = "publickey.pem"
message = "Hello World!"

pubkey = M2Crypto.RSA.load_pub_key(PUBKEY)
randdata = M2Crypto.Rand.rand_bytes(16)
msg = pubkey.public_encrypt(randdata,M2Crypto.RSA.pkcs1_padding)
print "== envelope key (Base64 encoded) =="
print base64.b64encode(msg)

cipher='rc4'
iv = ""
enc = M2Crypto.EVP.Cipher(cipher, randdata, iv, M2Crypto.encrypt)
data = enc.update(message)
data += enc.final()

print "== encrypted data (Base64 encoded) =="
print base64.b64encode(data)


これを実行すると、次のような結果が得られる。

== envelope key (Base64 encoded) ==
NIBGzm6ijGFjtruyVO4QDBGiWNu1bgJvJPlkY5kmCNLKEuabiBytsjRfOKZb7w4jsSnCrUREeCPHwa7SLMVceNQf6iWyE22RS6tAMVvzFBrKjXwNCZ+pU4v4pCQPTI+vZg7B/QcajR832hmBcG0NF8LRl1+9rSSvNpPMwJNTwos=
== encrypted data (Base64 encoded) ==
on5LIKdw1UxqfcYY


これらのデーターが復号化できることを、PHPのスクリプトでopenssl_open()を使って確認してみる。

$privatekey = file_get_contents("privatekey.pem");
$message= "";
$encrypted = "on5LIKdw1UxqfcYY";

$ekey = "NIBGzm6ijGFjtruyVO4QDBGiWNu1bgJvJPlkY5kmCNLKEuabiBytsjRfOKZb7w4jsSnCrUREeCPHwa7SLMVceNQf6iWyE22RS6tAMVvzFBrKjXwNCZ+pU4v4pCQPTI+vZg7B/QcajR832hmBcG0NF8LRl1+9rSSvNpPMwJNTwos=";

if (!openssl_open(base64_decode($encrypted), $message, base64_decode($ekey), $privatekey)){
echo "Failed decrypt\n";
die;
}
echo $message."\n";
?>


このPHPスクリプトを実行して、"Hello World!"が表示されれば、正しく復号化できたということ。


0 件のコメント:

コメントを投稿