ฉันต้องการจัดเก็บชื่อผู้ใช้และรหัสผ่านอย่างปลอดภัยใน Python มีตัวเลือกอะไรบ้าง? [ปิด]


95

ฉันกำลังเขียนสคริปต์ Python ขนาดเล็กซึ่งจะดึงข้อมูลจากบริการของบุคคลที่สามเป็นระยะโดยใช้คำสั่งผสมชื่อผู้ใช้และรหัสผ่าน ฉันไม่จำเป็นต้องสร้างสิ่งที่กันกระสุนได้ 100% (มีอยู่ 100% หรือไม่) แต่ฉันต้องการมีส่วนร่วมในการรักษาความปลอดภัยที่ดีอย่างน้อยที่สุดก็ต้องใช้เวลานานกว่าที่ใครบางคนจะทำลายมันได้

สคริปต์นี้จะไม่มี GUI และจะถูกเรียกใช้เป็นระยะ ๆcronดังนั้นการป้อนรหัสผ่านทุกครั้งที่เรียกใช้เพื่อถอดรหัสสิ่งต่างๆจะไม่ได้ผลจริง ๆ และฉันจะต้องเก็บชื่อผู้ใช้และรหัสผ่านไว้ในไฟล์ที่เข้ารหัสหรือเข้ารหัส ในฐานข้อมูล SQLite ซึ่งดีกว่าเพราะฉันจะใช้ SQLite อยู่แล้วและฉันอาจต้องแก้ไขรหัสผ่านในบางจุด นอกจากนี้ฉันอาจจะรวมโปรแกรมทั้งหมดไว้ใน EXE เนื่องจากเป็นเฉพาะสำหรับ Windows ในตอนนี้

ฉันจะจัดเก็บคำสั่งผสมชื่อผู้ใช้และรหัสผ่านอย่างปลอดภัยเพื่อใช้ในงานเป็นระยะ ๆ ได้cronอย่างไร?


ดูเพิ่มเติมที่ : stackoverflow.com/questions/157938
dreftymac

คำตอบ:


19

ผมขอแนะนำให้กลยุทธ์ที่คล้ายกับตัวแทน ssh หากคุณไม่สามารถใช้ ssh-agent ได้โดยตรงคุณสามารถใช้สิ่งนี้ได้เพื่อให้รหัสผ่านของคุณถูกเก็บไว้ใน RAM เท่านั้น งาน cron สามารถกำหนดค่าข้อมูลประจำตัวเพื่อรับรหัสผ่านจริงจากเอเจนต์ทุกครั้งที่รันใช้ครั้งเดียวและยกเลิกการอ้างอิงทันทีโดยใช้delคำสั่ง

ผู้ดูแลระบบยังคงต้องป้อนรหัสผ่านเพื่อเริ่ม ssh-agent ในเวลาบูตหรืออะไรก็ตาม แต่นี่เป็นการประนีประนอมที่สมเหตุสมผลที่จะหลีกเลี่ยงการเก็บรหัสผ่านข้อความธรรมดาไว้ที่ใดก็ได้บนดิสก์


2
+1 นั้นสมเหตุสมผลมาก ฉันสามารถสร้าง UI สำหรับมันได้ตลอดเวลาซึ่งโดยพื้นฐานแล้วจะขอรหัสผ่านจากผู้ใช้ในการบูตด้วยวิธีนี้จะไม่ถูกเก็บไว้ในดิสก์และปลอดภัยจากการสอดรู้สอดเห็น
Naftuli Kay

55

หลามพวงกุญแจห้องสมุดร่วมกับCryptProtectDataAPI บน Windows (พร้อมกับความเกี่ยวข้องของ API บน Mac และ Linux) ซึ่งจะเข้ารหัสข้อมูลที่มีสิทธิการเข้าสู่ระบบของผู้ใช้

ใช้งานง่าย:

import keyring

