| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250 | 
							- <?php
 - 
 - namespace Macaroons;
 - 
 - use Macaroons\Exceptions\InvalidMacaroonKeyException;
 - 
 - class Macaroon
 - {
 -   private $id;
 -   private $location;
 -   private $signature;
 -   private $caveats = array();
 - 
 -   public function __construct($key, $identifier, $location)
 -   {
 -     $this->identifier = $identifier;
 -     $this->location = $location;
 -     $this->signature = $this->initialSignature($key, $identifier);
 -   }
 - 
 -   public function getIdentifier()
 -   {
 -     return $this->identifier;
 -   }
 - 
 -   public function getLocation()
 -   {
 -     return $this->location;
 -   }
 - 
 -   public function getSignature()
 -   {
 -     return strtolower( Utils::hexlify( $this->signature ) );
 -   }
 - 
 -   public function getFirstPartyCaveats()
 -   {
 -     return array_filter($this->caveats, function(Caveat $caveat){
 -       return $caveat->isFirstParty();
 -     });
 -   }
 - 
 -   public function getThirdPartyCaveats()
 -   {
 -     return array_filter($this->caveats, function(Caveat $caveat){
 -       return $caveat->isThirdParty();
 -     });
 -   }
 - 
 -   public function getCaveats()
 -   {
 -     return $this->caveats;
 -   }
 - 
 -   public function setSignature($signature)
 -   {
 -     if (!isset($signature))
 -       throw new \InvalidArgumentException('Must supply updated signature');
 -     $this->signature = $signature;
 -   }
 - 
 -   public function setCaveats(Array $caveats)
 -   {
 -     $this->caveats = $caveats;
 -   }
 - 
 -   public function addFirstPartyCaveat($predicate)
 -   {
 -     array_push($this->caveats, new Caveat($predicate));
 -     $this->signature = Utils::signFirstPartyCaveat($this->signature, $predicate);
 -   }
 - 
 -   public function addThirdPartyCaveat($caveatKey, $caveatId, $caveatLocation)
 -   {
 -     $derivedCaveatKey = Utils::truncateOrPad( Utils::generateDerivedKey($caveatKey) );
 -     $truncatedOrPaddedSignature = Utils::truncateOrPad( $this->signature );
 -     // Generate cipher using libsodium
 -     $nonce = \Sodium\randombytes_buf(\Sodium\CRYPTO_SECRETBOX_NONCEBYTES);
 -     $verificationId = $nonce . \Sodium\crypto_secretbox($derivedCaveatKey, $nonce, $truncatedOrPaddedSignature);
 -     array_push($this->caveats, new Caveat($caveatId, $verificationId, $caveatLocation));
 -     $this->signature = Utils::signThirdPartyCaveat($this->signature, $verificationId, $caveatId);
 -     \Sodium\memzero($caveatKey);
 -     \Sodium\memzero($derivedCaveatKey);
 -     \Sodium\memzero($caveatId);
 -   }
 - 
 -   /**
 -    * [prepareForRequest description]
 -    * @param  Macaroon $macaroon
 -    * @return Macaroon           bound Macaroon (protected discharge)
 -    */
 -   public function prepareForRequest(Macaroon $macaroon)
 -   {
 -     $boundMacaroon = clone $macaroon;
 -     $boundMacaroon->setSignature($this->bindSignature($macaroon->getSignature()));
 -     return $boundMacaroon;
 -   }
 - 
 -   /**
 -    * [bindSignature description]
 -    * @param  string $signature
 -    * @return string
 -    */
 -   public function bindSignature($signature)
 -   {
 -     $key                  = Utils::truncateOrPad("\0");
 -     $currentSignatureHash = Utils::hmac($key, Utils::unhexlify($this->getSignature()));
 -     $newSignatureHash     = Utils::hmac($key, Utils::unhexlify($signature));
 -     return Utils::hmac($key, $currentSignatureHash . $newSignatureHash);
 -   }
 - 
 -   public function inspect()
 -   {
 -     $str = "location {$this->location}\n";
 -     $str .= "identifier {$this->identifier}\n";
 -     foreach ($this->caveats as $caveat)
 -     {
 -       $str .= "$caveat\n";
 -     }
 -     $str .= "signature {$this->getSignature()}";
 -     return $str;
 -   }
 - 
 -   private function initialSignature($key, $identifier)
 -   {
 -     return Utils::hmac( Utils::generateDerivedKey($key), $identifier);
 -   }
 - 
 -   // TODO: Move these into a separate object
 -   public function serialize()
 -   {
 -     $p = new Packet();
 -     $s = $p->packetize(
 -                         array(
 -                           'location' => $this->location,
 -                           'identifier' => $this->identifier
 -                         )
 -                       );
 -     foreach ($this->caveats as $caveat)
 -     {
 -       $caveatKeys = array(
 -                           'cid' => $caveat->getCaveatId()
 -                           );
 -       if ($caveat->getVerificationId() && $caveat->getCaveatLocation())
 -       {
 -         $caveatKeys = array_merge(
 -                                   $caveatKeys,
 -                                   array(
 -                                         'vid' => $caveat->getVerificationId(),
 -                                         'cl' => $caveat->getCaveatLocation()
 -                                         )
 -                                   );
 -       }
 -       $p = new Packet();
 -       $s = $s . $p->packetize($caveatKeys);
 -     }
 -     $p = new Packet();
 -     $s = $s . $p->packetize(array('signature' => $this->signature));
 -     return Utils::base64_url_encode($s);
 -   }
 - 
 -   public static function deserialize($serialized)
 -   {
 -     $location   = NULL;
 -     $identifier = NULL;
 -     $signature  = NULL;
 -     $caveats    = array();
 -     $decoded    = Utils::base64_url_decode($serialized);
 -     $index      = 0;
 - 
 -     while ($index < strlen($decoded))
 -     {
 -       // TOOD: Replace 4 with PACKET_PREFIX_LENGTH
 -       $packetLength    = hexdec(substr($decoded, $index, 4));
 -       $packetDataStart = $index + 4;
 -       $strippedPacket  = substr($decoded, $packetDataStart, $packetLength - 5);
 -       $packet          = new Packet();
 -       $packet          = $packet->decode($strippedPacket);
 - 
 -       switch($packet->getKey())
 -       {
 -         case 'location':
 -           $location = $packet->getData();
 -         break;
 -         case 'identifier':
 -           $identifier = $packet->getData();
 -         break;
 -         case 'signature':
 -           $signature = $packet->getData();
 -         break;
 -         case 'cid':
 -           array_push($caveats, new Caveat($packet->getData()));
 -         break;
 -         case 'vid':
 -           $caveat = $caveats[ count($caveats) - 1 ];
 -           $caveat->setVerificationId($packet->getData());
 -         break;
 -         case 'cl':
 -           $caveat = $caveats[ count($caveats) - 1 ];
 -           $caveat->setCaveatLocation($packet->getData());
 -         break;
 -         default:
 -           throw new InvalidMacaroonKeyException('Invalid key in binary macaroon. Macaroon may be corrupted.');
 -         break;
 -       }
 -       $index = $index + $packetLength;
 -     }
 -     $m = new Macaroon('no_key', $identifier, $location);
 -     $m->setCaveats($caveats);
 -     $m->setSignature($signature);
 -     return $m;
 -   }
 - 
 -   public function toJSON()
 -   {
 -     return json_encode(array(
 -       'location' => $this->location,
 -       'identifier' => $this->identifier,
 -       'caveats' => array_map(function(Caveat $caveat){
 -         $caveatAsArray = $caveat->toArray();
 -         if ($caveat->isThirdParty())
 -           $caveatAsArray['vid'] = Utils::hexlify($caveatAsArray['vid']);
 -         return $caveatAsArray;
 -       }, $this->getCaveats()),
 -       'signature' => $this->getSignature()
 -     ));
 -   }
 - 
 -   public static function fromJSON($serialized)
 -   {
 -     $data       = json_decode($serialized);
 -     $location   = $data->location;
 -     $identifier = $data->identifier;
 -     $signature  = $data->signature;
 -     $m          = new Macaroon(
 -                                 'no_key',
 -                                 $identifier,
 -                                 $location
 -                               );
 -     $caveats = array_map(function(stdClass $data){
 -       $caveatId       = $data->cid;
 -       $verificationId = $data->vid;
 -       $caveatLocation = $data->cl;
 -       return new Caveat($caveatId, $verificationId, $caveatLocation);
 -     }, $data->caveats);
 -     $m->setCaveats($caveats);
 -     $m->setSignature(Utils::unhexlify($signature));
 -     return $m;
 -   }
 - }
 
 
  |