Cryptography talk at DC Python

At the April meeting of DC Python I gave a talk on cryptography. A video of the event is now available on youtube.

DC Python is the local user group for the python programming language in the Washington, D.C., Maryland, and Northern Virginia area. I have been hosting a monthly event called Project Night with the group since 2015 and we have recently restarted a monthly talk event. All events can be seen on our meetup page.

My presentation was a summary of two of my recent posts on two factor authentication and partial passwords with an introduction to using cryptography in python.

The other presentation was given by Alan Swenson on JSON web tokens in flask. The video for his talk is also available.

A partial password implementation

Whilst working on my previous post on two factor authentication I was reminded of the broad spectrum of approaches taken to security by many sites. I have one bank that does two factor authentication, another using the standard username/password combination for one factor authentication, and then another that asks for a username, a piece of personal information and then a partial password. In this case, three characters from a password.

Of these three approaches it is the last that seems the weakest. The piece of personal information includes things like the town you grew up in, the name of your first school, etc. These are not generally secret and could be discovered for most people by a bit of research. The partial password scheme seems only slightly stronger than a three character password.

I believe the partial password is intended to prevent a keylogger on your computer from compromising your entire password. This scheme is often paired with selecting characters from a dropdown menu, potentially providing additional protection. The idea is that by requesting different characters on each visit you would need to log in multiple times on a compromised computer before an attacker discovered your entire password.

I don't think such a system would be used in a new application today but I did wonder how such a scheme might be implemented.

Continue reading ...

Adding second factor authentication with FIDO U2F

This is the first semester since the Fall of 2015 that I have not taught a course with the Foundation for Advanced Education in the Sciences. It was a pleasure teaching and I was lucky enough to spend most of my time on a course I had designed. For the Spring 2016 semester I designed the syllabus and began teaching a course on machine learning and object oriented python. I chose to include a web application as I felt it exposed the students to some unfamiliar ideas.

Most of the students were fellow scientists. Many only had previous experience writing scripts for use in their own research. Not trusting user input was often a novel concept. During the course I only had a couple of hours to introduce web applications. This meant I skipped over many important topics. I intend this post to be the first in a collection moving beyond the basics for anyone still new to these concepts. I will start with a basic background but the actual implementation will hopefully be new for most. If implementing web application authentication is familiar to you then skip ahead to the implementation.

Let me know if there are topics you think I should cover moving forward.

In this post I will cover authentication, specifically adding a second authentication factor for additional security.

Continue reading ...

Adding bcrypt-style password hashing to Zend_Auth with phpass

I've been using the Zend Framework to good effect on and off for a few months now and have found it very useful in rapidly bringing projects to completion. Many people feel Zend Framework is more a library than a framework and with good reason. There are few things it prevents you from doing but it's not ready to go 'out of the box' in the way some other frameworks are. One example is in the way passwords are stored in the database. The default is simply to store them in plain text.

The manual does cover hashing the password but even this isn't really ideal. There seems to be some consensus forming that the correct way to handle passwords is using bcrypt, a Blowfish-based hashing scheme. The most widely known demonstration of this within the PHP community is the phpass hashing framework. It has already been integrated into wordpress and phpBB. As such, I was in good company integrating it into my own projects.

The first step is making the phpass code available in your ZF project. The changes I made were minor, renaming the class and switching the PasswordHash function to __construct. I would encourage you to fetch the latest code from the phpass project page. The snippet of code I changed is below.

class Acai_Hash {
    
	var $itoa64;
	var $iteration_count_log2;
	var $portable_hashes;
	var $random_state;