# the service is just a namespace for your app
service_id = 'IM_YOUR_APP!'

keyring.set_password(service_id, 'dustin', 'my secret password')
password = keyring.get_password(service_id, 'dustin') # retrieve password

การใช้งานหากคุณต้องการจัดเก็บชื่อผู้ใช้บนพวงกุญแจ:

import keyring

MAGIC_USERNAME_KEY = 'im_the_magic_username_key'

# the service is just a namespace for your app
service_id = 'IM_YOUR_APP!'  

username = 'dustin'

# save password
keyring.set_password(service_id, username, "password")

# optionally, abuse `set_password` to save username onto keyring
# we're just using some known magic string in the username field
keyring.set_password(service_id, MAGIC_USERNAME_KEY, username)

ในภายหลังเพื่อรับข้อมูลของคุณจากพวงกุญแจ

# again, abusing `get_password` to get the username.
# after all, the keyring is just a key-value store
username = keyring.get_password(service_id, MAGIC_USERNAME_KEY)
password = keyring.get_password(service_id, username)  

รายการจะถูกเข้ารหัสด้วยข้อมูลรับรองระบบปฏิบัติการของผู้ใช้ดังนั้นแอปพลิเคชันอื่น ๆ ที่ทำงานในบัญชีผู้ใช้ของคุณจะสามารถเข้าถึงรหัสผ่านได้

หากต้องการปิดบังช่องโหว่นั้นเล็กน้อยคุณสามารถเข้ารหัส / ทำให้รหัสผ่านสับสนได้ในบางลักษณะก่อนที่จะเก็บไว้ในพวงกุญแจ แน่นอนว่าใครก็ตามที่กำหนดเป้าหมายสคริปต์ของคุณจะสามารถดูแหล่งที่มาและค้นหาวิธียกเลิกการเข้ารหัส / ยกเลิกการปิดบังรหัสผ่าน แต่อย่างน้อยคุณก็ควรป้องกันไม่ให้แอปพลิเคชันบางตัวดูดรหัสผ่านทั้งหมดในห้องนิรภัยและรับรหัสผ่านของคุณด้วย .


ควรเก็บชื่อผู้ใช้อย่างไร? ไม่keyringสนับสนุนการเรียกทั้งชื่อผู้ใช้และรหัสผ่าน?
Stevoisiak

1
@DustinWyatt การใช้อย่างชาญฉลาดget_passwordสำหรับชื่อผู้ใช้ แม้ว่าฉันคิดว่าคุณควรเริ่มคำตอบด้วยตัวอย่างที่เรียบง่ายดั้งเดิมของ keyring.set_password()และkeyring.get_password()
Stevoisiak

keyringไม่ได้เป็นส่วนหนึ่งของไลบรารีมาตรฐาน python
Ciasto piekarz

@Ciastopiekarz คำตอบบางอย่างทำให้คุณเชื่อว่ามันเป็นส่วนหนึ่งของไลบรารีมาตรฐานหรือไม่?
Dustin Wyatt

ไม่keyringปลอดภัยขัดรหัสผ่านจากบันทึกและ afterwords หน่วยความจำ?
Kebman

26

หลังจากดูคำตอบของคำถามนี้และคำถามที่เกี่ยวข้องแล้วฉันได้รวบรวมโค้ดบางส่วนโดยใช้วิธีการที่แนะนำสองสามวิธีในการเข้ารหัสและปิดบังข้อมูลลับ รหัสนี้มีไว้สำหรับเมื่อสคริปต์ต้องทำงานโดยไม่มีการแทรกแซงของผู้ใช้ (หากผู้ใช้เริ่มต้นด้วยตนเองควรใส่รหัสผ่านและเก็บไว้ในหน่วยความจำตามคำตอบของคำถามนี้เท่านั้น) วิธีนี้ไม่ปลอดภัยมาก โดยพื้นฐานแล้วสคริปต์สามารถเข้าถึงข้อมูลลับดังนั้นทุกคนที่มีสิทธิ์เข้าถึงระบบทั้งหมดจะมีสคริปต์และไฟล์ที่เกี่ยวข้องและสามารถเข้าถึงได้ สิ่งนี้ทำให้ id ปิดบังข้อมูลจากการตรวจสอบแบบไม่เป็นทางการและทำให้ไฟล์ข้อมูลปลอดภัยหากมีการตรวจสอบทีละรายการหรือรวมกันโดยไม่มีสคริปต์

