{ "nbformat": 4, "nbformat_minor": 0, "metadata": { "colab": { "name": "Code Kids - Cyber Security - Password Projects.ipynb", "provenance": [], "collapsed_sections": [] }, "kernelspec": { "name": "python3", "display_name": "Python 3" }, "language_info": { "name": "python" } }, "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# \ud83d\udd10 Code Kids Cyber Security Camp\n", "## Day 2 \u2014 Python Password Projects\n", "\n", "Welcome, **Cyber Security Explorers**! \ud83d\udd75\ufe0f\n", "\n", "Today you're going to build four Python projects that teach you how passwords actually work. By the end, you'll understand:\n", "\n", "1. How websites check if your password is correct\n", "2. How to hide your password while you type it (so nobody peeks)\n", "3. How websites store passwords safely using **hashing**\n", "4. How to check if a password is strong or weak\n", "\n", "Work through each project in order. Each one builds on what you learned before. Read the explanation, then run the code by clicking the \u25b6\ufe0f play button next to it.\n", "\n", "---\n", "\n", "**Remember the Cyber Security Explorer code:**\n", "- \ud83d\udee1\ufe0f Use these skills to PROTECT yourself and others\n", "- \ud83d\udeab Never use these skills to harm anyone or hack accounts that aren't yours\n", "- \ud83d\udca1 If you discover a real security problem, tell a trusted adult\n", "\n", "Let's get hacking! \ud83d\ude80\n", "\n", "---\n", "*Code Kids Robotics Limited \u00b7 codekids.org.uk*" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# \ud83d\udd11 Project 1: Simple Password Login\n", "\n", "### What you'll learn\n", "- How websites store usernames and passwords\n", "- How a login check actually works\n", "- Why this simple version is **dangerous** for real websites\n", "\n", "### How it works\n", "Every time you log into a website (Roblox, your school account, anything), the website checks:\n", "\n", "1. Does this username exist?\n", "2. Does the password match what we have stored?\n", "\n", "If both are YES, you're in. If either is NO, you stay out.\n", "\n", "Run the code below. Try logging in with the test accounts. Then try a wrong password and see what happens!\n", "\n", "\u26a0\ufe0f **Important:** This is a *simple* example for learning. Real websites NEVER store passwords like this. You'll see why in Project 3." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Project 1: Simple Password Login\n", "# Learn how passwords protect accounts\n", "\n", "print(\"=\" * 50)\n", "print(\" CODE KIDS SECURE LOGIN\")\n", "print(\"=\" * 50)\n", "\n", "# Our pretend database of users\n", "# In a real website, this would be in a secure database\n", "users = {\n", " \"alex\": \"sunshine123\",\n", " \"jordan\": \"mountain456\",\n", " \"sam\": \"ocean789\"\n", "}\n", "\n", "print(\"\\nTry logging in with these test accounts:\")\n", "print(\" Username: alex Password: sunshine123\")\n", "print(\" Username: jordan Password: mountain456\")\n", "print(\" Username: sam Password: ocean789\")\n", "\n", "# Get login attempt from user\n", "username = input(\"\\nEnter your username: \")\n", "password = input(\"Enter your password: \")\n", "\n", "# Check if login is correct\n", "if username in users and users[username] == password:\n", " print(f\"\\n\u2705 Success! Welcome back, {username}!\")\n", "else:\n", " print(\"\\n\u274c Login failed. Username or password is incorrect.\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### \ud83e\udd14 Think about it\n", "\n", "1. **Try logging in with `alex` and password `wrong`** \u2014 what happens?\n", "2. **Look at the code carefully.** Anyone reading this code can see ALL the passwords. Is that safe?\n", "3. **In real websites, where do you think they actually store passwords?**\n", "\n", "Keep these questions in mind \u2014 we'll fix the problems in Project 3!" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# \ud83d\udc41\ufe0f Project 2: Password Masking with Asterisks\n", "\n", "### What you'll learn\n", "- Why your password should be HIDDEN while you type it\n", "- How to use the `maskpass` library to show asterisks (*) instead of letters\n", "- The difference between **security** and **privacy** when typing passwords\n", "\n", "### Why does this matter?\n", "\n", "Imagine you're logging into your Roblox account at school. Your friend is right behind you, watching the screen. If your password shows up as text, they can see every letter!\n", "\n", "That's why real password fields show `********` instead of your actual password.\n", "\n", "### First \u2014 let's install the library\n", "Run the cell below. It installs a Python library called `maskpass` that hides your password while you type." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Install the maskpass library\n", "# The exclamation mark tells Colab to run this as a system command\n", "!pip install maskpass --quiet\n", "print(\"\u2705 maskpass installed!\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Now let's use it!\n", "\n", "In the code below, notice the difference: the **username** is typed normally with `input()`, but the **password** uses `maskpass.askpass()` which hides what you type.\n", "\n", "Try it \u2014 type your password and watch how it shows asterisks instead of letters! \ud83d\udd12" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Project 2: Password Masking with Asterisks\n", "# Learn how to hide passwords while typing\n", "\n", "import maskpass\n", "\n", "print(\"=\" * 50)\n", "print(\" CODE KIDS SECURE LOGIN (Version 2)\")\n", "print(\"=\" * 50)\n", "\n", "# Same pretend database of users\n", "users = {\n", " \"alex\": \"sunshine123\",\n", " \"jordan\": \"mountain456\",\n", " \"sam\": \"ocean789\"\n", "}\n", "\n", "print(\"\\nNotice how your password gets HIDDEN with asterisks!\")\n", "print(\"\\nTest accounts:\")\n", "print(\" Username: alex Password: sunshine123\")\n", "print(\" Username: jordan Password: mountain456\")\n", "print(\" Username: sam Password: ocean789\")\n", "\n", "# Get login attempt\n", "username = input(\"\\nEnter your username: \")\n", "\n", "# Use maskpass to hide the password input\n", "password = maskpass.askpass(prompt=\"Enter your password: \", mask=\"*\")\n", "\n", "# Check if login is correct\n", "if username in users and users[username] == password:\n", " print(f\"\\n\u2705 Success! Welcome back, {username}!\")\n", " print(\"\ud83d\udee1\ufe0f Your password was hidden while you typed \u2014 that's much safer!\")\n", "else:\n", " print(\"\\n\u274c Login failed. Username or password is incorrect.\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### \ud83e\udd14 Think about it\n", "\n", "1. **Why is masking important even in your bedroom at home?** (Hint: screen recording, screen sharing, video calls)\n", "2. **What other situations might someone \"shoulder surf\" your password?**\n", "3. **Is the password actually MORE secure with masking?** (Tricky question \u2014 think about it!)\n", "\n", "**Answer to question 3:** No! The password itself is exactly the same. Masking is about **privacy from people watching**, not about making the password harder to crack. That's a different problem \u2014 and that's what Project 3 fixes!" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# \ud83d\udd10 Project 3: Cryptographic Hashing\n", "\n", "### What you'll learn\n", "- Why real websites NEVER store your actual password\n", "- What \"hashing\" means and how it protects you\n", "- How even a tiny change makes a completely different hash\n", "\n", "### The BIG problem with our login from Project 1\n", "\n", "Look back at Project 1. We stored passwords like this:\n", "\n", "```python\n", "users = {\n", " \"alex\": \"sunshine123\",\n", " \"jordan\": \"mountain456\"\n", "}\n", "```\n", "\n", "**Imagine if hackers broke into the website's database.** They'd see EVERY password! \ud83d\ude31\n", "\n", "Real websites solve this with **hashing**. When you create an account:\n", "\n", "1. You type your password: `sunshine123`\n", "2. The website runs it through a **hash function** (a special one-way scrambler)\n", "3. The website stores the SCRAMBLED version: `0d1ee2c5ef...` (a long string of random-looking characters)\n", "4. Your actual password is **thrown away forever**\n", "\n", "When you log in next time:\n", "1. You type your password again\n", "2. The website hashes it again and compares the two hashes\n", "3. If they match \u2014 you're in! If not \u2014 login failed!\n", "\n", "### The magic part\n", "**Hashing is one-way.** You CAN'T reverse a hash to get the original password. Even if hackers steal the whole database, they only get the scrambled hashes \u2014 not your real passwords.\n", "\n", "Let's see it in action!" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Project 3: Cryptographic Hashing\n", "# Learn how passwords are securely stored\n", "\n", "import hashlib\n", "\n", "print(\"=\" * 50)\n", "print(\" CODE KIDS PASSWORD HASHING\")\n", "print(\"=\" * 50)\n", "\n", "# A function that turns any password into a hash\n", "def hash_password(password):\n", " # SHA-256 is a famous hashing algorithm used by real websites\n", " return hashlib.sha256(password.encode()).hexdigest()\n", "\n", "# Let's hash a password and see what comes out\n", "print(\"\\nLet's hash the password 'sunshine123'\")\n", "print(\"-\" * 50)\n", "example_password = \"sunshine123\"\n", "example_hash = hash_password(example_password)\n", "print(f\"Original password: {example_password}\")\n", "print(f\"Hashed password: {example_hash}\")\n", "print(\"\\n\ud83d\udd12 You can't reverse the hash to get the original password!\")\n", "print(\" Even the website doesn't know what your password actually is.\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Try it yourself!\n", "\n", "Now run the cell below and type your OWN password. Watch what happens when you hash it. Then try the same password again \u2014 notice that the same password always gives the SAME hash. That's how login checking works!" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Try hashing your own password\n", "print(\"=\" * 50)\n", "print(\" TRY IT YOURSELF\")\n", "print(\"=\" * 50)\n", "\n", "import maskpass\n", "import hashlib\n", "\n", "def hash_password(password):\n", " return hashlib.sha256(password.encode()).hexdigest()\n", "\n", "print(\"\\nType any password (use the asterisk masking!):\")\n", "my_password = maskpass.askpass(prompt=\"Password: \", mask=\"*\")\n", "my_hash = hash_password(my_password)\n", "\n", "print(f\"\\nYour password was hashed to:\")\n", "print(f\" {my_hash}\")\n", "print(f\"\\nLength of your password: {len(my_password)} characters\")\n", "print(f\"Length of the hash: {len(my_hash)} characters (always 64!)\")\n", "print(\"\\n\ud83d\udca1 Hashes are ALWAYS 64 characters long, no matter how long your password was.\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Watch the magic \u2014 tiny changes, huge differences\n", "\n", "Here's the really cool part. Even if you change ONE letter of your password, the hash becomes completely different. This is called the **avalanche effect**.\n", "\n", "Run the cell below to see it:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Show the avalanche effect \u2014 tiny change = totally different hash\n", "import hashlib\n", "\n", "def hash_password(password):\n", " return hashlib.sha256(password.encode()).hexdigest()\n", "\n", "print(\"=\" * 50)\n", "print(\" THE AVALANCHE EFFECT\")\n", "print(\"=\" * 50)\n", "\n", "test_1 = \"sunshine123\"\n", "test_2 = \"sunshine124\" # Only the last digit changed!\n", "test_3 = \"Sunshine123\" # Only the first letter capitalised!\n", "\n", "print(f\"\\nPassword 1: '{test_1}'\")\n", "print(f\"Hash 1: {hash_password(test_1)}\")\n", "print(f\"\\nPassword 2: '{test_2}' (changed last digit)\")\n", "print(f\"Hash 2: {hash_password(test_2)}\")\n", "print(f\"\\nPassword 3: '{test_3}' (capitalised first letter)\")\n", "print(f\"Hash 3: {hash_password(test_3)}\")\n", "\n", "print(\"\\n\ud83e\udd2f Look how completely different the hashes are!\")\n", "print(\"Even tiny changes to a password create totally different hashes.\")\n", "print(\"This is what makes hashing so powerful for security.\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### \ud83e\udd14 Think about it\n", "\n", "1. **Why is it good that even one letter changes the entire hash?**\n", "2. **If two people happen to have the same password, would their hashes look the same?** (Yes! That's actually a problem \u2014 real websites add something called \"salt\" to fix it, but that's a topic for another day.)\n", "3. **Does this mean your password is unhackable?** \n", "\n", "**Answer to question 3:** No! Hashing protects you from database breaches, but attackers can still:\n", "- Guess your password (Project 4 will help with this!)\n", "- Trick you into giving it away (phishing \u2014 see the phishing games)\n", "- Use brute force on weak passwords (see the brute force demo)\n", "\n", "That's why ALL the cyber security skills you learn this week work together! \ud83d\udee1\ufe0f" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# \ud83d\udcaa Project 4: Password Strength Checker\n", "\n", "### What you'll learn\n", "- What makes a password strong or weak\n", "- How to build a tool that gives instant feedback\n", "- The five rules of a really strong password\n", "\n", "### What we're building\n", "A real tool you can use to check if your passwords are strong enough. It checks:\n", "\n", "| Check | Why it matters |\n", "|-------|----------------|\n", "| **Length** (at least 8 characters) | Longer = exponentially harder to crack |\n", "| **Lowercase letters** (a-z) | Adds variety |\n", "| **Uppercase letters** (A-Z) | Adds even more variety |\n", "| **Numbers** (0-9) | Even more combinations |\n", "| **Special characters** (!@#$%) | Makes brute force much harder |\n", "\n", "### The maths bit (for the curious)\n", "\n", "Each character type you add MULTIPLIES the number of possible passwords:\n", "- Only lowercase: 26 possibilities per character\n", "- Lowercase + numbers: 36 possibilities per character\n", "- Lowercase + uppercase + numbers + symbols: ~95 possibilities per character\n", "\n", "For an 8-character password:\n", "- Lowercase only: 208 BILLION combinations\n", "- All four types: 6,634 TRILLION combinations \ud83e\udd2f\n", "\n", "Let's build the checker!" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Project 4: Password Strength Checker\n", "# Build a tool that rates passwords as weak, medium, or strong\n", "\n", "import maskpass\n", "\n", "print(\"=\" * 50)\n", "print(\" CODE KIDS PASSWORD STRENGTH CHECKER\")\n", "print(\"=\" * 50)\n", "\n", "def check_password_strength(password):\n", " \"\"\"Check a password and return a score plus feedback.\"\"\"\n", "\n", " # Track which criteria the password passes\n", " score = 0\n", " feedback = []\n", "\n", " # Check 1: Length\n", " if len(password) >= 12:\n", " score += 2\n", " feedback.append(\"\u2705 Great length (12+ characters)\")\n", " elif len(password) >= 8:\n", " score += 1\n", " feedback.append(\"\u26a0\ufe0f Okay length (8-11 characters) \u2014 longer is better!\")\n", " else:\n", " feedback.append(\"\u274c Too short (less than 8 characters)\")\n", "\n", " # Check 2: Lowercase letters\n", " has_lowercase = False\n", " for char in password:\n", " if char.islower():\n", " has_lowercase = True\n", " break\n", " if has_lowercase:\n", " score += 1\n", " feedback.append(\"\u2705 Contains lowercase letters\")\n", " else:\n", " feedback.append(\"\u274c No lowercase letters\")\n", "\n", " # Check 3: Uppercase letters\n", " has_uppercase = False\n", " for char in password:\n", " if char.isupper():\n", " has_uppercase = True\n", " break\n", " if has_uppercase:\n", " score += 1\n", " feedback.append(\"\u2705 Contains uppercase letters\")\n", " else:\n", " feedback.append(\"\u274c No uppercase letters\")\n", "\n", " # Check 4: Numbers\n", " has_number = False\n", " for char in password:\n", " if char.isdigit():\n", " has_number = True\n", " break\n", " if has_number:\n", " score += 1\n", " feedback.append(\"\u2705 Contains numbers\")\n", " else:\n", " feedback.append(\"\u274c No numbers\")\n", "\n", " # Check 5: Special characters\n", " special_chars = \"!@#$%^&*()_+-=[]{}|;:,.<>?/~`\"\n", " has_special = False\n", " for char in password:\n", " if char in special_chars:\n", " has_special = True\n", " break\n", " if has_special:\n", " score += 1\n", " feedback.append(\"\u2705 Contains special characters\")\n", " else:\n", " feedback.append(\"\u274c No special characters (like ! @ # $ %)\")\n", "\n", " # Determine overall strength\n", " if score >= 5:\n", " strength = \"\ud83d\udcaa STRONG\"\n", " elif score >= 3:\n", " strength = \"\ud83d\udc4c MEDIUM\"\n", " else:\n", " strength = \"\u26a0\ufe0f WEAK\"\n", "\n", " return strength, score, feedback\n", "\n", "\n", "# Get a password from the user\n", "print(\"\\nLet's check how strong your password is!\")\n", "print(\"(Don't use your REAL password \u2014 make one up to test)\")\n", "\n", "password = maskpass.askpass(prompt=\"\\nEnter a password to check: \", mask=\"*\")\n", "\n", "print(\"\\n\" + \"=\" * 50)\n", "print(\" RESULTS\")\n", "print(\"=\" * 50)\n", "\n", "strength, score, feedback = check_password_strength(password)\n", "\n", "print(f\"\\nOverall strength: {strength}\")\n", "print(f\"Score: {score} out of 6\")\n", "print(\"\\nBreakdown:\")\n", "for item in feedback:\n", " print(f\" {item}\")\n", "\n", "print(\"\\n\" + \"=\" * 50)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Try it with different passwords!\n", "\n", "Run the cell above multiple times with different passwords to see how it scores them. Try:\n", "\n", "| Password to try | Expected result |\n", "|-----------------|-----------------|\n", "| `password` | Very weak |\n", "| `password123` | Still weak |\n", "| `Password123` | Medium |\n", "| `MyDog$Name42` | Strong |\n", "| `correcthorsebatterystaple` | Strong (it's super long!) |\n", "\n", "### Bonus challenge \ud83c\udfc6\n", "\n", "Can you modify the code above to also check if the password contains common weak patterns? For example:\n", "- Does it contain the word \"password\"?\n", "- Is it just a single dictionary word?\n", "- Does it contain a sequence like \"123\" or \"abc\"?\n", "\n", "Try adding extra checks to make the tool even smarter!" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# \ud83c\udf89 You did it!\n", "\n", "### What you've learned today\n", "\n", "| Project | Skill |\n", "|---------|-------|\n", "| 1: Simple Login | How password checking works |\n", "| 2: Password Masking | Why passwords should be hidden while typing |\n", "| 3: Hashing | How real websites protect your passwords |\n", "| 4: Strength Checker | How to make passwords that are hard to crack |\n", "\n", "### The five rules of a really strong password\n", "\n", "1. \ud83d\udccf **Length first** \u2014 go for at least 12 characters\n", "2. \ud83c\udfa8 **Mix it up** \u2014 uppercase, lowercase, numbers, AND symbols\n", "3. \ud83e\udd2b **Don't use personal info** \u2014 no pet names, birthdays, favourite teams (attackers find these on social media!)\n", "4. \ud83d\udd01 **Don't reuse passwords** \u2014 different password for every account\n", "5. \ud83e\udd16 **Consider a password manager** \u2014 let it generate and remember complex passwords for you\n", "\n", "### What's next?\n", "\n", "Now that you understand passwords, you're ready for the Phishing Defender game and Social Engineering Challenge. Time to put your skills to the test! \ud83d\udee1\ufe0f\n", "\n", "---\n", "\n", "*Code Kids Robotics Limited \u00b7 codekids.org.uk*\n", "*Cyber Security Holiday Camp \u00b7 Day 2*" ] } ] }