web-dev-qa-db-de.com

Ein Passwort in einem Python-Skript ausblenden (nur unsichere Verschleierung)

Ich habe ein Python-Skript, das eine ODBC -Verbindung erstellt. Die Verbindung ODBC wird mit einer Verbindungszeichenfolge erstellt. In dieser Verbindungszeichenfolge muss ich den Benutzernamen und das Kennwort für diese Verbindung angeben. 

Gibt es eine einfache Möglichkeit, dieses Kennwort in der Datei zu verschleiern (nur dass niemand das Kennwort lesen kann, wenn ich die Datei bearbeite)? 

109
bernhardrusch

Base64-Codierung ist in der Standardbibliothek enthalten und soll Schulter-Surfer stoppen:

>>> import base64
>>> print base64.b64encode("password")
cGFzc3dvcmQ=
>>> print base64.b64decode("cGFzc3dvcmQ=")
password
99
Dave Webb

Douglas F Shearer's ist die allgemein anerkannte Lösung in Unix, wenn Sie ein Kennwort für eine Remote-Anmeldung angeben müssen.
Sie fügen eine --password-from-file - Option hinzu, um den Pfad anzugeben und Klartext aus einer Datei zu lesen.
Die Datei kann sich dann im eigenen Bereich des Benutzers befinden, der durch das Betriebssystem geschützt ist. Außerdem können verschiedene Benutzer ihre eigene Datei automatisch abrufen.

Für Kennwörter, die der Benutzer des Skripts nicht kennen darf - Sie können das Skript mit der erforderlichen Berechtigung ausführen und die Kennwortdatei dieses Root-/Admin-Benutzers besitzen.

48
Martin Beckett

Hier ist eine einfache Methode:

  1. Erstellen Sie ein Python-Modul - nennen wir es peekaboo.py. 
  2. Fügen Sie in peekaboo.py sowohl das Kennwort als auch den Code ein, der dieses Kennwort benötigt
  3. Erstellen Sie eine kompilierte Version - peekaboo.pyc -, indem Sie dieses Modul importieren (über die Python-Befehlszeile usw.).
  4. Löschen Sie nun peekaboo.py. 
  5. Sie können jetzt glücklich Peekaboo importieren, indem Sie sich nur auf peekaboo.pyc verlassen. Da peekaboo.pyc Byte kompiliert wird, ist es für den gelegentlichen Benutzer nicht lesbar.

Dies sollte etwas sicherer sein als die Base64-Dekodierung - obwohl es für einen py_to_pyc-Dekompiler anfällig ist.

37

Wenn Sie an einem Unix-System arbeiten, nutzen Sie das Modul netrc in der Standard-Python-Bibliothek. Es liest Passwörter aus einer separaten Textdatei (.netrc), die das Format hier hat.

Hier ist ein kleines Anwendungsbeispiel:

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
25
jonasberg

Die beste Lösung, vorausgesetzt, der Benutzername und das Kennwort können zur Laufzeit vom Benutzer nicht angegeben werden, ist wahrscheinlich eine separate Quelldatei, die nur die Initialisierung der Variablen für den Benutzernamen und das Kennwort enthält, die in Ihren Hauptcode importiert werden. Diese Datei muss nur bearbeitet werden, wenn sich die Anmeldeinformationen ändern. Ansonsten, wenn Sie sich nur um Schulter-Surfer mit durchschnittlichen Erinnerungen sorgen, ist die 64-Codierung wahrscheinlich die einfachste Lösung. ROT13 lässt sich einfach zu manuell decodieren, unterscheidet nicht zwischen Groß- und Kleinschreibung und behält im verschlüsselten Zustand zu viel Bedeutung. Kodieren Sie Ihr Kennwort und Ihre Benutzer-ID außerhalb des Python-Skripts. Habe das Skript zur Laufzeit zur Verwendung dekodiert.