แรงจูงใจของฉันสำหรับโครงการนี้คือโครงการที่สำรวจบัญชีธนาคารบางบัญชีของฉันเพื่อตรวจสอบธุรกรรม - ฉันต้องการให้มันทำงานในพื้นหลังโดยที่ฉันไม่ต้องป้อนรหัสผ่านซ้ำทุกๆนาทีหรือสองนาที

เพียงวางรหัสนี้ที่ด้านบนของสคริปต์ของคุณเปลี่ยน saltSeed จากนั้นใช้ store () ดึงข้อมูล () และต้องการ () ในโค้ดของคุณตามต้องการ:

from getpass import getpass
from pbkdf2 import PBKDF2
from Crypto.Cipher import AES
import os
import base64
import pickle


### Settings ###

saltSeed = 'mkhgts465wef4fwtdd' # MAKE THIS YOUR OWN RANDOM STRING

PASSPHRASE_FILE = './secret.p'
SECRETSDB_FILE = './secrets'
PASSPHRASE_SIZE = 64 # 512-bit passphrase
KEY_SIZE = 32 # 256-bit key
BLOCK_SIZE = 16  # 16-bit blocks
IV_SIZE = 16 # 128-bits to initialise
SALT_SIZE = 8 # 64-bits of salt


### System Functions ###

def getSaltForKey(key):
    return PBKDF2(key, saltSeed).read(SALT_SIZE) # Salt is generated as the hash of the key with it's own salt acting like a seed value

def encrypt(plaintext, salt):
    ''' Pad plaintext, then encrypt it with a new, randomly initialised cipher. Will not preserve trailing whitespace in plaintext!'''

    # Initialise Cipher Randomly
    initVector = os.urandom(IV_SIZE)

    # Prepare cipher key:
    key = PBKDF2(passphrase, salt).read(KEY_SIZE)

    cipher = AES.new(key, AES.MODE_CBC, initVector) # Create cipher

    return initVector + cipher.encrypt(plaintext + ' '*(BLOCK_SIZE - (len(plaintext) % BLOCK_SIZE))) # Pad and encrypt

def decrypt(ciphertext, salt):
    ''' Reconstruct the cipher object and decrypt. Will not preserve trailing whitespace in the retrieved value!'''

    # Prepare cipher key:
    key = PBKDF2(passphrase, salt).read(KEY_SIZE)

    # Extract IV:
    initVector = ciphertext[:IV_SIZE]
    ciphertext = ciphertext[IV_SIZE:]

    cipher = AES.new(key, AES.MODE_CBC, initVector) # Reconstruct cipher (IV isn't needed for edecryption so is set to zeros)

    return cipher.decrypt(ciphertext).rstrip(' ') # Decrypt and depad


### User Functions ###

def store(key, value):
    ''' Sore key-value pair safely and save to disk.'''
    global db

    db[key] = encrypt(value, getSaltForKey(key))
    with open(SECRETSDB_FILE, 'w') as f:
        pickle.dump(db, f)

def retrieve(key):
    ''' Fetch key-value pair.'''
    return decrypt(db[key], getSaltForKey(key))

def require(key):
    ''' Test if key is stored, if not, prompt the user for it while hiding their input from shoulder-surfers.'''
    if not key in db: store(key, getpass('Please enter a value for "%s":' % key))


### Setup ###

# Aquire passphrase:
try:
    with open(PASSPHRASE_FILE) as f:
        passphrase = f.read()
    if len(passphrase) == 0: raise IOError
