Code reading of Safe, a library for checking password strength in Python

Safe is a library for checking the strength of passwords.

https://pypi.python.org/pypi/Safe/ https://github.com/lepture/safe

INSTALL

You can install it with pip.

$ pip install safe

Try the README sample code

For the time being, import safe.

>>> import safe

You can check the strength with the safe.check () function.

>>> safe.check(1)
terrible
>>> safe.check('password')
simple
>>> safe.check('is.safe')
terrible
>>> safe.check('x*V-92Ba')
strong

The return value is an instance of safe.Strength ().

>>> type(safe.check('x*V-92Ba'))
<class 'safe.Strength'>

The result can be converted to bool ().

>>> bool(safe.check('x*V-92Ba'))
True
>>> bool(safe.check('a'))
False

Code reading

I will read the code.

safe.check ()-Check password strength

https://github.com/lepture/safe/blob/cb554022df8be8a4f7fa0b8fbee39639b4819495/safe/init.py#L147-L189

The safe.check () function checks the strength of the password.

argument

You can pass raw, length, freq, min_types, and level as arguments.

raw is the password string you want to look up. Normally, str is passed, but to_unicode () is done without a function, and even if int is passed, it is converted to str and processed. https://github.com/lepture/safe/blob/cb554022df8be8a4f7fa0b8fbee39639b4819495/safe/init.py#L156

to_unicode () is defined in _compat.py. https://github.com/lepture/safe/blob/cb554022df8be8a4f7fa0b8fbee39639b4819495/safe/_compat.py#L28-L38

length is the required password length. freq is used to find common passwords.

min_types specifies how many character types should be included. For example, if min_types = 3 and length = 3, 1qA is OK (number / lowercase / uppercase) and 1qa is NG (number / lowercase).

>>> bool(safe.check('1qA', length=3, min_types=3))
True
>>> bool(safe.check('1qa', length=3, min_types=3))
False

level is the threshold for whether the password strength is valid or not. It seems that int / float is acceptable for the input value, but even if you specify a number greater than or equal to STRONG, it will be returned to STRONG (otherwise it will always be invalid ...). https://github.com/lepture/safe/blob/cb554022df8be8a4f7fa0b8fbee39639b4819495/safe/init.py#L157-L158

The level is defined as follows:

TERRIBLE = 0
SIMPLE = 1
MEDIUM = 2
STRONG = 3

Return value

The return value is an instance of safe.Strength. safe.Strength has the attributes valid, strength, and message.

valid is a bool value. True is valid. strength is a string that indicates strength. The string that goes into strength is one of the following:

String used for strength meaning
strong Strong
medium Okay
simple Easy
terrible Nose fucking(Free translation)

(By the way, this string has been hard-coded in the code when instantiating safe.Strength orz)

message is a message that shows why it was judged so.

This function will return the result correctly if you pass a string that gets caught in safe.is_asdf () with one character, for example.

>>> safe.check('a', length=0, min_types=0)
simple

However, if you pass a string that does not get caught in safe.is_asdf () with one character, the exception sent by safe.is_by_step () will be thrown without handling.

>>> safe.check('(', length=0, min_types=0)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/sximada/ng/env/lib/python3.4/site-packages/safe/__init__.py", line 163, in check
    if is_asdf(raw) or is_by_step(raw):
  File "/home/sximada/ng/env/lib/python3.4/site-packages/safe/__init__.py", line 89, in is_by_step
    delta = ord(raw[1]) - ord(raw[0])
IndexError: string index out of range

