用相对安全的方法保存密码 [傻瓜指南]

创建密码周围有一个神秘的光环。 只有在对巴塔哥尼亚冰川和升速溶咖啡进行了数十年的沉思之后,遥远的密码隐士才升入必杀技,从而获得了某种神秘的知识。 在这篇文章中,我们将尝试翻译这一古老智慧的几滴,这样我们作为凡人,就有了安全的账户来存储我们永远不会阅读的猫的图片和电子书。

首先,本文不仅推荐给程序员新手,也推荐给那些想知道为什么需要一个人字难读的密码的用户。

要求:

如果您正在阅读本文,则假定您熟悉编程语言,或者至少熟悉它们的逻辑。 我们将使用 Python 3 尽可能简单地创建用户创建程序。 如果你是一个初学者,请阅读有关 数据录入 退出 ,然后再继续。

起初,上帝创造了一个待办事项清单,而人类以他的形象和相似之处,倾向于效仿这一策略。 这是我们需要做的:

  • 保存用户名;
  • 确保他的密码是安全的;
  • 安全保存密码;
  • 在第七天休息;

用户的神圣名称[请不要忘记]

这里没有秘密。让用户以他们喜欢的方式被称呼,我们没有义务去评判他。让我们抓住这个机会把基础课程准备好。数字表示上帝的Ctrl + C/Ctrl + V:

class User :

    def __init__ (self, user, passwd, salt) :
        self.username = user
        self.passwd = passwd
        self.salt = salt

不用担心“salt”。 我们将尽快讨论。

您的密码值得吗?

我想谈谈少于40行的代码每秒可以生成数百万个密码,如何从您的灵魂深处提取隐藏的单词并像我们在Netflix上拖延一样轻松地对其进行测试或查看我们的电子邮件。 但是,请遵守严格必要的条件。让我们把为什么留给哲学家、醉鬼和乞丐吧。

安全 <------------------------------------------------ ----------------------> 实用性

上面惊人的美丽象形文字(位于南美洲埃尔多拉多的黄金大厅中)描述了先进社会如何计算其密码需求。 他们发现,系统的安全性与其使用的实用性成反比。 也就是说,将煤运到沙丁鱼时,密码越安全,密码就越复杂。

用相对安全的方法保存密码 [傻瓜指南]_第1张图片

在我们的研究中,我们将任意决定一个体面的密码需要:

  • 至少六个字符;
  • 至少六位数;
  • 至少两个特殊字符;
  • 这使我们最少有14个字符;

让我们创建一个将接收密码并检查尊严级别的方法(为简单起见,我们不区分大写和小写字符。)

    def check_passwd (self, passwd) :
        """ Check if is a valid password """
        while True :
            # Check Size
            if len(passwd) < 14 :
                print( "This password is too short." )
                break            

            # Check Ascii Letters
            counter = 0
            for i in passwd:
                if i in self.passwd_characteres:
                    counter += 1
            if counter < 6 :
                print( "Your password need at last six (6) characteres." )
                break

            # Check Digits
            counter = 0
            for i in passwd:
                if i in self.passwd_numbers:
                    counter += 1
            if counter < 6 :
                print( "Your password need at last six (6) digits." )
                break

            # Check Special Characteres
            counter = 0
            for i in passwd:
                if i in self.passwd_special:
                    counter += 1
            if counter < 2 :
                print( "Your password need at last two (2) special characteres." )
                break

            # The password has passed!
            return True

您可能已经注意到此方法属于一个类。 我们创建了一个经理来测试这些功能。 我们仅在讨论主要功能,最后将提供完整的代码。

密码似乎很有价值。现在呢?

“似乎就是这个词。 没有什么可以阻止用户键入aaaaaa000000 **@abcedf123456@或类似的内容。 我们承担着开明生物的角色,因此不信任用户。 如果他的密码很弱,那么我们的系统将是不安全的,而不仅仅是他的数据。 该死的用户! 幸运的是,在Python中 ,有一个秘密叫做secrets

import secrets

