ODBC接続を作成するPythonスクリプトを取得しました。ODBC接続は、接続文字列を使用して生成されます。この接続文字列には、この接続のユーザー名とパスワードを含める必要があります。
このパスワードをファイル内で簡単に隠す方法はありますか(ファイルを編集しているときに誰もパスワードを読み取れないだけです)。
ODBC接続を作成するPythonスクリプトを取得しました。ODBC接続は、接続文字列を使用して生成されます。この接続文字列には、この接続のユーザー名とパスワードを含める必要があります。
このパスワードをファイル内で簡単に隠す方法はありますか(ファイルを編集しているときに誰もパスワードを読み取れないだけです)。
回答:
Base64エンコーディングは標準ライブラリにあり、肩のサーファーを停止するために行います:
>>> import base64
>>> print(base64.b64encode("password".encode("utf-8")))
cGFzc3dvcmQ=
>>> print(base64.b64decode("cGFzc3dvcmQ=").decode("utf-8"))
password
base64
はrot13
、この文脈よりも難読化する方が良いとは思いません。逆に、base64
はその典型的な特性(等号など)を備えているため、他のアプローチよりも簡単に検出できます。ただし、難読化には実用的なメリットはありません。この答えがこの高評価であることは本当に悪い。それは誤った安心感を与えるだけです...
base64
も望ましいrot13
です。
Douglas F Shearerは、リモートログインのパスワードを指定する必要がある場合に、Unixで一般に承認されているソリューションです。
あなたは追加--password-からファイルのパスを指定し、ファイルから平文を読み込むためのオプションを選択します。
このファイルは、オペレーティングシステムによって保護されているユーザー自身の領域に置くことができます。また、さまざまなユーザーが自分のファイルを自動的に取得することもできます。
スクリプトのユーザーが知ることを許可されていないパスワードの場合-特権を付与してスクリプトを実行し、そのroot / adminユーザーがパスワードファイルを所有することができます。
ここに簡単な方法があります:
これは、base64デコードよりも少し安全です-py_to_pyc逆コンパイラに対して脆弱です。
import peekabo
peekaboo.password
password='secret'
cythonizing
スクリプトによる生成されたバイナリを共有すると、この回答の利点が得られます+難読化の別のレイヤーが追加されます。これで、パスワードを取得するためのCコードを逆コンパイルすることができます。これは100%安全ではありませんが、非表示にしたい機密データを入手するには多くの労力がかかります。
Unixシステムで作業している場合は、標準Pythonライブラリのnetrcモジュールを利用してください。ここで説明する形式の別のテキストファイル(.netrc)からパスワードを読み取ります。
これは小さな使用例です:
import netrc
# Define which host in the .netrc file to use
HOST = 'mailcluster.loopia.se'
# Read from the .netrc file in your home directory
secrets = netrc.netrc()
username, account, password = secrets.authenticators( HOST )
print username, password
ユーザーが実行時にユーザー名とパスワードを指定できない場合の最善の解決策は、メインコードにインポートされるユーザー名とパスワードの変数初期化のみを含む別のソースファイルであると考えられます。このファイルは、資格情報が変更されたときにのみ編集する必要があります。それ以外の場合、平均的な記憶力を持つショルダーサーファーだけが心配な場合は、Base 64エンコーディングがおそらく最も簡単なソリューションです。ROT13は手動でデコードするのが簡単すぎて、大文字と小文字を区別せず、暗号化された状態で意味を保持しすぎます。Pythonスクリプトの外でパスワードとユーザーIDをエンコードします。実行時にスクリプトをデコードして使用します。
自動化されたタスクにスクリプトの資格情報を与えることは常に危険な提案です。スクリプトには独自の資格情報が必要です。また、スクリプトが使用するアカウントには、必要なもの以外はアクセスできないようにする必要があります。少なくともパスワードは長くランダムである必要があります。
base64は、単純なニーズに対応する方法です。何もインポートする必要はありません:
>>> 'your string'.encode('base64')
'eW91ciBzdHJpbmc=\n'
>>> _.decode('base64')
'your string'
以下のためのpython3の難読使用してbase64
別々に行われます。
import base64
base64.b64encode(b'PasswordStringAsStreamOfBytes')
その結果
b'UGFzc3dvcmRTdHJpbmdBc1N0cmVhbU9mQnl0ZXM='
非公式の文字列表現に注意してください。実際の文字列は引用符で囲まれています
元の文字列にデコードして戻します
base64.b64decode(b'UGFzc3dvcmRTdHJpbmdBc1N0cmVhbU9mQnl0ZXM=')
b'PasswordStringAsStreamOfBytes'
文字列オブジェクトが必要な場合にこの結果を使用するには、バイトオブジェクトを変換できます
repr = base64.b64decode(b'UGFzc3dvcmRTdHJpbmdBc1N0cmVhbU9mQnl0ZXM=')
secret = repr.decode('utf-8')
print(secret)
python3がバイト(およびそれに応じて文字列)を処理する方法の詳細については、公式ドキュメントを参照してください。
これはかなり一般的な問題です。通常、実行できる最善の方法は次のいずれかです。
A)エンコード/デコードするためのある種のシーザー暗号関数を作成する(rot13ではない)または
B)推奨される方法は、プログラムの範囲内で暗号化キーを使用し、パスワードをエンコード/デコードすることです。ファイル保護を使用して、キーへのアクセスを保護できます。
これらの線に沿って、アプリがサービス/デーモン(ウェブサーバーなど)として実行されている場合、サービスの起動の一部としてパスワードを入力し、パスワードで保護されたキーストアにキーを配置できます。アプリを再起動するには管理者が必要ですが、設定パスワードは非常に適切に保護されます。
お使いのオペレーティングシステムは、データを安全に暗号化する機能を備えている可能性があります。たとえば、WindowsにはDPAPI(データ保護API)があります。初めて実行するときにユーザーに資格情報を要求し、その後の実行のために暗号化して暗号化して削除しませんか?
認証/パスワード/ユーザー名を暗号化された詳細に変換するのではなく、より自作の手法。FTPLIBは単なる例です。" pass.csv "はcsvファイル名です
以下のようにパスワードをCSVに保存します。
user_name
ユーザーパスワード
(列見出しなし)
CSVを読み取り、リストに保存します。
認証の詳細としてリスト要素を使用します。
完全なコード。
import os
import ftplib
import csv
cred_detail = []
os.chdir("Folder where the csv file is stored")
for row in csv.reader(open("pass.csv","rb")):
cred_detail.append(row)
ftp = ftplib.FTP('server_name',cred_detail[0][0],cred_detail[1][0])
これがそのようなものの私の抜粋です。基本的には、関数をコードにインポートまたはコピーします。getCredentialsは、存在しない場合は暗号化されたファイルを作成して辞書を返し、updateCredentialは更新されます。
import os
def getCredentials():
import base64
splitter='<PC+,DFS/-SHQ.R'
directory='C:\\PCT'
if not os.path.exists(directory):
os.makedirs(directory)
try:
with open(directory+'\\Credentials.txt', 'r') as file:
cred = file.read()
file.close()
except:
print('I could not file the credentials file. \nSo I dont keep asking you for your email and password everytime you run me, I will be saving an encrypted file at {}.\n'.format(directory))
lanid = base64.b64encode(bytes(input(' LanID: '), encoding='utf-8')).decode('utf-8')
email = base64.b64encode(bytes(input(' eMail: '), encoding='utf-8')).decode('utf-8')
password = base64.b64encode(bytes(input(' PassW: '), encoding='utf-8')).decode('utf-8')
cred = lanid+splitter+email+splitter+password
with open(directory+'\\Credentials.txt','w+') as file:
file.write(cred)
file.close()
return {'lanid':base64.b64decode(bytes(cred.split(splitter)[0], encoding='utf-8')).decode('utf-8'),
'email':base64.b64decode(bytes(cred.split(splitter)[1], encoding='utf-8')).decode('utf-8'),
'password':base64.b64decode(bytes(cred.split(splitter)[2], encoding='utf-8')).decode('utf-8')}
def updateCredentials():
import base64
splitter='<PC+,DFS/-SHQ.R'
directory='C:\\PCT'
if not os.path.exists(directory):
os.makedirs(directory)
print('I will be saving an encrypted file at {}.\n'.format(directory))
lanid = base64.b64encode(bytes(input(' LanID: '), encoding='utf-8')).decode('utf-8')
email = base64.b64encode(bytes(input(' eMail: '), encoding='utf-8')).decode('utf-8')
password = base64.b64encode(bytes(input(' PassW: '), encoding='utf-8')).decode('utf-8')
cred = lanid+splitter+email+splitter+password
with open(directory+'\\Credentials.txt','w+') as file:
file.write(cred)
file.close()
cred = getCredentials()
updateCredentials()
あなたはピットを知っていますか?
https://pypi.python.org/pypi/pit(py2 only(version 0.3))
https://github.com/yoshiori/pit(py3(現在のバージョン0.4)で動作します)
test.py
from pit import Pit
config = Pit.get('section-name', {'require': {
'username': 'DEFAULT STRING',
'password': 'DEFAULT STRING',
}})
print(config)
実行:
$ python test.py
{'password': 'my-password', 'username': 'my-name'}
〜/ .pit / default.yml:
section-name:
password: my-password
username: my-name
/usr/lib/python3.7/site-packages/pit.py:93: YAMLLoadWarning: calling yaml.load() without Loader=... is deprecated, as the default Loader is unsafe. Please read https://msg.pyyaml.org/load for full details. return yaml.load(open(Pit._config))
Windowsで実行している場合は、win32cryptライブラリの使用を検討できます。スクリプトを実行しているユーザーが保護されたデータ(キー、パスワード)を保存および取得できるため、パスワードがコード内にクリアテキストまたは難読化形式で保存されることはありません。他のプラットフォームに同等の実装があるかどうかは不明なので、win32cryptを厳密に使用すると、コードを移植できなくなります。
モジュールはここで入手できると思います:http : //timgolden.me.uk/pywin32-docs/win32crypt.html
私がこれを行った方法は次のとおりです:
Pythonシェルで:
>>> from cryptography.fernet import Fernet
>>> key = Fernet.generate_key()
>>> print(key)
b'B8XBLJDiroM3N2nCBuUlzPL06AmfV4XkPJ5OKsPZbC4='
>>> cipher = Fernet(key)
>>> password = "thepassword".encode('utf-8')
>>> token = cipher.encrypt(password)
>>> print(token)
b'gAAAAABe_TUP82q1zMR9SZw1LpawRLHjgNLdUOmW31RApwASzeo4qWSZ52ZBYpSrb1kUeXNFoX0tyhe7kWuudNs2Iy7vUwaY7Q=='
次に、次のコードでモジュールを作成します。
from cryptography.fernet import Fernet
# you store the key and the token
key = b'B8XBLJDiroM3N2nCBuUlzPL06AmfV4XkPJ5OKsPZbC4='
token = b'gAAAAABe_TUP82q1zMR9SZw1LpawRLHjgNLdUOmW31RApwASzeo4qWSZ52ZBYpSrb1kUeXNFoX0tyhe7kWuudNs2Iy7vUwaY7Q=='
# create a cipher and decrypt when you need your password
cipher = Fernet(key)
mypassword = cipher.decrypt(token).decode('utf-8')
これを実行したら、mypasswordを直接インポートするか、必要に応じてトークンと暗号をインポートして復号化できます。
明らかに、このアプローチにはいくつかの欠点があります。誰かが(スクリプトを持っている場合と同様に)トークンとキーの両方を持っている場合、簡単に復号化できます。しかし、それは難読化し、コードを(Nuitkaのようなもので)コンパイルすると、少なくともパスワードは16進エディタでプレーンテキストとして表示されません。
スクリプトの外部でパスワードを保存し、実行時にパスワードを提供する可能性を検討することもできます
例:fred.py
import os
username = 'fred'
password = os.environ.get('PASSWORD', '')
print(username, password)
のように実行できます
$ PASSWORD=password123 python fred.py
fred password123
「あいまいさによるセキュリティ」の追加レイヤーは、 base64
(上記で提案したように)を使用して、コードであまり明確でない名前を使用し、実際のパスワードをコードから遠ざけるます。
コードがリポジトリにある場合、シークレットをその外部に保存すると便利なことがよくあります。そのため、これを~/.bashrc
(またはボールトや起動スクリプトなどに)追加できます。
export SURNAME=cGFzc3dvcmQxMjM=
そして、変更fred.py
に
import os
import base64
name = 'fred'
surname = base64.b64decode(os.environ.get('SURNAME', '')).decode('utf-8')
print(name, surname)
その後、再ログインして
$ python fred.py
fred password123
'ネット上のPythonで書かれたいくつかのROT13ユーティリティがあります-それらのためのグーグル。ROT13は文字列をオフラインでエンコードし、それをソースにコピーし、送信ポイントでデコードします。
しかし、これは本当に弱い保護です...