Das Bereitstellen von Skripts für automatisierte Aufgaben ist immer ein riskanter Vorschlag. Ihr Skript sollte über eigene Anmeldeinformationen verfügen, und das verwendete Konto sollte nur über den erforderlichen Zugriff verfügen. Zumindest sollte das Passwort lang und eher zufällig sein.

18
tduehr

Wie wäre es, den Benutzernamen und das Passwort aus einer Datei außerhalb des Skripts zu importieren? Auf diese Weise würde das Skript auch dann nicht automatisch erhalten, wenn jemand das Skript in die Hände bekommen hat.

16

base64 ist der Weg für Ihre einfachen Bedürfnisse. Es ist nicht notwendig, etwas zu importieren:

>>> 'your string'.encode('base64')
'eW91ciBzdHJpbmc=\n'
>>> _.decode('base64')
'your string'
15
tzot

Dies ist ein ziemlich häufiges Problem. Normalerweise können Sie entweder das Beste tun 

A) Erstellen Sie eine Art Ceasar-Chiffrierfunktion zum Kodieren/Dekodieren (einfach nicht rot13) Oder B) Die bevorzugte Methode ist die Verwendung eines Verschlüsselungsschlüssels, der sich in Reichweite Ihres Programms befindet, das Kennwort kodieren/dekodieren. Hier können Sie den Dateischutz verwenden, um den Zugriff auf den Schlüssel zu schützen . Wenn Ihre App als Dienst/Daemon (wie ein Webserver) ausgeführt wird, können Sie Ihren Schlüssel in einen kennwortgeschützten Keystore mit der Kennworteingabe als Teil des Dienststarts eingeben. Ein Neustart der App erfordert einen Administrator. Sie haben jedoch einen guten Schutz vor den Konfigurationskennwörtern.

4
Patrick

Eigenständigerer Ansatz, anstatt Authentifizierung/Kennwörter/Benutzername in verschlüsselte Details zu konvertieren.FTPLIBist nur das Beispiel . " pass.csv " ist der Name der CSV-Datei

Speichern Sie das Passwort in CSV wie folgt: 

nutzername

benutzer-Passwort

(Ohne Spaltenüberschrift)

CSV lesen und in einer Liste speichern. 

Verwenden von Listenelementen als Authentifizierungsdetails.

Vollständiger Code.

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])
2
LonelySoul

für python3 obfuscation mit base64 wird anders gemacht:

import base64
base64.b64encode(b'PasswordStringAsStreamOfBytes')

was in ... resultiert

b'UGFzc3dvcmRTdHJpbmdBc1N0cmVhbU9mQnl0ZXM='

beachten Sie die informelle Zeichenfolgendarstellung, die tatsächliche Zeichenfolge steht in Anführungszeichen

und Dekodieren zurück zu der ursprünglichen Zeichenfolge

base64.b64decode(b'UGFzc3dvcmRTdHJpbmdBc1N0cmVhbU9mQnl0ZXM=')
b'PasswordStringAsStreamOfBytes'

um dieses Ergebnis zu verwenden, wenn Zeichenfolgenobjekte erforderlich sind, kann das Byte-Objekt übersetzt sein.

repr = base64.b64decode(b'UGFzc3dvcmRTdHJpbmdBc1N0cmVhbU9mQnl0ZXM=')
secret = repr.decode('utf-8')
print(secret)

weitere Informationen darüber, wie python3 mit Bytes (und Strings entsprechend) umgeht, finden Sie in der official-Dokumentation .

2
jitter

Ihr Betriebssystem bietet wahrscheinlich Möglichkeiten, Daten sicher zu verschlüsseln. Unter Windows gibt es beispielsweise DPAPI (Data Protection API). Warum fragen Sie den Benutzer nicht beim ersten Ausführen nach den Anmeldeinformationen und lassen ihn dann für nachfolgende Läufe verschlüsselt weg?

2
Jamie Eisenhart

