Jump to content
Sign in to follow this  
benanamen

OOP - Token Generator

Recommended Posts

I wrote a Token Generator class based off the code from the following thread. It works as expected. I just want to get some more eyes on it for any feedback on improvements or problems.

 

http://forums.phpfreaks.com/topic/298729-forgotten-password/?hl=%2Bmcrypt_create_iv&do=findComment&comment=1524084

<?php

/**
 * Class Token
 *
 * Generates a Cryptographically Secure Pseudo Random Number Generator (CSPRNG)
 */

class Token
{
    /**
     * Generates a pseudo-random string of bytes
     *
     * @return string
     */
    public function getRandomBytes()
    {
        return openssl_random_pseudo_bytes(16);
    }

    /**
     * Convert (Encodes) binary data into hexadecimal representation
     *
     * Returns an ASCII string containing the hexadecimal representation of $randomBytes
     *
     * @param $randomBytes
     * @return string
     */
    public function getEncodedToken($randomBytes)
    {
        return bin2hex($randomBytes);
    }

    /**
     * Decodes a hexadecimally encoded binary string
     *
     * @param $encoded_token
     * @return string
     */
    public function getDecodedToken($encoded_token)
    {
        return hex2bin($encoded_token);
    }

    /**
     * Generate a hash value
     *
     * @param $raw_token
     * @return string
     */
    public function sha256Hash($raw_token)
    {
        return hash('sha256', $raw_token);
    }
}

//----------------------------------------------------------------------------
//Test
//----------------------------------------------------------------------------

$token = new Token();

/** Encode token and hash it */
$raw_token = $token->getRandomBytes();

echo $encoded_token =$token->getEncodedToken($raw_token);// Sent to User
echo '<br>';
echo $token_hash = $token->sha256Hash($raw_token);// Stored in DB
echo '<br>';


/** Decode token and hash it */
$raw_token = $token->getDecodedToken($encoded_token);
echo $token_hash = $token->sha256Hash($raw_token);// Compare user token to DB token

Share this post


Link to post
Share on other sites

I would use random_bytes rather than openssl to generate your random byte data. Use the compatibility library if you need to.

 

sha256 hash is probably fine, but I tend to just re-use the same hashing code as for passwords, namely password_hash and password_verify.

 

I'd also consider altering the token class inteface. You're exposing things that I'd consider to be implementation details currently which could make things harder to change in the future.

 

class Token
{
    private $token;

    public function __construct($token)
    {
        $this->token = $token;
    }

    public static function generate($length=16)
    {
        $raw = random_bytes($length);
        $token = bin2hex($raw);

        return new static($token);
    }

    public function getToken()
    {
        return $this->token;
    }

    public function getHash()
    {
        return password_hash($this->token, PASSWORD_DEFAULT);
    }

    public function matches($hash)
    {
        return password_verify($this->token, $hash);
    }
}


$token = Token::generate();
echo $token_plain = $token->getToken(); // Sent to User
echo '<br>';
echo $token_hash = $token->getHash(); //Stored in DB
echo '<br>';


/** Decode token and hash it */
$token = new Token($token_plain);
var_dump($token->matches($token_hash)); //Compare user token to DB token
I removed the encoding/decoding bit as I'm not sure if it's really necessary or not and it simplifies things. Hashing the bin2hex version instead means each byte has a limited value range, but you have twice as many bytes making up the hash.

Share this post


Link to post
Share on other sites

I wouldn't even use a class for this. All the methods are wrappers around a single function call, and even with kicken's version it's a stretch to make this proper OOP. What's the point of having this live somewhere separate from its usage? If you need a token in a class or function or something then put the logic there.

 

Or another answer is,

 

PHP is naturally not object-oriented. Making functionality into a function is not a crime.

function sha256($str, $raw_output = false) {
	return hash("sha256", $str, $raw_output);
}
function token($length = 16) {
	return bin2hex(random_bytes($length));
}
  • Like 1

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this  

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.