在 Python 脚本中隐藏密码(仅限不安全的混淆)

2025-03-13 09:04:00
admin
原创
97
摘要:问题描述:我有一个用于创建 ODBC 连接的 Python 脚本。ODBC 连接由连接字符串生成。在此连接字符串中,我必须包含此连接的用户名和密码。 有没有简单的方法可以隐藏文件中的密码(只是当我编辑文件时没有人可以读取密码)?解决方案 1:Base64 编码属于标准库,可以阻止肩窥者:>>>...

问题描述:

我有一个用于创建 ODBC 连接的 Python 脚本。ODBC 连接由连接字符串生成。在此连接字符串中,我必须包含此连接的用户名和密码。

有没有简单的方法可以隐藏文件中的密码(只是当我编辑文件时没有人可以读取密码)?


解决方案 1:

Base64 编码属于标准库,可以阻止肩窥者:

>>> import base64
>>>  print(base64.b64encode("password".encode("utf-8")))
cGFzc3dvcmQ=
>>> print(base64.b64decode("cGFzc3dvcmQ=").decode("utf-8"))
password

解决方案 2:

这是一个简单的方法:

  1. 创建一个 python 模块——我们称之为 peekaboo.py。

  2. 在 peekaboo.py 中,包含密码和任何需要该密码的代码

  3. 通过导入此模块(通过 python 命令行等)创建一个编译版本 - peekaboo.pyc。

  4. 现在,删除peekaboo.py。

  5. 现在您可以放心地仅依赖 peekaboo.pyc 来导入 peekaboo。由于 peekaboo.pyc 是字节编译的,因此普通用户无法读取。

这应该比 base64 解码更安全一些 - 尽管它容易受到 py_to_pyc 反编译器的攻击。

解决方案 3:

当您需要为远程登录指定密码时,Douglas F Shearer 的解决方案是 Unix 中普遍认可的解决方案。

您可以添加--password-from-file选项来指定路径并从文件中读取纯文本。

然后,该文件可以位于受操作系统保护的用户自己的区域中。它还允许不同的用户自动选择他们自己的文件。

对于脚本用户不允许知道的密码 - 您可以以提升的权限运行该脚本,并让该 root/admin 用户拥有密码文件。

解决方案 4:

如果您使用的是 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

解决方案 5:

如何从脚本外部的文件导入用户名和密码?这样,即使有人掌握了脚本,他们也不会自动获取密码。

解决方案 6:

base64 可以满足您的简单需求。无需导入任何内容:

>>> 'your string'.encode('base64')
'eW91ciBzdHJpbmc=
'
>>> _.decode('base64')
'your string'

解决方案 7:

假设用户名和密码不能由用户在运行时提供,那么最好的解决方案可能是创建一个单独的源文件,该文件仅包含导入到主代码中的用户名和密码的变量初始化。只有在凭据更改时才需要编辑此文件。否则,如果您只担心记忆力一般的肩窥者,那么 Base 64 编码可能是最简单的解决方案。ROT13 太容易手动解码,不区分大小写,并且在加密状态下保留了太多含义。在 Python 脚本之外对密码和用户 ID 进行编码。让脚本在运行时解码以供使用。

为脚本提供自动化任务的凭证始终是一个有风险的建议。您的脚本应该有自己的凭证,并且它使用的帐户除了必要的权限外,不应具有任何其他访问权限。至少密码应该很长并且是随机的。

解决方案 8:

我这样做的方法如下:

在 python shell 中:

>>> 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')

完成此操作后,您可以直接导入我的密码,也可以根据需要导入令牌和密码进行解密。

显然,这种方法存在一些缺点。如果有人同时拥有令牌和密钥(如果他们有脚本,他们就会这样做),他们可以轻松解密。但是它确实会混淆,如果你编译代码(使用 Nuitka 之类的东西),至少你的密码不会在十六进制编辑器中显示为纯文本。

解决方案 9:

对于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 如何处理字节(以及相应的字符串)的更多信息,请参阅官方文档。

解决方案 10:

这是一个很常见的问题。通常你能做的最好的事情是

A)创建某种凯撒密码函数来编码/解码(不是rot13)或

B) 首选方法是使用加密密钥,在您的程序可触及的范围内对密码进行编码/解码。您可以使用文件保护来保护对密钥的访问。

