2
2

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 3 years have passed since last update.

pythonでプライベートメソッドやプライベートフィールド【暗号】

Last updated at Posted at 2020-04-15

0.時間を無駄にしたくない方向けの要約

この記事はpythonでprivateメンバを無理やり実装するため、nonceや暗号化を取り入れたけど、可読性下がるしすぐに破られるから意味なかったってだけの記事です。

1.アイデア

暗号化nonceを設計すればいいじゃん。
暗号化機構についてはteitei_tkさんの記事を丸パクリさせていただいた。
特にaes_cipher.pyはそのままディレクトリに保存した。
ただしpip install pycryptoはwindows環境ではビルドエラーになるようなので、
pip install pycryptodomeで代替のこと。

2.実装

プライベートメソッド
import numpy as np
from aes_cipher import AESCipher
import string, random;
# importはすべてprivateメソッド用

class Test:
    def __init__(self):
        self.cipher = AESCipher(''.join([random.choice(string.ascii_letters + string.digits) for i in range(50)])) #鍵の作成、即登録
        self.nonce # nonce

    def caller(self):
        print('callerから_private_calleeを呼ぶ')
        self.nonce = np.random.rand() #nonce更新
        self._private_callee(self.cipher.encrypt(self.nonce)) #新しいnonceを暗号化してprivateメソッドへ送る

    def _private_callee(self, ciphered_nonce):
        nonce = cipher.decrypt(ciphered_nonce) #送られてきた暗号化済みnonceを復号
        if nonce==self.nonce:
            print('ノンスが一致したのでおそらcallerからの想定通りの呼び出し')
            #ここに処理をかく
        else:
            print('不正な呼び出し')

もちろん、外部からobj._private_callee(obj.cipher.encrypt(obj.nonce))とやれば不正な呼び出しに成功してしまうため、セキュリティ的には論外もいいところである。
でもまあ、これくらいしておけば「うっかりprivateメソッドを呼んでしまう」ということは考えにくい。
そもそもjavaのprivateメソッドでさえ、リフレクションを使えば外部から呼べてしまう。
知らない人がついprivateメソッドを呼んでしまうことを防ぐだけであればこれで十分ではないだろうか。

また、同じアプローチで、privateフィールドを作って、getter、setterを定義することも可能。

プライベートフィールド
import numpy as np
from aes_cipher import AESCipher
import string, random;
# importはすべてprivateフィールド用

class Test:
    def __init__(self):
        self.cipher = AESCipher(''.join([random.choice(string.ascii_letters + string.digits) for i in range(50)])) #鍵の作成、即登録
        self._private_field = self.cipher.encrypt('「最悪見られてもいい」が「うっかり見られたくはない」内容')

    def setter(self, value):
        self._private_field = self.cipher.encrypt(value)

    def getter(self):
        return self.cipher.decrypt(self._private_field)
    

2.結論

やっぱり暗号化したりnonceを導入したりしないで、素直に「先頭に_のついてるものはprivateだと思ってね!」と取り決めるだけにとどめておく方がよさそう。
無理やりそれっぽいことを実装しても、大した意味がないわりに、コードの可読性がめちゃくちゃ落ちるからだ。

2
2
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
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?