except IOError:
    with open(PASSPHRASE_FILE, 'w') as f:
        passphrase = os.urandom(PASSPHRASE_SIZE) # Random passphrase
        f.write(base64.b64encode(passphrase))

        try: os.remove(SECRETSDB_FILE) # If the passphrase has to be regenerated, then the old secrets file is irretrievable and should be removed
        except: pass
else:
    passphrase = base64.b64decode(passphrase) # Decode if loaded from already extant file

# Load or create secrets database:
try:
    with open(SECRETSDB_FILE) as f:
        db = pickle.load(f)
    if db == {}: raise IOError
except (IOError, EOFError):
    db = {}
    with open(SECRETSDB_FILE, 'w') as f:
        pickle.dump(db, f)

### Test (put your code here) ###
require('id')
require('password1')
require('password2')
print
print 'Stored Data:'
for key in db:
    print key, retrieve(key) # decode values on demand to avoid exposing the whole database in memory
    # DO STUFF

ความปลอดภัยของวิธีนี้จะได้รับการปรับปรุงอย่างมีนัยสำคัญหากมีการตั้งค่าการอนุญาตของระบบปฏิบัติการในไฟล์ลับเพื่อให้สคริปต์อ่านได้เท่านั้นและหากตัวสคริปต์นั้นถูกคอมไพล์และทำเครื่องหมายเป็นปฏิบัติการเท่านั้น (ไม่สามารถอ่านได้) บางอย่างอาจเป็นแบบอัตโนมัติ แต่ฉันไม่ได้ใส่ใจ อาจต้องมีการตั้งค่าผู้ใช้สำหรับสคริปต์และเรียกใช้สคริปต์ในฐานะผู้ใช้นั้น (และตั้งค่าความเป็นเจ้าของไฟล์ของสคริปต์ให้กับผู้ใช้รายนั้น)

ฉันชอบคำแนะนำคำติชมหรือจุดโหว่อื่น ๆ ที่ทุกคนสามารถนึกถึง ฉันค่อนข้างใหม่ในการเขียนโค้ด crypto ดังนั้นสิ่งที่ฉันทำไปจะดีขึ้นอย่างแน่นอน


26

มีตัวเลือกสองสามอย่างสำหรับการจัดเก็บรหัสผ่านและความลับอื่น ๆ ที่โปรแกรม Python จำเป็นต้องใช้โดยเฉพาะโปรแกรมที่ต้องทำงานในพื้นหลังซึ่งไม่สามารถขอให้ผู้ใช้พิมพ์รหัสผ่านได้

ปัญหาที่ควรหลีกเลี่ยง:

  1. การตรวจสอบรหัสผ่านในการควบคุมแหล่งที่มาซึ่งนักพัฒนารายอื่นหรือแม้แต่สาธารณชนสามารถดูได้
  2. ผู้ใช้รายอื่นบนเซิร์ฟเวอร์เดียวกันอ่านรหัสผ่านจากไฟล์คอนฟิกูเรชันหรือซอร์สโค้ด
  3. การมีรหัสผ่านในไฟล์ต้นฉบับที่ผู้อื่นสามารถมองเห็นได้บนไหล่ของคุณในขณะที่คุณกำลังแก้ไข

ตัวเลือกที่ 1: SSH

นี่ไม่ใช่ทางเลือกเสมอไป แต่น่าจะดีที่สุด คีย์ส่วนตัวของคุณจะไม่ถูกส่งผ่านเครือข่าย SSH เพียงแค่เรียกใช้การคำนวณทางคณิตศาสตร์เพื่อพิสูจน์ว่าคุณมีคีย์ที่ถูกต้อง