	function __construct($iteration_count_log2, $portable_hashes)
	{

The next step was altering the database table adapter in Zend_Auth. The code for this is below.

<?php

class Acai_Auth_Adapter_DbTable extends Zend_Auth_Adapter_DbTable
{

    public function __construct ($zendDb = null, $tableName = null, $identityColumn = null, $credentialColumn = null)
    {
        //Get the default db adapter
        //From where?  It is not stored in the registry.
        if ($zendDb == null) {
            $zendDb = Zend_Registry::get('DbAdapter');
        }

        //Set default values
        $tableName = $tableName ? $tableName : 'accounts';
        $identityColumn = $identityColumn ? $identityColumn : 'email';
        $credentialColumn = $credentialColumn ? $credentialColumn : 'password';

        parent::__construct($zendDb,
                                $tableName,
                                $identityColumn,
                                $credentialColumn);
    }

    protected function _authenticateCreateSelect()
    {
        // get select
        $dbSelect = clone $this->getDbSelect();
        $dbSelect->from($this->_tableName)
                 ->where(
            $this->_zendDb->quoteIdentifier($this->_identityColumn, true)
            . ' = ?', $this->_identity);

        return $dbSelect;
    }

    protected function _authenticateValidateResult($resultIdentity)
    {
        //Check that hash value is correct
        $hash = new Acai_Hash(8, false);
        $check = $hash->CheckPassword($this->_credential,
                                    $resultIdentity['password']);

        if (!$check) {
            $this->_authenticateResultInfo['code'] =
                            Zend_Auth_Result::FAILURE_CREDENTIAL_INVALID;
            $this->_authenticateResultInfo['messages'][] =
                            'Supplied credential is invalid.';
            return $this->_authenticateCreateAuthResult();
        }

        $this->_resultRow = $resultIdentity;

        $this->_authenticateResultInfo['code'] =
                            Zend_Auth_Result::SUCCESS;
        $this->_authenticateResultInfo['messages'][] =
                            'Authentication successful.';
        return $this->_authenticateCreateAuthResult();
    }

    
    public function getResultRowObject ($returnColumns = null, $omitColumns = null)
    {
        if ($returnColumns || $omitColumns) {
            return parent::getResultRowObject($returnColumns, $omitColumns);
        } else {
            $omitColumns = array('password');
            return parent::getResultRowObject($returnColumns, $omitColumns);
        }

    }

}

Usage is just as for the standard Zend adapter.

$auth = Zend_Auth::getInstance();
$authAdapter = new Acai_Auth_Adapter_DbTable;
$authAdapter->setIdentity($values['email'])
            ->setCredential($values['password']);
$result = $auth->authenticate($authAdapter);

if (!$result->isValid()) {

    //Bad credentials
    
} else {

    //Good credentials
    
}

When you're initially registering a new user a hash can be generated simply with the following code.

//Generate hash for password
$hash = new Acai_Hash(8, false);
$passwordHash = $hash->HashPassword($password);

Hopefully you can integrate the above code into your own projects. If you have any questions post them in the comments below and I'll try to answer them.

Ditching the custom wheel in backups

I've heard enough horror stories about lost data to know that backups are important. For those files that mainly live on my laptop I use Jungledisk to automatically backup the important files daily. At the time I signed up the program cost $20 and my storage costs are about $0.50 a month. Today you have to pay at least $2/month and then the storage fees as well. Not bad but after a couple of years those fees are going to add up. When I used shared hosting I sporadically backed up the files and then emailed a database dump to my gmail account daily. This worked perfectly well as the files rarely changed and gmail was able to hold several hundred copies of the database for my little blog. When I needed to I could simply go in and delete last years backup emails. Recently though I've started renting a VPS from Linode and I'm now in the position where both the files and the database are frequently changing. I need a way to backup both the files and the database and as I'm lazy I want it to be automated. I started looking around for information on how other people were handling this.

The Plan

I came across a post from John Eberly discussing how he automates his backups to amazon s3. This looked like a good place to start but I was sceptical about how rsync would work with amazon s3 as described and there was only one backup. Based on this I formulated the following plan: At the start of each week copy the directories to be backed up to a temporary directory using rsync and then encrypt using gnupg. Then push the resulting file to amazon s3. On each subsequent day make a differential backup using the batch mode of rsync, encrypt and then push to s3. Repeat for the start of the next week. After putting a surprisingly short script together I had a working approach. Except nothing was actually being pushed to s3. I still need to investigate why this was happening but it isn't at the top of my list of things to do as I have since found a far better way to handle my backups.

Tarsnap

I'm not an expert at backups. Nor am I a security expert. Nor am I interested in becoming an expert at either backups or security. This means someone has likely already built a better backup utility than I could. I believe I have found it in Tarsnap. Below is a list of what tarsnap does. I've highlighted the features which take it above and beyond my approach.
  • Multiple backups
  • Backups on my schedule
  • Files are encrypted
  • Utility pricing - pay only for what you use with no standing charges
  • Open source - I can check that only what I want to happen is really happening
  • Efficient - backups take up no more space than my full+differential strategy and yet each backup can be manipulated independently of any other backup
  • Permissions - With tarsnap I can allow my server to create and read backups but not delete them
The efficiency is nice but a difference between $0.50/month and $0.60/month isn't a massive deal. What is a big deal is the permissions. Backing up my files anywhere with an online connection has always made me slightly uneasy. Email works well as once an email is sent it can't be called back. If you want to backup to amazon s3 you have to give unrestricted access to read, edit and delete which means it is possible to loose all your backups. Tarsnap is not vulnerable to this weakness though and this is a big deal. It's one less thing to worry about which is certainly worth the $0.15/GB premium over s3 alone. My next post will detail how I have implemented backups using tarsnap.