質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
公開鍵認証

公開鍵認証とは、公開鍵と秘密鍵の2つの鍵の組を利用する、SSHで利用される認証方式です。

Kivy

Kivyは、Pythonを用いたNUI開発のためのオープンソースフレームワーク。マルチタッチなど多くの入力に対応したNUIアプリなどを開発することができます。多くの環境で動作するクロスプラットフォームです。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

API

APIはApplication Programming Interfaceの略です。APIはプログラムにリクエストされるサービスがどのように動作するかを、デベロッパーが定めたものです。

Q&A

解決済

2回答

889閲覧

pythonから自作APIへ暗号化されたバイナリデータを送りたい

saitou_san

総合スコア32

公開鍵認証

公開鍵認証とは、公開鍵と秘密鍵の2つの鍵の組を利用する、SSHで利用される認証方式です。

Kivy

Kivyは、Pythonを用いたNUI開発のためのオープンソースフレームワーク。マルチタッチなど多くの入力に対応したNUIアプリなどを開発することができます。多くの環境で動作するクロスプラットフォームです。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

API

APIはApplication Programming Interfaceの略です。APIはプログラムにリクエストされるサービスがどのように動作するかを、デベロッパーが定めたものです。

0グッド

0クリップ

投稿2023/02/03 06:38

編集2023/02/04 02:07

実現したいこと

pythonで作っているスマホアプリから、公開鍵で暗号化されたユーザネーム(bytes型)をbase64でエンコード

bytes型のデータをPHPで作った自作APIへ送る

API側で送られてきたデータを秘密鍵で復号
ということがしたいです。

これまでの取り組み

pythonでurlに暗号化・base64でのエンコードがされていないユーザネーム(str型)をURL+"?username=ユーザネーム"のようにして送り、
サーバ側でGET['username']で取り出し、処理することに成功しました。

python

1 url = "http://192.168.11.69/api/get_id_password.php?username="+input_username 2 json_data = requests.get(url)

しかし、送るユーザネームを暗号化・base64でエンコードした場合、URL(str型)にユーザネーム(bytes型)を連結することができず、渋々str型に変換したらPHP側でbytes型に戻せなくて困っています。

そこで、アプリ側(python)でpayloadを設定してPHPで取り出せるようにしようとしていますが上手くいきません。

該当のソースコード

アプリ側(python)でpayloadを設定してPHPで取り出せるようにしようとしています。

python

1#省略 2#公開鍵での暗号に使用 3from Crypto.PublicKey import RSA 4from Crypto.Cipher import PKCS1_OAEP 5import base64 6#省略 7 with open('public.key', 'rb') as f: 8 public_key = f.read() #.keyファイル読み取り 9 key = RSA.importKey(public_key) 10 cipher_rsa = PKCS1_OAEP.new(key) #公開鍵の読み込み 11 c_username = cipher_rsa.encrypt(input_username.encode()) #暗号化されたバイナリデータ 12 base64_username = base64.b64encode(c_username) 13 14 url = "http://192.168.11.69/api/get_id_password.php" 15 payload = {"username":base64_username} 16 json_data = requests.get(url,payload) 17 if str(json_data) == '<Response [200]>': 18 id = json_data.json()['id'] 19 hashed_password = json_data.json()['password'] 20 #省略

PHP