This is because the error is not handled correctly at the time of condition check. safe.is_by_step () will be described later, but when passing a one-character string, an IndexError exception will be thrown. If safe.is_asdf () is a non-True string (for example, (), then one character ( will be passed to safe.is_by_step ().

    if is_asdf(raw) or is_by_step(raw):
        return Strength(False, 'simple', 'password has a pattern')

https://github.com/lepture/safe/blob/cb554022df8be8a4f7fa0b8fbee39639b4819495/safe/init.py#L163-L164

However, it is rare that one character is allowed to be checked, so I feel that I don't have to be too nervous.

safe.is_asdf ()-Determine if the keyboard is in the order

https://github.com/lepture/safe/blob/cb554022df8be8a4f7fa0b8fbee39639b4819495/safe/init.py#L72-L83

Determines if the given string is in keyboard order. The sort order here is the character string defined in the next place. https://github.com/lepture/safe/blob/cb554022df8be8a4f7fa0b8fbee39639b4819495/safe/init.py#L69 Therefore, not all keyboard order patterns are inspected. (Isn't it a little too small?)

argument

raw is the character string to judge. The character string specified by raw and the character string whose order is reversed are subject to judgment. https://github.com/lepture/safe/blob/cb554022df8be8a4f7fa0b8fbee39639b4819495/safe/init.py#L75

Return value

Bool value. Returns True if the keyboard is in the order of the keyboard.

safe.is_by_step () --Determine if it is a shift cipher string

https://github.com/lepture/safe/blob/cb554022df8be8a4f7fa0b8fbee39639b4819495/safe/init.py#L86-L95

Shift cryptography is a classic and lovable (but never used) cryptography that shifts by n characters. Among them, the Caesar cipher is famous and shifts by 3 characters. For example, if you shift the string test by 3 characters, you will get the string whvw. Such strings are cracked in a blink of an eye, so it just makes you feel like you're hiding it, and it doesn't mean anything. This function determines whether it is such a character string.

The distance between the 1st and 0th characters of the specified character string raw is measured. https://github.com/lepture/safe/blob/cb554022df8be8a4f7fa0b8fbee39639b4819495/safe/init.py#L89

After that, it is judged whether all the characters are shifted according to the distance. https://github.com/lepture/safe/blob/cb554022df8be8a4f7fa0b8fbee39639b4819495/safe/init.py#L91-L95

If you pass a string of length 1, IndexError will be sent.

>>> safe.is_by_step('a')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/sximada/ng/env/lib/python3.4/site-packages/safe/__init__.py", line 89, in is_by_step
    delta = ord(raw[1]) - ord(raw[0])
IndexError: string index out of range

argument

raw is the character string to judge.

Return value

The bool value. True if it is a shift cipher string.

safe.is_common_password ()-Determine if it is a commonly used password

https://github.com/lepture/safe/blob/cb554022df8be8a4f7fa0b8fbee39639b4819495/safe/init.py#L98-L106

According to the docstring, it says that it uses the common password 1000 at https://xato.net/passwords/more-top-worst-passwords/, but unfortunately this URL was a 404 Not Found ( Hey!!).

A list of commonly used passwords is included in the package. This list is used by default. https://github.com/lepture/safe/blob/cb554022df8be8a4f7fa0b8fbee39639b4819495/safe/words.dat

This file has the following format.

String frequency level

Frequent level is an integer used to judge, and the larger the value, the more frequently it is used.

This file can also be a customized file. In that case, if you specify the path of the customized file in the environment variable PYTHON_SAFE_WORDS_FILE, that will be used.

The data in this file is used as a dict in the form {'string': integer, ...} when used. https://github.com/lepture/safe/blob/cb554022df8be8a4f7fa0b8fbee39639b4819495/safe/init.py#L58-L61

After that, the dict is cached, and the location of the cache file can be specified by the environment variable PYTHON_SAFE_WORDS_CACHE.

This data reads the file when importing the safe package and keeps it in safe.WORDS. https://github.com/lepture/safe/blob/cb554022df8be8a4f7fa0b8fbee39639b4819495/safe/init.py#L68

Therefore, if PYTHON_SAFE_WORDS_FILE is specified and the file does not exist, FileNotFoundError will be thrown and import will fail (slightly painful specification).

argument

raw is the character string to judge. freq seems to be a commonly used level. The higher the number, the more often it is used.

Return value

The bool value. True for commonly used strings. False if the frequency level is less than or equal to the number specified by the argument freq. It is also False if it does not correspond to a commonly used string.

safe.safety ()-Unpublished but public utility-like function

safe.safety () is a function that just calls safe.check () and returns its return value. The difference between the two is the default value of the argument. safe.check () has a min_type of 3, while safe.safety () has a value of 2. https://github.com/lepture/safe/blob/cb554022df8be8a4f7fa0b8fbee39639b4819495/safe/init.py#L192-L193

But this function is not included in all. And I don't use it inside the package. https://github.com/lepture/safe/blob/cb554022df8be8a4f7fa0b8fbee39639b4819495/safe/init.py#L20-L23 Whether you forgot to include it, or the author's intention to abolish it (I don't want you to do it that way ...), in any case, this function is not used and it is safe. It seems better to use .check (). (By the way, this author writes all fairly well in _compat.py, so it smells like I forgot to write it.)

Afterword

This library is a small library with only about 200 lines. It was made simple, so it seemed to be very easy to use. I spent about 2 hours writing this article. -> About 100 lines per hour

Recommended Posts

Code reading of Safe, a library for checking password strength in Python
Code reading for m3u8, a library for manipulating HLS video format m3u8 files in Python
Code for checking the operation of Python Matplotlib
Can be used with AtCoder! A collection of techniques for drawing short code in Python!
Create a Python environment for professionals in VS Code on Windows
Wrap (part of) the AtCoder Library in Cython for use in Python
A brief summary of Graphviz in python (explained only for mac)
[For beginners] How to register a library created in Python in PyPI
Display a list of alphabets in Python 3
Get a token for conoha in python
A tool for easily entering Python code
I created a password tool in Python.
[DSU Edition] AtCoder Library reading with a green coder ~ Implementation in Python ~
Python code to determine the monthly signal of a relative strength investment
Draw a graph of a quadratic function in Python
Get the caller of a function in Python
Make a copy of the list in Python
Rewriting elements in a loop of lists (Python)
A proposal for versioning of features in Kedro
Make a joyplot-like plot of R in python
Output in the form of a python array
Get a glimpse of machine learning in Python
Settings for Python coding in Visual Studio Code
A well-prepared record of data analysis in Python
Basic story of inheritance in Python (for beginners)
A python script that generates a sample dataset for checking the operation of a classification tree
Specific sample code for working with SQLite3 in Python
Allow real-time code checking in Python development with VS Code
A memorandum when writing experimental code ~ Logging in python
VS Code settings for developing in Python with completion
Try searching for a million character profile in Python
Ruby, Python code fragment execution of selection in Emacs
Python: Get a list of methods for an object
Group by consecutive elements of a list in Python
Display a histogram of image brightness values in python
A reminder about the implementation of recommendations in Python
Expose settings.json for efficient Python coding in VS Code
[Python] Code for measuring ambient light RGB of APDS9960
Publish / upload a library created in Python to PyPI
Set a proxy for Python pip (described in pip.ini)
Python code for k-means method in super simple case
Spit out a list of file name, last modified date and character code in python3
Find out the apparent width of a string in python
Check the operation of Python for .NET in each environment
Make a table of multiplication of each element in a spreadsheet (Python)
Create a child account for connect with Stripe in Python
[For beginners] Summary of standard input in Python (with explanation)
Get the number of specific elements in a python list
Comparison of exponential moving average (EMA) code written in Python
Building a development environment for Android apps-creating Android apps in Python
A simple way to avoid multiple for loops in Python
Developed a library to get Kindle collection list in Python
How to define multiple variables in a python for statement
How to develop in a virtual environment of Python [Memo]
Do something like a Python interpreter in Visual Studio Code
A sample for drawing points with PIL (Python Imaging Library).
[Note] Import of a file in the parent directory in Python
Decrypt one line of code in Python lambda, map, list
Create code that outputs "A and pretending B" in python
Try building a neural network in Python without using a library
How to get a list of built-in exceptions in python