public function write($ary, $now = 0) { // for this sample, we'll strip out meta data unset($ary[SecureString1::PREFIX_VERSION]); unset($ary[SecureString1::PREFIX_CREATED]); unset($ary[SecureString1::PREFIX_KEYID]); unset($ary[SecureString1::PREFIX_SALT]); unset($ary[SecureString1::PREFIX_MAC]); $payload = http_build_query($ary); // this is a "ok" 24-bit salt represent as 6 characters // (the substr is to remove padding chars which aren't useful here) // // A BETTER solution is use the DevUrandom // $salt = substr(SecureString1::b64_urlencode(pack("L", mt_rand())), 0, 6); $str = SecureString1::create($payload, $salt, $this->keys, $this->kid, $now); // grab cookie or URL from environment // since this is sample we'll just pull from global env $GLOBALS['userdata'] = $str; }
/** * what happens when the SS meta data fields are in the * payload? * * Not sure I like this behavior, but I'm just documenting it. * parse_str overwrites the original value when a key is duplicated * parse_str has all sorts of other issues. */ public function testPhpParseStrBehavior() { $keys = array(1 => hash('md5', 'this is my secret key', true)); $salt = '1234567890'; $macd = SecureString1::create(SecureString1::PREFIX_VERSION . '100' . SecureString1::PREFIX_CREATED . 'blah' . SecureString1::PREFIX_KEYID . '666', $salt, $keys, 1); $this->assertTrue(SecureString1::validate($macd, $keys)); parse_str($macd, $parts); $this->assertEquals($parts['_ver'], 1); $this->assertEquals($parts['_kid'], 1); $this->assertNotEquals($parts['_now'], 'blah'); }
public function _write($now) { $this->dirty = FALSE; $ary = $this->payload; // we'll strip out meta data unset($ary[SecureString1::PREFIX_VERSION]); unset($ary[SecureString1::PREFIX_CREATED]); unset($ary[SecureString1::PREFIX_KEYID]); unset($ary[SecureString1::PREFIX_SALT]); unset($ary[SecureString1::PREFIX_MAC]); $payload = http_build_query($ary); $salt = SecureString1::b64_urlencode($this->random->bytes(6)); $str = SecureString1::create($payload, $salt, $this->keys, $this->kid, $now); switch ($this->encoding) { case self::ENCODE_B64: $str = SecureString1::b64_urlencode($str); break; case self::ENCODE_URL: $str = urlencode($str); break; } return $str; }
#!/usr/bin/env php <?php include 'SecureString1.php'; // here some data $data = array('foo' => 'bar', 'ding' => 'bat', 'cow' => 'milk'); // turn it into a query string $qs = http_build_query($data); print $qs . "\n"; // ok here's some keys..... ideally from a config file // notice how the plain-text secret is md5'd to scramble the bits $keys = array(1 => hash('md5', "this is my secret key 1", true)); $mac = SecureString1::create($qs, $keys, 1); print $mac . "\n"; // if we do it again, the MAC is different (due to the salting) $mac = SecureString1::create($qs, $keys, 1); print $mac . "\n"; // the SecureString perserves query string formating // so you can break it apart just like this: parse_str($mac, $parts); // and now you have all the meta data in addition to your // data. print_r($parts); // Nice thing about PHP is that the associative array // keeps order. So we can reassemble the parts as is // and it still validates // print SecureString1::validate(http_build_query($parts), $keys) ? "same\n" : "different\n"; // like wise we can tamper with one element // and it won't re-validate $parts['cow'] = 'juice'; print_r($parts);