เพื่อให้ใช้งานได้คุณต้องมีสิ่งต่อไปนี้:

  • ฐานข้อมูลหรือสิ่งที่คุณกำลังเข้าถึงจำเป็นต้องเข้าถึงได้โดย SSH ลองค้นหา "SSH" บวกกับบริการที่คุณกำลังเข้าถึง ยกตัวอย่างเช่น"SSH PostgreSQL" หากนี่ไม่ใช่คุณสมบัติในฐานข้อมูลของคุณให้ไปยังตัวเลือกถัดไป
  • สร้างบัญชีเพื่อเรียกใช้บริการที่จะทำให้การโทรไปยังฐานข้อมูลและสร้างคีย์ SSH
  • เพิ่มคีย์สาธารณะลงในบริการที่คุณกำลังจะโทรหรือสร้างบัญชีภายในเครื่องบนเซิร์ฟเวอร์นั้นและติดตั้งคีย์สาธารณะที่นั่น

ตัวเลือกที่ 2: ตัวแปรสภาพแวดล้อม

อันนี้ง่ายที่สุดดังนั้นจึงอาจเป็นจุดเริ่มต้นที่ดี มันอธิบายได้ดีในสิบสองปัจจัย App แนวคิดพื้นฐานคือซอร์สโค้ดของคุณเพียงแค่ดึงรหัสผ่านหรือความลับอื่น ๆ จากตัวแปรสภาพแวดล้อมจากนั้นคุณกำหนดค่าตัวแปรสภาพแวดล้อมเหล่านั้นในแต่ละระบบที่คุณรันโปรแกรม นอกจากนี้ยังอาจเป็นสิ่งที่ดีหากคุณใช้ค่าเริ่มต้นที่จะใช้ได้กับนักพัฒนาส่วนใหญ่ คุณต้องสร้างสมดุลกับการทำให้ซอฟต์แวร์ของคุณ "ปลอดภัยโดยค่าเริ่มต้น"

นี่คือตัวอย่างที่ดึงเซิร์ฟเวอร์ชื่อผู้ใช้และรหัสผ่านจากตัวแปรสภาพแวดล้อม

import os

server = os.getenv('MY_APP_DB_SERVER', 'localhost')
user = os.getenv('MY_APP_DB_USER', 'myapp')
password = os.getenv('MY_APP_DB_PASSWORD', '')

db_connect(server, user, password)

ค้นหาวิธีตั้งค่าตัวแปรสภาพแวดล้อมในระบบปฏิบัติการของคุณและพิจารณาเรียกใช้บริการภายใต้บัญชีของตนเอง ด้วยวิธีนี้คุณจะไม่มีข้อมูลที่ละเอียดอ่อนในตัวแปรสภาพแวดล้อมเมื่อคุณเรียกใช้โปรแกรมในบัญชีของคุณเอง เมื่อคุณตั้งค่าตัวแปรสภาพแวดล้อมเหล่านั้นโปรดระมัดระวังเป็นพิเศษไม่ให้ผู้ใช้รายอื่นอ่านตัวแปรเหล่านั้น ตรวจสอบสิทธิ์ของไฟล์ตัวอย่างเช่น แน่นอนว่าผู้ใช้ที่ได้รับอนุญาตจากรูทจะสามารถอ่านได้ แต่ก็ไม่สามารถช่วยได้ หากคุณใช้ systemd โปรดดูที่หน่วยบริการและระมัดระวังในการใช้EnvironmentFileแทนEnvironmentความลับใด ๆ ค่าสามารถดูได้โดยผู้ใช้ที่มีEnvironmentsystemctl show

ตัวเลือกที่ 3: ไฟล์การกำหนดค่า

