Esempio n. 1
0
 public function testGenerationOfTheSigninInput()
 {
     $payload = array('a' => 'b');
     $header = array('a' => 'b');
     $jwt = new JWT($payload, $header);
     $encoder = new Base64UrlSafeEncoder();
     $this->assertEquals(sprintf("%s.%s", $encoder->encode(json_encode($payload)), $encoder->encode(json_encode($header))), $jwt->generateSigninInput());
 }
Esempio n. 2
0
 public function testGenerationOfTheSigninInputCanHandleSlashes()
 {
     $encoder = new Base64UrlSafeEncoder();
     $json_string = '{"a":"/b/"}';
     $encoded_json_string = $encoder->encode($json_string);
     $jwt = new JWT(json_decode($json_string, true), json_decode($json_string, true));
     $this->assertEquals(sprintf('%s.%s', $encoded_json_string, $encoded_json_string), $jwt->generateSigninInput());
 }
Esempio n. 3
0
/**
 * Generates the payload which must be provided in challenges, e.g. HTTP-01 and DNS-01.
 *
 * @api
 * @param KeyPair $accountKeyPair account key pair
 * @param string  $token challenge token
 * @return string payload to be provided at /.well-known/acme-challenge/$token for HTTP-01 and _acme-challenge.example.com for DNS-01
 * @throws AcmeException If something went wrong.
 * @see https://github.com/ietf-wg-acme/acme/blob/master/draft-ietf-acme-acme.md#key-authorizations
 */
function generateKeyAuthorization(KeyPair $accountKeyPair, $token)
{
    if (!is_string($token)) {
        throw new InvalidArgumentException(sprintf("\$token must be of type string, %s given.", gettype($token)));
    }
    if (!($privateKey = openssl_pkey_get_private($accountKeyPair->getPrivate()))) {
        throw new AcmeException("Couldn't read private key.");
    }
    if (!($details = openssl_pkey_get_details($privateKey))) {
        throw new AcmeException("Couldn't get private key details.");
    }
    if ($details["type"] !== OPENSSL_KEYTYPE_RSA) {
        throw new AcmeException("Key type not supported, only RSA supported currently.");
    }
    $enc = new Base64UrlSafeEncoder();
    $payload = ["e" => $enc->encode($details["rsa"]["e"]), "kty" => "RSA", "n" => $enc->encode($details["rsa"]["n"])];
    return $token . "." . $enc->encode(hash("sha256", json_encode($payload), true));
}
Esempio n. 4
0
 private function doPost(string $resource, array $payload) : Generator
 {
     $privateKey = openssl_pkey_get_private($this->keyPair->getPrivate());
     $details = openssl_pkey_get_details($privateKey);
     if ($details["type"] !== OPENSSL_KEYTYPE_RSA) {
         throw new \RuntimeException("Only RSA keys are supported right now.");
     }
     $uri = (yield $this->getResourceUri($resource));
     $enc = new Base64UrlSafeEncoder();
     $jws = new SimpleJWS(["alg" => "RS256", "jwk" => ["kty" => "RSA", "n" => $enc->encode($details["rsa"]["n"]), "e" => $enc->encode($details["rsa"]["e"])], "nonce" => (yield $this->getNonce($uri))]);
     $payload["resource"] = $payload["resource"] ?? $resource;
     $jws->setPayload($payload);
     $jws->sign($privateKey);
     $request = (new Request())->setMethod("POST")->setUri($uri)->setBody($jws->getTokenString());
     $response = (yield $this->http->request($request));
     $this->saveNonce($response);
     return $response;
 }
