/** * Verify the bundled assertion * * Verifies if the bundled assertion is valid. * * @access public * @param int $now Unix timestamp in milliseconds * @return array Containing the array of certificates as 'certChain', the additional assertion payload as 'payload' and an assertion object as 'assertion' */ public function verify($now) { // no certs? not okay if (sizeof($this->certs) == 0) { throw new \Exception("no certificates provided"); } // simplify error message try { // verify the chain $certChain = $this->verifyChain($now); } catch (Exception $e) { $err = $e->getMessage(); // allow through the malformed signature if ($err == 'malformed signature' || $err == "assertion issued later than verification date" || $err == "assertion has expired") { throw $e; } else { throw new \Exception("bad signature in chain"); } } // what was the last PK in the successful chain? $lastPK = $certChain[sizeof($certChain) - 1]->getCertParams()->getPublicKey(); $token = WebToken::parse($this->signedAssertion); if (!$token->verify($lastPK)) { throw new \Exception("signed assertion was not valid signed"); } // now verify the assertion $payload = $token->getPayload(); $assertion = Assertion::deserialize($payload); if (!$assertion->verify($now)) { throw new \Exception("assertion is not valid"); } return array("certChain" => $certChain, "payload" => $payload, "assertion" => $assertion); }
<pre> <?php // Comment the following line out to test the script! die; error_reporting(0); require_once "../lib/browserid.php"; $publicKeyIdentity = AbstractPublicKey::deserialize('{"algorithm":"DS","p":"ff600483db6abfc5b45eab78594b3533d550d9f1bf2a992a7a8daa6dc34f8045ad4e6e0c429d334eeeaaefd7e23d4810be00e4cc1492cba325ba81ff2d5a5b305a8d17eb3bf4a06a349d392e00d329744a5179380344e82a18c47933438f891e22aeef812d69c8f75e326cb70ea000c3f776dfdbd604638c2ef717fc26d02e17","q":"e21e04f911d1ed7991008ecaab3bf775984309c3","g":"c52a4a0ff3b7e61fdf1867ce84138369a6154f4afa92966e3c827e25cfa6cf508b90e5de419e1337e07a2e9e2a3cd5dea704d175f8ebf6af397d69e110b96afb17c7a03259329e4829b0d03bbc7896b15b4ade53e130858cc34d96269aa89041f409136c7242a38895c9d5bccad4f389af1d7a4bd1398bd072dffa896233397a","y":"80942e74d41162e7ab30bb4a7a1e0fb0417aad0a1b55b12e0232618502a2552510d631a02a679e60787b12799215b9c35865efb4c86b56584bf85c31f886b25413dc7ef028917e9afbe35726849cfe28a43fba6cdd8e24f4575d5d582317183599c23399e90f10b7e5c0f2bcf7a37e0559dbe492a17a74a49597b0996a2b616d"}'); $secretKeyIdentity = AbstractSecretKey::deserialize('{"algorithm":"DS","p":"ff600483db6abfc5b45eab78594b3533d550d9f1bf2a992a7a8daa6dc34f8045ad4e6e0c429d334eeeaaefd7e23d4810be00e4cc1492cba325ba81ff2d5a5b305a8d17eb3bf4a06a349d392e00d329744a5179380344e82a18c47933438f891e22aeef812d69c8f75e326cb70ea000c3f776dfdbd604638c2ef717fc26d02e17","q":"e21e04f911d1ed7991008ecaab3bf775984309c3","g":"c52a4a0ff3b7e61fdf1867ce84138369a6154f4afa92966e3c827e25cfa6cf508b90e5de419e1337e07a2e9e2a3cd5dea704d175f8ebf6af397d69e110b96afb17c7a03259329e4829b0d03bbc7896b15b4ade53e130858cc34d96269aa89041f409136c7242a38895c9d5bccad4f389af1d7a4bd1398bd072dffa896233397a","x":"a8e62a39c007ab3b7fbaad2e51398c15ec4a720c"}'); $principal = $_REQUEST['principal']; $audience = $_REQUEST['audience']; echo "Usage: createBundle.php?principal=<principal>&audience=<audience>\r\n"; echo "Allowed keysizes: 64, 128, 256!\r\n"; $assertion = CertAssertion::createAssertion($audience, $secretKeyIdentity); echo "Assertion: "; var_dump(WebToken::parse($assertion)->getPayload()); echo "\r\n"; $identityCert = CertAssertion::createIdentityCert($principal, $publicKeyIdentity); echo "Identity Cert: "; var_dump(WebToken::parse($identityCert)->getPayload()); echo "\r\n"; $bundle = new CertBundle($assertion, array($identityCert)); $assertion = $bundle->bundle(); echo "Bundle: "; var_dump($assertion); echo "\r\n"; $certAssertion = new CertAssertion($assertion, $audience); echo "isValid: "; var_dump($certAssertion->isValid()); ?> </pre>
/** * Get the public key of the basic support document of the identity provider * * @param optional string $name The basename of the certificate or null for default * @param optional string $dir The directory to the certificate or null for default * @return object An instance of the basic support document containing the public key or null */ static function readAndParseCert($name = null, $dir = null) { $p = Secrets::getPathPublicKey($name, $dir); $cert = null; // may throw $cert = @file_get_contents($p); if (!$cert) { return null; } try { // parse it // it should be a JSON structure with alg and serialized key // {alg: <ALG>, value: <SERIALIZED_KEY>} $payloadSegment = WebToken::parse($cert)->getPayloadSegment(); return json_decode(Utils::base64url_decode($payloadSegment), true); } catch (Exception $e) { return null; } }
/** * Sign assertion * * Sign and serialize the assertion using the users secret key belonging to his * identity certificate. * * @access public * @param type $secretKey Secret key of the identity certificate * @param array $additionalPayload Additional payload * @return string Signed assertion */ public function sign($secretKey, $additionalPayload = null) { $allParams = array(); if ($additionalPayload != null) { $allParams = array_merge($allParams, $additionalPayload); } $allParams = $this->serialize($allParams); $token = new WebToken($allParams); return $token->serialize($secretKey); }
<?php // Comment the following line out to test the script! die; error_reporting(0); require_once "../lib/browserid.php"; $name = $_REQUEST["name"]; $keysize = (int) $_REQUEST["keysize"]; echo "Usage: createKeys.php?name=<name>&keysize=<keysize>\r\n"; echo "Allowed keysizes: 64, 128, 256!\r\n"; // Generate keypair: echo "Generate key pair with keysize {$keysize}...\r\n"; $pair = RSAKeyPair::generate($keysize); echo "Keys were generated!\r\n"; // Write secret key to file: echo "Write Secret Key...\r\n"; $pathSecretKey = Secrets::getPathSecretKey($name); $handle = fopen($pathSecretKey, "w+"); fwrite($handle, $pair->getSecretKey()->serialize()); fclose($handle); echo "Secret Key was written to " . $pathSecretKey . "\r\n"; // Write public key to file: echo "Write Public Key...\r\n"; $pathPublicKey = Secrets::getPathPublicKey($name); $public = array("public-key" => json_decode($pair->getPublicKey()->serialize(), true)); $token = new WebToken($public); $handle = fopen($pathPublicKey, "w+"); fwrite($handle, $token->serialize($pair->getSecretKey())); fclose($handle); echo "Public Key was written to " . $pathPublicKey . "\r\n"; ?> </pre>
/** * Parse serialized identity certificate * * Parses a serialized, signed identity certificate and check if it's valid by * checking the signature against the public key of the issuer. * * @access public * @static * @param string $signedObject Signed identity certificate * @param AbstractPublicKey $publicKey Public key of the issuer * @return Cert Instance of the identity certificate */ public static function parse($signedObject, $publicKey) { $token = WebToken::parse($signedObject); // try { if (!$token->verify($publicKey)) { throw new \Exception("cert was not valid signed"); } /* } catch (\Exception $x) { // can't extract components throw new \Exception("cert was not valid signed"); }*/ $params = $token->getPayload(); return Cert::deserialize($params); }