Python密码保护
Posted
技术标签:
【中文标题】Python密码保护【英文标题】:Python Password Protection 【发布时间】:2013-09-05 08:38:26 【问题描述】:我是初学者,所以如果这个问题听起来很愚蠢,请多多包涵。
我想知道,当我们在python中编写用于用户名/密码检查的代码时,如果它没有编译为exeie script state
,人们不会轻易打开文件并删除正在执行密码检查的代码药水?
我假设整个程序完全是用python
编写的,而不是C
或C++
。
即使我使用像py2exe
这样的程序,它也可以很容易地反编译回源代码。那么,这是否意味着进行密码检查是没有用的?
专业程序员如何应对这种情况?
【问题讨论】:
你能举个例子说明你什么时候可以纯粹在 Python 程序中进行密码保护吗?通常输入密码是为了访问一些外部资源。 密码保护是指身份验证和授权,这意味着程序可以由“用户”运行或强制执行软件许可证,您希望用户购买许可证和程序检查。我认为许可证执行就像你在 python 中特别指出的那样,与 Java 相比。 @Daniel 我是初学者,所以我不太确定。目前我拥有的是一个程序,它接受用户输入并将数据存储在 sqlite 数据库中。我有一个使用哈希库的简单密码检查 【参考方案1】:编辑:您修改后的问题清楚地表明,您担心有人编辑代码以绕过密码检查。是的,这很有可能。您可以以 .pyc 形式交付代码,但这并不一定会阻止某人反编译和更改它。不幸的是,Python 并非旨在防止代码更改。您能做的最好的事情是使用安全服务器执行某种身份验证事务,这样无论有人如何更改代码,他们都无法绕过该步骤。根据您的具体应用,这可能有点过头了。
如何管理密码身份验证问题是一个棘手的安全问题,人们花费了整个职业生涯。但是,这里有一些关于它的信息,假设您正在尝试从头开始滚动自己的密码身份验证:
即使是临时密码保护,作为一般规则,用户密码也不会以明文形式存储。相反,通常使用可靠的单向哈希函数来创建与密码不相似的位模式。输入密码时,应用相同的散列函数并比较位模式。如果它们相同,则密码输入正确的可能性很高。
什么构成“可靠”的哈希函数是很棘手的。有几个是常用的,一些常见的散列函数容易受到已知漏洞的影响。
Noelkd 提供了一些代码来演示这种方法,尽管他的代码使用的 MD5(我相信)已经受到了一定程度的损害,因此有更好的选择。本文还提供了一些代码来做类似的事情:
Authentication of Users and Passwords in Python
如果您关心的是存储必须以明文形式传递给 SQLite 数据库的实际密码,那就是另一个问题了。大多数时候,我看到此类密码以明文形式存储在脚本或配置文件中,并且应用程序的结构使得泄露该密码的风险不大。
【讨论】:
是的,我不想看到我为生产发布的代码,但为了显示哈希密码检查,我觉得它可以达到目的。您的帖子有一些值得考虑的要点。 您的代码就是一个很好的例子!只是想提供一个答案,明确说明尝试使用本地脚本通过密码提供绝对安全可能会使 OP 陷入非常深的漏洞。 各方面都不错,从他的 cmets 来看,+1 OP 对我的剧本印象不深。 @Noelked 别搞错了。对不起,如果我听起来很粗鲁。你的代码很棒。只是密码保护的概念对于像我这样的初学者来说太混乱了。 我做服务器端身份验证,在虚拟机上的软件上,它在主机上有一个许可服务器。客人与主机 licserver 握手并将硬件信息发送到云另一个服务器可以继续,但是即使这也可以绕过。唯一可行的方法是在云端和本地机器中进行的计算或操作显示输出。这本质上是一个网页应用程序...【参考方案2】:如果您在用户的机器上进行检查,他们可以按照自己喜欢的方式编辑代码,几乎不管您做什么。如果您需要这样的安全性,那么代码应该运行在无法访问的地方,例如服务器。 “不要信任客户端”是重要的计算机安全原则。
我认为您要做的是制作一个服务器脚本,该脚本只能通过客户端程序提供的密码访问。该服务器程序的功能与其他答案中给出的示例代码非常相似:创建新客户端时,它们会向服务器发送明文密码,服务器对其进行单向加密并存储它。然后,当客户想要使用作为程序主体的代码时,他们会发送一个密码。服务器将其通过单向加密,并查看它是否与任何存储的散列密码匹配。如果是,则执行程序主体中的代码,并将结果返回给用户。
在相关主题上,其他答案建议使用md5
算法。然而,这不是最安全的算法 - 虽然对于许多用途来说足够安全,但标准库中的 hashlib
模块提供了其他更安全的算法,没有理由不使用这些算法。
【讨论】:
【参考方案3】:您可以检查用户输入内容的哈希值与密码的哈希值,以检查用户输入的密码是否正确,我做了一个非常简单的示例来说明这一点:
""" Python Password Check """
import hashlib
import sys
password = "2034f6e32958647fdff75d265b455ebf"
def main():
# Code goes here
print "Doing some stuff"
sys.exit(0)
while True:
input = raw_input("Enter password: ")
if hashlib.md5(input).hexdigest() == password:
print "welcome to the program"
main()
else:
print "Wrong Password"
在示例中,散列密码为"secretpassword"
,其散列为"2034f6e32958647fdff75d265b455ebf"
,因此即使源代码被反编译,您仍然只能看到密码的散列而不是密码的计划文本。
为了对 2016 年进行一些更新,目前如果您在 python 中使用散列密码,您应该查看以下三个库之一:
passlib
>>> # import the hash algorithm
>>> from passlib.hash import sha256_crypt
>>> # generate new salt, and hash a password
>>> hash = sha256_crypt.encrypt("toomanysecrets")
>>> hash
'$5$rounds=80000$zvpXD3gCkrt7tw.1$QqeTSolNHEfgryc5oMgiq1o8qCEAcmye3FoMSuvgToC'
>>> # verifying the password
>>> sha256_crypt.verify("toomanysecrets", hash)
True
>>> sha256_crypt.verify("joshua", hash)
False
示例取自here
bcrypt
import bcrypt
password = b"super secret password"
# Hash a password for the first time, with a certain number of rounds
hashed = bcrypt.hashpw(password, bcrypt.gensalt(14))
# Check that a unhashed password matches one that has previously been
# hashed
if bcrypt.hashpw(password, hashed) == hashed:
print("It Matches!")
else:
print("It Does not Match :(")
django-scrypt
【讨论】:
他们会绕过你的保护。 您可以绕过大多数保护。 感谢您指向 hashlib。使用 hashlib.pbkdf2_hmac(hash_name, password, salt, iterations, dklen=None) @GUIJunkie 已经用适合 2016 年的库更新了问题【参考方案4】:在服务器上,只有服务器管理员才有权更改代码。因此,要更改代码,您必须具有管理员访问权限,如果您这样做了,那么您无论如何都可以访问所有内容。 :-)
客户端程序也是如此。如果唯一的安全是密码检查,你不需要绕过密码检查,你可以直接读取数据文件。
在这两种情况下,为了防止有权访问文件的人读取这些文件,仅靠密码检查是不够的。您必须加密数据。
【讨论】:
【参考方案5】:现在让我们从基础开始,好吗?在进行登录凭证密码加密时,我们应该始终进行单向加密。一种加密方式意味着,一旦加密,您就无法解密文本。有一种称为md5
的加密,它只是一种加密方式。
在 Python 中已经有一个可用的库,名为 hashlib
。
来自 python 文档:
>>> import hashlib
>>> m = hashlib.md5()
>>> m.update("Nobody inspects")
>>> m.update(" the spammish repetition")
>>> m.digest()
'\xbbd\x9c\x83\xdd\x1e\xa5\xc9\xd9\xde\xc9\xa1\x8d\xf0\xff\xe9'
>>> m.digest_size
16
>>> m.block_size
64
更多信息:http://docs.python.org/2/library/hashlib.html?highlight=hashlib#hashlib
【讨论】:
据我了解,md5 加密已被破解。 blog.codinghorror.com/speed-hashing【参考方案6】:要保护存储在客户端计算机上的数据,您必须对其进行加密。期间。
如果您信任授权用户,则可以使用基于密码的加密密钥(Stack Exchange 上的许多其他答案都解决了这个问题),并希望他足够聪明以保护他的计算机免受恶意软件的侵害。
如果您不信任授权用户(又名 DRM),那您就完全不走运了 - 找到另一个项目。;-)
【讨论】:
【参考方案7】:一种方法是以任何算法的散列形式存储密码,并检查给定密码的散列是否等于存储的密码散列。
第二种方法可能是获取像“cat”这样的密码并将它们转换为ascii,然后将它们相加并存储总和。然后您可以将给定密码的 ascii 总和与您存储的比较。
或者你可以将它们结合起来!也许还散列 ascii 总和并比较给定密码的 ascii sun 散列。
这是我至少知道的三种方式。并且您可以在 python 中使用 chr 或 ord 默认函数来反复转换为 ascii。并且可以使用 hashlib 来散列。
【讨论】:
【参考方案8】:过去几天我一直在完善它并通过密码破解程序运行它,它似乎保持得相当强大。
这是我的代码供您查看:
import time
import os
import random
import string
passwordScore = 0
def optionOne():
global passwordScore
#Code for checking a password
os.system('cls')
print('Option One has been selected')
password = input('Please type in your password here: ')
#Password check begins
if (len(password) > 7) and (password.isspace() == False):
#Check for capitalisation
for p in password:
if p.isupper() == True:
passwordScore += 1
else:
pass
passwordScore += 2
for s in string.punctuation:
#Beginning test for special letters
for p in password:
if s == p:
passwordScore += 1
else:
pass
else:
pass
# Returning results to the user
if passwordScore >= 5:
print('Your password is safe enough to use')
time.sleep(2)
elif passwordScore == 3:
print('We believe your password could be safer')
time.sleep(2)
else:
print('Your password is not safe enough to use')
print('using this password may place your data at risk')
time.sleep(2)
def optionTwo():
#Code for creating a password at random
print('Option Two has been selected')
chars = string.ascii_uppercase + string.ascii_lowercase + string.digits + string.punctuation
size = random.randint(8, 12)
newPassword = ''.join(random.choice(chars) for x in range(size))
print(newPassword)
def start():
print('Option 1: Check my passsword')
print('Option 2: Create a password')
option = input('Please chose your option here [ENTER]: ')
if option == '1':
#Option 1 has been selected
return optionOne()
elif option == '2':
#Option 2 has been selected
return optionTwo()
else:
#An error has occured
print('You have not selected a valid option')
time.sleep(1)
os.system('cls')
return start()
for i in range(1):
start()
只要您根据自己的需要进行调整,这几乎可以完成所有工作!
【讨论】:
根据 NIST(美国国家标准与技术研究院)Digital Identity Guidelines 编号。" 要求最少 8 个字符,最多 >64 个字符,无截断或 6 个随机数字 使用字典来禁止常见的针对 10M 泄露密码的字典列表的密码 允许所有打印字符(Unicode 可选)+ 空格,但可以规范化空格 最好接受 Unicode,包括表情符号(1 个“字符”/代码点)?。但是它们是什么知道。? 密码也需要易于记忆。 然后是 XKCD Password Strength。有关详细信息,请参阅:SecLists 的密码列表。 Infosec password-cracking-tools Arstechnica How I became a password cracker 高级密码恢复 hashcat 另见PassMaker,只需大写并根据需要更改分隔符。以上是关于Python密码保护的主要内容,如果未能解决你的问题,请参考以下文章