Esempio n. 5
0
 public function generateHttp01Payload(string $token) : string
 {
     if (!($privateKey = openssl_pkey_get_private($this->accountKeyPair->getPrivate()))) {
         throw new AcmeException("Couldn't read private key");
     }
     if (!($details = openssl_pkey_get_details($privateKey))) {
         throw new AcmeException("Couldn't get private key details");
     }
     if ($details["type"] !== OPENSSL_KEYTYPE_RSA) {
         throw new AcmeException("Key type not supported, only RSA supported currently");
     }
     $enc = new Base64UrlSafeEncoder();
     $payload = ["e" => $enc->encode($details["rsa"]["e"]), "kty" => "RSA", "n" => $enc->encode($details["rsa"]["n"])];
     return $token . "." . $enc->encode(hash("sha256", json_encode($payload), true));
 }
Esempio n. 6
0
/**
 * Encodes a key authorization for use in the DNS-01 challenge as TXT payload.
 *
 * @api
 * @param string $keyAuthorization key authorization generated using `generateKeyAuthorization`
 * @return string Base64Url-encoded SHA256 digest of the `$keyAuthorization`
 * @see https://tools.ietf.org/html/draft-ietf-acme-acme-01#section-7.5
 */
function generateDns01Payload($keyAuthorization)
{
    $encoder = new Base64UrlSafeEncoder();
    return $encoder->encode(hash("sha256", $keyAuthorization, true));
}
Esempio n. 7
0
 private function doPost($resource, array $payload)
 {
     if (!is_string($resource)) {
         throw new InvalidArgumentException(sprintf("\$resource must be of type string, %s given.", gettype($resource)));
     }
     $privateKey = openssl_pkey_get_private($this->keyPair->getPrivate());
     $details = openssl_pkey_get_details($privateKey);
     if ($details["type"] !== OPENSSL_KEYTYPE_RSA) {
         throw new \RuntimeException("Only RSA keys are supported right now.");
     }
     $uri = (yield $this->getResourceUri($resource));
     $atempt = 0;
     do {
         $attempt++;
         if ($attempt > 3) {
             throw new AcmeException("POST request to {$uri} failed, received too many badNonce errors.");
         }
         $enc = new Base64UrlSafeEncoder();
         $jws = new SimpleJWS(["alg" => "RS256", "jwk" => ["kty" => "RSA", "n" => $enc->encode($details["rsa"]["n"]), "e" => $enc->encode($details["rsa"]["e"])], "nonce" => (yield $this->getNonce($uri))]);
         $payload["resource"] = isset($payload["resource"]) ? $payload["resource"] : $resource;
         $jws->setPayload($payload);
         $jws->sign($privateKey);
         $request = (new Request())->setMethod("POST")->setUri($uri)->setBody($jws->getTokenString());
         try {
             $response = (yield $this->http->request($request));
             $this->saveNonce($response);
             if ($response->getStatus() === 400) {
                 $info = json_decode($response->getBody());
                 if ($info && isset($info->type) && $info->type === "urn:acme:badNonce") {
                     continue;
                 }
             }
         } catch (Exception $e) {
             throw new AcmeException("POST request to {$uri} failed.", null, $e);
         } catch (Throwable $e) {
             throw new AcmeException("POST request to {$uri} failed.", null, $e);
         }
         (yield new CoroutineResult($response));
         return;
     } while (true);
 }
Esempio n. 8
0
 /**
  * Revokes a certificate.
  *
  * @param string $pem PEM encoded certificate
  * @return \Generator coroutine resolved by Amp returning true
  * @throws AcmeException If something went wrong.
  */
 private function doRevokeCertificate($pem)
 {
     if (!is_string($pem)) {
         throw new InvalidArgumentException(sprintf("\$pem must be of type string, %s given.", gettype($pem)));
     }
     $begin = "CERTIFICATE-----";
     $end = "----END";
     $pem = substr($pem, strpos($pem, $begin) + strlen($begin));
     $pem = substr($pem, 0, strpos($pem, $end));
     $enc = new Base64UrlSafeEncoder();
     /** @var Response $response */
     $response = (yield $this->acmeClient->post(AcmeResource::REVOKE_CERTIFICATE, ["certificate" => $enc->encode(base64_decode($pem))]));
     if ($response->getStatus() === 200) {
         (yield new CoroutineResult(true));
         return;
     }
     throw $this->generateException($response);
 }