Platzieren Sie die Konfigurationsinformationen in einer verschlüsselten Konfigurationsdatei. Fragen Sie diese Informationen mit einem Schlüssel in Ihrem Code ab. Platzieren Sie diesen Schlüssel in einer separaten Datei pro Umgebung und speichern Sie ihn nicht mit Ihrem Code.

1
FlySwat

Wenn Sie unter Windows laufen, können Sie die Verwendung der win32crypt-Bibliothek in Betracht ziehen. Es ermöglicht das Speichern und Abrufen geschützter Daten (Schlüssel, Kennwörter) durch den Benutzer, der das Skript ausführt. Daher werden Kennwörter niemals in Klartext oder verschleiertem Format in Ihrem Code gespeichert. Ich bin nicht sicher, ob es eine äquivalente Implementierung für andere Plattformen gibt. Daher ist Ihr Code bei strenger Verwendung von win32crypt nicht portierbar.

Ich glaube, das Modul kann hier bezogen werden: http://timgolden.me.uk/pywin32-docs/win32crypt.html

1
VilleLipponen

Es gibt mehrere ROT13-Dienstprogramme, die in Python im 'Net geschrieben sind - google nur für sie. ROT13 kodiert den String offline, kopiert ihn in die Quelle, decodiert am Übertragungspunkt.

Aber das ist wirklich schwacher Schutz ...

0
Kevin Little

Kennst du die Grube?

https://pypi.python.org/pypi/pit (nur py2 (Version 0.3))

https://github.com/yoshiori/pit (funktioniert mit py3 (aktuelle Version 0.4))

test.py

from pit import Pit

config = Pit.get('section-name', {'require': {
    'username': 'DEFAULT STRING',
    'password': 'DEFAULT STRING',
    }})
print(config)

Lauf:

$ python test.py
{'password': 'my-password', 'username': 'my-name'}

~/.pit/default.yml:

section-name:
  password: my-password
  username: my-name
0
TakesxiSximada

Dies beantwortet Ihre Frage nicht genau, aber sie hängt zusammen. Ich wollte einen Kommentar hinzufügen, aber es war mir nicht erlaubt ... Ich habe mich mit diesem Problem befasst und wir haben uns entschieden, das Skript den Benutzern mit Jenkins zur Verfügung zu stellen. Dies ermöglicht es uns, die Datenbank-Anmeldeinformationen in einer separaten Datei zu speichern, die auf einem Server verschlüsselt und gesichert ist und für Nicht-Administratoren nicht zugänglich ist. Dies ermöglicht uns auch eine kurze Verknüpfung zum Erstellen einer Benutzeroberfläche und zur Einschränkung der Ausführung.

0
Joe Hayes

Sie können auch die Möglichkeit in Betracht ziehen, das Kennwort außerhalb des Skripts zu speichern und zur Laufzeit anzugeben

z.B. fred.py

import os
username = 'fred'
password = os.environ.get('PASSWORD', '')
print(username, password)

was läuft wie

$ PASSWORD=password123 python fred.py
fred password123

Zusätzliche Ebenen der "Sicherheit durch Verschleierung" können erreicht werden, indem base64 (wie oben vorgeschlagen) verwendet wird, weniger offensichtliche Namen im Code verwendet werden und das tatsächliche Passwort weiter vom Code entfernt wird.

Wenn sich der Code in einem Repository befindet, ist es oft nützlich, Geheimnisse außerhalb des Repositorys zu speichern , sodass man dies zu ~/.bashrc (oder zu einem Tresor oder einem Startskript) hinzufügen kann. )

export SURNAME=cGFzc3dvcmQxMjM=

und ändere fred.py auf

import os
import base64
name = 'fred'
surname = base64.b64decode(os.environ.get('SURNAME', '')).decode('utf-8')
print(name, surname)

dann erneut anmelden und

$ python fred.py
fred password123
0
jalanb