您需要了解的所有信息都在这里 。 (#ReadtheDocs)让我们直接说清楚。 那就是我们的“盐”出现的地方。 “盐”是紧要关头,为了确保安全性,我们在用户密码中添加了一些小东西。 我们可以使用secrets模块自动生成它。 它提供了几种类型的令牌,特别是我更喜欢这种令牌:

# 32 is the number of bytes of the text to be generated.

secrets.token_urlsafe( 32 )

您可以在密码的开头,中间或结尾添加盐。 在这里,我们将使用结尾,并且密码将大致这样结束:

"aaaaaa*000000*ALE_tEwJXs87D-yfgU-D7DWbASX5g_D-oENWUIBi1q8"

如果有人可以通过反复试验找出答案,请给他所有其他密码。 他值得为此付出努力。

我们完了吗? 有一个情节在等我。

否。将鼠标指针移回并读取。 现在我们有了一个相当安全的密码,我们应该如何保存它? 现在是时候激活文章中的最后一个陷阱卡:在继续之前,您必须了解有关哈希的知识 。 如果您不知道,就用劣势来掷骰子,然后稍后再试。在保存密码之前需要对其进行加密的原因有以下几点。

用相对安全的方法保存密码 [傻瓜指南]_第2张图片

最重要的是,如果攻击者可以访问数据库,那么他将不会立即获得可用的密码。 因此,即使很大一部分受到损害,他也将无法访问帐户及其各自的数据。 最后,让我们将潜在可疑的密码变成间谍解码器的噩梦:

worthy_password = hashlib.sha256((password + salt).encode()).hexdigest()

保持坚强,生活不会等你。 我们正在整理。

最后,上帝又列出了另一个清单。 一是关于已完成的任务。 他(或我们)有一个用户名,该用户的“盐”和一个加密的密码。 我们将其分开保存,因为User类允许我们这样做。 我们保存了盐,以便尝试登录时,将其完全添加到创建时所输入的密码中,并检查哈希值是否相同。 如果是这样的话,密码则是正确的,在接下来的几分钟内我们将不会有任何麻烦。 或者直到用户再次忘记密码为止,以先到者为准。

至此,我们完成了。 现在我们明白了。 现在所有部件都组装在一起,我们对于在齿轮如何旋转和世界旋转之前没有注意到而感到愚蠢。 下面是完整的代码,在准备好进行测试的管理器中进行组织。 要获得更多巴塔哥尼亚人的智慧(或猜测的摘录),请访问Telegram上的Prometheus原型 。

# ================================================================== #
# The **basics** of how to save a reasonably secure username and
# password.
# ================================================================== #
#  DEPENDENCIES
# ================================================================== #
import hashlib
import secrets
import string

# ================================================================== #
#  USER CLASS
# ================================================================== #
class User :

    def __init__ (self, user, passwd, salt) :
        self.username = user
        self.passwd = passwd
        self.salt = salt

# ================================================================== #
#  MANAGER CLASS
# ================================================================== #
class Manager :

    def __init__ (self) :
        self.users = []
        self.passwd_characteres = string.ascii_letters
        self.passwd_numbers = string.digits
        self.passwd_special = string.punctuation

    def input_username (self) :
        """ Gets the Username """
        return input( "Enter your user name: " )

    def input_passwd (self) :
        """ Gets the Password """
        return input( "Enter your user name: " )

    def check_username (self, new_username) :
        """ Check if is a valid Username """
        for user in self.users:
            if user.username == new_username:
                print( "This username already exists." )
                return True
        return False

    def check_passwd (self, passwd) :
        """ Check if is a valid password """
        while True :
            # Check Size
            if len(passwd) < 14 :
                print( "This password is too short." )
                break            

            # Check Ascii Letters
            counter = 0
            for i in passwd:
                if i in self.passwd_characteres:
                    counter += 1
            if counter < 6 :
                print( "Your password need at last six (6) characteres." )
                break

            # Check Digits
            counter = 0
            for i in passwd:
                if i in self.passwd_numbers:
                    counter += 1
            if counter < 6 :
                print( "Your password need at last six (6) digits." )
                break

            # Check Special Characteres
            counter = 0
            for i in passwd:
                if i in self.passwd_special:
                    counter += 1
            if counter < 2 :
                print( "Your password need at last two (2) special characteres." )
                break

            # The password has passed!
            return True

    def protect_passwd (self, passwd) :
        """ Encrypt the password before save it. """
        salt = secrets.token_urlsafe( 32 )
        encripted_passwd = hashlib.sha256((passwd + salt).encode()).hexdigest()
        return (encripted_passwd, salt)

    def create_new_user (self) :
        """ Create a new user. """
        while True :
            user = input( "Type your username: " )
            if not self.check_username(user):
                break
        while True :
            passwd = input( "Type your password: " )
            if self.check_passwd(passwd):
                pass_pack = self.protect_passwd(passwd)
                break

        # Well done!
        new_user = User(user, pass_pack[ 0 ], pass_pack[ 1 ])
        self.users.append(new_user)
        print( "\nWellcome to this database!" )

# ================================================================== #
# We're done here. To load the user safely, simply add the 'salt'
# saved in the profile to the password entered at the time of login.
# ================================================================== #

# TESTING:
manager = Manager()
manager.create_new_user()

# Let's see:
print( "\n" )
print( "User name: " + manager.users[ 0 ].username)
print( "Saved password: " + manager.users[ 0 ].passwd)
print( "This-user salt: " + manager.users[ 0 ].salt)
print( "\n" )
input( "Press anything to quit." )

原文链接: https://hackernoon.com/saving-passwords-with-relative-security-a-guide-for-dummies-7p1s32pt

你可能感兴趣的:(用相对安全的方法保存密码 [傻瓜指南])