สิ่งนี้คล้ายกับตัวแปรสภาพแวดล้อมมาก แต่คุณอ่านความลับจากไฟล์ข้อความ ฉันยังพบว่าตัวแปรสภาพแวดล้อมมีความยืดหยุ่นมากกว่าสำหรับสิ่งต่างๆเช่นเครื่องมือการปรับใช้และเซิร์ฟเวอร์การรวมแบบต่อเนื่อง ถ้าคุณตัดสินใจที่จะใช้การตั้งค่าไฟล์, Python สนับสนุนรูปแบบต่าง ๆ ในห้องสมุดมาตรฐานเช่นJSON , INI , NetrcและXML นอกจากนี้คุณยังสามารถหาแพคเกจภายนอกเช่นPyYAMLและTOML โดยส่วนตัวแล้วฉันพบว่า JSON และ YAML ใช้ง่ายที่สุดและ YAML อนุญาตให้แสดงความคิดเห็น

สามสิ่งที่ควรพิจารณากับไฟล์กำหนดค่า:

  1. ไฟล์อยู่ที่ไหน อาจเป็นตำแหน่งเริ่มต้นเช่น~/.my_appและตัวเลือกบรรทัดคำสั่งเพื่อใช้ตำแหน่งอื่น
  2. ตรวจสอบให้แน่ใจว่าผู้ใช้รายอื่นไม่สามารถอ่านไฟล์ได้
  3. แน่นอนอย่าผูกมัดไฟล์คอนฟิกูเรชันกับซอร์สโค้ด คุณอาจต้องการกำหนดเทมเพลตที่ผู้ใช้สามารถคัดลอกไปยังโฮมไดเร็กทอรีของตนได้

ตัวเลือกที่ 4: โมดูล Python

บางโครงการก็ใส่ความลับลงในโมดูล Python

# settings.py
db_server = 'dbhost1'
db_user = 'my_app'
db_password = 'correcthorsebatterystaple'

จากนั้นนำเข้าโมดูลนั้นเพื่อรับค่า

# my_app.py
from settings import db_server, db_user, db_password

db_connect(db_server, db_user, db_password)

หนึ่งในโครงการที่ใช้เทคนิคนี้Django เห็นได้ชัดว่าคุณไม่ควรผูกมัดsettings.pyกับการควบคุมแหล่งที่มาแม้ว่าคุณอาจต้องการยอมรับไฟล์ที่เรียกsettings_template.pyว่าผู้ใช้สามารถคัดลอกและแก้ไขได้

ฉันพบปัญหาเล็กน้อยเกี่ยวกับเทคนิคนี้:

  1. นักพัฒนาอาจส่งไฟล์ไปยังคอนโทรลซอร์สโดยไม่ได้ตั้งใจ การเพิ่มเพื่อ.gitignoreลดความเสี่ยงนั้น
  2. รหัสบางส่วนของคุณไม่อยู่ภายใต้การควบคุมแหล่งที่มา หากคุณมีวินัยและใส่เฉพาะสตริงและตัวเลขที่นี่ก็จะไม่มีปัญหา หากคุณเริ่มเขียนคลาสตัวกรองการบันทึกที่นี่หยุด!

หากโครงการของคุณใช้เทคนิคนี้อยู่แล้วคุณสามารถเปลี่ยนไปใช้ตัวแปรสภาพแวดล้อมได้อย่างง่ายดาย เพียงแค่ย้ายค่าการตั้งค่าทั้งหมดไปยังตัวแปรสภาพแวดล้อมและเปลี่ยนโมดูล Python เพื่ออ่านจากตัวแปรสภาพแวดล้อมเหล่านั้น


สวัสดี. หากโครงการของคุณใช้เทคนิคนี้อยู่แล้วคุณสามารถเปลี่ยนไปใช้ตัวแปรสภาพแวดล้อมได้อย่างง่ายดาย ฉันรู้วิธีตั้งค่าตัวแปรสภาพแวดล้อมใน Windows 10 ด้วยตนเอง แต่สามารถเข้าถึงได้จากรหัส python ของฉันโดยใช้os.getenv(). เราควรทำอย่างไรหากมีการแชร์โค้ด หากนักพัฒนาซอฟต์แวร์รายอื่นดาวน์โหลดโค้ดเขา / เธอจะแน่ใจได้อย่างไรว่าได้ตั้งค่าตัวแปรสภาพแวดล้อมไว้แล้ว
a_sid

