Example #1
0
 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;
 }
Example #2
0
 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;
 }
Example #3
0
// 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);
print SecureString1::validate(http_build_query($parts), $keys) ? "same\n" : "different\n";
// and of course we can just directly tamper with it
$bad = $mac;
$bad[20] = '*';
// or anything, or add data or truncate
print SecureString1::validate($bad, $keys) ? "same\n" : "different\n";
print_r(substr(SecureString1::b64_urlencode(pack("L", mt_rand())), 0, 6));
print "\n";
 /**
  * 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 testSmoke()
 {
     $keys = array(1 => md5('whatever!'));
     $kid = 1;
     $random = new NotRandom();
     $cname = 'foo';
     $domain = 'client9.com';
     $path = '/';
     $secure = true;
     $httponly = true;
     $expiration = 86400;
     $sc = new SecureCookie($keys, $kid, $random, $cname, $domain, $path, $secure, $httponly, $expiration, $expiration, SecureCookie::ENCODE_NONE);
     // new cookie is not dirty
     $this->assertFalse($sc->dirty);
     // test non-exsistant property
     $this->assertEquals($sc->get('foo', 1), 1);
     $this->assertFalse($sc->dirty);
     // set and get property
     $sc->set('foo', 2);
     $this->assertEquals($sc->get('foo'), 2);
     $this->assertTrue($sc->dirty);
     // set and then unset
     $sc->set('ding', 'bat');
     $this->assertEquals($sc->get('ding'), 'bat');
     $sc->set('ding', null);
     $this->assertTrue(is_null($sc->get('ding')));
     // doing a read should wipe everything out
     $sc->read();
     $this->assertEquals($sc->get('foo', 1), 1);
     $sc->set('lead', 'gold');
     // fake time in seconds
     $now = 123456789;
     $str = $sc->_write($now);
     // since keys, salt, and time are all fixed this should
     // always be the same
     $expected = "lead=gold&_now=123456789&_slt=MTIzNDU2&_kid=1&_ver=1&_mac=fExl2Kj9ASCkVGvA7EfoOkc10RE5ehIwAXdzNJR6Jxc.";
     $this->assertEquals($str, $expected);
     //
     // TEST URL ENCODING
     //
     // write
     $sc = new SecureCookie($keys, $kid, $random, $cname, $domain, $path, $secure, $httponly, $expiration, $expiration, SecureCookie::ENCODE_URL);
     $sc->set('lead', 'gold');
     // new cookie is not dirty
     $this->assertTrue($sc->dirty);
     $now = 123456789;
     $str = $sc->_write($now);
     $this->assertEquals($str, urlencode($expected));
     // written out cookie is not dirty
     $this->assertFalse($sc->dirty);
     // read 1x
     $sc = new SecureCookie($keys, $kid, $random, $cname, $domain, $path, $secure, $httponly, $expiration, $expiration, SecureCookie::ENCODE_NONE);
     $_COOKIE[$cname] = urlencode($expected);
     $ok = $sc->read($now + 1);
     $this->assertEquals(SecureCookie::REASON_OK, $ok);
     // read 2x
     $sc = new SecureCookie($keys, $kid, $random, $cname, $domain, $path, $secure, $httponly, $expiration, $expiration, SecureCookie::ENCODE_NONE);
     $_COOKIE[$cname] = urlencode(urlencode($expected));
     $ok = $sc->read($now + 1);
     $this->assertEquals(SecureCookie::REASON_OK, $ok);
     // BASE 64
     // write 64
     $sc = new SecureCookie($keys, $kid, $random, $cname, $domain, $path, $secure, $httponly, $expiration, $expiration, SecureCookie::ENCODE_B64);
     $sc->set('lead', 'gold');
     $now = 123456789;
     $str = $sc->_write($now);
     $this->assertEquals($str, SecureString1::b64_urlencode($expected));
     // read base 64
     $sc = new SecureCookie($keys, $kid, $random, $cname, $domain, $path, $secure, $httponly, $expiration, $expiration, SecureCookie::ENCODE_NONE);
     $_COOKIE[$cname] = SecureString1::b64_urlencode($expected);
     $ok = $sc->read($now + 1);
     $this->assertEquals(SecureCookie::REASON_OK, $ok);
     // TAINT
     $str = SecureString1::b64_urlencode($expected);
     $str[10] = '*';
     // invalid char
     $_COOKIE[$cname] = $str;
     $ok = $sc->read($now + 1);
     $this->assertEquals(SecureCookie::REASON_INVALID, $ok);
     //
     // KEY PROBLEMS
     //
     //
     $sc = new SecureCookie($keys, $kid, $random, $cname, $domain, $path, $secure, $httponly, $expiration, $expiration, SecureCookie::ENCODE_NONE);
     $_COOKIE[$cname] = $expected;
     $ok = $sc->read($now + 1);
     $this->assertEquals(SecureCookie::REASON_OK, $ok);
     // test if the key is different
     $keys2 = array(1 => md5('different key'));
     $sc = new SecureCookie($keys2, $kid, $random, $cname, $domain, $path, $secure, $httponly, $expiration, $expiration, SecureCookie::ENCODE_NONE);
     $_COOKIE[$cname] = $expected;
     $ok = $sc->read($now + 1);
     $this->assertEquals(SecureCookie::REASON_INVALID, $ok);
     // let's try again but this time with a bad key id
     $keys2 = array(2 => md5('foo'));
     $sc = new SecureCookie($keys2, $kid, $random, $cname, $domain, $path, $secure, $httponly, $expiration, $expiration, SecureCookie::ENCODE_NONE);
     $_COOKIE[$cname] = $expected;
     $ok = $sc->read($now + 1);
     $this->assertEquals(SecureCookie::REASON_INVALID, $ok);
     //
     // EXPIRATION AND CLOCK SKEW
     //
     //
     $sc = new SecureCookie($keys, $kid, $random, $cname, $domain, $path, $secure, $httponly, $expiration, $expiration, SecureCookie::ENCODE_NONE);
     $_COOKIE[$cname] = $expected;
     $ok = $sc->read($now + $expiration + 1);
     $this->assertEquals(SecureCookie::REASON_EXPIRED, $ok);
     // clock skew
     $sc = new SecureCookie($keys, $kid, $random, $cname, $domain, $path, $secure, $httponly, $expiration, $expiration, SecureCookie::ENCODE_NONE);
     $_COOKIE[$cname] = $expected;
     $ok = $sc->read($now - $expiration);
     $this->assertEquals(SecureCookie::REASON_CLOCK_SKEW, $ok);
 }