1 $request_body = file_get_contents('php://input'); 2 $data = json_decode($request_body); 3 if(isset($data["username"])){ 4 $key = file_get_contents('秘密鍵の場所'); 5 openssl_private_decrypt(base64_decode($data['username']), $username, $key); 6 //以後省略

python側のエラー

File "C:\tenko\tenko.kv", line 54, in <module> on_press: app.root.login.check() File "C:\tenko\main.py", line 45, in check id = json_data.json()['id'] File "C:\Users\Owner\AppData\Local\Programs\Python\Python310\lib\site-packages\requests\models.py", line 975, in json raise RequestsJSONDecodeError(e.msg, e.doc, e.pos) requests.exceptions.JSONDecodeError: Expecting value: line 1 column 1 (char 0)

教えていただきたいこと

GETでもPOSTでもペイロードでも、どんな方法でもいいのでbytes型のデータをAPIに送る方法を教えてください!!!

補足情報(FW/ツールのバージョンなど)

PHP7.4.26
Python3.10.9

ここから新しく追加

謝辞

この質問と酷似した内容の質問を新たに投稿してしまいました。すみませんでした。
なので、この質問に編集で追記するという形で新たにやったことについての質問の回答を受け付けたいと思います。すみませんでした。

該当のソースコード(GETを使う方法)

送信側(Python)

python

1#省略 2 with open('public.key', 'rb') as f: 3 public_key = f.read() #.keyファイル読み取り 4 key = RSA.importKey(public_key) 5 cipher_rsa = PKCS1_OAEP.new(key) #公開鍵の読み込み 6 c_username = cipher_rsa.encrypt(input_username.encode()) #暗号化されたバイナリデータ 7 base64_username = base64.b64encode(c_username) 8 str_username = base64_username.decode('utf-8') 9 10 url = "http://192.168.11.69/api/get_id_password.php?username="+str_username 11 url_text = open('url.txt', 'w') #手動でアクセスできるようにURLを保存 12 url_text.write(url) 13 url_text.close() 14 json_data = requests.get(url) 15 print(json_data) 16 if str(json_data) == '<Response [200]>': 17 id = json_data.json()['id']

送信側エラー(Python)

on_press: app.root.login.check() File "C:\tenko\main.py", line 49, in check id = json_data.json()['id'] File "C:\Users\Owner\AppData\Local\Programs\Python\Python310\lib\site-packages\requests\models.py", line 975, in json raise RequestsJSONDecodeError(e.msg, e.doc, e.pos) requests.exceptions.JSONDecodeError: Expecting value: line 1 column 1 (char 0)

受信側(PHP)

PHP

1//省略 2 if(isset($_GET["username"])){ 3 var_dump($_GET["username"]); 4 $replaced = str_replace(' ', '+', $_GET['username']); 5 var_dump($replaced); 6 var_dump(base64_decode($replaced )); 7 $key = file_get_contents('秘密鍵のパス'); 8 openssl_private_decrypt(base64_decode($replaced ), $username, $key); 9 var_dump($username); 10//省略 11$array = [ 'id'=>$data['id'], 'password'=>$data['password'] ]; 12print json_encode($array); 13 }

受信側エラー(PHP)
URL:http://192.168.11.69/api/get_id_password.php?username=T55LIv6zH7GSG6iYzxJszz94kTFKaKGCX/A7HoiGJg0HS7qv6uLK4t06iMdrNdQ9wNr/SkYo+Fkn7j8hrkMFqlZ7FbqeKHJTJj92EY+bjC5T+gcW9DmOl2DYNa11RpZfnKuMsssELhaTqPCGECSBf0u/zfWwJWbql+s+uzhJofTD+VSo2ekmX5Z6saTKUxejFaxkMJ7hvNmZlg1zC7aFPCCTaOFWPLmixdBies5+y4egtBqvE/ANDC9uN+7oojVi2fAs4GiASQgES6QsJSBdWXffGPpG+Vdo7CrLnidBSXlJkPAHbq/W8OoRbjpHgH0B/TfE7jeC3Rjr7bCA1VJSWQ==
※1ファイルに記録したURLを直接ブラウザに貼り付けました。
※2ver_dump()の結果も含まれています

※var_dump($_GET["username"]); string(344) "T55LIv6zH7GSG6iYzxJszz94kTFKaKGCX/A7HoiGJg0HS7qv6uLK4t06iMdrNdQ9wNr/SkYo Fkn7j8hrkMFqlZ7FbqeKHJTJj92EY bjC5T gcW9DmOl2DYNa11RpZfnKuMsssELhaTqPCGECSBf0u/zfWwJWbql s uzhJofTD VSo2ekmX5Z6saTKUxejFaxkMJ7hvNmZlg1zC7aFPCCTaOFWPLmixdBies5 y4egtBqvE/ANDC9uN 7oojVi2fAs4GiASQgES6QsJSBdWXffGPpG Vdo7CrLnidBSXlJkPAHbq/W8OoRbjpHgH0B/TfE7jeC3Rjr7bCA1VJSWQ==" ※var_dump($replaced); string(344) "T55LIv6zH7GSG6iYzxJszz94kTFKaKGCX/A7HoiGJg0HS7qv6uLK4t06iMdrNdQ9wNr/SkYo+Fkn7j8hrkMFqlZ7FbqeKHJTJj92EY+bjC5T+gcW9DmOl2DYNa11RpZfnKuMsssELhaTqPCGECSBf0u/zfWwJWbql+s+uzhJofTD+VSo2ekmX5Z6saTKUxejFaxkMJ7hvNmZlg1zC7aFPCCTaOFWPLmixdBies5+y4egtBqvE/ANDC9uN+7oojVi2fAs4GiASQgES6QsJSBdWXffGPpG+Vdo7CrLnidBSXlJkPAHbq/W8OoRbjpHgH0B/TfE7jeC3Rjr7bCA1VJSWQ==" ※var_dump(base64_decode($replaced )); string(256) "O�K"�������l�?x�1Jh��_�;��& K�������:��k5�=���JF(�Y'�?!�C�V{��(rS&?v���.S��9��`�5�uF�_�����.����$�K����%f��>�8I����T���&_�z���S��d0��ٙ� s ��< �h�V<����bz�~ˇ���� /n7��5b��,�h�IK�,% ]Yw��F�Wh�*˞'AIyI��n����n:G�}�7��7�������RRY" ※var_dump($username); NULL <br /> <b>Notice</b>: Trying to access array offset on value of type bool in <b>C:\xampp\htdocs\api\get_id_password.php</b> on line <b>39</b><br /> <br /> <b>Notice</b>: Trying to access array offset on value of type bool in <b>C:\xampp\htdocs\api\get_id_password.php</b> on line <b>39</b><br /> ※print json_encode($array); {"id":null,"password":null}

該当のソースコード(POSTを使う方法)

送信側(python)

python

1 with open('public.key', 'rb') as f: 2 public_key = f.read() #.keyファイル読み取り 3 key = RSA.importKey(public_key) 4 cipher_rsa = PKCS1_OAEP.new(key) #公開鍵の読み込み 5 c_username = cipher_rsa.encrypt(input_username.encode()) #暗号化されたバイナリデータ 6 base64_username = base64.b64encode(c_username) 7 payload = {'username': base64_username} 8 #str_username = base64_username.decode('utf-8') 9 10 url = "http://192.168.11.69/api/get_id_password.php" 11 url_text = open('url.txt', 'w') 12 url_text.write(url) 13 url_text.close() 14 json_data = requests.post(url,payload) 15 print(json_data) 16 if str(json_data) == '<Response [200]>': 17 id = json_data.json()['id']

送信側エラー(python)

File "C:\tenko\main.py", line 50, in check id = json_data.json()['id'] File "C:\Users\Owner\AppData\Local\Programs\Python\Python310\lib\site-packages\requests\models.py", line 975, in json raise RequestsJSONDecodeError(e.msg, e.doc, e.pos) requests.exceptions.JSONDecodeError: Expecting value: line 1 column 1 (char 0)

受信側(PHP)

PHP

1<?php 2 header('Content-Type: application/json; charset=UTF-8'); 3 $request_body = file_get_contents('php://input'); 4 $json = mb_convert_encoding($json, 'UTF8', 'ASCII,JIS,UTF-8,EUC-JP,SJIS-WIN'); 5 $data = json_decode($request_body,true); 6//省略 7 8 if(isset($data["username"])){ 9 10 $key = file_get_contents('秘密鍵のパス'); 11 openssl_private_decrypt(base64_decode($data['username']), $username, $key); 12 13//省略 14 $array = [ 'id'=>$data['id'], 'password'=>$data['password'] ]; 15 print json_encode($array); 16 } 17?>

POSTの時は、PHP側のエラーを見ることができませんでした。(それをする技術がない)

コードが間違っている箇所がございましたら、ばんばん指摘してください。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

bsdfan

2023/02/03 07:37

エラーが起きているのは、get して 200 が返ってきたあとなのでは? (省略されている部分があるので確証ありませんが) サーバー側で動いた形跡はないのですか?
can110

2023/02/03 08:07 編集

受信PHP側ではGETではなくPOSTで受信するように修正できるでしょうか。 GETで送る場合は送信データをBASE64なりで文字列にする必要がありかつURLsafeにしないといけないなど面倒なので確認です。 送信Python(requests)側はPOSTでバイナリなりJSONでBASE64化したデータを内包するなり自由に送ることができます。
saitou_san

2023/02/03 08:14

ちょっと調べてみます。
saitou_san

2023/02/03 12:27

やってみました。コードを編集で追加してみたので良かったら見てみてください!
bsdfan

2023/02/03 14:27

var_dump($_GET["username"]) の結果で、スペースが含まれているので気になったのですが、もとのpython側では + ではないでしょうか。 url のパラメータでは空白を+(もしくは%20)で置き換えるので、サーバ側で + が空白に戻されます。
m.ts10806

2023/02/04 00:49 編集

もっとシンプルな構成を考えたほうが根本解決になるのでは。 いくら自作とはいえ、手段だけに着目してるのではまともなアプリケーションにはならないでしょうし、セキュリティリスクも高まるだけでしょうね。つまりあちこちで色々やろうとしすぎ。 「単一責任の原則」という考え方もあります。
saitou_san

2023/02/04 01:50

bsdfanさんコメントありがとうございます。 PHP側で空白を+に置き換える処理を追加したら、Python側で送った文字列とPHP側で受け取った文字列が一致するようになりました。 しかし、まだ、解読の出力はNULLのままです。。。
can110

2023/02/04 02:15

この修正依頼欄でやりとりをして個々のエラーを潰していくのは 本来のQ&Aサイトの使い方とは外れてきていると思います。 最終的な目的(問題)はタイトルの通りひとつですが、 すでに同じような指摘あるように、それを分解して 単一の問題=単一の質問を立てて、ひとつづつ解決していくほうがよいと思います。
can110

2023/02/04 02:20

具体的には、Pythonから(BASE64化された)バイナリデータを送信し PHP側で正しい内容を受信できることまでが確認できた時点で この質問は閉じた方がよいです。 そのあとの処理、Python側での受信時のエラーは別途質問を立てたほうがよいです。
saitou_san

2023/02/04 02:50

そうですね。内容をまとめなおして再度投稿しようと思います。
guest

回答2

0

自己解決

Pythonからバイナリデータを文字列型に変換して送信する

python

1c_username = cipher_rsa.encrypt(input_username.encode()) #暗号化されたバイナリデータ base64_username = base64.b64encode(c_username) 2str_username = base64_username.decode('utf-8') 3 4url = "http://192.168.11.69/api/get_id_password.php?username="+str_username 5json_data = requests.get(url)

PHP側で受け取る

PHP

1$replaced = str_replace(' ', '+', $_GET['username']); 2$decoded = base64_decode($replaced );

GETで送信されるパラメータは'+'が' '(半角空白)に置き換わるのでstr_replace()で置き換えてあげる必要がある。
秘密鍵で暗号化されたデータを複合する方法は発見できなかった

投稿2023/02/04 03:09

saitou_san

総合スコア32

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

URL(str型)にユーザネーム(bytes型)を連結することができず

って、文字列をバイト型にしてしまえば済む話なんでは

投稿2023/02/03 06:55

y_waiwai

総合スコア87774

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

saitou_san

2023/02/03 07:06

はい、バイト型を文字列にして送りました。それをPHP側でバイト型に戻す方法を教えていただけないでしょうか? PHPで文字列をバイナリに変換するのはdechex()というのを見つけましたが、これは一文字しか変換できないみたいで困っています。
saitou_san

2023/02/03 07:11

本当に簡単なことかもしれませんが、すごく困っています。
saitou_san

2023/02/03 07:38

PHPはバイト型と文字列型を区別しないみたいな記事も見つけたので、バイト型を送る方法を試して、再度質問を投稿してみます。
y_waiwai

2023/02/03 07:44

PHP 文字列 バイト配列 、でぐぐってみよう
saitou_san

2023/02/03 08:10

URLにバイト型を文字列型にしたものを貼り付けてPHPに送る ↓ PHP側で文字列型をバイト配列に変換して取り扱う ということですかね?
saitou_san

2023/02/03 08:13

すみません。そういうことではなさそうですね。。。 とりあえず、文字列に変換してURLと一緒に送る方法試してみたので、 よろしければ、次投稿される質問も見てください!
saitou_san

2023/02/03 12:30

URLに文字列として追加してPHPで$_GETで受け取る方法やってみました。バイト配列についてあまりよく分からなかったので渡されたまま処理しました。質問に編集でコードを追加したのでよろしければ、見てみてください!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問