ฉันพยายามส่งค่าเริ่มต้นที่สมเหตุสมผลไปที่os.getenv()@a_sid ดังนั้นอย่างน้อยรหัสจะทำงานสำหรับผู้ใช้ที่ไม่ได้ตั้งค่าตัวแปรสภาพแวดล้อม Noneถ้าไม่มีค่าเริ่มต้นที่ดีเพิ่มข้อผิดพลาดที่ชัดเจนเมื่อคุณได้รับ นอกเหนือจากนั้นใส่ความคิดเห็นที่ชัดเจนในไฟล์การตั้งค่า หากฉันเข้าใจผิดฉันขอแนะนำให้คุณถามคำถามแยกต่างหาก
Don Kirkby

8

ไม่มีจุดที่ต้องพยายามเข้ารหัสรหัสผ่านมากนัก: บุคคลที่คุณพยายามซ่อนไม่ให้มีสคริปต์ Python ซึ่งจะมีรหัสในการถอดรหัส วิธีที่เร็วที่สุดในการรับรหัสผ่านคือการเพิ่มคำสั่งพิมพ์ลงในสคริปต์ Python ก่อนที่จะใช้รหัสผ่านกับบริการของบุคคลที่สาม

ดังนั้นให้เก็บรหัสผ่านเป็นสตริงในสคริปต์และ base64 เข้ารหัสเพื่อให้อ่านไฟล์ไม่เพียงพอจากนั้นเรียกมันว่าวัน


ฉันจะต้องแก้ไขชื่อผู้ใช้และรหัสผ่านเป็นระยะและฉันจะรวมข้อมูลทั้งหมดไว้ใน EXE สำหรับ Windoze ฉันได้แก้ไขโพสต์เพื่อแสดงถึงสิ่งนี้ ฉันควรใช้ base64 ทุกที่ที่เก็บไว้หรือไม่?
Naftuli Kay

ฉันยอมรับว่าการ "เข้ารหัส" รหัสผ่านไม่ได้ช่วยได้เนื่องจากต้องได้รับรหัสผ่านข้อความธรรมดาในรูปแบบอัตโนมัติดังนั้นจึงต้องได้รับจากสิ่งที่จัดเก็บ แต่มีแนวทางที่เป็นไปได้
wberry

คิดว่าฉันจำชื่อคุณได้แล้วคุณอยู่ในกลุ่มผู้เริ่มต้นและผู้เชี่ยวชาญใน TalkPython ในฐานะผู้เริ่มต้นข้อความของคุณโดนใจฉันจริงๆขอบคุณ!
Manakin

7

ฉันคิดว่าสิ่งที่ดีที่สุดที่คุณทำได้คือปกป้องไฟล์สคริปต์และระบบที่กำลังทำงานอยู่

โดยทั่วไปให้ทำดังต่อไปนี้:

  • ใช้สิทธิ์ระบบไฟล์ (chmod 400)
  • รหัสผ่านที่คาดเดายากสำหรับบัญชีของเจ้าของในระบบ
  • ลดความสามารถในการบุกรุกระบบ (ไฟร์วอลล์ปิดใช้งานบริการที่ไม่จำเป็น ฯลฯ )
  • ลบสิทธิ์การดูแลระบบ / root / sudo สำหรับผู้ที่ไม่ต้องการ

น่าเสียดายที่มันเป็น Windows ฉันจะรวมมันไว้ใน EXE และฉันจะต้องเปลี่ยนรหัสผ่านบ่อยๆดังนั้นการเข้ารหัสอย่างหนักจึงไม่ใช่ตัวเลือก
Naftuli Kay

1
Windows ยังคงมีสิทธิ์ระบบไฟล์ จัดเก็บรหัสผ่านในไฟล์ภายนอกและลบการเข้าถึงของทุกคนยกเว้นของคุณเอง คุณอาจต้องลบสิทธิ์ระดับผู้ดูแลระบบด้วย
Corey D

