MAC

Small, short code snippets that other people may find useful. Do you have a good regex that you would like to share? Share it! Even better, the code can be commented on, and improved.

Moderator: General Moderators

Post Reply
McGruff
DevNet Master
Posts: 2893
Joined: Thu Jan 30, 2003 8:26 pm
Location: Glasgow, Scotland

MAC

Post by McGruff »

Message authenticity check.

Code: Select all

class Mac
{
    var $_private_key;  // (string)

    /*
        param (string)
    */
    function Mac($private_key)
    {
        $this->_private_key = $private_key;
    }
    /*
        An array arg allows the message to be supplied in parts.
        This is convenient if you want to store several pieces of data in the message.
        Named array keys will not be maintained - but order will be.
        param (array)
        return (string)
    */
    function signMessage($parts)
    {        
        $string  = implode('+', $parts) . '+';
        $string .= $this->_signature($string);
        return $string;
    }
    /*
        param (string)
        return (mixed) - an array of message parts or false if invalid
    */
    function getMessageParts($candidate_message)
    {
        $parts = explode('+', $candidate_message);
        $candidate_signature = array_pop($parts);        
        if($candidate_signature == $this->_signature(implode('+', $parts) . '+')) {
            return $parts;
        } else {
            return false;
        }
    }
    function _signature($string) 
    {
        return md5(md5($string) . $this->_private_key);
    }
}
And the test (using SimpleTest):

Code: Select all

class TestOfMac extends UnitTestCase 
{
    function TestOfMac() 
    {
        $this->UnitTestCase();
    }
    function testSinglePartMessage()
    {
        $mac =& new Mac('A private key.');
        $message = 'foo';
        $signed_message = $mac->signMessage(array($message));
        $last_char = substr($signed_message, -1);
        $first_char = $signed_message{0};
        $this->assertEqual($mac->getMessageParts($signed_message), array($message));
        $this->assertIdentical($mac->getMessageParts(substr($signed_message, 0, -1) . ++$last_char), false);
        $this->assertIdentical($mac->getMessageParts(++$first_char . substr($signed_message, 1)), false);
    }
    function testMultiplePartMessage()
    {
        $mac =& new Mac('A private key.');
        $message_parts = array('foo', 'bar');
        $signed_message = $mac->signMessage($message_parts);
        $last_char = substr($signed_message, -1);
        $first_char = $signed_message{0};
        $this->assertEqual($mac->getMessageParts($signed_message), $message_parts);
        $this->assertIdentical($mac->getMessageParts(substr($signed_message, 0, -1) . ++$last_char), false);
        $this->assertIdentical($mac->getMessageParts(++$first_char . substr($signed_message, 1)), false);
    }
    function testEmptyMessage()
    {
        $mac =& new Mac('A private key.');
        $message = '';
        $signed_message = $mac->signMessage(array($message));
        $last_char = substr($signed_message, -1);
        $this->assertEqual($mac->getMessageParts($signed_message), array($message));
        $this->assertIdentical($mac->getMessageParts(substr($signed_message, 0, -1) . ++$last_char), false);
        $this->assertIdentical($mac->getMessageParts('evil' . substr($signed_message, 1)), false);
    }
    function testMessageBuildingWithoutThePrivateKey()
    {
        $hacker_mac =& new Mac('A hacker doesn\'t know the private key even if they ' .
            'do know the digital signature algorithm.');
        $hacker_signed_message = $hacker_mac->signMessage(array('I\'ll be back.'));
        $my_mac =& new Mac('A private key.');
        $this->assertIdentical($my_mac->getMessageParts($hacker_signed_message), false);
    }

}
Post Reply