0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Pythonとphp間でRSA暗号

Posted at

実行環境

  • MacOS 12.6
  • Python 3.10.6
  • PHP8.1

モジュールのインストール

Python側でrsaモジュールを使うのでインストールします

pip install rsa

PEMファイル(鍵)の準備

PEMファイルを生成します
生成したいディレクトリで実行してください

openssl genrsa 2048 > private_key.pem
openssl rsa -in private_key.pem -pubout -out public_key.pem

実行するとこんな感じのファイルができます

private_key.pem
-----BEGIN RSA PRIVATE KEY-----
MIIEogIBAAKCAQEA8DoEBfIPUiTOBEivztYvcXVhZONbnbP8rihRFyRkaxBd9QVR
DG66TFefuMpbhLDTjD...p6qeqxzh2kBiTIfQDSQNakN8/mARLaLPlFN5Ly2QlTa
7aXFjs/+P6L17kD9DH25mTbTgpHz0OxjLmK/4ovsgMgTzkQpJa0=
-----END RSA PRIVATE KEY-----
public_key.pem
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA8DoEBfIPUiTOBEivztYv
cXVhZONbnbP8rihR...u37fLCSFgQZm9CbT67R8hGbVshqfH0Jpye68Oy6LMEHHv
e9tcc+MdmMLNiq3DLPzF7IgGPjyB9C3BCJzrHQwO7PiVcg6VAxz7aA+7f01VFHfu
9wIDAQAB
-----END PUBLIC KEY-----

Pythonで暗号化→phpで復号化

値の受け渡し方は色々なやり方があると思うのでここでは省略します

Python(暗号化)

encryption.py
import base64
import rsa

text = "hello world!" # 暗号化する文字列
pub_key_path = "./public_key.pem" # 公開鍵のパス

text_bytes = bytes(text, encoding="utf-8")
with open(pub_key_path, "rb") as f:
    public_key = rsa.PublicKey.load_pkcs1_openssl_pem(f.read())

cipher = rsa.encrypt(text_bytes, public_key)
cipher_encode = base64.b64encode(cipher)
cipher_str = cipher_encode.decode("utf-8")

print(cipher_str) # 暗号化された文字列

成功するとLDa0cxKYpkGKiKSGMkm+z...EvNh+nqnNRQ==のように暗号化された文字が出力されます

PHP(復号化)

decoding.php
<?php
$cipher = '{Python側で出力された暗号化された文字列}';
$privateKeyPath = './private_key.pem'; // 秘密鍵のパス
$privateKey = file_get_contents($privateKeyPath);

$cipherDecode = base64_decode($cipher);
openssl_private_decrypt($cipherDecode, $decipher, $privateKey);

echo $decipher.PHP_EOL;
?>

成功すると暗号化前の文字列が出力されます
失敗すると何も出力されないので気をつけてください

PHPで暗号化→Pythonで復号化

PHP(暗号化)

encryption.php
<?php
$text = 'Hello World!'; // 暗号化する文字列
$pubKeyPath = './public_key.pem'; // 公開鍵のパス

$pubKey = file_get_contents($pubKeyPath);

openssl_public_encrypt($text, $cipher, $pubKey);
$cipherEncode = base64_encode($cipher);

echo $cipherEncode.PHP_EOL;
?>

成功すると上と同じくE8Wa8PncC/m1UdK...HSrpAnm9wmY40rAKY+dz2OA==のように暗号化された文字が出力されます

Python(復号化)

decoding.py
import base64
import rsa

text = "{PHP側で出力された暗号化された文字列}"
private_key_path = "./private_key.pem" # 秘密鍵のパス

with open(private_key_path, "rb") as f:
    private_key = rsa.PrivateKey._load_pkcs1_pem(f.read())

cipher_decode = base64.b64decode(text)
decipher = rsa.decrypt(cipher_decode, private_key)
decipher_str = decipher.decode("utf-8")

print(decipher_str)

成功すると暗号化前の文字列が出力されます

注意点

  • privateKeyは絶対に公開しないでください
  • クエリパラメータ等を使ってPythonからPHPへ値を受け渡すときは+=を空白やパラメータと見られることがあるので受け渡す時は、
encryption.py(11~13行目)
cipher = rsa.encrypt(text_bytes, public_key)
cipher_encode = base64.b64encode(cipher)
- cipher_str = cipher_encode.decode("utf-8")
+ cipher_str = cipher_encode.decode("utf-8").replace('+', '%2B').replace("=", "%3D")

のようにreplaceを使ってエンコードしてください

おまけ: postを使ってPythonからphpへ値を渡す

暗号化した値の渡し方の例です
urllibモジュールを使います

encryption.py
import base64
import rsa
+ import urllib.request, urllib.parse

text = "hello world!" # 暗号化する文字列
pub_key_path = "./public_key.pem" # 公開鍵のパス

text_bytes = bytes(text, encoding="utf-8")
with open(pub_key_path, "rb") as f:
    public_key = rsa.PublicKey.load_pkcs1_openssl_pem(f.read())

cipher = rsa.encrypt(text_bytes, public_key)
cipher_encode = base64.b64encode(cipher)
cipher_str = cipher_encode.decode("utf-8")

- print(cipher_str) # 暗号化された文字列

+ URL = "http://localhost/decoding.php" # 復号化するPHPのURL
+ data = {"cipher": cipher_str} # 暗号化した文字をphp側に送信
+ post_data = urllib.parse.urlencode(data).encode("utf-8")
+ with urllib.request.urlopen(URL, data=post_data) as re:
+    print(re.read().decode("utf-8")) # 復号化した文字列が返ってくる
decoding.php
<?php
+ if (!isset($_POST['cipher'])) {
+    echo 'No cipher';
+    exit;
+ }

- $cipher = '{Python側で出力された暗号化された文字列}';
+ $cipher = $_POST['cipher'];
$privateKeyPath = './private_key.pem'; // 秘密鍵のパス
$privateKey = file_get_contents($privateKeyPath);

$cipherDecode = base64_decode($cipher);
openssl_private_decrypt($cipherDecode, $decipher, $privateKey);

echo $decipher.PHP_EOL;
?>

参考サイト

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?