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

时间:2008-10-01 14:37:17

标签: python security

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

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

21 个答案:

答案 0 :(得分:101)

Base64 encoding在标准库中,可以阻止肩膀冲浪者:

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

答案 1 :(得分:48)

当您需要为远程登录指定密码时,Douglas F Shearer是Unix中普遍认可的解决方案。
您可以添加 - password-from-file 选项来指定路径并从文件中读取明文。
然后,该文件可以位于受操作系统保护的用户自己的区域中。 它还允许不同的用户自动选择他们自己的文件。

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

答案 2 :(得分:41)

这是一个简单的方法:

  1. 创建一个python模块 - 让我们称之为peekaboo.py。
  2. 在peekaboo.py中,包括密码和需要该密码的任何代码
  3. 通过导入此模块(通过python命令行等)创建一个编译版本 - peekaboo.pyc。
  4. 现在,删除peekaboo.py。
  5. 你现在可以高兴地只依靠peekaboo.pyc导入躲猫猫。由于peekaboo.pyc是字节编译的,因此对于临时用户来说是不可读的。
  6. 这应该比base64解码更安全 - 尽管它容易受到py_to_pyc反编译器的攻击。<​​/ p>

答案 3 :(得分:25)

如果您正在使用Unix系统,请利用标准Python库中的netrc模块。它从单独的文本文件(.netrc)中读取密码,该文件的格式为here

这是一个小用法示例:

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

答案 4 :(得分:18)

假设用户在运行时无法提供用户名和密码的最佳解决方案,可能是一个单独的源文件,仅包含导入主代码的用户名和密码的变量初始化。凭据更改时,只需要编辑此文件。否则,如果您只担心具有平均记忆的肩膀冲浪者,基本64编码可能是最简单的解决方案。 ROT13太容易手动解码,不区分大小写并且在加密状态下保留太多含义。在python脚本之外编码您的密码和用户ID。他是否在运行时进行脚本解码以供使用。

为自动化任务提供脚本凭据始终是一个冒险的提议。您的脚本应该有自己的凭据,并且它使用的帐户应该没有其他所需的访问权限。至少密码应该很长而且是随机的。

答案 5 :(得分:16)

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

答案 6 :(得分:15)

base64是满足您简单需求的方法。无需导入任何内容:

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

答案 7 :(得分:4)

这是一个非常常见的问题。通常,您可以做的最好的是

A)创建某种ceasar密码函数来编码/解码(只是不是rot13) 要么 B)首选方法是使用加密密钥,在程序可及范围内对密码进行编码/解码。您可以使用文件保护来保护访问密钥。   如果您的应用程序作为服务/守护程序(如Web服务器)运行,那么您可以将密钥放入受密码保护的密钥库中,并将密码输入作为服务启动的一部分。管理员需要重新启动您的应用,但您将对配置密码有很好的保护。

答案 8 :(得分:2)

我执行此操作的方法如下:

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

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

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

答案 9 :(得分:2)

使用base64进行 python3 混淆处理的方式不同:

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如何处理字节(以及相应的字符串)的更多信息,请参见official documentation

答案 10 :(得分:2)

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

以CSV格式保存密码:

USER_NAME

USER_PASSWORD

(没有列标题)

读取CSV并将其保存到列表中。

使用List elelments作为身份验证详细信息。

完整代码。

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

答案 11 :(得分:2)

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

答案 12 :(得分:1)

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

答案 13 :(得分:1)

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

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

答案 14 :(得分:1)

这是我的摘录。您基本上是将函数导入或复制到代码中。如果不存在加密文件,则getCredentials将创建该加密文件并返回命令,并且updateCredential将更新。

jfrog rt c rt-server-1

答案 15 :(得分:0)

你知道坑吗?

https://pypi.python.org/pypi/pit(仅限py2(版本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

答案 16 :(得分:0)

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

答案 17 :(得分:0)

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

例如fred.py

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

可以像这样运行

$ PASSWORD=password123 python fred.py
fred password123

通过使用base64(如上面建议的那样),在代码中使用不太明显的名称,并进一步将实际密码与代码区分开,可以实现“通过隐秘的安全性”的额外层。

如果代码位于存储库中,通常对store secrets outside it很有用,因此可以将其添加到~/.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 :(得分:0)

为什么没有简单的xor?

优势:

  • 看起来像二进制数据
  • 任何人都无法在不知道键的情况下读取它(即使它是一个字符)

我到了可以识别普通单词和rot13的简单b64字符串的地步。 Xor将使工作变得更加困难。

答案 19 :(得分:0)

在Net上有几个用Python编写的ROT13实用程序 - 只是为他们谷歌。 ROT13离线编码字符串,将其复制到源中,在传输点解码。

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

答案 20 :(得分:-1)

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