Crazy idea…

I’ve been toying with the idea of using my cache as a data store for a project where the data doesn’t need to be updated very often.  Basically, I’d write out plain XHTML documents and then parse the data using XPath when needed.  But that’s a different story.  Once I decided to give my idea a try, I started thinking about how to store authentication information.  The application doesn’t store any private information, so authentication is only needed to prove that you are authorized to edit the information.  So why not store the authentication information publicly as well (as an HTML comment at the top of the file)?  Here’s what I was thinking, in pseudo code:

identity = base64(encrypt_rijndael256([
	sha512_hmac(username, appUsernameSecret),
	sha512_hmac(password, appPasswordSecret)
], appSecret))

This would produce an base64 representation of an encrypted array of hashes.  Basically, the system would produce two hashes using HMAC and two separate secret keys (one for the username hash and one for the password hash).  It would store that data in a way that it could later retrieve it (in my case a serialized array) and then encrypt the whole thing with a third key (the base64 is just so it could easily be represented by an ASCII string).  That way there are multiple points of failure.  An attacker would have to know all three keys just to get at the hashes, but then that’s all they’d have.  They’d still need to brute force both the username and password separately.  It seems to me that this would be pretty darn secure.  Clearly not good enough for a bank, but certainly fine for a web app that would have very few negative consequences if it were broken into.

I would love feedback from someone who know’s what they’re talking about :)   Below is some working PHP code to illustrate my point:

class PublicAuth
{
    private $_secret;
    private $_usernameSecret;
    private $_passwordSecret;

    private $_td = null;
    private $_iv = null;

    public function __construct($secret, $usernameSecret, $passwordSecret)
    {
        $this->_secret = $secret;
        $this->_usernameSecret = $usernameSecret;
        $this->_passwordSecret = $passwordSecret;
    }

    public function generateIdentifier($username, $password, $algorithm = 'sha512')
    {
        return $this->_encrypt(serialize(array(
            hash_hmac($algorithm, $username, $this->_usernameSecret, true),
            hash_hmac($algorithm, $password, $this->_passwordSecret, true),
        )));
    }

    public function verifyIdentity($identifier, $username, $password, $algorithm = 'sha512')
    {
        $identifier = unserialize($this->_decrypt($identifier));
        return (hash_hmac($algorithm, $username, $this->_usernameSecret, true) == $identifier[0]
            && hash_hmac($algorithm, $password, $this->_passwordSecret, true) == $identifier[1]);
    }

    private function _encrypt($string)
    {
        $this->_initMcrypt();
        return base64_encode(mcrypt_generic($this->_td, $string));
    }

    private function _decrypt($string)
    {
        $this->_initMcrypt();
        return mdecrypt_generic($this->_td, base64_decode($string));
    }

    private function _initMcrypt($algorithm = 'rijndael-256')
    {
        if (null == $this->_td || null == $this->_iv) {
            $this->_td = mcrypt_module_open($algorithm, '', 'ecb', '');
            $this->_iv = mcrypt_create_iv(mcrypt_enc_get_iv_size($this->_td), MCRYPT_RAND);
        }

        mcrypt_generic_init($this->_td, $this->_secret, $this->_iv);
    }
}

And here’s some sample usage:

$pa = new PublicAuth('a', 'b', 'c');
echo $pa->generateIdentifier('user', 'pass');

Which would print out:

NLgAYjlGbmJA2Wdcgwntm4ixhHHCiZBA6TvgrVMgEOBEjZQJ0tHgAlw7931p2S6KRtfCkLjrsA2DBilcgBX/pPPXFgyAx3g0/CKMcjdU8DKn3/9M2aIZHOrdi/G68C0oxVe6pDlWvVwvofpJnu9RxMbFN49x1uVgBuHTjKagpD6y83fm+hX4G+CoPRcHM5PUq/nJ1iwtZipRtno8TllO6A==

Then to verify the identity:

$pa = new PublicAuth('a', 'b', 'c'); // Needs to be the same as when generated
var_export($pa->verifyIdentity($id, 'user', 'pass')); // $id contains the string above; returns TRUE

Thoughts?

Related posts:

  1. E-Mail Address Obfuscator Class A project I’m working on needs to output text that...
This entry was posted in Web Development. Bookmark the permalink.