按照这种思路,如果您的应用作为服务/守护进程运行(如网络服务器),您可以将密钥放入受密码保护的密钥库中,并在服务启动时输入密码。这将需要管理员重新启动您的应用,但您将获得对配置密码的良好保护。

解决方案 11:

您的操作系统可能提供了安全加密数据的功能。例如,Windows 上有 DPAPI(数据保护 API)。为什么不在第一次运行时询问用户的凭据,然后在后续运行时将其加密保存起来呢?

解决方案 12:

这是我的代码片段。你基本上将函数导入或复制到你的代码中。如果加密文件不存在,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. 
So I dont keep asking you for your email and password everytime you run me, I will be saving an encrypted file at {}.
'.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 {}.
'.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()

解决方案 13:

将配置信息放在加密的配置文件中。使用密钥在代码中查询此信息。将此密钥放在每个环境的单独文件中,不要将其与代码一起存储。

解决方案 14:

更多自主开发的方法,而不是将身份验证/密码/用户名转换为加密的详细信息。FTPLIB只是一个例子。“ pass.csv ”是 csv 文件名

将密码保存在 CSV 中,如下所示:

用户名

用户密码

(无列标题)

读取 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])

解决方案 15:

知道坑吗?

https://pypi.python.org/pypi/pit(仅限 py2(版本 0.3))

https://github.com/yoshiori/pit(它将在 py3 上运行(当前版本 0.4))

测试.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/默认.yml:

section-name:
  password: my-password
  username: my-name

解决方案 16:

如果在 Windows 上运行,您可以考虑使用 win32crypt 库。它允许运行脚本的用户存储和检索受保护的数据(密钥、密码),因此密码永远不会以明文或模糊格式存储在您的代码中。我不确定其他平台是否有等效的实现,因此如果严格使用 win32crypt,您的代码将无法移植。

我相信该模块可以在这里获得:http://timgolden.me.uk/pywin32-docs/win32crypt.html

解决方案 17:

您还可以考虑将密码存储在脚本之外,并在运行时提供它的可能性

例如 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

解决方案 18:

为什么不使用一个简单的异或?

优点:

  • 看起来像二进制数据

  • 没有人可以在不知道密钥的情况下读取它(即使它只是一个字符)

我已经能够识别常用词的简单 b64 字符串以及 rot13。Xor 会让这一切变得更加困难。

解决方案 19:

网络上有几种用 Python 编写的 ROT13 实用程序 - 只需谷歌搜索即可。ROT13 离线编码字符串,将其复制到源中,在传输时解码。

但这种保护真的很弱...

解决方案 20:

这并不能准确回答您的问题,但与之相关。我本来想将其添加为评论,但被禁止。我一直在处理同样的问题,我们决定使用 Jenkins 将脚本公开给用户。这使我们能够将数据库凭据存储在单独的文件中,该文件在服务器上加密并受到保护,非管理员无法访问。它还为我们提供了创建 UI 和限制执行的捷径。

解决方案 21:

import base64
print(base64.b64encode("password".encode("utf-8")))
print(base64.b64decode(b'cGFzc3dvcmQ='.decode("utf-8")))
相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   4027  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   2755  
  本文介绍了以下10款项目管理软件工具:禅道项目管理软件、Freshdesk、ClickUp、nTask、Hubstaff、Plutio、Productive、Targa、Bonsai、Wrike。在当今快速变化的商业环境中,项目管理已成为企业成功的关键因素之一。然而,许多企业在项目管理过程中面临着诸多痛点,如任务分配不...
项目管理系统   86  
  本文介绍了以下10款项目管理软件工具:禅道项目管理软件、Monday、TeamGantt、Filestage、Chanty、Visor、Smartsheet、Productive、Quire、Planview。在当今快速变化的商业环境中,项目管理已成为企业成功的关键因素之一。然而,许多项目经理和团队在管理复杂项目时,常...
开源项目管理工具   99  
  本文介绍了以下10款项目管理软件工具:禅道项目管理软件、Smartsheet、GanttPRO、Backlog、Visor、ResourceGuru、Productive、Xebrio、Hive、Quire。在当今快节奏的商业环境中,项目管理已成为企业成功的关键因素之一。然而,许多企业在选择项目管理工具时常常面临困惑:...
项目管理系统   87  
热门文章
项目管理软件有哪些?
曾咪二维码

扫码咨询,免费领取项目管理大礼包!

云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用