diff --git a/docs/example.ipynb b/docs/example.ipynb index 805c2c0..a0166f3 100644 --- a/docs/example.ipynb +++ b/docs/example.ipynb @@ -1,236 +1,311 @@ { - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Using Passwordler\n", - "\n", - "Welcome to the Passwordler package documentation! This package offers a suite of functions designed to enhance your online password security. Here, we illustrate the usage of these functions with real-life examples, featuring Bob, a baseball fan who learned the hard way about the importance of strong passwords." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Bob's Journey\n", - "\n", - "For the past 10 years, Bob has been using the password 'baseball' for all his online accounts. While this made them easy to remember, it also made them easy to hack. Unfortunately for Bob, some not-so-flattering photos of his trip to Cancun were sent to **all** of his Facebook friends (think sunglasses burn). Due to this incident, Bob has decided to up his password security and begins by testing the strength of his previously used password. " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Password Strength" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "'Your password is: Weak'" - ] - }, - "execution_count": 6, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "from passwordler.password_strength import password_strength\n", - "\n", - "password_strength('baseball')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "As we can see, his password was weak! No wonder they were able to hack his account. Next he tries a few more variations to see if he can create something stronger.\n", - "\n", - "***Note**: A password is classified as weak if it is found in our list of common passwords, or is less than 8 characters and contains less than two capital letters, numbers or special characters. A good password contains between 8-12 characters and at least two capital letters, numbers or special characters. Finally, a strong password has 12 or more characters and at least one capital letter, one number and one special character.* " - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "'Your password is: Good'" - ] - }, - "execution_count": 7, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "password_strength('Baseball4life')" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "'Your password is: Strong'" - ] - }, - "execution_count": 8, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "password_strength('Baseball4life!')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Finally! Something Bob can work with, he's found a password he likes that is also strong. But then Bob reads about our password generator and decides to give that a try instead." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Generate Password\n", - "\n", - "The `generate_password` function allows users to create a secure, customized password.\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### First try: default settings\n", - "\n", - "Bob creates a password with the default settings. This returns a password of length 12, with at least one uppercase letter, number and symbol. " - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "'`iw:XP-t<32J'" - ] - }, - "execution_count": 7, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "from passwordler.generate_password import generate_password\n", - "\n", - "generate_password()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Going for Length" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Intrigued, Bob decides to generate a much longer password, setting the `length` to 100 characters. The minimum accepted length is 12 characters." - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "'@iWD9x4j^_UM7}Qd46NV[@-dz^qD/i^qSnzP\"yg#eOLy7\\'|emw/Y>ZCDt3GiDi\\'.M7$2zxv&r\\'m>GO_EZ&dlY?OMw9JvjL`4%E>>'" - ] - }, - "execution_count": 10, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "generate_password(length=100)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Simplifying It" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Next, he experiments with the `include_symbols` and `include_numbers` arguments. He sets both to false, overriding the default settings. This gives him a password with only letters: removing symbols and numbers" - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "'cHaJeZNKwGrh'" - ] - }, - "execution_count": 14, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "generate_password(include_symbols=False, include_numbers=False)" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.11.7" - } - }, - "nbformat": 4, - "nbformat_minor": 4 + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Using Passwordler\n", + "\n", + "Welcome to the Passwordler package documentation! This package offers a suite of functions designed to enhance your online password security. Here, we illustrate the usage of these functions with real-life examples, featuring Bob, a baseball fan who learned the hard way about the importance of strong passwords." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Bob's Journey\n", + "\n", + "For the past 10 years, Bob has been using the password 'baseball' for all his online accounts. While this made them easy to remember, it also made them easy to hack. Unfortunately for Bob, some not-so-flattering photos of his trip to Cancun were sent to **all** of his Facebook friends (think sunglasses burn). Due to this incident, Bob has decided to up his password security and begins by testing the strength of his previously used password. " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Password Strength" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'Your password is: Weak'" + ] + }, + "execution_count": 1, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from passwordler.password_strength import password_strength\n", + "\n", + "password_strength('baseball')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "As we can see, his password was weak! No wonder they were able to hack his account. Next he tries a few more variations to see if he can create something stronger.\n", + "\n", + "***Note**: A password is classified as weak if it is found in our list of common passwords, or is less than 8 characters and contains less than two capital letters, numbers or special characters. A good password contains between 8-12 characters and at least two capital letters, numbers or special characters. Finally, a strong password has 12 or more characters and at least one capital letter, one number and one special character.* " + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'Your password is: Good'" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "password_strength('Baseball4life')" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'Your password is: Strong'" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "password_strength('Baseball4life!')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Finally! Something Bob can work with, he's found a password he likes that is also strong. But then Bob reads about our password generator and decides to give that a try instead." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Generate Password\n", + "\n", + "The `generate_password` function allows users to create a secure, customized password.\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### First try: default settings\n", + "\n", + "Bob creates a password with the default settings. This returns a password of length 12, with at least one uppercase letter, number and symbol. " + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'2CG2=>Bz[Sp`o^x5,m&K7\\\\,MV,CUd!$Zi`SCU6y>A/K^FnS.cQLP:c&>A59z0t7y)@9xK(>\".I7iN$X?d$LE6'" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "generate_password(length=100)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Simplifying It" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Next, he experiments with the `include_symbols` and `include_numbers` arguments. He sets both to false, overriding the default settings. This gives him a password with only letters: removing symbols and numbers" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'ozcuYALomeYA'" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "generate_password(include_symbols=False, include_numbers=False)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Encrypt a Password\n", + "\n", + "The `encrypt_password` function encrypts a message using a simple substitution cipher, by substituting each character with a corresponding character from a shuffled set. It uses the same set of characters as the decryption function." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### First try: default settings\n", + "\n", + "Bob realizes the only problem is that the generated password is very difficult to remember. He needs to store it on his computer but is worried that he might be hacked again. He decides to use the Encrypt_Password function with the original password. He tried the default setting first, as below:" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Gh%YwhDDöDàdY \n" + ] + } + ], + "source": [ + "from passwordler.encrypt_password import encrypt_password\n", + "\n", + "# Encrypt a password with a default seed\n", + "encrypted_password = encrypt_password(\"Baseball4life!\")\n", + "print(encrypted_password) # Prints the encrypted password" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "What he didn’t know is that by not providing a seed, the default seed of 123 is used. Then he read the docs and figured out a random seed parameter controls the shuffled character mapping." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Going for a customized seed\n", + "\n", + "Then Bob felt it might be better to customize the seed, so he picked up a random number he liked as the seed (better not a lucky number or DOB the others can easily guess). This means that he needs to store the seed and the encrypted password in two different places, but as long as it is a unique seed, the encrypted password is in the safe house.\n", + "So Bob passes a seed as a second argument:" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "äMul MTT1T86l-\n" + ] + } + ], + "source": [ + "# Encrypt a password with a specific seed\n", + "encrypted_password = encrypt_password(\"Baseball4life!\", 42428)\n", + "print(encrypted_password) # Prints the encrypted password using the specified seed" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python [conda env:passwordler]", + "language": "python", + "name": "conda-env-passwordler-py" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.7" + } + }, + "nbformat": 4, + "nbformat_minor": 4 } diff --git a/src/passwordler/encrypt_password.py b/src/passwordler/encrypt_password.py index 74a3dee..b99549d 100644 --- a/src/passwordler/encrypt_password.py +++ b/src/passwordler/encrypt_password.py @@ -7,16 +7,25 @@ def encrypt_password(message, random_seed=123): """ Encrypt a message using a simple substitution cipher. - This function encrypts a given message by mapping each character to a corresponding character - in a shuffled character set. The function uses a predefined list of characters and a random - seed to ensure consistent shuffling. Characters not in the predefined list remain unchanged. + This function encrypts a message by substituting each character with a corresponding character + from a shuffled set, using the same set of characters as the decryption function. The shuffle + is controlled by a random seed to ensure reproducible results, allowing encrypted messages + to be consistently decrypted using the matching seed. Characters not included in the + substitution set remain unchanged in the encrypted message. Parameters: - message (str): The message to be encrypted. - random_seed (int): The seed used for random shuffling (default is 123). + - message (str): The message to be encrypted. + - random_seed (int): Seed for the random number generator to ensure consistent encryption + results. Default value is 123. Returns: - str: The encrypted message. + - str: The encrypted message. + + Example: + >>> original_message = 'Monty Python' + >>> encrypted_message = encrypt_password(original_message, random_seed = 123) + >>> decrypted_message = decrypt_password(encrypted_message, random_seed = 123) + Output: 'Monty Python' """ if not isinstance(message, str): raise TypeError(