ใช่การใช้สิทธิ์เป็นตัวเลือกความปลอดภัยที่เชื่อถือได้เพียงตัวเดียวที่นี่ เห็นได้ชัดว่าผู้ดูแลระบบทุกคนจะยังคงสามารถเข้าถึงข้อมูลได้ (อย่างน้อยก็บน windows / การแจกแจงลินุกซ์ตามปกติ) แต่นั่นเป็นการต่อสู้ที่แพ้ไปแล้ว
Voo

มันเป็นความจริง. เมื่อการถอดรหัสรหัสผ่านเป็นแบบอัตโนมัติก็จะดีพอ ๆ กับการมีรหัสผ่านแบบข้อความธรรมดา ความปลอดภัยที่แท้จริงคือการล็อกบัญชีผู้ใช้ที่มีการเข้าถึง สิ่งที่ดีที่สุดที่สามารถทำได้คือให้สิทธิ์แบบอ่านอย่างเดียวเฉพาะบัญชีผู้ใช้นั้น อาจสร้างผู้ใช้พิเศษโดยเฉพาะและเฉพาะสำหรับบริการนั้น ๆ
Sepero

1

ระบบปฏิบัติการมักจะรองรับการรักษาความปลอดภัยข้อมูลสำหรับผู้ใช้ ในกรณีของ windows ดูเหมือนว่าเป็นhttp://msdn.microsoft.com/en-us/library/aa380261.aspx

คุณสามารถเรียก win32 apis จาก python โดยใช้http://vermeulen.ca/python-win32api.html

เท่าที่ฉันเข้าใจนี่จะจัดเก็บข้อมูลเพื่อให้สามารถเข้าถึงได้จากบัญชีที่ใช้จัดเก็บเท่านั้น หากคุณต้องการแก้ไขข้อมูลคุณสามารถทำได้โดยการเขียนโค้ดเพื่อแยกเปลี่ยนและบันทึกค่า


นี่ดูเหมือนเป็นทางเลือกที่ดีที่สุดสำหรับฉัน แต่ฉันรู้สึกว่าคำตอบนี้ไม่สมบูรณ์เกินกว่าที่จะยอมรับได้เนื่องจากไม่มีตัวอย่างที่แท้จริง
ArtOfWarfare

1
มีตัวอย่างบางส่วนสำหรับการใช้ฟังก์ชันเหล่านี้ใน Python ที่นี่: stackoverflow.com/questions/463832/using-dpapi-with-python
ArtOfWarfare

1

ฉันใช้การเข้ารหัสเนื่องจากฉันมีปัญหาในการติดตั้ง (รวบรวม) ไลบรารีที่กล่าวถึงทั่วไปในระบบของฉัน (Win7 x64, Python 3.5)

from cryptography.fernet import Fernet
key = Fernet.generate_key()
cipher_suite = Fernet(key)
cipher_text = cipher_suite.encrypt(b"password = scarybunny")
plain_text = cipher_suite.decrypt(cipher_text)

สคริปต์ของฉันกำลังทำงานในระบบ / ห้องที่ปลอดภัย ฉันเข้ารหัสข้อมูลรับรองด้วย "สคริปต์เข้ารหัส" ไปยังไฟล์กำหนดค่า แล้วถอดรหัสเมื่อฉันต้องการใช้ "สคริปต์ตัวเข้ารหัส" ไม่ได้อยู่ในระบบจริงมีเพียงไฟล์กำหนดค่าที่เข้ารหัสเท่านั้น ผู้ที่วิเคราะห์รหัสสามารถทำลายการเข้ารหัสได้อย่างง่ายดายโดยการวิเคราะห์รหัส แต่คุณยังสามารถรวบรวมเป็น EXE ได้หากจำเป็น

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.