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);
}
}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);
}
}