public function authenticate(Store\Iface $storage)
 {
     $digest = isset($_SERVER['PHP_AUTH_DIGEST']) ? $_SERVER['PHP_AUTH_DIGEST'] : '';
     $request_method = isset($_SERVER['REQUEST_METHOD']) ? $_SERVER['REQUEST_METHOD'] : '';
     if (!preg_match('/username="******"]+)"/', $digest, $username) || !preg_match('/nonce="([^"]+)"/', $digest, $nonce) || !preg_match('/response="([^"]+)"/', $digest, $response) || !preg_match('/opaque="([^"]+)"/', $digest, $opaque) || !preg_match('/uri="([^"]+)"/', $digest, $uri)) {
         return FALSE;
     }
     $username = $username[1];
     $nonce = $nonce[1];
     $response = $response[1];
     $opaque = $opaque[1];
     $uri = $uri[1];
     $password = $storage->get($username);
     if (strlen($password) < 1) {
         return FALSE;
     }
     $A1 = !$this->isMd5($password) ? $this->hashPassword($username, $password) : $password;
     $A2 = md5($request_method . ':' . $uri);
     if (preg_match('/qop="?([^,\\s"]+)/', $digest, $qop) && preg_match('/nc=([^,\\s"]+)/', $digest, $nc) && preg_match('/cnonce="([^"]+)"/', $digest, $cnonce)) {
         $valid_response = md5($A1 . ':' . $nonce . ':' . $nc[1] . ':' . $cnonce[1] . ':' . $qop[1] . ':' . $A2);
     } else {
         $valid_response = md5($A1 . ':' . $nonce . ':' . $A2);
     }
     if ($response != $valid_response) {
         return FALSE;
     }
     return $username;
 }
 public static function bulkLoad(Iface $storage, array $keys)
 {
     $response = $storage->get($keys);
     $list = array();
     foreach ($keys as $key) {
         $entity = isset($response[$key]) ? $response[$key] : array();
         $entity["._entity"] = $key;
         $list[$key] = new self($storage, $entity);
     }
     return $list;
 }