Exemplo n.º 1
0
 /**
  * This is essentially the openid association flow where two parties
  * establish an shared secret. Only the server/client public key and mac key
  * are transfered over the wire. The shared secret can then be used to
  * encrypt or sign data
  */
 public function testDhComputeKey()
 {
     if (getenv('TRAVIS_PHP_VERSION') == 'hhvm') {
         $this->markTestSkipped('Key type DH is not supported');
     }
     // both parties must know these parameters
     $p = pack('H*', 'dcf93a0b883972ec0e19989ac5a2ce310e1d37717e8d9571bb7623731866e61ef75a2e27898b057f9891c2e27a639c3f29b60814581cd3b2ca3986d2683705577d45c2e7e52dc81c7a171876e5cea74b1448bfdfaf18828efd2519f14e45e3826634af1949e5b535cc829a483b8a76223e5d490a257f05bdff16f2fb22c583ab');
     $g = pack('H*', '02');
     $dhFunc = 'SHA256';
     // the client generates a new key
     $clientKey = new PKey(array('private_key_type' => OPENSSL_KEYTYPE_DH, 'dh' => array('p' => $p, 'g' => $g)));
     $details = $clientKey->getDetails();
     $clientPublicKey = $details['dh']['pub_key'];
     // the server receives the public key of the client
     // the server generates a random secret
     $secret = OpenSsl::randomPseudoBytes(32);
     // the server creates a new key
     $serverKey = new PKey(array('private_key_type' => OPENSSL_KEYTYPE_DH, 'dh' => array('p' => $p, 'g' => $g)));
     $details = $serverKey->getDetails();
     $serverPublicKey = $details['dh']['pub_key'];
     // the server generates the dh key
     $dhKey = OpenSsl::dhComputeKey($clientPublicKey, $serverKey);
     $digest = OpenSsl::digest($dhKey, $dhFunc, true);
     $macKey = $digest ^ $secret;
     // the client receives the public key and mac key of the server
     $dhKey = OpenSsl::dhComputeKey($serverPublicKey, $clientKey);
     $digest = OpenSsl::digest($dhKey, $dhFunc, true);
     $result = $digest ^ $macKey;
     // we have established a shared secret
     $this->assertEquals($secret, $result);
 }
Exemplo n.º 2
0
 public function testFlow()
 {
     $consumerRequest = $this->generateConsumerRequest();
     // association request
     $data = $this->doAssociation($consumerRequest['modulus'], $consumerRequest['gen'], $consumerRequest['consumer_public']);
     // we received the encrypted secret over the wire. The client can now
     // decrypt the secret
     $assocHandle = $data['assoc_handle'];
     $assocType = $data['assoc_type'];
     $serverPublicKey = $data['dh_server_public'];
     $encMacKey = $data['enc_mac_key'];
     $this->assertTrue(!empty($assocHandle));
     $this->assertTrue(!empty($assocType));
     $this->assertTrue(!empty($serverPublicKey));
     $this->assertTrue(!empty($encMacKey));
     $serverPub = base64_decode($serverPublicKey);
     $dhSec = OpenSsl::dhComputeKey($serverPub, $consumerRequest['pkey']);
     $sec = OpenSsl::digest(ProviderAbstract::btwoc($dhSec), 'SHA1', true);
     $serverSecret = base64_encode($sec ^ base64_decode($data['enc_mac_key']));
     // the client has established the association we can make now an
     // checkid setup request. If the user is authenticated he gets
     // redirected back to the relying party
     $url = $this->doCheckidSetupRequest($assocHandle);
     // later the relying party calls check authentication to verify the
     // callback
     $this->doCheckAuthentication($url);
 }
Exemplo n.º 3
0
 public function testDhSha1()
 {
     // generate consumer
     $request = $this->generateConsumerRequest();
     // generate server
     $dhGen = $request['gen'];
     $dhModulus = $request['modulus'];
     $dhConsumerPub = $request['consumer_public'];
     $dhFunc = 'SHA1';
     $secret = ProviderAbstract::randomBytes(20);
     $res = ProviderAbstract::generateDh($dhGen, $dhModulus, $dhConsumerPub, $dhFunc, $secret);
     $this->assertEquals(true, isset($res['pubKey']));
     $this->assertEquals(true, isset($res['macKey']));
     // calculate consumer
     $serverPub = base64_decode($res['pubKey']);
     $dhSec = OpenSsl::dhComputeKey($serverPub, $request['pkey']);
     $sec = OpenSsl::digest(ProviderAbstract::btwoc($dhSec), $dhFunc, true);
     $serverSecret = $sec ^ base64_decode($res['macKey']);
     // compare with server
     $this->assertEquals(true, $secret === $serverSecret);
 }
