id = $id; if (Key::hasX509Certificate($item) || Key::hasPublicKey($item)) { $publicKey = Key::getPublicKey($item); } else { $publicKey = null; } if (Key::hasPrivateKey($item)) { $privateKey = Key::getPrivateKey($item); } else { $privateKey = null; } if (($publicKey || $privateKey)) { $this->type = 'asymmetric'; if ($publicKey && $privateKey) { $publicKeyPEM = openssl_pkey_get_details($publicKey)['key']; $privateKeyPublicPEM = openssl_pkey_get_details($privateKey)['key']; if ($privateKeyPublicPEM != $publicKeyPEM) { throw new KeyException('Supplied Certificate and Key are not related'); } } $this->privateKey = $privateKey; $this->publicKey = $publicKey; $this->secret = null; } else { $this->type = 'secret'; $this->secret = $item; $this->publicKey = null; $this->privateKey = null; } } /** * Retrieves private key resource from a input string or * array of strings. * * @param string|array $object PEM-format Private Key or file path to same * * @return resource|false */ public static function getPrivateKey($object) { if (is_array($object)) { foreach ($object as $candidateKey) { $privateKey = Key::getPrivateKey($candidateKey); if ($privateKey) { return $privateKey; } } } else { // OpenSSL libraries don't have detection methods, so try..catch try { $privateKey = openssl_get_privatekey($object); return $privateKey; } catch (\Exception $e) { return null; } } } /** * Retrieves public key resource from a input string or * array of strings. * * @param string|array $object PEM-format Public Key or file path to same * * @return resource|false */ public static function getPublicKey($object) { if (is_array($object)) { // If we implement key rotation in future, this should add to a collection foreach ($object as $candidateKey) { $publicKey = Key::getPublicKey($candidateKey); if ($publicKey) { return $publicKey; } } } else { // OpenSSL libraries don't have detection methods, so try..catch try { $publicKey = openssl_get_publickey($object); return $publicKey; } catch (\Exception $e) { return null; } } } /** * Signing HTTP Messages 'keyId' field. * * @return string * * @throws KeyException */ public function getId() { return $this->id; } /** * Retrieve Verifying Key - Public Key for Asymmetric/PKI, or shared secret for HMAC. * * @return string Shared Secret or PEM-format Public Key * * @throws KeyException */ public function getVerifyingKey() { switch ($this->type) { case 'asymmetric': if ($this->publicKey) { return openssl_pkey_get_details($this->publicKey)['key']; } else { return null; } break; case 'secret': return $this->secret; default: throw new KeyException("Unknown key type $this->type"); } } /** * Retrieve Signing Key - Private Key for Asymmetric/PKI, or shared secret for HMAC. * * @return string Shared Secret or PEM-format Private Key * * @throws KeyException */ public function getSigningKey() { switch ($this->type) { case 'asymmetric': if ($this->privateKey) { openssl_pkey_export($this->privateKey, $pem); return $pem; } else { return null; } break; case 'secret': return $this->secret; default: throw new KeyException("Unknown key type $this->type"); } } /** * @return string 'secret' for HMAC or 'asymmetric' */ public function getType() { return $this->type; } /** * Test if $object is, points to or contains, X.509 PEM-format certificate. * * @param string|array $object PEM Format X.509 Certificate or file path to one * * @return bool */ public static function hasX509Certificate($object) { if (is_array($object)) { foreach ($object as $candidateCertificate) { $result = Key::hasX509Certificate($candidateCertificate); if ($result) { return $result; } } } else { // OpenSSL libraries don't have detection methods, so try..catch try { openssl_x509_export($object, $null); return true; } catch (\Exception $e) { return false; } } } /** * Test if $object is, points to or contains, PEM-format Public Key. * * @param string|array $object PEM-format Public Key or file path to one * * @return bool */ public static function hasPublicKey($object) { if (is_array($object)) { foreach ($object as $candidatePublicKey) { $result = Key::hasPublicKey($candidatePublicKey); if ($result) { return $result; } } } else { return false == !openssl_pkey_get_public($object); } } /** * Test if $object is, points to or contains, PEM-format Private Key. * * @param string|array $object PEM-format Private Key or file path to one * * @return bool */ public static function hasPrivateKey($object) { if (is_array($object)) { foreach ($object as $candidatePrivateKey) { $result = Key::hasPrivateKey($candidatePrivateKey); if ($result) { return $result; } } } else { return false != openssl_pkey_get_private($object); } } }