Masonite Documentation
v2.2 LTS
v2.2 LTS
  • Introduction and Installation
  • Creating a Blog
  • Prologue
    • Contributing Guide
    • How To Contribute
    • Release Cycle
    • Known Installation Issues
    • Deprecation
  • What's New
    • Masonite 1.3
    • Masonite 1.4
    • Masonite 1.5
    • Masonite 1.6
    • Masonite 2.0
    • Masonite 2.1
    • Masonite 2.2
  • Upgrade Guide
    • Masonite 1.3 to 1.4
    • Masonite 1.4 to 1.5
    • Masonite 1.5 to 1.6
    • Masonite 1.6 to 2.0
    • Masonite 2.0 to 2.1
    • Masonite 2.1 to 2.2
  • The Basics
    • Controllers
    • Helper Functions
    • Requests
    • Routing
    • Static Files
    • Views
  • The Craft Command
    • Introduction
    • Creating Commands
  • Architectural Concepts
    • Request Lifecycle
    • Service Container
    • Service Providers
  • Advanced
    • Autoloading
    • Creating a Mail Driver
    • Creating Packages
    • Database Seeding
    • Extending Classes
    • Middleware
    • Responses
    • Sessions
    • Status Codes
    • Validation
  • Useful Features
    • Broadcasting
    • Caching
    • Compiling Assets
    • Environments
    • Events
    • Framework Hooks
    • Mail
    • Queues and Jobs
    • Task Scheduling
    • Testing
    • Selenium Testing
    • Template Caching
    • Uploading
    • View Composers, Sharing and Filters
  • Security
    • Authentication
    • CSRF Protection
    • Encryption
    • Headers
    • Releases
  • Orator ORM
    • Database Migrations
    • Basic Usage
    • Collections
    • ORM
    • Pagination
    • Query Builder
    • Schema Builder
  • Managers and Drivers
    • About Drivers
    • About Managers
    • Contracts
  • Official Packages
    • Masonite API
    • Masonite Billing
    • Masonite Logging
    • Masonite Notifications
  • Masonite Essentials
    • Hash ID's
  • Tutorials
    • Creating a Blog
  • How-to Guides
    • Build Email Verification from Scratch With Masonite Framework and JSON Web Tokens
    • Deploying a Masonite Application to Heroku
    • How To Deploy Masonite to PythonAnywhere
    • How-To: Use RabbitMQ with Masonite 2.0 queues
    • How To Use The Repository Pattern with Masonite
    • Making Masonite and Laravel Mix work together
  • Deployment
    • Drivers
    • Optimization
Powered by GitBook
On this page
  • Introduction
  • Background
  • Secret Key
  • Cryptographic Signing
  • Using bcrypt
  • Hashing Passwords
  • Checking Hashed Passwords
Edit on Git
Export as PDF
  1. Security

Encryption

PreviousCSRF ProtectionNextHeaders

Last updated 6 years ago

Introduction

Masonite comes with bcrypt out of the box but leaves it up to the developer to actually encrypt things like passwords. You can opt to use any other hashing library but bcrypt is the standard of a lot of libraries and comes with some one way hashing algorithms with no known vulnerabilities. Many of hashing algorithms like SHA-1 and MD5 are not secure and you should not use them in your application.

You can read the .

Background

Also, we make sure that Javascript cannot read your cookies. It's important to know that although your website may be secure, you are susceptible to attacks if you import third party Javascript packages (since those libraries could be compromised) which can read all cookies on your website and send them to the hacker.

Other frameworks use cryptographic signing which attaches a special key to your cookies that prevents manipulation. This does't make sense as a major part of XSS protection is preventing third parties from reading cookies. It doesn't make sense to attach a digital signature to a plaintext cookie if you don't want third parties to see the cookie (such as a session id). Masonite takes this one step further and encrypts the entire string and can only be decrypted using your secret key (so make sure you keep it secret!).

Secret Key

In your .env file, you will find a setting called KEY=your-secret-key. This is the SALT that is used to encrypt and decrypt your cookies. It is important to change this key sometime before development. You can generate new secret keys by running:

$ craft key

This will generate a new key in your terminal which you can copy and paste into your .env file. Your config/application.py file uses this environment variable to set the KEY configuration setting.

Additionally you can pass the --store flag which will automatically set the KEY= value in your .env file for you:

$ craft key --store

Remember to not share this secret key as a loss of this key could lead to someone being able to decrypt any cookies set by your application. If you find that your secret key is compromised, just generate a new key.

Cryptographic Signing

You can use the same cryptographic signing that Masonite uses to encrypt cookies on any data you want. Just import the masonite.sign.Sign class. A complete signing will look something like:

from masonite.auth import Sign

sign = Sign()

signed = sign.sign('value') # PSJDUudbs87SB....

sign.unsign(signed) # 'value'

By default, Sign() uses the encryption key in your config/application.py file but you could also pass in your own key.

from masonite.auth import Sign

encryption_key = b'SJS(839dhs...'

sign = Sign(encryption_key)

signed = sign.sign('value') # PSJDUudbs87SB....

sign.unsign(signed) # 'value'
from masonite.auth import Sign
from cryptography.fernet import Fernet

encryption_key = Fernet.generate_key()

sign = Sign(encryption_key)

signed = sign.sign('value') # PSJDUudbs87SB....

sign.unsign(signed) # 'value'

Just remember to store the key you generated or you will not be able to decrypt any values that you encrypted in the first place.

Using bcrypt

Bcrypt is very easy to use and basically consists of a 1 way hash, and then a check to verify if that 1 way hash matches an input given to it.

It's important to note that any values passed to bcrypt need to be in bytes.

Hashing Passwords

Again, all values passed into bcrypt need to be in bytes so we can pass in a password using the password helper function:

from masonite.helpers import password

encrypted_password = password('secret')

Notice that the value passed in from the request was converted into bytes using the bytes() Python function.

Once the password is hashed, we can just safely store it into our database

User.create(
    name=request.input('name'),
    password=password,
    email=request.input('email'),
)

Do not store unhashed passwords in your database. Also, do not use unsafe encryption methods like MD5 or SHA-1.

Checking Hashed Passwords

In order to check if a password matches it's hashed form, such as trying to login a user, we can use the bcrypt.checkpw() function:

bcrypt.checkpw(bytes('password', 'utf-8'), bytes(model.password, 'utf-8'))

This will return true if the string 'password' is equal to the models password.

More information on bcrypt can be found by reading it's documentation.

This feature uses for this kind of encryption. Because of this, we can generate keys using Fernet.

bcrypt documentation here
pyca/cryptography