Exemplo n.º 4
0
 /**
  * Tries to establish a association with the op if a store is available. The
  * method returns null or PSX\OpenId\Provider\Data\Association. Discovery
  * must be made before calling this method
  *
  * @return PSX\OpenId\Provider\Data\Association|null
  */
 private function establishAssociaton($assocType = 'HMAC-SHA256', $sessionType = 'DH-SHA256')
 {
     // request association
     $g = pack('H*', ProviderAbstract::DH_G);
     $p = pack('H*', ProviderAbstract::DH_P);
     $pkey = new PKey(array('private_key_type' => OPENSSL_KEYTYPE_DH, 'dh' => array('p' => $p, 'g' => $g)));
     $details = $pkey->getDetails();
     $params = array('openid.ns' => ProviderAbstract::NS, 'openid.mode' => 'associate', 'openid.assoc_type' => $assocType, 'openid.session_type' => $sessionType, 'openid.dh_modulus' => base64_encode(ProviderAbstract::btwoc($details['dh']['p'])), 'openid.dh_gen' => base64_encode(ProviderAbstract::btwoc($details['dh']['g'])), 'openid.dh_consumer_public' => base64_encode(ProviderAbstract::btwoc($details['dh']['pub_key'])));
     $request = new PostRequest($this->identity->getServer(), array('User-Agent' => __CLASS__ . ' ' . Base::VERSION), $params);
     $response = $this->http->request($request);
     if ($response->getStatusCode() == 200) {
         $data = self::keyValueDecode($response->getBody());
         // check values
         $diff = array_diff(array('ns', 'assoc_handle', 'session_type', 'assoc_type', 'expires_in'), array_keys($data));
         if (count($diff) > 0) {
             throw new Exception('Missing fields ' . implode(', ', $diff));
         }
         if ($data['ns'] != ProviderAbstract::NS) {
             throw new Exception('Invalid namesspace');
         }
         if (!in_array($data['session_type'], self::$supportedSessionTypes)) {
             throw new Exception('Invalid session type');
         }
         if (!in_array($data['assoc_type'], self::$supportedAssocTypes)) {
             throw new Exception('Invalid assoc type');
         }
         // decrypt shared secret
         if ($data['session_type'] != 'no-encryption') {
             if (!isset($data['dh_server_public'])) {
                 throw new Exception('DH server public not set');
             }
             if (!isset($data['enc_mac_key'])) {
                 throw new Exception('Encoded mac key not set');
             }
             $dhFunc = str_replace('DH-', '', $data['session_type']);
             $serverPub = base64_decode($data['dh_server_public']);
             $dhSec = OpenSsl::dhComputeKey($serverPub, $pkey);
             $sec = OpenSsl::digest(ProviderAbstract::btwoc($dhSec), $dhFunc, true);
             $serverSecret = base64_encode($sec ^ base64_decode($data['enc_mac_key']));
         } else {
             if (!isset($data['mac_key'])) {
                 throw new Exception('Mac key not set');
             }
             $dhFunc = null;
             $serverSecret = $data['mac_key'];
         }
         // build association
         $assoc = new Association();
         $assoc->setAssocHandle($data['assoc_handle']);
         $assoc->setAssocType($data['assoc_type']);
         $assoc->setSessionType($data['session_type']);
         $assoc->setSecret($serverSecret);
         $assoc->setExpire($data['expires_in']);
         return $assoc;
     } else {
         throw new Exception('Could not establish associaton received ' . $response->getStatusCode());
     }
 }
Exemplo n.º 5
0
 public static function generateDh($dhGen, $dhModulus, $dhConsumerPublic, $dhFunc, $secret)
 {
     if (empty($dhConsumerPublic)) {
         throw new Exception('Empty "openid.dh_consumer_public"');
     }
     $g = empty($dhGen) ? pack('H*', self::DH_G) : base64_decode($dhGen);
     $p = empty($dhModulus) ? pack('H*', self::DH_P) : base64_decode($dhModulus);
     $dhKey = self::createDhKey($p, $g);
     $details = $dhKey->getDetails();
     $dh = isset($details['dh']) ? $details['dh'] : null;
     if (empty($dh)) {
         throw new Exception('Could not get dh details');
     }
     $sec = OpenSsl::dhComputeKey(base64_decode($dhConsumerPublic), $dhKey);
     $digest = OpenSsl::digest(self::btwoc($sec), $dhFunc, true);
     $res = array('pubKey' => base64_encode(self::btwoc($dh['pub_key'])), 'macKey' => base64_encode($digest ^ $secret));
     return $res;
 }